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