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