Skip to content

Commit 840091a

Browse files
committed
add unit test
1 parent ab17d04 commit 840091a

2 files changed

Lines changed: 80 additions & 3 deletions

File tree

stackit/internal/services/objectstorage/utils/util.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ func ConfigureClient(ctx context.Context, providerData *core.ProviderData, diags
151151
retryRoundTripper := &RetryTransport{
152152
Base: providerData.RoundTripper,
153153
MaxRetries: 3,
154-
BaseBackoff: 1 * time.Second,
154+
BaseBackoff: 10 * time.Second,
155155
MaxJitter: 500 * time.Millisecond, // Always added to wait time
156156
}
157157

stackit/internal/services/objectstorage/utils/util_test.go

Lines changed: 79 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,14 @@ import (
55
"crypto/tls"
66
"fmt"
77
"net/http"
8+
"net/http/httptest"
89
"os"
910
"reflect"
1011
"testing"
1112
"testing/synctest"
1213
"time"
1314

15+
"github.com/google/uuid"
1416
"github.com/hashicorp/terraform-plugin-framework/diag"
1517
sdkClients "github.com/stackitcloud/stackit-sdk-go/core/clients"
1618
"github.com/stackitcloud/stackit-sdk-go/core/config"
@@ -61,7 +63,7 @@ func TestConfigureClient(t *testing.T) {
6163
config.WithCustomAuth(&RetryTransport{
6264
Base: roundTripper,
6365
MaxRetries: 3,
64-
BaseBackoff: 1 * time.Second,
66+
BaseBackoff: 10 * time.Second,
6567
MaxJitter: 500 * time.Millisecond,
6668
}),
6769
)
@@ -89,7 +91,7 @@ func TestConfigureClient(t *testing.T) {
8991
config.WithCustomAuth(&RetryTransport{
9092
Base: roundTripper,
9193
MaxRetries: 3,
92-
BaseBackoff: 1 * time.Second,
94+
BaseBackoff: 10 * time.Second,
9395
MaxJitter: 500 * time.Millisecond,
9496
}),
9597
)
@@ -118,6 +120,81 @@ func TestConfigureClient(t *testing.T) {
118120
}
119121
}
120122

123+
func TestClientRetry(t *testing.T) {
124+
ctx := context.Background()
125+
diags := diag.Diagnostics{}
126+
127+
testProjectId := uuid.New().String()
128+
const testRegion = "eu01"
129+
const testBucketName = "karl-otto"
130+
131+
attempts := 0
132+
133+
// Create mock server returning HTTP 429 on first & second call, HTTP 200 on final retry
134+
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
135+
attempts++
136+
137+
if r.URL.Path != fmt.Sprintf("/v2/project/%s/regions/%s/bucket/%s", testProjectId, testRegion, testBucketName) {
138+
t.Fatalf("invalid endpoint called")
139+
}
140+
141+
// first request: HTTP 429 *with* Retry-After header
142+
if attempts == 1 {
143+
w.Header().Set("Retry-After", "1")
144+
w.Header().Set("Content-Type", "application/json")
145+
w.WriteHeader(http.StatusTooManyRequests)
146+
_, err := w.Write([]byte(`{"error": "rate_limit_exceeded"}`))
147+
if err != nil {
148+
t.Fatalf("error writing response: %v", err)
149+
}
150+
return
151+
}
152+
153+
// second request: HTTP 429 *without* Retry-After header (we expect base backoff to be used now)
154+
if attempts == 2 {
155+
w.Header().Set("Content-Type", "application/json")
156+
w.WriteHeader(http.StatusTooManyRequests)
157+
_, err := w.Write([]byte(`{"error": "rate_limit_exceeded"}`))
158+
if err != nil {
159+
t.Fatalf("error writing response: %v", err)
160+
}
161+
return
162+
}
163+
164+
w.Header().Set("Content-Type", "application/json")
165+
w.WriteHeader(http.StatusOK)
166+
_, err := w.Write([]byte(`{
167+
"bucket": {
168+
"name": "bucket-1",
169+
"objectLockEnabled": false,
170+
"region": "eu01",
171+
"urlPathStyle": "https://object.storage.eu01.onstackit.cloud/bucket-1",
172+
"urlVirtualHostedStyle": "https://bucket-1.object.storage.eu01.onstackit.cloud"
173+
},
174+
"project": "` + testProjectId + `"}`))
175+
if err != nil {
176+
t.Fatalf("error writing response: %v", err)
177+
}
178+
}))
179+
defer server.Close()
180+
181+
client := ConfigureClient(ctx, &core.ProviderData{
182+
ObjectStorageCustomEndpoint: server.URL,
183+
}, &diags)
184+
if diags.HasError() {
185+
t.Fatalf("error configuring client: %v", diags)
186+
}
187+
188+
_, err := client.DefaultAPI.GetBucket(ctx, testProjectId, testRegion, testBucketName).Execute()
189+
if err != nil {
190+
t.Fatalf("unexpected request error: %v", err)
191+
}
192+
193+
if attempts != 3 {
194+
t.Fatalf("expected 3 attempts, got %d", attempts)
195+
}
196+
}
197+
121198
func TestEnableProject(t *testing.T) {
122199
tests := []struct {
123200
description string

0 commit comments

Comments
 (0)