Home | History | Annotate | Download | only in tests
      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 
     15 Suite *
     16 suite_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 
     25 TCase *
     26 tcase_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 
     35 void
     36 suite_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 
     46 void
     47 tcase_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 
     56 void
     57 tcase_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 
     75 SRunner *
     76 srunner_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 
     85 static jmp_buf env;
     86 
     87 static char const *_check_current_function = NULL;
     88 static int _check_current_lineno = -1;
     89 static char const *_check_current_filename = NULL;
     90 
     91 void
     92 _check_set_test_info(char const *function, char const *filename, int lineno)
     93 {
     94     _check_current_function = function;
     95     _check_current_lineno = lineno;
     96     _check_current_filename = filename;
     97 }
     98 
     99 
    100 static void
    101 add_failure(SRunner *runner, int verbosity)
    102 {
    103     runner->nfailures++;
    104     if (verbosity >= CK_VERBOSE) {
    105         printf("%s:%d: %s\n", _check_current_filename,
    106                _check_current_lineno, _check_current_function);
    107     }
    108 }
    109 
    110 void
    111 srunner_run_all(SRunner *runner, int verbosity)
    112 {
    113     Suite *suite;
    114     TCase *tc;
    115     assert(runner != NULL);
    116     suite = runner->suite;
    117     tc = suite->tests;
    118     while (tc != NULL) {
    119         int i;
    120         for (i = 0; i < tc->ntests; ++i) {
    121             runner->nchecks++;
    122 
    123             if (tc->setup != NULL) {
    124                 /* setup */
    125                 if (setjmp(env)) {
    126                     add_failure(runner, verbosity);
    127                     continue;
    128                 }
    129                 tc->setup();
    130             }
    131             /* test */
    132             if (setjmp(env)) {
    133                 add_failure(runner, verbosity);
    134                 continue;
    135             }
    136             (tc->tests[i])();
    137 
    138             /* teardown */
    139             if (tc->teardown != NULL) {
    140                 if (setjmp(env)) {
    141                     add_failure(runner, verbosity);
    142                     continue;
    143                 }
    144                 tc->teardown();
    145             }
    146         }
    147         tc = tc->next_tcase;
    148     }
    149     if (verbosity) {
    150         int passed = runner->nchecks - runner->nfailures;
    151         double percentage = ((double) passed) / runner->nchecks;
    152         int display = (int) (percentage * 100);
    153         printf("%d%%: Checks: %d, Failed: %d\n",
    154                display, runner->nchecks, runner->nfailures);
    155     }
    156 }
    157 
    158 void
    159 _fail_unless(int condition, const char *file, int line, char *msg)
    160 {
    161     /* Always print the error message so it isn't lost.  In this case,
    162        we have a failure, so there's no reason to be quiet about what
    163        it is.
    164     */
    165     if (msg != NULL)
    166         printf("%s", msg);
    167     longjmp(env, 1);
    168 }
    169 
    170 int
    171 srunner_ntests_failed(SRunner *runner)
    172 {
    173     assert(runner != NULL);
    174     return runner->nfailures;
    175 }
    176 
    177 void
    178 srunner_free(SRunner *runner)
    179 {
    180     free(runner->suite);
    181     free(runner);
    182 }
    183