Home | History | Annotate | Line # | Download | only in testutil
tests.c revision 1.7
      1 /*
      2  * Copyright 2017-2021 The OpenSSL Project Authors. All Rights Reserved.
      3  *
      4  * Licensed under the Apache License 2.0 (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 <errno.h>
     15 #include <string.h>
     16 #include <ctype.h>
     17 #include "internal/nelem.h"
     18 #include <openssl/asn1.h>
     19 
     20 /*
     21  * Output a failed test first line.
     22  * All items are optional are generally not preinted if passed as NULL.
     23  * The special cases are for prefix where "ERROR" is assumed and for left
     24  * and right where a non-failure message is produced if either is NULL.
     25  */
     26 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: ", prefix != NULL ? prefix : "ERROR");
     32     if (type)
     33         test_printf_stderr("(%s) ", type);
     34     if (op != NULL) {
     35         if (left != NULL && right != NULL)
     36             test_printf_stderr("'%s %s %s' failed", left, op, right);
     37         else
     38             test_printf_stderr("'%s'", op);
     39     }
     40     if (file != NULL) {
     41         test_printf_stderr(" @ %s:%d", file, line);
     42     }
     43     test_printf_stderr("\n");
     44 }
     45 
     46 /*
     47  * A common routine to output test failure messages.  Generally this should not
     48  * be called directly, rather it should be called by the following functions.
     49  *
     50  * |desc| is a printf formatted description with arguments |args| that is
     51  * supplied by the user and |desc| can be NULL.  |type| is the data type
     52  * that was tested (int, char, ptr, ...).  |fmt| is a system provided
     53  * printf format with following arguments that spell out the failure
     54  * details i.e. the actual values compared and the operator used.
     55  *
     56  * The typical use for this is from an utility test function:
     57  *
     58  * int test6(const char *file, int line, int n) {
     59  *     if (n != 6) {
     60  *         test_fail_message(1, file, line, "int", "value %d is not %d", n, 6);
     61  *         return 0;
     62  *     }
     63  *     return 1;
     64  * }
     65  *
     66  * calling test6(3, "oops") will return 0 and produce out along the lines of:
     67  *      FAIL oops: (int) value 3 is not 6\n
     68  */
     69 static void test_fail_message(const char *prefix, const char *file, int line,
     70                               const char *type, const char *left,
     71                               const char *right, const char *op,
     72                               const char *fmt, ...)
     73             PRINTF_FORMAT(8, 9);
     74 
     75 PRINTF_FORMAT(8, 0)
     76 static void test_fail_message_va(const char *prefix, const char *file,
     77                                  int line, const char *type,
     78                                  const char *left, const char *right,
     79                                  const char *op, const char *fmt, va_list ap)
     80 {
     81     test_fail_message_prefix(prefix, file, line, type, left, right, op);
     82     if (fmt != NULL) {
     83         test_vprintf_stderr(fmt, ap);
     84         test_printf_stderr("\n");
     85     }
     86     test_flush_stderr();
     87 }
     88 
     89 static void test_fail_message(const char *prefix, const char *file,
     90                               int line, const char *type,
     91                               const char *left, const char *right,
     92                               const char *op, const char *fmt, ...)
     93 {
     94     va_list ap;
     95 
     96     va_start(ap, fmt);
     97     test_fail_message_va(prefix, file, line, type, left, right, op, fmt, ap);
     98     va_end(ap);
     99 }
    100 
    101 void test_info_c90(const char *desc, ...)
    102 {
    103     va_list ap;
    104 
    105     va_start(ap, desc);
    106     test_fail_message_va("INFO", NULL, -1, NULL, NULL, NULL, NULL, desc, ap);
    107     va_end(ap);
    108 }
    109 
    110 void test_info(const char *file, int line, const char *desc, ...)
    111 {
    112     va_list ap;
    113 
    114     va_start(ap, desc);
    115     test_fail_message_va("INFO", file, line, NULL, NULL, NULL, NULL, desc, ap);
    116     va_end(ap);
    117 }
    118 
    119 void test_error_c90(const char *desc, ...)
    120 {
    121     va_list ap;
    122 
    123     va_start(ap, desc);
    124     test_fail_message_va(NULL, NULL, -1, NULL, NULL, NULL, NULL, desc, ap);
    125     va_end(ap);
    126     test_printf_stderr("\n");
    127 }
    128 
    129 void test_error(const char *file, int line, const char *desc, ...)
    130 {
    131     va_list ap;
    132 
    133     va_start(ap, desc);
    134     test_fail_message_va(NULL, file, line, NULL, NULL, NULL, NULL, desc, ap);
    135     va_end(ap);
    136     test_printf_stderr("\n");
    137 }
    138 
    139 void test_perror(const char *s)
    140 {
    141     /*
    142      * Using openssl_strerror_r causes linking issues since it isn't
    143      * exported from libcrypto.so
    144      */
    145     TEST_error("%s: %s", s, strerror(errno));
    146 }
    147 
    148 void test_note(const char *fmt, ...)
    149 {
    150     if (fmt != NULL) {
    151         va_list ap;
    152 
    153         va_start(ap, fmt);
    154         test_vprintf_stderr(fmt, ap);
    155         va_end(ap);
    156         test_printf_stderr("\n");
    157     }
    158     test_flush_stderr();
    159 }
    160 
    161 
    162 int test_skip(const char *file, int line, const char *desc, ...)
    163 {
    164     va_list ap;
    165 
    166     va_start(ap, desc);
    167     test_fail_message_va("SKIP", file, line, NULL, NULL, NULL, NULL, desc, ap);
    168     va_end(ap);
    169     return TEST_SKIP_CODE;
    170 }
    171 
    172 int test_skip_c90(const char *desc, ...)
    173 {
    174     va_list ap;
    175 
    176     va_start(ap, desc);
    177     test_fail_message_va("SKIP", NULL, -1, NULL, NULL, NULL, NULL, desc, ap);
    178     va_end(ap);
    179     test_printf_stderr("\n");
    180     return TEST_SKIP_CODE;
    181 }
    182 
    183 
    184 void test_openssl_errors(void)
    185 {
    186     ERR_print_errors_cb(openssl_error_cb, NULL);
    187     ERR_clear_error();
    188 }
    189 
    190 /*
    191  * Define some comparisons between pairs of various types.
    192  * These functions return 1 if the test is true.
    193  * Otherwise, they return 0 and pretty-print diagnostics.
    194  *
    195  * In each case the functions produced are:
    196  *  int test_name_eq(const type t1, const type t2, const char *desc, ...);
    197  *  int test_name_ne(const type t1, const type t2, const char *desc, ...);
    198  *  int test_name_lt(const type t1, const type t2, const char *desc, ...);
    199  *  int test_name_le(const type t1, const type t2, const char *desc, ...);
    200  *  int test_name_gt(const type t1, const type t2, const char *desc, ...);
    201  *  int test_name_ge(const type t1, const type t2, const char *desc, ...);
    202  *
    203  * The t1 and t2 arguments are to be compared for equality, inequality,
    204  * less than, less than or equal to, greater than and greater than or
    205  * equal to respectively.  If the specified condition holds, the functions
    206  * return 1.  If the condition does not hold, the functions print a diagnostic
    207  * message and return 0.
    208  *
    209  * The desc argument is a printf format string followed by its arguments and
    210  * this is included in the output if the condition being tested for is false.
    211  */
    212 #define DEFINE_COMPARISON(type, name, opname, op, fmt)                  \
    213     int test_ ## name ## _ ## opname(const char *file, int line,        \
    214                                      const char *s1, const char *s2,    \
    215                                      const type t1, const type t2)      \
    216     {                                                                   \
    217         if (t1 op t2)                                                   \
    218             return 1;                                                   \
    219         test_fail_message(NULL, file, line, #type, s1, s2, #op,         \
    220                           "[" fmt "] compared to [" fmt "]",            \
    221                           t1, t2);                                      \
    222         return 0;                                                       \
    223     }
    224 
    225 #define DEFINE_COMPARISONS(type, name, fmt)                             \
    226     DEFINE_COMPARISON(type, name, eq, ==, fmt)                          \
    227     DEFINE_COMPARISON(type, name, ne, !=, fmt)                          \
    228     DEFINE_COMPARISON(type, name, lt, <, fmt)                           \
    229     DEFINE_COMPARISON(type, name, le, <=, fmt)                          \
    230     DEFINE_COMPARISON(type, name, gt, >, fmt)                           \
    231     DEFINE_COMPARISON(type, name, ge, >=, fmt)
    232 
    233 DEFINE_COMPARISONS(int, int, "%d")
    234 DEFINE_COMPARISONS(unsigned int, uint, "%u")
    235 DEFINE_COMPARISONS(char, char, "%c")
    236 DEFINE_COMPARISONS(unsigned char, uchar, "%u")
    237 DEFINE_COMPARISONS(long, long, "%ld")
    238 DEFINE_COMPARISONS(unsigned long, ulong, "%lu")
    239 DEFINE_COMPARISONS(size_t, size_t, "%zu")
    240 DEFINE_COMPARISONS(double, double, "%g")
    241 
    242 DEFINE_COMPARISON(void *, ptr, eq, ==, "%p")
    243 DEFINE_COMPARISON(void *, ptr, ne, !=, "%p")
    244 
    245 int test_ptr_null(const char *file, int line, const char *s, const void *p)
    246 {
    247     if (p == NULL)
    248         return 1;
    249     test_fail_message(NULL, file, line, "ptr", s, "NULL", "==", "%p", p);
    250     return 0;
    251 }
    252 
    253 int test_ptr(const char *file, int line, const char *s, const void *p)
    254 {
    255     if (p != NULL)
    256         return 1;
    257     test_fail_message(NULL, file, line, "ptr", s, "NULL", "!=", "%p", p);
    258     return 0;
    259 }
    260 
    261 int test_true(const char *file, int line, const char *s, int b)
    262 {
    263     if (b)
    264         return 1;
    265     test_fail_message(NULL, file, line, "bool", s, "true", "==", "false");
    266     return 0;
    267 }
    268 
    269 int test_false(const char *file, int line, const char *s, int b)
    270 {
    271     if (!b)
    272         return 1;
    273     test_fail_message(NULL, file, line, "bool", s, "false", "==", "true");
    274     return 0;
    275 }
    276 
    277 int test_str_eq(const char *file, int line, const char *st1, const char *st2,
    278                 const char *s1, const char *s2)
    279 {
    280     if (s1 == NULL && s2 == NULL)
    281       return 1;
    282     if (s1 == NULL || s2 == NULL || strcmp(s1, s2) != 0) {
    283         test_fail_string_message(NULL, file, line, "string", st1, st2, "==",
    284                                  s1, s1 == NULL ? 0 : strlen(s1),
    285                                  s2, s2 == NULL ? 0 : strlen(s2));
    286         return 0;
    287     }
    288     return 1;
    289 }
    290 
    291 int test_str_ne(const char *file, int line, const char *st1, const char *st2,
    292                 const char *s1, const char *s2)
    293 {
    294     if ((s1 == NULL) ^ (s2 == NULL))
    295       return 1;
    296     if (s1 == NULL || strcmp(s1, s2) == 0) {
    297         test_fail_string_message(NULL, file, line, "string", st1, st2, "!=",
    298                                  s1, s1 == NULL ? 0 : strlen(s1),
    299                                  s2, s2 == NULL ? 0 : strlen(s2));
    300         return 0;
    301     }
    302     return 1;
    303 }
    304 
    305 int test_strn_eq(const char *file, int line, const char *st1, const char *st2,
    306                  const char *s1, size_t n1, const char *s2, size_t n2)
    307 {
    308     if (s1 == NULL && s2 == NULL)
    309       return 1;
    310     if (n1 != n2 || s1 == NULL || s2 == NULL || strncmp(s1, s2, n1) != 0) {
    311         test_fail_string_message(NULL, file, line, "string", st1, st2, "==",
    312                                  s1, s1 == NULL ? 0 : OPENSSL_strnlen(s1, n1),
    313                                  s2, s2 == NULL ? 0 : OPENSSL_strnlen(s2, n2));
    314         return 0;
    315     }
    316     return 1;
    317 }
    318 
    319 int test_strn_ne(const char *file, int line, const char *st1, const char *st2,
    320                  const char *s1, size_t n1, const char *s2, size_t n2)
    321 {
    322     if ((s1 == NULL) ^ (s2 == NULL))
    323       return 1;
    324     if (n1 != n2 || s1 == NULL || strncmp(s1, s2, n1) == 0) {
    325         test_fail_string_message(NULL, file, line, "string", st1, st2, "!=",
    326                                  s1, s1 == NULL ? 0 : OPENSSL_strnlen(s1, n1),
    327                                  s2, s2 == NULL ? 0 : OPENSSL_strnlen(s2, n2));
    328         return 0;
    329     }
    330     return 1;
    331 }
    332 
    333 int test_mem_eq(const char *file, int line, const char *st1, const char *st2,
    334                 const void *s1, size_t n1, const void *s2, size_t n2)
    335 {
    336     if (s1 == NULL && s2 == NULL)
    337         return 1;
    338     if (n1 != n2 || s1 == NULL || s2 == NULL || memcmp(s1, s2, n1) != 0) {
    339         test_fail_memory_message(NULL, file, line, "memory", st1, st2, "==",
    340                                  s1, n1, s2, n2);
    341         return 0;
    342     }
    343     return 1;
    344 }
    345 
    346 int test_mem_ne(const char *file, int line, const char *st1, const char *st2,
    347                 const void *s1, size_t n1, const void *s2, size_t n2)
    348 {
    349     if ((s1 == NULL) ^ (s2 == NULL))
    350         return 1;
    351     if (n1 != n2)
    352         return 1;
    353     if (s1 == NULL || memcmp(s1, s2, n1) == 0) {
    354         test_fail_memory_message(NULL, file, line, "memory", st1, st2, "!=",
    355                                  s1, n1, s2, n2);
    356         return 0;
    357     }
    358     return 1;
    359 }
    360 
    361 #define DEFINE_BN_COMPARISONS(opname, op, zero_cond)                    \
    362     int test_BN_ ## opname(const char *file, int line,                  \
    363                            const char *s1, const char *s2,              \
    364                            const BIGNUM *t1, const BIGNUM *t2)          \
    365     {                                                                   \
    366         if (BN_cmp(t1, t2) op 0)                                        \
    367             return 1;                                                   \
    368         test_fail_bignum_message(NULL, file, line, "BIGNUM", s1, s2,    \
    369                                  #op, t1, t2);                          \
    370         return 0;                                                       \
    371     }                                                                   \
    372     int test_BN_ ## opname ## _zero(const char *file, int line,         \
    373                                     const char *s, const BIGNUM *a)     \
    374     {                                                                   \
    375         if (a != NULL &&(zero_cond))                                    \
    376             return 1;                                                   \
    377         test_fail_bignum_mono_message(NULL, file, line, "BIGNUM",       \
    378                                       s, "0", #op, a);                  \
    379         return 0;                                                       \
    380     }
    381 
    382 DEFINE_BN_COMPARISONS(eq, ==, BN_is_zero(a))
    383 DEFINE_BN_COMPARISONS(ne, !=, !BN_is_zero(a))
    384 DEFINE_BN_COMPARISONS(gt, >,  !BN_is_negative(a) && !BN_is_zero(a))
    385 DEFINE_BN_COMPARISONS(ge, >=, !BN_is_negative(a) || BN_is_zero(a))
    386 DEFINE_BN_COMPARISONS(lt, <,  BN_is_negative(a) && !BN_is_zero(a))
    387 DEFINE_BN_COMPARISONS(le, <=, BN_is_negative(a) || BN_is_zero(a))
    388 
    389 int test_BN_eq_one(const char *file, int line, const char *s, const BIGNUM *a)
    390 {
    391     if (a != NULL && BN_is_one(a))
    392         return 1;
    393     test_fail_bignum_mono_message(NULL, file, line, "BIGNUM", s, "1", "==", a);
    394     return 0;
    395 }
    396 
    397 int test_BN_odd(const char *file, int line, const char *s, const BIGNUM *a)
    398 {
    399     if (a != NULL && BN_is_odd(a))
    400         return 1;
    401     test_fail_bignum_mono_message(NULL, file, line, "BIGNUM", "ODD(", ")", s, a);
    402     return 0;
    403 }
    404 
    405 int test_BN_even(const char *file, int line, const char *s, const BIGNUM *a)
    406 {
    407     if (a != NULL && !BN_is_odd(a))
    408         return 1;
    409     test_fail_bignum_mono_message(NULL, file, line, "BIGNUM", "EVEN(", ")", s,
    410                                   a);
    411     return 0;
    412 }
    413 
    414 int test_BN_eq_word(const char *file, int line, const char *bns, const char *ws,
    415                     const BIGNUM *a, BN_ULONG w)
    416 {
    417     BIGNUM *bw;
    418 
    419     if (a != NULL && BN_is_word(a, w))
    420         return 1;
    421     if ((bw = BN_new()) != NULL)
    422         BN_set_word(bw, w);
    423     test_fail_bignum_message(NULL, file, line, "BIGNUM", bns, ws, "==", a, bw);
    424     BN_free(bw);
    425     return 0;
    426 }
    427 
    428 int test_BN_abs_eq_word(const char *file, int line, const char *bns,
    429                         const char *ws, const BIGNUM *a, BN_ULONG w)
    430 {
    431     BIGNUM *bw, *aa;
    432 
    433     if (a != NULL && BN_abs_is_word(a, w))
    434         return 1;
    435     if ((aa = BN_dup(a)) != NULL)
    436         BN_set_negative(aa, 0);
    437     if ((bw = BN_new()) != NULL)
    438         BN_set_word(bw, w);
    439     test_fail_bignum_message(NULL, file, line, "BIGNUM", bns, ws, "abs==",
    440                              aa, bw);
    441     BN_free(bw);
    442     BN_free(aa);
    443     return 0;
    444 }
    445 
    446 static const char *print_time(const ASN1_TIME *t)
    447 {
    448     return t == NULL ? "<null>" : (const char *)ASN1_STRING_get0_data(t);
    449 }
    450 
    451 #define DEFINE_TIME_T_COMPARISON(opname, op)                            \
    452     int test_time_t_ ## opname(const char *file, int line,              \
    453                                const char *s1, const char *s2,          \
    454                                const time_t t1, const time_t t2)        \
    455     {                                                                   \
    456         ASN1_TIME *at1 = ASN1_TIME_set(NULL, t1);                       \
    457         ASN1_TIME *at2 = ASN1_TIME_set(NULL, t2);                       \
    458         int r = at1 != NULL && at2 != NULL                              \
    459                 && ASN1_TIME_compare(at1, at2) op 0;                    \
    460         if (!r)                                                         \
    461             test_fail_message(NULL, file, line, "time_t", s1, s2, #op,  \
    462                               "[%s] compared to [%s]",                  \
    463                               print_time(at1), print_time(at2));        \
    464         ASN1_STRING_free(at1);                                          \
    465         ASN1_STRING_free(at2);                                          \
    466         return r;                                                       \
    467     }
    468 DEFINE_TIME_T_COMPARISON(eq, ==)
    469 DEFINE_TIME_T_COMPARISON(ne, !=)
    470 DEFINE_TIME_T_COMPARISON(gt, >)
    471 DEFINE_TIME_T_COMPARISON(ge, >=)
    472 DEFINE_TIME_T_COMPARISON(lt, <)
    473 DEFINE_TIME_T_COMPARISON(le, <=)
    474