diff --git a/sefht.geany b/sefht.geany index 4d6615ed2b1d56c71743924940f2c86b98b7a488..5bbbe47b572d6466fc12a1e52737cec8033c56da 100644 --- a/sefht.geany +++ b/sefht.geany @@ -61,12 +61,12 @@ FILE_NAME_28=1867;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fp FILE_NAME_29=3036;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Fvalidator.c;0;8 FILE_NAME_30=1159;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Fvalidator.h;0;8 FILE_NAME_31=1111;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Fvalidator_html.h;0;8 -FILE_NAME_32=5802;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Fvalidator_tag.c;0;8 +FILE_NAME_32=13741;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Fvalidator_tag.c;0;8 FILE_NAME_33=1148;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Fvalidator_tag.h;0;8 FILE_NAME_34=1124;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Fvalidator_tag_data.h;0;8 -FILE_NAME_35=1818;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Fvalidator_attr.c;0;8 -FILE_NAME_36=1874;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Fvalidator_attr.h;0;8 -FILE_NAME_37=1099;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Fvalidator_attr_data.h;0;8 +FILE_NAME_35=15732;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Fvalidator_attr.c;0;8 +FILE_NAME_36=1682;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Fvalidator_attr.h;0;8 +FILE_NAME_37=1111;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Fvalidator_attr_data.h;0;8 FILE_NAME_38=924;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Fstatus.h;0;8 FILE_NAME_39=18;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Flog.h;0;4 FILE_NAME_40=20;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Fmacro.h;0;8 @@ -83,8 +83,8 @@ FILE_NAME_50=4221;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fp FILE_NAME_51=994;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Ftests%2Ftest_text_mark.c;0;8 FILE_NAME_52=2447;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Ftests%2Ftest_validator.c;0;8 FILE_NAME_53=3880;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Ftests%2Ftest_validator_tag.c;0;8 -FILE_NAME_54=13518;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Ftests%2Ftest_validator_attr.c;0;8 -FILE_NAME_55=536;None;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Ftodo.txt;0;8 +FILE_NAME_54=29231;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Ftests%2Ftest_validator_attr.c;0;8 +FILE_NAME_55=667;None;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Ftodo.txt;0;8 FILE_NAME_56=201;YAML;0;EUTF-8;0;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2F.gitlab-ci.yml;0;4 FILE_NAME_57=71;Sh;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fgitlab-ci%2Fupload.sh.in;0;8 FILE_NAME_58=806;Sh;0;EUTF-8;0;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fgitlab-ci%2Frelease.sh.in;0;4 diff --git a/src/lib/sefht/validator_attr.c b/src/lib/sefht/validator_attr.c index d5f6218d63401268f1ff07a901bcfed127c99f85..5f42049fe7cd4f3a99a721085c33680d16670d3d 100644 --- a/src/lib/sefht/validator_attr.c +++ b/src/lib/sefht/validator_attr.c @@ -78,10 +78,18 @@ find_attr (const struct SH_Validator * validator, /*@out@*/ size_t * index) /*@modifies index@*/; +static inline +bool +find_attr_tag (const struct attr_info * attr, + /*@dependent@*/ const char * tag, + /*@out@*/ size_t * index) + /*@modifies index@*/; + static inline Attr add_attr (struct SH_Validator * validator, const char * attr, + /*@dependent@*/ const char * tag, size_t index, /*@null@*/ /*@out@*/ struct SH_Status * status) /*@modifies validator->attrs@*/ @@ -122,7 +130,7 @@ get_attr_id_by_name (struct SH_Validator * validator, static inline bool remove_attr (struct SH_Validator * validator, - const char * attr, + const size_t index, /*@null@*/ /*@out@*/ struct SH_Status * status) /*@modifies validator->attrs@*/ /*@modifies validator->attr_n@*/ @@ -132,6 +140,40 @@ remove_attr (struct SH_Validator * validator, /*@modifies status@*/; +static inline +bool +attr_add_tag (struct attr_info * attr, + const size_t index, + /*@dependent@*/ const char * tag, + /*@null@*/ /*@out@*/ struct SH_Status * status) + /*@modifies attr@*/ + /*@globals fileSystem@*/ + /*@modifies fileSystem@*/ + /*@modifies status@*/; + +static inline +bool +attr_remove_tag (struct attr_info * attr, + const size_t index, + /*@null@*/ /*@out@*/ struct SH_Status * status) + /*@modifies attr@*/ + /*@globals fileSystem@*/ + /*@modifies fileSystem@*/ + /*@modifies status@*/; + +static inline +bool +remove_tag_for_all_attrs (struct SH_Validator * validator, + /*@dependent@*/ const char * tag, + /*@null@*/ /*@out@*/ + struct SH_Status * status) + /*@modifies validator->attrs@*/ + /*@modifies validator->attr_n@*/ + /*@modifies validator->last_attr@*/ + /*@globals fileSystem@*/ + /*@modifies fileSystem@*/ + /*@modifies status@*/; + static inline bool @@ -166,7 +208,9 @@ copy_attr (/*@special@*/ struct attr_info * copy, /*@modifies fileSystem@*/ /*@modifies status@*/ { + size_t index; char * name; + struct attr_tag_info * tags; name = strdup (attr->name); if (NULL == name) @@ -175,8 +219,22 @@ copy_attr (/*@special@*/ struct attr_info * copy, return FALSE; } + tags = malloc (sizeof (struct attr_tag_info) * attr->tag_n); + if (NULL == tags) + { + set_status (status, E_ALLOC, 3, "malloc failed"); + free (name); + return FALSE; + } + copy->id = attr->id; copy->name = name; + copy->tag_n = attr->tag_n; + copy->tags = tags; + for (index = 0; index < attr->tag_n; index++) + { + copy->tags[index] = attr->tags[index]; + } return TRUE; } @@ -234,6 +292,7 @@ free_attr (struct attr_info attr) /*@releases attr.name@*/ { free (attr.name); + free (attr.tags); return; } @@ -294,10 +353,49 @@ find_attr (const struct SH_Validator * validator, return FALSE; } +static inline +bool +find_attr_tag (const struct attr_info * attr, + /*@dependent@*/ const char * tag, + /*@out@*/ size_t * index) + /*@modifies index@*/ +{ + size_t start; + size_t end; + size_t pivot; + + start = 0; + end = attr->tag_n; + pivot = (end - start) / 2; + + while (start != end) + { + if (tag < attr->tags[pivot].name) + { + end = pivot; + pivot = (pivot - start) / 2 + start; + } + else if (tag == attr->tags[pivot].name) + { + *index = pivot; + return TRUE; + } + else + { + start = pivot + 1; + pivot = (end - pivot) / 2 + pivot; + } + } + + *index = start; + return FALSE; +} + static inline Attr add_attr (struct SH_Validator * validator, const char * attr, + /*@dependent@*/ const char * tag, size_t index, /*@null@*/ /*@out@*/ struct SH_Status * status) /*@modifies validator->attrs@*/ @@ -331,6 +429,17 @@ add_attr (struct SH_Validator * validator, return ATTR_ERR; } + attr_data.tags = malloc (sizeof (struct attr_tag_info)); + if (NULL == attr_data.tags) + { + set_status (status, E_ALLOC, 3, "malloc failed"); + free (attr_data.name); + return ATTR_ERR; + } + + attr_data.tags[0].name = tag; + attr_data.tag_n = 1; + /* allocate new space */ /* The addition and the multiplication is save, * because we have tested for this @@ -445,7 +554,7 @@ get_attr_id_by_name (struct SH_Validator * validator, static inline bool remove_attr (struct SH_Validator * validator, - const char * attr, + const size_t index, /*@null@*/ /*@out@*/ struct SH_Status * status) /*@modifies validator->attrs@*/ /*@modifies validator->attr_n@*/ @@ -456,16 +565,8 @@ remove_attr (struct SH_Validator * validator, { struct attr_info attr_data; struct attr_info * new_attrs; - size_t index; size_t index2; - if (!find_attr (validator, attr, &index)) - { - /* TODO: define whether this is an error */ - set_status (status, E_VALUE, 3, "no such attr"); - return FALSE; - } - /* preserve data as realloc may fail */ attr_data = validator->attrs[index]; @@ -502,16 +603,170 @@ remove_attr (struct SH_Validator * validator, return TRUE; } +static inline +bool +attr_add_tag (struct attr_info * attr, + const size_t index, + /*@dependent@*/ const char * tag, + /*@null@*/ /*@out@*/ struct SH_Status * status) + /*@modifies attr@*/ + /*@globals fileSystem@*/ + /*@modifies fileSystem@*/ + /*@modifies status@*/ +{ + struct attr_tag_info * new_tags; + + if ((attr->tag_n == SIZE_MAX) + || ((attr->tag_n + 1) + > (SIZE_MAX / sizeof (struct attr_tag_info)))) + { + set_status (status, E_DOMAIN, 2, + "maximum number of tags per attr reached"); + return FALSE; + } + + new_tags = realloc (attr->tags, sizeof (struct attr_tag_info) + * (attr->tag_n + 1)); + if (NULL == new_tags) + { + set_status (status, E_ALLOC, 4, "realloc failed"); + return FALSE; + } + + for (size_t i = attr->tag_n; i > index; i--) + { + new_tags[i] = new_tags[i-1]; + } + new_tags[index].name = tag; + + attr->tags = new_tags; + attr->tag_n++; + + return TRUE; +} + +static inline +bool +attr_remove_tag (struct attr_info * attr, + const size_t index, + /*@null@*/ /*@out@*/ struct SH_Status * status) + /*@modifies attr@*/ + /*@globals fileSystem@*/ + /*@modifies fileSystem@*/ + /*@modifies status@*/ +{ + struct attr_tag_info tag_data; + struct attr_tag_info * new_tags; + + /* preserve data as realloc may fail */ + tag_data = attr->tags[index]; + + for (size_t i = index; i < attr->tag_n-1; i++) + { + attr->tags[i] = attr->tags[i+1]; + } + + new_tags = realloc (attr->tags, sizeof (struct attr_tag_info) + * (attr->tag_n - 1)); + if (NULL == new_tags) + { + set_status (status, E_ALLOC, 4, "realloc failed"); + + for (size_t i = attr->tag_n; i > index; i--) + { + attr->tags[i] = attr->tags[i-1]; + } + attr->tags[index] = tag_data; + + return FALSE; + } + + attr->tags = new_tags; + attr->tag_n--; + + set_success (status); + return TRUE; +} + +static inline +bool +remove_tag_for_all_attrs (struct SH_Validator * validator, + /*@dependent@*/ const char * tag, + /*@null@*/ /*@out@*/ + struct SH_Status * status) + /*@modifies validator->attrs@*/ + /*@modifies validator->attr_n@*/ + /*@modifies validator->last_attr@*/ + /*@globals fileSystem@*/ + /*@modifies fileSystem@*/ + /*@modifies status@*/ +{ + /* note, that index is used for two different arrays */ + size_t index; + + for (index = 0; index < validator->attr_n; index++) + { + struct attr_info * attr; + attr = &validator->attrs[index]; + + if (1 == attr->tag_n) + { + if (tag == attr->tags[0].name) + { + if (!remove_attr (validator, index, + status)) + { + return FALSE; + } + } + } + else + { + size_t index; + if (find_attr_tag (attr, tag, &index)) + { + if (!attr_remove_tag (attr, index, + status)) + { + return FALSE; + } + } + } + } + + set_success (status); + return TRUE; +} + bool SH_Validator_check_attr (struct SH_Validator * validator, + /*@null@*/ const char * tag, const char * attr) /*@*/ { - return is_attr_name (validator, attr); + /* note, that index is used for three different arrays */ + size_t index; + + if (!find_attr (validator, attr, &index)) return FALSE; + + { + struct attr_info * attr; + attr = &validator->attrs[index]; + + if (NULL == tag) return TRUE; + + if (!find_tag (validator, tag, &index)) return FALSE; + tag = validator->tags[index].name; + + if (!find_attr_tag (attr, tag, &index)) return FALSE; + } + + return TRUE; } Attr SH_Validator_register_attr (struct SH_Validator * validator, + const char * tag, const char * attr, /*@null@*/ /*@out@*/ struct SH_Status * status) @@ -523,22 +778,41 @@ SH_Validator_register_attr (struct SH_Validator * validator, /*@modifies status@*/ { Attr attr_id; + /* note, that index is used for three different arrays */ size_t index; + if ((!find_tag (validator, tag, &index)) + && (!add_tag (validator, tag, index, status))) + { + return ATTR_ERR; + } + + tag = validator->tags[index].name; + /* attr already registered */ attr_id = get_attr_id_by_name (validator, attr, &index); if (attr_id != ATTR_ERR) { + struct attr_info * attr; + attr = &validator->attrs[index]; + + if ((!find_attr_tag (attr, tag, &index)) + && (!attr_add_tag (attr, index, tag, status))) + { + return ATTR_ERR; + } + set_success (status); return attr_id; } - return add_attr (validator, attr, index, status); + return add_attr (validator, attr, tag, index, status); } bool SH_Validator_deregister_attr (struct SH_Validator * validator, - const char * attr, + /*@null@*/ const char * tag, + /*@null@*/ const char * attr, /*@null@*/ /*@out@*/ struct SH_Status * status) /*@modifies validator->attr_n@*/ @@ -548,5 +822,75 @@ SH_Validator_deregister_attr (struct SH_Validator * validator, /*@modifies fileSystem@*/ /*@modifies status@*/ { - return remove_attr (validator, attr, status); + /* note, that index is used for three different arrays */ + size_t index; + + if ((NULL == tag) && (NULL == attr)) + { + free_attrs (validator); + init_attrs (validator); + set_success (status); + return TRUE; + } + + if (NULL == attr) + { + if (!find_tag (validator, tag, &index)) + { + /* TODO: define whether this is an error */ + set_status (status, E_VALUE, 3, "no such tag"); + return ATTR_ERR; + } + + tag = validator->tags[index].name; + return remove_tag_for_all_attrs (validator, tag, status); + } + + if (!find_attr (validator, attr, &index)) + { + /* TODO: define whether this is an error */ + set_status (status, E_VALUE, 3, "no such attr"); + return FALSE; + } + + { + struct attr_info * attr; + attr = &validator->attrs[index]; + + if (NULL == tag) + { + return remove_attr (validator, index, status); + } + + if (1 == attr->tag_n) + { + /* TODO: define whether this is an error */ + if (0 != strcmp (tag, attr->tags[0].name)) + { + set_status (status, E_VALUE, 2, + "no such tag"); + return ATTR_ERR; + } + + return remove_attr (validator, index, status); + } + + if (!find_tag (validator, tag, &index)) + { + /* TODO: define whether this is an error */ + set_status (status, E_VALUE, 3, "no such tag"); + return ATTR_ERR; + } + + tag = validator->tags[index].name; + + if (!find_attr_tag (attr, tag, &index)) + { + /* TODO: define whether this is an error */ + set_status (status, E_VALUE, 3, "no such tag"); + return FALSE; + } + + return attr_remove_tag (attr, index, status); + } } diff --git a/src/lib/sefht/validator_attr.h b/src/lib/sefht/validator_attr.h index 64ec2a5c974b2bc0953af00cbafa33b579c84a46..e17e12aee42b7db5794fe43f8d1077a46a16f8ac 100644 --- a/src/lib/sefht/validator_attr.h +++ b/src/lib/sefht/validator_attr.h @@ -43,6 +43,7 @@ typedef unsigned int Attr; Attr SH_Validator_register_attr (SH_Validator * validator, + const char * tag, const char * attr, /*@null@*/ /*@out@*/ struct SH_Status * status) @@ -53,7 +54,8 @@ SH_Validator_register_attr (SH_Validator * validator, bool SH_Validator_deregister_attr (SH_Validator * validator, - const char * attr, + /*@null@*/ const char * tag, + /*@null@*/ const char * attr, /*@null@*/ /*@out@*/ struct SH_Status * status) /*@modifies validator@*/ @@ -63,6 +65,7 @@ SH_Validator_deregister_attr (SH_Validator * validator, bool SH_Validator_check_attr (struct SH_Validator * validator, + /*@null@*/ const char * tag, const char * attr) /*@*/; diff --git a/src/lib/sefht/validator_attr_data.h b/src/lib/sefht/validator_attr_data.h index ff9d6cfd8d1dc9549eb0d1e287c7b8eed53ead40..858a1b2df4a64c70b8900351151ac8466c5ec639 100644 --- a/src/lib/sefht/validator_attr_data.h +++ b/src/lib/sefht/validator_attr_data.h @@ -29,10 +29,17 @@ #error "Only <sefht/sefht.h> can be included directly." #endif +struct attr_tag_info +{ + /*@relnull@*/ /*@dependent@*/ const char * name; +}; + struct attr_info { Attr id; /*@only@*/ char * name; + size_t tag_n; + struct attr_tag_info * tags; }; #define NEXT_ATTR(attr) (attr + 1) diff --git a/src/lib/sefht/validator_tag.c b/src/lib/sefht/validator_tag.c index ab7f28e9110f18cac524a957354462f5ca942190..9a24acf32f6600d6747f6629839df3d12bf123fa 100644 --- a/src/lib/sefht/validator_tag.c +++ b/src/lib/sefht/validator_tag.c @@ -562,6 +562,19 @@ get_tag_id_by_name (const struct SH_Validator * validator, return validator->tags[*index].id; } +static inline +bool +remove_tag_for_all_attrs (struct SH_Validator * validator, + /*@dependent@*/ const char * tag, + /*@null@*/ /*@out@*/ + struct SH_Status * status) + /*@modifies validator->attrs@*/ + /*@modifies validator->attr_n@*/ + /*@modifies validator->last_attr@*/ + /*@globals fileSystem@*/ + /*@modifies fileSystem@*/ + /*@modifies status@*/; + static inline bool remove_tag (struct SH_Validator * validator, Tag id, @@ -587,6 +600,12 @@ remove_tag (struct SH_Validator * validator, Tag id, /* don't free name yet, as realloc may fail */ name = tags[index].name; + /* clear all references of this tag */ + if (!remove_tag_for_all_attrs (validator, name, status)) + { + return FALSE; + } + for (index2 = index; index2 < tag_n-1; index2++) { tags[index2] = tags[index2+1]; diff --git a/tests/test_validator_attr.c b/tests/test_validator_attr.c index fdf49b412c8e3de79cfac84a5fed0f1c2c2e1aaa..f6cb44a43b7bd41b0cb9a9a251f33a29df78df7d 100644 --- a/tests/test_validator_attr.c +++ b/tests/test_validator_attr.c @@ -83,10 +83,10 @@ START_TEST(test_validator_copy_no_status) validator = SH_Validator_new_html5 (NULL); ck_assert_ptr_ne (NULL, validator); - attr = SH_Validator_register_attr (validator, "id", NULL); + attr = SH_Validator_register_attr (validator, "body", "id", NULL); ck_assert_int_ne (ATTR_ERR, attr); - attr = SH_Validator_register_attr (validator, "lang", NULL); + attr = SH_Validator_register_attr (validator, "html", "lang", NULL); ck_assert_int_ne (ATTR_ERR, attr); /* test */ @@ -99,6 +99,7 @@ START_TEST(test_validator_copy_no_status) ck_assert_int_eq (validator->last_attr, copy->last_attr); #define TEST_INT(I) ck_assert_int_eq (validator->I, copy->I); + #define TEST_PTR(P) ck_assert_ptr_eq (validator->P, copy->P); #define TEST_STR(S) ck_assert_ptr_ne (validator->S, copy->S); \ ck_assert_str_eq (validator->S, copy->S); @@ -106,8 +107,15 @@ START_TEST(test_validator_copy_no_status) { TEST_INT(attrs[index].id) TEST_STR(attrs[index].name) + + TEST_INT(attrs[index].tag_n) + for (size_t j = 0; j < copy->attrs[index].tag_n; j++) + { + TEST_PTR(attrs[index].tags[j].name) + } } #undef TEST_INT + #undef TEST_PTR #undef TEST_STR SH_Validator_free (copy); @@ -126,10 +134,10 @@ START_TEST(test_validator_copy_with_status) validator = SH_Validator_new_html5 (NULL); ck_assert_ptr_ne (NULL, validator); - attr = SH_Validator_register_attr (validator, "id", NULL); + attr = SH_Validator_register_attr (validator, "body", "id", NULL); ck_assert_int_ne (ATTR_ERR, attr); - attr = SH_Validator_register_attr (validator, "lang", NULL); + attr = SH_Validator_register_attr (validator, "html", "lang", NULL); ck_assert_int_ne (ATTR_ERR, attr); /* test */ @@ -144,6 +152,7 @@ START_TEST(test_validator_copy_with_status) ck_assert_int_eq (validator->last_attr, copy->last_attr); #define TEST_INT(I) ck_assert_int_eq (validator->I, copy->I); + #define TEST_PTR(P) ck_assert_ptr_eq (validator->P, copy->P); #define TEST_STR(S) ck_assert_ptr_ne (validator->S, copy->S); \ ck_assert_str_eq (validator->S, copy->S); @@ -151,8 +160,15 @@ START_TEST(test_validator_copy_with_status) { TEST_INT(attrs[index].id) TEST_STR(attrs[index].name) + + TEST_INT(attrs[index].tag_n) + for (size_t j = 0; j < copy->attrs[index].tag_n; j++) + { + TEST_PTR(attrs[index].tags[j].name) + } } #undef TEST_INT + #undef TEST_PTR #undef TEST_STR SH_Validator_free (copy); @@ -163,6 +179,11 @@ END_TEST START_TEST(test_validator_register_no_status) { struct SH_Validator * validator; + const char * tag1 = "html"; + const char * tag2 = "foobarbaz"; // mustn't be registered yet + const char * tag3 = "body"; + const char * tag4 = "nav"; + const char * tag5 = "aside"; const char * attr1 = "id"; const char * attr2 = "class"; const char * attr3 = "name"; @@ -177,33 +198,73 @@ START_TEST(test_validator_register_no_status) ck_assert_ptr_ne (NULL, validator); /* test - register */ - attr = SH_Validator_register_attr (validator, attr1, NULL); + attr = SH_Validator_register_attr (validator, tag1, attr1, NULL); ck_assert_int_eq (1, attr); ck_assert_int_eq (validator->attr_n, 1); ck_assert_int_eq (validator->last_attr, attr); ck_assert_int_eq (validator->attrs[0].id, attr); + ck_assert_ptr_ne (validator->attrs[0].name, attr1); ck_assert_str_eq (validator->attrs[0].name, attr1); + ck_assert_int_eq (validator->attrs[0].tag_n, 1); + ck_assert_ptr_ne (validator->attrs[0].tags[0].name, tag1); + ck_assert_str_eq (validator->attrs[0].tags[0].name, tag1); + /* test - duplicate registration */ - attr_ = SH_Validator_register_attr (validator, attr1, NULL); + attr_ = SH_Validator_register_attr (validator, tag1, attr1, NULL); ck_assert_int_eq (attr_, attr); ck_assert_int_eq (validator->attr_n, 1); ck_assert_int_eq (validator->last_attr, attr); + ck_assert_int_eq (validator->attrs[0].id, attr); + ck_assert_ptr_ne (validator->attrs[0].name, attr1); + ck_assert_str_eq (validator->attrs[0].name, attr1); + + ck_assert_int_eq (validator->attrs[0].tag_n, 1); + ck_assert_ptr_ne (validator->attrs[0].tags[0].name, tag1); + ck_assert_str_eq (validator->attrs[0].tags[0].name, tag1); + + /* test - automatic tag register */ + attr = SH_Validator_register_attr (validator, tag2, attr1, NULL); + ck_assert_int_eq (1, attr); + + ck_assert_int_eq (validator->attr_n, 1); + ck_assert_int_eq (validator->last_attr, attr); + ck_assert_int_eq (validator->attrs[0].id, attr); ck_assert_str_eq (validator->attrs[0].name, attr1); - /* test - order */ - attr = SH_Validator_register_attr (validator, attr3, NULL); + ck_assert_int_eq (validator->attrs[0].tag_n, 2); + /* The storage order depends on the relative position of memory, + * allocated by different malloc calls. This can change and + * thus must be determined. */ + if (validator->attrs[0].tags[0].name[0] + > validator->attrs[0].tags[1].name[0]) + { + ck_assert_ptr_ne (validator->attrs[0].tags[0].name, tag1); + ck_assert_str_eq (validator->attrs[0].tags[0].name, tag1); + ck_assert_ptr_ne (validator->attrs[0].tags[1].name, tag2); + ck_assert_str_eq (validator->attrs[0].tags[1].name, tag2); + } + else + { + ck_assert_ptr_ne (validator->attrs[0].tags[1].name, tag1); + ck_assert_str_eq (validator->attrs[0].tags[1].name, tag1); + ck_assert_ptr_ne (validator->attrs[0].tags[0].name, tag2); + ck_assert_str_eq (validator->attrs[0].tags[0].name, tag2); + } + + /* test - order (attr) */ + attr = SH_Validator_register_attr (validator, tag1, attr3, NULL); ck_assert_int_eq (attr, 2); - attr = SH_Validator_register_attr (validator, attr4, NULL); + attr = SH_Validator_register_attr (validator, tag1, attr4, NULL); ck_assert_int_eq (attr, 3); - attr = SH_Validator_register_attr (validator, attr5, NULL); + attr = SH_Validator_register_attr (validator, tag1, attr5, NULL); ck_assert_int_eq (attr, 4); ck_assert_int_eq (validator->attr_n, 4); @@ -213,6 +274,27 @@ START_TEST(test_validator_register_no_status) ck_assert_str_eq (validator->attrs[2].name, attr3); ck_assert_str_eq (validator->attrs[3].name, attr4); + /* test - order (tag) */ + attr = SH_Validator_register_attr (validator, tag2, attr4, NULL); + ck_assert_int_eq (attr, 3); + + attr = SH_Validator_register_attr (validator, tag3, attr4, NULL); + ck_assert_int_eq (attr, 3); + + attr = SH_Validator_register_attr (validator, tag4, attr4, NULL); + ck_assert_int_eq (attr, 3); + + attr = SH_Validator_register_attr (validator, tag5, attr4, NULL); + ck_assert_int_eq (attr, 3); + + ck_assert_int_eq (5, validator->attrs[3].tag_n); + + for (size_t i = 0; i < validator->attrs[3].tag_n-1; i++) + { + ck_assert_int_lt ((size_t)validator->attrs[3].tags[i].name, + (size_t)validator->attrs[3].tags[i+1].name); + } + /* test - overflow detection */ /* make method fail by filling with garbage until * upper boundary is reached */ @@ -230,12 +312,12 @@ START_TEST(test_validator_register_no_status) { sprintf (attrN, "attr%zu", validator->attr_n); } - while (ATTR_ERR != SH_Validator_register_attr (validator, attrN, NULL)); + while (ATTR_ERR != SH_Validator_register_attr (validator, tag1, attrN, NULL)); free (attrN); /* test overflow #1 */ - attr = SH_Validator_register_attr (validator, attr2, NULL); + attr = SH_Validator_register_attr (validator, tag1, attr2, NULL); ck_assert_int_eq (ATTR_ERR, attr); ck_assert_int_eq (validator->attr_n, 10); @@ -244,7 +326,7 @@ START_TEST(test_validator_register_no_status) validator->attr_n = 1; validator->last_attr = ATTR_MAX; - attr = SH_Validator_register_attr (validator, attr2, NULL); + attr = SH_Validator_register_attr (validator, tag1, attr2, NULL); ck_assert_int_eq (ATTR_ERR, attr); ck_assert_int_eq (validator->attr_n, 1); @@ -260,6 +342,11 @@ START_TEST(test_validator_register_with_status) { struct SH_Status status; struct SH_Validator * validator; + const char * tag1 = "html"; + const char * tag2 = "foobarbaz"; // mustn't be registered yet + const char * tag3 = "body"; + const char * tag4 = "nav"; + const char * tag5 = "aside"; const char * attr1 = "id"; const char * attr2 = "class"; const char * attr3 = "name"; @@ -275,7 +362,7 @@ START_TEST(test_validator_register_with_status) /* test - register */ _status_preinit (status); - attr = SH_Validator_register_attr (validator, attr1, &status); + attr = SH_Validator_register_attr (validator, tag1, attr1, &status); ck_assert_int_eq (1, attr); ck_assert_int_eq (SUCCESS, status.status); @@ -283,33 +370,75 @@ START_TEST(test_validator_register_with_status) ck_assert_int_eq (validator->last_attr, attr); ck_assert_int_eq (validator->attrs[0].id, attr); + ck_assert_ptr_ne (validator->attrs[0].name, attr1); ck_assert_str_eq (validator->attrs[0].name, attr1); + ck_assert_int_eq (validator->attrs[0].tag_n, 1); + ck_assert_ptr_ne (validator->attrs[0].tags[0].name, tag1); + ck_assert_str_eq (validator->attrs[0].tags[0].name, tag1); + /* test - duplicate registration */ _status_preinit (status); - attr_ = SH_Validator_register_attr (validator, attr1, &status); + attr_ = SH_Validator_register_attr (validator, tag1, attr1, &status); ck_assert_int_eq (attr_, attr); ck_assert_int_eq (SUCCESS, status.status); ck_assert_int_eq (validator->attr_n, 1); ck_assert_int_eq (validator->last_attr, attr); + ck_assert_int_eq (validator->attrs[0].id, attr); + ck_assert_ptr_ne (validator->attrs[0].name, attr1); + ck_assert_str_eq (validator->attrs[0].name, attr1); + + ck_assert_int_eq (validator->attrs[0].tag_n, 1); + ck_assert_ptr_ne (validator->attrs[0].tags[0].name, tag1); + ck_assert_str_eq (validator->attrs[0].tags[0].name, tag1); + + /* test - automatic tag register */ + _status_preinit (status); + attr = SH_Validator_register_attr (validator, tag2, attr1, &status); + ck_assert_int_eq (1, attr); + ck_assert_int_eq (SUCCESS, status.status); + + ck_assert_int_eq (validator->attr_n, 1); + ck_assert_int_eq (validator->last_attr, attr); + ck_assert_int_eq (validator->attrs[0].id, attr); ck_assert_str_eq (validator->attrs[0].name, attr1); - /* test - order */ + ck_assert_int_eq (validator->attrs[0].tag_n, 2); + /* The storage order depends on the relative position of memory, + * allocated by different malloc calls. This can change and + * thus must be determined. */ + if (validator->attrs[0].tags[0].name[0] + > validator->attrs[0].tags[1].name[0]) + { + ck_assert_ptr_ne (validator->attrs[0].tags[0].name, tag1); + ck_assert_str_eq (validator->attrs[0].tags[0].name, tag1); + ck_assert_ptr_ne (validator->attrs[0].tags[1].name, tag2); + ck_assert_str_eq (validator->attrs[0].tags[1].name, tag2); + } + else + { + ck_assert_ptr_ne (validator->attrs[0].tags[1].name, tag1); + ck_assert_str_eq (validator->attrs[0].tags[1].name, tag1); + ck_assert_ptr_ne (validator->attrs[0].tags[0].name, tag2); + ck_assert_str_eq (validator->attrs[0].tags[0].name, tag2); + } + + /* test - order (attr) */ _status_preinit (status); - attr = SH_Validator_register_attr (validator, attr3, &status); + attr = SH_Validator_register_attr (validator, tag1, attr3, &status); ck_assert_int_eq (attr, 2); ck_assert_int_eq (status.status, SUCCESS); _status_preinit (status); - attr = SH_Validator_register_attr (validator, attr4, &status); + attr = SH_Validator_register_attr (validator, tag1, attr4, &status); ck_assert_int_eq (attr, 3); ck_assert_int_eq (status.status, SUCCESS); _status_preinit (status); - attr = SH_Validator_register_attr (validator, attr5, &status); + attr = SH_Validator_register_attr (validator, tag1, attr5, &status); ck_assert_int_eq (attr, 4); ck_assert_int_eq (status.status, SUCCESS); @@ -320,6 +449,35 @@ START_TEST(test_validator_register_with_status) ck_assert_str_eq (validator->attrs[2].name, attr3); ck_assert_str_eq (validator->attrs[3].name, attr4); + /* test - order (tag) */ + _status_preinit (status); + attr = SH_Validator_register_attr (validator, tag2, attr4, &status); + ck_assert_int_eq (attr, 3); + ck_assert_int_eq (status.status, SUCCESS); + + _status_preinit (status); + attr = SH_Validator_register_attr (validator, tag3, attr4, &status); + ck_assert_int_eq (attr, 3); + ck_assert_int_eq (status.status, SUCCESS); + + _status_preinit (status); + attr = SH_Validator_register_attr (validator, tag4, attr4, &status); + ck_assert_int_eq (attr, 3); + ck_assert_int_eq (status.status, SUCCESS); + + _status_preinit (status); + attr = SH_Validator_register_attr (validator, tag5, attr4, &status); + ck_assert_int_eq (attr, 3); + ck_assert_int_eq (status.status, SUCCESS); + + ck_assert_int_eq (5, validator->attrs[3].tag_n); + + for (size_t i = 0; i < validator->attrs[3].tag_n-1; i++) + { + ck_assert_int_lt ((size_t)validator->attrs[3].tags[i].name, + (size_t)validator->attrs[3].tags[i+1].name); + } + /* test - overflow detection */ /* make method fail by filling with garbage until * upper boundary is reached */ @@ -337,13 +495,13 @@ START_TEST(test_validator_register_with_status) { sprintf (attrN, "attr%zu", validator->attr_n); } - while (ATTR_ERR != SH_Validator_register_attr (validator, attrN, NULL)); + while (ATTR_ERR != SH_Validator_register_attr (validator, tag1, attrN, NULL)); free (attrN); /* test overflow #1 */ _status_preinit (status); - attr = SH_Validator_register_attr (validator, attr2, &status); + attr = SH_Validator_register_attr (validator, tag1, attr2, &status); ck_assert_int_eq (ATTR_ERR, attr); ck_assert_int_eq (E_DOMAIN, status.status); @@ -354,7 +512,7 @@ START_TEST(test_validator_register_with_status) validator->last_attr = ATTR_MAX; _status_preinit (status); - attr = SH_Validator_register_attr (validator, attr2, &status); + attr = SH_Validator_register_attr (validator, tag1, attr2, &status); ck_assert_int_eq (ATTR_ERR, attr); ck_assert_int_eq (E_DOMAIN, status.status); @@ -377,27 +535,156 @@ START_TEST(test_validator_deregister_no_status) validator = SH_Validator_new (NULL); ck_assert_ptr_ne (NULL, validator); - attr = SH_Validator_register_attr (validator, "attr", NULL); + attr = SH_Validator_register_attr (validator, "html", "attr", NULL); + ck_assert_int_ne (ATTR_ERR, attr); + attr = SH_Validator_register_attr (validator, "html", "id", NULL); + ck_assert_int_ne (ATTR_ERR, attr); + attr = SH_Validator_register_attr (validator, "html", "name", NULL); + ck_assert_int_ne (ATTR_ERR, attr); + attr = SH_Validator_register_attr (validator, "html", "class", NULL); + ck_assert_int_ne (ATTR_ERR, attr); + attr = SH_Validator_register_attr (validator, "body", "attr", NULL); + ck_assert_int_ne (ATTR_ERR, attr); + attr = SH_Validator_register_attr (validator, "body", "id", NULL); + ck_assert_int_ne (ATTR_ERR, attr); + attr = SH_Validator_register_attr (validator, "body", "name", NULL); ck_assert_int_ne (ATTR_ERR, attr); - attr = SH_Validator_register_attr (validator, "id", NULL); + attr = SH_Validator_register_attr (validator, "body", "class", NULL); ck_assert_int_ne (ATTR_ERR, attr); /* test - consistency */ - ck_assert_int_eq (2, validator->attr_n); + ck_assert_int_eq (4, validator->attr_n); ck_assert_str_eq ("attr", validator->attrs[0].name); - ck_assert_str_eq ("id", validator->attrs[1].name); + ck_assert_str_eq ("class", validator->attrs[1].name); + ck_assert_str_eq ("id", validator->attrs[2].name); + ck_assert_str_eq ("name", validator->attrs[3].name); + ck_assert_int_eq (2, validator->attrs[0].tag_n); + ck_assert_int_eq (2, validator->attrs[1].tag_n); + ck_assert_int_eq (2, validator->attrs[2].tag_n); + ck_assert_int_eq (2, validator->attrs[3].tag_n); + + /* The storage order depends on the relative position of memory, + * allocated by different malloc calls. This can change and + * thus must be determined. */ + if (validator->attrs[0].tags[0].name[0] + > validator->attrs[0].tags[1].name[0]) + { + ck_assert_str_eq ("html", validator->attrs[0].tags[0].name); + ck_assert_str_eq ("html", validator->attrs[1].tags[0].name); + ck_assert_str_eq ("html", validator->attrs[2].tags[0].name); + ck_assert_str_eq ("html", validator->attrs[3].tags[0].name); + ck_assert_str_eq ("body", validator->attrs[0].tags[1].name); + ck_assert_str_eq ("body", validator->attrs[1].tags[1].name); + ck_assert_str_eq ("body", validator->attrs[2].tags[1].name); + ck_assert_str_eq ("body", validator->attrs[3].tags[1].name); + } + else + { + ck_assert_str_eq ("html", validator->attrs[0].tags[1].name); + ck_assert_str_eq ("html", validator->attrs[1].tags[1].name); + ck_assert_str_eq ("html", validator->attrs[2].tags[1].name); + ck_assert_str_eq ("html", validator->attrs[3].tags[1].name); + ck_assert_str_eq ("body", validator->attrs[0].tags[0].name); + ck_assert_str_eq ("body", validator->attrs[1].tags[0].name); + ck_assert_str_eq ("body", validator->attrs[2].tags[0].name); + ck_assert_str_eq ("body", validator->attrs[3].tags[0].name); + } + /* test - existent attr */ - result = SH_Validator_deregister_attr (validator, "attr", NULL); + result = SH_Validator_deregister_attr (validator, "html", "attr", + NULL); + ck_assert_int_eq (TRUE, result); + + /* test - non existent tag */ + result = SH_Validator_deregister_attr (validator, "html", "attr", + NULL); + ck_assert_int_eq (FALSE, result); + + /* test - existent attr, auto remove */ + result = SH_Validator_deregister_attr (validator, "body", "attr", + NULL); ck_assert_int_eq (TRUE, result); + /* test - consistency */ + ck_assert_int_eq (3, validator->attr_n); + ck_assert_str_eq ("class", validator->attrs[0].name); + ck_assert_str_eq ("id", validator->attrs[1].name); + ck_assert_str_eq ("name", validator->attrs[2].name); + ck_assert_int_eq (2, validator->attrs[0].tag_n); + ck_assert_int_eq (2, validator->attrs[1].tag_n); + ck_assert_int_eq (2, validator->attrs[2].tag_n); + + /* test - non existent attr */ - result = SH_Validator_deregister_attr (validator, "attr", NULL); + result = SH_Validator_deregister_attr (validator, "html", "attr", + NULL); + ck_assert_int_eq (FALSE, result); + + /* test - existent attr, total remove */ + result = SH_Validator_deregister_attr (validator, NULL, "name", + NULL); + ck_assert_int_eq (TRUE, result); + + /* test - non existent attr, total remove */ + result = SH_Validator_deregister_attr (validator, NULL, "attr", + NULL); ck_assert_int_eq (FALSE, result); /* test - consistency */ - ck_assert_int_eq (1, validator->attr_n); - ck_assert_str_eq ("id", validator->attrs[0].name); + ck_assert_int_eq (2, validator->attr_n); + ck_assert_str_eq ("class", validator->attrs[0].name); + ck_assert_str_eq ("id", validator->attrs[1].name); + ck_assert_int_eq (2, validator->attrs[0].tag_n); + ck_assert_int_eq (2, validator->attrs[1].tag_n); + + /* The storage order depends on the relative position of memory, + * allocated by different malloc calls. This can change and + * thus must be determined. */ + if (validator->attrs[0].tags[0].name[0] + > validator->attrs[0].tags[1].name[0]) + { + ck_assert_str_eq ("html", validator->attrs[0].tags[0].name); + ck_assert_str_eq ("html", validator->attrs[1].tags[0].name); + ck_assert_str_eq ("body", validator->attrs[0].tags[1].name); + ck_assert_str_eq ("body", validator->attrs[1].tags[1].name); + } + else + { + ck_assert_str_eq ("html", validator->attrs[0].tags[1].name); + ck_assert_str_eq ("html", validator->attrs[1].tags[1].name); + ck_assert_str_eq ("body", validator->attrs[0].tags[0].name); + ck_assert_str_eq ("body", validator->attrs[1].tags[0].name); + } + + + /* test - existent tag, total remove */ + result = SH_Validator_deregister_attr (validator, "html", NULL, + NULL); + ck_assert_int_eq (TRUE, result); + + /* test - non existent tag, total remove */ + result = SH_Validator_deregister_attr (validator, "nav", NULL, + NULL); + ck_assert_int_eq (FALSE, result); + + /* test - consistency */ + ck_assert_int_eq (2, validator->attr_n); + ck_assert_str_eq ("class", validator->attrs[0].name); + ck_assert_str_eq ("id", validator->attrs[1].name); + ck_assert_int_eq (1, validator->attrs[0].tag_n); + ck_assert_int_eq (1, validator->attrs[1].tag_n); + ck_assert_str_eq ("body", validator->attrs[0].tags[0].name); + ck_assert_str_eq ("body", validator->attrs[1].tags[0].name); + + /* test - total clear */ + result = SH_Validator_deregister_attr (validator, NULL, NULL, + NULL); + ck_assert_int_eq (TRUE, result); + + /* test - consistency */ + ck_assert_int_eq (0, validator->attr_n); + /* cleanup */ SH_Validator_free (validator); @@ -415,33 +702,174 @@ START_TEST(test_validator_deregister_with_status) validator = SH_Validator_new (NULL); ck_assert_ptr_ne (NULL, validator); - attr = SH_Validator_register_attr (validator, "attr", NULL); + attr = SH_Validator_register_attr (validator, "html", "attr", NULL); + ck_assert_int_ne (ATTR_ERR, attr); + attr = SH_Validator_register_attr (validator, "html", "id", NULL); + ck_assert_int_ne (ATTR_ERR, attr); + attr = SH_Validator_register_attr (validator, "html", "name", NULL); ck_assert_int_ne (ATTR_ERR, attr); - attr = SH_Validator_register_attr (validator, "id", NULL); + attr = SH_Validator_register_attr (validator, "html", "class", NULL); + ck_assert_int_ne (ATTR_ERR, attr); + attr = SH_Validator_register_attr (validator, "body", "attr", NULL); + ck_assert_int_ne (ATTR_ERR, attr); + attr = SH_Validator_register_attr (validator, "body", "id", NULL); + ck_assert_int_ne (ATTR_ERR, attr); + attr = SH_Validator_register_attr (validator, "body", "name", NULL); + ck_assert_int_ne (ATTR_ERR, attr); + attr = SH_Validator_register_attr (validator, "body", "class", NULL); ck_assert_int_ne (ATTR_ERR, attr); /* test - consistency */ - ck_assert_int_eq (2, validator->attr_n); + ck_assert_int_eq (4, validator->attr_n); ck_assert_str_eq ("attr", validator->attrs[0].name); - ck_assert_str_eq ("id", validator->attrs[1].name); + ck_assert_str_eq ("class", validator->attrs[1].name); + ck_assert_str_eq ("id", validator->attrs[2].name); + ck_assert_str_eq ("name", validator->attrs[3].name); + ck_assert_int_eq (2, validator->attrs[0].tag_n); + ck_assert_int_eq (2, validator->attrs[1].tag_n); + ck_assert_int_eq (2, validator->attrs[2].tag_n); + ck_assert_int_eq (2, validator->attrs[3].tag_n); + + /* The storage order depends on the relative position of memory, + * allocated by different malloc calls. This can change and + * thus must be determined. */ + if (validator->attrs[0].tags[0].name[0] + > validator->attrs[0].tags[1].name[0]) + { + ck_assert_str_eq ("html", validator->attrs[0].tags[0].name); + ck_assert_str_eq ("html", validator->attrs[1].tags[0].name); + ck_assert_str_eq ("html", validator->attrs[2].tags[0].name); + ck_assert_str_eq ("html", validator->attrs[3].tags[0].name); + ck_assert_str_eq ("body", validator->attrs[0].tags[1].name); + ck_assert_str_eq ("body", validator->attrs[1].tags[1].name); + ck_assert_str_eq ("body", validator->attrs[2].tags[1].name); + ck_assert_str_eq ("body", validator->attrs[3].tags[1].name); + } + else + { + ck_assert_str_eq ("html", validator->attrs[0].tags[1].name); + ck_assert_str_eq ("html", validator->attrs[1].tags[1].name); + ck_assert_str_eq ("html", validator->attrs[2].tags[1].name); + ck_assert_str_eq ("html", validator->attrs[3].tags[1].name); + ck_assert_str_eq ("body", validator->attrs[0].tags[0].name); + ck_assert_str_eq ("body", validator->attrs[1].tags[0].name); + ck_assert_str_eq ("body", validator->attrs[2].tags[0].name); + ck_assert_str_eq ("body", validator->attrs[3].tags[0].name); + } + /* test - existent attr */ _status_preinit (status); - result = SH_Validator_deregister_attr (validator, "attr", + result = SH_Validator_deregister_attr (validator, "html", "attr", &status); ck_assert_int_eq (TRUE, result); ck_assert_int_eq (SUCCESS, status.status); + /* test - non existent tag */ + _status_preinit (status); + result = SH_Validator_deregister_attr (validator, "html", "attr", + &status); + ck_assert_int_eq (FALSE, result); + ck_assert_int_eq (E_VALUE, status.status); + + /* test - existent attr, auto remove */ + _status_preinit (status); + result = SH_Validator_deregister_attr (validator, "body", "attr", + &status); + ck_assert_int_eq (TRUE, result); + ck_assert_int_eq (SUCCESS, status.status); + + /* test - consistency */ + ck_assert_int_eq (3, validator->attr_n); + ck_assert_str_eq ("class", validator->attrs[0].name); + ck_assert_str_eq ("id", validator->attrs[1].name); + ck_assert_str_eq ("name", validator->attrs[2].name); + ck_assert_int_eq (2, validator->attrs[0].tag_n); + ck_assert_int_eq (2, validator->attrs[1].tag_n); + ck_assert_int_eq (2, validator->attrs[2].tag_n); + + /* test - non existent attr */ _status_preinit (status); - result = SH_Validator_deregister_attr (validator, "attr", + result = SH_Validator_deregister_attr (validator, "html", "attr", + &status); + ck_assert_int_eq (FALSE, result); + ck_assert_int_eq (E_VALUE, status.status); + + /* test - existent attr, total remove */ + _status_preinit (status); + result = SH_Validator_deregister_attr (validator, NULL, "name", + &status); + ck_assert_int_eq (TRUE, result); + ck_assert_int_eq (SUCCESS, status.status); + + /* test - non existent attr, total remove */ + _status_preinit (status); + result = SH_Validator_deregister_attr (validator, NULL, "attr", &status); ck_assert_int_eq (FALSE, result); ck_assert_int_eq (E_VALUE, status.status); /* test - consistency */ - ck_assert_int_eq (1, validator->attr_n); - ck_assert_str_eq ("id", validator->attrs[0].name); + ck_assert_int_eq (2, validator->attr_n); + ck_assert_str_eq ("class", validator->attrs[0].name); + ck_assert_str_eq ("id", validator->attrs[1].name); + ck_assert_int_eq (2, validator->attrs[0].tag_n); + ck_assert_int_eq (2, validator->attrs[1].tag_n); + + /* The storage order depends on the relative position of memory, + * allocated by different malloc calls. This can change and + * thus must be determined. */ + if (validator->attrs[0].tags[0].name[0] + > validator->attrs[0].tags[1].name[0]) + { + ck_assert_str_eq ("html", validator->attrs[0].tags[0].name); + ck_assert_str_eq ("html", validator->attrs[1].tags[0].name); + ck_assert_str_eq ("body", validator->attrs[0].tags[1].name); + ck_assert_str_eq ("body", validator->attrs[1].tags[1].name); + } + else + { + ck_assert_str_eq ("html", validator->attrs[0].tags[1].name); + ck_assert_str_eq ("html", validator->attrs[1].tags[1].name); + ck_assert_str_eq ("body", validator->attrs[0].tags[0].name); + ck_assert_str_eq ("body", validator->attrs[1].tags[0].name); + } + + + /* test - existent tag, total remove */ + _status_preinit (status); + result = SH_Validator_deregister_attr (validator, "html", NULL, + &status); + ck_assert_int_eq (TRUE, result); + ck_assert_int_eq (SUCCESS, status.status); + + /* test - non existent tag, total remove */ + _status_preinit (status); + result = SH_Validator_deregister_attr (validator, "nav", NULL, + &status); + ck_assert_int_eq (FALSE, result); + ck_assert_int_eq (E_VALUE, status.status); + + /* test - consistency */ + ck_assert_int_eq (2, validator->attr_n); + ck_assert_str_eq ("class", validator->attrs[0].name); + ck_assert_str_eq ("id", validator->attrs[1].name); + ck_assert_int_eq (1, validator->attrs[0].tag_n); + ck_assert_int_eq (1, validator->attrs[1].tag_n); + ck_assert_str_eq ("body", validator->attrs[0].tags[0].name); + ck_assert_str_eq ("body", validator->attrs[1].tags[0].name); + + /* test - total clear */ + _status_preinit (status); + result = SH_Validator_deregister_attr (validator, NULL, NULL, + &status); + ck_assert_int_eq (TRUE, result); + ck_assert_int_eq (SUCCESS, status.status); + + /* test - consistency */ + ck_assert_int_eq (0, validator->attr_n); + /* cleanup */ SH_Validator_free (validator); @@ -451,9 +879,14 @@ END_TEST START_TEST(test_validator_check) { struct SH_Validator * validator; + const char * tag1 = "html"; + const char * tag2 = "html"; + const char * tag3 = "head"; + const char * tag4 = "body"; const char * attr1 = "id"; const char * attr2 = "id"; const char * attr3 = "class"; + const char * attr4 = "name"; Tag attr; bool result; @@ -461,17 +894,34 @@ START_TEST(test_validator_check) validator = SH_Validator_new (NULL); ck_assert_ptr_ne (NULL, validator); - attr = SH_Validator_register_attr (validator, attr1, NULL); + attr = SH_Validator_register_attr (validator, tag1, attr1, NULL); + ck_assert_int_ne (ATTR_ERR, attr); + attr = SH_Validator_register_attr (validator, tag3, attr3, NULL); ck_assert_int_ne (ATTR_ERR, attr); /* test */ - result = SH_Validator_check_attr (validator, attr1); + result = SH_Validator_check_attr (validator, tag1, attr1); + ck_assert_int_eq (TRUE, result); + + result = SH_Validator_check_attr (validator, tag2, attr2); ck_assert_int_eq (TRUE, result); - result = SH_Validator_check_attr (validator, attr2); + result = SH_Validator_check_attr (validator, tag1, attr3); + ck_assert_int_eq (FALSE, result); + + result = SH_Validator_check_attr (validator, tag3, attr4); + ck_assert_int_eq (FALSE, result); + + result = SH_Validator_check_attr (validator, tag4, attr2); + ck_assert_int_eq (FALSE, result); + + result = SH_Validator_check_attr (validator, tag4, attr4); + ck_assert_int_eq (FALSE, result); + + result = SH_Validator_check_attr (validator, NULL, attr2); ck_assert_int_eq (TRUE, result); - result = SH_Validator_check_attr (validator, attr3); + result = SH_Validator_check_attr (validator, NULL, attr4); ck_assert_int_eq (FALSE, result); /* cleanup */ diff --git a/todo.txt b/todo.txt index 0de5b07d491a360e2d6eeda4d7085fd3463d95a4..3c9b4df92fb45ea9bfa7d898c5791f2863890eb2 100644 --- a/todo.txt +++ b/todo.txt @@ -20,3 +20,8 @@ Fragment: - support of newlines (72/79/80) - support of escaping html symbols (but only which are special in context) - support for mapping special chars -> html entities + +Validator: +- bugfix: remove_attr: failure recovery, fix move back loop +- remove unnecessary ids +- tests missing for deregister_tag