Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
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 <stdio.h>
52#endif
53
54#ifndef ARRAY_SIZE
55#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
56#endif
57
58/*
59 * gcc cpuid.h provides __cpuid_count() since v4.4.
60 * Clang/LLVM cpuid.h provides __cpuid_count() since v3.4.0.
61 *
62 * Provide local define for tests needing __cpuid_count() because
63 * selftests need to work in older environments that do not yet
64 * have __cpuid_count().
65 */
66#ifndef __cpuid_count
67#define __cpuid_count(level, count, a, b, c, d) \
68 __asm__ __volatile__ ("cpuid\n\t" \
69 : "=a" (a), "=b" (b), "=c" (c), "=d" (d) \
70 : "0" (level), "2" (count))
71#endif
72
73/* define kselftest exit codes */
74#define KSFT_PASS 0
75#define KSFT_FAIL 1
76#define KSFT_XFAIL 2
77#define KSFT_XPASS 3
78#define KSFT_SKIP 4
79
80/* counters */
81struct ksft_count {
82 unsigned int ksft_pass;
83 unsigned int ksft_fail;
84 unsigned int ksft_xfail;
85 unsigned int ksft_xpass;
86 unsigned int ksft_xskip;
87 unsigned int ksft_error;
88};
89
90static struct ksft_count ksft_cnt;
91static unsigned int ksft_plan;
92
93static inline unsigned int ksft_test_num(void)
94{
95 return ksft_cnt.ksft_pass + ksft_cnt.ksft_fail +
96 ksft_cnt.ksft_xfail + ksft_cnt.ksft_xpass +
97 ksft_cnt.ksft_xskip + ksft_cnt.ksft_error;
98}
99
100static inline void ksft_inc_pass_cnt(void) { ksft_cnt.ksft_pass++; }
101static inline void ksft_inc_fail_cnt(void) { ksft_cnt.ksft_fail++; }
102static inline void ksft_inc_xfail_cnt(void) { ksft_cnt.ksft_xfail++; }
103static inline void ksft_inc_xpass_cnt(void) { ksft_cnt.ksft_xpass++; }
104static inline void ksft_inc_xskip_cnt(void) { ksft_cnt.ksft_xskip++; }
105static inline void ksft_inc_error_cnt(void) { ksft_cnt.ksft_error++; }
106
107static inline int ksft_get_pass_cnt(void) { return ksft_cnt.ksft_pass; }
108static inline int ksft_get_fail_cnt(void) { return ksft_cnt.ksft_fail; }
109static inline int ksft_get_xfail_cnt(void) { return ksft_cnt.ksft_xfail; }
110static inline int ksft_get_xpass_cnt(void) { return ksft_cnt.ksft_xpass; }
111static inline int ksft_get_xskip_cnt(void) { return ksft_cnt.ksft_xskip; }
112static inline int ksft_get_error_cnt(void) { return ksft_cnt.ksft_error; }
113
114static inline void ksft_print_header(void)
115{
116 if (!(getenv("KSFT_TAP_LEVEL")))
117 printf("TAP version 13\n");
118}
119
120static inline void ksft_set_plan(unsigned int plan)
121{
122 ksft_plan = plan;
123 printf("1..%d\n", ksft_plan);
124}
125
126static inline void ksft_print_cnts(void)
127{
128 if (ksft_plan != ksft_test_num())
129 printf("# Planned tests != run tests (%u != %u)\n",
130 ksft_plan, ksft_test_num());
131 printf("# Totals: pass:%d fail:%d xfail:%d xpass:%d skip:%d error:%d\n",
132 ksft_cnt.ksft_pass, ksft_cnt.ksft_fail,
133 ksft_cnt.ksft_xfail, ksft_cnt.ksft_xpass,
134 ksft_cnt.ksft_xskip, ksft_cnt.ksft_error);
135}
136
137static inline void ksft_print_msg(const char *msg, ...)
138{
139 int saved_errno = errno;
140 va_list args;
141
142 va_start(args, msg);
143 printf("# ");
144 errno = saved_errno;
145 vprintf(msg, args);
146 va_end(args);
147}
148
149static inline void ksft_test_result_pass(const char *msg, ...)
150{
151 int saved_errno = errno;
152 va_list args;
153
154 ksft_cnt.ksft_pass++;
155
156 va_start(args, msg);
157 printf("ok %d ", ksft_test_num());
158 errno = saved_errno;
159 vprintf(msg, args);
160 va_end(args);
161}
162
163static inline void ksft_test_result_fail(const char *msg, ...)
164{
165 int saved_errno = errno;
166 va_list args;
167
168 ksft_cnt.ksft_fail++;
169
170 va_start(args, msg);
171 printf("not ok %d ", ksft_test_num());
172 errno = saved_errno;
173 vprintf(msg, args);
174 va_end(args);
175}
176
177/**
178 * ksft_test_result() - Report test success based on truth of condition
179 *
180 * @condition: if true, report test success, otherwise failure.
181 */
182#define ksft_test_result(condition, fmt, ...) do { \
183 if (!!(condition)) \
184 ksft_test_result_pass(fmt, ##__VA_ARGS__);\
185 else \
186 ksft_test_result_fail(fmt, ##__VA_ARGS__);\
187 } while (0)
188
189static inline void ksft_test_result_xfail(const char *msg, ...)
190{
191 int saved_errno = errno;
192 va_list args;
193
194 ksft_cnt.ksft_xfail++;
195
196 va_start(args, msg);
197 printf("ok %d # XFAIL ", ksft_test_num());
198 errno = saved_errno;
199 vprintf(msg, args);
200 va_end(args);
201}
202
203static inline void ksft_test_result_skip(const char *msg, ...)
204{
205 int saved_errno = errno;
206 va_list args;
207
208 ksft_cnt.ksft_xskip++;
209
210 va_start(args, msg);
211 printf("ok %d # SKIP ", ksft_test_num());
212 errno = saved_errno;
213 vprintf(msg, args);
214 va_end(args);
215}
216
217/* TODO: how does "error" differ from "fail" or "skip"? */
218static inline void ksft_test_result_error(const char *msg, ...)
219{
220 int saved_errno = errno;
221 va_list args;
222
223 ksft_cnt.ksft_error++;
224
225 va_start(args, msg);
226 printf("not ok %d # error ", ksft_test_num());
227 errno = saved_errno;
228 vprintf(msg, args);
229 va_end(args);
230}
231
232static inline int ksft_exit_pass(void)
233{
234 ksft_print_cnts();
235 exit(KSFT_PASS);
236}
237
238static inline int ksft_exit_fail(void)
239{
240 ksft_print_cnts();
241 exit(KSFT_FAIL);
242}
243
244/**
245 * ksft_exit() - Exit selftest based on truth of condition
246 *
247 * @condition: if true, exit self test with success, otherwise fail.
248 */
249#define ksft_exit(condition) do { \
250 if (!!(condition)) \
251 ksft_exit_pass(); \
252 else \
253 ksft_exit_fail(); \
254 } while (0)
255
256/**
257 * ksft_finished() - Exit selftest with success if all tests passed
258 */
259#define ksft_finished() \
260 ksft_exit(ksft_plan == \
261 ksft_cnt.ksft_pass + \
262 ksft_cnt.ksft_xfail + \
263 ksft_cnt.ksft_xskip)
264
265static inline int ksft_exit_fail_msg(const char *msg, ...)
266{
267 int saved_errno = errno;
268 va_list args;
269
270 va_start(args, msg);
271 printf("Bail out! ");
272 errno = saved_errno;
273 vprintf(msg, args);
274 va_end(args);
275
276 ksft_print_cnts();
277 exit(KSFT_FAIL);
278}
279
280static inline int ksft_exit_xfail(void)
281{
282 ksft_print_cnts();
283 exit(KSFT_XFAIL);
284}
285
286static inline int ksft_exit_xpass(void)
287{
288 ksft_print_cnts();
289 exit(KSFT_XPASS);
290}
291
292static inline int ksft_exit_skip(const char *msg, ...)
293{
294 int saved_errno = errno;
295 va_list args;
296
297 va_start(args, msg);
298
299 /*
300 * FIXME: several tests misuse ksft_exit_skip so produce
301 * something sensible if some tests have already been run
302 * or a plan has been printed. Those tests should use
303 * ksft_test_result_skip or ksft_exit_fail_msg instead.
304 */
305 if (ksft_plan || ksft_test_num()) {
306 ksft_cnt.ksft_xskip++;
307 printf("ok %d # SKIP ", 1 + ksft_test_num());
308 } else {
309 printf("1..0 # SKIP ");
310 }
311 if (msg) {
312 errno = saved_errno;
313 vprintf(msg, args);
314 va_end(args);
315 }
316 if (ksft_test_num())
317 ksft_print_cnts();
318 exit(KSFT_SKIP);
319}
320
321#endif /* __KSELFTEST_H */