From e940df1c2b14b045083eca74334ed6147ddeee7e Mon Sep 17 00:00:00 2001 From: Andreas Schneider Date: Sat, 7 Feb 2015 15:27:29 +0100 Subject: cmocka: Add Test Anything Protocol message output This adds support to print test reporting in the Test Anything Protocol. See http://testanything.org/tap-specification.html Signed-off-by: Andreas Schneider --- doc/mainpage.dox | 5 ++-- include/cmocka.h | 3 ++- src/cmocka.c | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 80 insertions(+), 5 deletions(-) diff --git a/doc/mainpage.dox b/doc/mainpage.dox index e747777..5d658e0 100644 --- a/doc/mainpage.dox +++ b/doc/mainpage.dox @@ -33,7 +33,7 @@ The CMocka library provides: - Very well tested - Testing of memory leaks, buffer overflows and underflows. - A set of assert macros. - - Several supported output formats (stdout, jUnit XML, Subunit) + - Several supported output formats (stdout, TAP, xUnit XML, Subunit) - License: Apache License 2.0 @section main-test A cmocka test @@ -105,8 +105,9 @@ possible to configure several other output formats. The configuration is done using the CMOCKA_MESSAGE_OUTPUT environment variable. The supported values are: - STDOUT for the default standard output printer - - XML for jUnit XML format - SUBUNIT for subunit output + - TAP for Test Anything Protocol (TAP) output + - XML for xUnit XML format The case doesn't matter. The XML output goes to stderr by default. If the environment variable diff --git a/include/cmocka.h b/include/cmocka.h index 0459d43..85e264f 100644 --- a/include/cmocka.h +++ b/include/cmocka.h @@ -1955,6 +1955,7 @@ void vprint_error(const char* const format, va_list args) CMOCKA_PRINTF_ATTRIBUT enum cm_message_output { CM_OUTPUT_STDOUT, CM_OUTPUT_SUBUNIT, + CM_OUTPUT_TAP, CM_OUTPUT_XML, }; @@ -1964,7 +1965,7 @@ enum cm_message_output { * The ouput format for the test can either be set globally using this * function or overriden with environment variable CMOCKA_MESSAGE_OUTPUT. * - * The environment variable can be set to either STDOUT or SUBUNIT. + * The environment variable can be set to either STDOUT, SUBUNIT, TAP or XML. * * @param[in] output The output format to use for the test. * diff --git a/src/cmocka.c b/src/cmocka.c index d7da540..5323fde 100644 --- a/src/cmocka.c +++ b/src/cmocka.c @@ -1876,6 +1876,8 @@ static enum cm_message_output cm_get_output(void) output = CM_OUTPUT_STDOUT; } else if (strcasecmp(env, "SUBUNIT") == 0) { output = CM_OUTPUT_SUBUNIT; + } else if (strcasecmp(env, "TAP") == 0) { + output = CM_OUTPUT_TAP; } else if (strcasecmp(env, "XML") == 0) { output = CM_OUTPUT_XML; } @@ -2030,6 +2032,63 @@ static void cmprintf_standard(enum cm_printf_type type, } } +static void cmprintf_group_start_tap(const size_t num_tests) +{ + print_message("1..%u\n", (unsigned)num_tests); +} + +static void cmprintf_tap(enum cm_printf_type type, + uint32_t test_number, + const char *test_name, + const char *error_message) +{ + switch (type) { + case PRINTF_TEST_START: + break; + case PRINTF_TEST_SUCCESS: + print_message("ok %u - %s\n", (unsigned)test_number, test_name); + break; + case PRINTF_TEST_FAILURE: + print_message("not ok %u - %s\n", (unsigned)test_number, test_name); + if (error_message != NULL) { + char *msg; + char *p; + + msg = strdup(error_message); + if (msg == NULL) { + return; + } + p = msg; + + while (p[0] != '\0') { + char *q = p; + + p = strchr(q, '\n'); + if (p != NULL) { + p[0] = '\0'; + } + + print_message("# %s\n", q); + + if (p == NULL) { + libc_free(msg); + break; + } + p++; + } + libc_free(msg); + } + break; + case PRINTF_TEST_SKIPPED: + print_message("not ok %u # SKIP %s\n", (unsigned)test_number, test_name); + break; + case PRINTF_TEST_ERROR: + print_message("not ok %u - %s %s\n", + (unsigned)test_number, test_name, error_message); + break; + } +} + static void cmprintf_subunit(enum cm_printf_type type, const char *test_name, const char *error_message) @@ -2068,6 +2127,9 @@ static void cmprintf_group_start(const size_t num_tests) break; case CM_OUTPUT_SUBUNIT: break; + case CM_OUTPUT_TAP: + cmprintf_group_start_tap(num_tests); + break; case CM_OUTPUT_XML: break; } @@ -2094,6 +2156,7 @@ static void cmprintf_group_finish(const char *group_name, cm_tests); break; case CM_OUTPUT_SUBUNIT: + case CM_OUTPUT_TAP: break; case CM_OUTPUT_XML: cmprintf_group_finish_xml(group_name, @@ -2107,6 +2170,7 @@ static void cmprintf_group_finish(const char *group_name, } static void cmprintf(enum cm_printf_type type, + size_t test_number, const char *test_name, const char *error_message) { @@ -2121,6 +2185,9 @@ static void cmprintf(enum cm_printf_type type, case CM_OUTPUT_SUBUNIT: cmprintf_subunit(type, test_name, error_message); break; + case CM_OUTPUT_TAP: + cmprintf_tap(type, test_number, test_name, error_message); + break; case CM_OUTPUT_XML: break; } @@ -2420,8 +2487,9 @@ int _cmocka_run_group_tests(const char *group_name, /* Execute tests */ for (i = 0; i < num_tests; i++) { struct CMUnitTestState *cmtest = &cm_tests[i]; + size_t test_number = i + 1; - cmprintf(PRINTF_TEST_START, cmtest->test->name, NULL); + cmprintf(PRINTF_TEST_START, test_number, cmtest->test->name, NULL); if (group_state != NULL) { cm_tests[i].state = group_state; @@ -2433,23 +2501,27 @@ int _cmocka_run_group_tests(const char *group_name, switch (cmtest->status) { case CM_TEST_PASSED: cmprintf(PRINTF_TEST_SUCCESS, + test_number, cmtest->test->name, cmtest->error_message); total_passed++; break; case CM_TEST_SKIPPED: cmprintf(PRINTF_TEST_SKIPPED, + test_number, cmtest->test->name, cmtest->error_message); break; case CM_TEST_FAILED: cmprintf(PRINTF_TEST_FAILURE, + test_number, cmtest->test->name, cmtest->error_message); total_failed++; break; default: cmprintf(PRINTF_TEST_ERROR, + test_number, cmtest->test->name, "Internal cmocka error"); total_errors++; @@ -2457,13 +2529,14 @@ int _cmocka_run_group_tests(const char *group_name, } } else { cmprintf(PRINTF_TEST_ERROR, + test_number, cmtest->test->name, "Could not run the test - check test fixtures"); total_errors++; } } } else { - cmprintf(PRINTF_TEST_ERROR, + cmprintf(PRINTF_TEST_ERROR, 0, group_name, "Group setup failed"); total_errors++; } -- cgit v1.1