blob: ee7d6470728cb916c34f3c4e2f73cfa9a1edb31c [file] [log] [blame]
Austin Clementse862f982017-11-21 17:55:18 -05001// run -gcflags=-l=4
David Lazaree972162017-03-06 14:48:36 -05002
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 (
Russ Cox7dea5092017-10-11 20:39:28 -040010 "fmt"
David Lazaree972162017-03-06 14:48:36 -050011 "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++ {
Keith Randall956879d2019-01-05 14:31:23 -080034 fn := runtime.FuncForPC(pcs[i] - 1)
David Lazaree972162017-03-06 14:48:36 -050035 frames = append(frames, fn.Name())
36 if fn.Name() == "main.main" {
37 break
38 }
39 }
40 return
41}
42
David Lazar7bf0adc2017-03-07 21:14:12 -050043func 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
David Lazaree972162017-03-06 14:48:36 -050058var expectedFrames [][]string = [][]string{
Keith Randall956879d2019-01-05 14:31:23 -080059 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"},
Keith Randall69c2c562018-12-04 07:58:18 -080063 4: {"main.testCallers", "main.main"},
David Lazaree972162017-03-06 14:48:36 -050064 5: {"main.main"},
65}
66
David Lazar7bf0adc2017-03-07 21:14:12 -050067var allFrames = []string{"runtime.Callers", "main.h", "main.g", "main.f", "main.testCallersFrames", "main.main"}
68
David Lazaree972162017-03-06 14:48:36 -050069func 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) {
Austin Clementse862f982017-11-21 17:55:18 -050086 fmt.Printf("testCallers(%d):\n got %v\n want %v\n", i, frames, expected)
David Lazaree972162017-03-06 14:48:36 -050087 }
David Lazar7bf0adc2017-03-07 21:14:12 -050088
89 frames = testCallersFrames(i)
90 expected = allFrames[i:]
91 if !same(frames, expected) {
Austin Clementse862f982017-11-21 17:55:18 -050092 fmt.Printf("testCallersFrames(%d):\n got %v\n want %v\n", i, frames, expected)
David Lazar7bf0adc2017-03-07 21:14:12 -050093 }
David Lazaree972162017-03-06 14:48:36 -050094 }
95}