e2e/robustness_test.go
115 lines · 4451 bytes
2 symbols in this file
1package e2e
2
3import (
4 "net/http"
5 "net/url"
6 "os"
7 "os/exec"
8 "path/filepath"
9 "strings"
10 "sync"
11 "testing"
12)
13
14// Paths and content outside ASCII go through every read surface: the
15// tree, cat, grep, blame and the web blob page. Nothing in the suite
16// covered a non-ASCII path before (#129).
17func TestNonASCIIPaths(t *testing.T) {
18 t.Parallel()
19 inst := startInstance(t)
20 aliceKey := inst.newKey(t, "alice")
21 inst.admin(t, "admin", "user", "create", "alice", "--key", aliceKey+".pub")
22 if _, errOut, code := inst.ssh(t, aliceKey, "", "repo", "create", "alice/app"); code != 0 {
23 t.Fatalf("repo create: %s", errOut)
24 }
25 work := t.TempDir()
26 env := inst.gitEnv(aliceKey)
27 mustGit(t, work, env, "clone", inst.sshURL("alice/app"), "w")
28 dir := filepath.Join(work, "w")
29 const name = "dokumente/übersicht — ünïcode.txt"
30 os.MkdirAll(filepath.Join(dir, "dokumente"), 0o755)
31 os.WriteFile(filepath.Join(dir, name), []byte("Grüße aus Nürnberg\n日本語の行\n"), 0o644)
32 mustGit(t, dir, env, "-c", "core.quotepath=off", "checkout", "-q", "-b", "main")
33 mustGit(t, dir, env, "add", ".")
34 mustGit(t, dir, env, "commit", "-q", "-m", "ünïcode")
35 mustGit(t, dir, env, "push", "-q", "origin", "main")
36
37 if out, errOut, code := inst.ssh(t, aliceKey, "", "repo", "tree", "alice/app", "dokumente", "--json"); code != 0 || !strings.Contains(out, "übersicht") {
38 t.Fatalf("repo tree: exit %d\n%s%s", code, out, errOut)
39 }
40 // inst.ssh joins arguments into one command line; the name has spaces.
41 quoted := "'" + name + "'"
42 if out, errOut, code := inst.ssh(t, aliceKey, "", "repo", "cat", "alice/app", quoted); code != 0 || !strings.Contains(out, "Nürnberg") {
43 t.Fatalf("repo cat: exit %d\n%s%s", code, out, errOut)
44 }
45 if out, errOut, code := inst.ssh(t, aliceKey, "", "repo", "grep", "alice/app", "日本語"); code != 0 || !strings.Contains(out, "übersicht") {
46 t.Fatalf("repo grep: exit %d\n%s%s", code, out, errOut)
47 }
48 if out, errOut, code := inst.ssh(t, aliceKey, "", "repo", "blame", "alice/app", quoted); code != 0 || !strings.Contains(out, "Nürnberg") {
49 t.Fatalf("repo blame: exit %d\n%s%s", code, out, errOut)
50 }
51 page := inst.base() + "/alice/app/blob/main/" + url.PathEscape("dokumente") + "/" + url.PathEscape("übersicht — ünïcode.txt")
52 resp, err := http.Get(page)
53 if err != nil {
54 t.Fatal(err)
55 }
56 defer resp.Body.Close()
57 if resp.StatusCode != 200 {
58 t.Fatalf("web blob page: %d", resp.StatusCode)
59 }
60}
61
62// Pushes to different branches of one repository at the same time all
63// land: the receive hooks, the post-receive work and the store take
64// them concurrently without losing one (#129).
65func TestConcurrentPushes(t *testing.T) {
66 t.Parallel()
67 inst := startInstance(t)
68 aliceKey := inst.newKey(t, "alice")
69 inst.admin(t, "admin", "user", "create", "alice", "--key", aliceKey+".pub")
70 if _, errOut, code := inst.ssh(t, aliceKey, "", "repo", "create", "alice/app"); code != 0 {
71 t.Fatalf("repo create: %s", errOut)
72 }
73 env := inst.gitEnv(aliceKey)
74 seed := filepath.Join(t.TempDir(), "seed")
75 mustGit(t, t.TempDir(), env, "clone", inst.sshURL("alice/app"), seed)
76 os.WriteFile(filepath.Join(seed, "f.txt"), []byte("x\n"), 0o644)
77 mustGit(t, seed, env, "checkout", "-q", "-b", "main")
78 mustGit(t, seed, env, "add", ".")
79 mustGit(t, seed, env, "commit", "-q", "-m", "base")
80 mustGit(t, seed, env, "push", "-q", "origin", "main")
81
82 const n = 6
83 var wg sync.WaitGroup
84 errs := make([]string, n)
85 for i := 0; i < n; i++ {
86 branch := "b" + string(rune('0'+i))
87 clone := filepath.Join(t.TempDir(), branch)
88 mustGit(t, t.TempDir(), env, "clone", "-q", inst.sshURL("alice/app"), clone)
89 mustGit(t, clone, env, "checkout", "-q", "-b", branch)
90 os.WriteFile(filepath.Join(clone, branch+".txt"), []byte(branch+"\n"), 0o644)
91 mustGit(t, clone, env, "add", ".")
92 mustGit(t, clone, env, "commit", "-q", "-m", branch)
93 wg.Add(1)
94 go func(i int, clone, branch string) {
95 defer wg.Done()
96 cmd := exec.Command("git", "push", "-q", "origin", branch)
97 cmd.Dir, cmd.Env = clone, env
98 if out, err := cmd.CombinedOutput(); err != nil {
99 errs[i] = string(out)
100 }
101 }(i, clone, branch)
102 }
103 wg.Wait()
104 for i, e := range errs {
105 if e != "" {
106 t.Errorf("push %d failed:\n%s", i, e)
107 }
108 }
109 out, _, _ := inst.ssh(t, aliceKey, "", "repo", "refs", "alice/app")
110 for i := 0; i < n; i++ {
111 if !strings.Contains(out, "b"+string(rune('0'+i))) {
112 t.Errorf("branch b%d missing after concurrent pushes:\n%s", i, out)
113 }
114 }
115}