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