Convert shlibloadtest to new framework
[openssl.git] / test / shlibloadtest.c
1 /*
2  * Copyright 2016 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 <stdio.h>
11 #include <string.h>
12 #include <stdlib.h>
13 #include <openssl/opensslv.h>
14 #include <openssl/ssl.h>
15 #include <openssl/ossl_typ.h>
16 #include "testutil.h"
17
18 #if !defined(DSO_DLFCN) && !defined(DSO_WIN32)
19 int main(void)
20 {
21     TEST_info("Not implemented on this platform\n");
22     return 0;
23 }
24
25 #else
26
27 typedef const SSL_METHOD * (*TLS_method_t)(void);
28 typedef SSL_CTX * (*SSL_CTX_new_t)(const SSL_METHOD *meth);
29 typedef void (*SSL_CTX_free_t)(SSL_CTX *);
30 typedef unsigned long (*ERR_get_error_t)(void);
31 typedef unsigned long (*OpenSSL_version_num_t)(void);
32
33 #ifdef DSO_DLFCN
34
35 # include <dlfcn.h>
36
37 typedef void *SHLIB;
38 typedef void *SHLIB_SYM;
39 # define SHLIB_INIT NULL
40
41 static int shlib_load(const char *filename, SHLIB *lib)
42 {
43     *lib = dlopen(filename, RTLD_GLOBAL | RTLD_LAZY);
44     return *lib == NULL ? 0 : 1;
45 }
46
47 static int shlib_sym(SHLIB lib, const char *symname, SHLIB_SYM *sym)
48 {
49     *sym = dlsym(lib, symname);
50     return *sym != NULL;
51 }
52
53 static int shlib_close(SHLIB lib)
54 {
55     return dlclose(lib) != 0 ? 0 : 1;
56 }
57 #endif
58
59 #ifdef DSO_WIN32
60
61 # include <windows.h>
62
63 typedef HINSTANCE SHLIB;
64 typedef void *SHLIB_SYM;
65 # define SHLIB_INIT 0
66
67 static int shlib_load(const char *filename, SHLIB *lib)
68 {
69     *lib = LoadLibraryA(filename);
70     return *lib == NULL ? 0 : 1;
71 }
72
73 static int shlib_sym(SHLIB lib, const char *symname, SHLIB_SYM *sym)
74 {
75     *sym = (SHLIB_SYM)GetProcAddress(lib, symname);
76     return *sym != NULL;
77 }
78
79 static int shlib_close(SHLIB lib)
80 {
81     return FreeLibrary(lib) == 0 ? 0 : 1;
82 }
83 #endif
84
85 typedef enum test_types_en {
86     CRYPTO_FIRST,
87     SSL_FIRST,
88     JUST_CRYPTO
89 } TEST_TYPE;
90
91 static TEST_TYPE test_type;
92 static const char *path_crypto;
93 static const char *path_ssl;
94
95 static int test_lib(void)
96 {
97     SHLIB ssllib = SHLIB_INIT;
98     SHLIB cryptolib = SHLIB_INIT;
99     SSL_CTX *ctx;
100     union {
101         void (*func)(void);
102         SHLIB_SYM sym;
103     } symbols[3];
104     TLS_method_t myTLS_method;
105     SSL_CTX_new_t mySSL_CTX_new;
106     SSL_CTX_free_t mySSL_CTX_free;
107     ERR_get_error_t myERR_get_error;
108     OpenSSL_version_num_t myOpenSSL_version_num;
109     int result = 0;
110
111     switch (test_type) {
112     case JUST_CRYPTO:
113         if (!TEST_true(shlib_load(path_crypto, &cryptolib)))
114             goto end;
115         break;
116     case CRYPTO_FIRST:
117         if (!TEST_true(shlib_load(path_crypto, &cryptolib))
118                 || !TEST_true(shlib_load(path_ssl, &ssllib)))
119             goto end;
120     case SSL_FIRST:
121         if (!TEST_true(shlib_load(path_ssl, &ssllib))
122                 || !TEST_true(shlib_load(path_crypto, &cryptolib)))
123             goto end;
124         break;
125     }
126
127     if (test_type != JUST_CRYPTO) {
128         if (!TEST_true(shlib_sym(ssllib, "TLS_method", &symbols[0].sym))
129                 || !TEST_true(shlib_sym(ssllib, "SSL_CTX_new", &symbols[1].sym))
130                 || !TEST_true(shlib_sym(ssllib, "SSL_CTX_free", &symbols[2].sym)))
131             goto end;
132         myTLS_method = (TLS_method_t)symbols[0].func;
133         mySSL_CTX_new = (SSL_CTX_new_t)symbols[1].func;
134         mySSL_CTX_free = (SSL_CTX_free_t)symbols[2].func;
135         if (!TEST_ptr(ctx = mySSL_CTX_new(myTLS_method())))
136             goto end;
137         mySSL_CTX_free(ctx);
138     }
139
140     if (!TEST_true(shlib_sym(cryptolib, "ERR_get_error", &symbols[0].sym))
141             || !TEST_true(shlib_sym(cryptolib, "OpenSSL_version_num",
142                                     &symbols[1].sym)))
143         goto end;
144     myERR_get_error = (ERR_get_error_t)symbols[0].func;
145     if (!TEST_int_eq(myERR_get_error(), 0))
146         goto end;
147     myOpenSSL_version_num = (OpenSSL_version_num_t)symbols[1].func;
148     if (!TEST_int_eq(myOpenSSL_version_num(), OPENSSL_VERSION_NUMBER))
149         goto end;
150
151     switch (test_type) {
152     case JUST_CRYPTO:
153         if (!TEST_true(shlib_close(cryptolib)))
154             goto end;
155         break;
156     case CRYPTO_FIRST:
157         if (!TEST_true(shlib_close(cryptolib))
158                 || !TEST_true(shlib_close(ssllib)))
159             goto end;
160     case SSL_FIRST:
161         if (!TEST_true(shlib_close(ssllib))
162                 || !TEST_true(shlib_close(cryptolib)))
163             goto end;
164         break;
165     }
166
167     result = 1;
168 end:
169     return result;
170 }
171
172 int test_main(int argc, char **argv)
173 {
174     if (argc != 4) {
175         TEST_error("Unexpected number of arguments");
176         return EXIT_FAILURE;
177     }
178
179     if (strcmp(argv[1], "-crypto_first") == 0) {
180         test_type = CRYPTO_FIRST;
181     } else if (strcmp(argv[1], "-ssl_first") == 0) {
182         test_type = SSL_FIRST;
183     } else if (strcmp(argv[1], "-just_crypto") == 0) {
184         test_type = JUST_CRYPTO;
185     } else {
186         TEST_error("Unrecognised argument");
187         return EXIT_FAILURE;
188     }
189     path_crypto = argv[2];
190     path_ssl = argv[3];
191
192     ADD_TEST(test_lib);
193     return run_tests(argv[0]);
194 }
195 #endif