From ee30089152344a47151c29451490c8440387d60f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jonathan=20Sch=C3=B6bel?= <jonathan@xn--schbel-yxa.info>
Date: Fri, 29 Sep 2023 10:49:35 +0200
Subject: [PATCH] Validator: added initializer for attributes

Similar to the tags, the attributes can be initialized. Missing tags are
automatically added. The declaration syntax is currently a bit annoying,
as the tags, that belong to an attribute, either have to be declared
explicitly or a pointer to the tag declaration must be given, but then
only concurrent tags are possible.
Support for global attributes is likewise missing; it must be ensured,
that (tag_n != 0) && (tags != NULL). Otherwise validator will be
inconsistent and there might be a bug.
---
 sefht.geany                    |  10 +-
 src/lib/sefht/validator.c      |   7 +-
 src/lib/sefht/validator_attr.c | 210 +++++++++++++++++++++++++++++++++
 src/lib/sefht/validator_html.h |  10 ++
 tests/test_validator_attr.c    | 127 +++++++++++++++++++-
 5 files changed, 356 insertions(+), 8 deletions(-)

diff --git a/sefht.geany b/sefht.geany
index cd85443..4f62b7f 100644
--- a/sefht.geany
+++ b/sefht.geany
@@ -28,7 +28,7 @@ long_line_behaviour=1
 long_line_column=72
 
 [files]
-current_page=31
+current_page=54
 FILE_NAME_0=139;None;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2FREADME;0;8
 FILE_NAME_1=134;None;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2F.gitignore;0;8
 FILE_NAME_2=1737;Sh;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fconfigure.ac;0;8
@@ -58,13 +58,13 @@ FILE_NAME_25=8479;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fp
 FILE_NAME_26=1083;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Ftext_segment.h;0;8
 FILE_NAME_27=900;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Ftext_segment_mark.c;0;8
 FILE_NAME_28=1867;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Fsrc%2Flib%2Fsefht%2Ftext_mark_static.c;0;8
-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_29=2191;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=1100;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_31=1303;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=4198;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=1068;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=1287;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=16395;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_35=7484;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=1051;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=1413;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
@@ -83,7 +83,7 @@ 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=4963;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=28881;C;0;EUTF-8;1;1;0;%2Fhome%2Fjonathan%2FDokumente%2Fprojekte%2Fprgm%2Finternet%2Fweb%2FSeFHT%2Ftests%2Ftest_validator_attr.c;0;8
+FILE_NAME_54=33431;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=548;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
diff --git a/src/lib/sefht/validator.c b/src/lib/sefht/validator.c
index fa6aecd..6a81c87 100644
--- a/src/lib/sefht/validator.c
+++ b/src/lib/sefht/validator.c
@@ -95,7 +95,12 @@ SH_Validator_new_html5 (/*@null@*/ /*@out@*/ struct SH_Status * status)
 		return NULL;
 	}
 
-	init_attrs (validator);
+	if (!init_attrs_spec_html5 (validator, status))
+	{
+		free_tags (validator);
+		free (validator);
+		return NULL;
+	}
 
 	set_success (status);
 	return validator;
diff --git a/src/lib/sefht/validator_attr.c b/src/lib/sefht/validator_attr.c
index d8720eb..e4696a3 100644
--- a/src/lib/sefht/validator_attr.c
+++ b/src/lib/sefht/validator_attr.c
@@ -42,6 +42,51 @@ init_attrs (/*@special@*/ struct SH_Validator * validator)
 	/*@modifies validator->attrs@*/
 	/*@modifies validator->attr_n@*/;
 
+static inline
+bool
+init_attrs_spec_html5 (/*@special@*/ struct SH_Validator * validator,
+                       /*@null@*/ /*@out@*/ struct SH_Status * status)
+        /*@uses validator->tags,
+                validator->tag_n@*/
+	/*@defines validator->attrs,
+	           validator->attr_n@*/
+	/*@modifies validator->attrs@*/
+	/*@modifies validator->attr_n@*/
+	/*@globals fileSystem@*/
+	/*@modifies fileSystem@*/
+	/*@modifies status@*/;
+
+static inline
+bool
+init_attr_from_spec (/*@special@*/ struct SH_Validator * validator,
+                     /*@out@*/ struct attr_info * attr_data,
+                     const struct HTML_ATTR_DEFINITION spec,
+                     /*@null@*/ /*@out@*/ struct SH_Status * status)
+        /*@uses validator->tags,
+                validator->tag_n@*/
+	/*@modifies attr_data->name@*/
+	/*@modifies attr_data->tags@*/
+	/*@modifies attr_data->tag_n@*/
+	/*@globals fileSystem@*/
+	/*@modifies fileSystem@*/
+	/*@modifies status@*/;
+
+static inline
+bool
+init_attrs_from_spec (/*@special@*/ struct SH_Validator * validator,
+                      const struct HTML_ATTR_DEFINITION * spec,
+                      const size_t size,
+                      /*@null@*/ /*@out@*/ struct SH_Status * status)
+        /*@uses validator->tags,
+                validator->tag_n@*/
+	/*@defines validator->attrs,
+	           validator->attr_n@*/
+	/*@modifies validator->attrs@*/
+	/*@modifies validator->attr_n@*/
+	/*@globals fileSystem@*/
+	/*@modifies fileSystem@*/
+	/*@modifies status@*/;
+
 static inline
 bool
 copy_attrs (/*@special@*/ struct SH_Validator * copy,
@@ -153,6 +198,171 @@ init_attrs (/*@special@*/ struct SH_Validator * validator)
 	return TRUE;
 }
 
