1 | /* SPDX-License-Identifier: GPL-2.0 */ |
2 | /* |
3 | * kselftest.h: low-level kselftest framework to include from |
4 | * selftest programs. When possible, please use |
5 | * kselftest_harness.h instead. |
6 | * |
7 | * Copyright (c) 2014 Shuah Khan <shuahkh@osg.samsung.com> |
8 | * Copyright (c) 2014 Samsung Electronics Co., Ltd. |
9 | * |
10 | * Using this API consists of first counting how many tests your code |
11 | * has to run, and then starting up the reporting: |
12 | * |
13 | * ksft_print_header(); |
14 | * ksft_set_plan(total_number_of_tests); |
15 | * |
16 | * For each test, report any progress, debugging, etc with: |
17 | * |
18 | * ksft_print_msg(fmt, ...); |
19 | * |
20 | * and finally report the pass/fail/skip/xfail state of the test with one of: |
21 | * |
22 | * ksft_test_result(condition, fmt, ...); |
23 | * ksft_test_result_pass(fmt, ...); |
24 | * ksft_test_result_fail(fmt, ...); |
25 | * ksft_test_result_skip(fmt, ...); |
26 | * ksft_test_result_xfail(fmt, ...); |
27 | * ksft_test_result_error(fmt, ...); |
28 | * |
29 | * When all tests are finished, clean up and exit the program with one of: |
30 | * |
31 | * ksft_finished(); |
32 | * ksft_exit(condition); |
33 | * ksft_exit_pass(); |
34 | * ksft_exit_fail(); |
35 | * |
36 | * If the program wants to report details on why the entire program has |
37 | * failed, it can instead exit with a message (this is usually done when |
38 | * the program is aborting before finishing all tests): |
39 | * |
40 | * ksft_exit_fail_msg(fmt, ...); |
41 | * |
42 | */ |
43 | #ifndef __KSELFTEST_H |
44 | #define __KSELFTEST_H |
45 | |
46 | #ifndef NOLIBC |
47 | #include <errno.h> |
48 | #include <stdlib.h> |
49 | #include <unistd.h> |
50 | #include <stdarg.h> |
51 | #include <string.h> |
52 | #include <stdio.h> |
53 | #endif |
54 | |
55 | #ifndef ARRAY_SIZE |
56 | #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) |
57 | #endif |
58 | |
59 | /* |
60 | * gcc cpuid.h provides __cpuid_count() since v4.4. |
61 | * Clang/LLVM cpuid.h provides __cpuid_count() since v3.4.0. |
62 | * |
63 | * Provide local define for tests needing __cpuid_count() because |
64 | * selftests need to work in older environments that do not yet |
65 | * have __cpuid_count(). |
66 | */ |
67 | #ifndef __cpuid_count |
68 | #define __cpuid_count(level, count, a, b, c, d) \ |
69 | __asm__ __volatile__ ("cpuid\n\t" \ |
70 | : "=a" (a), "=b" (b), "=c" (c), "=d" (d) \ |
71 | : "0" (level), "2" (count)) |
72 | #endif |
73 | |
74 | /* define kselftest exit codes */ |
75 | #define KSFT_PASS 0 |
76 | #define KSFT_FAIL 1 |
77 | #define KSFT_XFAIL 2 |
78 | #define KSFT_XPASS 3 |
79 | #define KSFT_SKIP 4 |
80 | |
81 | #define __printf(a, b) __attribute__((format(printf, a, b))) |
82 | |
83 | /* counters */ |
84 | struct ksft_count { |
85 | unsigned int ksft_pass; |
86 | unsigned int ksft_fail; |
87 | unsigned int ksft_xfail; |
88 | unsigned int ksft_xpass; |
89 | unsigned int ksft_xskip; |
90 | unsigned int ksft_error; |
91 | }; |
92 | |
93 | static struct ksft_count ksft_cnt; |
94 | static unsigned int ksft_plan; |
95 | |
96 | static inline unsigned int ksft_test_num(void) |
97 | { |
98 | return ksft_cnt.ksft_pass + ksft_cnt.ksft_fail + |
99 | ksft_cnt.ksft_xfail + ksft_cnt.ksft_xpass + |
100 | ksft_cnt.ksft_xskip + ksft_cnt.ksft_error; |
101 | } |
102 | |
103 | static inline void ksft_inc_pass_cnt(void) { ksft_cnt.ksft_pass++; } |
104 | static inline void ksft_inc_fail_cnt(void) { ksft_cnt.ksft_fail++; } |
105 | static inline void ksft_inc_xfail_cnt(void) { ksft_cnt.ksft_xfail++; } |
106 | static inline void ksft_inc_xpass_cnt(void) { ksft_cnt.ksft_xpass++; } |
107 | static inline void ksft_inc_xskip_cnt(void) { ksft_cnt.ksft_xskip++; } |
108 | static inline void ksft_inc_error_cnt(void) { ksft_cnt.ksft_error++; } |
109 | |
110 | static inline int ksft_get_pass_cnt(void) { return ksft_cnt.ksft_pass; } |
111 | static inline int ksft_get_fail_cnt(void) { return ksft_cnt.ksft_fail; } |
112 | static inline int ksft_get_xfail_cnt(void) { return ksft_cnt.ksft_xfail; } |
113 | static inline int ksft_get_xpass_cnt(void) { return ksft_cnt.ksft_xpass; } |
114 | static inline int ksft_get_xskip_cnt(void) { return ksft_cnt.ksft_xskip; } |
115 | static inline int ksft_get_error_cnt(void) { return ksft_cnt.ksft_error; } |
116 | |
117 | static inline void (void) |
118 | { |
119 | /* |
120 | * Force line buffering; If stdout is not connected to a terminal, it |
121 | * will otherwise default to fully buffered, which can cause output |
122 | * duplication if there is content in the buffer when fork()ing. If |
123 | * there is a crash, line buffering also means the most recent output |
124 | * line will be visible. |
125 | */ |
126 | setvbuf(stdout, NULL, _IOLBF, 0); |
127 | |
128 | if (!(getenv("KSFT_TAP_LEVEL" ))) |
129 | printf("TAP version 13\n" ); |
130 | } |
131 | |
132 | static inline void ksft_set_plan(unsigned int plan) |
133 | { |
134 | ksft_plan = plan; |
135 | printf("1..%u\n" , ksft_plan); |
136 | } |
137 | |
138 | static inline void ksft_print_cnts(void) |
139 | { |
140 | if (ksft_plan != ksft_test_num()) |
141 | printf("# Planned tests != run tests (%u != %u)\n" , |
142 | ksft_plan, ksft_test_num()); |
143 | printf("# Totals: pass:%u fail:%u xfail:%u xpass:%u skip:%u error:%u\n" , |
144 | ksft_cnt.ksft_pass, ksft_cnt.ksft_fail, |
145 | ksft_cnt.ksft_xfail, ksft_cnt.ksft_xpass, |
146 | ksft_cnt.ksft_xskip, ksft_cnt.ksft_error); |
147 | } |
148 | |
149 | static inline __printf(1, 2) void ksft_print_msg(const char *msg, ...) |
150 | { |
151 | int saved_errno = errno; |
152 | va_list args; |
153 | |
154 | va_start(args, msg); |
155 | printf("# " ); |
156 | errno = saved_errno; |
157 | vprintf(msg, args); |
158 | va_end(args); |
159 | } |
160 | |
161 | static inline void ksft_perror(const char *msg) |
162 | { |
163 | #ifndef NOLIBC |
164 | ksft_print_msg(msg: "%s: %s (%d)\n" , msg, strerror(errno), errno); |
165 | #else |
166 | /* |
167 | * nolibc doesn't provide strerror() and it seems |
168 | * inappropriate to add one, just print the errno. |
169 | */ |
170 | ksft_print_msg("%s: %d)\n" , msg, errno); |
171 | #endif |
172 | } |
173 | |
174 | static inline __printf(1, 2) void ksft_test_result_pass(const char *msg, ...) |
175 | { |
176 | int saved_errno = errno; |
177 | va_list args; |
178 | |
179 | ksft_cnt.ksft_pass++; |
180 | |
181 | va_start(args, msg); |
182 | printf("ok %u " , ksft_test_num()); |
183 | errno = saved_errno; |
184 | vprintf(msg, args); |
185 | va_end(args); |
186 | } |
187 | |
188 | static inline __printf(1, 2) void ksft_test_result_fail(const char *msg, ...) |
189 | { |
190 | int saved_errno = errno; |
191 | va_list args; |
192 | |
193 | ksft_cnt.ksft_fail++; |
194 | |
195 | va_start(args, msg); |
196 | printf("not ok %u " , ksft_test_num()); |
197 | errno = saved_errno; |
198 | vprintf(msg, args); |
199 | va_end(args); |
200 | } |
201 | |
202 | /** |
203 | * ksft_test_result() - Report test success based on truth of condition |
204 | * |
205 | * @condition: if true, report test success, otherwise failure. |
206 | */ |
207 | #define ksft_test_result(condition, fmt, ...) do { \ |
208 | if (!!(condition)) \ |
209 | ksft_test_result_pass(fmt, ##__VA_ARGS__);\ |
210 | else \ |
211 | ksft_test_result_fail(fmt, ##__VA_ARGS__);\ |
212 | } while (0) |
213 | |
214 | static inline __printf(1, 2) void ksft_test_result_xfail(const char *msg, ...) |
215 | { |
216 | int saved_errno = errno; |
217 | va_list args; |
218 | |
219 | ksft_cnt.ksft_xfail++; |
220 | |
221 | va_start(args, msg); |
222 | printf("ok %u # XFAIL " , ksft_test_num()); |
223 | errno = saved_errno; |
224 | vprintf(msg, args); |
225 | va_end(args); |
226 | } |
227 | |
228 | static inline __printf(1, 2) void ksft_test_result_skip(const char *msg, ...) |
229 | { |
230 | int saved_errno = errno; |
231 | va_list args; |
232 | |
233 | ksft_cnt.ksft_xskip++; |
234 | |
235 | va_start(args, msg); |
236 | printf("ok %u # SKIP " , ksft_test_num()); |
237 | errno = saved_errno; |
238 | vprintf(msg, args); |
239 | va_end(args); |
240 | } |
241 | |
242 | /* TODO: how does "error" differ from "fail" or "skip"? */ |
243 | static inline __printf(1, 2) void ksft_test_result_error(const char *msg, ...) |
244 | { |
245 | int saved_errno = errno; |
246 | va_list args; |
247 | |
248 | ksft_cnt.ksft_error++; |
249 | |
250 | va_start(args, msg); |
251 | printf("not ok %u # error " , ksft_test_num()); |
252 | errno = saved_errno; |
253 | vprintf(msg, args); |
254 | va_end(args); |
255 | } |
256 | |
257 | static inline int ksft_exit_pass(void) |
258 | { |
259 | ksft_print_cnts(); |
260 | exit(KSFT_PASS); |
261 | } |
262 | |
263 | static inline int ksft_exit_fail(void) |
264 | { |
265 | ksft_print_cnts(); |
266 | exit(KSFT_FAIL); |
267 | } |
268 | |
269 | /** |
270 | * ksft_exit() - Exit selftest based on truth of condition |
271 | * |
272 | * @condition: if true, exit self test with success, otherwise fail. |
273 | */ |
274 | #define ksft_exit(condition) do { \ |
275 | if (!!(condition)) \ |
276 | ksft_exit_pass(); \ |
277 | else \ |
278 | ksft_exit_fail(); \ |
279 | } while (0) |
280 | |
281 | /** |
282 | * ksft_finished() - Exit selftest with success if all tests passed |
283 | */ |
284 | #define ksft_finished() \ |
285 | ksft_exit(ksft_plan == \ |
286 | ksft_cnt.ksft_pass + \ |
287 | ksft_cnt.ksft_xfail + \ |
288 | ksft_cnt.ksft_xskip) |
289 | |
290 | static inline __printf(1, 2) int ksft_exit_fail_msg(const char *msg, ...) |
291 | { |
292 | int saved_errno = errno; |
293 | va_list args; |
294 | |
295 | va_start(args, msg); |
296 | printf("Bail out! " ); |
297 | errno = saved_errno; |
298 | vprintf(msg, args); |
299 | va_end(args); |
300 | |
301 | ksft_print_cnts(); |
302 | exit(KSFT_FAIL); |
303 | } |
304 | |
305 | static inline int ksft_exit_xfail(void) |
306 | { |
307 | ksft_print_cnts(); |
308 | exit(KSFT_XFAIL); |
309 | } |
310 | |
311 | static inline int ksft_exit_xpass(void) |
312 | { |
313 | ksft_print_cnts(); |
314 | exit(KSFT_XPASS); |
315 | } |
316 | |
317 | static inline __printf(1, 2) int ksft_exit_skip(const char *msg, ...) |
318 | { |
319 | int saved_errno = errno; |
320 | va_list args; |
321 | |
322 | va_start(args, msg); |
323 | |
324 | /* |
325 | * FIXME: several tests misuse ksft_exit_skip so produce |
326 | * something sensible if some tests have already been run |
327 | * or a plan has been printed. Those tests should use |
328 | * ksft_test_result_skip or ksft_exit_fail_msg instead. |
329 | */ |
330 | if (ksft_plan || ksft_test_num()) { |
331 | ksft_cnt.ksft_xskip++; |
332 | printf("ok %d # SKIP " , 1 + ksft_test_num()); |
333 | } else { |
334 | printf("1..0 # SKIP " ); |
335 | } |
336 | if (msg) { |
337 | errno = saved_errno; |
338 | vprintf(msg, args); |
339 | va_end(args); |
340 | } |
341 | if (ksft_test_num()) |
342 | ksft_print_cnts(); |
343 | exit(KSFT_SKIP); |
344 | } |
345 | |
346 | #endif /* __KSELFTEST_H */ |
347 | |