Files
gen1recomp/tests/engine/pad_hints_bug2452_test.lua

173 lines
5.8 KiB
Lua

package.path = "./?.lua;./?/init.lua;" .. package.path
if not _G.love then _G.love = require("tests.love_stub") end
local T = require("tests.harness")
local check, eq = T.check, T.eq
local PadHints = require("src.core.PadHints")
local function fakeFfi(opts)
opts = opts or {}
local calls = {}
local ffi = {
cdef = function() end,
load = function(name)
calls[#calls + 1] = { "load", name }
if opts.loadThrows then error("no SDL2 here") end
return {
SDL_SetHint = function(name2, value)
calls[#calls + 1] = { "hint", name2, value }
return 1
end,
}
end,
}
return ffi, calls
end
local function env(values)
return function(k) return values[k] end
end
local ffi, calls = fakeFfi()
check(PadHints.apply("Windows", ffi, env({})), "Windows sets the hint")
eq(calls[1] and calls[1][2], "SDL2", "the hint goes through SDL2.dll")
eq(calls[2] and calls[2][2], "SDL_JOYSTICK_ALLOW_BACKGROUND_EVENTS", "hint name")
eq(calls[2] and calls[2][3], "1", "hint value")
for _, name in ipairs({ "OS X", "Linux", "Android", "iOS", "NX" }) do
local f, c = fakeFfi()
check(not PadHints.apply(name, f, env({})), name .. " leaves the hint alone")
eq(#c, 0, name .. " never touches SDL")
end
local f0, c0 = fakeFfi()
check(not PadHints.apply("Windows", f0, env({ POKEPORT_PAD_BACKGROUND = "0" })),
"POKEPORT_PAD_BACKGROUND=0 opts out")
eq(#c0, 0, "and never loads SDL2")
local f1, c1 = fakeFfi()
check(PadHints.apply("Windows", f1, env({ POKEPORT_PAD_BACKGROUND = "1" })),
"POKEPORT_PAD_BACKGROUND=1 still sets it")
eq(#c1, 2, "one load and one hint")
local fThrow = fakeFfi({ loadThrows = true })
local okThrow, result = pcall(PadHints.apply, "Windows", fThrow, env({}))
check(okThrow, "a throwing ffi.load is swallowed")
check(result == false, "and reports the hint as unset")
local savedWindow = love.window
local minimized, focused = false, true
love.window = {
isMinimized = function() return minimized end,
isVisible = function() return not minimized end,
hasFocus = function() return focused end,
}
check(not PadHints.windowMinimized(), "a shown window is not minimized")
minimized = true
check(PadHints.windowMinimized(), "a minimized window is")
minimized = false
focused = false
check(not PadHints.windowMinimized(), "losing focus alone does not count as minimized")
love.window = { isVisible = function() return false end }
check(PadHints.windowMinimized(), "isVisible false is the fallback")
love.window = { isMinimized = function() error("boom") end }
check(not PadHints.windowMinimized(), "a throwing window query reads as shown")
love.window = nil
check(not PadHints.windowMinimized(), "no window module reads as shown")
local Input = require("src.core.Input")
local physical = {}
local pad = {
isGamepad = function() return true end,
isGamepadDown = function(_, button) return physical[button] == true end,
getGamepadAxis = function() return 0 end,
getName = function() return "Xbox Controller" end,
getGUID = function() return "030000005e040000" end,
isConnected = function() return true end,
}
local savedJoystick = love.joystick
love.joystick = {
getJoystickCount = function() return 1 end,
getJoysticks = function() return { pad } end,
}
minimized, focused = false, false
love.window = {
isMinimized = function() return minimized end,
isVisible = function() return not minimized end,
hasFocus = function() return focused end,
}
Input:init()
Input:applyBindings(nil)
Input:reset()
Input:step()
physical.a = true
Input:step()
check(Input:wasPressed("a"), "unfocused but shown: the pad A press still lands")
physical.a = false
Input:step()
check(not Input:isDown("a"), "and releases")
minimized = true
physical.a = true
Input:step()
check(not Input:wasPressed("a"), "minimized: a pad press is dropped")
check(not Input:isDown("a"), "and never held")
physical.a = false
Input:step()
minimized = false
Input:step()
physical.a = true
Input:step()
check(Input:wasPressed("a"), "restored: the next press lands")
physical.a = false
Input:step()
local SwitchDiagnostics = require("src.debug.SwitchDiagnostics")
local savedSystem = love.system
love.system = { getOS = function() return "OS X" end }
SwitchDiagnostics._resetForTests()
love.filesystem.write("switch-debug.txt", "")
focused = false
SwitchDiagnostics.onFocus(false)
SwitchDiagnostics.onJoystickEvent("gamepadpressed", pad, "a")
focused = true
SwitchDiagnostics.onFocus(true)
SwitchDiagnostics.maybeFlush(true, 100)
local log = love.filesystem.read("switch.log") or ""
check(log:find("focus f=false hasFocus=false visible=true", 1, true) ~= nil,
"focus loss lands in the ring with hasFocus and visible")
check(log:find("focus f=true hasFocus=true visible=true", 1, true) ~= nil,
"focus gain lands in the ring")
check(log:find("gamepadpressed button=a guid=030000005e040000 hf=false", 1, true) ~= nil,
"joystick lines carry hf=")
check(not log:find("fg=", 1, true), "fg= is Windows only")
eq(PadHints.foreground("OS X"), nil, "foreground probe is Windows only")
PadHints._resetForTests()
local fgFfi = {
cdef = function() end,
C = {
GetForegroundWindow = function() return {} end,
GetWindowThreadProcessId = function(_, pid) pid[0] = 42 end,
GetCurrentProcessId = function() return 42 end,
},
new = function() return {} end,
}
eq(PadHints.foreground("Windows", fgFfi), "ours", "our foreground window reads ours")
fgFfi.C.GetCurrentProcessId = function() return 7 end
eq(PadHints.foreground("Windows", fgFfi), "other", "another process reads other")
PadHints._resetForTests()
eq(PadHints.foreground("Windows", { cdef = function() end, C = {} }), nil,
"a missing user32 export is swallowed")
love.filesystem.remove("switch-debug.txt")
love.filesystem.remove("switch.log")
SwitchDiagnostics._resetForTests()
PadHints._resetForTests()
love.window, love.joystick, love.system = savedWindow, savedJoystick, savedSystem
T.finish("pad hints bug 2452")