Sign in

Search issue titles and bodies, change requests and comments. Private repositories you cannot read are not included.

vole
Clone

Read only, no credentials:

https://rodent.software/vole.git

Write over SSH with a registered key:

git clone ssh://git@rodent.software:2222/vole.git

A free and open-source forge that lives in your Git repo.

Code

396 commit(s) on main

Turn off the disk reserve for test-spawned runners Keenan Nemetz · 10m ago c284cb2c
history blame raw 4.1 KiB
1package index
2
3// The index is derived, which is what lets a schema change be a rebuild instead
4// of a migration chain. These tests hold that promise to its two halves: a file
5// written by an older build is emptied rather than misread, and the version it
6// reports is the one this build writes.
7
8import (
9 "path/filepath"
10 "slices"
11 "testing"
12)
13
14func TestSearchIssuesMatchesTitleNumberAndIDPrefix(t *testing.T) {
15 t.Parallel()
16 s, err := Open(filepath.Join(t.TempDir(), "index.db"))
17 if err != nil {
18 t.Fatal(err)
19 }
20 defer s.Close()
21
22 const (
23 first = "01M5JR2JK29KKMAA1T9MDNTPBP"
24 second = "01M5JR2JK29KKMAA1T9MDNTRBZ"
25 )
26 for _, issue := range []struct {
27 id string
28 title string
29 number int
30 }{
31 {first, "Quick retry on timeout", 42},
32 {second, "Slow parser", 43},
33 } {
34 if _, err := s.db.Exec(
35 `INSERT INTO issues(repo_id, id, title, state, author, created) VALUES('r1',?,?,'open','keenan',0)`,
36 issue.id, issue.title); err != nil {
37 t.Fatal(err)
38 }
39 if _, err := s.db.Exec(
40 `INSERT INTO entity_numbers(repo_id, number, kind, id) VALUES('r1',?,'issue',?)`,
41 issue.number, issue.id); err != nil {
42 t.Fatal(err)
43 }
44 }
45
46 for _, test := range []struct {
47 term string
48 want []string
49 }{
50 {"quick", []string{first}},
51 {"Quick", []string{first}},
52 {"#42", []string{first}},
53 {"42", []string{first}},
54 {"01M5JR2JK29KKMAA1T9MDNTR", []string{second}},
55 {first, []string{first}},
56 {"nothing", nil},
57 {"", nil},
58 } {
59 got, err := s.SearchIssues("r1", test.term, 8)
60 if err != nil {
61 t.Fatalf("SearchIssues(%q): %v", test.term, err)
62 }
63 ids := make([]string, len(got))
64 for i, issue := range got {
65 ids[i] = issue.ID
66 }
67 if !slices.Equal(ids, test.want) {
68 t.Fatalf("SearchIssues(%q) = %v, want %v", test.term, ids, test.want)
69 }
70 }
71}
72
73func TestSchemaVersionDropsRowsFromAnOlderShape(t *testing.T) {
74 t.Parallel()
75 path := filepath.Join(t.TempDir(), "index.db")
76 s, err := Open(path)
77 if err != nil {
78 t.Fatal(err)
79 }
80 // Rows as an older build would have left them, with the file claiming the
81 // previous version — the state every existing instance is in on upgrade.
82 if _, err := s.db.Exec(`
83INSERT INTO repos(id, name, created, issues_sha) VALUES('r1','demo',0,'deadbeef');
84INSERT INTO issues(repo_id, id, title, state, author, created) VALUES('r1','i1','stale','open','keenan',0);
85INSERT INTO issue_labels(repo_id, issue_id, label) VALUES('r1','i1','old');
86INSERT INTO issue_assignees(repo_id, issue_id, assignee) VALUES('r1','i1','wilbur');
87PRAGMA user_version = 1;`); err != nil {
88 t.Fatal(err)
89 }
90 if err := s.Close(); err != nil {
91 t.Fatal(err)
92 }
93
94 // Opening with this build clears the derived rows and leaves the repo with no
95 // indexed issues, so the next read rebuilds it from git instead of serving
96 // rows derived from a shape that no longer exists.
97 s2, err := Open(path)
98 if err != nil {
99 t.Fatal(err)
100 }
101 defer s2.Close()
102
103 for _, q := range []string{
104 `SELECT COUNT(*) FROM issues`,
105 `SELECT COUNT(*) FROM issue_labels`,
106 `SELECT COUNT(*) FROM issue_assignees`,
107 `SELECT COUNT(*) FROM entity_numbers`,
108 } {
109 var n int
110 if err := s2.db.QueryRow(q).Scan(&n); err != nil {
111 t.Fatalf("%s: %v", q, err)
112 }
113 if n != 0 {
114 t.Fatalf("%s = %d, want 0 after a version bump", q, n)
115 }
116 }
117 var sha string
118 if err := s2.db.QueryRow(`SELECT issues_sha FROM repos WHERE id='r1'`).Scan(&sha); err != nil {
119 t.Fatal(err)
120 }
121 if sha != "" {
122 t.Fatalf("issues_sha = %q, want empty so the repo is re-read from git", sha)
123 }
124 var v int
125 if err := s2.db.QueryRow(`PRAGMA user_version`).Scan(&v); err != nil {
126 t.Fatal(err)
127 }
128 if v != schemaVersion {
129 t.Fatalf("user_version = %d, want %d", v, schemaVersion)
130 }
131
132 // A second open is a no-op: the fix is not re-applied every time.
133 if _, err := s2.db.Exec(`INSERT INTO issues(repo_id, id, title, state, author, created) VALUES('r1','i2','fresh','open','keenan',0)`); err != nil {
134 t.Fatal(err)
135 }
136 if err := s2.Close(); err != nil {
137 t.Fatal(err)
138 }
139 s3, err := Open(path)
140 if err != nil {
141 t.Fatal(err)
142 }
143 defer s3.Close()
144 var n int
145 if err := s3.db.QueryRow(`SELECT COUNT(*) FROM issues`).Scan(&n); err != nil {
146 t.Fatal(err)
147 }
148 if n != 1 {
149 t.Fatalf("reopening at the current version dropped rows: %d", n)
150 }
151}
152