package utils import ( "net/http" "net/http/httptest" "testing" "time" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) func TestDoRequestWithRetry(t *testing.T) { retryDelayUnit = time.Millisecond t.Cleanup(func() { retryDelayUnit = time.Second }) testcases := []struct { name string serverBehavior func(*httptest.Server) int wantSuccess bool wantAttempts int }{ { name: "success-on-first-attempt", serverBehavior: func(server *httptest.Server) int { return 0 }, wantSuccess: true, wantAttempts: 1, }, { name: "fail-all-attempts", serverBehavior: func(server *httptest.Server) int { return 4 }, wantSuccess: false, wantAttempts: 3, }, } for _, tc := range testcases { t.Run(tc.name, func(t *testing.T) { attempts := 0 server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { attempts++ if attempts <= tc.serverBehavior(nil) { w.WriteHeader(http.StatusInternalServerError) return } w.WriteHeader(http.StatusOK) w.Write([]byte("success")) })) t.Cleanup(func() { server.Close() }) client := &http.Client{Timeout: 5 * time.Second} req, err := http.NewRequest(http.MethodGet, server.URL, nil) require.NoError(t, err) resp, err := DoRequestWithRetry(client, req) if tc.wantSuccess { require.NoError(t, err) require.NotNil(t, resp) assert.Equal(t, http.StatusOK, resp.StatusCode) resp.Body.Close() } else { require.NotNil(t, resp) assert.Equal(t, http.StatusInternalServerError, resp.StatusCode) resp.Body.Close() } assert.Equal(t, tc.wantAttempts, attempts) }) } } func TestDoRequestWithRetry_Delay(t *testing.T) { retryDelayUnit = time.Millisecond t.Cleanup(func() { retryDelayUnit = time.Second }) var start time.Time delays := []time.Duration{} server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if len(delays) == 0 { delays = append(delays, 0) w.WriteHeader(http.StatusInternalServerError) return } if len(delays) == 1 { start = time.Now() delays = append(delays, 0) w.WriteHeader(http.StatusInternalServerError) return } if len(delays) == 2 { elapsed := time.Since(start) delays = append(delays, elapsed) w.WriteHeader(http.StatusOK) w.Write([]byte("success")) } })) defer server.Close() client := &http.Client{Timeout: 10 * time.Second} req, err := http.NewRequest(http.MethodGet, server.URL, nil) require.NoError(t, err) resp, err := DoRequestWithRetry(client, req) require.NoError(t, err) require.NotNil(t, resp) assert.Equal(t, http.StatusOK, resp.StatusCode) resp.Body.Close() assert.GreaterOrEqual(t, delays[2], time.Millisecond) }