// Copyright The OpenTelemetry Authors // SPDX-License-Identifier: Apache-2.0 package errorhandler import ( "bytes" "errors" "log" "os" "strings" "sync" "testing" "github.com/stretchr/testify/assert" ) type fnErrHandler func(error) func (f fnErrHandler) Handle(err error) { f(err) } var noopEH = fnErrHandler(func(error) {}) type nonComparableErrorHandler struct { ErrorHandler nonComparable func() //nolint:unused // This is not called. } func resetForTest(t testing.TB) { t.Cleanup(func() { globalErrorHandler = defaultErrorHandler() delegateErrorHandlerOnce = sync.Once{} }) } func TestErrDelegator(t *testing.T) { buf := new(bytes.Buffer) log.Default().SetOutput(buf) t.Cleanup(func() { log.Default().SetOutput(os.Stderr) }) e := &ErrDelegator{} err := errors.New("testing") e.Handle(err) got := buf.String() if !strings.Contains(got, err.Error()) { t.Error("default handler did not log") } buf.Reset() var gotErr error e.setDelegate(fnErrHandler(func(e error) { gotErr = e })) e.Handle(err) if buf.String() != "" { t.Error("delegate not set") } else if !errors.Is(gotErr, err) { t.Error("error not passed to delegate") } } func TestSetErrorHandler(t *testing.T) { t.Run("Set With default is a noop", func(t *testing.T) { resetForTest(t) SetErrorHandler(GetErrorHandler()) eh, ok := GetErrorHandler().(*ErrDelegator) if !ok { t.Fatal("Global ErrorHandler should be the default ErrorHandler") } if eh.delegate.Load() != nil { t.Fatal("ErrorHandler should not delegate when setting itself") } }) t.Run("First Set() should replace the delegate", func(t *testing.T) { resetForTest(t) SetErrorHandler(noopEH) _, ok := GetErrorHandler().(*ErrDelegator) if ok { t.Fatal("Global ErrorHandler was not changed") } }) t.Run("Set() should delegate existing ErrorHandlers", func(t *testing.T) { resetForTest(t) eh := GetErrorHandler() SetErrorHandler(noopEH) errDel, ok := eh.(*ErrDelegator) if !ok { t.Fatal("Wrong ErrorHandler returned") } if errDel.delegate.Load() == nil { t.Fatal("The ErrDelegator should have a delegate") } }) t.Run("non-comparable types should not panic", func(t *testing.T) { resetForTest(t) eh := nonComparableErrorHandler{} assert.NotPanics(t, func() { SetErrorHandler(eh) }, "delegate") assert.NotPanics(t, func() { SetErrorHandler(eh) }, "replacement") }) }