From: Ahmad Fatoum <[email protected]>

We currently have no way to differentiate between a variable that's set
and one that's empty, but this would be useful for scripts that source
other scripts for customization and want to verify if some variables
have been explicitly set to be empty or not, e.g. an initrd override
that's empty would mean to omit the initrd as opposed to not setting it,
which means to attempt no override.

Signed-off-by: Ahmad Fatoum <[email protected]>
---
 commands/test.c       | 12 +++++++++++-
 test/py/test_shell.py | 43 +++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 54 insertions(+), 1 deletion(-)

diff --git a/commands/test.c b/commands/test.c
index c2f2993df406..d32536b0fd3e 100644
--- a/commands/test.c
+++ b/commands/test.c
@@ -10,6 +10,7 @@
 #include <common.h>
 #include <command.h>
 #include <fnmatch.h>
+#include <environment.h>
 #include <fs.h>
 #include <linux/stat.h>
 
@@ -34,6 +35,7 @@ typedef enum {
        OPT_CHAR,
        OPT_SYMBOLIC_LINK,
        OPT_NONZERO_SIZE,
+       OPT_VAR_EXISTS,
        OPT_MAX,
 } test_opts;
 
@@ -58,6 +60,7 @@ static char *test_options[] = {
        [OPT_CHAR]                      = "-c",
        [OPT_SYMBOLIC_LINK]             = "-L",
        [OPT_NONZERO_SIZE]              = "-s",
+       [OPT_VAR_EXISTS]                = "-v",
 };
 
 static int parse_opt(const char *opt)
@@ -197,6 +200,13 @@ static int do_test(int argc, char *argv[])
                        expr = (opt == OPT_ZERO) ? zero : !zero;
                        break;
 
+               case OPT_VAR_EXISTS:
+                       adv = 2;
+                       if (left < 2)
+                               break;
+                       expr = getenv(ap[1]) != NULL;
+                       break;
+
                case OPT_FILE:
                case OPT_DIRECTORY:
                case OPT_EXISTS:
@@ -302,7 +312,7 @@ static const char * const test_aliases[] = { "[", "[[", 
NULL};
 BAREBOX_CMD_HELP_START(test)
 BAREBOX_CMD_HELP_TEXT("Options:")
 BAREBOX_CMD_HELP_TEXT("\t!, =, !=, -eq, -ne, -ge, -gt, -le, -lt, -o, -a, -z, 
-n, -d, -e,")
-BAREBOX_CMD_HELP_TEXT("\t-s, -f, -L; see 'man test' on your PC for more 
information.")
+BAREBOX_CMD_HELP_TEXT("\t-s, -f, -L, -v; see 'man test' on your PC for more 
information.")
 BAREBOX_CMD_HELP_END
 
 BAREBOX_CMD_START(test)
diff --git a/test/py/test_shell.py b/test/py/test_shell.py
index 22a076d10e1e..23c2d5dbb0b6 100644
--- a/test/py/test_shell.py
+++ b/test/py/test_shell.py
@@ -112,3 +112,46 @@ def test_cmd_clk(barebox, barebox_config):
     assert regions >= 0
 
     assert count_dicts_in_command_output(barebox, 'clk_dump -vj') == regions
+
+
+def test_barebox_test_var_exists(barebox, barebox_config):
+    skip_disabled(barebox_config, "CONFIG_CMD_TEST", "CONFIG_CMD_ECHO")
+
+    # Create a file with variable definitions
+    barebox.run_check('echo -o /tmp/testvars "TEST_VAR=value"')
+    barebox.run_check('echo -a /tmp/testvars "EMPTY_VAR="')
+
+    # Test with unset variable - should fail
+    _, _, returncode = barebox.run('test -v NONEXISTENT_VAR')
+    assert returncode == 1
+
+    _, _, returncode = barebox.run('[[ -v NONEXISTENT_VAR ]]')
+    assert returncode == 1
+
+    # Test with set variable - should succeed
+    _, _, returncode = barebox.run('. /tmp/testvars; test -v TEST_VAR')
+    assert returncode == 0
+
+    _, _, returncode = barebox.run('. /tmp/testvars; [[ -v TEST_VAR ]]')
+    assert returncode == 0
+
+    # Test with empty but set variable - should succeed
+    _, _, returncode = barebox.run('. /tmp/testvars; test -v EMPTY_VAR')
+    assert returncode == 0
+
+    _, _, returncode = barebox.run('. /tmp/testvars; [[ -v EMPTY_VAR ]]')
+    assert returncode == 0
+
+    # Test negation with !
+    _, _, returncode = barebox.run('test ! -v NONEXISTENT_VAR')
+    assert returncode == 0
+
+    _, _, returncode = barebox.run('. /tmp/testvars; test ! -v TEST_VAR')
+    assert returncode == 1
+
+    # Test in conditional context
+    barebox.run_check('. /tmp/testvars; [[ -v TEST_VAR ]] && echo ok')
+    barebox.run_check('[[ ! -v NONEXISTENT_VAR ]] && echo ok')
+
+    # Clean up
+    barebox.run_check('rm /tmp/testvars')
-- 
2.47.3


Reply via email to