"Das U-Boot" Source Tree
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * (C) Copyright 2015
4 * Joe Hershberger, National Instruments, joe.hershberger@ni.com
5 */
6
7#include <command.h>
8#include <console.h>
9#include <vsprintf.h>
10#include <test/suites.h>
11#include <test/test.h>
12#include <test/ut.h>
13
14/**
15 * struct suite - A set of tests for a certain topic
16 *
17 * All tests end up in a single 'struct unit_test' linker-list array, in order
18 * of the suite they are in
19 *
20 * @name: Name of suite
21 * @start: First test in suite
22 * @end: End test in suite (points to the first test in the next suite)
23 * @cmd: Command to use to run the suite
24 * @help: Help-string to show for this suite
25 */
26struct suite {
27 const char *name;
28 struct unit_test *start;
29 struct unit_test *end;
30 ut_cmd_func cmd;
31 const char *help;
32};
33
34static int do_ut_all(struct unit_test_state *uts, struct cmd_tbl *cmdtp,
35 int flag, int argc, char *const argv[]);
36
37static int do_ut_info(struct cmd_tbl *cmdtp, int flag, int argc,
38 char *const argv[]);
39
40int cmd_ut_category(struct unit_test_state *uts, const char *name,
41 const char *prefix, struct unit_test *tests, int n_ents,
42 int argc, char *const argv[])
43{
44 const char *test_insert = NULL;
45 int runs_per_text = 1;
46 bool force_run = false;
47 int ret;
48
49 while (argc > 1 && *argv[1] == '-') {
50 const char *str = argv[1];
51
52 switch (str[1]) {
53 case 'r':
54 runs_per_text = dectoul(str + 2, NULL);
55 break;
56 case 'f':
57 force_run = true;
58 break;
59 case 'I':
60 test_insert = str + 2;
61 break;
62 }
63 argv++;
64 argc--;
65 }
66
67 ret = ut_run_list(uts, name, prefix, tests, n_ents,
68 cmd_arg1(argc, argv), runs_per_text, force_run,
69 test_insert);
70
71 return ret ? CMD_RET_FAILURE : 0;
72}
73
74/* declare linker-list symbols for the start and end of a suite */
75#define SUITE_DECL(_name) \
76 ll_start_decl(suite_start_ ## _name, struct unit_test, ut_ ## _name); \
77 ll_end_decl(suite_end_ ## _name, struct unit_test, ut_ ## _name)
78
79/* declare a test suite which uses a subcommand to run */
80#define SUITE_CMD(_name, _cmd_func, _help) { \
81 #_name, \
82 suite_start_ ## _name, \
83 suite_end_ ## _name, \
84 _cmd_func, \
85 _help, \
86 }
87
88/* declare a test suite which can be run directly without a subcommand */
89#define SUITE(_name, _help) { \
90 #_name, \
91 suite_start_ ## _name, \
92 suite_end_ ## _name, \
93 NULL, \
94 _help, \
95 }
96
97SUITE_DECL(addrmap);
98SUITE_DECL(bdinfo);
99SUITE_DECL(bloblist);
100SUITE_DECL(bootm);
101SUITE_DECL(bootstd);
102SUITE_DECL(cmd);
103SUITE_DECL(common);
104SUITE_DECL(dm);
105SUITE_DECL(env);
106SUITE_DECL(exit);
107SUITE_DECL(fdt);
108SUITE_DECL(font);
109SUITE_DECL(hush);
110SUITE_DECL(lib);
111SUITE_DECL(loadm);
112SUITE_DECL(log);
113SUITE_DECL(mbr);
114SUITE_DECL(measurement);
115SUITE_DECL(mem);
116SUITE_DECL(optee);
117SUITE_DECL(overlay);
118SUITE_DECL(pci_mps);
119SUITE_DECL(seama);
120SUITE_DECL(setexpr);
121SUITE_DECL(upl);
122
123static struct suite suites[] = {
124 SUITE(addrmap, "very basic test of addrmap command"),
125 SUITE(bdinfo, "bdinfo (board info) command"),
126 SUITE(bloblist, "bloblist implementation"),
127 SUITE(bootm, "bootm command"),
128#ifdef CONFIG_UT_BOOTSTD
129 SUITE_CMD(bootstd, do_ut_bootstd, "standard boot implementation"),
130#endif
131 SUITE(cmd, "various commands"),
132 SUITE(common, "tests for common/ directory"),
133 SUITE(dm, "driver model"),
134 SUITE(env, "environment"),
135 SUITE(exit, "shell exit and variables"),
136 SUITE(fdt, "fdt command"),
137 SUITE(font, "font command"),
138 SUITE(hush, "hush behaviour"),
139 SUITE(lib, "library functions"),
140 SUITE(loadm, "loadm command parameters and loading memory blob"),
141 SUITE(log, "logging functions"),
142 SUITE(mbr, "mbr command"),
143 SUITE(measurement, "TPM-based measured boot"),
144 SUITE(mem, "memory-related commands"),
145#ifdef CONFIG_UT_OPTEE
146 SUITE_CMD(optee, do_ut_optee, "OP-TEE"),
147#endif
148#ifdef CONFIG_UT_OVERLAY
149 SUITE_CMD(overlay, do_ut_overlay, "device tree overlays"),
150#endif
151 SUITE(pci_mps, "PCI Express Maximum Payload Size"),
152 SUITE(seama, "seama command parameters loading and decoding"),
153 SUITE(setexpr, "setexpr command"),
154 SUITE(upl, "Universal payload support"),
155};
156
157/**
158 * has_tests() - Check if a suite has tests, i.e. is supported in this build
159 *
160 * If the suite is run using a command, we have to assume that tests may be
161 * present, since we have no visibility
162 *
163 * @ste: Suite to check
164 * Return: true if supported, false if not
165 */
166static bool has_tests(struct suite *ste)
167{
168 int n_ents = ste->end - ste->start;
169
170 return n_ents || ste->cmd;
171}
172
173/** run_suite() - Run a suite of tests */
174static int run_suite(struct unit_test_state *uts, struct suite *ste,
175 struct cmd_tbl *cmdtp, int flag, int argc,
176 char *const argv[])
177{
178 int ret;
179
180 if (ste->cmd) {
181 ret = ste->cmd(uts, cmdtp, flag, argc, argv);
182 } else {
183 int n_ents = ste->end - ste->start;
184 char prefix[30];
185
186 /* use a standard prefix */
187 snprintf(prefix, sizeof(prefix), "%s_test", ste->name);
188 ret = cmd_ut_category(uts, ste->name, prefix, ste->start,
189 n_ents, argc, argv);
190 }
191
192 return ret;
193}
194
195static int do_ut_all(struct unit_test_state *uts, struct cmd_tbl *cmdtp,
196 int flag, int argc, char *const argv[])
197{
198 int i;
199 int retval;
200 int any_fail = 0;
201
202 for (i = 0; i < ARRAY_SIZE(suites); i++) {
203 struct suite *ste = &suites[i];
204 char *const argv[] = {(char *)ste->name, NULL};
205
206 if (has_tests(ste)) {
207 printf("----Running %s tests----\n", ste->name);
208 retval = run_suite(uts, ste, cmdtp, flag, 1, argv);
209 if (!any_fail)
210 any_fail = retval;
211 }
212 }
213 ut_report(&uts->total, uts->run_count);
214
215 return any_fail;
216}
217
218static int do_ut_info(struct cmd_tbl *cmdtp, int flag, int argc,
219 char *const argv[])
220{
221 int suite_count, i;
222 const char *flags;
223
224 for (suite_count = 0, i = 0; i < ARRAY_SIZE(suites); i++) {
225 struct suite *ste = &suites[i];
226
227 if (has_tests(ste))
228 suite_count++;
229 }
230
231 printf("Test suites: %d\n", suite_count);
232 printf("Total tests: %d\n", (int)UNIT_TEST_ALL_COUNT());
233
234 flags = cmd_arg1(argc, argv);
235 if (flags && !strcmp("-s", flags)) {
236 int i;
237
238 puts("\nTests Suite Purpose");
239 puts("\n----- ------------ -------------------------\n");
240 for (i = 0; i < ARRAY_SIZE(suites); i++) {
241 struct suite *ste = &suites[i];
242 long n_ent = ste->end - ste->start;
243
244 if (n_ent)
245 printf("%5ld", n_ent);
246 else if (ste->cmd)
247 printf("%5s", "?");
248 else /* suite is not present */
249 continue;
250 printf(" %-13.13s %s\n", ste->name, ste->help);
251 }
252 }
253
254 return 0;
255}
256
257static struct suite *find_suite(const char *name)
258{
259 struct suite *ste;
260 int i;
261
262 for (i = 0, ste = suites; i < ARRAY_SIZE(suites); i++, ste++) {
263 if (!strcmp(ste->name, name))
264 return ste;
265 }
266
267 return NULL;
268}
269
270static int do_ut(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
271{
272 struct unit_test_state uts;
273 struct suite *ste;
274 const char *name;
275 int ret;
276
277 if (argc < 2)
278 return CMD_RET_USAGE;
279
280 /* drop initial "ut" arg */
281 argc--;
282 argv++;
283
284 ut_init_state(&uts);
285 name = argv[0];
286 if (!strcmp(name, "all")) {
287 ret = do_ut_all(&uts, cmdtp, flag, argc, argv);
288 } else if (!strcmp(name, "info")) {
289 ret = do_ut_info(cmdtp, flag, argc, argv);
290 } else {
291 ste = find_suite(argv[0]);
292 if (!ste) {
293 printf("Suite '%s' not found\n", argv[0]);
294 return CMD_RET_FAILURE;
295 } else if (!has_tests(ste)) {
296 /* perhaps a Kconfig option needs to be set? */
297 printf("Suite '%s' is not enabled\n", argv[0]);
298 return CMD_RET_FAILURE;
299 }
300
301 ret = run_suite(&uts, ste, cmdtp, flag, argc, argv);
302 }
303 if (ret)
304 return ret;
305 ut_uninit_state(&uts);
306
307 return 0;
308}
309
310U_BOOT_LONGHELP(ut,
311 "[-r] [-f] [<suite>] - run unit tests\n"
312 " -r<runs> Number of times to run each test\n"
313 " -f Force 'manual' tests to run as well\n"
314 " <suite> Test suite to run, or all\n"
315 "\n"
316 "\nOptions for <suite>:"
317 "\nall - execute all enabled tests"
318 "\ninfo [-s] - show info about tests [and suites]"
319 );
320
321U_BOOT_CMD(
322 ut, CONFIG_SYS_MAXARGS, 1, do_ut,
323 "unit tests", ut_help_text
324);