package gperr import ( "errors" "strings" "testing" "github.com/yusing/go-proxy/internal/utils/strutils/ansi" . "github.com/yusing/go-proxy/internal/utils/testing" ) func TestBaseString(t *testing.T) { ExpectEqual(t, New("error").Error(), "error") } func TestBaseWithSubject(t *testing.T) { err := New("error") withSubject := err.Subject("foo") withSubjectf := err.Subjectf("%s %s", "foo", "bar") ExpectError(t, err, withSubject) ExpectEqual(t, ansi.StripANSI(withSubject.Error()), "foo: error") ExpectTrue(t, withSubject.Is(err)) ExpectError(t, err, withSubjectf) ExpectEqual(t, ansi.StripANSI(withSubjectf.Error()), "foo bar: error") ExpectTrue(t, withSubjectf.Is(err)) } func TestBaseWithExtra(t *testing.T) { err := New("error") extra := New("bar").Subject("baz") withExtra := err.With(extra) ExpectTrue(t, withExtra.Is(extra)) ExpectTrue(t, withExtra.Is(err)) ExpectTrue(t, errors.Is(withExtra, extra)) ExpectTrue(t, errors.Is(withExtra, err)) ExpectTrue(t, strings.Contains(withExtra.Error(), err.Error())) ExpectTrue(t, strings.Contains(withExtra.Error(), extra.Error())) ExpectTrue(t, strings.Contains(withExtra.Error(), "baz")) } func TestBaseUnwrap(t *testing.T) { err := errors.New("err") wrapped := Wrap(err) ExpectError(t, err, errors.Unwrap(wrapped)) } func TestNestedUnwrap(t *testing.T) { err := errors.New("err") err2 := New("err2") wrapped := Wrap(err).Subject("foo").With(err2.Subject("bar")) unwrapper, ok := wrapped.(interface{ Unwrap() []error }) ExpectTrue(t, ok) ExpectError(t, err, wrapped) ExpectError(t, err2, wrapped) ExpectEqual(t, len(unwrapper.Unwrap()), 2) } func TestErrorIs(t *testing.T) { from := errors.New("error") err := Wrap(from) ExpectError(t, from, err) ExpectTrue(t, err.Is(from)) ExpectFalse(t, err.Is(New("error"))) ExpectTrue(t, errors.Is(err.Subject("foo"), from)) ExpectTrue(t, errors.Is(err.Withf("foo"), from)) ExpectTrue(t, errors.Is(err.Subject("foo").Withf("bar"), from)) } func TestErrorImmutability(t *testing.T) { err := New("err") err2 := New("err2") for range 3 { // t.Logf("%d: %v %T %s", i, errors.Unwrap(err), err, err) _ = err.Subject("foo") ExpectFalse(t, strings.Contains(err.Error(), "foo")) _ = err.With(err2) ExpectFalse(t, strings.Contains(err.Error(), "extra")) ExpectFalse(t, err.Is(err2)) err = err.Subject("bar").Withf("baz") ExpectTrue(t, err != nil) } } func TestErrorWith(t *testing.T) { err1 := New("err1") err2 := New("err2") err3 := err1.With(err2) ExpectTrue(t, err3.Is(err1)) ExpectTrue(t, err3.Is(err2)) _ = err2.Subject("foo") ExpectTrue(t, err3.Is(err1)) ExpectTrue(t, err3.Is(err2)) // check if err3 is affected by err2.Subject ExpectFalse(t, strings.Contains(err3.Error(), "foo")) } func TestErrorStringSimple(t *testing.T) { errFailure := New("generic failure") ne := errFailure.Subject("foo bar") ExpectEqual(t, ansi.StripANSI(ne.Error()), "foo bar: generic failure") ne = ne.Subject("baz") ExpectEqual(t, ansi.StripANSI(ne.Error()), "baz > foo bar: generic failure") } func TestErrorStringNested(t *testing.T) { errFailure := New("generic failure") inner := errFailure.Subject("inner"). Withf("1"). Withf("1") inner2 := errFailure.Subject("inner2"). Subject("action 2"). Withf("2"). Withf("2") inner3 := errFailure.Subject("inner3"). Subject("action 3"). Withf("3"). Withf("3") ne := errFailure. Subject("foo"). Withf("bar"). Withf("baz"). With(inner). With(inner.With(inner2.With(inner3))) want := `foo: generic failure • bar • baz • inner: generic failure • 1 • 1 • inner: generic failure • 1 • 1 • action 2 > inner2: generic failure • 2 • 2 • action 3 > inner3: generic failure • 3 • 3` ExpectEqual(t, ansi.StripANSI(ne.Error()), want) }