Monorepo for Tangled
tangled.org
1package db
2
3import (
4 "context"
5 "path/filepath"
6 "testing"
7
8 "github.com/bluesky-social/indigo/atproto/syntax"
9)
10
11func newTestDB(t *testing.T) *DB {
12 t.Helper()
13 d, err := Make(context.Background(), filepath.Join(t.TempDir(), "spindle.db"))
14 if err != nil {
15 t.Fatalf("Make: %v", err)
16 }
17 t.Cleanup(func() { d.Close() })
18 return d
19}
20
21func TestCollapseRepoSiblings_DeletesStaleNullCreatedAtWithDifferentRkey(t *testing.T) {
22 d := newTestDB(t)
23 owner := syntax.DID("did:plc:akshay")
24 repoDid := syntax.DID("did:plc:boltless")
25
26 if _, err := d.Exec(`insert into repos (knot, owner, rkey, repo_did, created_at) values
27 ('k', ?, 'stale-bogus-rkey', ?, null),
28 ('k', ?, 'fresh-pds-rkey', ?, '2024-06-01T00:00:00Z')`,
29 owner.String(), repoDid.String(),
30 owner.String(), repoDid.String()); err != nil {
31 t.Fatalf("seed: %v", err)
32 }
33
34 n, err := d.CollapseRepoSiblings(owner, repoDid)
35 if err != nil {
36 t.Fatalf("CollapseRepoSiblings: %v", err)
37 }
38 if n != 1 {
39 t.Errorf("expected 1 stale row deleted, got %d", n)
40 }
41
42 var rkey string
43 if err := d.QueryRow(`select rkey from repos where owner = ? and repo_did = ?`,
44 owner.String(), repoDid.String()).Scan(&rkey); err != nil {
45 t.Fatalf("query: %v", err)
46 }
47 if rkey != "fresh-pds-rkey" {
48 t.Errorf("expected fresh row preserved, got rkey=%q", rkey)
49 }
50}
51
52func TestCollapseRepoSiblings_KeepsNullCreatedAtWhenAlone(t *testing.T) {
53 d := newTestDB(t)
54 owner := syntax.DID("did:plc:akshay")
55 repoDid := syntax.DID("did:plc:boltless")
56
57 if _, err := d.Exec(`insert into repos (knot, owner, rkey, repo_did, created_at) values
58 ('k', ?, 'sole-row', ?, null)`,
59 owner.String(), repoDid.String()); err != nil {
60 t.Fatalf("seed: %v", err)
61 }
62
63 n, err := d.CollapseRepoSiblings(owner, repoDid)
64 if err != nil {
65 t.Fatalf("CollapseRepoSiblings: %v", err)
66 }
67 if n != 0 {
68 t.Errorf("expected 0 deletions when only NULL row exists, got %d", n)
69 }
70
71 var count int
72 if err := d.QueryRow(`select count(*) from repos where owner = ?`, owner.String()).Scan(&count); err != nil {
73 t.Fatalf("count: %v", err)
74 }
75 if count != 1 {
76 t.Errorf("sole NULL row should survive, got %d remaining", count)
77 }
78}
79
80func TestCollapseRepoSiblings_OlderTimestampLoses(t *testing.T) {
81 d := newTestDB(t)
82 owner := syntax.DID("did:plc:akshay")
83 repoDid := syntax.DID("did:plc:boltless")
84
85 if _, err := d.Exec(`insert into repos (knot, owner, rkey, repo_did, created_at) values
86 ('k', ?, 'older-rkey', ?, '2024-01-01T00:00:00Z'),
87 ('k', ?, 'newer-rkey', ?, '2024-06-01T00:00:00Z')`,
88 owner.String(), repoDid.String(),
89 owner.String(), repoDid.String()); err != nil {
90 t.Fatalf("seed: %v", err)
91 }
92
93 n, err := d.CollapseRepoSiblings(owner, repoDid)
94 if err != nil {
95 t.Fatalf("CollapseRepoSiblings: %v", err)
96 }
97 if n != 1 {
98 t.Errorf("expected older row collapsed, got %d", n)
99 }
100
101 var rkey string
102 if err := d.QueryRow(`select rkey from repos where owner = ? and repo_did = ?`,
103 owner.String(), repoDid.String()).Scan(&rkey); err != nil {
104 t.Fatalf("query: %v", err)
105 }
106 if rkey != "newer-rkey" {
107 t.Errorf("expected newer row preserved, got rkey=%q", rkey)
108 }
109}
110
111func TestCollapseRepoSiblings_KeepsNullRowWithMatchingRkey(t *testing.T) {
112 d := newTestDB(t)
113 owner := syntax.DID("did:plc:akshay")
114 repoDid := syntax.DID("did:plc:boltless")
115
116 if _, err := d.Exec(`insert into repos (knot, owner, rkey, repo_did, created_at) values
117 ('k', ?, 'matched-rkey', ?, null)`,
118 owner.String(), repoDid.String()); err != nil {
119 t.Fatalf("seed: %v", err)
120 }
121
122 if err := d.AddRepo(Repo{
123 Knot: "k",
124 Owner: owner,
125 Rkey: "matched-rkey",
126 RepoDid: repoDid,
127 CreatedAt: "2024-06-01T00:00:00Z",
128 }); err != nil {
129 t.Fatalf("AddRepo upsert: %v", err)
130 }
131
132 if _, err := d.CollapseRepoSiblings(owner, repoDid); err != nil {
133 t.Fatalf("CollapseRepoSiblings: %v", err)
134 }
135
136 var count int
137 if err := d.QueryRow(`select count(*) from repos where owner = ?`, owner.String()).Scan(&count); err != nil {
138 t.Fatalf("count: %v", err)
139 }
140 if count != 1 {
141 t.Errorf("upserted row should be the single survivor, got %d", count)
142 }
143}