Bring the memory output inline with the suggestions in #3465.
[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     (2000)
20 #define MAX_STRING_WIDTH    (80)
21 #define BN_OUTPUT_SIZE      (8)
22
23 /* Output a failed test first line */
24 static void test_fail_message_prefix(const char *prefix, const char *file,
25                                      int line, const char *type,
26                                      const char *left, const char *right,
27                                      const char *op)
28 {
29     test_printf_stderr("%*s# %s: ", subtest_level(), "",
30                        prefix != NULL ? prefix : "ERROR");
31     if (type)
32         test_printf_stderr("(%s) ", type);
33     if (op != NULL)
34         test_printf_stderr("'%s %s %s' failed", left, op, right);
35     if (file != NULL) {
36         test_printf_stderr(" @ %s:%d", file, line);
37     }
38     test_printf_stderr("\n");
39 }
40
41 /* Output a diff header */
42 static void test_diff_header(const char *left, const char *right)
43 {
44     test_printf_stderr("%*s# --- %s\n", subtest_level(), "", left);
45     test_printf_stderr("%*s# +++ %s\n", subtest_level(), "", right);
46 }
47
48 /*
49  * A common routine to output test failure messages.  Generally this should not
50  * be called directly, rather it should be called by the following functions.
51  *
52  * |desc| is a printf formatted description with arguments |args| that is
53  * supplied by the user and |desc| can be NULL.  |type| is the data type
54  * that was tested (int, char, ptr, ...).  |fmt| is a system provided
55  * printf format with following arguments that spell out the failure
56  * details i.e. the actual values compared and the operator used.
57  *
58  * The typical use for this is from an utility test function:
59  *
60  * int test6(const char *file, int line, int n) {
61  *     if (n != 6) {
62  *         test_fail_message(1, file, line, "int", "value %d is not %d", n, 6);
63  *         return 0;
64  *     }
65  *     return 1;
66  * }
67  *
68  * calling test6(3, "oops") will return 0 and produce out along the lines of:
69  *      FAIL oops: (int) value 3 is not 6\n
70  */
71 static void test_fail_message(const char *prefix, const char *file, int line,
72                               const char *type, const char *left,
73                               const char *right, const char *op,
74                               const char *fmt, ...)
75             PRINTF_FORMAT(8, 9);
76
77 static void test_fail_message_va(const char *prefix, const char *file,
78                                  int line, const char *type,
79                                  const char *left, const char *right,
80                                  const char *op, const char *fmt, va_list ap)
81 {
82     test_fail_message_prefix(prefix, file, line, type, left, right, op);
83     if (fmt != NULL) {
84         test_printf_stderr("%*s# ", subtest_level(), "");
85         test_vprintf_stderr(fmt, ap);
86         test_printf_stderr("\n");
87     }
88     test_printf_stderr("\n");
89     test_flush_stderr();
90 }
91
92 static void test_fail_string_message(const char *prefix, const char *file,
93                                      int line, const char *type,
94                                      const char *left, const char *right,
95                                      const char *op, const char *m1, size_t l1,
96                                      const char *m2, size_t l2)
97 {
98     const int indent = subtest_level();
99     const size_t width = (MAX_STRING_WIDTH - indent - 12) / 16 * 16;
100     char b1[MAX_STRING_WIDTH + 1], b2[MAX_STRING_WIDTH + 1];
101     char bdiff[MAX_STRING_WIDTH + 1];
102     size_t n1, n2, i;
103     unsigned int cnt = 0, diff;
104
105     test_fail_message_prefix(prefix, file, line, type, left, right, op);
106     if (m1 == NULL)
107         l1 = 0;
108     if (m2 == NULL)
109         l2 = 0;
110     if (l1 == 0 && l2 == 0) {
111         if ((m1 == NULL) == (m2 == NULL)) {
112             test_printf_stderr("%*s# % 4s   %s\n", indent, "", "",
113                                m1 == NULL ? "NULL" : "''");
114         } else {
115             test_diff_header(left, right);
116             test_printf_stderr("%*s# % 4s - %s\n", indent, "", "",
117                                m1 == NULL ? "NULL" : "''");
118             test_printf_stderr("%*s# % 4s + %s\n", indent, "", "",
119                                m2 == NULL ? "NULL" : "''");
120         }
121         goto fin;
122     }
123
124     if (l1 != l2 || strcmp(m1, m2) != 0)
125         test_diff_header(left, right);
126
127     while (l1 > 0 || l2 > 0) {
128         n1 = n2 = 0;
129         if (l1 > 0) {
130             b1[n1 = l1 > width ? width : l1] = 0;
131             for (i = 0; i < n1; i++)
132                 b1[i] = isprint(m1[i]) ? m1[i] : '.';
133         }
134         if (l2 > 0) {
135             b2[n2 = l2 > width ? width : l2] = 0;
136             for (i = 0; i < n2; i++)
137                 b2[i] = isprint(m2[i]) ? m2[i] : '.';
138         }
139         diff = n1 != n2;
140         i = 0;
141         if (n1 > 0 && n2 > 0) {
142             const size_t j = n1 < n2 ? n1 : n2;
143             const size_t k = n1 > n2 ? n1 : n2;
144
145             for (; i < j; i++)
146                 if (m1[i] == m2[i]) {
147                     bdiff[i] = ' ';
148                 } else {
149                     bdiff[i] = '^';
150                     diff = 1;
151                 }
152             for (; i < k; i++)
153                 bdiff[i] = '^';
154             bdiff[i] = '\0';
155         }
156         if (!diff) {
157             test_printf_stderr("%*s# % 4u:  '%s'\n", indent, "", cnt, b1);
158         } else {
159             if (cnt == 0 && m1 == NULL)
160                 test_printf_stderr("%*s# % 4s - NULL\n", indent, "", "");
161             else if (cnt == 0 && *m1 == '\0')
162                 test_printf_stderr("%*s# % 4s - ''\n", indent, "", "");
163             else if (n1 > 0)
164                 test_printf_stderr("%*s# % 4u:- '%s'\n", indent, "", cnt, b1);
165             if (cnt == 0 && m2 == NULL)
166                 test_printf_stderr("%*s# % 4s + NULL\n", indent, "", "");
167             else if (cnt == 0 && *m2 == '\0')
168                 test_printf_stderr("%*s# % 4s + ''\n", indent, "", "");
169             else if (n2 > 0)
170                 test_printf_stderr("%*s# % 4u:+ '%s'\n", indent, "", cnt, b2);
171             if (i > 0)
172                 test_printf_stderr("%*s# % 4s    %s\n", indent, "", "", bdiff);
173         }
174         m1 += n1;
175         m2 += n2;
176         l1 -= n1;
177         l2 -= n2;
178         cnt += width;
179     }
180 fin:
181     test_printf_stderr("\n");
182     test_flush_stderr();
183 }
184
185 static void hex_convert_memory(const unsigned char *m, size_t n, char *b,
186                                size_t width)
187 {
188     size_t i;
189
190     for (i = 0; i < n; i++) {
191         const unsigned char c = *m++;
192
193         *b++ = "0123456789abcdef"[c >> 4];
194         *b++ = "0123456789abcdef"[c & 15];
195         if (i % width == width - 1 && i != n - 1)
196             *b++ = ' ';
197     }
198     *b = '\0';
199 }
200
201 static const int bn_bytes = (MAX_STRING_WIDTH - 9) / (BN_OUTPUT_SIZE * 2 + 1)
202                             * BN_OUTPUT_SIZE;
203 static const int bn_chars = (MAX_STRING_WIDTH - 9) / (BN_OUTPUT_SIZE * 2 + 1)
204                             * (BN_OUTPUT_SIZE * 2 + 1) - 1;
205
206 static void test_bignum_header_line(void)
207 {
208     test_printf_stderr("%*s#  %*s\n", subtest_level(), "", bn_chars + 6,
209                        "bit position");
210 }
211
212 static void test_bignum_zero_print(const BIGNUM *bn, char sep)
213 {
214     const char *v = "NULL", *suf = "";
215     if (bn != NULL) {
216         suf = ":    0";
217         v = BN_is_negative(bn) ? "-0" : "0";
218     }
219     test_printf_stderr("%*s# %c%*s%s\n", subtest_level(), "", sep, bn_chars,
220                        v, suf);
221 }
222
223 static int convert_bn_memory(const unsigned char *in, size_t bytes,
224                              char *out, int *lz, const BIGNUM *bn)
225 {
226     int n = bytes * 2, i;
227     char *p = out, *q = NULL;
228
229     if (bn != NULL && !BN_is_zero(bn)) {
230         hex_convert_memory(in, bytes, out, BN_OUTPUT_SIZE);
231         if (*lz) {
232             for (; *p == '0' || *p == ' '; p++)
233                 if (*p == '0') {
234                     q = p;
235                     *p = ' ';
236                     n--;
237                 }
238             if (*p == '\0') {
239                 /*
240                  * in[bytes] is defined because we're converting a non-zero
241                  * number and we've not seen a non-zero yet.
242                  */
243                 if ((in[bytes] & 0xf0) != 0 && BN_is_negative(bn)) {
244                     *lz = 0;
245                     *q = '-';
246                     n++;
247                 }
248             } else {
249                 *lz = 0;
250                 if (BN_is_negative(bn)) {
251                     /*
252                      * This is valid because we always convert more digits than
253                      * the number holds.
254                      */
255                     *q = '-';
256                     n++;
257                 }
258             }
259         }
260        return n;
261     }
262
263     for (i = 0; i < n; i++) {
264         *p++ = ' ';
265         if (i % (2 * BN_OUTPUT_SIZE) == 2 * BN_OUTPUT_SIZE - 1 && i != n - 1)
266             *p++ = ' ';
267     }
268     *p = '\0';
269     if (bn == NULL)
270         q = "NULL";
271     else
272         q = BN_is_negative(bn) ? "-0" : "0";
273     strcpy(p - strlen(q), q);
274     return 0;
275 }
276
277 static void test_fail_bignum_common(const char *prefix, const char *file,
278                                     int line, const char *type,
279                                     const char *left, const char *right,
280                                     const char *op,
281                                     const BIGNUM *bn1, const BIGNUM *bn2)
282 {
283     const int indent = subtest_level();
284     const size_t bytes = bn_bytes;
285     char b1[MAX_STRING_WIDTH + 1], b2[MAX_STRING_WIDTH + 1];
286     char *p, bdiff[MAX_STRING_WIDTH + 1];
287     size_t l1, l2, n1, n2, i, len;
288     unsigned int cnt, diff, real_diff;
289     unsigned char *m1 = NULL, *m2 = NULL;
290     int lz1 = 1, lz2 = 1;
291     unsigned char buffer[MEM_BUFFER_SIZE * 2], *bufp = buffer;
292
293     l1 = bn1 == NULL ? 0 : (BN_num_bytes(bn1) + (BN_is_negative(bn1) ? 1 : 0));
294     l2 = bn2 == NULL ? 0 : (BN_num_bytes(bn2) + (BN_is_negative(bn2) ? 1 : 0));
295     if (l1 == 0 && l2 == 0) {
296         if ((bn1 == NULL) == (bn2 == NULL)) {
297             test_bignum_header_line();
298             test_bignum_zero_print(bn1, ' ');
299         } else {
300             test_diff_header(left, right);
301             test_bignum_header_line();
302             test_bignum_zero_print(bn1, '-');
303             test_bignum_zero_print(bn2, '+');
304         }
305         goto fin;
306     }
307
308     if (l1 != l2 || bn1 == NULL || bn2 == NULL || BN_cmp(bn1, bn2) != 0)
309         test_diff_header(left, right);
310     test_bignum_header_line();
311
312     len = ((l1 > l2 ? l1 : l2) + bytes - 1) / bytes * bytes;
313
314     if (len > MEM_BUFFER_SIZE && (bufp = OPENSSL_malloc(len * 2)) == NULL) {
315         bufp = buffer;
316         len = MEM_BUFFER_SIZE;
317         test_printf_stderr("%*s# WARNING: these BIGNUMs have been truncated",
318                            indent, "");
319     }
320
321     if (bn1 != NULL) {
322         m1 = bufp;
323         BN_bn2binpad(bn1, m1, len);
324     }
325     if (bn2 != NULL) {
326         m2 = bufp + len;
327         BN_bn2binpad(bn2, m2, len);
328     }
329
330     while (len > 0) {
331         cnt = 8 * (len - bytes);
332         n1 = convert_bn_memory(m1, bytes, b1, &lz1, bn1);
333         n2 = convert_bn_memory(m2, bytes, b2, &lz2, bn2);
334
335         diff = real_diff = 0;
336         i = 0;
337         p = bdiff;
338         for (i=0; b1[i] != '\0'; i++)
339             if (b1[i] == b2[i] || b1[i] == ' ' || b2[i] == ' ') {
340                 *p++ = ' ';
341                 diff |= b1[i] != b2[i];
342             } else {
343                 *p++ = '^';
344                 real_diff = diff = 1;
345             }
346         *p++ = '\0';
347         if (!diff) {
348             test_printf_stderr("%*s#  %s:% 5d\n", indent, "",
349                                n2 > n1 ? b2 : b1, cnt);
350         } else {
351             if (cnt == 0 && bn1 == NULL)
352                 test_printf_stderr("%*s# -%s\n", indent, "", b1);
353             else if (cnt == 0 || n1 > 0)
354                 test_printf_stderr("%*s# -%s:% 5d\n", indent, "", b1, cnt);
355             if (cnt == 0 && bn2 == NULL)
356                 test_printf_stderr("%*s# +%s\n", indent, "", b2);
357             else if (cnt == 0 || n2 > 0)
358                 test_printf_stderr("%*s# +%s:% 5d\n", indent, "", b2, cnt);
359             if (real_diff && (cnt == 0 || (n1 > 0 && n2 > 0))
360                     && bn1 != NULL && bn2 != NULL)
361                 test_printf_stderr("%*s#  %s\n", indent, "", bdiff);
362         }
363         if (m1 != NULL)
364             m1 += bytes;
365         if (m2 != NULL)
366             m2 += bytes;
367         len -= bytes;
368     }
369 fin:
370     test_printf_stderr("\n");
371     test_flush_stderr();
372     if (bufp != buffer)
373         OPENSSL_free(bufp);
374 }
375
376 static void test_fail_bignum_message(const char *prefix, const char *file,
377                                      int line, const char *type,
378                                      const char *left, const char *right,
379                                      const char *op,
380                                      const BIGNUM *bn1, const BIGNUM *bn2)
381 {
382     test_fail_message_prefix(prefix, file, line, type, left, right, op);
383     test_fail_bignum_common(prefix, file, line, type, left, right, op, bn1, bn2);
384 }
385
386 static void test_fail_bignum_mono_message(const char *prefix, const char *file,
387                                           int line, const char *type,
388                                           const char *left, const char *right,
389                                           const char *op, const BIGNUM *bn)
390 {
391     test_fail_message_prefix(prefix, file, line, type, left, right, op);
392     test_fail_bignum_common(prefix, file, line, type, left, right, op, bn, bn);
393 }
394
395 static void test_memory_null_empty(const unsigned char *m, int indent, char c)
396 {
397     if (m == NULL)
398         test_printf_stderr("%*s# % 4s %c%s\n", indent, "", "", c, "NULL");
399     else
400         test_printf_stderr("%*s# %04x %c%s\n", indent, "", 0u, c, "empty");
401 }
402
403 static void test_fail_memory_message(const char *prefix, const char *file,
404                                      int line, const char *type,
405                                      const char *left, const char *right,
406                                      const char *op,
407                                      const unsigned char *m1, size_t l1,
408                                      const unsigned char *m2, size_t l2)
409 {
410     const int indent = subtest_level();
411     const size_t bytes = (MAX_STRING_WIDTH - 9) / 17 * 8;
412     char b1[MAX_STRING_WIDTH + 1], b2[MAX_STRING_WIDTH + 1];
413     char *p, bdiff[MAX_STRING_WIDTH + 1];
414     size_t n1, n2, i;
415     unsigned int cnt = 0, diff;
416
417     test_fail_message_prefix(prefix, file, line, type, left, right, op);
418     if (m1 == NULL)
419         l1 = 0;
420     if (m2 == NULL)
421         l2 = 0;
422     if (l1 == 0 && l2 == 0) {
423         if ((m1 == NULL) == (m2 == NULL)) {
424             test_memory_null_empty(m1, indent, ' ');
425         } else {
426             test_diff_header(left, right);
427             test_memory_null_empty(m1, indent, '-');
428             test_memory_null_empty(m2, indent, '+');
429         }
430         goto fin;
431     }
432
433     if (l1 != l2 || memcmp(m1, m2, l1) != 0)
434         test_diff_header(left, right);
435
436     while (l1 > 0 || l2 > 0) {
437         n1 = n2 = 0;
438         if (l1 > 0) {
439             n1 = l1 > bytes ? bytes : l1;
440             hex_convert_memory(m1, n1, b1, 8);
441         }
442         if (l2 > 0) {
443             n2 = l2 > bytes ? bytes : l2;
444             hex_convert_memory(m2, n2, b2, 8);
445         }
446
447         diff = 0;
448         i = 0;
449         p = bdiff;
450         if (n1 > 0 && n2 > 0) {
451             const size_t j = n1 < n2 ? n1 : n2;
452
453             for (; i < j; i++) {
454                 if (m1[i] == m2[i]) {
455                     *p++ = ' ';
456                     *p++ = ' ';
457                 } else {
458                     *p++ = '^';
459                     *p++ = '^';
460                     diff = 1;
461                 }
462                 if (i % 8 == 7 && i != j - 1)
463                     *p++ = ' ';
464             }
465             *p++ = '\0';
466         }
467
468         if (n1 == n2 && !diff) {
469             test_printf_stderr("%*s# %04x: %s\n", indent, "", cnt, b1);
470         } else {
471             if (cnt == 0 && (m1 == NULL || l1 == 0))
472                 test_memory_null_empty(m1, indent, '-');
473             else if (n1 > 0)
474                 test_printf_stderr("%*s# %04x:-%s\n", indent, "", cnt, b1);
475             if (cnt == 0 && (m2 == NULL || l2 == 0))
476                 test_memory_null_empty(m2, indent, '+');
477             else if (n2 > 0)
478                 test_printf_stderr("%*s# %04x:+%s\n", indent, "", cnt, b2);
479             if (diff && i > 0)
480                 test_printf_stderr("%*s# % 4s  %s\n", indent, "", "", bdiff);
481         }
482         m1 += n1;
483         m2 += n2;
484         l1 -= n1;
485         l2 -= n2;
486         cnt += bytes;
487     }
488 fin:
489     test_printf_stderr("\n");
490     test_flush_stderr();
491 }
492
493 static void test_fail_message(const char *prefix, const char *file,
494                               int line, const char *type,
495                               const char *left, const char *right,
496                               const char *op, const char *fmt, ...)
497 {
498     va_list ap;
499
500     va_start(ap, fmt);
501     test_fail_message_va(prefix, file, line, type, left, right, op, fmt, ap);
502     va_end(ap);
503 }
504
505 void test_info_c90(const char *desc, ...)
506 {
507     va_list ap;
508
509     va_start(ap, desc);
510     test_fail_message_va("INFO", NULL, -1, NULL, NULL, NULL, NULL, desc, ap);
511     va_end(ap);
512 }
513
514 void test_info(const char *file, int line, const char *desc, ...)
515 {
516     va_list ap;
517
518     va_start(ap, desc);
519     test_fail_message_va("INFO", file, line, NULL, NULL, NULL, NULL, desc, ap);
520     va_end(ap);
521 }
522
523 void test_error_c90(const char *desc, ...)
524 {
525     va_list ap;
526
527     va_start(ap, desc);
528     test_fail_message(NULL, NULL, -1, NULL, NULL, NULL, NULL, desc, ap);
529     va_end(ap);
530 }
531
532 void test_error(const char *file, int line, const char *desc, ...)
533 {
534     va_list ap;
535
536     va_start(ap, desc);
537     test_fail_message_va(NULL, file, line, NULL, NULL, NULL, NULL, desc, ap);
538     va_end(ap);
539 }
540
541 void test_openssl_errors(void)
542 {
543     ERR_print_errors_cb(openssl_error_cb, NULL);
544 }
545
546 /*
547  * Define some comparisons between pairs of various types.
548  * These functions return 1 if the test is true.
549  * Otherwise, they return 0 and pretty-print diagnostics.
550  *
551  * In each case the functions produced are:
552  *  int test_name_eq(const type t1, const type t2, const char *desc, ...);
553  *  int test_name_ne(const type t1, const type t2, const char *desc, ...);
554  *  int test_name_lt(const type t1, const type t2, const char *desc, ...);
555  *  int test_name_le(const type t1, const type t2, const char *desc, ...);
556  *  int test_name_gt(const type t1, const type t2, const char *desc, ...);
557  *  int test_name_ge(const type t1, const type t2, const char *desc, ...);
558  *
559  * The t1 and t2 arguments are to be compared for equality, inequality,
560  * less than, less than or equal to, greater than and greater than or
561  * equal to respectively.  If the specified condition holds, the functions
562  * return 1.  If the condition does not hold, the functions print a diagnostic
563  * message and return 0.
564  *
565  * The desc argument is a printf format string followed by its arguments and
566  * this is included in the output if the condition being tested for is false.
567  */
568 #define DEFINE_COMPARISON(type, name, opname, op, fmt)                  \
569     int test_ ## name ## _ ## opname(const char *file, int line,        \
570                                      const char *s1, const char *s2,    \
571                                      const type t1, const type t2)      \
572     {                                                                   \
573         if (t1 op t2)                                                   \
574             return 1;                                                   \
575         test_fail_message(NULL, file, line, #type, s1, s2, #op,         \
576                           "[" fmt "] compared to [" fmt "]",            \
577                           t1, t2);                                      \
578         return 0;                                                       \
579     }
580
581 #define DEFINE_COMPARISONS(type, name, fmt)                             \
582     DEFINE_COMPARISON(type, name, eq, ==, fmt)                          \
583     DEFINE_COMPARISON(type, name, ne, !=, fmt)                          \
584     DEFINE_COMPARISON(type, name, lt, <, fmt)                           \
585     DEFINE_COMPARISON(type, name, le, <=, fmt)                          \
586     DEFINE_COMPARISON(type, name, gt, >, fmt)                           \
587     DEFINE_COMPARISON(type, name, ge, >=, fmt)
588
589 DEFINE_COMPARISONS(int, int, "%d")
590 DEFINE_COMPARISONS(unsigned int, uint, "%u")
591 DEFINE_COMPARISONS(char, char, "%c")
592 DEFINE_COMPARISONS(unsigned char, uchar, "%u")
593 DEFINE_COMPARISONS(long, long, "%ld")
594 DEFINE_COMPARISONS(unsigned long, ulong, "%lu")
595 DEFINE_COMPARISONS(size_t, size_t, "%zu")
596
597 DEFINE_COMPARISON(void *, ptr, eq, ==, "%p")
598 DEFINE_COMPARISON(void *, ptr, ne, !=, "%p")
599
600 int test_ptr_null(const char *file, int line, const char *s, const void *p)
601 {
602     if (p == NULL)
603         return 1;
604     test_fail_message(NULL, file, line, "ptr", s, "NULL", "==", "%p", p);
605     return 0;
606 }
607
608 int test_ptr(const char *file, int line, const char *s, const void *p)
609 {
610     if (p != NULL)
611         return 1;
612     test_fail_message(NULL, file, line, "ptr", s, "NULL", "!=", "%p", p);
613     return 0;
614 }
615
616 int test_true(const char *file, int line, const char *s, int b)
617 {
618     if (b)
619         return 1;
620     test_fail_message(NULL, file, line, "bool", s, "true", "==", "false");
621     return 0;
622 }
623
624 int test_false(const char *file, int line, const char *s, int b)
625 {
626     if (!b)
627         return 1;
628     test_fail_message(NULL, file, line, "bool", s, "false", "==", "true");
629     return 0;
630 }
631
632 int test_str_eq(const char *file, int line, const char *st1, const char *st2,
633                 const char *s1, const char *s2)
634 {
635     if (s1 == NULL && s2 == NULL)
636       return 1;
637     if (s1 == NULL || s2 == NULL || strcmp(s1, s2) != 0) {
638         test_fail_string_message(NULL, file, line, "string", st1, st2, "==",
639                                  s1, s1 == NULL ? 0 : strlen(s1),
640                                  s2, s2 == NULL ? 0 : strlen(s2));
641         return 0;
642     }
643     return 1;
644 }
645
646 int test_str_ne(const char *file, int line, const char *st1, const char *st2,
647                 const char *s1, const char *s2)
648 {
649     if ((s1 == NULL) ^ (s2 == NULL))
650       return 1;
651     if (s1 == NULL || strcmp(s1, s2) == 0) {
652         test_fail_string_message(NULL, file, line, "string", st1, st2, "!=",
653                                  s1, s1 == NULL ? 0 : strlen(s1),
654                                  s2, s2 == NULL ? 0 : strlen(s2));
655         return 0;
656     }
657     return 1;
658 }
659
660 int test_strn_eq(const char *file, int line, const char *st1, const char *st2,
661                  const char *s1, const char *s2, size_t len)
662 {
663     if (s1 == NULL && s2 == NULL)
664       return 1;
665     if (s1 == NULL || s2 == NULL || strncmp(s1, s2, len) != 0) {
666         test_fail_string_message(NULL, file, line, "string", st1, st2, "==",
667                                  s1, s1 == NULL ? 0 : OPENSSL_strnlen(s1, len),
668                                  s2, s2 == NULL ? 0 : OPENSSL_strnlen(s2, len));
669         return 0;
670     }
671     return 1;
672 }
673
674 int test_strn_ne(const char *file, int line, const char *st1, const char *st2,
675                  const char *s1, const char *s2, size_t len)
676 {
677     if ((s1 == NULL) ^ (s2 == NULL))
678       return 1;
679     if (s1 == NULL || strncmp(s1, s2, len) == 0) {
680         test_fail_string_message(NULL, file, line, "string", st1, st2, "!=",
681                                  s1, s1 == NULL ? 0 : OPENSSL_strnlen(s1, len),
682                                  s2, s2 == NULL ? 0 : OPENSSL_strnlen(s2, len));
683         return 0;
684     }
685     return 1;
686 }
687
688 int test_mem_eq(const char *file, int line, const char *st1, const char *st2,
689                 const void *s1, size_t n1, const void *s2, size_t n2)
690 {
691     if (s1 == NULL && s2 == NULL)
692         return 1;
693     if (n1 != n2 || s1 == NULL || s2 == NULL || memcmp(s1, s2, n1) != 0) {
694         test_fail_memory_message(NULL, file, line, "memory", st1, st2, "==",
695                                  s1, n1, s2, n2);
696         return 0;
697     }
698     return 1;
699 }
700
701 int test_mem_ne(const char *file, int line, const char *st1, const char *st2,
702                 const void *s1, size_t n1, const void *s2, size_t n2)
703 {
704     if ((s1 == NULL) ^ (s2 == NULL))
705         return 1;
706     if (n1 != n2)
707         return 1;
708     if (s1 == NULL || memcmp(s1, s2, n1) == 0) {
709         test_fail_memory_message(NULL, file, line, "memory", st1, st2, "!=",
710                                  s1, n1, s2, n2);
711         return 0;
712     }
713     return 1;
714 }
715
716 #define DEFINE_BN_COMPARISONS(opname, op, zero_cond)                    \
717     int test_BN_ ## opname(const char *file, int line,                  \
718                            const char *s1, const char *s2,              \
719                            const BIGNUM *t1, const BIGNUM *t2)          \
720     {                                                                   \
721         if (BN_cmp(t1, t2) op 0)                                        \
722             return 1;                                                   \
723         test_fail_bignum_message(NULL, file, line, "BIGNUM", s1, s2,    \
724                                  #op, t1, t2);                          \
725         return 0;                                                       \
726     }                                                                   \
727     int test_BN_ ## opname ## _zero(const char *file, int line,         \
728                                     const char *s, const BIGNUM *a)     \
729     {                                                                   \
730         if (a != NULL &&(zero_cond))                                    \
731             return 1;                                                   \
732         test_fail_bignum_mono_message(NULL, file, line, "BIGNUM",       \
733                                       s, "0", #op, a);                  \
734         return 0;                                                       \
735     }
736
737 DEFINE_BN_COMPARISONS(eq, ==, BN_is_zero(a))
738 DEFINE_BN_COMPARISONS(ne, !=, !BN_is_zero(a))
739 DEFINE_BN_COMPARISONS(gt, >,  !BN_is_negative(a) && !BN_is_zero(a))
740 DEFINE_BN_COMPARISONS(ge, >=, !BN_is_negative(a) || BN_is_zero(a))
741 DEFINE_BN_COMPARISONS(lt, <,  BN_is_negative(a) && !BN_is_zero(a))
742 DEFINE_BN_COMPARISONS(le, <=, BN_is_negative(a) || BN_is_zero(a))
743
744 int test_BN_eq_one(const char *file, int line, const char *s, const BIGNUM *a)
745 {
746     if (a != NULL && BN_is_one(a))
747         return 1;
748     test_fail_bignum_mono_message(NULL, file, line, "BIGNUM", s, "1", "==", a);
749     return 0;
750 }
751
752 int test_BN_odd(const char *file, int line, const char *s, const BIGNUM *a)
753 {
754     if (a != NULL && BN_is_odd(a))
755         return 1;
756     test_fail_bignum_mono_message(NULL, file, line, "BIGNUM", "ODD(", ")", s, a);
757     return 0;
758 }
759
760 int test_BN_even(const char *file, int line, const char *s, const BIGNUM *a)
761 {
762     if (a != NULL && !BN_is_odd(a))
763         return 1;
764     test_fail_bignum_mono_message(NULL, file, line, "BIGNUM", "EVEN(", ")", s,
765                                   a);
766     return 0;
767 }
768
769 int test_BN_eq_word(const char *file, int line, const char *bns, const char *ws,
770                     const BIGNUM *a, BN_ULONG w)
771 {
772     BIGNUM *bw;
773
774     if (a != NULL && BN_is_word(a, w))
775         return 1;
776     bw = BN_new();
777     BN_set_word(bw, w);
778     test_fail_bignum_message(NULL, file, line, "BIGNUM", bns, ws, "==", a, bw);
779     BN_free(bw);
780     return 0;
781 }
782
783 int test_BN_abs_eq_word(const char *file, int line, const char *bns,
784                         const char *ws, const BIGNUM *a, BN_ULONG w)
785 {
786     BIGNUM *bw, *aa;
787
788     if (a != NULL && BN_abs_is_word(a, w))
789         return 1;
790     bw = BN_new();
791     aa = BN_dup(a);
792     BN_set_negative(aa, 0);
793     BN_set_word(bw, w);
794     test_fail_bignum_message(NULL, file, line, "BIGNUM", bns, ws, "abs==",
795                              aa, bw);
796     BN_free(bw);
797     BN_free(aa);
798     return 0;
799 }