blob: b3821a0fe6846830503b1f6b362661a2c03b94b6 [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)
Simon Glass46093b32025-01-20 14:26:05 -070023 * @help: Help-string to show for this suite
Simon Glass78fd76b2025-01-20 14:25:33 -070024 */
25struct suite {
26 const char *name;
27 struct unit_test *start;
28 struct unit_test *end;
Simon Glass46093b32025-01-20 14:26:05 -070029 const char *help;
Simon Glass78fd76b2025-01-20 14:25:33 -070030};
31
Simon Glass6685ece2025-01-20 14:25:58 -070032static int do_ut_all(struct unit_test_state *uts, struct cmd_tbl *cmdtp,
33 int flag, int argc, char *const argv[]);
Joe Hershberger11dd7cc2015-05-20 14:27:28 -050034
Simon Glassfb998c22022-10-29 19:47:12 -060035static int do_ut_info(struct cmd_tbl *cmdtp, int flag, int argc,
36 char *const argv[]);
37
Simon Glass6685ece2025-01-20 14:25:58 -070038int cmd_ut_category(struct unit_test_state *uts, const char *name,
39 const char *prefix, struct unit_test *tests, int n_ents,
Simon Glassed38aef2020-05-10 11:40:03 -060040 int argc, char *const argv[])
Simon Glass81cbe1c2017-11-25 11:57:29 -070041{
Simon Glass85ba7c32022-10-29 19:47:13 -060042 const char *test_insert = NULL;
Simon Glass91a187b2022-08-01 07:58:45 -060043 int runs_per_text = 1;
Simon Glass1f1614b2022-10-20 18:22:50 -060044 bool force_run = false;
Simon Glass5722fb22021-03-07 17:34:47 -070045 int ret;
Simon Glass81cbe1c2017-11-25 11:57:29 -070046
Simon Glass1f1614b2022-10-20 18:22:50 -060047 while (argc > 1 && *argv[1] == '-') {
48 const char *str = argv[1];
49
50 switch (str[1]) {
51 case 'r':
52 runs_per_text = dectoul(str + 2, NULL);
53 break;
54 case 'f':
55 force_run = true;
56 break;
Simon Glass85ba7c32022-10-29 19:47:13 -060057 case 'I':
58 test_insert = str + 2;
59 break;
Simon Glass1f1614b2022-10-20 18:22:50 -060060 }
Simon Glass91a187b2022-08-01 07:58:45 -060061 argv++;
Simon Glass85ba7c32022-10-29 19:47:13 -060062 argc--;
Simon Glass91a187b2022-08-01 07:58:45 -060063 }
64
Simon Glass6685ece2025-01-20 14:25:58 -070065 ret = ut_run_list(uts, name, prefix, tests, n_ents,
Simon Glass793a98e2023-11-18 14:05:20 -070066 cmd_arg1(argc, argv), runs_per_text, force_run,
Simon Glass85ba7c32022-10-29 19:47:13 -060067 test_insert);
Simon Glass81cbe1c2017-11-25 11:57:29 -070068
Simon Glass5722fb22021-03-07 17:34:47 -070069 return ret ? CMD_RET_FAILURE : 0;
Simon Glass81cbe1c2017-11-25 11:57:29 -070070}
71
Simon Glass78fd76b2025-01-20 14:25:33 -070072/* declare linker-list symbols for the start and end of a suite */
73#define SUITE_DECL(_name) \
74 ll_start_decl(suite_start_ ## _name, struct unit_test, ut_ ## _name); \
75 ll_end_decl(suite_end_ ## _name, struct unit_test, ut_ ## _name)
76
Simon Glass78fd76b2025-01-20 14:25:33 -070077/* declare a test suite which can be run directly without a subcommand */
Simon Glass46093b32025-01-20 14:26:05 -070078#define SUITE(_name, _help) { \
Simon Glass78fd76b2025-01-20 14:25:33 -070079 #_name, \
80 suite_start_ ## _name, \
81 suite_end_ ## _name, \
Simon Glass46093b32025-01-20 14:26:05 -070082 _help, \
Simon Glass78fd76b2025-01-20 14:25:33 -070083 }
84
Simon Glass4c990702025-01-20 14:26:03 -070085SUITE_DECL(addrmap);
Simon Glass78fd76b2025-01-20 14:25:33 -070086SUITE_DECL(bdinfo);
Simon Glass4c990702025-01-20 14:26:03 -070087SUITE_DECL(bloblist);
88SUITE_DECL(bootm);
Simon Glass78fd76b2025-01-20 14:25:33 -070089SUITE_DECL(bootstd);
90SUITE_DECL(cmd);
91SUITE_DECL(common);
92SUITE_DECL(dm);
93SUITE_DECL(env);
94SUITE_DECL(exit);
95SUITE_DECL(fdt);
Simon Glass04e76d52025-02-07 11:30:39 -070096SUITE_DECL(fdt_overlay);
Simon Glass78fd76b2025-01-20 14:25:33 -070097SUITE_DECL(font);
Simon Glass4c990702025-01-20 14:26:03 -070098SUITE_DECL(hush);
Simon Glass78fd76b2025-01-20 14:25:33 -070099SUITE_DECL(lib);
Simon Glass4c990702025-01-20 14:26:03 -0700100SUITE_DECL(loadm);
Simon Glass78fd76b2025-01-20 14:25:33 -0700101SUITE_DECL(log);
102SUITE_DECL(mbr);
Simon Glass78fd76b2025-01-20 14:25:33 -0700103SUITE_DECL(measurement);
Simon Glass4c990702025-01-20 14:26:03 -0700104SUITE_DECL(mem);
105SUITE_DECL(optee);
Simon Glass78fd76b2025-01-20 14:25:33 -0700106SUITE_DECL(pci_mps);
107SUITE_DECL(seama);
Simon Glass4c990702025-01-20 14:26:03 -0700108SUITE_DECL(setexpr);
Simon Glass78fd76b2025-01-20 14:25:33 -0700109SUITE_DECL(upl);
110
111static struct suite suites[] = {
Simon Glass46093b32025-01-20 14:26:05 -0700112 SUITE(addrmap, "very basic test of addrmap command"),
113 SUITE(bdinfo, "bdinfo (board info) command"),
114 SUITE(bloblist, "bloblist implementation"),
115 SUITE(bootm, "bootm command"),
Simon Glassf8573fc2025-02-07 11:30:49 -0700116 SUITE(bootstd, "standard boot implementation"),
Simon Glass46093b32025-01-20 14:26:05 -0700117 SUITE(cmd, "various commands"),
118 SUITE(common, "tests for common/ directory"),
119 SUITE(dm, "driver model"),
120 SUITE(env, "environment"),
121 SUITE(exit, "shell exit and variables"),
122 SUITE(fdt, "fdt command"),
Simon Glass0f50f902025-02-07 11:30:47 -0700123 SUITE(fdt_overlay, "device tree overlays"),
Simon Glass46093b32025-01-20 14:26:05 -0700124 SUITE(font, "font command"),
125 SUITE(hush, "hush behaviour"),
126 SUITE(lib, "library functions"),
127 SUITE(loadm, "loadm command parameters and loading memory blob"),
128 SUITE(log, "logging functions"),
129 SUITE(mbr, "mbr command"),
130 SUITE(measurement, "TPM-based measured boot"),
131 SUITE(mem, "memory-related commands"),
Simon Glass3947f792025-02-07 11:30:52 -0700132 SUITE(optee, "OP-TEE"),
Simon Glass46093b32025-01-20 14:26:05 -0700133 SUITE(pci_mps, "PCI Express Maximum Payload Size"),
134 SUITE(seama, "seama command parameters loading and decoding"),
135 SUITE(setexpr, "setexpr command"),
136 SUITE(upl, "Universal payload support"),
Joe Hershberger11dd7cc2015-05-20 14:27:28 -0500137};
138
Simon Glassa3ce1292025-01-20 14:25:57 -0700139/**
140 * has_tests() - Check if a suite has tests, i.e. is supported in this build
141 *
142 * If the suite is run using a command, we have to assume that tests may be
143 * present, since we have no visibility
144 *
145 * @ste: Suite to check
146 * Return: true if supported, false if not
147 */
148static bool has_tests(struct suite *ste)
149{
150 int n_ents = ste->end - ste->start;
151
Simon Glass0a85dd02025-02-07 11:30:54 -0700152 return n_ents;
Simon Glassa3ce1292025-01-20 14:25:57 -0700153}
154
Simon Glass78fd76b2025-01-20 14:25:33 -0700155/** run_suite() - Run a suite of tests */
Simon Glass6685ece2025-01-20 14:25:58 -0700156static int run_suite(struct unit_test_state *uts, struct suite *ste,
157 struct cmd_tbl *cmdtp, int flag, int argc,
158 char *const argv[])
Simon Glass78fd76b2025-01-20 14:25:33 -0700159{
Simon Glass0a85dd02025-02-07 11:30:54 -0700160 int n_ents = ste->end - ste->start;
161 char prefix[30];
Simon Glass78fd76b2025-01-20 14:25:33 -0700162 int ret;
163
Simon Glass78fd76b2025-01-20 14:25:33 -0700164
Simon Glass0a85dd02025-02-07 11:30:54 -0700165 /* use a standard prefix */
166 snprintf(prefix, sizeof(prefix), "%s_test_", ste->name);
167 ret = cmd_ut_category(uts, ste->name, prefix, ste->start, n_ents,
168 argc, argv);
Simon Glass78fd76b2025-01-20 14:25:33 -0700169
170 return ret;
171}
172
Simon Glassbd9b1512025-02-07 11:30:36 -0700173static void show_stats(struct unit_test_state *uts)
174{
175 if (uts->run_count < 2)
176 return;
177
178 ut_report(&uts->total, uts->run_count);
179 if (CONFIG_IS_ENABLED(UNIT_TEST_DURATION) &&
180 uts->total.test_count && uts->worst) {
181 ulong avg = uts->total.duration_ms / uts->total.test_count;
182
183 printf("Average test time: %ld ms, worst case '%s' took %d ms\n",
184 avg, uts->worst->name, uts->worst_ms);
185 }
186}
187
188static void update_stats(struct unit_test_state *uts, const struct suite *ste)
189{
190 if (CONFIG_IS_ENABLED(UNIT_TEST_DURATION) && uts->cur.test_count) {
191 ulong avg;
192
193 avg = uts->cur.duration_ms ?
194 uts->cur.duration_ms /
195 uts->cur.test_count : 0;
196 if (avg > uts->worst_ms) {
197 uts->worst_ms = avg;
198 uts->worst = ste;
199 }
200 }
201}
202
Simon Glass6685ece2025-01-20 14:25:58 -0700203static int do_ut_all(struct unit_test_state *uts, struct cmd_tbl *cmdtp,
204 int flag, int argc, char *const argv[])
Joe Hershberger11dd7cc2015-05-20 14:27:28 -0500205{
206 int i;
207 int retval;
208 int any_fail = 0;
209
Simon Glass78fd76b2025-01-20 14:25:33 -0700210 for (i = 0; i < ARRAY_SIZE(suites); i++) {
211 struct suite *ste = &suites[i];
212 char *const argv[] = {(char *)ste->name, NULL};
213
Simon Glassa3ce1292025-01-20 14:25:57 -0700214 if (has_tests(ste)) {
215 printf("----Running %s tests----\n", ste->name);
Simon Glass6685ece2025-01-20 14:25:58 -0700216 retval = run_suite(uts, ste, cmdtp, flag, 1, argv);
Simon Glassa3ce1292025-01-20 14:25:57 -0700217 if (!any_fail)
218 any_fail = retval;
Simon Glassbd9b1512025-02-07 11:30:36 -0700219 update_stats(uts, ste);
Simon Glassa3ce1292025-01-20 14:25:57 -0700220 }
Joe Hershberger11dd7cc2015-05-20 14:27:28 -0500221 }
Simon Glassfb82a042025-01-20 14:26:02 -0700222 ut_report(&uts->total, uts->run_count);
Joe Hershberger11dd7cc2015-05-20 14:27:28 -0500223
224 return any_fail;
225}
226
Simon Glassfb998c22022-10-29 19:47:12 -0600227static int do_ut_info(struct cmd_tbl *cmdtp, int flag, int argc,
228 char *const argv[])
229{
Simon Glassa3ce1292025-01-20 14:25:57 -0700230 int suite_count, i;
Simon Glasscfb38f82025-01-20 14:25:30 -0700231 const char *flags;
232
Simon Glassa3ce1292025-01-20 14:25:57 -0700233 for (suite_count = 0, i = 0; i < ARRAY_SIZE(suites); i++) {
234 struct suite *ste = &suites[i];
235
236 if (has_tests(ste))
237 suite_count++;
238 }
239
240 printf("Test suites: %d\n", suite_count);
Simon Glassfb998c22022-10-29 19:47:12 -0600241 printf("Total tests: %d\n", (int)UNIT_TEST_ALL_COUNT());
242
Simon Glasscfb38f82025-01-20 14:25:30 -0700243 flags = cmd_arg1(argc, argv);
244 if (flags && !strcmp("-s", flags)) {
Simon Glass3669a972025-02-07 11:30:34 -0700245 int i, total;
Simon Glasscfb38f82025-01-20 14:25:30 -0700246
Simon Glass46093b32025-01-20 14:26:05 -0700247 puts("\nTests Suite Purpose");
248 puts("\n----- ------------ -------------------------\n");
Simon Glass3669a972025-02-07 11:30:34 -0700249 for (i = 0, total = 0; i < ARRAY_SIZE(suites); i++) {
Simon Glass78fd76b2025-01-20 14:25:33 -0700250 struct suite *ste = &suites[i];
251 long n_ent = ste->end - ste->start;
252
Simon Glass0a85dd02025-02-07 11:30:54 -0700253 if (n_ent) {
254 printf("%5ld %-13.13s %s\n", n_ent, ste->name,
255 ste->help);
256 total += n_ent;
257 }
Simon Glass78fd76b2025-01-20 14:25:33 -0700258 }
Simon Glass3669a972025-02-07 11:30:34 -0700259 puts("----- ------------ -------------------------\n");
260 printf("%5d %-13.13s\n", total, "Total");
261
262 if (UNIT_TEST_ALL_COUNT() != total)
263 puts("Error: Suite test-count does not match total\n");
Simon Glasscfb38f82025-01-20 14:25:30 -0700264 }
265
Simon Glassfb998c22022-10-29 19:47:12 -0600266 return 0;
267}
268
Simon Glass78fd76b2025-01-20 14:25:33 -0700269static struct suite *find_suite(const char *name)
270{
271 struct suite *ste;
272 int i;
273
274 for (i = 0, ste = suites; i < ARRAY_SIZE(suites); i++, ste++) {
275 if (!strcmp(ste->name, name))
276 return ste;
277 }
278
279 return NULL;
280}
281
Simon Glassed38aef2020-05-10 11:40:03 -0600282static int do_ut(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
Joe Hershberger11dd7cc2015-05-20 14:27:28 -0500283{
Simon Glass6685ece2025-01-20 14:25:58 -0700284 struct unit_test_state uts;
Simon Glass78fd76b2025-01-20 14:25:33 -0700285 struct suite *ste;
286 const char *name;
287 int ret;
Joe Hershberger11dd7cc2015-05-20 14:27:28 -0500288
289 if (argc < 2)
290 return CMD_RET_USAGE;
291
292 /* drop initial "ut" arg */
293 argc--;
294 argv++;
295
Simon Glass6685ece2025-01-20 14:25:58 -0700296 ut_init_state(&uts);
Simon Glass78fd76b2025-01-20 14:25:33 -0700297 name = argv[0];
298 if (!strcmp(name, "all")) {
Simon Glass6685ece2025-01-20 14:25:58 -0700299 ret = do_ut_all(&uts, cmdtp, flag, argc, argv);
Simon Glass78fd76b2025-01-20 14:25:33 -0700300 } else if (!strcmp(name, "info")) {
301 ret = do_ut_info(cmdtp, flag, argc, argv);
302 } else {
303 ste = find_suite(argv[0]);
304 if (!ste) {
305 printf("Suite '%s' not found\n", argv[0]);
306 return CMD_RET_FAILURE;
Simon Glassa3ce1292025-01-20 14:25:57 -0700307 } else if (!has_tests(ste)) {
308 /* perhaps a Kconfig option needs to be set? */
309 printf("Suite '%s' is not enabled\n", argv[0]);
310 return CMD_RET_FAILURE;
Simon Glass78fd76b2025-01-20 14:25:33 -0700311 }
Joe Hershberger11dd7cc2015-05-20 14:27:28 -0500312
Simon Glass6685ece2025-01-20 14:25:58 -0700313 ret = run_suite(&uts, ste, cmdtp, flag, argc, argv);
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 Glass154bb8e2022-10-29 19:47:10 -0600324 "[-r] [-f] [<suite>] - run unit tests\n"
325 " -r<runs> Number of times to run each test\n"
326 " -f Force 'manual' tests to run as well\n"
327 " <suite> Test suite to run, or all\n"
328 "\n"
Simon Glassfb998c22022-10-29 19:47:12 -0600329 "\nOptions for <suite>:"
Simon Glass154bb8e2022-10-29 19:47:10 -0600330 "\nall - execute all enabled tests"
Simon Glasscfb38f82025-01-20 14:25:30 -0700331 "\ninfo [-s] - show info about tests [and suites]"
Tom Rini03f146c2023-10-07 15:13:08 -0400332 );
Joe Hershberger11dd7cc2015-05-20 14:27:28 -0500333
334U_BOOT_CMD(
335 ut, CONFIG_SYS_MAXARGS, 1, do_ut,
336 "unit tests", ut_help_text
337);