1 // Copyright 2009 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package runtime_test 6 7 import ( 8 "runtime" 9 "strings" 10 "testing" 11 ) 12 13 func TestCaller(t *testing.T) { 14 procs := runtime.GOMAXPROCS(-1) 15 c := make(chan bool, procs) 16 for p := 0; p < procs; p++ { 17 go func() { 18 for i := 0; i < 1000; i++ { 19 testCallerFoo(t) 20 } 21 c <- true 22 }() 23 defer func() { 24 <-c 25 }() 26 } 27 } 28 29 func testCallerFoo(t *testing.T) { 30 testCallerBar(t) 31 } 32 33 func testCallerBar(t *testing.T) { 34 for i := 0; i < 2; i++ { 35 pc, file, line, ok := runtime.Caller(i) 36 f := runtime.FuncForPC(pc) 37 if !ok || 38 !strings.HasSuffix(file, "symtab_test.go") || 39 (i == 0 && !strings.HasSuffix(f.Name(), "testCallerBar")) || 40 (i == 1 && !strings.HasSuffix(f.Name(), "testCallerFoo")) || 41 line < 5 || line > 1000 || 42 f.Entry() >= pc { 43 t.Errorf("incorrect symbol info %d: %t %d %d %s %s %d", 44 i, ok, f.Entry(), pc, f.Name(), file, line) 45 } 46 } 47 } 48 49 func lineNumber() int { 50 _, _, line, _ := runtime.Caller(1) 51 return line // return 0 for error 52 } 53 54 // Do not add/remove lines in this block without updating the line numbers. 55 var firstLine = lineNumber() // 0 56 var ( // 1 57 lineVar1 = lineNumber() // 2 58 lineVar2a, lineVar2b = lineNumber(), lineNumber() // 3 59 ) // 4 60 var compLit = []struct { // 5 61 lineA, lineB int // 6 62 }{ // 7 63 { // 8 64 lineNumber(), lineNumber(), // 9 65 }, // 10 66 { // 11 67 lineNumber(), // 12 68 lineNumber(), // 13 69 }, // 14 70 { // 15 71 lineB: lineNumber(), // 16 72 lineA: lineNumber(), // 17 73 }, // 18 74 } // 19 75 var arrayLit = [...]int{lineNumber(), // 20 76 lineNumber(), lineNumber(), // 21 77 lineNumber(), // 22 78 } // 23 79 var sliceLit = []int{lineNumber(), // 24 80 lineNumber(), lineNumber(), // 25 81 lineNumber(), // 26 82 } // 27 83 var mapLit = map[int]int{ // 28 84 29: lineNumber(), // 29 85 30: lineNumber(), // 30 86 lineNumber(): 31, // 31 87 lineNumber(): 32, // 32 88 } // 33 89 var intLit = lineNumber() + // 34 90 lineNumber() + // 35 91 lineNumber() // 36 92 func trythis() { // 37 93 recordLines(lineNumber(), // 38 94 lineNumber(), // 39 95 lineNumber()) // 40 96 } 97 98 // Modifications below this line are okay. 99 100 var l38, l39, l40 int 101 102 func recordLines(a, b, c int) { 103 l38 = a 104 l39 = b 105 l40 = c 106 } 107 108 func TestLineNumber(t *testing.T) { 109 trythis() 110 for _, test := range []struct { 111 name string 112 val int 113 want int 114 }{ 115 {"firstLine", firstLine, 0}, 116 {"lineVar1", lineVar1, 2}, 117 {"lineVar2a", lineVar2a, 3}, 118 {"lineVar2b", lineVar2b, 3}, 119 {"compLit[0].lineA", compLit[0].lineA, 9}, 120 {"compLit[0].lineB", compLit[0].lineB, 9}, 121 {"compLit[1].lineA", compLit[1].lineA, 12}, 122 {"compLit[1].lineB", compLit[1].lineB, 13}, 123 {"compLit[2].lineA", compLit[2].lineA, 17}, 124 {"compLit[2].lineB", compLit[2].lineB, 16}, 125 126 {"arrayLit[0]", arrayLit[0], 20}, 127 {"arrayLit[1]", arrayLit[1], 21}, 128 {"arrayLit[2]", arrayLit[2], 21}, 129 {"arrayLit[3]", arrayLit[3], 22}, 130 131 {"sliceLit[0]", sliceLit[0], 24}, 132 {"sliceLit[1]", sliceLit[1], 25}, 133 {"sliceLit[2]", sliceLit[2], 25}, 134 {"sliceLit[3]", sliceLit[3], 26}, 135 136 {"mapLit[29]", mapLit[29], 29}, 137 {"mapLit[30]", mapLit[30], 30}, 138 {"mapLit[31]", mapLit[31+firstLine] + firstLine, 31}, // nb it's the key not the value 139 {"mapLit[32]", mapLit[32+firstLine] + firstLine, 32}, // nb it's the key not the value 140 141 {"intLit", intLit - 2*firstLine, 34 + 35 + 36}, 142 143 {"l38", l38, 38}, 144 {"l39", l39, 39}, 145 {"l40", l40, 40}, 146 } { 147 if got := test.val - firstLine; got != test.want { 148 t.Errorf("%s on firstLine+%d want firstLine+%d (firstLine=%d, val=%d)", 149 test.name, got, test.want, firstLine, test.val) 150 } 151 } 152 } 153