Source file
src/runtime/symtab_test.go
1
2
3
4
5 package runtime_test
6
7 import (
8 "runtime"
9 "strings"
10 "testing"
11 "unsafe"
12 )
13
14 func TestCaller(t *testing.T) {
15 procs := runtime.GOMAXPROCS(-1)
16 c := make(chan bool, procs)
17 for p := 0; p < procs; p++ {
18 go func() {
19 for i := 0; i < 1000; i++ {
20 testCallerFoo(t)
21 }
22 c <- true
23 }()
24 defer func() {
25 <-c
26 }()
27 }
28 }
29
30
31
32
33 func testCallerFoo(t *testing.T) {
34 testCallerBar(t)
35 }
36
37
38 func testCallerBar(t *testing.T) {
39 for i := 0; i < 2; i++ {
40 pc, file, line, ok := runtime.Caller(i)
41 f := runtime.FuncForPC(pc)
42 if !ok ||
43 !strings.HasSuffix(file, "symtab_test.go") ||
44 (i == 0 && !strings.HasSuffix(f.Name(), "testCallerBar")) ||
45 (i == 1 && !strings.HasSuffix(f.Name(), "testCallerFoo")) ||
46 line < 5 || line > 1000 ||
47 f.Entry() >= pc {
48 t.Errorf("incorrect symbol info %d: %t %d %d %s %s %d",
49 i, ok, f.Entry(), pc, f.Name(), file, line)
50 }
51 }
52 }
53
54 func lineNumber() int {
55 _, _, line, _ := runtime.Caller(1)
56 return line
57 }
58
59
60 var firstLine = lineNumber()
61 var (
62 lineVar1 = lineNumber()
63 lineVar2a, lineVar2b = lineNumber(), lineNumber()
64 )
65 var compLit = []struct {
66 lineA, lineB int
67 }{
68 {
69 lineNumber(), lineNumber(),
70 },
71 {
72 lineNumber(),
73 lineNumber(),
74 },
75 {
76 lineB: lineNumber(),
77 lineA: lineNumber(),
78 },
79 }
80 var arrayLit = [...]int{lineNumber(),
81 lineNumber(), lineNumber(),
82 lineNumber(),
83 }
84 var sliceLit = []int{lineNumber(),
85 lineNumber(), lineNumber(),
86 lineNumber(),
87 }
88 var mapLit = map[int]int{
89 29: lineNumber(),
90 30: lineNumber(),
91 lineNumber(): 31,
92 lineNumber(): 32,
93 }
94 var intLit = lineNumber() +
95 lineNumber() +
96 lineNumber()
97 func trythis() {
98 recordLines(lineNumber(),
99 lineNumber(),
100 lineNumber())
101 }
102
103
104
105 var l38, l39, l40 int
106
107 func recordLines(a, b, c int) {
108 l38 = a
109 l39 = b
110 l40 = c
111 }
112
113 func TestLineNumber(t *testing.T) {
114 trythis()
115 for _, test := range []struct {
116 name string
117 val int
118 want int
119 }{
120 {"firstLine", firstLine, 0},
121 {"lineVar1", lineVar1, 2},
122 {"lineVar2a", lineVar2a, 3},
123 {"lineVar2b", lineVar2b, 3},
124 {"compLit[0].lineA", compLit[0].lineA, 9},
125 {"compLit[0].lineB", compLit[0].lineB, 9},
126 {"compLit[1].lineA", compLit[1].lineA, 12},
127 {"compLit[1].lineB", compLit[1].lineB, 13},
128 {"compLit[2].lineA", compLit[2].lineA, 17},
129 {"compLit[2].lineB", compLit[2].lineB, 16},
130
131 {"arrayLit[0]", arrayLit[0], 20},
132 {"arrayLit[1]", arrayLit[1], 21},
133 {"arrayLit[2]", arrayLit[2], 21},
134 {"arrayLit[3]", arrayLit[3], 22},
135
136 {"sliceLit[0]", sliceLit[0], 24},
137 {"sliceLit[1]", sliceLit[1], 25},
138 {"sliceLit[2]", sliceLit[2], 25},
139 {"sliceLit[3]", sliceLit[3], 26},
140
141 {"mapLit[29]", mapLit[29], 29},
142 {"mapLit[30]", mapLit[30], 30},
143 {"mapLit[31]", mapLit[31+firstLine] + firstLine, 31},
144 {"mapLit[32]", mapLit[32+firstLine] + firstLine, 32},
145
146 {"intLit", intLit - 2*firstLine, 34 + 35 + 36},
147
148 {"l38", l38, 38},
149 {"l39", l39, 39},
150 {"l40", l40, 40},
151 } {
152 if got := test.val - firstLine; got != test.want {
153 t.Errorf("%s on firstLine+%d want firstLine+%d (firstLine=%d, val=%d)",
154 test.name, got, test.want, firstLine, test.val)
155 }
156 }
157 }
158
159 func TestNilName(t *testing.T) {
160 defer func() {
161 if ex := recover(); ex != nil {
162 t.Fatalf("expected no nil panic, got=%v", ex)
163 }
164 }()
165 if got := (*runtime.Func)(nil).Name(); got != "" {
166 t.Errorf("Name() = %q, want %q", got, "")
167 }
168 }
169
170 var dummy int
171
172 func inlined() {
173
174 dummy = 42
175 }
176
177
178
179
180
181
182 func tracebackFunc(t *testing.T) uintptr {
183
184
185 inlined()
186 inlined()
187
188
189 pc, _, _, ok := runtime.Caller(0)
190 if !ok {
191 t.Fatalf("Caller(0) got ok false, want true")
192 }
193
194 return pc
195 }
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219 func TestFunctionAlignmentTraceback(t *testing.T) {
220 pc := tracebackFunc(t)
221
222
223 f := runtime.FuncForPC(pc)
224 if !strings.HasSuffix(f.Name(), "tracebackFunc") {
225 t.Fatalf("Caller(0) = %+v, want tracebackFunc", f)
226 }
227
228
229
230 for runtime.FuncForPC(pc) == f {
231 pc++
232 }
233 pc--
234
235
236
237
238 if runtime.GOARCH == "amd64" {
239 code := *(*uint8)(unsafe.Pointer(pc))
240 if code != 0xcc {
241 t.Errorf("PC %v code got %#x want 0xcc", pc, code)
242 }
243 }
244
245
246
247 frames := runtime.CallersFrames([]uintptr{pc})
248 frame, _ := frames.Next()
249 if frame.Func != f {
250 t.Errorf("frames.Next() got %+v want %+v", frame.Func, f)
251 }
252 }
253
254 func BenchmarkFunc(b *testing.B) {
255 pc, _, _, ok := runtime.Caller(0)
256 if !ok {
257 b.Fatal("failed to look up PC")
258 }
259 f := runtime.FuncForPC(pc)
260 b.Run("Name", func(b *testing.B) {
261 for i := 0; i < b.N; i++ {
262 name := f.Name()
263 if name != "runtime_test.BenchmarkFunc" {
264 b.Fatalf("unexpected name %q", name)
265 }
266 }
267 })
268 b.Run("Entry", func(b *testing.B) {
269 for i := 0; i < b.N; i++ {
270 pc := f.Entry()
271 if pc == 0 {
272 b.Fatal("zero PC")
273 }
274 }
275 })
276 b.Run("FileLine", func(b *testing.B) {
277 for i := 0; i < b.N; i++ {
278 file, line := f.FileLine(pc)
279 if !strings.HasSuffix(file, "symtab_test.go") || line == 0 {
280 b.Fatalf("unexpected file/line %q:%d", file, line)
281 }
282 }
283 })
284 }
285
View as plain text