1 /**
2 (this notice added by dstn)
3
4 Copyright 2002-2003 Asim Jalis.
5
6 Licensed under the zlib/libpng License:
7
8 This software is provided 'as-is', without any express or implied
9 warranty. In no event will the authors be held liable for any damages
10 arising from the use of this software.
11
12 Permission is granted to anyone to use this software for any purpose,
13 including commercial applications, and to alter it and redistribute it
14 freely, subject to the following restrictions:
15
16 1. The origin of this software must not be misrepresented; you must not
17 claim that you wrote the original software. If you use this software
18 in a product, an acknowledgment in the product documentation would be
19 appreciated but is not required.
20
21 2. Altered source versions must be plainly marked as such, and must not be
22 misrepresented as being the original software.
23
24 3. This notice may not be removed or altered from any source
25 distribution.
26 */
27
28 /*
29 This is clearly marked as an altered version by the Astrometry.net project.
30 */
31
32 #include <assert.h>
33 #include <setjmp.h>
34 #include <stdlib.h>
35 #include <stdio.h>
36 #include <string.h>
37 #include <math.h>
38
39 #include "cutest.h"
40
41 static int CUTEST_DIE_ON_FAIL = 0;
42
CuDieOnFail()43 void CuDieOnFail() {
44 CUTEST_DIE_ON_FAIL = 1;
45 }
46
47 /*-------------------------------------------------------------------------*
48 * CuStr
49 *-------------------------------------------------------------------------*/
50
CuStrAlloc(int size)51 char* CuStrAlloc(int size)
52 {
53 char* newStr = (char*) malloc( sizeof(char) * (size) );
54 return newStr;
55 }
56
CuStrCopy(const char * old)57 char* CuStrCopy(const char* old)
58 {
59 int len = strlen(old);
60 char* newStr = CuStrAlloc(len + 1);
61 strcpy(newStr, old);
62 return newStr;
63 }
64
65 /*-------------------------------------------------------------------------*
66 * CuString
67 *-------------------------------------------------------------------------*/
68
CuStringInit(CuString * str)69 void CuStringInit(CuString* str)
70 {
71 str->length = 0;
72 str->size = STRING_MAX;
73 str->buffer = (char*) malloc(sizeof(char) * str->size);
74 str->buffer[0] = '\0';
75 }
76
CuStringNew(void)77 CuString* CuStringNew(void)
78 {
79 CuString* str = (CuString*) malloc(sizeof(CuString));
80 str->length = 0;
81 str->size = STRING_MAX;
82 str->buffer = (char*) malloc(sizeof(char) * str->size);
83 str->buffer[0] = '\0';
84 return str;
85 }
86
CuStringResize(CuString * str,int newSize)87 void CuStringResize(CuString* str, int newSize)
88 {
89 str->buffer = (char*) realloc(str->buffer, sizeof(char) * newSize);
90 str->size = newSize;
91 }
92
CuStringAppend(CuString * str,const char * text)93 void CuStringAppend(CuString* str, const char* text)
94 {
95 int length;
96
97 if (text == NULL) {
98 text = "NULL";
99 }
100
101 length = strlen(text);
102 if (str->length + length + 1 >= str->size)
103 CuStringResize(str, str->length + length + 1 + STRING_INC);
104 str->length += length;
105 strcat(str->buffer, text);
106 }
107
CuStringAppendChar(CuString * str,char ch)108 void CuStringAppendChar(CuString* str, char ch)
109 {
110 char text[2];
111 text[0] = ch;
112 text[1] = '\0';
113 CuStringAppend(str, text);
114 }
115
CuStringAppendFormat(CuString * str,const char * format,...)116 void CuStringAppendFormat(CuString* str, const char* format, ...)
117 {
118 va_list argp;
119 char buf[HUGE_STRING_LEN];
120 va_start(argp, format);
121 vsprintf(buf, format, argp);
122 va_end(argp);
123 CuStringAppend(str, buf);
124 }
125
CuStringInsert(CuString * str,const char * text,int pos)126 void CuStringInsert(CuString* str, const char* text, int pos)
127 {
128 int length = strlen(text);
129 if (pos > str->length)
130 pos = str->length;
131 if (str->length + length + 1 >= str->size)
132 CuStringResize(str, str->length + length + 1 + STRING_INC);
133 memmove(str->buffer + pos + length, str->buffer + pos, (str->length - pos) + 1);
134 str->length += length;
135 memcpy(str->buffer + pos, text, length);
136 }
137
CuStringFree(CuString * str)138 void CuStringFree(CuString* str) {
139 if (!str) return;
140 free(str->buffer);
141 free(str);
142 }
143
144 /*-------------------------------------------------------------------------*
145 * CuTest
146 *-------------------------------------------------------------------------*/
147
CuTestInit(CuTest * t,const char * name,TestFunction function)148 void CuTestInit(CuTest* t, const char* name, TestFunction function)
149 {
150 t->name = CuStrCopy(name);
151 t->failed = 0;
152 t->ran = 0;
153 t->message = NULL;
154 t->function = function;
155 t->jumpBuf = NULL;
156 }
157
CuTestFree(CuTest * t)158 void CuTestFree(CuTest* t) {
159 if (!t) return;
160 free((void*)t->name);
161 free((void*)t->message);
162 free(t);
163 }
164
CuTestNew(const char * name,TestFunction function)165 CuTest* CuTestNew(const char* name, TestFunction function)
166 {
167 CuTest* tc = CU_ALLOC(CuTest);
168 CuTestInit(tc, name, function);
169 return tc;
170 }
171
CuTestRun(CuTest * tc)172 void CuTestRun(CuTest* tc)
173 {
174 jmp_buf buf;
175 tc->jumpBuf = &buf;
176 if (setjmp(buf) == 0)
177 {
178 tc->ran = 1;
179 (tc->function)(tc);
180 }
181 tc->jumpBuf = 0;
182 }
183
CuFailInternal(CuTest * tc,const char * file,int line,CuString * string)184 static void CuFailInternal(CuTest* tc, const char* file, int line, CuString* string)
185 {
186 char buf[HUGE_STRING_LEN];
187
188 sprintf(buf, "%s:%d: ", file, line);
189 CuStringInsert(string, buf, 0);
190
191 if (CUTEST_DIE_ON_FAIL) {
192 printf("Dying from TEST_DIE.\n");
193 assert(0);
194 }
195
196 tc->failed = 1;
197 tc->message = string->buffer;
198 if (tc->jumpBuf != 0) longjmp(*(tc->jumpBuf), 0);
199 }
200
CuFail_Line(CuTest * tc,const char * file,int line,const char * message2,const char * message)201 void CuFail_Line(CuTest* tc, const char* file, int line, const char* message2, const char* message)
202 {
203 CuString string;
204
205 CuStringInit(&string);
206 if (message2 != NULL)
207 {
208 CuStringAppend(&string, message2);
209 CuStringAppend(&string, ": ");
210 }
211 CuStringAppend(&string, message);
212 CuFailInternal(tc, file, line, &string);
213 }
214
CuAssert_Line(CuTest * tc,const char * file,int line,const char * message,int condition)215 void CuAssert_Line(CuTest* tc, const char* file, int line, const char* message, int condition)
216 {
217 if (condition) return;
218 CuFail_Line(tc, file, line, NULL, message);
219 }
220
CuAssertStrEquals_LineMsg(CuTest * tc,const char * file,int line,const char * message,const char * expected,const char * actual)221 void CuAssertStrEquals_LineMsg(CuTest* tc, const char* file, int line, const char* message,
222 const char* expected, const char* actual)
223 {
224 CuString string;
225 if ((expected == NULL && actual == NULL) ||
226 (expected != NULL && actual != NULL &&
227 strcmp(expected, actual) == 0))
228 {
229 return;
230 }
231
232 CuStringInit(&string);
233 if (message != NULL)
234 {
235 CuStringAppend(&string, message);
236 CuStringAppend(&string, ": ");
237 }
238 CuStringAppend(&string, "expected <");
239 CuStringAppend(&string, expected);
240 CuStringAppend(&string, "> but was <");
241 CuStringAppend(&string, actual);
242 CuStringAppend(&string, ">");
243 CuFailInternal(tc, file, line, &string);
244 }
245
CuAssertIntEquals_LineMsg(CuTest * tc,const char * file,int line,const char * message,int expected,int actual)246 void CuAssertIntEquals_LineMsg(CuTest* tc, const char* file, int line, const char* message,
247 int expected, int actual)
248 {
249 char buf[STRING_MAX];
250 if (expected == actual) return;
251 sprintf(buf, "expected <%d> but was <%d>", expected, actual);
252 CuFail_Line(tc, file, line, message, buf);
253 }
254
CuAssertDblEquals_LineMsg(CuTest * tc,const char * file,int line,const char * message,double expected,double actual,double delta)255 void CuAssertDblEquals_LineMsg(CuTest* tc, const char* file, int line, const char* message,
256 double expected, double actual, double delta)
257 {
258 char buf[STRING_MAX];
259 if (fabs(expected - actual) <= delta) return;
260 sprintf(buf, "expected <%lf> but was <%lf>", expected, actual);
261 CuFail_Line(tc, file, line, message, buf);
262 }
263
CuAssertPtrEquals_LineMsg(CuTest * tc,const char * file,int line,const char * message,const void * expected,const void * actual)264 void CuAssertPtrEquals_LineMsg(CuTest* tc, const char* file, int line, const char* message,
265 const void* expected, const void* actual)
266 {
267 char buf[STRING_MAX];
268 if (expected == actual) return;
269 sprintf(buf, "expected pointer <0x%p> but was <0x%p>", expected, actual);
270 CuFail_Line(tc, file, line, message, buf);
271 }
272
273
274 /*-------------------------------------------------------------------------*
275 * CuSuite
276 *-------------------------------------------------------------------------*/
277
CuSuiteInit(CuSuite * testSuite)278 void CuSuiteInit(CuSuite* testSuite)
279 {
280 testSuite->count = 0;
281 testSuite->failCount = 0;
282 }
283
CuSuiteNew(void)284 CuSuite* CuSuiteNew(void)
285 {
286 CuSuite* testSuite = CU_ALLOC(CuSuite);
287 CuSuiteInit(testSuite);
288 return testSuite;
289 }
290
CuSuiteFree(CuSuite * cs)291 void CuSuiteFree(CuSuite* cs) {
292 int i;
293 if (!cs) return;
294 for (i=0; i<cs->count; i++) {
295 CuTestFree(cs->list[i]);
296 }
297 free(cs);
298 }
299
CuSuiteAdd(CuSuite * testSuite,CuTest * testCase)300 void CuSuiteAdd(CuSuite* testSuite, CuTest *testCase)
301 {
302 assert(testSuite->count < MAX_TEST_CASES);
303 testSuite->list[testSuite->count] = testCase;
304 testSuite->count++;
305 }
306
CuSuiteAddSuite(CuSuite * testSuite,CuSuite * testSuite2)307 void CuSuiteAddSuite(CuSuite* testSuite, CuSuite* testSuite2)
308 {
309 int i;
310 for (i = 0 ; i < testSuite2->count ; ++i)
311 {
312 CuTest* testCase = testSuite2->list[i];
313 CuSuiteAdd(testSuite, testCase);
314 }
315 }
316
CuSuiteRun(CuSuite * testSuite)317 void CuSuiteRun(CuSuite* testSuite)
318 {
319 int i;
320 for (i = 0 ; i < testSuite->count ; ++i)
321 {
322 CuTest* testCase = testSuite->list[i];
323 CuTestRun(testCase);
324 if (testCase->failed) { testSuite->failCount += 1; }
325 }
326 }
327
CuSuiteSummary(CuSuite * testSuite,CuString * summary)328 void CuSuiteSummary(CuSuite* testSuite, CuString* summary)
329 {
330 int i;
331 for (i = 0 ; i < testSuite->count ; ++i)
332 {
333 CuTest* testCase = testSuite->list[i];
334 CuStringAppend(summary, testCase->failed ? "F" : ".");
335 }
336 CuStringAppend(summary, "\n\n");
337 }
338
CuSuiteDetails(CuSuite * testSuite,CuString * details)339 void CuSuiteDetails(CuSuite* testSuite, CuString* details)
340 {
341 int i;
342 int failCount = 0;
343
344 if (testSuite->failCount == 0)
345 {
346 int passCount = testSuite->count - testSuite->failCount;
347 const char* testWord = passCount == 1 ? "test" : "tests";
348 CuStringAppendFormat(details, "OK (%d %s)\n", passCount, testWord);
349 }
350 else
351 {
352 if (testSuite->failCount == 1)
353 CuStringAppend(details, "There was 1 failure:\n");
354 else
355 CuStringAppendFormat(details, "There were %d failures:\n", testSuite->failCount);
356
357 for (i = 0 ; i < testSuite->count ; ++i)
358 {
359 CuTest* testCase = testSuite->list[i];
360 if (testCase->failed)
361 {
362 failCount++;
363 CuStringAppendFormat(details, "%d) %s: %s\n",
364 failCount, testCase->name, testCase->message);
365 }
366 }
367 CuStringAppend(details, "\n!!!FAILURES!!!\n");
368
369 CuStringAppendFormat(details, "Runs: %d ", testSuite->count);
370 CuStringAppendFormat(details, "Passes: %d ", testSuite->count - testSuite->failCount);
371 CuStringAppendFormat(details, "Fails: %d\n", testSuite->failCount);
372 }
373 }
374