kevo/pkg/transport/errors_test.go
Jeremy Tregunna 2d1e42b4d6
feat: implement integrity validation with checksums for replication transport
- Add checksums for WAL entries and WAL entry batches
- Implement robust retry and circuit breaker patterns for reliability
- Add comprehensive tests for message processing and reliability features
- Enhance error handling and timeout management
2025-04-26 14:07:31 -06:00

151 lines
4.2 KiB
Go

package transport
import (
"errors"
"fmt"
"strings"
"testing"
)
func TestTemporaryError(t *testing.T) {
t.Run("Basic error wrapping", func(t *testing.T) {
baseErr := errors.New("base error")
tempErr := NewTemporaryError(baseErr, true)
if !tempErr.IsTemporary() {
t.Error("Expected IsTemporary() to return true")
}
if tempErr.GetRetryAfter() != 0 {
t.Errorf("Expected GetRetryAfter() to return 0, got %d", tempErr.GetRetryAfter())
}
if !strings.Contains(tempErr.Error(), baseErr.Error()) {
t.Errorf("Expected Error() to contain the base error message")
}
if !strings.Contains(tempErr.Error(), "temporary: true") {
t.Errorf("Expected Error() to indicate temporary status")
}
// Test unwrap
unwrapped := errors.Unwrap(tempErr)
if unwrapped != baseErr {
t.Errorf("Expected Unwrap() to return the base error")
}
})
t.Run("Error with retry hint", func(t *testing.T) {
baseErr := errors.New("connection refused")
retryAfter := 1000 // 1 second
tempErr := NewTemporaryErrorWithRetry(baseErr, true, retryAfter)
if !tempErr.IsTemporary() {
t.Error("Expected IsTemporary() to return true")
}
if tempErr.GetRetryAfter() != retryAfter {
t.Errorf("Expected GetRetryAfter() to return %d, got %d", retryAfter, tempErr.GetRetryAfter())
}
if !strings.Contains(tempErr.Error(), baseErr.Error()) {
t.Errorf("Expected Error() to contain the base error message")
}
if !strings.Contains(tempErr.Error(), "temporary: true") {
t.Errorf("Expected Error() to indicate temporary status")
}
if !strings.Contains(tempErr.Error(), "retry after: 1000ms") {
t.Errorf("Expected Error() to include retry hint")
}
})
t.Run("Non-temporary error", func(t *testing.T) {
baseErr := errors.New("permanent error")
tempErr := NewTemporaryError(baseErr, false)
if tempErr.IsTemporary() {
t.Error("Expected IsTemporary() to return false")
}
if !strings.Contains(tempErr.Error(), "temporary: false") {
t.Errorf("Expected Error() to indicate non-temporary status")
}
})
}
func TestIsTemporary(t *testing.T) {
t.Run("With TemporaryError", func(t *testing.T) {
err := NewTemporaryError(errors.New("test error"), true)
if !IsTemporary(err) {
t.Error("Expected IsTemporary() to return true")
}
err = NewTemporaryError(errors.New("test error"), false)
if IsTemporary(err) {
t.Error("Expected IsTemporary() to return false")
}
})
t.Run("With regular error", func(t *testing.T) {
err := errors.New("regular error")
if IsTemporary(err) {
t.Error("Expected IsTemporary() to return false for regular error")
}
})
t.Run("With wrapped error", func(t *testing.T) {
tempErr := NewTemporaryError(errors.New("base error"), true)
wrappedErr := errors.New("wrapper: " + tempErr.Error())
wrappedTempErr := fmt.Errorf("wrapper: %w", tempErr)
// Regular wrapping doesn't preserve error type
if IsTemporary(wrappedErr) {
t.Error("Expected IsTemporary() to return false for string-wrapped error")
}
// fmt.Errorf with %w preserves error type
if !IsTemporary(wrappedTempErr) {
t.Error("Expected IsTemporary() to return true for properly wrapped error")
}
})
}
func TestGetRetryAfter(t *testing.T) {
t.Run("With retry hint", func(t *testing.T) {
retryAfter := 2000 // 2 seconds
err := NewTemporaryErrorWithRetry(errors.New("test error"), true, retryAfter)
if GetRetryAfter(err) != retryAfter {
t.Errorf("Expected GetRetryAfter() to return %d, got %d", retryAfter, GetRetryAfter(err))
}
})
t.Run("Without retry hint", func(t *testing.T) {
err := NewTemporaryError(errors.New("test error"), true)
if GetRetryAfter(err) != 0 {
t.Errorf("Expected GetRetryAfter() to return 0, got %d", GetRetryAfter(err))
}
})
t.Run("With regular error", func(t *testing.T) {
err := errors.New("regular error")
if GetRetryAfter(err) != 0 {
t.Errorf("Expected GetRetryAfter() to return 0, got %d", GetRetryAfter(err))
}
})
t.Run("With wrapped error", func(t *testing.T) {
retryAfter := 3000 // 3 seconds
tempErr := NewTemporaryErrorWithRetry(errors.New("base error"), true, retryAfter)
wrappedTempErr := fmt.Errorf("wrapper: %w", tempErr)
if GetRetryAfter(wrappedTempErr) != retryAfter {
t.Errorf("Expected GetRetryAfter() to return %d, got %d", retryAfter, GetRetryAfter(wrappedTempErr))
}
})
}