package main import ( "flag" "io/ioutil" "net/http" "os" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) var pagesBinary = flag.String("gitlab-pages-binary", "./gitlab-pages", "Path to the gitlab-pages binary") // TODO: Use TCP port 0 everywhere to avoid conflicts. The binary could output // the actual port (and type of listener) for us to read in place of the // hardcoded values below. var listeners = []ListenSpec{ {"http", "127.0.0.1", "37000"}, {"http", "::1", "37000"}, {"https", "127.0.0.1", "37001"}, {"https", "::1", "37001"}, {"proxy", "127.0.0.1", "37002"}, {"proxy", "::1", "37002"}, } var ( httpListener = listeners[0] httpsListener = listeners[2] ) func skipUnlessEnabled(t *testing.T) { if testing.Short() { t.Log("Acceptance tests disabled") t.SkipNow() } if _, err := os.Stat(*pagesBinary); os.IsNotExist(err) { t.Errorf("Couldn't find gitlab-pages binary at %s", *pagesBinary) t.FailNow() } } func TestUnknownHostReturnsNotFound(t *testing.T) { skipUnlessEnabled(t) teardown := RunPagesProcess(t, *pagesBinary, listeners, "", "-redirect-http=false") defer teardown() for _, spec := range listeners { rsp, err := GetPageFromListener(t, spec, "invalid.invalid", "") assert.NoError(t, err) rsp.Body.Close() assert.Equal(t, http.StatusNotFound, rsp.StatusCode) } } func TestKnownHostReturns200(t *testing.T) { skipUnlessEnabled(t) teardown := RunPagesProcess(t, *pagesBinary, listeners, "") defer teardown() for _, spec := range listeners { rsp, err := GetPageFromListener(t, spec, "group.gitlab-example.com", "project/") assert.NoError(t, err) rsp.Body.Close() assert.Equal(t, http.StatusOK, rsp.StatusCode) } } func TestCORSWhenDisabled(t *testing.T) { skipUnlessEnabled(t) teardown := RunPagesProcess(t, *pagesBinary, listeners, "", "-disable-cross-origin-requests") defer teardown() for _, spec := range listeners { for _, method := range []string{"GET", "OPTIONS"} { rsp := doCrossOriginRequest(t, method, method, spec.URL("project/")) assert.Equal(t, http.StatusOK, rsp.StatusCode) assert.Equal(t, "", rsp.Header.Get("Access-Control-Allow-Origin")) assert.Equal(t, "", rsp.Header.Get("Access-Control-Allow-Credentials")) } } } func TestCORSAllowsGET(t *testing.T) { skipUnlessEnabled(t) teardown := RunPagesProcess(t, *pagesBinary, listeners, "") defer teardown() for _, spec := range listeners { for _, method := range []string{"GET", "OPTIONS"} { rsp := doCrossOriginRequest(t, method, method, spec.URL("project/")) assert.Equal(t, http.StatusOK, rsp.StatusCode) assert.Equal(t, "*", rsp.Header.Get("Access-Control-Allow-Origin")) assert.Equal(t, "", rsp.Header.Get("Access-Control-Allow-Credentials")) } } } func TestCORSForbidsPOST(t *testing.T) { skipUnlessEnabled(t) teardown := RunPagesProcess(t, *pagesBinary, listeners, "") defer teardown() for _, spec := range listeners { rsp := doCrossOriginRequest(t, "OPTIONS", "POST", spec.URL("project/")) assert.Equal(t, http.StatusOK, rsp.StatusCode) assert.Equal(t, "", rsp.Header.Get("Access-Control-Allow-Origin")) assert.Equal(t, "", rsp.Header.Get("Access-Control-Allow-Credentials")) } } func doCrossOriginRequest(t *testing.T, method, reqMethod, url string) *http.Response { req, err := http.NewRequest(method, url, nil) require.NoError(t, err) req.Host = "group.gitlab-example.com" req.Header.Add("Origin", "example.com") req.Header.Add("Access-Control-Request-Method", reqMethod) rsp, err := DoPagesRequest(t, req) require.NoError(t, err) rsp.Body.Close() return rsp } func TestKnownHostWithPortReturns200(t *testing.T) { skipUnlessEnabled(t) teardown := RunPagesProcess(t, *pagesBinary, listeners, "") defer teardown() for _, spec := range listeners { rsp, err := GetPageFromListener(t, spec, "group.gitlab-example.com:"+spec.Port, "project/") assert.NoError(t, err) rsp.Body.Close() assert.Equal(t, http.StatusOK, rsp.StatusCode) } } func TestHttpToHttpsRedirectDisabled(t *testing.T) { skipUnlessEnabled(t) teardown := RunPagesProcess(t, *pagesBinary, listeners, "", "-redirect-http=false") defer teardown() rsp, err := GetRedirectPage(t, httpListener, "group.gitlab-example.com", "project/") assert.NoError(t, err) defer rsp.Body.Close() assert.Equal(t, http.StatusOK, rsp.StatusCode) rsp, err = GetPageFromListener(t, httpsListener, "group.gitlab-example.com", "project/") assert.NoError(t, err) defer rsp.Body.Close() assert.Equal(t, http.StatusOK, rsp.StatusCode) } func TestHttpToHttpsRedirectEnabled(t *testing.T) { skipUnlessEnabled(t) teardown := RunPagesProcess(t, *pagesBinary, listeners, "", "-redirect-http=true") defer teardown() rsp, err := GetRedirectPage(t, httpListener, "group.gitlab-example.com", "project/") assert.NoError(t, err) defer rsp.Body.Close() assert.Equal(t, http.StatusTemporaryRedirect, rsp.StatusCode) assert.Equal(t, 1, len(rsp.Header["Location"])) assert.Equal(t, "https://group.gitlab-example.com/project/", rsp.Header.Get("Location")) rsp, err = GetPageFromListener(t, httpsListener, "group.gitlab-example.com", "project/") assert.NoError(t, err) defer rsp.Body.Close() assert.Equal(t, http.StatusOK, rsp.StatusCode) } func TestPrometheusMetricsCanBeScraped(t *testing.T) { skipUnlessEnabled(t) listener := []ListenSpec{{"http", "127.0.0.1", "37003"}} teardown := RunPagesProcess(t, *pagesBinary, listener, ":42345") defer teardown() resp, err := http.Get("http://localhost:42345/metrics") if assert.NoError(t, err) { defer resp.Body.Close() body, _ := ioutil.ReadAll(resp.Body) assert.Contains(t, string(body), "gitlab_pages_http_sessions_active 0") assert.Contains(t, string(body), "gitlab_pages_domains_served_total 7") } } func TestStatusPage(t *testing.T) { skipUnlessEnabled(t) teardown := RunPagesProcess(t, *pagesBinary, listeners, "", "-redirect-http=false", "-pages-status=/@statuscheck") defer teardown() rsp, err := GetPageFromListener(t, httpListener, "group.gitlab-example.com", "@statuscheck") assert.NoError(t, err) defer rsp.Body.Close() assert.Equal(t, http.StatusOK, rsp.StatusCode) }