mirror of
https://git.pumpin.online/funkpower/typikon.git
synced 2026-10-22 18:57:13 +00:00
There is one engine and nine doors into it, and nothing until now checked that the doors agree. CI tested each binding against itself: the Python wheel imported, the C demo compiled, the npm package type-checked. None of that would have caught a field that crosses one boundary wrong, which is the failure this library is most exposed to, because a wrong answer about a fast day looks exactly like a right one. So: twelve days, chosen where the bindings could plausibly differ, and all twenty-two fields compared against what the command line says. The days are Pascha itself, the Nativity on both calendars, a Wednesday of the Great Fast under Byzantine Catholic law and again at the Typikon, a weekday of the Nativity Fast where Greek and Slavic usage part, the one Orthodox church on the Gregorian Paschalion, and a day with no feast. A release now runs what a push runs. It had been gated on cargo test alone, so the C ABI, the Lua binding, the Python parity check and the README examples were checked on the branch that led to a release and not on the release. Neither registry will reuse a version, so the gate belongs before the upload. Writing it found three things. The npm exports map did not expose the wasm by package path, so a bundler asked for typikon/web/typikon_bg.wasm was told no such path exists and had to reach into node_modules; the documented init() call was never affected. The suite could hang instead of fail, because the test web server was backgrounded inside a subshell and killed by job spec, leaving bash in do_wait forever. And pointing XDG_CONFIG_HOME at a path that does not exist isolates typikon and breaks every other program that keeps state under it, a browser included. A surface whose toolchain is missing is named as skipped, and fewer than three surfaces running is a failure rather than a pass, so a container with nothing installed cannot come out green.
60 lines
2.5 KiB
Lua
60 lines
2.5 KiB
Lua
-- The binding under test is the one in examples/lua.
|
|
package.path = (os.getenv("TYPIKON_LUA") or "examples/lua") .. "/?.lua;" .. package.path
|
|
local typikon = require("typikon")
|
|
|
|
-- Minimal JSON writer: the binding hands back Lua tables, and the point is to
|
|
-- compare them with everything else, not to pull in a dependency.
|
|
local function esc(s)
|
|
return '"' .. s:gsub('[%c"\\]', function(c)
|
|
if c == '"' then return '\\"' elseif c == '\\' then return '\\\\' end
|
|
return string.format('\\u%04x', c:byte())
|
|
end) .. '"'
|
|
end
|
|
local function val(v)
|
|
if v == nil then return "null"
|
|
elseif type(v) == "number" then return tostring(math.floor(v))
|
|
elseif type(v) == "table" then
|
|
local parts = {}
|
|
for i = 1, #v do parts[i] = esc(v[i]) end
|
|
return "[" .. table.concat(parts, ",") .. "]"
|
|
else return esc(v) end
|
|
end
|
|
|
|
local probes = {
|
|
{2026,4,12,"moscow",false}, {2026,4,12,"goarch",false}, {2026,1,7,"moscow",false},
|
|
{2025,12,25,"old",false}, {2026,3,4,"ruthenian",false},{2026,3,4,"ruthenian",true},
|
|
{2025,12,9,"old",false}, {2026,2,16,"oca",false}, {2026,8,15,"antiochian",false},
|
|
{2026,9,18,"finnish",false},{2027,5,2,"serbian",false}, {2026,6,28,"constantinople",false},
|
|
}
|
|
|
|
local fields = {
|
|
{"date","iso"}, {"weekday","weekday"}, {"jurisdiction","jurisdiction"},
|
|
{"calendar","calendar"}, {"churchDate","church_date"}, {"season","season"},
|
|
{"cycle","cycle"}, {"feast","feast"}, {"rank","rank"}, {"sign","sign"},
|
|
{"tradition","tradition"}, {"title","title"}, {"fast","fast"},
|
|
{"fastLabel","fast_label"}, {"emoji","emoji"}, {"reason","reason"},
|
|
{"obligation","obligation"}, {"binds","binds"},
|
|
{"commemorations","commemorations"},
|
|
}
|
|
|
|
local out, firstkey = {}, true
|
|
for _, p in ipairs(probes) do
|
|
local jdn = assert(typikon.jdn(p[1], p[2], p[3]))
|
|
local day = assert(typikon.describe(jdn, { jurisdiction = p[4], typikon = p[5] }))
|
|
local parts = {}
|
|
for _, f in ipairs(fields) do
|
|
parts[#parts + 1] = esc(f[1]) .. ":" .. val(day[f[2]])
|
|
end
|
|
local py, pm, pd = typikon.ymd(day.pascha_jdn)
|
|
parts[#parts + 1] = esc("pascha") .. ":" .. esc(string.format("%04d-%02d-%02d", py, pm, pd))
|
|
parts[#parts + 1] = esc("daysToPascha") .. ":" .. tostring(day.days_to_pascha)
|
|
parts[#parts + 1] = esc("julianOffset") .. ":" .. tostring(day.julian_offset)
|
|
local key = string.format("%04d-%02d-%02d|%s|%d", p[1], p[2], p[3], p[4], p[5] and 1 or 0)
|
|
out[#out + 1] = (firstkey and "" or ",") .. esc(key) .. ":{" .. table.concat(parts, ",") .. "}"
|
|
firstkey = false
|
|
end
|
|
|
|
local f = assert(io.open(arg[1], "w"))
|
|
f:write("{" .. table.concat(out) .. "}\n")
|
|
f:close()
|