oficina / docs Public

Clone
git clone https://amadan.net/oficina/docs

Plain git — no account needed to clone.

Download

Download this file

1package docs
2
3import (
4 "bytes"
5 "context"
6 "encoding/base64"
7 "errors"
8 "os"
9 "path/filepath"
10 "testing"
11
12 "amadan.net/rastrillo/rastrillo/db"
13)
14
15func TestContentMaintenanceRequiresExpectedKeyBeforeOpeningDatabase(t *testing.T) {
16 path := filepath.Join(t.TempDir(), "missing.db")
17 encoded := base64.StdEncoding.EncodeToString(bytes.Repeat([]byte{62}, 32))
18 c, err := newContentCipher(encoded, "production")
19 if err != nil {
20 t.Fatal(err)
21 }
22 for _, fingerprint := range []string{"", "incorrect"} {
23 err := MaintainContent(context.Background(), ContentMaintenanceConfig{DBPath: path, ContentKey: encoded, ExpectedFingerprint: fingerprint})
24 if !errors.Is(err, errContentKey) {
25 t.Fatalf("fingerprint %q: %v", fingerprint, err)
26 }
27 }
28 err = MaintainContent(context.Background(), ContentMaintenanceConfig{DBPath: path, ContentKey: encoded, ExpectedFingerprint: c.fingerprint})
29 if !errors.Is(err, os.ErrNotExist) {
30 t.Fatalf("missing database: %v", err)
31 }
32 if _, err := os.Stat(path); !errors.Is(err, os.ErrNotExist) {
33 t.Fatalf("maintenance created missing database: %v", err)
34 }
35}
36
37func TestContentMaintenancePreservesContentInRestoredCopy(t *testing.T) {
38 ctx := context.Background()
39 path := filepath.Join(t.TempDir(), "source.db")
40 app, err := New(Config{Env: "development", DBPath: path})
41 if err != nil {
42 t.Fatal(err)
43 }
44 doc, err := app.Store().Create(ctx, app.TestPerson(t, "owner@example.com"), "Restore")
45 if err != nil {
46 app.Close()
47 t.Fatal(err)
48 }
49 if _, err := app.Store().ApplyUpdate(ctx, doc, app.TestActorFor(t, doc), validUpdate(t)); err != nil {
50 app.Close()
51 t.Fatal(err)
52 }
53 if err := app.Close(); err != nil {
54 t.Fatal(err)
55 }
56 encoded := base64.StdEncoding.EncodeToString(bytes.Repeat([]byte{63}, 32))
57 c, err := newContentCipher(encoded, "production")
58 if err != nil {
59 t.Fatal(err)
60 }
61 cfg := ContentMaintenanceConfig{DBPath: path, ContentKey: encoded, ExpectedFingerprint: c.fingerprint, Scrub: true}
62 if err := MaintainContent(ctx, cfg); err != nil {
63 t.Fatal(err)
64 }
65 snapshot, err := os.ReadFile(path)
66 if err != nil {
67 t.Fatal(err)
68 }
69 restoredPath := filepath.Join(t.TempDir(), "restored.db")
70 if err := os.WriteFile(restoredPath, snapshot, 0600); err != nil {
71 t.Fatal(err)
72 }
73 cfg.DBPath = restoredPath
74 if err := MaintainContent(ctx, cfg); err != nil {
75 t.Fatalf("restored maintenance: %v", err)
76 }
77 d, err := db.Open(restoredPath, nil)
78 if err != nil {
79 t.Fatal(err)
80 }
81 defer d.Close()
82 state, err := readContentSealing(ctx, d.G, c)
83 if err != nil || state == nil || !state.Scrubbed {
84 t.Fatalf("restored state: %#v, %v", state, err)
85 }
86 var row DocUpdate
87 if err := d.G.Where("doc_id = ?", doc.ID).First(&row).Error; err != nil {
88 t.Fatal(err)
89 }
90 if err := c.openUpdate(doc.GUID, &row); err != nil {
91 t.Fatal(err)
92 }
93 if !bytes.Equal(row.UpdateBin, validUpdate(t)) {
94 t.Fatal("restored document changed")
95 }
96}
97