18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * kselftest_harness.h: simple C unit test helper.
68c2ecf20Sopenharmony_ci *
78c2ecf20Sopenharmony_ci * See documentation in Documentation/dev-tools/kselftest.rst
88c2ecf20Sopenharmony_ci *
98c2ecf20Sopenharmony_ci * API inspired by code.google.com/p/googletest
108c2ecf20Sopenharmony_ci */
118c2ecf20Sopenharmony_ci
128c2ecf20Sopenharmony_ci/**
138c2ecf20Sopenharmony_ci * DOC: example
148c2ecf20Sopenharmony_ci *
158c2ecf20Sopenharmony_ci * .. code-block:: c
168c2ecf20Sopenharmony_ci *
178c2ecf20Sopenharmony_ci *    #include "../kselftest_harness.h"
188c2ecf20Sopenharmony_ci *
198c2ecf20Sopenharmony_ci *    TEST(standalone_test) {
208c2ecf20Sopenharmony_ci *      do_some_stuff;
218c2ecf20Sopenharmony_ci *      EXPECT_GT(10, stuff) {
228c2ecf20Sopenharmony_ci *         stuff_state_t state;
238c2ecf20Sopenharmony_ci *         enumerate_stuff_state(&state);
248c2ecf20Sopenharmony_ci *         TH_LOG("expectation failed with state: %s", state.msg);
258c2ecf20Sopenharmony_ci *      }
268c2ecf20Sopenharmony_ci *      more_stuff;
278c2ecf20Sopenharmony_ci *      ASSERT_NE(some_stuff, NULL) TH_LOG("how did it happen?!");
288c2ecf20Sopenharmony_ci *      last_stuff;
298c2ecf20Sopenharmony_ci *      EXPECT_EQ(0, last_stuff);
308c2ecf20Sopenharmony_ci *    }
318c2ecf20Sopenharmony_ci *
328c2ecf20Sopenharmony_ci *    FIXTURE(my_fixture) {
338c2ecf20Sopenharmony_ci *      mytype_t *data;
348c2ecf20Sopenharmony_ci *      int awesomeness_level;
358c2ecf20Sopenharmony_ci *    };
368c2ecf20Sopenharmony_ci *    FIXTURE_SETUP(my_fixture) {
378c2ecf20Sopenharmony_ci *      self->data = mytype_new();
388c2ecf20Sopenharmony_ci *      ASSERT_NE(NULL, self->data);
398c2ecf20Sopenharmony_ci *    }
408c2ecf20Sopenharmony_ci *    FIXTURE_TEARDOWN(my_fixture) {
418c2ecf20Sopenharmony_ci *      mytype_free(self->data);
428c2ecf20Sopenharmony_ci *    }
438c2ecf20Sopenharmony_ci *    TEST_F(my_fixture, data_is_good) {
448c2ecf20Sopenharmony_ci *      EXPECT_EQ(1, is_my_data_good(self->data));
458c2ecf20Sopenharmony_ci *    }
468c2ecf20Sopenharmony_ci *
478c2ecf20Sopenharmony_ci *    TEST_HARNESS_MAIN
488c2ecf20Sopenharmony_ci */
498c2ecf20Sopenharmony_ci
508c2ecf20Sopenharmony_ci#ifndef __KSELFTEST_HARNESS_H
518c2ecf20Sopenharmony_ci#define __KSELFTEST_HARNESS_H
528c2ecf20Sopenharmony_ci
538c2ecf20Sopenharmony_ci#ifndef _GNU_SOURCE
548c2ecf20Sopenharmony_ci#define _GNU_SOURCE
558c2ecf20Sopenharmony_ci#endif
568c2ecf20Sopenharmony_ci#include <asm/types.h>
578c2ecf20Sopenharmony_ci#include <errno.h>
588c2ecf20Sopenharmony_ci#include <stdbool.h>
598c2ecf20Sopenharmony_ci#include <stdint.h>
608c2ecf20Sopenharmony_ci#include <stdio.h>
618c2ecf20Sopenharmony_ci#include <stdlib.h>
628c2ecf20Sopenharmony_ci#include <string.h>
638c2ecf20Sopenharmony_ci#include <sys/mman.h>
648c2ecf20Sopenharmony_ci#include <sys/types.h>
658c2ecf20Sopenharmony_ci#include <sys/wait.h>
668c2ecf20Sopenharmony_ci#include <unistd.h>
678c2ecf20Sopenharmony_ci
688c2ecf20Sopenharmony_ci#include "kselftest.h"
698c2ecf20Sopenharmony_ci
708c2ecf20Sopenharmony_ci#define TEST_TIMEOUT_DEFAULT 30
718c2ecf20Sopenharmony_ci
728c2ecf20Sopenharmony_ci/* Utilities exposed to the test definitions */
738c2ecf20Sopenharmony_ci#ifndef TH_LOG_STREAM
748c2ecf20Sopenharmony_ci#  define TH_LOG_STREAM stderr
758c2ecf20Sopenharmony_ci#endif
768c2ecf20Sopenharmony_ci
778c2ecf20Sopenharmony_ci#ifndef TH_LOG_ENABLED
788c2ecf20Sopenharmony_ci#  define TH_LOG_ENABLED 1
798c2ecf20Sopenharmony_ci#endif
808c2ecf20Sopenharmony_ci
818c2ecf20Sopenharmony_ci/**
828c2ecf20Sopenharmony_ci * TH_LOG(fmt, ...)
838c2ecf20Sopenharmony_ci *
848c2ecf20Sopenharmony_ci * @fmt: format string
858c2ecf20Sopenharmony_ci * @...: optional arguments
868c2ecf20Sopenharmony_ci *
878c2ecf20Sopenharmony_ci * .. code-block:: c
888c2ecf20Sopenharmony_ci *
898c2ecf20Sopenharmony_ci *     TH_LOG(format, ...)
908c2ecf20Sopenharmony_ci *
918c2ecf20Sopenharmony_ci * Optional debug logging function available for use in tests.
928c2ecf20Sopenharmony_ci * Logging may be enabled or disabled by defining TH_LOG_ENABLED.
938c2ecf20Sopenharmony_ci * E.g., #define TH_LOG_ENABLED 1
948c2ecf20Sopenharmony_ci *
958c2ecf20Sopenharmony_ci * If no definition is provided, logging is enabled by default.
968c2ecf20Sopenharmony_ci *
978c2ecf20Sopenharmony_ci * If there is no way to print an error message for the process running the
988c2ecf20Sopenharmony_ci * test (e.g. not allowed to write to stderr), it is still possible to get the
998c2ecf20Sopenharmony_ci * ASSERT_* number for which the test failed.  This behavior can be enabled by
1008c2ecf20Sopenharmony_ci * writing `_metadata->no_print = true;` before the check sequence that is
1018c2ecf20Sopenharmony_ci * unable to print.  When an error occur, instead of printing an error message
1028c2ecf20Sopenharmony_ci * and calling `abort(3)`, the test process call `_exit(2)` with the assert
1038c2ecf20Sopenharmony_ci * number as argument, which is then printed by the parent process.
1048c2ecf20Sopenharmony_ci */
1058c2ecf20Sopenharmony_ci#define TH_LOG(fmt, ...) do { \
1068c2ecf20Sopenharmony_ci	if (TH_LOG_ENABLED) \
1078c2ecf20Sopenharmony_ci		__TH_LOG(fmt, ##__VA_ARGS__); \
1088c2ecf20Sopenharmony_ci} while (0)
1098c2ecf20Sopenharmony_ci
1108c2ecf20Sopenharmony_ci/* Unconditional logger for internal use. */
1118c2ecf20Sopenharmony_ci#define __TH_LOG(fmt, ...) \
1128c2ecf20Sopenharmony_ci		fprintf(TH_LOG_STREAM, "# %s:%d:%s:" fmt "\n", \
1138c2ecf20Sopenharmony_ci			__FILE__, __LINE__, _metadata->name, ##__VA_ARGS__)
1148c2ecf20Sopenharmony_ci
1158c2ecf20Sopenharmony_ci/**
1168c2ecf20Sopenharmony_ci * SKIP(statement, fmt, ...)
1178c2ecf20Sopenharmony_ci *
1188c2ecf20Sopenharmony_ci * @statement: statement to run after reporting SKIP
1198c2ecf20Sopenharmony_ci * @fmt: format string
1208c2ecf20Sopenharmony_ci * @...: optional arguments
1218c2ecf20Sopenharmony_ci *
1228c2ecf20Sopenharmony_ci * This forces a "pass" after reporting why something is being skipped
1238c2ecf20Sopenharmony_ci * and runs "statement", which is usually "return" or "goto skip".
1248c2ecf20Sopenharmony_ci */
1258c2ecf20Sopenharmony_ci#define SKIP(statement, fmt, ...) do { \
1268c2ecf20Sopenharmony_ci	snprintf(_metadata->results->reason, \
1278c2ecf20Sopenharmony_ci		 sizeof(_metadata->results->reason), fmt, ##__VA_ARGS__); \
1288c2ecf20Sopenharmony_ci	if (TH_LOG_ENABLED) { \
1298c2ecf20Sopenharmony_ci		fprintf(TH_LOG_STREAM, "#      SKIP      %s\n", \
1308c2ecf20Sopenharmony_ci			_metadata->results->reason); \
1318c2ecf20Sopenharmony_ci	} \
1328c2ecf20Sopenharmony_ci	_metadata->passed = 1; \
1338c2ecf20Sopenharmony_ci	_metadata->skip = 1; \
1348c2ecf20Sopenharmony_ci	_metadata->trigger = 0; \
1358c2ecf20Sopenharmony_ci	statement; \
1368c2ecf20Sopenharmony_ci} while (0)
1378c2ecf20Sopenharmony_ci
1388c2ecf20Sopenharmony_ci/**
1398c2ecf20Sopenharmony_ci * TEST(test_name) - Defines the test function and creates the registration
1408c2ecf20Sopenharmony_ci * stub
1418c2ecf20Sopenharmony_ci *
1428c2ecf20Sopenharmony_ci * @test_name: test name
1438c2ecf20Sopenharmony_ci *
1448c2ecf20Sopenharmony_ci * .. code-block:: c
1458c2ecf20Sopenharmony_ci *
1468c2ecf20Sopenharmony_ci *     TEST(name) { implementation }
1478c2ecf20Sopenharmony_ci *
1488c2ecf20Sopenharmony_ci * Defines a test by name.
1498c2ecf20Sopenharmony_ci * Names must be unique and tests must not be run in parallel.  The
1508c2ecf20Sopenharmony_ci * implementation containing block is a function and scoping should be treated
1518c2ecf20Sopenharmony_ci * as such.  Returning early may be performed with a bare "return;" statement.
1528c2ecf20Sopenharmony_ci *
1538c2ecf20Sopenharmony_ci * EXPECT_* and ASSERT_* are valid in a TEST() { } context.
1548c2ecf20Sopenharmony_ci */
1558c2ecf20Sopenharmony_ci#define TEST(test_name) __TEST_IMPL(test_name, -1)
1568c2ecf20Sopenharmony_ci
1578c2ecf20Sopenharmony_ci/**
1588c2ecf20Sopenharmony_ci * TEST_SIGNAL(test_name, signal)
1598c2ecf20Sopenharmony_ci *
1608c2ecf20Sopenharmony_ci * @test_name: test name
1618c2ecf20Sopenharmony_ci * @signal: signal number
1628c2ecf20Sopenharmony_ci *
1638c2ecf20Sopenharmony_ci * .. code-block:: c
1648c2ecf20Sopenharmony_ci *
1658c2ecf20Sopenharmony_ci *     TEST_SIGNAL(name, signal) { implementation }
1668c2ecf20Sopenharmony_ci *
1678c2ecf20Sopenharmony_ci * Defines a test by name and the expected term signal.
1688c2ecf20Sopenharmony_ci * Names must be unique and tests must not be run in parallel.  The
1698c2ecf20Sopenharmony_ci * implementation containing block is a function and scoping should be treated
1708c2ecf20Sopenharmony_ci * as such.  Returning early may be performed with a bare "return;" statement.
1718c2ecf20Sopenharmony_ci *
1728c2ecf20Sopenharmony_ci * EXPECT_* and ASSERT_* are valid in a TEST() { } context.
1738c2ecf20Sopenharmony_ci */
1748c2ecf20Sopenharmony_ci#define TEST_SIGNAL(test_name, signal) __TEST_IMPL(test_name, signal)
1758c2ecf20Sopenharmony_ci
1768c2ecf20Sopenharmony_ci#define __TEST_IMPL(test_name, _signal) \
1778c2ecf20Sopenharmony_ci	static void test_name(struct __test_metadata *_metadata); \
1788c2ecf20Sopenharmony_ci	static inline void wrapper_##test_name( \
1798c2ecf20Sopenharmony_ci		struct __test_metadata *_metadata, \
1808c2ecf20Sopenharmony_ci		struct __fixture_variant_metadata *variant) \
1818c2ecf20Sopenharmony_ci	{ \
1828c2ecf20Sopenharmony_ci		test_name(_metadata); \
1838c2ecf20Sopenharmony_ci	} \
1848c2ecf20Sopenharmony_ci	static struct __test_metadata _##test_name##_object = \
1858c2ecf20Sopenharmony_ci		{ .name = #test_name, \
1868c2ecf20Sopenharmony_ci		  .fn = &wrapper_##test_name, \
1878c2ecf20Sopenharmony_ci		  .fixture = &_fixture_global, \
1888c2ecf20Sopenharmony_ci		  .termsig = _signal, \
1898c2ecf20Sopenharmony_ci		  .timeout = TEST_TIMEOUT_DEFAULT, }; \
1908c2ecf20Sopenharmony_ci	static void __attribute__((constructor)) _register_##test_name(void) \
1918c2ecf20Sopenharmony_ci	{ \
1928c2ecf20Sopenharmony_ci		__register_test(&_##test_name##_object); \
1938c2ecf20Sopenharmony_ci	} \
1948c2ecf20Sopenharmony_ci	static void test_name( \
1958c2ecf20Sopenharmony_ci		struct __test_metadata __attribute__((unused)) *_metadata)
1968c2ecf20Sopenharmony_ci
1978c2ecf20Sopenharmony_ci/**
1988c2ecf20Sopenharmony_ci * FIXTURE_DATA(datatype_name) - Wraps the struct name so we have one less
1998c2ecf20Sopenharmony_ci * argument to pass around
2008c2ecf20Sopenharmony_ci *
2018c2ecf20Sopenharmony_ci * @datatype_name: datatype name
2028c2ecf20Sopenharmony_ci *
2038c2ecf20Sopenharmony_ci * .. code-block:: c
2048c2ecf20Sopenharmony_ci *
2058c2ecf20Sopenharmony_ci *     FIXTURE_DATA(datatype_name)
2068c2ecf20Sopenharmony_ci *
2078c2ecf20Sopenharmony_ci * Almost always, you want just FIXTURE() instead (see below).
2088c2ecf20Sopenharmony_ci * This call may be used when the type of the fixture data
2098c2ecf20Sopenharmony_ci * is needed.  In general, this should not be needed unless
2108c2ecf20Sopenharmony_ci * the *self* is being passed to a helper directly.
2118c2ecf20Sopenharmony_ci */
2128c2ecf20Sopenharmony_ci#define FIXTURE_DATA(datatype_name) struct _test_data_##datatype_name
2138c2ecf20Sopenharmony_ci
2148c2ecf20Sopenharmony_ci/**
2158c2ecf20Sopenharmony_ci * FIXTURE(fixture_name) - Called once per fixture to setup the data and
2168c2ecf20Sopenharmony_ci * register
2178c2ecf20Sopenharmony_ci *
2188c2ecf20Sopenharmony_ci * @fixture_name: fixture name
2198c2ecf20Sopenharmony_ci *
2208c2ecf20Sopenharmony_ci * .. code-block:: c
2218c2ecf20Sopenharmony_ci *
2228c2ecf20Sopenharmony_ci *     FIXTURE(fixture_name) {
2238c2ecf20Sopenharmony_ci *       type property1;
2248c2ecf20Sopenharmony_ci *       ...
2258c2ecf20Sopenharmony_ci *     };
2268c2ecf20Sopenharmony_ci *
2278c2ecf20Sopenharmony_ci * Defines the data provided to TEST_F()-defined tests as *self*.  It should be
2288c2ecf20Sopenharmony_ci * populated and cleaned up using FIXTURE_SETUP() and FIXTURE_TEARDOWN().
2298c2ecf20Sopenharmony_ci */
2308c2ecf20Sopenharmony_ci#define FIXTURE(fixture_name) \
2318c2ecf20Sopenharmony_ci	FIXTURE_VARIANT(fixture_name); \
2328c2ecf20Sopenharmony_ci	static struct __fixture_metadata _##fixture_name##_fixture_object = \
2338c2ecf20Sopenharmony_ci		{ .name =  #fixture_name, }; \
2348c2ecf20Sopenharmony_ci	static void __attribute__((constructor)) \
2358c2ecf20Sopenharmony_ci	_register_##fixture_name##_data(void) \
2368c2ecf20Sopenharmony_ci	{ \
2378c2ecf20Sopenharmony_ci		__register_fixture(&_##fixture_name##_fixture_object); \
2388c2ecf20Sopenharmony_ci	} \
2398c2ecf20Sopenharmony_ci	FIXTURE_DATA(fixture_name)
2408c2ecf20Sopenharmony_ci
2418c2ecf20Sopenharmony_ci/**
2428c2ecf20Sopenharmony_ci * FIXTURE_SETUP(fixture_name) - Prepares the setup function for the fixture.
2438c2ecf20Sopenharmony_ci * *_metadata* is included so that EXPECT_* and ASSERT_* work correctly.
2448c2ecf20Sopenharmony_ci *
2458c2ecf20Sopenharmony_ci * @fixture_name: fixture name
2468c2ecf20Sopenharmony_ci *
2478c2ecf20Sopenharmony_ci * .. code-block:: c
2488c2ecf20Sopenharmony_ci *
2498c2ecf20Sopenharmony_ci *     FIXTURE_SETUP(fixture_name) { implementation }
2508c2ecf20Sopenharmony_ci *
2518c2ecf20Sopenharmony_ci * Populates the required "setup" function for a fixture.  An instance of the
2528c2ecf20Sopenharmony_ci * datatype defined with FIXTURE_DATA() will be exposed as *self* for the
2538c2ecf20Sopenharmony_ci * implementation.
2548c2ecf20Sopenharmony_ci *
2558c2ecf20Sopenharmony_ci * ASSERT_* are valid for use in this context and will prempt the execution
2568c2ecf20Sopenharmony_ci * of any dependent fixture tests.
2578c2ecf20Sopenharmony_ci *
2588c2ecf20Sopenharmony_ci * A bare "return;" statement may be used to return early.
2598c2ecf20Sopenharmony_ci */
2608c2ecf20Sopenharmony_ci#define FIXTURE_SETUP(fixture_name) \
2618c2ecf20Sopenharmony_ci	void fixture_name##_setup( \
2628c2ecf20Sopenharmony_ci		struct __test_metadata __attribute__((unused)) *_metadata, \
2638c2ecf20Sopenharmony_ci		FIXTURE_DATA(fixture_name) __attribute__((unused)) *self, \
2648c2ecf20Sopenharmony_ci		const FIXTURE_VARIANT(fixture_name) \
2658c2ecf20Sopenharmony_ci			__attribute__((unused)) *variant)
2668c2ecf20Sopenharmony_ci
2678c2ecf20Sopenharmony_ci/**
2688c2ecf20Sopenharmony_ci * FIXTURE_TEARDOWN(fixture_name)
2698c2ecf20Sopenharmony_ci * *_metadata* is included so that EXPECT_* and ASSERT_* work correctly.
2708c2ecf20Sopenharmony_ci *
2718c2ecf20Sopenharmony_ci * @fixture_name: fixture name
2728c2ecf20Sopenharmony_ci *
2738c2ecf20Sopenharmony_ci * .. code-block:: c
2748c2ecf20Sopenharmony_ci *
2758c2ecf20Sopenharmony_ci *     FIXTURE_TEARDOWN(fixture_name) { implementation }
2768c2ecf20Sopenharmony_ci *
2778c2ecf20Sopenharmony_ci * Populates the required "teardown" function for a fixture.  An instance of the
2788c2ecf20Sopenharmony_ci * datatype defined with FIXTURE_DATA() will be exposed as *self* for the
2798c2ecf20Sopenharmony_ci * implementation to clean up.
2808c2ecf20Sopenharmony_ci *
2818c2ecf20Sopenharmony_ci * A bare "return;" statement may be used to return early.
2828c2ecf20Sopenharmony_ci */
2838c2ecf20Sopenharmony_ci#define FIXTURE_TEARDOWN(fixture_name) \
2848c2ecf20Sopenharmony_ci	void fixture_name##_teardown( \
2858c2ecf20Sopenharmony_ci		struct __test_metadata __attribute__((unused)) *_metadata, \
2868c2ecf20Sopenharmony_ci		FIXTURE_DATA(fixture_name) __attribute__((unused)) *self)
2878c2ecf20Sopenharmony_ci
2888c2ecf20Sopenharmony_ci/**
2898c2ecf20Sopenharmony_ci * FIXTURE_VARIANT(fixture_name) - Optionally called once per fixture
2908c2ecf20Sopenharmony_ci * to declare fixture variant
2918c2ecf20Sopenharmony_ci *
2928c2ecf20Sopenharmony_ci * @fixture_name: fixture name
2938c2ecf20Sopenharmony_ci *
2948c2ecf20Sopenharmony_ci * .. code-block:: c
2958c2ecf20Sopenharmony_ci *
2968c2ecf20Sopenharmony_ci *     FIXTURE_VARIANT(fixture_name) {
2978c2ecf20Sopenharmony_ci *       type property1;
2988c2ecf20Sopenharmony_ci *       ...
2998c2ecf20Sopenharmony_ci *     };
3008c2ecf20Sopenharmony_ci *
3018c2ecf20Sopenharmony_ci * Defines type of constant parameters provided to FIXTURE_SETUP() and TEST_F()
3028c2ecf20Sopenharmony_ci * as *variant*. Variants allow the same tests to be run with different
3038c2ecf20Sopenharmony_ci * arguments.
3048c2ecf20Sopenharmony_ci */
3058c2ecf20Sopenharmony_ci#define FIXTURE_VARIANT(fixture_name) struct _fixture_variant_##fixture_name
3068c2ecf20Sopenharmony_ci
3078c2ecf20Sopenharmony_ci/**
3088c2ecf20Sopenharmony_ci * FIXTURE_VARIANT_ADD(fixture_name, variant_name) - Called once per fixture
3098c2ecf20Sopenharmony_ci * variant to setup and register the data
3108c2ecf20Sopenharmony_ci *
3118c2ecf20Sopenharmony_ci * @fixture_name: fixture name
3128c2ecf20Sopenharmony_ci * @variant_name: name of the parameter set
3138c2ecf20Sopenharmony_ci *
3148c2ecf20Sopenharmony_ci * .. code-block:: c
3158c2ecf20Sopenharmony_ci *
3168c2ecf20Sopenharmony_ci *     FIXTURE_VARIANT_ADD(fixture_name, variant_name) {
3178c2ecf20Sopenharmony_ci *       .property1 = val1,
3188c2ecf20Sopenharmony_ci *       ...
3198c2ecf20Sopenharmony_ci *     };
3208c2ecf20Sopenharmony_ci *
3218c2ecf20Sopenharmony_ci * Defines a variant of the test fixture, provided to FIXTURE_SETUP() and
3228c2ecf20Sopenharmony_ci * TEST_F() as *variant*. Tests of each fixture will be run once for each
3238c2ecf20Sopenharmony_ci * variant.
3248c2ecf20Sopenharmony_ci */
3258c2ecf20Sopenharmony_ci#define FIXTURE_VARIANT_ADD(fixture_name, variant_name) \
3268c2ecf20Sopenharmony_ci	extern FIXTURE_VARIANT(fixture_name) \
3278c2ecf20Sopenharmony_ci		_##fixture_name##_##variant_name##_variant; \
3288c2ecf20Sopenharmony_ci	static struct __fixture_variant_metadata \
3298c2ecf20Sopenharmony_ci		_##fixture_name##_##variant_name##_object = \
3308c2ecf20Sopenharmony_ci		{ .name = #variant_name, \
3318c2ecf20Sopenharmony_ci		  .data = &_##fixture_name##_##variant_name##_variant}; \
3328c2ecf20Sopenharmony_ci	static void __attribute__((constructor)) \
3338c2ecf20Sopenharmony_ci		_register_##fixture_name##_##variant_name(void) \
3348c2ecf20Sopenharmony_ci	{ \
3358c2ecf20Sopenharmony_ci		__register_fixture_variant(&_##fixture_name##_fixture_object, \
3368c2ecf20Sopenharmony_ci			&_##fixture_name##_##variant_name##_object);	\
3378c2ecf20Sopenharmony_ci	} \
3388c2ecf20Sopenharmony_ci	FIXTURE_VARIANT(fixture_name) \
3398c2ecf20Sopenharmony_ci		_##fixture_name##_##variant_name##_variant =
3408c2ecf20Sopenharmony_ci
3418c2ecf20Sopenharmony_ci/**
3428c2ecf20Sopenharmony_ci * TEST_F(fixture_name, test_name) - Emits test registration and helpers for
3438c2ecf20Sopenharmony_ci * fixture-based test cases
3448c2ecf20Sopenharmony_ci *
3458c2ecf20Sopenharmony_ci * @fixture_name: fixture name
3468c2ecf20Sopenharmony_ci * @test_name: test name
3478c2ecf20Sopenharmony_ci *
3488c2ecf20Sopenharmony_ci * .. code-block:: c
3498c2ecf20Sopenharmony_ci *
3508c2ecf20Sopenharmony_ci *     TEST_F(fixture, name) { implementation }
3518c2ecf20Sopenharmony_ci *
3528c2ecf20Sopenharmony_ci * Defines a test that depends on a fixture (e.g., is part of a test case).
3538c2ecf20Sopenharmony_ci * Very similar to TEST() except that *self* is the setup instance of fixture's
3548c2ecf20Sopenharmony_ci * datatype exposed for use by the implementation.
3558c2ecf20Sopenharmony_ci *
3568c2ecf20Sopenharmony_ci * Warning: use of ASSERT_* here will skip TEARDOWN.
3578c2ecf20Sopenharmony_ci */
3588c2ecf20Sopenharmony_ci/* TODO(wad) register fixtures on dedicated test lists. */
3598c2ecf20Sopenharmony_ci#define TEST_F(fixture_name, test_name) \
3608c2ecf20Sopenharmony_ci	__TEST_F_IMPL(fixture_name, test_name, -1, TEST_TIMEOUT_DEFAULT)
3618c2ecf20Sopenharmony_ci
3628c2ecf20Sopenharmony_ci#define TEST_F_SIGNAL(fixture_name, test_name, signal) \
3638c2ecf20Sopenharmony_ci	__TEST_F_IMPL(fixture_name, test_name, signal, TEST_TIMEOUT_DEFAULT)
3648c2ecf20Sopenharmony_ci
3658c2ecf20Sopenharmony_ci#define TEST_F_TIMEOUT(fixture_name, test_name, timeout) \
3668c2ecf20Sopenharmony_ci	__TEST_F_IMPL(fixture_name, test_name, -1, timeout)
3678c2ecf20Sopenharmony_ci
3688c2ecf20Sopenharmony_ci#define __TEST_F_IMPL(fixture_name, test_name, signal, tmout) \
3698c2ecf20Sopenharmony_ci	static void fixture_name##_##test_name( \
3708c2ecf20Sopenharmony_ci		struct __test_metadata *_metadata, \
3718c2ecf20Sopenharmony_ci		FIXTURE_DATA(fixture_name) *self, \
3728c2ecf20Sopenharmony_ci		const FIXTURE_VARIANT(fixture_name) *variant); \
3738c2ecf20Sopenharmony_ci	static inline void wrapper_##fixture_name##_##test_name( \
3748c2ecf20Sopenharmony_ci		struct __test_metadata *_metadata, \
3758c2ecf20Sopenharmony_ci		struct __fixture_variant_metadata *variant) \
3768c2ecf20Sopenharmony_ci	{ \
3778c2ecf20Sopenharmony_ci		/* fixture data is alloced, setup, and torn down per call. */ \
3788c2ecf20Sopenharmony_ci		FIXTURE_DATA(fixture_name) self; \
3798c2ecf20Sopenharmony_ci		memset(&self, 0, sizeof(FIXTURE_DATA(fixture_name))); \
3808c2ecf20Sopenharmony_ci		fixture_name##_setup(_metadata, &self, variant->data); \
3818c2ecf20Sopenharmony_ci		/* Let setup failure terminate early. */ \
3828c2ecf20Sopenharmony_ci		if (!_metadata->passed) \
3838c2ecf20Sopenharmony_ci			return; \
3848c2ecf20Sopenharmony_ci		fixture_name##_##test_name(_metadata, &self, variant->data); \
3858c2ecf20Sopenharmony_ci		fixture_name##_teardown(_metadata, &self); \
3868c2ecf20Sopenharmony_ci	} \
3878c2ecf20Sopenharmony_ci	static struct __test_metadata \
3888c2ecf20Sopenharmony_ci		      _##fixture_name##_##test_name##_object = { \
3898c2ecf20Sopenharmony_ci		.name = #test_name, \
3908c2ecf20Sopenharmony_ci		.fn = &wrapper_##fixture_name##_##test_name, \
3918c2ecf20Sopenharmony_ci		.fixture = &_##fixture_name##_fixture_object, \
3928c2ecf20Sopenharmony_ci		.termsig = signal, \
3938c2ecf20Sopenharmony_ci		.timeout = tmout, \
3948c2ecf20Sopenharmony_ci	 }; \
3958c2ecf20Sopenharmony_ci	static void __attribute__((constructor)) \
3968c2ecf20Sopenharmony_ci			_register_##fixture_name##_##test_name(void) \
3978c2ecf20Sopenharmony_ci	{ \
3988c2ecf20Sopenharmony_ci		__register_test(&_##fixture_name##_##test_name##_object); \
3998c2ecf20Sopenharmony_ci	} \
4008c2ecf20Sopenharmony_ci	static void fixture_name##_##test_name( \
4018c2ecf20Sopenharmony_ci		struct __test_metadata __attribute__((unused)) *_metadata, \
4028c2ecf20Sopenharmony_ci		FIXTURE_DATA(fixture_name) __attribute__((unused)) *self, \
4038c2ecf20Sopenharmony_ci		const FIXTURE_VARIANT(fixture_name) \
4048c2ecf20Sopenharmony_ci			__attribute__((unused)) *variant)
4058c2ecf20Sopenharmony_ci
4068c2ecf20Sopenharmony_ci/**
4078c2ecf20Sopenharmony_ci * TEST_HARNESS_MAIN - Simple wrapper to run the test harness
4088c2ecf20Sopenharmony_ci *
4098c2ecf20Sopenharmony_ci * .. code-block:: c
4108c2ecf20Sopenharmony_ci *
4118c2ecf20Sopenharmony_ci *     TEST_HARNESS_MAIN
4128c2ecf20Sopenharmony_ci *
4138c2ecf20Sopenharmony_ci * Use once to append a main() to the test file.
4148c2ecf20Sopenharmony_ci */
4158c2ecf20Sopenharmony_ci#define TEST_HARNESS_MAIN \
4168c2ecf20Sopenharmony_ci	static void __attribute__((constructor)) \
4178c2ecf20Sopenharmony_ci	__constructor_order_last(void) \
4188c2ecf20Sopenharmony_ci	{ \
4198c2ecf20Sopenharmony_ci		if (!__constructor_order) \
4208c2ecf20Sopenharmony_ci			__constructor_order = _CONSTRUCTOR_ORDER_BACKWARD; \
4218c2ecf20Sopenharmony_ci	} \
4228c2ecf20Sopenharmony_ci	int main(int argc, char **argv) { \
4238c2ecf20Sopenharmony_ci		return test_harness_run(argc, argv); \
4248c2ecf20Sopenharmony_ci	}
4258c2ecf20Sopenharmony_ci
4268c2ecf20Sopenharmony_ci/**
4278c2ecf20Sopenharmony_ci * DOC: operators
4288c2ecf20Sopenharmony_ci *
4298c2ecf20Sopenharmony_ci * Operators for use in TEST() and TEST_F().
4308c2ecf20Sopenharmony_ci * ASSERT_* calls will stop test execution immediately.
4318c2ecf20Sopenharmony_ci * EXPECT_* calls will emit a failure warning, note it, and continue.
4328c2ecf20Sopenharmony_ci */
4338c2ecf20Sopenharmony_ci
4348c2ecf20Sopenharmony_ci/**
4358c2ecf20Sopenharmony_ci * ASSERT_EQ()
4368c2ecf20Sopenharmony_ci *
4378c2ecf20Sopenharmony_ci * @expected: expected value
4388c2ecf20Sopenharmony_ci * @seen: measured value
4398c2ecf20Sopenharmony_ci *
4408c2ecf20Sopenharmony_ci * ASSERT_EQ(expected, measured): expected == measured
4418c2ecf20Sopenharmony_ci */
4428c2ecf20Sopenharmony_ci#define ASSERT_EQ(expected, seen) \
4438c2ecf20Sopenharmony_ci	__EXPECT(expected, #expected, seen, #seen, ==, 1)
4448c2ecf20Sopenharmony_ci
4458c2ecf20Sopenharmony_ci/**
4468c2ecf20Sopenharmony_ci * ASSERT_NE()
4478c2ecf20Sopenharmony_ci *
4488c2ecf20Sopenharmony_ci * @expected: expected value
4498c2ecf20Sopenharmony_ci * @seen: measured value
4508c2ecf20Sopenharmony_ci *
4518c2ecf20Sopenharmony_ci * ASSERT_NE(expected, measured): expected != measured
4528c2ecf20Sopenharmony_ci */
4538c2ecf20Sopenharmony_ci#define ASSERT_NE(expected, seen) \
4548c2ecf20Sopenharmony_ci	__EXPECT(expected, #expected, seen, #seen, !=, 1)
4558c2ecf20Sopenharmony_ci
4568c2ecf20Sopenharmony_ci/**
4578c2ecf20Sopenharmony_ci * ASSERT_LT()
4588c2ecf20Sopenharmony_ci *
4598c2ecf20Sopenharmony_ci * @expected: expected value
4608c2ecf20Sopenharmony_ci * @seen: measured value
4618c2ecf20Sopenharmony_ci *
4628c2ecf20Sopenharmony_ci * ASSERT_LT(expected, measured): expected < measured
4638c2ecf20Sopenharmony_ci */
4648c2ecf20Sopenharmony_ci#define ASSERT_LT(expected, seen) \
4658c2ecf20Sopenharmony_ci	__EXPECT(expected, #expected, seen, #seen, <, 1)
4668c2ecf20Sopenharmony_ci
4678c2ecf20Sopenharmony_ci/**
4688c2ecf20Sopenharmony_ci * ASSERT_LE()
4698c2ecf20Sopenharmony_ci *
4708c2ecf20Sopenharmony_ci * @expected: expected value
4718c2ecf20Sopenharmony_ci * @seen: measured value
4728c2ecf20Sopenharmony_ci *
4738c2ecf20Sopenharmony_ci * ASSERT_LE(expected, measured): expected <= measured
4748c2ecf20Sopenharmony_ci */
4758c2ecf20Sopenharmony_ci#define ASSERT_LE(expected, seen) \
4768c2ecf20Sopenharmony_ci	__EXPECT(expected, #expected, seen, #seen, <=, 1)
4778c2ecf20Sopenharmony_ci
4788c2ecf20Sopenharmony_ci/**
4798c2ecf20Sopenharmony_ci * ASSERT_GT()
4808c2ecf20Sopenharmony_ci *
4818c2ecf20Sopenharmony_ci * @expected: expected value
4828c2ecf20Sopenharmony_ci * @seen: measured value
4838c2ecf20Sopenharmony_ci *
4848c2ecf20Sopenharmony_ci * ASSERT_GT(expected, measured): expected > measured
4858c2ecf20Sopenharmony_ci */
4868c2ecf20Sopenharmony_ci#define ASSERT_GT(expected, seen) \
4878c2ecf20Sopenharmony_ci	__EXPECT(expected, #expected, seen, #seen, >, 1)
4888c2ecf20Sopenharmony_ci
4898c2ecf20Sopenharmony_ci/**
4908c2ecf20Sopenharmony_ci * ASSERT_GE()
4918c2ecf20Sopenharmony_ci *
4928c2ecf20Sopenharmony_ci * @expected: expected value
4938c2ecf20Sopenharmony_ci * @seen: measured value
4948c2ecf20Sopenharmony_ci *
4958c2ecf20Sopenharmony_ci * ASSERT_GE(expected, measured): expected >= measured
4968c2ecf20Sopenharmony_ci */
4978c2ecf20Sopenharmony_ci#define ASSERT_GE(expected, seen) \
4988c2ecf20Sopenharmony_ci	__EXPECT(expected, #expected, seen, #seen, >=, 1)
4998c2ecf20Sopenharmony_ci
5008c2ecf20Sopenharmony_ci/**
5018c2ecf20Sopenharmony_ci * ASSERT_NULL()
5028c2ecf20Sopenharmony_ci *
5038c2ecf20Sopenharmony_ci * @seen: measured value
5048c2ecf20Sopenharmony_ci *
5058c2ecf20Sopenharmony_ci * ASSERT_NULL(measured): NULL == measured
5068c2ecf20Sopenharmony_ci */
5078c2ecf20Sopenharmony_ci#define ASSERT_NULL(seen) \
5088c2ecf20Sopenharmony_ci	__EXPECT(NULL, "NULL", seen, #seen, ==, 1)
5098c2ecf20Sopenharmony_ci
5108c2ecf20Sopenharmony_ci/**
5118c2ecf20Sopenharmony_ci * ASSERT_TRUE()
5128c2ecf20Sopenharmony_ci *
5138c2ecf20Sopenharmony_ci * @seen: measured value
5148c2ecf20Sopenharmony_ci *
5158c2ecf20Sopenharmony_ci * ASSERT_TRUE(measured): measured != 0
5168c2ecf20Sopenharmony_ci */
5178c2ecf20Sopenharmony_ci#define ASSERT_TRUE(seen) \
5188c2ecf20Sopenharmony_ci	__EXPECT(0, "0", seen, #seen, !=, 1)
5198c2ecf20Sopenharmony_ci
5208c2ecf20Sopenharmony_ci/**
5218c2ecf20Sopenharmony_ci * ASSERT_FALSE()
5228c2ecf20Sopenharmony_ci *
5238c2ecf20Sopenharmony_ci * @seen: measured value
5248c2ecf20Sopenharmony_ci *
5258c2ecf20Sopenharmony_ci * ASSERT_FALSE(measured): measured == 0
5268c2ecf20Sopenharmony_ci */
5278c2ecf20Sopenharmony_ci#define ASSERT_FALSE(seen) \
5288c2ecf20Sopenharmony_ci	__EXPECT(0, "0", seen, #seen, ==, 1)
5298c2ecf20Sopenharmony_ci
5308c2ecf20Sopenharmony_ci/**
5318c2ecf20Sopenharmony_ci * ASSERT_STREQ()
5328c2ecf20Sopenharmony_ci *
5338c2ecf20Sopenharmony_ci * @expected: expected value
5348c2ecf20Sopenharmony_ci * @seen: measured value
5358c2ecf20Sopenharmony_ci *
5368c2ecf20Sopenharmony_ci * ASSERT_STREQ(expected, measured): !strcmp(expected, measured)
5378c2ecf20Sopenharmony_ci */
5388c2ecf20Sopenharmony_ci#define ASSERT_STREQ(expected, seen) \
5398c2ecf20Sopenharmony_ci	__EXPECT_STR(expected, seen, ==, 1)
5408c2ecf20Sopenharmony_ci
5418c2ecf20Sopenharmony_ci/**
5428c2ecf20Sopenharmony_ci * ASSERT_STRNE()
5438c2ecf20Sopenharmony_ci *
5448c2ecf20Sopenharmony_ci * @expected: expected value
5458c2ecf20Sopenharmony_ci * @seen: measured value
5468c2ecf20Sopenharmony_ci *
5478c2ecf20Sopenharmony_ci * ASSERT_STRNE(expected, measured): strcmp(expected, measured)
5488c2ecf20Sopenharmony_ci */
5498c2ecf20Sopenharmony_ci#define ASSERT_STRNE(expected, seen) \
5508c2ecf20Sopenharmony_ci	__EXPECT_STR(expected, seen, !=, 1)
5518c2ecf20Sopenharmony_ci
5528c2ecf20Sopenharmony_ci/**
5538c2ecf20Sopenharmony_ci * EXPECT_EQ()
5548c2ecf20Sopenharmony_ci *
5558c2ecf20Sopenharmony_ci * @expected: expected value
5568c2ecf20Sopenharmony_ci * @seen: measured value
5578c2ecf20Sopenharmony_ci *
5588c2ecf20Sopenharmony_ci * EXPECT_EQ(expected, measured): expected == measured
5598c2ecf20Sopenharmony_ci */
5608c2ecf20Sopenharmony_ci#define EXPECT_EQ(expected, seen) \
5618c2ecf20Sopenharmony_ci	__EXPECT(expected, #expected, seen, #seen, ==, 0)
5628c2ecf20Sopenharmony_ci
5638c2ecf20Sopenharmony_ci/**
5648c2ecf20Sopenharmony_ci * EXPECT_NE()
5658c2ecf20Sopenharmony_ci *
5668c2ecf20Sopenharmony_ci * @expected: expected value
5678c2ecf20Sopenharmony_ci * @seen: measured value
5688c2ecf20Sopenharmony_ci *
5698c2ecf20Sopenharmony_ci * EXPECT_NE(expected, measured): expected != measured
5708c2ecf20Sopenharmony_ci */
5718c2ecf20Sopenharmony_ci#define EXPECT_NE(expected, seen) \
5728c2ecf20Sopenharmony_ci	__EXPECT(expected, #expected, seen, #seen, !=, 0)
5738c2ecf20Sopenharmony_ci
5748c2ecf20Sopenharmony_ci/**
5758c2ecf20Sopenharmony_ci * EXPECT_LT()
5768c2ecf20Sopenharmony_ci *
5778c2ecf20Sopenharmony_ci * @expected: expected value
5788c2ecf20Sopenharmony_ci * @seen: measured value
5798c2ecf20Sopenharmony_ci *
5808c2ecf20Sopenharmony_ci * EXPECT_LT(expected, measured): expected < measured
5818c2ecf20Sopenharmony_ci */
5828c2ecf20Sopenharmony_ci#define EXPECT_LT(expected, seen) \
5838c2ecf20Sopenharmony_ci	__EXPECT(expected, #expected, seen, #seen, <, 0)
5848c2ecf20Sopenharmony_ci
5858c2ecf20Sopenharmony_ci/**
5868c2ecf20Sopenharmony_ci * EXPECT_LE()
5878c2ecf20Sopenharmony_ci *
5888c2ecf20Sopenharmony_ci * @expected: expected value
5898c2ecf20Sopenharmony_ci * @seen: measured value
5908c2ecf20Sopenharmony_ci *
5918c2ecf20Sopenharmony_ci * EXPECT_LE(expected, measured): expected <= measured
5928c2ecf20Sopenharmony_ci */
5938c2ecf20Sopenharmony_ci#define EXPECT_LE(expected, seen) \
5948c2ecf20Sopenharmony_ci	__EXPECT(expected, #expected, seen, #seen, <=, 0)
5958c2ecf20Sopenharmony_ci
5968c2ecf20Sopenharmony_ci/**
5978c2ecf20Sopenharmony_ci * EXPECT_GT()
5988c2ecf20Sopenharmony_ci *
5998c2ecf20Sopenharmony_ci * @expected: expected value
6008c2ecf20Sopenharmony_ci * @seen: measured value
6018c2ecf20Sopenharmony_ci *
6028c2ecf20Sopenharmony_ci * EXPECT_GT(expected, measured): expected > measured
6038c2ecf20Sopenharmony_ci */
6048c2ecf20Sopenharmony_ci#define EXPECT_GT(expected, seen) \
6058c2ecf20Sopenharmony_ci	__EXPECT(expected, #expected, seen, #seen, >, 0)
6068c2ecf20Sopenharmony_ci
6078c2ecf20Sopenharmony_ci/**
6088c2ecf20Sopenharmony_ci * EXPECT_GE()
6098c2ecf20Sopenharmony_ci *
6108c2ecf20Sopenharmony_ci * @expected: expected value
6118c2ecf20Sopenharmony_ci * @seen: measured value
6128c2ecf20Sopenharmony_ci *
6138c2ecf20Sopenharmony_ci * EXPECT_GE(expected, measured): expected >= measured
6148c2ecf20Sopenharmony_ci */
6158c2ecf20Sopenharmony_ci#define EXPECT_GE(expected, seen) \
6168c2ecf20Sopenharmony_ci	__EXPECT(expected, #expected, seen, #seen, >=, 0)
6178c2ecf20Sopenharmony_ci
6188c2ecf20Sopenharmony_ci/**
6198c2ecf20Sopenharmony_ci * EXPECT_NULL()
6208c2ecf20Sopenharmony_ci *
6218c2ecf20Sopenharmony_ci * @seen: measured value
6228c2ecf20Sopenharmony_ci *
6238c2ecf20Sopenharmony_ci * EXPECT_NULL(measured): NULL == measured
6248c2ecf20Sopenharmony_ci */
6258c2ecf20Sopenharmony_ci#define EXPECT_NULL(seen) \
6268c2ecf20Sopenharmony_ci	__EXPECT(NULL, "NULL", seen, #seen, ==, 0)
6278c2ecf20Sopenharmony_ci
6288c2ecf20Sopenharmony_ci/**
6298c2ecf20Sopenharmony_ci * EXPECT_TRUE()
6308c2ecf20Sopenharmony_ci *
6318c2ecf20Sopenharmony_ci * @seen: measured value
6328c2ecf20Sopenharmony_ci *
6338c2ecf20Sopenharmony_ci * EXPECT_TRUE(measured): 0 != measured
6348c2ecf20Sopenharmony_ci */
6358c2ecf20Sopenharmony_ci#define EXPECT_TRUE(seen) \
6368c2ecf20Sopenharmony_ci	__EXPECT(0, "0", seen, #seen, !=, 0)
6378c2ecf20Sopenharmony_ci
6388c2ecf20Sopenharmony_ci/**
6398c2ecf20Sopenharmony_ci * EXPECT_FALSE()
6408c2ecf20Sopenharmony_ci *
6418c2ecf20Sopenharmony_ci * @seen: measured value
6428c2ecf20Sopenharmony_ci *
6438c2ecf20Sopenharmony_ci * EXPECT_FALSE(measured): 0 == measured
6448c2ecf20Sopenharmony_ci */
6458c2ecf20Sopenharmony_ci#define EXPECT_FALSE(seen) \
6468c2ecf20Sopenharmony_ci	__EXPECT(0, "0", seen, #seen, ==, 0)
6478c2ecf20Sopenharmony_ci
6488c2ecf20Sopenharmony_ci/**
6498c2ecf20Sopenharmony_ci * EXPECT_STREQ()
6508c2ecf20Sopenharmony_ci *
6518c2ecf20Sopenharmony_ci * @expected: expected value
6528c2ecf20Sopenharmony_ci * @seen: measured value
6538c2ecf20Sopenharmony_ci *
6548c2ecf20Sopenharmony_ci * EXPECT_STREQ(expected, measured): !strcmp(expected, measured)
6558c2ecf20Sopenharmony_ci */
6568c2ecf20Sopenharmony_ci#define EXPECT_STREQ(expected, seen) \
6578c2ecf20Sopenharmony_ci	__EXPECT_STR(expected, seen, ==, 0)
6588c2ecf20Sopenharmony_ci
6598c2ecf20Sopenharmony_ci/**
6608c2ecf20Sopenharmony_ci * EXPECT_STRNE()
6618c2ecf20Sopenharmony_ci *
6628c2ecf20Sopenharmony_ci * @expected: expected value
6638c2ecf20Sopenharmony_ci * @seen: measured value
6648c2ecf20Sopenharmony_ci *
6658c2ecf20Sopenharmony_ci * EXPECT_STRNE(expected, measured): strcmp(expected, measured)
6668c2ecf20Sopenharmony_ci */
6678c2ecf20Sopenharmony_ci#define EXPECT_STRNE(expected, seen) \
6688c2ecf20Sopenharmony_ci	__EXPECT_STR(expected, seen, !=, 0)
6698c2ecf20Sopenharmony_ci
6708c2ecf20Sopenharmony_ci#define ARRAY_SIZE(a)	(sizeof(a) / sizeof(a[0]))
6718c2ecf20Sopenharmony_ci
6728c2ecf20Sopenharmony_ci/* Support an optional handler after and ASSERT_* or EXPECT_*.  The approach is
6738c2ecf20Sopenharmony_ci * not thread-safe, but it should be fine in most sane test scenarios.
6748c2ecf20Sopenharmony_ci *
6758c2ecf20Sopenharmony_ci * Using __bail(), which optionally abort()s, is the easiest way to early
6768c2ecf20Sopenharmony_ci * return while still providing an optional block to the API consumer.
6778c2ecf20Sopenharmony_ci */
6788c2ecf20Sopenharmony_ci#define OPTIONAL_HANDLER(_assert) \
6798c2ecf20Sopenharmony_ci	for (; _metadata->trigger; _metadata->trigger = \
6808c2ecf20Sopenharmony_ci			__bail(_assert, _metadata->no_print, _metadata->step))
6818c2ecf20Sopenharmony_ci
6828c2ecf20Sopenharmony_ci#define __INC_STEP(_metadata) \
6838c2ecf20Sopenharmony_ci	/* Keep "step" below 255 (which is used for "SKIP" reporting). */	\
6848c2ecf20Sopenharmony_ci	if (_metadata->passed && _metadata->step < 253) \
6858c2ecf20Sopenharmony_ci		_metadata->step++;
6868c2ecf20Sopenharmony_ci
6878c2ecf20Sopenharmony_ci#define is_signed_type(var)       (!!(((__typeof__(var))(-1)) < (__typeof__(var))1))
6888c2ecf20Sopenharmony_ci
6898c2ecf20Sopenharmony_ci#define __EXPECT(_expected, _expected_str, _seen, _seen_str, _t, _assert) do { \
6908c2ecf20Sopenharmony_ci	/* Avoid multiple evaluation of the cases */ \
6918c2ecf20Sopenharmony_ci	__typeof__(_expected) __exp = (_expected); \
6928c2ecf20Sopenharmony_ci	__typeof__(_seen) __seen = (_seen); \
6938c2ecf20Sopenharmony_ci	if (_assert) __INC_STEP(_metadata); \
6948c2ecf20Sopenharmony_ci	if (!(__exp _t __seen)) { \
6958c2ecf20Sopenharmony_ci		/* Report with actual signedness to avoid weird output. */ \
6968c2ecf20Sopenharmony_ci		switch (is_signed_type(__exp) * 2 + is_signed_type(__seen)) { \
6978c2ecf20Sopenharmony_ci		case 0: { \
6988c2ecf20Sopenharmony_ci			unsigned long long __exp_print = (uintptr_t)__exp; \
6998c2ecf20Sopenharmony_ci			unsigned long long __seen_print = (uintptr_t)__seen; \
7008c2ecf20Sopenharmony_ci			__TH_LOG("Expected %s (%llu) %s %s (%llu)", \
7018c2ecf20Sopenharmony_ci				 _expected_str, __exp_print, #_t, \
7028c2ecf20Sopenharmony_ci				 _seen_str, __seen_print); \
7038c2ecf20Sopenharmony_ci			break; \
7048c2ecf20Sopenharmony_ci			} \
7058c2ecf20Sopenharmony_ci		case 1: { \
7068c2ecf20Sopenharmony_ci			unsigned long long __exp_print = (uintptr_t)__exp; \
7078c2ecf20Sopenharmony_ci			long long __seen_print = (intptr_t)__seen; \
7088c2ecf20Sopenharmony_ci			__TH_LOG("Expected %s (%llu) %s %s (%lld)", \
7098c2ecf20Sopenharmony_ci				 _expected_str, __exp_print, #_t, \
7108c2ecf20Sopenharmony_ci				 _seen_str, __seen_print); \
7118c2ecf20Sopenharmony_ci			break; \
7128c2ecf20Sopenharmony_ci			} \
7138c2ecf20Sopenharmony_ci		case 2: { \
7148c2ecf20Sopenharmony_ci			long long __exp_print = (intptr_t)__exp; \
7158c2ecf20Sopenharmony_ci			unsigned long long __seen_print = (uintptr_t)__seen; \
7168c2ecf20Sopenharmony_ci			__TH_LOG("Expected %s (%lld) %s %s (%llu)", \
7178c2ecf20Sopenharmony_ci				 _expected_str, __exp_print, #_t, \
7188c2ecf20Sopenharmony_ci				 _seen_str, __seen_print); \
7198c2ecf20Sopenharmony_ci			break; \
7208c2ecf20Sopenharmony_ci			} \
7218c2ecf20Sopenharmony_ci		case 3: { \
7228c2ecf20Sopenharmony_ci			long long __exp_print = (intptr_t)__exp; \
7238c2ecf20Sopenharmony_ci			long long __seen_print = (intptr_t)__seen; \
7248c2ecf20Sopenharmony_ci			__TH_LOG("Expected %s (%lld) %s %s (%lld)", \
7258c2ecf20Sopenharmony_ci				 _expected_str, __exp_print, #_t, \
7268c2ecf20Sopenharmony_ci				 _seen_str, __seen_print); \
7278c2ecf20Sopenharmony_ci			break; \
7288c2ecf20Sopenharmony_ci			} \
7298c2ecf20Sopenharmony_ci		} \
7308c2ecf20Sopenharmony_ci		_metadata->passed = 0; \
7318c2ecf20Sopenharmony_ci		/* Ensure the optional handler is triggered */ \
7328c2ecf20Sopenharmony_ci		_metadata->trigger = 1; \
7338c2ecf20Sopenharmony_ci	} \
7348c2ecf20Sopenharmony_ci} while (0); OPTIONAL_HANDLER(_assert)
7358c2ecf20Sopenharmony_ci
7368c2ecf20Sopenharmony_ci#define __EXPECT_STR(_expected, _seen, _t, _assert) do { \
7378c2ecf20Sopenharmony_ci	const char *__exp = (_expected); \
7388c2ecf20Sopenharmony_ci	const char *__seen = (_seen); \
7398c2ecf20Sopenharmony_ci	if (_assert) __INC_STEP(_metadata); \
7408c2ecf20Sopenharmony_ci	if (!(strcmp(__exp, __seen) _t 0))  { \
7418c2ecf20Sopenharmony_ci		__TH_LOG("Expected '%s' %s '%s'.", __exp, #_t, __seen); \
7428c2ecf20Sopenharmony_ci		_metadata->passed = 0; \
7438c2ecf20Sopenharmony_ci		_metadata->trigger = 1; \
7448c2ecf20Sopenharmony_ci	} \
7458c2ecf20Sopenharmony_ci} while (0); OPTIONAL_HANDLER(_assert)
7468c2ecf20Sopenharmony_ci
7478c2ecf20Sopenharmony_ci/* List helpers */
7488c2ecf20Sopenharmony_ci#define __LIST_APPEND(head, item) \
7498c2ecf20Sopenharmony_ci{ \
7508c2ecf20Sopenharmony_ci	/* Circular linked list where only prev is circular. */ \
7518c2ecf20Sopenharmony_ci	if (head == NULL) { \
7528c2ecf20Sopenharmony_ci		head = item; \
7538c2ecf20Sopenharmony_ci		item->next = NULL; \
7548c2ecf20Sopenharmony_ci		item->prev = item; \
7558c2ecf20Sopenharmony_ci		return;	\
7568c2ecf20Sopenharmony_ci	} \
7578c2ecf20Sopenharmony_ci	if (__constructor_order == _CONSTRUCTOR_ORDER_FORWARD) { \
7588c2ecf20Sopenharmony_ci		item->next = NULL; \
7598c2ecf20Sopenharmony_ci		item->prev = head->prev; \
7608c2ecf20Sopenharmony_ci		item->prev->next = item; \
7618c2ecf20Sopenharmony_ci		head->prev = item; \
7628c2ecf20Sopenharmony_ci	} else { \
7638c2ecf20Sopenharmony_ci		item->next = head; \
7648c2ecf20Sopenharmony_ci		item->next->prev = item; \
7658c2ecf20Sopenharmony_ci		item->prev = item; \
7668c2ecf20Sopenharmony_ci		head = item; \
7678c2ecf20Sopenharmony_ci	} \
7688c2ecf20Sopenharmony_ci}
7698c2ecf20Sopenharmony_ci
7708c2ecf20Sopenharmony_cistruct __test_results {
7718c2ecf20Sopenharmony_ci	char reason[1024];	/* Reason for test result */
7728c2ecf20Sopenharmony_ci};
7738c2ecf20Sopenharmony_ci
7748c2ecf20Sopenharmony_cistruct __test_metadata;
7758c2ecf20Sopenharmony_cistruct __fixture_variant_metadata;
7768c2ecf20Sopenharmony_ci
7778c2ecf20Sopenharmony_ci/* Contains all the information about a fixture. */
7788c2ecf20Sopenharmony_cistruct __fixture_metadata {
7798c2ecf20Sopenharmony_ci	const char *name;
7808c2ecf20Sopenharmony_ci	struct __test_metadata *tests;
7818c2ecf20Sopenharmony_ci	struct __fixture_variant_metadata *variant;
7828c2ecf20Sopenharmony_ci	struct __fixture_metadata *prev, *next;
7838c2ecf20Sopenharmony_ci} _fixture_global __attribute__((unused)) = {
7848c2ecf20Sopenharmony_ci	.name = "global",
7858c2ecf20Sopenharmony_ci	.prev = &_fixture_global,
7868c2ecf20Sopenharmony_ci};
7878c2ecf20Sopenharmony_ci
7888c2ecf20Sopenharmony_cistatic struct __fixture_metadata *__fixture_list = &_fixture_global;
7898c2ecf20Sopenharmony_cistatic int __constructor_order;
7908c2ecf20Sopenharmony_ci
7918c2ecf20Sopenharmony_ci#define _CONSTRUCTOR_ORDER_FORWARD   1
7928c2ecf20Sopenharmony_ci#define _CONSTRUCTOR_ORDER_BACKWARD -1
7938c2ecf20Sopenharmony_ci
7948c2ecf20Sopenharmony_cistatic inline void __register_fixture(struct __fixture_metadata *f)
7958c2ecf20Sopenharmony_ci{
7968c2ecf20Sopenharmony_ci	__LIST_APPEND(__fixture_list, f);
7978c2ecf20Sopenharmony_ci}
7988c2ecf20Sopenharmony_ci
7998c2ecf20Sopenharmony_cistruct __fixture_variant_metadata {
8008c2ecf20Sopenharmony_ci	const char *name;
8018c2ecf20Sopenharmony_ci	const void *data;
8028c2ecf20Sopenharmony_ci	struct __fixture_variant_metadata *prev, *next;
8038c2ecf20Sopenharmony_ci};
8048c2ecf20Sopenharmony_ci
8058c2ecf20Sopenharmony_cistatic inline void
8068c2ecf20Sopenharmony_ci__register_fixture_variant(struct __fixture_metadata *f,
8078c2ecf20Sopenharmony_ci			   struct __fixture_variant_metadata *variant)
8088c2ecf20Sopenharmony_ci{
8098c2ecf20Sopenharmony_ci	__LIST_APPEND(f->variant, variant);
8108c2ecf20Sopenharmony_ci}
8118c2ecf20Sopenharmony_ci
8128c2ecf20Sopenharmony_ci/* Contains all the information for test execution and status checking. */
8138c2ecf20Sopenharmony_cistruct __test_metadata {
8148c2ecf20Sopenharmony_ci	const char *name;
8158c2ecf20Sopenharmony_ci	void (*fn)(struct __test_metadata *,
8168c2ecf20Sopenharmony_ci		   struct __fixture_variant_metadata *);
8178c2ecf20Sopenharmony_ci	pid_t pid;	/* pid of test when being run */
8188c2ecf20Sopenharmony_ci	struct __fixture_metadata *fixture;
8198c2ecf20Sopenharmony_ci	int termsig;
8208c2ecf20Sopenharmony_ci	int passed;
8218c2ecf20Sopenharmony_ci	int skip;	/* did SKIP get used? */
8228c2ecf20Sopenharmony_ci	int trigger; /* extra handler after the evaluation */
8238c2ecf20Sopenharmony_ci	int timeout;	/* seconds to wait for test timeout */
8248c2ecf20Sopenharmony_ci	bool timed_out;	/* did this test timeout instead of exiting? */
8258c2ecf20Sopenharmony_ci	__u8 step;
8268c2ecf20Sopenharmony_ci	bool no_print; /* manual trigger when TH_LOG_STREAM is not available */
8278c2ecf20Sopenharmony_ci	struct __test_results *results;
8288c2ecf20Sopenharmony_ci	struct __test_metadata *prev, *next;
8298c2ecf20Sopenharmony_ci};
8308c2ecf20Sopenharmony_ci
8318c2ecf20Sopenharmony_ci/*
8328c2ecf20Sopenharmony_ci * Since constructors are called in reverse order, reverse the test
8338c2ecf20Sopenharmony_ci * list so tests are run in source declaration order.
8348c2ecf20Sopenharmony_ci * https://gcc.gnu.org/onlinedocs/gccint/Initialization.html
8358c2ecf20Sopenharmony_ci * However, it seems not all toolchains do this correctly, so use
8368c2ecf20Sopenharmony_ci * __constructor_order to detect which direction is called first
8378c2ecf20Sopenharmony_ci * and adjust list building logic to get things running in the right
8388c2ecf20Sopenharmony_ci * direction.
8398c2ecf20Sopenharmony_ci */
8408c2ecf20Sopenharmony_cistatic inline void __register_test(struct __test_metadata *t)
8418c2ecf20Sopenharmony_ci{
8428c2ecf20Sopenharmony_ci	__LIST_APPEND(t->fixture->tests, t);
8438c2ecf20Sopenharmony_ci}
8448c2ecf20Sopenharmony_ci
8458c2ecf20Sopenharmony_cistatic inline int __bail(int for_realz, bool no_print, __u8 step)
8468c2ecf20Sopenharmony_ci{
8478c2ecf20Sopenharmony_ci	if (for_realz) {
8488c2ecf20Sopenharmony_ci		if (no_print)
8498c2ecf20Sopenharmony_ci			_exit(step);
8508c2ecf20Sopenharmony_ci		abort();
8518c2ecf20Sopenharmony_ci	}
8528c2ecf20Sopenharmony_ci	return 0;
8538c2ecf20Sopenharmony_ci}
8548c2ecf20Sopenharmony_ci
8558c2ecf20Sopenharmony_cistruct __test_metadata *__active_test;
8568c2ecf20Sopenharmony_cistatic void __timeout_handler(int sig, siginfo_t *info, void *ucontext)
8578c2ecf20Sopenharmony_ci{
8588c2ecf20Sopenharmony_ci	struct __test_metadata *t = __active_test;
8598c2ecf20Sopenharmony_ci
8608c2ecf20Sopenharmony_ci	/* Sanity check handler execution environment. */
8618c2ecf20Sopenharmony_ci	if (!t) {
8628c2ecf20Sopenharmony_ci		fprintf(TH_LOG_STREAM,
8638c2ecf20Sopenharmony_ci			"# no active test in SIGALRM handler!?\n");
8648c2ecf20Sopenharmony_ci		abort();
8658c2ecf20Sopenharmony_ci	}
8668c2ecf20Sopenharmony_ci	if (sig != SIGALRM || sig != info->si_signo) {
8678c2ecf20Sopenharmony_ci		fprintf(TH_LOG_STREAM,
8688c2ecf20Sopenharmony_ci			"# %s: SIGALRM handler caught signal %d!?\n",
8698c2ecf20Sopenharmony_ci			t->name, sig != SIGALRM ? sig : info->si_signo);
8708c2ecf20Sopenharmony_ci		abort();
8718c2ecf20Sopenharmony_ci	}
8728c2ecf20Sopenharmony_ci
8738c2ecf20Sopenharmony_ci	t->timed_out = true;
8748c2ecf20Sopenharmony_ci	// signal process group
8758c2ecf20Sopenharmony_ci	kill(-(t->pid), SIGKILL);
8768c2ecf20Sopenharmony_ci}
8778c2ecf20Sopenharmony_ci
8788c2ecf20Sopenharmony_civoid __wait_for_test(struct __test_metadata *t)
8798c2ecf20Sopenharmony_ci{
8808c2ecf20Sopenharmony_ci	struct sigaction action = {
8818c2ecf20Sopenharmony_ci		.sa_sigaction = __timeout_handler,
8828c2ecf20Sopenharmony_ci		.sa_flags = SA_SIGINFO,
8838c2ecf20Sopenharmony_ci	};
8848c2ecf20Sopenharmony_ci	struct sigaction saved_action;
8858c2ecf20Sopenharmony_ci	int status;
8868c2ecf20Sopenharmony_ci
8878c2ecf20Sopenharmony_ci	if (sigaction(SIGALRM, &action, &saved_action)) {
8888c2ecf20Sopenharmony_ci		t->passed = 0;
8898c2ecf20Sopenharmony_ci		fprintf(TH_LOG_STREAM,
8908c2ecf20Sopenharmony_ci			"# %s: unable to install SIGALRM handler\n",
8918c2ecf20Sopenharmony_ci			t->name);
8928c2ecf20Sopenharmony_ci		return;
8938c2ecf20Sopenharmony_ci	}
8948c2ecf20Sopenharmony_ci	__active_test = t;
8958c2ecf20Sopenharmony_ci	t->timed_out = false;
8968c2ecf20Sopenharmony_ci	alarm(t->timeout);
8978c2ecf20Sopenharmony_ci	waitpid(t->pid, &status, 0);
8988c2ecf20Sopenharmony_ci	alarm(0);
8998c2ecf20Sopenharmony_ci	if (sigaction(SIGALRM, &saved_action, NULL)) {
9008c2ecf20Sopenharmony_ci		t->passed = 0;
9018c2ecf20Sopenharmony_ci		fprintf(TH_LOG_STREAM,
9028c2ecf20Sopenharmony_ci			"# %s: unable to uninstall SIGALRM handler\n",
9038c2ecf20Sopenharmony_ci			t->name);
9048c2ecf20Sopenharmony_ci		return;
9058c2ecf20Sopenharmony_ci	}
9068c2ecf20Sopenharmony_ci	__active_test = NULL;
9078c2ecf20Sopenharmony_ci
9088c2ecf20Sopenharmony_ci	if (t->timed_out) {
9098c2ecf20Sopenharmony_ci		t->passed = 0;
9108c2ecf20Sopenharmony_ci		fprintf(TH_LOG_STREAM,
9118c2ecf20Sopenharmony_ci			"# %s: Test terminated by timeout\n", t->name);
9128c2ecf20Sopenharmony_ci	} else if (WIFEXITED(status)) {
9138c2ecf20Sopenharmony_ci		if (WEXITSTATUS(status) == 255) {
9148c2ecf20Sopenharmony_ci			/* SKIP */
9158c2ecf20Sopenharmony_ci			t->passed = 1;
9168c2ecf20Sopenharmony_ci			t->skip = 1;
9178c2ecf20Sopenharmony_ci		} else if (t->termsig != -1) {
9188c2ecf20Sopenharmony_ci			t->passed = 0;
9198c2ecf20Sopenharmony_ci			fprintf(TH_LOG_STREAM,
9208c2ecf20Sopenharmony_ci				"# %s: Test exited normally instead of by signal (code: %d)\n",
9218c2ecf20Sopenharmony_ci				t->name,
9228c2ecf20Sopenharmony_ci				WEXITSTATUS(status));
9238c2ecf20Sopenharmony_ci		} else {
9248c2ecf20Sopenharmony_ci			switch (WEXITSTATUS(status)) {
9258c2ecf20Sopenharmony_ci			/* Success */
9268c2ecf20Sopenharmony_ci			case 0:
9278c2ecf20Sopenharmony_ci				t->passed = 1;
9288c2ecf20Sopenharmony_ci				break;
9298c2ecf20Sopenharmony_ci			/* Other failure, assume step report. */
9308c2ecf20Sopenharmony_ci			default:
9318c2ecf20Sopenharmony_ci				t->passed = 0;
9328c2ecf20Sopenharmony_ci				fprintf(TH_LOG_STREAM,
9338c2ecf20Sopenharmony_ci					"# %s: Test failed at step #%d\n",
9348c2ecf20Sopenharmony_ci					t->name,
9358c2ecf20Sopenharmony_ci					WEXITSTATUS(status));
9368c2ecf20Sopenharmony_ci			}
9378c2ecf20Sopenharmony_ci		}
9388c2ecf20Sopenharmony_ci	} else if (WIFSIGNALED(status)) {
9398c2ecf20Sopenharmony_ci		t->passed = 0;
9408c2ecf20Sopenharmony_ci		if (WTERMSIG(status) == SIGABRT) {
9418c2ecf20Sopenharmony_ci			fprintf(TH_LOG_STREAM,
9428c2ecf20Sopenharmony_ci				"# %s: Test terminated by assertion\n",
9438c2ecf20Sopenharmony_ci				t->name);
9448c2ecf20Sopenharmony_ci		} else if (WTERMSIG(status) == t->termsig) {
9458c2ecf20Sopenharmony_ci			t->passed = 1;
9468c2ecf20Sopenharmony_ci		} else {
9478c2ecf20Sopenharmony_ci			fprintf(TH_LOG_STREAM,
9488c2ecf20Sopenharmony_ci				"# %s: Test terminated unexpectedly by signal %d\n",
9498c2ecf20Sopenharmony_ci				t->name,
9508c2ecf20Sopenharmony_ci				WTERMSIG(status));
9518c2ecf20Sopenharmony_ci		}
9528c2ecf20Sopenharmony_ci	} else {
9538c2ecf20Sopenharmony_ci		fprintf(TH_LOG_STREAM,
9548c2ecf20Sopenharmony_ci			"# %s: Test ended in some other way [%u]\n",
9558c2ecf20Sopenharmony_ci			t->name,
9568c2ecf20Sopenharmony_ci			status);
9578c2ecf20Sopenharmony_ci	}
9588c2ecf20Sopenharmony_ci}
9598c2ecf20Sopenharmony_ci
9608c2ecf20Sopenharmony_civoid __run_test(struct __fixture_metadata *f,
9618c2ecf20Sopenharmony_ci		struct __fixture_variant_metadata *variant,
9628c2ecf20Sopenharmony_ci		struct __test_metadata *t)
9638c2ecf20Sopenharmony_ci{
9648c2ecf20Sopenharmony_ci	/* reset test struct */
9658c2ecf20Sopenharmony_ci	t->passed = 1;
9668c2ecf20Sopenharmony_ci	t->skip = 0;
9678c2ecf20Sopenharmony_ci	t->trigger = 0;
9688c2ecf20Sopenharmony_ci	t->step = 1;
9698c2ecf20Sopenharmony_ci	t->no_print = 0;
9708c2ecf20Sopenharmony_ci	memset(t->results->reason, 0, sizeof(t->results->reason));
9718c2ecf20Sopenharmony_ci
9728c2ecf20Sopenharmony_ci	ksft_print_msg(" RUN           %s%s%s.%s ...\n",
9738c2ecf20Sopenharmony_ci	       f->name, variant->name[0] ? "." : "", variant->name, t->name);
9748c2ecf20Sopenharmony_ci
9758c2ecf20Sopenharmony_ci	/* Make sure output buffers are flushed before fork */
9768c2ecf20Sopenharmony_ci	fflush(stdout);
9778c2ecf20Sopenharmony_ci	fflush(stderr);
9788c2ecf20Sopenharmony_ci
9798c2ecf20Sopenharmony_ci	t->pid = fork();
9808c2ecf20Sopenharmony_ci	if (t->pid < 0) {
9818c2ecf20Sopenharmony_ci		ksft_print_msg("ERROR SPAWNING TEST CHILD\n");
9828c2ecf20Sopenharmony_ci		t->passed = 0;
9838c2ecf20Sopenharmony_ci	} else if (t->pid == 0) {
9848c2ecf20Sopenharmony_ci		setpgrp();
9858c2ecf20Sopenharmony_ci		t->fn(t, variant);
9868c2ecf20Sopenharmony_ci		if (t->skip)
9878c2ecf20Sopenharmony_ci			_exit(255);
9888c2ecf20Sopenharmony_ci		/* Pass is exit 0 */
9898c2ecf20Sopenharmony_ci		if (t->passed)
9908c2ecf20Sopenharmony_ci			_exit(0);
9918c2ecf20Sopenharmony_ci		/* Something else happened, report the step. */
9928c2ecf20Sopenharmony_ci		_exit(t->step);
9938c2ecf20Sopenharmony_ci	} else {
9948c2ecf20Sopenharmony_ci		__wait_for_test(t);
9958c2ecf20Sopenharmony_ci	}
9968c2ecf20Sopenharmony_ci	ksft_print_msg("         %4s  %s%s%s.%s\n", t->passed ? "OK" : "FAIL",
9978c2ecf20Sopenharmony_ci	       f->name, variant->name[0] ? "." : "", variant->name, t->name);
9988c2ecf20Sopenharmony_ci
9998c2ecf20Sopenharmony_ci	if (t->skip)
10008c2ecf20Sopenharmony_ci		ksft_test_result_skip("%s\n", t->results->reason[0] ?
10018c2ecf20Sopenharmony_ci					t->results->reason : "unknown");
10028c2ecf20Sopenharmony_ci	else
10038c2ecf20Sopenharmony_ci		ksft_test_result(t->passed, "%s%s%s.%s\n",
10048c2ecf20Sopenharmony_ci			f->name, variant->name[0] ? "." : "", variant->name, t->name);
10058c2ecf20Sopenharmony_ci}
10068c2ecf20Sopenharmony_ci
10078c2ecf20Sopenharmony_cistatic int test_harness_run(int __attribute__((unused)) argc,
10088c2ecf20Sopenharmony_ci			    char __attribute__((unused)) **argv)
10098c2ecf20Sopenharmony_ci{
10108c2ecf20Sopenharmony_ci	struct __fixture_variant_metadata no_variant = { .name = "", };
10118c2ecf20Sopenharmony_ci	struct __fixture_variant_metadata *v;
10128c2ecf20Sopenharmony_ci	struct __fixture_metadata *f;
10138c2ecf20Sopenharmony_ci	struct __test_results *results;
10148c2ecf20Sopenharmony_ci	struct __test_metadata *t;
10158c2ecf20Sopenharmony_ci	int ret = 0;
10168c2ecf20Sopenharmony_ci	unsigned int case_count = 0, test_count = 0;
10178c2ecf20Sopenharmony_ci	unsigned int count = 0;
10188c2ecf20Sopenharmony_ci	unsigned int pass_count = 0;
10198c2ecf20Sopenharmony_ci
10208c2ecf20Sopenharmony_ci	for (f = __fixture_list; f; f = f->next) {
10218c2ecf20Sopenharmony_ci		for (v = f->variant ?: &no_variant; v; v = v->next) {
10228c2ecf20Sopenharmony_ci			case_count++;
10238c2ecf20Sopenharmony_ci			for (t = f->tests; t; t = t->next)
10248c2ecf20Sopenharmony_ci				test_count++;
10258c2ecf20Sopenharmony_ci		}
10268c2ecf20Sopenharmony_ci	}
10278c2ecf20Sopenharmony_ci
10288c2ecf20Sopenharmony_ci	results = mmap(NULL, sizeof(*results), PROT_READ | PROT_WRITE,
10298c2ecf20Sopenharmony_ci		       MAP_SHARED | MAP_ANONYMOUS, -1, 0);
10308c2ecf20Sopenharmony_ci
10318c2ecf20Sopenharmony_ci	ksft_print_header();
10328c2ecf20Sopenharmony_ci	ksft_set_plan(test_count);
10338c2ecf20Sopenharmony_ci	ksft_print_msg("Starting %u tests from %u test cases.\n",
10348c2ecf20Sopenharmony_ci	       test_count, case_count);
10358c2ecf20Sopenharmony_ci	for (f = __fixture_list; f; f = f->next) {
10368c2ecf20Sopenharmony_ci		for (v = f->variant ?: &no_variant; v; v = v->next) {
10378c2ecf20Sopenharmony_ci			for (t = f->tests; t; t = t->next) {
10388c2ecf20Sopenharmony_ci				count++;
10398c2ecf20Sopenharmony_ci				t->results = results;
10408c2ecf20Sopenharmony_ci				__run_test(f, v, t);
10418c2ecf20Sopenharmony_ci				t->results = NULL;
10428c2ecf20Sopenharmony_ci				if (t->passed)
10438c2ecf20Sopenharmony_ci					pass_count++;
10448c2ecf20Sopenharmony_ci				else
10458c2ecf20Sopenharmony_ci					ret = 1;
10468c2ecf20Sopenharmony_ci			}
10478c2ecf20Sopenharmony_ci		}
10488c2ecf20Sopenharmony_ci	}
10498c2ecf20Sopenharmony_ci	munmap(results, sizeof(*results));
10508c2ecf20Sopenharmony_ci
10518c2ecf20Sopenharmony_ci	ksft_print_msg("%s: %u / %u tests passed.\n", ret ? "FAILED" : "PASSED",
10528c2ecf20Sopenharmony_ci			pass_count, count);
10538c2ecf20Sopenharmony_ci	ksft_exit(ret == 0);
10548c2ecf20Sopenharmony_ci
10558c2ecf20Sopenharmony_ci	/* unreachable */
10568c2ecf20Sopenharmony_ci	return KSFT_FAIL;
10578c2ecf20Sopenharmony_ci}
10588c2ecf20Sopenharmony_ci
10598c2ecf20Sopenharmony_cistatic void __attribute__((constructor)) __constructor_order_first(void)
10608c2ecf20Sopenharmony_ci{
10618c2ecf20Sopenharmony_ci	if (!__constructor_order)
10628c2ecf20Sopenharmony_ci		__constructor_order = _CONSTRUCTOR_ORDER_FORWARD;
10638c2ecf20Sopenharmony_ci}
10648c2ecf20Sopenharmony_ci
10658c2ecf20Sopenharmony_ci#endif  /* __KSELFTEST_HARNESS_H */
1066