blob: d5b6b3ac3ce53e0a9ffe208e49fde63a469d36f6 [file] [log] [blame]
Brad Fitzpatrick51947442016-03-01 22:57:46 +00001// Copyright 2012 The Go Authors. All rights reserved.
Russ Coxf91cc3b2012-02-11 00:19:24 -05002// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package runtime_test
6
7import (
Russ Cox94471f62017-10-27 13:30:09 -04008 "flag"
Russ Coxf91cc3b2012-02-11 00:19:24 -05009 "io"
Russ Cox439f9392013-09-13 14:19:23 -040010 . "runtime"
Russ Coxe56c6e72014-02-20 16:18:05 -050011 "runtime/debug"
Russ Cox7e9fa3c2016-12-05 11:11:47 -050012 "strings"
Russ Coxf91cc3b2012-02-11 00:19:24 -050013 "testing"
Russ Coxe56c6e72014-02-20 16:18:05 -050014 "unsafe"
Russ Coxf91cc3b2012-02-11 00:19:24 -050015)
16
Russ Cox94471f62017-10-27 13:30:09 -040017var flagQuick = flag.Bool("quick", false, "skip slow tests, for second run in all.bash")
18
Austin Clements1556c312016-01-14 16:43:40 -050019func init() {
20 // We're testing the runtime, so make tracebacks show things
21 // in the runtime. This only raises the level, so it won't
22 // override GOTRACEBACK=crash from the user.
23 SetTracebackEnv("system")
24}
25
Russ Coxf91cc3b2012-02-11 00:19:24 -050026var errf error
27
28func errfn() error {
29 return errf
30}
31
32func errfn1() error {
33 return io.EOF
34}
35
36func BenchmarkIfaceCmp100(b *testing.B) {
37 for i := 0; i < b.N; i++ {
38 for j := 0; j < 100; j++ {
39 if errfn() == io.EOF {
40 b.Fatal("bad comparison")
41 }
42 }
43 }
44}
45
46func BenchmarkIfaceCmpNil100(b *testing.B) {
47 for i := 0; i < b.N; i++ {
48 for j := 0; j < 100; j++ {
49 if errfn1() == nil {
50 b.Fatal("bad comparison")
51 }
52 }
53 }
54}
Russ Cox0de71612012-12-22 14:54:39 -050055
Keith Randalle67d8812017-03-24 14:03:15 -070056var efaceCmp1 interface{}
57var efaceCmp2 interface{}
58
59func BenchmarkEfaceCmpDiff(b *testing.B) {
60 x := 5
61 efaceCmp1 = &x
62 y := 6
63 efaceCmp2 = &y
64 for i := 0; i < b.N; i++ {
65 for j := 0; j < 100; j++ {
66 if efaceCmp1 == efaceCmp2 {
67 b.Fatal("bad comparison")
68 }
69 }
70 }
71}
72
Russ Cox0de71612012-12-22 14:54:39 -050073func BenchmarkDefer(b *testing.B) {
74 for i := 0; i < b.N; i++ {
75 defer1()
76 }
77}
78
79func defer1() {
80 defer func(x, y, z int) {
81 if recover() != nil || x != 1 || y != 2 || z != 3 {
82 panic("bad recover")
83 }
84 }(1, 2, 3)
Russ Cox0de71612012-12-22 14:54:39 -050085}
86
87func BenchmarkDefer10(b *testing.B) {
88 for i := 0; i < b.N/10; i++ {
89 defer2()
90 }
91}
92
93func defer2() {
94 for i := 0; i < 10; i++ {
95 defer func(x, y, z int) {
96 if recover() != nil || x != 1 || y != 2 || z != 3 {
97 panic("bad recover")
98 }
99 }(1, 2, 3)
100 }
101}
102
103func BenchmarkDeferMany(b *testing.B) {
104 for i := 0; i < b.N; i++ {
105 defer func(x, y, z int) {
106 if recover() != nil || x != 1 || y != 2 || z != 3 {
107 panic("bad recover")
108 }
109 }(1, 2, 3)
110 }
111}
Russ Cox439f9392013-09-13 14:19:23 -0400112
Emil Hessmanaeeda702014-01-06 09:53:55 -0800113// golang.org/issue/7063
114func TestStopCPUProfilingWithProfilerOff(t *testing.T) {
115 SetCPUProfileRate(0)
116}
Russ Coxe56c6e72014-02-20 16:18:05 -0500117
Russ Cox17f94232014-04-03 19:07:33 -0400118// Addresses to test for faulting behavior.
119// This is less a test of SetPanicOnFault and more a check that
120// the operating system and the runtime can process these faults
121// correctly. That is, we're indirectly testing that without SetPanicOnFault
122// these would manage to turn into ordinary crashes.
123// Note that these are truncated on 32-bit systems, so the bottom 32 bits
124// of the larger addresses must themselves be invalid addresses.
125// We might get unlucky and the OS might have mapped one of these
126// addresses, but probably not: they're all in the first page, very high
Martin Möhrmannfdd01792016-02-24 11:55:20 +0100127// addresses that normally an OS would reserve for itself, or malformed
Russ Cox17f94232014-04-03 19:07:33 -0400128// addresses. Even so, we might have to remove one or two on different
129// systems. We will see.
130
131var faultAddrs = []uint64{
132 // low addresses
133 0,
134 1,
135 0xfff,
136 // high (kernel) addresses
137 // or else malformed.
138 0xffffffffffffffff,
139 0xfffffffffffff001,
Russ Cox5fdea342014-09-18 21:43:09 -0400140 0xffffffffffff0001,
141 0xfffffffffff00001,
Russ Cox17f94232014-04-03 19:07:33 -0400142 0xffffffffff000001,
143 0xfffffffff0000001,
144 0xffffffff00000001,
145 0xfffffff000000001,
146 0xffffff0000000001,
147 0xfffff00000000001,
148 0xffff000000000001,
149 0xfff0000000000001,
150 0xff00000000000001,
151 0xf000000000000001,
152 0x8000000000000001,
153}
154
Russ Coxe56c6e72014-02-20 16:18:05 -0500155func TestSetPanicOnFault(t *testing.T) {
156 old := debug.SetPanicOnFault(true)
157 defer debug.SetPanicOnFault(old)
158
Russ Cox5fdea342014-09-18 21:43:09 -0400159 nfault := 0
Russ Cox17f94232014-04-03 19:07:33 -0400160 for _, addr := range faultAddrs {
Russ Cox5fdea342014-09-18 21:43:09 -0400161 testSetPanicOnFault(t, uintptr(addr), &nfault)
162 }
163 if nfault == 0 {
164 t.Fatalf("none of the addresses faulted")
Russ Cox17f94232014-04-03 19:07:33 -0400165 }
166}
167
Russ Cox5fdea342014-09-18 21:43:09 -0400168func testSetPanicOnFault(t *testing.T, addr uintptr, nfault *int) {
Russ Cox0c2a7272014-05-20 12:10:19 -0400169 if GOOS == "nacl" {
170 t.Skip("nacl doesn't seem to fault on high addresses")
171 }
172
Russ Coxe56c6e72014-02-20 16:18:05 -0500173 defer func() {
Russ Cox5fdea342014-09-18 21:43:09 -0400174 if err := recover(); err != nil {
175 *nfault++
Russ Coxe56c6e72014-02-20 16:18:05 -0500176 }
177 }()
178
Russ Cox5fdea342014-09-18 21:43:09 -0400179 // The read should fault, except that sometimes we hit
180 // addresses that have had C or kernel pages mapped there
181 // readable by user code. So just log the content.
182 // If no addresses fault, we'll fail the test.
Keith Randall3b2577c2014-09-20 23:31:11 -0700183 v := *(*byte)(unsafe.Pointer(addr))
184 t.Logf("addr %#x: %#x\n", addr, v)
Russ Coxe56c6e72014-02-20 16:18:05 -0500185}
Keith Randallb36ed902014-06-16 21:00:37 -0700186
187func eqstring_generic(s1, s2 string) bool {
188 if len(s1) != len(s2) {
189 return false
190 }
191 // optimization in assembly versions:
192 // if s1.str == s2.str { return true }
193 for i := 0; i < len(s1); i++ {
194 if s1[i] != s2[i] {
195 return false
196 }
197 }
198 return true
199}
200
201func TestEqString(t *testing.T) {
Martin Möhrmann3216e0c2017-08-07 22:36:22 +0200202 // This isn't really an exhaustive test of == on strings, it's
Keith Randallb36ed902014-06-16 21:00:37 -0700203 // just a convenient way of documenting (via eqstring_generic)
Martin Möhrmann3216e0c2017-08-07 22:36:22 +0200204 // what == does.
Keith Randallb36ed902014-06-16 21:00:37 -0700205 s := []string{
206 "",
207 "a",
208 "c",
209 "aaa",
210 "ccc",
211 "cccc"[:3], // same contents, different string
212 "1234567890",
213 }
214 for _, s1 := range s {
215 for _, s2 := range s {
216 x := s1 == s2
217 y := eqstring_generic(s1, s2)
218 if x != y {
Martin Möhrmann3216e0c2017-08-07 22:36:22 +0200219 t.Errorf(`("%s" == "%s") = %t, want %t`, s1, s2, x, y)
Keith Randallb36ed902014-06-16 21:00:37 -0700220 }
221 }
222 }
223}
Keith Randall6f07ac22015-01-07 09:25:23 -0800224
225func TestTrailingZero(t *testing.T) {
226 // make sure we add padding for structs with trailing zero-sized fields
227 type T1 struct {
228 n int32
229 z [0]byte
230 }
231 if unsafe.Sizeof(T1{}) != 8 {
232 t.Errorf("sizeof(%#v)==%d, want 8", T1{}, unsafe.Sizeof(T1{}))
233 }
234 type T2 struct {
235 n int64
236 z struct{}
237 }
David Crawshaw1e0e2ff2015-02-26 10:01:37 -0500238 if unsafe.Sizeof(T2{}) != 8+unsafe.Sizeof(Uintreg(0)) {
239 t.Errorf("sizeof(%#v)==%d, want %d", T2{}, unsafe.Sizeof(T2{}), 8+unsafe.Sizeof(Uintreg(0)))
Keith Randall6f07ac22015-01-07 09:25:23 -0800240 }
241 type T3 struct {
242 n byte
243 z [4]struct{}
244 }
245 if unsafe.Sizeof(T3{}) != 2 {
246 t.Errorf("sizeof(%#v)==%d, want 2", T3{}, unsafe.Sizeof(T3{}))
247 }
248 // make sure padding can double for both zerosize and alignment
249 type T4 struct {
250 a int32
251 b int16
252 c int8
253 z struct{}
254 }
255 if unsafe.Sizeof(T4{}) != 8 {
256 t.Errorf("sizeof(%#v)==%d, want 8", T4{}, unsafe.Sizeof(T4{}))
257 }
258 // make sure we don't pad a zero-sized thing
259 type T5 struct {
260 }
261 if unsafe.Sizeof(T5{}) != 0 {
262 t.Errorf("sizeof(%#v)==%d, want 0", T5{}, unsafe.Sizeof(T5{}))
263 }
264}
Keith Randallf584c052015-03-02 20:16:48 -0800265
266func TestBadOpen(t *testing.T) {
267 if GOOS == "windows" || GOOS == "nacl" {
268 t.Skip("skipping OS that doesn't have open/read/write/close")
269 }
Brad Fitzpatrick5fea2cc2016-03-01 23:21:55 +0000270 // make sure we get the correct error code if open fails. Same for
271 // read/write/close on the resulting -1 fd. See issue 10052.
Keith Randallf584c052015-03-02 20:16:48 -0800272 nonfile := []byte("/notreallyafile")
273 fd := Open(&nonfile[0], 0, 0)
274 if fd != -1 {
275 t.Errorf("open(\"%s\")=%d, want -1", string(nonfile), fd)
276 }
277 var buf [32]byte
278 r := Read(-1, unsafe.Pointer(&buf[0]), int32(len(buf)))
279 if r != -1 {
280 t.Errorf("read()=%d, want -1", r)
281 }
282 w := Write(^uintptr(0), unsafe.Pointer(&buf[0]), int32(len(buf)))
283 if w != -1 {
284 t.Errorf("write()=%d, want -1", w)
285 }
286 c := Close(-1)
287 if c != -1 {
288 t.Errorf("close()=%d, want -1", c)
289 }
290}
Russ Cox32fddad2015-06-25 19:27:20 -0400291
292func TestAppendGrowth(t *testing.T) {
293 var x []int64
294 check := func(want int) {
295 if cap(x) != want {
296 t.Errorf("len=%d, cap=%d, want cap=%d", len(x), cap(x), want)
297 }
298 }
299
300 check(0)
301 want := 1
302 for i := 1; i <= 100; i++ {
303 x = append(x, 1)
304 check(want)
305 if i&(i-1) == 0 {
306 want = 2 * i
307 }
308 }
309}
310
311var One = []int64{1}
312
313func TestAppendSliceGrowth(t *testing.T) {
314 var x []int64
315 check := func(want int) {
316 if cap(x) != want {
317 t.Errorf("len=%d, cap=%d, want cap=%d", len(x), cap(x), want)
318 }
319 }
320
321 check(0)
322 want := 1
323 for i := 1; i <= 100; i++ {
324 x = append(x, One...)
325 check(want)
326 if i&(i-1) == 0 {
327 want = 2 * i
328 }
329 }
330}
Russ Cox313fd1c2016-01-26 22:58:59 -0500331
332func TestGoroutineProfileTrivial(t *testing.T) {
Russ Cox1c6a35b2016-02-02 10:15:34 -0500333 // Calling GoroutineProfile twice in a row should find the same number of goroutines,
334 // but it's possible there are goroutines just about to exit, so we might end up
335 // with fewer in the second call. Try a few times; it should converge once those
336 // zombies are gone.
337 for i := 0; ; i++ {
338 n1, ok := GoroutineProfile(nil) // should fail, there's at least 1 goroutine
339 if n1 < 1 || ok {
340 t.Fatalf("GoroutineProfile(nil) = %d, %v, want >0, false", n1, ok)
341 }
342 n2, ok := GoroutineProfile(make([]StackRecord, n1))
343 if n2 == n1 && ok {
344 break
345 }
346 t.Logf("GoroutineProfile(%d) = %d, %v, want %d, true", n1, n2, ok, n1)
347 if i >= 10 {
348 t.Fatalf("GoroutineProfile not converging")
349 }
Russ Cox313fd1c2016-01-26 22:58:59 -0500350 }
351}
Russ Cox7e9fa3c2016-12-05 11:11:47 -0500352
353func TestVersion(t *testing.T) {
354 // Test that version does not contain \r or \n.
355 vers := Version()
356 if strings.Contains(vers, "\r") || strings.Contains(vers, "\n") {
357 t.Fatalf("cr/nl in version: %q", vers)
358 }
359}