|
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 void |
|
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 |
|
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 |
|
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 |
|
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 |
|
165 _fail_unless(int condition, const char *file, int line, char *msg) |
|
166 { |
|
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 } |