ztest: expand ztest functionality.

Expanding the ZTEST shell to include a command that
accepts additional parameters, such as ztest run_testcase
<suite:test> -p any_value.

Adding the new ZTEST_P macro, to create the
parameterized test.

Signed-off-by: Arkadiusz Cholewinski <arkadiuszx.cholewinski@intel.com>
This commit is contained in:
Arkadiusz Cholewinski 2024-08-13 12:14:52 +02:00 committed by Fabio Baltieri
commit f58a4c4b1c
3 changed files with 52 additions and 18 deletions

View file

@ -46,10 +46,13 @@ Below is an example of a test suite using a predicate:
Adding tests to a suite
***********************
There are 4 macros used to add a test to a suite, they are:
There are 5 macros used to add a test to a suite, they are:
* :c:macro:`ZTEST` ``(suite_name, test_name)`` - Which can be used to add a test by ``test_name`` to a
given suite by ``suite_name``.
* :c:macro:`ZTEST_P` ``(suite_name, test_name)`` - Add a parameterized test to a given suite by specifying
the ``suite_name`` and ``test_name``. You can then access the passed parameter within
the body of the test using the ``data`` pointer.
* :c:macro:`ZTEST_USER` ``(suite_name, test_name)`` - Which behaves the same as :c:macro:`ZTEST`, only
that when :kconfig:option:`CONFIG_USERSPACE` is enabled, then the test will be run in a userspace
thread.

View file

