...

Source file src/runtime/runtime_test.go

Documentation: runtime

		 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  }
	 365  

View as plain text