Home | History | Annotate | Download | only in test
      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