Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tests for Lua API extension proposed in martanne/vis#675 #12

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
Empty file added lua/subprocess.in
Empty file.
81 changes: 81 additions & 0 deletions lua/subprocess.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
require 'busted.runner'()

local function hardfail()
-- It is only way to change exitcode of vis from the QUIT event handler
io.popen("kill -9 $PPID", "r")
end

local expected_events = {}

local failed = false
vis.events.subscribe(vis.events.QUIT, function ()
for k, v in pairs(expected_events) do
if v and #v > 0 then
failed = true
print("The following events did not happened for process", k)
for i, vv in pairs(v) do
print(i, ": ", vv.etype, " - ", vv.expected)
print(tostring(i)..": ", vv.etype, " - ("..type(vv.expected)..")",
vv.expected)
end
end
end
if failed then hardfail() end
end)

vis.events.subscribe(vis.events.PROCESS_RESPONSE, function (name, et, ec, eb)
if expected_events[name] and #(expected_events[name]) > 0 then
local current_event = table.remove(expected_events[name], 1)
if ec ~= current_event.expected_code or eb ~= current_event.expected_buffer or et ~= current_event.etype then
print("Event assert failed for process", name)
print("Got event type: ("..type(et)..")", et)
print("Expected event type:", current_event.etype)
print("Got event code: (", type(ec), ")", ec)
print("Expected code:("..type(current_event.expected_code)..")",
current_event.expected_code)
print("Got event buffer: (", type(eb), ")", eb)
print("Expected buffer:("..type(current_event.expected_buffer)..")",
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
print("Event assert failed for process", name)
print("Got event type: ("..type(et)..")", et)
print("Expected event type:", current_event.etype)
print("Got event code: (", type(ec), ")", ec)
print("Expected code:("..type(current_event.expected_code)..")",
current_event.expected_code)
print("Got event buffer: (", type(eb), ")", eb)
print("Expected buffer:("..type(current_event.expected_buffer)..")",
print("Event assert failed for process:", name)
print("Got event type:", "("..type(et)..")", et)
print("Expected:", "("..type(current_event.etype)..")",
current_event.etype)
print("Got event code:", "("..type(ec)..")", ec)
print("Expected:", "("..type(current_event.expected_code)..")",
current_event.expected_code)
print("Got event data:", "("..type(eb)..")", eb)
print("Expected:", "("..type(current_event.expected_buffer)..")",

current_event.expected_buffer)
if #(expected_events[name]) > 0 then
print("Remaining expected events to be fired by process", name)
for i, k in pairs(expected_events[name]) do
print(tostring(i)..": ",
k.etype, " - ("..tostring(k.expected_code) .. ", " .. k.expected_buffer..")",
k.expected)
end
end
hardfail()
end
end
end)

local function event_assert(name, eventtype, expected_code, expected_buffer)
if not expected_events[name] then expected_events[name] = {} end
table.insert(expected_events[name], {
etype = eventtype,
expected_code = expected_code,
expected_buffer = expected_buffer
})
end

describe("vis.communicate", function ()
it("process creation", function ()
event_assert("starttest", "STDOUT", nil, "testanswer\n")
event_assert("starttest", "EXIT", 0, nil)
vis:communicate("starttest", "echo testanswer")
end)
it("process termination", function()
event_assert("termtest", "SIGNAL", 15, nil)
local handle = vis:communicate("termtest", "sleep 1s")
handle:close()
end)
Comment on lines +65 to +69
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did this ever work? Shouldn't the assert be event_assert("termtest", "EXIT", 143, nil)? I'm not sure there is a reliable way to catch a SIGNAL event.

it("process input/stderr", function()
event_assert("inputtest", "STDERR", nil, "testdata\n")
event_assert("inputtest", "EXIT", 0, nil)
local handle = vis:communicate("inputtest", "read n; echo $n 1>&2")
handle:write("testdata\n")
handle:flush()
-- do not close handle because it is being closed automaticaly
-- when process quits
end)
end)
7 changes: 5 additions & 2 deletions lua/test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,18 @@ for t in $test_files; do
t=${t%.lua}
t=${t#./}
printf "%-30s" "$t"
$VIS "$t.in" < /dev/null 2> /dev/null > "$t.busted"

mkfifo infifo
$VIS "$t.in" <infifo 2> /dev/null > "$t.busted" &
for i in 1; do sleep 0.1s; echo ":qall!"; done > infifo &
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not a fan of the non-posix sleep usage here and in the lua script.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do not see any good way of performing it without the race condition. May be putting read -t 0.1 will be ok?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

read -t 0.1

Also not defined in posix. Its not elegant but to keep the script completely posix compatible and minimize the sleep cost something like this should work:

	if [ $(grep -q "vis:communicate" < "$t.lua") ]; then
		{ sleep 1; echo ":qall!"; } > infifo &
	else
		echo ":qall!" > infifo &
	fi

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you mean by "non-posix" and "not defined in posix"? I checked it on wiki and found both commands in the list of posix commands.
https://en.wikipedia.org/wiki/List_of_POSIX_commands

There is a problem with sleep in the shell script, because it is a bad way to overcome a race condition. We need to give async processes some time to finish and produce all necessary events, but there should be a better way for syncronization and I am still thinking about it.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you mean by "non-posix" and "not defined in posix"? I checked it on wiki and found both commands in the list of posix commands. https://en.wikipedia.org/wiki/List_of_POSIX_commands

https://pubs.opengroup.org/onlinepubs/9699919799/

wait %1 && wait %2
if [ $? -ne 0 ]; then
printf "FAIL\n"
cat "$t.busted"
else
TESTS_OK=$((TESTS_OK + 1))
printf "OK\n"
fi
rm infifo
done

printf "Tests ok %d/%d\n" $TESTS_OK $TESTS_RUN
Expand Down
3 changes: 1 addition & 2 deletions lua/visrc.lua
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ io.stderr = io.stdout

-- make sure we gracefully terminate, cleanup terminal state etc.
os.exit = function(status)
vis:exit(status)
if status ~= 0 then vis:exit(status) end
end

vis.events.subscribe(vis.events.WIN_OPEN, function(win)
Expand All @@ -24,5 +24,4 @@ vis.events.subscribe(vis.events.WIN_OPEN, function(win)
return
end
end
vis:exit(0)
end)