DVX_GUI/server/test/testReview.lua
2026-10-15 17:45:45 -05:00

111 lines
4.9 KiB
Lua

-- testReview.lua -- the operator's review tool (tools/review.lua) against the running service: what
-- waits, a fetch and the package tool's word on it, an approval signed with the repository's key
-- that DVX would trust, a rejection, withdrawing and publishing again, and a fetched file changed
-- before signing that the service refuses.
--
-- calog test/testReview.lua -- <base URL> <data folder> <dvxpkg> <admin token> <calog> <singemaster>
local BASE = calogArgs()[1]
local DATA = calogArgs()[2]
local DVXPKG = calogArgs()[3]
local ADMIN = calogArgs()[4]
local CALOG = calogArgs()[5]
local SINGE = calogArgs()[6]
local CONF = DATA .. "/review.conf"
local WORK = DATA .. "/review"
local pass, fail = 0, 0
local function check(name, got, want)
if got == want then pass = pass + 1 else fail = fail + 1
calogPrint("FAIL", name, "got", tostring(got), "want", tostring(want)) end
end
local function call(method, path, body, token, raw)
local headers = { ["Content-Type"] = raw and "application/octet-stream" or "application/json" }
if token then headers["Authorization"] = "Bearer " .. token end
local r = httpRequest({ method = method, url = BASE .. path, headers = headers,
body = raw and body or (body and jsonStringify(body) or nil) })
local parsed = {}
if r.body and r.body ~= "" then
local ok, value = pcall(jsonParse, r.body)
if ok and type(value) == "table" then parsed = value end
end
return r.status, parsed, r
end
local function dpk(name)
return fsRead(DATA .. "/" .. name .. ".dpk")
end
-- The tool: its exit status and what it printed
local function review(...)
local run = procRun({ CALOG, "tools/review.lua", "--", "singe=" .. SINGE, CONF, ... })
return run.exit, (run.stdout or "") .. (run.stderr or "")
end
local function listed(id)
local _, cat = call("GET", "/v1/catalogue")
for _, entry in ipairs(cat.packages or {}) do
if entry.id == id then return entry end
end
return nil
end
fsWrite(CONF, table.concat({ "server = " .. BASE, "token = " .. ADMIN, "dvxpkg = " .. DVXPKG,
"secret = " .. DATA .. "/REPO.SEC", "work = " .. WORK, "" }, "\n"))
check("dice uploaded", (call("POST", "/v1/upload", dpk("dice"), ADMIN, true)), 202)
local exit, said = review("pending")
check("pending runs", exit, 0)
check("and lists dice", said:find("acme.dice 1.0.0", 1, true) ~= nil, true)
exit, said = review("fetch", "acme.dice", "1.0.0")
check("fetch runs", exit, 0)
check("into the work folder", fsExists(WORK .. "/acme.dice-1.0.0.DPK"), true)
check("the bytes uploaded", fsRead(WORK .. "/acme.dice-1.0.0.DPK") == dpk("dice"), true)
check("and shows what it is", said:find("acme.dice", 1, true) ~= nil and said:find("fetched", 1, true) ~= nil, true)
check("nothing listed before approval", listed("acme.dice"), nil)
exit, said = review("approve", "acme.dice", "1.0.0", "looks fine")
check("approve runs", exit, 0)
check("and says so", said:find("approved acme.dice 1.0.0", 1, true) ~= nil, true)
local entry = listed("acme.dice")
check("now listed", entry and entry.version, "1.0.0")
check("signed by the repository", entry and entry.signed, true)
local _, _, sig = call("GET", "/v1/signature/acme.dice/1.0.0")
fsWrite(DATA .. "/dice.SIG", sig.body)
check("DVX would trust it", procRun({ DVXPKG, "verify", DATA .. "/dice.dpk", "-s", DATA .. "/dice.SIG", DATA .. "/REPO.KEY" }).exit, 0)
check("dice 1.1 uploaded", (call("POST", "/v1/upload", dpk("dice2"), ADMIN, true)), 202)
exit, said = review("reject", "acme.dice", "1.1.0", "not yet")
check("reject runs", exit, 0)
local _, versions = call("GET", "/v1/package/acme.dice")
check("still one version", #(versions.versions or {}), 1)
exit = review("reject", "acme.dice", "1.1.0")
check("a rejection needs a note", exit, 2)
exit = review("withdraw", "acme.dice")
check("withdraw runs", exit, 0)
check("not listed", listed("acme.dice"), nil)
exit = review("publish", "acme.dice")
check("publish runs", exit, 0)
check("listed again", listed("acme.dice") ~= nil, true)
-- A fetched file that is not what was uploaded: the signature is of other bytes, and refused
check("dice 1.2 uploaded", (call("POST", "/v1/upload", dpk("dice3"), ADMIN, true)), 202)
check("fetched", (review("fetch", "acme.dice", "1.2.0")), 0)
fsWrite(WORK .. "/acme.dice-1.2.0.DPK", dpk("dice2"))
exit, said = review("approve", "acme.dice", "1.2.0")
check("a changed file's signature is refused", exit, 1)
check("as not the repository's", said:find("repository", 1, true) ~= nil, true)
check("still at 1.0.0", listed("acme.dice").version, "1.0.0")
check("an unknown command", (review("bless", "acme.dice")), 2)
local bad = DATA .. "/badtoken.conf"
fsWrite(bad, (fsRead(CONF):gsub("token = %w+", "token = wrong")))
check("a wrong token", (procRun({ CALOG, "tools/review.lua", "--", "singe=" .. SINGE, bad, "pending" }).exit), 1)
calogPrint(string.format("%d passed, %d failed", pass, fail))
calogExit(fail == 0 and 0 or 1)