package e2e import ( "context" "net/http" "os/exec" "strconv" "testing" "github.com/barerepo/server/internal/token" ) // A HEAD is a GET that stops at the headers, so a page that answers one must answer the other. func TestEveryPageAnswersHeadTheWayItAnswersGet(t *testing.T) { if _, err := exec.LookPath("git"); err != nil { t.Skip("git is not installed") } in := newInstance(t) john := in.account("john") seed(t, in, john, "john", "johnbot") // The two a stranger sees first are the two that were wrong, so they lead the list. paths := []string{ "/signin", "/signup", "/", "/john", "/john/johnbot", "/john/johnbot/files", "/john/johnbot/threads", "/john/johnbot/runs", "/john/johnbot/releases", "/john/johnbot/config", "/john/johnbot/runners", "/search?q=irc", "/john.atom", "/john/johnbot.atom", "/nobody/nothing", } for _, path := range paths { want := status(t, in, http.MethodGet, path) got := status(t, in, http.MethodHead, path) if got != want { t.Errorf("%s answers %d to a reader and %d to a link checker", path, want, got) } } } // status asks once and follows nothing, because a redirect answered is still an answer. func status(t *testing.T, in *instance, method, path string) int { t.Helper() req, err := http.NewRequest(method, in.http.URL+path, nil) if err != nil { t.Fatal(err) } client := &http.Client{CheckRedirect: func(*http.Request, []*http.Request) error { return http.ErrUseLastResponse }} resp, err := client.Do(req) if err != nil { t.Fatal(err) } resp.Body.Close() return resp.StatusCode } // The runner poll takes a job off the queue, so it is the one GET that a HEAD must not reach. func TestAHeadDoesNotSwallowAQueuedBuild(t *testing.T) { if _, err := exec.LookPath("git"); err != nil { t.Skip("git is not installed") } ctx := context.Background() in := newInstance(t) john := in.account("john") seed(t, in, john, "john", "johnbot") secret, tok, err := in.db.CreateToken(ctx, token.Runner, "john", "john/johnbot", "a runner") if err != nil { t.Fatal(err) } runner, err := in.db.AttachRunner(ctx, tok.ID, "john/johnbot", "uproar.local", "linux", "amd64", nil) if err != nil { t.Fatal(err) } if _, err := in.db.QueueJob(ctx, "john/johnbot", "refs/heads/master", "abc", "go build", ""); err != nil { t.Fatal(err) } poll := "/runner/poll?token=" + secret + "&id=" + strconv.FormatInt(runner.ID, 10) if code := status(t, in, http.MethodHead, poll); code == http.StatusOK { t.Errorf("a HEAD to the poll answered %d, and the job it answered with is gone", code) } // The job has to still be there, or a link checker walking the site emptied the queue. job, err := in.db.TakeJob(ctx, "john/johnbot", *runner) if err != nil { t.Fatal(err) } if job == nil { t.Error("a HEAD to the poll took the build, and no runner will ever see it") } }