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,69 @@ func funcWithBadPanic() {
111111func 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+ go doMischief (ch1 )
120+ go doMoreMischief (ch0 , ch1 )
121+
122+ select {
123+ case err := <- ch0 :
124+ require .Error (t , err )
125+ require .False (t , IsOfType (err , AssertionFailed ))
126+ output := fmt .Sprintf ("%+v" , err )
127+ require .Contains (t , output , "mischiefProper" , output )
128+ require .Contains (t , output , "mischiefAsPanic" , output )
129+ require .Contains (t , output , "doMischief" , output )
130+ require .Contains (t , output , "handleMischief" , output )
131+ require .NotContains (t , output , "doMoreMischief" , output ) // stack trace is only enhanced in Panic, not in user code
132+ t .Log (output )
133+ case <- time .After (time .Second ):
134+ require .Fail (t , "expected error" )
135+ }
136+ }
137+
138+ func doMoreMischief (ch0 chan error , ch1 chan error ) {
139+ defer func () {
140+ if e := recover (); e != nil {
141+ err , ok := ErrorFromPanic (e )
142+ if ok {
143+ ch0 <- Decorate (err , "hop 2" )
144+ return
145+ }
146+ }
147+ ch0 <- AssertionFailed .New ("test failed" )
148+ }()
149+
150+ handleMischief (ch1 )
151+ }
152+
153+ func handleMischief (ch chan error ) {
154+ err := <- ch
155+ Panic (Decorate (err , "handle" ))
156+ }
157+
158+ func doMischief (ch chan error ) {
159+ defer func () {
160+ if e := recover (); e != nil {
161+ err , ok := ErrorFromPanic (e )
162+ if ok {
163+ ch <- Decorate (err , "hop 1" )
164+ return
165+ }
166+ }
167+ ch <- AssertionFailed .New ("test failed" )
168+ }()
169+
170+ mischiefAsPanic ()
171+ }
172+
173+ func mischiefAsPanic () {
174+ Panic (mischiefProper ())
175+ }
176+
177+ func mischiefProper () error {
178+ return ExternalError .New ("mischief" )
179+ }
0 commit comments