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