@ -342,9 +342,11 @@ void ztest_verify_all_test_suites_ran(void);
* @param shuffle Shuffle tests
* @param suite_iter Test suite repetitions.
* @param case_iter Test case repetitions.
* @param param Parameter passing into test.
* @return Negative value if the test suite never ran; otherwise, return the number of failures.
*/
int z_ztest_run_test_suite(const char *name, bool shuffle, int suite_iter, int case_iter);
int z_ztest_run_test_suite(const char *name, bool shuffle, int suite_iter,
int case_iter, void *param);
/**
* @brief Returns next test within suite.
@ -404,6 +406,26 @@ void ztest_test_skip(void);
void ztest_skip_failed_assumption(void);
#define Z_TEST_P(suite, fn, t_options) \
struct ztest_unit_test_stats z_ztest_unit_test_stats_##suite##_##fn; \
static void _##suite##_##fn##_wrapper(void *data); \
static void suite##_##fn(void *data); \
static STRUCT_SECTION_ITERABLE(ztest_unit_test, z_ztest_unit_test__##suite##__##fn) = { \
.test_suite_name = STRINGIFY(suite), \
.name = STRINGIFY(fn), \
.test = (_##suite##_##fn##_wrapper), \
.thread_options = t_options, \
.stats = &z_ztest_unit_test_stats_##suite##_##fn \
}; \
static void _##suite##_##fn##_wrapper(void *wrapper_data) \
{ \
suite##_##fn(wrapper_data); \
} \
static inline void suite##_##fn(void *data)
#define ZTEST_P(suite, fn) Z_TEST_P(suite, fn, 0)
#define Z_TEST(suite, fn, t_options, use_fixture) \
struct ztest_unit_test_stats z_ztest_unit_test_stats_##suite##_##fn; \
static void _##suite##_##fn##_wrapper(void *data); \

View file

@ -789,7 +789,7 @@ static void z_ztest_shuffle(bool shuffle, void *dest[], intptr_t start, size_t n
#endif
static int z_ztest_run_test_suite_ptr(struct ztest_suite_node *suite, bool shuffle, int suite_iter,
int case_iter)
int case_iter, void *param)
{
struct ztest_unit_test *test = NULL;
void *data = NULL;
@ -828,6 +828,9 @@ static int z_ztest_run_test_suite_ptr(struct ztest_suite_node *suite, bool shuff
if (test_result != ZTEST_RESULT_SUITE_FAIL && suite->setup != NULL) {
data = suite->setup();
}
if (param != NULL) {
data = param;
}
for (int i = 0; i < case_iter; i++) {
#ifdef CONFIG_ZTEST_SHUFFLE
@ -899,10 +902,11 @@ static int z_ztest_run_test_suite_ptr(struct ztest_suite_node *suite, bool shuff
return fail;
}
int z_ztest_run_test_suite(const char *name, bool shuffle, int suite_iter, int case_iter)
int z_ztest_run_test_suite(const char *name, bool shuffle,
int suite_iter, int case_iter, void *param)
{
return z_ztest_run_test_suite_ptr(ztest_find_test_suite(name), shuffle, suite_iter,
case_iter);
case_iter, param);
}
#ifdef CONFIG_USERSPACE
@ -1053,14 +1057,15 @@ static void __ztest_show_suite_summary(void)
}
static int __ztest_run_test_suite(struct ztest_suite_node *ptr, const void *state, bool shuffle,
int suite_iter, int case_iter)
int suite_iter, int case_iter, void *param)
{
struct ztest_suite_stats *stats = ptr->stats;
int count = 0;
for (int i = 0; i < suite_iter; i++) {
if (ztest_api.should_suite_run(state, ptr)) {
int fail = z_ztest_run_test_suite_ptr(ptr, shuffle, suite_iter, case_iter);
int fail = z_ztest_run_test_suite_ptr(ptr, shuffle,
suite_iter, case_iter, param);
count++;
stats->run_count++;
@ -1076,7 +1081,7 @@ static int __ztest_run_test_suite(struct ztest_suite_node *ptr, const void *stat
int z_impl_ztest_run_test_suites(const void *state, bool shuffle, int suite_iter, int case_iter)
{
int count = 0;
void *param = NULL;
if (test_status == ZTEST_STATUS_CRITICAL_ERROR) {
return count;
}
@ -1096,7 +1101,7 @@ int z_impl_ztest_run_test_suites(const void *state, bool shuffle, int suite_iter
}
for (size_t i = 0; i < ZTEST_SUITE_COUNT; ++i) {
count += __ztest_run_test_suite(suites_to_run[i], state, shuffle, suite_iter,
case_iter);
case_iter, param);
/* Stop running tests if we have a critical error or if we have a failure and
* FAIL_FAST was set
*/
@ -1109,7 +1114,7 @@ int z_impl_ztest_run_test_suites(const void *state, bool shuffle, int suite_iter
for (struct ztest_suite_node *ptr = _ztest_suite_node_list_start;
ptr < _ztest_suite_node_list_end; ++ptr) {
__ztest_init_unit_test_result_for_suite(ptr);
count += __ztest_run_test_suite(ptr, state, shuffle, suite_iter, case_iter);
count += __ztest_run_test_suite(ptr, state, shuffle, suite_iter, case_iter, param);
/* Stop running tests if we have a critical error or if we have a failure and
* FAIL_FAST was set
*/
@ -1322,10 +1327,10 @@ static int cmd_run_suite(const struct shell *sh, size_t argc, char **argv)
int opt_index = 0;
int val;
int opt_num = 0;
void *param = NULL;
int repeat_iter = 1;
while ((opt = getopt_long(argc, argv, "r:", long_options, &opt_index)) != -1) {
while ((opt = getopt_long(argc, argv, "r:p:", long_options, &opt_index)) != -1) {
state = getopt_state_get();
switch (opt) {
case 'r':
@ -1338,6 +1343,10 @@ static int cmd_run_suite(const struct shell *sh, size_t argc, char **argv)
repeat_iter = val;
opt_num++;
break;
case 'p':
param = state->optarg;
opt_num++;
break;
default:
shell_fprintf(sh, SHELL_ERROR,
"Invalid option or option usage: %s\n", argv[opt_index + 1]);
@ -1349,10 +1358,10 @@ static int cmd_run_suite(const struct shell *sh, size_t argc, char **argv)
const char *shell_command = argv[0];
/*
* This if statement sets the appropriate test argument for ztest_set_test_args.
* If the optional argument is used (opt_num == 1), it sets the test argument to the third element (argv[3]).
* If the optional argument is not used, it sets the test argument to the first element (argv[1]).
*/
* This if statement determines which argv contains the test name.
* If the optional argument is used, the test name is in the third
* argv instead of the first.
*/
if (opt_num == 1) {
ztest_set_test_args(argv[3]);
} else {
@ -1363,9 +1372,9 @@ static int cmd_run_suite(const struct shell *sh, size_t argc, char **argv)
ptr < _ztest_suite_node_list_end; ++ptr) {
__ztest_init_unit_test_result_for_suite(ptr);
if (strcmp(shell_command, "run-testcase") == 0) {
count += __ztest_run_test_suite(ptr, NULL, shuffle, 1, repeat_iter);
count += __ztest_run_test_suite(ptr, NULL, shuffle, 1, repeat_iter, param);
} else if (strcmp(shell_command, "run-testsuite") == 0) {
count += __ztest_run_test_suite(ptr, NULL, shuffle, repeat_iter, 1);
count += __ztest_run_test_suite(ptr, NULL, shuffle, repeat_iter, 1, NULL);
}
if (test_status == ZTEST_STATUS_CRITICAL_ERROR ||
(test_status == ZTEST_STATUS_HAS_FAILURE && FAIL_FAST)) {