1 |
/* |
2 |
* Common code for automated test suite. |
3 |
* |
4 |
* Written by Edgar Simo "bobbens" |
5 |
* |
6 |
* Released under Public Domain. |
7 |
*/ |
8 |
|
9 |
|
10 |
#include "SDL_at.h" |
11 |
#include "SDL_stdinc.h" |
12 |
#include "SDL_error.h" |
13 |
|
14 |
#include <stdio.h> /* printf/fprintf */ |
15 |
#include <stdarg.h> /* va_list */ |
16 |
|
17 |
|
18 |
/* |
19 |
* Internal usage SDL_AT variables. |
20 |
*/ |
21 |
static char *at_suite_msg = NULL; /**< Testsuite message. */ |
22 |
static char *at_test_msg = NULL; /**< Testcase message. */ |
23 |
static int at_success = 0; /**< Number of successful testcases. */ |
24 |
static int at_failure = 0; /**< Number of failed testcases. */ |
25 |
|
26 |
|
27 |
/* |
28 |
* Global properties. |
29 |
*/ |
30 |
static int at_verbose = 0; /**< Verbosity. */ |
31 |
static int at_quiet = 0; /**< Quietness. */ |
32 |
|
33 |
|
34 |
/* |
35 |
* Prototypes. |
36 |
*/ |
37 |
static void SDL_ATcleanup (void); |
38 |
static void SDL_ATendWith( int success ); |
39 |
static void SDL_ATassertFailed( const char *msg ); |
40 |
|
41 |
|
42 |
/** |
43 |
* @brief Cleans up the automated testsuite state. |
44 |
*/ |
45 |
static void SDL_ATcleanup (void) |
46 |
{ |
47 |
if (at_suite_msg != NULL) |
48 |
SDL_free(at_suite_msg); |
49 |
at_suite_msg = NULL; |
50 |
if (at_test_msg != NULL) |
51 |
SDL_free(at_test_msg); |
52 |
at_test_msg = NULL; |
53 |
at_success = 0; |
54 |
at_failure = 0; |
55 |
} |
56 |
|
57 |
|
58 |
/** |
59 |
* @brief Begin testsuite. |
60 |
*/ |
61 |
void SDL_ATinit( const char *suite ) |
62 |
{ |
63 |
/* Do not open twice. */ |
64 |
if (at_suite_msg) { |
65 |
SDL_ATprintErr( "AT suite '%s' not closed before opening suite '%s'\n", |
66 |
at_suite_msg, suite ); |
67 |
} |
68 |
/* Must have a name. */ |
69 |
if (suite == NULL) { |
70 |
SDL_ATprintErr( "AT testsuite does not have a name.\n"); |
71 |
} |
72 |
SDL_ATcleanup(); |
73 |
at_suite_msg = SDL_strdup(suite); |
74 |
|
75 |
/* Verbose message. */ |
76 |
SDL_ATprintVerbose( 2, "--+---> Started Test Suite '%s'\n", at_suite_msg ); |
77 |
} |
78 |
|
79 |
|
80 |
/** |
81 |
* @brief Finish testsuite. |
82 |
*/ |
83 |
int SDL_ATfinish (void) |
84 |
{ |
85 |
int failed; |
86 |
|
87 |
/* Make sure initialized. */ |
88 |
if (at_suite_msg == NULL) { |
89 |
SDL_ATprintErr("Ended testcase without initializing.\n"); |
90 |
return 1; |
91 |
} |
92 |
|
93 |
/* Finished without closing testcase. */ |
94 |
if (at_test_msg) { |
95 |
SDL_ATprintErr( "AT suite '%s' finished without closing testcase '%s'\n", |
96 |
at_suite_msg, at_test_msg ); |
97 |
} |
98 |
|
99 |
/* Verbose message. */ |
100 |
SDL_ATprintVerbose( 2, "<-+---- Finished Test Suite '%s'\n", at_suite_msg ); |
101 |
|
102 |
/* Display message if verbose on failed. */ |
103 |
failed = at_failure; |
104 |
if (at_failure > 0) { |
105 |
SDL_ATprintErr( "%s : Failed %d out of %d testcases!\n", |
106 |
at_suite_msg, at_failure, at_failure+at_success ); |
107 |
} |
108 |
else { |
109 |
SDL_ATprint( "%s : All tests successful (%d)\n", |
110 |
at_suite_msg, at_success ); |
111 |
} |
112 |
|
113 |
/* Clean up. */ |
114 |
SDL_ATcleanup(); |
115 |
|
116 |
/* Return failed. */ |
117 |
return failed; |
118 |
} |
119 |
|
120 |
|
121 |
/** |
122 |
* @brief Sets a property. |
123 |
*/ |
124 |
void SDL_ATseti( int property, int value ) |
125 |
{ |
126 |
switch (property) { |
127 |
case SDL_AT_VERBOSE: |
128 |
at_verbose = value; |
129 |
break; |
130 |
|
131 |
case SDL_AT_QUIET: |
132 |
at_quiet = value; |
133 |
break; |
134 |
} |
135 |
} |
136 |
|
137 |
|
138 |
/** |
139 |
* @brief Gets a property. |
140 |
*/ |
141 |
void SDL_ATgeti( int property, int *value ) |
142 |
{ |
143 |
switch (property) { |
144 |
case SDL_AT_VERBOSE: |
145 |
*value = at_verbose; |
146 |
break; |
147 |
|
148 |
case SDL_AT_QUIET: |
149 |
*value = at_quiet; |
150 |
break; |
151 |
} |
152 |
} |
153 |
|
154 |
|
155 |
/** |
156 |
* @brief Begin testcase. |
157 |
*/ |
158 |
void SDL_ATbegin( const char *testcase ) |
159 |
{ |
160 |
/* Do not open twice. */ |
161 |
if (at_test_msg) { |
162 |
SDL_ATprintErr( "AT testcase '%s' not closed before opening testcase '%s'\n", |
163 |
at_test_msg, testcase ); |
164 |
} |
165 |
/* Must have a name. */ |
166 |
if (testcase == NULL) { |
167 |
SDL_ATprintErr( "AT testcase does not have a name.\n"); |
168 |
} |
169 |
at_test_msg = SDL_strdup(testcase); |
170 |
|
171 |
/* Verbose message. */ |
172 |
SDL_ATprintVerbose( 2, " +---> StartedTest Case '%s'\n", testcase ); |
173 |
} |
174 |
|
175 |
|
176 |
/** |
177 |
* @brief Ends the testcase with a succes or failure. |
178 |
*/ |
179 |
static void SDL_ATendWith( int success ) |
180 |
{ |
181 |
/* Make sure initialized. */ |
182 |
if (at_test_msg == NULL) { |
183 |
SDL_ATprintErr("Ended testcase without initializing.\n"); |
184 |
return; |
185 |
} |
186 |
|
187 |
/* Mark as success or failure. */ |
188 |
if (success) |
189 |
at_success++; |
190 |
else |
191 |
at_failure++; |
192 |
|
193 |
/* Verbose message. */ |
194 |
SDL_ATprintVerbose( 2, " +---- Finished Test Case '%s'\n", at_test_msg ); |
195 |
|
196 |
/* Clean up. */ |
197 |
if (at_test_msg != NULL) |
198 |
SDL_free(at_test_msg); |
199 |
at_test_msg = NULL; |
200 |
} |
201 |
|
202 |
|
203 |
/** |
204 |
* @brief Display failed assert message. |
205 |
*/ |
206 |
static void SDL_ATassertFailed( const char *msg ) |
207 |
{ |
208 |
/* Print. */ |
209 |
SDL_ATprintErr( "Assert Failed!\n" ); |
210 |
SDL_ATprintErr( " %s\n", msg ); |
211 |
SDL_ATprintErr( " Test Case '%s'\n", at_test_msg ); |
212 |
SDL_ATprintErr( " Test Suite '%s'\n", at_suite_msg ); |
213 |
SDL_ATprintErr( " Last SDL error '%s'\n", SDL_GetError() ); |
214 |
/* End. */ |
215 |
SDL_ATendWith(0); |
216 |
} |
217 |
|
218 |
|
219 |
/** |
220 |
* @brief Testcase test. |
221 |
*/ |
222 |
int SDL_ATassert( const char *msg, int condition ) |
223 |
{ |
224 |
/* Condition failed. */ |
225 |
if (!condition) { |
226 |
/* Failed message. */ |
227 |
SDL_ATassertFailed(msg); |
228 |
} |
229 |
return !condition; |
230 |
} |
231 |
|
232 |
|
233 |
/** |
234 |
* @brief Testcase test. |
235 |
*/ |
236 |
int SDL_ATvassert( int condition, const char *msg, ... ) |
237 |
{ |
238 |
va_list args; |
239 |
char buf[256]; |
240 |
|
241 |
/* Condition failed. */ |
242 |
if (!condition) { |
243 |
/* Get message. */ |
244 |
va_start( args, msg ); |
245 |
SDL_vsnprintf( buf, sizeof(buf), msg, args ); |
246 |
va_end( args ); |
247 |
/* Failed message. */ |
248 |
SDL_ATassertFailed( buf ); |
249 |
} |
250 |
return !condition; |
251 |
} |
252 |
|
253 |
|
254 |
/** |
255 |
* @brief End testcase. |
256 |
*/ |
257 |
void SDL_ATend (void) |
258 |
{ |
259 |
SDL_ATendWith(1); |
260 |
} |
261 |
|
262 |
|
263 |
/** |
264 |
* @brief Displays an error. |
265 |
*/ |
266 |
int SDL_ATprintErr( const char *msg, ... ) |
267 |
{ |
268 |
va_list ap; |
269 |
int ret; |
270 |
|
271 |
/* Make sure there is something to print. */ |
272 |
if (msg == NULL) |
273 |
return 0; |
274 |
else { |
275 |
va_start(ap, msg); |
276 |
ret = vfprintf( stderr, msg, ap ); |
277 |
va_end(ap); |
278 |
} |
279 |
|
280 |
return ret; |
281 |
} |
282 |
|
283 |
|
284 |
/** |
285 |
* @brief Displays a message. |
286 |
*/ |
287 |
int SDL_ATprint( const char *msg, ... ) |
288 |
{ |
289 |
va_list ap; |
290 |
int ret; |
291 |
|
292 |
/* Only print if not quiet. */ |
293 |
if (at_quiet) |
294 |
return 0; |
295 |
|
296 |
/* Make sure there is something to print. */ |
297 |
if (msg == NULL) |
298 |
return 0; |
299 |
else { |
300 |
va_start(ap, msg); |
301 |
ret = vfprintf( stdout, msg, ap ); |
302 |
va_end(ap); |
303 |
} |
304 |
|
305 |
return ret; |
306 |
} |
307 |
|
308 |
|
309 |
/** |
310 |
* @brief Displays a verbose message. |
311 |
*/ |
312 |
int SDL_ATprintVerbose( int level, const char *msg, ... ) |
313 |
{ |
314 |
va_list ap; |
315 |
int ret; |
316 |
|
317 |
/* Only print if not quiet. */ |
318 |
if (at_quiet || (at_verbose < level)) |
319 |
return 0; |
320 |
|
321 |
/* Make sure there is something to print. */ |
322 |
if (msg == NULL) |
323 |
return 0; |
324 |
else { |
325 |
va_start(ap, msg); |
326 |
ret = vfprintf( stdout, msg, ap ); |
327 |
va_end(ap); |
328 |
} |
329 |
|
330 |
return ret; |
331 |
} |