clar: add tap output
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153
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(); \