• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include <assert.h>
2 #include <setjmp.h>
3 #include <stdlib.h>
4 #include <stdio.h>
5 #include <string.h>
6 #include <math.h>
7 
8 #include "CuTest.h"
9 
10 /*-------------------------------------------------------------------------*
11  * CuStr
12  *-------------------------------------------------------------------------*/
13 
CuStrAlloc(int size)14 char* CuStrAlloc(int size)
15 {
16 	char* newStr = (char*) malloc( sizeof(char) * (size) );
17 	return newStr;
18 }
19 
CuStrCopy(const char * old)20 char* CuStrCopy(const char* old)
21 {
22 	int len = strlen(old);
23 	char* newStr = CuStrAlloc(len + 1);
24 	strcpy(newStr, old);
25 	return newStr;
26 }
27 
28 /*-------------------------------------------------------------------------*
29  * CuString
30  *-------------------------------------------------------------------------*/
31 
CuStringInit(CuString * str)32 void CuStringInit(CuString* str)
33 {
34 	str->length = 0;
35 	str->size = STRING_MAX;
36 	str->buffer = (char*) malloc(sizeof(char) * str->size);
37 	str->buffer[0] = '\0';
38 }
39 
CuStringNew(void)40 CuString* CuStringNew(void)
41 {
42 	CuString* str = (CuString*) malloc(sizeof(CuString));
43 	str->length = 0;
44 	str->size = STRING_MAX;
45 	str->buffer = (char*) malloc(sizeof(char) * str->size);
46 	str->buffer[0] = '\0';
47 	return str;
48 }
49 
CuStringDelete(CuString * str)50 void CuStringDelete(CuString *str)
51 {
52         if (!str) return;
53         free(str->buffer);
54         free(str);
55 }
56 
CuStringResize(CuString * str,int newSize)57 void CuStringResize(CuString* str, int newSize)
58 {
59 	str->buffer = (char*) realloc(str->buffer, sizeof(char) * newSize);
60 	str->size = newSize;
61 }
62 
CuStringAppend(CuString * str,const char * text)63 void CuStringAppend(CuString* str, const char* text)
64 {
65 	int length;
66 
67 	if (text == NULL) {
68 		text = "NULL";
69 	}
70 
71 	length = strlen(text);
72 	if (str->length + length + 1 >= str->size)
73 		CuStringResize(str, str->length + length + 1 + STRING_INC);
74 	str->length += length;
75 	strcat(str->buffer, text);
76 }
77 
CuStringAppendChar(CuString * str,char ch)78 void CuStringAppendChar(CuString* str, char ch)
79 {
80 	char text[2];
81 	text[0] = ch;
82 	text[1] = '\0';
83 	CuStringAppend(str, text);
84 }
85 
CuStringAppendFormat(CuString * str,const char * format,...)86 void CuStringAppendFormat(CuString* str, const char* format, ...)
87 {
88 	va_list argp;
89 	char buf[HUGE_STRING_LEN];
90 	va_start(argp, format);
91 	vsprintf(buf, format, argp);
92 	va_end(argp);
93 	CuStringAppend(str, buf);
94 }
95 
CuStringInsert(CuString * str,const char * text,int pos)96 void CuStringInsert(CuString* str, const char* text, int pos)
97 {
98 	int length = strlen(text);
99 	if (pos > str->length)
100 		pos = str->length;
101 	if (str->length + length + 1 >= str->size)
102 		CuStringResize(str, str->length + length + 1 + STRING_INC);
103 	memmove(str->buffer + pos + length, str->buffer + pos, (str->length - pos) + 1);
104 	str->length += length;
105 	memcpy(str->buffer + pos, text, length);
106 }
107 
108 /*-------------------------------------------------------------------------*
109  * CuTest
110  *-------------------------------------------------------------------------*/
111 
CuTestInit(CuTest * t,const char * name,TestFunction function)112 void CuTestInit(CuTest* t, const char* name, TestFunction function)
113 {
114 	t->name = CuStrCopy(name);
115 	t->failed = 0;
116 	t->ran = 0;
117 	t->message = NULL;
118 	t->function = function;
119 	t->jumpBuf = NULL;
120 }
121 
CuTestNew(const char * name,TestFunction function)122 CuTest* CuTestNew(const char* name, TestFunction function)
123 {
124 	CuTest* tc = CU_ALLOC(CuTest);
125 	CuTestInit(tc, name, function);
126 	return tc;
127 }
128 
CuTestDelete(CuTest * t)129 void CuTestDelete(CuTest *t)
130 {
131         if (!t) return;
132         free(t->name);
133         free(t);
134 }
135 
CuTestRun(CuTest * tc)136 void CuTestRun(CuTest* tc)
137 {
138 	jmp_buf buf;
139 	tc->jumpBuf = &buf;
140 	if (setjmp(buf) == 0)
141 	{
142 		tc->ran = 1;
143 		(tc->function)(tc);
144 	}
145 	tc->jumpBuf = 0;
146 }
147 
CuFailInternal(CuTest * tc,const char * file,int line,CuString * string)148 static void CuFailInternal(CuTest* tc, const char* file, int line, CuString* string)
149 {
150 	char buf[HUGE_STRING_LEN];
151 
152 	sprintf(buf, "%s:%d: ", file, line);
153 	CuStringInsert(string, buf, 0);
154 
155 	tc->failed = 1;
156 	tc->message = string->buffer;
157 	if (tc->jumpBuf != 0) longjmp(*(tc->jumpBuf), 0);
158 }
159 
CuFail_Line(CuTest * tc,const char * file,int line,const char * message2,const char * message)160 void CuFail_Line(CuTest* tc, const char* file, int line, const char* message2, const char* message)
161 {
162 	CuString string;
163 
164 	CuStringInit(&string);
165 	if (message2 != NULL)
166 	{
167 		CuStringAppend(&string, message2);
168 		CuStringAppend(&string, ": ");
169 	}
170 	CuStringAppend(&string, message);
171 	CuFailInternal(tc, file, line, &string);
172 }
173 
CuAssert_Line(CuTest * tc,const char * file,int line,const char * message,int condition)174 void CuAssert_Line(CuTest* tc, const char* file, int line, const char* message, int condition)
175 {
176 	if (condition) return;
177 	CuFail_Line(tc, file, line, NULL, message);
178 }
179 
CuAssertStrEquals_LineMsg(CuTest * tc,const char * file,int line,const char * message,const char * expected,const char * actual)180 void CuAssertStrEquals_LineMsg(CuTest* tc, const char* file, int line, const char* message,
181 	const char* expected, const char* actual)
182 {
183 	CuString string;
184 	if ((expected == NULL && actual == NULL) ||
185 	    (expected != NULL && actual != NULL &&
186 	     strcmp(expected, actual) == 0))
187 	{
188 		return;
189 	}
190 
191 	CuStringInit(&string);
192 	if (message != NULL)
193 	{
194 		CuStringAppend(&string, message);
195 		CuStringAppend(&string, ": ");
196 	}
197 	CuStringAppend(&string, "expected <");
198 	CuStringAppend(&string, expected);
199 	CuStringAppend(&string, "> but was <");
200 	CuStringAppend(&string, actual);
201 	CuStringAppend(&string, ">");
202 	CuFailInternal(tc, file, line, &string);
203 }
204 
CuAssertIntEquals_LineMsg(CuTest * tc,const char * file,int line,const char * message,int expected,int actual)205 void CuAssertIntEquals_LineMsg(CuTest* tc, const char* file, int line, const char* message,
206 	int expected, int actual)
207 {
208 	char buf[STRING_MAX];
209 	if (expected == actual) return;
210 	sprintf(buf, "expected <%d> but was <%d>", expected, actual);
211 	CuFail_Line(tc, file, line, message, buf);
212 }
213 
CuAssertLongIntEquals_LineMsg(CuTest * tc,const char * file,int line,const char * message,long int expected,long int actual)214 void CuAssertLongIntEquals_LineMsg(CuTest *tc, const char *file, int line, const char *message,
215     long int expected, long int actual)
216 {
217 	char buf[STRING_MAX];
218 	if (expected == actual) return;
219 	sprintf(buf, "expected <%ld> but was <%ld>", expected, actual);
220 	CuFail_Line(tc, file, line, message, buf);
221 }
222 
CuAssertDblEquals_LineMsg(CuTest * tc,const char * file,int line,const char * message,double expected,double actual,double delta)223 void CuAssertDblEquals_LineMsg(CuTest* tc, const char* file, int line, const char* message,
224 	double expected, double actual, double delta)
225 {
226 	char buf[STRING_MAX];
227 	if (fabs(expected - actual) <= delta) return;
228 	sprintf(buf, "expected <%f> but was <%f>", expected, actual);
229 
230 	CuFail_Line(tc, file, line, message, buf);
231 }
232 
CuAssertPtrEquals_LineMsg(CuTest * tc,const char * file,int line,const char * message,const void * expected,const void * actual)233 void CuAssertPtrEquals_LineMsg(CuTest* tc, const char* file, int line, const char* message,
234 	const void* expected, const void* actual)
235 {
236 	char buf[STRING_MAX];
237 	if (expected == actual) return;
238 	sprintf(buf, "expected pointer <0x%p> but was <0x%p>", expected, actual);
239 	CuFail_Line(tc, file, line, message, buf);
240 }
241 
242 
243 /*-------------------------------------------------------------------------*
244  * CuSuite
245  *-------------------------------------------------------------------------*/
246 
CuSuiteInit(CuSuite * testSuite)247 void CuSuiteInit(CuSuite* testSuite)
248 {
249 	testSuite->count = 0;
250 	testSuite->failCount = 0;
251         memset(testSuite->list, 0, sizeof(testSuite->list));
252 }
253 
CuSuiteNew(void)254 CuSuite* CuSuiteNew(void)
255 {
256 	CuSuite* testSuite = CU_ALLOC(CuSuite);
257 	CuSuiteInit(testSuite);
258 	return testSuite;
259 }
260 
CuSuiteDelete(CuSuite * testSuite)261 void CuSuiteDelete(CuSuite *testSuite)
262 {
263         unsigned int n;
264         for (n=0; n < MAX_TEST_CASES; n++)
265         {
266                 if (testSuite->list[n])
267                 {
268                         CuTestDelete(testSuite->list[n]);
269                 }
270         }
271         free(testSuite);
272 
273 }
274 
CuSuiteAdd(CuSuite * testSuite,CuTest * testCase)275 void CuSuiteAdd(CuSuite* testSuite, CuTest *testCase)
276 {
277 	assert(testSuite->count < MAX_TEST_CASES);
278 	testSuite->list[testSuite->count] = testCase;
279 	testSuite->count++;
280 }
281 
CuSuiteAddSuite(CuSuite * testSuite,CuSuite * testSuite2)282 void CuSuiteAddSuite(CuSuite* testSuite, CuSuite* testSuite2)
283 {
284 	int i;
285 	for (i = 0 ; i < testSuite2->count ; ++i)
286 	{
287 		CuTest* testCase = testSuite2->list[i];
288 		CuSuiteAdd(testSuite, testCase);
289 	}
290 }
291 
CuSuiteRun(CuSuite * testSuite)292 void CuSuiteRun(CuSuite* testSuite)
293 {
294 	int i;
295 	for (i = 0 ; i < testSuite->count ; ++i)
296 	{
297 		CuTest* testCase = testSuite->list[i];
298 		CuTestRun(testCase);
299 		if (testCase->failed) { testSuite->failCount += 1; }
300 	}
301 }
302 
CuSuiteSummary(CuSuite * testSuite,CuString * summary)303 void CuSuiteSummary(CuSuite* testSuite, CuString* summary)
304 {
305 	int i;
306 	for (i = 0 ; i < testSuite->count ; ++i)
307 	{
308 		CuTest* testCase = testSuite->list[i];
309 		CuStringAppend(summary, testCase->failed ? "F" : ".");
310 	}
311 	CuStringAppend(summary, "\n\n");
312 }
313 
CuSuiteDetails(CuSuite * testSuite,CuString * details)314 void CuSuiteDetails(CuSuite* testSuite, CuString* details)
315 {
316 	int i;
317 	int failCount = 0;
318 
319 	if (testSuite->failCount == 0)
320 	{
321 		int passCount = testSuite->count - testSuite->failCount;
322 		const char* testWord = passCount == 1 ? "test" : "tests";
323 		CuStringAppendFormat(details, "OK (%d %s)\n", passCount, testWord);
324 	}
325 	else
326 	{
327 		if (testSuite->failCount == 1)
328 			CuStringAppend(details, "There was 1 failure:\n");
329 		else
330 			CuStringAppendFormat(details, "There were %d failures:\n", testSuite->failCount);
331 
332 		for (i = 0 ; i < testSuite->count ; ++i)
333 		{
334 			CuTest* testCase = testSuite->list[i];
335 			if (testCase->failed)
336 			{
337 				failCount++;
338 				CuStringAppendFormat(details, "%d) %s: %s\n",
339 					failCount, testCase->name, testCase->message);
340 			}
341 		}
342 		CuStringAppend(details, "\n!!!FAILURES!!!\n");
343 
344 		CuStringAppendFormat(details, "Runs: %d ",   testSuite->count);
345 		CuStringAppendFormat(details, "Passes: %d ", testSuite->count - testSuite->failCount);
346 		CuStringAppendFormat(details, "Fails: %d\n",  testSuite->failCount);
347 	}
348 }
349