+static inline
+bool
+init_attrs_spec_html5 (/*@special@*/ struct SH_Validator * validator,
+                       /*@null@*/ /*@out@*/ struct SH_Status * status)
+        /*@uses validator->tags,
+                validator->tag_n@*/
+	/*@defines validator->attrs,
+	           validator->attr_n@*/
+	/*@modifies validator->attrs@*/
+	/*@modifies validator->attr_n@*/
+	/*@globals fileSystem@*/
+	/*@modifies fileSystem@*/
+	/*@modifies status@*/
+{
+	size_t size;
+	size = sizeof (HTML5_ATTRS) / sizeof (HTML5_ATTRS[0]);
+	return init_attrs_from_spec (validator, HTML5_ATTRS, size, status);
+}
+
+static inline
+bool
+init_attr_from_spec (/*@special@*/ struct SH_Validator * validator,
+                     /*@out@*/ struct attr_info * attr_data,
+                     const struct HTML_ATTR_DEFINITION spec,
+                     /*@null@*/ /*@out@*/ struct SH_Status * status)
+        /*@uses validator->tags,
+                validator->tag_n@*/
+	/*@modifies validator->tags@*/
+	/*@modifies validator->tag_n@*/
+	/*@modifies attr_data->name@*/
+	/*@modifies attr_data->tags@*/
+	/*@modifies attr_data->tag_n@*/
+	/*@globals fileSystem@*/
+	/*@modifies fileSystem@*/
+	/*@modifies status@*/
+{
+	attr_data->name = strdup (spec.attr);
+	if (NULL == attr_data->name)
+	{
+		set_status (status, E_ALLOC, 3, "strdup failed");
+		return FALSE;
+	}
+
+	if (spec.tag_n >= (SIZE_MAX / sizeof (struct attr_tag_info)))
+	{
+		set_status (status, E_DOMAIN, 2,
+		            "maximum number of tags per attr reached");
+		free (attr_data->name);
+		return FALSE;
+	}
+
+	attr_data->tags = malloc (spec.tag_n
+	                          * sizeof (struct attr_tag_info));
+	if (NULL == attr_data->tags)
+	{
+		set_status (status, E_ALLOC, 3, "malloc failed");
+		free (attr_data->name);
+		return FALSE;
+	}
+
+	attr_data->tag_n = 0;
+
+	for (size_t index = 0; index < spec.tag_n; index++)
+	{
+		size_t position;
+		const char * tag;
+
+		tag = spec.tags[index].tag;
+		if ((!find_tag (validator, tag, &position))
+		&& (!add_tag (validator, tag, position, status)))
+		{
+			free (attr_data->name);
+			free (attr_data->tags);
+			return FALSE;
+		}
+		tag = validator->tags[position].name;
+
+		#define tags attr_data->tags
+		#define tag_n attr_data->tag_n
+		/* ignore duplicate tags */
+		if (!find_attr_tag (attr_data, tag, &position))
+		{
+			for (size_t i = tag_n; i > position; i--)
+			{
+				tags[i] = tags[i-1];
+			}
+			tags[position].name = tag;
+			tag_n++;
+		}
+		#undef tag_n
+		#undef tags
+	}
+
+	return TRUE;
+}
+
+static inline
+bool
+init_attrs_from_spec (/*@special@*/ struct SH_Validator * validator,
+                      const struct HTML_ATTR_DEFINITION * spec,
+                      const size_t size,
+                      /*@null@*/ /*@out@*/ struct SH_Status * status)
+        /*@uses validator->tags,
+                validator->tag_n@*/
+	/*@defines validator->attrs,
+	           validator->attr_n@*/
+	/*@modifies validator->attrs@*/
+	/*@modifies validator->attr_n@*/
+	/*@globals fileSystem@*/
+	/*@modifies fileSystem@*/
+	/*@modifies status@*/
+{
+	/* overflow detection */
+	if (size >= (SIZE_MAX / sizeof (struct attr_info)))
+	{
+		set_status (status, E_DOMAIN, 2,
+		            "maximum number of attrs reached");
+		return FALSE;
+	}
+
+	validator->attrs = malloc (size * sizeof (struct attr_info));
+	if (NULL == validator->attrs)
+	{
+		set_status (status, E_ALLOC, 3, "malloc failed");
+		return FALSE;
+	}
+
+
+	/* needs to be initialized, as find_attr uses it */
+	validator->attr_n = 0;
+
+	/* insertion sort */
+	#define attrs validator->attrs
+	#define attr_n validator->attr_n
+	for (size_t index = 0; index < size; index++)
+	{
+		size_t position;
+
+		/* ignore duplicate attrs */
+		if (!find_attr (validator, spec[index].attr, &position))
+		{
+			struct attr_info attr_data;
+
+			if (!init_attr_from_spec (validator, &attr_data,
+			                          spec[index], status))
+			{
+				free_attrs (validator);
+				return FALSE;
+			}
+
+			for (size_t i = attr_n; i > position; i--)
+			{
+				attrs[i] = attrs[i-1];
+			}
+
+			attrs[position] = attr_data;
+			attr_n++;
+		}
+	}
+	#undef attr_n
+	#undef attrs
+
+	return TRUE;
+}
+
 static inline
 bool
 copy_attr (/*@special@*/ struct attr_info * copy,
diff --git a/src/lib/sefht/validator_html.h b/src/lib/sefht/validator_html.h
index 54cdfc2..f952eb2 100644
--- a/src/lib/sefht/validator_html.h
+++ b/src/lib/sefht/validator_html.h
@@ -34,8 +34,18 @@ struct HTML_TAG_DEFINITION
 	/*@observer@*/ const char * tag;
 };
 
