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: fixed init/dt regressions and add os.exit() if UNATTENDED=1 #271

Merged
merged 2 commits into from
Jan 27, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 42 additions & 32 deletions test/main.lua
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
-- Lutro Tester
local availableStates = {
"config/print",
"graphics/print",
"unit/tests",
"joystick/isDown",
Expand All @@ -18,8 +17,7 @@ local joystickButton = 0
local keypressed = ""

local function write_error_traceback(errmsg)
print(errmsg)
print(debug.traceback())
print(debug.traceback(errmsg))
end

local function get_write_error_traceback(noprint)
Expand All @@ -38,33 +36,36 @@ local function create_failed_test(state, msg)
end

function lutro.load()
font = lutro.graphics.newImageFont("graphics/font.png", " abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.,!?-+/")
lutro.graphics.setFont(font)
lutro.graphics.setBackgroundColor(0, 0, 0)
g_font = lutro.graphics.newImageFont("graphics/font.png", " abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.,!?-+/")

-- Initiate all available test states.
-- Do not add states that fail to initialize, to avoid potentially deadlocking errors later on.
for i, state in ipairs(availableStates) do
local success, test = xpcall(
function() return require(state) end,
write_error_traceback
)
if not success then
local msg = ("An error occurred at importing %s"):format(state)
test = create_failed_test(state, msg)
end
if state then
local name = "lutro." .. string.gsub(state, "/", ".")
print (("Test #%d:%s:Import..."):format(i, name))
local success, test = xpcall(
function() return require(state) end,
write_error_traceback
)
if not success then
local msg = ("An error occurred at importing %s"):format(state)
test = create_failed_test(state, msg)
end

test['name'] = "lutro." .. string.gsub(state, "/", ".")
table.insert(states, test)
test.name = name
table.insert(states, test)
end
end

-- Load all states.
for i, state in ipairs(states) do
if states[i] and states[i]['load'] then
local success, test = xpcall(states[i]['load'], write_error_traceback)
print (("Test #%d:%s:Load..."):format(i, state.name))
if state and state.load then
local success, test = xpcall(state.load, write_error_traceback)
if not success then
local msg = ("An error occurred loading %s"):format(state)
states[i] = create_failed_test(state, msg)
local msg = ("An error occurred loading %s"):format(state.name)
states[i] = create_failed_test(availableStates[i], msg)
end
end
end
Expand All @@ -82,16 +83,19 @@ function lutro.update(dt)
end

-- Update the current state.
if states[currentState] and states[currentState]['update'] then
local success, test = xpcall(states[currentState]['update'], get_write_error_traceback(states[currentState].has_update_error), dt)
if states[currentState] and states[currentState].update then
local success, test = xpcall(
function() return states[currentState].update(dt) end,
get_write_error_traceback(states[currentState].has_update_error)
)
if not success then
-- if an error occurs during update, hook the draw routine to add a message to the display.
-- this allows the draw to continue even if update fails, as sometimes draws don't explicitly
-- require updates to work to still report useful results to the developer.
if not states[currentState].has_update_error then
local name = states[currentState]['name']
local origdraw = states[currentState]['draw']
states[currentState]['draw'] = function()
local name = states[currentState].name
local origdraw = states[currentState].draw
states[currentState].draw = function()
local msg = ("An error occurred updating %s"):format(name)
if origdraw then origdraw() end
lutro.graphics.print(msg, 30, 20)
Expand All @@ -108,16 +112,22 @@ function lutro.draw()
return
end

-- Draw the current state.
-- setup graphics defaults. Some tests may override this just for the test's render context.
lutro.graphics.setFont(g_font)
lutro.graphics.setBackgroundColor(30, 0, 30)
lutro.graphics.clear()
local success, test = xpcall(states[currentState]['draw'], get_write_error_traceback(states[currentState].has_draw_error), dt)
if not success then
local msg = ("An error occurred drawing %s"):format(states[currentState]['name'])
lutro.graphics.print(msg, 30, 35)
states[currentState].has_draw_error = true

-- Draw the current active test
if states[currentState].draw then
local success, test = xpcall(states[currentState].draw, get_write_error_traceback(states[currentState].has_draw_error))
if not success then
local msg = ("An error occurred drawing %s"):format(states[currentState].name)
lutro.graphics.print(msg, 30, 35)
states[currentState].has_draw_error = true
end
end

local status = 'Test ' .. currentState .. ' - ' .. states[currentState]['name']
local status = 'Test ' .. currentState .. ' - ' .. states[currentState].name
lutro.graphics.print(status, 10, 5)

-- Testing the keyboard/joystick pressed event.
Expand Down
31 changes: 31 additions & 0 deletions test/window/close.lua
Original file line number Diff line number Diff line change
@@ -1,5 +1,36 @@
local m_is_unattended = false

return {
load = function()
-- When deciding to terminate the process, check for "UNATTENDED" env var. This is preferred over
-- "CI" as the name is more explicit. "CI" is short and likely to have other meanings in casual
-- user/developer environments and should be avoided when making potentially surprising actions
-- like sudden process termination.
local env_ci = os.getenv("UNATTENDED")
if env_ci then
print ("env: UNATTENDED=" .. env_ci)
env_ci = env_ci:lower()
-- consider any value other than something specifically "false" as a truthy value.
if env_ci ~= "false" and env_ci ~= "0" and env_ci ~= "no" then
m_is_unattended = true
end
end
end,

draw = function()
-- test that window.close() operates normally, but also terminate the process via lua to
-- force stop the test even if the libretro frontend is designed or configured to be persistent.
-- This allows using the tests via some automatic PR sweeps.

print ("All Tests Complete. Closing libretro frontend window...")
lutro.window.close()

if m_is_unattended then
print (" > Exiting process due to env UNATTENDED=" .. os.getenv("UNATTENDED"))
os.exit()
else
print ("Note: Libretro frontend may continue running depending on mode/settings.")
print (" > Set UNATTENDED=1 in the process environment to exit the libretro frontend immediately.")
end
end
}
Loading