2 * This code is based on CuTest by Asim Jalis
3 * http://sourceforge.net/projects/cutest/
5 * The license for the original code is
8 * Copyright (c) 2003 Asim Jalis
10 * This software is provided 'as-is', without any express or implied
11 * warranty. In no event will the authors be held liable for any damages
12 * arising from the use of this software.
14 * Permission is granted to anyone to use this software for any purpose,
15 * including commercial applications, and to alter it and redistribute it
16 * freely, subject to the following restrictions:
18 * 1. The origin of this software must not be misrepresented; you must not
19 * claim that you wrote the original software. If you use this software in
20 * a product, an acknowledgment in the product documentation would be
21 * appreciated but is not required.
23 * 2. Altered source versions must be plainly marked as such, and must not be
24 * misrepresented as being the original software.
26 * 3. This notice may not be removed or altered from any source distribution.
42 #define HUGE_STRING_LEN 8192
43 #define STRING_MAX 256
45 #define asprintf_or_die(strp, fmt, args ...) \
46 if (asprintf(strp, fmt, ## args) == -1) { \
47 fprintf(stderr, "Fatal error (probably out of memory)\n"); \
52 printf("Ran out of memory. Send more\n");
56 /*-------------------------------------------------------------------------*
58 *-------------------------------------------------------------------------*/
60 void CuTestInit(CuTest* t, const char* name, TestFunction function) {
61 t->name = strdup(name);
65 t->function = function;
69 CuTest* CuTestNew(const char* name, TestFunction function) {
73 CuTestInit(tc, name, function);
77 void CuTestRun(CuTest* tc, TestFunction setup, TestFunction teardown) {
80 if (getenv("CUTEST") && STRNEQ(getenv("CUTEST"), tc->name))
83 if (setjmp(buf) == 0) {
89 if (teardown && setjmp(buf) == 0) {
95 static void CuFailInternal(CuTest* tc, const char* file, int line,
99 asprintf_or_die(&buf, "%s:%d: %s", file, line, string);
103 if (tc->jumpBuf != 0) longjmp(*(tc->jumpBuf), 0);
106 void CuFail_Line(CuTest* tc, const char* file, int line,
107 const char* message2, const char* message) {
110 if (message2 != NULL) {
111 asprintf_or_die(&string, "%s:%s", message2, message);
113 string = strdup(message);
115 CuFailInternal(tc, file, line, string);
118 void CuAssert_Line(CuTest* tc, const char* file, int line,
119 const char* message, int condition) {
120 if (condition) return;
121 CuFail_Line(tc, file, line, NULL, message);
124 void CuAssertStrEquals_LineMsg(CuTest* tc, const char* file, int line,
126 const char* expected, const char* actual) {
129 if ((expected == NULL && actual == NULL) ||
130 (expected != NULL && actual != NULL &&
131 strcmp(expected, actual) == 0))
136 if (message != NULL) {
137 asprintf_or_die(&string, "%s: expected <%s> but was <%s>", message,
140 asprintf_or_die(&string, "expected <%s> but was <%s>", expected, actual);
142 CuFailInternal(tc, file, line, string);
145 void CuAssertStrNotEqual_LineMsg(CuTest* tc, const char* file, int line,
147 const char* expected, const char* actual) {
150 if (expected != NULL && actual != NULL && strcmp(expected, actual) != 0)
153 if (message != NULL) {
154 asprintf_or_die(&string, "%s: expected <%s> but was <%s>", message,
157 asprintf_or_die(&string, "expected <%s> but was <%s>", expected, actual);
159 CuFailInternal(tc, file, line, string);
162 void CuAssertIntEquals_LineMsg(CuTest* tc, const char* file, int line,
164 int expected, int actual) {
165 char buf[STRING_MAX];
166 if (expected == actual) return;
167 sprintf(buf, "expected <%d> but was <%d>", expected, actual);
168 CuFail_Line(tc, file, line, message, buf);
171 void CuAssertDblEquals_LineMsg(CuTest* tc, const char* file, int line,
173 double expected, double actual, double delta) {
174 char buf[STRING_MAX];
175 if (fabs(expected - actual) <= delta) return;
176 sprintf(buf, "expected <%lf> but was <%lf>", expected, actual);
177 CuFail_Line(tc, file, line, message, buf);
180 void CuAssertPtrEquals_LineMsg(CuTest* tc, const char* file, int line,
182 const void* expected, const void* actual) {
183 char buf[STRING_MAX];
184 if (expected == actual) return;
185 sprintf(buf, "expected pointer <0x%p> but was <0x%p>", expected, actual);
186 CuFail_Line(tc, file, line, message, buf);
189 void CuAssertPtrNotEqual_LineMsg(CuTest* tc, const char* file, int line,
191 const void* expected, const void* actual) {
192 char buf[STRING_MAX];
193 if (expected != actual) return;
194 sprintf(buf, "expected pointer <0x%p> to be different from <0x%p>",
196 CuFail_Line(tc, file, line, message, buf);
200 /*-------------------------------------------------------------------------*
202 *-------------------------------------------------------------------------*/
204 void CuSuiteInit(CuSuite* testSuite) {
205 testSuite->count = 0;
206 testSuite->failCount = 0;
209 CuSuite* CuSuiteNew(void) {
210 CuSuite* testSuite = NULL;
211 if (ALLOC(testSuite) < 0)
213 CuSuiteInit(testSuite);
217 void CuSuiteSetup(CuSuite *testSuite,
218 TestFunction setup, TestFunction teardown) {
219 testSuite->setup = setup;
220 testSuite->teardown = teardown;
223 void CuSuiteAdd(CuSuite* testSuite, CuTest *testCase) {
224 assert(testSuite->count < MAX_TEST_CASES);
225 testSuite->list[testSuite->count] = testCase;
229 void CuSuiteAddSuite(CuSuite* testSuite, CuSuite* testSuite2) {
231 for (i = 0 ; i < testSuite2->count ; ++i)
233 CuTest* testCase = testSuite2->list[i];
234 CuSuiteAdd(testSuite, testCase);
238 void CuSuiteRun(CuSuite* testSuite) {
240 for (i = 0 ; i < testSuite->count ; ++i)
242 CuTest* testCase = testSuite->list[i];
243 CuTestRun(testCase, testSuite->setup, testSuite->teardown);
244 if (testCase->failed) { testSuite->failCount += 1; }
248 static void string_append(char **s, const char *p) {
252 int len = strlen(*s) + strlen(p) + 1;
253 *s = realloc(*s, len);
260 void CuSuiteSummary(CuSuite* testSuite, char **summary) {
263 for (i = 0 ; i < testSuite->count ; ++i)
265 CuTest* testCase = testSuite->list[i];
266 string_append(summary, testCase->failed ? "F" : ".");
268 string_append(summary, "\n\n");
271 void CuSuiteDetails(CuSuite* testSuite, char **details) {
276 if (testSuite->failCount == 0)
278 int passCount = testSuite->count - testSuite->failCount;
279 const char* testWord = passCount == 1 ? "test" : "tests";
280 asprintf_or_die(&s, "OK (%d %s)\n", passCount, testWord);
281 string_append(details, s);
284 if (testSuite->failCount == 1)
285 string_append(details, "There was 1 failure:\n");
287 asprintf_or_die(&s, "There were %d failures:\n",
288 testSuite->failCount);
289 string_append(details, s);
292 for (i = 0 ; i < testSuite->count ; ++i) {
293 CuTest* testCase = testSuite->list[i];
294 if (testCase->failed) {
296 asprintf_or_die(&s, "%d) %s:\n%s\n",
297 failCount, testCase->name, testCase->message);
298 string_append(details, s);
302 string_append(details, "\n!!!FAILURES!!!\n");
304 asprintf_or_die(&s, "Runs: %d ", testSuite->count);
305 string_append(details, s);
308 asprintf_or_die(&s, "Passes: %d ",
309 testSuite->count - testSuite->failCount);
310 string_append(details, s);
313 asprintf_or_die(&s, "Fails: %d\n", testSuite->failCount);
314 string_append(details, s);
319 void CuSuiteFree(CuSuite *suite) {
320 for (int i=0; i < suite->count; i++) {
321 CuTest *test = suite->list[i];
331 void run(CuTest *tc, const char *format, ...) {
336 va_start(args, format);
337 r = vasprintf(&command, format, args);
340 CuFail(tc, "Failed to format command (out of memory)");
342 if (r < 0 || (WIFEXITED(r) && WEXITSTATUS(r) != 0)) {
344 r = asprintf(&msg, "Command %s failed with status %d\n",
345 command, WEXITSTATUS(r));
352 int should_run(const char *name, int argc, char **argv) {
355 for (int i=0; i < argc; i++)
356 if (STREQ(argv[i], name))
363 * indent-tabs-mode: nil