1220ed979SColeman Kane /* Miniature re-implementation of the "check" library. 2220ed979SColeman Kane * 3220ed979SColeman Kane * This is intended to support just enough of check to run the Expat 4220ed979SColeman Kane * tests. This interface is based entirely on the portion of the 5220ed979SColeman Kane * check library being used. 6220ed979SColeman Kane */ 7220ed979SColeman Kane 8220ed979SColeman Kane #include <stdio.h> 9220ed979SColeman Kane #include <stdlib.h> 10220ed979SColeman Kane #include <setjmp.h> 11220ed979SColeman Kane #include <assert.h> 12220ed979SColeman Kane 13220ed979SColeman Kane #include "minicheck.h" 14220ed979SColeman Kane 15220ed979SColeman Kane Suite * 16220ed979SColeman Kane suite_create(char *name) 17220ed979SColeman Kane { 18220ed979SColeman Kane Suite *suite = (Suite *) calloc(1, sizeof(Suite)); 19220ed979SColeman Kane if (suite != NULL) { 20220ed979SColeman Kane suite->name = name; 21220ed979SColeman Kane } 22220ed979SColeman Kane return suite; 23220ed979SColeman Kane } 24220ed979SColeman Kane 25220ed979SColeman Kane TCase * 26220ed979SColeman Kane tcase_create(char *name) 27220ed979SColeman Kane { 28220ed979SColeman Kane TCase *tc = (TCase *) calloc(1, sizeof(TCase)); 29220ed979SColeman Kane if (tc != NULL) { 30220ed979SColeman Kane tc->name = name; 31220ed979SColeman Kane } 32220ed979SColeman Kane return tc; 33220ed979SColeman Kane } 34220ed979SColeman Kane 35220ed979SColeman Kane void 36220ed979SColeman Kane suite_add_tcase(Suite *suite, TCase *tc) 37220ed979SColeman Kane { 38220ed979SColeman Kane assert(suite != NULL); 39220ed979SColeman Kane assert(tc != NULL); 40220ed979SColeman Kane assert(tc->next_tcase == NULL); 41220ed979SColeman Kane 42220ed979SColeman Kane tc->next_tcase = suite->tests; 43220ed979SColeman Kane suite->tests = tc; 44220ed979SColeman Kane } 45220ed979SColeman Kane 46220ed979SColeman Kane void 47220ed979SColeman Kane tcase_add_checked_fixture(TCase *tc, 48220ed979SColeman Kane tcase_setup_function setup, 49220ed979SColeman Kane tcase_teardown_function teardown) 50220ed979SColeman Kane { 51220ed979SColeman Kane assert(tc != NULL); 52220ed979SColeman Kane tc->setup = setup; 53220ed979SColeman Kane tc->teardown = teardown; 54220ed979SColeman Kane } 55220ed979SColeman Kane 56220ed979SColeman Kane void 57220ed979SColeman Kane tcase_add_test(TCase *tc, tcase_test_function test) 58220ed979SColeman Kane { 59220ed979SColeman Kane assert(tc != NULL); 60220ed979SColeman Kane if (tc->allocated == tc->ntests) { 61220ed979SColeman Kane int nalloc = tc->allocated + 100; 62220ed979SColeman Kane size_t new_size = sizeof(tcase_test_function) * nalloc; 63220ed979SColeman Kane tcase_test_function *new_tests = realloc(tc->tests, new_size); 64220ed979SColeman Kane assert(new_tests != NULL); 65220ed979SColeman Kane if (new_tests != tc->tests) { 66220ed979SColeman Kane free(tc->tests); 67220ed979SColeman Kane tc->tests = new_tests; 68220ed979SColeman Kane } 69220ed979SColeman Kane tc->allocated = nalloc; 70220ed979SColeman Kane } 71220ed979SColeman Kane tc->tests[tc->ntests] = test; 72220ed979SColeman Kane tc->ntests++; 73220ed979SColeman Kane } 74220ed979SColeman Kane 75220ed979SColeman Kane SRunner * 76220ed979SColeman Kane srunner_create(Suite *suite) 77220ed979SColeman Kane { 78220ed979SColeman Kane SRunner *runner = calloc(1, sizeof(SRunner)); 79220ed979SColeman Kane if (runner != NULL) { 80220ed979SColeman Kane runner->suite = suite; 81220ed979SColeman Kane } 82220ed979SColeman Kane return runner; 83220ed979SColeman Kane } 84220ed979SColeman Kane 85220ed979SColeman Kane static jmp_buf env; 86220ed979SColeman Kane 87220ed979SColeman Kane static char const *_check_current_function = NULL; 88220ed979SColeman Kane static int _check_current_lineno = -1; 89220ed979SColeman Kane static char const *_check_current_filename = NULL; 90220ed979SColeman Kane 91220ed979SColeman Kane void 92220ed979SColeman Kane _check_set_test_info(char const *function, char const *filename, int lineno) 93220ed979SColeman Kane { 94220ed979SColeman Kane _check_current_function = function; 95220ed979SColeman Kane _check_current_lineno = lineno; 96220ed979SColeman Kane _check_current_filename = filename; 97220ed979SColeman Kane } 98220ed979SColeman Kane 99220ed979SColeman Kane 100220ed979SColeman Kane static void 101220ed979SColeman Kane add_failure(SRunner *runner, int verbosity) 102220ed979SColeman Kane { 103220ed979SColeman Kane runner->nfailures++; 104220ed979SColeman Kane if (verbosity >= CK_VERBOSE) { 105220ed979SColeman Kane printf("%s:%d: %s\n", _check_current_filename, 106220ed979SColeman Kane _check_current_lineno, _check_current_function); 107220ed979SColeman Kane } 108220ed979SColeman Kane } 109220ed979SColeman Kane 110220ed979SColeman Kane void 111220ed979SColeman Kane srunner_run_all(SRunner *runner, int verbosity) 112220ed979SColeman Kane { 113220ed979SColeman Kane Suite *suite; 114220ed979SColeman Kane TCase *tc; 115220ed979SColeman Kane assert(runner != NULL); 116220ed979SColeman Kane suite = runner->suite; 117220ed979SColeman Kane tc = suite->tests; 118220ed979SColeman Kane while (tc != NULL) { 119220ed979SColeman Kane int i; 120220ed979SColeman Kane for (i = 0; i < tc->ntests; ++i) { 121220ed979SColeman Kane runner->nchecks++; 122220ed979SColeman Kane 123220ed979SColeman Kane if (tc->setup != NULL) { 124220ed979SColeman Kane /* setup */ 125220ed979SColeman Kane if (setjmp(env)) { 126220ed979SColeman Kane add_failure(runner, verbosity); 127220ed979SColeman Kane continue; 128220ed979SColeman Kane } 129220ed979SColeman Kane tc->setup(); 130220ed979SColeman Kane } 131220ed979SColeman Kane /* test */ 132220ed979SColeman Kane if (setjmp(env)) { 133220ed979SColeman Kane add_failure(runner, verbosity); 134220ed979SColeman Kane continue; 135220ed979SColeman Kane } 136220ed979SColeman Kane (tc->tests[i])(); 137220ed979SColeman Kane 138220ed979SColeman Kane /* teardown */ 139220ed979SColeman Kane if (tc->teardown != NULL) { 140220ed979SColeman Kane if (setjmp(env)) { 141220ed979SColeman Kane add_failure(runner, verbosity); 142220ed979SColeman Kane continue; 143220ed979SColeman Kane } 144220ed979SColeman Kane tc->teardown(); 145220ed979SColeman Kane } 146220ed979SColeman Kane } 147220ed979SColeman Kane tc = tc->next_tcase; 148220ed979SColeman Kane } 149220ed979SColeman Kane if (verbosity) { 150220ed979SColeman Kane int passed = runner->nchecks - runner->nfailures; 151220ed979SColeman Kane double percentage = ((double) passed) / runner->nchecks; 152220ed979SColeman Kane int display = (int) (percentage * 100); 153220ed979SColeman Kane printf("%d%%: Checks: %d, Failed: %d\n", 154220ed979SColeman Kane display, runner->nchecks, runner->nfailures); 155220ed979SColeman Kane } 156220ed979SColeman Kane } 157220ed979SColeman Kane 158220ed979SColeman Kane void 159220ed979SColeman Kane _fail_unless(int condition, const char *file, int line, char *msg) 160220ed979SColeman Kane { 161220ed979SColeman Kane /* Always print the error message so it isn't lost. In this case, 162220ed979SColeman Kane we have a failure, so there's no reason to be quiet about what 163220ed979SColeman Kane it is. 164220ed979SColeman Kane */ 165220ed979SColeman Kane if (msg != NULL) 166220ed979SColeman Kane printf("%s", msg); 167220ed979SColeman Kane longjmp(env, 1); 168220ed979SColeman Kane } 169220ed979SColeman Kane 170220ed979SColeman Kane int 171220ed979SColeman Kane srunner_ntests_failed(SRunner *runner) 172220ed979SColeman Kane { 173220ed979SColeman Kane assert(runner != NULL); 174220ed979SColeman Kane return runner->nfailures; 175220ed979SColeman Kane } 176220ed979SColeman Kane 177220ed979SColeman Kane void 178220ed979SColeman Kane srunner_free(SRunner *runner) 179220ed979SColeman Kane { 180220ed979SColeman Kane free(runner->suite); 181220ed979SColeman Kane free(runner); 182220ed979SColeman Kane } 183