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