/home/liu/actions-runner/_work/ccv/ccv/test/case.h
Line | Count | Source |
1 | | #ifndef _GUARD_case_h_ |
2 | | #define _GUARD_case_h_ |
3 | | |
4 | | #include <stdio.h> |
5 | | #include <stdint.h> |
6 | | #include <unistd.h> |
7 | | |
8 | | #ifndef CASE_UNIQUE_NAME_PREFIX |
9 | | #define CASE_UNIQUE_NAME_PREFIX |
10 | | #endif |
11 | | |
12 | | #ifndef CASE_TEST_DIR |
13 | | #define CASE_TEST_DIR "." |
14 | | #endif |
15 | | |
16 | | #define CASE_TESTS |
17 | | |
18 | | /* the following 9 lines to generate unique name was taken from Catch: https://github.com/philsquared/Catch |
19 | | * here is the licence: |
20 | | * Boost Software License - Version 1.0 - August 17th, 2003 |
21 | | * |
22 | | * Permission is hereby granted, free of charge, to any person or organization |
23 | | * obtaining a copy of the software and accompanying documentation covered by |
24 | | * this license (the "Software") to use, reproduce, display, distribute, |
25 | | * execute, and transmit the Software, and to prepare derivative works of the |
26 | | * Software, and to permit third-parties to whom the Software is furnished to |
27 | | * do so, all subject to the following: |
28 | | * |
29 | | * The copyright notices in the Software and this entire statement, including |
30 | | * the above license grant, this restriction and the following disclaimer, |
31 | | * must be included in all copies of the Software, in whole or in part, and |
32 | | * all derivative works of the Software, unless such copies or derivative |
33 | | * works are solely in the form of machine-executable object code generated by |
34 | | * a source language processor. |
35 | | * |
36 | | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
37 | | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
38 | | * FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT |
39 | | * SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE |
40 | | * FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, |
41 | | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
42 | | * DEALINGS IN THE SOFTWARE. */ |
43 | | #ifndef INTERNAL_CATCH_UNIQUE_NAME_LINE2 |
44 | | #define INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) CASE_UNIQUE_NAME_PREFIX##name##line |
45 | | #endif |
46 | | #ifndef INTERNAL_CATCH_UNIQUE_NAME_LINE |
47 | | #define INTERNAL_CATCH_UNIQUE_NAME_LINE( name, line ) INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) |
48 | | #endif |
49 | | #ifndef INTERNAL_CATCH_UNIQUE_NAME |
50 | | #define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __LINE__ ) |
51 | | #endif |
52 | | |
53 | | typedef void (*case_f)(char*, int*); |
54 | | |
55 | | void __attribute__((weak)) __test_case_setup(void); |
56 | | void __attribute__((weak)) __test_case_teardown(void); |
57 | | |
58 | | #define TEST_SETUP() void __test_case_setup(void) |
59 | | #define TEST_TEARDOWN() void __test_case_teardown(void) |
60 | | |
61 | | #if defined(__ELF__) || defined(__APPLE__) |
62 | | // in ELF object format, we can simply query custom section rather than scan through the whole binary memory |
63 | | // to find function pointer. We do this whenever possible because in this way, we don't have access error |
64 | | // when hooking up with memory checkers such as address sanitizer or valgrind |
65 | | typedef struct { |
66 | | uint64_t sig_head; |
67 | | case_f func; |
68 | | char* name; |
69 | | char* dir; |
70 | | uint64_t sig_tail; |
71 | | } case_t; |
72 | | |
73 | | #ifdef __ELF__ |
74 | | #define TEST_CASE(desc) \ |
75 | | static void __attribute__((used)) INTERNAL_CATCH_UNIQUE_NAME(__test_case_func__) (char* __case_name__, int* __case_result__); \ |
76 | | static case_t INTERNAL_CATCH_UNIQUE_NAME(__test_case_ctx__) __attribute__((used, section("case_data"), aligned(8))) = { .func = INTERNAL_CATCH_UNIQUE_NAME(__test_case_func__), .sig_head = 0x883253372849284B, .name = desc, .dir = CASE_TEST_DIR, .sig_tail = 0x883253372849284B + 2 }; \ |
77 | | static void INTERNAL_CATCH_UNIQUE_NAME(__test_case_func__) (char* __case_name__, int* __case_result__) |
78 | | #else |
79 | | #define TEST_CASE(desc) \ |
80 | | static void __attribute__((used)) INTERNAL_CATCH_UNIQUE_NAME(__test_case_func__) (char* __case_name__, int* __case_result__); \ |
81 | | static case_t INTERNAL_CATCH_UNIQUE_NAME(__test_case_ctx__) __attribute__((used, section("__DATA,case_data"), aligned(8))) = { .func = INTERNAL_CATCH_UNIQUE_NAME(__test_case_func__), .sig_head = 0x883253372849284B, .name = desc, .dir = CASE_TEST_DIR, .sig_tail = 0x883253372849284B + 2 }; \ |
82 | | static void INTERNAL_CATCH_UNIQUE_NAME(__test_case_func__) (char* __case_name__, int* __case_result__) |
83 | | #endif |
84 | | #else |
85 | | typedef struct { |
86 | | uint64_t sig_head; |
87 | | case_f func; |
88 | | char* name; |
89 | | char* dir; |
90 | | uint64_t sig_tail; |
91 | | } case_t; |
92 | | |
93 | | #define TEST_CASE(desc) \ |
94 | | static void __attribute__((used)) INTERNAL_CATCH_UNIQUE_NAME(__test_case_func__) (char* __case_name__, int* __case_result__); \ |
95 | | static case_t INTERNAL_CATCH_UNIQUE_NAME(__test_case_ctx__) __attribute__((used, aligned(8))) = { .func = INTERNAL_CATCH_UNIQUE_NAME(__test_case_func__), .sig_head = 0x883253372849284B, .name = desc, .dir = CASE_TEST_DIR, .sig_tail = 0x883253372849284B + 2 }; \ |
96 | | static void INTERNAL_CATCH_UNIQUE_NAME(__test_case_func__) (char* __case_name__, int* __case_result__) |
97 | | #endif |
98 | | |
99 | 0 | #define ABORT_CASE (*__case_result__) = -1; return; |
100 | | |
101 | 1.12k | #define GUARD_ELSE_RETURN(x) if (551 x) {}400 else { (*__case_result__) = -2; return; }151 |
102 | | |
103 | 100M | #define REQUIRE(a, err, ...) { \ |
104 | 100M | if (!(a308 )) \ |
105 | 0 | { \ |
106 | 0 | if (isatty(fileno(stdout))) \ |
107 | 0 | printf("\n\t\033[0;31mREQUIRE\033[0;0m: %s:%d: %s is not true, " err, __FILE__, __LINE__, #a, ##__VA_ARGS__); \ |
108 | 0 | else \ |
109 | 0 | printf("\n\tREQUIRE: %s:%d: %s is not true, " err, __FILE__, __LINE__, #a, ##__VA_ARGS__); \ |
110 | 0 | ABORT_CASE; \ |
111 | 0 | } } |
112 | | |
113 | 103M | #define REQUIRE_EQ(a, b, err, ...) { \ |
114 | 103M | if ((a) != (b)103M ) \ |
115 | 0 | { \ |
116 | 0 | if (isatty(fileno(stdout))) \ |
117 | 0 | printf("\n\t\033[0;31mREQUIRE_EQ\033[0;0m: %s:%d: %s(%lg) != %s(%lg), " err, __FILE__, __LINE__, #a, (double)(a), #b, (double)(b), ##__VA_ARGS__); \ |
118 | 0 | else \ |
119 | 0 | printf("\n\tREQUIRE_EQ: %s:%d: %s(%lg) != %s(%lg), " err, __FILE__, __LINE__, #a, (double)(a), #b, (double)(b), ##__VA_ARGS__); \ |
120 | 0 | ABORT_CASE; \ |
121 | 0 | } } |
122 | | |
123 | 133 | #define REQUIRE_ARRAY_EQ(type, a, b, len, err, ...) { \ |
124 | 133 | int __case_i__; \ |
125 | 242k | for (__case_i__ = 0; __case_i__ < (len); __case_i__++242k ) \ |
126 | 242k | if (((type*)(a))[__case_i__] != ((type*)(b))[__case_i__]) \ |
127 | 242k | { \ |
128 | 0 | if (isatty(fileno(stdout))) \ |
129 | 0 | printf("\n\t\033[0;31mREQUIRE_ARRAY_EQ\033[0;0m: %s:%d: %s[%d](%lg) != %s[%d](%lg), " err, __FILE__, __LINE__, #a, __case_i__, (double)((type*)(a))[__case_i__], #b, __case_i__, (double)((type*)(b))[__case_i__], ##__VA_ARGS__); \ |
130 | 0 | else \ |
131 | 0 | printf("\n\tREQUIRE_ARRAY_EQ: %s:%d: %s[%d](%lg) != %s[%d](%lg), " err, __FILE__, __LINE__, #a, __case_i__, (double)((type*)(a))[__case_i__], #b, __case_i__, (double)((type*)(b))[__case_i__], ##__VA_ARGS__); \ |
132 | 0 | ABORT_CASE; \ |
133 | 0 | } } |
134 | | |
135 | 3.30k | #define REQUIRE_EQ_WITH_TOLERANCE(a, b, t, err, ...) { \ |
136 | 3.30k | if ((double)((a) - (b18 )) > (t) || (double)((a) - (b18 )) < -(t)) \ |
137 | 0 | { \ |
138 | 0 | if (isatty(fileno(stdout))) \ |
139 | 0 | printf("\n\t\033[0;31mREQUIRE_EQ_WITH_TOLERANCE\033[0;0m: %s:%d: %s(%lg) != %s(%lg) | +-%lg, " err, __FILE__, __LINE__, #a, (double)(a), #b, (double)(b), (double)(t), ##__VA_ARGS__); \ |
140 | 0 | else \ |
141 | 0 | printf("\n\tREQUIRE_EQ_WITH_TOLERANCE: %s:%d: %s(%lg) != %s(%lg) | +-%lg, " err, __FILE__, __LINE__, #a, (double)(a), #b, (double)(b), (double)(t), ##__VA_ARGS__); \ |
142 | 0 | ABORT_CASE; \ |
143 | 0 | } } |
144 | | |
145 | 278 | #define REQUIRE_ARRAY_EQ_WITH_TOLERANCE(type, a, b, len, t, err, ...) { \ |
146 | 278 | int __case_i__; \ |
147 | 607M | for (__case_i__ = 0; __case_i__ < (len); __case_i__++607M ) \ |
148 | 607M | if ((double)(((type*)(a))[__case_i__] - ((type*)(b))[__case_i__]) > (t) || (double)(((type*)(a))[__case_i__] - ((type*)(b))[__case_i__]) < -(t)) \ |
149 | 607M | { \ |
150 | 0 | if (isatty(fileno(stdout))) \ |
151 | 0 | printf("\n\t\033[0;31mREQUIRE_ARRAY_EQ_WITH_TOLERANCE\033[0;0m: %s:%d: %s[%d](%lg) != %s[%d](%lg) | +-%lg, " err, __FILE__, __LINE__, #a, __case_i__, (double)((type*)(a))[__case_i__], #b, __case_i__, (double)((type*)(b))[__case_i__], (double)(t), ##__VA_ARGS__); \ |
152 | 0 | else \ |
153 | 0 | printf("\n\tREQUIRE_ARRAY_EQ_WITH_TOLERANCE: %s:%d: %s[%d](%lg) != %s[%d](%lg) | +-%lg, " err, __FILE__, __LINE__, #a, __case_i__, (double)((type*)(a))[__case_i__], #b, __case_i__, (double)((type*)(b))[__case_i__], (double)(t), ##__VA_ARGS__); \ |
154 | 0 | ABORT_CASE; \ |
155 | 0 | } } |
156 | | |
157 | 13 | #define REQUIRE_NOT_EQ(a, b, err, ...) { \ |
158 | 13 | if ((a) == (b)) \ |
159 | 0 | { \ |
160 | 0 | if (isatty(fileno(stdout))) \ |
161 | 0 | printf("\n\t\033[0;31mREQUIRE_NOT_EQ\033[0;0m: %s:%d: %s(%lg) == %s(%lg), " err, __FILE__, __LINE__, #a, (double)(a), #b, (double)(b), ##__VA_ARGS__); \ |
162 | 0 | else \ |
163 | 0 | printf("\n\tREQUIRE_NOT_EQ: %s:%d: %s(%lg) == %s(%lg), " err, __FILE__, __LINE__, #a, (double)(a), #b, (double)(b), ##__VA_ARGS__); \ |
164 | 0 | ABORT_CASE; \ |
165 | 0 | } } |
166 | | |
167 | 1 | #define REQUIRE_ARRAY_NOT_EQ(type, a, b, len, err, ...) { \ |
168 | 1 | int __case_i__; \ |
169 | 1 | int __flag__ = 0; \ |
170 | 2 | for (__case_i__ = 0; !__flag__ && __case_i__ < (len)1 ; __case_i__++1 ) \ |
171 | 1 | __flag__ = (((type*)(a))[__case_i__] != ((type*)(b))[__case_i__]); \ |
172 | 1 | if (!__flag__) \ |
173 | 0 | { \ |
174 | 0 | if (isatty(fileno(stdout))) \ |
175 | 0 | printf("\n\t\033[0;31mREQUIRE_ARRAY_NOT_EQ\033[0;0m: %s:%d: %s[%d](%lg) == %s[%d](%lg), " err, __FILE__, __LINE__, #a, __case_i__, (double)((type*)(a))[__case_i__], #b, __case_i__, (double)((type*)(b))[__case_i__], ##__VA_ARGS__); \ |
176 | 0 | else \ |
177 | 0 | printf("\n\tREQUIRE_ARRAY_NOT_EQ: %s:%d: %s[%d](%lg) == %s[%d](%lg), " err, __FILE__, __LINE__, #a, __case_i__, (double)((type*)(a))[__case_i__], #b, __case_i__, (double)((type*)(b))[__case_i__], ##__VA_ARGS__); \ |
178 | 0 | ABORT_CASE; \ |
179 | 0 | } } |
180 | | |
181 | 4 | #define REQUIRE_NOT_EQ_WITH_TOLERANCE(a, b, t, err, ...) { \ |
182 | 4 | if ((double)((a) - (b)) <= (t) && (double)((a) - (b)) >= -(t)) \ |
183 | 0 | { \ |
184 | 0 | if (isatty(fileno(stdout))) \ |
185 | 0 | printf("\n\t\033[0;31mREQUIRE_NOT_EQ_WITH_TLERANCE\033[0;0m: %s:%d: %s(%lg) == %s(%lg) | +-%lg, " err, __FILE__, __LINE__, #a, (double)(a), #b, (double)(b), (double)(t), ##__VA_ARGS__); \ |
186 | 0 | else \ |
187 | 0 | printf("\n\tREQUIRE_NOT_EQ_WITH_TLERANCE: %s:%d: %s(%lg) == %s(%lg) | +-%lg, " err, __FILE__, __LINE__, #a, (double)(a), #b, (double)(b), (double)(t), ##__VA_ARGS__); \ |
188 | 0 | ABORT_CASE; \ |
189 | 0 | } } |
190 | | |
191 | | #define REQUIRE_ARRAY_NOT_EQ_WITH_TOLERANCE(type, a, b, len, t, err, ...) { \ |
192 | | int __case_i__; \ |
193 | | int __flag__ = 0; \ |
194 | | for (__case_i__ = 0; !__flag__ && __case_i__ < (len); __case_i__++) \ |
195 | | __flag__ = ((double)(((type*)(a))[__case_i__] - ((type*)(b))[__case_i__]) > (t) || (double)(((type*)(a))[__case_i__] - ((type*)(b))[__case_i__]) < -(t)); \ |
196 | | if (!__flag__) \ |
197 | | { \ |
198 | | if (isatty(fileno(stdout))) \ |
199 | | printf("\n\t\033[0;31mREQUIRE_ARRAY_NOT_EQ_WITH_TOLERANCE\033[0;0m: %s:%d: %s[%d](%lg) == %s[%d](%lg) | +-%lg, " err, __FILE__, __LINE__, #a, __case_i__, (double)((type*)(a))[__case_i__], #b, __case_i__, (double)((type*)(b))[__case_i__], (double)(t), ##__VA_ARGS__); \ |
200 | | else \ |
201 | | printf("\n\tREQUIRE_ARRAY_NOT_EQ_WITH_TOLERANCE: %s:%d: %s[%d](%lg) == %s[%d](%lg) | +-%lg, " err, __FILE__, __LINE__, #a, __case_i__, (double)((type*)(a))[__case_i__], #b, __case_i__, (double)((type*)(b))[__case_i__], (double)(t), ##__VA_ARGS__); \ |
202 | | ABORT_CASE; \ |
203 | | } } |
204 | | |
205 | | #endif |