From: Stephen Warren <swar...@nvidia.com> Most of command_ut.c simply runs shell commands which could just as easily be invoked from the command-line. Convert all of that testing to Python. I'd classify all of these tests as "system" tests since they use the standard interface to the U-Boot "system".
The remaining tests rely on features only available to C code, such as compound shell commands using \n as a separator, and validating the return value of functions that invoke shell commands directly. I'd classify these as unit tests, since they rely on mechanisms only available internally. Signed-off-by: Stephen Warren <swar...@nvidia.com> --- I wonder how useful do_ut_cmd() is now. It does test some things that can't be tested from the command-line, but... --- test/command_ut.c | 133 ---------------------------------------- test/py/test_env.py | 26 +++++++- test/py/test_hush_if_test.py | 137 ++++++++++++++++++++++++++++++++++++++++++ test/py/test_shell_basics.py | 31 ++++++++++ test/py/uboot_console_base.py | 4 +- 5 files changed, 194 insertions(+), 137 deletions(-) create mode 100644 test/py/test_hush_if_test.py create mode 100644 test/py/test_shell_basics.py diff --git a/test/command_ut.c b/test/command_ut.c index 926573a39543..35bd35ae2e30 100644 --- a/test/command_ut.c +++ b/test/command_ut.c @@ -20,21 +20,6 @@ static int do_ut_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) printf("%s: Testing commands\n", __func__); run_command("env default -f -a", 0); - /* run a single command */ - run_command("setenv single 1", 0); - assert(!strcmp("1", getenv("single"))); - - /* make sure that compound statements work */ -#ifdef CONFIG_SYS_HUSH_PARSER - run_command("if test -n ${single} ; then setenv check 1; fi", 0); - assert(!strcmp("1", getenv("check"))); - run_command("setenv check", 0); -#endif - - /* commands separated by ; */ - run_command_list("setenv list 1; setenv list ${list}1", -1, 0); - assert(!strcmp("11", getenv("list"))); - /* commands separated by \n */ run_command_list("setenv list 1\n setenv list ${list}1", -1, 0); assert(!strcmp("11", getenv("list"))); @@ -43,11 +28,6 @@ static int do_ut_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) run_command_list("setenv list 1${list}\n", -1, 0); assert(!strcmp("111", getenv("list"))); - /* three commands in a row */ - run_command_list("setenv list 1\n setenv list ${list}2; " - "setenv list ${list}3", -1, 0); - assert(!strcmp("123", getenv("list"))); - /* a command string with \0 in it. Stuff after \0 should be ignored */ run_command("setenv list", 0); run_command_list(test_cmd, sizeof(test_cmd), 0); @@ -66,13 +46,6 @@ static int do_ut_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) assert(run_command_list("false", -1, 0) == 1); assert(run_command_list("echo", -1, 0) == 0); - run_command("setenv foo 'setenv monty 1; setenv python 2'", 0); - run_command("run foo", 0); - assert(getenv("monty") != NULL); - assert(!strcmp("1", getenv("monty"))); - assert(getenv("python") != NULL); - assert(!strcmp("2", getenv("python"))); - #ifdef CONFIG_SYS_HUSH_PARSER run_command("setenv foo 'setenv black 1\nsetenv adder 2'", 0); run_command("run foo", 0); @@ -80,112 +53,6 @@ static int do_ut_cmd(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) assert(!strcmp("1", getenv("black"))); assert(getenv("adder") != NULL); assert(!strcmp("2", getenv("adder"))); - - /* Test the 'test' command */ - -#define HUSH_TEST(name, expr, expected_result) \ - run_command("if test " expr " ; then " \ - "setenv " #name "_" #expected_result " y; else " \ - "setenv " #name "_" #expected_result " n; fi", 0); \ - assert(!strcmp(#expected_result, getenv(#name "_" #expected_result))); \ - setenv(#name "_" #expected_result, NULL); - - /* Basic operators */ - HUSH_TEST(streq, "aaa = aaa", y); - HUSH_TEST(streq, "aaa = bbb", n); - - HUSH_TEST(strneq, "aaa != bbb", y); - HUSH_TEST(strneq, "aaa != aaa", n); - - HUSH_TEST(strlt, "aaa < bbb", y); - HUSH_TEST(strlt, "bbb < aaa", n); - - HUSH_TEST(strgt, "bbb > aaa", y); - HUSH_TEST(strgt, "aaa > bbb", n); - - HUSH_TEST(eq, "123 -eq 123", y); - HUSH_TEST(eq, "123 -eq 456", n); - - HUSH_TEST(ne, "123 -ne 456", y); - HUSH_TEST(ne, "123 -ne 123", n); - - HUSH_TEST(lt, "123 -lt 456", y); - HUSH_TEST(lt_eq, "123 -lt 123", n); - HUSH_TEST(lt, "456 -lt 123", n); - - HUSH_TEST(le, "123 -le 456", y); - HUSH_TEST(le_eq, "123 -le 123", y); - HUSH_TEST(le, "456 -le 123", n); - - HUSH_TEST(gt, "456 -gt 123", y); - HUSH_TEST(gt_eq, "123 -gt 123", n); - HUSH_TEST(gt, "123 -gt 456", n); - - HUSH_TEST(ge, "456 -ge 123", y); - HUSH_TEST(ge_eq, "123 -ge 123", y); - HUSH_TEST(ge, "123 -ge 456", n); - - HUSH_TEST(z, "-z \"\"", y); - HUSH_TEST(z, "-z \"aaa\"", n); - - HUSH_TEST(n, "-n \"aaa\"", y); - HUSH_TEST(n, "-n \"\"", n); - - /* Inversion of simple tests */ - HUSH_TEST(streq_inv, "! aaa = aaa", n); - HUSH_TEST(streq_inv, "! aaa = bbb", y); - - HUSH_TEST(streq_inv_inv, "! ! aaa = aaa", y); - HUSH_TEST(streq_inv_inv, "! ! aaa = bbb", n); - - /* Binary operators */ - HUSH_TEST(or_0_0, "aaa != aaa -o bbb != bbb", n); - HUSH_TEST(or_0_1, "aaa != aaa -o bbb = bbb", y); - HUSH_TEST(or_1_0, "aaa = aaa -o bbb != bbb", y); - HUSH_TEST(or_1_1, "aaa = aaa -o bbb = bbb", y); - - HUSH_TEST(and_0_0, "aaa != aaa -a bbb != bbb", n); - HUSH_TEST(and_0_1, "aaa != aaa -a bbb = bbb", n); - HUSH_TEST(and_1_0, "aaa = aaa -a bbb != bbb", n); - HUSH_TEST(and_1_1, "aaa = aaa -a bbb = bbb", y); - - /* Inversion within binary operators */ - HUSH_TEST(or_0_0_inv, "! aaa != aaa -o ! bbb != bbb", y); - HUSH_TEST(or_0_1_inv, "! aaa != aaa -o ! bbb = bbb", y); - HUSH_TEST(or_1_0_inv, "! aaa = aaa -o ! bbb != bbb", y); - HUSH_TEST(or_1_1_inv, "! aaa = aaa -o ! bbb = bbb", n); - - HUSH_TEST(or_0_0_inv_inv, "! ! aaa != aaa -o ! ! bbb != bbb", n); - HUSH_TEST(or_0_1_inv_inv, "! ! aaa != aaa -o ! ! bbb = bbb", y); - HUSH_TEST(or_1_0_inv_inv, "! ! aaa = aaa -o ! ! bbb != bbb", y); - HUSH_TEST(or_1_1_inv_inv, "! ! aaa = aaa -o ! ! bbb = bbb", y); - - setenv("ut_var_nonexistent", NULL); - setenv("ut_var_exists", "1"); - HUSH_TEST(z_varexp_quoted, "-z \"$ut_var_nonexistent\"", y); - HUSH_TEST(z_varexp_quoted, "-z \"$ut_var_exists\"", n); - setenv("ut_var_exists", NULL); - - run_command("setenv ut_var_space \" \"", 0); - assert(!strcmp(getenv("ut_var_space"), " ")); - run_command("setenv ut_var_test $ut_var_space", 0); - assert(!getenv("ut_var_test")); - run_command("setenv ut_var_test \"$ut_var_space\"", 0); - assert(!strcmp(getenv("ut_var_test"), " ")); - run_command("setenv ut_var_test \" 1${ut_var_space}${ut_var_space} 2 \"", 0); - assert(!strcmp(getenv("ut_var_test"), " 1 2 ")); - setenv("ut_var_space", NULL); - setenv("ut_var_test", NULL); - -#ifdef CONFIG_SANDBOX - /* File existence */ - HUSH_TEST(e, "-e hostfs - creating_this_file_breaks_uboot_unit_test", n); - run_command("sb save hostfs - creating_this_file_breaks_uboot_unit_test 0 1", 0); - HUSH_TEST(e, "-e hostfs - creating_this_file_breaks_uboot_unit_test", y); - /* Perhaps this could be replaced by an "rm" shell command one day */ - assert(!os_unlink("creating_this_file_breaks_uboot_unit_test")); - HUSH_TEST(e, "-e hostfs - creating_this_file_breaks_uboot_unit_test", n); -#endif #endif assert(run_command("", 0) == 0); diff --git a/test/py/test_env.py b/test/py/test_env.py index 16891cd6bb15..38c305f98250 100644 --- a/test/py/test_env.py +++ b/test/py/test_env.py @@ -39,7 +39,7 @@ def unset_var(state_test_env, var): del state_test_env.env[var] def set_var(state_test_env, var, value): - state_test_env.uboot_console.run_command("setenv " + var + " " + value) + state_test_env.uboot_console.run_command("setenv " + var + " \"" + value + "\"") state_test_env.env[var] = value def validate_empty(state_test_env, var): @@ -47,8 +47,10 @@ def validate_empty(state_test_env, var): assert response == "" def validate_set(state_test_env, var, value): - response = state_test_env.uboot_console.run_command("echo $" + var) - assert response == value + # echo does not preserve leading, internal, or trailing whitespace in the + # value. printenv does, and hence allows more complete testing. + response = state_test_env.uboot_console.run_command("printenv " + var) + assert response == (var + "=" + value) def test_env_echo_exists(state_test_env): """Echo a variable that exists""" @@ -94,3 +96,21 @@ def test_env_unset_existing(state_test_env): var = state_test_env.set_var unset_var(state_test_env, var) validate_empty(state_test_env, var) + +def test_env_expansion_spaces(state_test_env): + var_space = None + var_test = None + try: + var_space = state_test_env.get_non_existent_var() + set_var(state_test_env, var_space, " ") + + var_test = state_test_env.get_non_existent_var() + value = " 1${%(var_space)s}${%(var_space)s} 2 " % locals() + set_var(state_test_env, var_test, value) + value = " 1 2 " + validate_set(state_test_env, var_test, value) + finally: + if var_space: + unset_var(state_test_env, var_space) + if var_test: + unset_var(state_test_env, var_test) diff --git a/test/py/test_hush_if_test.py b/test/py/test_hush_if_test.py new file mode 100644 index 000000000000..3504922dcf12 --- /dev/null +++ b/test/py/test_hush_if_test.py @@ -0,0 +1,137 @@ +import os +import os.path +import pytest + +subtests = ( + # Base if functionality + + ("true", True), + ("false", False), + + # Basic operators + + ("test aaa = aaa", True), + ("test aaa = bbb", False), + + ("test aaa != bbb", True), + ("test aaa != aaa", False), + + ("test aaa < bbb", True), + ("test bbb < aaa", False), + + ("test bbb > aaa", True), + ("test aaa > bbb", False), + + ("test 123 -eq 123", True), + ("test 123 -eq 456", False), + + ("test 123 -ne 456", True), + ("test 123 -ne 123", False), + + ("test 123 -lt 456", True), + ("test 123 -lt 123", False), + ("test 456 -lt 123", False), + + ("test 123 -le 456", True), + ("test 123 -le 123", True), + ("test 456 -le 123", False), + + ("test 456 -gt 123", True), + ("test 123 -gt 123", False), + ("test 123 -gt 456", False), + + ("test 456 -ge 123", True), + ("test 123 -ge 123", True), + ("test 123 -ge 456", False), + + ("test -z \"\"", True), + ("test -z \"aaa\"", False), + + ("test -n \"aaa\"", True), + ("test -n \"\"", False), + + # Inversion of simple tests + + ("test ! aaa = aaa", False), + ("test ! aaa = bbb", True), + ("test ! ! aaa = aaa", True), + ("test ! ! aaa = bbb", False), + + # Binary operators + + ("test aaa != aaa -o bbb != bbb", False), + ("test aaa != aaa -o bbb = bbb", True), + ("test aaa = aaa -o bbb != bbb", True), + ("test aaa = aaa -o bbb = bbb", True), + + ("test aaa != aaa -a bbb != bbb", False), + ("test aaa != aaa -a bbb = bbb", False), + ("test aaa = aaa -a bbb != bbb", False), + ("test aaa = aaa -a bbb = bbb", True), + + # Inversion within binary operators + + ("test ! aaa != aaa -o ! bbb != bbb", True), + ("test ! aaa != aaa -o ! bbb = bbb", True), + ("test ! aaa = aaa -o ! bbb != bbb", True), + ("test ! aaa = aaa -o ! bbb = bbb", False), + + ("test ! ! aaa != aaa -o ! ! bbb != bbb", False), + ("test ! ! aaa != aaa -o ! ! bbb = bbb", True), + ("test ! ! aaa = aaa -o ! ! bbb != bbb", True), + ("test ! ! aaa = aaa -o ! ! bbb = bbb", True), + + # -z operator + + ("test -z \"$ut_var_nonexistent\"", True), + ("test -z \"$ut_var_exists\"", False), +) + +def exec_hush_if(uboot_console, expr, result): + cmd = "if " + expr + "; then echo true; else echo false; fi" + response = uboot_console.run_command(cmd) + assert response.strip() == str(result).lower() + +@pytest.mark.buildconfigspec("sys_hush_parser") +def test_hush_if_test_setup(uboot_console): + uboot_console.run_command("setenv ut_var_nonexistent") + uboot_console.run_command("setenv ut_var_exists 1") + +@pytest.mark.buildconfigspec("sys_hush_parser") +@pytest.mark.parametrize("expr,result", subtests) +def test_hush_if_test(uboot_console, expr, result): + exec_hush_if(uboot_console, expr, result) + +@pytest.mark.buildconfigspec("sys_hush_parser") +def test_hush_if_test_teardown(uboot_console): + uboot_console.run_command("setenv ut_var_exists") + +@pytest.mark.buildconfigspec("sys_hush_parser") +# We might test this on real filesystems via UMS, DFU, "save", etc. +# Of those, only UMS currently allows file removal though. +@pytest.mark.boardspec("sandbox") +def test_hush_if_test_host_file_exists(uboot_console): + test_file = uboot_console.config.result_dir + \ + "/creating_this_file_breaks_uboot_tests" + + try: + os.unlink(test_file) + except: + pass + assert not os.path.exists(test_file) + + expr = "test -e hostfs - " + test_file + exec_hush_if(uboot_console, expr, False) + + try: + with file(test_file, "wb"): + pass + assert os.path.exists(test_file) + + expr = "test -e hostfs - " + test_file + exec_hush_if(uboot_console, expr, True) + finally: + os.unlink(test_file) + + expr = "test -e hostfs - " + test_file + exec_hush_if(uboot_console, expr, False) diff --git a/test/py/test_shell_basics.py b/test/py/test_shell_basics.py new file mode 100644 index 000000000000..5477ea4e32ea --- /dev/null +++ b/test/py/test_shell_basics.py @@ -0,0 +1,31 @@ +def test_shell_execute(uboot_console): + """Test any shell command""" + response = uboot_console.run_command("echo hello") + assert response.strip() == "hello" + +def test_shell_semicolon_two(uboot_console): + """Test two shell commands separate by a semi-colon""" + cmd = "echo hello; echo world" + response = uboot_console.run_command(cmd) + # This validation method ignores the exact whitespace between the strings + assert response.index("hello") < response.index("world") + +def test_shell_semicolon_three(uboot_console): + """Test three shell commands separate by a semi-colon""" + cmd = "setenv list 1; setenv list ${list}2; setenv list ${list}3; " + \ + "echo ${list}" + response = uboot_console.run_command(cmd) + assert response.strip() == "123" + uboot_console.run_command("setenv list") + +def test_shell_run(uboot_console): + """Test the 'run' shell command""" + uboot_console.run_command("setenv foo 'setenv monty 1; setenv python 2'") + uboot_console.run_command("run foo") + response = uboot_console.run_command("echo $monty") + assert response.strip() == "1" + response = uboot_console.run_command("echo $python") + assert response.strip() == "2" + uboot_console.run_command("setenv foo") + uboot_console.run_command("setenv monty") + uboot_console.run_command("setenv python") diff --git a/test/py/uboot_console_base.py b/test/py/uboot_console_base.py index 4bf9e8303633..5ecddd88e124 100644 --- a/test/py/uboot_console_base.py +++ b/test/py/uboot_console_base.py @@ -84,7 +84,9 @@ class ConsoleBase(object): raise Exception("Bad pattern found on console: " + bad_pattern_ids[m - 1]) self.at_prompt = True - return self.p.before.strip() + # Only strip \r\n; space/TAB might be significant if testing + # indentation. + return self.p.before.strip("\r\n") except Exception as ex: self.log.error(str(ex)) self.cleanup_spawn() -- 1.9.1 _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot