223 lines
4.7 KiB
Lua
223 lines
4.7 KiB
Lua
local _VERSION = "1.1.0"
|
|
|
|
local SUCCESS_MARKER = "__TRAPOS_TEST_OK__"
|
|
local DEFAULT_REPORT_PATH = "/trapos-test-report"
|
|
|
|
local function printUsage()
|
|
print("runtest usage:")
|
|
print()
|
|
print("\t\truntest [--pretty] [--verbose] [--output <path>] [--timeout <seconds>] [--no-timeout] [--shutdown] [test ...]")
|
|
print("\t\truntest --version")
|
|
print("\t\truntest --help")
|
|
end
|
|
|
|
local function parseArgs(args)
|
|
local opts = {
|
|
pretty = false,
|
|
verbose = false,
|
|
shutdown = false,
|
|
outputPath = nil,
|
|
timeout = nil,
|
|
noTimeout = false,
|
|
tests = {},
|
|
}
|
|
|
|
local i = 1
|
|
while i <= #args do
|
|
local arg = args[i]
|
|
if arg == "--version" or arg == "-version" then
|
|
print("runtest v" .. _VERSION)
|
|
return nil
|
|
elseif arg == "--help" or arg == "-help" then
|
|
printUsage()
|
|
return nil
|
|
elseif arg == "--pretty" then
|
|
opts.pretty = true
|
|
elseif arg == "--verbose" or arg == "-v" then
|
|
opts.pretty = true
|
|
opts.verbose = true
|
|
elseif arg == "--output" then
|
|
opts.outputPath = args[i + 1]
|
|
i = i + 1
|
|
elseif arg == "--timeout" then
|
|
opts.timeout = args[i + 1]
|
|
i = i + 1
|
|
elseif arg == "--no-timeout" then
|
|
opts.noTimeout = true
|
|
elseif arg == "--shutdown" then
|
|
opts.shutdown = true
|
|
elseif string.sub(arg, 1, 1) == "-" then
|
|
print("Unknown option: " .. arg)
|
|
printUsage()
|
|
return nil
|
|
else
|
|
opts.tests[#opts.tests + 1] = arg
|
|
end
|
|
i = i + 1
|
|
end
|
|
|
|
return opts
|
|
end
|
|
|
|
local function normalizeTestPath(path)
|
|
if string.sub(path, 1, 1) == "/" then
|
|
return path
|
|
end
|
|
return "/" .. path
|
|
end
|
|
|
|
local function discoverTests()
|
|
local tests = {}
|
|
if not fs.exists("/tests") then
|
|
return tests
|
|
end
|
|
|
|
for _, name in ipairs(fs.list("/tests")) do
|
|
local path = "/tests/" .. name
|
|
if not fs.isDir(path) and string.sub(name, -4) == ".lua" then
|
|
tests[#tests + 1] = path
|
|
end
|
|
end
|
|
table.sort(tests)
|
|
return tests
|
|
end
|
|
|
|
local function readLines(path)
|
|
local lines = {}
|
|
local file = fs.open(path, "r")
|
|
if not file then
|
|
return lines
|
|
end
|
|
|
|
while true do
|
|
local line = file.readLine()
|
|
if line == nil then
|
|
break
|
|
end
|
|
lines[#lines + 1] = line
|
|
end
|
|
file.close()
|
|
return lines
|
|
end
|
|
|
|
local function createEmitter(outputPath)
|
|
local file = nil
|
|
if outputPath then
|
|
file = fs.open(outputPath, "w")
|
|
end
|
|
|
|
local function emit(line)
|
|
if file then
|
|
file.writeLine(line)
|
|
else
|
|
print(line)
|
|
end
|
|
end
|
|
|
|
local function close()
|
|
if file then
|
|
file.close()
|
|
end
|
|
end
|
|
|
|
return emit, close
|
|
end
|
|
|
|
local function renderReport(emit, script, reportLines, ok, verbose, color)
|
|
local green = color and string.char(27) .. "[32m" or ""
|
|
local red = color and string.char(27) .. "[31m" or ""
|
|
local dim = color and string.char(27) .. "[2m" or ""
|
|
local reset = color and string.char(27) .. "[0m" or ""
|
|
local displayScript = string.sub(script, 1, 1) == "/" and string.sub(script, 2) or script
|
|
|
|
emit(displayScript)
|
|
if verbose then
|
|
emit(" " .. dim .. "report: " .. DEFAULT_REPORT_PATH .. reset)
|
|
end
|
|
|
|
if #reportLines == 0 then
|
|
if ok then
|
|
emit(" " .. green .. "[OK]" .. reset .. " script completed")
|
|
else
|
|
emit(" " .. red .. "[KO]" .. reset .. " script failed before reporting a case")
|
|
end
|
|
return
|
|
end
|
|
|
|
for _, line in ipairs(reportLines) do
|
|
if string.sub(line, 1, 3) == "OK " then
|
|
emit(" " .. green .. "[OK]" .. reset .. " " .. string.sub(line, 4))
|
|
elseif string.sub(line, 1, 3) == "KO " then
|
|
emit(" " .. red .. "[KO]" .. reset .. " " .. string.sub(line, 4))
|
|
elseif verbose and string.sub(line, 1, 4) == "LOG " then
|
|
emit(" " .. dim .. "[log] " .. string.sub(line, 5) .. reset)
|
|
end
|
|
end
|
|
end
|
|
|
|
local opts = parseArgs({ ... })
|
|
if not opts then
|
|
return
|
|
end
|
|
|
|
local tests = opts.tests
|
|
if #tests == 0 then
|
|
tests = discoverTests()
|
|
else
|
|
for i, path in ipairs(tests) do
|
|
tests[i] = normalizeTestPath(path)
|
|
end
|
|
end
|
|
|
|
if #tests == 0 then
|
|
print("FAIL: no tests found")
|
|
if opts.shutdown then
|
|
os.shutdown()
|
|
end
|
|
return
|
|
end
|
|
|
|
local emit, closeOutput = createEmitter(opts.outputPath)
|
|
local suiteOk = true
|
|
|
|
for _, script in ipairs(tests) do
|
|
fs.delete(DEFAULT_REPORT_PATH)
|
|
|
|
local scriptArgs = { "--no-marker", "--report", DEFAULT_REPORT_PATH }
|
|
if opts.verbose then
|
|
scriptArgs[#scriptArgs + 1] = "--verbose"
|
|
elseif opts.pretty then
|
|
scriptArgs[#scriptArgs + 1] = "--pretty"
|
|
end
|
|
if opts.noTimeout then
|
|
scriptArgs[#scriptArgs + 1] = "--no-timeout"
|
|
elseif opts.timeout then
|
|
scriptArgs[#scriptArgs + 1] = "--timeout"
|
|
scriptArgs[#scriptArgs + 1] = opts.timeout
|
|
end
|
|
|
|
local ok = shell.run(script, table.unpack(scriptArgs))
|
|
local reportLines = readLines(DEFAULT_REPORT_PATH)
|
|
|
|
if opts.pretty then
|
|
renderReport(emit, script, reportLines, ok, opts.verbose, opts.outputPath ~= nil)
|
|
end
|
|
|
|
if not ok then
|
|
suiteOk = false
|
|
break
|
|
end
|
|
end
|
|
|
|
closeOutput()
|
|
|
|
if suiteOk then
|
|
print(SUCCESS_MARKER)
|
|
else
|
|
print("FAIL: CraftOS integration tests failed")
|
|
end
|
|
|
|
if opts.shutdown then
|
|
os.shutdown()
|
|
end
|