diff options
Diffstat (limited to 'tests/clar.c')
-rw-r--r-- | tests/clar.c | 216 |
1 files changed, 164 insertions, 52 deletions
diff --git a/tests/clar.c b/tests/clar.c index 905d67db7..27d35e1c7 100644 --- a/tests/clar.c +++ b/tests/clar.c @@ -95,9 +95,6 @@ static const char * fixture_path(const char *base, const char *fixture_name); struct clar_error { - const char *test; - int test_number; - const char *suite; const char *file; int line_number; const char *error_msg; @@ -106,11 +103,34 @@ struct clar_error { struct clar_error *next; }; -static struct { - int argc; - char **argv; +struct clar_explicit { + size_t suite_idx; + const char *filter; + + struct clar_explicit *next; +}; + +struct clar_report { + const char *test; + int test_number; + const char *suite; + + enum cl_test_status status; + + struct clar_error *errors; + struct clar_error *last_error; + + struct clar_report *next; +}; + +struct clar_summary { + const char *filename; + FILE *fp; +}; +static struct { enum cl_test_status test_status; + const char *active_test; const char *active_suite; @@ -124,8 +144,15 @@ static struct { int exit_on_error; int report_suite_names; - struct clar_error *errors; - struct clar_error *last_error; + int write_summary; + const char *summary_filename; + struct clar_summary *summary; + + struct clar_explicit *explicit; + struct clar_explicit *last_explicit; + + struct clar_report *reports; + struct clar_report *last_report; void (*local_cleanup)(void *); void *local_cleanup_payload; @@ -155,7 +182,7 @@ struct clar_suite { /* From clar_print_*.c */ static void clar_print_init(int test_count, int suite_count, const char *suite_names); static void clar_print_shutdown(int test_count, int suite_count, int error_count); -static void clar_print_error(int num, const struct clar_error *error); +static void clar_print_error(int num, const struct clar_report *report, const struct clar_error *error); static void clar_print_ontest(const char *test_name, int test_number, enum cl_test_status failed); static void clar_print_onsuite(const char *suite_name, int suite_index); static void clar_print_onabort(const char *msg, ...); @@ -164,6 +191,10 @@ static void clar_print_onabort(const char *msg, ...); static void clar_unsandbox(void); static int clar_sandbox(void); +/* From summary.h */ +static struct clar_summary *clar_summary_init(const char *filename); +static int clar_summary_shutdown(struct clar_summary *fp); + /* Load the declarations for the test suite */ #include "clar.suite" @@ -186,21 +217,29 @@ void cl_trace_register(cl_trace_cb *cb, void *payload) /* Core test functions */ static void -clar_report_errors(void) +clar_report_errors(struct clar_report *report) { + struct clar_error *error; int i = 1; - struct clar_error *error, *next; - - error = _clar.errors; - while (error != NULL) { - next = error->next; - clar_print_error(i++, error); - free(error->description); - free(error); - error = next; - } - _clar.errors = _clar.last_error = NULL; + for (error = report->errors; error; error = error->next) + clar_print_error(i++, _clar.last_report, error); +} + +static void +clar_report_all(void) +{ + struct clar_report *report; + struct clar_error *error; + int i = 1; + + for (report = _clar.reports; report; report = report->next) { + if (report->status != CL_TEST_FAILURE) + continue; + + for (error = report->errors; error; error = error->next) + clar_print_error(i++, report, error); + } } static void @@ -209,7 +248,6 @@ clar_run_test( const struct clar_func *initialize, const struct clar_func *cleanup) { - _clar.test_status = CL_TEST_OK; _clar.trampoline_enabled = 1; CL_TRACE(CL_TRACE__TEST__BEGIN); @@ -225,6 +263,9 @@ clar_run_test( _clar.trampoline_enabled = 0; + if (_clar.last_report->status == CL_TEST_NOTRUN) + _clar.last_report->status = CL_TEST_OK; + if (_clar.local_cleanup != NULL) _clar.local_cleanup(_clar.local_cleanup_payload); @@ -240,9 +281,9 @@ clar_run_test( _clar.local_cleanup_payload = NULL; if (_clar.report_errors_only) { - clar_report_errors(); + clar_report_errors(_clar.last_report); } else { - clar_print_ontest(test->name, _clar.tests_ran, _clar.test_status); + clar_print_ontest(test->name, _clar.tests_ran, _clar.last_report->status); } } @@ -251,6 +292,7 @@ clar_run_suite(const struct clar_suite *suite, const char *filter) { const struct clar_func *test = suite->tests; size_t i, matchlen; + struct clar_report *report; if (!suite->enabled) return; @@ -283,6 +325,21 @@ clar_run_suite(const struct clar_suite *suite, const char *filter) continue; _clar.active_test = test[i].name; + + report = calloc(1, sizeof(struct clar_report)); + report->suite = _clar.active_suite; + report->test = _clar.active_test; + report->test_number = _clar.tests_ran; + report->status = CL_TEST_NOTRUN; + + if (_clar.reports == NULL) + _clar.reports = report; + + if (_clar.last_report != NULL) + _clar.last_report->next = report; + + _clar.last_report = report; + clar_run_test(&test[i], &suite->initialize, &suite->cleanup); if (_clar.exit_on_error && _clar.total_errors) @@ -298,13 +355,14 @@ clar_usage(const char *arg) { printf("Usage: %s [options]\n\n", arg); printf("Options:\n"); - printf(" -sname\tRun only the suite with `name` (can go to individual test name)\n"); - printf(" -iname\tInclude the suite with `name`\n"); - printf(" -xname\tExclude the suite with `name`\n"); - printf(" -v \tIncrease verbosity (show suite names)\n"); - printf(" -q \tOnly report tests that had an error\n"); - printf(" -Q \tQuit as soon as a test fails\n"); - printf(" -l \tPrint suite names\n"); + printf(" -sname Run only the suite with `name` (can go to individual test name)\n"); + printf(" -iname Include the suite with `name`\n"); + printf(" -xname Exclude the suite with `name`\n"); + 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(" -l Print suite names\n"); + printf(" -r[filename] Write summary file (to the optional filename)\n"); exit(-1); } @@ -313,11 +371,18 @@ clar_parse_args(int argc, char **argv) { int i; + /* Verify options before execute */ for (i = 1; i < argc; ++i) { char *argument = argv[i]; - if (argument[0] != '-') + if (argument[0] != '-' || argument[1] == '\0' + || strchr("sixvqQlr", argument[1]) == NULL) { clar_usage(argv[0]); + } + } + + for (i = 1; i < argc; ++i) { + char *argument = argv[i]; switch (argument[1]) { case 's': @@ -352,7 +417,24 @@ clar_parse_args(int argc, char **argv) _clar.report_suite_names = 1; switch (action) { - case 's': _clar_suites[j].enabled = 1; clar_run_suite(&_clar_suites[j], argument); break; + case 's': { + struct clar_explicit *explicit = + calloc(1, sizeof(struct clar_explicit)); + assert(explicit); + + explicit->suite_idx = j; + explicit->filter = argument; + + if (_clar.explicit == NULL) + _clar.explicit = explicit; + + if (_clar.last_explicit != NULL) + _clar.last_explicit->next = explicit; + + _clar_suites[j].enabled = 1; + _clar.last_explicit = explicit; + break; + } case 'i': _clar_suites[j].enabled = 1; break; case 'x': _clar_suites[j].enabled = 0; break; } @@ -390,8 +472,14 @@ clar_parse_args(int argc, char **argv) _clar.report_suite_names = 1; break; + case 'r': + _clar.write_summary = 1; + _clar.summary_filename = *(argument + 2) ? (argument + 2) : + "summary.xml"; + break; + default: - clar_usage(argv[0]); + assert(!"Unexpected commandline argument!"); } } } @@ -405,23 +493,31 @@ clar_test_init(int argc, char **argv) "" ); + if (argc > 1) + clar_parse_args(argc, argv); + + if (_clar.write_summary && + !(_clar.summary = clar_summary_init(_clar.summary_filename))) { + clar_print_onabort("Failed to open the summary file\n"); + exit(-1); + } + if (clar_sandbox() < 0) { clar_print_onabort("Failed to sandbox the test runner.\n"); exit(-1); } - - _clar.argc = argc; - _clar.argv = argv; } int clar_test_run(void) { - if (_clar.argc > 1) - clar_parse_args(_clar.argc, _clar.argv); + size_t i; + struct clar_explicit *explicit; - if (!_clar.suites_ran) { - size_t i; + if (_clar.explicit) { + for (explicit = _clar.explicit; explicit; explicit = explicit->next) + clar_run_suite(&_clar_suites[explicit->suite_idx], explicit->filter); + } else { for (i = 0; i < _clar_suite_count; ++i) clar_run_suite(&_clar_suites[i], NULL); } @@ -432,6 +528,9 @@ clar_test_run(void) void clar_test_shutdown(void) { + struct clar_explicit *explicit, *explicit_next; + struct clar_report *report, *report_next; + clar_print_shutdown( _clar.tests_ran, (int)_clar_suite_count, @@ -439,6 +538,21 @@ clar_test_shutdown(void) ); clar_unsandbox(); + + if (_clar.write_summary && clar_summary_shutdown(_clar.summary) < 0) { + clar_print_onabort("Failed to write the summary file\n"); + exit(-1); + } + + for (explicit = _clar.explicit; explicit; explicit = explicit_next) { + explicit_next = explicit->next; + free(explicit); + } + + for (report = _clar.reports; report; report = report_next) { + report_next = report->next; + free(report); + } } int @@ -458,7 +572,7 @@ static void abort_test(void) if (!_clar.trampoline_enabled) { clar_print_onabort( "Fatal error: a cleanup method raised an exception."); - clar_report_errors(); + clar_report_errors(_clar.last_report); exit(-1); } @@ -468,7 +582,7 @@ static void abort_test(void) void clar__skip(void) { - _clar.test_status = CL_TEST_SKIP; + _clar.last_report->status = CL_TEST_SKIP; _clar.total_skipped++; abort_test(); } @@ -482,17 +596,14 @@ void clar__fail( { struct clar_error *error = calloc(1, sizeof(struct clar_error)); - if (_clar.errors == NULL) - _clar.errors = error; + if (_clar.last_report->errors == NULL) + _clar.last_report->errors = error; - if (_clar.last_error != NULL) - _clar.last_error->next = error; + if (_clar.last_report->last_error != NULL) + _clar.last_report->last_error->next = error; - _clar.last_error = error; + _clar.last_report->last_error = error; - error->test = _clar.active_test; - error->test_number = _clar.tests_ran; - error->suite = _clar.active_suite; error->file = file; error->line_number = line; error->error_msg = error_msg; @@ -501,7 +612,7 @@ void clar__fail( error->description = strdup(description); _clar.total_errors++; - _clar.test_status = CL_TEST_FAILURE; + _clar.last_report->status = CL_TEST_FAILURE; if (should_abort) abort_test(); @@ -646,3 +757,4 @@ void cl_set_cleanup(void (*cleanup)(void *), void *opaque) #include "clar/fixtures.h" #include "clar/fs.h" #include "clar/print.h" +#include "clar/summary.h" |