Implement piping between commands in backtick syntax (issue #06)
Add split_pipeline() to split command strings on unquoted | and exec_pipeline() to fork N children connected by inter-stage pipes. Only the last stage's stdout/stderr are captured; middle stages' stderr is inherited. Exit code comes from the last stage.
This commit is contained in:
83
testes/lush/piping.lua
Normal file
83
testes/lush/piping.lua
Normal file
@@ -0,0 +1,83 @@
|
||||
-- testes/lush/piping.lua
|
||||
-- Tests for piping between commands (issue #06).
|
||||
|
||||
print "testing piping"
|
||||
|
||||
-- basic pipe
|
||||
do
|
||||
local r = `echo hello | cat`
|
||||
assert(r.stdout == "hello\n", "basic pipe stdout: " .. r.stdout)
|
||||
assert(r.code == 0)
|
||||
end
|
||||
|
||||
-- multi-stage pipe
|
||||
do
|
||||
local r = `printf "a\nb\nc\n" | grep b | cat`
|
||||
assert(r.stdout == "b\n", "multi-stage pipe stdout: " .. r.stdout)
|
||||
end
|
||||
|
||||
-- exit code is from last stage
|
||||
do
|
||||
local r = `echo hello | sh -c "exit 42"`
|
||||
assert(r.code == 42, "exit code from last stage: " .. r.code)
|
||||
end
|
||||
|
||||
-- pipe with first stage failing: cat gets EOF, succeeds
|
||||
do
|
||||
local r = `nonexistent_cmd_999 | cat`
|
||||
assert(r.code == 0, "cat should succeed with EOF: " .. r.code)
|
||||
end
|
||||
|
||||
-- quoted pipe character is NOT a pipe separator (double quotes)
|
||||
do
|
||||
local r = `echo "a|b"`
|
||||
assert(r.stdout == "a|b\n", "double-quoted pipe: " .. r.stdout)
|
||||
end
|
||||
|
||||
-- single-quoted pipe character is NOT a pipe separator
|
||||
do
|
||||
local r = `echo 'a|b'`
|
||||
assert(r.stdout == "a|b\n", "single-quoted pipe: " .. r.stdout)
|
||||
end
|
||||
|
||||
-- pipe with interpolation
|
||||
do
|
||||
local ext = ".lua"
|
||||
local r = `echo "test.lua test.py" | grep "${ext}"`
|
||||
assert(r.stdout == "test.lua test.py\n", "pipe with interpolation: " .. r.stdout)
|
||||
end
|
||||
|
||||
-- stderr from middle stages goes to terminal, not captured
|
||||
do
|
||||
local r = `sh -c "echo err >&2; echo out" | cat`
|
||||
assert(r.stdout == "out\n", "stdout through pipe: " .. r.stdout)
|
||||
assert(r.stderr == "", "middle stderr not captured: '" .. r.stderr .. "'")
|
||||
end
|
||||
|
||||
-- single command unchanged (regression check)
|
||||
do
|
||||
local r = `echo hello`
|
||||
assert(r.stdout == "hello\n")
|
||||
assert(r.code == 0)
|
||||
end
|
||||
|
||||
-- pipe preserves multi-line output
|
||||
do
|
||||
local r = `printf "line1\nline2\nline3\n" | cat`
|
||||
assert(r.stdout == "line1\nline2\nline3\n", "multiline pipe: " .. r.stdout)
|
||||
end
|
||||
|
||||
-- pipe with whitespace around |
|
||||
do
|
||||
local r = `echo hello | cat`
|
||||
assert(r.stdout == "hello\n", "whitespace around pipe: " .. r.stdout)
|
||||
end
|
||||
|
||||
-- last stage stderr is captured
|
||||
do
|
||||
local r = `echo hello | sh -c "cat; echo piperr >&2"`
|
||||
assert(r.stdout == "hello\n", "last stage stdout: " .. r.stdout)
|
||||
assert(r.stderr == "piperr\n", "last stage stderr: " .. r.stderr)
|
||||
end
|
||||
|
||||
print "OK"
|
||||
Reference in New Issue
Block a user