1 // Copyright 2012 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 "io" 9 . "runtime" 10 "runtime/debug" 11 "strings" 12 "testing" 13 "unsafe" 14 ) 15 16 func init() { 17 // We're testing the runtime, so make tracebacks show things 18 // in the runtime. This only raises the level, so it won't 19 // override GOTRACEBACK=crash from the user. 20 SetTracebackEnv("system") 21 } 22 23 var errf error 24 25 func errfn() error { 26 return errf 27 } 28 29 func errfn1() error { 30 return io.EOF 31 } 32 33 func BenchmarkIfaceCmp100(b *testing.B) { 34 for i := 0; i < b.N; i++ { 35 for j := 0; j < 100; j++ { 36 if errfn() == io.EOF { 37 b.Fatal("bad comparison") 38 } 39 } 40 } 41 } 42 43 func BenchmarkIfaceCmpNil100(b *testing.B) { 44 for i := 0; i < b.N; i++ { 45 for j := 0; j < 100; j++ { 46 if errfn1() == nil { 47 b.Fatal("bad comparison") 48 } 49 } 50 } 51 } 52 53 func BenchmarkDefer(b *testing.B) { 54 for i := 0; i < b.N; i++ { 55 defer1() 56 } 57 } 58 59 func defer1() { 60 defer func(x, y, z int) { 61 if recover() != nil || x != 1 || y != 2 || z != 3 { 62 panic("bad recover") 63 } 64 }(1, 2, 3) 65 return 66 } 67 68 func BenchmarkDefer10(b *testing.B) { 69 for i := 0; i < b.N/10; i++ { 70 defer2() 71 } 72 } 73 74 func defer2() { 75 for i := 0; i < 10; i++ { 76 defer func(x, y, z int) { 77 if recover() != nil || x != 1 || y != 2 || z != 3 { 78 panic("bad recover") 79 } 80 }(1, 2, 3) 81 } 82 } 83 84 func BenchmarkDeferMany(b *testing.B) { 85 for i := 0; i < b.N; i++ { 86 defer func(x, y, z int) { 87 if recover() != nil || x != 1 || y != 2 || z != 3 { 88 panic("bad recover") 89 } 90 }(1, 2, 3) 91 } 92 } 93 94 // golang.org/issue/7063 95 func TestStopCPUProfilingWithProfilerOff(t *testing.T) { 96 SetCPUProfileRate(0) 97 } 98 99 // Addresses to test for faulting behavior. 100 // This is less a test of SetPanicOnFault and more a check that 101 // the operating system and the runtime can process these faults 102 // correctly. That is, we're indirectly testing that without SetPanicOnFault 103 // these would manage to turn into ordinary crashes. 104 // Note that these are truncated on 32-bit systems, so the bottom 32 bits 105 // of the larger addresses must themselves be invalid addresses. 106 // We might get unlucky and the OS might have mapped one of these 107 // addresses, but probably not: they're all in the first page, very high 108 // addresses that normally an OS would reserve for itself, or malformed 109 // addresses. Even so, we might have to remove one or two on different 110 // systems. We will see. 111 112 var faultAddrs = []uint64{ 113 // low addresses 114 0, 115 1, 116 0xfff, 117 // high (kernel) addresses 118 // or else malformed. 119 0xffffffffffffffff, 120 0xfffffffffffff001, 121 0xffffffffffff0001, 122 0xfffffffffff00001, 123 0xffffffffff000001, 124 0xfffffffff0000001, 125 0xffffffff00000001, 126 0xfffffff000000001, 127 0xffffff0000000001, 128 0xfffff00000000001, 129 0xffff000000000001, 130 0xfff0000000000001, 131 0xff00000000000001, 132 0xf000000000000001, 133 0x8000000000000001, 134 } 135 136 func TestSetPanicOnFault(t *testing.T) { 137 old := debug.SetPanicOnFault(true) 138 defer debug.SetPanicOnFault(old) 139 140 nfault := 0 141 for _, addr := range faultAddrs { 142 testSetPanicOnFault(t, uintptr(addr), &nfault) 143 } 144 if nfault == 0 { 145 t.Fatalf("none of the addresses faulted") 146 } 147 } 148 149 func testSetPanicOnFault(t *testing.T, addr uintptr, nfault *int) { 150 if GOOS == "nacl" { 151 t.Skip("nacl doesn't seem to fault on high addresses") 152 } 153 154 defer func() { 155 if err := recover(); err != nil { 156 *nfault++ 157 } 158 }() 159 160 // The read should fault, except that sometimes we hit 161 // addresses that have had C or kernel pages mapped there 162 // readable by user code. So just log the content. 163 // If no addresses fault, we'll fail the test. 164 v := *(*byte)(unsafe.Pointer(addr)) 165 t.Logf("addr %#x: %#x\n", addr, v) 166 } 167 168 func eqstring_generic(s1, s2 string) bool { 169 if len(s1) != len(s2) { 170 return false 171 } 172 // optimization in assembly versions: 173 // if s1.str == s2.str { return true } 174 for i := 0; i < len(s1); i++ { 175 if s1[i] != s2[i] { 176 return false 177 } 178 } 179 return true 180 } 181 182 func TestEqString(t *testing.T) { 183 // This isn't really an exhaustive test of eqstring, it's 184 // just a convenient way of documenting (via eqstring_generic) 185 // what eqstring does. 186 s := []string{ 187 "", 188 "a", 189 "c", 190 "aaa", 191 "ccc", 192 "cccc"[:3], // same contents, different string 193 "1234567890", 194 } 195 for _, s1 := range s { 196 for _, s2 := range s { 197 x := s1 == s2 198 y := eqstring_generic(s1, s2) 199 if x != y { 200 t.Errorf(`eqstring("%s","%s") = %t, want %t`, s1, s2, x, y) 201 } 202 } 203 } 204 } 205 206 func TestTrailingZero(t *testing.T) { 207 // make sure we add padding for structs with trailing zero-sized fields 208 type T1 struct { 209 n int32 210 z [0]byte 211 } 212 if unsafe.Sizeof(T1{}) != 8 { 213 t.Errorf("sizeof(%#v)==%d, want 8", T1{}, unsafe.Sizeof(T1{})) 214 } 215 type T2 struct { 216 n int64 217 z struct{} 218 } 219 if unsafe.Sizeof(T2{}) != 8+unsafe.Sizeof(Uintreg(0)) { 220 t.Errorf("sizeof(%#v)==%d, want %d", T2{}, unsafe.Sizeof(T2{}), 8+unsafe.Sizeof(Uintreg(0))) 221 } 222 type T3 struct { 223 n byte 224 z [4]struct{} 225 } 226 if unsafe.Sizeof(T3{}) != 2 { 227 t.Errorf("sizeof(%#v)==%d, want 2", T3{}, unsafe.Sizeof(T3{})) 228 } 229 // make sure padding can double for both zerosize and alignment 230 type T4 struct { 231 a int32 232 b int16 233 c int8 234 z struct{} 235 } 236 if unsafe.Sizeof(T4{}) != 8 { 237 t.Errorf("sizeof(%#v)==%d, want 8", T4{}, unsafe.Sizeof(T4{})) 238 } 239 // make sure we don't pad a zero-sized thing 240 type T5 struct { 241 } 242 if unsafe.Sizeof(T5{}) != 0 { 243 t.Errorf("sizeof(%#v)==%d, want 0", T5{}, unsafe.Sizeof(T5{})) 244 } 245 } 246 247 func TestBadOpen(t *testing.T) { 248 if GOOS == "windows" || GOOS == "nacl" { 249 t.Skip("skipping OS that doesn't have open/read/write/close") 250 } 251 // make sure we get the correct error code if open fails. Same for 252 // read/write/close on the resulting -1 fd. See issue 10052. 253 nonfile := []byte("/notreallyafile") 254 fd := Open(&nonfile[0], 0, 0) 255 if fd != -1 { 256 t.Errorf("open(\"%s\")=%d, want -1", string(nonfile), fd) 257 } 258 var buf [32]byte 259 r := Read(-1, unsafe.Pointer(&buf[0]), int32(len(buf))) 260 if r != -1 { 261 t.Errorf("read()=%d, want -1", r) 262 } 263 w := Write(^uintptr(0), unsafe.Pointer(&buf[0]), int32(len(buf))) 264 if w != -1 { 265 t.Errorf("write()=%d, want -1", w) 266 } 267 c := Close(-1) 268 if c != -1 { 269 t.Errorf("close()=%d, want -1", c) 270 } 271 } 272 273 func TestAppendGrowth(t *testing.T) { 274 var x []int64 275 check := func(want int) { 276 if cap(x) != want { 277 t.Errorf("len=%d, cap=%d, want cap=%d", len(x), cap(x), want) 278 } 279 } 280 281 check(0) 282 want := 1 283 for i := 1; i <= 100; i++ { 284 x = append(x, 1) 285 check(want) 286 if i&(i-1) == 0 { 287 want = 2 * i 288 } 289 } 290 } 291 292 var One = []int64{1} 293 294 func TestAppendSliceGrowth(t *testing.T) { 295 var x []int64 296 check := func(want int) { 297 if cap(x) != want { 298 t.Errorf("len=%d, cap=%d, want cap=%d", len(x), cap(x), want) 299 } 300 } 301 302 check(0) 303 want := 1 304 for i := 1; i <= 100; i++ { 305 x = append(x, One...) 306 check(want) 307 if i&(i-1) == 0 { 308 want = 2 * i 309 } 310 } 311 } 312 313 func TestGoroutineProfileTrivial(t *testing.T) { 314 // Calling GoroutineProfile twice in a row should find the same number of goroutines, 315 // but it's possible there are goroutines just about to exit, so we might end up 316 // with fewer in the second call. Try a few times; it should converge once those 317 // zombies are gone. 318 for i := 0; ; i++ { 319 n1, ok := GoroutineProfile(nil) // should fail, there's at least 1 goroutine 320 if n1 < 1 || ok { 321 t.Fatalf("GoroutineProfile(nil) = %d, %v, want >0, false", n1, ok) 322 } 323 n2, ok := GoroutineProfile(make([]StackRecord, n1)) 324 if n2 == n1 && ok { 325 break 326 } 327 t.Logf("GoroutineProfile(%d) = %d, %v, want %d, true", n1, n2, ok, n1) 328 if i >= 10 { 329 t.Fatalf("GoroutineProfile not converging") 330 } 331 } 332 } 333 334 func TestVersion(t *testing.T) { 335 // Test that version does not contain \r or \n. 336 vers := Version() 337 if strings.Contains(vers, "\r") || strings.Contains(vers, "\n") { 338 t.Fatalf("cr/nl in version: %q", vers) 339 } 340 } 341