Skip to content

Commit 826cd09

Browse files
committed
add support for chained panic handlers
1 parent 1eb1095 commit 826cd09

File tree

2 files changed

+76
-15
lines changed

2 files changed

+76
-15
lines changed

panic.go

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -38,33 +38,29 @@ func ErrorFromPanic(recoverResult interface{}) (error, bool) {
3838
}
3939

4040
if wrapper, ok := err.(*panicErrorWrapper); ok {
41-
return wrapper.errorWithStackTrace, true
41+
return wrapper.inner, true
4242
}
4343

4444
return err, true
4545
}
4646

4747
func newPanicErrorWrapper(err error) *panicErrorWrapper {
48-
originalError, errWithStackTrace := err, err
49-
if typedErr, ok := errWithStackTrace.(*Error); !ok || typedErr.stackTrace == nil {
50-
builder := NewErrorBuilder(panicPayloadWrap).WithConditionallyFormattedMessage("").WithCause(err)
51-
errWithStackTrace = builder.Create()
52-
}
53-
5448
return &panicErrorWrapper{
55-
originalError: originalError,
56-
errorWithStackTrace: errWithStackTrace,
49+
inner: NewErrorBuilder(panicPayloadWrap).
50+
WithConditionallyFormattedMessage("panic").
51+
WithCause(err).
52+
EnhanceStackTrace().
53+
Create(),
5754
}
5855
}
5956

57+
// panicErrorWrapper is designed for the original stack trace not to be lost in any way it may be handled
6058
type panicErrorWrapper struct {
61-
originalError error
62-
errorWithStackTrace error
59+
inner error
6360
}
6461

65-
// Original error is used, as the wrapped one contains only the same stack trace as the panic
6662
func (w *panicErrorWrapper) Error() string {
67-
return fmt.Sprintf("%+v", w.originalError)
63+
return fmt.Sprintf("%+v", w.inner)
6864
}
6965

7066
func (w *panicErrorWrapper) String() string {

panic_test.go

Lines changed: 67 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"errors"
55
"fmt"
66
"testing"
7+
"time"
78

89
"github.com/stretchr/testify/require"
910
)
@@ -29,8 +30,7 @@ func TestPanicErrorx(t *testing.T) {
2930
output := fmt.Sprintf("%v", r)
3031

3132
require.Contains(t, output, "awful", output)
32-
// original error was non-errorx, no use of adding panic callstack to message
33-
require.NotContains(t, output, "errorx.funcWithBadPanic()", output)
33+
require.Contains(t, output, "errorx.funcWithBadPanic()", output)
3434
}()
3535

3636
funcWithBadPanic()
@@ -111,3 +111,68 @@ func funcWithBadPanic() {
111111
func funcWithBadErr() error {
112112
return errors.New("awful")
113113
}
114+
115+
func TestPanicChain(t *testing.T) {
116+
ch0 := make(chan error, 1)
117+
ch1 := make(chan error, 1)
118+
119+
doMischief(ch1)
120+
doMoreMischief(ch0, ch1)
121+
122+
select {
123+
case err := <-ch0:
124+
require.Error(t, err)
125+
output := fmt.Sprintf("%+v", err)
126+
require.Contains(t, output, "mischiefProper", output)
127+
require.Contains(t, output, "mischiefAsPanic", output)
128+
require.Contains(t, output, "doMischief", output)
129+
require.Contains(t, output, "handleMischief", output)
130+
require.Contains(t, output, "doMoreMischief", output)
131+
t.Log(output)
132+
case <-time.After(time.Second):
133+
require.Fail(t, "expected error")
134+
}
135+
}
136+
137+
func doMoreMischief(ch0 chan error, ch1 chan error) {
138+
defer func() {
139+
if e := recover(); e != nil {
140+
err, ok := ErrorFromPanic(e)
141+
if ok {
142+
ch0 <- Decorate(err, "hop 2")
143+
return
144+
}
145+
}
146+
ch0 <- AssertionFailed.New("test failed")
147+
}()
148+
149+
handleMischief(ch1)
150+
}
151+
152+
func handleMischief(ch chan error) {
153+
err := <-ch
154+
Panic(Decorate(err, "handle"))
155+
}
156+
157+
func doMischief(ch chan error) {
158+
defer func() {
159+
if e := recover(); e != nil {
160+
err, ok := ErrorFromPanic(e)
161+
if ok {
162+
ch <- Decorate(err, "hop 1")
163+
return
164+
}
165+
}
166+
ch <- AssertionFailed.New("test failed") // todo check
167+
}()
168+
169+
mischiefAsPanic()
170+
}
171+
172+
func mischiefAsPanic() {
173+
Panic(mischiefProper())
174+
}
175+
176+
func mischiefProper() error {
177+
return ExternalError.New("mischief")
178+
}

0 commit comments

Comments
 (0)