mirror of
https://github.com/bryanthaboi/gen1recomp.git
synced 2026-08-12 08:21:02 +02:00
Make ROM-free test tiers actually run on Windows (#267)
Suite discovery, the extension-point catalog scan, mod test-dir pickup, and the meta-coverage corpus all shelled out to ls/find/test -d, which do not exist in cmd.exe. Every listing came back empty on Windows, so tiers ran 0 suites and still reported ALL TESTS PASSED. Add portable probes to tests/fs_io.lua (same Unix commands on Linux/macOS; dir /b and a shell-free rename-self existence check on Windows) and rewire the four call sites to them. 15/15 engine suites and 2/2 modkit suites now genuinely run and pass on Windows. Fixes #266 Co-authored-by: johnjohto <johnjohto@users.noreply.github.com>
This commit is contained in:
@@ -63,13 +63,17 @@ end
|
||||
-- engine tier, the SDK cases, and any tests a shipped mod carries
|
||||
local function testCorpus()
|
||||
local files, bodies = {}, {}
|
||||
local pipe = io.popen(
|
||||
"ls tests/*.lua tests/engine/*.lua tests/modkit/cases/*.lua mods/*/tests/*.lua 2>/dev/null")
|
||||
if pipe then
|
||||
for line in pipe:lines() do
|
||||
if line ~= "" then files[#files + 1] = line end
|
||||
local FsIo = require("tests.fs_io")
|
||||
local function addLuaFrom(dir)
|
||||
for _, name in ipairs(FsIo.listDir(dir)) do
|
||||
if name:match("%.lua$") then files[#files + 1] = dir .. "/" .. name end
|
||||
end
|
||||
pipe:close()
|
||||
end
|
||||
addLuaFrom("tests")
|
||||
addLuaFrom("tests/engine")
|
||||
addLuaFrom("tests/modkit/cases")
|
||||
for _, mod in ipairs(FsIo.listDir("mods")) do
|
||||
if not mod:find(".", 1, true) then addLuaFrom("mods/" .. mod .. "/tests") end
|
||||
end
|
||||
for _, path in ipairs(files) do
|
||||
bodies[path] = slurp(path) or ""
|
||||
|
||||
+67
-11
@@ -15,6 +15,71 @@ local function quote(path)
|
||||
return "'" .. tostring(path):gsub("'", "'\\''") .. "'"
|
||||
end
|
||||
|
||||
-- The suites also run on Windows checkouts, where cmd has no ls/find/test.
|
||||
-- These probes pick the spelling the host shell understands; anything that
|
||||
-- listed a directory through a bare Unix command silently returned nothing
|
||||
-- there, and a tier built on an empty listing passes vacuously.
|
||||
FsIo.isWindows = package.config:sub(1, 1) == "\\"
|
||||
|
||||
local function shellLines(cmd)
|
||||
local lines = {}
|
||||
local pipe = io.popen(cmd)
|
||||
if not pipe then return lines end
|
||||
for line in pipe:lines() do
|
||||
if line ~= "" then lines[#lines + 1] = line end
|
||||
end
|
||||
pipe:close()
|
||||
return lines
|
||||
end
|
||||
|
||||
-- names directly inside path (files and directories mixed, like ls -1)
|
||||
function FsIo.listDir(path)
|
||||
local cmd
|
||||
if FsIo.isWindows then
|
||||
cmd = 'dir /b "' .. tostring(path) .. '" 2>nul'
|
||||
else
|
||||
cmd = "ls -1 " .. quote(path) .. " 2>/dev/null"
|
||||
end
|
||||
local items = shellLines(cmd)
|
||||
table.sort(items)
|
||||
return items
|
||||
end
|
||||
|
||||
-- every *.lua under dir, recursively, as forward-slash paths
|
||||
function FsIo.luaFilesUnder(dir)
|
||||
local cmd
|
||||
if FsIo.isWindows then
|
||||
cmd = 'dir /b /s "' .. tostring(dir) .. '\\*.lua" 2>nul'
|
||||
else
|
||||
-- -L follows symlinks: a checkout that symlinks src/ (worktrees, the
|
||||
-- ROM-free CI probe) would otherwise scan nothing and hand every gate
|
||||
-- an empty catalog to pass vacuously against
|
||||
cmd = "find -L " .. quote(dir) .. " -name '*.lua' -type f 2>/dev/null"
|
||||
end
|
||||
local files = {}
|
||||
for _, line in ipairs(shellLines(cmd)) do
|
||||
files[#files + 1] = (line:gsub("\\", "/"))
|
||||
end
|
||||
table.sort(files)
|
||||
return files
|
||||
end
|
||||
|
||||
-- existence probe that never shells out on Windows: directories do not
|
||||
-- open() there at all, and rename-self succeeds for anything that exists
|
||||
function FsIo.isDir(path)
|
||||
local handle = io.open(path, "rb")
|
||||
if handle then
|
||||
local probe = handle:read(1)
|
||||
handle:close()
|
||||
if probe ~= nil then return false end
|
||||
if FsIo.isWindows then return false end -- opened but empty: a file
|
||||
elseif FsIo.isWindows then
|
||||
return os.rename(path, path) == true
|
||||
end
|
||||
local ok = os.execute("test -d " .. quote(path))
|
||||
return ok == true or ok == 0
|
||||
end
|
||||
|
||||
function FsIo.new(rootDir)
|
||||
local base = rootDir or "."
|
||||
|
||||
@@ -50,8 +115,7 @@ function FsIo.new(rootDir)
|
||||
-- a directory opens on some libc builds but reads nothing
|
||||
if probe ~= nil then return { type = "file" } end
|
||||
end
|
||||
local ok = os.execute("test -d " .. quote(abs(path)))
|
||||
if ok == true or ok == 0 then return { type = "directory" } end
|
||||
if FsIo.isDir(abs(path)) then return { type = "directory" } end
|
||||
if handle then return { type = "file" } end
|
||||
return nil
|
||||
end
|
||||
@@ -61,15 +125,7 @@ function FsIo.new(rootDir)
|
||||
end
|
||||
|
||||
function fs.getDirectoryItems(path)
|
||||
local items = {}
|
||||
local pipe = io.popen("ls -1 " .. quote(abs(path)) .. " 2>/dev/null")
|
||||
if not pipe then return items end
|
||||
for line in pipe:lines() do
|
||||
if line ~= "" then items[#items + 1] = line end
|
||||
end
|
||||
pipe:close()
|
||||
table.sort(items)
|
||||
return items
|
||||
return FsIo.listDir(abs(path))
|
||||
end
|
||||
|
||||
fs.root = base
|
||||
|
||||
@@ -10,22 +10,12 @@
|
||||
-- call site exists.
|
||||
|
||||
local Schemas = require("src.mods.Schemas")
|
||||
local FsIo = require("tests.fs_io")
|
||||
|
||||
local Catalog = {}
|
||||
|
||||
local function luaFilesUnder(dir)
|
||||
local files = {}
|
||||
-- -L follows symlinks: a checkout that symlinks src/ (worktrees, the
|
||||
-- ROM-free CI probe) would otherwise scan nothing and hand every gate an
|
||||
-- empty catalog to pass vacuously against
|
||||
local pipe = io.popen("find -L " .. dir .. " -name '*.lua' -type f 2>/dev/null")
|
||||
if not pipe then return files end
|
||||
for line in pipe:lines() do
|
||||
if line ~= "" then files[#files + 1] = line end
|
||||
end
|
||||
pipe:close()
|
||||
table.sort(files)
|
||||
return files
|
||||
return FsIo.luaFilesUnder(dir)
|
||||
end
|
||||
|
||||
local function scan(dirs, patterns)
|
||||
|
||||
@@ -11,12 +11,12 @@ local dirs = { "tests/modkit/cases" }
|
||||
|
||||
-- mods ship their own tests (21-testing-and-ci "how mods ship their own
|
||||
-- tests"); pick up every mods/<id>/tests directory that exists
|
||||
local pipe = io.popen("ls -d mods/*/tests 2>/dev/null")
|
||||
if pipe then
|
||||
for line in pipe:lines() do
|
||||
if line ~= "" then dirs[#dirs + 1] = line end
|
||||
local FsIo = require("tests.fs_io")
|
||||
for _, name in ipairs(FsIo.listDir("mods")) do
|
||||
if not name:find(".", 1, true) then
|
||||
local dir = "mods/" .. name .. "/tests"
|
||||
if FsIo.isDir(dir) then dirs[#dirs + 1] = dir end
|
||||
end
|
||||
pipe:close()
|
||||
end
|
||||
|
||||
Runner.main(dirs, "modkit")
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
|
||||
local Runner = {}
|
||||
|
||||
local FsIo = require("tests.fs_io")
|
||||
|
||||
local function interpreter()
|
||||
-- arg[-1] is how the suite was invoked (luajit here, lua5.4 elsewhere)
|
||||
return (arg and arg[-1]) or "luajit"
|
||||
@@ -22,17 +24,13 @@ end
|
||||
|
||||
function Runner.suites(dir)
|
||||
local files = {}
|
||||
local pipe = io.popen(("ls -1 '%s'/*.lua 2>/dev/null"):format(dir))
|
||||
if not pipe then return files end
|
||||
for line in pipe:lines() do
|
||||
local name = line:match("[^/]+$")
|
||||
for _, name in ipairs(FsIo.listDir(dir)) do
|
||||
-- "_" prefixes helpers; facts.lua is the tier's pinned-value table
|
||||
-- (a content_<mod>/facts.lua is data the suites read, not a suite)
|
||||
if name and name:sub(1, 1) ~= "_" and name ~= "facts.lua" then
|
||||
files[#files + 1] = line
|
||||
if name:match("%.lua$") and name:sub(1, 1) ~= "_" and name ~= "facts.lua" then
|
||||
files[#files + 1] = dir .. "/" .. name
|
||||
end
|
||||
end
|
||||
pipe:close()
|
||||
table.sort(files)
|
||||
return files
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user