This repository has been archived by the owner on Feb 11, 2021. It is now read-only.
/
runner.c
314 lines (262 loc) · 7.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/*
Copyright (C) 2011 Markus Kauppila <markus.kauppila@gmail.com>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
21
#include "SDL/SDL.h"
22
23
24
25
26
27
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
28
#include "SDL_test.h"
29
30
//!< Function pointer to a test case function
31
32
33
34
35
typedef void (*TestCase)(void *arg);
//!< Function pointer to a test case init function
typedef void (*TestCaseInit)(void);
//!< Function pointer to a test case quit function
typedef int (*TestCaseQuit)(void);
36
37
38
39
//!< Flag for executing tests in-process
static int execute_inproc = 0;
40
/*!
41
42
* Returns the name for the dynamic library
* which implements the test suite.
43
*
44
45
46
47
48
* (in the future: scans the test/ directory and
* returns the names of the dynamic libraries
* implementing the test suites)
*
* \return Name of the dummy test suite
49
*/
50
51
char *
ScanForTestSuites() {
52
53
#if defined(linux) || defined( __linux)
char *libName = "tests/libtest.so";
54
#else
55
char *libName = "tests/libtest.dylib";
56
#endif
57
58
59
return libName;
}
60
61
62
63
64
65
66
67
68
69
70
71
/*!
* Loads test suite which is implemented as dynamic library.
*
* \param test0,330
*
* \return Pointer to loaded test suite, or NULL if library could not be loaded
*/
void *
LoadTestSuite(char *testSuiteName)
{
void *library = SDL_LoadObject(testSuiteName);
72
if(library == NULL) {
73
fprintf(stderr, "Loading %s failed\n", testSuiteName);
74
fprintf(stderr, "%s\n", SDL_GetError());
75
76
}
77
78
79
return library;
}
80
81
82
83
/*!
* Loads the test case references from the given test suite.
* \param library Previously loaded dynamic library AKA test suite
84
* \return Pointer to array of TestCaseReferences or NULL if function failed
85
*/
86
87
88
TestCaseReference **
QueryTestCases(void *library)
{
89
TestCaseReference **(*suite)(void);
90
91
suite = (TestCaseReference **(*)(void)) SDL_LoadFunction(library, "QueryTestSuite");
92
if(suite == NULL) {
93
94
fprintf(stderr, "Loading QueryTestCaseReferences() failed.\n");
fprintf(stderr, "%s\n", SDL_GetError());
95
96
}
97
TestCaseReference **tests = suite();
98
if(tests == NULL) {
99
100
fprintf(stderr, "Failed to load test references.\n");
fprintf(stderr, "%s\n", SDL_GetError());
101
102
103
104
105
}
return tests;
}
106
107
108
109
/*!
* Loads test case from a test suite
*
110
111
* \param suite a test suite
* \param testName Name of the test that is going to be loaded
112
*
113
* \return Function Pointer (TestCase) to loaded test case, NULL if function failed
114
*/
115
116
117
TestCase
LoadTestCase(void *suite, char *testName)
{
118
TestCase test = (TestCase) SDL_LoadFunction(suite, testName);
119
if(test == NULL) {
120
121
fprintf(stderr, "Loading test failed, tests == NULL\n");
fprintf(stderr, "%s\n", SDL_GetError());
122
123
124
125
126
}
return test;
}
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
/*!
* Loads function that initialises the test case from the
* given test suite.
*
* \param suite Used test suite
*
* \return Function pointer (TestCaseInit) which points to loaded init function. NULL if function fails.
*/
TestCaseInit
LoadTestCaseInit(void *suite) {
TestCaseInit testCaseInit = (TestCaseInit) SDL_LoadFunction(suite, "_TestCaseInit");
if(testCaseInit == NULL) {
fprintf(stderr, "Loading TestCaseInit function failed, testCaseInit == NULL\n");
fprintf(stderr, "%s\n", SDL_GetError());
}
return testCaseInit;
}
/*!
* Loads function that deinitialises the executed test case from the
* given test suite.
*
* \param suite Used test suite
*
* \return Function pointer (TestCaseInit) which points to loaded init function. NULL if function fails.
*/
TestCaseQuit
LoadTestCaseQuit(void *suite) {
TestCaseQuit testCaseQuit = (TestCaseQuit) SDL_LoadFunction(suite, "_TestCaseQuit");
if(testCaseQuit == NULL) {
fprintf(stderr, "Loading TestCaseQuit function failed, testCaseQuit == NULL\n");
fprintf(stderr, "%s\n", SDL_GetError());
}
return testCaseQuit;
}
164
165
/*!
166
167
168
169
* If using out-of-proc execution of tests. This function
* will handle the return value of the child process
* and interprets it to the runner. Also prints warnings
* if child was aborted by a signela.
170
*
171
* \param stat_lock information about the exited child process
172
*
173
* \return 0 if test case succeeded, 1 otherwise
174
*/
175
176
177
178
int
HandleTestReturnValue(int stat_lock)
{
//! \todo rename to: HandleChildProcessReturnValue?
179
int returnValue = -1;
180
181
182
if(WIFEXITED(stat_lock)) {
returnValue = WEXITSTATUS(stat_lock);
183
184
} else if(WIFSIGNALED(stat_lock)) {
int signal = WTERMSIG(stat_lock);
185
fprintf(stderr, "FAILURE: test was aborted due to signal no %d\n", signal);
186
returnValue = 1;
187
188
}
189
return returnValue;
190
191
}
192
193
194
195
196
197
198
199
200
201
/*!
* Prints usage information
*/
void printUsage() {
printf("Usage: ./runner [--in-proc] [--help]\n");
printf("Options:\n");
printf(" --in-proc Executes tests in-process\n");
printf(" --help Print this help\n");
}
202
203
/*!
* Parse command line arguments
204
205
206
*
* \param argc Count of command line arguments
* \param argv Array of commond lines arguments
207
208
209
210
211
212
213
214
*/
void
ParseOptions(int argc, char *argv[])
{
int i;
for (i = 1; i < argc; ++i) {
const char *arg = argv[i];
215
if(SDL_strcmp(arg, "--in-proc") == 0) {
216
217
execute_inproc = 1;
}
218
else if(SDL_strcmp(arg, "--help") == 0 || SDL_strcmp(arg, "-h") == 0) {
219
220
221
222
223
printUsage();
exit(0);
} else {
printf("runner: unknown command '%s'\n", arg);
printUsage();
224
225
exit(0);
}
226
227
}
}
228
229
230
231
232
233
234
/*!
* Entry point for test runner
*
* \param argc Count of command line arguments
* \param argv Array of commond lines arguments
*/
235
236
237
238
int
main(int argc, char *argv[])
{
ParseOptions(argc, argv);
239
240
// print: Testing against SDL version fuu (rev: bar) if verbose == true
241
242
243
244
245
int failureCount = 0, passCount = 0;
const Uint32 startTicks = SDL_GetTicks();
246
247
char *testSuiteName = ScanForTestSuites();
void *suite = LoadTestSuite(testSuiteName);
248
TestCaseReference **tests = QueryTestCases(suite);
249
250
251
252
253
TestCaseReference *reference = NULL;
int counter = 0;
for(reference = tests[counter]; reference; reference = tests[++counter]) {
254
if(reference->enabled == TEST_DISABLED) {
255
printf("Test %s (in %s) disabled. Omitting...\n", reference->name, testSuiteName);
256
} else {
257
258
char *testname = reference->name;
259
printf("Running %s (in %s):\n", testname, testSuiteName);
260
261
262
263
264
TestCaseInit testCaseInit = LoadTestCaseInit(suite);
TestCaseQuit testCaseQuit = LoadTestCaseQuit(suite);
TestCase test = (TestCase) LoadTestCase(suite, testname);
265
266
int retVal = 1;
if(execute_inproc) {
267
268
269
270
271
testCaseInit();
test(0x0);
retVal = testCaseQuit();
272
} else {
273
274
int childpid = fork();
if(childpid == 0) {
275
276
277
278
279
testCaseInit();
test(0x0);
return testCaseQuit();
280
} else {
281
282
283
284
int stat_lock = -1;
int child = wait(&stat_lock);
retVal = HandleTestReturnValue(stat_lock);
285
}
286
}
287
288
289
if(retVal) {
failureCount++;
290
291
292
293
294
if(retVal == 2) {
printf("%s (in %s): FAILED -> No asserts\n", testname, testSuiteName);
} else {
printf("%s (in %s): FAILED\n", testname, testSuiteName);
}
295
296
} else {
passCount++;
297
printf("%s (in %s): ok\n", testname, testSuiteName);
298
}
299
}
300
301
printf("\n");
302
303
}
304
SDL_UnloadObject(suite);
305
306
307
const Uint32 endTicks = SDL_GetTicks();
308
printf("Ran %d tests in %0.5f seconds.\n", (passCount + failureCount), (endTicks-startTicks)/1000.0f);
309
310
311
312
printf("%d tests passed\n", passCount);
printf("%d tests failed\n", failureCount);
313
314
return 0;
}