openssl/test/shlibloadtest.c
Pauli ad887416f1 Update the test framework so that the need for test_main is removed. Everything
that needed test_main now works using the same infrastructure as tests that used
register_tests.

This meant:
* renaming register_tests to setup_tests and giving it a success/failure return.
* renaming the init_test function to setup_test_framework.
* renaming the finish_test function to pulldown_test_framework.
* adding a user provided global_init function that runs before the test frame
    work is initialised.  It returns a failure indication that stops the stest.
* adding helper functions that permit tests to access their command line args.
* spliting the BIO initialisation and finalisation out from the test setup and
    teardown.
* hiding some of the now test internal functions.
* fix the comments in testutil.h

Reviewed-by: Richard Levitte <levitte@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/3953)
2017-07-27 07:53:08 +10:00

200 lines
5 KiB
C

/*
* Copyright 2016-2017 The OpenSSL Project Authors. All Rights Reserved.
*
* 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 <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <openssl/opensslv.h>
#include <openssl/ssl.h>
#include <openssl/ossl_typ.h>
#include "testutil.h"
typedef const SSL_METHOD * (*TLS_method_t)(void);
typedef SSL_CTX * (*SSL_CTX_new_t)(const SSL_METHOD *meth);
typedef void (*SSL_CTX_free_t)(SSL_CTX *);
typedef unsigned long (*ERR_get_error_t)(void);
typedef unsigned long (*OpenSSL_version_num_t)(void);
typedef enum test_types_en {
CRYPTO_FIRST,
SSL_FIRST,
JUST_CRYPTO
} TEST_TYPE;
static TEST_TYPE test_type;
static const char *path_crypto;
static const char *path_ssl;
#ifdef DSO_DLFCN
# include <dlfcn.h>
# define SHLIB_INIT NULL
typedef void *SHLIB;
typedef void *SHLIB_SYM;
static int shlib_load(const char *filename, SHLIB *lib)
{
*lib = dlopen(filename, RTLD_GLOBAL | RTLD_LAZY);
return *lib == NULL ? 0 : 1;
}
static int shlib_sym(SHLIB lib, const char *symname, SHLIB_SYM *sym)
{
*sym = dlsym(lib, symname);
return *sym != NULL;
}
# ifdef OPENSSL_USE_NODELETE
static int shlib_close(SHLIB lib)
{
return dlclose(lib) != 0 ? 0 : 1;
}
# endif
#endif
#ifdef DSO_WIN32
# include <windows.h>
# define SHLIB_INIT 0
typedef HINSTANCE SHLIB;
typedef void *SHLIB_SYM;
static int shlib_load(const char *filename, SHLIB *lib)
{
*lib = LoadLibraryA(filename);
return *lib == NULL ? 0 : 1;
}
static int shlib_sym(SHLIB lib, const char *symname, SHLIB_SYM *sym)
{
*sym = (SHLIB_SYM)GetProcAddress(lib, symname);
return *sym != NULL;
}
# ifdef OPENSSL_USE_NODELETE
static int shlib_close(SHLIB lib)
{
return FreeLibrary(lib) == 0 ? 0 : 1;
}
# endif
#endif
#if defined(DSO_DLFCN) || defined(DSO_WIN32)
static int test_lib(void)
{
SHLIB ssllib = SHLIB_INIT;
SHLIB cryptolib = SHLIB_INIT;
SSL_CTX *ctx;
union {
void (*func)(void);
SHLIB_SYM sym;
} symbols[3];
TLS_method_t myTLS_method;
SSL_CTX_new_t mySSL_CTX_new;
SSL_CTX_free_t mySSL_CTX_free;
ERR_get_error_t myERR_get_error;
OpenSSL_version_num_t myOpenSSL_version_num;
int result = 0;
switch (test_type) {
case JUST_CRYPTO:
if (!TEST_true(shlib_load(path_crypto, &cryptolib)))
goto end;
break;
case CRYPTO_FIRST:
if (!TEST_true(shlib_load(path_crypto, &cryptolib))
|| !TEST_true(shlib_load(path_ssl, &ssllib)))
goto end;
break;
case SSL_FIRST:
if (!TEST_true(shlib_load(path_ssl, &ssllib))
|| !TEST_true(shlib_load(path_crypto, &cryptolib)))
goto end;
break;
}
if (test_type != JUST_CRYPTO) {
if (!TEST_true(shlib_sym(ssllib, "TLS_method", &symbols[0].sym))
|| !TEST_true(shlib_sym(ssllib, "SSL_CTX_new", &symbols[1].sym))
|| !TEST_true(shlib_sym(ssllib, "SSL_CTX_free", &symbols[2].sym)))
goto end;
myTLS_method = (TLS_method_t)symbols[0].func;
mySSL_CTX_new = (SSL_CTX_new_t)symbols[1].func;
mySSL_CTX_free = (SSL_CTX_free_t)symbols[2].func;
if (!TEST_ptr(ctx = mySSL_CTX_new(myTLS_method())))
goto end;
mySSL_CTX_free(ctx);
}
if (!TEST_true(shlib_sym(cryptolib, "ERR_get_error", &symbols[0].sym))
|| !TEST_true(shlib_sym(cryptolib, "OpenSSL_version_num",
&symbols[1].sym)))
goto end;
myERR_get_error = (ERR_get_error_t)symbols[0].func;
if (!TEST_int_eq(myERR_get_error(), 0))
goto end;
myOpenSSL_version_num = (OpenSSL_version_num_t)symbols[1].func;
if (!TEST_int_eq(myOpenSSL_version_num(), OPENSSL_VERSION_NUMBER))
goto end;
#ifdef OPENSSL_USE_NODELETE
switch (test_type) {
case JUST_CRYPTO:
if (!TEST_true(shlib_close(cryptolib)))
goto end;
break;
case CRYPTO_FIRST:
if (!TEST_true(shlib_close(cryptolib))
|| !TEST_true(shlib_close(ssllib)))
goto end;
break;
case SSL_FIRST:
if (!TEST_true(shlib_close(ssllib))
|| !TEST_true(shlib_close(cryptolib)))
goto end;
break;
}
#endif
result = 1;
end:
return result;
}
#endif
int setup_tests(void)
{
const char *p = test_get_argument(0);
if (strcmp(p, "-crypto_first") == 0) {
test_type = CRYPTO_FIRST;
} else if (strcmp(p, "-ssl_first") == 0) {
test_type = SSL_FIRST;
} else if (strcmp(p, "-just_crypto") == 0) {
test_type = JUST_CRYPTO;
} else {
TEST_error("Unrecognised argument");
return 0;
}
if (!TEST_ptr(path_crypto = test_get_argument(1))
|| !TEST_ptr(path_ssl = test_get_argument(2)))
return 0;
#if defined(DSO_DLFCN) || defined(DSO_WIN32)
ADD_TEST(test_lib);
#endif
return 1;
}