+struct HTML_ATTR_DEFINITION
+{
+	/*@observer@*/ const char * attr;
+	/*@observer@*/ const struct HTML_TAG_DEFINITION * tags;
+	size_t tag_n;
+};
+
 
 const struct HTML_TAG_DEFINITION HTML5_TAGS[] = {
 };
 
+const struct HTML_ATTR_DEFINITION HTML5_ATTRS[] = {
+};
+
 #endif /* SEFHT_VALIDATOR_HTML_H */
diff --git a/tests/test_validator_attr.c b/tests/test_validator_attr.c
index fd769a1..37e5490 100644
--- a/tests/test_validator_attr.c
+++ b/tests/test_validator_attr.c
@@ -38,6 +38,24 @@
 #include "status.h"
 
 
+/* override HTML spec */
+#include "validator_html.h"
+
+const struct HTML_TAG_DEFINITION HTML_TAGS[] = {
+	{"html"},
+	{"aside"},
+	{"a"},
+};
+
+const struct HTML_ATTR_DEFINITION HTML_ATTRS[] = {
+	{"lang", &HTML_TAGS[0], 2},
+	{"href", &HTML_TAGS[2], 1},
+};
+
+#define HTML5_TAGS HTML_TAGS
+#define HTML5_ATTRS HTML_ATTRS
+
+
 /* C file is needed, because we want to override SIZE_MAX */
 #include "validator.c"
 
@@ -174,6 +192,109 @@ START_TEST(test_validator_copy_with_status)
 }
 END_TEST
 
