X-Git-Url: https://git.openssl.org/gitweb/?p=openssl.git;a=blobdiff_plain;f=test%2Ftestutil.c;h=aab451367195524f60eff8720487661e9fec9732;hp=908eb5b392f86c2ea72441904d02b45fc01e060f;hb=e72040c1dcd61d6669762a60924b8fa3a48c37fc;hpb=1d97c8435171a7af575f73c526d79e1ef0ee5960 diff --git a/test/testutil.c b/test/testutil.c index 908eb5b392..aab4513671 100644 --- a/test/testutil.c +++ b/test/testutil.c @@ -1,59 +1,10 @@ -/* test/testutil.c */ -/*- - * Utilities for writing OpenSSL unit tests. +/* + * Copyright 2014-2016 The OpenSSL Project Authors. All Rights Reserved. * - * More information: - * http://wiki.openssl.org/index.php/How_To_Write_Unit_Tests_For_OpenSSL - * - * Author: Mike Bland (mbland@acm.org) - * Date: 2014-07-15 - * ==================================================================== - * Copyright (c) 2014 The OpenSSL Project. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * 3. All advertising materials mentioning features or use of this - * software must display the following acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" - * - * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to - * endorse or promote products derived from this software without - * prior written permission. For written permission, please contact - * licensing@OpenSSL.org. - * - * 5. Products derived from this software may not be called "OpenSSL" - * nor may "OpenSSL" appear in their names without prior written - * permission of the OpenSSL Project. - * - * 6. Redistributions of any form whatsoever must retain the following - * acknowledgment: - * "This product includes software developed by the OpenSSL Project - * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" - * - * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY - * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR - * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - * ==================================================================== + * Licensed under the OpenSSL license (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html */ #include "testutil.h" @@ -61,49 +12,152 @@ #include #include #include +#include +#include "e_os.h" -/* Declares the structures needed to register each test case function. +#include +#include +#include + +/* + * Declares the structures needed to register each test case function. */ -typedef struct test_info - { - const char* test_case_name; - int (*test_fn)(); - } TEST_INFO; +typedef struct test_info { + const char *test_case_name; + int (*test_fn) (); + int (*param_test_fn)(int idx); + int num; +} TEST_INFO; static TEST_INFO all_tests[1024]; static int num_tests = 0; +/* + * A parameterised tests runs a loop of test cases. + * |num_test_cases| counts the total number of test cases + * across all tests. + */ +static int num_test_cases = 0; + +void add_test(const char *test_case_name, int (*test_fn) ()) +{ + assert(num_tests != OSSL_NELEM(all_tests)); + all_tests[num_tests].test_case_name = test_case_name; + all_tests[num_tests].test_fn = test_fn; + all_tests[num_tests].num = -1; + ++num_test_cases; + ++num_tests; +} + +void add_all_tests(const char *test_case_name, int(*test_fn)(int idx), + int num) +{ + assert(num_tests != OSSL_NELEM(all_tests)); + all_tests[num_tests].test_case_name = test_case_name; + all_tests[num_tests].param_test_fn = test_fn; + all_tests[num_tests].num = num; + ++num_tests; + num_test_cases += num; +} + +#ifndef OPENSSL_NO_CRYPTO_MDEBUG +static int should_report_leaks() +{ + /* + * When compiled with enable-crypto-mdebug, OPENSSL_DEBUG_MEMORY=0 + * can be used to disable leak checking at runtime. + * Note this only works when running the test binary manually; + * the test harness always enables OPENSSL_DEBUG_MEMORY. + */ + char *mem_debug_env = getenv("OPENSSL_DEBUG_MEMORY"); + + return mem_debug_env == NULL + || (strcmp(mem_debug_env, "0") && strcmp(mem_debug_env, "")); +} +#endif + + +void setup_test() +{ +#ifndef OPENSSL_NO_CRYPTO_MDEBUG + if (should_report_leaks()) { + CRYPTO_set_mem_debug(1); + CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON); + } +#endif +} + +int finish_test(int ret) +{ +#ifndef OPENSSL_NO_CRYPTO_MDEBUG + if (should_report_leaks() && CRYPTO_mem_leaks_fp(stderr) <= 0) + return EXIT_FAILURE; +#endif + return ret; +} + +static void finalize(int success) +{ + if (success) + ERR_clear_error(); + else + ERR_print_errors_fp(stderr); +} + +int run_tests(const char *test_prog_name) +{ + int num_failed = 0; + + int i, j; + + printf("%s: %d test case%s\n", test_prog_name, num_test_cases, + num_test_cases == 1 ? "" : "s"); + + for (i = 0; i != num_tests; ++i) { + if (all_tests[i].num == -1) { + int ret = all_tests[i].test_fn(); + + if (!ret) { + printf("** %s failed **\n--------\n", + all_tests[i].test_case_name); + ++num_failed; + } + finalize(ret); + } else { + for (j = 0; j < all_tests[i].num; j++) { + int ret = all_tests[i].param_test_fn(j); + + if (!ret) { + printf("** %s failed test %d\n--------\n", + all_tests[i].test_case_name, j); + ++num_failed; + } + finalize(ret); + } + } + } + + if (num_failed != 0) { + printf("%s: %d test%s failed (out of %d)\n", test_prog_name, + num_failed, num_failed != 1 ? "s" : "", num_test_cases); + return EXIT_FAILURE; + } + printf(" All tests passed.\n"); + return EXIT_SUCCESS; +} + +static const char *print_string_maybe_null(const char *s) +{ + return s == NULL ? "(NULL)" : s; +} -void add_test(const char* test_case_name, int (*test_fn)()) - { - assert(num_tests != (sizeof(all_tests) / sizeof(all_tests)[0])); - all_tests[num_tests].test_case_name = test_case_name; - all_tests[num_tests].test_fn = test_fn; - ++num_tests; - } - -int run_tests(const char* test_prog_name) - { - int num_failed = 0; - int i = 0; - - printf("%s: %d test case%s\n", test_prog_name, num_tests, - num_tests == 1 ? "" : "s"); - for (i = 0; i != num_tests; ++i) - { - if (all_tests[i].test_fn()) - { - printf("** %s failed **\n--------\n", - all_tests[i].test_case_name); - ++num_failed; - } - } - - if (num_failed != 0) - { - printf("%s: %d test%s failed (out of %d)\n", test_prog_name, - num_failed, num_failed != 1 ? "s" : "", num_tests); - return EXIT_FAILURE; - } - printf(" All tests passed.\n"); - return EXIT_SUCCESS; - } +int strings_equal(const char *desc, const char *s1, const char *s2) +{ + if (s1 == NULL && s2 == NULL) + return 1; + if (s1 == NULL || s2 == NULL || strcmp(s1, s2) != 0) { + fprintf(stderr, "%s mismatch: %s vs %s\n", desc, print_string_maybe_null(s1), + print_string_maybe_null(s2)); + return 0; + } + return 1; +}