[Concept,14/21] test: Enhance the ut command to pass test arguments

Message ID 20251214175449.3799539-15-sjg@u-boot.org
State New
Headers
Series test: Add support for passing arguments to C unit tests |

Commit Message

Simon Glass Dec. 14, 2025, 5:54 p.m. UTC
  From: Simon Glass <simon.glass@canonical.com>

Update the ut command to permit passing arguments to tests.

Usage: ut -f fs test_name key1=value1 key2=value2

Co-developed-by: Claude Opus 4.5 <noreply@anthropic.com>
Signed-off-by: Simon Glass <simon.glass@canonical.com>
---

 doc/usage/cmd/ut.rst | 11 ++++++++++-
 test/cmd_ut.c        | 29 ++++++++++++++++++++---------
 2 files changed, 30 insertions(+), 10 deletions(-)
  

Patch

diff --git a/doc/usage/cmd/ut.rst b/doc/usage/cmd/ut.rst
index 1acf3126680..d8c3cbf496c 100644
--- a/doc/usage/cmd/ut.rst
+++ b/doc/usage/cmd/ut.rst
@@ -11,7 +11,7 @@  Synopsis
 
 ::
 
-    ut [-r<runs>] [-f] [-I<n>:<one_test>] [-r<n>] [<suite> | 'all' [<test>]]
+    ut [-r<runs>] [-f] [-I<n>:<one_test>] [<suite> | all [<test>]] [<args>...]
     ut [-s] info
 
 Description
@@ -37,6 +37,11 @@  test
     causes another test to fail. If the one test fails, testing stops
     immediately.
 
+args
+    Optional arguments to pass to the test, in `name=value` format. These are
+    used by tests declared with `UNIT_TEST_ARGS()` which define expected
+    argument names and types.
+
 Typically the command is run on :ref:`arch/sandbox/sandbox:sandbox` since it
 includes a near-complete set of emulators, no code-size limits, many CONFIG
 options enabled and runs easily in CI without needing QEMU. It is also possible
@@ -201,3 +206,7 @@  Run a selection of three suites::
     Tests run: 10, 12 ms, average: 1 ms, failures: 0
     Suites run: 3, total tests run: 37, 26 ms, average: 0 ms, failures: 0
     Average test time: 0 ms, worst case 'mem' took 1 ms
+
+Run a test with arguments (used by tests declared with UNIT_TEST_ARGS)::
+
+    => ut -f fs fs_test_ls_norun fs_type=ext4 fs_image=/tmp/img small=1MB.file
diff --git a/test/cmd_ut.c b/test/cmd_ut.c
index bad123a75fd..adc96fcbcdc 100644
--- a/test/cmd_ut.c
+++ b/test/cmd_ut.c
@@ -30,7 +30,7 @@  struct suite {
 
 static int do_ut_all(struct unit_test_state *uts, const char *select_name,
 		     int runs_per_test, bool force_run,
-		     const char *test_insert);
+		     const char *test_insert, int argc, char *const argv[]);
 
 static int do_ut_info(bool show_suites);
 
@@ -122,7 +122,7 @@  static bool has_tests(struct suite *ste)
 /** run_suite() - Run a suite of tests */
 static int run_suite(struct unit_test_state *uts, struct suite *ste,
 		     const char *select_name, int runs_per_test, bool force_run,
-		     const char *test_insert)
+		     const char *test_insert, int argc, char *const argv[])
 {
 	int n_ents = ste->end - ste->start;
 	char prefix[30];
@@ -133,7 +133,7 @@  static int run_suite(struct unit_test_state *uts, struct suite *ste,
 
 	ret = ut_run_list(uts, ste->name, prefix, ste->start, n_ents,
 			  select_name, runs_per_test, force_run, test_insert,
-			  0, NULL);
+			  argc, argv);
 
 	return ret;
 }
@@ -169,7 +169,8 @@  static void update_stats(struct unit_test_state *uts, const struct suite *ste)
 }
 
 static int do_ut_all(struct unit_test_state *uts, const char *select_name,
-		     int runs_per_test, bool force_run, const char *test_insert)
+		     int runs_per_test, bool force_run, const char *test_insert,
+		     int argc, char *const argv[])
 {
 	int i;
 	int retval;
@@ -181,7 +182,7 @@  static int do_ut_all(struct unit_test_state *uts, const char *select_name,
 		if (has_tests(ste)) {
 			printf("----Running %s tests----\n", ste->name);
 			retval = run_suite(uts, ste, select_name, runs_per_test,
-					   force_run, test_insert);
+					   force_run, test_insert, argc, argv);
 			if (!any_fail)
 				any_fail = retval;
 			update_stats(uts, ste);
@@ -246,6 +247,8 @@  static struct suite *find_suite(const char *name)
 static int do_ut(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
 {
 	const char *test_insert = NULL, *select_name;
+	int test_argc;
+	char *const *test_argv;
 	struct unit_test_state uts;
 	bool show_suites = false;
 	bool force_run = false;
@@ -287,9 +290,14 @@  static int do_ut(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
 	ut_init_state(&uts);
 	name = argv[0];
 	select_name = cmd_arg1(argc, argv);
+
+	/* Test arguments are after suite name and test name */
+	test_argc = argc > 2 ? argc - 2 : 0;
+	test_argv = argc > 2 ? argv + 2 : NULL;
+
 	if (!strcmp(name, "all")) {
 		ret = do_ut_all(&uts, select_name, runs_per_text, force_run,
-				test_insert);
+				test_insert, test_argc, test_argv);
 	} else if (!strcmp(name, "info")) {
 		ret = do_ut_info(show_suites);
 	} else {
@@ -308,7 +316,8 @@  static int do_ut(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
 			}
 
 			ret = run_suite(&uts, ste, select_name, runs_per_text,
-					force_run, test_insert);
+					force_run, test_insert, test_argc,
+					test_argv);
 			if (!any_fail)
 				any_fail = ret;
 			update_stats(&uts, ste);
@@ -324,12 +333,14 @@  static int do_ut(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
 }
 
 U_BOOT_LONGHELP(ut,
-	"[-rs] [-f] [-I<n>:<one_test>][<suites>] - run unit tests\n"
+	"[-rs] [-f] [-I<n>:<one_test>] <suite> [<test> [<args>...]] - run unit tests\n"
 	"   -r<runs>   Number of times to run each test\n"
 	"   -f         Force 'manual' tests to run as well\n"
 	"   -I         Test to run after <n> other tests have run\n"
 	"   -s         Show all suites with ut info\n"
-	"   <suites>   Comma-separated list of suites to run\n"
+	"   <suite>    Test suite to run (or comma-separated list)\n"
+	"   <test>     Specific test to run (optional)\n"
+	"   <args>     Test arguments as key=value pairs (optional)\n"
 	"\n"
 	"Options for <suite>:\n"
 	"all       - execute all enabled tests\n"