// +build go1.9 package stack_test import ( "runtime" "testing" "github.com/go-stack/stack" ) func TestCallerInlinedPanic(t *testing.T) { t.Parallel() var line int defer func() { if recover() != nil { var pcs [32]uintptr n := runtime.Callers(1, pcs[:]) frames := runtime.CallersFrames(pcs[:n]) // count frames to runtime.sigpanic panicIdx := 0 for { f, more := frames.Next() if f.Function == "runtime.sigpanic" { break } panicIdx++ if !more { t.Fatal("no runtime.sigpanic entry on the stack") } } c := stack.Caller(panicIdx) if got, want := c.Frame().Function, "runtime.sigpanic"; got != want { t.Errorf("sigpanic frame: got name == %v, want name == %v", got, want) } c1 := stack.Caller(panicIdx + 1) if got, want := c1.Frame().Function, "github.com/go-stack/stack_test.inlinablePanic"; got != want { t.Errorf("TestCallerInlinedPanic frame: got name == %v, want name == %v", got, want) } if got, want := c1.Frame().Line, line; got != want { t.Errorf("TestCallerInlinedPanic frame: got line == %v, want line == %v", got, want) } } }() doPanic(t, &line) t.Fatal("failed to panic") } func doPanic(t *testing.T, panicLine *int) { _, _, line, ok := runtime.Caller(0) *panicLine = line + 11 // adjust to match line of panic below if !ok { t.Fatal("runtime.Caller(0) failed") } inlinablePanic() } func inlinablePanic() { // Initiate a sigpanic. var x *uintptr _ = *x }