e2e/robustness_test.go

ff759b53942049b2043e132f5482b442a7265b98
gitbay/e2e/robustness_test.go history · blame · raw

115 lines · 4451 bytes

  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}