Austin Clements | e862f98 | 2017-11-21 17:55:18 -0500 | [diff] [blame] | 1 | // run -gcflags=-l=4 |
David Lazar | ee97216 | 2017-03-06 14:48:36 -0500 | [diff] [blame] | 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 | |
| 7 | package main |
| 8 | |
| 9 | import ( |
Russ Cox | 7dea509 | 2017-10-11 20:39:28 -0400 | [diff] [blame] | 10 | "fmt" |
David Lazar | ee97216 | 2017-03-06 14:48:36 -0500 | [diff] [blame] | 11 | "runtime" |
| 12 | ) |
| 13 | |
| 14 | var skip int |
| 15 | var npcs int |
| 16 | var pcs = make([]uintptr, 32) |
| 17 | |
| 18 | func f() { |
| 19 | g() |
| 20 | } |
| 21 | |
| 22 | func g() { |
| 23 | h() |
| 24 | } |
| 25 | |
| 26 | func h() { |
| 27 | npcs = runtime.Callers(skip, pcs) |
| 28 | } |
| 29 | |
| 30 | func testCallers(skp int) (frames []string) { |
| 31 | skip = skp |
| 32 | f() |
| 33 | for i := 0; i < npcs; i++ { |
Keith Randall | 956879d | 2019-01-05 14:31:23 -0800 | [diff] [blame] | 34 | fn := runtime.FuncForPC(pcs[i] - 1) |
David Lazar | ee97216 | 2017-03-06 14:48:36 -0500 | [diff] [blame] | 35 | frames = append(frames, fn.Name()) |
| 36 | if fn.Name() == "main.main" { |
| 37 | break |
| 38 | } |
| 39 | } |
| 40 | return |
| 41 | } |
| 42 | |
David Lazar | 7bf0adc | 2017-03-07 21:14:12 -0500 | [diff] [blame] | 43 | func 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 Lazar | ee97216 | 2017-03-06 14:48:36 -0500 | [diff] [blame] | 58 | var expectedFrames [][]string = [][]string{ |
Keith Randall | 956879d | 2019-01-05 14:31:23 -0800 | [diff] [blame] | 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"}, |
Keith Randall | 69c2c56 | 2018-12-04 07:58:18 -0800 | [diff] [blame] | 63 | 4: {"main.testCallers", "main.main"}, |
David Lazar | ee97216 | 2017-03-06 14:48:36 -0500 | [diff] [blame] | 64 | 5: {"main.main"}, |
| 65 | } |
| 66 | |
David Lazar | 7bf0adc | 2017-03-07 21:14:12 -0500 | [diff] [blame] | 67 | var allFrames = []string{"runtime.Callers", "main.h", "main.g", "main.f", "main.testCallersFrames", "main.main"} |
| 68 | |
David Lazar | ee97216 | 2017-03-06 14:48:36 -0500 | [diff] [blame] | 69 | func 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 | |
| 81 | func main() { |
| 82 | for i := 0; i <= 5; i++ { |
| 83 | frames := testCallers(i) |
| 84 | expected := expectedFrames[i] |
| 85 | if !same(frames, expected) { |
Austin Clements | e862f98 | 2017-11-21 17:55:18 -0500 | [diff] [blame] | 86 | fmt.Printf("testCallers(%d):\n got %v\n want %v\n", i, frames, expected) |
David Lazar | ee97216 | 2017-03-06 14:48:36 -0500 | [diff] [blame] | 87 | } |
David Lazar | 7bf0adc | 2017-03-07 21:14:12 -0500 | [diff] [blame] | 88 | |
| 89 | frames = testCallersFrames(i) |
| 90 | expected = allFrames[i:] |
| 91 | if !same(frames, expected) { |
Austin Clements | e862f98 | 2017-11-21 17:55:18 -0500 | [diff] [blame] | 92 | fmt.Printf("testCallersFrames(%d):\n got %v\n want %v\n", i, frames, expected) |
David Lazar | 7bf0adc | 2017-03-07 21:14:12 -0500 | [diff] [blame] | 93 | } |
David Lazar | ee97216 | 2017-03-06 14:48:36 -0500 | [diff] [blame] | 94 | } |
| 95 | } |