ztest: Fix userspace ztests in new API

Update the new API to use K_USER as the flags for both
CONFIG_USERSPACE and CONFIG_TEST_USERSPACE. Also, fix the linker
script to properly include the suites, tests, and rules.

Fixes #44108

Signed-off-by: Yuval Peress <peress@google.com>
This commit is contained in:
Yuval Peress 2022-04-05 11:42:31 -06:00 committed by Anas Nashif
commit 900b6723e7
7 changed files with 80 additions and 52 deletions

View file

@ -62,7 +62,7 @@ target_compile_options(testbinary PRIVATE
) )
target_link_options(testbinary PRIVATE target_link_options(testbinary PRIVATE
-T "${ZEPHYR_BASE}/subsys/testsuite/include/ztest.ld" -T "${ZEPHYR_BASE}/subsys/testsuite/include/ztest_unittest.ld"
) )
target_link_libraries(testbinary PRIVATE target_link_libraries(testbinary PRIVATE

View file

@ -145,11 +145,3 @@
#ifdef CONFIG_USERSPACE #ifdef CONFIG_USERSPACE
_static_kernel_objects_end = .; _static_kernel_objects_end = .;
#endif #endif
#if defined(CONFIG_ZTEST)
ITERABLE_SECTION_RAM(ztest_suite_node, 4)
#if defined(CONFIG_ZTEST_NEW_API)
ITERABLE_SECTION_RAM(ztest_unit_test, 4)
ITERABLE_SECTION_RAM(ztest_test_rule, 4)
#endif /* CONFIG_ZTEST_NEW_API */
#endif /* CONFIG_ZTEST */

View file

@ -8,3 +8,7 @@ zephyr_include_directories_ifdef(CONFIG_TEST
add_subdirectory_ifdef(CONFIG_COVERAGE_GCOV coverage) add_subdirectory_ifdef(CONFIG_COVERAGE_GCOV coverage)
zephyr_library_sources_ifdef(CONFIG_TEST_BUSY_SIM busy_sim/busy_sim.c) zephyr_library_sources_ifdef(CONFIG_TEST_BUSY_SIM busy_sim/busy_sim.c)
if(NOT BOARD STREQUAL unit_testing)
zephyr_linker_sources(RODATA include/ztest.ld)
endif()

View file

@ -4,25 +4,22 @@
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
SECTIONS #if defined(CONFIG_ARM_MMU)
{ #define _ZTEST_ALIGN CONFIG_MMU_PAGE_SIZE
.data.ztest_suite_node_area : ALIGN(4) #elif defined(CONFIG_ARM_MPU)
{ #define _ZTEST_ALIGN CONFIG_ARM_MPU_REGION_MIN_ALIGN_AND_SIZE
_ztest_suite_node_list_start = .; #elif defined(CONFIG_PMP_POWER_OF_TWO_ALIGNMENT)
KEEP(*(SORT_BY_NAME(._ztest_suite_node.static.*))) #define _ZTEST_ALIGN 16
_ztest_suite_node_list_end = .; #else
} #define _ZTEST_ALIGN 4
.data.ztest_unit_test_area : ALIGN(4) #endif
{
_ztest_unit_test_list_start = .; #if defined(CONFIG_ZTEST)
KEEP(*(SORT_BY_NAME(._ztest_unit_test.static.*))) Z_LINK_ITERABLE_ALIGNED(ztest_suite_node, _ZTEST_ALIGN);
_ztest_unit_test_list_end = .;
} #if defined(CONFIG_ZTEST_NEW_API)
.data.ztest_test_rule_area : ALIGN(4) Z_LINK_ITERABLE_ALIGNED(ztest_unit_test, _ZTEST_ALIGN);
{ Z_LINK_ITERABLE_ALIGNED(ztest_test_rule, _ZTEST_ALIGN);
_ztest_test_rule_list_start = .; #endif /* CONFIG_ZTEST_NEW_API */
KEEP(*(SORT_BY_NAME(._ztest_test_rule.static.*)))
_ztest_test_rule_list_end = .; #endif /* CONFIG_ZTEST */
}
}
INSERT AFTER .data;

View file

@ -0,0 +1,28 @@
/*
* Copyright 2022 Google LLC
*
* SPDX-License-Identifier: Apache-2.0
*/
SECTIONS
{
.data.ztest_suite_node_area : ALIGN(4)
{
_ztest_suite_node_list_start = .;
KEEP(*(SORT_BY_NAME(._ztest_suite_node.static.*)))
_ztest_suite_node_list_end = .;
}
.data.ztest_unit_test_area : ALIGN(4)
{
_ztest_unit_test_list_start = .;
KEEP(*(SORT_BY_NAME(._ztest_unit_test.static.*)))
_ztest_unit_test_list_end = .;
}
.data.ztest_test_rule_area : ALIGN(4)
{
_ztest_test_rule_list_start = .;
KEEP(*(SORT_BY_NAME(._ztest_test_rule.static.*)))
_ztest_test_rule_list_end = .;
}
}
INSERT AFTER .data;

View file

@ -17,6 +17,12 @@
#include <init.h> #include <init.h>
#include <stdbool.h> #include <stdbool.h>
#if defined(CONFIG_USERSPACE) || defined(CONFIG_TEST_USERSPACE)
#define __USERSPACE_FLAGS (K_USER)
#else
#define __USERSPACE_FLAGS (0)
#endif
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
@ -49,31 +55,31 @@ struct ztest_suite_stats {
*/ */
struct ztest_suite_node { struct ztest_suite_node {
/** The name of the test suite. */ /** The name of the test suite. */
const char *name; const char * const name;
/** /**
* Setup function to run before running this suite * Setup function to run before running this suite
* *
* @return Pointer to the data structure that will be used throughout this test suite * @return Pointer to the data structure that will be used throughout this test suite
*/ */
void *(*setup)(void); void *(*const setup)(void);
/** /**
* Function to run before each test in this suite * Function to run before each test in this suite
* *
* @param data The test suite's data returned from setup() * @param data The test suite's data returned from setup()
*/ */
void (*before)(void *data); void (*const before)(void *data);
/** /**
* Function to run after each test in this suite * Function to run after each test in this suite
* *
* @param data The test suite's data returned from setup() * @param data The test suite's data returned from setup()
*/ */
void (*after)(void *data); void (*const after)(void *data);
/** /**
* Teardown function to run after running this suite * Teardown function to run after running this suite
* *
* @param data The test suite's data returned from setup() * @param data The test suite's data returned from setup()
*/ */
void (*teardown)(void *data); void (*const teardown)(void *data);
/** /**
* An optional predicate function to determine if the test should run. If NULL, then the * An optional predicate function to determine if the test should run. If NULL, then the
* test will only run once on the first attempt. * test will only run once on the first attempt.
@ -81,9 +87,9 @@ struct ztest_suite_node {
* @param state The current state of the test application. * @param state The current state of the test application.
* @return True if the suite should be run; false to skip. * @return True if the suite should be run; false to skip.
*/ */
bool (*predicate)(const void *state); bool (*const predicate)(const void *state);
/** Stats */ /** Stats */
struct ztest_suite_stats stats; struct ztest_suite_stats * const stats;
}; };
extern struct ztest_suite_node _ztest_suite_node_list_start[]; extern struct ztest_suite_node _ztest_suite_node_list_start[];
@ -103,17 +109,18 @@ extern struct ztest_suite_node _ztest_suite_node_list_end[];
* @param after_fn The function to call after each unit test in this suite * @param after_fn The function to call after each unit test in this suite
* @param teardown_fn The function to call after running all the tests in this suite * @param teardown_fn The function to call after running all the tests in this suite
*/ */
#define ZTEST_SUITE(SUITE_NAME, PREDICATE, setup_fn, before_fn, after_fn, teardown_fn) \ #define ZTEST_SUITE(SUITE_NAME, PREDICATE, setup_fn, before_fn, after_fn, teardown_fn) \
static STRUCT_SECTION_ITERABLE(ztest_suite_node, \ static struct ztest_suite_stats UTIL_CAT(z_ztest_test_node_stats_, SUITE_NAME); \
UTIL_CAT(z_ztest_test_node_, SUITE_NAME)) = { \ static const STRUCT_SECTION_ITERABLE(ztest_suite_node, \
.name = STRINGIFY(SUITE_NAME), \ UTIL_CAT(z_ztest_test_node_, SUITE_NAME)) = { \
.setup = (setup_fn), \ .name = STRINGIFY(SUITE_NAME), \
.before = (before_fn), \ .setup = (setup_fn), \
.after = (after_fn), \ .before = (before_fn), \
.teardown = (teardown_fn), \ .after = (after_fn), \
.predicate = PREDICATE, \ .teardown = (teardown_fn), \
.predicate = PREDICATE, \
.stats = &UTIL_CAT(z_ztest_test_node_stats_, SUITE_NAME), \
} }
/** /**
* Run the registered unit tests which return true from their pragma function. * Run the registered unit tests which return true from their pragma function.
* *
@ -240,7 +247,7 @@ static inline void unit_test_noop(void)
* @param suite The name of the test suite to attach this test * @param suite The name of the test suite to attach this test
* @param fn The test function to call. * @param fn The test function to call.
*/ */
#define ZTEST_USER(suite, fn) Z_ZTEST(suite, fn, COND_CODE_1(CONFIG_USERSPACE, (K_USER), (0))) #define ZTEST_USER(suite, fn) Z_ZTEST(suite, fn, __USERSPACE_FLAGS)
/** /**
* @brief Define a test function * @brief Define a test function
@ -262,7 +269,7 @@ static inline void unit_test_noop(void)
* @param suite The name of the test suite to attach this test * @param suite The name of the test suite to attach this test
* @param fn The test function to call. * @param fn The test function to call.
*/ */
#define ZTEST_USER_F(suite, fn) Z_ZTEST_F(suite, fn, COND_CODE_1(CONFIG_USERSPACE, (K_USER), (0))) #define ZTEST_USER_F(suite, fn) Z_ZTEST_F(suite, fn, __USERSPACE_FLAGS)
/** /**
* @brief Test rule callback function signature * @brief Test rule callback function signature

View file

@ -559,7 +559,7 @@ int ztest_run_test_suites(const void *state)
int count = 0; int count = 0;
for (ptr = _ztest_suite_node_list_start; ptr < _ztest_suite_node_list_end; ++ptr) { for (ptr = _ztest_suite_node_list_start; ptr < _ztest_suite_node_list_end; ++ptr) {
struct ztest_suite_stats *stats = &ptr->stats; struct ztest_suite_stats *stats = ptr->stats;
bool should_run = true; bool should_run = true;
if (ptr->predicate != NULL) { if (ptr->predicate != NULL) {
@ -590,7 +590,7 @@ void ztest_verify_all_test_suites_ran(void)
struct ztest_unit_test *test; struct ztest_unit_test *test;
for (suite = _ztest_suite_node_list_start; suite < _ztest_suite_node_list_end; ++suite) { for (suite = _ztest_suite_node_list_start; suite < _ztest_suite_node_list_end; ++suite) {
if (suite->stats.run_count < 1) { if (suite->stats->run_count < 1) {
PRINT("ERROR: Test suite '%s' did not run.\n", suite->name); PRINT("ERROR: Test suite '%s' did not run.\n", suite->name);
all_tests_run = false; all_tests_run = false;
} }