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 7 package main 8 9 import ( 10 "fmt" 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++ { 34 fn := runtime.FuncForPC(pcs[i]) 35 frames = append(frames, fn.Name()) 36 if fn.Name() == "main.main" { 37 break 38 } 39 } 40 return 41 } 42 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 58 var expectedFrames [][]string = [][]string{ 59 0: {"runtime.Callers", "main.testCallers", "main.main"}, 60 1: {"main.testCallers", "main.main"}, 61 2: {"main.testCallers", "runtime.skipPleaseUseCallersFrames", "main.main"}, 62 3: {"main.testCallers", "runtime.skipPleaseUseCallersFrames", "main.main"}, 63 4: {"main.testCallers", "runtime.skipPleaseUseCallersFrames", "main.main"}, 64 5: {"main.main"}, 65 } 66 67 var allFrames = []string{"runtime.Callers", "main.h", "main.g", "main.f", "main.testCallersFrames", "main.main"} 68 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) { 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