David Lazar | 0ea120a | 2017-04-10 14:33:07 -0400 | [diff] [blame] | 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 | type frame struct { |
| 15 | pc uintptr |
| 16 | file string |
| 17 | line int |
| 18 | ok bool |
| 19 | } |
| 20 | |
| 21 | var ( |
| 22 | skip int |
| 23 | globalFrame frame |
| 24 | ) |
| 25 | |
| 26 | func f() { |
| 27 | g() // line 27 |
| 28 | } |
| 29 | |
| 30 | func g() { |
| 31 | h() // line 31 |
| 32 | } |
| 33 | |
| 34 | func h() { |
| 35 | x := &globalFrame |
| 36 | x.pc, x.file, x.line, x.ok = runtime.Caller(skip) // line 36 |
| 37 | } |
| 38 | |
| 39 | //go:noinline |
| 40 | func testCaller(skp int) frame { |
| 41 | skip = skp |
| 42 | f() // line 42 |
| 43 | frame := globalFrame |
| 44 | if !frame.ok { |
| 45 | panic(fmt.Sprintf("skip=%d runtime.Caller failed", skp)) |
| 46 | } |
| 47 | return frame |
| 48 | } |
| 49 | |
| 50 | type wantFrame struct { |
| 51 | funcName string |
| 52 | line int |
| 53 | } |
| 54 | |
| 55 | // -1 means don't care |
| 56 | var expected = []wantFrame{ |
Keith Randall | 956879d | 2019-01-05 14:31:23 -0800 | [diff] [blame] | 57 | 0: {"main.h", 36}, |
| 58 | 1: {"main.g", 31}, |
| 59 | 2: {"main.f", 27}, |
David Lazar | 0ea120a | 2017-04-10 14:33:07 -0400 | [diff] [blame] | 60 | 3: {"main.testCaller", 42}, |
| 61 | 4: {"main.main", 68}, |
| 62 | 5: {"runtime.main", -1}, |
| 63 | 6: {"runtime.goexit", -1}, |
| 64 | } |
| 65 | |
| 66 | func main() { |
| 67 | for i := 0; i <= 6; i++ { |
| 68 | frame := testCaller(i) // line 68 |
| 69 | fn := runtime.FuncForPC(frame.pc) |
| 70 | if expected[i].line >= 0 && frame.line != expected[i].line { |
| 71 | panic(fmt.Sprintf("skip=%d expected line %d, got line %d", i, expected[i].line, frame.line)) |
| 72 | } |
| 73 | if fn.Name() != expected[i].funcName { |
| 74 | panic(fmt.Sprintf("skip=%d expected function %s, got %s", i, expected[i].funcName, fn.Name())) |
| 75 | } |
| 76 | } |
| 77 | } |