| /* |
| * Copyright (c) 2022 Google LLC |
| * |
| * SPDX-License-Identifier: Apache-2.0 |
| */ |
| |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <unistd.h> |
| #include "cmdline.h" /* native_posix command line options header */ |
| #include "soc.h" |
| #include <zephyr/tc_util.h> |
| #include <zephyr/ztest_test_new.h> |
| |
| static const char *test_args; |
| static bool list_tests; |
| |
| static void add_test_filter_option(void) |
| { |
| static struct args_struct_t test_filter_s[] = { |
| /* |
| * Fields: |
| * manual, mandatory, switch, |
| * option_name, var_name ,type, |
| * destination, callback, |
| * description |
| */ |
| { false, false, true, "list", NULL, 'b', (void *)&list_tests, NULL, |
| "List all suite and test cases" }, |
| { false, false, false, "test", "suite::test", 's', (void *)&test_args, NULL, |
| "Name of tests to run. Comma separated list formatted as " |
| "\'suiteA::test1,suiteA::test2,suiteB::*\'. An * can be used " |
| "as a wildcard to run all tests within a suite." }, |
| ARG_TABLE_ENDMARKER |
| }; |
| |
| native_add_command_line_opts(test_filter_s); |
| } |
| |
| NATIVE_TASK(add_test_filter_option, PRE_BOOT_1, 10); |
| |
| /** |
| * @brief Try to shorten a filename by removing the current directory |
| * |
| * This helps to reduce the very long filenames in assertion failures. It |
| * removes the current directory from the filename and returns the rest. |
| * This makes assertions a lot more readable, and sometimes they fit on one |
| * line. |
| * |
| * Overrides implementation in ztest_new.c |
| * |
| * @param file Filename to check |
| * @returns Shortened filename, or @file if it could not be shortened |
| */ |
| const char *ztest_relative_filename(const char *file) |
| { |
| const char *cwd; |
| char buf[200]; |
| |
| cwd = getcwd(buf, sizeof(buf)); |
| if (cwd && strlen(file) > strlen(cwd) && !strncmp(file, cwd, strlen(cwd))) { |
| return file + strlen(cwd) + 1; /* move past the trailing '/' */ |
| } |
| return file; |
| } |
| |
| /** |
| * @brief Helper function to set list_tests |
| * |
| * @param value - Sets list_tests to value |
| */ |
| void ztest_set_list_test(bool value) |
| { |
| list_tests = value; |
| } |
| |
| /** |
| * @brief Helper function to get command line argument for listing tests |
| * |
| * @return true |
| * @return false |
| */ |
| bool z_ztest_get_list_test(void) |
| { |
| return list_tests; |
| } |
| |
| /** |
| * @brief Helper function to get command line test arguments |
| * |
| * @return const char* |
| */ |
| const char *ztest_get_test_args(void) |
| { |
| return test_args; |
| } |
| |
| /** |
| * @brief Lists registered unit tests in this binary, one per line |
| * |
| * @return int Number of tests in binary |
| */ |
| int z_ztest_list_tests(void) |
| { |
| struct ztest_suite_node *ptr; |
| struct ztest_unit_test *test = NULL; |
| int test_count = 0; |
| static bool list_once = true; |
| |
| if (list_once) { |
| for (ptr = _ztest_suite_node_list_start; ptr < _ztest_suite_node_list_end; ++ptr) { |
| test = NULL; |
| while ((test = z_ztest_get_next_test(ptr->name, test)) != NULL) { |
| TC_PRINT("%s::%s\n", test->test_suite_name, test->name); |
| test_count++; |
| } |
| } |
| list_once = false; |
| } |
| |
| return test_count; |
| } |
| |
| /** |
| * Default entry point for running or listing registered unit tests. |
| * |
| * @param state The current state of the machine as it relates to the test executable. |
| */ |
| void z_ztest_run_all(const void *state) |
| { |
| if (z_ztest_get_list_test()) { |
| z_ztest_list_tests(); |
| } else { |
| ztest_run_test_suites(state); |
| } |
| } |
| |
| /** |
| * @brief Checks if the test_args contains the suite/test name. |
| * |
| * @param suite_name |
| * @param test_name |
| * @return true |
| * @return false |
| */ |
| static bool z_ztest_testargs_contains(const char *suite_name, const char *test_name) |
| { |
| bool found = false; |
| char *test_args_local = strdup(test_args); |
| char *suite_test_pair; |
| char *last_suite_test_pair; |
| char *suite_arg; |
| char *test_arg; |
| char *last_arg; |
| |
| suite_test_pair = strtok_r(test_args_local, ",", &last_suite_test_pair); |
| |
| while (suite_test_pair && !found) { |
| suite_arg = strtok_r(suite_test_pair, ":", &last_arg); |
| test_arg = strtok_r(NULL, ":", &last_arg); |
| |
| found = !strcmp(suite_arg, suite_name); |
| if (test_name) { |
| found &= !strcmp(test_arg, "*") || |
| !strcmp(test_arg, test_name); |
| } |
| |
| suite_test_pair = strtok_r(NULL, ",", &last_suite_test_pair); |
| } |
| |
| free(test_args_local); |
| return found; |
| } |
| |
| /** |
| * @brief Determines if the test case should run based on test cases listed |
| * in the command line argument. |
| * |
| * Overrides implementation in ztest_new.c |
| * |
| * @param suite - name of test suite |
| * @param test - name of unit test |
| * @return true |
| * @return false |
| */ |
| bool z_ztest_should_test_run(const char *suite, const char *test) |
| { |
| bool run_test = false; |
| |
| run_test = (test_args == NULL || |
| z_ztest_testargs_contains(suite, test)); |
| |
| return run_test; |
| } |
| |
| /** |
| * @brief Determines if the test suite should run based on test cases listed |
| * in the command line argument. |
| * |
| * Overrides implementation in ztest_new.c |
| * |
| * @param state The current state of the machine as it relates to the test |
| * executable. |
| * @param suite Pointer to ztest_suite_node |
| * @return true |
| * @return false |
| */ |
| bool z_ztest_should_suite_run(const void *state, struct ztest_suite_node *suite) |
| { |
| bool run_suite = true; |
| |
| if (test_args != NULL && !z_ztest_testargs_contains(suite->name, NULL)) { |
| run_suite = false; |
| suite->stats->run_count++; |
| } else if (suite->predicate != NULL) { |
| run_suite = suite->predicate(state); |
| } |
| |
| return run_suite; |
| } |
| |
| ZTEST_DMEM const struct ztest_arch_api ztest_api = { |
| .run_all = z_ztest_run_all, |
| .should_suite_run = z_ztest_should_suite_run, |
| .should_test_run = z_ztest_should_test_run |
| }; |