File view with blame information shown in the left gutter beside each line.

barerepo / server / internal/store/move_test.go
162 lines · 5.7kb · master
log files threads runs releases config jump to file t
133728e barerepo 1mo
1
package store
133728e barerepo 1mo
2
133728e barerepo 1mo
3
import (
133728e barerepo 1mo
4
"context"
133728e barerepo 1mo
5
"testing"
133728e barerepo 1mo
6
133728e barerepo 1mo
7
"github.com/barerepo/server/internal/token"
133728e barerepo 1mo
8
)
133728e barerepo 1mo
9
133728e barerepo 1mo
10
// A rename or a transfer changes the path every table keys on, so every one of them has to follow.
133728e barerepo 1mo
11
func TestMoveCarriesEverythingKeyedByTheRepository(t *testing.T) {
133728e barerepo 1mo
12
ctx := context.Background()
133728e barerepo 1mo
13
db := open(t)
133728e barerepo 1mo
14
for _, who := range []string{"john", "lisa"} {
133728e barerepo 1mo
15
if _, err := db.CreateAccount(ctx, who, keyFor(who), false); err != nil {
133728e barerepo 1mo
16
t.Fatal(err)
133728e barerepo 1mo
17
}
133728e barerepo 1mo
18
}
133728e barerepo 1mo
19
if _, err := db.ExecContext(ctx,
133728e barerepo 1mo
20
`INSERT INTO repos (owner, name, created_at) VALUES ('john', 'johnbot', 0)`); err != nil {
133728e barerepo 1mo
21
t.Fatal(err)
133728e barerepo 1mo
22
}
133728e barerepo 1mo
23
133728e barerepo 1mo
24
const old, want = "john/johnbot", "lisa/ircbot"
133728e barerepo 1mo
25
_, tok, err := db.CreateToken(ctx, token.Runner, "john", old, "a runner")
133728e barerepo 1mo
26
if err != nil {
133728e barerepo 1mo
27
t.Fatal(err)
133728e barerepo 1mo
28
}
133728e barerepo 1mo
29
if _, err := db.AttachRunner(ctx, tok.ID, old, "uproar.local", "linux", "amd64", nil); err != nil {
133728e barerepo 1mo
30
t.Fatal(err)
133728e barerepo 1mo
31
}
133728e barerepo 1mo
32
if _, err := db.QueueJob(ctx, old, "refs/heads/master", "abc", "go test", ""); err != nil {
133728e barerepo 1mo
33
t.Fatal(err)
133728e barerepo 1mo
34
}
133728e barerepo 1mo
35
if err := db.Record(ctx, Event{Kind: ThreadOpened, Actor: "lisa", Repo: old, Number: 1,
133728e barerepo 1mo
36
Title: "something"}); err != nil {
133728e barerepo 1mo
37
t.Fatal(err)
133728e barerepo 1mo
38
}
133728e barerepo 1mo
39
if err := db.TookPart(ctx, "lisa", old, 1); err != nil {
133728e barerepo 1mo
40
t.Fatal(err)
133728e barerepo 1mo
41
}
133728e barerepo 1mo
42
if err := db.HookFailed(ctx, old, "https://deploy.example/hook", "it went wrong"); err != nil {
133728e barerepo 1mo
43
t.Fatal(err)
133728e barerepo 1mo
44
}
133728e barerepo 1mo
45
if err := db.PutDoc(ctx, Doc{Repo: old, Kind: Code, Path: "a.go", Body: "package main"},
133728e barerepo 1mo
46
true, Readers("john", nil)); err != nil {
133728e barerepo 1mo
47
t.Fatal(err)
133728e barerepo 1mo
48
}
133728e barerepo 1mo
49
133728e barerepo 1mo
50
if err := db.Move(ctx, "john", "johnbot", "lisa", "ircbot"); err != nil {
133728e barerepo 1mo
51
t.Fatal(err)
133728e barerepo 1mo
52
}
133728e barerepo 1mo
53
133728e barerepo 1mo
54
// Every table below is keyed by the path, and a miss in any one of them breaks something.
133728e barerepo 1mo
55
if got, err := db.RunnersOf(ctx, want); err != nil || len(got) != 1 {
133728e barerepo 1mo
56
t.Errorf("the runner did not follow: %d, %v", len(got), err)
133728e barerepo 1mo
57
}
133728e barerepo 1mo
58
if got, err := db.RunnersOf(ctx, old); err != nil || len(got) != 0 {
133728e barerepo 1mo
59
t.Errorf("the runner is still at the old path: %d, %v", len(got), err)
133728e barerepo 1mo
60
}
133728e barerepo 1mo
61
// The token's scope is what a runner is checked against, so it has to move with the repository.
133728e barerepo 1mo
62
var scope string
133728e barerepo 1mo
63
if err := db.QueryRowContext(ctx, `SELECT scope FROM tokens WHERE id = ?`, tok.ID).Scan(&scope); err != nil {
133728e barerepo 1mo
64
t.Fatal(err)
133728e barerepo 1mo
65
}
133728e barerepo 1mo
66
if scope != want {
133728e barerepo 1mo
67
t.Errorf("the runner token is still scoped to %q, so it can never take another job", scope)
133728e barerepo 1mo
68
}
133728e barerepo 1mo
69
if got, err := db.QueuedJobs(ctx, want); err != nil || len(got) != 1 {
133728e barerepo 1mo
70
t.Errorf("the queued job did not follow: %d, %v", len(got), err)
133728e barerepo 1mo
71
}
133728e barerepo 1mo
72
if got, err := db.EventsFor(ctx, want, 10); err != nil || len(got) != 1 {
133728e barerepo 1mo
73
t.Errorf("the events did not follow: %d, %v", len(got), err)
133728e barerepo 1mo
74
}
133728e barerepo 1mo
75
if got, err := db.Inbox(ctx, "lisa", 10); err != nil || len(got) != 1 {
133728e barerepo 1mo
76
t.Errorf("the new owner's inbox lost the thread she took part in: %d, %v", len(got), err)
133728e barerepo 1mo
77
}
133728e barerepo 1mo
78
if got, err := db.HooksOf(ctx, want); err != nil || len(got) != 1 {
133728e barerepo 1mo
79
t.Errorf("the webhook state did not follow: %d, %v", len(got), err)
133728e barerepo 1mo
80
}
133728e barerepo 1mo
81
if got, err := db.FindDocs(ctx, "", "package main", 10); err != nil || len(got) != 1 ||
133728e barerepo 1mo
82
got[0].Repo != want {
133728e barerepo 1mo
83
t.Errorf("the search index did not follow: %v, %v", got, err)
133728e barerepo 1mo
84
}
133728e barerepo 1mo
85
}
133728e barerepo 1mo
86
133728e barerepo 1mo
87
func keyFor(who string) string {
133728e barerepo 1mo
88
if who == "john" {
133728e barerepo 1mo
89
return keyA
133728e barerepo 1mo
90
}
133728e barerepo 1mo
91
return keyB
133728e barerepo 1mo
92
}
133728e barerepo 1mo
93
133728e barerepo 1mo
94
// seedRepo fills one row in every table that keys on a repository, so a move or a delete has work.
133728e barerepo 1mo
95
func seedRepo(t *testing.T, db *DB, owner, name string) int64 {
133728e barerepo 1mo
96
t.Helper()
133728e barerepo 1mo
97
ctx := context.Background()
133728e barerepo 1mo
98
repo := owner + "/" + name
133728e barerepo 1mo
99
if _, err := db.ExecContext(ctx,
133728e barerepo 1mo
100
`INSERT INTO repos (owner, name, created_at) VALUES (?, ?, 0)`, owner, name); err != nil {
133728e barerepo 1mo
101
t.Fatal(err)
133728e barerepo 1mo
102
}
133728e barerepo 1mo
103
_, tok, err := db.CreateToken(ctx, token.Runner, owner, repo, "a runner")
133728e barerepo 1mo
104
if err != nil {
133728e barerepo 1mo
105
t.Fatal(err)
133728e barerepo 1mo
106
}
133728e barerepo 1mo
107
if _, err := db.AttachRunner(ctx, tok.ID, repo, "uproar.local", "linux", "amd64", nil); err != nil {
133728e barerepo 1mo
108
t.Fatal(err)
133728e barerepo 1mo
109
}
133728e barerepo 1mo
110
if _, err := db.QueueJob(ctx, repo, "refs/heads/master", "abc", "go test", ""); err != nil {
133728e barerepo 1mo
111
t.Fatal(err)
133728e barerepo 1mo
112
}
133728e barerepo 1mo
113
if err := db.Record(ctx, Event{Kind: ThreadOpened, Actor: owner, Repo: repo, Number: 1,
133728e barerepo 1mo
114
Title: "something"}); err != nil {
133728e barerepo 1mo
115
t.Fatal(err)
133728e barerepo 1mo
116
}
133728e barerepo 1mo
117
if err := db.TookPart(ctx, owner, repo, 1); err != nil {
133728e barerepo 1mo
118
t.Fatal(err)
133728e barerepo 1mo
119
}
133728e barerepo 1mo
120
if err := db.HookFailed(ctx, repo, "https://deploy.example/hook", "it went wrong"); err != nil {
133728e barerepo 1mo
121
t.Fatal(err)
133728e barerepo 1mo
122
}
133728e barerepo 1mo
123
if err := db.PutDoc(ctx, Doc{Repo: repo, Kind: Code, Path: "a.go", Body: "package main"},
133728e barerepo 1mo
124
true, Readers(owner, nil)); err != nil {
133728e barerepo 1mo
125
t.Fatal(err)
133728e barerepo 1mo
126
}
133728e barerepo 1mo
127
return tok.ID
133728e barerepo 1mo
128
}
133728e barerepo 1mo
129
133728e barerepo 1mo
130
// A deleted repository leaves nothing pointing at it, or a token, a runner and an inbox line outlive it.
133728e barerepo 1mo
131
func TestForgetDropsEverythingKeyedByTheRepository(t *testing.T) {
133728e barerepo 1mo
132
ctx := context.Background()
133728e barerepo 1mo
133
db := open(t)
133728e barerepo 1mo
134
if _, err := db.CreateAccount(ctx, "john", keyA, false); err != nil {
133728e barerepo 1mo
135
t.Fatal(err)
133728e barerepo 1mo
136
}
133728e barerepo 1mo
137
const repo = "john/johnbot"
133728e barerepo 1mo
138
seedRepo(t, db, "john", "johnbot")
133728e barerepo 1mo
139
133728e barerepo 1mo
140
if err := db.Forget(ctx, "john", "johnbot"); err != nil {
133728e barerepo 1mo
141
t.Fatal(err)
133728e barerepo 1mo
142
}
133728e barerepo 1mo
143
133728e barerepo 1mo
144
if got, err := db.RunnersOf(ctx, repo); err != nil || len(got) != 0 {
133728e barerepo 1mo
145
t.Errorf("a runner is still attached to a repository that is gone: %d, %v", len(got), err)
133728e barerepo 1mo
146
}
133728e barerepo 1mo
147
if got, err := db.TokensOf(ctx, "john"); err != nil || len(got) != 0 {
133728e barerepo 1mo
148
t.Errorf("the keys page still lists a token for a repository that is gone: %d, %v", len(got), err)
133728e barerepo 1mo
149
}
133728e barerepo 1mo
150
if got, err := db.QueuedJobs(ctx, repo); err != nil || len(got) != 0 {
133728e barerepo 1mo
151
t.Errorf("a job is still queued for a repository that is gone: %d, %v", len(got), err)
133728e barerepo 1mo
152
}
133728e barerepo 1mo
153
if got, err := db.EventsFor(ctx, repo, 10); err != nil || len(got) != 0 {
133728e barerepo 1mo
154
t.Errorf("the inbox still links to a repository that is gone: %d, %v", len(got), err)
133728e barerepo 1mo
155
}
133728e barerepo 1mo
156
if got, err := db.HooksOf(ctx, repo); err != nil || len(got) != 0 {
133728e barerepo 1mo
157
t.Errorf("webhook state outlived its repository: %d, %v", len(got), err)
133728e barerepo 1mo
158
}
133728e barerepo 1mo
159
if got, err := db.FindDocs(ctx, "", "package main", 10); err != nil || len(got) != 0 {
133728e barerepo 1mo
160
t.Errorf("search still finds a repository that is gone: %v, %v", got, err)
133728e barerepo 1mo
161
}
133728e barerepo 1mo
162
}
history · rawbarerepo 0.1.0