Imported Upstream version 1.3.0
[platform/upstream/augeas.git] / tests / cutest.c
1 /*
2  * This code is based on CuTest by Asim Jalis
3  * http://sourceforge.net/projects/cutest/
4  *
5  * The license for the original code is
6  * LICENSE
7  *
8  * Copyright (c) 2003 Asim Jalis
9  *
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.
13  *
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:
17  *
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.
22  *
23  * 2. Altered source versions must be plainly marked as such, and must not be
24  * misrepresented as being the original software.
25  *
26  * 3. This notice may not be removed or altered from any source distribution.
27  */
28
29 #include <config.h>
30
31 #include <sys/wait.h>
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 #include "memory.h"
41
42 #define HUGE_STRING_LEN 8192
43 #define STRING_MAX              256
44
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");      \
48         abort();                                                        \
49     }
50
51 void die_oom(void) {
52     printf("Ran out of memory. Send more\n");
53     exit(2);
54 }
55
56 /*-------------------------------------------------------------------------*
57  * CuTest
58  *-------------------------------------------------------------------------*/
59
60 void CuTestInit(CuTest* t, const char* name, TestFunction function) {
61         t->name = strdup(name);
62         t->failed = 0;
63         t->ran = 0;
64         t->message = NULL;
65         t->function = function;
66         t->jumpBuf = NULL;
67 }
68
69 CuTest* CuTestNew(const char* name, TestFunction function) {
70         CuTest* tc = NULL;
71     if (ALLOC(tc) < 0)
72         die_oom();
73         CuTestInit(tc, name, function);
74         return tc;
75 }
76
77 void CuTestRun(CuTest* tc, TestFunction setup, TestFunction teardown) {
78         jmp_buf buf;
79
80     if (getenv("CUTEST") && STRNEQ(getenv("CUTEST"), tc->name))
81         return;
82         tc->jumpBuf = &buf;
83         if (setjmp(buf) == 0) {
84         if (setup)
85             (setup)(tc);
86                 tc->ran = 1;
87                 (tc->function)(tc);
88         }
89     if (teardown && setjmp(buf) == 0) {
90         (teardown)(tc);
91     }
92         tc->jumpBuf = 0;
93 }
94
95 static void CuFailInternal(CuTest* tc, const char* file, int line,
96                            const char *string) {
97         char *buf = NULL;
98
99         asprintf_or_die(&buf, "%s:%d: %s", file, line, string);
100
101         tc->failed = 1;
102         tc->message = buf;
103         if (tc->jumpBuf != 0) longjmp(*(tc->jumpBuf), 0);
104 }
105
106 void CuFail_Line(CuTest* tc, const char* file, int line,
107                  const char* message2, const char* message) {
108     char *string = NULL;
109
110         if (message2 != NULL) {
111                 asprintf_or_die(&string, "%s:%s", message2, message);
112         } else {
113         string = strdup(message);
114     }
115         CuFailInternal(tc, file, line, string);
116 }
117
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);
122 }
123
124 void CuAssertStrEquals_LineMsg(CuTest* tc, const char* file, int line,
125                                const char* message,
126                                const char* expected, const char* actual) {
127         char *string = NULL;
128
129         if ((expected == NULL && actual == NULL) ||
130             (expected != NULL && actual != NULL &&
131              strcmp(expected, actual) == 0))
132         {
133             return;
134         }
135
136         if (message != NULL) {
137         asprintf_or_die(&string, "%s: expected <%s> but was <%s>", message,
138                         expected, actual);
139         } else {
140         asprintf_or_die(&string, "expected <%s> but was <%s>", expected, actual);
141     }
142         CuFailInternal(tc, file, line, string);
143 }
144
145 void CuAssertStrNotEqual_LineMsg(CuTest* tc, const char* file, int line,
146                                  const char* message,
147                                  const char* expected, const char* actual) {
148         char *string = NULL;
149
150     if (expected != NULL && actual != NULL && strcmp(expected, actual) != 0)
151         return;
152
153         if (message != NULL) {
154         asprintf_or_die(&string, "%s: expected <%s> but was <%s>", message,
155                         expected, actual);
156         } else {
157         asprintf_or_die(&string, "expected <%s> but was <%s>", expected, actual);
158     }
159         CuFailInternal(tc, file, line, string);
160 }
161
162 void CuAssertIntEquals_LineMsg(CuTest* tc, const char* file, int line,
163                                const char* message,
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);
169 }
170
171 void CuAssertDblEquals_LineMsg(CuTest* tc, const char* file, int line,
172                                const char* message,
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);
178 }
179
180 void CuAssertPtrEquals_LineMsg(CuTest* tc, const char* file, int line,
181                                const char* message,
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);
187 }
188
189 void CuAssertPtrNotEqual_LineMsg(CuTest* tc, const char* file, int line,
190                                  const char* message,
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>",
195             expected, actual);
196         CuFail_Line(tc, file, line, message, buf);
197 }
198
199
200 /*-------------------------------------------------------------------------*
201  * CuSuite
202  *-------------------------------------------------------------------------*/
203
204 void CuSuiteInit(CuSuite* testSuite) {
205         testSuite->count = 0;
206         testSuite->failCount = 0;
207 }
208
209 CuSuite* CuSuiteNew(void) {
210         CuSuite* testSuite = NULL;
211     if (ALLOC(testSuite) < 0)
212         die_oom();
213         CuSuiteInit(testSuite);
214         return testSuite;
215 }
216
217 void CuSuiteSetup(CuSuite *testSuite,
218                   TestFunction setup, TestFunction teardown) {
219     testSuite->setup = setup;
220     testSuite->teardown = teardown;
221 }
222
223 void CuSuiteAdd(CuSuite* testSuite, CuTest *testCase) {
224         assert(testSuite->count < MAX_TEST_CASES);
225         testSuite->list[testSuite->count] = testCase;
226         testSuite->count++;
227 }
228
229 void CuSuiteAddSuite(CuSuite* testSuite, CuSuite* testSuite2) {
230         int i;
231         for (i = 0 ; i < testSuite2->count ; ++i)
232         {
233             CuTest* testCase = testSuite2->list[i];
234             CuSuiteAdd(testSuite, testCase);
235         }
236 }
237
238 void CuSuiteRun(CuSuite* testSuite) {
239         int i;
240         for (i = 0 ; i < testSuite->count ; ++i)
241         {
242             CuTest* testCase = testSuite->list[i];
243             CuTestRun(testCase, testSuite->setup, testSuite->teardown);
244             if (testCase->failed) { testSuite->failCount += 1; }
245         }
246 }
247
248 static void string_append(char **s, const char *p) {
249     if (*s == NULL) {
250         *s = strdup(p);
251     } else {
252         int len = strlen(*s) + strlen(p) + 1;
253         *s = realloc(*s, len);
254         if (*s == NULL)
255             die_oom();
256         strcat(*s, p);
257     }
258 }
259
260 void CuSuiteSummary(CuSuite* testSuite, char **summary) {
261         int i;
262
263         for (i = 0 ; i < testSuite->count ; ++i)
264         {
265             CuTest* testCase = testSuite->list[i];
266             string_append(summary, testCase->failed ? "F" : ".");
267         }
268         string_append(summary, "\n\n");
269 }
270
271 void CuSuiteDetails(CuSuite* testSuite, char **details) {
272         int i;
273         int failCount = 0;
274     char *s = NULL;
275
276         if (testSuite->failCount == 0)
277         {
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);
282             free(s);
283         } else {
284                 if (testSuite->failCount == 1)
285                         string_append(details, "There was 1 failure:\n");
286                 else {
287             asprintf_or_die(&s, "There were %d failures:\n",
288                             testSuite->failCount);
289             string_append(details, s);
290             free(s);
291         }
292                 for (i = 0 ; i < testSuite->count ; ++i) {
293                         CuTest* testCase = testSuite->list[i];
294                         if (testCase->failed) {
295                                 failCount++;
296                                 asprintf_or_die(&s, "%d) %s:\n%s\n",
297                          failCount, testCase->name, testCase->message);
298                 string_append(details, s);
299                 free(s);
300                         }
301                 }
302                 string_append(details, "\n!!!FAILURES!!!\n");
303
304                 asprintf_or_die(&s, "Runs: %d ",   testSuite->count);
305         string_append(details, s);
306         free(s);
307
308         asprintf_or_die(&s, "Passes: %d ",
309                         testSuite->count - testSuite->failCount);
310         string_append(details, s);
311         free(s);
312
313                 asprintf_or_die(&s, "Fails: %d\n",  testSuite->failCount);
314         string_append(details, s);
315         free(s);
316         }
317 }
318
319 /*
320  * Test utilities
321  */
322 void run(CuTest *tc, const char *format, ...) {
323     char *command;
324     va_list args;
325     int r;
326
327     va_start(args, format);
328     r = vasprintf(&command, format, args);
329     va_end (args);
330     if (r < 0)
331         CuFail(tc, "Failed to format command (out of memory)");
332     r = system(command);
333     if (r < 0 || (WIFEXITED(r) && WEXITSTATUS(r) != 0)) {
334         char *msg;
335         r = asprintf(&msg, "Command %s failed with status %d\n",
336                      command, WEXITSTATUS(r));
337         CuFail(tc, msg);
338         free(msg);
339     }
340     free(command);
341 }
342
343 int should_run(const char *name, int argc, char **argv) {
344     if (argc == 0)
345         return 1;
346     for (int i=0; i < argc; i++)
347         if (STREQ(argv[i], name))
348             return 1;
349     return 0;
350 }
351
352 /*
353  * Local variables:
354  *  indent-tabs-mode: nil
355  *  c-indent-level: 4
356  *  c-basic-offset: 4
357  *  tab-width: 4
358  * End:
359  */