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

barerepo / server / internal/thread/anchor_test.go
149 lines · 4.5kb · 133728eaa05486504991b230f9d4c7e986b7defc
log files threads runs releases config jump to file t
133728e barerepo 1mo
1
package thread
133728e barerepo 1mo
2
133728e barerepo 1mo
3
import (
133728e barerepo 1mo
4
"context"
133728e barerepo 1mo
5
"os"
133728e barerepo 1mo
6
"os/exec"
133728e barerepo 1mo
7
"path/filepath"
133728e barerepo 1mo
8
"strings"
133728e barerepo 1mo
9
"testing"
133728e barerepo 1mo
10
133728e barerepo 1mo
11
"github.com/barerepo/server/internal/gitx"
133728e barerepo 1mo
12
)
133728e barerepo 1mo
13
133728e barerepo 1mo
14
// anchorRepo commits a file, changes it in a named way, and returns the original blob hash.
133728e barerepo 1mo
15
func anchorRepo(t *testing.T, before, after string) (dir, oldBlob string) {
133728e barerepo 1mo
16
t.Helper()
133728e barerepo 1mo
17
if _, err := gitx.Version(context.Background()); err != nil {
133728e barerepo 1mo
18
t.Skip("git is not installed")
133728e barerepo 1mo
19
}
133728e barerepo 1mo
20
dir = t.TempDir()
133728e barerepo 1mo
21
run := func(args ...string) string {
133728e barerepo 1mo
22
t.Helper()
133728e barerepo 1mo
23
cmd := exec.Command(gitx.Bin, args...)
133728e barerepo 1mo
24
cmd.Dir = dir
133728e barerepo 1mo
25
cmd.Env = append(cmd.Environ(),
133728e barerepo 1mo
26
"GIT_AUTHOR_NAME=m", "GIT_AUTHOR_EMAIL=m@x",
133728e barerepo 1mo
27
"GIT_COMMITTER_NAME=m", "GIT_COMMITTER_EMAIL=m@x")
133728e barerepo 1mo
28
out, err := cmd.CombinedOutput()
133728e barerepo 1mo
29
if err != nil {
133728e barerepo 1mo
30
t.Fatalf("git %v: %v\n%s", args, err, out)
133728e barerepo 1mo
31
}
133728e barerepo 1mo
32
return strings.TrimSpace(string(out))
133728e barerepo 1mo
33
}
133728e barerepo 1mo
34
write := func(body string) {
133728e barerepo 1mo
35
if err := os.WriteFile(filepath.Join(dir, "config.go"), []byte(body), 0o644); err != nil {
133728e barerepo 1mo
36
t.Fatal(err)
133728e barerepo 1mo
37
}
133728e barerepo 1mo
38
}
133728e barerepo 1mo
39
run("init", "-q", "-b", "master")
133728e barerepo 1mo
40
write(before)
133728e barerepo 1mo
41
run("add", "-A")
133728e barerepo 1mo
42
run("commit", "-qm", "before")
133728e barerepo 1mo
43
oldBlob = run("rev-parse", "HEAD:config.go")
133728e barerepo 1mo
44
if after != before {
133728e barerepo 1mo
45
write(after)
133728e barerepo 1mo
46
run("add", "-A")
133728e barerepo 1mo
47
run("commit", "-qm", "after")
133728e barerepo 1mo
48
}
133728e barerepo 1mo
49
return dir, oldBlob
133728e barerepo 1mo
50
}
133728e barerepo 1mo
51
133728e barerepo 1mo
52
// Chapter 43.3's three outcomes, plus 43.5's fourth for when the original is gone.
133728e barerepo 1mo
53
func TestResolve(t *testing.T) {
133728e barerepo 1mo
54
const before = "package main\n\nfunc Load() error {\n\treturn nil\n}\n"
133728e barerepo 1mo
55
133728e barerepo 1mo
56
t.Run("unchanged blob is exact", func(t *testing.T) {
133728e barerepo 1mo
57
dir, blob := anchorRepo(t, before, before)
133728e barerepo 1mo
58
got := Resolve(context.Background(), dir,
133728e barerepo 1mo
59
Anchor{Path: "config.go", Line: 4, Blob: blob}, "HEAD")
133728e barerepo 1mo
60
if got.Placement != Exact || got.Line != 4 {
133728e barerepo 1mo
61
t.Errorf("got %+v, want exact at 4", got)
133728e barerepo 1mo
62
}
133728e barerepo 1mo
63
if got.Excerpt != "\treturn nil" {
133728e barerepo 1mo
64
t.Errorf("excerpt = %q", got.Excerpt)
133728e barerepo 1mo
65
}
133728e barerepo 1mo
66
})
133728e barerepo 1mo
67
133728e barerepo 1mo
68
t.Run("line moved down", func(t *testing.T) {
133728e barerepo 1mo
69
// Two lines added above, so line 4 becomes line 6.
133728e barerepo 1mo
70
after := "package main\n\nimport \"os\"\n\nfunc Load() error {\n\treturn nil\n}\n"
133728e barerepo 1mo
71
dir, blob := anchorRepo(t, before, after)
133728e barerepo 1mo
72
got := Resolve(context.Background(), dir,
133728e barerepo 1mo
73
Anchor{Path: "config.go", Line: 4, Blob: blob}, "HEAD")
133728e barerepo 1mo
74
if got.Placement != Moved || got.Line != 6 {
133728e barerepo 1mo
75
t.Errorf("got %+v, want moved to 6", got)
133728e barerepo 1mo
76
}
133728e barerepo 1mo
77
// The excerpt is what the commenter saw, not what is there now.
133728e barerepo 1mo
78
if got.Excerpt != "\treturn nil" {
133728e barerepo 1mo
79
t.Errorf("excerpt = %q", got.Excerpt)
133728e barerepo 1mo
80
}
133728e barerepo 1mo
81
})
133728e barerepo 1mo
82
133728e barerepo 1mo
83
t.Run("line rewritten is outdated", func(t *testing.T) {
133728e barerepo 1mo
84
after := "package main\n\nfunc Load() error {\n\treturn fmt.Errorf(\"no\")\n}\n"
133728e barerepo 1mo
85
dir, blob := anchorRepo(t, before, after)
133728e barerepo 1mo
86
got := Resolve(context.Background(), dir,
133728e barerepo 1mo
87
Anchor{Path: "config.go", Line: 4, Blob: blob}, "HEAD")
133728e barerepo 1mo
88
if got.Placement != Outdated {
133728e barerepo 1mo
89
t.Errorf("got %+v, want outdated", got)
133728e barerepo 1mo
90
}
133728e barerepo 1mo
91
// Chapter 43.4: never hide an outdated comment, and show the code it referred to.
133728e barerepo 1mo
92
if got.Excerpt != "\treturn nil" {
133728e barerepo 1mo
93
t.Errorf("the original line was lost: %q", got.Excerpt)
133728e barerepo 1mo
94
}
133728e barerepo 1mo
95
})
133728e barerepo 1mo
96
133728e barerepo 1mo
97
t.Run("file deleted is outdated", func(t *testing.T) {
133728e barerepo 1mo
98
dir, blob := anchorRepo(t, before, before)
133728e barerepo 1mo
99
cmd := exec.Command(gitx.Bin, "rm", "-q", "config.go")
133728e barerepo 1mo
100
cmd.Dir = dir
133728e barerepo 1mo
101
cmd.Run()
133728e barerepo 1mo
102
cmd = exec.Command(gitx.Bin, "-c", "user.email=m@x", "-c", "user.name=m", "commit", "-qm", "gone")
133728e barerepo 1mo
103
cmd.Dir = dir
133728e barerepo 1mo
104
cmd.Run()
133728e barerepo 1mo
105
got := Resolve(context.Background(), dir,
133728e barerepo 1mo
106
Anchor{Path: "config.go", Line: 4, Blob: blob}, "HEAD")
133728e barerepo 1mo
107
if got.Placement != Outdated {
133728e barerepo 1mo
108
t.Errorf("got %+v, want outdated", got)
133728e barerepo 1mo
109
}
133728e barerepo 1mo
110
if got.Excerpt != "\treturn nil" {
133728e barerepo 1mo
111
t.Errorf("the original line was lost: %q", got.Excerpt)
133728e barerepo 1mo
112
}
133728e barerepo 1mo
113
})
133728e barerepo 1mo
114
133728e barerepo 1mo
115
t.Run("blob gone degrades to lost", func(t *testing.T) {
133728e barerepo 1mo
116
dir, _ := anchorRepo(t, before, before)
133728e barerepo 1mo
117
got := Resolve(context.Background(), dir,
133728e barerepo 1mo
118
Anchor{Path: "config.go", Line: 4,
133728e barerepo 1mo
119
Blob: "0000000000000000000000000000000000000000"}, "HEAD")
133728e barerepo 1mo
120
if got.Placement != Lost {
133728e barerepo 1mo
121
t.Errorf("got %+v, want lost", got)
133728e barerepo 1mo
122
}
133728e barerepo 1mo
123
})
133728e barerepo 1mo
124
133728e barerepo 1mo
125
t.Run("no blob stored degrades to lost", func(t *testing.T) {
133728e barerepo 1mo
126
dir, _ := anchorRepo(t, before, before)
133728e barerepo 1mo
127
got := Resolve(context.Background(), dir,
133728e barerepo 1mo
128
Anchor{Path: "config.go", Line: 4}, "HEAD")
133728e barerepo 1mo
129
if got.Placement != Lost {
133728e barerepo 1mo
130
t.Errorf("got %+v, want lost", got)
133728e barerepo 1mo
131
}
133728e barerepo 1mo
132
})
133728e barerepo 1mo
133
}
133728e barerepo 1mo
134
133728e barerepo 1mo
135
func TestParseAnchor(t *testing.T) {
133728e barerepo 1mo
136
a, ok := ParseAnchor("config.go:43")
133728e barerepo 1mo
137
if !ok || a.Path != "config.go" || a.Line != 43 {
133728e barerepo 1mo
138
t.Errorf("got %+v %v", a, ok)
133728e barerepo 1mo
139
}
133728e barerepo 1mo
140
if a.String() != "config.go:43" {
133728e barerepo 1mo
141
t.Errorf("String() = %q", a.String())
133728e barerepo 1mo
142
}
133728e barerepo 1mo
143
for _, bad := range []string{"", "config.go", "config.go:0", "config.go:-1",
133728e barerepo 1mo
144
"config.go:x", "../../etc/passwd:1", ":4", "-rf:1"} {
133728e barerepo 1mo
145
if _, ok := ParseAnchor(bad); ok {
133728e barerepo 1mo
146
t.Errorf("ParseAnchor(%q) was accepted", bad)
133728e barerepo 1mo
147
}
133728e barerepo 1mo
148
}
133728e barerepo 1mo
149
}
history · rawbarerepo 0.1.0