e2e/rangediff_test.go

32a5f76e5b270097b63a5bba9a43557cf50ad63d
gitbay/e2e/rangediff_test.go history · blame · raw

125 lines · 4723 bytes

  1package e2e
  2
  3import (
  4	"encoding/json"
  5	"os"
  6	"path/filepath"
  7	"strings"
  8	"testing"
  9)
 10
 11// TestMRRangeDiff is #111's last stage: a push stales every review and
 12// nothing said what had changed between the two heads. A plain diff of
 13// the heads cannot answer that — it shows the whole branch again.
 14func TestMRRangeDiff(t *testing.T) {
 15	t.Parallel()
 16	inst := startInstance(t)
 17	key := inst.newKey(t, "alice")
 18	inst.admin(t, "admin", "user", "create", "alice", "--key", key+".pub")
 19	if _, errOut, code := inst.ssh(t, key, "", "repo", "create", "alice/app"); code != 0 {
 20		t.Fatalf("repo create: %s", errOut)
 21	}
 22	env := inst.gitEnv(key)
 23	work := t.TempDir()
 24	mustGit(t, work, env, "clone", inst.sshURL("alice/app"), "w")
 25	dir := filepath.Join(work, "w")
 26	os.WriteFile(filepath.Join(dir, "a.txt"), []byte("one\n"), 0o644)
 27	mustGit(t, dir, env, "checkout", "-q", "-b", "main")
 28	mustGit(t, dir, env, "add", ".")
 29	mustGit(t, dir, env, "commit", "-q", "-m", "base")
 30	mustGit(t, dir, env, "push", "-q", "origin", "main")
 31
 32	mustGit(t, dir, env, "checkout", "-q", "-b", "feat")
 33	os.WriteFile(filepath.Join(dir, "b.txt"), []byte("alpha\nbeta\ngamma\n"), 0o644)
 34	mustGit(t, dir, env, "add", ".")
 35	mustGit(t, dir, env, "commit", "-q", "-m", "add b")
 36	mustGit(t, dir, env, "push", "-q", "origin", "feat")
 37	if _, errOut, code := inst.ssh(t, key, "", "mr", "create", "alice/app",
 38		"--source", "feat", "--target", "main", "--title", "'add b'"); code != 0 {
 39		t.Fatalf("mr create: %s", errOut)
 40	}
 41
 42	// One revision: nothing to compare, and saying so is not a failure.
 43	out, errOut, code := inst.ssh(t, key, "", "mr", "range-diff", "alice/app", "1")
 44	if code != 0 || !strings.Contains(errOut, "one revision") {
 45		t.Fatalf("single-revision range-diff: exit %d, %s, %s", code, errOut, out)
 46	}
 47
 48	// Amend and force-push: the same commit with one line changed, which
 49	// is what addressing review feedback looks like. A diff of the two
 50	// heads cannot describe this — it shows the whole branch again.
 51	os.WriteFile(filepath.Join(dir, "b.txt"), []byte("alpha\nbeta revised\ngamma\n"), 0o644)
 52	mustGit(t, dir, env, "add", ".")
 53	mustGit(t, dir, env, "commit", "-q", "--amend", "--no-edit")
 54	mustGit(t, dir, env, "push", "-q", "--force", "origin", "feat")
 55
 56	revs := revisions(t, inst, key)
 57	if len(revs) != 2 {
 58		t.Fatalf("revisions = %d, want 2 after a force-push: %+v", len(revs), revs)
 59	}
 60	if !revs[1].Current {
 61		t.Fatalf("the newest revision is not marked current: %+v", revs)
 62	}
 63
 64	out, errOut, code = inst.ssh(t, key, "", "mr", "range-diff", "alice/app", "1")
 65	if code != 0 {
 66		t.Fatalf("range-diff: %s", errOut)
 67	}
 68	// The two versions of the one commit are paired — "1: <old> ! 1:
 69	// <new>" — and the interdiff shows the one line that moved, not the
 70	// whole branch.
 71	if !strings.Contains(out, "add b") {
 72		t.Fatalf("range-diff does not mention the commit:\n%s", out)
 73	}
 74	if !strings.Contains(out, "!") {
 75		t.Fatalf("range-diff did not pair the amended commit:\n%s", out)
 76	}
 77	if !strings.Contains(out, "beta revised") {
 78		t.Fatalf("range-diff does not show the changed line:\n%s", out)
 79	}
 80	// One commit on each side, paired: a plain diff of the two heads
 81	// would instead show b.txt created from nothing all over again.
 82	if strings.Count(out, "add b") != 1 {
 83		t.Fatalf("range-diff lists the commit more than once:\n%s", out)
 84	}
 85
 86	// Naming revisions explicitly, and refusing one that is not a
 87	// revision of this merge request.
 88	if _, _, code := inst.ssh(t, key, "", "mr", "range-diff", "alice/app", "1",
 89		"--from", revs[0].SHA, "--to", revs[1].SHA); code != 0 {
 90		t.Fatal("explicit --from/--to failed")
 91	}
 92	if _, errOut, code := inst.ssh(t, key, "", "mr", "range-diff", "alice/app", "1",
 93		"--from", "0123456789ab"); code != 3 || !strings.Contains(errOut, "not a revision") {
 94		t.Fatalf("unknown revision: exit %d, %s", code, errOut)
 95	}
 96	if _, _, code := inst.ssh(t, key, "", "mr", "range-diff", "alice/app", "1",
 97		"--from", revs[1].SHA, "--to", revs[1].SHA); code != 2 {
 98		t.Fatal("comparing a revision with itself was accepted")
 99	}
100
101	// A push that changes nothing does not add a revision.
102	mustGit(t, dir, env, "push", "-q", "--force", "origin", "feat")
103	if got := revisions(t, inst, key); len(got) != 2 {
104		t.Fatalf("a no-op push added a revision: %d", len(got))
105	}
106}
107
108type revision struct {
109	N       int    `json:"n"`
110	SHA     string `json:"sha"`
111	Current bool   `json:"current"`
112}
113
114func revisions(t *testing.T, inst *instance, key string) []revision {
115	t.Helper()
116	out, errOut, code := inst.ssh(t, key, "", "mr", "revisions", "alice/app", "1", "--json")
117	if code != 0 {
118		t.Fatalf("mr revisions: %s", errOut)
119	}
120	var env struct {
121		Data []revision `json:"data"`
122	}
123	json.Unmarshal([]byte(out), &env)
124	return env.Data
125}