minicheck.c revision 5c19771335cf67c9955a5a58ea52dae9870a8035
1/* Miniature re-implementation of the "check" library. 2 * 3 * This is intended to support just enough of check to run the Expat 4 * tests. This interface is based entirely on the portion of the 5 * check library being used. 6 */ 7 8#include <stdio.h> 9#include <stdlib.h> 10#include <setjmp.h> 11#include <assert.h> 12 13#include "minicheck.h" 14 15Suite * 16suite_create(char *name) 17{ 18 Suite *suite = (Suite *) calloc(1, sizeof(Suite)); 19 if (suite != NULL) { 20 suite->name = name; 21 } 22 return suite; 23} 24 25TCase * 26tcase_create(char *name) 27{ 28 TCase *tc = (TCase *) calloc(1, sizeof(TCase)); 29 if (tc != NULL) { 30 tc->name = name; 31 } 32 return tc; 33} 34 35void 36suite_add_tcase(Suite *suite, TCase *tc) 37{ 38 assert(suite != NULL); 39 assert(tc != NULL); 40 assert(tc->next_tcase == NULL); 41 42 tc->next_tcase = suite->tests; 43 suite->tests = tc; 44} 45 46void 47tcase_add_checked_fixture(TCase *tc, 48 tcase_setup_function setup, 49 tcase_teardown_function teardown) 50{ 51 assert(tc != NULL); 52 tc->setup = setup; 53 tc->teardown = teardown; 54} 55 56void 57tcase_add_test(TCase *tc, tcase_test_function test) 58{ 59 assert(tc != NULL); 60 if (tc->allocated == tc->ntests) { 61 int nalloc = tc->allocated + 100; 62 size_t new_size = sizeof(tcase_test_function) * nalloc; 63 tcase_test_function *new_tests = realloc(tc->tests, new_size); 64 assert(new_tests != NULL); 65 if (new_tests != tc->tests) { 66 free(tc->tests); 67 tc->tests = new_tests; 68 } 69 tc->allocated = nalloc; 70 } 71 tc->tests[tc->ntests] = test; 72 tc->ntests++; 73} 74 75SRunner * 76srunner_create(Suite *suite) 77{ 78 SRunner *runner = calloc(1, sizeof(SRunner)); 79 if (runner != NULL) { 80 runner->suite = suite; 81 } 82 return runner; 83} 84 85void 86srunner_set_fork_status(SRunner *runner, int status) 87{ 88 /* We ignore this. */ 89} 90 91static jmp_buf env; 92 93static char const *_check_current_function = NULL; 94static int _check_current_lineno = -1; 95static char const *_check_current_filename = NULL; 96 97void 98_check_set_test_info(char const *function, char const *filename, int lineno) 99{ 100 _check_current_function = function; 101 _check_current_lineno = lineno; 102 _check_current_filename = filename; 103} 104 105 106static void 107add_failure(SRunner *runner, int verbosity) 108{ 109 runner->nfailures++; 110 if (verbosity >= CK_VERBOSE) { 111 printf("%s:%d: %s\n", _check_current_filename, 112 _check_current_lineno, _check_current_function); 113 } 114} 115 116void 117srunner_run_all(SRunner *runner, int verbosity) 118{ 119 Suite *suite; 120 TCase *tc; 121 assert(runner != NULL); 122 suite = runner->suite; 123 tc = suite->tests; 124 while (tc != NULL) { 125 int i; 126 for (i = 0; i < tc->ntests; ++i) { 127 runner->nchecks++; 128 129 if (tc->setup != NULL) { 130 /* setup */ 131 if (setjmp(env)) { 132 add_failure(runner, verbosity); 133 continue; 134 } 135 tc->setup(); 136 } 137 /* test */ 138 if (setjmp(env)) { 139 add_failure(runner, verbosity); 140 continue; 141 } 142 (tc->tests[i])(); 143 144 /* teardown */ 145 if (tc->teardown != NULL) { 146 if (setjmp(env)) { 147 add_failure(runner, verbosity); 148 continue; 149 } 150 tc->teardown(); 151 } 152 } 153 tc = tc->next_tcase; 154 } 155 if (verbosity) { 156 int passed = runner->nchecks - runner->nfailures; 157 double percentage = ((double) passed) / runner->nchecks; 158 int display = (int) (percentage * 100); 159 printf("%d%%: Checks: %d, Failed: %d\n", 160 display, runner->nchecks, runner->nfailures); 161 } 162} 163 164void 165_fail_unless(int condition, const char *file, int line, char *msg) 166{ 167 longjmp(env, 1); 168} 169 170int 171srunner_ntests_failed(SRunner *runner) 172{ 173 assert(runner != NULL); 174 return runner->nfailures; 175} 176 177void 178srunner_free(SRunner *runner) 179{ 180 free(runner->suite); 181 free(runner); 182} 183