From: NeilBrown <neil@brown.name>
Date: Sat, 30 Oct 2021 04:19:39 +0000 (+1100)
Subject: oceani: improve test coverage
X-Git-Url: https://ocean-lang.org/code/?a=commitdiff_plain;h=dd984d3a50a51eaadea073b3bdc7d7ebef6def2c;p=ocean

oceani: improve test coverage

Add a tool 'mark-untest' which adds comments to untested lines.
Then resolve some of them, either adding more tests, or marking
lines as NOTEST

Signed-off-by: NeilBrown <neil@brown.name>
---

diff --git a/csrc/oceani-tests.mdc b/csrc/oceani-tests.mdc
index 3bda937..dde99bf 100644
--- a/csrc/oceani-tests.mdc
+++ b/csrc/oceani-tests.mdc
@@ -794,7 +794,7 @@ various places that `type_err()` are called.
 	oceani: type error in program - not running.
 
 ###### test list
-	oceani_failing_tests += type_err_const type_err_const1
+	oceani_failing_tests += type_err_const type_err_const1 missing_program
 
 ###### test: type_err_const
 	const
@@ -825,6 +825,13 @@ various places that `type_err()` are called.
 	.tmp.code:3:12: Syntax error in constant: :
 	.tmp.code:4:12: Syntax error in constant: :
 
+###### test: missing_program
+	const
+		foo::="bar"
+
+###### output: missing_program
+	oceani: no program found.
+
 ## Test erroneous command line args
 
 To improve coverage, we want to test correct handling of strange command
diff --git a/csrc/oceani.mdc b/csrc/oceani.mdc
index 65790ec..415c024 100644
--- a/csrc/oceani.mdc
+++ b/csrc/oceani.mdc
@@ -226,7 +226,7 @@ structures can be used.
 				exit(1);
 			}
 		} else
-			ss = s;
+			ss = s;				// NOTEST
 		parse_oceani(ss->code, &context.config, dotrace ? stderr : NULL);
 
 		if (!context.prog) {
@@ -494,7 +494,7 @@ Named type are stored in a simple linked list.  Objects of each type are
 	static void type_print(struct type *type, FILE *f)
 	{
 		if (!type)
-			fputs("*unknown*type*", f);
+			fputs("*unknown*type*", f);	// NOTEST
 		else if (type->name.len)
 			fprintf(f, "%.*s", type->name.len, type->name.txt);
 		else if (type->print_type)
@@ -509,7 +509,7 @@ Named type are stored in a simple linked list.  Objects of each type are
 			type->init(type, val);
 	}
 
-	static void dup_value(struct type *type, 
+	static void dup_value(struct type *type,
 	                      struct value *vold, struct value *vnew)
 	{
 		if (type && type->dup)
@@ -523,7 +523,7 @@ Named type are stored in a simple linked list.  Objects of each type are
 			return tl->cmp_order(tl, tr, left, right);
 		if (tl && tl->cmp_eq)
 			return tl->cmp_eq(tl, tr, left, right);
-		return -1;
+		return -1;				// NOTEST
 	}
 
 	static void print_value(struct type *type, struct value *v)
@@ -619,7 +619,7 @@ A separate function encoding these cases will simplify some code later.
 	static void _free_value(struct type *type, struct value *v)
 	{
 		if (!v)
-			return;
+			return;		// NOTEST
 		switch (type->vtype) {
 		case Vnone: break;
 		case Vstr: free(v->str.txt); break;
@@ -645,9 +645,9 @@ A separate function encoding these cases will simplify some code later.
 		case Vbool:
 			val->bool = 0;
 			break;
-		case Vlabel:			// NOTEST
-			val->label = NULL;	// NOTEST
-			break;			// NOTEST
+		case Vlabel:
+			val->label = NULL;
+			break;
 		}
 	}
 
@@ -970,7 +970,7 @@ need to be freed.  For this we need to be able to find it, so assume that
 
 		if (primary->merged)
 			// shouldn't happen
-			primary = primary->merged;
+			primary = primary->merged;	// NOTEST
 
 		for (v = primary->previous; v; v=v->previous)
 			if (v == secondary || v == secondary->merged ||
@@ -1214,8 +1214,8 @@ is started, so there is no need to allocate until the size is known.
 			if (!c->local || !v->type)
 				return NULL;
 			if (v->frame_pos + v->type->size > c->local_size) {
-				printf("INVALID frame_pos\n"); // NOTEST
-				exit(2);
+				printf("INVALID frame_pos\n");	// NOTEST
+				exit(2);			// NOTEST
 			}
 			return c->local + v->frame_pos;
 		}
@@ -1349,8 +1349,8 @@ from the `exec_types` enum.
 		}
 		if (loc->type == Xbinode)
 			return __fput_loc(cast(binode,loc)->left, f) ||
-			       __fput_loc(cast(binode,loc)->right, f);
-		return 0;
+			       __fput_loc(cast(binode,loc)->right, f);	// NOTEST
+		return 0;			// NOTEST
 	}
 	static void fput_loc(struct exec *loc, FILE *f)
 	{
diff --git a/tools/mark-untested b/tools/mark-untested
new file mode 100755
index 0000000..d88d24a
--- /dev/null
+++ b/tools/mark-untested
@@ -0,0 +1,29 @@
+#!/bin/sh
+
+sed -i -e 's,	// UNTESTED$,,' $(git grep -l  '// UNTESTED$' .)
+
+case $1 in
+  remove )
+	exit 0
+    ;;
+
+  * )
+	rm coverage/*.mdc.gcov
+	make SKIP_VALGRIND=1 oceani_test_suite || exit 1
+	for i in coverage/*.mdc.gcov
+	do
+	 b=${i%.gcov}
+	 b=${b#coverage/}
+	 if [ ! -f "$b" ]; then 
+	    continue
+	 fi
+	 grep '#####:' "$i" | grep -vE '(NOTEST|UNTESTED|:######|}\$$|:$|:[	]*(\||\$))' |
+	     awk -F: '{printf "%ds,$,	// UNTESTED,\n", $2}' |
+	     sed -i -e 's,[	 ]*// UNTESTED$,,' -f - "$b"
+         grep '[0-8]: *[1-9][0-9]*:.*// NOTEST$' "$i" |
+	     awk -F: '{printf "%ds,[ 	]*// NOTEST$,,\n", $2}' |
+		sed -i -f - "$b"
+	 grep -c UNTESTED "$b"
+	done
+esac
+