Merge pull request #2711 from psychon/improve_test_runner
Improve the test runner: allow "direct" tests (instead of only steps-based tests)
This commit is contained in:
commit
a802d0c2c8
|
@ -43,7 +43,54 @@ runner.step_kill_clients = function(step)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
runner.run_steps = function(steps, options)
|
--- 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(message .. "\n")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
--- 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
|
||||||
|
end
|
||||||
|
|
||||||
|
local client_count = #client.get()
|
||||||
|
if client_count > 0 then
|
||||||
|
io.stderr:write(string.format(
|
||||||
|
"NOTE: there were %d clients left after the test.\n", client_count))
|
||||||
|
|
||||||
|
-- Remove any clients.
|
||||||
|
for _,c in ipairs(client.get()) do
|
||||||
|
c:kill()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
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.
|
-- Setup timer/timeout to limit waiting for signal and quitting awesome.
|
||||||
local t = timer({timeout=0})
|
local t = timer({timeout=0})
|
||||||
local wait=20
|
local wait=20
|
||||||
|
@ -52,8 +99,7 @@ runner.run_steps = function(steps, options)
|
||||||
options = options or {
|
options = options or {
|
||||||
kill_clients=true,
|
kill_clients=true,
|
||||||
}
|
}
|
||||||
assert(not running, "run_steps() was called twice")
|
runner.run_direct()
|
||||||
running = true
|
|
||||||
|
|
||||||
if options.kill_clients then
|
if options.kill_clients then
|
||||||
-- Add a final step to kill all clients and wait for them to finish.
|
-- Add a final step to kill all clients and wait for them to finish.
|
||||||
|
@ -65,9 +111,7 @@ runner.run_steps = function(steps, options)
|
||||||
io.flush() -- for "tail -f".
|
io.flush() -- for "tail -f".
|
||||||
step_count = step_count + 1
|
step_count = step_count + 1
|
||||||
local step_as_string = step..'/'..#steps..' (@'..step_count..')'
|
local step_as_string = step..'/'..#steps..' (@'..step_count..')'
|
||||||
if verbose then
|
runner.verbose(string.format('Running step %s..\n', step_as_string))
|
||||||
io.stderr:write(string.format('Running step %s..\n', step_as_string))
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Call the current step's function.
|
-- Call the current step's function.
|
||||||
local success, result = xpcall(function()
|
local success, result = xpcall(function()
|
||||||
|
@ -75,14 +119,9 @@ runner.run_steps = function(steps, options)
|
||||||
end, debug.traceback)
|
end, debug.traceback)
|
||||||
|
|
||||||
if not success then
|
if not success then
|
||||||
io.stderr:write('Error: running function for step '
|
runner.done('running function for step '
|
||||||
..step_as_string..': '..tostring(result)..'!\n')
|
..step_as_string..': '..tostring(result)..'!')
|
||||||
t:stop()
|
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
|
elseif result then
|
||||||
-- true: test succeeded.
|
-- true: test succeeded.
|
||||||
if step < #steps then
|
if step < #steps then
|
||||||
|
@ -92,16 +131,12 @@ runner.run_steps = function(steps, options)
|
||||||
wait = 20
|
wait = 20
|
||||||
t.timeout = 0
|
t.timeout = 0
|
||||||
t:again()
|
t:again()
|
||||||
return
|
else
|
||||||
|
-- All steps finished, we are done.
|
||||||
|
runner.done()
|
||||||
end
|
end
|
||||||
|
|
||||||
elseif result == false then
|
elseif result == false then
|
||||||
io.stderr:write("Step "..step_as_string.." failed (returned false).\n")
|
runner.done("Step "..step_as_string.." failed (returned false).")
|
||||||
if not runner.quit_awesome_on_error then
|
|
||||||
io.stderr:write("Keeping awesome open...\n")
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
else
|
else
|
||||||
-- No result yet, run this step again.
|
-- No result yet, run this step again.
|
||||||
wait = wait-1
|
wait = wait-1
|
||||||
|
@ -109,28 +144,11 @@ runner.run_steps = function(steps, options)
|
||||||
t.timeout = 0.1
|
t.timeout = 0.1
|
||||||
t:again()
|
t:again()
|
||||||
else
|
else
|
||||||
io.stderr:write("Error: timeout waiting for signal in step "
|
runner.done("timeout waiting for signal in step "
|
||||||
..step_as_string..".\n")
|
..step_as_string..".")
|
||||||
t:stop()
|
t:stop()
|
||||||
end
|
end
|
||||||
return
|
|
||||||
end
|
end
|
||||||
|
|
||||||
local client_count = #client.get()
|
|
||||||
if client_count > 0 then
|
|
||||||
io.stderr:write(string.format(
|
|
||||||
"NOTE: there were %d clients left after the test.\n", client_count))
|
|
||||||
|
|
||||||
-- Remove any clients.
|
|
||||||
for _,c in ipairs(client.get()) do
|
|
||||||
c:kill()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if success and result then
|
|
||||||
io.stderr:write("Test finished successfully.\n")
|
|
||||||
end
|
|
||||||
awesome.quit()
|
|
||||||
end) end)
|
end) end)
|
||||||
t:start()
|
t:start()
|
||||||
end
|
end
|
||||||
|
|
|
@ -3,62 +3,44 @@
|
||||||
local runner = require("_runner")
|
local runner = require("_runner")
|
||||||
local spawn = require("awful.spawn")
|
local spawn = require("awful.spawn")
|
||||||
|
|
||||||
local todo = 2
|
local had_exit, had_success
|
||||||
local had_error = false
|
local had_error = false
|
||||||
|
|
||||||
local function wait_a_bit(count)
|
local function check_done()
|
||||||
if todo == 0 or count == 5 then
|
if had_exit and had_success then
|
||||||
return true
|
if had_error then
|
||||||
end
|
runner.done("Some error occurred, see above")
|
||||||
end
|
else
|
||||||
runner.run_steps({
|
runner.done()
|
||||||
function()
|
|
||||||
local err = spawn.with_line_callback(
|
|
||||||
{ os.getenv("build_dir") .. "/test-gravity" },
|
|
||||||
{
|
|
||||||
exit = function(what, code)
|
|
||||||
assert(what == "exit", what)
|
|
||||||
assert(code == 0, "Exit code was " .. code)
|
|
||||||
todo = todo - 1
|
|
||||||
end,
|
|
||||||
stderr = function(line)
|
|
||||||
had_error = true
|
|
||||||
print("Read on stderr: " .. line)
|
|
||||||
end,
|
|
||||||
stdout = function(line)
|
|
||||||
if line == "SUCCESS" then
|
|
||||||
todo = todo - 1
|
|
||||||
elseif line:sub(1, 5) ~= "LOG: " then
|
|
||||||
had_error = true
|
|
||||||
print("Read on stdout: " .. line)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
})
|
|
||||||
assert(type(err) ~= "string", err)
|
|
||||||
return true
|
|
||||||
end,
|
|
||||||
-- Buy the external program some time to finish
|
|
||||||
wait_a_bit,
|
|
||||||
wait_a_bit,
|
|
||||||
wait_a_bit,
|
|
||||||
wait_a_bit,
|
|
||||||
wait_a_bit,
|
|
||||||
wait_a_bit,
|
|
||||||
wait_a_bit,
|
|
||||||
wait_a_bit,
|
|
||||||
wait_a_bit,
|
|
||||||
wait_a_bit,
|
|
||||||
wait_a_bit,
|
|
||||||
wait_a_bit,
|
|
||||||
wait_a_bit,
|
|
||||||
wait_a_bit,
|
|
||||||
wait_a_bit,
|
|
||||||
function()
|
|
||||||
if todo == 0 then
|
|
||||||
assert(not had_error, "Some error occurred, see above")
|
|
||||||
return true
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
})
|
end
|
||||||
|
|
||||||
|
local err = spawn.with_line_callback(
|
||||||
|
{ os.getenv("build_dir") .. "/test-gravity" },
|
||||||
|
{
|
||||||
|
exit = function(what, code)
|
||||||
|
assert(what == "exit", what)
|
||||||
|
assert(code == 0, "Exit code was " .. code)
|
||||||
|
had_exit = true
|
||||||
|
check_done()
|
||||||
|
end,
|
||||||
|
stderr = function(line)
|
||||||
|
had_error = true
|
||||||
|
print("Read on stderr: " .. line)
|
||||||
|
end,
|
||||||
|
stdout = function(line)
|
||||||
|
if line == "SUCCESS" then
|
||||||
|
had_success = true
|
||||||
|
check_done()
|
||||||
|
elseif line:sub(1, 5) ~= "LOG: " then
|
||||||
|
had_error = true
|
||||||
|
print("Read on stdout: " .. line)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
})
|
||||||
|
|
||||||
|
assert(type(err) ~= "string", err)
|
||||||
|
runner.run_direct()
|
||||||
|
|
||||||
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
|
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
|
||||||
|
|
Loading…
Reference in New Issue