]> git.saurik.com Git - apple/security.git/blob - Security/regressions/test/testmore.c
Security-57031.1.35.tar.gz
[apple/security.git] / Security / regressions / test / testmore.c
1 /*
2 * Copyright (c) 2005-2007,2012-2014 Apple Inc. All Rights Reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 *
23 * testmore.c
24 */
25
26 #include <fcntl.h>
27 #include <stdarg.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <sys/stat.h>
31 #include <sys/types.h>
32 #include <sys/time.h>
33 #include <unistd.h>
34 #include <AvailabilityMacros.h>
35
36 #include "testmore.h"
37 #include "testenv.h"
38
39 static int test_num = 0;
40 static int test_fails = 0;
41 static int test_cases = 0;
42 static const char *test_plan_file;
43 static int test_plan_line=0;
44
45 const char *test_directive = NULL;
46 const char *test_reason = NULL;
47
48 static void fprint_string(FILE *file, CFStringRef string) {
49 UInt8 buf[256];
50 CFRange range = { .location = 0 };
51 range.length = CFStringGetLength(string);
52 while (range.length > 0) {
53 CFIndex bytesUsed = 0;
54 CFIndex converted = CFStringGetBytes(string, range, kCFStringEncodingUTF8, 0, false, buf, sizeof(buf), &bytesUsed);
55 fwrite(buf, 1, bytesUsed, file);
56 range.length -= converted;
57 range.location += converted;
58 }
59 }
60
61 static void cffprint(FILE *file, CFStringRef fmt, ...) CF_FORMAT_FUNCTION(2,0);
62
63 static void cffprint_v(FILE *file, CFStringRef fmt, va_list args);
64 static void cffprint_c_v(FILE *file, const char *fmt, va_list args);
65
66 static void cffprint_v(FILE *file, CFStringRef fmt, va_list args) {
67 CFStringRef line = CFStringCreateWithFormatAndArguments(NULL, NULL, fmt, args);
68 fprint_string(file, line);
69 CFRelease(line);
70 }
71
72 static void cffprint_c_v(FILE *file, const char *fmt, va_list args) {
73 CFStringRef cffmt = CFStringCreateWithCString(kCFAllocatorDefault, fmt, kCFStringEncodingUTF8);
74 cffprint_v(file, cffmt, args);
75 CFRelease(cffmt);
76 }
77
78 static void cffprint(FILE *file, CFStringRef fmt, ...) {
79 va_list args;
80 va_start(args, fmt);
81 cffprint_v(file, fmt, args);
82 va_end(args);
83 }
84
85 void test_skip(const char *reason, int how_many, int unless)
86 {
87 if (unless)
88 return;
89
90 int done;
91 for (done = 0; done < how_many; ++done)
92 test_ok(1, NULL, "skip", reason, __FILE__, __LINE__, NULL);
93 }
94
95 void test_bail_out(const char *reason, const char *file, unsigned line)
96 {
97 fprintf(stdout, "[FAIL] BAIL OUT! (%s at line %u) %s\n", file, line, reason);
98 fflush(stdout);
99 exit(255);
100 }
101
102 void test_plan_skip_all(const char *reason)
103 {
104 if (test_num < test_cases)
105 {
106 test_skip(reason, test_cases - test_num, 0);
107 }
108 }
109
110 static int test_plan_exit(void)
111 {
112 int status = 0;
113 fflush(stderr);
114
115 if (!test_num)
116 {
117 if (test_cases)
118 {
119 fprintf(stdout, "[BEGIN] plan_tests\nNo tests run!\n[WARN] plan_tests\n");
120 status = 1;
121 }
122 else
123 {
124 fprintf(stdout, "[BEGIN] plan_tests\nLooks like your test died before it could output anything.\n[FAIL] plan_tests\n");
125 status = 1;
126 }
127 }
128 else if (test_num < test_cases)
129 {
130 fprintf(stdout, "[BEGIN] plan_tests\nLooks like you planned %d tests but only ran %d.\n[WARN] plan_tests\n",
131 test_cases, test_num);
132 }
133 else if (test_num > test_cases)
134 {
135 fprintf(stdout, "[BEGIN] plan_tests\nLooks like you planned %d tests but ran %d.\n[WARN] plan_tests\n",
136 test_cases, test_num);
137 }
138 if (test_fails)
139 {
140 fprintf(stdout, "Failed %d tests of %d.\n", test_fails, test_num);
141 status = test_fails;
142 }
143 fflush(stdout);
144
145 /* reset the test plan */
146 test_num = 0;
147 test_fails = 0;
148 test_cases = 0;
149
150 return status;
151 }
152
153 void test_plan_tests(int count, const char *file, unsigned line)
154 {
155 #if 0
156 if (atexit(test_plan_exit) < 0)
157 {
158 fprintf(stdout, "failed to setup atexit handler: %s\n",
159 strerror(errno));
160 fflush(stdout);
161 exit(255);
162 }
163 #endif
164
165 if (test_cases)
166 {
167 fprintf(stdout,
168 "[FAIL] You tried to plan twice!\n");
169
170 fflush(stdout);
171 exit(255);
172 }
173 else
174 {
175 if (!count)
176 {
177 fprintf(stdout, "[BEGIN] plan_tests\nYou said to run 0 tests! "
178 "You've got to run something.\n[WARN] plan_tests\n");
179 fflush(stdout);
180 }
181
182 test_plan_file=file;
183 test_plan_line=line;
184
185 test_cases = count;
186 }
187 }
188
189 int
190 test_diag(const char *directive, const char *reason,
191 const char *file, unsigned line, const char *fmt, ...)
192 {
193 int is_todo = directive && !strcmp(directive, "TODO");
194 va_list args;
195
196 va_start(args, fmt);
197
198 if (is_todo)
199 {
200 fputs("# ", stdout);
201 if (fmt)
202 vprintf(fmt, args);
203 fputs("\n", stdout);
204 fflush(stdout);
205 }
206 else
207 {
208 fputs("# ", stdout);
209 if (fmt)
210 vfprintf(stdout, fmt, args);
211 fputs("\n", stdout);
212 fflush(stdout);
213 }
214
215 va_end(args);
216
217 return 1;
218 }
219
220 int
221 test_ok(int passed, __attribute((cf_consumed)) CFStringRef description, const char *directive,
222 const char *reason, const char *file, unsigned line,
223 const char *fmt, ...)
224 {
225 int is_todo = !passed && directive && !strcmp(directive, "TODO");
226 int is_setup = directive && !is_todo && !strcmp(directive, "SETUP");
227
228 if (is_setup)
229 {
230 if (!passed)
231 {
232 fflush(stderr);
233 fprintf(stdout, "[BEGIN] SETUP\n");
234 if (fmt) {
235 va_list args;
236 va_start(args, fmt);
237 cffprint_c_v(stdout, fmt, args);
238 va_end(args);
239 }
240 cffprint(stdout, CFSTR("[WARN] SETUP%s%@%s%s\n"),
241 description ? " - " : "",
242 description ? description : CFSTR(""),
243 reason ? " - " : "",
244 reason ? reason : "");
245 fflush(stdout);
246 }
247 }
248 else
249 {
250 if (!test_cases)
251 {
252 atexit((void(*)(void))test_plan_exit);
253 fprintf(stdout, "[FAIL] You tried to run a test without a plan! "
254 "Gotta have a plan. at %s line %u\n", file, line);
255 fflush(stdout);
256 exit(255);
257 }
258
259 ++test_num;
260 if (!passed && !is_todo)
261 ++test_fails;
262
263 /* We only print this when a test fail, unless verbose is enabled */
264 if ((!passed && !is_todo) || test_verbose > 0) {
265 fflush(stderr);
266 if (test_strict_bats) {
267 cffprint(stdout, CFSTR("[BEGIN] %d%s%@\n"),
268 test_num,
269 description ? " - " : "",
270 description ? description : CFSTR(""));
271 }
272 if (is_todo && passed) {
273 fprintf(stdout, "%s:%d: warning: Unexpectedly passed (TODO) test\n", file, line);
274 } else if (is_todo && !passed) {
275 /* Enable this to output TODO as warning */
276 fprintf(stdout, "%s:%d: ok: Failed (TODO) test\n", file, line);
277 } else if (!passed) {
278 fprintf(stdout, "%s:%d: error: Failed test\n", file, line);
279 }
280 if (fmt) {
281 va_list args;
282 va_start(args, fmt);
283 cffprint_c_v(stdout, fmt, args);
284 va_end(args);
285 }
286 cffprint(stdout, CFSTR("[%s] %d%s%@%s%s%s%s\n"), passed ? (is_todo ? "WARN" : "PASS") : (is_todo ? "PASS" : "FAIL"),
287 test_num,
288 description ? " - " : "",
289 description ? description : CFSTR(""),
290 directive ? " # " : "",
291 directive ? directive : "",
292 reason ? " " : "",
293 reason ? reason : "");
294 fflush(stdout);
295 }
296 }
297
298 if (description)
299 CFRelease(description);
300
301 return passed;
302 }
303
304
305 const char *
306 sec_errstr(int err)
307 {
308 #if 1
309 static int bufnum = 0;
310 static char buf[2][20];
311 bufnum = bufnum ? 0 : 1;
312 sprintf(buf[bufnum], "0x%X", err);
313 return buf[bufnum];
314 #else /* !1 */
315 if (err >= errSecErrnoBase && err <= errSecErrnoLimit)
316 return strerror(err - 100000);
317
318 #ifdef MAC_OS_X_VERSION_10_4
319 /* AvailabilityMacros.h would only define this if we are on a
320 Tiger or later machine. */
321 extern const char *cssmErrorString(long);
322 return cssmErrorString(err);
323 #else /* !defined(MAC_OS_X_VERSION_10_4) */
324 extern const char *_ZN8Security15cssmErrorStringEl(long);
325 return _ZN8Security15cssmErrorStringEl(err);
326 #endif /* MAC_OS_X_VERSION_10_4 */
327 #endif /* !1 */
328 }
329
330 /* run one test, described by test, return info in test struct */
331 int run_one_test(struct one_test_s *test, int argc, char * const *argv)
332 {
333 struct timeval start, stop;
334
335 if(test->entry==NULL) {
336 fprintf(stdout, "%s:%d: error, no entry\n", __FILE__, __LINE__);
337 return -1;
338 }
339
340 gettimeofday(&start, NULL);
341 test->entry(argc, argv);
342 gettimeofday(&stop, NULL);
343
344
345 /* this may overflow... */
346 test->duration=(stop.tv_sec-start.tv_sec)*1000+(stop.tv_usec/1000)-(start.tv_usec/1000);
347 test->failed_tests=test_fails;
348
349 return test_plan_exit();
350 };