File indexing completed on 2026-11-07 10:15:35
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #ifndef TEST_HELPERS_H
0014 #define TEST_HELPERS_H
0015
0016 #include <time.h> /* clock */
0017 #include <string.h> /* strlen, strcmp, strncmp */
0018 #include <stdlib.h> /* strtol */
0019 #include <limits.h> /* LONG_MIN */
0020 #include "templates.h"
0021 #include "flint.h"
0022
0023 #if FLINT_WANT_PRETTY_TESTS
0024 # define _RED "\033[0;31m"
0025 # define _RED_B "\033[1;31m"
0026 # define _GREEN "\033[0;32m"
0027 # define _GREEN_B "\033[1;32m"
0028 # define _YELLOW "\033[0;33m"
0029 # define _YELLOW_B "\033[1;33m"
0030 # define _RESET "\033[0m"
0031 #else
0032 # define _RED
0033 # define _RED_B
0034 # define _GREEN
0035 # define _GREEN_B
0036 # define _YELLOW
0037 # define _YELLOW_B
0038 # define _RESET
0039 #endif
0040
0041
0042 #define FLINT_TEST(e) \
0043 do { \
0044 if (!(e)) \
0045 { \
0046 flint_throw(FLINT_ERROR, "test %s FAILED\n%s:%d", #e, __FILE__, __LINE__); \
0047 } \
0048 } while (0)
0049
0050
0051
0052 typedef struct
0053 {
0054 int (* test_function)(void);
0055 char * name;
0056 }
0057 test_struct;
0058
0059 #define TEST_FUNCTION(label) { CAT(test, label), #label }
0060
0061 #define TEST_FUNCTION_START(label, state) \
0062 int CAT(test, label)(void) \
0063 { \
0064 double FLINT_SET_BUT_UNUSED(_start_time_), FLINT_SET_BUT_UNUSED(_end_time_); \
0065 char _test_io_string_[128] = #label " "; \
0066 const int _label_len_ = sizeof(#label) - 1; \
0067 puts(#label "..."); \
0068 FLINT_TEST_INIT(state); \
0069 _start_time_ = clock();
0070
0071 #define TEST_GR_FUNCTION_START(label, state, count_success, count_domain, count_unable) \
0072 int CAT(test, label)(void) \
0073 { \
0074 slong count_success = 0, count_unable = 0, count_domain = 0; \
0075 double FLINT_SET_BUT_UNUSED(_start_time_), FLINT_SET_BUT_UNUSED(_end_time_); \
0076 char _test_io_string_[128] = #label " "; \
0077 const int _label_len_ = sizeof(#label) - 1; \
0078 puts(#label "..."); \
0079 FLINT_TEST_INIT(state); \
0080 _start_time_ = clock();
0081
0082 #define TEST_TEMPLATE_FUNCTION_START(T, label, state) \
0083 int TEMPLATE3(test, T, label)(void) \
0084 { \
0085 double FLINT_SET_BUT_UNUSED(_start_time_), FLINT_SET_BUT_UNUSED(_end_time_); \
0086 char _test_io_string_[128] = TEMPLATE_STR(T) "_" #label " "; \
0087 const int _label_len_ = sizeof(TEMPLATE_STR(T) "_" #label) - 1; \
0088 puts(TEMPLATE_STR(T) "_" #label "..."); \
0089 FLINT_TEST_INIT(state); \
0090 _start_time_ = clock();
0091
0092 #define TEST_TEMPLATE2_FUNCTION_START(T, label1, label2, state)\
0093 int TEMPLATE5(test, T, label1, T, label2)(void) \
0094 { \
0095 double FLINT_SET_BUT_UNUSED(_start_time_), FLINT_SET_BUT_UNUSED(_end_time_); \
0096 char _test_io_string_[128] = TEMPLATE_STR(T) "_" #label1 "_" TEMPLATE_STR(T) "_" #label2 " "; \
0097 const int _label_len_ = sizeof(TEMPLATE_STR(T) "_" #label1 "_" TEMPLATE_STR(T) "_" #label2) - 1; \
0098 puts(TEMPLATE_STR(T) "_" #label1 "_" TEMPLATE_STR(T) "_" #label2 "..."); \
0099 FLINT_TEST_INIT(state); \
0100 _start_time_ = clock();
0101
0102 #define TEST_FUNCTION_END(state) \
0103 _end_time_ = clock(); \
0104 FLINT_TEST_CLEAR(state); \
0105 if (_label_len_ < 48) \
0106 printf("%.48s%6.2f (" _GREEN_B "PASS" _RESET ")\n", \
0107 _test_io_string_, \
0108 (_end_time_ - _start_time_) / CLOCKS_PER_SEC); \
0109 else \
0110 printf("%.*s\n%54.2f (" _GREEN_B "PASS" _RESET ")\n", \
0111 _label_len_, _test_io_string_, \
0112 (_end_time_ - _start_time_) / CLOCKS_PER_SEC); \
0113 return 0; \
0114 }
0115
0116 #define TEST_GR_FUNCTION_END(state, count_success, count_domain, count_unable) \
0117 _end_time_ = clock(); \
0118 FLINT_TEST_CLEAR(state); \
0119 printf("%.*s\n " \
0120 "%5" _WORD_FMT "d success, " \
0121 "%5" _WORD_FMT "d domain, " \
0122 "%5" _WORD_FMT "d unable" \
0123 "%11.2f " \
0124 "(" _GREEN_B "PASS" _RESET ")\n", \
0125 _label_len_, _test_io_string_, \
0126 count_success, count_domain, count_unable, \
0127 (_end_time_ - _start_time_) / CLOCKS_PER_SEC); \
0128 return 0; \
0129 }
0130
0131 #define TEST_FUNCTION_END_SKIPPED(state) \
0132 FLINT_TEST_CLEAR(state); \
0133 if (_label_len_ < 54) \
0134 printf("%.*s(" _YELLOW_B "SKIPPED" _RESET ")\n", \
0135 54, _test_io_string_); \
0136 else \
0137 printf("%.*s\n%*s(" _YELLOW_B "SKIPPED" _RESET ")\n", \
0138 _label_len_, _test_io_string_, \
0139 54, ""); \
0140 return 0; \
0141 }
0142
0143 #define TEST_FUNCTION_FAIL(...) \
0144 do \
0145 { \
0146 _end_time_ = clock(); \
0147 if (_label_len_ < 48) \
0148 printf("%.48s%6.2f (" _RED_B "FAIL" _RESET ")\n", \
0149 _test_io_string_, \
0150 (_end_time_ - _start_time_) / CLOCKS_PER_SEC); \
0151 else \
0152 printf("%.*s\n%54.2f (" _RED_B "FAIL" _RESET ")\n", \
0153 _label_len_, _test_io_string_, \
0154 (_end_time_ - _start_time_) / CLOCKS_PER_SEC); \
0155 flint_printf(__VA_ARGS__); \
0156 return 1; \
0157 } while (0)
0158
0159 #define TEST_MAIN(tests) \
0160 int \
0161 main(int argc, char ** argv) \
0162 { \
0163 char numthreads_str[] = "--numthreads="; \
0164 char thread_str[] = "--thread="; \
0165 size_t numthreads_str_len = sizeof(numthreads_str) / sizeof(char) - 1; \
0166 size_t thread_str_len = sizeof(thread_str) / sizeof(char) - 1; \
0167 long int numthreads, thread; \
0168 int ix, ix_max, numtests; \
0169 \
0170 numtests = sizeof(tests) / sizeof(test_struct); \
0171 \
0172 \
0173 if (argc < 2) \
0174 { \
0175 for (ix = 0; ix < numtests; ix++) \
0176 if ((tests)[ix].test_function()) \
0177 flint_abort(); \
0178 \
0179 return 0; \
0180 } \
0181 \
0182 \
0183 if (argv[1][0] != '-' && argv[1][1] != '-') \
0184 { \
0185 int jx; \
0186 \
0187 for (jx = 1; jx < argc; jx++) \
0188 { \
0189 for (ix = 0; ix < numtests; ix++) \
0190 { \
0191 \
0192 if (strcmp(argv[jx], (tests)[ix].name) == 0) \
0193 { \
0194 if ((tests)[ix].test_function()) \
0195 flint_abort(); \
0196 break; \
0197 } \
0198 } \
0199 \
0200 if (ix == numtests) \
0201 { \
0202 flint_throw(FLINT_ERROR, "Could not find test function for %s\n", argv[jx]); \
0203 } \
0204 } \
0205 \
0206 return 0; \
0207 } \
0208 \
0209
0210
0211 \
0212 if (strlen(argv[1]) <= numthreads_str_len \
0213 || strncmp(argv[1], numthreads_str, numthreads_str_len) != 0) \
0214 { \
0215 printf("Invalid first option, must be --numthreads=NUM.\n"); \
0216 return 1; \
0217 } \
0218 \
0219
0220
0221 \
0222 numthreads = strtol(argv[1] + numthreads_str_len, NULL, 10); \
0223 if (numthreads == LONG_MAX || numthreads <= 0) \
0224 { \
0225 printf("Invalid parameter for option --numthreads=NUM.\n"); \
0226 return 1; \
0227 } \
0228 \
0229 \
0230 if (strlen(argv[2]) <= thread_str_len \
0231 || strncmp(argv[2], thread_str, thread_str_len) != 0) \
0232 { \
0233 printf("Invalid second option, must be --thread=NUM.\n"); \
0234 return 1; \
0235 } \
0236 \
0237
0238 \
0239 thread = strtol(argv[2] + thread_str_len, NULL, 10); \
0240 if (thread == LONG_MAX || thread <= 0 || thread > numthreads) \
0241 { \
0242 printf("Invalid parameter for option --thread=NUM.\n"); \
0243 return 1; \
0244 } \
0245 \
0246
0247 \
0248 ix = (thread - 1) * ((numtests + numthreads - 1) / numthreads); \
0249 ix_max = FLINT_MIN(thread * ((numtests + numthreads - 1) / numthreads), numtests);\
0250 for (; ix < ix_max; ix++) \
0251 if ((tests)[ix].test_function()) \
0252 flint_abort(); \
0253 \
0254 return 0; \
0255 }
0256
0257 #endif