Home | History | Annotate | Line # | Download | only in testutil
      1 /*
      2  * Copyright 2017-2025 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 <openssl/asn1.h>
     18 
     19 /*
     20  * Output a failed test first line.
     21  * All items are optional are generally not printed if passed as NULL.
     22  * The special cases are for prefix where "ERROR" is assumed and for left
     23  * and right where a non-failure message is produced if either is NULL.
     24  */
     25 void test_fail_message_prefix(const char *prefix, const char *file,
     26     int line, const char *type,
     27     const char *left, const char *right,
     28     const char *op)
     29 {
     30     test_printf_stderr("%s: ", prefix != NULL ? prefix : "ERROR");
     31     if (type)
     32         test_printf_stderr("(%s) ", type);
     33     if (op != NULL) {
     34         if (left != NULL && right != NULL)
     35             test_printf_stderr("'%s %s %s' failed", left, op, right);
     36         else
     37             test_printf_stderr("'%s'", op);
     38     }
     39     if (file != NULL) {
     40         test_printf_stderr(" @ %s:%d", file, line);
     41     }
     42     test_printf_stderr("\n");
     43 }
     44 
     45 /*
     46  * A common routine to output test failure messages.  Generally this should not
     47  * be called directly, rather it should be called by the following functions.
     48  *
     49  * |desc| is a printf formatted description with arguments |args| that is
     50  * supplied by the user and |desc| can be NULL.  |type| is the data type
     51  * that was tested (int, char, ptr, ...).  |fmt| is a system provided
     52  * printf format with following arguments that spell out the failure
     53  * details i.e. the actual values compared and the operator used.
     54  *
     55  * The typical use for this is from an utility test function:
     56  *
     57  * int test6(const char *file, int line, int n) {
     58  *     if (n != 6) {
     59  *         test_fail_message(1, file, line, "int", "value %d is not %d", n, 6);
     60  *         return 0;
     61  *     }
     62  *     return 1;
     63  * }
     64  *
     65  * calling test6(3, "oops") will return 0 and produce out along the lines of:
     66  *      FAIL oops: (int) value 3 is not 6\n
     67  */
     68 static void test_fail_message(const char *prefix, const char *file, int line,
     69     const char *type, const char *left,
     70     const char *right, const char *op,
     71     const char *fmt, ...)
     72     PRINTF_FORMAT(8, 9);
     73 
     74 PRINTF_FORMAT(8, 0)
     75 static void test_fail_message_va(const char *prefix, const char *file,
     76     int line, const char *type,
     77     const char *left, const char *right,
     78     const char *op, const char *fmt, va_list ap)
     79 {
     80     test_fail_message_prefix(prefix, file, line, type, left, right, op);
     81     if (fmt != NULL) {
     82         test_vprintf_stderr(fmt, ap);
     83         test_printf_stderr("\n");
     84     }
     85     test_flush_stderr();
     86 }
     87 
     88 static void test_fail_message(const char *prefix, const char *file,
     89     int line, const char *type,
     90     const char *left, const char *right,
     91     const char *op, const char *fmt, ...)
     92 {
     93     va_list ap;
     94 
     95     va_start(ap, fmt);
     96     test_fail_message_va(prefix, file, line, type, left, right, op, fmt, ap);
     97     va_end(ap);
     98 }
     99 
    100 void test_info_c90(const char *desc, ...)
    101 {
    102     va_list ap;
    103 
    104     va_start(ap, desc);
    105     test_fail_message_va("INFO", NULL, -1, NULL, NULL, NULL, NULL, desc, ap);
    106     va_end(ap);
    107 }
    108 
    109 void test_info(const char *file, int line, const char *desc, ...)
    110 {
    111     va_list ap;
    112 
    113     va_start(ap, desc);
    114     test_fail_message_va("INFO", file, line, NULL, NULL, NULL, NULL, desc, ap);
    115     va_end(ap);
    116 }
    117 
    118 void test_error_c90(const char *desc, ...)
    119 {
    120     va_list ap;
    121 
    122     va_start(ap, desc);
    123     test_fail_message_va(NULL, NULL, -1, NULL, NULL, NULL, NULL, desc, ap);
    124     va_end(ap);
    125     test_printf_stderr("\n");
    126 }
    127 
    128 void test_error(const char *file, int line, const char *desc, ...)
    129 {
    130     va_list ap;
    131 
    132     va_start(ap, desc);
    133     test_fail_message_va(NULL, file, line, NULL, NULL, NULL, NULL, desc, ap);
    134     va_end(ap);
    135     test_printf_stderr("\n");
    136 }
    137 
    138 void test_perror(const char *s)
    139 {
    140     /*
    141      * Using openssl_strerror_r causes linking issues since it isn't
    142      * exported from libcrypto.so
    143      */
    144     TEST_error("%s: %s", s, strerror(errno));
    145 }
    146 
    147 void test_note(const char *fmt, ...)
    148 {
    149     test_flush_stdout();
    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 int test_skip(const char *file, int line, const char *desc, ...)
    162 {
    163     va_list ap;
    164 
    165     va_start(ap, desc);
    166     test_fail_message_va("SKIP", file, line, NULL, NULL, NULL, NULL, desc, ap);
    167     va_end(ap);
    168     return TEST_SKIP_CODE;
    169 }
    170 
    171 int test_skip_c90(const char *desc, ...)
    172 {
    173     va_list ap;
    174 
    175     va_start(ap, desc);
    176     test_fail_message_va("SKIP", NULL, -1, NULL, NULL, NULL, NULL, desc, ap);
    177     va_end(ap);
    178     test_printf_stderr("\n");
    179     return TEST_SKIP_CODE;
    180 }
    181 
    182 void test_openssl_errors(void)
    183 {
    184     ERR_print_errors_cb(openssl_error_cb, NULL);
    185     ERR_clear_error();
    186 }
    187 
    188 /*
    189  * Define some comparisons between pairs of various types.
    190  * These functions return 1 if the test is true.
    191  * Otherwise, they return 0 and pretty-print diagnostics.
    192  *
    193  * In each case the functions produced are:
    194  *  int test_name_eq(const type t1, const type t2, const char *desc, ...);
    195  *  int test_name_ne(const type t1, const type t2, const char *desc, ...);
    196  *  int test_name_lt(const type t1, const type t2, const char *desc, ...);
    197  *  int test_name_le(const type t1, const type t2, const char *desc, ...);
    198  *  int test_name_gt(const type t1, const type t2, const char *desc, ...);
    199  *  int test_name_ge(const type t1, const type t2, const char *desc, ...);
    200  *
    201  * The t1 and t2 arguments are to be compared for equality, inequality,
    202  * less than, less than or equal to, greater than and greater than or
    203  * equal to respectively.  If the specified condition holds, the functions
    204  * return 1.  If the condition does not hold, the functions print a diagnostic
    205  * message and return 0.
    206  *
    207  * The desc argument is a printf format string followed by its arguments and
    208  * this is included in the output if the condition being tested for is false.
    209  */
    210 #define DEFINE_COMPARISON(type, name, opname, op, fmt, cast)    \
    211     int test_##name##_##opname(const char *file, int line,      \
    212         const char *s1, const char *s2,                         \
    213         const type t1, const type t2)                           \
    214     {                                                           \
    215         if (t1 op t2)                                           \
    216             return 1;                                           \
    217         test_fail_message(NULL, file, line, #type, s1, s2, #op, \
    218             "[" fmt "] compared to [" fmt "]",                  \
    219             (cast)t1, (cast)t2);                                \
    220         return 0;                                               \
    221     }
    222 
    223 #define DEFINE_COMPARISONS(type, name, fmt, cast)    \
    224     DEFINE_COMPARISON(type, name, eq, ==, fmt, cast) \
    225     DEFINE_COMPARISON(type, name, ne, !=, fmt, cast) \
    226     DEFINE_COMPARISON(type, name, lt, <, fmt, cast)  \
    227     DEFINE_COMPARISON(type, name, le, <=, fmt, cast) \
    228     DEFINE_COMPARISON(type, name, gt, >, fmt, cast)  \
    229     DEFINE_COMPARISON(type, name, ge, >=, fmt, cast)
    230 
    231 DEFINE_COMPARISONS(int, int, "%d", int)
    232 DEFINE_COMPARISONS(unsigned int, uint, "%u", unsigned int)
    233 DEFINE_COMPARISONS(char, char, "%c", char)
    234 DEFINE_COMPARISONS(unsigned char, uchar, "%u", unsigned char)
    235 DEFINE_COMPARISONS(long, long, "%ld", long)
    236 DEFINE_COMPARISONS(unsigned long, ulong, "%lu", unsigned long)
    237 DEFINE_COMPARISONS(int64_t, int64_t, "%lld", long long)
    238 DEFINE_COMPARISONS(uint64_t, uint64_t, "%llu", unsigned long long)
    239 DEFINE_COMPARISONS(size_t, size_t, "%zu", size_t)
    240 DEFINE_COMPARISONS(double, double, "%g", double)
    241 
    242 DEFINE_COMPARISON(void *, ptr, eq, ==, "%p", void *)
    243 DEFINE_COMPARISON(void *, ptr, ne, !=, "%p", void *)
    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