Files
Towbar/tests/persistence-registry-42.20-spec.lua
2026-08-13 18:59:54 -04:00

70 lines
3.7 KiB
Lua

local failures = 0
local function expect(condition, message)
if not condition then
failures = failures + 1
io.stderr:write("FAIL: " .. message .. "\n")
end
end
local globalData = {}
local transmitted = 0
ModData = {
getOrCreate = function(name)
globalData[name] = globalData[name] or {}
return globalData[name]
end,
transmit = function() transmitted = transmitted + 1 end
}
function isServer() return true end
TowBarMod = {}
dofile("42.20/media/lua/shared/TowBar/Persistence.lua")
local function vehicle(sqlId)
return { getSqlId = function() return sqlId end }
end
local towing, towed = vehicle(101), vehicle(202)
expect(TowBarMod.Persistence.savePair("towbar", towing, towed, "trailer", "trailerfront"), "valid SQL pair must save")
local pair = TowBarMod.Persistence.getPair("towbar", towing, towed)
expect(pair and pair.towingSqlId == 101 and pair.towedSqlId == 202, "saved pair must use stable SQL IDs")
expect(pair and pair.attachmentA == "trailer" and pair.attachmentB == "trailerfront", "saved pair must retain attachments")
expect(TowBarMod.Persistence.savePair("wrecker", towing, towed, "towbarWreckerHookHigh", "trailer", 2), "wrecker pair must save")
local wreckerPair = TowBarMod.Persistence.getPair("wrecker", towing, towed)
expect(wreckerPair and wreckerPair.heightLevel == 2, "wrecker pair must retain hook height")
local seen = 0
TowBarMod.Persistence.forEachPair("towbar", function(record)
if record.towingSqlId == 101 and record.towedSqlId == 202 then seen = seen + 1 end
end)
expect(seen == 1, "registry iteration must return the saved pair exactly once")
expect(TowBarMod.Persistence.removePair("towbar", towing, towed), "saved pair must be removable")
expect(TowBarMod.Persistence.getPair("towbar", towing, towed) == nil, "removed pair must stay absent")
expect(transmitted >= 3, "server registry changes must transmit")
expect(not TowBarMod.Persistence.savePair("towbar", vehicle(-1), towed, "trailer", "trailerfront"), "unsaved vehicles must not create unstable records")
local state, action = TowBarMod.Persistence.advanceRecoveryState(nil, 1000, false, false, 2000, 5000)
expect(action == "restore", "first missing-link observation must start one restore")
state, action = TowBarMod.Persistence.advanceRecoveryState(state, 1500, false, false, 2000, 5000)
expect(action == "wait", "an in-flight restore must not be duplicated")
state, action = TowBarMod.Persistence.advanceRecoveryState(state, 3000, true, false, 2000, 5000)
expect(action == "adopt" and state.confirmed, "a restored link must be adopted")
state, action = TowBarMod.Persistence.advanceRecoveryState(state, 3100, false, false, 2000, 5000)
expect(action == "wait", "one missing sample must not destroy an adopted link")
state, action = TowBarMod.Persistence.advanceRecoveryState(state, 8099, false, false, 2000, 5000)
expect(action == "wait", "cleanup must wait for the complete break grace period")
state, action = TowBarMod.Persistence.advanceRecoveryState(state, 8100, false, false, 2000, 5000)
expect(action == "break", "a continuously missing confirmed link must eventually break")
state = TowBarMod.Persistence.notePeerAvailability({ confirmed = true }, false)
expect(state.peerMissing, "an unloaded peer must be remembered")
state = TowBarMod.Persistence.notePeerAvailability(state, true)
expect(state.confirmed == false, "a reloaded pair must re-enter recovery instead of break cleanup")
expect(state.peerMissing == nil, "the peer-missing marker must clear after both vehicles load")
state, action = TowBarMod.Persistence.advanceRecoveryState(state, 9000, false, false, 2000, 5000)
expect(action == "restore", "a reloaded pair must rebuild its constraint")
if failures > 0 then os.exit(1) end
print("PASS: persistent pair registry behavior")