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