Branch data Line data Source code
1 : : // Copyright 2011-2024 David Robillard <d@drobilla.net> 2 : : // SPDX-License-Identifier: ISC 3 : : 4 : : #ifndef EXESS_TEST_NUM_TEST_UTILS_H 5 : : #define EXESS_TEST_NUM_TEST_UTILS_H 6 : : 7 : : #include <stdbool.h> 8 : : #include <stdint.h> 9 : : #include <stdio.h> 10 : : #include <stdlib.h> 11 : : #include <time.h> 12 : : 13 : : #ifdef _WIN32 14 : : # include <process.h> 15 : : #else 16 : : # include <unistd.h> 17 : : #endif 18 : : 19 : : typedef struct { 20 : : size_t n_tests; 21 : : int64_t low; 22 : : int64_t high; 23 : : uint32_t seed; 24 : : bool exhaustive; 25 : : bool error; 26 : : } ExessNumTestOptions; 27 : : 28 : : static inline bool 29 : 741 : is_digit(const int c) 30 : : { 31 [ + - + - ]: 741 : return c >= '0' && c <= '9'; 32 : : } 33 : : 34 : : static bool 35 : 5 : print_num_test_usage(const char* const name) 36 : : { 37 : 5 : fprintf(stderr, "Usage: %s [OPTION]...\n", name); 38 : 5 : fprintf(stderr, 39 : : " -h Optional high value for exhaustive tests\n" 40 : : " -l Optional low value for exhaustive tests\n" 41 : : " -n NUM_TESTS Number of random tests to run\n" 42 : : " -s SEED Random seed\n" 43 : : " -x Exhaustively test numbers\n"); 44 : 5 : return true; 45 : : } 46 : : 47 : : static ExessNumTestOptions 48 : 20 : parse_num_test_options(const int argc, 49 : : char* const* const argv, 50 : : const size_t default_n_tests, 51 : : const int64_t min_rep, 52 : : const int64_t max_rep) 53 : : { 54 : 40 : ExessNumTestOptions opts = {default_n_tests, 55 : : min_rep, 56 : : max_rep, 57 : 20 : (uint32_t)time(NULL) + (uint32_t)getpid(), 58 : : false, 59 : : false}; 60 : : 61 : 20 : int a = 1; 62 [ + + + - ]: 35 : for (; a < argc && argv[a][0] == '-'; ++a) { 63 [ + + ]: 20 : if (argv[a][1] == 'h') { 64 [ + + ]: 5 : if (++a == argc) { 65 : 1 : opts.error = print_num_test_usage(argv[0]); 66 : 1 : break; 67 : : } 68 : : 69 : 4 : opts.high = (int64_t)strtoll(argv[a], NULL, 10); 70 [ + + ]: 15 : } else if (argv[a][1] == 'l') { 71 [ + + ]: 5 : if (++a == argc) { 72 : 1 : opts.error = print_num_test_usage(argv[0]); 73 : 1 : break; 74 : : } 75 : : 76 : 4 : opts.low = (int64_t)strtoll(argv[a], NULL, 10); 77 [ + + ]: 10 : } else if (argv[a][1] == 'x') { 78 : 5 : opts.exhaustive = true; 79 [ + + ]: 5 : } else if (argv[a][1] == 's') { 80 [ + + ]: 2 : if (++a == argc) { 81 : 1 : opts.error = print_num_test_usage(argv[0]); 82 : 1 : break; 83 : : } 84 : : 85 : 1 : opts.seed = (uint32_t)strtol(argv[a], NULL, 10); 86 [ + + ]: 3 : } else if (argv[a][1] == 'n') { 87 [ + + ]: 2 : if (++a == argc) { 88 : 1 : opts.error = print_num_test_usage(argv[0]); 89 : 1 : break; 90 : : } 91 : : 92 : 1 : opts.n_tests = (uint32_t)strtol(argv[a], NULL, 10); 93 : : } else { 94 : 1 : opts.error = print_num_test_usage(argv[0]); 95 : 1 : break; 96 : : } 97 : : } 98 : : 99 : 20 : return opts; 100 : : } 101 : : 102 : : static void 103 : 85507 : print_num_test_progress(const uint64_t i, const uint64_t n_tests) 104 : : { 105 [ + + ]: 85507 : if (i % (n_tests / 20) == 1) { 106 : 253 : fprintf(stderr, "%f%%\n", (double)i / (double)n_tests * 100.0); 107 : : } 108 : 85507 : } 109 : : 110 : : #endif // EXESS_TEST_NUM_TEST_UTILS_H