blob: b44e60d5a8763cf1a4e001a4807d3fc597d6a907 [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>
Simon Glass81cbe1c2017-11-25 11:57:29 -070010#include <test/test.h>
Simon Glass5722fb22021-03-07 17:34:47 -070011#include <test/ut.h>
Joe Hershberger11dd7cc2015-05-20 14:27:28 -050012
Simon Glass78fd76b2025-01-20 14:25:33 -070013/**
14 * struct suite - A set of tests for a certain topic
15 *
16 * All tests end up in a single 'struct unit_test' linker-list array, in order
17 * of the suite they are in
18 *
19 * @name: Name of suite
20 * @start: First test in suite
21 * @end: End test in suite (points to the first test in the next suite)
Simon Glass46093b32025-01-20 14:26:05 -070022 * @help: Help-string to show for this suite
Simon Glass78fd76b2025-01-20 14:25:33 -070023 */
24struct suite {
25 const char *name;
26 struct unit_test *start;
27 struct unit_test *end;
Simon Glass46093b32025-01-20 14:26:05 -070028 const char *help;
Simon Glass78fd76b2025-01-20 14:25:33 -070029};
30
Simon Glass6685ece2025-01-20 14:25:58 -070031static int do_ut_all(struct unit_test_state *uts, struct cmd_tbl *cmdtp,
32 int flag, int argc, char *const argv[]);
Joe Hershberger11dd7cc2015-05-20 14:27:28 -050033
Simon Glassfb998c22022-10-29 19:47:12 -060034static int do_ut_info(struct cmd_tbl *cmdtp, int flag, int argc,
35 char *const argv[]);
36
Simon Glass623e01c2025-02-07 11:30:55 -070037static int cmd_ut_category(struct unit_test_state *uts, const char *name,
38 const char *prefix, struct unit_test *tests,
39 int n_ents, int argc, char *const argv[])
Simon Glass81cbe1c2017-11-25 11:57:29 -070040{
Simon Glass85ba7c32022-10-29 19:47:13 -060041 const char *test_insert = NULL;
Simon Glass91a187b2022-08-01 07:58:45 -060042 int runs_per_text = 1;
Simon Glass1f1614b2022-10-20 18:22:50 -060043 bool force_run = false;
Simon Glass5722fb22021-03-07 17:34:47 -070044 int ret;
Simon Glass81cbe1c2017-11-25 11:57:29 -070045
Simon Glass1f1614b2022-10-20 18:22:50 -060046 while (argc > 1 && *argv[1] == '-') {
47 const char *str = argv[1];
48
49 switch (str[1]) {
50 case 'r':
51 runs_per_text = dectoul(str + 2, NULL);
52 break;
53 case 'f':
54 force_run = true;
55 break;
Simon Glass85ba7c32022-10-29 19:47:13 -060056 case 'I':
57 test_insert = str + 2;
58 break;
Simon Glass1f1614b2022-10-20 18:22:50 -060059 }
Simon Glass91a187b2022-08-01 07:58:45 -060060 argv++;
Simon Glass85ba7c32022-10-29 19:47:13 -060061 argc--;
Simon Glass91a187b2022-08-01 07:58:45 -060062 }
63
Simon Glass6685ece2025-01-20 14:25:58 -070064 ret = ut_run_list(uts, name, prefix, tests, n_ents,
Simon Glass793a98e2023-11-18 14:05:20 -070065 cmd_arg1(argc, argv), runs_per_text, force_run,
Simon Glass85ba7c32022-10-29 19:47:13 -060066 test_insert);
Simon Glass81cbe1c2017-11-25 11:57:29 -070067
Simon Glass5722fb22021-03-07 17:34:47 -070068 return ret ? CMD_RET_FAILURE : 0;
Simon Glass81cbe1c2017-11-25 11:57:29 -070069}
70
Simon Glass78fd76b2025-01-20 14:25:33 -070071/* declare linker-list symbols for the start and end of a suite */
72#define SUITE_DECL(_name) \
73 ll_start_decl(suite_start_ ## _name, struct unit_test, ut_ ## _name); \
74 ll_end_decl(suite_end_ ## _name, struct unit_test, ut_ ## _name)
75
Simon Glass78fd76b2025-01-20 14:25:33 -070076/* declare a test suite which can be run directly without a subcommand */
Simon Glass46093b32025-01-20 14:26:05 -070077#define SUITE(_name, _help) { \
Simon Glass78fd76b2025-01-20 14:25:33 -070078 #_name, \
79 suite_start_ ## _name, \
80 suite_end_ ## _name, \
Simon Glass46093b32025-01-20 14:26:05 -070081 _help, \
Simon Glass78fd76b2025-01-20 14:25:33 -070082 }
83
Simon Glass4c990702025-01-20 14:26:03 -070084SUITE_DECL(addrmap);
Simon Glass78fd76b2025-01-20 14:25:33 -070085SUITE_DECL(bdinfo);
Simon Glass4c990702025-01-20 14:26:03 -070086SUITE_DECL(bloblist);
87SUITE_DECL(bootm);
Simon Glass78fd76b2025-01-20 14:25:33 -070088SUITE_DECL(bootstd);
89SUITE_DECL(cmd);
90SUITE_DECL(common);
91SUITE_DECL(dm);
92SUITE_DECL(env);
93SUITE_DECL(exit);
94SUITE_DECL(fdt);
Simon Glass04e76d52025-02-07 11:30:39 -070095SUITE_DECL(fdt_overlay);
Simon Glass78fd76b2025-01-20 14:25:33 -070096SUITE_DECL(font);
Simon Glass4c990702025-01-20 14:26:03 -070097SUITE_DECL(hush);
Simon Glass78fd76b2025-01-20 14:25:33 -070098SUITE_DECL(lib);
Simon Glass4c990702025-01-20 14:26:03 -070099SUITE_DECL(loadm);
Simon Glass78fd76b2025-01-20 14:25:33 -0700100SUITE_DECL(log);
101SUITE_DECL(mbr);
Simon Glass78fd76b2025-01-20 14:25:33 -0700102SUITE_DECL(measurement);
Simon Glass4c990702025-01-20 14:26:03 -0700103SUITE_DECL(mem);
104SUITE_DECL(optee);
Simon Glass78fd76b2025-01-20 14:25:33 -0700105SUITE_DECL(pci_mps);
106SUITE_DECL(seama);
Simon Glass4c990702025-01-20 14:26:03 -0700107SUITE_DECL(setexpr);
Simon Glass78fd76b2025-01-20 14:25:33 -0700108SUITE_DECL(upl);
109
110static struct suite suites[] = {
Simon Glass46093b32025-01-20 14:26:05 -0700111 SUITE(addrmap, "very basic test of addrmap command"),
112 SUITE(bdinfo, "bdinfo (board info) command"),
113 SUITE(bloblist, "bloblist implementation"),
114 SUITE(bootm, "bootm command"),
Simon Glassf8573fc2025-02-07 11:30:49 -0700115 SUITE(bootstd, "standard boot implementation"),
Simon Glass46093b32025-01-20 14:26:05 -0700116 SUITE(cmd, "various commands"),
117 SUITE(common, "tests for common/ directory"),
118 SUITE(dm, "driver model"),
119 SUITE(env, "environment"),
120 SUITE(exit, "shell exit and variables"),
121 SUITE(fdt, "fdt command"),
Simon Glass0f50f902025-02-07 11:30:47 -0700122 SUITE(fdt_overlay, "device tree overlays"),
Simon Glass46093b32025-01-20 14:26:05 -0700123 SUITE(font, "font command"),
124 SUITE(hush, "hush behaviour"),
125 SUITE(lib, "library functions"),
126 SUITE(loadm, "loadm command parameters and loading memory blob"),
127 SUITE(log, "logging functions"),
128 SUITE(mbr, "mbr command"),
129 SUITE(measurement, "TPM-based measured boot"),
130 SUITE(mem, "memory-related commands"),
Simon Glass3947f792025-02-07 11:30:52 -0700131 SUITE(optee, "OP-TEE"),
Simon Glass46093b32025-01-20 14:26:05 -0700132 SUITE(pci_mps, "PCI Express Maximum Payload Size"),
133 SUITE(seama, "seama command parameters loading and decoding"),
134 SUITE(setexpr, "setexpr command"),
135 SUITE(upl, "Universal payload support"),
Joe Hershberger11dd7cc2015-05-20 14:27:28 -0500136};
137
Simon Glassa3ce1292025-01-20 14:25:57 -0700138/**
139 * has_tests() - Check if a suite has tests, i.e. is supported in this build
140 *
141 * If the suite is run using a command, we have to assume that tests may be
142 * present, since we have no visibility
143 *
144 * @ste: Suite to check
145 * Return: true if supported, false if not
146 */
147static bool has_tests(struct suite *ste)
148{
149 int n_ents = ste->end - ste->start;
150
Simon Glass0a85dd02025-02-07 11:30:54 -0700151 return n_ents;
Simon Glassa3ce1292025-01-20 14:25:57 -0700152}
153
Simon Glass78fd76b2025-01-20 14:25:33 -0700154/** run_suite() - Run a suite of tests */
Simon Glass6685ece2025-01-20 14:25:58 -0700155static int run_suite(struct unit_test_state *uts, struct suite *ste,
156 struct cmd_tbl *cmdtp, int flag, int argc,
157 char *const argv[])
Simon Glass78fd76b2025-01-20 14:25:33 -0700158{
Simon Glass0a85dd02025-02-07 11:30:54 -0700159 int n_ents = ste->end - ste->start;
160 char prefix[30];
Simon Glass78fd76b2025-01-20 14:25:33 -0700161 int ret;
162
Simon Glass78fd76b2025-01-20 14:25:33 -0700163
Simon Glass0a85dd02025-02-07 11:30:54 -0700164 /* use a standard prefix */
165 snprintf(prefix, sizeof(prefix), "%s_test_", ste->name);
166 ret = cmd_ut_category(uts, ste->name, prefix, ste->start, n_ents,
167 argc, argv);
Simon Glass78fd76b2025-01-20 14:25:33 -0700168
169 return ret;
170}
171
Simon Glassbd9b1512025-02-07 11:30:36 -0700172static void show_stats(struct unit_test_state *uts)
173{
174 if (uts->run_count < 2)
175 return;
176
177 ut_report(&uts->total, uts->run_count);
178 if (CONFIG_IS_ENABLED(UNIT_TEST_DURATION) &&
179 uts->total.test_count && uts->worst) {
180 ulong avg = uts->total.duration_ms / uts->total.test_count;
181
182 printf("Average test time: %ld ms, worst case '%s' took %d ms\n",
183 avg, uts->worst->name, uts->worst_ms);
184 }
185}
186
187static void update_stats(struct unit_test_state *uts, const struct suite *ste)
188{
189 if (CONFIG_IS_ENABLED(UNIT_TEST_DURATION) && uts->cur.test_count) {
190 ulong avg;
191
192 avg = uts->cur.duration_ms ?
193 uts->cur.duration_ms /
194 uts->cur.test_count : 0;
195 if (avg > uts->worst_ms) {
196 uts->worst_ms = avg;
197 uts->worst = ste;
198 }
199 }
200}
201
Simon Glass6685ece2025-01-20 14:25:58 -0700202static int do_ut_all(struct unit_test_state *uts, struct cmd_tbl *cmdtp,
203 int flag, int argc, char *const argv[])
Joe Hershberger11dd7cc2015-05-20 14:27:28 -0500204{
205 int i;
206 int retval;
207 int any_fail = 0;
208
Simon Glass78fd76b2025-01-20 14:25:33 -0700209 for (i = 0; i < ARRAY_SIZE(suites); i++) {
210 struct suite *ste = &suites[i];
211 char *const argv[] = {(char *)ste->name, NULL};
212
Simon Glassa3ce1292025-01-20 14:25:57 -0700213 if (has_tests(ste)) {
214 printf("----Running %s tests----\n", ste->name);
Simon Glass6685ece2025-01-20 14:25:58 -0700215 retval = run_suite(uts, ste, cmdtp, flag, 1, argv);
Simon Glassa3ce1292025-01-20 14:25:57 -0700216 if (!any_fail)
217 any_fail = retval;
Simon Glassbd9b1512025-02-07 11:30:36 -0700218 update_stats(uts, ste);
Simon Glassa3ce1292025-01-20 14:25:57 -0700219 }
Joe Hershberger11dd7cc2015-05-20 14:27:28 -0500220 }
Simon Glassfb82a042025-01-20 14:26:02 -0700221 ut_report(&uts->total, uts->run_count);
Joe Hershberger11dd7cc2015-05-20 14:27:28 -0500222
223 return any_fail;
224}
225
Simon Glassfb998c22022-10-29 19:47:12 -0600226static int do_ut_info(struct cmd_tbl *cmdtp, int flag, int argc,
227 char *const argv[])
228{
Simon Glassa3ce1292025-01-20 14:25:57 -0700229 int suite_count, i;
Simon Glasscfb38f82025-01-20 14:25:30 -0700230 const char *flags;
231
Simon Glassa3ce1292025-01-20 14:25:57 -0700232 for (suite_count = 0, i = 0; i < ARRAY_SIZE(suites); i++) {
233 struct suite *ste = &suites[i];
234
235 if (has_tests(ste))
236 suite_count++;
237 }
238
239 printf("Test suites: %d\n", suite_count);
Simon Glassfb998c22022-10-29 19:47:12 -0600240 printf("Total tests: %d\n", (int)UNIT_TEST_ALL_COUNT());
241
Simon Glasscfb38f82025-01-20 14:25:30 -0700242 flags = cmd_arg1(argc, argv);
243 if (flags && !strcmp("-s", flags)) {
Simon Glass3669a972025-02-07 11:30:34 -0700244 int i, total;
Simon Glasscfb38f82025-01-20 14:25:30 -0700245
Simon Glass46093b32025-01-20 14:26:05 -0700246 puts("\nTests Suite Purpose");
247 puts("\n----- ------------ -------------------------\n");
Simon Glass3669a972025-02-07 11:30:34 -0700248 for (i = 0, total = 0; i < ARRAY_SIZE(suites); i++) {
Simon Glass78fd76b2025-01-20 14:25:33 -0700249 struct suite *ste = &suites[i];
250 long n_ent = ste->end - ste->start;
251
Simon Glass0a85dd02025-02-07 11:30:54 -0700252 if (n_ent) {
253 printf("%5ld %-13.13s %s\n", n_ent, ste->name,
254 ste->help);
255 total += n_ent;
256 }
Simon Glass78fd76b2025-01-20 14:25:33 -0700257 }
Simon Glass3669a972025-02-07 11:30:34 -0700258 puts("----- ------------ -------------------------\n");
259 printf("%5d %-13.13s\n", total, "Total");
260
261 if (UNIT_TEST_ALL_COUNT() != total)
262 puts("Error: Suite test-count does not match total\n");
Simon Glasscfb38f82025-01-20 14:25:30 -0700263 }
264
Simon Glassfb998c22022-10-29 19:47:12 -0600265 return 0;
266}
267
Simon Glass78fd76b2025-01-20 14:25:33 -0700268static struct suite *find_suite(const char *name)
269{
270 struct suite *ste;
271 int i;
272
273 for (i = 0, ste = suites; i < ARRAY_SIZE(suites); i++, ste++) {
274 if (!strcmp(ste->name, name))
275 return ste;
276 }
277
278 return NULL;
279}
280
Simon Glassed38aef2020-05-10 11:40:03 -0600281static int do_ut(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
Joe Hershberger11dd7cc2015-05-20 14:27:28 -0500282{
Simon Glass6685ece2025-01-20 14:25:58 -0700283 struct unit_test_state uts;
Simon Glass78fd76b2025-01-20 14:25:33 -0700284 struct suite *ste;
285 const char *name;
286 int ret;
Joe Hershberger11dd7cc2015-05-20 14:27:28 -0500287
288 if (argc < 2)
289 return CMD_RET_USAGE;
290
291 /* drop initial "ut" arg */
292 argc--;
293 argv++;
294
Simon Glass6685ece2025-01-20 14:25:58 -0700295 ut_init_state(&uts);
Simon Glass78fd76b2025-01-20 14:25:33 -0700296 name = argv[0];
297 if (!strcmp(name, "all")) {
Simon Glass6685ece2025-01-20 14:25:58 -0700298 ret = do_ut_all(&uts, cmdtp, flag, argc, argv);
Simon Glass78fd76b2025-01-20 14:25:33 -0700299 } else if (!strcmp(name, "info")) {
300 ret = do_ut_info(cmdtp, flag, argc, argv);
301 } else {
302 ste = find_suite(argv[0]);
303 if (!ste) {
304 printf("Suite '%s' not found\n", argv[0]);
305 return CMD_RET_FAILURE;
Simon Glassa3ce1292025-01-20 14:25:57 -0700306 } else if (!has_tests(ste)) {
307 /* perhaps a Kconfig option needs to be set? */
308 printf("Suite '%s' is not enabled\n", argv[0]);
309 return CMD_RET_FAILURE;
Simon Glass78fd76b2025-01-20 14:25:33 -0700310 }
Joe Hershberger11dd7cc2015-05-20 14:27:28 -0500311
Simon Glass6685ece2025-01-20 14:25:58 -0700312 ret = run_suite(&uts, ste, cmdtp, flag, argc, argv);
Simon Glass78fd76b2025-01-20 14:25:33 -0700313 }
Simon Glassbd9b1512025-02-07 11:30:36 -0700314 show_stats(&uts);
Simon Glass78fd76b2025-01-20 14:25:33 -0700315 if (ret)
316 return ret;
Simon Glass6685ece2025-01-20 14:25:58 -0700317 ut_uninit_state(&uts);
Joe Hershberger11dd7cc2015-05-20 14:27:28 -0500318
Simon Glass78fd76b2025-01-20 14:25:33 -0700319 return 0;
Joe Hershberger11dd7cc2015-05-20 14:27:28 -0500320}
321
Tom Rini03f146c2023-10-07 15:13:08 -0400322U_BOOT_LONGHELP(ut,
Simon Glass154bb8e2022-10-29 19:47:10 -0600323 "[-r] [-f] [<suite>] - run unit tests\n"
324 " -r<runs> Number of times to run each test\n"
325 " -f Force 'manual' tests to run as well\n"
326 " <suite> Test suite to run, or all\n"
327 "\n"
Simon Glassfb998c22022-10-29 19:47:12 -0600328 "\nOptions for <suite>:"
Simon Glass154bb8e2022-10-29 19:47:10 -0600329 "\nall - execute all enabled tests"
Simon Glasscfb38f82025-01-20 14:25:30 -0700330 "\ninfo [-s] - show info about tests [and suites]"
Tom Rini03f146c2023-10-07 15:13:08 -0400331 );
Joe Hershberger11dd7cc2015-05-20 14:27:28 -0500332
333U_BOOT_CMD(
334 ut, CONFIG_SYS_MAXARGS, 1, do_ut,
335 "unit tests", ut_help_text
336);