Source file
src/runtime/runtime_test.go
1
2
3
4
5 package runtime_test
6
7 import (
8 "flag"
9 "fmt"
10 "io"
11 . "runtime"
12 "runtime/debug"
13 "strings"
14 "testing"
15 "unsafe"
16 )
17
18 var flagQuick = flag.Bool("quick", false, "skip slow tests, for second run in all.bash")
19
20 func init() {
21
22
23
24 SetTracebackEnv("system")
25 }
26
27 var errf error
28
29 func errfn() error {
30 return errf
31 }
32
33 func errfn1() error {
34 return io.EOF
35 }
36
37 func BenchmarkIfaceCmp100(b *testing.B) {
38 for i := 0; i < b.N; i++ {
39 for j := 0; j < 100; j++ {
40 if errfn() == io.EOF {
41 b.Fatal("bad comparison")
42 }
43 }
44 }
45 }
46
47 func BenchmarkIfaceCmpNil100(b *testing.B) {
48 for i := 0; i < b.N; i++ {
49 for j := 0; j < 100; j++ {
50 if errfn1() == nil {
51 b.Fatal("bad comparison")
52 }
53 }
54 }
55 }
56
57 var efaceCmp1 any
58 var efaceCmp2 any
59
60 func BenchmarkEfaceCmpDiff(b *testing.B) {
61 x := 5
62 efaceCmp1 = &x
63 y := 6
64 efaceCmp2 = &y
65 for i := 0; i < b.N; i++ {
66 for j := 0; j < 100; j++ {
67 if efaceCmp1 == efaceCmp2 {
68 b.Fatal("bad comparison")
69 }
70 }
71 }
72 }
73
74 func BenchmarkEfaceCmpDiffIndirect(b *testing.B) {
75 efaceCmp1 = [2]int{1, 2}
76 efaceCmp2 = [2]int{1, 2}
77 for i := 0; i < b.N; i++ {
78 for j := 0; j < 100; j++ {
79 if efaceCmp1 != efaceCmp2 {
80 b.Fatal("bad comparison")
81 }
82 }
83 }
84 }
85
86 func BenchmarkDefer(b *testing.B) {
87 for i := 0; i < b.N; i++ {
88 defer1()
89 }
90 }
91
92 func defer1() {
93 defer func(x, y, z int) {
94 if recover() != nil || x != 1 || y != 2 || z != 3 {
95 panic("bad recover")
96 }
97 }(1, 2, 3)
98 }
99
100 func BenchmarkDefer10(b *testing.B) {
101 for i := 0; i < b.N/10; i++ {
102 defer2()
103 }
104 }
105
106 func defer2() {
107 for i := 0; i < 10; i++ {
108 defer func(x, y, z int) {
109 if recover() != nil || x != 1 || y != 2 || z != 3 {
110 panic("bad recover")
111 }
112 }(1, 2, 3)
113 }
114 }
115
116 func BenchmarkDeferMany(b *testing.B) {
117 for i := 0; i < b.N; i++ {
118 defer func(x, y, z int) {
119 if recover() != nil || x != 1 || y != 2 || z != 3 {
120 panic("bad recover")
121 }
122 }(1, 2, 3)
123 }
124 }
125
126 func BenchmarkPanicRecover(b *testing.B) {
127 for i := 0; i < b.N; i++ {
128 defer3()
129 }
130 }
131
132 func defer3() {
133 defer func(x, y, z int) {
134 if recover() == nil {
135 panic("failed recover")
136 }
137 }(1, 2, 3)
138 panic("hi")
139 }
140
141
142 func TestStopCPUProfilingWithProfilerOff(t *testing.T) {
143 SetCPUProfileRate(0)
144 }
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159 var faultAddrs = []uint64{
160
161 0,
162 1,
163 0xfff,
164
165
166 0xffffffffffffffff,
167 0xfffffffffffff001,
168 0xffffffffffff0001,
169 0xfffffffffff00001,
170 0xffffffffff000001,
171 0xfffffffff0000001,
172 0xffffffff00000001,
173 0xfffffff000000001,
174 0xffffff0000000001,
175 0xfffff00000000001,
176 0xffff000000000001,
177 0xfff0000000000001,
178 0xff00000000000001,
179 0xf000000000000001,
180 0x8000000000000001,
181 }
182
183 func TestSetPanicOnFault(t *testing.T) {
184 old := debug.SetPanicOnFault(true)
185 defer debug.SetPanicOnFault(old)
186
187 nfault := 0
188 for _, addr := range faultAddrs {
189 testSetPanicOnFault(t, uintptr(addr), &nfault)
190 }
191 if nfault == 0 {
192 t.Fatalf("none of the addresses faulted")
193 }
194 }
195
196
197
198
199
200 func testSetPanicOnFault(t *testing.T, addr uintptr, nfault *int) {
201 if GOOS == "js" {
202 t.Skip("js does not support catching faults")
203 }
204
205 defer func() {
206 if err := recover(); err != nil {
207 *nfault++
208 }
209 }()
210
211
212
213
214
215 v := *(*byte)(unsafe.Pointer(addr))
216 t.Logf("addr %#x: %#x\n", addr, v)
217 }
218
219 func eqstring_generic(s1, s2 string) bool {
220 if len(s1) != len(s2) {
221 return false
222 }
223
224
225 for i := 0; i < len(s1); i++ {
226 if s1[i] != s2[i] {
227 return false
228 }
229 }
230 return true
231 }
232
233 func TestEqString(t *testing.T) {
234
235
236
237 s := []string{
238 "",
239 "a",
240 "c",
241 "aaa",
242 "ccc",
243 "cccc"[:3],
244 "1234567890",
245 }
246 for _, s1 := range s {
247 for _, s2 := range s {
248 x := s1 == s2
249 y := eqstring_generic(s1, s2)
250 if x != y {
251 t.Errorf(`("%s" == "%s") = %t, want %t`, s1, s2, x, y)
252 }
253 }
254 }
255 }
256
257 func TestTrailingZero(t *testing.T) {
258
259 type T1 struct {
260 n int32
261 z [0]byte
262 }
263 if unsafe.Sizeof(T1{}) != 8 {
264 t.Errorf("sizeof(%#v)==%d, want 8", T1{}, unsafe.Sizeof(T1{}))
265 }
266 type T2 struct {
267 n int64
268 z struct{}
269 }
270 if unsafe.Sizeof(T2{}) != 8+unsafe.Sizeof(uintptr(0)) {
271 t.Errorf("sizeof(%#v)==%d, want %d", T2{}, unsafe.Sizeof(T2{}), 8+unsafe.Sizeof(uintptr(0)))
272 }
273 type T3 struct {
274 n byte
275 z [4]struct{}
276 }
277 if unsafe.Sizeof(T3{}) != 2 {
278 t.Errorf("sizeof(%#v)==%d, want 2", T3{}, unsafe.Sizeof(T3{}))
279 }
280
281 type T4 struct {
282 a int32
283 b int16
284 c int8
285 z struct{}
286 }
287 if unsafe.Sizeof(T4{}) != 8 {
288 t.Errorf("sizeof(%#v)==%d, want 8", T4{}, unsafe.Sizeof(T4{}))
289 }
290
291 type T5 struct {
292 }
293 if unsafe.Sizeof(T5{}) != 0 {
294 t.Errorf("sizeof(%#v)==%d, want 0", T5{}, unsafe.Sizeof(T5{}))
295 }
296 }
297
298 func TestAppendGrowth(t *testing.T) {
299 var x []int64
300 check := func(want int) {
301 if cap(x) != want {
302 t.Errorf("len=%d, cap=%d, want cap=%d", len(x), cap(x), want)
303 }
304 }
305
306 check(0)
307 want := 1
308 for i := 1; i <= 100; i++ {
309 x = append(x, 1)
310 check(want)
311 if i&(i-1) == 0 {
312 want = 2 * i
313 }
314 }
315 }
316
317 var One = []int64{1}
318
319 func TestAppendSliceGrowth(t *testing.T) {
320 var x []int64
321 check := func(want int) {
322 if cap(x) != want {
323 t.Errorf("len=%d, cap=%d, want cap=%d", len(x), cap(x), want)
324 }
325 }
326
327 check(0)
328 want := 1
329 for i := 1; i <= 100; i++ {
330 x = append(x, One...)
331 check(want)
332 if i&(i-1) == 0 {
333 want = 2 * i
334 }
335 }
336 }
337
338 func TestGoroutineProfileTrivial(t *testing.T) {
339
340
341
342
343 for i := 0; ; i++ {
344 n1, ok := GoroutineProfile(nil)
345 if n1 < 1 || ok {
346 t.Fatalf("GoroutineProfile(nil) = %d, %v, want >0, false", n1, ok)
347 }
348 n2, ok := GoroutineProfile(make([]StackRecord, n1))
349 if n2 == n1 && ok {
350 break
351 }
352 t.Logf("GoroutineProfile(%d) = %d, %v, want %d, true", n1, n2, ok, n1)
353 if i >= 10 {
354 t.Fatalf("GoroutineProfile not converging")
355 }
356 }
357 }
358
359 func TestVersion(t *testing.T) {
360
361 vers := Version()
362 if strings.Contains(vers, "\r") || strings.Contains(vers, "\n") {
363 t.Fatalf("cr/nl in version: %q", vers)
364 }
365 }
366
367 func TestTimediv(t *testing.T) {
368 for _, tc := range []struct {
369 num int64
370 div int32
371 ret int32
372 rem int32
373 }{
374 {
375 num: 8,
376 div: 2,
377 ret: 4,
378 rem: 0,
379 },
380 {
381 num: 9,
382 div: 2,
383 ret: 4,
384 rem: 1,
385 },
386 {
387
388 num: 12345*1000000000 + 54321,
389 div: 1000000000,
390 ret: 12345,
391 rem: 54321,
392 },
393 {
394 num: 1<<32 - 1,
395 div: 2,
396 ret: 1<<31 - 1,
397 rem: 1,
398 },
399 {
400 num: 1 << 32,
401 div: 2,
402 ret: 1<<31 - 1,
403 rem: 0,
404 },
405 {
406 num: 1 << 40,
407 div: 2,
408 ret: 1<<31 - 1,
409 rem: 0,
410 },
411 {
412 num: 1<<40 + 1,
413 div: 1 << 10,
414 ret: 1 << 30,
415 rem: 1,
416 },
417 } {
418 name := fmt.Sprintf("%d div %d", tc.num, tc.div)
419 t.Run(name, func(t *testing.T) {
420
421
422 ret64 := tc.num / int64(tc.div)
423 rem64 := tc.num % int64(tc.div)
424 if ret64 != int64(int32(ret64)) {
425
426 ret64 = 1<<31 - 1
427 rem64 = 0
428 }
429 if ret64 != int64(tc.ret) {
430 t.Errorf("%d / %d got ret %d rem %d want ret %d rem %d", tc.num, tc.div, ret64, rem64, tc.ret, tc.rem)
431 }
432
433 var rem int32
434 ret := Timediv(tc.num, tc.div, &rem)
435 if ret != tc.ret || rem != tc.rem {
436 t.Errorf("timediv %d / %d got ret %d rem %d want ret %d rem %d", tc.num, tc.div, ret, rem, tc.ret, tc.rem)
437 }
438 })
439 }
440 }
441
View as plain text