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:
@@ -199,6 +199,12 @@ dofile('bitwise.lua')
|
|||||||
assert(dofile('verybig.lua', true) == 10); collectgarbage()
|
assert(dofile('verybig.lua', true) == 10); collectgarbage()
|
||||||
dofile('files.lua')
|
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
|
if #msgs > 0 then
|
||||||
local m = table.concat(msgs, "\n ")
|
local m = table.concat(msgs, "\n ")
|
||||||
warn("#tests not performed:\n ", m, "\n")
|
warn("#tests not performed:\n ", m, "\n")
|
||||||
|
|||||||
@@ -471,13 +471,15 @@ do print("testing flush")
|
|||||||
assert(io.flush()) -- write to device
|
assert(io.flush()) -- write to device
|
||||||
assert(f:close())
|
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(f:write("abcd")) -- write to buffer
|
||||||
assert(not f:flush()) -- cannot write to device
|
assert(not f:flush()) -- cannot write to device
|
||||||
assert(f:write("abcd")) -- write to buffer
|
assert(f:write("abcd")) -- write to buffer
|
||||||
assert(not io.flush()) -- cannot write to device
|
assert(not io.flush()) -- cannot write to device
|
||||||
assert(f:close())
|
assert(f:close())
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
-- test for multiple arguments in 'lines'
|
-- test for multiple arguments in 'lines'
|
||||||
|
|||||||
53
testes/lush/argv.lua
Normal file
53
testes/lush/argv.lua
Normal 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
90
testes/lush/commands.lua
Normal 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
69
testes/lush/envvars.lua
Normal 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"
|
||||||
55
testes/lush/interpolation.lua
Normal file
55
testes/lush/interpolation.lua
Normal 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"
|
||||||
Reference in New Issue
Block a user