Branch data Line data Source code
1 : : /*
2 : : * Copyright (c) 2022 Google LLC
3 : : *
4 : : * SPDX-License-Identifier: Apache-2.0
5 : : */
6 : :
7 : : #include <stdio.h>
8 : : #include <stdlib.h>
9 : : #include "cmdline.h" /* native_sim command line options header */
10 : : #include "soc.h"
11 : : #include <zephyr/tc_util.h>
12 : : #include <zephyr/ztest_test.h>
13 : : #include "nsi_host_trampolines.h"
14 : : #include <nsi_tracing.h>
15 : :
16 : : static const char *test_args;
17 : : static bool list_tests;
18 : :
19 : : #if !defined(CONFIG_ZTEST_SHELL)
20 : 1 : static void add_test_filter_option(void)
21 : : {
22 : 1 : static struct args_struct_t test_filter_s[] = {
23 : : /*
24 : : * Fields:
25 : : * manual, mandatory, switch,
26 : : * option_name, var_name ,type,
27 : : * destination, callback,
28 : : * description
29 : : */
30 : : { false, false, true, "list", NULL, 'b', (void *)&list_tests, NULL,
31 : : "List all suite and test cases" },
32 : : { false, false, false, "test", "suite::test", 's', (void *)&test_args, NULL,
33 : : "Name of tests to run. Comma separated list formatted as "
34 : : "\'suiteA::test1,suiteA::test2,suiteB::*\'. An * can be used "
35 : : "as a wildcard to run all tests within a suite." },
36 : : ARG_TABLE_ENDMARKER
37 : : };
38 : :
39 : 1 : native_add_command_line_opts(test_filter_s);
40 : 1 : }
41 : :
42 : : NATIVE_TASK(add_test_filter_option, PRE_BOOT_1, 10);
43 : : #endif
44 : :
45 : : /**
46 : : * @brief Try to shorten a filename by removing the current directory
47 : : *
48 : : * This helps to reduce the very long filenames in assertion failures. It
49 : : * removes the current directory from the filename and returns the rest.
50 : : * This makes assertions a lot more readable, and sometimes they fit on one
51 : : * line.
52 : : *
53 : : * Overrides implementation in ztest.c
54 : : *
55 : : * @param file Filename to check
56 : : * @returns Shortened filename, or @file if it could not be shortened
57 : : */
58 : 0 : const char *ztest_relative_filename(const char *file)
59 : : {
60 : 0 : const char *cwd;
61 : 0 : char buf[200];
62 : :
63 : 0 : cwd = nsi_host_getcwd(buf, sizeof(buf));
64 [ # # # # : 0 : if (cwd && strlen(file) > strlen(cwd) && !strncmp(file, cwd, strlen(cwd))) {
# # ]
65 : 0 : return file + strlen(cwd) + 1; /* move past the trailing '/' */
66 : : }
67 : : return file;
68 : : }
69 : :
70 : : /**
71 : : * @brief Helper function to set list_tests
72 : : *
73 : : * @param value - Sets list_tests to value
74 : : */
75 : 0 : void ztest_set_list_test(bool value)
76 : : {
77 : 0 : list_tests = value;
78 : 0 : }
79 : :
80 : : /**
81 : : * @brief Helper function to get command line argument for listing tests
82 : : *
83 : : * @return true
84 : : * @return false
85 : : */
86 : 1 : bool z_ztest_get_list_test(void)
87 : : {
88 : 1 : return list_tests;
89 : : }
90 : :
91 : 0 : void ztest_reset_test_args(void)
92 : : {
93 [ # # ]: 0 : if (test_args != NULL) {
94 : 0 : nsi_host_free((void *)test_args);
95 : : }
96 : 0 : test_args = NULL;
97 : 0 : }
98 : :
99 : 0 : void ztest_set_test_args(char *args)
100 : : {
101 : 0 : ztest_reset_test_args();
102 : 0 : test_args = nsi_host_strdup(args);
103 : 0 : }
104 : :
105 : : /**
106 : : * @brief Helper function to get command line test arguments
107 : : *
108 : : * @return const char*
109 : : */
110 : 0 : const char *ztest_get_test_args(void)
111 : : {
112 : 0 : return test_args;
113 : : }
114 : :
115 : :
116 : :
117 : : /**
118 : : * @brief Lists registered unit tests in this binary, one per line
119 : : *
120 : : * @return int Number of tests in binary
121 : : */
122 : 0 : int z_ztest_list_tests(void)
123 : : {
124 : 0 : struct ztest_suite_node *ptr;
125 : 0 : struct ztest_unit_test *test = NULL;
126 : 0 : int test_count = 0;
127 : 0 : static bool list_once = true;
128 : :
129 [ # # ]: 0 : if (list_once) {
130 [ # # ]: 0 : for (ptr = _ztest_suite_node_list_start; ptr < _ztest_suite_node_list_end; ++ptr) {
131 : : test = NULL;
132 [ # # ]: 0 : while ((test = z_ztest_get_next_test(ptr->name, test)) != NULL) {
133 : 0 : TC_PRINT("%s::%s\n", test->test_suite_name, test->name);
134 : 0 : test_count++;
135 : : }
136 : : }
137 : 0 : list_once = false;
138 : : }
139 : :
140 : 0 : return test_count;
141 : : }
142 : :
143 : : /**
144 : : * Default entry point for running or listing registered unit tests.
145 : : *
146 : : * @param state The current state of the machine as it relates to the test executable.
147 : : */
148 : 1 : void z_ztest_run_all(const void *state, bool shuffle, int suite_iter, int case_iter)
149 : : {
150 [ - + ]: 1 : if (z_ztest_get_list_test()) {
151 : 0 : z_ztest_list_tests();
152 : : } else {
153 : 1 : ztest_run_test_suites(state, shuffle, suite_iter, case_iter);
154 : : }
155 : 1 : }
156 : :
157 : : /**
158 : : * @brief Checks if the test_args contains the suite/test name.
159 : : *
160 : : * @param suite_name
161 : : * @param test_name
162 : : * @return true
163 : : * @return false
164 : : */
165 : 0 : static bool z_ztest_testargs_contains(const char *suite_name, const char *test_name)
166 : : {
167 : 0 : bool found = false;
168 : 0 : char *test_args_local = nsi_host_strdup(test_args);
169 : 0 : char *suite_test_pair;
170 : 0 : char *last_suite_test_pair;
171 : 0 : char *suite_arg;
172 : 0 : char *test_arg;
173 : 0 : char *last_arg;
174 : :
175 : 0 : suite_test_pair = strtok_r(test_args_local, ",", &last_suite_test_pair);
176 : :
177 [ # # ]: 0 : while (suite_test_pair && !found) {
178 : 0 : suite_arg = strtok_r(suite_test_pair, ":", &last_arg);
179 : 0 : test_arg = strtok_r(NULL, ":", &last_arg);
180 : :
181 : : /* Validate format: must be test_suite::* or test_suite::test_case */
182 [ # # # # ]: 0 : if (!suite_arg || !test_arg || strtok_r(NULL, ":", &last_arg) != NULL) {
183 : : /* Invalid format, report error and exit */
184 : 0 : nsi_print_error_and_exit(
185 : : "Invalid test argument format '%s'. Expected a set of pairs like"
186 : : "'suite::test' or 'suite::*', got instead '%s'.\n",
187 : : test_args, suite_test_pair);
188 : : }
189 : :
190 : 0 : found = !strcmp(suite_arg, suite_name);
191 [ # # ]: 0 : if (test_name) {
192 [ # # # # ]: 0 : found &= (!strcmp(test_arg, "*") || !strcmp(test_arg, test_name));
193 : : }
194 : :
195 : 0 : suite_test_pair = strtok_r(NULL, ",", &last_suite_test_pair);
196 : : }
197 : :
198 : 0 : nsi_host_free(test_args_local);
199 : 0 : return found;
200 : : }
201 : :
202 : : /**
203 : : * @brief Determines if the test case should run based on test cases listed
204 : : * in the command line argument.
205 : : *
206 : : * Overrides implementation in ztest.c
207 : : *
208 : : * @param suite - name of test suite
209 : : * @param test - name of unit test
210 : : * @return true
211 : : * @return false
212 : : */
213 : 42 : bool z_ztest_should_test_run(const char *suite, const char *test)
214 : : {
215 : 42 : bool run_test = false;
216 : :
217 [ - + - - ]: 42 : run_test = (test_args == NULL ||
218 : 0 : z_ztest_testargs_contains(suite, test));
219 : :
220 : 42 : return run_test;
221 : : }
222 : :
223 : : /**
224 : : * @brief Determines if the test suite should run based on test cases listed
225 : : * in the command line argument.
226 : : *
227 : : * Overrides implementation in ztest.c
228 : : *
229 : : * @param state The current state of the machine as it relates to the test
230 : : * executable.
231 : : * @param suite Pointer to ztest_suite_node
232 : : * @return true
233 : : * @return false
234 : : */
235 : 1 : bool z_ztest_should_suite_run(const void *state, struct ztest_suite_node *suite)
236 : : {
237 : 1 : bool run_suite = true;
238 : :
239 [ - + - - ]: 1 : if (test_args != NULL && !z_ztest_testargs_contains(suite->name, NULL)) {
240 : 0 : run_suite = false;
241 : 0 : suite->stats->run_count++;
242 [ - + ]: 1 : } else if (suite->predicate != NULL) {
243 : 0 : run_suite = suite->predicate(state);
244 : : }
245 : :
246 : 1 : return run_suite;
247 : : }
248 : :
249 : : ZTEST_DMEM const struct ztest_arch_api ztest_api = {
250 : : .run_all = z_ztest_run_all,
251 : : .should_suite_run = z_ztest_should_suite_run,
252 : : .should_test_run = z_ztest_should_test_run
253 : : };
|