blob: 44e5fdfdaa6eaa21c770f137c8ae928871ffb05d [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 Glassda9925f2025-02-07 11:30:59 -070031static int do_ut_all(struct unit_test_state *uts, const char *select_name,
32 int runs_per_test, bool force_run,
33 const char *test_insert);
Joe Hershberger11dd7cc2015-05-20 14:27:28 -050034
Simon Glassda9925f2025-02-07 11:30:59 -070035static int do_ut_info(bool show_suites);
Simon Glassfb998c22022-10-29 19:47:12 -060036
Simon Glass78fd76b2025-01-20 14:25:33 -070037/* declare linker-list symbols for the start and end of a suite */
38#define SUITE_DECL(_name) \
39 ll_start_decl(suite_start_ ## _name, struct unit_test, ut_ ## _name); \
40 ll_end_decl(suite_end_ ## _name, struct unit_test, ut_ ## _name)
41
Simon Glass78fd76b2025-01-20 14:25:33 -070042/* declare a test suite which can be run directly without a subcommand */
Simon Glass46093b32025-01-20 14:26:05 -070043#define SUITE(_name, _help) { \
Simon Glass78fd76b2025-01-20 14:25:33 -070044 #_name, \
45 suite_start_ ## _name, \
46 suite_end_ ## _name, \
Simon Glass46093b32025-01-20 14:26:05 -070047 _help, \
Simon Glass78fd76b2025-01-20 14:25:33 -070048 }
49
Simon Glass4c990702025-01-20 14:26:03 -070050SUITE_DECL(addrmap);
Simon Glass78fd76b2025-01-20 14:25:33 -070051SUITE_DECL(bdinfo);
Simon Glass4c990702025-01-20 14:26:03 -070052SUITE_DECL(bloblist);
53SUITE_DECL(bootm);
Simon Glass78fd76b2025-01-20 14:25:33 -070054SUITE_DECL(bootstd);
55SUITE_DECL(cmd);
56SUITE_DECL(common);
57SUITE_DECL(dm);
58SUITE_DECL(env);
59SUITE_DECL(exit);
60SUITE_DECL(fdt);
Simon Glass04e76d52025-02-07 11:30:39 -070061SUITE_DECL(fdt_overlay);
Simon Glass78fd76b2025-01-20 14:25:33 -070062SUITE_DECL(font);
Simon Glass4c990702025-01-20 14:26:03 -070063SUITE_DECL(hush);
Simon Glass78fd76b2025-01-20 14:25:33 -070064SUITE_DECL(lib);
Simon Glass4c990702025-01-20 14:26:03 -070065SUITE_DECL(loadm);
Simon Glass78fd76b2025-01-20 14:25:33 -070066SUITE_DECL(log);
67SUITE_DECL(mbr);
Simon Glass78fd76b2025-01-20 14:25:33 -070068SUITE_DECL(measurement);
Simon Glass4c990702025-01-20 14:26:03 -070069SUITE_DECL(mem);
70SUITE_DECL(optee);
Simon Glass78fd76b2025-01-20 14:25:33 -070071SUITE_DECL(pci_mps);
72SUITE_DECL(seama);
Simon Glass4c990702025-01-20 14:26:03 -070073SUITE_DECL(setexpr);
Simon Glass78fd76b2025-01-20 14:25:33 -070074SUITE_DECL(upl);
75
76static struct suite suites[] = {
Simon Glass46093b32025-01-20 14:26:05 -070077 SUITE(addrmap, "very basic test of addrmap command"),
78 SUITE(bdinfo, "bdinfo (board info) command"),
79 SUITE(bloblist, "bloblist implementation"),
80 SUITE(bootm, "bootm command"),
Simon Glassf8573fc2025-02-07 11:30:49 -070081 SUITE(bootstd, "standard boot implementation"),
Simon Glass46093b32025-01-20 14:26:05 -070082 SUITE(cmd, "various commands"),
83 SUITE(common, "tests for common/ directory"),
84 SUITE(dm, "driver model"),
85 SUITE(env, "environment"),
86 SUITE(exit, "shell exit and variables"),
87 SUITE(fdt, "fdt command"),
Simon Glass0f50f902025-02-07 11:30:47 -070088 SUITE(fdt_overlay, "device tree overlays"),
Simon Glass46093b32025-01-20 14:26:05 -070089 SUITE(font, "font command"),
90 SUITE(hush, "hush behaviour"),
91 SUITE(lib, "library functions"),
92 SUITE(loadm, "loadm command parameters and loading memory blob"),
93 SUITE(log, "logging functions"),
94 SUITE(mbr, "mbr command"),
95 SUITE(measurement, "TPM-based measured boot"),
96 SUITE(mem, "memory-related commands"),
Simon Glass3947f792025-02-07 11:30:52 -070097 SUITE(optee, "OP-TEE"),
Simon Glass46093b32025-01-20 14:26:05 -070098 SUITE(pci_mps, "PCI Express Maximum Payload Size"),
99 SUITE(seama, "seama command parameters loading and decoding"),
100 SUITE(setexpr, "setexpr command"),
101 SUITE(upl, "Universal payload support"),
Joe Hershberger11dd7cc2015-05-20 14:27:28 -0500102};
103
Simon Glassa3ce1292025-01-20 14:25:57 -0700104/**
105 * has_tests() - Check if a suite has tests, i.e. is supported in this build
106 *
107 * If the suite is run using a command, we have to assume that tests may be
108 * present, since we have no visibility
109 *
110 * @ste: Suite to check
111 * Return: true if supported, false if not
112 */
113static bool has_tests(struct suite *ste)
114{
115 int n_ents = ste->end - ste->start;
116
Simon Glass0a85dd02025-02-07 11:30:54 -0700117 return n_ents;
Simon Glassa3ce1292025-01-20 14:25:57 -0700118}
119
Simon Glass78fd76b2025-01-20 14:25:33 -0700120/** run_suite() - Run a suite of tests */
Simon Glass6685ece2025-01-20 14:25:58 -0700121static int run_suite(struct unit_test_state *uts, struct suite *ste,
Simon Glassda9925f2025-02-07 11:30:59 -0700122 const char *select_name, int runs_per_test, bool force_run,
123 const char *test_insert)
Simon Glass78fd76b2025-01-20 14:25:33 -0700124{
Simon Glass0a85dd02025-02-07 11:30:54 -0700125 int n_ents = ste->end - ste->start;
126 char prefix[30];
Simon Glass78fd76b2025-01-20 14:25:33 -0700127 int ret;
128
Simon Glass0a85dd02025-02-07 11:30:54 -0700129 /* use a standard prefix */
130 snprintf(prefix, sizeof(prefix), "%s_test_", ste->name);
Simon Glassb6f23882025-02-07 11:30:58 -0700131
Simon Glassb6f23882025-02-07 11:30:58 -0700132 ret = ut_run_list(uts, ste->name, prefix, ste->start, n_ents,
Simon Glassda9925f2025-02-07 11:30:59 -0700133 select_name, runs_per_test, force_run, test_insert);
Simon Glass78fd76b2025-01-20 14:25:33 -0700134
135 return ret;
136}
137
Simon Glassbd9b1512025-02-07 11:30:36 -0700138static void show_stats(struct unit_test_state *uts)
139{
140 if (uts->run_count < 2)
141 return;
142
143 ut_report(&uts->total, uts->run_count);
144 if (CONFIG_IS_ENABLED(UNIT_TEST_DURATION) &&
145 uts->total.test_count && uts->worst) {
146 ulong avg = uts->total.duration_ms / uts->total.test_count;
147
148 printf("Average test time: %ld ms, worst case '%s' took %d ms\n",
149 avg, uts->worst->name, uts->worst_ms);
150 }
151}
152
153static void update_stats(struct unit_test_state *uts, const struct suite *ste)
154{
155 if (CONFIG_IS_ENABLED(UNIT_TEST_DURATION) && uts->cur.test_count) {
156 ulong avg;
157
158 avg = uts->cur.duration_ms ?
159 uts->cur.duration_ms /
160 uts->cur.test_count : 0;
161 if (avg > uts->worst_ms) {
162 uts->worst_ms = avg;
163 uts->worst = ste;
164 }
165 }
166}
167
Simon Glassda9925f2025-02-07 11:30:59 -0700168static int do_ut_all(struct unit_test_state *uts, const char *select_name,
169 int runs_per_test, bool force_run, const char *test_insert)
Joe Hershberger11dd7cc2015-05-20 14:27:28 -0500170{
171 int i;
172 int retval;
173 int any_fail = 0;
174
Simon Glass78fd76b2025-01-20 14:25:33 -0700175 for (i = 0; i < ARRAY_SIZE(suites); i++) {
176 struct suite *ste = &suites[i];
Simon Glass78fd76b2025-01-20 14:25:33 -0700177
Simon Glassa3ce1292025-01-20 14:25:57 -0700178 if (has_tests(ste)) {
179 printf("----Running %s tests----\n", ste->name);
Simon Glassda9925f2025-02-07 11:30:59 -0700180 retval = run_suite(uts, ste, select_name, runs_per_test,
181 force_run, test_insert);
Simon Glassa3ce1292025-01-20 14:25:57 -0700182 if (!any_fail)
183 any_fail = retval;
Simon Glassbd9b1512025-02-07 11:30:36 -0700184 update_stats(uts, ste);
Simon Glassa3ce1292025-01-20 14:25:57 -0700185 }
Joe Hershberger11dd7cc2015-05-20 14:27:28 -0500186 }
187
188 return any_fail;
189}
190
Simon Glassda9925f2025-02-07 11:30:59 -0700191static int do_ut_info(bool show_suites)
Simon Glassfb998c22022-10-29 19:47:12 -0600192{
Simon Glassa3ce1292025-01-20 14:25:57 -0700193 int suite_count, i;
Simon Glasscfb38f82025-01-20 14:25:30 -0700194
Simon Glassa3ce1292025-01-20 14:25:57 -0700195 for (suite_count = 0, i = 0; i < ARRAY_SIZE(suites); i++) {
196 struct suite *ste = &suites[i];
197
198 if (has_tests(ste))
199 suite_count++;
200 }
201
202 printf("Test suites: %d\n", suite_count);
Simon Glassfb998c22022-10-29 19:47:12 -0600203 printf("Total tests: %d\n", (int)UNIT_TEST_ALL_COUNT());
204
Simon Glassda9925f2025-02-07 11:30:59 -0700205 if (show_suites) {
Simon Glass3669a972025-02-07 11:30:34 -0700206 int i, total;
Simon Glasscfb38f82025-01-20 14:25:30 -0700207
Simon Glass46093b32025-01-20 14:26:05 -0700208 puts("\nTests Suite Purpose");
209 puts("\n----- ------------ -------------------------\n");
Simon Glass3669a972025-02-07 11:30:34 -0700210 for (i = 0, total = 0; i < ARRAY_SIZE(suites); i++) {
Simon Glass78fd76b2025-01-20 14:25:33 -0700211 struct suite *ste = &suites[i];
212 long n_ent = ste->end - ste->start;
213
Simon Glass0a85dd02025-02-07 11:30:54 -0700214 if (n_ent) {
215 printf("%5ld %-13.13s %s\n", n_ent, ste->name,
216 ste->help);
217 total += n_ent;
218 }
Simon Glass78fd76b2025-01-20 14:25:33 -0700219 }
Simon Glass3669a972025-02-07 11:30:34 -0700220 puts("----- ------------ -------------------------\n");
221 printf("%5d %-13.13s\n", total, "Total");
222
223 if (UNIT_TEST_ALL_COUNT() != total)
224 puts("Error: Suite test-count does not match total\n");
Simon Glasscfb38f82025-01-20 14:25:30 -0700225 }
226
Simon Glassfb998c22022-10-29 19:47:12 -0600227 return 0;
228}
229
Simon Glass78fd76b2025-01-20 14:25:33 -0700230static struct suite *find_suite(const char *name)
231{
232 struct suite *ste;
233 int i;
234
235 for (i = 0, ste = suites; i < ARRAY_SIZE(suites); i++, ste++) {
236 if (!strcmp(ste->name, name))
237 return ste;
238 }
239
240 return NULL;
241}
242
Simon Glassed38aef2020-05-10 11:40:03 -0600243static int do_ut(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
Joe Hershberger11dd7cc2015-05-20 14:27:28 -0500244{
Simon Glassda9925f2025-02-07 11:30:59 -0700245 const char *test_insert = NULL, *select_name;
Simon Glass6685ece2025-01-20 14:25:58 -0700246 struct unit_test_state uts;
Simon Glassda9925f2025-02-07 11:30:59 -0700247 bool show_suites = false;
248 bool force_run = false;
249 int runs_per_text = 1;
Simon Glass78fd76b2025-01-20 14:25:33 -0700250 struct suite *ste;
Simon Glass70737152025-02-07 11:30:57 -0700251 char *name;
Simon Glass78fd76b2025-01-20 14:25:33 -0700252 int ret;
Joe Hershberger11dd7cc2015-05-20 14:27:28 -0500253
Joe Hershberger11dd7cc2015-05-20 14:27:28 -0500254 /* drop initial "ut" arg */
255 argc--;
256 argv++;
257
Simon Glassda9925f2025-02-07 11:30:59 -0700258 while (argc > 0 && *argv[0] == '-') {
259 const char *str = argv[0];
260
261 switch (str[1]) {
262 case 'r':
263 runs_per_text = dectoul(str + 2, NULL);
264 break;
265 case 'f':
266 force_run = true;
267 break;
268 case 'I':
269 test_insert = str + 2;
270 if (!strchr(test_insert, ':'))
271 return CMD_RET_USAGE;
272 break;
273 case 's':
274 show_suites = true;
275 break;
276 }
277 argv++;
278 argc--;
279 }
280
281 if (argc < 1)
282 return CMD_RET_USAGE;
283
Simon Glass6685ece2025-01-20 14:25:58 -0700284 ut_init_state(&uts);
Simon Glass78fd76b2025-01-20 14:25:33 -0700285 name = argv[0];
Simon Glassda9925f2025-02-07 11:30:59 -0700286 select_name = cmd_arg1(argc, argv);
Simon Glass78fd76b2025-01-20 14:25:33 -0700287 if (!strcmp(name, "all")) {
Simon Glassda9925f2025-02-07 11:30:59 -0700288 ret = do_ut_all(&uts, select_name, runs_per_text, force_run,
289 test_insert);
Simon Glass78fd76b2025-01-20 14:25:33 -0700290 } else if (!strcmp(name, "info")) {
Simon Glassda9925f2025-02-07 11:30:59 -0700291 ret = do_ut_info(show_suites);
Simon Glass78fd76b2025-01-20 14:25:33 -0700292 } else {
Simon Glass70737152025-02-07 11:30:57 -0700293 int any_fail = 0;
294 const char *p;
295
296 for (; p = strsep(&name, ","), p; name = NULL) {
297 ste = find_suite(p);
298 if (!ste) {
299 printf("Suite '%s' not found\n", p);
300 return CMD_RET_FAILURE;
301 } else if (!has_tests(ste)) {
302 /* perhaps a Kconfig option needs to be set? */
303 printf("Suite '%s' is not enabled\n", p);
304 return CMD_RET_FAILURE;
305 }
Joe Hershberger11dd7cc2015-05-20 14:27:28 -0500306
Simon Glassda9925f2025-02-07 11:30:59 -0700307 ret = run_suite(&uts, ste, select_name, runs_per_text,
308 force_run, test_insert);
Simon Glass70737152025-02-07 11:30:57 -0700309 if (!any_fail)
310 any_fail = ret;
311 update_stats(&uts, ste);
312 }
313 ret = any_fail;
Simon Glass78fd76b2025-01-20 14:25:33 -0700314 }
Simon Glassbd9b1512025-02-07 11:30:36 -0700315 show_stats(&uts);
Simon Glass78fd76b2025-01-20 14:25:33 -0700316 if (ret)
317 return ret;
Simon Glass6685ece2025-01-20 14:25:58 -0700318 ut_uninit_state(&uts);
Joe Hershberger11dd7cc2015-05-20 14:27:28 -0500319
Simon Glass78fd76b2025-01-20 14:25:33 -0700320 return 0;
Joe Hershberger11dd7cc2015-05-20 14:27:28 -0500321}
322
Tom Rini03f146c2023-10-07 15:13:08 -0400323U_BOOT_LONGHELP(ut,
Simon Glassc2402642025-02-07 11:31:00 -0700324 "[-rs] [-f] [-I<n>:<one_test>][<suites>] - run unit tests\n"
Simon Glass154bb8e2022-10-29 19:47:10 -0600325 " -r<runs> Number of times to run each test\n"
326 " -f Force 'manual' tests to run as well\n"
Simon Glassc2402642025-02-07 11:31:00 -0700327 " -I Test to run after <n> other tests have run\n"
328 " -s Show all suites with ut info\n"
329 " <suites> Comma-separated list of suites to run\n"
Simon Glass154bb8e2022-10-29 19:47:10 -0600330 "\n"
Simon Glassc2402642025-02-07 11:31:00 -0700331 "Options for <suite>:\n"
332 "all - execute all enabled tests\n"
333 "info - show info about tests [and suites]"
Tom Rini03f146c2023-10-07 15:13:08 -0400334 );
Joe Hershberger11dd7cc2015-05-20 14:27:28 -0500335
336U_BOOT_CMD(
337 ut, CONFIG_SYS_MAXARGS, 1, do_ut,
338 "unit tests", ut_help_text
339);