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 "internal.h"  /* for UNUSED_P only */
     14 #include "minicheck.h"
     15 
     16 Suite *
     17 suite_create(const char *name)
     18 {
     19     Suite *suite = (Suite *) calloc(1, sizeof(Suite));
     20     if (suite != NULL) {
     21         suite->name = name;
     22     }
     23     return suite;
     24 }
     25 
     26 TCase *
     27 tcase_create(const char *name)
     28 {
     29     TCase *tc = (TCase *) calloc(1, sizeof(TCase));
     30     if (tc != NULL) {
     31         tc->name = name;
     32     }
     33     return tc;
     34 }
     35 
     36 void
     37 suite_add_tcase(Suite *suite, TCase *tc)
     38 {
     39     assert(suite != NULL);
     40     assert(tc != NULL);
     41     assert(tc->next_tcase == NULL);
     42 
     43     tc->next_tcase = suite->tests;
     44     suite->tests = tc;
     45 }
     46 
     47 void
     48 tcase_add_checked_fixture(TCase *tc,
     49                           tcase_setup_function setup,
     50                           tcase_teardown_function teardown)
     51 {
     52     assert(tc != NULL);
     53     tc->setup = setup;
     54     tc->teardown = teardown;
     55 }
     56 
     57 void
     58 tcase_add_test(TCase *tc, tcase_test_function test)
     59 {
     60     assert(tc != NULL);
     61     if (tc->allocated == tc->ntests) {
     62         int nalloc = tc->allocated + 100;
     63         size_t new_size = sizeof(tcase_test_function) * nalloc;
     64         tcase_test_function *new_tests = realloc(tc->tests, new_size);
     65         assert(new_tests != NULL);
     66         if (new_tests != tc->tests) {
     67             free(tc->tests);
     68             tc->tests = new_tests;
     69         }
     70         tc->allocated = nalloc;
     71     }
     72     tc->tests[tc->ntests] = test;
     73     tc->ntests++;
     74 }
     75 
     76 SRunner *
     77 srunner_create(Suite *suite)
     78 {
     79     SRunner *runner = calloc(1, sizeof(SRunner));
     80     if (runner != NULL) {
     81         runner->suite = suite;
     82     }
     83     return runner;
     84 }
     85 
     86 static jmp_buf env;
     87 
     88 static char const *_check_current_function = NULL;
     89 static int _check_current_lineno = -1;
     90 static char const *_check_current_filename = NULL;
     91 
     92 void
     93 _check_set_test_info(char const *function, char const *filename, int lineno)
     94 {
     95     _check_current_function = function;
     96     _check_current_lineno = lineno;
     97     _check_current_filename = filename;
     98 }
     99 
    100 
    101 static void
    102 add_failure(SRunner *runner, int verbosity)
    103 {
    104     runner->nfailures++;
    105     if (verbosity >= CK_VERBOSE) {
    106         printf("%s:%d: %s\n", _check_current_filename,
    107                _check_current_lineno, _check_current_function);
    108     }
    109 }
    110 
    111 void
    112 srunner_run_all(SRunner *runner, int verbosity)
    113 {
    114     Suite *suite;
    115     TCase *tc;
    116     assert(runner != NULL);
    117     suite = runner->suite;
    118     tc = suite->tests;
    119     while (tc != NULL) {
    120         int i;
    121         for (i = 0; i < tc->ntests; ++i) {
    122             runner->nchecks++;
    123 
    124             if (tc->setup != NULL) {
    125                 /* setup */
    126                 if (setjmp(env)) {
    127                     add_failure(runner, verbosity);
    128                     continue;
    129                 }
    130                 tc->setup();
    131             }
    132             /* test */
    133             if (setjmp(env)) {
    134                 add_failure(runner, verbosity);
    135                 continue;
    136             }
    137             (tc->tests[i])();
    138 
    139             /* teardown */
    140             if (tc->teardown != NULL) {
    141                 if (setjmp(env)) {
    142                     add_failure(runner, verbosity);
    143                     continue;
    144                 }
    145                 tc->teardown();
    146             }
    147         }
    148         tc = tc->next_tcase;
    149     }
    150     if (verbosity) {
    151         int passed = runner->nchecks - runner->nfailures;
    152         double percentage = ((double) passed) / runner->nchecks;
    153         int display = (int) (percentage * 100);
    154         printf("%d%%: Checks: %d, Failed: %d\n",
    155                display, runner->nchecks, runner->nfailures);
    156     }
    157 }
    158 
    159 void
    160 _fail_unless(int UNUSED_P(condition), const char *UNUSED_P(file), int UNUSED_P(line), const char *msg)
    161 {
    162     /* Always print the error message so it isn't lost.  In this case,
    163        we have a failure, so there's no reason to be quiet about what
    164        it is.
    165     */
    166     if (msg != NULL)
    167         printf("%s", msg);
    168     longjmp(env, 1);
    169 }
    170 
    171 int
    172 srunner_ntests_failed(SRunner *runner)
    173 {
    174     assert(runner != NULL);
    175     return runner->nfailures;
    176 }
    177 
    178 void
    179 srunner_free(SRunner *runner)
    180 {
    181     free(runner->suite);
    182     free(runner);
    183 }
    184