Add lush feature tests and fix /dev/full test for macOS

Add test suite under testes/lush/ covering backtick commands, argv
parsing, ${} interpolation, and $NAME environment variables. Wire
them into testes/all.lua so they run with the full Lua 5.5 suite.

Skip /dev/full test in files.lua when the device doesn't exist
(macOS has no /dev/full).
This commit is contained in:
Cormac Shannon
2026-02-28 19:07:00 +00:00
parent 4b49907ce7
commit 27f16b126d
6 changed files with 281 additions and 6 deletions

View File

@@ -199,6 +199,12 @@ dofile('bitwise.lua')
assert(dofile('verybig.lua', true) == 10); collectgarbage()
dofile('files.lua')
-- lush shell feature tests
dofile('lush/commands.lua')
dofile('lush/argv.lua')
dofile('lush/interpolation.lua')
dofile('lush/envvars.lua')
if #msgs > 0 then
local m = table.concat(msgs, "\n ")
warn("#tests not performed:\n ", m, "\n")

View File

@@ -471,12 +471,14 @@ do print("testing flush")
assert(io.flush()) -- write to device
assert(f:close())
local f = io.output("/dev/full")
local ok, f = pcall(io.output, "/dev/full")
if ok then -- /dev/full exists (Linux); skip on macOS
assert(f:write("abcd")) -- write to buffer
assert(not f:flush()) -- cannot write to device
assert(f:write("abcd")) -- write to buffer
assert(not io.flush()) -- cannot write to device
assert(f:close())
end
end

53
testes/lush/argv.lua Normal file
View File

@@ -0,0 +1,53 @@
-- testes/lush/argv.lua
-- Tests for argv parsing (issue #04).
print "testing argv parsing"
-- simple whitespace splitting
do
local r = `echo a b c`
assert(r.stdout == "a b c\n")
end
-- single-quoted strings (literal, no escapes)
do
local r = `echo 'hello world'`
assert(r.stdout == "hello world\n")
end
-- double-quoted strings
do
local r = `echo "hello world"`
assert(r.stdout == "hello world\n")
end
-- multiple quoted arguments
do
local r = `echo "a b" "c d"`
assert(r.stdout == "a b c d\n")
end
-- backslash escaping outside quotes
do
local r = `echo hello\ world`
assert(r.stdout == "hello world\n")
end
-- double-quote escapes: \" and \\
do
local r = `echo "hello\"world"`
assert(r.stdout == 'hello"world\n')
end
do
local r = `echo "hello\\world"`
assert(r.stdout == "hello\\world\n")
end
-- tab escape in double quotes
do
local r = `echo "a\tb"`
assert(r.stdout == "a\tb\n")
end
print "OK"

90
testes/lush/commands.lua Normal file
View File

@@ -0,0 +1,90 @@
-- testes/lush/commands.lua
-- Tests for backtick command execution (issues #02, #03).
print "testing backtick commands"
-- basic command, result is a table with code/stdout/stderr
do
local r = `echo hello`
assert(type(r) == "table")
assert(type(r.code) == "number")
assert(type(r.stdout) == "string")
assert(type(r.stderr) == "string")
end
-- successful command returns exit code 0
do
local r = `true`
assert(r.code == 0)
end
-- failed command returns non-zero exit code
do
local r = `false`
assert(r.code == 1)
end
-- specific exit codes are preserved
do
local r = `sh -c "exit 42"`
assert(r.code == 42)
end
-- command not found returns 127
do
local r = `nonexistent_command_xyz_999`
assert(r.code == 127)
end
-- stdout capture
do
local r = `echo hello`
assert(r.stdout == "hello\n")
end
-- stderr capture
do
local r = `sh -c "echo err >&2"`
assert(r.stderr == "err\n")
assert(r.stdout == "")
end
-- stdout and stderr are independent
do
local r = `sh -c "echo out; echo err >&2"`
assert(r.stdout == "out\n")
assert(r.stderr == "err\n")
end
-- empty command returns code 0 and empty strings
do
local r = ``
assert(r.code == 0)
assert(r.stdout == "")
assert(r.stderr == "")
end
-- multi-word output preserved
do
local r = `echo hello world`
assert(r.stdout == "hello world\n")
end
-- backtick as statement (result discarded, no error)
do
`true`
end
-- backtick result used inline
do
local code = `true`.code
assert(code == 0)
end
-- multiline output captured
do
local r = `printf "a\nb\nc\n"`
assert(r.stdout == "a\nb\nc\n")
end
print "OK"

69
testes/lush/envvars.lua Normal file
View File

@@ -0,0 +1,69 @@
-- testes/lush/envvars.lua
-- Tests for environment variable access with $NAME syntax (issue #05).
print "testing environment variables"
-- $NAME reads an existing environment variable
do
local p = $PATH
assert(type(p) == "string")
assert(#p > 0)
end
-- $NAME returns nil for unset variable
do
local v = $_LUSH_TEST_UNSET_VAR
assert(v == nil)
end
-- $NAME = expr sets an environment variable
do
$_LUSH_TEST_A = "hello"
assert($_LUSH_TEST_A == "hello")
end
-- $NAME = expr with number coerces to string
do
$_LUSH_TEST_B = 42
assert($_LUSH_TEST_B == "42")
end
-- $NAME = nil unsets the variable
do
$_LUSH_TEST_C = "temp"
assert($_LUSH_TEST_C == "temp")
$_LUSH_TEST_C = nil
assert($_LUSH_TEST_C == nil)
end
-- env vars are visible to child processes
do
$_LUSH_TEST_D = "from_lush"
local r = `sh -c "echo $_LUSH_TEST_D"`
-- the $_LUSH_TEST_D here is NOT lush interpolation (no {}),
-- it's a literal string passed to sh which expands it
assert(r.stdout == "from_lush\n", r.stdout)
end
-- overwriting an env var
do
$_LUSH_TEST_E = "first"
$_LUSH_TEST_E = "second"
assert($_LUSH_TEST_E == "second")
end
-- env var used in interpolation
do
$_LUSH_TEST_F = "works"
local r = `echo ${$_LUSH_TEST_F}`
assert(r.stdout == "works\n")
end
-- clean up
$_LUSH_TEST_A = nil
$_LUSH_TEST_B = nil
$_LUSH_TEST_D = nil
$_LUSH_TEST_E = nil
$_LUSH_TEST_F = nil
print "OK"

View File

@@ -0,0 +1,55 @@
-- testes/lush/interpolation.lua
-- Tests for ${expr} interpolation in backtick commands (issue #02).
print "testing string interpolation"
-- single interpolation
do
local name = "world"
local r = `echo ${name}`
assert(r.stdout == "world\n")
end
-- multiple interpolations
do
local a = "hello"
local b = "world"
local r = `echo ${a} ${b}`
assert(r.stdout == "hello world\n")
end
-- interpolation with number
do
local n = 42
local r = `echo ${n}`
assert(r.stdout == "42\n")
end
-- interpolation with expression
do
local x = 3
local r = `echo ${x + 1}`
assert(r.stdout == "4\n")
end
-- interpolation with string concatenation
do
local prefix = "hello"
local r = `echo ${prefix .. " world"}`
assert(r.stdout == "hello world\n")
end
-- interpolation surrounded by literal text
do
local mid = "b"
local r = `echo a${mid}c`
assert(r.stdout == "abc\n")
end
-- literal $ (not followed by {) is kept
do
local r = `echo $`
assert(r.stdout == "$\n")
end
print "OK"