| /* Miniature re-implementation of the "check" library. |
| * |
| * This is intended to support just enough of check to run the Expat |
| * tests. This interface is based entirely on the portion of the |
| * check library being used. |
| */ |
| |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <setjmp.h> |
| #include <assert.h> |
| |
| #include "minicheck.h" |
| |
| Suite * |
| suite_create(char *name) |
| { |
| Suite *suite = (Suite *) calloc(1, sizeof(Suite)); |
| if (suite != NULL) { |
| suite->name = name; |
| } |
| return suite; |
| } |
| |
| TCase * |
| tcase_create(char *name) |
| { |
| TCase *tc = (TCase *) calloc(1, sizeof(TCase)); |
| if (tc != NULL) { |
| tc->name = name; |
| } |
| return tc; |
| } |
| |
| void |
| suite_add_tcase(Suite *suite, TCase *tc) |
| { |
| assert(suite != NULL); |
| assert(tc != NULL); |
| assert(tc->next_tcase == NULL); |
| |
| tc->next_tcase = suite->tests; |
| suite->tests = tc; |
| } |
| |
| void |
| tcase_add_checked_fixture(TCase *tc, |
| tcase_setup_function setup, |
| tcase_teardown_function teardown) |
| { |
| assert(tc != NULL); |
| tc->setup = setup; |
| tc->teardown = teardown; |
| } |
| |
| void |
| tcase_add_test(TCase *tc, tcase_test_function test) |
| { |
| assert(tc != NULL); |
| if (tc->allocated == tc->ntests) { |
| int nalloc = tc->allocated + 100; |
| size_t new_size = sizeof(tcase_test_function) * nalloc; |
| tcase_test_function *new_tests = realloc(tc->tests, new_size); |
| assert(new_tests != NULL); |
| if (new_tests != tc->tests) { |
| free(tc->tests); |
| tc->tests = new_tests; |
| } |
| tc->allocated = nalloc; |
| } |
| tc->tests[tc->ntests] = test; |
| tc->ntests++; |
| } |
| |
| SRunner * |
| srunner_create(Suite *suite) |
| { |
| SRunner *runner = calloc(1, sizeof(SRunner)); |
| if (runner != NULL) { |
| runner->suite = suite; |
| } |
| return runner; |
| } |
| |
| static jmp_buf env; |
| |
| static char const *_check_current_function = NULL; |
| static int _check_current_lineno = -1; |
| static char const *_check_current_filename = NULL; |
| |
| void |
| _check_set_test_info(char const *function, char const *filename, int lineno) |
| { |
| _check_current_function = function; |
| _check_current_lineno = lineno; |
| _check_current_filename = filename; |
| } |
| |
| |
| static void |
| add_failure(SRunner *runner, int verbosity) |
| { |
| runner->nfailures++; |
| if (verbosity >= CK_VERBOSE) { |
| printf("%s:%d: %s\n", _check_current_filename, |
| _check_current_lineno, _check_current_function); |
| } |
| } |
| |
| void |
| srunner_run_all(SRunner *runner, int verbosity) |
| { |
| Suite *suite; |
| TCase *tc; |
| assert(runner != NULL); |
| suite = runner->suite; |
| tc = suite->tests; |
| while (tc != NULL) { |
| int i; |
| for (i = 0; i < tc->ntests; ++i) { |
| runner->nchecks++; |
| |
| if (tc->setup != NULL) { |
| /* setup */ |
| if (setjmp(env)) { |
| add_failure(runner, verbosity); |
| continue; |
| } |
| tc->setup(); |
| } |
| /* test */ |
| if (setjmp(env)) { |
| add_failure(runner, verbosity); |
| continue; |
| } |
| (tc->tests[i])(); |
| |
| /* teardown */ |
| if (tc->teardown != NULL) { |
| if (setjmp(env)) { |
| add_failure(runner, verbosity); |
| continue; |
| } |
| tc->teardown(); |
| } |
| } |
| tc = tc->next_tcase; |
| } |
| if (verbosity) { |
| int passed = runner->nchecks - runner->nfailures; |
| double percentage = ((double) passed) / runner->nchecks; |
| int display = (int) (percentage * 100); |
| printf("%d%%: Checks: %d, Failed: %d\n", |
| display, runner->nchecks, runner->nfailures); |
| } |
| } |
| |
| void |
| _fail_unless(int condition, const char *file, int line, char *msg) |
| { |
| /* Always print the error message so it isn't lost. In this case, |
| we have a failure, so there's no reason to be quiet about what |
| it is. |
| */ |
| if (msg != NULL) |
| printf("%s", msg); |
| longjmp(env, 1); |
| } |
| |
| int |
| srunner_ntests_failed(SRunner *runner) |
| { |
| assert(runner != NULL); |
| return runner->nfailures; |
| } |
| |
| void |
| srunner_free(SRunner *runner) |
| { |
| free(runner->suite); |
| free(runner); |
| } |