| /* | |
| * Copyright (c) 2013 Google, Inc | |
| * | |
| * SPDX-License-Identifier: GPL-2.0+ | |
| */ | |
| #include <common.h> | |
| #include <command.h> | |
| #include <console.h> | |
| #include <dm.h> | |
| #include <errno.h> | |
| #include <malloc.h> | |
| #include <asm/state.h> | |
| #include <dm/test.h> | |
| #include <dm/root.h> | |
| #include <dm/uclass-internal.h> | |
| #include <test/ut.h> | |
| DECLARE_GLOBAL_DATA_PTR; | |
| struct unit_test_state global_dm_test_state; | |
| static struct dm_test_state _global_priv_dm_test_state; | |
| /* Get ready for testing */ | |
| static int dm_test_init(struct unit_test_state *uts) | |
| { | |
| struct dm_test_state *dms = uts->priv; | |
| memset(dms, '\0', sizeof(*dms)); | |
| gd->dm_root = NULL; | |
| memset(dm_testdrv_op_count, '\0', sizeof(dm_testdrv_op_count)); | |
| ut_assertok(dm_init()); | |
| dms->root = dm_root(); | |
| return 0; | |
| } | |
| /* Ensure all the test devices are probed */ | |
| static int do_autoprobe(struct unit_test_state *uts) | |
| { | |
| struct udevice *dev; | |
| int ret; | |
| /* Scanning the uclass is enough to probe all the devices */ | |
| for (ret = uclass_first_device(UCLASS_TEST, &dev); | |
| dev; | |
| ret = uclass_next_device(&dev)) | |
| ; | |
| return ret; | |
| } | |
| static int dm_test_destroy(struct unit_test_state *uts) | |
| { | |
| int id; | |
| for (id = 0; id < UCLASS_COUNT; id++) { | |
| struct uclass *uc; | |
| /* | |
| * If the uclass doesn't exist we don't want to create it. So | |
| * check that here before we call uclass_find_device()/ | |
| */ | |
| uc = uclass_find(id); | |
| if (!uc) | |
| continue; | |
| ut_assertok(uclass_destroy(uc)); | |
| } | |
| return 0; | |
| } | |
| static int dm_test_main(const char *test_name) | |
| { | |
| struct unit_test *tests = ll_entry_start(struct unit_test, dm_test); | |
| const int n_ents = ll_entry_count(struct unit_test, dm_test); | |
| struct unit_test_state *uts = &global_dm_test_state; | |
| struct sandbox_state *state = state_get_current(); | |
| uts->priv = &_global_priv_dm_test_state; | |
| struct unit_test *test; | |
| int run_count; | |
| uts->fail_count = 0; | |
| /* | |
| * If we have no device tree, or it only has a root node, then these | |
| * tests clearly aren't going to work... | |
| */ | |
| if (!gd->fdt_blob || fdt_next_node(gd->fdt_blob, 0, NULL) < 0) { | |
| puts("Please run with test device tree:\n" | |
| " ./u-boot -d arch/sandbox/dts/test.dtb\n"); | |
| ut_assert(gd->fdt_blob); | |
| } | |
| if (!test_name) | |
| printf("Running %d driver model tests\n", n_ents); | |
| run_count = 0; | |
| for (test = tests; test < tests + n_ents; test++) { | |
| const char *name = test->name; | |
| /* All tests have this prefix */ | |
| if (!strncmp(name, "dm_test_", 8)) | |
| name += 8; | |
| if (test_name && strcmp(test_name, name)) | |
| continue; | |
| printf("Test: %s\n", test->name); | |
| run_count++; | |
| ut_assertok(dm_test_init(uts)); | |
| uts->start = mallinfo(); | |
| if (test->flags & DM_TESTF_SCAN_PDATA) | |
| ut_assertok(dm_scan_platdata(false)); | |
| if (test->flags & DM_TESTF_PROBE_TEST) | |
| ut_assertok(do_autoprobe(uts)); | |
| if (test->flags & DM_TESTF_SCAN_FDT) | |
| ut_assertok(dm_scan_fdt(gd->fdt_blob, false)); | |
| /* | |
| * Silence the console and rely on console reocrding to get | |
| * our output. | |
| */ | |
| console_record_reset(); | |
| if (!state->show_test_output) | |
| gd->flags |= GD_FLG_SILENT; | |
| test->func(uts); | |
| gd->flags &= ~GD_FLG_SILENT; | |
| state_set_skip_delays(false); | |
| ut_assertok(dm_test_destroy(uts)); | |
| } | |
| if (test_name && !run_count) | |
| printf("Test '%s' not found\n", test_name); | |
| else | |
| printf("Failures: %d\n", uts->fail_count); | |
| gd->dm_root = NULL; | |
| ut_assertok(dm_init()); | |
| dm_scan_platdata(false); | |
| dm_scan_fdt(gd->fdt_blob, false); | |
| return uts->fail_count ? CMD_RET_FAILURE : 0; | |
| } | |
| int do_ut_dm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) | |
| { | |
| const char *test_name = NULL; | |
| if (argc > 1) | |
| test_name = argv[1]; | |
| return dm_test_main(test_name); | |
| } |