diff --git a/configs/sandbox64_defconfig b/configs/sandbox64_defconfig
index c3ca796d51..7e156e9813 100644
--- a/configs/sandbox64_defconfig
+++ b/configs/sandbox64_defconfig
@@ -25,6 +25,7 @@ CONFIG_CMD_LICENSE=y
 CONFIG_CMD_BOOTZ=y
 CONFIG_CMD_BOOTEFI_HELLO=y
 # CONFIG_CMD_ELF is not set
+CONFIG_CMD_CALL=y
 CONFIG_CMD_ASKENV=y
 CONFIG_CMD_GREPENV=y
 CONFIG_CMD_ERASEENV=y
diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig
index 6e9f029cc9..ac06a8dc67 100644
--- a/configs/sandbox_defconfig
+++ b/configs/sandbox_defconfig
@@ -30,6 +30,7 @@ CONFIG_CMD_BOOTZ=y
 CONFIG_CMD_BOOTEFI_HELLO=y
 CONFIG_CMD_ABOOTIMG=y
 # CONFIG_CMD_ELF is not set
+CONFIG_CMD_CALL=y
 CONFIG_CMD_ASKENV=y
 CONFIG_CMD_GREPENV=y
 CONFIG_CMD_ERASEENV=y
diff --git a/include/test/suites.h b/include/test/suites.h
index ab7b3bd9ca..082b87ce52 100644
--- a/include/test/suites.h
+++ b/include/test/suites.h
@@ -32,6 +32,7 @@ int do_ut_compression(struct cmd_tbl *cmdtp, int flag, int argc,
 		      char *const argv[]);
 int do_ut_dm(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
 int do_ut_env(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
+int do_ut_hush(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
 int do_ut_lib(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
 int do_ut_log(struct cmd_tbl *cmdtp, int flag, int argc, char * const argv[]);
 int do_ut_mem(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]);
diff --git a/test/cmd/Makefile b/test/cmd/Makefile
index 859dcda239..adc5ba0307 100644
--- a/test/cmd/Makefile
+++ b/test/cmd/Makefile
@@ -4,3 +4,4 @@
 
 obj-y += mem.o
 obj-$(CONFIG_CMD_MEM_SEARCH) += mem_search.o
+obj-$(CONFIG_HUSH_PARSER) += hush.o
diff --git a/test/cmd/hush.c b/test/cmd/hush.c
new file mode 100644
index 0000000000..c4ad7b5e94
--- /dev/null
+++ b/test/cmd/hush.c
@@ -0,0 +1,90 @@
+// SPDX-License-Identifier: GPL-2.0+
+
+#include <common.h>
+#include <console.h>
+#include <test/suites.h>
+#include <test/ut.h>
+
+#define HUSH_TEST(_name, _flags) UNIT_TEST(_name, _flags, hush_test)
+
+int do_ut_hush(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[])
+{
+	struct unit_test *tests = ll_entry_start(struct unit_test, hush_test);
+	const int n_ents = ll_entry_count(struct unit_test, hush_test);
+
+	return cmd_ut_category("cmd_hush", "cmd_hush_", tests, n_ents, argc,
+			       argv);
+}
+
+static int hush_test_basic(struct unit_test_state *uts)
+{
+	run_command("true", 0);
+	ut_assert_console_end();
+
+	run_command("echo $?", 0);
+	ut_assert_nextline("0");
+	ut_assert_console_end();
+
+	run_command("false", 0);
+	ut_assert_console_end();
+
+	run_command("echo $?", 0);
+	ut_assert_nextline("1");
+	ut_assert_console_end();
+
+	return 0;
+}
+HUSH_TEST(hush_test_basic, UT_TESTF_CONSOLE_REC);
+
+static int hush_test_cond(struct unit_test_state *uts)
+{
+	run_command("if true ; then echo yay ; else echo nay ; fi", 0);
+	ut_assert_nextline("yay");
+	ut_assert_console_end();
+
+	run_command("if false ; then echo yay ; else echo nay ; fi", 0);
+	ut_assert_nextline("nay");
+	ut_assert_console_end();
+
+	/* Short-circuiting */
+	run_command("if true || echo x ; then echo yay; else echo nay ; fi", 0);
+	ut_assert_nextline("yay");
+	ut_assert_console_end();
+
+	run_command("if false || echo x ; then echo yay; else echo nay ; fi", 0);
+	ut_assert_nextline("x");
+	ut_assert_nextline("yay");
+	ut_assert_console_end();
+
+	run_command("if true && echo x ; then echo yay; else echo nay ; fi", 0);
+	ut_assert_nextline("x");
+	ut_assert_nextline("yay");
+	ut_assert_console_end();
+
+	run_command("if false && echo x ; then echo yay; else echo nay ; fi", 0);
+	ut_assert_nextline("nay");
+	ut_assert_console_end();
+
+	return 0;
+}
+HUSH_TEST(hush_test_cond, UT_TESTF_CONSOLE_REC);
+
+#ifdef CONFIG_CMD_CALL
+static int hush_test_call(struct unit_test_state *uts)
+{
+	run_command("env set f 'echo f: argc=$#, [$1] [${2}] [${3:-z}]; call g $2; echo f: [$1] [${2}]'", 0);
+	ut_assert_console_end();
+
+	run_command("env set g 'echo g: argc=$#, [$1] [$2] [${2:-y}]'", 0);
+	ut_assert_console_end();
+
+	run_command("call f 11 22", 0);
+	ut_assert_nextline("f: argc=2, [11] [22] [z]");
+	ut_assert_nextline("g: argc=1, [22] [] [y]");
+	ut_assert_nextline("f: [11] [22]");
+	ut_assert_console_end();
+
+	return 0;
+}
+HUSH_TEST(hush_test_call, UT_TESTF_CONSOLE_REC);
+#endif
diff --git a/test/cmd_ut.c b/test/cmd_ut.c
index 8f0bc688a2..cd903186b9 100644
--- a/test/cmd_ut.c
+++ b/test/cmd_ut.c
@@ -81,6 +81,9 @@ static struct cmd_tbl cmd_ut_sub[] = {
 #if CONFIG_IS_ENABLED(UT_UNICODE) && !defined(API_BUILD)
 	U_BOOT_CMD_MKENT(unicode, CONFIG_SYS_MAXARGS, 1, do_ut_unicode, "", ""),
 #endif
+#ifdef CONFIG_HUSH_PARSER
+	U_BOOT_CMD_MKENT(hush, CONFIG_SYS_MAXARGS, 1, do_ut_hush, "", ""),
+#endif
 #ifdef CONFIG_SANDBOX
 	U_BOOT_CMD_MKENT(compression, CONFIG_SYS_MAXARGS, 1, do_ut_compression,
 			 "", ""),
@@ -140,6 +143,9 @@ static char ut_help_text[] =
 #ifdef CONFIG_UT_ENV
 	"ut env [test-name]\n"
 #endif
+#ifdef CONFIG_HUSH_PARSER
+	"ut hush - test (hush) shell functionality\n"
+#endif
 #ifdef CONFIG_UT_LIB
 	"ut lib [test-name] - test library functions\n"
 #endif
