package e2e import ( "fmt" "os" "os/exec" "strings" "testing" ) // setLimits appends a limits block to an instance's config, which the hooks read at push time. func setLimits(t *testing.T, in *instance, block string) { t.Helper() body, err := os.ReadFile(in.cfg.Path) if err != nil { t.Fatal(err) } if err := os.WriteFile(in.cfg.Path, append(body, []byte(block)...), 0o600); err != nil { t.Fatal(err) } } // Chapter 27: rule 5 is an open door, and a cap on open proposals is how it is defended. func TestOpenProposalsAreCappedPerAccountPerRepository(t *testing.T) { if _, err := exec.LookPath("git"); err != nil { t.Skip("git is not installed") } in := newInstance(t) john := in.account("john") mark := in.account("mark") seed(t, in, john, "john", "johnbot") setLimits(t, in, "\n[limits]\nmax_open_proposals = 2\n") mine := clone(t, in, mark, "/john/johnbot") for i := 0; i < 2; i++ { commit(t, mine, fmt.Sprintf("package main\n\nvar v = %d\n", i), fmt.Sprintf("proposal %d", i)) run(t, mine, "git", "push", "-q", in.url(mark, "/john/johnbot"), "HEAD:refs/proposals/new") } commit(t, mine, "package main\n\nvar v = 99\n", "one too many") out, err := try(t, mine, "git", "push", in.url(mark, "/john/johnbot"), "HEAD:refs/proposals/new") if err == nil { t.Fatalf("a third proposal opened against a cap of two:\n%s", out) } if !strings.Contains(out, "you have 2 proposals open") { t.Errorf("the rejection does not say how many are open:\n%s", out) } if !strings.Contains(out, "the limit is 2") { t.Errorf("the rejection does not say what the limit is:\n%s", out) } if !strings.Contains(out, "land or close one") { t.Errorf("the rejection does not say what to do about it:\n%s", out) } // The cap is per account, so somebody else is not held back by mark's two. theirs := clone(t, in, john, "/john/johnbot") commit(t, theirs, "package main\n\nvar w = 1\n", "john proposes") run(t, theirs, "git", "push", "-q", in.url(john, "/john/johnbot"), "HEAD:refs/proposals/new") // Updating a proposal already open is not opening a new one. commit(t, mine, "package main\n\nvar v = 100\n", "revise the second") run(t, mine, "git", "push", "-q", "-f", in.url(mark, "/john/johnbot"), "HEAD:refs/proposals/2") }