1// run -gcflags=-l=4
2
3// Copyright 2017 The Go Authors. All rights reserved.
4// Use of this source code is governed by a BSD-style
5// license that can be found in the LICENSE file.
6
7package main
8
9import (
10	"fmt"
11	"runtime"
12)
13
14var skip int
15var npcs int
16var pcs = make([]uintptr, 32)
17
18func f() {
19	g()
20}
21
22func g() {
23	h()
24}
25
26func h() {
27	npcs = runtime.Callers(skip, pcs)
28}
29
30func testCallers(skp int) (frames []string) {
31	skip = skp
32	f()
33	for i := 0; i < npcs; i++ {
34		fn := runtime.FuncForPC(pcs[i] - 1)
35		frames = append(frames, fn.Name())
36		if fn.Name() == "main.main" {
37			break
38		}
39	}
40	return
41}
42
43func testCallersFrames(skp int) (frames []string) {
44	skip = skp
45	f()
46	callers := pcs[:npcs]
47	ci := runtime.CallersFrames(callers)
48	for {
49		frame, more := ci.Next()
50		frames = append(frames, frame.Function)
51		if !more || frame.Function == "main.main" {
52			break
53		}
54	}
55	return
56}
57
58var expectedFrames [][]string = [][]string{
59	0: {"runtime.Callers", "main.h", "main.g", "main.f", "main.testCallers", "main.main"},
60	1: {"main.h", "main.g", "main.f", "main.testCallers", "main.main"},
61	2: {"main.g", "main.f", "main.testCallers", "main.main"},
62	3: {"main.f", "main.testCallers", "main.main"},
63	4: {"main.testCallers", "main.main"},
64	5: {"main.main"},
65}
66
67var allFrames = []string{"runtime.Callers", "main.h", "main.g", "main.f", "main.testCallersFrames", "main.main"}
68
69func same(xs, ys []string) bool {
70	if len(xs) != len(ys) {
71		return false
72	}
73	for i := range xs {
74		if xs[i] != ys[i] {
75			return false
76		}
77	}
78	return true
79}
80
81func main() {
82	for i := 0; i <= 5; i++ {
83		frames := testCallers(i)
84		expected := expectedFrames[i]
85		if !same(frames, expected) {
86			fmt.Printf("testCallers(%d):\n got %v\n want %v\n", i, frames, expected)
87		}
88
89		frames = testCallersFrames(i)
90		expected = allFrames[i:]
91		if !same(frames, expected) {
92			fmt.Printf("testCallersFrames(%d):\n got %v\n want %v\n", i, frames, expected)
93		}
94	}
95}
96