int ret;
ret = ut_run_list("spl", NULL, tests, count,
- state->select_unittests);
+ state->select_unittests, 1);
/* continue execution into U-Boot */
}
}
You can then single-step and look at variables as needed.
+Running tests multiple times
+----------------------------
+
+Some tests can have race conditions which are hard to detect on a single
+one. It is possible to run each individual test multiple times, before moving
+to the next test, with the '-r' flag.
+
+This is most useful when running a single test, since running all tests
+multiple times can take a while.
+
+For example::
+
+ => ut dm -r1000 dm_test_rtc_set_get
+ ...
+ Test: dm_test_rtc_set_get: rtc.c (flat tree)
+ Test: dm_test_rtc_set_get: rtc.c
+ test/dm/rtc.c:257, dm_test_rtc_reset(): old_base_time == base_time: Expected 0x62e7453c (1659323708), got 0x62e7453d (1659323709)
+ Test: dm_test_rtc_set_get: rtc.c (flat tree)
+ Test: dm_test_rtc_set_get: rtc.c
+ Test: dm_test_rtc_set_get: rtc.c (flat tree)
+ ...
+ Test dm_test_rtc_reset failed 3 times
+
+
Running sandbox_spl tests directly
----------------------------------
* @testdev: Test device
* @force_fail_alloc: Force all memory allocs to fail
* @skip_post_probe: Skip uclass post-probe processing
+ * @runs_per_test: Number of times to run each test (typically 1)
* @expect_str: Temporary string used to hold expected string value
* @actual_str: Temporary string used to hold actual string value
*/
struct udevice *testdev;
int force_fail_alloc;
int skip_post_probe;
+ int runs_per_test;
char expect_str[512];
char actual_str[512];
};
* @count: Number of tests to run
* @select_name: Name of a single test to run (from the list provided). If NULL
* then all tests are run
+ * @runs_per_test: Number of times to run each test (typically 1)
* Return: 0 if all tests passed, -1 if any failed
*/
int ut_run_list(const char *name, const char *prefix, struct unit_test *tests,
- int count, const char *select_name);
+ int count, const char *select_name, int runs_per_test);
#endif
struct unit_test *tests, int n_ents,
int argc, char *const argv[])
{
+ int runs_per_text = 1;
int ret;
+ if (argc > 1 && !strncmp("-r", argv[1], 2)) {
+ runs_per_text = dectoul(argv[1] + 2, NULL);
+ argv++;
+ argc++;
+ }
+
ret = ut_run_list(name, prefix, tests, n_ents,
- argc > 1 ? argv[1] : NULL);
+ argc > 1 ? argv[1] : NULL, runs_per_text);
return ret ? CMD_RET_FAILURE : 0;
}
#ifdef CONFIG_CMD_LOADM
"ut loadm [test-name]- test of parameters and load memory blob\n"
#endif
- ;
+ "All commands accept an optional [-r<runs>] flag before [test-name], to\n"
+ "run each test multiple times (<runs> is in decimal)";
#endif /* CONFIG_SYS_LONGHELP */
U_BOOT_CMD(
* "fdt_pre_reloc"), or NULL to run all
* Return: 0 if all tests passed, 1 if not
*/
-static int dm_test_run(const char *test_name)
+static int dm_test_run(const char *test_name, int runs_per_text)
{
struct unit_test *tests = UNIT_TEST_SUITE_START(dm_test);
const int n_ents = UNIT_TEST_SUITE_COUNT(dm_test);
int ret;
- ret = ut_run_list("driver model", "dm_test_", tests, n_ents, test_name);
+ ret = ut_run_list("driver model", "dm_test_", tests, n_ents, test_name,
+ runs_per_text);
return ret ? CMD_RET_FAILURE : 0;
}
int do_ut_dm(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
{
const char *test_name = NULL;
+ int runs_per_text = 1;
+ if (argc > 1 && !strncmp("-r", argv[1], 2)) {
+ runs_per_text = dectoul(argv[1] + 2, NULL);
+ argv++;
+ argc++;
+ }
if (argc > 1)
test_name = argv[1];
- return dm_test_run(test_name);
+ return dm_test_run(test_name, runs_per_text);
}
for (test = tests; test < tests + count; test++) {
const char *test_name = test->name;
- int ret;
+ int ret, i, old_fail_count;
if (!test_matches(prefix, test_name, select_name))
continue;
- ret = ut_run_test_live_flat(uts, test, select_name);
+ old_fail_count = uts->fail_count;
+ for (i = 0; i < uts->runs_per_test; i++)
+ ret = ut_run_test_live_flat(uts, test, select_name);
+ if (uts->fail_count != old_fail_count) {
+ printf("Test %s failed %d times\n", select_name,
+ uts->fail_count - old_fail_count);
+ }
found++;
if (ret == -EAGAIN)
continue;
}
int ut_run_list(const char *category, const char *prefix,
- struct unit_test *tests, int count, const char *select_name)
+ struct unit_test *tests, int count, const char *select_name,
+ int runs_per_test)
{
struct unit_test_state uts = { .fail_count = 0 };
bool has_dm_tests = false;
printf("Running %d %s tests\n", count, category);
uts.of_root = gd_of_root();
+ uts.runs_per_test = runs_per_test;
ret = ut_run_tests(&uts, prefix, tests, count, select_name);
if (ret == -ENOENT)