mirror of
https://github.com/bryanthaboi/gen1recomp.git
synced 2026-08-19 12:15:31 +02:00
121 lines
4.3 KiB
Lua
121 lines
4.3 KiB
Lua
package.path = "./?.lua;./?/init.lua;" .. package.path
|
|
|
|
local T = require("tests.harness")
|
|
love = love or require("tests.love_stub")
|
|
|
|
local SaveData = require("src.core.SaveData")
|
|
local SyncState = require("src.sync.SyncState")
|
|
|
|
local realFS = love.filesystem
|
|
|
|
local function memfs(files)
|
|
return {
|
|
files = files,
|
|
write = function(path, content) files[path] = content return true end,
|
|
read = function(path) return files[path] end,
|
|
remove = function(path) files[path] = nil return true end,
|
|
getInfo = function(path)
|
|
if files[path] then return { type = "file" } end
|
|
return nil
|
|
end,
|
|
}
|
|
end
|
|
|
|
local function fresh()
|
|
local files = {}
|
|
love.filesystem = memfs(files)
|
|
SaveData.resetSlotState()
|
|
return files
|
|
end
|
|
|
|
do
|
|
local opts = SaveData.defaultOptions()
|
|
T.check(type(opts.saveSync) == "table", "defaultOptions carries saveSync")
|
|
T.eq(opts.saveSync.enabled, false, "sync is off until the player sets it up")
|
|
T.check(type(opts.saveSync.revs) == "table", "and starts with no synced revs")
|
|
T.eq(opts.saveSync.account, nil, "and no account")
|
|
|
|
local state = SyncState.defaults()
|
|
T.eq(SyncState.linked(state), false, "a default state is not linked")
|
|
T.eq(state.lastSyncAt, 0, "and has never synced")
|
|
end
|
|
|
|
do
|
|
local dirty = SyncState.sanitize({
|
|
enabled = "yes",
|
|
account = "aa11bb22cc33dd44",
|
|
deviceToken = "tok",
|
|
deviceLabel = "",
|
|
lastSyncAt = 0 / 0,
|
|
code1 = "12345678",
|
|
code2 = "87654321",
|
|
revs = { ["red/aaa"] = 4, [7] = 9, ["red/bad"] = "no" },
|
|
stamps = { ["red/aaa"] = 1700 },
|
|
pendingConflicts = { { key = "red/aaa", version = "red", overlap = true },
|
|
{ nope = true } },
|
|
})
|
|
T.eq(dirty.enabled, false, "a non-boolean enabled reads as off")
|
|
T.eq(dirty.account, "aa11bb22cc33dd44", "the account id survives")
|
|
T.eq(dirty.deviceLabel, nil, "an empty device label is dropped")
|
|
T.eq(dirty.lastSyncAt, 0, "a NaN lastSyncAt is refused")
|
|
T.eq(dirty.code1, nil, "the first account code is never kept")
|
|
T.eq(dirty.code2, nil, "nor the second")
|
|
T.eq(dirty.revs["red/aaa"], 4, "numeric revs survive")
|
|
T.eq(dirty.revs["red/bad"], nil, "a non-numeric rev is dropped")
|
|
T.eq(dirty.revs[7], nil, "a non-string rev key is dropped")
|
|
T.eq(dirty.stamps["red/aaa"], 1700, "the savedAt stamp survives")
|
|
T.eq(#dirty.pendingConflicts, 1, "only well-formed conflicts are kept")
|
|
T.eq(dirty.pendingConflicts[1].overlap, true, "with their overlap flag")
|
|
end
|
|
|
|
do
|
|
local files = fresh()
|
|
local state = SyncState.load()
|
|
T.eq(SyncState.linked(state), false, "a first boot has no linked account")
|
|
|
|
state.account = "aa11bb22cc33dd44"
|
|
state.deviceToken = "feedface"
|
|
state.deviceId = "0a1b2c3d"
|
|
state.deviceLabel = "laptop"
|
|
state.enabled = true
|
|
state.code1 = "12345678"
|
|
SyncState.setRev(state, SyncState.key("red", "abc"), 3, 1700000000)
|
|
SyncState.save(state)
|
|
|
|
T.check(files["options.lua"] ~= nil, "the state lands in options.lua")
|
|
T.eq(files["options.lua"]:find("12345678", 1, true), nil,
|
|
"the account codes are never written to disk")
|
|
|
|
local back = SyncState.load()
|
|
T.eq(SyncState.linked(back), true, "the linked account survives a reload")
|
|
T.eq(back.deviceLabel, "laptop", "and the device label")
|
|
T.eq(back.deviceId, "0a1b2c3d",
|
|
"and the device id the server revokes tokens by")
|
|
T.eq(SyncState.rev(back, "red/abc"), 3, "and the last synced rev")
|
|
T.eq(SyncState.stamp(back, "red/abc"), 1700000000, "and the savedAt stamp")
|
|
T.eq(back.code1, nil, "the code is gone from the reloaded state")
|
|
|
|
local opts = SaveData.loadOptions()
|
|
T.eq(opts.textSpeed, 3, "writing sync state leaves other options alone")
|
|
|
|
SyncState.forget(back, "red/abc")
|
|
T.eq(SyncState.rev(back, "red/abc"), nil, "forget drops the rev")
|
|
T.eq(SyncState.stamp(back, "red/abc"), nil, "and the stamp")
|
|
|
|
SyncState.clear()
|
|
T.eq(SyncState.linked(SyncState.load()), false, "clear unlinks the device")
|
|
end
|
|
|
|
do
|
|
T.eq(SyncState.key("red", "abc"), "red/abc", "keys join version and id")
|
|
T.eq(SyncState.key("red", ""), nil, "an empty playthrough id has no key")
|
|
T.eq(SyncState.key(nil, "abc"), nil, "and neither does a missing version")
|
|
local version, id = SyncState.splitKey("gold/deadbeef")
|
|
T.eq(version, "gold", "splitKey reads the version back")
|
|
T.eq(id, "deadbeef", "and the playthrough id")
|
|
end
|
|
|
|
love.filesystem = realFS
|
|
|
|
T.finish("sync_state")
|