Files
wehub-resource-sync bf9395e022
CI / results (push) Blocked by required conditions
CI / license-header (push) Has been skipped
CI / e2e-dry-run (push) Has been skipped
CI / e2e-live (push) Waiting to run
CI / fast-gate (push) Failing after 0s
Test PR Label Logic / test-pr-labels (push) Failing after 1s
Skill Format Check / check-format (push) Failing after 2s
CI / security (push) Failing after 5s
CI / unit-test (push) Has been skipped
CI / lint (push) Has been skipped
CI / script-test (push) Has been skipped
CI / deterministic-gate (push) Has been skipped
CI / coverage (push) Has been skipped
CI / deadcode (push) Waiting to run
chore: import upstream snapshot with attribution
2026-07-13 12:22:54 +08:00

104 lines
2.8 KiB
Go

// Copyright (c) 2026 Lark Technologies Pte. Ltd.
// SPDX-License-Identifier: MIT
package transport
import (
"errors"
"fmt"
"testing"
)
func TestAbortError_Error(t *testing.T) {
tests := []struct {
name string
err *AbortError
want string
}{
{
name: "with extension name",
err: &AbortError{Extension: "audit", Reason: errors.New("bad")},
want: `extension "audit" aborted round trip: bad`,
},
{
name: "without extension name",
err: &AbortError{Reason: errors.New("bad")},
want: "extension aborted round trip: bad",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := tt.err.Error(); got != tt.want {
t.Fatalf("Error() = %q, want %q", got, tt.want)
}
})
}
}
func TestAbortError_Unwrap(t *testing.T) {
reason := errors.New("bad")
e := &AbortError{Reason: reason}
if got := e.Unwrap(); got != reason {
t.Fatalf("Unwrap() = %v, want %v", got, reason)
}
}
func TestAbortError_IsErrAborted(t *testing.T) {
e := &AbortError{Reason: errors.New("bad")}
if !errors.Is(e, ErrAborted) {
t.Fatal("errors.Is(e, ErrAborted) = false, want true")
}
// Sanity: not matched by unrelated sentinels.
if errors.Is(e, errors.New("other")) {
t.Fatal("errors.Is matched unrelated sentinel")
}
}
func TestAbortError_UnwrapReachesInnerSentinel(t *testing.T) {
// Extensions often return typed/sentinel errors; callers should still be
// able to errors.Is against those after the middleware wraps them.
innerSentinel := errors.New("policy-deny-42")
e := &AbortError{Reason: fmt.Errorf("wrapped: %w", innerSentinel)}
if !errors.Is(e, innerSentinel) {
t.Fatal("errors.Is(e, innerSentinel) = false, want true (Unwrap chain broken)")
}
}
func TestAbortError_As(t *testing.T) {
reason := errors.New("bad")
base := &AbortError{Extension: "audit", Reason: reason}
// Direct As.
var aErr *AbortError
if !errors.As(base, &aErr) {
t.Fatal("errors.As(base, *AbortError) = false")
}
if aErr.Extension != "audit" || aErr.Reason != reason {
t.Fatalf("aErr = %+v, want {audit, bad}", aErr)
}
// Nested As: even when the *AbortError is wrapped in another error,
// errors.As must still find it via Unwrap chain.
wrapped := fmt.Errorf("outer: %w", base)
var aErr2 *AbortError
if !errors.As(wrapped, &aErr2) {
t.Fatal("errors.As(wrapped, *AbortError) = false")
}
if aErr2 != base {
t.Fatalf("aErr2 = %p, want %p", aErr2, base)
}
// errors.Is still matches the sentinel through the outer wrapper.
if !errors.Is(wrapped, ErrAborted) {
t.Fatal("errors.Is(wrapped, ErrAborted) = false via nested wrap")
}
}
func TestErrAborted_IsItselfSentinel(t *testing.T) {
// Guard against accidental re-assignment of ErrAborted: a bare ErrAborted
// value should still satisfy errors.Is(err, ErrAborted) for symmetry.
if !errors.Is(ErrAborted, ErrAborted) {
t.Fatal("errors.Is(ErrAborted, ErrAborted) = false")
}
}