162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * kselftest.h: low-level kselftest framework to include from 462306a36Sopenharmony_ci * selftest programs. When possible, please use 562306a36Sopenharmony_ci * kselftest_harness.h instead. 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * Copyright (c) 2014 Shuah Khan <shuahkh@osg.samsung.com> 862306a36Sopenharmony_ci * Copyright (c) 2014 Samsung Electronics Co., Ltd. 962306a36Sopenharmony_ci * 1062306a36Sopenharmony_ci * Using this API consists of first counting how many tests your code 1162306a36Sopenharmony_ci * has to run, and then starting up the reporting: 1262306a36Sopenharmony_ci * 1362306a36Sopenharmony_ci * ksft_print_header(); 1462306a36Sopenharmony_ci * ksft_set_plan(total_number_of_tests); 1562306a36Sopenharmony_ci * 1662306a36Sopenharmony_ci * For each test, report any progress, debugging, etc with: 1762306a36Sopenharmony_ci * 1862306a36Sopenharmony_ci * ksft_print_msg(fmt, ...); 1962306a36Sopenharmony_ci * 2062306a36Sopenharmony_ci * and finally report the pass/fail/skip/xfail state of the test with one of: 2162306a36Sopenharmony_ci * 2262306a36Sopenharmony_ci * ksft_test_result(condition, fmt, ...); 2362306a36Sopenharmony_ci * ksft_test_result_pass(fmt, ...); 2462306a36Sopenharmony_ci * ksft_test_result_fail(fmt, ...); 2562306a36Sopenharmony_ci * ksft_test_result_skip(fmt, ...); 2662306a36Sopenharmony_ci * ksft_test_result_xfail(fmt, ...); 2762306a36Sopenharmony_ci * ksft_test_result_error(fmt, ...); 2862306a36Sopenharmony_ci * 2962306a36Sopenharmony_ci * When all tests are finished, clean up and exit the program with one of: 3062306a36Sopenharmony_ci * 3162306a36Sopenharmony_ci * ksft_finished(); 3262306a36Sopenharmony_ci * ksft_exit(condition); 3362306a36Sopenharmony_ci * ksft_exit_pass(); 3462306a36Sopenharmony_ci * ksft_exit_fail(); 3562306a36Sopenharmony_ci * 3662306a36Sopenharmony_ci * If the program wants to report details on why the entire program has 3762306a36Sopenharmony_ci * failed, it can instead exit with a message (this is usually done when 3862306a36Sopenharmony_ci * the program is aborting before finishing all tests): 3962306a36Sopenharmony_ci * 4062306a36Sopenharmony_ci * ksft_exit_fail_msg(fmt, ...); 4162306a36Sopenharmony_ci * 4262306a36Sopenharmony_ci */ 4362306a36Sopenharmony_ci#ifndef __KSELFTEST_H 4462306a36Sopenharmony_ci#define __KSELFTEST_H 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_ci#ifndef NOLIBC 4762306a36Sopenharmony_ci#include <errno.h> 4862306a36Sopenharmony_ci#include <stdlib.h> 4962306a36Sopenharmony_ci#include <unistd.h> 5062306a36Sopenharmony_ci#include <stdarg.h> 5162306a36Sopenharmony_ci#include <stdio.h> 5262306a36Sopenharmony_ci#endif 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_ci#ifndef ARRAY_SIZE 5562306a36Sopenharmony_ci#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) 5662306a36Sopenharmony_ci#endif 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_ci/* 5962306a36Sopenharmony_ci * gcc cpuid.h provides __cpuid_count() since v4.4. 6062306a36Sopenharmony_ci * Clang/LLVM cpuid.h provides __cpuid_count() since v3.4.0. 6162306a36Sopenharmony_ci * 6262306a36Sopenharmony_ci * Provide local define for tests needing __cpuid_count() because 6362306a36Sopenharmony_ci * selftests need to work in older environments that do not yet 6462306a36Sopenharmony_ci * have __cpuid_count(). 6562306a36Sopenharmony_ci */ 6662306a36Sopenharmony_ci#ifndef __cpuid_count 6762306a36Sopenharmony_ci#define __cpuid_count(level, count, a, b, c, d) \ 6862306a36Sopenharmony_ci __asm__ __volatile__ ("cpuid\n\t" \ 6962306a36Sopenharmony_ci : "=a" (a), "=b" (b), "=c" (c), "=d" (d) \ 7062306a36Sopenharmony_ci : "0" (level), "2" (count)) 7162306a36Sopenharmony_ci#endif 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_ci/* define kselftest exit codes */ 7462306a36Sopenharmony_ci#define KSFT_PASS 0 7562306a36Sopenharmony_ci#define KSFT_FAIL 1 7662306a36Sopenharmony_ci#define KSFT_XFAIL 2 7762306a36Sopenharmony_ci#define KSFT_XPASS 3 7862306a36Sopenharmony_ci#define KSFT_SKIP 4 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_ci/* counters */ 8162306a36Sopenharmony_cistruct ksft_count { 8262306a36Sopenharmony_ci unsigned int ksft_pass; 8362306a36Sopenharmony_ci unsigned int ksft_fail; 8462306a36Sopenharmony_ci unsigned int ksft_xfail; 8562306a36Sopenharmony_ci unsigned int ksft_xpass; 8662306a36Sopenharmony_ci unsigned int ksft_xskip; 8762306a36Sopenharmony_ci unsigned int ksft_error; 8862306a36Sopenharmony_ci}; 8962306a36Sopenharmony_ci 9062306a36Sopenharmony_cistatic struct ksft_count ksft_cnt; 9162306a36Sopenharmony_cistatic unsigned int ksft_plan; 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_cistatic inline unsigned int ksft_test_num(void) 9462306a36Sopenharmony_ci{ 9562306a36Sopenharmony_ci return ksft_cnt.ksft_pass + ksft_cnt.ksft_fail + 9662306a36Sopenharmony_ci ksft_cnt.ksft_xfail + ksft_cnt.ksft_xpass + 9762306a36Sopenharmony_ci ksft_cnt.ksft_xskip + ksft_cnt.ksft_error; 9862306a36Sopenharmony_ci} 9962306a36Sopenharmony_ci 10062306a36Sopenharmony_cistatic inline void ksft_inc_pass_cnt(void) { ksft_cnt.ksft_pass++; } 10162306a36Sopenharmony_cistatic inline void ksft_inc_fail_cnt(void) { ksft_cnt.ksft_fail++; } 10262306a36Sopenharmony_cistatic inline void ksft_inc_xfail_cnt(void) { ksft_cnt.ksft_xfail++; } 10362306a36Sopenharmony_cistatic inline void ksft_inc_xpass_cnt(void) { ksft_cnt.ksft_xpass++; } 10462306a36Sopenharmony_cistatic inline void ksft_inc_xskip_cnt(void) { ksft_cnt.ksft_xskip++; } 10562306a36Sopenharmony_cistatic inline void ksft_inc_error_cnt(void) { ksft_cnt.ksft_error++; } 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_cistatic inline int ksft_get_pass_cnt(void) { return ksft_cnt.ksft_pass; } 10862306a36Sopenharmony_cistatic inline int ksft_get_fail_cnt(void) { return ksft_cnt.ksft_fail; } 10962306a36Sopenharmony_cistatic inline int ksft_get_xfail_cnt(void) { return ksft_cnt.ksft_xfail; } 11062306a36Sopenharmony_cistatic inline int ksft_get_xpass_cnt(void) { return ksft_cnt.ksft_xpass; } 11162306a36Sopenharmony_cistatic inline int ksft_get_xskip_cnt(void) { return ksft_cnt.ksft_xskip; } 11262306a36Sopenharmony_cistatic inline int ksft_get_error_cnt(void) { return ksft_cnt.ksft_error; } 11362306a36Sopenharmony_ci 11462306a36Sopenharmony_cistatic inline void ksft_print_header(void) 11562306a36Sopenharmony_ci{ 11662306a36Sopenharmony_ci /* 11762306a36Sopenharmony_ci * Force line buffering; If stdout is not connected to a terminal, it 11862306a36Sopenharmony_ci * will otherwise default to fully buffered, which can cause output 11962306a36Sopenharmony_ci * duplication if there is content in the buffer when fork()ing. If 12062306a36Sopenharmony_ci * there is a crash, line buffering also means the most recent output 12162306a36Sopenharmony_ci * line will be visible. 12262306a36Sopenharmony_ci */ 12362306a36Sopenharmony_ci setvbuf(stdout, NULL, _IOLBF, 0); 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_ci if (!(getenv("KSFT_TAP_LEVEL"))) 12662306a36Sopenharmony_ci printf("TAP version 13\n"); 12762306a36Sopenharmony_ci} 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_cistatic inline void ksft_set_plan(unsigned int plan) 13062306a36Sopenharmony_ci{ 13162306a36Sopenharmony_ci ksft_plan = plan; 13262306a36Sopenharmony_ci printf("1..%d\n", ksft_plan); 13362306a36Sopenharmony_ci} 13462306a36Sopenharmony_ci 13562306a36Sopenharmony_cistatic inline void ksft_print_cnts(void) 13662306a36Sopenharmony_ci{ 13762306a36Sopenharmony_ci if (ksft_plan != ksft_test_num()) 13862306a36Sopenharmony_ci printf("# Planned tests != run tests (%u != %u)\n", 13962306a36Sopenharmony_ci ksft_plan, ksft_test_num()); 14062306a36Sopenharmony_ci printf("# Totals: pass:%d fail:%d xfail:%d xpass:%d skip:%d error:%d\n", 14162306a36Sopenharmony_ci ksft_cnt.ksft_pass, ksft_cnt.ksft_fail, 14262306a36Sopenharmony_ci ksft_cnt.ksft_xfail, ksft_cnt.ksft_xpass, 14362306a36Sopenharmony_ci ksft_cnt.ksft_xskip, ksft_cnt.ksft_error); 14462306a36Sopenharmony_ci} 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_cistatic inline void ksft_print_msg(const char *msg, ...) 14762306a36Sopenharmony_ci{ 14862306a36Sopenharmony_ci int saved_errno = errno; 14962306a36Sopenharmony_ci va_list args; 15062306a36Sopenharmony_ci 15162306a36Sopenharmony_ci va_start(args, msg); 15262306a36Sopenharmony_ci printf("# "); 15362306a36Sopenharmony_ci errno = saved_errno; 15462306a36Sopenharmony_ci vprintf(msg, args); 15562306a36Sopenharmony_ci va_end(args); 15662306a36Sopenharmony_ci} 15762306a36Sopenharmony_ci 15862306a36Sopenharmony_cistatic inline void ksft_test_result_pass(const char *msg, ...) 15962306a36Sopenharmony_ci{ 16062306a36Sopenharmony_ci int saved_errno = errno; 16162306a36Sopenharmony_ci va_list args; 16262306a36Sopenharmony_ci 16362306a36Sopenharmony_ci ksft_cnt.ksft_pass++; 16462306a36Sopenharmony_ci 16562306a36Sopenharmony_ci va_start(args, msg); 16662306a36Sopenharmony_ci printf("ok %d ", ksft_test_num()); 16762306a36Sopenharmony_ci errno = saved_errno; 16862306a36Sopenharmony_ci vprintf(msg, args); 16962306a36Sopenharmony_ci va_end(args); 17062306a36Sopenharmony_ci} 17162306a36Sopenharmony_ci 17262306a36Sopenharmony_cistatic inline void ksft_test_result_fail(const char *msg, ...) 17362306a36Sopenharmony_ci{ 17462306a36Sopenharmony_ci int saved_errno = errno; 17562306a36Sopenharmony_ci va_list args; 17662306a36Sopenharmony_ci 17762306a36Sopenharmony_ci ksft_cnt.ksft_fail++; 17862306a36Sopenharmony_ci 17962306a36Sopenharmony_ci va_start(args, msg); 18062306a36Sopenharmony_ci printf("not ok %d ", ksft_test_num()); 18162306a36Sopenharmony_ci errno = saved_errno; 18262306a36Sopenharmony_ci vprintf(msg, args); 18362306a36Sopenharmony_ci va_end(args); 18462306a36Sopenharmony_ci} 18562306a36Sopenharmony_ci 18662306a36Sopenharmony_ci/** 18762306a36Sopenharmony_ci * ksft_test_result() - Report test success based on truth of condition 18862306a36Sopenharmony_ci * 18962306a36Sopenharmony_ci * @condition: if true, report test success, otherwise failure. 19062306a36Sopenharmony_ci */ 19162306a36Sopenharmony_ci#define ksft_test_result(condition, fmt, ...) do { \ 19262306a36Sopenharmony_ci if (!!(condition)) \ 19362306a36Sopenharmony_ci ksft_test_result_pass(fmt, ##__VA_ARGS__);\ 19462306a36Sopenharmony_ci else \ 19562306a36Sopenharmony_ci ksft_test_result_fail(fmt, ##__VA_ARGS__);\ 19662306a36Sopenharmony_ci } while (0) 19762306a36Sopenharmony_ci 19862306a36Sopenharmony_cistatic inline void ksft_test_result_xfail(const char *msg, ...) 19962306a36Sopenharmony_ci{ 20062306a36Sopenharmony_ci int saved_errno = errno; 20162306a36Sopenharmony_ci va_list args; 20262306a36Sopenharmony_ci 20362306a36Sopenharmony_ci ksft_cnt.ksft_xfail++; 20462306a36Sopenharmony_ci 20562306a36Sopenharmony_ci va_start(args, msg); 20662306a36Sopenharmony_ci printf("ok %d # XFAIL ", ksft_test_num()); 20762306a36Sopenharmony_ci errno = saved_errno; 20862306a36Sopenharmony_ci vprintf(msg, args); 20962306a36Sopenharmony_ci va_end(args); 21062306a36Sopenharmony_ci} 21162306a36Sopenharmony_ci 21262306a36Sopenharmony_cistatic inline void ksft_test_result_skip(const char *msg, ...) 21362306a36Sopenharmony_ci{ 21462306a36Sopenharmony_ci int saved_errno = errno; 21562306a36Sopenharmony_ci va_list args; 21662306a36Sopenharmony_ci 21762306a36Sopenharmony_ci ksft_cnt.ksft_xskip++; 21862306a36Sopenharmony_ci 21962306a36Sopenharmony_ci va_start(args, msg); 22062306a36Sopenharmony_ci printf("ok %d # SKIP ", ksft_test_num()); 22162306a36Sopenharmony_ci errno = saved_errno; 22262306a36Sopenharmony_ci vprintf(msg, args); 22362306a36Sopenharmony_ci va_end(args); 22462306a36Sopenharmony_ci} 22562306a36Sopenharmony_ci 22662306a36Sopenharmony_ci/* TODO: how does "error" differ from "fail" or "skip"? */ 22762306a36Sopenharmony_cistatic inline void ksft_test_result_error(const char *msg, ...) 22862306a36Sopenharmony_ci{ 22962306a36Sopenharmony_ci int saved_errno = errno; 23062306a36Sopenharmony_ci va_list args; 23162306a36Sopenharmony_ci 23262306a36Sopenharmony_ci ksft_cnt.ksft_error++; 23362306a36Sopenharmony_ci 23462306a36Sopenharmony_ci va_start(args, msg); 23562306a36Sopenharmony_ci printf("not ok %d # error ", ksft_test_num()); 23662306a36Sopenharmony_ci errno = saved_errno; 23762306a36Sopenharmony_ci vprintf(msg, args); 23862306a36Sopenharmony_ci va_end(args); 23962306a36Sopenharmony_ci} 24062306a36Sopenharmony_ci 24162306a36Sopenharmony_cistatic inline int ksft_exit_pass(void) 24262306a36Sopenharmony_ci{ 24362306a36Sopenharmony_ci ksft_print_cnts(); 24462306a36Sopenharmony_ci exit(KSFT_PASS); 24562306a36Sopenharmony_ci} 24662306a36Sopenharmony_ci 24762306a36Sopenharmony_cistatic inline int ksft_exit_fail(void) 24862306a36Sopenharmony_ci{ 24962306a36Sopenharmony_ci ksft_print_cnts(); 25062306a36Sopenharmony_ci exit(KSFT_FAIL); 25162306a36Sopenharmony_ci} 25262306a36Sopenharmony_ci 25362306a36Sopenharmony_ci/** 25462306a36Sopenharmony_ci * ksft_exit() - Exit selftest based on truth of condition 25562306a36Sopenharmony_ci * 25662306a36Sopenharmony_ci * @condition: if true, exit self test with success, otherwise fail. 25762306a36Sopenharmony_ci */ 25862306a36Sopenharmony_ci#define ksft_exit(condition) do { \ 25962306a36Sopenharmony_ci if (!!(condition)) \ 26062306a36Sopenharmony_ci ksft_exit_pass(); \ 26162306a36Sopenharmony_ci else \ 26262306a36Sopenharmony_ci ksft_exit_fail(); \ 26362306a36Sopenharmony_ci } while (0) 26462306a36Sopenharmony_ci 26562306a36Sopenharmony_ci/** 26662306a36Sopenharmony_ci * ksft_finished() - Exit selftest with success if all tests passed 26762306a36Sopenharmony_ci */ 26862306a36Sopenharmony_ci#define ksft_finished() \ 26962306a36Sopenharmony_ci ksft_exit(ksft_plan == \ 27062306a36Sopenharmony_ci ksft_cnt.ksft_pass + \ 27162306a36Sopenharmony_ci ksft_cnt.ksft_xfail + \ 27262306a36Sopenharmony_ci ksft_cnt.ksft_xskip) 27362306a36Sopenharmony_ci 27462306a36Sopenharmony_cistatic inline int ksft_exit_fail_msg(const char *msg, ...) 27562306a36Sopenharmony_ci{ 27662306a36Sopenharmony_ci int saved_errno = errno; 27762306a36Sopenharmony_ci va_list args; 27862306a36Sopenharmony_ci 27962306a36Sopenharmony_ci va_start(args, msg); 28062306a36Sopenharmony_ci printf("Bail out! "); 28162306a36Sopenharmony_ci errno = saved_errno; 28262306a36Sopenharmony_ci vprintf(msg, args); 28362306a36Sopenharmony_ci va_end(args); 28462306a36Sopenharmony_ci 28562306a36Sopenharmony_ci ksft_print_cnts(); 28662306a36Sopenharmony_ci exit(KSFT_FAIL); 28762306a36Sopenharmony_ci} 28862306a36Sopenharmony_ci 28962306a36Sopenharmony_cistatic inline int ksft_exit_xfail(void) 29062306a36Sopenharmony_ci{ 29162306a36Sopenharmony_ci ksft_print_cnts(); 29262306a36Sopenharmony_ci exit(KSFT_XFAIL); 29362306a36Sopenharmony_ci} 29462306a36Sopenharmony_ci 29562306a36Sopenharmony_cistatic inline int ksft_exit_xpass(void) 29662306a36Sopenharmony_ci{ 29762306a36Sopenharmony_ci ksft_print_cnts(); 29862306a36Sopenharmony_ci exit(KSFT_XPASS); 29962306a36Sopenharmony_ci} 30062306a36Sopenharmony_ci 30162306a36Sopenharmony_cistatic inline int ksft_exit_skip(const char *msg, ...) 30262306a36Sopenharmony_ci{ 30362306a36Sopenharmony_ci int saved_errno = errno; 30462306a36Sopenharmony_ci va_list args; 30562306a36Sopenharmony_ci 30662306a36Sopenharmony_ci va_start(args, msg); 30762306a36Sopenharmony_ci 30862306a36Sopenharmony_ci /* 30962306a36Sopenharmony_ci * FIXME: several tests misuse ksft_exit_skip so produce 31062306a36Sopenharmony_ci * something sensible if some tests have already been run 31162306a36Sopenharmony_ci * or a plan has been printed. Those tests should use 31262306a36Sopenharmony_ci * ksft_test_result_skip or ksft_exit_fail_msg instead. 31362306a36Sopenharmony_ci */ 31462306a36Sopenharmony_ci if (ksft_plan || ksft_test_num()) { 31562306a36Sopenharmony_ci ksft_cnt.ksft_xskip++; 31662306a36Sopenharmony_ci printf("ok %d # SKIP ", 1 + ksft_test_num()); 31762306a36Sopenharmony_ci } else { 31862306a36Sopenharmony_ci printf("1..0 # SKIP "); 31962306a36Sopenharmony_ci } 32062306a36Sopenharmony_ci if (msg) { 32162306a36Sopenharmony_ci errno = saved_errno; 32262306a36Sopenharmony_ci vprintf(msg, args); 32362306a36Sopenharmony_ci va_end(args); 32462306a36Sopenharmony_ci } 32562306a36Sopenharmony_ci if (ksft_test_num()) 32662306a36Sopenharmony_ci ksft_print_cnts(); 32762306a36Sopenharmony_ci exit(KSFT_SKIP); 32862306a36Sopenharmony_ci} 32962306a36Sopenharmony_ci 33062306a36Sopenharmony_ci#endif /* __KSELFTEST_H */ 331