+START_TEST(test_validator_spec_no_status)
+{
+	struct SH_Validator * validator;
+
+	/* test */
+	validator = SH_Validator_new_html5 (NULL);
+	ck_assert_ptr_ne (NULL, validator);
+
+	ck_assert_ptr_ne (NULL, validator->attrs);
+	ck_assert_int_eq (2, validator->attr_n);
+
+	#define attrs validator->attrs
+	#define TEST_STR(S1, S2) ck_assert_ptr_ne (S1, S2);            \
+	                         ck_assert_str_eq (S1, S2);
+
+	ck_assert_ptr_ne (HTML_ATTRS[1].attr, attrs[0].name);
+	ck_assert_str_eq (HTML_ATTRS[1].attr, attrs[0].name);
+	ck_assert_int_eq (HTML_ATTRS[1].tag_n, attrs[0].tag_n);
+	ck_assert_ptr_ne (NULL, attrs[0].tags);
+
+	TEST_STR (HTML_TAGS[2].tag, attrs[0].tags[0].name);
+
+	ck_assert_ptr_ne (HTML_ATTRS[0].attr, attrs[1].name);
+	ck_assert_str_eq (HTML_ATTRS[0].attr, attrs[1].name);
+	ck_assert_int_eq (HTML_ATTRS[0].tag_n, attrs[1].tag_n);
+	ck_assert_ptr_ne (NULL, attrs[1].tags);
+
+	/* The storage order depends on the relative position of memory,
+	 * allocated by different malloc calls. This can change and
+	 * thus must be determined. */
+	if (attrs[1].tags[0].name[0]
+	  > attrs[1].tags[1].name[0])
+	{
+		TEST_STR (HTML_TAGS[0].tag, attrs[1].tags[0].name);
+		TEST_STR (HTML_TAGS[1].tag, attrs[1].tags[1].name);
+	}
+	else
+	{
+		TEST_STR (HTML_TAGS[1].tag, attrs[1].tags[0].name);
+		TEST_STR (HTML_TAGS[0].tag, attrs[1].tags[1].name);
+	}
+
+	#undef TEST_STR
+	#undef attrs
+
+	/* cleanup */
+	SH_Validator_free (validator);
+}
+END_TEST
+
+START_TEST(test_validator_spec_with_status)
+{
+	struct SH_Status status;
+	struct SH_Validator * validator;
+
+	/* test */
+	_status_preinit (status);
+	validator = SH_Validator_new_html5 (&status);
+	ck_assert_ptr_ne (NULL, validator);
+	ck_assert_int_eq (SUCCESS, status.status);
+
+	ck_assert_ptr_ne (NULL, validator->attrs);
+	ck_assert_int_eq (2, validator->attr_n);
+
+	#define attrs validator->attrs
+	#define TEST_STR(S1, S2) ck_assert_ptr_ne (S1, S2);            \
+	                         ck_assert_str_eq (S1, S2);
+
+	ck_assert_ptr_ne (HTML_ATTRS[1].attr, attrs[0].name);
+	ck_assert_str_eq (HTML_ATTRS[1].attr, attrs[0].name);
+	ck_assert_int_eq (HTML_ATTRS[1].tag_n, attrs[0].tag_n);
+	ck_assert_ptr_ne (NULL, attrs[0].tags);
+
+	TEST_STR (HTML_TAGS[2].tag, attrs[0].tags[0].name);
+
+	ck_assert_ptr_ne (HTML_ATTRS[0].attr, attrs[1].name);
+	ck_assert_str_eq (HTML_ATTRS[0].attr, attrs[1].name);
+	ck_assert_int_eq (HTML_ATTRS[0].tag_n, attrs[1].tag_n);
+	ck_assert_ptr_ne (NULL, attrs[1].tags);
+
+	/* The storage order depends on the relative position of memory,
+	 * allocated by different malloc calls. This can change and
+	 * thus must be determined. */
+	if (attrs[1].tags[0].name[0]
+	  > attrs[1].tags[1].name[0])
+	{
+		TEST_STR (HTML_TAGS[0].tag, attrs[1].tags[0].name);
+		TEST_STR (HTML_TAGS[1].tag, attrs[1].tags[1].name);
+	}
+	else
+	{
+		TEST_STR (HTML_TAGS[1].tag, attrs[1].tags[0].name);
+		TEST_STR (HTML_TAGS[0].tag, attrs[1].tags[1].name);
+	}
+
+	#undef TEST_STR
+	#undef attrs
+
+	/* cleanup */
+	SH_Validator_free (validator);
+}
+END_TEST
+
 START_TEST(test_validator_register_no_status)
 {
 	struct SH_Validator * validator;
@@ -191,7 +312,7 @@ START_TEST(test_validator_register_no_status)
 	bool result;
 
 	/* setup */
-	validator = SH_Validator_new_html5 (NULL);
+	validator = SH_Validator_new (NULL);
 	ck_assert_ptr_ne (NULL, validator);
 
 	/* test - register */
@@ -347,7 +468,7 @@ START_TEST(test_validator_register_with_status)
 	bool result;
 
 	/* setup */
-	validator = SH_Validator_new_html5 (NULL);
+	validator = SH_Validator_new (NULL);
 	ck_assert_ptr_ne (NULL, validator);
 
 	/* test - register */
@@ -940,6 +1061,8 @@ Suite * test_suite (void)
 	tcase_add_test (tc_core, test_validator_with_status);
 	tcase_add_test (tc_core, test_validator_copy_no_status);
 	tcase_add_test (tc_core, test_validator_copy_with_status);
+	tcase_add_test (tc_core, test_validator_spec_no_status);
+	tcase_add_test (tc_core, test_validator_spec_with_status);
 	tcase_add_test (tc_core, test_validator_register_no_status);
 	tcase_add_test (tc_core, test_validator_register_with_status);
 	tcase_add_test (tc_core, test_validator_deregister_no_status);
-- 
GitLab