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 } |
|