diff options
| author | cirakg <cirakg@cirakg.xyz> | 2026-10-19 15:27:37 +0200 |
|---|---|---|
| committer | cirakg <cirakg@cirakg.xyz> | 2026-10-19 15:27:37 +0200 |
| commit | 8ac04a0c2f5cd949a45866f938bd1aa72fbe56e2 (patch) | |
| tree | 80642928d00ab7ee463032db331f41ffcc7ccb11 /test/storage/MigrationTest.mc | |
| parent | dd5d0f68726fe56ee4d199867d414aea81905cc4 (diff) | |
test(storage): cover records, vault, PINs, lockout and migrations
34 new tests (65 per device): round trips per entry type, every tampered
byte, swapped records, the pending queue, the entry cap, a full store at
67 fill levels, the lockout schedule on a fake clock including restarts,
erase, PIN change and reset, auto-lock wiping, and v0 to v1 migration.
Adds an in-memory store with a size limit and storage benchmarks.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Diffstat (limited to 'test/storage/MigrationTest.mc')
| -rw-r--r-- | test/storage/MigrationTest.mc | 69 |
1 files changed, 69 insertions, 0 deletions
diff --git a/test/storage/MigrationTest.mc b/test/storage/MigrationTest.mc new file mode 100644 index 0000000..046ee04 --- /dev/null +++ b/test/storage/MigrationTest.mc @@ -0,0 +1,69 @@ +// Author: cirakg & claude ai +// Summary: Tests for schema migration: fresh store, the v0 fixture to v1, idempotency, newer and damaged metadata. + +import Toybox.Application; +import Toybox.Lang; +import Toybox.Test; + +(:test) +function migrationCreatesFreshMetadata(logger as Test.Logger) as Boolean { + var store = new MemoryBackend(); + var vault = new Vault(store, new FakeTime()); + var meta = store.getValue(Migration.META_KEY) as Dictionary<Application.Storage.KeyType, Application.Storage.ValueType>; + return vault.ids().size() == 0 && (meta["schema"] as Number) == Migration.CURRENT; +} + +// The v0 fixture: entries written in the current record format, listed by +// the old "order" key. After migration they open as before, and running the +// migration again changes nothing. +(:test) +function migrationV0ToV1(logger as Test.Logger) as Boolean { + var store = new MemoryBackend(); + var vault = new Vault(store, new FakeTime()); + var a = vault.add(StorageFixtures.totp("A")); + var b = vault.add(StorageFixtures.code("B")); + store.setValue(Migration.META_KEY, {"order" => [b, a]}); + var migrated = new Vault(store, new FakeTime()); + var ids = migrated.ids(); + var meta = store.getValue(Migration.META_KEY) as Dictionary<Application.Storage.KeyType, Application.Storage.ValueType>; + var opened = migrated.open(a); + opened.wipeSecrets(); + var again = new Vault(store, new FakeTime()); + return ids.size() == 2 && ids[0].equals(b) && ids[1].equals(a) && (meta["schema"] as Number) == 1 + && !meta.hasKey("order") && again.ids().size() == 2 && again.pendingIds().size() == 0; +} + +(:test) +function migrationRefusesNewerAndDamagedMetadata(logger as Test.Logger) as Boolean { + var cases = [ + {"schema" => Migration.CURRENT + 1, "ids" => [], "pending" => []}, + "not a dictionary", + {"schema" => "1", "ids" => [], "pending" => []}, + {"schema" => 1, "ids" => ["K7F2", "K7F2"], "pending" => []}, + {"schema" => 1, "ids" => ["bad"], "pending" => []}, + {"schema" => 1, "ids" => [], "pending" => 5} + ]; + var expected = [VaultError.NEWER_SCHEMA, VaultError.DAMAGED, VaultError.DAMAGED, VaultError.DAMAGED, + VaultError.DAMAGED, VaultError.DAMAGED]; + for (var i = 0; i < cases.size(); i++) { + var store = new MemoryBackend(); + store.setValue(Migration.META_KEY, cases[i] as Application.Storage.ValueType); + var code = 0; + try { + new Vault(store, new FakeTime()); + } catch (err instanceof VaultError) { + code = err.code; + } + if (code != expected[i]) { + logger.error("case " + i + ": got " + code); + return false; + } + // Newer or damaged data is never modified. + var after = store.getValue(Migration.META_KEY); + if (cases[i] instanceof String ? !(after as String).equals(cases[i] as String) : MemoryBackend.sizeOf(after) != MemoryBackend.sizeOf(cases[i] as Application.Storage.ValueType)) { + logger.error("case " + i + ": metadata was modified"); + return false; + } + } + return true; +} |
