| 1 | package store_test |
| 2 | |
| 3 | import ( |
| 4 | "path/filepath" |
| 5 | "testing" |
| 6 | |
| 7 | "amadan.net/oficina/sheets/internal/sheets/seal" |
| 8 | "amadan.net/oficina/sheets/internal/sheets/sealtest" |
| 9 | "amadan.net/oficina/sheets/internal/sheets/store" |
| 10 | ) |
| 11 | |
| 12 | // The handle is the busiest writer in the app: every edit goes through |
| 13 | // Set, which seals an input, a recalculated cache and an event payload |
| 14 | // in one call. This is the most valuable place to run the plaintext |
| 15 | // gate, per the task brief — it exercises the real write path Set takes, |
| 16 | // not a synthetic insert standing in for it. |
| 17 | // |
| 18 | // This test builds its own db (rather than reusing seeded()) so it keeps |
| 19 | // the file path in scope for the gate — seeded()'s signature is pinned to |
| 20 | // the brief's own TestStaleCacheIsRecomputedOnOpen snippet and does not |
| 21 | // return one. |
| 22 | func TestSetDoesNotLeakPlaintext(t *testing.T) { |
| 23 | dir := t.TempDir() |
| 24 | dbPath := filepath.Join(dir, "test.db") |
| 25 | db := openTestDB(t, dbPath) |
| 26 | s, err := seal.New(make32()) |
| 27 | if err != nil { |
| 28 | t.Fatal(err) |
| 29 | } |
| 30 | |
| 31 | const gateTabID, gateRow, gateCol uint64 = 1, 1, 1 |
| 32 | if err := db.Create(&store.Tab{ID: gateTabID, SheetID: 1}).Error; err != nil { |
| 33 | t.Fatalf("seed tab: %v", err) |
| 34 | } |
| 35 | if err := db.Create(&store.Row{ID: gateRow, TabID: gateTabID, Position: 0}).Error; err != nil { |
| 36 | t.Fatalf("seed row: %v", err) |
| 37 | } |
| 38 | if err := db.Create(&store.Col{ID: gateCol, TabID: gateTabID, Position: 0}).Error; err != nil { |
| 39 | t.Fatalf("seed col: %v", err) |
| 40 | } |
| 41 | |
| 42 | h, err := store.Open(db, s, gateTabID) |
| 43 | if err != nil { |
| 44 | t.Fatalf("Open: %v", err) |
| 45 | } |
| 46 | // sealtest.Canaries are strings AssertNoPlaintext greps the raw file |
| 47 | // for; seeding one through Set — as a literal cell input, the shape |
| 48 | // user content actually takes — is what proves the real write path |
| 49 | // seals it, rather than a stand-in insert bypassing it. |
| 50 | if err := h.Set(gateRow, gateCol, string(sealtest.Canaries[0]), actor); err != nil { |
| 51 | t.Fatalf("Set: %v", err) |
| 52 | } |
| 53 | h.Release() |
| 54 | |
| 55 | checkpoint(t, db) |
| 56 | sealtest.AssertNoPlaintext(t, dbPath) |
| 57 | } |
| 58 | |