package e2e import ( "bytes" "context" "encoding/json" "net/http" "os/exec" "strings" "testing" "github.com/barerepo/server/internal/token" ) // Chapter 25 budgets any page with no diff at 15kb, and a build log is the thing that can break it. func TestALongBuildLogDoesNotBreakTheRunPage(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") sha := strings.TrimSpace(run(t, work, "git", "rev-parse", "HEAD")) jobID, runnerToken := jobOn(t, in, "john", "john/johnbot", sha) // A build that says a lot, which is what a real one does when it fails. var log strings.Builder for i := 0; i < 4000; i++ { log.WriteString("go: downloading example.com/some/module v1.2.3\n") } log.WriteString("store/db.go:14:2: cannot find module providing package\n") body, err := json.Marshal(map[string]any{ "token": runnerToken, "job_id": jobID, "chunk": log.String(), }) if err != nil { t.Fatal(err) } resp, err := http.Post(in.http.URL+"/runner/log", "application/json", bytes.NewReader(body)) if err != nil { t.Fatal(err) } resp.Body.Close() finish(t, in, runnerToken, jobID, 1) code, _, page := get(t, in.http.URL+"/john/johnbot/run/"+sha) if code != http.StatusOK { t.Fatalf("the run page answered %d", code) } if len(page) > 15<<10 { t.Errorf("the run page sent %dkb, over chapter 25's 15kb", len(page)>>10) } // The end of a log is where the failure is, so that is the end that stays. if !strings.Contains(page, "cannot find module providing package") { t.Error("the page cut off the line the reader came for") } if !strings.Contains(page, "the whole log") { t.Error("the page does not offer the rest of the log it cut") } } // jobOn queues and takes a job for one real commit, which is what the run page can then find. func jobOn(t *testing.T, in *instance, account, repo, sha string) (int64, string) { t.Helper() ctx := context.Background() runnerToken, tok, err := in.db.CreateToken(ctx, token.Runner, account, repo, "a runner") if err != nil { t.Fatal(err) } runner, err := in.db.AttachRunner(ctx, tok.ID, repo, "uproar.local", "linux", "amd64", nil) if err != nil { t.Fatal(err) } if _, err := in.db.QueueJob(ctx, repo, "refs/heads/master", sha, "go build", ""); err != nil { t.Fatal(err) } job, err := in.db.TakeJob(ctx, repo, *runner) if err != nil || job == nil { t.Fatalf("the runner could not take the job: %v", err) } return job.ID, runnerToken }