18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * kselftest.h:	low-level kselftest framework to include from
48c2ecf20Sopenharmony_ci *		selftest programs. When possible, please use
58c2ecf20Sopenharmony_ci *		kselftest_harness.h instead.
68c2ecf20Sopenharmony_ci *
78c2ecf20Sopenharmony_ci * Copyright (c) 2014 Shuah Khan <shuahkh@osg.samsung.com>
88c2ecf20Sopenharmony_ci * Copyright (c) 2014 Samsung Electronics Co., Ltd.
98c2ecf20Sopenharmony_ci *
108c2ecf20Sopenharmony_ci * Using this API consists of first counting how many tests your code
118c2ecf20Sopenharmony_ci * has to run, and then starting up the reporting:
128c2ecf20Sopenharmony_ci *
138c2ecf20Sopenharmony_ci *     ksft_print_header();
148c2ecf20Sopenharmony_ci *     ksft_set_plan(total_number_of_tests);
158c2ecf20Sopenharmony_ci *
168c2ecf20Sopenharmony_ci * For each test, report any progress, debugging, etc with:
178c2ecf20Sopenharmony_ci *
188c2ecf20Sopenharmony_ci *     ksft_print_msg(fmt, ...);
198c2ecf20Sopenharmony_ci *
208c2ecf20Sopenharmony_ci * and finally report the pass/fail/skip/xfail state of the test with one of:
218c2ecf20Sopenharmony_ci *
228c2ecf20Sopenharmony_ci *     ksft_test_result(condition, fmt, ...);
238c2ecf20Sopenharmony_ci *     ksft_test_result_pass(fmt, ...);
248c2ecf20Sopenharmony_ci *     ksft_test_result_fail(fmt, ...);
258c2ecf20Sopenharmony_ci *     ksft_test_result_skip(fmt, ...);
268c2ecf20Sopenharmony_ci *     ksft_test_result_xfail(fmt, ...);
278c2ecf20Sopenharmony_ci *     ksft_test_result_error(fmt, ...);
288c2ecf20Sopenharmony_ci *
298c2ecf20Sopenharmony_ci * When all tests are finished, clean up and exit the program with one of:
308c2ecf20Sopenharmony_ci *
318c2ecf20Sopenharmony_ci *    ksft_exit(condition);
328c2ecf20Sopenharmony_ci *    ksft_exit_pass();
338c2ecf20Sopenharmony_ci *    ksft_exit_fail();
348c2ecf20Sopenharmony_ci *
358c2ecf20Sopenharmony_ci * If the program wants to report details on why the entire program has
368c2ecf20Sopenharmony_ci * failed, it can instead exit with a message (this is usually done when
378c2ecf20Sopenharmony_ci * the program is aborting before finishing all tests):
388c2ecf20Sopenharmony_ci *
398c2ecf20Sopenharmony_ci *    ksft_exit_fail_msg(fmt, ...);
408c2ecf20Sopenharmony_ci *
418c2ecf20Sopenharmony_ci */
428c2ecf20Sopenharmony_ci#ifndef __KSELFTEST_H
438c2ecf20Sopenharmony_ci#define __KSELFTEST_H
448c2ecf20Sopenharmony_ci
458c2ecf20Sopenharmony_ci#include <errno.h>
468c2ecf20Sopenharmony_ci#include <stdlib.h>
478c2ecf20Sopenharmony_ci#include <unistd.h>
488c2ecf20Sopenharmony_ci#include <stdarg.h>
498c2ecf20Sopenharmony_ci#include <stdio.h>
508c2ecf20Sopenharmony_ci
518c2ecf20Sopenharmony_ci/* define kselftest exit codes */
528c2ecf20Sopenharmony_ci#define KSFT_PASS  0
538c2ecf20Sopenharmony_ci#define KSFT_FAIL  1
548c2ecf20Sopenharmony_ci#define KSFT_XFAIL 2
558c2ecf20Sopenharmony_ci#define KSFT_XPASS 3
568c2ecf20Sopenharmony_ci#define KSFT_SKIP  4
578c2ecf20Sopenharmony_ci
588c2ecf20Sopenharmony_ci/* counters */
598c2ecf20Sopenharmony_cistruct ksft_count {
608c2ecf20Sopenharmony_ci	unsigned int ksft_pass;
618c2ecf20Sopenharmony_ci	unsigned int ksft_fail;
628c2ecf20Sopenharmony_ci	unsigned int ksft_xfail;
638c2ecf20Sopenharmony_ci	unsigned int ksft_xpass;
648c2ecf20Sopenharmony_ci	unsigned int ksft_xskip;
658c2ecf20Sopenharmony_ci	unsigned int ksft_error;
668c2ecf20Sopenharmony_ci};
678c2ecf20Sopenharmony_ci
688c2ecf20Sopenharmony_cistatic struct ksft_count ksft_cnt;
698c2ecf20Sopenharmony_cistatic unsigned int ksft_plan;
708c2ecf20Sopenharmony_ci
718c2ecf20Sopenharmony_cistatic inline unsigned int ksft_test_num(void)
728c2ecf20Sopenharmony_ci{
738c2ecf20Sopenharmony_ci	return ksft_cnt.ksft_pass + ksft_cnt.ksft_fail +
748c2ecf20Sopenharmony_ci		ksft_cnt.ksft_xfail + ksft_cnt.ksft_xpass +
758c2ecf20Sopenharmony_ci		ksft_cnt.ksft_xskip + ksft_cnt.ksft_error;
768c2ecf20Sopenharmony_ci}
778c2ecf20Sopenharmony_ci
788c2ecf20Sopenharmony_cistatic inline void ksft_inc_pass_cnt(void) { ksft_cnt.ksft_pass++; }
798c2ecf20Sopenharmony_cistatic inline void ksft_inc_fail_cnt(void) { ksft_cnt.ksft_fail++; }
808c2ecf20Sopenharmony_cistatic inline void ksft_inc_xfail_cnt(void) { ksft_cnt.ksft_xfail++; }
818c2ecf20Sopenharmony_cistatic inline void ksft_inc_xpass_cnt(void) { ksft_cnt.ksft_xpass++; }
828c2ecf20Sopenharmony_cistatic inline void ksft_inc_xskip_cnt(void) { ksft_cnt.ksft_xskip++; }
838c2ecf20Sopenharmony_cistatic inline void ksft_inc_error_cnt(void) { ksft_cnt.ksft_error++; }
848c2ecf20Sopenharmony_ci
858c2ecf20Sopenharmony_cistatic inline int ksft_get_pass_cnt(void) { return ksft_cnt.ksft_pass; }
868c2ecf20Sopenharmony_cistatic inline int ksft_get_fail_cnt(void) { return ksft_cnt.ksft_fail; }
878c2ecf20Sopenharmony_cistatic inline int ksft_get_xfail_cnt(void) { return ksft_cnt.ksft_xfail; }
888c2ecf20Sopenharmony_cistatic inline int ksft_get_xpass_cnt(void) { return ksft_cnt.ksft_xpass; }
898c2ecf20Sopenharmony_cistatic inline int ksft_get_xskip_cnt(void) { return ksft_cnt.ksft_xskip; }
908c2ecf20Sopenharmony_cistatic inline int ksft_get_error_cnt(void) { return ksft_cnt.ksft_error; }
918c2ecf20Sopenharmony_ci
928c2ecf20Sopenharmony_cistatic inline void ksft_print_header(void)
938c2ecf20Sopenharmony_ci{
948c2ecf20Sopenharmony_ci	if (!(getenv("KSFT_TAP_LEVEL")))
958c2ecf20Sopenharmony_ci		printf("TAP version 13\n");
968c2ecf20Sopenharmony_ci}
978c2ecf20Sopenharmony_ci
988c2ecf20Sopenharmony_cistatic inline void ksft_set_plan(unsigned int plan)
998c2ecf20Sopenharmony_ci{
1008c2ecf20Sopenharmony_ci	ksft_plan = plan;
1018c2ecf20Sopenharmony_ci	printf("1..%d\n", ksft_plan);
1028c2ecf20Sopenharmony_ci}
1038c2ecf20Sopenharmony_ci
1048c2ecf20Sopenharmony_cistatic inline void ksft_print_cnts(void)
1058c2ecf20Sopenharmony_ci{
1068c2ecf20Sopenharmony_ci	if (ksft_plan != ksft_test_num())
1078c2ecf20Sopenharmony_ci		printf("# Planned tests != run tests (%u != %u)\n",
1088c2ecf20Sopenharmony_ci			ksft_plan, ksft_test_num());
1098c2ecf20Sopenharmony_ci	printf("# Totals: pass:%d fail:%d xfail:%d xpass:%d skip:%d error:%d\n",
1108c2ecf20Sopenharmony_ci		ksft_cnt.ksft_pass, ksft_cnt.ksft_fail,
1118c2ecf20Sopenharmony_ci		ksft_cnt.ksft_xfail, ksft_cnt.ksft_xpass,
1128c2ecf20Sopenharmony_ci		ksft_cnt.ksft_xskip, ksft_cnt.ksft_error);
1138c2ecf20Sopenharmony_ci}
1148c2ecf20Sopenharmony_ci
1158c2ecf20Sopenharmony_cistatic inline void ksft_print_msg(const char *msg, ...)
1168c2ecf20Sopenharmony_ci{
1178c2ecf20Sopenharmony_ci	int saved_errno = errno;
1188c2ecf20Sopenharmony_ci	va_list args;
1198c2ecf20Sopenharmony_ci
1208c2ecf20Sopenharmony_ci	va_start(args, msg);
1218c2ecf20Sopenharmony_ci	printf("# ");
1228c2ecf20Sopenharmony_ci	errno = saved_errno;
1238c2ecf20Sopenharmony_ci	vprintf(msg, args);
1248c2ecf20Sopenharmony_ci	va_end(args);
1258c2ecf20Sopenharmony_ci}
1268c2ecf20Sopenharmony_ci
1278c2ecf20Sopenharmony_cistatic inline void ksft_test_result_pass(const char *msg, ...)
1288c2ecf20Sopenharmony_ci{
1298c2ecf20Sopenharmony_ci	int saved_errno = errno;
1308c2ecf20Sopenharmony_ci	va_list args;
1318c2ecf20Sopenharmony_ci
1328c2ecf20Sopenharmony_ci	ksft_cnt.ksft_pass++;
1338c2ecf20Sopenharmony_ci
1348c2ecf20Sopenharmony_ci	va_start(args, msg);
1358c2ecf20Sopenharmony_ci	printf("ok %d ", ksft_test_num());
1368c2ecf20Sopenharmony_ci	errno = saved_errno;
1378c2ecf20Sopenharmony_ci	vprintf(msg, args);
1388c2ecf20Sopenharmony_ci	va_end(args);
1398c2ecf20Sopenharmony_ci}
1408c2ecf20Sopenharmony_ci
1418c2ecf20Sopenharmony_cistatic inline void ksft_test_result_fail(const char *msg, ...)
1428c2ecf20Sopenharmony_ci{
1438c2ecf20Sopenharmony_ci	int saved_errno = errno;
1448c2ecf20Sopenharmony_ci	va_list args;
1458c2ecf20Sopenharmony_ci
1468c2ecf20Sopenharmony_ci	ksft_cnt.ksft_fail++;
1478c2ecf20Sopenharmony_ci
1488c2ecf20Sopenharmony_ci	va_start(args, msg);
1498c2ecf20Sopenharmony_ci	printf("not ok %d ", ksft_test_num());
1508c2ecf20Sopenharmony_ci	errno = saved_errno;
1518c2ecf20Sopenharmony_ci	vprintf(msg, args);
1528c2ecf20Sopenharmony_ci	va_end(args);
1538c2ecf20Sopenharmony_ci}
1548c2ecf20Sopenharmony_ci
1558c2ecf20Sopenharmony_ci/**
1568c2ecf20Sopenharmony_ci * ksft_test_result() - Report test success based on truth of condition
1578c2ecf20Sopenharmony_ci *
1588c2ecf20Sopenharmony_ci * @condition: if true, report test success, otherwise failure.
1598c2ecf20Sopenharmony_ci */
1608c2ecf20Sopenharmony_ci#define ksft_test_result(condition, fmt, ...) do {	\
1618c2ecf20Sopenharmony_ci	if (!!(condition))				\
1628c2ecf20Sopenharmony_ci		ksft_test_result_pass(fmt, ##__VA_ARGS__);\
1638c2ecf20Sopenharmony_ci	else						\
1648c2ecf20Sopenharmony_ci		ksft_test_result_fail(fmt, ##__VA_ARGS__);\
1658c2ecf20Sopenharmony_ci	} while (0)
1668c2ecf20Sopenharmony_ci
1678c2ecf20Sopenharmony_cistatic inline void ksft_test_result_xfail(const char *msg, ...)
1688c2ecf20Sopenharmony_ci{
1698c2ecf20Sopenharmony_ci	int saved_errno = errno;
1708c2ecf20Sopenharmony_ci	va_list args;
1718c2ecf20Sopenharmony_ci
1728c2ecf20Sopenharmony_ci	ksft_cnt.ksft_xfail++;
1738c2ecf20Sopenharmony_ci
1748c2ecf20Sopenharmony_ci	va_start(args, msg);
1758c2ecf20Sopenharmony_ci	printf("ok %d # XFAIL ", ksft_test_num());
1768c2ecf20Sopenharmony_ci	errno = saved_errno;
1778c2ecf20Sopenharmony_ci	vprintf(msg, args);
1788c2ecf20Sopenharmony_ci	va_end(args);
1798c2ecf20Sopenharmony_ci}
1808c2ecf20Sopenharmony_ci
1818c2ecf20Sopenharmony_cistatic inline void ksft_test_result_skip(const char *msg, ...)
1828c2ecf20Sopenharmony_ci{
1838c2ecf20Sopenharmony_ci	int saved_errno = errno;
1848c2ecf20Sopenharmony_ci	va_list args;
1858c2ecf20Sopenharmony_ci
1868c2ecf20Sopenharmony_ci	ksft_cnt.ksft_xskip++;
1878c2ecf20Sopenharmony_ci
1888c2ecf20Sopenharmony_ci	va_start(args, msg);
1898c2ecf20Sopenharmony_ci	printf("ok %d # SKIP ", ksft_test_num());
1908c2ecf20Sopenharmony_ci	errno = saved_errno;
1918c2ecf20Sopenharmony_ci	vprintf(msg, args);
1928c2ecf20Sopenharmony_ci	va_end(args);
1938c2ecf20Sopenharmony_ci}
1948c2ecf20Sopenharmony_ci
1958c2ecf20Sopenharmony_ci/* TODO: how does "error" differ from "fail" or "skip"? */
1968c2ecf20Sopenharmony_cistatic inline void ksft_test_result_error(const char *msg, ...)
1978c2ecf20Sopenharmony_ci{
1988c2ecf20Sopenharmony_ci	int saved_errno = errno;
1998c2ecf20Sopenharmony_ci	va_list args;
2008c2ecf20Sopenharmony_ci
2018c2ecf20Sopenharmony_ci	ksft_cnt.ksft_error++;
2028c2ecf20Sopenharmony_ci
2038c2ecf20Sopenharmony_ci	va_start(args, msg);
2048c2ecf20Sopenharmony_ci	printf("not ok %d # error ", ksft_test_num());
2058c2ecf20Sopenharmony_ci	errno = saved_errno;
2068c2ecf20Sopenharmony_ci	vprintf(msg, args);
2078c2ecf20Sopenharmony_ci	va_end(args);
2088c2ecf20Sopenharmony_ci}
2098c2ecf20Sopenharmony_ci
2108c2ecf20Sopenharmony_cistatic inline int ksft_exit_pass(void)
2118c2ecf20Sopenharmony_ci{
2128c2ecf20Sopenharmony_ci	ksft_print_cnts();
2138c2ecf20Sopenharmony_ci	exit(KSFT_PASS);
2148c2ecf20Sopenharmony_ci}
2158c2ecf20Sopenharmony_ci
2168c2ecf20Sopenharmony_cistatic inline int ksft_exit_fail(void)
2178c2ecf20Sopenharmony_ci{
2188c2ecf20Sopenharmony_ci	ksft_print_cnts();
2198c2ecf20Sopenharmony_ci	exit(KSFT_FAIL);
2208c2ecf20Sopenharmony_ci}
2218c2ecf20Sopenharmony_ci
2228c2ecf20Sopenharmony_ci/**
2238c2ecf20Sopenharmony_ci * ksft_exit() - Exit selftest based on truth of condition
2248c2ecf20Sopenharmony_ci *
2258c2ecf20Sopenharmony_ci * @condition: if true, exit self test with success, otherwise fail.
2268c2ecf20Sopenharmony_ci */
2278c2ecf20Sopenharmony_ci#define ksft_exit(condition) do {	\
2288c2ecf20Sopenharmony_ci	if (!!(condition))		\
2298c2ecf20Sopenharmony_ci		ksft_exit_pass();	\
2308c2ecf20Sopenharmony_ci	else				\
2318c2ecf20Sopenharmony_ci		ksft_exit_fail();	\
2328c2ecf20Sopenharmony_ci	} while (0)
2338c2ecf20Sopenharmony_ci
2348c2ecf20Sopenharmony_cistatic inline int ksft_exit_fail_msg(const char *msg, ...)
2358c2ecf20Sopenharmony_ci{
2368c2ecf20Sopenharmony_ci	int saved_errno = errno;
2378c2ecf20Sopenharmony_ci	va_list args;
2388c2ecf20Sopenharmony_ci
2398c2ecf20Sopenharmony_ci	va_start(args, msg);
2408c2ecf20Sopenharmony_ci	printf("Bail out! ");
2418c2ecf20Sopenharmony_ci	errno = saved_errno;
2428c2ecf20Sopenharmony_ci	vprintf(msg, args);
2438c2ecf20Sopenharmony_ci	va_end(args);
2448c2ecf20Sopenharmony_ci
2458c2ecf20Sopenharmony_ci	ksft_print_cnts();
2468c2ecf20Sopenharmony_ci	exit(KSFT_FAIL);
2478c2ecf20Sopenharmony_ci}
2488c2ecf20Sopenharmony_ci
2498c2ecf20Sopenharmony_cistatic inline int ksft_exit_xfail(void)
2508c2ecf20Sopenharmony_ci{
2518c2ecf20Sopenharmony_ci	ksft_print_cnts();
2528c2ecf20Sopenharmony_ci	exit(KSFT_XFAIL);
2538c2ecf20Sopenharmony_ci}
2548c2ecf20Sopenharmony_ci
2558c2ecf20Sopenharmony_cistatic inline int ksft_exit_xpass(void)
2568c2ecf20Sopenharmony_ci{
2578c2ecf20Sopenharmony_ci	ksft_print_cnts();
2588c2ecf20Sopenharmony_ci	exit(KSFT_XPASS);
2598c2ecf20Sopenharmony_ci}
2608c2ecf20Sopenharmony_ci
2618c2ecf20Sopenharmony_cistatic inline int ksft_exit_skip(const char *msg, ...)
2628c2ecf20Sopenharmony_ci{
2638c2ecf20Sopenharmony_ci	int saved_errno = errno;
2648c2ecf20Sopenharmony_ci	va_list args;
2658c2ecf20Sopenharmony_ci
2668c2ecf20Sopenharmony_ci	va_start(args, msg);
2678c2ecf20Sopenharmony_ci
2688c2ecf20Sopenharmony_ci	/*
2698c2ecf20Sopenharmony_ci	 * FIXME: several tests misuse ksft_exit_skip so produce
2708c2ecf20Sopenharmony_ci	 * something sensible if some tests have already been run
2718c2ecf20Sopenharmony_ci	 * or a plan has been printed.  Those tests should use
2728c2ecf20Sopenharmony_ci	 * ksft_test_result_skip or ksft_exit_fail_msg instead.
2738c2ecf20Sopenharmony_ci	 */
2748c2ecf20Sopenharmony_ci	if (ksft_plan || ksft_test_num()) {
2758c2ecf20Sopenharmony_ci		ksft_cnt.ksft_xskip++;
2768c2ecf20Sopenharmony_ci		printf("ok %d # SKIP ", 1 + ksft_test_num());
2778c2ecf20Sopenharmony_ci	} else {
2788c2ecf20Sopenharmony_ci		printf("1..0 # SKIP ");
2798c2ecf20Sopenharmony_ci	}
2808c2ecf20Sopenharmony_ci	if (msg) {
2818c2ecf20Sopenharmony_ci		errno = saved_errno;
2828c2ecf20Sopenharmony_ci		vprintf(msg, args);
2838c2ecf20Sopenharmony_ci		va_end(args);
2848c2ecf20Sopenharmony_ci	}
2858c2ecf20Sopenharmony_ci	if (ksft_test_num())
2868c2ecf20Sopenharmony_ci		ksft_print_cnts();
2878c2ecf20Sopenharmony_ci	exit(KSFT_SKIP);
2888c2ecf20Sopenharmony_ci}
2898c2ecf20Sopenharmony_ci
2908c2ecf20Sopenharmony_ci#endif /* __KSELFTEST_H */
291