// Copyright (c) 2026 Petr BalvĂ­n (https://petrbalvin.org) // SPDX-License-Identifier: MIT package base import ( "errors" "strings" "testing" ) // TestWrapErrCarriesTagOnce pins the WrapErr contract the ten wrap // points rely on: the message carries the tensor tag and the operation // once each, whatever the inner error already carries, and the chain // stays open for errors.Is. The wrap these properties answer to used to // be fmt.Errorf("op: %w", err) over an Errf-built cause, which printed // the tag twice. func TestWrapErrCarriesTagOnce(t *testing.T) { if got := WrapErr("Anything", nil); got != nil { t.Fatalf("WrapErr of nil = %v, want nil", got) } // A bare cause the library did not build: the tag and the operation // are added, once each. bare := errors.New("the caller's own failure") got := WrapErr("Jacobian", bare) if want := "tensor: Jacobian: the caller's own failure"; got.Error() != want { t.Errorf("WrapErr of a bare cause = %q, want %q", got.Error(), want) } if !errors.Is(got, bare) { t.Errorf("WrapErr of a bare cause does not unwrap to it") } // A cause the library already tagged: the tag is not doubled. tagged := Errf("the shape holds more elements than fit in an index") got = WrapErr("Tile", tagged) if want := "tensor: Tile: the shape holds more elements than fit in an index"; got.Error() != want { t.Errorf("WrapErr of a tagged cause = %q, want %q", got.Error(), want) } if !errors.Is(got, tagged) { t.Errorf("WrapErr of a tagged cause does not unwrap to it") } if n := strings.Count(got.Error(), "tensor: "); n != 1 { t.Errorf("WrapErr message carries the tag %d times, want exactly one", n) } // A nested WrapErr composes the same way: each layer names its own // operation and the tag still appears once. inner := WrapErr("Concat", tagged) got = WrapErr("Repeat", inner) if want := "tensor: Repeat: Concat: the shape holds more elements than fit in an index"; got.Error() != want { t.Errorf("nested WrapErr = %q, want %q", got.Error(), want) } if !errors.Is(got, tagged) { t.Errorf("nested WrapErr does not unwrap down to the cause") } }