blob: fbfdaaae0b54c86366802df3e85caf197ffdd4a1 [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0
Joe Hershberger11dd7cc2015-05-20 14:27:28 -05002/*
3 * (C) Copyright 2015
4 * Joe Hershberger, National Instruments, joe.hershberger@ni.com
Joe Hershberger11dd7cc2015-05-20 14:27:28 -05005 */
6
Joe Hershberger11dd7cc2015-05-20 14:27:28 -05007#include <command.h>
Simon Glass6db8ea52020-07-28 19:41:13 -06008#include <console.h>
Tom Rinidec7ea02024-05-20 13:35:03 -06009#include <vsprintf.h>
Joe Hershberger11dd7cc2015-05-20 14:27:28 -050010#include <test/suites.h>
Simon Glass81cbe1c2017-11-25 11:57:29 -070011#include <test/test.h>
Simon Glass5722fb22021-03-07 17:34:47 -070012#include <test/ut.h>
Joe Hershberger11dd7cc2015-05-20 14:27:28 -050013
Simon Glass78fd76b2025-01-20 14:25:33 -070014/**
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
Simon Glass46093b32025-01-20 14:26:05 -070024 * @help: Help-string to show for this suite
Simon Glass78fd76b2025-01-20 14:25:33 -070025 */
26struct suite {
27 const char *name;
28 struct unit_test *start;
29 struct unit_test *end;
30 ut_cmd_func cmd;
Simon Glass46093b32025-01-20 14:26:05 -070031 const char *help;
Simon Glass78fd76b2025-01-20 14:25:33 -070032};
33
Simon Glass6685ece2025-01-20 14:25:58 -070034static int do_ut_all(struct unit_test_state *uts, struct cmd_tbl *cmdtp,
35 int flag, int argc, char *const argv[]);
Joe Hershberger11dd7cc2015-05-20 14:27:28 -050036
Simon Glassfb998c22022-10-29 19:47:12 -060037static int do_ut_info(struct cmd_tbl *cmdtp, int flag, int argc,
38 char *const argv[]);
39
Simon Glass6685ece2025-01-20 14:25:58 -070040int cmd_ut_category(struct unit_test_state *uts, const char *name,
41 const char *prefix, struct unit_test *tests, int n_ents,
Simon Glassed38aef2020-05-10 11:40:03 -060042 int argc, char *const argv[])
Simon Glass81cbe1c2017-11-25 11:57:29 -070043{
Simon Glass85ba7c32022-10-29 19:47:13 -060044 const char *test_insert = NULL;
Simon Glass91a187b2022-08-01 07:58:45 -060045 int runs_per_text = 1;
Simon Glass1f1614b2022-10-20 18:22:50 -060046 bool force_run = false;
Simon Glass5722fb22021-03-07 17:34:47 -070047 int ret;
Simon Glass81cbe1c2017-11-25 11:57:29 -070048
Simon Glass1f1614b2022-10-20 18:22:50 -060049 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;
Simon Glass85ba7c32022-10-29 19:47:13 -060059 case 'I':
60 test_insert = str + 2;
61 break;
Simon Glass1f1614b2022-10-20 18:22:50 -060062 }
Simon Glass91a187b2022-08-01 07:58:45 -060063 argv++;
Simon Glass85ba7c32022-10-29 19:47:13 -060064 argc--;
Simon Glass91a187b2022-08-01 07:58:45 -060065 }
66
Simon Glass6685ece2025-01-20 14:25:58 -070067 ret = ut_run_list(uts, name, prefix, tests, n_ents,
Simon Glass793a98e2023-11-18 14:05:20 -070068 cmd_arg1(argc, argv), runs_per_text, force_run,
Simon Glass85ba7c32022-10-29 19:47:13 -060069 test_insert);
Simon Glass81cbe1c2017-11-25 11:57:29 -070070
Simon Glass5722fb22021-03-07 17:34:47 -070071 return ret ? CMD_RET_FAILURE : 0;
Simon Glass81cbe1c2017-11-25 11:57:29 -070072}
73
Simon Glass78fd76b2025-01-20 14:25:33 -070074/* 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 */
Simon Glass46093b32025-01-20 14:26:05 -070080#define SUITE_CMD(_name, _cmd_func, _help) { \
Simon Glass78fd76b2025-01-20 14:25:33 -070081 #_name, \
82 suite_start_ ## _name, \
83 suite_end_ ## _name, \
84 _cmd_func, \
Simon Glass46093b32025-01-20 14:26:05 -070085 _help, \
Simon Glass78fd76b2025-01-20 14:25:33 -070086 }
87
88/* declare a test suite which can be run directly without a subcommand */
Simon Glass46093b32025-01-20 14:26:05 -070089#define SUITE(_name, _help) { \
Simon Glass78fd76b2025-01-20 14:25:33 -070090 #_name, \
91 suite_start_ ## _name, \
92 suite_end_ ## _name, \
93 NULL, \
Simon Glass46093b32025-01-20 14:26:05 -070094 _help, \
Simon Glass78fd76b2025-01-20 14:25:33 -070095 }
96
Simon Glass4c990702025-01-20 14:26:03 -070097SUITE_DECL(addrmap);
Simon Glass78fd76b2025-01-20 14:25:33 -070098SUITE_DECL(bdinfo);
Simon Glass4c990702025-01-20 14:26:03 -070099SUITE_DECL(bloblist);
100SUITE_DECL(bootm);
Simon Glass78fd76b2025-01-20 14:25:33 -0700101SUITE_DECL(bootstd);
102SUITE_DECL(cmd);
103SUITE_DECL(common);
104SUITE_DECL(dm);
105SUITE_DECL(env);
106SUITE_DECL(exit);
107SUITE_DECL(fdt);
108SUITE_DECL(font);
Simon Glass4c990702025-01-20 14:26:03 -0700109SUITE_DECL(hush);
Simon Glass78fd76b2025-01-20 14:25:33 -0700110SUITE_DECL(lib);
Simon Glass4c990702025-01-20 14:26:03 -0700111SUITE_DECL(loadm);
Simon Glass78fd76b2025-01-20 14:25:33 -0700112SUITE_DECL(log);
113SUITE_DECL(mbr);
Simon Glass78fd76b2025-01-20 14:25:33 -0700114SUITE_DECL(measurement);
Simon Glass4c990702025-01-20 14:26:03 -0700115SUITE_DECL(mem);
116SUITE_DECL(optee);
117SUITE_DECL(overlay);
Simon Glass78fd76b2025-01-20 14:25:33 -0700118SUITE_DECL(pci_mps);
119SUITE_DECL(seama);
Simon Glass4c990702025-01-20 14:26:03 -0700120SUITE_DECL(setexpr);
Simon Glass78fd76b2025-01-20 14:25:33 -0700121SUITE_DECL(upl);
122
123static struct suite suites[] = {
Simon Glass46093b32025-01-20 14:26:05 -0700124 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"),
Simon Glass804aa372023-10-01 19:15:15 -0600128#ifdef CONFIG_UT_BOOTSTD
Simon Glass46093b32025-01-20 14:26:05 -0700129 SUITE_CMD(bootstd, do_ut_bootstd, "standard boot implementation"),
Simon Glassb255efc2022-04-24 23:31:24 -0600130#endif
Simon Glass46093b32025-01-20 14:26:05 -0700131 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"),
Heiko Stuebner1c9bb9b2019-10-23 16:46:41 +0200145#ifdef CONFIG_UT_OPTEE
Simon Glass46093b32025-01-20 14:26:05 -0700146 SUITE_CMD(optee, do_ut_optee, "OP-TEE"),
Heiko Stuebner1c9bb9b2019-10-23 16:46:41 +0200147#endif
Maxime Ripard0e31a112016-07-05 10:26:46 +0200148#ifdef CONFIG_UT_OVERLAY
Simon Glass46093b32025-01-20 14:26:05 -0700149 SUITE_CMD(overlay, do_ut_overlay, "device tree overlays"),
Maxime Ripard0e31a112016-07-05 10:26:46 +0200150#endif
Simon Glass46093b32025-01-20 14:26:05 -0700151 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"),
Joe Hershberger11dd7cc2015-05-20 14:27:28 -0500155};
156
Simon Glassa3ce1292025-01-20 14:25:57 -0700157/**
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
Simon Glass78fd76b2025-01-20 14:25:33 -0700173/** run_suite() - Run a suite of tests */
Simon Glass6685ece2025-01-20 14:25:58 -0700174static int run_suite(struct unit_test_state *uts, struct suite *ste,
175 struct cmd_tbl *cmdtp, int flag, int argc,
176 char *const argv[])
Simon Glass78fd76b2025-01-20 14:25:33 -0700177{
178 int ret;
179
180 if (ste->cmd) {
Simon Glass6685ece2025-01-20 14:25:58 -0700181 ret = ste->cmd(uts, cmdtp, flag, argc, argv);
Simon Glass78fd76b2025-01-20 14:25:33 -0700182 } 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);
Simon Glass6685ece2025-01-20 14:25:58 -0700188 ret = cmd_ut_category(uts, ste->name, prefix, ste->start,
189 n_ents, argc, argv);
Simon Glass78fd76b2025-01-20 14:25:33 -0700190 }
191
192 return ret;
193}
194
Simon Glass6685ece2025-01-20 14:25:58 -0700195static int do_ut_all(struct unit_test_state *uts, struct cmd_tbl *cmdtp,
196 int flag, int argc, char *const argv[])
Joe Hershberger11dd7cc2015-05-20 14:27:28 -0500197{
198 int i;
199 int retval;
200 int any_fail = 0;
201
Simon Glass78fd76b2025-01-20 14:25:33 -0700202 for (i = 0; i < ARRAY_SIZE(suites); i++) {
203 struct suite *ste = &suites[i];
204 char *const argv[] = {(char *)ste->name, NULL};
205
Simon Glassa3ce1292025-01-20 14:25:57 -0700206 if (has_tests(ste)) {
207 printf("----Running %s tests----\n", ste->name);
Simon Glass6685ece2025-01-20 14:25:58 -0700208 retval = run_suite(uts, ste, cmdtp, flag, 1, argv);
Simon Glassa3ce1292025-01-20 14:25:57 -0700209 if (!any_fail)
210 any_fail = retval;
211 }
Joe Hershberger11dd7cc2015-05-20 14:27:28 -0500212 }
Simon Glassfb82a042025-01-20 14:26:02 -0700213 ut_report(&uts->total, uts->run_count);
Joe Hershberger11dd7cc2015-05-20 14:27:28 -0500214
215 return any_fail;
216}
217
Simon Glassfb998c22022-10-29 19:47:12 -0600218static int do_ut_info(struct cmd_tbl *cmdtp, int flag, int argc,
219 char *const argv[])
220{
Simon Glassa3ce1292025-01-20 14:25:57 -0700221 int suite_count, i;
Simon Glasscfb38f82025-01-20 14:25:30 -0700222 const char *flags;
223
Simon Glassa3ce1292025-01-20 14:25:57 -0700224 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);
Simon Glassfb998c22022-10-29 19:47:12 -0600232 printf("Total tests: %d\n", (int)UNIT_TEST_ALL_COUNT());
233
Simon Glasscfb38f82025-01-20 14:25:30 -0700234 flags = cmd_arg1(argc, argv);
235 if (flags && !strcmp("-s", flags)) {
236 int i;
237
Simon Glass46093b32025-01-20 14:26:05 -0700238 puts("\nTests Suite Purpose");
239 puts("\n----- ------------ -------------------------\n");
Simon Glass7d4ae012025-01-20 14:25:56 -0700240 for (i = 0; i < ARRAY_SIZE(suites); i++) {
Simon Glass78fd76b2025-01-20 14:25:33 -0700241 struct suite *ste = &suites[i];
242 long n_ent = ste->end - ste->start;
243
244 if (n_ent)
Simon Glass46093b32025-01-20 14:26:05 -0700245 printf("%5ld", n_ent);
Simon Glassa3ce1292025-01-20 14:25:57 -0700246 else if (ste->cmd)
Simon Glass46093b32025-01-20 14:26:05 -0700247 printf("%5s", "?");
248 else /* suite is not present */
249 continue;
250 printf(" %-13.13s %s\n", ste->name, ste->help);
Simon Glass78fd76b2025-01-20 14:25:33 -0700251 }
Simon Glasscfb38f82025-01-20 14:25:30 -0700252 }
253
Simon Glassfb998c22022-10-29 19:47:12 -0600254 return 0;
255}
256
Simon Glass78fd76b2025-01-20 14:25:33 -0700257static 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
Simon Glassed38aef2020-05-10 11:40:03 -0600270static int do_ut(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
Joe Hershberger11dd7cc2015-05-20 14:27:28 -0500271{
Simon Glass6685ece2025-01-20 14:25:58 -0700272 struct unit_test_state uts;
Simon Glass78fd76b2025-01-20 14:25:33 -0700273 struct suite *ste;
274 const char *name;
275 int ret;
Joe Hershberger11dd7cc2015-05-20 14:27:28 -0500276
277 if (argc < 2)
278 return CMD_RET_USAGE;
279
280 /* drop initial "ut" arg */
281 argc--;
282 argv++;
283
Simon Glass6685ece2025-01-20 14:25:58 -0700284 ut_init_state(&uts);
Simon Glass78fd76b2025-01-20 14:25:33 -0700285 name = argv[0];
286 if (!strcmp(name, "all")) {
Simon Glass6685ece2025-01-20 14:25:58 -0700287 ret = do_ut_all(&uts, cmdtp, flag, argc, argv);
Simon Glass78fd76b2025-01-20 14:25:33 -0700288 } 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;
Simon Glassa3ce1292025-01-20 14:25:57 -0700295 } 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;
Simon Glass78fd76b2025-01-20 14:25:33 -0700299 }
Joe Hershberger11dd7cc2015-05-20 14:27:28 -0500300
Simon Glass6685ece2025-01-20 14:25:58 -0700301 ret = run_suite(&uts, ste, cmdtp, flag, argc, argv);
Simon Glass78fd76b2025-01-20 14:25:33 -0700302 }
303 if (ret)
304 return ret;
Simon Glass6685ece2025-01-20 14:25:58 -0700305 ut_uninit_state(&uts);
Joe Hershberger11dd7cc2015-05-20 14:27:28 -0500306
Simon Glass78fd76b2025-01-20 14:25:33 -0700307 return 0;
Joe Hershberger11dd7cc2015-05-20 14:27:28 -0500308}
309
Tom Rini03f146c2023-10-07 15:13:08 -0400310U_BOOT_LONGHELP(ut,
Simon Glass154bb8e2022-10-29 19:47:10 -0600311 "[-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"
Simon Glassfb998c22022-10-29 19:47:12 -0600316 "\nOptions for <suite>:"
Simon Glass154bb8e2022-10-29 19:47:10 -0600317 "\nall - execute all enabled tests"
Simon Glasscfb38f82025-01-20 14:25:30 -0700318 "\ninfo [-s] - show info about tests [and suites]"
Tom Rini03f146c2023-10-07 15:13:08 -0400319 );
Joe Hershberger11dd7cc2015-05-20 14:27:28 -0500320
321U_BOOT_CMD(
322 ut, CONFIG_SYS_MAXARGS, 1, do_ut,
323 "unit tests", ut_help_text
324);