source: trunk/src/CuTest.c @ 440

Last change on this file since 440 was 227, checked in by katerina, 13 years ago

Fix warnings with -fstack-check

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