162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * kselftest_harness.h: simple C unit test helper.
662306a36Sopenharmony_ci *
762306a36Sopenharmony_ci * See documentation in Documentation/dev-tools/kselftest.rst
862306a36Sopenharmony_ci *
962306a36Sopenharmony_ci * API inspired by code.google.com/p/googletest
1062306a36Sopenharmony_ci */
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_ci/**
1362306a36Sopenharmony_ci * DOC: example
1462306a36Sopenharmony_ci *
1562306a36Sopenharmony_ci * .. code-block:: c
1662306a36Sopenharmony_ci *
1762306a36Sopenharmony_ci *    #include "../kselftest_harness.h"
1862306a36Sopenharmony_ci *
1962306a36Sopenharmony_ci *    TEST(standalone_test) {
2062306a36Sopenharmony_ci *      do_some_stuff;
2162306a36Sopenharmony_ci *      EXPECT_GT(10, stuff) {
2262306a36Sopenharmony_ci *         stuff_state_t state;
2362306a36Sopenharmony_ci *         enumerate_stuff_state(&state);
2462306a36Sopenharmony_ci *         TH_LOG("expectation failed with state: %s", state.msg);
2562306a36Sopenharmony_ci *      }
2662306a36Sopenharmony_ci *      more_stuff;
2762306a36Sopenharmony_ci *      ASSERT_NE(some_stuff, NULL) TH_LOG("how did it happen?!");
2862306a36Sopenharmony_ci *      last_stuff;
2962306a36Sopenharmony_ci *      EXPECT_EQ(0, last_stuff);
3062306a36Sopenharmony_ci *    }
3162306a36Sopenharmony_ci *
3262306a36Sopenharmony_ci *    FIXTURE(my_fixture) {
3362306a36Sopenharmony_ci *      mytype_t *data;
3462306a36Sopenharmony_ci *      int awesomeness_level;
3562306a36Sopenharmony_ci *    };
3662306a36Sopenharmony_ci *    FIXTURE_SETUP(my_fixture) {
3762306a36Sopenharmony_ci *      self->data = mytype_new();
3862306a36Sopenharmony_ci *      ASSERT_NE(NULL, self->data);
3962306a36Sopenharmony_ci *    }
4062306a36Sopenharmony_ci *    FIXTURE_TEARDOWN(my_fixture) {
4162306a36Sopenharmony_ci *      mytype_free(self->data);
4262306a36Sopenharmony_ci *    }
4362306a36Sopenharmony_ci *    TEST_F(my_fixture, data_is_good) {
4462306a36Sopenharmony_ci *      EXPECT_EQ(1, is_my_data_good(self->data));
4562306a36Sopenharmony_ci *    }
4662306a36Sopenharmony_ci *
4762306a36Sopenharmony_ci *    TEST_HARNESS_MAIN
4862306a36Sopenharmony_ci */
4962306a36Sopenharmony_ci
5062306a36Sopenharmony_ci#ifndef __KSELFTEST_HARNESS_H
5162306a36Sopenharmony_ci#define __KSELFTEST_HARNESS_H
5262306a36Sopenharmony_ci
5362306a36Sopenharmony_ci#ifndef _GNU_SOURCE
5462306a36Sopenharmony_ci#define _GNU_SOURCE
5562306a36Sopenharmony_ci#endif
5662306a36Sopenharmony_ci#include <asm/types.h>
5762306a36Sopenharmony_ci#include <ctype.h>
5862306a36Sopenharmony_ci#include <errno.h>
5962306a36Sopenharmony_ci#include <stdbool.h>
6062306a36Sopenharmony_ci#include <stdint.h>
6162306a36Sopenharmony_ci#include <stdio.h>
6262306a36Sopenharmony_ci#include <stdlib.h>
6362306a36Sopenharmony_ci#include <string.h>
6462306a36Sopenharmony_ci#include <sys/mman.h>
6562306a36Sopenharmony_ci#include <sys/types.h>
6662306a36Sopenharmony_ci#include <sys/wait.h>
6762306a36Sopenharmony_ci#include <unistd.h>
6862306a36Sopenharmony_ci#include <setjmp.h>
6962306a36Sopenharmony_ci
7062306a36Sopenharmony_ci#include "kselftest.h"
7162306a36Sopenharmony_ci
7262306a36Sopenharmony_ci#define TEST_TIMEOUT_DEFAULT 30
7362306a36Sopenharmony_ci
7462306a36Sopenharmony_ci/* Utilities exposed to the test definitions */
7562306a36Sopenharmony_ci#ifndef TH_LOG_STREAM
7662306a36Sopenharmony_ci#  define TH_LOG_STREAM stderr
7762306a36Sopenharmony_ci#endif
7862306a36Sopenharmony_ci
7962306a36Sopenharmony_ci#ifndef TH_LOG_ENABLED
8062306a36Sopenharmony_ci#  define TH_LOG_ENABLED 1
8162306a36Sopenharmony_ci#endif
8262306a36Sopenharmony_ci
8362306a36Sopenharmony_ci/**
8462306a36Sopenharmony_ci * TH_LOG()
8562306a36Sopenharmony_ci *
8662306a36Sopenharmony_ci * @fmt: format string
8762306a36Sopenharmony_ci * @...: optional arguments
8862306a36Sopenharmony_ci *
8962306a36Sopenharmony_ci * .. code-block:: c
9062306a36Sopenharmony_ci *
9162306a36Sopenharmony_ci *     TH_LOG(format, ...)
9262306a36Sopenharmony_ci *
9362306a36Sopenharmony_ci * Optional debug logging function available for use in tests.
9462306a36Sopenharmony_ci * Logging may be enabled or disabled by defining TH_LOG_ENABLED.
9562306a36Sopenharmony_ci * E.g., #define TH_LOG_ENABLED 1
9662306a36Sopenharmony_ci *
9762306a36Sopenharmony_ci * If no definition is provided, logging is enabled by default.
9862306a36Sopenharmony_ci *
9962306a36Sopenharmony_ci * If there is no way to print an error message for the process running the
10062306a36Sopenharmony_ci * test (e.g. not allowed to write to stderr), it is still possible to get the
10162306a36Sopenharmony_ci * ASSERT_* number for which the test failed.  This behavior can be enabled by
10262306a36Sopenharmony_ci * writing `_metadata->no_print = true;` before the check sequence that is
10362306a36Sopenharmony_ci * unable to print.  When an error occur, instead of printing an error message
10462306a36Sopenharmony_ci * and calling `abort(3)`, the test process call `_exit(2)` with the assert
10562306a36Sopenharmony_ci * number as argument, which is then printed by the parent process.
10662306a36Sopenharmony_ci */
10762306a36Sopenharmony_ci#define TH_LOG(fmt, ...) do { \
10862306a36Sopenharmony_ci	if (TH_LOG_ENABLED) \
10962306a36Sopenharmony_ci		__TH_LOG(fmt, ##__VA_ARGS__); \
11062306a36Sopenharmony_ci} while (0)
11162306a36Sopenharmony_ci
11262306a36Sopenharmony_ci/* Unconditional logger for internal use. */
11362306a36Sopenharmony_ci#define __TH_LOG(fmt, ...) \
11462306a36Sopenharmony_ci		fprintf(TH_LOG_STREAM, "# %s:%d:%s:" fmt "\n", \
11562306a36Sopenharmony_ci			__FILE__, __LINE__, _metadata->name, ##__VA_ARGS__)
11662306a36Sopenharmony_ci
11762306a36Sopenharmony_ci/**
11862306a36Sopenharmony_ci * SKIP()
11962306a36Sopenharmony_ci *
12062306a36Sopenharmony_ci * @statement: statement to run after reporting SKIP
12162306a36Sopenharmony_ci * @fmt: format string
12262306a36Sopenharmony_ci * @...: optional arguments
12362306a36Sopenharmony_ci *
12462306a36Sopenharmony_ci * .. code-block:: c
12562306a36Sopenharmony_ci *
12662306a36Sopenharmony_ci *     SKIP(statement, fmt, ...);
12762306a36Sopenharmony_ci *
12862306a36Sopenharmony_ci * This forces a "pass" after reporting why something is being skipped
12962306a36Sopenharmony_ci * and runs "statement", which is usually "return" or "goto skip".
13062306a36Sopenharmony_ci */
13162306a36Sopenharmony_ci#define SKIP(statement, fmt, ...) do { \
13262306a36Sopenharmony_ci	snprintf(_metadata->results->reason, \
13362306a36Sopenharmony_ci		 sizeof(_metadata->results->reason), fmt, ##__VA_ARGS__); \
13462306a36Sopenharmony_ci	if (TH_LOG_ENABLED) { \
13562306a36Sopenharmony_ci		fprintf(TH_LOG_STREAM, "#      SKIP      %s\n", \
13662306a36Sopenharmony_ci			_metadata->results->reason); \
13762306a36Sopenharmony_ci	} \
13862306a36Sopenharmony_ci	_metadata->passed = 1; \
13962306a36Sopenharmony_ci	_metadata->skip = 1; \
14062306a36Sopenharmony_ci	_metadata->trigger = 0; \
14162306a36Sopenharmony_ci	statement; \
14262306a36Sopenharmony_ci} while (0)
14362306a36Sopenharmony_ci
14462306a36Sopenharmony_ci/**
14562306a36Sopenharmony_ci * TEST() - Defines the test function and creates the registration
14662306a36Sopenharmony_ci * stub
14762306a36Sopenharmony_ci *
14862306a36Sopenharmony_ci * @test_name: test name
14962306a36Sopenharmony_ci *
15062306a36Sopenharmony_ci * .. code-block:: c
15162306a36Sopenharmony_ci *
15262306a36Sopenharmony_ci *     TEST(name) { implementation }
15362306a36Sopenharmony_ci *
15462306a36Sopenharmony_ci * Defines a test by name.
15562306a36Sopenharmony_ci * Names must be unique and tests must not be run in parallel.  The
15662306a36Sopenharmony_ci * implementation containing block is a function and scoping should be treated
15762306a36Sopenharmony_ci * as such.  Returning early may be performed with a bare "return;" statement.
15862306a36Sopenharmony_ci *
15962306a36Sopenharmony_ci * EXPECT_* and ASSERT_* are valid in a TEST() { } context.
16062306a36Sopenharmony_ci */
16162306a36Sopenharmony_ci#define TEST(test_name) __TEST_IMPL(test_name, -1)
16262306a36Sopenharmony_ci
16362306a36Sopenharmony_ci/**
16462306a36Sopenharmony_ci * TEST_SIGNAL()
16562306a36Sopenharmony_ci *
16662306a36Sopenharmony_ci * @test_name: test name
16762306a36Sopenharmony_ci * @signal: signal number
16862306a36Sopenharmony_ci *
16962306a36Sopenharmony_ci * .. code-block:: c
17062306a36Sopenharmony_ci *
17162306a36Sopenharmony_ci *     TEST_SIGNAL(name, signal) { implementation }
17262306a36Sopenharmony_ci *
17362306a36Sopenharmony_ci * Defines a test by name and the expected term signal.
17462306a36Sopenharmony_ci * Names must be unique and tests must not be run in parallel.  The
17562306a36Sopenharmony_ci * implementation containing block is a function and scoping should be treated
17662306a36Sopenharmony_ci * as such.  Returning early may be performed with a bare "return;" statement.
17762306a36Sopenharmony_ci *
17862306a36Sopenharmony_ci * EXPECT_* and ASSERT_* are valid in a TEST() { } context.
17962306a36Sopenharmony_ci */
18062306a36Sopenharmony_ci#define TEST_SIGNAL(test_name, signal) __TEST_IMPL(test_name, signal)
18162306a36Sopenharmony_ci
18262306a36Sopenharmony_ci#define __TEST_IMPL(test_name, _signal) \
18362306a36Sopenharmony_ci	static void test_name(struct __test_metadata *_metadata); \
18462306a36Sopenharmony_ci	static inline void wrapper_##test_name( \
18562306a36Sopenharmony_ci		struct __test_metadata *_metadata, \
18662306a36Sopenharmony_ci		struct __fixture_variant_metadata *variant) \
18762306a36Sopenharmony_ci	{ \
18862306a36Sopenharmony_ci		_metadata->setup_completed = true; \
18962306a36Sopenharmony_ci		if (setjmp(_metadata->env) == 0) \
19062306a36Sopenharmony_ci			test_name(_metadata); \
19162306a36Sopenharmony_ci		__test_check_assert(_metadata); \
19262306a36Sopenharmony_ci	} \
19362306a36Sopenharmony_ci	static struct __test_metadata _##test_name##_object = \
19462306a36Sopenharmony_ci		{ .name = #test_name, \
19562306a36Sopenharmony_ci		  .fn = &wrapper_##test_name, \
19662306a36Sopenharmony_ci		  .fixture = &_fixture_global, \
19762306a36Sopenharmony_ci		  .termsig = _signal, \
19862306a36Sopenharmony_ci		  .timeout = TEST_TIMEOUT_DEFAULT, }; \
19962306a36Sopenharmony_ci	static void __attribute__((constructor)) _register_##test_name(void) \
20062306a36Sopenharmony_ci	{ \
20162306a36Sopenharmony_ci		__register_test(&_##test_name##_object); \
20262306a36Sopenharmony_ci	} \
20362306a36Sopenharmony_ci	static void test_name( \
20462306a36Sopenharmony_ci		struct __test_metadata __attribute__((unused)) *_metadata)
20562306a36Sopenharmony_ci
20662306a36Sopenharmony_ci/**
20762306a36Sopenharmony_ci * FIXTURE_DATA() - Wraps the struct name so we have one less
20862306a36Sopenharmony_ci * argument to pass around
20962306a36Sopenharmony_ci *
21062306a36Sopenharmony_ci * @datatype_name: datatype name
21162306a36Sopenharmony_ci *
21262306a36Sopenharmony_ci * .. code-block:: c
21362306a36Sopenharmony_ci *
21462306a36Sopenharmony_ci *     FIXTURE_DATA(datatype_name)
21562306a36Sopenharmony_ci *
21662306a36Sopenharmony_ci * Almost always, you want just FIXTURE() instead (see below).
21762306a36Sopenharmony_ci * This call may be used when the type of the fixture data
21862306a36Sopenharmony_ci * is needed.  In general, this should not be needed unless
21962306a36Sopenharmony_ci * the *self* is being passed to a helper directly.
22062306a36Sopenharmony_ci */
22162306a36Sopenharmony_ci#define FIXTURE_DATA(datatype_name) struct _test_data_##datatype_name
22262306a36Sopenharmony_ci
22362306a36Sopenharmony_ci/**
22462306a36Sopenharmony_ci * FIXTURE() - Called once per fixture to setup the data and
22562306a36Sopenharmony_ci * register
22662306a36Sopenharmony_ci *
22762306a36Sopenharmony_ci * @fixture_name: fixture name
22862306a36Sopenharmony_ci *
22962306a36Sopenharmony_ci * .. code-block:: c
23062306a36Sopenharmony_ci *
23162306a36Sopenharmony_ci *     FIXTURE(fixture_name) {
23262306a36Sopenharmony_ci *       type property1;
23362306a36Sopenharmony_ci *       ...
23462306a36Sopenharmony_ci *     };
23562306a36Sopenharmony_ci *
23662306a36Sopenharmony_ci * Defines the data provided to TEST_F()-defined tests as *self*.  It should be
23762306a36Sopenharmony_ci * populated and cleaned up using FIXTURE_SETUP() and FIXTURE_TEARDOWN().
23862306a36Sopenharmony_ci */
23962306a36Sopenharmony_ci#define FIXTURE(fixture_name) \
24062306a36Sopenharmony_ci	FIXTURE_VARIANT(fixture_name); \
24162306a36Sopenharmony_ci	static struct __fixture_metadata _##fixture_name##_fixture_object = \
24262306a36Sopenharmony_ci		{ .name =  #fixture_name, }; \
24362306a36Sopenharmony_ci	static void __attribute__((constructor)) \
24462306a36Sopenharmony_ci	_register_##fixture_name##_data(void) \
24562306a36Sopenharmony_ci	{ \
24662306a36Sopenharmony_ci		__register_fixture(&_##fixture_name##_fixture_object); \
24762306a36Sopenharmony_ci	} \
24862306a36Sopenharmony_ci	FIXTURE_DATA(fixture_name)
24962306a36Sopenharmony_ci
25062306a36Sopenharmony_ci/**
25162306a36Sopenharmony_ci * FIXTURE_SETUP() - Prepares the setup function for the fixture.
25262306a36Sopenharmony_ci * *_metadata* is included so that EXPECT_*, ASSERT_* etc. work correctly.
25362306a36Sopenharmony_ci *
25462306a36Sopenharmony_ci * @fixture_name: fixture name
25562306a36Sopenharmony_ci *
25662306a36Sopenharmony_ci * .. code-block:: c
25762306a36Sopenharmony_ci *
25862306a36Sopenharmony_ci *     FIXTURE_SETUP(fixture_name) { implementation }
25962306a36Sopenharmony_ci *
26062306a36Sopenharmony_ci * Populates the required "setup" function for a fixture.  An instance of the
26162306a36Sopenharmony_ci * datatype defined with FIXTURE_DATA() will be exposed as *self* for the
26262306a36Sopenharmony_ci * implementation.
26362306a36Sopenharmony_ci *
26462306a36Sopenharmony_ci * ASSERT_* are valid for use in this context and will prempt the execution
26562306a36Sopenharmony_ci * of any dependent fixture tests.
26662306a36Sopenharmony_ci *
26762306a36Sopenharmony_ci * A bare "return;" statement may be used to return early.
26862306a36Sopenharmony_ci */
26962306a36Sopenharmony_ci#define FIXTURE_SETUP(fixture_name) \
27062306a36Sopenharmony_ci	void fixture_name##_setup( \
27162306a36Sopenharmony_ci		struct __test_metadata __attribute__((unused)) *_metadata, \
27262306a36Sopenharmony_ci		FIXTURE_DATA(fixture_name) __attribute__((unused)) *self, \
27362306a36Sopenharmony_ci		const FIXTURE_VARIANT(fixture_name) \
27462306a36Sopenharmony_ci			__attribute__((unused)) *variant)
27562306a36Sopenharmony_ci
27662306a36Sopenharmony_ci/**
27762306a36Sopenharmony_ci * FIXTURE_TEARDOWN()
27862306a36Sopenharmony_ci * *_metadata* is included so that EXPECT_*, ASSERT_* etc. work correctly.
27962306a36Sopenharmony_ci *
28062306a36Sopenharmony_ci * @fixture_name: fixture name
28162306a36Sopenharmony_ci *
28262306a36Sopenharmony_ci * .. code-block:: c
28362306a36Sopenharmony_ci *
28462306a36Sopenharmony_ci *     FIXTURE_TEARDOWN(fixture_name) { implementation }
28562306a36Sopenharmony_ci *
28662306a36Sopenharmony_ci * Populates the required "teardown" function for a fixture.  An instance of the
28762306a36Sopenharmony_ci * datatype defined with FIXTURE_DATA() will be exposed as *self* for the
28862306a36Sopenharmony_ci * implementation to clean up.
28962306a36Sopenharmony_ci *
29062306a36Sopenharmony_ci * A bare "return;" statement may be used to return early.
29162306a36Sopenharmony_ci */
29262306a36Sopenharmony_ci#define FIXTURE_TEARDOWN(fixture_name) \
29362306a36Sopenharmony_ci	void fixture_name##_teardown( \
29462306a36Sopenharmony_ci		struct __test_metadata __attribute__((unused)) *_metadata, \
29562306a36Sopenharmony_ci		FIXTURE_DATA(fixture_name) __attribute__((unused)) *self, \
29662306a36Sopenharmony_ci		const FIXTURE_VARIANT(fixture_name) \
29762306a36Sopenharmony_ci			__attribute__((unused)) *variant)
29862306a36Sopenharmony_ci
29962306a36Sopenharmony_ci/**
30062306a36Sopenharmony_ci * FIXTURE_VARIANT() - Optionally called once per fixture
30162306a36Sopenharmony_ci * to declare fixture variant
30262306a36Sopenharmony_ci *
30362306a36Sopenharmony_ci * @fixture_name: fixture name
30462306a36Sopenharmony_ci *
30562306a36Sopenharmony_ci * .. code-block:: c
30662306a36Sopenharmony_ci *
30762306a36Sopenharmony_ci *     FIXTURE_VARIANT(fixture_name) {
30862306a36Sopenharmony_ci *       type property1;
30962306a36Sopenharmony_ci *       ...
31062306a36Sopenharmony_ci *     };
31162306a36Sopenharmony_ci *
31262306a36Sopenharmony_ci * Defines type of constant parameters provided to FIXTURE_SETUP(), TEST_F() and
31362306a36Sopenharmony_ci * FIXTURE_TEARDOWN as *variant*. Variants allow the same tests to be run with
31462306a36Sopenharmony_ci * different arguments.
31562306a36Sopenharmony_ci */
31662306a36Sopenharmony_ci#define FIXTURE_VARIANT(fixture_name) struct _fixture_variant_##fixture_name
31762306a36Sopenharmony_ci
31862306a36Sopenharmony_ci/**
31962306a36Sopenharmony_ci * FIXTURE_VARIANT_ADD() - Called once per fixture
32062306a36Sopenharmony_ci * variant to setup and register the data
32162306a36Sopenharmony_ci *
32262306a36Sopenharmony_ci * @fixture_name: fixture name
32362306a36Sopenharmony_ci * @variant_name: name of the parameter set
32462306a36Sopenharmony_ci *
32562306a36Sopenharmony_ci * .. code-block:: c
32662306a36Sopenharmony_ci *
32762306a36Sopenharmony_ci *     FIXTURE_VARIANT_ADD(fixture_name, variant_name) {
32862306a36Sopenharmony_ci *       .property1 = val1,
32962306a36Sopenharmony_ci *       ...
33062306a36Sopenharmony_ci *     };
33162306a36Sopenharmony_ci *
33262306a36Sopenharmony_ci * Defines a variant of the test fixture, provided to FIXTURE_SETUP() and
33362306a36Sopenharmony_ci * TEST_F() as *variant*. Tests of each fixture will be run once for each
33462306a36Sopenharmony_ci * variant.
33562306a36Sopenharmony_ci */
33662306a36Sopenharmony_ci#define FIXTURE_VARIANT_ADD(fixture_name, variant_name) \
33762306a36Sopenharmony_ci	extern FIXTURE_VARIANT(fixture_name) \
33862306a36Sopenharmony_ci		_##fixture_name##_##variant_name##_variant; \
33962306a36Sopenharmony_ci	static struct __fixture_variant_metadata \
34062306a36Sopenharmony_ci		_##fixture_name##_##variant_name##_object = \
34162306a36Sopenharmony_ci		{ .name = #variant_name, \
34262306a36Sopenharmony_ci		  .data = &_##fixture_name##_##variant_name##_variant}; \
34362306a36Sopenharmony_ci	static void __attribute__((constructor)) \
34462306a36Sopenharmony_ci		_register_##fixture_name##_##variant_name(void) \
34562306a36Sopenharmony_ci	{ \
34662306a36Sopenharmony_ci		__register_fixture_variant(&_##fixture_name##_fixture_object, \
34762306a36Sopenharmony_ci			&_##fixture_name##_##variant_name##_object);	\
34862306a36Sopenharmony_ci	} \
34962306a36Sopenharmony_ci	FIXTURE_VARIANT(fixture_name) \
35062306a36Sopenharmony_ci		_##fixture_name##_##variant_name##_variant =
35162306a36Sopenharmony_ci
35262306a36Sopenharmony_ci/**
35362306a36Sopenharmony_ci * TEST_F() - Emits test registration and helpers for
35462306a36Sopenharmony_ci * fixture-based test cases
35562306a36Sopenharmony_ci *
35662306a36Sopenharmony_ci * @fixture_name: fixture name
35762306a36Sopenharmony_ci * @test_name: test name
35862306a36Sopenharmony_ci *
35962306a36Sopenharmony_ci * .. code-block:: c
36062306a36Sopenharmony_ci *
36162306a36Sopenharmony_ci *     TEST_F(fixture, name) { implementation }
36262306a36Sopenharmony_ci *
36362306a36Sopenharmony_ci * Defines a test that depends on a fixture (e.g., is part of a test case).
36462306a36Sopenharmony_ci * Very similar to TEST() except that *self* is the setup instance of fixture's
36562306a36Sopenharmony_ci * datatype exposed for use by the implementation.
36662306a36Sopenharmony_ci */
36762306a36Sopenharmony_ci#define TEST_F(fixture_name, test_name) \
36862306a36Sopenharmony_ci	__TEST_F_IMPL(fixture_name, test_name, -1, TEST_TIMEOUT_DEFAULT)
36962306a36Sopenharmony_ci
37062306a36Sopenharmony_ci#define TEST_F_SIGNAL(fixture_name, test_name, signal) \
37162306a36Sopenharmony_ci	__TEST_F_IMPL(fixture_name, test_name, signal, TEST_TIMEOUT_DEFAULT)
37262306a36Sopenharmony_ci
37362306a36Sopenharmony_ci#define TEST_F_TIMEOUT(fixture_name, test_name, timeout) \
37462306a36Sopenharmony_ci	__TEST_F_IMPL(fixture_name, test_name, -1, timeout)
37562306a36Sopenharmony_ci
37662306a36Sopenharmony_ci#define __TEST_F_IMPL(fixture_name, test_name, signal, tmout) \
37762306a36Sopenharmony_ci	static void fixture_name##_##test_name( \
37862306a36Sopenharmony_ci		struct __test_metadata *_metadata, \
37962306a36Sopenharmony_ci		FIXTURE_DATA(fixture_name) *self, \
38062306a36Sopenharmony_ci		const FIXTURE_VARIANT(fixture_name) *variant); \
38162306a36Sopenharmony_ci	static inline void wrapper_##fixture_name##_##test_name( \
38262306a36Sopenharmony_ci		struct __test_metadata *_metadata, \
38362306a36Sopenharmony_ci		struct __fixture_variant_metadata *variant) \
38462306a36Sopenharmony_ci	{ \
38562306a36Sopenharmony_ci		/* fixture data is alloced, setup, and torn down per call. */ \
38662306a36Sopenharmony_ci		FIXTURE_DATA(fixture_name) self; \
38762306a36Sopenharmony_ci		memset(&self, 0, sizeof(FIXTURE_DATA(fixture_name))); \
38862306a36Sopenharmony_ci		if (setjmp(_metadata->env) == 0) { \
38962306a36Sopenharmony_ci			fixture_name##_setup(_metadata, &self, variant->data); \
39062306a36Sopenharmony_ci			/* Let setup failure terminate early. */ \
39162306a36Sopenharmony_ci                       if (!_metadata->passed || _metadata->skip) \
39262306a36Sopenharmony_ci				return; \
39362306a36Sopenharmony_ci			_metadata->setup_completed = true; \
39462306a36Sopenharmony_ci			fixture_name##_##test_name(_metadata, &self, variant->data); \
39562306a36Sopenharmony_ci		} \
39662306a36Sopenharmony_ci		if (_metadata->setup_completed) \
39762306a36Sopenharmony_ci			fixture_name##_teardown(_metadata, &self, variant->data); \
39862306a36Sopenharmony_ci		__test_check_assert(_metadata); \
39962306a36Sopenharmony_ci	} \
40062306a36Sopenharmony_ci	static struct __test_metadata \
40162306a36Sopenharmony_ci		      _##fixture_name##_##test_name##_object = { \
40262306a36Sopenharmony_ci		.name = #test_name, \
40362306a36Sopenharmony_ci		.fn = &wrapper_##fixture_name##_##test_name, \
40462306a36Sopenharmony_ci		.fixture = &_##fixture_name##_fixture_object, \
40562306a36Sopenharmony_ci		.termsig = signal, \
40662306a36Sopenharmony_ci		.timeout = tmout, \
40762306a36Sopenharmony_ci	 }; \
40862306a36Sopenharmony_ci	static void __attribute__((constructor)) \
40962306a36Sopenharmony_ci			_register_##fixture_name##_##test_name(void) \
41062306a36Sopenharmony_ci	{ \
41162306a36Sopenharmony_ci		__register_test(&_##fixture_name##_##test_name##_object); \
41262306a36Sopenharmony_ci	} \
41362306a36Sopenharmony_ci	static void fixture_name##_##test_name( \
41462306a36Sopenharmony_ci		struct __test_metadata __attribute__((unused)) *_metadata, \
41562306a36Sopenharmony_ci		FIXTURE_DATA(fixture_name) __attribute__((unused)) *self, \
41662306a36Sopenharmony_ci		const FIXTURE_VARIANT(fixture_name) \
41762306a36Sopenharmony_ci			__attribute__((unused)) *variant)
41862306a36Sopenharmony_ci
41962306a36Sopenharmony_ci/**
42062306a36Sopenharmony_ci * TEST_HARNESS_MAIN - Simple wrapper to run the test harness
42162306a36Sopenharmony_ci *
42262306a36Sopenharmony_ci * .. code-block:: c
42362306a36Sopenharmony_ci *
42462306a36Sopenharmony_ci *     TEST_HARNESS_MAIN
42562306a36Sopenharmony_ci *
42662306a36Sopenharmony_ci * Use once to append a main() to the test file.
42762306a36Sopenharmony_ci */
42862306a36Sopenharmony_ci#define TEST_HARNESS_MAIN \
42962306a36Sopenharmony_ci	static void __attribute__((constructor)) \
43062306a36Sopenharmony_ci	__constructor_order_last(void) \
43162306a36Sopenharmony_ci	{ \
43262306a36Sopenharmony_ci		if (!__constructor_order) \
43362306a36Sopenharmony_ci			__constructor_order = _CONSTRUCTOR_ORDER_BACKWARD; \
43462306a36Sopenharmony_ci	} \
43562306a36Sopenharmony_ci	int main(int argc, char **argv) { \
43662306a36Sopenharmony_ci		return test_harness_run(argc, argv); \
43762306a36Sopenharmony_ci	}
43862306a36Sopenharmony_ci
43962306a36Sopenharmony_ci/**
44062306a36Sopenharmony_ci * DOC: operators
44162306a36Sopenharmony_ci *
44262306a36Sopenharmony_ci * Operators for use in TEST() and TEST_F().
44362306a36Sopenharmony_ci * ASSERT_* calls will stop test execution immediately.
44462306a36Sopenharmony_ci * EXPECT_* calls will emit a failure warning, note it, and continue.
44562306a36Sopenharmony_ci */
44662306a36Sopenharmony_ci
44762306a36Sopenharmony_ci/**
44862306a36Sopenharmony_ci * ASSERT_EQ()
44962306a36Sopenharmony_ci *
45062306a36Sopenharmony_ci * @expected: expected value
45162306a36Sopenharmony_ci * @seen: measured value
45262306a36Sopenharmony_ci *
45362306a36Sopenharmony_ci * ASSERT_EQ(expected, measured): expected == measured
45462306a36Sopenharmony_ci */
45562306a36Sopenharmony_ci#define ASSERT_EQ(expected, seen) \
45662306a36Sopenharmony_ci	__EXPECT(expected, #expected, seen, #seen, ==, 1)
45762306a36Sopenharmony_ci
45862306a36Sopenharmony_ci/**
45962306a36Sopenharmony_ci * ASSERT_NE()
46062306a36Sopenharmony_ci *
46162306a36Sopenharmony_ci * @expected: expected value
46262306a36Sopenharmony_ci * @seen: measured value
46362306a36Sopenharmony_ci *
46462306a36Sopenharmony_ci * ASSERT_NE(expected, measured): expected != measured
46562306a36Sopenharmony_ci */
46662306a36Sopenharmony_ci#define ASSERT_NE(expected, seen) \
46762306a36Sopenharmony_ci	__EXPECT(expected, #expected, seen, #seen, !=, 1)
46862306a36Sopenharmony_ci
46962306a36Sopenharmony_ci/**
47062306a36Sopenharmony_ci * ASSERT_LT()
47162306a36Sopenharmony_ci *
47262306a36Sopenharmony_ci * @expected: expected value
47362306a36Sopenharmony_ci * @seen: measured value
47462306a36Sopenharmony_ci *
47562306a36Sopenharmony_ci * ASSERT_LT(expected, measured): expected < measured
47662306a36Sopenharmony_ci */
47762306a36Sopenharmony_ci#define ASSERT_LT(expected, seen) \
47862306a36Sopenharmony_ci	__EXPECT(expected, #expected, seen, #seen, <, 1)
47962306a36Sopenharmony_ci
48062306a36Sopenharmony_ci/**
48162306a36Sopenharmony_ci * ASSERT_LE()
48262306a36Sopenharmony_ci *
48362306a36Sopenharmony_ci * @expected: expected value
48462306a36Sopenharmony_ci * @seen: measured value
48562306a36Sopenharmony_ci *
48662306a36Sopenharmony_ci * ASSERT_LE(expected, measured): expected <= measured
48762306a36Sopenharmony_ci */
48862306a36Sopenharmony_ci#define ASSERT_LE(expected, seen) \
48962306a36Sopenharmony_ci	__EXPECT(expected, #expected, seen, #seen, <=, 1)
49062306a36Sopenharmony_ci
49162306a36Sopenharmony_ci/**
49262306a36Sopenharmony_ci * ASSERT_GT()
49362306a36Sopenharmony_ci *
49462306a36Sopenharmony_ci * @expected: expected value
49562306a36Sopenharmony_ci * @seen: measured value
49662306a36Sopenharmony_ci *
49762306a36Sopenharmony_ci * ASSERT_GT(expected, measured): expected > measured
49862306a36Sopenharmony_ci */
49962306a36Sopenharmony_ci#define ASSERT_GT(expected, seen) \
50062306a36Sopenharmony_ci	__EXPECT(expected, #expected, seen, #seen, >, 1)
50162306a36Sopenharmony_ci
50262306a36Sopenharmony_ci/**
50362306a36Sopenharmony_ci * ASSERT_GE()
50462306a36Sopenharmony_ci *
50562306a36Sopenharmony_ci * @expected: expected value
50662306a36Sopenharmony_ci * @seen: measured value
50762306a36Sopenharmony_ci *
50862306a36Sopenharmony_ci * ASSERT_GE(expected, measured): expected >= measured
50962306a36Sopenharmony_ci */
51062306a36Sopenharmony_ci#define ASSERT_GE(expected, seen) \
51162306a36Sopenharmony_ci	__EXPECT(expected, #expected, seen, #seen, >=, 1)
51262306a36Sopenharmony_ci
51362306a36Sopenharmony_ci/**
51462306a36Sopenharmony_ci * ASSERT_NULL()
51562306a36Sopenharmony_ci *
51662306a36Sopenharmony_ci * @seen: measured value
51762306a36Sopenharmony_ci *
51862306a36Sopenharmony_ci * ASSERT_NULL(measured): NULL == measured
51962306a36Sopenharmony_ci */
52062306a36Sopenharmony_ci#define ASSERT_NULL(seen) \
52162306a36Sopenharmony_ci	__EXPECT(NULL, "NULL", seen, #seen, ==, 1)
52262306a36Sopenharmony_ci
52362306a36Sopenharmony_ci/**
52462306a36Sopenharmony_ci * ASSERT_TRUE()
52562306a36Sopenharmony_ci *
52662306a36Sopenharmony_ci * @seen: measured value
52762306a36Sopenharmony_ci *
52862306a36Sopenharmony_ci * ASSERT_TRUE(measured): measured != 0
52962306a36Sopenharmony_ci */
53062306a36Sopenharmony_ci#define ASSERT_TRUE(seen) \
53162306a36Sopenharmony_ci	__EXPECT(0, "0", seen, #seen, !=, 1)
53262306a36Sopenharmony_ci
53362306a36Sopenharmony_ci/**
53462306a36Sopenharmony_ci * ASSERT_FALSE()
53562306a36Sopenharmony_ci *
53662306a36Sopenharmony_ci * @seen: measured value
53762306a36Sopenharmony_ci *
53862306a36Sopenharmony_ci * ASSERT_FALSE(measured): measured == 0
53962306a36Sopenharmony_ci */
54062306a36Sopenharmony_ci#define ASSERT_FALSE(seen) \
54162306a36Sopenharmony_ci	__EXPECT(0, "0", seen, #seen, ==, 1)
54262306a36Sopenharmony_ci
54362306a36Sopenharmony_ci/**
54462306a36Sopenharmony_ci * ASSERT_STREQ()
54562306a36Sopenharmony_ci *
54662306a36Sopenharmony_ci * @expected: expected value
54762306a36Sopenharmony_ci * @seen: measured value
54862306a36Sopenharmony_ci *
54962306a36Sopenharmony_ci * ASSERT_STREQ(expected, measured): !strcmp(expected, measured)
55062306a36Sopenharmony_ci */
55162306a36Sopenharmony_ci#define ASSERT_STREQ(expected, seen) \
55262306a36Sopenharmony_ci	__EXPECT_STR(expected, seen, ==, 1)
55362306a36Sopenharmony_ci
55462306a36Sopenharmony_ci/**
55562306a36Sopenharmony_ci * ASSERT_STRNE()
55662306a36Sopenharmony_ci *
55762306a36Sopenharmony_ci * @expected: expected value
55862306a36Sopenharmony_ci * @seen: measured value
55962306a36Sopenharmony_ci *
56062306a36Sopenharmony_ci * ASSERT_STRNE(expected, measured): strcmp(expected, measured)
56162306a36Sopenharmony_ci */
56262306a36Sopenharmony_ci#define ASSERT_STRNE(expected, seen) \
56362306a36Sopenharmony_ci	__EXPECT_STR(expected, seen, !=, 1)
56462306a36Sopenharmony_ci
56562306a36Sopenharmony_ci/**
56662306a36Sopenharmony_ci * EXPECT_EQ()
56762306a36Sopenharmony_ci *
56862306a36Sopenharmony_ci * @expected: expected value
56962306a36Sopenharmony_ci * @seen: measured value
57062306a36Sopenharmony_ci *
57162306a36Sopenharmony_ci * EXPECT_EQ(expected, measured): expected == measured
57262306a36Sopenharmony_ci */
57362306a36Sopenharmony_ci#define EXPECT_EQ(expected, seen) \
57462306a36Sopenharmony_ci	__EXPECT(expected, #expected, seen, #seen, ==, 0)
57562306a36Sopenharmony_ci
57662306a36Sopenharmony_ci/**
57762306a36Sopenharmony_ci * EXPECT_NE()
57862306a36Sopenharmony_ci *
57962306a36Sopenharmony_ci * @expected: expected value
58062306a36Sopenharmony_ci * @seen: measured value
58162306a36Sopenharmony_ci *
58262306a36Sopenharmony_ci * EXPECT_NE(expected, measured): expected != measured
58362306a36Sopenharmony_ci */
58462306a36Sopenharmony_ci#define EXPECT_NE(expected, seen) \
58562306a36Sopenharmony_ci	__EXPECT(expected, #expected, seen, #seen, !=, 0)
58662306a36Sopenharmony_ci
58762306a36Sopenharmony_ci/**
58862306a36Sopenharmony_ci * EXPECT_LT()
58962306a36Sopenharmony_ci *
59062306a36Sopenharmony_ci * @expected: expected value
59162306a36Sopenharmony_ci * @seen: measured value
59262306a36Sopenharmony_ci *
59362306a36Sopenharmony_ci * EXPECT_LT(expected, measured): expected < measured
59462306a36Sopenharmony_ci */
59562306a36Sopenharmony_ci#define EXPECT_LT(expected, seen) \
59662306a36Sopenharmony_ci	__EXPECT(expected, #expected, seen, #seen, <, 0)
59762306a36Sopenharmony_ci
59862306a36Sopenharmony_ci/**
59962306a36Sopenharmony_ci * EXPECT_LE()
60062306a36Sopenharmony_ci *
60162306a36Sopenharmony_ci * @expected: expected value
60262306a36Sopenharmony_ci * @seen: measured value
60362306a36Sopenharmony_ci *
60462306a36Sopenharmony_ci * EXPECT_LE(expected, measured): expected <= measured
60562306a36Sopenharmony_ci */
60662306a36Sopenharmony_ci#define EXPECT_LE(expected, seen) \
60762306a36Sopenharmony_ci	__EXPECT(expected, #expected, seen, #seen, <=, 0)
60862306a36Sopenharmony_ci
60962306a36Sopenharmony_ci/**
61062306a36Sopenharmony_ci * EXPECT_GT()
61162306a36Sopenharmony_ci *
61262306a36Sopenharmony_ci * @expected: expected value
61362306a36Sopenharmony_ci * @seen: measured value
61462306a36Sopenharmony_ci *
61562306a36Sopenharmony_ci * EXPECT_GT(expected, measured): expected > measured
61662306a36Sopenharmony_ci */
61762306a36Sopenharmony_ci#define EXPECT_GT(expected, seen) \
61862306a36Sopenharmony_ci	__EXPECT(expected, #expected, seen, #seen, >, 0)
61962306a36Sopenharmony_ci
62062306a36Sopenharmony_ci/**
62162306a36Sopenharmony_ci * EXPECT_GE()
62262306a36Sopenharmony_ci *
62362306a36Sopenharmony_ci * @expected: expected value
62462306a36Sopenharmony_ci * @seen: measured value
62562306a36Sopenharmony_ci *
62662306a36Sopenharmony_ci * EXPECT_GE(expected, measured): expected >= measured
62762306a36Sopenharmony_ci */
62862306a36Sopenharmony_ci#define EXPECT_GE(expected, seen) \
62962306a36Sopenharmony_ci	__EXPECT(expected, #expected, seen, #seen, >=, 0)
63062306a36Sopenharmony_ci
63162306a36Sopenharmony_ci/**
63262306a36Sopenharmony_ci * EXPECT_NULL()
63362306a36Sopenharmony_ci *
63462306a36Sopenharmony_ci * @seen: measured value
63562306a36Sopenharmony_ci *
63662306a36Sopenharmony_ci * EXPECT_NULL(measured): NULL == measured
63762306a36Sopenharmony_ci */
63862306a36Sopenharmony_ci#define EXPECT_NULL(seen) \
63962306a36Sopenharmony_ci	__EXPECT(NULL, "NULL", seen, #seen, ==, 0)
64062306a36Sopenharmony_ci
64162306a36Sopenharmony_ci/**
64262306a36Sopenharmony_ci * EXPECT_TRUE()
64362306a36Sopenharmony_ci *
64462306a36Sopenharmony_ci * @seen: measured value
64562306a36Sopenharmony_ci *
64662306a36Sopenharmony_ci * EXPECT_TRUE(measured): 0 != measured
64762306a36Sopenharmony_ci */
64862306a36Sopenharmony_ci#define EXPECT_TRUE(seen) \
64962306a36Sopenharmony_ci	__EXPECT(0, "0", seen, #seen, !=, 0)
65062306a36Sopenharmony_ci
65162306a36Sopenharmony_ci/**
65262306a36Sopenharmony_ci * EXPECT_FALSE()
65362306a36Sopenharmony_ci *
65462306a36Sopenharmony_ci * @seen: measured value
65562306a36Sopenharmony_ci *
65662306a36Sopenharmony_ci * EXPECT_FALSE(measured): 0 == measured
65762306a36Sopenharmony_ci */
65862306a36Sopenharmony_ci#define EXPECT_FALSE(seen) \
65962306a36Sopenharmony_ci	__EXPECT(0, "0", seen, #seen, ==, 0)
66062306a36Sopenharmony_ci
66162306a36Sopenharmony_ci/**
66262306a36Sopenharmony_ci * EXPECT_STREQ()
66362306a36Sopenharmony_ci *
66462306a36Sopenharmony_ci * @expected: expected value
66562306a36Sopenharmony_ci * @seen: measured value
66662306a36Sopenharmony_ci *
66762306a36Sopenharmony_ci * EXPECT_STREQ(expected, measured): !strcmp(expected, measured)
66862306a36Sopenharmony_ci */
66962306a36Sopenharmony_ci#define EXPECT_STREQ(expected, seen) \
67062306a36Sopenharmony_ci	__EXPECT_STR(expected, seen, ==, 0)
67162306a36Sopenharmony_ci
67262306a36Sopenharmony_ci/**
67362306a36Sopenharmony_ci * EXPECT_STRNE()
67462306a36Sopenharmony_ci *
67562306a36Sopenharmony_ci * @expected: expected value
67662306a36Sopenharmony_ci * @seen: measured value
67762306a36Sopenharmony_ci *
67862306a36Sopenharmony_ci * EXPECT_STRNE(expected, measured): strcmp(expected, measured)
67962306a36Sopenharmony_ci */
68062306a36Sopenharmony_ci#define EXPECT_STRNE(expected, seen) \
68162306a36Sopenharmony_ci	__EXPECT_STR(expected, seen, !=, 0)
68262306a36Sopenharmony_ci
68362306a36Sopenharmony_ci#ifndef ARRAY_SIZE
68462306a36Sopenharmony_ci#define ARRAY_SIZE(a)	(sizeof(a) / sizeof(a[0]))
68562306a36Sopenharmony_ci#endif
68662306a36Sopenharmony_ci
68762306a36Sopenharmony_ci/* Support an optional handler after and ASSERT_* or EXPECT_*.  The approach is
68862306a36Sopenharmony_ci * not thread-safe, but it should be fine in most sane test scenarios.
68962306a36Sopenharmony_ci *
69062306a36Sopenharmony_ci * Using __bail(), which optionally abort()s, is the easiest way to early
69162306a36Sopenharmony_ci * return while still providing an optional block to the API consumer.
69262306a36Sopenharmony_ci */
69362306a36Sopenharmony_ci#define OPTIONAL_HANDLER(_assert) \
69462306a36Sopenharmony_ci	for (; _metadata->trigger; _metadata->trigger = \
69562306a36Sopenharmony_ci			__bail(_assert, _metadata))
69662306a36Sopenharmony_ci
69762306a36Sopenharmony_ci#define __INC_STEP(_metadata) \
69862306a36Sopenharmony_ci	/* Keep "step" below 255 (which is used for "SKIP" reporting). */	\
69962306a36Sopenharmony_ci	if (_metadata->passed && _metadata->step < 253) \
70062306a36Sopenharmony_ci		_metadata->step++;
70162306a36Sopenharmony_ci
70262306a36Sopenharmony_ci#define is_signed_type(var)       (!!(((__typeof__(var))(-1)) < (__typeof__(var))1))
70362306a36Sopenharmony_ci
70462306a36Sopenharmony_ci#define __EXPECT(_expected, _expected_str, _seen, _seen_str, _t, _assert) do { \
70562306a36Sopenharmony_ci	/* Avoid multiple evaluation of the cases */ \
70662306a36Sopenharmony_ci	__typeof__(_expected) __exp = (_expected); \
70762306a36Sopenharmony_ci	__typeof__(_seen) __seen = (_seen); \
70862306a36Sopenharmony_ci	if (_assert) __INC_STEP(_metadata); \
70962306a36Sopenharmony_ci	if (!(__exp _t __seen)) { \
71062306a36Sopenharmony_ci		/* Report with actual signedness to avoid weird output. */ \
71162306a36Sopenharmony_ci		switch (is_signed_type(__exp) * 2 + is_signed_type(__seen)) { \
71262306a36Sopenharmony_ci		case 0: { \
71362306a36Sopenharmony_ci			unsigned long long __exp_print = (uintptr_t)__exp; \
71462306a36Sopenharmony_ci			unsigned long long __seen_print = (uintptr_t)__seen; \
71562306a36Sopenharmony_ci			__TH_LOG("Expected %s (%llu) %s %s (%llu)", \
71662306a36Sopenharmony_ci				 _expected_str, __exp_print, #_t, \
71762306a36Sopenharmony_ci				 _seen_str, __seen_print); \
71862306a36Sopenharmony_ci			break; \
71962306a36Sopenharmony_ci			} \
72062306a36Sopenharmony_ci		case 1: { \
72162306a36Sopenharmony_ci			unsigned long long __exp_print = (uintptr_t)__exp; \
72262306a36Sopenharmony_ci			long long __seen_print = (intptr_t)__seen; \
72362306a36Sopenharmony_ci			__TH_LOG("Expected %s (%llu) %s %s (%lld)", \
72462306a36Sopenharmony_ci				 _expected_str, __exp_print, #_t, \
72562306a36Sopenharmony_ci				 _seen_str, __seen_print); \
72662306a36Sopenharmony_ci			break; \
72762306a36Sopenharmony_ci			} \
72862306a36Sopenharmony_ci		case 2: { \
72962306a36Sopenharmony_ci			long long __exp_print = (intptr_t)__exp; \
73062306a36Sopenharmony_ci			unsigned long long __seen_print = (uintptr_t)__seen; \
73162306a36Sopenharmony_ci			__TH_LOG("Expected %s (%lld) %s %s (%llu)", \
73262306a36Sopenharmony_ci				 _expected_str, __exp_print, #_t, \
73362306a36Sopenharmony_ci				 _seen_str, __seen_print); \
73462306a36Sopenharmony_ci			break; \
73562306a36Sopenharmony_ci			} \
73662306a36Sopenharmony_ci		case 3: { \
73762306a36Sopenharmony_ci			long long __exp_print = (intptr_t)__exp; \
73862306a36Sopenharmony_ci			long long __seen_print = (intptr_t)__seen; \
73962306a36Sopenharmony_ci			__TH_LOG("Expected %s (%lld) %s %s (%lld)", \
74062306a36Sopenharmony_ci				 _expected_str, __exp_print, #_t, \
74162306a36Sopenharmony_ci				 _seen_str, __seen_print); \
74262306a36Sopenharmony_ci			break; \
74362306a36Sopenharmony_ci			} \
74462306a36Sopenharmony_ci		} \
74562306a36Sopenharmony_ci		_metadata->passed = 0; \
74662306a36Sopenharmony_ci		/* Ensure the optional handler is triggered */ \
74762306a36Sopenharmony_ci		_metadata->trigger = 1; \
74862306a36Sopenharmony_ci	} \
74962306a36Sopenharmony_ci} while (0); OPTIONAL_HANDLER(_assert)
75062306a36Sopenharmony_ci
75162306a36Sopenharmony_ci#define __EXPECT_STR(_expected, _seen, _t, _assert) do { \
75262306a36Sopenharmony_ci	const char *__exp = (_expected); \
75362306a36Sopenharmony_ci	const char *__seen = (_seen); \
75462306a36Sopenharmony_ci	if (_assert) __INC_STEP(_metadata); \
75562306a36Sopenharmony_ci	if (!(strcmp(__exp, __seen) _t 0))  { \
75662306a36Sopenharmony_ci		__TH_LOG("Expected '%s' %s '%s'.", __exp, #_t, __seen); \
75762306a36Sopenharmony_ci		_metadata->passed = 0; \
75862306a36Sopenharmony_ci		_metadata->trigger = 1; \
75962306a36Sopenharmony_ci	} \
76062306a36Sopenharmony_ci} while (0); OPTIONAL_HANDLER(_assert)
76162306a36Sopenharmony_ci
76262306a36Sopenharmony_ci/* List helpers */
76362306a36Sopenharmony_ci#define __LIST_APPEND(head, item) \
76462306a36Sopenharmony_ci{ \
76562306a36Sopenharmony_ci	/* Circular linked list where only prev is circular. */ \
76662306a36Sopenharmony_ci	if (head == NULL) { \
76762306a36Sopenharmony_ci		head = item; \
76862306a36Sopenharmony_ci		item->next = NULL; \
76962306a36Sopenharmony_ci		item->prev = item; \
77062306a36Sopenharmony_ci		return;	\
77162306a36Sopenharmony_ci	} \
77262306a36Sopenharmony_ci	if (__constructor_order == _CONSTRUCTOR_ORDER_FORWARD) { \
77362306a36Sopenharmony_ci		item->next = NULL; \
77462306a36Sopenharmony_ci		item->prev = head->prev; \
77562306a36Sopenharmony_ci		item->prev->next = item; \
77662306a36Sopenharmony_ci		head->prev = item; \
77762306a36Sopenharmony_ci	} else { \
77862306a36Sopenharmony_ci		item->next = head; \
77962306a36Sopenharmony_ci		item->next->prev = item; \
78062306a36Sopenharmony_ci		item->prev = item; \
78162306a36Sopenharmony_ci		head = item; \
78262306a36Sopenharmony_ci	} \
78362306a36Sopenharmony_ci}
78462306a36Sopenharmony_ci
78562306a36Sopenharmony_cistruct __test_results {
78662306a36Sopenharmony_ci	char reason[1024];	/* Reason for test result */
78762306a36Sopenharmony_ci};
78862306a36Sopenharmony_ci
78962306a36Sopenharmony_cistruct __test_metadata;
79062306a36Sopenharmony_cistruct __fixture_variant_metadata;
79162306a36Sopenharmony_ci
79262306a36Sopenharmony_ci/* Contains all the information about a fixture. */
79362306a36Sopenharmony_cistruct __fixture_metadata {
79462306a36Sopenharmony_ci	const char *name;
79562306a36Sopenharmony_ci	struct __test_metadata *tests;
79662306a36Sopenharmony_ci	struct __fixture_variant_metadata *variant;
79762306a36Sopenharmony_ci	struct __fixture_metadata *prev, *next;
79862306a36Sopenharmony_ci} _fixture_global __attribute__((unused)) = {
79962306a36Sopenharmony_ci	.name = "global",
80062306a36Sopenharmony_ci	.prev = &_fixture_global,
80162306a36Sopenharmony_ci};
80262306a36Sopenharmony_ci
80362306a36Sopenharmony_cistatic struct __fixture_metadata *__fixture_list = &_fixture_global;
80462306a36Sopenharmony_cistatic int __constructor_order;
80562306a36Sopenharmony_ci
80662306a36Sopenharmony_ci#define _CONSTRUCTOR_ORDER_FORWARD   1
80762306a36Sopenharmony_ci#define _CONSTRUCTOR_ORDER_BACKWARD -1
80862306a36Sopenharmony_ci
80962306a36Sopenharmony_cistatic inline void __register_fixture(struct __fixture_metadata *f)
81062306a36Sopenharmony_ci{
81162306a36Sopenharmony_ci	__LIST_APPEND(__fixture_list, f);
81262306a36Sopenharmony_ci}
81362306a36Sopenharmony_ci
81462306a36Sopenharmony_cistruct __fixture_variant_metadata {
81562306a36Sopenharmony_ci	const char *name;
81662306a36Sopenharmony_ci	const void *data;
81762306a36Sopenharmony_ci	struct __fixture_variant_metadata *prev, *next;
81862306a36Sopenharmony_ci};
81962306a36Sopenharmony_ci
82062306a36Sopenharmony_cistatic inline void
82162306a36Sopenharmony_ci__register_fixture_variant(struct __fixture_metadata *f,
82262306a36Sopenharmony_ci			   struct __fixture_variant_metadata *variant)
82362306a36Sopenharmony_ci{
82462306a36Sopenharmony_ci	__LIST_APPEND(f->variant, variant);
82562306a36Sopenharmony_ci}
82662306a36Sopenharmony_ci
82762306a36Sopenharmony_ci/* Contains all the information for test execution and status checking. */
82862306a36Sopenharmony_cistruct __test_metadata {
82962306a36Sopenharmony_ci	const char *name;
83062306a36Sopenharmony_ci	void (*fn)(struct __test_metadata *,
83162306a36Sopenharmony_ci		   struct __fixture_variant_metadata *);
83262306a36Sopenharmony_ci	pid_t pid;	/* pid of test when being run */
83362306a36Sopenharmony_ci	struct __fixture_metadata *fixture;
83462306a36Sopenharmony_ci	int termsig;
83562306a36Sopenharmony_ci	int passed;
83662306a36Sopenharmony_ci	int skip;	/* did SKIP get used? */
83762306a36Sopenharmony_ci	int trigger; /* extra handler after the evaluation */
83862306a36Sopenharmony_ci	int timeout;	/* seconds to wait for test timeout */
83962306a36Sopenharmony_ci	bool timed_out;	/* did this test timeout instead of exiting? */
84062306a36Sopenharmony_ci	__u8 step;
84162306a36Sopenharmony_ci	bool no_print; /* manual trigger when TH_LOG_STREAM is not available */
84262306a36Sopenharmony_ci	bool aborted;	/* stopped test due to failed ASSERT */
84362306a36Sopenharmony_ci	bool setup_completed; /* did setup finish? */
84462306a36Sopenharmony_ci	jmp_buf env;	/* for exiting out of test early */
84562306a36Sopenharmony_ci	struct __test_results *results;
84662306a36Sopenharmony_ci	struct __test_metadata *prev, *next;
84762306a36Sopenharmony_ci};
84862306a36Sopenharmony_ci
84962306a36Sopenharmony_ci/*
85062306a36Sopenharmony_ci * Since constructors are called in reverse order, reverse the test
85162306a36Sopenharmony_ci * list so tests are run in source declaration order.
85262306a36Sopenharmony_ci * https://gcc.gnu.org/onlinedocs/gccint/Initialization.html
85362306a36Sopenharmony_ci * However, it seems not all toolchains do this correctly, so use
85462306a36Sopenharmony_ci * __constructor_order to detect which direction is called first
85562306a36Sopenharmony_ci * and adjust list building logic to get things running in the right
85662306a36Sopenharmony_ci * direction.
85762306a36Sopenharmony_ci */
85862306a36Sopenharmony_cistatic inline void __register_test(struct __test_metadata *t)
85962306a36Sopenharmony_ci{
86062306a36Sopenharmony_ci	__LIST_APPEND(t->fixture->tests, t);
86162306a36Sopenharmony_ci}
86262306a36Sopenharmony_ci
86362306a36Sopenharmony_cistatic inline int __bail(int for_realz, struct __test_metadata *t)
86462306a36Sopenharmony_ci{
86562306a36Sopenharmony_ci	/* if this is ASSERT, return immediately. */
86662306a36Sopenharmony_ci	if (for_realz) {
86762306a36Sopenharmony_ci		t->aborted = true;
86862306a36Sopenharmony_ci		longjmp(t->env, 1);
86962306a36Sopenharmony_ci	}
87062306a36Sopenharmony_ci	/* otherwise, end the for loop and continue. */
87162306a36Sopenharmony_ci	return 0;
87262306a36Sopenharmony_ci}
87362306a36Sopenharmony_ci
87462306a36Sopenharmony_cistatic inline void __test_check_assert(struct __test_metadata *t)
87562306a36Sopenharmony_ci{
87662306a36Sopenharmony_ci	if (t->aborted) {
87762306a36Sopenharmony_ci		if (t->no_print)
87862306a36Sopenharmony_ci			_exit(t->step);
87962306a36Sopenharmony_ci		abort();
88062306a36Sopenharmony_ci	}
88162306a36Sopenharmony_ci}
88262306a36Sopenharmony_ci
88362306a36Sopenharmony_cistruct __test_metadata *__active_test;
88462306a36Sopenharmony_cistatic void __timeout_handler(int sig, siginfo_t *info, void *ucontext)
88562306a36Sopenharmony_ci{
88662306a36Sopenharmony_ci	struct __test_metadata *t = __active_test;
88762306a36Sopenharmony_ci
88862306a36Sopenharmony_ci	/* Sanity check handler execution environment. */
88962306a36Sopenharmony_ci	if (!t) {
89062306a36Sopenharmony_ci		fprintf(TH_LOG_STREAM,
89162306a36Sopenharmony_ci			"# no active test in SIGALRM handler!?\n");
89262306a36Sopenharmony_ci		abort();
89362306a36Sopenharmony_ci	}
89462306a36Sopenharmony_ci	if (sig != SIGALRM || sig != info->si_signo) {
89562306a36Sopenharmony_ci		fprintf(TH_LOG_STREAM,
89662306a36Sopenharmony_ci			"# %s: SIGALRM handler caught signal %d!?\n",
89762306a36Sopenharmony_ci			t->name, sig != SIGALRM ? sig : info->si_signo);
89862306a36Sopenharmony_ci		abort();
89962306a36Sopenharmony_ci	}
90062306a36Sopenharmony_ci
90162306a36Sopenharmony_ci	t->timed_out = true;
90262306a36Sopenharmony_ci	// signal process group
90362306a36Sopenharmony_ci	kill(-(t->pid), SIGKILL);
90462306a36Sopenharmony_ci}
90562306a36Sopenharmony_ci
90662306a36Sopenharmony_civoid __wait_for_test(struct __test_metadata *t)
90762306a36Sopenharmony_ci{
90862306a36Sopenharmony_ci	struct sigaction action = {
90962306a36Sopenharmony_ci		.sa_sigaction = __timeout_handler,
91062306a36Sopenharmony_ci		.sa_flags = SA_SIGINFO,
91162306a36Sopenharmony_ci	};
91262306a36Sopenharmony_ci	struct sigaction saved_action;
91362306a36Sopenharmony_ci	int status;
91462306a36Sopenharmony_ci
91562306a36Sopenharmony_ci	if (sigaction(SIGALRM, &action, &saved_action)) {
91662306a36Sopenharmony_ci		t->passed = 0;
91762306a36Sopenharmony_ci		fprintf(TH_LOG_STREAM,
91862306a36Sopenharmony_ci			"# %s: unable to install SIGALRM handler\n",
91962306a36Sopenharmony_ci			t->name);
92062306a36Sopenharmony_ci		return;
92162306a36Sopenharmony_ci	}
92262306a36Sopenharmony_ci	__active_test = t;
92362306a36Sopenharmony_ci	t->timed_out = false;
92462306a36Sopenharmony_ci	alarm(t->timeout);
92562306a36Sopenharmony_ci	waitpid(t->pid, &status, 0);
92662306a36Sopenharmony_ci	alarm(0);
92762306a36Sopenharmony_ci	if (sigaction(SIGALRM, &saved_action, NULL)) {
92862306a36Sopenharmony_ci		t->passed = 0;
92962306a36Sopenharmony_ci		fprintf(TH_LOG_STREAM,
93062306a36Sopenharmony_ci			"# %s: unable to uninstall SIGALRM handler\n",
93162306a36Sopenharmony_ci			t->name);
93262306a36Sopenharmony_ci		return;
93362306a36Sopenharmony_ci	}
93462306a36Sopenharmony_ci	__active_test = NULL;
93562306a36Sopenharmony_ci
93662306a36Sopenharmony_ci	if (t->timed_out) {
93762306a36Sopenharmony_ci		t->passed = 0;
93862306a36Sopenharmony_ci		fprintf(TH_LOG_STREAM,
93962306a36Sopenharmony_ci			"# %s: Test terminated by timeout\n", t->name);
94062306a36Sopenharmony_ci	} else if (WIFEXITED(status)) {
94162306a36Sopenharmony_ci		if (WEXITSTATUS(status) == 255) {
94262306a36Sopenharmony_ci			/* SKIP */
94362306a36Sopenharmony_ci			t->passed = 1;
94462306a36Sopenharmony_ci			t->skip = 1;
94562306a36Sopenharmony_ci		} else if (t->termsig != -1) {
94662306a36Sopenharmony_ci			t->passed = 0;
94762306a36Sopenharmony_ci			fprintf(TH_LOG_STREAM,
94862306a36Sopenharmony_ci				"# %s: Test exited normally instead of by signal (code: %d)\n",
94962306a36Sopenharmony_ci				t->name,
95062306a36Sopenharmony_ci				WEXITSTATUS(status));
95162306a36Sopenharmony_ci		} else {
95262306a36Sopenharmony_ci			switch (WEXITSTATUS(status)) {
95362306a36Sopenharmony_ci			/* Success */
95462306a36Sopenharmony_ci			case 0:
95562306a36Sopenharmony_ci				t->passed = 1;
95662306a36Sopenharmony_ci				break;
95762306a36Sopenharmony_ci			/* Other failure, assume step report. */
95862306a36Sopenharmony_ci			default:
95962306a36Sopenharmony_ci				t->passed = 0;
96062306a36Sopenharmony_ci				fprintf(TH_LOG_STREAM,
96162306a36Sopenharmony_ci					"# %s: Test failed at step #%d\n",
96262306a36Sopenharmony_ci					t->name,
96362306a36Sopenharmony_ci					WEXITSTATUS(status));
96462306a36Sopenharmony_ci			}
96562306a36Sopenharmony_ci		}
96662306a36Sopenharmony_ci	} else if (WIFSIGNALED(status)) {
96762306a36Sopenharmony_ci		t->passed = 0;
96862306a36Sopenharmony_ci		if (WTERMSIG(status) == SIGABRT) {
96962306a36Sopenharmony_ci			fprintf(TH_LOG_STREAM,
97062306a36Sopenharmony_ci				"# %s: Test terminated by assertion\n",
97162306a36Sopenharmony_ci				t->name);
97262306a36Sopenharmony_ci		} else if (WTERMSIG(status) == t->termsig) {
97362306a36Sopenharmony_ci			t->passed = 1;
97462306a36Sopenharmony_ci		} else {
97562306a36Sopenharmony_ci			fprintf(TH_LOG_STREAM,
97662306a36Sopenharmony_ci				"# %s: Test terminated unexpectedly by signal %d\n",
97762306a36Sopenharmony_ci				t->name,
97862306a36Sopenharmony_ci				WTERMSIG(status));
97962306a36Sopenharmony_ci		}
98062306a36Sopenharmony_ci	} else {
98162306a36Sopenharmony_ci		fprintf(TH_LOG_STREAM,
98262306a36Sopenharmony_ci			"# %s: Test ended in some other way [%u]\n",
98362306a36Sopenharmony_ci			t->name,
98462306a36Sopenharmony_ci			status);
98562306a36Sopenharmony_ci	}
98662306a36Sopenharmony_ci}
98762306a36Sopenharmony_ci
98862306a36Sopenharmony_cistatic void test_harness_list_tests(void)
98962306a36Sopenharmony_ci{
99062306a36Sopenharmony_ci	struct __fixture_variant_metadata *v;
99162306a36Sopenharmony_ci	struct __fixture_metadata *f;
99262306a36Sopenharmony_ci	struct __test_metadata *t;
99362306a36Sopenharmony_ci
99462306a36Sopenharmony_ci	for (f = __fixture_list; f; f = f->next) {
99562306a36Sopenharmony_ci		v = f->variant;
99662306a36Sopenharmony_ci		t = f->tests;
99762306a36Sopenharmony_ci
99862306a36Sopenharmony_ci		if (f == __fixture_list)
99962306a36Sopenharmony_ci			fprintf(stderr, "%-20s %-25s %s\n",
100062306a36Sopenharmony_ci				"# FIXTURE", "VARIANT", "TEST");
100162306a36Sopenharmony_ci		else
100262306a36Sopenharmony_ci			fprintf(stderr, "--------------------------------------------------------------------------------\n");
100362306a36Sopenharmony_ci
100462306a36Sopenharmony_ci		do {
100562306a36Sopenharmony_ci			fprintf(stderr, "%-20s %-25s %s\n",
100662306a36Sopenharmony_ci				t == f->tests ? f->name : "",
100762306a36Sopenharmony_ci				v ? v->name : "",
100862306a36Sopenharmony_ci				t ? t->name : "");
100962306a36Sopenharmony_ci
101062306a36Sopenharmony_ci			v = v ? v->next : NULL;
101162306a36Sopenharmony_ci			t = t ? t->next : NULL;
101262306a36Sopenharmony_ci		} while (v || t);
101362306a36Sopenharmony_ci	}
101462306a36Sopenharmony_ci}
101562306a36Sopenharmony_ci
101662306a36Sopenharmony_cistatic int test_harness_argv_check(int argc, char **argv)
101762306a36Sopenharmony_ci{
101862306a36Sopenharmony_ci	int opt;
101962306a36Sopenharmony_ci
102062306a36Sopenharmony_ci	while ((opt = getopt(argc, argv, "hlF:f:V:v:t:T:r:")) != -1) {
102162306a36Sopenharmony_ci		switch (opt) {
102262306a36Sopenharmony_ci		case 'f':
102362306a36Sopenharmony_ci		case 'F':
102462306a36Sopenharmony_ci		case 'v':
102562306a36Sopenharmony_ci		case 'V':
102662306a36Sopenharmony_ci		case 't':
102762306a36Sopenharmony_ci		case 'T':
102862306a36Sopenharmony_ci		case 'r':
102962306a36Sopenharmony_ci			break;
103062306a36Sopenharmony_ci		case 'l':
103162306a36Sopenharmony_ci			test_harness_list_tests();
103262306a36Sopenharmony_ci			return KSFT_SKIP;
103362306a36Sopenharmony_ci		case 'h':
103462306a36Sopenharmony_ci		default:
103562306a36Sopenharmony_ci			fprintf(stderr,
103662306a36Sopenharmony_ci				"Usage: %s [-h|-l] [-t|-T|-v|-V|-f|-F|-r name]\n"
103762306a36Sopenharmony_ci				"\t-h       print help\n"
103862306a36Sopenharmony_ci				"\t-l       list all tests\n"
103962306a36Sopenharmony_ci				"\n"
104062306a36Sopenharmony_ci				"\t-t name  include test\n"
104162306a36Sopenharmony_ci				"\t-T name  exclude test\n"
104262306a36Sopenharmony_ci				"\t-v name  include variant\n"
104362306a36Sopenharmony_ci				"\t-V name  exclude variant\n"
104462306a36Sopenharmony_ci				"\t-f name  include fixture\n"
104562306a36Sopenharmony_ci				"\t-F name  exclude fixture\n"
104662306a36Sopenharmony_ci				"\t-r name  run specified test\n"
104762306a36Sopenharmony_ci				"\n"
104862306a36Sopenharmony_ci				"Test filter options can be specified "
104962306a36Sopenharmony_ci				"multiple times. The filtering stops\n"
105062306a36Sopenharmony_ci				"at the first match. For example to "
105162306a36Sopenharmony_ci				"include all tests from variant 'bla'\n"
105262306a36Sopenharmony_ci				"but not test 'foo' specify '-T foo -v bla'.\n"
105362306a36Sopenharmony_ci				"", argv[0]);
105462306a36Sopenharmony_ci			return opt == 'h' ? KSFT_SKIP : KSFT_FAIL;
105562306a36Sopenharmony_ci		}
105662306a36Sopenharmony_ci	}
105762306a36Sopenharmony_ci
105862306a36Sopenharmony_ci	return KSFT_PASS;
105962306a36Sopenharmony_ci}
106062306a36Sopenharmony_ci
106162306a36Sopenharmony_cistatic bool test_enabled(int argc, char **argv,
106262306a36Sopenharmony_ci			 struct __fixture_metadata *f,
106362306a36Sopenharmony_ci			 struct __fixture_variant_metadata *v,
106462306a36Sopenharmony_ci			 struct __test_metadata *t)
106562306a36Sopenharmony_ci{
106662306a36Sopenharmony_ci	unsigned int flen = 0, vlen = 0, tlen = 0;
106762306a36Sopenharmony_ci	bool has_positive = false;
106862306a36Sopenharmony_ci	int opt;
106962306a36Sopenharmony_ci
107062306a36Sopenharmony_ci	optind = 1;
107162306a36Sopenharmony_ci	while ((opt = getopt(argc, argv, "F:f:V:v:t:T:r:")) != -1) {
107262306a36Sopenharmony_ci		has_positive |= islower(opt);
107362306a36Sopenharmony_ci
107462306a36Sopenharmony_ci		switch (tolower(opt)) {
107562306a36Sopenharmony_ci		case 't':
107662306a36Sopenharmony_ci			if (!strcmp(t->name, optarg))
107762306a36Sopenharmony_ci				return islower(opt);
107862306a36Sopenharmony_ci			break;
107962306a36Sopenharmony_ci		case 'f':
108062306a36Sopenharmony_ci			if (!strcmp(f->name, optarg))
108162306a36Sopenharmony_ci				return islower(opt);
108262306a36Sopenharmony_ci			break;
108362306a36Sopenharmony_ci		case 'v':
108462306a36Sopenharmony_ci			if (!strcmp(v->name, optarg))
108562306a36Sopenharmony_ci				return islower(opt);
108662306a36Sopenharmony_ci			break;
108762306a36Sopenharmony_ci		case 'r':
108862306a36Sopenharmony_ci			if (!tlen) {
108962306a36Sopenharmony_ci				flen = strlen(f->name);
109062306a36Sopenharmony_ci				vlen = strlen(v->name);
109162306a36Sopenharmony_ci				tlen = strlen(t->name);
109262306a36Sopenharmony_ci			}
109362306a36Sopenharmony_ci			if (strlen(optarg) == flen + 1 + vlen + !!vlen + tlen &&
109462306a36Sopenharmony_ci			    !strncmp(f->name, &optarg[0], flen) &&
109562306a36Sopenharmony_ci			    !strncmp(v->name, &optarg[flen + 1], vlen) &&
109662306a36Sopenharmony_ci			    !strncmp(t->name, &optarg[flen + 1 + vlen + !!vlen], tlen))
109762306a36Sopenharmony_ci				return true;
109862306a36Sopenharmony_ci			break;
109962306a36Sopenharmony_ci		}
110062306a36Sopenharmony_ci	}
110162306a36Sopenharmony_ci
110262306a36Sopenharmony_ci	/*
110362306a36Sopenharmony_ci	 * If there are no positive tests then we assume user just wants
110462306a36Sopenharmony_ci	 * exclusions and everything else is a pass.
110562306a36Sopenharmony_ci	 */
110662306a36Sopenharmony_ci	return !has_positive;
110762306a36Sopenharmony_ci}
110862306a36Sopenharmony_ci
110962306a36Sopenharmony_civoid __run_test(struct __fixture_metadata *f,
111062306a36Sopenharmony_ci		struct __fixture_variant_metadata *variant,
111162306a36Sopenharmony_ci		struct __test_metadata *t)
111262306a36Sopenharmony_ci{
111362306a36Sopenharmony_ci	/* reset test struct */
111462306a36Sopenharmony_ci	t->passed = 1;
111562306a36Sopenharmony_ci	t->skip = 0;
111662306a36Sopenharmony_ci	t->trigger = 0;
111762306a36Sopenharmony_ci	t->step = 1;
111862306a36Sopenharmony_ci	t->no_print = 0;
111962306a36Sopenharmony_ci	memset(t->results->reason, 0, sizeof(t->results->reason));
112062306a36Sopenharmony_ci
112162306a36Sopenharmony_ci	ksft_print_msg(" RUN           %s%s%s.%s ...\n",
112262306a36Sopenharmony_ci	       f->name, variant->name[0] ? "." : "", variant->name, t->name);
112362306a36Sopenharmony_ci
112462306a36Sopenharmony_ci	/* Make sure output buffers are flushed before fork */
112562306a36Sopenharmony_ci	fflush(stdout);
112662306a36Sopenharmony_ci	fflush(stderr);
112762306a36Sopenharmony_ci
112862306a36Sopenharmony_ci	t->pid = fork();
112962306a36Sopenharmony_ci	if (t->pid < 0) {
113062306a36Sopenharmony_ci		ksft_print_msg("ERROR SPAWNING TEST CHILD\n");
113162306a36Sopenharmony_ci		t->passed = 0;
113262306a36Sopenharmony_ci	} else if (t->pid == 0) {
113362306a36Sopenharmony_ci		setpgrp();
113462306a36Sopenharmony_ci		t->fn(t, variant);
113562306a36Sopenharmony_ci		if (t->skip)
113662306a36Sopenharmony_ci			_exit(255);
113762306a36Sopenharmony_ci		/* Pass is exit 0 */
113862306a36Sopenharmony_ci		if (t->passed)
113962306a36Sopenharmony_ci			_exit(0);
114062306a36Sopenharmony_ci		/* Something else happened, report the step. */
114162306a36Sopenharmony_ci		_exit(t->step);
114262306a36Sopenharmony_ci	} else {
114362306a36Sopenharmony_ci		__wait_for_test(t);
114462306a36Sopenharmony_ci	}
114562306a36Sopenharmony_ci	ksft_print_msg("         %4s  %s%s%s.%s\n", t->passed ? "OK" : "FAIL",
114662306a36Sopenharmony_ci	       f->name, variant->name[0] ? "." : "", variant->name, t->name);
114762306a36Sopenharmony_ci
114862306a36Sopenharmony_ci	if (t->skip)
114962306a36Sopenharmony_ci		ksft_test_result_skip("%s\n", t->results->reason[0] ?
115062306a36Sopenharmony_ci					t->results->reason : "unknown");
115162306a36Sopenharmony_ci	else
115262306a36Sopenharmony_ci		ksft_test_result(t->passed, "%s%s%s.%s\n",
115362306a36Sopenharmony_ci			f->name, variant->name[0] ? "." : "", variant->name, t->name);
115462306a36Sopenharmony_ci}
115562306a36Sopenharmony_ci
115662306a36Sopenharmony_cistatic int test_harness_run(int argc, char **argv)
115762306a36Sopenharmony_ci{
115862306a36Sopenharmony_ci	struct __fixture_variant_metadata no_variant = { .name = "", };
115962306a36Sopenharmony_ci	struct __fixture_variant_metadata *v;
116062306a36Sopenharmony_ci	struct __fixture_metadata *f;
116162306a36Sopenharmony_ci	struct __test_results *results;
116262306a36Sopenharmony_ci	struct __test_metadata *t;
116362306a36Sopenharmony_ci	int ret;
116462306a36Sopenharmony_ci	unsigned int case_count = 0, test_count = 0;
116562306a36Sopenharmony_ci	unsigned int count = 0;
116662306a36Sopenharmony_ci	unsigned int pass_count = 0;
116762306a36Sopenharmony_ci
116862306a36Sopenharmony_ci	ret = test_harness_argv_check(argc, argv);
116962306a36Sopenharmony_ci	if (ret != KSFT_PASS)
117062306a36Sopenharmony_ci		return ret;
117162306a36Sopenharmony_ci
117262306a36Sopenharmony_ci	for (f = __fixture_list; f; f = f->next) {
117362306a36Sopenharmony_ci		for (v = f->variant ?: &no_variant; v; v = v->next) {
117462306a36Sopenharmony_ci			unsigned int old_tests = test_count;
117562306a36Sopenharmony_ci
117662306a36Sopenharmony_ci			for (t = f->tests; t; t = t->next)
117762306a36Sopenharmony_ci				if (test_enabled(argc, argv, f, v, t))
117862306a36Sopenharmony_ci					test_count++;
117962306a36Sopenharmony_ci
118062306a36Sopenharmony_ci			if (old_tests != test_count)
118162306a36Sopenharmony_ci				case_count++;
118262306a36Sopenharmony_ci		}
118362306a36Sopenharmony_ci	}
118462306a36Sopenharmony_ci
118562306a36Sopenharmony_ci	results = mmap(NULL, sizeof(*results), PROT_READ | PROT_WRITE,
118662306a36Sopenharmony_ci		       MAP_SHARED | MAP_ANONYMOUS, -1, 0);
118762306a36Sopenharmony_ci
118862306a36Sopenharmony_ci	ksft_print_header();
118962306a36Sopenharmony_ci	ksft_set_plan(test_count);
119062306a36Sopenharmony_ci	ksft_print_msg("Starting %u tests from %u test cases.\n",
119162306a36Sopenharmony_ci	       test_count, case_count);
119262306a36Sopenharmony_ci	for (f = __fixture_list; f; f = f->next) {
119362306a36Sopenharmony_ci		for (v = f->variant ?: &no_variant; v; v = v->next) {
119462306a36Sopenharmony_ci			for (t = f->tests; t; t = t->next) {
119562306a36Sopenharmony_ci				if (!test_enabled(argc, argv, f, v, t))
119662306a36Sopenharmony_ci					continue;
119762306a36Sopenharmony_ci				count++;
119862306a36Sopenharmony_ci				t->results = results;
119962306a36Sopenharmony_ci				__run_test(f, v, t);
120062306a36Sopenharmony_ci				t->results = NULL;
120162306a36Sopenharmony_ci				if (t->passed)
120262306a36Sopenharmony_ci					pass_count++;
120362306a36Sopenharmony_ci				else
120462306a36Sopenharmony_ci					ret = 1;
120562306a36Sopenharmony_ci			}
120662306a36Sopenharmony_ci		}
120762306a36Sopenharmony_ci	}
120862306a36Sopenharmony_ci	munmap(results, sizeof(*results));
120962306a36Sopenharmony_ci
121062306a36Sopenharmony_ci	ksft_print_msg("%s: %u / %u tests passed.\n", ret ? "FAILED" : "PASSED",
121162306a36Sopenharmony_ci			pass_count, count);
121262306a36Sopenharmony_ci	ksft_exit(ret == 0);
121362306a36Sopenharmony_ci
121462306a36Sopenharmony_ci	/* unreachable */
121562306a36Sopenharmony_ci	return KSFT_FAIL;
121662306a36Sopenharmony_ci}
121762306a36Sopenharmony_ci
121862306a36Sopenharmony_cistatic void __attribute__((constructor)) __constructor_order_first(void)
121962306a36Sopenharmony_ci{
122062306a36Sopenharmony_ci	if (!__constructor_order)
122162306a36Sopenharmony_ci		__constructor_order = _CONSTRUCTOR_ORDER_FORWARD;
122262306a36Sopenharmony_ci}
122362306a36Sopenharmony_ci
122462306a36Sopenharmony_ci#endif  /* __KSELFTEST_HARNESS_H */
1225