minicheck.c revision 178848
1178848Scokane/* Miniature re-implementation of the "check" library. 2178848Scokane * 3178848Scokane * This is intended to support just enough of check to run the Expat 4178848Scokane * tests. This interface is based entirely on the portion of the 5178848Scokane * check library being used. 6178848Scokane */ 7178848Scokane 8178848Scokane#include <stdio.h> 9178848Scokane#include <stdlib.h> 10178848Scokane#include <setjmp.h> 11178848Scokane#include <assert.h> 12178848Scokane 13178848Scokane#include "minicheck.h" 14178848Scokane 15178848ScokaneSuite * 16178848Scokanesuite_create(char *name) 17178848Scokane{ 18178848Scokane Suite *suite = (Suite *) calloc(1, sizeof(Suite)); 19178848Scokane if (suite != NULL) { 20178848Scokane suite->name = name; 21178848Scokane } 22178848Scokane return suite; 23178848Scokane} 24178848Scokane 25178848ScokaneTCase * 26178848Scokanetcase_create(char *name) 27178848Scokane{ 28178848Scokane TCase *tc = (TCase *) calloc(1, sizeof(TCase)); 29178848Scokane if (tc != NULL) { 30178848Scokane tc->name = name; 31178848Scokane } 32178848Scokane return tc; 33178848Scokane} 34178848Scokane 35178848Scokanevoid 36178848Scokanesuite_add_tcase(Suite *suite, TCase *tc) 37178848Scokane{ 38178848Scokane assert(suite != NULL); 39178848Scokane assert(tc != NULL); 40178848Scokane assert(tc->next_tcase == NULL); 41178848Scokane 42178848Scokane tc->next_tcase = suite->tests; 43178848Scokane suite->tests = tc; 44178848Scokane} 45178848Scokane 46178848Scokanevoid 47178848Scokanetcase_add_checked_fixture(TCase *tc, 48178848Scokane tcase_setup_function setup, 49178848Scokane tcase_teardown_function teardown) 50178848Scokane{ 51178848Scokane assert(tc != NULL); 52178848Scokane tc->setup = setup; 53178848Scokane tc->teardown = teardown; 54178848Scokane} 55178848Scokane 56178848Scokanevoid 57178848Scokanetcase_add_test(TCase *tc, tcase_test_function test) 58178848Scokane{ 59178848Scokane assert(tc != NULL); 60178848Scokane if (tc->allocated == tc->ntests) { 61178848Scokane int nalloc = tc->allocated + 100; 62178848Scokane size_t new_size = sizeof(tcase_test_function) * nalloc; 63178848Scokane tcase_test_function *new_tests = realloc(tc->tests, new_size); 64178848Scokane assert(new_tests != NULL); 65178848Scokane if (new_tests != tc->tests) { 66178848Scokane free(tc->tests); 67178848Scokane tc->tests = new_tests; 68178848Scokane } 69178848Scokane tc->allocated = nalloc; 70178848Scokane } 71178848Scokane tc->tests[tc->ntests] = test; 72178848Scokane tc->ntests++; 73178848Scokane} 74178848Scokane 75178848ScokaneSRunner * 76178848Scokanesrunner_create(Suite *suite) 77178848Scokane{ 78178848Scokane SRunner *runner = calloc(1, sizeof(SRunner)); 79178848Scokane if (runner != NULL) { 80178848Scokane runner->suite = suite; 81178848Scokane } 82178848Scokane return runner; 83178848Scokane} 84178848Scokane 85178848Scokanestatic jmp_buf env; 86178848Scokane 87178848Scokanestatic char const *_check_current_function = NULL; 88178848Scokanestatic int _check_current_lineno = -1; 89178848Scokanestatic char const *_check_current_filename = NULL; 90178848Scokane 91178848Scokanevoid 92178848Scokane_check_set_test_info(char const *function, char const *filename, int lineno) 93178848Scokane{ 94178848Scokane _check_current_function = function; 95178848Scokane _check_current_lineno = lineno; 96178848Scokane _check_current_filename = filename; 97178848Scokane} 98178848Scokane 99178848Scokane 100178848Scokanestatic void 101178848Scokaneadd_failure(SRunner *runner, int verbosity) 102178848Scokane{ 103178848Scokane runner->nfailures++; 104178848Scokane if (verbosity >= CK_VERBOSE) { 105178848Scokane printf("%s:%d: %s\n", _check_current_filename, 106178848Scokane _check_current_lineno, _check_current_function); 107178848Scokane } 108178848Scokane} 109178848Scokane 110178848Scokanevoid 111178848Scokanesrunner_run_all(SRunner *runner, int verbosity) 112178848Scokane{ 113178848Scokane Suite *suite; 114178848Scokane TCase *tc; 115178848Scokane assert(runner != NULL); 116178848Scokane suite = runner->suite; 117178848Scokane tc = suite->tests; 118178848Scokane while (tc != NULL) { 119178848Scokane int i; 120178848Scokane for (i = 0; i < tc->ntests; ++i) { 121178848Scokane runner->nchecks++; 122178848Scokane 123178848Scokane if (tc->setup != NULL) { 124178848Scokane /* setup */ 125178848Scokane if (setjmp(env)) { 126178848Scokane add_failure(runner, verbosity); 127178848Scokane continue; 128178848Scokane } 129178848Scokane tc->setup(); 130178848Scokane } 131178848Scokane /* test */ 132178848Scokane if (setjmp(env)) { 133178848Scokane add_failure(runner, verbosity); 134178848Scokane continue; 135178848Scokane } 136178848Scokane (tc->tests[i])(); 137178848Scokane 138178848Scokane /* teardown */ 139178848Scokane if (tc->teardown != NULL) { 140178848Scokane if (setjmp(env)) { 141178848Scokane add_failure(runner, verbosity); 142178848Scokane continue; 143178848Scokane } 144178848Scokane tc->teardown(); 145178848Scokane } 146178848Scokane } 147178848Scokane tc = tc->next_tcase; 148178848Scokane } 149178848Scokane if (verbosity) { 150178848Scokane int passed = runner->nchecks - runner->nfailures; 151178848Scokane double percentage = ((double) passed) / runner->nchecks; 152178848Scokane int display = (int) (percentage * 100); 153178848Scokane printf("%d%%: Checks: %d, Failed: %d\n", 154178848Scokane display, runner->nchecks, runner->nfailures); 155178848Scokane } 156178848Scokane} 157178848Scokane 158178848Scokanevoid 159178848Scokane_fail_unless(int condition, const char *file, int line, char *msg) 160178848Scokane{ 161178848Scokane /* Always print the error message so it isn't lost. In this case, 162178848Scokane we have a failure, so there's no reason to be quiet about what 163178848Scokane it is. 164178848Scokane */ 165178848Scokane if (msg != NULL) 166178848Scokane printf("%s", msg); 167178848Scokane longjmp(env, 1); 168178848Scokane} 169178848Scokane 170178848Scokaneint 171178848Scokanesrunner_ntests_failed(SRunner *runner) 172178848Scokane{ 173178848Scokane assert(runner != NULL); 174178848Scokane return runner->nfailures; 175178848Scokane} 176178848Scokane 177178848Scokanevoid 178178848Scokanesrunner_free(SRunner *runner) 179178848Scokane{ 180178848Scokane free(runner->suite); 181178848Scokane free(runner); 182178848Scokane} 183