github.com/razvanm/vanadium-go-1.3@v0.0.0-20160721203343-4a65068e5915/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 "io/ioutil" 10 "os" 11 "os/exec" 12 . "runtime" 13 "runtime/debug" 14 "strconv" 15 "strings" 16 "testing" 17 "unsafe" 18 ) 19 20 var errf error 21 22 func errfn() error { 23 return errf 24 } 25 26 func errfn1() error { 27 return io.EOF 28 } 29 30 func BenchmarkIfaceCmp100(b *testing.B) { 31 for i := 0; i < b.N; i++ { 32 for j := 0; j < 100; j++ { 33 if errfn() == io.EOF { 34 b.Fatal("bad comparison") 35 } 36 } 37 } 38 } 39 40 func BenchmarkIfaceCmpNil100(b *testing.B) { 41 for i := 0; i < b.N; i++ { 42 for j := 0; j < 100; j++ { 43 if errfn1() == nil { 44 b.Fatal("bad comparison") 45 } 46 } 47 } 48 } 49 50 func BenchmarkDefer(b *testing.B) { 51 for i := 0; i < b.N; i++ { 52 defer1() 53 } 54 } 55 56 func defer1() { 57 defer func(x, y, z int) { 58 if recover() != nil || x != 1 || y != 2 || z != 3 { 59 panic("bad recover") 60 } 61 }(1, 2, 3) 62 return 63 } 64 65 func BenchmarkDefer10(b *testing.B) { 66 for i := 0; i < b.N/10; i++ { 67 defer2() 68 } 69 } 70 71 func defer2() { 72 for i := 0; i < 10; i++ { 73 defer func(x, y, z int) { 74 if recover() != nil || x != 1 || y != 2 || z != 3 { 75 panic("bad recover") 76 } 77 }(1, 2, 3) 78 } 79 } 80 81 func BenchmarkDeferMany(b *testing.B) { 82 for i := 0; i < b.N; i++ { 83 defer func(x, y, z int) { 84 if recover() != nil || x != 1 || y != 2 || z != 3 { 85 panic("bad recover") 86 } 87 }(1, 2, 3) 88 } 89 } 90 91 // The profiling signal handler needs to know whether it is executing runtime.gogo. 92 // The constant RuntimeGogoBytes in arch_*.h gives the size of the function; 93 // we don't have a way to obtain it from the linker (perhaps someday). 94 // Test that the constant matches the size determined by 'go tool nm -S'. 95 // The value reported will include the padding between runtime.gogo and the 96 // next function in memory. That's fine. 97 func TestRuntimeGogoBytes(t *testing.T) { 98 switch GOOS { 99 case "android", "nacl": 100 t.Skipf("skipping on %s", GOOS) 101 } 102 103 dir, err := ioutil.TempDir("", "go-build") 104 if err != nil { 105 t.Fatalf("failed to create temp directory: %v", err) 106 } 107 defer os.RemoveAll(dir) 108 109 out, err := exec.Command("go", "build", "-o", dir+"/hello", "../../test/helloworld.go").CombinedOutput() 110 if err != nil { 111 t.Fatalf("building hello world: %v\n%s", err, out) 112 } 113 114 out, err = exec.Command("go", "tool", "nm", "-size", dir+"/hello").CombinedOutput() 115 if err != nil { 116 t.Fatalf("go tool nm: %v\n%s", err, out) 117 } 118 119 for _, line := range strings.Split(string(out), "\n") { 120 f := strings.Fields(line) 121 if len(f) == 4 && f[3] == "runtime.gogo" { 122 size, _ := strconv.Atoi(f[1]) 123 if GogoBytes() != int32(size) { 124 t.Fatalf("RuntimeGogoBytes = %d, should be %d", GogoBytes(), size) 125 } 126 return 127 } 128 } 129 130 t.Fatalf("go tool nm did not report size for runtime.gogo") 131 } 132 133 // golang.org/issue/7063 134 func TestStopCPUProfilingWithProfilerOff(t *testing.T) { 135 SetCPUProfileRate(0) 136 } 137 138 // Addresses to test for faulting behavior. 139 // This is less a test of SetPanicOnFault and more a check that 140 // the operating system and the runtime can process these faults 141 // correctly. That is, we're indirectly testing that without SetPanicOnFault 142 // these would manage to turn into ordinary crashes. 143 // Note that these are truncated on 32-bit systems, so the bottom 32 bits 144 // of the larger addresses must themselves be invalid addresses. 145 // We might get unlucky and the OS might have mapped one of these 146 // addresses, but probably not: they're all in the first page, very high 147 // adderesses that normally an OS would reserve for itself, or malformed 148 // addresses. Even so, we might have to remove one or two on different 149 // systems. We will see. 150 151 var faultAddrs = []uint64{ 152 // low addresses 153 0, 154 1, 155 0xfff, 156 // high (kernel) addresses 157 // or else malformed. 158 0xffffffffffffffff, 159 0xfffffffffffff001, 160 0xffffffffffff0001, 161 0xfffffffffff00001, 162 0xffffffffff000001, 163 0xfffffffff0000001, 164 0xffffffff00000001, 165 0xfffffff000000001, 166 0xffffff0000000001, 167 0xfffff00000000001, 168 0xffff000000000001, 169 0xfff0000000000001, 170 0xff00000000000001, 171 0xf000000000000001, 172 0x8000000000000001, 173 } 174 175 func TestSetPanicOnFault(t *testing.T) { 176 // This currently results in a fault in the signal trampoline on 177 // dragonfly/386 - see issue 7421. 178 if GOOS == "dragonfly" && GOARCH == "386" { 179 t.Skip("skipping test on dragonfly/386") 180 } 181 182 old := debug.SetPanicOnFault(true) 183 defer debug.SetPanicOnFault(old) 184 185 nfault := 0 186 for _, addr := range faultAddrs { 187 testSetPanicOnFault(t, uintptr(addr), &nfault) 188 } 189 if nfault == 0 { 190 t.Fatalf("none of the addresses faulted") 191 } 192 } 193 194 func testSetPanicOnFault(t *testing.T, addr uintptr, nfault *int) { 195 if GOOS == "nacl" { 196 t.Skip("nacl doesn't seem to fault on high addresses") 197 } 198 199 defer func() { 200 if err := recover(); err != nil { 201 *nfault++ 202 } 203 }() 204 205 // The read should fault, except that sometimes we hit 206 // addresses that have had C or kernel pages mapped there 207 // readable by user code. So just log the content. 208 // If no addresses fault, we'll fail the test. 209 v := *(*byte)(unsafe.Pointer(addr)) 210 t.Logf("addr %#x: %#x\n", addr, v) 211 } 212 213 func eqstring_generic(s1, s2 string) bool { 214 if len(s1) != len(s2) { 215 return false 216 } 217 // optimization in assembly versions: 218 // if s1.str == s2.str { return true } 219 for i := 0; i < len(s1); i++ { 220 if s1[i] != s2[i] { 221 return false 222 } 223 } 224 return true 225 } 226 227 func TestEqString(t *testing.T) { 228 // This isn't really an exhaustive test of eqstring, it's 229 // just a convenient way of documenting (via eqstring_generic) 230 // what eqstring does. 231 s := []string{ 232 "", 233 "a", 234 "c", 235 "aaa", 236 "ccc", 237 "cccc"[:3], // same contents, different string 238 "1234567890", 239 } 240 for _, s1 := range s { 241 for _, s2 := range s { 242 x := s1 == s2 243 y := eqstring_generic(s1, s2) 244 if x != y { 245 t.Errorf(`eqstring("%s","%s") = %t, want %t`, s1, s2, x, y) 246 } 247 } 248 } 249 }