mirror of
https://github.com/Refactorio/RedMew.git
synced 2025-03-17 21:08:08 +02:00
module startup/teardown hooks
This commit is contained in:
parent
a1908b93d5
commit
df47b5aa02
@ -8,6 +8,20 @@ local config = global.config.landfill_remover
|
||||
Declare.module(
|
||||
'landfill remover',
|
||||
function()
|
||||
Declare.module_startup(
|
||||
function()
|
||||
game.print('landfill remover startup')
|
||||
error('landfill remover startup')
|
||||
end
|
||||
)
|
||||
|
||||
Declare.module_teardown(
|
||||
function()
|
||||
game.print('landfill remover teardown')
|
||||
error('landfill remover teardown')
|
||||
end
|
||||
)
|
||||
|
||||
Declare.test(
|
||||
'can remove landfill',
|
||||
function()
|
||||
|
@ -15,6 +15,7 @@ local function init_inner(module, depth)
|
||||
count = count + 1
|
||||
tests[#tests + 1] = {
|
||||
name = name,
|
||||
module = module,
|
||||
func = func,
|
||||
steps = nil,
|
||||
current_step = nil,
|
||||
@ -46,38 +47,100 @@ function Public.get_root_modules()
|
||||
return ModuleStore.root_module
|
||||
end
|
||||
|
||||
local function prepare_pre_module_hooks(module, runnables)
|
||||
local startup_func = module.startup_func
|
||||
if startup_func then
|
||||
runnables[#runnables + 1] = {
|
||||
is_hook = true,
|
||||
name = 'startup',
|
||||
module = module,
|
||||
func = startup_func,
|
||||
steps = Steps.new(),
|
||||
current_step = 0,
|
||||
error = nil
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
local function build_pre_module_hooks(module, runnables)
|
||||
if module == nil then
|
||||
return
|
||||
end
|
||||
|
||||
build_pre_module_hooks(module.parent, runnables)
|
||||
prepare_pre_module_hooks(module, runnables)
|
||||
end
|
||||
|
||||
local function prepare_post_module_hooks(module, runnables)
|
||||
local teardown_func = module.teardown_func
|
||||
if teardown_func then
|
||||
runnables[#runnables + 1] = {
|
||||
is_hook = true,
|
||||
name = 'teardown',
|
||||
module = module,
|
||||
func = teardown_func,
|
||||
steps = Steps.new(),
|
||||
current_step = 0,
|
||||
error = nil
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
local function build_post_module_hooks(module, runnables)
|
||||
if module == nil then
|
||||
return
|
||||
end
|
||||
|
||||
prepare_post_module_hooks(module, runnables)
|
||||
build_post_module_hooks(module.parent, runnables)
|
||||
end
|
||||
|
||||
local function prepare_test(test)
|
||||
test.steps = Steps.new()
|
||||
test.current_step = 0
|
||||
test.passed = nil
|
||||
test.error = nil
|
||||
return test
|
||||
end
|
||||
|
||||
local function prepare_module(module, tests)
|
||||
local function prepare_module(module, runnables)
|
||||
module.passed = nil
|
||||
prepare_pre_module_hooks(module, runnables)
|
||||
|
||||
for _, test in pairs(module.tests) do
|
||||
prepare_test(test)
|
||||
tests[#tests + 1] = test
|
||||
runnables[#runnables + 1] = test
|
||||
end
|
||||
|
||||
for _, child in pairs(module.children) do
|
||||
prepare_module(child, tests)
|
||||
prepare_module(child, runnables)
|
||||
end
|
||||
|
||||
prepare_post_module_hooks(module, runnables)
|
||||
end
|
||||
|
||||
function Public.build_test_for_run(test)
|
||||
Public.init()
|
||||
prepare_test(test)
|
||||
return test
|
||||
|
||||
local runnables = {}
|
||||
|
||||
build_pre_module_hooks(test.module, runnables)
|
||||
runnables[#runnables + 1] = prepare_test(test)
|
||||
build_post_module_hooks(test.module, runnables)
|
||||
|
||||
return runnables
|
||||
end
|
||||
|
||||
function Public.build_module_for_run(module)
|
||||
Public.init()
|
||||
|
||||
local tests = {}
|
||||
prepare_module(module, tests)
|
||||
return tests
|
||||
local runnables = {}
|
||||
|
||||
build_pre_module_hooks(module.parent, runnables)
|
||||
prepare_module(module, runnables)
|
||||
build_post_module_hooks(module.parent, runnables)
|
||||
|
||||
return runnables
|
||||
end
|
||||
|
||||
return Public
|
||||
|
@ -4,5 +4,7 @@ local Public = {}
|
||||
|
||||
Public.module = ModuleStore.module
|
||||
Public.test = ModuleStore.test
|
||||
Public.module_startup = ModuleStore.module_startup
|
||||
Public.module_teardown = ModuleStore.module_teardown
|
||||
|
||||
return Public
|
||||
|
@ -3,7 +3,16 @@ local Public = {}
|
||||
local function new_module(module_name)
|
||||
return {
|
||||
name = module_name,
|
||||
parent = nil,
|
||||
children = {},
|
||||
startup_func = nil,
|
||||
startup_steps = nil,
|
||||
startup_current_step = nil,
|
||||
startup_error = nil,
|
||||
teardown_func = nil,
|
||||
teardown_steps = nil,
|
||||
teardown_current_step = nil,
|
||||
teardown_error = nil,
|
||||
test_funcs = {},
|
||||
tests = nil,
|
||||
is_open = true,
|
||||
@ -25,6 +34,7 @@ local function add_module(module_name, module_func, parent)
|
||||
if not module then
|
||||
module = new_module(module_name)
|
||||
parent_children[module_name] = module
|
||||
module.parent = parent_module
|
||||
end
|
||||
|
||||
parent_module = module
|
||||
@ -75,4 +85,36 @@ function Public.test(test_name, test_func)
|
||||
test_funcs[test_name] = test_func
|
||||
end
|
||||
|
||||
function Public.module_startup(startup_func)
|
||||
if type(startup_func) ~= 'function' then
|
||||
error('startup_func must be of type function.')
|
||||
end
|
||||
|
||||
if parent_module == nil then
|
||||
error('root module can not have startup_func.')
|
||||
end
|
||||
|
||||
if parent_module.startup_func ~= nil then
|
||||
error('startup_func can not be declared twice for the same module.')
|
||||
end
|
||||
|
||||
parent_module.startup_func = startup_func
|
||||
end
|
||||
|
||||
function Public.module_teardown(teardown_func)
|
||||
if type(teardown_func) ~= 'function' then
|
||||
error('teardown_func must be of type function.')
|
||||
end
|
||||
|
||||
if parent_module == nil then
|
||||
error('root module can not have teardown_func.')
|
||||
end
|
||||
|
||||
if parent_module.teardown_func ~= nil then
|
||||
error('teardown_func can not be declared twice for the same module.')
|
||||
end
|
||||
|
||||
parent_module.teardown_func = teardown_func
|
||||
end
|
||||
|
||||
return Public
|
||||
|
@ -12,6 +12,8 @@ Public.events = {
|
||||
tests_run_finished = Event.generate_event_name('test_run_finished')
|
||||
}
|
||||
|
||||
local run_tests_token
|
||||
|
||||
local function print_summary(count, fail_count)
|
||||
local pass_count = count - fail_count
|
||||
game.print(table.concat {pass_count, ' of ', count, ' tests passed.'})
|
||||
@ -61,6 +63,55 @@ local function print_success(test_name)
|
||||
game.print(table.concat {"Passed - '", test_name, "'"}, {g = 1})
|
||||
end
|
||||
|
||||
local function print_hook_error(hook)
|
||||
game.print(table.concat {'Failed ', hook.name, " hook -':", tostring(hook.error)}, {r = 1})
|
||||
end
|
||||
|
||||
local function record_hook_error_in_module(hook)
|
||||
if hook.name == 'startup' then
|
||||
hook.module.startup_error = hook.error
|
||||
elseif hook.name == 'teardown' then
|
||||
hook.module.teardown_error = hook.error
|
||||
end
|
||||
end
|
||||
|
||||
local function run_hook(hook)
|
||||
local steps = hook.steps
|
||||
local current_step = hook.current_step
|
||||
local func
|
||||
if current_step == 0 then
|
||||
func = hook.func
|
||||
else
|
||||
func = steps[current_step].func
|
||||
end
|
||||
local success, return_value = pcall(func, steps)
|
||||
|
||||
if not success then
|
||||
hook.error = return_value
|
||||
print_hook_error(hook)
|
||||
record_hook_error_in_module(hook)
|
||||
return false
|
||||
end
|
||||
|
||||
if current_step == #steps then
|
||||
return true
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
local function do_hook(hook, data)
|
||||
local hook_success = run_hook(hook)
|
||||
if hook_success == nil then
|
||||
hook.current_step = hook.current_step + 1
|
||||
else
|
||||
data.index = data.index + 1
|
||||
end
|
||||
|
||||
Task.set_timeout_in_ticks(1, run_tests_token, data)
|
||||
return
|
||||
end
|
||||
|
||||
local function run_test(test)
|
||||
local steps = test.steps
|
||||
local current_step = test.current_step
|
||||
@ -88,29 +139,20 @@ local function run_test(test)
|
||||
return nil
|
||||
end
|
||||
|
||||
local run_tests_token
|
||||
local function run_tests(data)
|
||||
local index = data.index
|
||||
|
||||
local test = data.tests[index]
|
||||
if test == nil then
|
||||
finish_test_run(data)
|
||||
return
|
||||
end
|
||||
|
||||
local function do_test(test, data)
|
||||
local success = run_test(test)
|
||||
|
||||
if success == false then
|
||||
data.count = data.count + 1
|
||||
data.fail_count = data.fail_count + 1
|
||||
data.index = index + 1
|
||||
data.index = data.index + 1
|
||||
Task.set_timeout_in_ticks(1, run_tests_token, data)
|
||||
return
|
||||
end
|
||||
|
||||
if success == true then
|
||||
data.count = data.count + 1
|
||||
data.index = index + 1
|
||||
data.index = data.index + 1
|
||||
Task.set_timeout_in_ticks(1, run_tests_token, data)
|
||||
return
|
||||
end
|
||||
@ -121,20 +163,37 @@ local function run_tests(data)
|
||||
Task.set_timeout_in_ticks(step.delay or 1, run_tests_token, data)
|
||||
end
|
||||
|
||||
local function run_tests(data)
|
||||
local index = data.index
|
||||
local runnable = data.runnables[index]
|
||||
|
||||
if runnable == nil then
|
||||
finish_test_run(data)
|
||||
return
|
||||
end
|
||||
|
||||
if runnable.is_hook then
|
||||
do_hook(runnable, data)
|
||||
return
|
||||
end
|
||||
|
||||
do_test(runnable, data)
|
||||
end
|
||||
|
||||
run_tests_token = Token.register(run_tests)
|
||||
|
||||
local function run(tests)
|
||||
run_tests({tests = tests, index = 1, count = 0, fail_count = 0})
|
||||
local function run(runnables)
|
||||
run_tests({runnables = runnables, index = 1, count = 0, fail_count = 0})
|
||||
end
|
||||
|
||||
function Public.run_module(module)
|
||||
local tests = Builder.build_module_for_run(module or ModuleStore.root_module)
|
||||
run(tests)
|
||||
local runnables = Builder.build_module_for_run(module or ModuleStore.root_module)
|
||||
run(runnables)
|
||||
end
|
||||
|
||||
function Public.run_test(test)
|
||||
Builder.build_test_for_run(test)
|
||||
run({test})
|
||||
local runnables = Builder.build_test_for_run(test)
|
||||
run(runnables)
|
||||
end
|
||||
|
||||
return Public
|
||||
|
@ -23,6 +23,15 @@ local error_test_box_name = Gui.uid_name()
|
||||
local selected_modules = {}
|
||||
local selected_tests = {}
|
||||
|
||||
local function get_module_state(module)
|
||||
local passed = module.passed
|
||||
if passed == false or module.startup_error or module.teardown_error then
|
||||
return false
|
||||
end
|
||||
|
||||
return passed
|
||||
end
|
||||
|
||||
local function set_selected_style(style, selected)
|
||||
if selected then
|
||||
style.font_color = Color.orange
|
||||
@ -77,7 +86,7 @@ local function draw_tests_module(container, module)
|
||||
local is_selected = selected_modules[module]
|
||||
set_selected_style(label_style, is_selected)
|
||||
if not is_selected then
|
||||
set_passed_style(label_style, module.passed)
|
||||
set_passed_style(label_style, get_module_state(module))
|
||||
end
|
||||
|
||||
Gui.set_data(label, {module = module, container = container})
|
||||
@ -221,7 +230,22 @@ Gui.on_click(
|
||||
end
|
||||
|
||||
local error_text_box = get_error_text_box(event.player)
|
||||
error_text_box.text = ''
|
||||
if is_selected then
|
||||
local errors = {}
|
||||
if module.startup_error then
|
||||
errors[#errors + 1] = 'startup error: '
|
||||
errors[#errors + 1] = module.startup_error
|
||||
errors[#errors + 1] = '\n\n'
|
||||
end
|
||||
if module.teardown_error then
|
||||
errors[#errors + 1] = 'teardown error: '
|
||||
errors[#errors + 1] = module.teardown_error
|
||||
end
|
||||
|
||||
error_text_box.text = table.concat(errors)
|
||||
else
|
||||
error_text_box.text = ''
|
||||
end
|
||||
|
||||
redraw_tests(container)
|
||||
end
|
||||
|
Loading…
x
Reference in New Issue
Block a user