Files
gen1recomp/tests/engine/game3_capabilities_test.lua
bryanthaboi d920f7acdb clean up
2026-09-22 17:05:12 -04:00

159 lines
6.5 KiB
Lua

package.path = "./?.lua;./?/init.lua;" .. package.path
local T = require("tests.harness")
local check, eq = T.check, T.eq
local GameVersion = require("src.core.GameVersion")
local Capabilities = require("src.core.game3.capabilities")
local FireredProfile = require("src.core.game3.profiles.firered")
local prevVersion = GameVersion.get()
for name, value in pairs(Capabilities.NAMES) do
check(value == true, "NAMES." .. name .. " is a legal flag")
end
local function subset(inner, outer, label)
for key in pairs(inner) do
check(outer[key] ~= nil, label .. " carries " .. key)
end
end
for key in pairs(Capabilities.CORE) do
check(Capabilities.NAMES[key] ~= nil, "CORE flag " .. key .. " is legal")
check(Capabilities.FRLG[key] ~= nil, "CORE flag " .. key .. " is in FRLG")
check(Capabilities.RSE[key] ~= nil, "CORE flag " .. key .. " is in RSE")
end
subset(Capabilities.FRLG, Capabilities.NAMES, "FRLG")
subset(Capabilities.RSE, Capabilities.NAMES, "RSE")
for key in pairs(Capabilities.FRLG) do
check(Capabilities.RSE[key] == nil or Capabilities.CORE[key] ~= nil,
"FRLG-only flag " .. key .. " is not shared with RSE")
end
GameVersion.set("firered")
local row = FireredProfile
local okAudit, problems = Capabilities.audit(row.capabilities)
check(okAudit, "the FireRed capability row audits clean"
.. (okAudit and "" or (": " .. table.concat(problems, "; "))))
for key in pairs(Capabilities.FRLG) do
check(row.capabilities[key] == true, "FireRed row enables FRLG flag " .. key)
end
for _, rseOnly in ipairs({ "contests", "secretBase", "matchCall", "pokeNav", "battleTower" }) do
check(row.capabilities[rseOnly] == nil, "FireRed row leaves RSE flag " .. rseOnly .. " unset")
end
local function fileExists(rel)
local f = io.open(rel, "r")
if f then f:close() return true end
return false
end
local function modulePath(value)
if value:sub(1, 4) == "src." then return (value:gsub("%.", "/") .. ".lua") end
return "src/core/game3/scripting/" .. value .. ".lua"
end
for id, feature in pairs(Capabilities.FEATURES) do
check(Capabilities.NAMES[feature.cap] ~= nil, id .. " maps to a legal flag")
check(type(feature.label) == "string" and #feature.label > 0, id .. " has a label")
local repo, rel = feature.source:match("^(%w+)/(.+)$")
check(repo ~= nil and rel ~= nil, id .. " cites a pret repo + path")
check(type(feature.counterpart) == "string" and #feature.counterpart > 0,
id .. " records the counterpart check")
for _, field in ipairs({ "core", "ui", "data", "natives" }) do
local value = feature[field]
if value then
check(fileExists(modulePath(value)), id .. "." .. field .. " exists: " .. modulePath(value))
end
end
if feature.extractor then
check(fileExists("src/import/gba/" .. feature.extractor .. ".lua"),
id .. ".extractor exists: src/import/gba/" .. feature.extractor .. ".lua")
end
end
for _, id in ipairs({ "fame_checker", "teachy_tv", "vs_seeker", "trainer_tower", "seagallop" }) do
check(Capabilities.FEATURES[id] ~= nil, "feature registered: " .. id)
check(Capabilities.FRLG[Capabilities.FEATURES[id].cap] == true,
"feature is in the FRLG set: " .. id)
end
local repoCloned = {}
do
for _, feature in pairs(Capabilities.FEATURES) do
local repo, rel = feature.source:match("^(%w+)/(.+)$")
if repo and not repoCloned[repo] then
repoCloned[repo] = fileExists("../" .. repo .. "/Makefile")
or fileExists("../" .. repo .. "/README.md")
end
if repo and repoCloned[repo] then
check(fileExists("../" .. repo .. "/" .. rel),
"pret source exists for " .. feature.cap .. ": " .. feature.source)
end
end
end
eq(Capabilities.has({ version = "firered" }, "fameChecker"), true,
"FireRed has the Fame Checker")
eq(Capabilities.has({ version = "firered" }, "contests"), false,
"FireRed has no contests")
eq(Capabilities.has({ version = "firered" }, "noSuchFlag"), false,
"an unknown flag reads false, not nil")
eq(Capabilities.gate({ version = "firered" }, "fame_checker"), true,
"the Fame Checker gate is open on FireRed")
eq(Capabilities.gate({ version = "firered" }, "tm_case"), true,
"the TM Case gate is open on FireRed")
eq(Capabilities.gate({ version = "firered" }, "contests"), false,
"an unknown feature id reads false (and warns once)")
eq(Capabilities.gate({ version = "ruby" }, "fame_checker"), true,
"an RSE id without a profile fails closed to FireRed")
eq(Capabilities.enabled({ vsSeeker = false }, "vs_seeker"), false,
"enabled() reads the feature's own flag")
eq(Capabilities.enabled(Capabilities.FRLG, "fame_checker"), true,
"enabled() accepts a composed set")
eq(Capabilities.enabled(Capabilities.RSE, "fame_checker"), false,
"the RSE set has no Fame Checker")
eq(Capabilities.enabled(Capabilities.RSE, "contests"), true,
"the RSE set has contests")
eq(Capabilities.enabled(nil, "fame_checker"), false, "nil caps is false")
eq(Capabilities.enabled({}, "no_such_feature"), false, "an unknown feature is false")
eq(Capabilities.nativeFeature("natives_fame"), "fame_checker",
"the Fame Checker natives module maps to its feature")
eq(Capabilities.nativeFeature("natives_tower"), "trainer_tower",
"the tower natives module maps to its feature")
eq(Capabilities.nativeFeature("natives_queries"), nil,
"an unmapped natives module is shared")
eq(Capabilities.nativeAllowed({ version = "firered" }, "natives_fame"), true,
"FireRed allows the Fame Checker natives module")
eq(Capabilities.nativeAllowed({ version = "firered" }, "natives_queries"), true,
"shared natives modules are always allowed")
eq(Capabilities.nativeAllowed({ version = "firered" }, "natives_bogus"), true,
"an unknown module name is treated as shared, not gated")
eq(Capabilities.nativeAllowed({ version = "firered" }, nil), true,
"a nil module name is shared")
local okBad, badProblems = Capabilities.audit({ bogusFlag = true })
check(okBad == false, "audit rejects an unknown flag")
check(#badProblems == 1 and badProblems[1]:find("bogusFlag", 1, true) ~= nil,
"audit names the offending flag")
local okType, typeProblems = Capabilities.audit({ fameChecker = 1 })
check(okType == false, "audit rejects a non-boolean flag")
check(#typeProblems == 1 and typeProblems[1]:find("fameChecker", 1, true) ~= nil,
"audit names the non-boolean flag")
local okNil, nilProblems = Capabilities.audit(nil)
check(okNil == false, "audit rejects a missing table")
eq(#nilProblems, 1, "a missing table is one problem")
check(Capabilities.audit(Capabilities.RSE) == true, "the RSE set audits clean")
Capabilities.reset()
GameVersion.set(prevVersion)
T.finish("game3_capabilities_test")