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 * ksft_perror(msg); 20 * 21 * and finally report the pass/fail/skip/xfail/xpass state of the test 22 * with one of: 23 * 24 * ksft_test_result(condition, fmt, ...); 25 * ksft_test_result_report(result, fmt, ...); 26 * ksft_test_result_pass(fmt, ...); 27 * ksft_test_result_fail(fmt, ...); 28 * ksft_test_result_skip(fmt, ...); 29 * ksft_test_result_xfail(fmt, ...); 30 * ksft_test_result_xpass(fmt, ...); 31 * ksft_test_result_error(fmt, ...); 32 * ksft_test_result_code(exit_code, test_name, fmt, ...); 33 * 34 * When all tests are finished, clean up and exit the program with one of: 35 * 36 * ksft_finished(); 37 * ksft_exit(condition); 38 * ksft_exit_pass(); 39 * ksft_exit_fail(); 40 * 41 * If the program wants to report details on why the entire program has 42 * failed, it can instead exit with a message (this is usually done when 43 * the program is aborting before finishing all tests): 44 * 45 * ksft_exit_fail_msg(fmt, ...); 46 * ksft_exit_fail_perror(msg); 47 * 48 */ 49 #ifndef __KSELFTEST_H 50 #define __KSELFTEST_H 51 52 #ifndef NOLIBC 53 #include <errno.h> 54 #include <stdlib.h> 55 #include <unistd.h> 56 #include <stdarg.h> 57 #include <stdbool.h> 58 #include <string.h> 59 #include <stdio.h> 60 #include <sys/utsname.h> 61 #endif 62 63 #ifndef ARRAY_SIZE 64 #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) 65 #endif 66 67 #if defined(__i386__) || defined(__x86_64__) /* arch */ 68 /* 69 * gcc cpuid.h provides __cpuid_count() since v4.4. 70 * Clang/LLVM cpuid.h provides __cpuid_count() since v3.4.0. 71 * 72 * Provide local define for tests needing __cpuid_count() because 73 * selftests need to work in older environments that do not yet 74 * have __cpuid_count(). 75 */ 76 #ifndef __cpuid_count 77 #define __cpuid_count(level, count, a, b, c, d) \ 78 __asm__ __volatile__ ("cpuid\n\t" \ 79 : "=a" (a), "=b" (b), "=c" (c), "=d" (d) \ 80 : "0" (level), "2" (count)) 81 #endif 82 #endif /* end arch */ 83 84 /* define kselftest exit codes */ 85 #define KSFT_PASS 0 86 #define KSFT_FAIL 1 87 #define KSFT_XFAIL 2 88 #define KSFT_XPASS 3 89 #define KSFT_SKIP 4 90 91 #ifndef __noreturn 92 #define __noreturn __attribute__((__noreturn__)) 93 #endif 94 #define __printf(a, b) __attribute__((format(printf, a, b))) 95 96 #ifndef __always_unused 97 #define __always_unused __attribute__((__unused__)) 98 #endif 99 100 #ifndef __maybe_unused 101 #define __maybe_unused __attribute__((__unused__)) 102 #endif 103 104 /* counters */ 105 struct ksft_count { 106 unsigned int ksft_pass; 107 unsigned int ksft_fail; 108 unsigned int ksft_xfail; 109 unsigned int ksft_xpass; 110 unsigned int ksft_xskip; 111 unsigned int ksft_error; 112 }; 113 114 static struct ksft_count ksft_cnt; 115 static unsigned int ksft_plan; 116 static bool ksft_debug_enabled; 117 118 static inline unsigned int ksft_test_num(void) 119 { 120 return ksft_cnt.ksft_pass + ksft_cnt.ksft_fail + 121 ksft_cnt.ksft_xfail + ksft_cnt.ksft_xpass + 122 ksft_cnt.ksft_xskip + ksft_cnt.ksft_error; 123 } 124 125 static inline void ksft_inc_pass_cnt(void) { ksft_cnt.ksft_pass++; } 126 static inline void ksft_inc_fail_cnt(void) { ksft_cnt.ksft_fail++; } 127 static inline void ksft_inc_xfail_cnt(void) { ksft_cnt.ksft_xfail++; } 128 static inline void ksft_inc_xpass_cnt(void) { ksft_cnt.ksft_xpass++; } 129 static inline void ksft_inc_xskip_cnt(void) { ksft_cnt.ksft_xskip++; } 130 static inline void ksft_inc_error_cnt(void) { ksft_cnt.ksft_error++; } 131 132 static inline int ksft_get_pass_cnt(void) { return ksft_cnt.ksft_pass; } 133 static inline int ksft_get_fail_cnt(void) { return ksft_cnt.ksft_fail; } 134 static inline int ksft_get_xfail_cnt(void) { return ksft_cnt.ksft_xfail; } 135 static inline int ksft_get_xpass_cnt(void) { return ksft_cnt.ksft_xpass; } 136 static inline int ksft_get_xskip_cnt(void) { return ksft_cnt.ksft_xskip; } 137 static inline int ksft_get_error_cnt(void) { return ksft_cnt.ksft_error; } 138 139 static inline void ksft_print_header(void) 140 { 141 /* 142 * Force line buffering; If stdout is not connected to a terminal, it 143 * will otherwise default to fully buffered, which can cause output 144 * duplication if there is content in the buffer when fork()ing. If 145 * there is a crash, line buffering also means the most recent output 146 * line will be visible. 147 */ 148 setvbuf(stdout, NULL, _IOLBF, 0); 149 150 if (!(getenv("KSFT_TAP_LEVEL"))) 151 printf("TAP version 13\n"); 152 } 153 154 static inline void ksft_set_plan(unsigned int plan) 155 { 156 ksft_plan = plan; 157 printf("1..%u\n", ksft_plan); 158 } 159 160 static inline void ksft_print_cnts(void) 161 { 162 if (ksft_cnt.ksft_xskip > 0) 163 printf( 164 "# %u skipped test(s) detected. Consider enabling relevant config options to improve coverage.\n", 165 ksft_cnt.ksft_xskip 166 ); 167 if (ksft_plan != ksft_test_num()) 168 printf("# Planned tests != run tests (%u != %u)\n", 169 ksft_plan, ksft_test_num()); 170 printf("# Totals: pass:%u fail:%u xfail:%u xpass:%u skip:%u error:%u\n", 171 ksft_cnt.ksft_pass, ksft_cnt.ksft_fail, 172 ksft_cnt.ksft_xfail, ksft_cnt.ksft_xpass, 173 ksft_cnt.ksft_xskip, ksft_cnt.ksft_error); 174 } 175 176 static inline __printf(1, 2) void ksft_print_msg(const char *msg, ...) 177 { 178 int saved_errno = errno; 179 va_list args; 180 181 va_start(args, msg); 182 printf("# "); 183 errno = saved_errno; 184 vprintf(msg, args); 185 va_end(args); 186 } 187 188 static inline void ksft_print_dbg_msg(const char *msg, ...) 189 { 190 va_list args; 191 192 if (!ksft_debug_enabled) 193 return; 194 195 va_start(args, msg); 196 ksft_print_msg(msg, args); 197 va_end(args); 198 } 199 200 static inline void ksft_perror(const char *msg) 201 { 202 ksft_print_msg("%s: %s (%d)\n", msg, strerror(errno), errno); 203 } 204 205 static inline __printf(1, 2) void ksft_test_result_pass(const char *msg, ...) 206 { 207 int saved_errno = errno; 208 va_list args; 209 210 ksft_cnt.ksft_pass++; 211 212 va_start(args, msg); 213 printf("ok %u ", ksft_test_num()); 214 errno = saved_errno; 215 vprintf(msg, args); 216 va_end(args); 217 } 218 219 static inline __printf(1, 2) void ksft_test_result_fail(const char *msg, ...) 220 { 221 int saved_errno = errno; 222 va_list args; 223 224 ksft_cnt.ksft_fail++; 225 226 va_start(args, msg); 227 printf("not ok %u ", ksft_test_num()); 228 errno = saved_errno; 229 vprintf(msg, args); 230 va_end(args); 231 } 232 233 /** 234 * ksft_test_result() - Report test success based on truth of condition 235 * 236 * @condition: if true, report test success, otherwise failure. 237 */ 238 #define ksft_test_result(condition, fmt, ...) do { \ 239 if (!!(condition)) \ 240 ksft_test_result_pass(fmt, ##__VA_ARGS__);\ 241 else \ 242 ksft_test_result_fail(fmt, ##__VA_ARGS__);\ 243 } while (0) 244 245 static inline __printf(1, 2) void ksft_test_result_xfail(const char *msg, ...) 246 { 247 int saved_errno = errno; 248 va_list args; 249 250 ksft_cnt.ksft_xfail++; 251 252 va_start(args, msg); 253 printf("ok %u # XFAIL ", ksft_test_num()); 254 errno = saved_errno; 255 vprintf(msg, args); 256 va_end(args); 257 } 258 259 static inline __printf(1, 2) void ksft_test_result_xpass(const char *msg, ...) 260 { 261 int saved_errno = errno; 262 va_list args; 263 264 ksft_cnt.ksft_xpass++; 265 266 va_start(args, msg); 267 printf("ok %u # XPASS ", ksft_test_num()); 268 errno = saved_errno; 269 vprintf(msg, args); 270 va_end(args); 271 } 272 273 static inline __printf(1, 2) void ksft_test_result_skip(const char *msg, ...) 274 { 275 int saved_errno = errno; 276 va_list args; 277 278 ksft_cnt.ksft_xskip++; 279 280 va_start(args, msg); 281 printf("ok %u # SKIP ", ksft_test_num()); 282 errno = saved_errno; 283 vprintf(msg, args); 284 va_end(args); 285 } 286 287 /* TODO: how does "error" differ from "fail" or "skip"? */ 288 static inline __printf(1, 2) void ksft_test_result_error(const char *msg, ...) 289 { 290 int saved_errno = errno; 291 va_list args; 292 293 ksft_cnt.ksft_error++; 294 295 va_start(args, msg); 296 printf("not ok %u # error ", ksft_test_num()); 297 errno = saved_errno; 298 vprintf(msg, args); 299 va_end(args); 300 } 301 302 static inline __printf(3, 4) 303 void ksft_test_result_code(int exit_code, const char *test_name, 304 const char *msg, ...) 305 { 306 const char *tap_code = "ok"; 307 const char *directive = ""; 308 int saved_errno = errno; 309 va_list args; 310 311 switch (exit_code) { 312 case KSFT_PASS: 313 ksft_cnt.ksft_pass++; 314 break; 315 case KSFT_XFAIL: 316 directive = " # XFAIL "; 317 ksft_cnt.ksft_xfail++; 318 break; 319 case KSFT_XPASS: 320 directive = " # XPASS "; 321 ksft_cnt.ksft_xpass++; 322 break; 323 case KSFT_SKIP: 324 directive = " # SKIP "; 325 ksft_cnt.ksft_xskip++; 326 break; 327 case KSFT_FAIL: 328 default: 329 tap_code = "not ok"; 330 ksft_cnt.ksft_fail++; 331 break; 332 } 333 334 /* Docs seem to call for double space if directive is absent */ 335 if (!directive[0] && msg) 336 directive = " # "; 337 338 printf("%s %u %s%s", tap_code, ksft_test_num(), test_name, directive); 339 errno = saved_errno; 340 if (msg) { 341 va_start(args, msg); 342 vprintf(msg, args); 343 va_end(args); 344 } 345 printf("\n"); 346 } 347 348 /** 349 * ksft_test_result() - Report test success based on truth of condition 350 * 351 * @condition: if true, report test success, otherwise failure. 352 */ 353 #define ksft_test_result_report(result, fmt, ...) do { \ 354 switch (result) { \ 355 case KSFT_PASS: \ 356 ksft_test_result_pass(fmt, ##__VA_ARGS__); \ 357 break; \ 358 case KSFT_FAIL: \ 359 ksft_test_result_fail(fmt, ##__VA_ARGS__); \ 360 break; \ 361 case KSFT_XFAIL: \ 362 ksft_test_result_xfail(fmt, ##__VA_ARGS__); \ 363 break; \ 364 case KSFT_XPASS: \ 365 ksft_test_result_xpass(fmt, ##__VA_ARGS__); \ 366 break; \ 367 case KSFT_SKIP: \ 368 ksft_test_result_skip(fmt, ##__VA_ARGS__); \ 369 break; \ 370 } } while (0) 371 372 static inline __noreturn void ksft_exit_pass(void) 373 { 374 ksft_print_cnts(); 375 exit(KSFT_PASS); 376 } 377 378 static inline __noreturn void ksft_exit_fail(void) 379 { 380 ksft_print_cnts(); 381 exit(KSFT_FAIL); 382 } 383 384 /** 385 * ksft_exit() - Exit selftest based on truth of condition 386 * 387 * @condition: if true, exit self test with success, otherwise fail. 388 */ 389 #define ksft_exit(condition) do { \ 390 if (!!(condition)) \ 391 ksft_exit_pass(); \ 392 else \ 393 ksft_exit_fail(); \ 394 } while (0) 395 396 /** 397 * ksft_finished() - Exit selftest with success if all tests passed 398 */ 399 #define ksft_finished() \ 400 ksft_exit(ksft_plan == \ 401 ksft_cnt.ksft_pass + \ 402 ksft_cnt.ksft_xfail + \ 403 ksft_cnt.ksft_xskip) 404 405 static inline __noreturn __printf(1, 2) void ksft_exit_fail_msg(const char *msg, ...) 406 { 407 int saved_errno = errno; 408 va_list args; 409 410 va_start(args, msg); 411 printf("Bail out! "); 412 errno = saved_errno; 413 vprintf(msg, args); 414 va_end(args); 415 416 ksft_print_cnts(); 417 exit(KSFT_FAIL); 418 } 419 420 static inline __noreturn void ksft_exit_fail_perror(const char *msg) 421 { 422 ksft_exit_fail_msg("%s: %s (%d)\n", msg, strerror(errno), errno); 423 } 424 425 static inline __noreturn void ksft_exit_xfail(void) 426 { 427 ksft_print_cnts(); 428 exit(KSFT_XFAIL); 429 } 430 431 static inline __noreturn void ksft_exit_xpass(void) 432 { 433 ksft_print_cnts(); 434 exit(KSFT_XPASS); 435 } 436 437 static inline __noreturn __printf(1, 2) void ksft_exit_skip(const char *msg, ...) 438 { 439 int saved_errno = errno; 440 va_list args; 441 442 va_start(args, msg); 443 444 /* 445 * FIXME: several tests misuse ksft_exit_skip so produce 446 * something sensible if some tests have already been run 447 * or a plan has been printed. Those tests should use 448 * ksft_test_result_skip or ksft_exit_fail_msg instead. 449 */ 450 if (ksft_plan || ksft_test_num()) { 451 ksft_cnt.ksft_xskip++; 452 printf("ok %u # SKIP ", 1 + ksft_test_num()); 453 } else { 454 printf("1..0 # SKIP "); 455 } 456 if (msg) { 457 errno = saved_errno; 458 vprintf(msg, args); 459 va_end(args); 460 } 461 if (ksft_test_num()) 462 ksft_print_cnts(); 463 exit(KSFT_SKIP); 464 } 465 466 static inline int ksft_min_kernel_version(unsigned int min_major, 467 unsigned int min_minor) 468 { 469 unsigned int major, minor; 470 struct utsname info; 471 472 if (uname(&info) || sscanf(info.release, "%u.%u.", &major, &minor) != 2) 473 ksft_exit_fail_msg("Can't parse kernel version\n"); 474 475 return major > min_major || (major == min_major && minor >= min_minor); 476 } 477 478 #endif /* __KSELFTEST_H */ 479