1 /* $OpenBSD */
2 /*
3 * Copyright (c) 2011 Damien Miller <djm@mindrot.org>
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
18 /* Utility functions/framework for regress tests */
19
20 #include <sys/types.h>
21
22 #include <fcntl.h>
23 #include <limits.h>
24 #include <stdio.h>
25 #include <stdint.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <assert.h>
29 #include <unistd.h>
30
31 #include <openssl/bn.h>
32
33 #include <vis.h>
34
35 #include "test_helper.h"
36
37 #define TEST_CHECK_INT(r, pred) do { \
38 switch (pred) { \
39 case TEST_EQ: \
40 if (r == 0) \
41 return; \
42 break; \
43 case TEST_NE: \
44 if (r != 0) \
45 return; \
46 break; \
47 case TEST_LT: \
48 if (r < 0) \
49 return; \
50 break; \
51 case TEST_LE: \
52 if (r <= 0) \
53 return; \
54 break; \
55 case TEST_GT: \
56 if (r > 0) \
57 return; \
58 break; \
59 case TEST_GE: \
60 if (r >= 0) \
61 return; \
62 break; \
63 default: \
64 abort(); \
65 } \
66 } while (0)
67
68 #define TEST_CHECK(x1, x2, pred) do { \
69 switch (pred) { \
70 case TEST_EQ: \
71 if (x1 == x2) \
72 return; \
73 break; \
74 case TEST_NE: \
75 if (x1 != x2) \
76 return; \
77 break; \
78 case TEST_LT: \
79 if (x1 < x2) \
80 return; \
81 break; \
82 case TEST_LE: \
83 if (x1 <= x2) \
84 return; \
85 break; \
86 case TEST_GT: \
87 if (x1 > x2) \
88 return; \
89 break; \
90 case TEST_GE: \
91 if (x1 >= x2) \
92 return; \
93 break; \
94 default: \
95 abort(); \
96 } \
97 } while (0)
98
99 extern char *__progname;
100
101 static int verbose_mode = 0;
102 static int quiet_mode = 0;
103 static char *active_test_name = NULL;
104 static u_int test_number = 0;
105 static test_onerror_func_t *test_onerror = NULL;
106 static void *onerror_ctx = NULL;
107 static const char *data_dir = NULL;
108
109 int
main(int argc,char ** argv)110 main(int argc, char **argv)
111 {
112 int ch;
113
114 while ((ch = getopt(argc, argv, "vqd:")) != -1) {
115 switch (ch) {
116 case 'd':
117 data_dir = optarg;
118 break;
119 case 'q':
120 verbose_mode = 0;
121 quiet_mode = 1;
122 break;
123 case 'v':
124 verbose_mode = 1;
125 quiet_mode = 0;
126 break;
127 default:
128 fprintf(stderr, "Unrecognised command line option\n");
129 fprintf(stderr, "Usage: %s [-v]\n", __progname);
130 exit(1);
131 }
132 }
133 setvbuf(stdout, NULL, _IONBF, 0);
134 if (!quiet_mode)
135 printf("%s: ", __progname);
136 if (verbose_mode)
137 printf("\n");
138
139 tests();
140
141 if (!quiet_mode)
142 printf(" %u tests ok\n", test_number);
143 return 0;
144 }
145
146 const char *
test_data_file(const char * name)147 test_data_file(const char *name)
148 {
149 static char ret[PATH_MAX];
150
151 if (data_dir != NULL)
152 snprintf(ret, sizeof(ret), "%s/%s", data_dir, name);
153 else
154 strlcpy(ret, name, sizeof(ret));
155 if (access(ret, F_OK) != 0) {
156 fprintf(stderr, "Cannot access data file %s: %s\n",
157 ret, strerror(errno));
158 exit(1);
159 }
160 return ret;
161 }
162
163 void
test_start(const char * n)164 test_start(const char *n)
165 {
166 assert(active_test_name == NULL);
167 assert((active_test_name = strdup(n)) != NULL);
168 if (verbose_mode)
169 printf("test %u - \"%s\": ", test_number, active_test_name);
170 test_number++;
171 }
172
173 void
set_onerror_func(test_onerror_func_t * f,void * ctx)174 set_onerror_func(test_onerror_func_t *f, void *ctx)
175 {
176 test_onerror = f;
177 onerror_ctx = ctx;
178 }
179
180 void
test_done(void)181 test_done(void)
182 {
183 assert(active_test_name != NULL);
184 free(active_test_name);
185 active_test_name = NULL;
186 if (verbose_mode)
187 printf("OK\n");
188 else if (!quiet_mode) {
189 printf(".");
190 fflush(stdout);
191 }
192 }
193
194 static const char *
pred_name(enum test_predicate p)195 pred_name(enum test_predicate p)
196 {
197 switch (p) {
198 case TEST_EQ:
199 return "EQ";
200 case TEST_NE:
201 return "NE";
202 case TEST_LT:
203 return "LT";
204 case TEST_LE:
205 return "LE";
206 case TEST_GT:
207 return "GT";
208 case TEST_GE:
209 return "GE";
210 default:
211 return "UNKNOWN";
212 }
213 }
214
215 static void
test_die(void)216 test_die(void)
217 {
218 if (test_onerror != NULL)
219 test_onerror(onerror_ctx);
220 abort();
221 }
222
223 static void
test_header(const char * file,int line,const char * a1,const char * a2,const char * name,enum test_predicate pred)224 test_header(const char *file, int line, const char *a1, const char *a2,
225 const char *name, enum test_predicate pred)
226 {
227 fprintf(stderr, "\n%s:%d test #%u \"%s\"\n",
228 file, line, test_number, active_test_name);
229 fprintf(stderr, "ASSERT_%s_%s(%s%s%s) failed:\n",
230 name, pred_name(pred), a1,
231 a2 != NULL ? ", " : "", a2 != NULL ? a2 : "");
232 }
233
234 void
assert_string(const char * file,int line,const char * a1,const char * a2,const char * aa1,const char * aa2,enum test_predicate pred)235 assert_string(const char *file, int line, const char *a1, const char *a2,
236 const char *aa1, const char *aa2, enum test_predicate pred)
237 {
238 int r = strcmp(aa1, aa2);
239
240 TEST_CHECK_INT(r, pred);
241 test_header(file, line, a1, a2, "STRING", pred);
242 fprintf(stderr, "%12s = %s (len %zu)\n", a1, aa1, strlen(aa1));
243 fprintf(stderr, "%12s = %s (len %zu)\n", a2, aa2, strlen(aa2));
244 test_die();
245 }
246
247 static char *
tohex(const void * _s,size_t l)248 tohex(const void *_s, size_t l)
249 {
250 uint8_t *s = (uint8_t *)_s;
251 size_t i, j;
252 const char *hex = "0123456789abcdef";
253 char *r = malloc((l * 2) + 1);
254
255 assert(r != NULL);
256 for (i = j = 0; i < l; i++) {
257 r[j++] = hex[(s[i] >> 4) & 0xf];
258 r[j++] = hex[s[i] & 0xf];
259 }
260 r[j] = '\0';
261 return r;
262 }
263
264 void
assert_mem(const char * file,int line,const char * a1,const char * a2,const void * aa1,const void * aa2,size_t l,enum test_predicate pred)265 assert_mem(const char *file, int line, const char *a1, const char *a2,
266 const void *aa1, const void *aa2, size_t l, enum test_predicate pred)
267 {
268 int r = memcmp(aa1, aa2, l);
269
270 TEST_CHECK_INT(r, pred);
271 test_header(file, line, a1, a2, "STRING", pred);
272 fprintf(stderr, "%12s = %s (len %zu)\n", a1,
273 tohex(aa1, MINIMUM(l, 256)), l);
274 fprintf(stderr, "%12s = %s (len %zu)\n", a2,
275 tohex(aa2, MINIMUM(l, 256)), l);
276 test_die();
277 }
278
279 static int
memvalcmp(const uint8_t * s,u_char v,size_t l,size_t * where)280 memvalcmp(const uint8_t *s, u_char v, size_t l, size_t *where)
281 {
282 size_t i;
283
284 for (i = 0; i < l; i++) {
285 if (s[i] != v) {
286 *where = i;
287 return 1;
288 }
289 }
290 return 0;
291 }
292
293 void
assert_mem_filled(const char * file,int line,const char * a1,const void * aa1,u_char v,size_t l,enum test_predicate pred)294 assert_mem_filled(const char *file, int line, const char *a1,
295 const void *aa1, u_char v, size_t l, enum test_predicate pred)
296 {
297 size_t where = -1;
298 int r = memvalcmp(aa1, v, l, &where);
299 char tmp[64];
300
301 if (l == 0)
302 return;
303 TEST_CHECK_INT(r, pred);
304 test_header(file, line, a1, NULL, "MEM_ZERO", pred);
305 fprintf(stderr, "%20s = %s%s (len %zu)\n", a1,
306 tohex(aa1, MINIMUM(l, 20)), l > 20 ? "..." : "", l);
307 snprintf(tmp, sizeof(tmp), "(%s)[%zu]", a1, where);
308 fprintf(stderr, "%20s = 0x%02x (expected 0x%02x)\n", tmp,
309 ((u_char *)aa1)[where], v);
310 test_die();
311 }
312
313 void
assert_int(const char * file,int line,const char * a1,const char * a2,int aa1,int aa2,enum test_predicate pred)314 assert_int(const char *file, int line, const char *a1, const char *a2,
315 int aa1, int aa2, enum test_predicate pred)
316 {
317 TEST_CHECK(aa1, aa2, pred);
318 test_header(file, line, a1, a2, "INT", pred);
319 fprintf(stderr, "%12s = %d\n", a1, aa1);
320 fprintf(stderr, "%12s = %d\n", a2, aa2);
321 test_die();
322 }
323
324 void
assert_size_t(const char * file,int line,const char * a1,const char * a2,size_t aa1,size_t aa2,enum test_predicate pred)325 assert_size_t(const char *file, int line, const char *a1, const char *a2,
326 size_t aa1, size_t aa2, enum test_predicate pred)
327 {
328 TEST_CHECK(aa1, aa2, pred);
329 test_header(file, line, a1, a2, "SIZE_T", pred);
330 fprintf(stderr, "%12s = %zu\n", a1, aa1);
331 fprintf(stderr, "%12s = %zu\n", a2, aa2);
332 test_die();
333 }
334
335 void
assert_u_int(const char * file,int line,const char * a1,const char * a2,u_int aa1,u_int aa2,enum test_predicate pred)336 assert_u_int(const char *file, int line, const char *a1, const char *a2,
337 u_int aa1, u_int aa2, enum test_predicate pred)
338 {
339 TEST_CHECK(aa1, aa2, pred);
340 test_header(file, line, a1, a2, "U_INT", pred);
341 fprintf(stderr, "%12s = %u / 0x%x\n", a1, aa1, aa1);
342 fprintf(stderr, "%12s = %u / 0x%x\n", a2, aa2, aa2);
343 test_die();
344 }
345
346 void
assert_long_long(const char * file,int line,const char * a1,const char * a2,long long aa1,long long aa2,enum test_predicate pred)347 assert_long_long(const char *file, int line, const char *a1, const char *a2,
348 long long aa1, long long aa2, enum test_predicate pred)
349 {
350 TEST_CHECK(aa1, aa2, pred);
351 test_header(file, line, a1, a2, "LONG LONG", pred);
352 fprintf(stderr, "%12s = %lld / 0x%llx\n", a1, aa1, aa1);
353 fprintf(stderr, "%12s = %lld / 0x%llx\n", a2, aa2, aa2);
354 test_die();
355 }
356
357 void
assert_char(const char * file,int line,const char * a1,const char * a2,char aa1,char aa2,enum test_predicate pred)358 assert_char(const char *file, int line, const char *a1, const char *a2,
359 char aa1, char aa2, enum test_predicate pred)
360 {
361 char buf[8];
362
363 TEST_CHECK(aa1, aa2, pred);
364 test_header(file, line, a1, a2, "CHAR", pred);
365 fprintf(stderr, "%12s = '%s' / 0x02%x\n", a1,
366 vis(buf, aa1, VIS_SAFE|VIS_NL|VIS_TAB|VIS_OCTAL, 0), aa1);
367 fprintf(stderr, "%12s = '%s' / 0x02%x\n", a1,
368 vis(buf, aa2, VIS_SAFE|VIS_NL|VIS_TAB|VIS_OCTAL, 0), aa2);
369 test_die();
370 }
371
372 void
assert_u8(const char * file,int line,const char * a1,const char * a2,uint8_t aa1,uint8_t aa2,enum test_predicate pred)373 assert_u8(const char *file, int line, const char *a1, const char *a2,
374 uint8_t aa1, uint8_t aa2, enum test_predicate pred)
375 {
376 TEST_CHECK(aa1, aa2, pred);
377 test_header(file, line, a1, a2, "U8", pred);
378 fprintf(stderr, "%12s = 0x%02x %u\n", a1, aa1, aa1);
379 fprintf(stderr, "%12s = 0x%02x %u\n", a2, aa2, aa2);
380 test_die();
381 }
382
383 void
assert_u16(const char * file,int line,const char * a1,const char * a2,uint16_t aa1,uint16_t aa2,enum test_predicate pred)384 assert_u16(const char *file, int line, const char *a1, const char *a2,
385 uint16_t aa1, uint16_t aa2, enum test_predicate pred)
386 {
387 TEST_CHECK(aa1, aa2, pred);
388 test_header(file, line, a1, a2, "U16", pred);
389 fprintf(stderr, "%12s = 0x%04x %u\n", a1, aa1, aa1);
390 fprintf(stderr, "%12s = 0x%04x %u\n", a2, aa2, aa2);
391 test_die();
392 }
393
394 void
assert_u32(const char * file,int line,const char * a1,const char * a2,uint32_t aa1,uint32_t aa2,enum test_predicate pred)395 assert_u32(const char *file, int line, const char *a1, const char *a2,
396 uint32_t aa1, uint32_t aa2, enum test_predicate pred)
397 {
398 TEST_CHECK(aa1, aa2, pred);
399 test_header(file, line, a1, a2, "U32", pred);
400 fprintf(stderr, "%12s = 0x%08x %u\n", a1, aa1, aa1);
401 fprintf(stderr, "%12s = 0x%08x %u\n", a2, aa2, aa2);
402 test_die();
403 }
404
405 void
assert_u64(const char * file,int line,const char * a1,const char * a2,uint64_t aa1,uint64_t aa2,enum test_predicate pred)406 assert_u64(const char *file, int line, const char *a1, const char *a2,
407 uint64_t aa1, uint64_t aa2, enum test_predicate pred)
408 {
409 TEST_CHECK(aa1, aa2, pred);
410 test_header(file, line, a1, a2, "U64", pred);
411 fprintf(stderr, "%12s = 0x%016llx %llu\n", a1,
412 (unsigned long long)aa1, (unsigned long long)aa1);
413 fprintf(stderr, "%12s = 0x%016llx %llu\n", a2,
414 (unsigned long long)aa2, (unsigned long long)aa2);
415 test_die();
416 }
417
418 void
assert_ptr(const char * file,int line,const char * a1,const char * a2,const void * aa1,const void * aa2,enum test_predicate pred)419 assert_ptr(const char *file, int line, const char *a1, const char *a2,
420 const void *aa1, const void *aa2, enum test_predicate pred)
421 {
422 TEST_CHECK(aa1, aa2, pred);
423 test_header(file, line, a1, a2, "PTR", pred);
424 fprintf(stderr, "%12s = %p\n", a1, aa1);
425 fprintf(stderr, "%12s = %p\n", a2, aa2);
426 test_die();
427 }
428
429