package e2e import ( "fmt" "os/exec" "strings" "testing" ) // Chapter 20.2: LFS off is not enough without a size limit, and the message must name the file. func TestAnOversizedBlobIsRejectedByName(t *testing.T) { if _, err := exec.LookPath("git"); err != nil { t.Skip("git is not installed") } in := newInstance(t) john := in.account("john") work := seed(t, in, john, "john", "johnbot") setLimits(t, in, "\n[limits]\nmax_blob_mb = 1\n") big := strings.Repeat("video frame padding, not source code\n", 60000) write(t, work, "demo.mov", big) write(t, work, "notes.txt", "small and fine\n") run(t, work, "git", "add", "-A") run(t, work, "git", "commit", "-qm", "add a video") out, err := try(t, work, "git", "push", in.url(john, "/john/johnbot"), "master") if err == nil { t.Fatalf("a 2mb blob was accepted against a 1mb limit:\n%s", out) } if !strings.Contains(out, "demo.mov") { t.Errorf("the rejection does not name the file, so the user has to hunt:\n%s", out) } if !strings.Contains(out, "the limit is 1mb") { t.Errorf("the rejection does not say what the limit is:\n%s", out) } if !strings.Contains(out, "object storage") { t.Errorf("chapter 20.4 says to tell the user where large files belong:\n%s", out) } if strings.Contains(out, "notes.txt") { t.Errorf("the rejection blames a file that is under the limit:\n%s", out) } // The push is all or nothing, so nothing landed. if _, _, body := get(t, in.http.URL+"/john/johnbot"); strings.Contains(body, "add a video") { t.Error("the rejected commit is on the log anyway") } } // A push under the limit must not pay for the check with a rejection. func TestASmallPushIsNotAffectedByTheBlobLimit(t *testing.T) { if _, err := exec.LookPath("git"); err != nil { t.Skip("git is not installed") } in := newInstance(t) john := in.account("john") work := seed(t, in, john, "john", "johnbot") setLimits(t, in, "\n[limits]\nmax_blob_mb = 1\n") write(t, work, "small.go", "package main\n\nfunc main() {}\n") run(t, work, "git", "add", "-A") run(t, work, "git", "commit", "-qm", "a small change") run(t, work, "git", "push", "-q", in.url(john, "/john/johnbot"), "master") if _, _, body := get(t, in.http.URL+"/john/johnbot"); !strings.Contains(body, "a small change") { t.Error("a push under the limit did not land") } } // Chapter 20.2 bounds the whole push as well as one file in it, and the two are one pass of git. func TestAPushOverTheWholeLimitIsRejected(t *testing.T) { if _, err := exec.LookPath("git"); err != nil { t.Skip("git is not installed") } in := newInstance(t) john := in.account("john") work := seed(t, in, john, "john", "johnbot") setLimits(t, in, "\n[limits]\nmax_blob_mb = 4\nmax_push_mb = 1\n") // Three files, each under the blob limit, together over the push limit. for i := 0; i < 3; i++ { write(t, work, fmt.Sprintf("part%d.bin", i), strings.Repeat(fmt.Sprintf("chunk %d padding padding padding\n", i), 15000)) } run(t, work, "git", "add", "-A") run(t, work, "git", "commit", "-qm", "a first import") out, err := try(t, work, "git", "push", in.url(john, "/john/johnbot"), "master") if err == nil { t.Fatalf("a push over the whole limit was accepted:\n%s", out) } if strings.Contains(out, "part0.bin") { t.Errorf("the whole push was refused by naming one file, which is the other limit:\n%s", out) } if !strings.Contains(out, "the limit is 1mb") { t.Errorf("the rejection does not say what the limit is:\n%s", out) } if !strings.Contains(out, "max_push_mb") { t.Errorf("the rejection does not say which setting to raise:\n%s", out) } }