From f304c608e84320eb9be8eb0a8a3dcae05d108c3b Mon Sep 17 00:00:00 2001 From: Uli Schlachter Date: Thu, 28 Feb 2019 09:22:36 +0100 Subject: [PATCH 1/2] 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 --- tests/_runner.lua | 98 ++++++++++++++++++++++++++++------------------- 1 file changed, 58 insertions(+), 40 deletions(-) diff --git a/tests/_runner.lua b/tests/_runner.lua index fc65b67d..532d8fed 100644 --- a/tests/_runner.lua +++ b/tests/_runner.lua @@ -43,7 +43,54 @@ runner.step_kill_clients = function(step) 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. local t = timer({timeout=0}) local wait=20 @@ -52,8 +99,7 @@ runner.run_steps = function(steps, options) options = options or { kill_clients=true, } - assert(not running, "run_steps() was called twice") - running = true + runner.run_direct() if options.kill_clients then -- 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". step_count = step_count + 1 local step_as_string = step..'/'..#steps..' (@'..step_count..')' - if verbose then - io.stderr:write(string.format('Running step %s..\n', step_as_string)) - end + runner.verbose(string.format('Running step %s..\n', step_as_string)) -- Call the current step's function. local success, result = xpcall(function() @@ -75,14 +119,9 @@ runner.run_steps = function(steps, options) end, debug.traceback) if not success then - io.stderr:write('Error: running function for step ' - ..step_as_string..': '..tostring(result)..'!\n') + runner.done('running function for step ' + ..step_as_string..': '..tostring(result)..'!') 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 @@ -92,16 +131,12 @@ runner.run_steps = function(steps, options) wait = 20 t.timeout = 0 t:again() - return + else + -- All steps finished, we are done. + runner.done() end - elseif result == false then - io.stderr:write("Step "..step_as_string.." failed (returned false).\n") - if not runner.quit_awesome_on_error then - io.stderr:write("Keeping awesome open...\n") - return - end - + runner.done("Step "..step_as_string.." failed (returned false).") else -- No result yet, run this step again. wait = wait-1 @@ -109,28 +144,11 @@ runner.run_steps = function(steps, options) t.timeout = 0.1 t:again() else - io.stderr:write("Error: timeout waiting for signal in step " - ..step_as_string..".\n") + runner.done("timeout waiting for signal in step " + ..step_as_string..".") t:stop() end - return 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) t:start() end From a7f47772722a53f0c8e214e1693da46765234d54 Mon Sep 17 00:00:00 2001 From: Uli Schlachter Date: Thu, 28 Feb 2019 09:24:12 +0100 Subject: [PATCH 2/2] test-gravity.lua: Turn into a direct test This commit makes test-gravity.lua use the new infrastructure that was added in the previous commit: Instead of pretending to be a steps-based test, this is now a direct test. This gets rid of all the useless wait_a_bit steps that exist purely to satisfy the steps-based test runner. This commit makes test-gravity.lua about one third shorter. Also, the test might run a tiny bit faster, since there is no more timer that regularly checks if the test is done, but instead it finishes immediately when the external process finishes. Signed-off-by: Uli Schlachter --- tests/test-gravity.lua | 88 +++++++++++++++++------------------------- 1 file changed, 35 insertions(+), 53 deletions(-) diff --git a/tests/test-gravity.lua b/tests/test-gravity.lua index 087a5abc..bf5fcf80 100644 --- a/tests/test-gravity.lua +++ b/tests/test-gravity.lua @@ -3,62 +3,44 @@ local runner = require("_runner") local spawn = require("awful.spawn") -local todo = 2 +local had_exit, had_success local had_error = false -local function wait_a_bit(count) - if todo == 0 or count == 5 then - return true - end -end -runner.run_steps({ - 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 +local function check_done() + if had_exit and had_success then + if had_error then + runner.done("Some error occurred, see above") + else + runner.done() 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