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.
41 #define HUGE_STRING_LEN 8192
42 #define STRING_MAX 256
44 #define asprintf_or_die(strp, fmt, args ...) \
45 if (asprintf(strp, fmt, ## args) == -1) { \
46 fprintf(stderr, "Fatal error (probably out of memory)\n"); \
51 printf("Ran out of memory. Send more\n");
55 /*-------------------------------------------------------------------------*
57 *-------------------------------------------------------------------------*/
59 void CuTestInit(CuTest* t, const char* name, TestFunction function) {
60 t->name = strdup(name);
64 t->function = function;
68 CuTest* CuTestNew(const char* name, TestFunction function) {
72 CuTestInit(tc, name, function);
76 void CuTestRun(CuTest* tc, TestFunction setup, TestFunction teardown) {
79 if (getenv("CUTEST") && STRNEQ(getenv("CUTEST"), tc->name))
82 if (setjmp(buf) == 0) {
88 if (teardown && setjmp(buf) == 0) {
94 static void CuFailInternal(CuTest* tc, const char* file, int line,
98 asprintf_or_die(&buf, "%s:%d: %s", file, line, string);
102 if (tc->jumpBuf != 0) longjmp(*(tc->jumpBuf), 0);
105 void CuFail_Line(CuTest* tc, const char* file, int line,
106 const char* message2, const char* message) {
109 if (message2 != NULL) {
110 asprintf_or_die(&string, "%s:%s", message2, message);
112 string = strdup(message);
114 CuFailInternal(tc, file, line, string);
117 void CuAssert_Line(CuTest* tc, const char* file, int line,
118 const char* message, int condition) {
119 if (condition) return;
120 CuFail_Line(tc, file, line, NULL, message);
123 void CuAssertStrEquals_LineMsg(CuTest* tc, const char* file, int line,
125 const char* expected, const char* actual) {
128 if ((expected == NULL && actual == NULL) ||
129 (expected != NULL && actual != NULL &&
130 strcmp(expected, actual) == 0))
135 if (message != NULL) {
136 asprintf_or_die(&string, "%s: expected <%s> but was <%s>", message,
139 asprintf_or_die(&string, "expected <%s> but was <%s>", expected, actual);
141 CuFailInternal(tc, file, line, string);
144 void CuAssertStrNotEqual_LineMsg(CuTest* tc, const char* file, int line,
146 const char* expected, const char* actual) {
149 if (expected != NULL && actual != NULL && strcmp(expected, actual) != 0)
152 if (message != NULL) {
153 asprintf_or_die(&string, "%s: expected <%s> but was <%s>", message,
156 asprintf_or_die(&string, "expected <%s> but was <%s>", expected, actual);
158 CuFailInternal(tc, file, line, string);
161 void CuAssertIntEquals_LineMsg(CuTest* tc, const char* file, int line,
163 int expected, int actual) {
164 char buf[STRING_MAX];
165 if (expected == actual) return;
166 sprintf(buf, "expected <%d> but was <%d>", expected, actual);
167 CuFail_Line(tc, file, line, message, buf);
170 void CuAssertDblEquals_LineMsg(CuTest* tc, const char* file, int line,
172 double expected, double actual, double delta) {
173 char buf[STRING_MAX];
174 if (fabs(expected - actual) <= delta) return;
175 sprintf(buf, "expected <%lf> but was <%lf>", expected, actual);
176 CuFail_Line(tc, file, line, message, buf);
179 void CuAssertPtrEquals_LineMsg(CuTest* tc, const char* file, int line,
181 const void* expected, const void* actual) {
182 char buf[STRING_MAX];
183 if (expected == actual) return;
184 sprintf(buf, "expected pointer <0x%p> but was <0x%p>", expected, actual);
185 CuFail_Line(tc, file, line, message, buf);
188 void CuAssertPtrNotEqual_LineMsg(CuTest* tc, const char* file, int line,
190 const void* expected, const void* actual) {
191 char buf[STRING_MAX];
192 if (expected != actual) return;
193 sprintf(buf, "expected pointer <0x%p> to be different from <0x%p>",
195 CuFail_Line(tc, file, line, message, buf);
199 /*-------------------------------------------------------------------------*
201 *-------------------------------------------------------------------------*/
203 void CuSuiteInit(CuSuite* testSuite) {
204 testSuite->count = 0;
205 testSuite->failCount = 0;
208 CuSuite* CuSuiteNew(void) {
209 CuSuite* testSuite = NULL;
210 if (ALLOC(testSuite) < 0)
212 CuSuiteInit(testSuite);
216 void CuSuiteSetup(CuSuite *testSuite,
217 TestFunction setup, TestFunction teardown) {
218 testSuite->setup = setup;
219 testSuite->teardown = teardown;
222 void CuSuiteAdd(CuSuite* testSuite, CuTest *testCase) {
223 assert(testSuite->count < MAX_TEST_CASES);
224 testSuite->list[testSuite->count] = testCase;
228 void CuSuiteAddSuite(CuSuite* testSuite, CuSuite* testSuite2) {
230 for (i = 0 ; i < testSuite2->count ; ++i)
232 CuTest* testCase = testSuite2->list[i];
233 CuSuiteAdd(testSuite, testCase);
237 void CuSuiteRun(CuSuite* testSuite) {
239 for (i = 0 ; i < testSuite->count ; ++i)
241 CuTest* testCase = testSuite->list[i];
242 CuTestRun(testCase, testSuite->setup, testSuite->teardown);
243 if (testCase->failed) { testSuite->failCount += 1; }
247 static void string_append(char **s, const char *p) {
251 int len = strlen(*s) + strlen(p) + 1;
252 *s = realloc(*s, len);
259 void CuSuiteSummary(CuSuite* testSuite, char **summary) {
262 for (i = 0 ; i < testSuite->count ; ++i)
264 CuTest* testCase = testSuite->list[i];
265 string_append(summary, testCase->failed ? "F" : ".");
267 string_append(summary, "\n\n");
270 void CuSuiteDetails(CuSuite* testSuite, char **details) {
275 if (testSuite->failCount == 0)
277 int passCount = testSuite->count - testSuite->failCount;
278 const char* testWord = passCount == 1 ? "test" : "tests";
279 asprintf_or_die(&s, "OK (%d %s)\n", passCount, testWord);
280 string_append(details, s);
283 if (testSuite->failCount == 1)
284 string_append(details, "There was 1 failure:\n");
286 asprintf_or_die(&s, "There were %d failures:\n",
287 testSuite->failCount);
288 string_append(details, s);
291 for (i = 0 ; i < testSuite->count ; ++i) {
292 CuTest* testCase = testSuite->list[i];
293 if (testCase->failed) {
295 asprintf_or_die(&s, "%d) %s:\n%s\n",
296 failCount, testCase->name, testCase->message);
297 string_append(details, s);
301 string_append(details, "\n!!!FAILURES!!!\n");
303 asprintf_or_die(&s, "Runs: %d ", testSuite->count);
304 string_append(details, s);
307 asprintf_or_die(&s, "Passes: %d ",
308 testSuite->count - testSuite->failCount);
309 string_append(details, s);
312 asprintf_or_die(&s, "Fails: %d\n", testSuite->failCount);
313 string_append(details, s);
321 void run(CuTest *tc, const char *format, ...) {
326 va_start(args, format);
327 r = vasprintf(&command, format, args);
330 CuFail(tc, "Failed to format command (out of memory)");
332 if (r < 0 || (WIFEXITED(r) && WEXITSTATUS(r) != 0)) {
334 r = asprintf(&msg, "Command %s failed with status %d\n",
335 command, WEXITSTATUS(r));
344 * indent-tabs-mode: nil