Home | History | Annotate | Download | only in runtime
      1 // Copyright 2016 The Go Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style
      3 // license that can be found in the LICENSE file.
      4 
      5 package runtime_test
      6 
      7 import (
      8 	"runtime"
      9 	"strings"
     10 	"testing"
     11 )
     12 
     13 func f1(pan bool) []uintptr {
     14 	return f2(pan) // line 14
     15 }
     16 
     17 func f2(pan bool) []uintptr {
     18 	return f3(pan) // line 18
     19 }
     20 
     21 func f3(pan bool) []uintptr {
     22 	if pan {
     23 		panic("f3") // line 23
     24 	}
     25 	ret := make([]uintptr, 20)
     26 	return ret[:runtime.Callers(0, ret)] // line 26
     27 }
     28 
     29 func testCallers(t *testing.T, pcs []uintptr, pan bool) {
     30 	m := make(map[string]int, len(pcs))
     31 	frames := runtime.CallersFrames(pcs)
     32 	for {
     33 		frame, more := frames.Next()
     34 		if frame.Function != "" {
     35 			m[frame.Function] = frame.Line
     36 		}
     37 		if !more {
     38 			break
     39 		}
     40 	}
     41 
     42 	var seen []string
     43 	for k := range m {
     44 		seen = append(seen, k)
     45 	}
     46 	t.Logf("functions seen: %s", strings.Join(seen, " "))
     47 
     48 	var f3Line int
     49 	if pan {
     50 		f3Line = 23
     51 	} else {
     52 		f3Line = 26
     53 	}
     54 	want := []struct {
     55 		name string
     56 		line int
     57 	}{
     58 		{"f1", 14},
     59 		{"f2", 18},
     60 		{"f3", f3Line},
     61 	}
     62 	for _, w := range want {
     63 		if got := m["runtime_test."+w.name]; got != w.line {
     64 			t.Errorf("%s is line %d, want %d", w.name, got, w.line)
     65 		}
     66 	}
     67 }
     68 
     69 func TestCallers(t *testing.T) {
     70 	testCallers(t, f1(false), false)
     71 }
     72 
     73 func TestCallersPanic(t *testing.T) {
     74 	defer func() {
     75 		if r := recover(); r == nil {
     76 			t.Fatal("did not panic")
     77 		}
     78 		pcs := make([]uintptr, 20)
     79 		pcs = pcs[:runtime.Callers(0, pcs)]
     80 		testCallers(t, pcs, true)
     81 	}()
     82 	f1(true)
     83 }
     84