Commit f7250cc36a77e45c5a46c911548b6bd23b613411

Edward Thomson 2020-06-04T07:23:15

clar: add tap output

diff --git a/tests/clar.c b/tests/clar.c
index 070447a..f4c7688 100644
--- a/tests/clar.c
+++ b/tests/clar.c
@@ -363,6 +363,7 @@ clar_usage(const char *arg)
 	printf("  -v            Increase verbosity (show suite names)\n");
 	printf("  -q            Only report tests that had an error\n");
 	printf("  -Q            Quit as soon as a test fails\n");
+	printf("  -t            Display results in tap format\n");
 	printf("  -l            Print suite names\n");
 	printf("  -r[filename]  Write summary file (to the optional filename)\n");
 	exit(-1);
@@ -378,7 +379,7 @@ clar_parse_args(int argc, char **argv)
 		char *argument = argv[i];
 
 		if (argument[0] != '-' || argument[1] == '\0'
-		    || strchr("sixvqQlr", argument[1]) == NULL) {
+		    || strchr("sixvqQtlr", argument[1]) == NULL) {
 			clar_usage(argv[0]);
 		}
 	}
@@ -461,6 +462,10 @@ clar_parse_args(int argc, char **argv)
 			_clar.exit_on_error = 1;
 			break;
 
+		case 't':
+			_clar.output_format = CL_OUTPUT_TAP;
+			break;
+
 		case 'l': {
 			size_t j;
 			printf("Test suites (use -s<name> to run just one):\n");
diff --git a/tests/clar.h b/tests/clar.h
index 8bcba35..49bb4fb 100644
--- a/tests/clar.h
+++ b/tests/clar.h
@@ -18,6 +18,7 @@ enum cl_test_status {
 
 enum cl_output_format {
 	CL_OUTPUT_CLAP,
+	CL_OUTPUT_TAP,
 };
 
 /** Setup clar environment */
diff --git a/tests/clar/print.h b/tests/clar/print.h
index 0b27f1c..b020a9a 100644
--- a/tests/clar/print.h
+++ b/tests/clar/print.h
@@ -64,12 +64,102 @@ static void clar_print_clap_onabort(const char *fmt, va_list arg)
 	vfprintf(stderr, fmt, arg);
 }
 
+/* tap: test anywhere protocol format */
+
+static void clar_print_tap_init(int test_count, int suite_count, const char *suite_names)
+{
+	(void)test_count;
+	(void)suite_count;
+	(void)suite_names;
+	printf("TAP version 13\n");
+}
+
+static void clar_print_tap_shutdown(int test_count, int suite_count, int error_count)
+{
+	(void)suite_count;
+	(void)error_count;
+
+	printf("1..%d\n", test_count);
+}
+
+static void clar_print_tap_error(int num, const struct clar_report *report, const struct clar_error *error)
+{
+	(void)num;
+	(void)report;
+	(void)error;
+}
+
+static void print_escaped(const char *str)
+{
+	char *c;
+
+	while ((c = strchr(str, '\'')) != NULL) {
+		printf("%.*s", (int)(c - str), str);
+		printf("''");
+		str = c + 1;
+	}
+
+	printf("%s", str);
+}
+
+static void clar_print_tap_ontest(const char *test_name, int test_number, enum cl_test_status status)
+{
+	const struct clar_error *error = _clar.last_report->errors;
+
+	(void)test_name;
+	(void)test_number;
+
+	switch(status) {
+	case CL_TEST_OK:
+		printf("ok %d - %s::%s\n", test_number, _clar.active_suite, test_name);
+		break;
+	case CL_TEST_FAILURE:
+		printf("not ok %d - %s::%s\n", test_number, _clar.active_suite, test_name);
+
+		printf("    ---\n");
+		printf("    reason: |\n");
+		printf("      %s\n", error->error_msg);
+
+		if (error->description)
+			printf("      %s\n", error->description);
+
+		printf("    at:\n");
+		printf("      file: '"); print_escaped(error->file); printf("'\n");
+		printf("      line: %" PRIuZ "\n", error->line_number);
+		printf("      function: '%s::%s'\n", _clar.active_suite, test_name);
+		printf("    ---\n");
+
+		break;
+	case CL_TEST_SKIP:
+	case CL_TEST_NOTRUN:
+		printf("ok %d - # SKIP %s::%s\n", test_number, _clar.active_suite, test_name);
+		break;
+	}
+
+	fflush(stdout);
+}
+
+static void clar_print_tap_onsuite(const char *suite_name, int suite_index)
+{
+	printf("# start of suite %d: %s\n", suite_index, suite_name);
+}
+
+static void clar_print_tap_onabort(const char *fmt, va_list arg)
+{
+	printf("Bail out! ");
+	vprintf(fmt, arg);
+	fflush(stdout);
+}
+
 /* indirection between protocol output selection */
 
-#define PRINT(FN, args...) do { \
+#define PRINT(FN, ...) do { \
 		switch (_clar.output_format) { \
 			case CL_OUTPUT_CLAP: \
-				clar_print_clap_##FN (args); \
+				clar_print_clap_##FN (__VA_ARGS__); \
+				break; \
+			case CL_OUTPUT_TAP: \
+				clar_print_tap_##FN (__VA_ARGS__); \
 				break; \
 			default: \
 				abort(); \