From 6115d9ef8e53a496b60ebe296fc7961455d57dac Mon Sep 17 00:00:00 2001 From: 3Juhwan <13selfesteem91@naver.com> Date: Thu, 31 Oct 2024 01:37:15 +0900 Subject: [PATCH] test(web): speed up test execution Signed-off-by: 3Juhwan <13selfesteem91@naver.com> --- web/api/v1/api_test.go | 1 + web/api/v1/codec_test.go | 3 + web/api/v1/errors_test.go | 2 + web/api/v1/json_codec_test.go | 1 + web/federate_test.go | 4 ++ web/web_test.go | 109 ++++++++++++++++++++-------------- 6 files changed, 74 insertions(+), 46 deletions(-) diff --git a/web/api/v1/api_test.go b/web/api/v1/api_test.go index 35ad4a9ad..addbf6a58 100644 --- a/web/api/v1/api_test.go +++ b/web/api/v1/api_test.go @@ -443,6 +443,7 @@ func TestEndpoints(t *testing.T) { ng := testEngine(t) t.Run("local", func(t *testing.T) { + t.Parallel() algr := rulesRetrieverMock{testing: t} algr.CreateAlertingRules() diff --git a/web/api/v1/codec_test.go b/web/api/v1/codec_test.go index 911bf206e..07f6f955e 100644 --- a/web/api/v1/codec_test.go +++ b/web/api/v1/codec_test.go @@ -21,12 +21,14 @@ import ( ) func TestMIMEType_String(t *testing.T) { + t.Parallel() m := MIMEType{Type: "application", SubType: "json"} require.Equal(t, "application/json", m.String()) } func TestMIMEType_Satisfies(t *testing.T) { + t.Parallel() m := MIMEType{Type: "application", SubType: "json"} scenarios := map[string]struct { @@ -61,6 +63,7 @@ func TestMIMEType_Satisfies(t *testing.T) { for name, scenario := range scenarios { t.Run(name, func(t *testing.T) { + t.Parallel() actual := m.Satisfies(scenario.accept) require.Equal(t, scenario.expected, actual) }) diff --git a/web/api/v1/errors_test.go b/web/api/v1/errors_test.go index f5e75615e..34bf66b60 100644 --- a/web/api/v1/errors_test.go +++ b/web/api/v1/errors_test.go @@ -40,6 +40,7 @@ import ( ) func TestApiStatusCodes(t *testing.T) { + t.Parallel() for name, tc := range map[string]struct { err error expectedString string @@ -87,6 +88,7 @@ func TestApiStatusCodes(t *testing.T) { "error from seriesset": errorTestQueryable{q: errorTestQuerier{s: errorTestSeriesSet{err: tc.err}}}, } { t.Run(fmt.Sprintf("%s/%s", name, k), func(t *testing.T) { + t.Parallel() r := createPrometheusAPI(t, q) rec := httptest.NewRecorder() diff --git a/web/api/v1/json_codec_test.go b/web/api/v1/json_codec_test.go index 759dabd28..c2181ff3d 100644 --- a/web/api/v1/json_codec_test.go +++ b/web/api/v1/json_codec_test.go @@ -25,6 +25,7 @@ import ( ) func TestJsonCodec_Encode(t *testing.T) { + t.Parallel() cases := []struct { response interface{} expected string diff --git a/web/federate_test.go b/web/federate_test.go index 056a95d67..aeacbbb73 100644 --- a/web/federate_test.go +++ b/web/federate_test.go @@ -203,6 +203,7 @@ test_metric_without_labels{instance="baz"} 1001 6000000 } func TestFederation(t *testing.T) { + t.Parallel() storage := promqltest.LoadedStorage(t, ` load 1m test_metric1{foo="bar",instance="i"} 0+100x100 @@ -254,8 +255,10 @@ func (notReadyReadStorage) Stats(string, int) (*tsdb.Stats, error) { // Regression test for https://github.com/prometheus/prometheus/issues/7181. func TestFederation_NotReady(t *testing.T) { + t.Parallel() for name, scenario := range scenarios { t.Run(name, func(t *testing.T) { + t.Parallel() h := &Handler{ localStorage: notReadyReadStorage{}, lookbackDelta: 5 * time.Minute, @@ -302,6 +305,7 @@ func normalizeBody(body *bytes.Buffer) string { } func TestFederationWithNativeHistograms(t *testing.T) { + t.Parallel() storage := teststorage.New(t) t.Cleanup(func() { storage.Close() }) diff --git a/web/web_test.go b/web/web_test.go index 696ba80d1..851536665 100644 --- a/web/web_test.go +++ b/web/web_test.go @@ -115,12 +115,10 @@ func TestReadyAndHealthy(t *testing.T) { } }() - // Give some time for the web goroutine to run since we need the server - // to be up before starting tests. - time.Sleep(5 * time.Second) - baseURL := "http://localhost" + port + waitForServerReady(t, baseURL, 5*time.Second) + resp, err := http.Get(baseURL + "/-/healthy") require.NoError(t, err) require.Equal(t, http.StatusOK, resp.StatusCode) @@ -233,28 +231,26 @@ func TestRoutePrefix(t *testing.T) { } }() - // Give some time for the web goroutine to run since we need the server - // to be up before starting tests. - time.Sleep(5 * time.Second) + baseURL := "http://localhost" + port + opts.RoutePrefix - baseURL := "http://localhost" + port + waitForServerReady(t, baseURL, 5*time.Second) - resp, err := http.Get(baseURL + opts.RoutePrefix + "/-/healthy") + resp, err := http.Get(baseURL + "/-/healthy") require.NoError(t, err) require.Equal(t, http.StatusOK, resp.StatusCode) cleanupTestResponse(t, resp) - resp, err = http.Get(baseURL + opts.RoutePrefix + "/-/ready") + resp, err = http.Get(baseURL + "/-/ready") require.NoError(t, err) require.Equal(t, http.StatusServiceUnavailable, resp.StatusCode) cleanupTestResponse(t, resp) - resp, err = http.Post(baseURL+opts.RoutePrefix+"/api/v1/admin/tsdb/snapshot", "", strings.NewReader("")) + resp, err = http.Post(baseURL+"/api/v1/admin/tsdb/snapshot", "", strings.NewReader("")) require.NoError(t, err) require.Equal(t, http.StatusServiceUnavailable, resp.StatusCode) cleanupTestResponse(t, resp) - resp, err = http.Post(baseURL+opts.RoutePrefix+"/api/v1/admin/tsdb/delete_series", "", strings.NewReader("{}")) + resp, err = http.Post(baseURL+"/api/v1/admin/tsdb/delete_series", "", strings.NewReader("{}")) require.NoError(t, err) require.Equal(t, http.StatusServiceUnavailable, resp.StatusCode) cleanupTestResponse(t, resp) @@ -262,29 +258,30 @@ func TestRoutePrefix(t *testing.T) { // Set to ready. webHandler.SetReady(Ready) - resp, err = http.Get(baseURL + opts.RoutePrefix + "/-/healthy") + resp, err = http.Get(baseURL + "/-/healthy") require.NoError(t, err) require.Equal(t, http.StatusOK, resp.StatusCode) cleanupTestResponse(t, resp) - resp, err = http.Get(baseURL + opts.RoutePrefix + "/-/ready") + resp, err = http.Get(baseURL + "/-/ready") require.NoError(t, err) require.Equal(t, http.StatusOK, resp.StatusCode) cleanupTestResponse(t, resp) - resp, err = http.Post(baseURL+opts.RoutePrefix+"/api/v1/admin/tsdb/snapshot", "", strings.NewReader("")) + resp, err = http.Post(baseURL+"/api/v1/admin/tsdb/snapshot", "", strings.NewReader("")) require.NoError(t, err) require.Equal(t, http.StatusOK, resp.StatusCode) cleanupSnapshot(t, dbDir, resp) cleanupTestResponse(t, resp) - resp, err = http.Post(baseURL+opts.RoutePrefix+"/api/v1/admin/tsdb/delete_series?match[]=up", "", nil) + resp, err = http.Post(baseURL+"/api/v1/admin/tsdb/delete_series?match[]=up", "", nil) require.NoError(t, err) require.Equal(t, http.StatusNoContent, resp.StatusCode) cleanupTestResponse(t, resp) } func TestDebugHandler(t *testing.T) { + t.Parallel() for _, tc := range []struct { prefix, url string code int @@ -298,26 +295,30 @@ func TestDebugHandler(t *testing.T) { {"/", "/debug/pprof/foo", 404}, {"/foo", "/bar/debug/pprof/goroutine", 404}, } { - opts := &Options{ - RoutePrefix: tc.prefix, - ListenAddresses: []string{"somehost:9090"}, - ExternalURL: &url.URL{ - Host: "localhost.localdomain:9090", - Scheme: "http", - }, - } - handler := New(nil, opts) - handler.SetReady(Ready) - - w := httptest.NewRecorder() + tc := tc + t.Run(tc.url, func(t *testing.T) { + t.Parallel() + opts := &Options{ + RoutePrefix: tc.prefix, + ListenAddresses: []string{"somehost:9090"}, + ExternalURL: &url.URL{ + Host: "localhost.localdomain:9090", + Scheme: "http", + }, + } + handler := New(nil, opts) + handler.SetReady(Ready) + + w := httptest.NewRecorder() + + req, err := http.NewRequest(http.MethodGet, tc.url, nil) - req, err := http.NewRequest(http.MethodGet, tc.url, nil) - - require.NoError(t, err) + require.NoError(t, err) - handler.router.ServeHTTP(w, req) + handler.router.ServeHTTP(w, req) - require.Equal(t, tc.code, w.Code) + require.Equal(t, tc.code, w.Code) + }) } } @@ -369,6 +370,7 @@ func TestHTTPMetrics(t *testing.T) { } func TestShutdownWithStaleConnection(t *testing.T) { + t.Parallel() dbDir := t.TempDir() db, err := tsdb.Open(dbDir, nil, nil, nil, nil) @@ -424,9 +426,9 @@ func TestShutdownWithStaleConnection(t *testing.T) { close(closed) }() - // Give some time for the web goroutine to run since we need the server - // to be up before starting tests. - time.Sleep(5 * time.Second) + baseURL := "http://localhost" + port + + waitForServerReady(t, baseURL, 5*time.Second) // Open a socket, and don't use it. This connection should then be closed // after the ReadTimeout. @@ -445,6 +447,7 @@ func TestShutdownWithStaleConnection(t *testing.T) { } func TestHandleMultipleQuitRequests(t *testing.T) { + t.Parallel() port := fmt.Sprintf(":%d", testutil.RandomUnprivilegedPort(t)) opts := &Options{ @@ -475,12 +478,10 @@ func TestHandleMultipleQuitRequests(t *testing.T) { close(closed) }() - // Give some time for the web goroutine to run since we need the server - // to be up before starting tests. - time.Sleep(5 * time.Second) - baseURL := opts.ExternalURL.Scheme + "://" + opts.ExternalURL.Host + waitForServerReady(t, baseURL, 5*time.Second) + start := make(chan struct{}) var wg sync.WaitGroup for i := 0; i < 3; i++ { @@ -554,11 +555,10 @@ func TestAgentAPIEndPoints(t *testing.T) { } }() - // Give some time for the web goroutine to run since we need the server - // to be up before starting tests. - time.Sleep(5 * time.Second) baseURL := "http://localhost" + port + "/api/v1" + waitForServerReady(t, "http://localhost"+port, 5*time.Second) + // Test for non-available endpoints in the Agent mode. for path, methods := range map[string][]string{ "/labels": {http.MethodGet, http.MethodPost}, @@ -687,9 +687,7 @@ func TestMultipleListenAddresses(t *testing.T) { } }() - // Give some time for the web goroutine to run since we need the server - // to be up before starting tests. - time.Sleep(5 * time.Second) + waitForServerReady(t, "http://localhost"+port1, 5*time.Second) // Set to ready. webHandler.SetReady(Ready) @@ -708,3 +706,22 @@ func TestMultipleListenAddresses(t *testing.T) { cleanupTestResponse(t, resp) } } + +// Give some time for the web goroutine to run since we need the server +// to be up before starting tests. +func waitForServerReady(t *testing.T, baseURL string, timeout time.Duration) { + t.Helper() + + interval := 100 * time.Millisecond + deadline := time.Now().Add(timeout) + + for time.Now().Before(deadline) { + resp, err := http.Get(baseURL + "/-/healthy") + if err == nil && resp.StatusCode == http.StatusOK { + cleanupTestResponse(t, resp) + return + } + time.Sleep(interval) + } + t.Fatalf("Server did not become ready within %v", timeout) +}