111 lines
4.9 KiB
Lua
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)
|