]>
Commit | Line | Data |
---|---|---|
1c721751 SG |
1 | // SPDX-License-Identifier: GPL-2.0+ |
2 | /* | |
3 | * Copyright 2021 Google LLC | |
4 | * Written by Simon Glass <sjg@chromium.org> | |
5 | */ | |
6 | ||
5ea894ac | 7 | #include <blk.h> |
1c721751 | 8 | #include <console.h> |
af042c21 | 9 | #include <cyclic.h> |
d8ed234b | 10 | #include <dm.h> |
7d02645f | 11 | #include <event.h> |
70dd8865 | 12 | #include <net.h> |
8d468a18 | 13 | #include <of_live.h> |
0e4b697f | 14 | #include <os.h> |
ee88ba71 | 15 | #include <dm/ofnode.h> |
d8ed234b | 16 | #include <dm/root.h> |
c79705ea | 17 | #include <dm/test.h> |
e77615d3 | 18 | #include <dm/uclass-internal.h> |
1c721751 | 19 | #include <test/test.h> |
d8ed234b | 20 | #include <test/ut.h> |
0e4b697f | 21 | #include <u-boot/crc.h> |
1c721751 | 22 | |
30a0d206 SG |
23 | DECLARE_GLOBAL_DATA_PTR; |
24 | ||
0e4b697f SG |
25 | /** |
26 | * enum fdtchk_t - what to do with the device tree (gd->fdt_blob) | |
27 | * | |
28 | * This affects what happens with the device tree before and after a test | |
29 | * | |
30 | * @FDTCHK_NONE: Do nothing | |
31 | * @FDTCHK_CHECKSUM: Take a checksum of the FDT before the test runs and | |
32 | * compare it afterwards to detect any changes | |
33 | * @FDTCHK_COPY: Make a copy of the FDT and restore it afterwards | |
34 | */ | |
35 | enum fdtchk_t { | |
36 | FDTCHK_NONE, | |
37 | FDTCHK_CHECKSUM, | |
38 | FDTCHK_COPY, | |
39 | }; | |
40 | ||
41 | /** | |
42 | * fdt_action() - get the required action for the FDT | |
43 | * | |
44 | * @return the action that should be taken for this build | |
45 | */ | |
46 | static enum fdtchk_t fdt_action(void) | |
47 | { | |
0e4b697f | 48 | /* For sandbox SPL builds, do nothing */ |
d5774594 | 49 | if (IS_ENABLED(CONFIG_SANDBOX) && IS_ENABLED(CONFIG_SPL_BUILD)) |
0e4b697f SG |
50 | return FDTCHK_NONE; |
51 | ||
d5774594 SG |
52 | /* Do a copy for sandbox (but only the U-Boot build, not SPL) */ |
53 | if (IS_ENABLED(CONFIG_SANDBOX)) | |
54 | return FDTCHK_COPY; | |
55 | ||
0e4b697f SG |
56 | /* For all other boards, do a checksum */ |
57 | return FDTCHK_CHECKSUM; | |
58 | } | |
59 | ||
fe806861 SG |
60 | /* This is valid when a test is running, NULL otherwise */ |
61 | static struct unit_test_state *cur_test_state; | |
62 | ||
63 | struct unit_test_state *test_get_state(void) | |
64 | { | |
65 | return cur_test_state; | |
66 | } | |
67 | ||
68 | void test_set_state(struct unit_test_state *uts) | |
69 | { | |
70 | cur_test_state = uts; | |
71 | } | |
72 | ||
c79705ea SG |
73 | /** |
74 | * dm_test_pre_run() - Get ready to run a driver model test | |
75 | * | |
76 | * This clears out the driver model data structures. For sandbox it resets the | |
77 | * state structure | |
78 | * | |
79 | * @uts: Test state | |
80 | */ | |
81 | static int dm_test_pre_run(struct unit_test_state *uts) | |
82 | { | |
83 | bool of_live = uts->of_live; | |
84 | ||
eb6e903a SG |
85 | if (of_live && (gd->flags & GD_FLG_FDT_CHANGED)) { |
86 | printf("Cannot run live tree test as device tree changed\n"); | |
87 | return -EFAULT; | |
88 | } | |
c79705ea SG |
89 | uts->root = NULL; |
90 | uts->testdev = NULL; | |
91 | uts->force_fail_alloc = false; | |
92 | uts->skip_post_probe = false; | |
0e4b697f SG |
93 | if (fdt_action() == FDTCHK_CHECKSUM) |
94 | uts->fdt_chksum = crc8(0, gd->fdt_blob, | |
95 | fdt_totalsize(gd->fdt_blob)); | |
c79705ea | 96 | gd->dm_root = NULL; |
62d63838 | 97 | malloc_disable_testing(); |
719d2864 | 98 | if (CONFIG_IS_ENABLED(UT_DM) && !CONFIG_IS_ENABLED(OF_PLATDATA)) |
c79705ea | 99 | memset(dm_testdrv_op_count, '\0', sizeof(dm_testdrv_op_count)); |
d4a1592a | 100 | arch_reset_for_test(); |
c79705ea SG |
101 | |
102 | /* Determine whether to make the live tree available */ | |
103 | gd_set_of_root(of_live ? uts->of_root : NULL); | |
ee88ba71 | 104 | oftree_reset(); |
c79705ea SG |
105 | ut_assertok(dm_init(of_live)); |
106 | uts->root = dm_root(); | |
107 | ||
108 | return 0; | |
109 | } | |
110 | ||
e77615d3 SG |
111 | static int dm_test_post_run(struct unit_test_state *uts) |
112 | { | |
113 | int id; | |
114 | ||
0e4b697f SG |
115 | if (gd->fdt_blob) { |
116 | switch (fdt_action()) { | |
117 | case FDTCHK_COPY: | |
118 | memcpy((void *)gd->fdt_blob, uts->fdt_copy, uts->fdt_size); | |
119 | break; | |
120 | case FDTCHK_CHECKSUM: { | |
121 | uint chksum; | |
122 | ||
123 | chksum = crc8(0, gd->fdt_blob, fdt_totalsize(gd->fdt_blob)); | |
eb6e903a SG |
124 | if (chksum != uts->fdt_chksum) { |
125 | /* | |
126 | * We cannot run any more tests that need the | |
127 | * live tree, since its strings point into the | |
128 | * flat tree, which has changed. This likely | |
129 | * means that at least some of the pointers from | |
130 | * the live tree point to different things | |
131 | */ | |
0e4b697f | 132 | printf("Device tree changed: cannot run live tree tests\n"); |
eb6e903a SG |
133 | gd->flags |= GD_FLG_FDT_CHANGED; |
134 | } | |
0e4b697f SG |
135 | break; |
136 | } | |
137 | case FDTCHK_NONE: | |
138 | break; | |
139 | } | |
140 | } | |
141 | ||
e8c023c3 SG |
142 | /* |
143 | * With of-platdata-inst the uclasses are created at build time. If we | |
144 | * destroy them we cannot get them back since uclass_add() is not | |
145 | * supported. So skip this. | |
146 | */ | |
147 | if (!CONFIG_IS_ENABLED(OF_PLATDATA_INST)) { | |
148 | for (id = 0; id < UCLASS_COUNT; id++) { | |
149 | struct uclass *uc; | |
e77615d3 | 150 | |
e8c023c3 SG |
151 | /* |
152 | * If the uclass doesn't exist we don't want to create | |
153 | * it. So check that here before we call | |
154 | * uclass_find_device(). | |
155 | */ | |
156 | uc = uclass_find(id); | |
157 | if (!uc) | |
158 | continue; | |
159 | ut_assertok(uclass_destroy(uc)); | |
160 | } | |
e77615d3 SG |
161 | } |
162 | ||
163 | return 0; | |
164 | } | |
165 | ||
4b8b27e3 SG |
166 | /* Ensure all the test devices are probed */ |
167 | static int do_autoprobe(struct unit_test_state *uts) | |
168 | { | |
c0648b7b | 169 | return uclass_probe_all(UCLASS_TEST); |
4b8b27e3 SG |
170 | } |
171 | ||
d2281bb0 SG |
172 | /* |
173 | * ut_test_run_on_flattree() - Check if we should run a test with flat DT | |
174 | * | |
175 | * This skips long/slow tests where there is not much value in running a flat | |
176 | * DT test in addition to a live DT test. | |
177 | * | |
185f812c | 178 | * Return: true to run the given test on the flat device tree |
d2281bb0 SG |
179 | */ |
180 | static bool ut_test_run_on_flattree(struct unit_test *test) | |
181 | { | |
182 | const char *fname = strrchr(test->file, '/') + 1; | |
183 | ||
184 | if (!(test->flags & UT_TESTF_DM)) | |
185 | return false; | |
186 | ||
187 | return !strstr(fname, "video") || strstr(test->name, "video_base"); | |
188 | } | |
189 | ||
f97f85e6 SG |
190 | /** |
191 | * test_matches() - Check if a test should be run | |
192 | * | |
193 | * This checks if the a test should be run. In the normal case of running all | |
194 | * tests, @select_name is NULL. | |
195 | * | |
196 | * @prefix: String prefix for the tests. Any tests that have this prefix will be | |
197 | * printed without the prefix, so that it is easier to see the unique part | |
8482356f SG |
198 | * of the test name. If NULL, any suite name (xxx_test) is considered to be |
199 | * a prefix. | |
f97f85e6 SG |
200 | * @test_name: Name of current test |
201 | * @select_name: Name of test to run (or NULL for all) | |
185f812c | 202 | * Return: true to run this test, false to skip it |
f97f85e6 SG |
203 | */ |
204 | static bool test_matches(const char *prefix, const char *test_name, | |
205 | const char *select_name) | |
206 | { | |
ff232a72 AS |
207 | size_t len; |
208 | ||
f97f85e6 SG |
209 | if (!select_name) |
210 | return true; | |
211 | ||
ff232a72 AS |
212 | /* Allow glob expansion in the test name */ |
213 | len = select_name[strlen(select_name) - 1] == '*' ? strlen(select_name) : 0; | |
214 | if (len-- == 1) | |
215 | return true; | |
216 | ||
217 | if (!strncmp(test_name, select_name, len)) | |
f97f85e6 SG |
218 | return true; |
219 | ||
494a5e12 AS |
220 | if (prefix) { |
221 | /* All tests have this prefix */ | |
222 | if (!strncmp(test_name, prefix, strlen(prefix))) | |
223 | test_name += strlen(prefix); | |
224 | } else { | |
8482356f SG |
225 | const char *p = strstr(test_name, "_test_"); |
226 | ||
227 | /* convert xxx_test_yyy to yyy, i.e. remove the suite name */ | |
228 | if (p) | |
494a5e12 | 229 | test_name = p + strlen("_test_"); |
8482356f | 230 | } |
f97f85e6 | 231 | |
ff232a72 | 232 | if (!strncmp(test_name, select_name, len)) |
f97f85e6 SG |
233 | return true; |
234 | ||
235 | return false; | |
236 | } | |
237 | ||
664277f1 | 238 | /** |
1fc9c122 SG |
239 | * ut_list_has_dm_tests() - Check if a list of tests has driver model ones |
240 | * | |
241 | * @tests: List of tests to run | |
242 | * @count: Number of tests to ru | |
185f812c | 243 | * Return: true if any of the tests have the UT_TESTF_DM flag |
1fc9c122 SG |
244 | */ |
245 | static bool ut_list_has_dm_tests(struct unit_test *tests, int count) | |
246 | { | |
247 | struct unit_test *test; | |
248 | ||
249 | for (test = tests; test < tests + count; test++) { | |
250 | if (test->flags & UT_TESTF_DM) | |
251 | return true; | |
252 | } | |
253 | ||
254 | return false; | |
255 | } | |
256 | ||
664277f1 SG |
257 | /** |
258 | * dm_test_restore() Put things back to normal so sandbox works as expected | |
259 | * | |
260 | * @of_root: Value to set for of_root | |
185f812c | 261 | * Return: 0 if OK, -ve on error |
664277f1 SG |
262 | */ |
263 | static int dm_test_restore(struct device_node *of_root) | |
264 | { | |
265 | int ret; | |
266 | ||
267 | gd_set_of_root(of_root); | |
268 | gd->dm_root = NULL; | |
269 | ret = dm_init(CONFIG_IS_ENABLED(OF_LIVE)); | |
270 | if (ret) | |
271 | return ret; | |
272 | dm_scan_plat(false); | |
273 | if (!CONFIG_IS_ENABLED(OF_PLATDATA)) | |
230038f8 | 274 | dm_extended_scan(false); |
664277f1 SG |
275 | |
276 | return 0; | |
277 | } | |
278 | ||
ca44ca05 SG |
279 | /** |
280 | * test_pre_run() - Handle any preparation needed to run a test | |
281 | * | |
282 | * @uts: Test state | |
283 | * @test: Test to prepare for | |
185f812c | 284 | * Return: 0 if OK, -EAGAIN to skip this test since some required feature is not |
ca44ca05 SG |
285 | * available, other -ve on error (meaning that testing cannot likely |
286 | * continue) | |
287 | */ | |
288 | static int test_pre_run(struct unit_test_state *uts, struct unit_test *test) | |
d002a276 | 289 | { |
7d02645f SG |
290 | ut_assertok(event_init()); |
291 | ||
72b524cf | 292 | if (test->flags & UT_TESTF_DM) |
c79705ea | 293 | ut_assertok(dm_test_pre_run(uts)); |
72b524cf | 294 | |
47ec3ede SG |
295 | ut_set_skip_delays(uts, false); |
296 | ||
19fb3dba | 297 | uts->start = mallinfo(); |
d002a276 | 298 | |
ecb274cf | 299 | if (test->flags & UT_TESTF_SCAN_PDATA) |
5a986f3f SG |
300 | ut_assertok(dm_scan_plat(false)); |
301 | ||
4b8b27e3 SG |
302 | if (test->flags & UT_TESTF_PROBE_TEST) |
303 | ut_assertok(do_autoprobe(uts)); | |
304 | ||
eaf73855 | 305 | if (CONFIG_IS_ENABLED(OF_REAL) && |
70dd8865 SG |
306 | (test->flags & UT_TESTF_SCAN_FDT)) { |
307 | /* | |
308 | * only set this if we know the ethernet uclass will be created | |
309 | */ | |
310 | eth_set_enable_bootdevs(test->flags & UT_TESTF_ETH_BOOTDEV); | |
081bdc52 | 311 | test_sf_set_enable_bootdevs(test->flags & UT_TESTF_SF_BOOTDEV); |
d8ed234b | 312 | ut_assertok(dm_extended_scan(false)); |
70dd8865 | 313 | } |
d8ed234b | 314 | |
ecb274cf SG |
315 | /* |
316 | * Do this after FDT scan since dm_scan_other() in bootstd-uclass.c | |
317 | * checks for the existence of bootstd | |
318 | */ | |
319 | if (test->flags & UT_TESTF_SCAN_PDATA) | |
320 | ut_assertok(dm_scan_other(false)); | |
321 | ||
8d468a18 SG |
322 | if (IS_ENABLED(CONFIG_SANDBOX) && (test->flags & UT_TESTF_OTHER_FDT)) { |
323 | /* make sure the other FDT is available */ | |
324 | ut_assertok(test_load_other_fdt(uts)); | |
325 | ||
326 | /* | |
327 | * create a new live tree with it for every test, in case a | |
328 | * test modifies the tree | |
329 | */ | |
330 | if (of_live_active()) { | |
331 | ut_assertok(unflatten_device_tree(uts->other_fdt, | |
332 | &uts->of_other)); | |
333 | } | |
334 | } | |
335 | ||
d002a276 SG |
336 | if (test->flags & UT_TESTF_CONSOLE_REC) { |
337 | int ret = console_record_reset_enable(); | |
338 | ||
339 | if (ret) { | |
340 | printf("Skipping: Console recording disabled\n"); | |
341 | return -EAGAIN; | |
342 | } | |
343 | } | |
74524712 | 344 | ut_silence_console(uts); |
d002a276 SG |
345 | |
346 | return 0; | |
347 | } | |
348 | ||
ca44ca05 SG |
349 | /** |
350 | * test_post_run() - Handle cleaning up after a test | |
351 | * | |
352 | * @uts: Test state | |
353 | * @test: Test to clean up after | |
185f812c | 354 | * Return: 0 if OK, -ve on error (meaning that testing cannot likely continue) |
ca44ca05 SG |
355 | */ |
356 | static int test_post_run(struct unit_test_state *uts, struct unit_test *test) | |
d002a276 | 357 | { |
74524712 | 358 | ut_unsilence_console(uts); |
e77615d3 SG |
359 | if (test->flags & UT_TESTF_DM) |
360 | ut_assertok(dm_test_post_run(uts)); | |
50128aeb | 361 | ut_assertok(cyclic_unregister_all()); |
7d02645f | 362 | ut_assertok(event_uninit()); |
30a0d206 | 363 | |
8d468a18 SG |
364 | free(uts->of_other); |
365 | uts->of_other = NULL; | |
366 | ||
5ea894ac SG |
367 | blkcache_free(); |
368 | ||
d002a276 SG |
369 | return 0; |
370 | } | |
371 | ||
1facaade SG |
372 | /** |
373 | * skip_test() - Handle skipping a test | |
374 | * | |
375 | * @uts: Test state to update | |
376 | * @return -EAGAIN (always) | |
377 | */ | |
378 | static int skip_test(struct unit_test_state *uts) | |
379 | { | |
380 | uts->skip_count++; | |
381 | ||
382 | return -EAGAIN; | |
383 | } | |
384 | ||
d2281bb0 SG |
385 | /** |
386 | * ut_run_test() - Run a single test | |
387 | * | |
388 | * This runs the test, handling any preparation and clean-up needed. It prints | |
389 | * the name of each test before running it. | |
390 | * | |
391 | * @uts: Test state to update. The caller should ensure that this is zeroed for | |
392 | * the first call to this function. On exit, @uts->fail_count is | |
393 | * incremented by the number of failures (0, one hopes) | |
394 | * @test_name: Test to run | |
395 | * @name: Name of test, possibly skipping a prefix that should not be displayed | |
185f812c | 396 | * Return: 0 if all tests passed, -EAGAIN if the test should be skipped, -1 if |
d2281bb0 SG |
397 | * any failed |
398 | */ | |
399 | static int ut_run_test(struct unit_test_state *uts, struct unit_test *test, | |
400 | const char *test_name) | |
99a88fe1 | 401 | { |
ca44ca05 SG |
402 | const char *fname = strrchr(test->file, '/') + 1; |
403 | const char *note = ""; | |
99a88fe1 SG |
404 | int ret; |
405 | ||
ca44ca05 SG |
406 | if ((test->flags & UT_TESTF_DM) && !uts->of_live) |
407 | note = " (flat tree)"; | |
408 | printf("Test: %s: %s%s\n", test_name, fname, note); | |
99a88fe1 | 409 | |
fe806861 SG |
410 | /* Allow access to test state from drivers */ |
411 | test_set_state(uts); | |
412 | ||
99a88fe1 SG |
413 | ret = test_pre_run(uts, test); |
414 | if (ret == -EAGAIN) | |
1facaade | 415 | return skip_test(uts); |
99a88fe1 SG |
416 | if (ret) |
417 | return ret; | |
418 | ||
1facaade SG |
419 | ret = test->func(uts); |
420 | if (ret == -EAGAIN) | |
421 | skip_test(uts); | |
99a88fe1 SG |
422 | |
423 | ret = test_post_run(uts, test); | |
424 | if (ret) | |
425 | return ret; | |
426 | ||
fe806861 SG |
427 | test_set_state( NULL); |
428 | ||
99a88fe1 SG |
429 | return 0; |
430 | } | |
431 | ||
f97f85e6 SG |
432 | /** |
433 | * ut_run_test_live_flat() - Run a test with both live and flat tree | |
434 | * | |
435 | * This calls ut_run_test() with livetree enabled, which is the standard setup | |
436 | * for runnig tests. Then, for driver model test, it calls it again with | |
437 | * livetree disabled. This allows checking of flattree being used when OF_LIVE | |
438 | * is enabled, as is the case in U-Boot proper before relocation, as well as in | |
439 | * SPL. | |
440 | * | |
441 | * @uts: Test state to update. The caller should ensure that this is zeroed for | |
442 | * the first call to this function. On exit, @uts->fail_count is | |
443 | * incremented by the number of failures (0, one hopes) | |
444 | * @test: Test to run | |
185f812c | 445 | * Return: 0 if all tests passed, -EAGAIN if the test should be skipped, -1 if |
f97f85e6 SG |
446 | * any failed |
447 | */ | |
448 | static int ut_run_test_live_flat(struct unit_test_state *uts, | |
f7a68d22 | 449 | struct unit_test *test) |
d2281bb0 SG |
450 | { |
451 | int runs; | |
452 | ||
8d468a18 | 453 | if ((test->flags & UT_TESTF_OTHER_FDT) && !IS_ENABLED(CONFIG_SANDBOX)) |
1facaade | 454 | return skip_test(uts); |
8d468a18 | 455 | |
d2281bb0 SG |
456 | /* Run with the live tree if possible */ |
457 | runs = 0; | |
458 | if (CONFIG_IS_ENABLED(OF_LIVE)) { | |
7c14dc7f | 459 | if (!(test->flags & UT_TESTF_FLAT_TREE)) { |
d2281bb0 SG |
460 | uts->of_live = true; |
461 | ut_assertok(ut_run_test(uts, test, test->name)); | |
462 | runs++; | |
463 | } | |
464 | } | |
465 | ||
466 | /* | |
8d468a18 SG |
467 | * Run with the flat tree if: |
468 | * - it is not marked for live tree only | |
469 | * - it doesn't require the 'other' FDT when OFNODE_MULTI_TREE_MAX is | |
470 | * not enabled (since flat tree can only support a single FDT in that | |
471 | * case | |
472 | * - we couldn't run it with live tree, | |
473 | * - it is a core test (dm tests except video) | |
474 | * - the FDT is still valid and has not been updated by an earlier test | |
475 | * (for sandbox we handle this by copying the tree, but not for other | |
476 | * boards) | |
d2281bb0 | 477 | */ |
3f876cb7 SA |
478 | if ((!CONFIG_IS_ENABLED(OF_LIVE) || |
479 | (test->flags & UT_TESTF_SCAN_FDT)) && | |
6ec5178c | 480 | !(test->flags & UT_TESTF_LIVE_TREE) && |
8d468a18 SG |
481 | (CONFIG_IS_ENABLED(OFNODE_MULTI_TREE) || |
482 | !(test->flags & UT_TESTF_OTHER_FDT)) && | |
eb6e903a SG |
483 | (!runs || ut_test_run_on_flattree(test)) && |
484 | !(gd->flags & GD_FLG_FDT_CHANGED)) { | |
d2281bb0 SG |
485 | uts->of_live = false; |
486 | ut_assertok(ut_run_test(uts, test, test->name)); | |
487 | runs++; | |
488 | } | |
489 | ||
490 | return 0; | |
491 | } | |
492 | ||
f97f85e6 SG |
493 | /** |
494 | * ut_run_tests() - Run a set of tests | |
495 | * | |
496 | * This runs the tests, handling any preparation and clean-up needed. It prints | |
497 | * the name of each test before running it. | |
498 | * | |
499 | * @uts: Test state to update. The caller should ensure that this is zeroed for | |
500 | * the first call to this function. On exit, @uts->fail_count is | |
501 | * incremented by the number of failures (0, one hopes) | |
502 | * @prefix: String prefix for the tests. Any tests that have this prefix will be | |
503 | * printed without the prefix, so that it is easier to see the unique part | |
504 | * of the test name. If NULL, no prefix processing is done | |
505 | * @tests: List of tests to run | |
506 | * @count: Number of tests to run | |
507 | * @select_name: Name of a single test to run (from the list provided). If NULL | |
508 | * then all tests are run | |
185f812c | 509 | * Return: 0 if all tests passed, -ENOENT if test @select_name was not found, |
f97f85e6 SG |
510 | * -EBADF if any failed |
511 | */ | |
512 | static int ut_run_tests(struct unit_test_state *uts, const char *prefix, | |
513 | struct unit_test *tests, int count, | |
d1b46595 | 514 | const char *select_name, const char *test_insert) |
1c721751 | 515 | { |
d1b46595 | 516 | struct unit_test *test, *one; |
1c721751 | 517 | int found = 0; |
d1b46595 SG |
518 | int pos = 0; |
519 | int upto; | |
1c721751 | 520 | |
d1b46595 SG |
521 | one = NULL; |
522 | if (test_insert) { | |
523 | char *p; | |
524 | ||
525 | pos = dectoul(test_insert, NULL); | |
526 | p = strchr(test_insert, ':'); | |
527 | if (p) | |
528 | p++; | |
529 | ||
530 | for (test = tests; test < tests + count; test++) { | |
531 | if (!strcmp(p, test->name)) | |
532 | one = test; | |
533 | } | |
534 | } | |
535 | ||
536 | for (upto = 0, test = tests; test < tests + count; test++, upto++) { | |
1c721751 | 537 | const char *test_name = test->name; |
ea94d053 | 538 | int ret, i, old_fail_count; |
1c721751 | 539 | |
f97f85e6 | 540 | if (!test_matches(prefix, test_name, select_name)) |
1c721751 | 541 | continue; |
cbd71fad SG |
542 | |
543 | if (test->flags & UT_TESTF_MANUAL) { | |
544 | int len; | |
545 | ||
546 | /* | |
547 | * manual tests must have a name ending "_norun" as this | |
548 | * is how pytest knows to skip them. See | |
549 | * generate_ut_subtest() for this check. | |
550 | */ | |
551 | len = strlen(test_name); | |
552 | if (len < 6 || strcmp(test_name + len - 6, "_norun")) { | |
553 | printf("Test %s is manual so must have a name ending in _norun\n", | |
554 | test_name); | |
555 | uts->fail_count++; | |
556 | return -EBADF; | |
557 | } | |
558 | if (!uts->force_run) { | |
559 | if (select_name) { | |
560 | printf("Test %s skipped as it is manual (use -f to run it)\n", | |
561 | test_name); | |
562 | } | |
563 | continue; | |
564 | } | |
565 | } | |
ea94d053 | 566 | old_fail_count = uts->fail_count; |
d1b46595 SG |
567 | |
568 | if (one && upto == pos) { | |
569 | ret = ut_run_test_live_flat(uts, one); | |
570 | if (uts->fail_count != old_fail_count) { | |
571 | printf("Test %s failed %d times (position %d)\n", | |
572 | one->name, | |
573 | uts->fail_count - old_fail_count, pos); | |
574 | } | |
575 | return -EBADF; | |
576 | } | |
577 | ||
ea94d053 | 578 | for (i = 0; i < uts->runs_per_test; i++) |
f7a68d22 | 579 | ret = ut_run_test_live_flat(uts, test); |
ea94d053 SG |
580 | if (uts->fail_count != old_fail_count) { |
581 | printf("Test %s failed %d times\n", select_name, | |
582 | uts->fail_count - old_fail_count); | |
583 | } | |
1c721751 | 584 | found++; |
d002a276 SG |
585 | if (ret == -EAGAIN) |
586 | continue; | |
587 | if (ret) | |
588 | return ret; | |
1c721751 SG |
589 | } |
590 | if (select_name && !found) | |
591 | return -ENOENT; | |
592 | ||
593 | return uts->fail_count ? -EBADF : 0; | |
594 | } | |
595 | ||
596 | int ut_run_list(const char *category, const char *prefix, | |
ea94d053 | 597 | struct unit_test *tests, int count, const char *select_name, |
d1b46595 | 598 | int runs_per_test, bool force_run, const char *test_insert) |
1c721751 SG |
599 | { |
600 | struct unit_test_state uts = { .fail_count = 0 }; | |
664277f1 | 601 | bool has_dm_tests = false; |
1c721751 SG |
602 | int ret; |
603 | ||
1fc9c122 SG |
604 | if (!CONFIG_IS_ENABLED(OF_PLATDATA) && |
605 | ut_list_has_dm_tests(tests, count)) { | |
664277f1 | 606 | has_dm_tests = true; |
1fc9c122 SG |
607 | /* |
608 | * If we have no device tree, or it only has a root node, then | |
609 | * these * tests clearly aren't going to work... | |
610 | */ | |
611 | if (!gd->fdt_blob || fdt_next_node(gd->fdt_blob, 0, NULL) < 0) { | |
612 | puts("Please run with test device tree:\n" | |
613 | " ./u-boot -d arch/sandbox/dts/test.dtb\n"); | |
614 | return CMD_RET_FAILURE; | |
615 | } | |
616 | } | |
617 | ||
1c721751 SG |
618 | if (!select_name) |
619 | printf("Running %d %s tests\n", count, category); | |
620 | ||
f97f85e6 | 621 | uts.of_root = gd_of_root(); |
ea94d053 | 622 | uts.runs_per_test = runs_per_test; |
0e4b697f SG |
623 | if (fdt_action() == FDTCHK_COPY && gd->fdt_blob) { |
624 | uts.fdt_size = fdt_totalsize(gd->fdt_blob); | |
625 | uts.fdt_copy = os_malloc(uts.fdt_size); | |
626 | if (!uts.fdt_copy) { | |
627 | printf("Out of memory for device tree copy\n"); | |
628 | return -ENOMEM; | |
629 | } | |
630 | memcpy(uts.fdt_copy, gd->fdt_blob, uts.fdt_size); | |
631 | } | |
cbd71fad | 632 | uts.force_run = force_run; |
d1b46595 SG |
633 | ret = ut_run_tests(&uts, prefix, tests, count, select_name, |
634 | test_insert); | |
1c721751 | 635 | |
0e4b697f SG |
636 | /* Best efforts only...ignore errors */ |
637 | if (has_dm_tests) | |
638 | dm_test_restore(uts.of_root); | |
8d468a18 | 639 | if (IS_ENABLED(CONFIG_SANDBOX)) { |
0e4b697f | 640 | os_free(uts.fdt_copy); |
8d468a18 SG |
641 | os_free(uts.other_fdt); |
642 | } | |
0e4b697f | 643 | |
1facaade SG |
644 | if (uts.skip_count) |
645 | printf("Skipped: %d, ", uts.skip_count); | |
1c721751 SG |
646 | if (ret == -ENOENT) |
647 | printf("Test '%s' not found\n", select_name); | |
648 | else | |
649 | printf("Failures: %d\n", uts.fail_count); | |
650 | ||
651 | return ret; | |
652 | } |