• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 *
suite_create(char * name)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 *
tcase_create(char * name)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
suite_add_tcase(Suite * suite,TCase * tc)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
tcase_add_checked_fixture(TCase * tc,tcase_setup_function setup,tcase_teardown_function teardown)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
tcase_add_test(TCase * tc,tcase_test_function test)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 *
srunner_create(Suite * suite)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 void
srunner_set_fork_status(SRunner * runner,int status)86 srunner_set_fork_status(SRunner *runner, int status)
87 {
88     /* We ignore this. */
89 }
90 
91 static jmp_buf env;
92 
93 static char const *_check_current_function = NULL;
94 static int _check_current_lineno = -1;
95 static char const *_check_current_filename = NULL;
96 
97 void
_check_set_test_info(char const * function,char const * filename,int lineno)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 
106 static void
add_failure(SRunner * runner,int verbosity)107 add_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 
116 void
srunner_run_all(SRunner * runner,int verbosity)117 srunner_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 
164 void
_fail_unless(int condition,const char * file,int line,char * msg)165 _fail_unless(int condition, const char *file, int line, char *msg)
166 {
167     longjmp(env, 1);
168 }
169 
170 int
srunner_ntests_failed(SRunner * runner)171 srunner_ntests_failed(SRunner *runner)
172 {
173     assert(runner != NULL);
174     return runner->nfailures;
175 }
176 
177 void
srunner_free(SRunner * runner)178 srunner_free(SRunner *runner)
179 {
180     free(runner->suite);
181     free(runner);
182 }
183