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.
|
67dd8854
Keenan Nemetz
17d ago
|
1 | package 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 | ||
| 8 | import ( | |
| 9 | "path/filepath" | |
|
838f282e
Keenan Nemetz
11d ago
|
10 | "slices" |
|
67dd8854
Keenan Nemetz
17d ago
|
11 | "testing" |
| 12 | ) | |
| 13 | ||
|
838f282e
Keenan Nemetz
11d ago
|
14 | func 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 | ||
|
67dd8854
Keenan Nemetz
17d ago
|
73 | func TestSchemaVersionDropsRowsFromAnOlderShape(t *testing.T) { |
|
44530e74
Keenan Nemetz
17d ago
|
74 | t.Parallel() |
|
67dd8854
Keenan Nemetz
17d ago
|
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(` | |
| 83 | INSERT INTO repos(id, name, created, issues_sha) VALUES('r1','demo',0,'deadbeef'); | |
| 84 | INSERT INTO issues(repo_id, id, title, state, author, created) VALUES('r1','i1','stale','open','keenan',0); | |
| 85 | INSERT INTO issue_labels(repo_id, issue_id, label) VALUES('r1','i1','old'); | |
| 86 | INSERT INTO issue_assignees(repo_id, issue_id, assignee) VALUES('r1','i1','wilbur'); | |
| 87 | PRAGMA 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`, | |
|
e05f1c48
Keenan Nemetz
13d ago
|
107 | `SELECT COUNT(*) FROM entity_numbers`, |
|
67dd8854
Keenan Nemetz
17d ago
|
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 | } |