tests/_runner.lua: Allow non-step based tests

The current _runner.lua expects a table containing steps to be passed
in. However, not all tests look like this. This commits adds an API to
the runner that allows tests to run however they like. They just have to
call run_direct() initially and call done() when they are finished.

Signed-off-by: Uli Schlachter <psychon@znc.in>
This commit is contained in:
Uli Schlachter 2019-02-28 09:22:36 +01:00
parent 2d2dba0d80
commit f304c608e8
1 changed files with 58 additions and 40 deletions

View File

@ -43,77 +43,23 @@ runner.step_kill_clients = function(step)
end
end
runner.run_steps = function(steps, options)
-- Setup timer/timeout to limit waiting for signal and quitting awesome.
local t = timer({timeout=0})
local wait=20
local step=1
local step_count=0
options = options or {
kill_clients=true,
}
assert(not running, "run_steps() was called twice")
running = true
if options.kill_clients then
-- Add a final step to kill all clients and wait for them to finish.
-- Ref: https://github.com/awesomeWM/awesome/pull/1904#issuecomment-312793006
steps[#steps + 1] = runner.step_kill_clients
end
t:connect_signal("timeout", function() timer.delayed_call(function()
io.flush() -- for "tail -f".
step_count = step_count + 1
local step_as_string = step..'/'..#steps..' (@'..step_count..')'
--- Print a message if verbose mode is enabled.
-- @tparam string message The message to print.
function runner.verbose(message)
if verbose then
io.stderr:write(string.format('Running step %s..\n', step_as_string))
io.stderr:write(message .. "\n")
end
end
-- Call the current step's function.
local success, result = xpcall(function()
return steps[step](step_count)
end, debug.traceback)
if not success then
io.stderr:write('Error: running function for step '
..step_as_string..': '..tostring(result)..'!\n')
t:stop()
if not runner.quit_awesome_on_error then
io.stderr:write("Keeping awesome open...\n")
return -- keep awesome open on error.
end
elseif result then
-- true: test succeeded.
if step < #steps then
-- Next step.
step = step+1
step_count = 0
wait = 20
t.timeout = 0
t:again()
return
end
elseif result == false then
io.stderr:write("Step "..step_as_string.." failed (returned false).\n")
--- When using run_direct(), this function indicates that the test is now done.
-- @tparam[opt=nil] string message An error message explaining the test failure, if it failed.
function runner.done(message)
if message then
io.stderr:write("Error: " .. message .. "\n")
if not runner.quit_awesome_on_error then
io.stderr:write("Keeping awesome open...\n")
return
end
else
-- No result yet, run this step again.
wait = wait-1
if wait > 0 then
t.timeout = 0.1
t:again()
else
io.stderr:write("Error: timeout waiting for signal in step "
..step_as_string..".\n")
t:stop()
end
return
end
local client_count = #client.get()
@ -127,10 +73,82 @@ runner.run_steps = function(steps, options)
end
end
if success and result then
if not message then
io.stderr:write("Test finished successfully.\n")
end
awesome.quit()
end
--- This function is called to indicate that a test does not use the run_steps()
-- facility, but instead runs something else directly.
function runner.run_direct()
assert(not running, "API abuse: Test was started twice")
running = true
end
--- Start some step-wise tests. The given steps are called in order until all
-- succeeded. Each step is a function that can return true/false to indicate
-- success/failure, but can also return nothing if it needs to be called again
-- later.
function runner.run_steps(steps, options)
-- Setup timer/timeout to limit waiting for signal and quitting awesome.
local t = timer({timeout=0})
local wait=20
local step=1
local step_count=0
options = options or {
kill_clients=true,
}
runner.run_direct()
if options.kill_clients then
-- Add a final step to kill all clients and wait for them to finish.
-- Ref: https://github.com/awesomeWM/awesome/pull/1904#issuecomment-312793006
steps[#steps + 1] = runner.step_kill_clients
end
t:connect_signal("timeout", function() timer.delayed_call(function()
io.flush() -- for "tail -f".
step_count = step_count + 1
local step_as_string = step..'/'..#steps..' (@'..step_count..')'
runner.verbose(string.format('Running step %s..\n', step_as_string))
-- Call the current step's function.
local success, result = xpcall(function()
return steps[step](step_count)
end, debug.traceback)
if not success then
runner.done('running function for step '
..step_as_string..': '..tostring(result)..'!')
t:stop()
elseif result then
-- true: test succeeded.
if step < #steps then
-- Next step.
step = step+1
step_count = 0
wait = 20
t.timeout = 0
t:again()
else
-- All steps finished, we are done.
runner.done()
end
elseif result == false then
runner.done("Step "..step_as_string.." failed (returned false).")
else
-- No result yet, run this step again.
wait = wait-1
if wait > 0 then
t.timeout = 0.1
t:again()
else
runner.done("timeout waiting for signal in step "
..step_as_string..".")
t:stop()
end
end
end) end)
t:start()
end