126 lines
4.1 KiB
Go
126 lines
4.1 KiB
Go
package merrors
|
|
|
|
import (
|
|
"errors"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
type testReasonedError struct {
|
|
error
|
|
reason string
|
|
}
|
|
|
|
func (e testReasonedError) Reason() string {
|
|
return e.reason
|
|
}
|
|
|
|
func TestReasonUsesReasonedError(t *testing.T) {
|
|
err := testReasonedError{
|
|
error: InvalidArgument("value is invalid"),
|
|
reason: "amount_below_minimum",
|
|
}
|
|
reason, ok := Reason(err)
|
|
if !ok {
|
|
t.Fatalf("expected reason")
|
|
}
|
|
if reason != "amount_below_minimum" {
|
|
t.Fatalf("reason mismatch: got=%q", reason)
|
|
}
|
|
}
|
|
|
|
func TestInvalidArgumentSupportsBrokenArgumentName(t *testing.T) {
|
|
t.Run("without argument name keeps old behavior", func(t *testing.T) {
|
|
err := InvalidArgument("value is missing")
|
|
expected := "invalidArgError: value is missing"
|
|
if err.Error() != expected {
|
|
t.Fatalf("unexpected error message: %s", err)
|
|
}
|
|
if !errors.Is(err, ErrInvalidArg) {
|
|
t.Fatalf("error should wrap ErrInvalidArg")
|
|
}
|
|
})
|
|
|
|
t.Run("single argument name", func(t *testing.T) {
|
|
err := InvalidArgument("value is missing", "bot_token_env")
|
|
expected := `invalidArgError: broken argument "bot_token_env": value is missing`
|
|
if err.Error() != expected {
|
|
t.Fatalf("unexpected error message: %s", err)
|
|
}
|
|
})
|
|
|
|
t.Run("multiple argument names", func(t *testing.T) {
|
|
err := InvalidArgument("value mismatch", "bot_token_env", "chat_id_env", " ")
|
|
expected := `invalidArgError: broken arguments "bot_token_env", "chat_id_env": value mismatch`
|
|
if err.Error() != expected {
|
|
t.Fatalf("unexpected error message: %s", err)
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestInvalidArgumentWithNamesfSupportsBrokenArgumentName(t *testing.T) {
|
|
err := InvalidArgumentWithNamesf([]string{"gateway.supported_assets.currency"}, "asset[%d] %s", 2, "is invalid")
|
|
expected := `invalidArgError: broken argument "gateway.supported_assets.currency": asset[2] is invalid`
|
|
if err.Error() != expected {
|
|
t.Fatalf("unexpected error message: %s", err)
|
|
}
|
|
if !errors.Is(err, ErrInvalidArg) {
|
|
t.Fatalf("error should wrap ErrInvalidArg")
|
|
}
|
|
}
|
|
|
|
func TestInvalidArgumentWrapSupportsBrokenArgumentName(t *testing.T) {
|
|
base := Define("root cause")
|
|
err := InvalidArgumentWrap(base, "value is missing", "bot_token_env")
|
|
if !strings.Contains(err.Error(), `invalidArgError: broken argument "bot_token_env": value is missing`) {
|
|
t.Fatalf("wrapped error should include broken argument name: %s", err)
|
|
}
|
|
if !errors.Is(err, ErrInvalidArg) || !errors.Is(err, base) {
|
|
t.Fatalf("wrapped error should preserve all error layers")
|
|
}
|
|
}
|
|
|
|
func TestInternalWrapAllPreservesAllCauses(t *testing.T) {
|
|
first := Define("first cause")
|
|
second := Define("second cause")
|
|
err := InternalWrapAll("combined failure", first, nil, second)
|
|
if !strings.Contains(err.Error(), "internal: combined failure") {
|
|
t.Fatalf("wrapped error should include context: %s", err)
|
|
}
|
|
if !errors.Is(err, ErrInternal) || !errors.Is(err, first) || !errors.Is(err, second) {
|
|
t.Fatalf("wrapped error should preserve all error layers")
|
|
}
|
|
}
|
|
|
|
func TestOpaqueWrapPreservesCauseWithoutExposingItsText(t *testing.T) {
|
|
cause := DataConflict("restricted storage key")
|
|
err := OpaqueWrap(ErrInternal, cause, "safe persistence failure")
|
|
|
|
if got, want := err.Error(), "internal: safe persistence failure"; got != want {
|
|
t.Fatalf("opaque error mismatch: got=%q want=%q", got, want)
|
|
}
|
|
if !errors.Is(err, ErrInternal) || !errors.Is(err, ErrDataConflict) {
|
|
t.Fatalf("opaque error did not preserve classifications: %v", err)
|
|
}
|
|
}
|
|
|
|
func TestOperationalWrapsPreserveClassificationAndCause(t *testing.T) {
|
|
cause := Define("dependency failure")
|
|
tests := []struct {
|
|
name string
|
|
err error
|
|
kind error
|
|
}{
|
|
{name: "failed precondition", err: FailedPreconditionWrap(cause, "AA capability unavailable"), kind: ErrFailedPrecondition},
|
|
{name: "service unavailable", err: ServiceUnavailableWrap(cause, "Arbitrum RPC unavailable"), kind: ErrServiceUnavailable},
|
|
{name: "data conflict", err: DataConflictWrap(cause, "managed wallet replay differs"), kind: ErrDataConflict},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
if !errors.Is(tt.err, tt.kind) || !errors.Is(tt.err, cause) {
|
|
t.Fatalf("wrapped error should preserve classification and cause: %s", tt.err)
|
|
}
|
|
})
|
|
}
|
|
}
|