Skip to content

Commit 83687c5

Browse files
committed
test: add Docker test for enhanced error handling system - comprehensive test suite with validation, retry, and checkpoint systems
1 parent ef792d8 commit 83687c5

File tree

2 files changed

+228
-0
lines changed

2 files changed

+228
-0
lines changed

Dockerfile.test

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
# Test Dockerfile for Enhanced Error Handling System
2+
FROM golang:1.22-alpine AS builder
3+
4+
# Install build dependencies
5+
RUN apk add --no-cache git gcc musl-dev
6+
7+
# Set working directory
8+
WORKDIR /app
9+
10+
# Copy go module files
11+
COPY go.mod go.sum ./
12+
RUN go mod download
13+
14+
# Copy source code
15+
COPY . .
16+
17+
# Build test binary
18+
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo \
19+
-o test-errors ./cmd/test_errors
20+
21+
# Runtime stage
22+
FROM alpine:3.19
23+
24+
# Install CA certificates and basic tools
25+
RUN apk add --no-cache ca-certificates
26+
27+
# Set working directory
28+
WORKDIR /app
29+
30+
# Copy test binary from builder stage
31+
COPY --from=builder /app/test-errors /app/test-errors
32+
33+
# Create temporary directory for checkpoints
34+
RUN mkdir -p /tmp/test_checkpoints
35+
36+
# Run the test
37+
ENTRYPOINT ["/app/test-errors"]

cmd/test_errors/main.go

