]> git.ipfire.org Git - thirdparty/openssl.git/blob - test/testutil/tests.c
Add BN support to the test infrastructure.
[thirdparty/openssl.git] / test / testutil / tests.c
1 /*
2 * Copyright 2017 The OpenSSL Project Authors. All Rights Reserved.
3 *
4 * Licensed under the OpenSSL license (the "License"). You may not use
5 * this file except in compliance with the License. You can obtain a copy
6 * in the file LICENSE in the source distribution or at
7 * https://www.openssl.org/source/license.html
8 */
9
10 #include "../testutil.h"
11 #include "output.h"
12 #include "tu_local.h"
13
14 #include <string.h>
15 #include <ctype.h>
16 #include "../../e_os.h"
17
18 /* The size of memory buffers to display on failure */
19 #define MEM_BUFFER_SIZE (33)
20 #define MAX_STRING_WIDTH (80)
21
22 /* Special representation of -0 */
23 static char BN_minus_zero[] = "-0";
24
25 /* Output a failed test first line */
26 static void test_fail_message_prefix(const char *prefix, const char *file,
27 int line, const char *type,
28 const char *left, const char *right,
29 const char *op)
30 {
31 test_printf_stderr("%*s# %s: ", subtest_level(), "",
32 prefix != NULL ? prefix : "ERROR");
33 if (type)
34 test_printf_stderr("(%s) ", type);
35 if (op != NULL)
36 test_printf_stderr("%s %s %s", left, op, right);
37 if (file != NULL) {
38 test_printf_stderr(" @ %s:%d", file, line);
39 }
40 test_printf_stderr("\n");
41 }
42
43 /*
44 * A common routine to output test failure messages. Generally this should not
45 * be called directly, rather it should be called by the following functions.
46 *
47 * |desc| is a printf formatted description with arguments |args| that is
48 * supplied by the user and |desc| can be NULL. |type| is the data type
49 * that was tested (int, char, ptr, ...). |fmt| is a system provided
50 * printf format with following arguments that spell out the failure
51 * details i.e. the actual values compared and the operator used.
52 *
53 * The typical use for this is from an utility test function:
54 *
55 * int test6(const char *file, int line, int n) {
56 * if (n != 6) {
57 * test_fail_message(1, file, line, "int", "value %d is not %d", n, 6);
58 * return 0;
59 * }
60 * return 1;
61 * }
62 *
63 * calling test6(3, "oops") will return 0 and produce out along the lines of:
64 * FAIL oops: (int) value 3 is not 6\n
65 */
66 static void test_fail_message(const char *prefix, const char *file, int line,
67 const char *type, const char *left,
68 const char *right, const char *op,
69 const char *fmt, ...)
70 PRINTF_FORMAT(8, 9);
71
72 static void test_fail_message_va(const char *prefix, const char *file,
73 int line, const char *type,
74 const char *left, const char *right,
75 const char *op, const char *fmt, va_list ap)
76 {
77 test_fail_message_prefix(prefix, file, line, type, left, right, op);
78 if (fmt != NULL) {
79 test_printf_stderr("%*s# ", subtest_level(), "");
80 test_vprintf_stderr(fmt, ap);
81 test_printf_stderr("\n");
82 }
83 test_printf_stderr("\n");
84 test_flush_stderr();
85 }
86
87 static void test_fail_string_message(const char *prefix, const char *file,
88 int line, const char *type,
89 const char *left, const char *right,
90 const char *op, const char *m1, size_t l1,
91 const char *m2, size_t l2)
92 {
93 const int indent = subtest_level();
94 const size_t width = (MAX_STRING_WIDTH - indent - 12) / 16 * 16;
95 char b1[MAX_STRING_WIDTH + 1], b2[MAX_STRING_WIDTH + 1];
96 char bdiff[MAX_STRING_WIDTH + 1];
97 size_t n1, n2, i;
98 unsigned int cnt = 0, diff;
99
100 test_fail_message_prefix(prefix, file, line, type, left, right, op);
101 if (m1 == NULL)
102 l1 = 0;
103 if (m2 == NULL)
104 l2 = 0;
105 if (l1 == 0 && l2 == 0) {
106 if ((m1 == NULL) == (m2 == NULL)) {
107 test_printf_stderr("%*s# % 4s %s\n", indent, "", "",
108 m1 == NULL ? "NULL" : "''");
109 } else {
110 test_printf_stderr("%*s# % 4s - %s\n", indent, "", "",
111 m1 == NULL ? "NULL" : "''");
112 test_printf_stderr("%*s# % 4s + %s\n", indent, "", "",
113 m2 == NULL ? "NULL" : "''");
114 }
115 goto fin;
116 }
117
118 while (l1 > 0 || l2 > 0) {
119 n1 = n2 = 0;
120 if (l1 > 0) {
121 b1[n1 = l1 > width ? width : l1] = 0;
122 for (i = 0; i < n1; i++)
123 b1[i] = isprint(m1[i]) ? m1[i] : '.';
124 }
125 if (l2 > 0) {
126 b2[n2 = l2 > width ? width : l2] = 0;
127 for (i = 0; i < n2; i++)
128 b2[i] = isprint(m2[i]) ? m2[i] : '.';
129 }
130 diff = n1 != n2;
131 i = 0;
132 if (n1 > 0 && n2 > 0) {
133 const size_t j = n1 < n2 ? n1 : n2;
134 const size_t k = n1 > n2 ? n1 : n2;
135
136 for (; i < j; i++)
137 if (m1[i] == m2[i]) {
138 bdiff[i] = ' ';
139 } else {
140 bdiff[i] = '^';
141 diff = 1;
142 }
143 for (; i < k; i++)
144 bdiff[i] = '^';
145 bdiff[i] = '\0';
146 }
147 if (!diff) {
148 test_printf_stderr("%*s# % 4u: '%s'\n", indent, "", cnt, b1);
149 } else {
150 if (cnt == 0 && m1 == NULL)
151 test_printf_stderr("%*s# % 4s - NULL\n", indent, "", "");
152 else if (cnt == 0 && *m1 == '\0')
153 test_printf_stderr("%*s# % 4s - ''\n", indent, "", "");
154 else if (n1 > 0)
155 test_printf_stderr("%*s# % 4u:- '%s'\n", indent, "", cnt, b1);
156 if (cnt == 0 && m2 == NULL)
157 test_printf_stderr("%*s# % 4s + NULL\n", indent, "", "");
158 else if (cnt == 0 && *m2 == '\0')
159 test_printf_stderr("%*s# % 4s + ''\n", indent, "", "");
160 else if (n2 > 0)
161 test_printf_stderr("%*s# % 4u:+ '%s'\n", indent, "", cnt, b2);
162 if (i > 0)
163 test_printf_stderr("%*s# % 4s %s\n", indent, "", "", bdiff);
164 }
165 m1 += n1;
166 m2 += n2;
167 l1 -= n1;
168 l2 -= n2;
169 cnt += width;
170 }
171 fin:
172 test_printf_stderr("\n");
173 test_flush_stderr();
174 }
175
176 static char *convertBN(const BIGNUM *b)
177 {
178 if (b == NULL)
179 return NULL;
180 if (BN_is_zero(b) && BN_is_negative(b))
181 return BN_minus_zero;
182 return BN_bn2hex(b);
183 }
184
185 static void test_fail_bignum_message(const char *prefix, const char *file,
186 int line, const char *type,
187 const char *left, const char *right,
188 const char *op,
189 const BIGNUM *bn1, const BIGNUM *bn2)
190 {
191 char *s1 = convertBN(bn1), *s2 = convertBN(bn2);
192 size_t l1 = s1 != NULL ? strlen(s1) : 0;
193 size_t l2 = s2 != NULL ? strlen(s2) : 0;
194
195 test_fail_string_message(prefix, file, line, type, left, right, op,
196 s1, l1, s2, l2);
197 if (s1 != BN_minus_zero)
198 OPENSSL_free(s1);
199 if (s2 != BN_minus_zero)
200 OPENSSL_free(s2);
201 }
202
203 static void test_fail_bignum_mono_message(const char *prefix, const char *file,
204 int line, const char *type,
205 const char *left, const char *right,
206 const char *op, const BIGNUM *bn)
207 {
208 char *s = convertBN(bn);
209 size_t l = s != NULL ? strlen(s) : 0;
210
211 test_fail_string_message(prefix, file, line, type, left, right, op,
212 s, l, s, l);
213 if (s != BN_minus_zero)
214 OPENSSL_free(s);
215 }
216
217 static void hex_convert_memory(const char *m, size_t n, char *b)
218 {
219 size_t i;
220
221 for (i = 0; i < n; i++) {
222 const unsigned char c = *m++;
223
224 *b++ = "0123456789abcdef"[c >> 4];
225 *b++ = "0123456789abcdef"[c & 15];
226 if ((i % 8) == 7 && i != n - 1)
227 *b++ = ' ';
228 }
229 *b = '\0';
230 }
231
232 static void test_fail_memory_message(const char *prefix, const char *file,
233 int line, const char *type,
234 const char *left, const char *right,
235 const char *op, const char *m1, size_t l1,
236 const char *m2, size_t l2)
237 {
238 const int indent = subtest_level();
239 const size_t bytes = (MAX_STRING_WIDTH - 9) / 17 * 8;
240 char b1[MAX_STRING_WIDTH + 1], b2[MAX_STRING_WIDTH + 1];
241 char *p, bdiff[MAX_STRING_WIDTH + 1];
242 size_t n1, n2, i;
243 unsigned int cnt = 0, diff;
244
245 test_fail_message_prefix(prefix, file, line, type, left, right, op);
246 if (m1 == NULL)
247 l1 = 0;
248 if (m2 == NULL)
249 l2 = 0;
250 if (l1 == 0 && l2 == 0) {
251 if ((m1 == NULL) == (m2 == NULL)) {
252 test_printf_stderr("%*s# %04s %s\n", indent, "", "",
253 m1 == NULL ? "NULL" : "empty");
254 } else {
255 test_printf_stderr("%*s# %04s -%s\n", indent, "", "",
256 m1 == NULL ? "NULL" : "empty");
257 test_printf_stderr("%*s# %04s +%s\n", indent, "", "",
258 m2 == NULL ? "NULL" : "empty");
259 }
260 goto fin;
261 }
262
263 while (l1 > 0 || l2 > 0) {
264 n1 = n2 = 0;
265 if (l1 > 0) {
266 n1 = l1 > bytes ? bytes : l1;
267 hex_convert_memory(m1, n1, b1);
268 }
269 if (l2 > 0) {
270 n2 = l2 > bytes ? bytes : l2;
271 hex_convert_memory(m2, n2, b2);
272 }
273
274 diff = n1 != n2;
275 i = 0;
276 p = bdiff;
277 if (n1 > 0 && n2 > 0) {
278 const size_t j = n1 < n2 ? n1 : n2;
279 const size_t k = n1 > n2 ? n1 : n2;
280
281 for (; i < j; i++) {
282 if (m1[i] == m2[i]) {
283 *p++ = ' ';
284 *p++ = ' ';
285 } else {
286 *p++ = '^';
287 *p++ = '^';
288 diff = 1;
289 }
290 if ((i % 8) == 7 && (i != j - 1 || j != k))
291 *p++ = ' ';
292 }
293
294 for (; i < k; i++) {
295 *p++ = '^';
296 *p++ = '^';
297 if ((i % 8) == 7 && i != k - 1)
298 *p++ = ' ';
299 }
300 *p++ = '\0';
301 }
302
303 if (!diff) {
304 test_printf_stderr("%*s# %04x: %s\n", indent, "", cnt, b1);
305 } else {
306 if (cnt == 0 && m1 == NULL)
307 test_printf_stderr("%*s# %04s -NULL\n", indent, "", "");
308 else if (cnt == 0 && l1 == 0)
309 test_printf_stderr("%*s# %04s -empty\n", indent, "", "");
310 else if (n1 > 0)
311 test_printf_stderr("%*s# %04x:-%s\n", indent, "", cnt, b1);
312 if (cnt == 0 && m2 == NULL)
313 test_printf_stderr("%*s# %04s +NULL\n", indent, "", "");
314 else if (cnt == 0 && l2 == 0)
315 test_printf_stderr("%*s# %04s +empty\n", indent, "", "");
316 else if (n2 > 0)
317 test_printf_stderr("%*s# %04x:+%s\n", indent, "", cnt, b2);
318 if (i > 0)
319 test_printf_stderr("%*s# % 4s %s\n", indent, "", "", bdiff);
320 }
321 m1 += n1;
322 m2 += n2;
323 l1 -= n1;
324 l2 -= n2;
325 cnt += bytes;
326 }
327 fin:
328 test_printf_stderr("\n");
329 test_flush_stderr();
330 }
331
332 static void test_fail_message(const char *prefix, const char *file,
333 int line, const char *type,
334 const char *left, const char *right,
335 const char *op, const char *fmt, ...)
336 {
337 va_list ap;
338
339 va_start(ap, fmt);
340 test_fail_message_va(prefix, file, line, type, left, right, op, fmt, ap);
341 va_end(ap);
342 }
343
344 void test_info_c90(const char *desc, ...)
345 {
346 va_list ap;
347
348 va_start(ap, desc);
349 test_fail_message_va("INFO", NULL, -1, NULL, NULL, NULL, NULL, desc, ap);
350 va_end(ap);
351 }
352
353 void test_info(const char *file, int line, const char *desc, ...)
354 {
355 va_list ap;
356
357 va_start(ap, desc);
358 test_fail_message_va("INFO", file, line, NULL, NULL, NULL, NULL, desc, ap);
359 va_end(ap);
360 }
361
362 void test_error_c90(const char *desc, ...)
363 {
364 va_list ap;
365
366 va_start(ap, desc);
367 test_fail_message(NULL, NULL, -1, NULL, NULL, NULL, NULL, desc, ap);
368 va_end(ap);
369 }
370
371 void test_error(const char *file, int line, const char *desc, ...)
372 {
373 va_list ap;
374
375 va_start(ap, desc);
376 test_fail_message_va(NULL, file, line, NULL, NULL, NULL, NULL, desc, ap);
377 va_end(ap);
378 }
379
380 void test_openssl_errors(void)
381 {
382 ERR_print_errors_cb(openssl_error_cb, NULL);
383 }
384
385 /*
386 * Define some comparisons between pairs of various types.
387 * These functions return 1 if the test is true.
388 * Otherwise, they return 0 and pretty-print diagnostics.
389 *
390 * In each case the functions produced are:
391 * int test_name_eq(const type t1, const type t2, const char *desc, ...);
392 * int test_name_ne(const type t1, const type t2, const char *desc, ...);
393 * int test_name_lt(const type t1, const type t2, const char *desc, ...);
394 * int test_name_le(const type t1, const type t2, const char *desc, ...);
395 * int test_name_gt(const type t1, const type t2, const char *desc, ...);
396 * int test_name_ge(const type t1, const type t2, const char *desc, ...);
397 *
398 * The t1 and t2 arguments are to be compared for equality, inequality,
399 * less than, less than or equal to, greater than and greater than or
400 * equal to respectively. If the specified condition holds, the functions
401 * return 1. If the condition does not hold, the functions print a diagnostic
402 * message and return 0.
403 *
404 * The desc argument is a printf format string followed by its arguments and
405 * this is included in the output if the condition being tested for is false.
406 */
407 #define DEFINE_COMPARISON(type, name, opname, op, fmt) \
408 int test_ ## name ## _ ## opname(const char *file, int line, \
409 const char *s1, const char *s2, \
410 const type t1, const type t2) \
411 { \
412 if (t1 op t2) \
413 return 1; \
414 test_fail_message(NULL, file, line, #type, s1, s2, #op, \
415 "[" fmt "] compared to [" fmt "]", \
416 t1, t2); \
417 return 0; \
418 }
419
420 #define DEFINE_COMPARISONS(type, name, fmt) \
421 DEFINE_COMPARISON(type, name, eq, ==, fmt) \
422 DEFINE_COMPARISON(type, name, ne, !=, fmt) \
423 DEFINE_COMPARISON(type, name, lt, <, fmt) \
424 DEFINE_COMPARISON(type, name, le, <=, fmt) \
425 DEFINE_COMPARISON(type, name, gt, >, fmt) \
426 DEFINE_COMPARISON(type, name, ge, >=, fmt)
427
428 DEFINE_COMPARISONS(int, int, "%d")
429 DEFINE_COMPARISONS(unsigned int, uint, "%u")
430 DEFINE_COMPARISONS(char, char, "%c")
431 DEFINE_COMPARISONS(unsigned char, uchar, "%u")
432 DEFINE_COMPARISONS(long, long, "%ld")
433 DEFINE_COMPARISONS(unsigned long, ulong, "%lu")
434 DEFINE_COMPARISONS(size_t, size_t, "%zu")
435
436 DEFINE_COMPARISON(void *, ptr, eq, ==, "%p")
437 DEFINE_COMPARISON(void *, ptr, ne, !=, "%p")
438
439 int test_ptr_null(const char *file, int line, const char *s, const void *p)
440 {
441 if (p == NULL)
442 return 1;
443 test_fail_message(NULL, file, line, "ptr", s, "NULL", "==", "%p", p);
444 return 0;
445 }
446
447 int test_ptr(const char *file, int line, const char *s, const void *p)
448 {
449 if (p != NULL)
450 return 1;
451 test_fail_message(NULL, file, line, "ptr", s, "NULL", "!=", "%p", p);
452 return 0;
453 }
454
455 int test_true(const char *file, int line, const char *s, int b)
456 {
457 if (b)
458 return 1;
459 test_fail_message(NULL, file, line, "bool", s, "true", "==", "false");
460 return 0;
461 }
462
463 int test_false(const char *file, int line, const char *s, int b)
464 {
465 if (!b)
466 return 1;
467 test_fail_message(NULL, file, line, "bool", s, "false", "==", "true");
468 return 0;
469 }
470
471 int test_str_eq(const char *file, int line, const char *st1, const char *st2,
472 const char *s1, const char *s2)
473 {
474 if (s1 == NULL && s2 == NULL)
475 return 1;
476 if (s1 == NULL || s2 == NULL || strcmp(s1, s2) != 0) {
477 test_fail_string_message(NULL, file, line, "string", st1, st2, "==",
478 s1, s1 == NULL ? 0 : strlen(s1),
479 s2, s2 == NULL ? 0 : strlen(s2));
480 return 0;
481 }
482 return 1;
483 }
484
485 int test_str_ne(const char *file, int line, const char *st1, const char *st2,
486 const char *s1, const char *s2)
487 {
488 if ((s1 == NULL) ^ (s2 == NULL))
489 return 1;
490 if (s1 == NULL || strcmp(s1, s2) == 0) {
491 test_fail_string_message(NULL, file, line, "string", st1, st2, "!=",
492 s1, s1 == NULL ? 0 : strlen(s1),
493 s2, s2 == NULL ? 0 : strlen(s2));
494 return 0;
495 }
496 return 1;
497 }
498
499 int test_strn_eq(const char *file, int line, const char *st1, const char *st2,
500 const char *s1, const char *s2, size_t len)
501 {
502 if (s1 == NULL && s2 == NULL)
503 return 1;
504 if (s1 == NULL || s2 == NULL || strncmp(s1, s2, len) != 0) {
505 test_fail_string_message(NULL, file, line, "string", st1, st2, "==",
506 s1, s1 == NULL ? 0 : OPENSSL_strnlen(s1, len),
507 s2, s2 == NULL ? 0 : OPENSSL_strnlen(s2, len));
508 return 0;
509 }
510 return 1;
511 }
512
513 int test_strn_ne(const char *file, int line, const char *st1, const char *st2,
514 const char *s1, const char *s2, size_t len)
515 {
516 if ((s1 == NULL) ^ (s2 == NULL))
517 return 1;
518 if (s1 == NULL || strncmp(s1, s2, len) == 0) {
519 test_fail_string_message(NULL, file, line, "string", st1, st2, "!=",
520 s1, s1 == NULL ? 0 : OPENSSL_strnlen(s1, len),
521 s2, s2 == NULL ? 0 : OPENSSL_strnlen(s2, len));
522 return 0;
523 }
524 return 1;
525 }
526
527 int test_mem_eq(const char *file, int line, const char *st1, const char *st2,
528 const void *s1, size_t n1, const void *s2, size_t n2)
529 {
530 if (s1 == NULL && s2 == NULL)
531 return 1;
532 if (n1 != n2 || s1 == NULL || s2 == NULL || memcmp(s1, s2, n1) != 0) {
533 test_fail_memory_message(NULL, file, line, "memory", st1, st2, "==",
534 s1, n1, s2, n2);
535 return 0;
536 }
537 return 1;
538 }
539
540 int test_mem_ne(const char *file, int line, const char *st1, const char *st2,
541 const void *s1, size_t n1, const void *s2, size_t n2)
542 {
543 if ((s1 == NULL) ^ (s2 == NULL))
544 return 1;
545 if (n1 != n2)
546 return 1;
547 if (s1 == NULL || memcmp(s1, s2, n1) == 0) {
548 test_fail_memory_message(NULL, file, line, "memory", st1, st2, "!=",
549 s1, n1, s2, n2);
550 return 0;
551 }
552 return 1;
553 }
554
555 #define DEFINE_BN_COMPARISONS(opname, op, zero_cond) \
556 int test_BN_ ## opname(const char *file, int line, \
557 const char *s1, const char *s2, \
558 const BIGNUM *t1, const BIGNUM *t2) \
559 { \
560 if (BN_cmp(t1, t2) op 0) \
561 return 1; \
562 test_fail_bignum_message(NULL, file, line, "BIGNUM", s1, s2, \
563 #op, t1, t2); \
564 return 0; \
565 } \
566 int test_BN_ ## opname ## _zero(const char *file, int line, \
567 const char *s, const BIGNUM *a) \
568 { \
569 if (a != NULL &&(zero_cond)) \
570 return 1; \
571 test_fail_bignum_mono_message(NULL, file, line, "BIGNUM", \
572 s, "0", #op, a); \
573 return 0; \
574 }
575
576 DEFINE_BN_COMPARISONS(eq, ==, BN_is_zero(a))
577 DEFINE_BN_COMPARISONS(ne, !=, !BN_is_zero(a))
578 DEFINE_BN_COMPARISONS(gt, >, !BN_is_negative(a) && !BN_is_zero(a))
579 DEFINE_BN_COMPARISONS(ge, >=, !BN_is_negative(a) || BN_is_zero(a))
580 DEFINE_BN_COMPARISONS(lt, <, BN_is_negative(a) && !BN_is_zero(a))
581 DEFINE_BN_COMPARISONS(le, <=, BN_is_negative(a) || BN_is_zero(a))
582
583 int test_BN_eq_one(const char *file, int line, const char *s, const BIGNUM *a)
584 {
585 if (a != NULL && BN_is_one(a))
586 return 1;
587 test_fail_bignum_mono_message(NULL, file, line, "BIGNUM", s, "1", "==", a);
588 return 0;
589 }
590
591 int test_BN_odd(const char *file, int line, const char *s, const BIGNUM *a)
592 {
593 if (a != NULL && BN_is_odd(a))
594 return 1;
595 test_fail_bignum_mono_message(NULL, file, line, "BIGNUM", "ODD(", ")", s,
596 a);
597 return 0;
598 }
599
600 int test_BN_even(const char *file, int line, const char *s, const BIGNUM *a)
601 {
602 if (a != NULL && !BN_is_odd(a))
603 return 1;
604 test_fail_bignum_mono_message(NULL, file, line, "BIGNUM", "EVEN(", ")", s,
605 a);
606 return 0;
607 }
608
609 int test_BN_eq_word(const char *file, int line, const char *bns, const char *ws,
610 const BIGNUM *a, BN_ULONG w)
611 {
612 BIGNUM *bw;
613
614 if (a != NULL && BN_is_word(a, w))
615 return 1;
616 bw = BN_new();
617 BN_set_word(bw, w);
618 test_fail_bignum_message(NULL, file, line, "BIGNUM", bns, ws, "==", a, bw);
619 BN_free(bw);
620 return 0;
621 }
622
623 int test_BN_abs_eq_word(const char *file, int line, const char *bns,
624 const char *ws, const BIGNUM *a, BN_ULONG w)
625 {
626 BIGNUM *bw, *aa;
627
628 if (a != NULL && BN_abs_is_word(a, w))
629 return 1;
630 bw = BN_new();
631 aa = BN_dup(a);
632 BN_set_negative(aa, 0);
633 BN_set_word(bw, w);
634 test_fail_bignum_message(NULL, file, line, "BIGNUM", bns, ws, "abs==",
635 aa, bw);
636 BN_free(bw);
637 BN_free(aa);
638 return 0;
639 }