driver.c revision 1.2 1 1.1 christos /*
2 1.1 christos * Copyright 2016-2023 The OpenSSL Project Authors. All Rights Reserved.
3 1.1 christos *
4 1.1 christos * Licensed under the Apache License 2.0 (the "License"). You may not use
5 1.1 christos * this file except in compliance with the License. You can obtain a copy
6 1.1 christos * in the file LICENSE in the source distribution or at
7 1.1 christos * https://www.openssl.org/source/license.html
8 1.1 christos */
9 1.1 christos
10 1.1 christos #include "../testutil.h"
11 1.1 christos #include "output.h"
12 1.1 christos #include "tu_local.h"
13 1.1 christos
14 1.1 christos #include <string.h>
15 1.1 christos #include <assert.h>
16 1.1 christos
17 1.1 christos #include "internal/nelem.h"
18 1.1 christos #include <openssl/bio.h>
19 1.1 christos
20 1.1 christos #include "platform.h" /* From libapps */
21 1.1 christos
22 1.1 christos #if defined(_WIN32) && !defined(__BORLANDC__)
23 1.1 christos # define strdup _strdup
24 1.1 christos #endif
25 1.1 christos
26 1.1 christos
27 1.1 christos /*
28 1.1 christos * Declares the structures needed to register each test case function.
29 1.1 christos */
30 1.1 christos typedef struct test_info {
31 1.1 christos const char *test_case_name;
32 1.1 christos int (*test_fn) (void);
33 1.1 christos int (*param_test_fn)(int idx);
34 1.1 christos int num;
35 1.1 christos
36 1.1 christos /* flags */
37 1.1 christos int subtest:1;
38 1.1 christos } TEST_INFO;
39 1.1 christos
40 1.1 christos static TEST_INFO all_tests[1024];
41 1.1 christos static int num_tests = 0;
42 1.1 christos static int show_list = 0;
43 1.1 christos static int single_test = -1;
44 1.1 christos static int single_iter = -1;
45 1.1 christos static int level = 0;
46 1.1 christos static int seed = 0;
47 1.1 christos static int rand_order = 0;
48 1.1 christos
49 1.1 christos /*
50 1.1 christos * A parameterised test runs a loop of test cases.
51 1.1 christos * |num_test_cases| counts the total number of non-subtest test cases
52 1.1 christos * across all tests.
53 1.1 christos */
54 1.1 christos static int num_test_cases = 0;
55 1.1 christos
56 1.1 christos static int process_shared_options(void);
57 1.1 christos
58 1.1 christos
59 1.1 christos void add_test(const char *test_case_name, int (*test_fn) (void))
60 1.1 christos {
61 1.1 christos assert(num_tests != OSSL_NELEM(all_tests));
62 1.1 christos all_tests[num_tests].test_case_name = test_case_name;
63 1.1 christos all_tests[num_tests].test_fn = test_fn;
64 1.1 christos all_tests[num_tests].num = -1;
65 1.1 christos ++num_tests;
66 1.1 christos ++num_test_cases;
67 1.1 christos }
68 1.1 christos
69 1.1 christos void add_all_tests(const char *test_case_name, int(*test_fn)(int idx),
70 1.1 christos int num, int subtest)
71 1.1 christos {
72 1.1 christos assert(num_tests != OSSL_NELEM(all_tests));
73 1.1 christos all_tests[num_tests].test_case_name = test_case_name;
74 1.1 christos all_tests[num_tests].param_test_fn = test_fn;
75 1.1 christos all_tests[num_tests].num = num;
76 1.1 christos all_tests[num_tests].subtest = subtest;
77 1.1 christos ++num_tests;
78 1.1 christos if (subtest)
79 1.1 christos ++num_test_cases;
80 1.1 christos else
81 1.1 christos num_test_cases += num;
82 1.1 christos }
83 1.1 christos
84 1.1 christos static int gcd(int a, int b)
85 1.1 christos {
86 1.1 christos while (b != 0) {
87 1.1 christos int t = b;
88 1.1 christos b = a % b;
89 1.1 christos a = t;
90 1.1 christos }
91 1.1 christos return a;
92 1.1 christos }
93 1.1 christos
94 1.1 christos static void set_seed(int s)
95 1.1 christos {
96 1.1 christos seed = s;
97 1.1 christos if (seed <= 0)
98 1.1 christos seed = (int)time(NULL);
99 1.1 christos test_random_seed(seed);
100 1.1 christos }
101 1.1 christos
102 1.1 christos
103 1.1 christos int setup_test_framework(int argc, char *argv[])
104 1.1 christos {
105 1.1 christos char *test_rand_order = getenv("OPENSSL_TEST_RAND_ORDER");
106 1.1 christos char *test_rand_seed = getenv("OPENSSL_TEST_RAND_SEED");
107 1.1 christos char *TAP_levels = getenv("HARNESS_OSSL_LEVEL");
108 1.1 christos
109 1.1 christos if (TAP_levels != NULL)
110 1.1 christos level = 4 * atoi(TAP_levels);
111 1.1 christos test_adjust_streams_tap_level(level);
112 1.1 christos if (test_rand_order != NULL) {
113 1.1 christos rand_order = 1;
114 1.1 christos set_seed(atoi(test_rand_order));
115 1.1 christos } else if (test_rand_seed != NULL) {
116 1.1 christos set_seed(atoi(test_rand_seed));
117 1.1 christos } else {
118 1.1 christos set_seed(0);
119 1.1 christos }
120 1.1 christos
121 1.1 christos #if defined(OPENSSL_SYS_VMS) && defined(__DECC)
122 1.1 christos argv = copy_argv(&argc, argv);
123 1.1 christos #elif defined(_WIN32)
124 1.1 christos /*
125 1.1 christos * Replace argv[] with UTF-8 encoded strings.
126 1.1 christos */
127 1.1 christos win32_utf8argv(&argc, &argv);
128 1.1 christos #endif
129 1.1 christos
130 1.1 christos if (!opt_init(argc, argv, test_get_options()))
131 1.1 christos return 0;
132 1.1 christos return 1;
133 1.1 christos }
134 1.1 christos
135 1.1 christos
136 1.1 christos /*
137 1.1 christos * This can only be called after setup() has run, since num_tests and
138 1.1 christos * all_tests[] are setup at this point
139 1.1 christos */
140 1.1 christos static int check_single_test_params(char *name, char *testname, char *itname)
141 1.1 christos {
142 1.1 christos if (name != NULL) {
143 1.1 christos int i;
144 1.1 christos for (i = 0; i < num_tests; ++i) {
145 1.1 christos if (strcmp(name, all_tests[i].test_case_name) == 0) {
146 1.1 christos single_test = 1 + i;
147 1.1 christos break;
148 1.1 christos }
149 1.1 christos }
150 1.1 christos if (i >= num_tests)
151 1.1 christos single_test = atoi(name);
152 1.1 christos }
153 1.1 christos
154 1.1 christos
155 1.1 christos /* if only iteration is specified, assume we want the first test */
156 1.1 christos if (single_test == -1 && single_iter != -1)
157 1.1 christos single_test = 1;
158 1.1 christos
159 1.1 christos if (single_test != -1) {
160 1.1 christos if (single_test < 1 || single_test > num_tests) {
161 1.1 christos test_printf_stderr("Invalid -%s value "
162 1.1 christos "(Value must be a valid test name OR a value between %d..%d)\n",
163 1.1 christos testname, 1, num_tests);
164 1.1 christos return 0;
165 1.1 christos }
166 1.1 christos }
167 1.1 christos if (single_iter != -1) {
168 1.1 christos if (all_tests[single_test - 1].num == -1) {
169 1.1 christos test_printf_stderr("-%s option is not valid for test %d:%s\n",
170 1.1 christos itname,
171 1.1 christos single_test,
172 1.1 christos all_tests[single_test - 1].test_case_name);
173 1.1 christos return 0;
174 1.1 christos } else if (single_iter < 1
175 1.1 christos || single_iter > all_tests[single_test - 1].num) {
176 1.1 christos test_printf_stderr("Invalid -%s value for test %d:%s\t"
177 1.1 christos "(Value must be in the range %d..%d)\n",
178 1.1 christos itname, single_test,
179 1.1 christos all_tests[single_test - 1].test_case_name,
180 1.1 christos 1, all_tests[single_test - 1].num);
181 1.1 christos return 0;
182 1.1 christos }
183 1.1 christos }
184 1.1 christos return 1;
185 1.1 christos }
186 1.1 christos
187 1.1 christos static int process_shared_options(void)
188 1.1 christos {
189 1.1 christos OPTION_CHOICE_DEFAULT o;
190 1.1 christos int value;
191 1.1 christos int ret = -1;
192 1.2 christos char empty[] = "";
193 1.2 christos char *flag_test = empty;
194 1.2 christos char *flag_iter = empty;
195 1.1 christos char *testname = NULL;
196 1.1 christos
197 1.1 christos opt_begin();
198 1.1 christos while ((o = opt_next()) != OPT_EOF) {
199 1.1 christos switch (o) {
200 1.1 christos /* Ignore any test options at this level */
201 1.1 christos default:
202 1.1 christos break;
203 1.1 christos case OPT_ERR:
204 1.1 christos return ret;
205 1.1 christos case OPT_TEST_HELP:
206 1.1 christos opt_help(test_get_options());
207 1.1 christos return 0;
208 1.1 christos case OPT_TEST_LIST:
209 1.1 christos show_list = 1;
210 1.1 christos break;
211 1.1 christos case OPT_TEST_SINGLE:
212 1.1 christos flag_test = opt_flag();
213 1.1 christos testname = opt_arg();
214 1.1 christos break;
215 1.1 christos case OPT_TEST_ITERATION:
216 1.1 christos flag_iter = opt_flag();
217 1.1 christos if (!opt_int(opt_arg(), &single_iter))
218 1.1 christos goto end;
219 1.1 christos break;
220 1.1 christos case OPT_TEST_INDENT:
221 1.1 christos if (!opt_int(opt_arg(), &value))
222 1.1 christos goto end;
223 1.1 christos level = 4 * value;
224 1.1 christos test_adjust_streams_tap_level(level);
225 1.1 christos break;
226 1.1 christos case OPT_TEST_SEED:
227 1.1 christos if (!opt_int(opt_arg(), &value))
228 1.1 christos goto end;
229 1.1 christos set_seed(value);
230 1.1 christos break;
231 1.1 christos }
232 1.1 christos }
233 1.1 christos if (!check_single_test_params(testname, flag_test, flag_iter))
234 1.1 christos goto end;
235 1.1 christos ret = 1;
236 1.1 christos end:
237 1.1 christos return ret;
238 1.1 christos }
239 1.1 christos
240 1.1 christos
241 1.1 christos int pulldown_test_framework(int ret)
242 1.1 christos {
243 1.1 christos set_test_title(NULL);
244 1.1 christos return ret;
245 1.1 christos }
246 1.1 christos
247 1.1 christos static void finalize(int success)
248 1.1 christos {
249 1.1 christos if (success)
250 1.1 christos ERR_clear_error();
251 1.1 christos else
252 1.1 christos ERR_print_errors_cb(openssl_error_cb, NULL);
253 1.1 christos }
254 1.1 christos
255 1.1 christos static char *test_title = NULL;
256 1.1 christos
257 1.1 christos void set_test_title(const char *title)
258 1.1 christos {
259 1.1 christos free(test_title);
260 1.1 christos test_title = title == NULL ? NULL : strdup(title);
261 1.1 christos }
262 1.1 christos
263 1.1 christos PRINTF_FORMAT(2, 3) static void test_verdict(int verdict,
264 1.1 christos const char *description, ...)
265 1.1 christos {
266 1.1 christos va_list ap;
267 1.1 christos
268 1.1 christos test_flush_stdout();
269 1.1 christos test_flush_stderr();
270 1.1 christos
271 1.1 christos if (verdict == 0) {
272 1.1 christos if (rand_order)
273 1.1 christos test_printf_tapout("# OPENSSL_TEST_RAND_ORDER=%d\n", seed);
274 1.1 christos else
275 1.1 christos test_printf_tapout("# OPENSSL_TEST_RAND_SEED=%d\n", seed);
276 1.1 christos }
277 1.1 christos test_printf_tapout("%s ", verdict != 0 ? "ok" : "not ok");
278 1.1 christos va_start(ap, description);
279 1.1 christos test_vprintf_tapout(description, ap);
280 1.1 christos va_end(ap);
281 1.1 christos if (verdict == TEST_SKIP_CODE)
282 1.1 christos test_printf_tapout(" # skipped");
283 1.1 christos test_printf_tapout("\n");
284 1.1 christos test_flush_tapout();
285 1.1 christos }
286 1.1 christos
287 1.1 christos int run_tests(const char *test_prog_name)
288 1.1 christos {
289 1.1 christos int num_failed = 0;
290 1.1 christos int verdict = 1;
291 1.1 christos int ii, i, jj, j, jstep;
292 1.1 christos int test_case_count = 0;
293 1.1 christos int subtest_case_count = 0;
294 1.1 christos int permute[OSSL_NELEM(all_tests)];
295 1.1 christos
296 1.1 christos i = process_shared_options();
297 1.1 christos if (i == 0)
298 1.1 christos return EXIT_SUCCESS;
299 1.1 christos if (i == -1)
300 1.1 christos return EXIT_FAILURE;
301 1.1 christos
302 1.1 christos if (num_tests < 1) {
303 1.1 christos test_printf_tapout("1..0 # Skipped: %s\n", test_prog_name);
304 1.1 christos } else if (show_list == 0 && single_test == -1) {
305 1.1 christos if (level > 0) {
306 1.1 christos test_printf_stdout("Subtest: %s\n", test_prog_name);
307 1.1 christos test_flush_stdout();
308 1.1 christos }
309 1.1 christos test_printf_tapout("1..%d\n", num_test_cases);
310 1.1 christos }
311 1.1 christos
312 1.1 christos test_flush_tapout();
313 1.1 christos
314 1.1 christos for (i = 0; i < num_tests; i++)
315 1.1 christos permute[i] = i;
316 1.1 christos if (rand_order != 0)
317 1.1 christos for (i = num_tests - 1; i >= 1; i--) {
318 1.1 christos j = test_random() % (1 + i);
319 1.1 christos ii = permute[j];
320 1.1 christos permute[j] = permute[i];
321 1.1 christos permute[i] = ii;
322 1.1 christos }
323 1.1 christos
324 1.1 christos for (ii = 0; ii != num_tests; ++ii) {
325 1.1 christos i = permute[ii];
326 1.1 christos
327 1.1 christos if (single_test != -1 && ((i+1) != single_test)) {
328 1.1 christos continue;
329 1.1 christos }
330 1.1 christos else if (show_list) {
331 1.1 christos if (all_tests[i].num != -1) {
332 1.1 christos test_printf_tapout("%d - %s (%d..%d)\n", ii + 1,
333 1.1 christos all_tests[i].test_case_name, 1,
334 1.1 christos all_tests[i].num);
335 1.1 christos } else {
336 1.1 christos test_printf_tapout("%d - %s\n", ii + 1,
337 1.1 christos all_tests[i].test_case_name);
338 1.1 christos }
339 1.1 christos test_flush_tapout();
340 1.1 christos } else if (all_tests[i].num == -1) {
341 1.1 christos set_test_title(all_tests[i].test_case_name);
342 1.1 christos ERR_clear_error();
343 1.1 christos verdict = all_tests[i].test_fn();
344 1.1 christos finalize(verdict != 0);
345 1.1 christos test_verdict(verdict, "%d - %s", test_case_count + 1, test_title);
346 1.1 christos if (verdict == 0)
347 1.1 christos num_failed++;
348 1.1 christos test_case_count++;
349 1.1 christos } else {
350 1.1 christos verdict = TEST_SKIP_CODE;
351 1.1 christos set_test_title(all_tests[i].test_case_name);
352 1.1 christos if (all_tests[i].subtest) {
353 1.1 christos level += 4;
354 1.1 christos test_adjust_streams_tap_level(level);
355 1.1 christos if (single_iter == -1) {
356 1.1 christos test_printf_stdout("Subtest: %s\n", test_title);
357 1.1 christos test_printf_tapout("%d..%d\n", 1, all_tests[i].num);
358 1.1 christos test_flush_stdout();
359 1.1 christos test_flush_tapout();
360 1.1 christos }
361 1.1 christos }
362 1.1 christos
363 1.1 christos j = -1;
364 1.1 christos if (rand_order == 0 || all_tests[i].num < 3)
365 1.1 christos jstep = 1;
366 1.1 christos else
367 1.1 christos do
368 1.1 christos jstep = test_random() % all_tests[i].num;
369 1.1 christos while (jstep == 0 || gcd(all_tests[i].num, jstep) != 1);
370 1.1 christos
371 1.1 christos for (jj = 0; jj < all_tests[i].num; jj++) {
372 1.1 christos int v;
373 1.1 christos
374 1.1 christos j = (j + jstep) % all_tests[i].num;
375 1.1 christos if (single_iter != -1 && ((jj + 1) != single_iter))
376 1.1 christos continue;
377 1.1 christos ERR_clear_error();
378 1.1 christos v = all_tests[i].param_test_fn(j);
379 1.1 christos
380 1.1 christos if (v == 0) {
381 1.1 christos verdict = 0;
382 1.1 christos } else if (v != TEST_SKIP_CODE && verdict != 0) {
383 1.1 christos verdict = 1;
384 1.1 christos }
385 1.1 christos
386 1.1 christos finalize(v != 0);
387 1.1 christos
388 1.1 christos if (all_tests[i].subtest)
389 1.1 christos test_verdict(v, "%d - iteration %d",
390 1.1 christos subtest_case_count + 1, j + 1);
391 1.1 christos else
392 1.1 christos test_verdict(v, "%d - %s - iteration %d",
393 1.1 christos test_case_count + subtest_case_count + 1,
394 1.1 christos test_title, j + 1);
395 1.1 christos subtest_case_count++;
396 1.1 christos }
397 1.1 christos
398 1.1 christos if (all_tests[i].subtest) {
399 1.1 christos level -= 4;
400 1.1 christos test_adjust_streams_tap_level(level);
401 1.1 christos }
402 1.1 christos if (verdict == 0)
403 1.1 christos ++num_failed;
404 1.1 christos if (all_tests[i].num == -1 || all_tests[i].subtest)
405 1.1 christos test_verdict(verdict, "%d - %s", test_case_count + 1,
406 1.1 christos all_tests[i].test_case_name);
407 1.1 christos test_case_count++;
408 1.1 christos }
409 1.1 christos }
410 1.1 christos if (num_failed != 0)
411 1.1 christos return EXIT_FAILURE;
412 1.1 christos return EXIT_SUCCESS;
413 1.1 christos }
414 1.1 christos
415 1.1 christos /*
416 1.1 christos * Glue an array of strings together and return it as an allocated string.
417 1.1 christos * Optionally return the whole length of this string in |out_len|
418 1.1 christos */
419 1.1 christos char *glue_strings(const char *list[], size_t *out_len)
420 1.1 christos {
421 1.1 christos size_t len = 0;
422 1.1 christos char *p, *ret;
423 1.1 christos int i;
424 1.1 christos
425 1.1 christos for (i = 0; list[i] != NULL; i++)
426 1.1 christos len += strlen(list[i]);
427 1.1 christos
428 1.1 christos if (out_len != NULL)
429 1.1 christos *out_len = len;
430 1.1 christos
431 1.1 christos if (!TEST_ptr(ret = p = OPENSSL_malloc(len + 1)))
432 1.1 christos return NULL;
433 1.1 christos
434 1.1 christos for (i = 0; list[i] != NULL; i++)
435 1.1 christos p += strlen(strcpy(p, list[i]));
436 1.1 christos
437 1.1 christos return ret;
438 1.1 christos }
439 1.1 christos
440 1.1 christos char *test_mk_file_path(const char *dir, const char *file)
441 1.1 christos {
442 1.1 christos # ifndef OPENSSL_SYS_VMS
443 1.1 christos const char *sep = "/";
444 1.1 christos # else
445 1.1 christos const char *sep = "";
446 1.1 christos char *dir_end;
447 1.1 christos char dir_end_sep;
448 1.1 christos # endif
449 1.1 christos size_t dirlen = dir != NULL ? strlen(dir) : 0;
450 1.1 christos size_t len = dirlen + strlen(sep) + strlen(file) + 1;
451 1.1 christos char *full_file = OPENSSL_zalloc(len);
452 1.1 christos
453 1.1 christos if (full_file != NULL) {
454 1.1 christos if (dir != NULL && dirlen > 0) {
455 1.1 christos OPENSSL_strlcpy(full_file, dir, len);
456 1.1 christos # ifdef OPENSSL_SYS_VMS
457 1.1 christos /*
458 1.1 christos * If |file| contains a directory spec, we need to do some
459 1.1 christos * careful merging.
460 1.1 christos * "vol:[dir.dir]" + "[.certs]sm2-root.crt" should become
461 1.1 christos * "vol:[dir.dir.certs]sm2-root.crt"
462 1.1 christos */
463 1.1 christos dir_end = &full_file[strlen(full_file) - 1];
464 1.1 christos dir_end_sep = *dir_end;
465 1.1 christos if ((dir_end_sep == ']' || dir_end_sep == '>')
466 1.1 christos && (file[0] == '[' || file[0] == '<')) {
467 1.1 christos file++;
468 1.1 christos if (file[0] == '.')
469 1.1 christos *dir_end = '\0';
470 1.1 christos else
471 1.1 christos *dir_end = '.';
472 1.1 christos }
473 1.1 christos #else
474 1.1 christos OPENSSL_strlcat(full_file, sep, len);
475 1.1 christos #endif
476 1.1 christos }
477 1.1 christos OPENSSL_strlcat(full_file, file, len);
478 1.1 christos }
479 1.1 christos
480 1.1 christos return full_file;
481 1.1 christos }
482