Lines changed: 191 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,191 @@
1+
package main
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"os"
7+
"time"
8+
9+
"github.com/JohanDevl/Export_Trakt_4_Letterboxd/pkg/errors/types"
10+
"github.com/JohanDevl/Export_Trakt_4_Letterboxd/pkg/errors/validation"
11+
"github.com/JohanDevl/Export_Trakt_4_Letterboxd/pkg/resilience/checkpoints"
12+
"github.com/JohanDevl/Export_Trakt_4_Letterboxd/pkg/retry"
13+
"github.com/JohanDevl/Export_Trakt_4_Letterboxd/pkg/retry/backoff"
14+
"github.com/JohanDevl/Export_Trakt_4_Letterboxd/pkg/retry/circuit"
15+
)
16+
17+
func main() {
18+
fmt.Println("🧪 Testing Enhanced Error Handling System in Docker...")
19+
fmt.Println("============================================================")
20+
21+
ctx := context.Background()
22+
23+
// Test 1: Custom Error Types
24+
fmt.Println("\n1️⃣ Testing Custom Error Types...")
25+
testCustomErrors(ctx)
26+
27+
// Test 2: Validation System
28+
fmt.Println("\n2️⃣ Testing Validation System...")
29+
testValidation(ctx)
30+
31+
// Test 3: Retry with Circuit Breaker
32+
fmt.Println("\n3️⃣ Testing Retry with Circuit Breaker...")
33+
testRetrySystem(ctx)
34+
35+
// Test 4: Checkpoint System
36+
fmt.Println("\n4️⃣ Testing Checkpoint System...")
37+
testCheckpointSystem(ctx)
38+
39+
fmt.Println("\n✅ All tests completed successfully!")
40+
fmt.Println("🎉 Enhanced Error Handling System is working in Docker!")
41+
}
42+
43+
func testCustomErrors(ctx context.Context) {
44+
defer func() {
45+
if r := recover(); r != nil {
46+
fmt.Printf("❌ Custom error test failed: %v\n", r)
47+
}
48+
}()
49+
50+
// Create a custom error with context
51+
err := types.NewAppErrorWithOperation(
52+
types.ErrNetworkTimeout,
53+
"Test API call failed",
54+
"test_operation",
55+
fmt.Errorf("simulated network error"),
56+
).WithContext(ctx).WithMetadata("endpoint", "/api/test")
57+
58+
fmt.Printf("✅ Created custom error: %s\n", err.Error())
59+
fmt.Printf(" Code: %s, Category: %s\n", err.Code, types.GetErrorCategory(err.Code))
60+
fmt.Printf(" Retryable: %v\n", types.IsRetryableError(err.Code))
61+
}
62+
63+
func testValidation(ctx context.Context) {
64+
defer func() {
65+
if r := recover(); r != nil {
66+
fmt.Printf("❌ Validation test failed: %v\n", r)
67+
}
68+
}()
69+
70+
// Test validation framework
71+
validator := validation.NewStructValidator()
72+
validator.Field("api_key").Required().Format(validation.APIKeyPattern, "API key format")
73+
validator.Field("timeout").Range(1, 300)
74+
75+
// Test with invalid data
76+
invalidData := map[string]interface{}{
77+
"api_key": "", // Missing required field
78+
"timeout": 500, // Out of range
79+
}
80+
81+
err := validator.Validate(ctx, invalidData)
82+
if err != nil {
83+
fmt.Printf("✅ Validation correctly caught errors: %s\n", err.Error())
84+
}
85+
86+
// Test with valid data
87+
validData := map[string]interface{}{
88+
"api_key": "abcdef1234567890abcdef1234567890abcd",
89+
"timeout": 30,
90+
}
91+
92+
err = validator.Validate(ctx, validData)
93+
if err == nil {
94+
fmt.Printf("✅ Validation passed for valid data\n")
95+
}
96+
}
97+
98+
func testRetrySystem(ctx context.Context) {
99+
defer func() {
100+
if r := recover(); r != nil {
101+
fmt.Printf("❌ Retry system test failed: %v\n", r)
102+
}
103+
}()
104+
105+
// Create retry client with custom configuration
106+
config := &retry.Config{
107+
BackoffConfig: backoff.NewExponentialBackoff(100*time.Millisecond, 1*time.Second, 2.0, true, 3),
108+
CircuitBreakerConfig: &circuit.Config{
109+
FailureThreshold: 2,
110+
Timeout: 500 * time.Millisecond,
111+
RecoveryTime: 1 * time.Second,
112+
},
113+
RetryChecker: retry.DefaultRetryChecker,
114+
}
115+
116+
retryClient := retry.NewClient(config)
117+
118+
// Test with a failing operation that should be retried
119+
attemptCount := 0
120+
err := retryClient.Execute(ctx, "test_operation", func(ctx context.Context) error {
121+
attemptCount++
122+
if attemptCount < 3 {
123+
return types.NewAppError(types.ErrNetworkTimeout, "simulated timeout", nil)
124+
}
125+
return nil // Success on 3rd attempt
126+
})
127+
128+
if err == nil {
129+
fmt.Printf("✅ Retry system worked: succeeded after %d attempts\n", attemptCount)
130+
} else {
131+
fmt.Printf("❌ Retry system failed: %s\n", err.Error())
132+
}
133+
134+
// Check circuit breaker stats
135+
stats := retryClient.Stats()
136+
fmt.Printf(" Circuit breaker state: %s, Total requests: %d\n", stats.State.String(), stats.TotalRequests)
137+
}
138+
139+
func testCheckpointSystem(ctx context.Context) {
140+
defer func() {
141+
if r := recover(); r != nil {
142+
fmt.Printf("❌ Checkpoint system test failed: %v\n", r)
143+
}
144+
}()
145+
146+
// Create checkpoint manager
147+
config := &checkpoints.Config{
148+
CheckpointDir: "/tmp/test_checkpoints",
149+
MaxAge: 1 * time.Hour,
150+
}
151+
152+
manager, err := checkpoints.NewManager(config)
153+
if err != nil {
154+
fmt.Printf("❌ Failed to create checkpoint manager: %s\n", err.Error())
155+
return
156+
}
157+
158+
// Create and save a checkpoint
159+
checkpoint := checkpoints.NewCheckpoint(
160+
"test_op_123",
161+
"test_operation",
162+
0.5,
163+
map[string]interface{}{
164+
"processed_items": 50,
165+
"total_items": 100,
166+
},
167+
"process_remaining_items",
168+
)
169+
checkpoint.AddMetadata("test_run", "docker_test")
170+
171+
err = manager.Save(ctx, checkpoint)
172+
if err != nil {
173+
fmt.Printf("❌ Failed to save checkpoint: %s\n", err.Error())
174+
return
175+
}
176+
177+
// Load the checkpoint
178+
loadedCheckpoint, err := manager.Load(ctx, "test_op_123")
179+
if err != nil {
180+
fmt.Printf("❌ Failed to load checkpoint: %s\n", err.Error())
181+
return
182+
}
183+
184+
if loadedCheckpoint.Progress == 0.5 {
185+
fmt.Printf("✅ Checkpoint system worked: saved and loaded progress %.1f%%\n", loadedCheckpoint.Progress*100)
186+
}
187+
188+
// Cleanup
189+
manager.Delete(ctx, "test_op_123")
190+
os.RemoveAll("/tmp/test_checkpoints")
191+
}

0 commit comments

Comments
 (0)