init push
This commit is contained in:
92
internal/resilience/breaker_test.go
Normal file
92
internal/resilience/breaker_test.go
Normal file
@@ -0,0 +1,92 @@
|
||||
package resilience
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"io"
|
||||
"log/slog"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/aws/smithy-go"
|
||||
|
||||
"wucher/internal/config"
|
||||
)
|
||||
|
||||
func TestExecutor_ExcludedErrorsDoNotTrip(t *testing.T) {
|
||||
executor := NewExecutor("ses", config.CircuitBreakerPolicy{
|
||||
Enabled: true,
|
||||
Timeout: time.Second,
|
||||
MinRequests: 2,
|
||||
FailureRatio: 0.5,
|
||||
ConsecutiveFailures: 2,
|
||||
}, slog.New(slog.NewJSONHandler(io.Discard, nil)), func(error) Classification {
|
||||
return ClassificationExcluded
|
||||
})
|
||||
|
||||
for range 2 {
|
||||
err := executor.Execute(context.Background(), func(context.Context) error {
|
||||
return errors.New("validation error")
|
||||
})
|
||||
if err == nil {
|
||||
t.Fatalf("expected original error")
|
||||
}
|
||||
}
|
||||
|
||||
counts := executor.Counts()
|
||||
if counts.TotalExclusions != 2 {
|
||||
t.Fatalf("expected 2 exclusions, got %+v", counts)
|
||||
}
|
||||
if counts.TotalFailures != 0 {
|
||||
t.Fatalf("expected 0 failures, got %+v", counts)
|
||||
}
|
||||
}
|
||||
|
||||
func TestExecutor_FailuresTripBreaker(t *testing.T) {
|
||||
executor := NewExecutor("sqs", config.CircuitBreakerPolicy{
|
||||
Enabled: true,
|
||||
Timeout: time.Second,
|
||||
MinRequests: 1,
|
||||
FailureRatio: 0.5,
|
||||
ConsecutiveFailures: 2,
|
||||
}, slog.New(slog.NewJSONHandler(io.Discard, nil)), nil)
|
||||
|
||||
for range 2 {
|
||||
err := executor.Execute(context.Background(), func(context.Context) error {
|
||||
return errors.New("dependency down")
|
||||
})
|
||||
if err == nil {
|
||||
t.Fatalf("expected dependency error")
|
||||
}
|
||||
}
|
||||
|
||||
err := executor.Execute(context.Background(), func(context.Context) error {
|
||||
return nil
|
||||
})
|
||||
var openErr *OpenError
|
||||
if !errors.As(err, &openErr) {
|
||||
t.Fatalf("expected breaker open error, got %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestClassifySQSError(t *testing.T) {
|
||||
if got := ClassifySQSError(apiError{code: "AccessDenied", fault: smithy.FaultClient}); got != ClassificationExcluded {
|
||||
t.Fatalf("expected client fault excluded, got %v", got)
|
||||
}
|
||||
if got := ClassifySQSError(apiError{code: "InternalError", fault: smithy.FaultServer}); got != ClassificationFailure {
|
||||
t.Fatalf("expected server fault failure, got %v", got)
|
||||
}
|
||||
if got := ClassifySQSError(apiError{code: "ThrottlingException", fault: smithy.FaultClient}); got != ClassificationFailure {
|
||||
t.Fatalf("expected throttling failure, got %v", got)
|
||||
}
|
||||
}
|
||||
|
||||
type apiError struct {
|
||||
code string
|
||||
fault smithy.ErrorFault
|
||||
}
|
||||
|
||||
func (e apiError) Error() string { return e.code }
|
||||
func (e apiError) ErrorCode() string { return e.code }
|
||||
func (e apiError) ErrorMessage() string { return e.code }
|
||||
func (e apiError) ErrorFault() smithy.ErrorFault { return e.fault }
|
||||
Reference in New Issue
Block a user