github.com/graybobo/golang.org-package-offline-cache@v0.0.0-20200626051047-6608995c132f/x/tools/go/ssa/interp/testdata/coverage.go (about)

     1  // This interpreter test is designed to run very quickly yet provide
     2  // some coverage of a broad selection of constructs.
     3  //
     4  // Validate this file with 'go run' after editing.
     5  // TODO(adonovan): break this into small files organized by theme.
     6  
     7  package main
     8  
     9  import (
    10  	"fmt"
    11  	"reflect"
    12  )
    13  
    14  func init() {
    15  	// Call of variadic function with (implicit) empty slice.
    16  	if x := fmt.Sprint(); x != "" {
    17  		panic(x)
    18  	}
    19  }
    20  
    21  type empty interface{}
    22  
    23  type I interface {
    24  	f() int
    25  }
    26  
    27  type T struct{ z int }
    28  
    29  func (t T) f() int { return t.z }
    30  
    31  func use(interface{}) {}
    32  
    33  var counter = 2
    34  
    35  // Test initialization, including init blocks containing 'return'.
    36  // Assertion is in main.
    37  func init() {
    38  	counter *= 3
    39  	return
    40  	counter *= 3
    41  }
    42  
    43  func init() {
    44  	counter *= 5
    45  	return
    46  	counter *= 5
    47  }
    48  
    49  // Recursion.
    50  func fib(x int) int {
    51  	if x < 2 {
    52  		return x
    53  	}
    54  	return fib(x-1) + fib(x-2)
    55  }
    56  
    57  func fibgen(ch chan int) {
    58  	for x := 0; x < 10; x++ {
    59  		ch <- fib(x)
    60  	}
    61  	close(ch)
    62  }
    63  
    64  // Goroutines and channels.
    65  func init() {
    66  	ch := make(chan int)
    67  	go fibgen(ch)
    68  	var fibs []int
    69  	for v := range ch {
    70  		fibs = append(fibs, v)
    71  		if len(fibs) == 10 {
    72  			break
    73  		}
    74  	}
    75  	if x := fmt.Sprint(fibs); x != "[0 1 1 2 3 5 8 13 21 34]" {
    76  		panic(x)
    77  	}
    78  }
    79  
    80  // Test of aliasing.
    81  func init() {
    82  	type S struct {
    83  		a, b string
    84  	}
    85  
    86  	s1 := []string{"foo", "bar"}
    87  	s2 := s1 // creates an alias
    88  	s2[0] = "wiz"
    89  	if x := fmt.Sprint(s1, s2); x != "[wiz bar] [wiz bar]" {
    90  		panic(x)
    91  	}
    92  
    93  	pa1 := &[2]string{"foo", "bar"}
    94  	pa2 := pa1 // creates an alias
    95  	pa2[0] = "wiz"
    96  	if x := fmt.Sprint(*pa1, *pa2); x != "[wiz bar] [wiz bar]" {
    97  		panic(x)
    98  	}
    99  
   100  	a1 := [2]string{"foo", "bar"}
   101  	a2 := a1 // creates a copy
   102  	a2[0] = "wiz"
   103  	if x := fmt.Sprint(a1, a2); x != "[foo bar] [wiz bar]" {
   104  		panic(x)
   105  	}
   106  
   107  	t1 := S{"foo", "bar"}
   108  	t2 := t1 // copy
   109  	t2.a = "wiz"
   110  	if x := fmt.Sprint(t1, t2); x != "{foo bar} {wiz bar}" {
   111  		panic(x)
   112  	}
   113  }
   114  
   115  func main() {
   116  	print() // legal
   117  
   118  	if counter != 2*3*5 {
   119  		panic(counter)
   120  	}
   121  
   122  	// Test builtins (e.g. complex) preserve named argument types.
   123  	type N complex128
   124  	var n N
   125  	n = complex(1.0, 2.0)
   126  	if n != complex(1.0, 2.0) {
   127  		panic(n)
   128  	}
   129  	if x := reflect.TypeOf(n).String(); x != "main.N" {
   130  		panic(x)
   131  	}
   132  	if real(n) != 1.0 || imag(n) != 2.0 {
   133  		panic(n)
   134  	}
   135  
   136  	// Channel + select.
   137  	ch := make(chan int, 1)
   138  	select {
   139  	case ch <- 1:
   140  		// ok
   141  	default:
   142  		panic("couldn't send")
   143  	}
   144  	if <-ch != 1 {
   145  		panic("couldn't receive")
   146  	}
   147  	// A "receive" select-case that doesn't declare its vars.  (regression test)
   148  	anint := 0
   149  	ok := false
   150  	select {
   151  	case anint, ok = <-ch:
   152  	case anint = <-ch:
   153  	default:
   154  	}
   155  	_ = anint
   156  	_ = ok
   157  
   158  	// Anon structs with methods.
   159  	anon := struct{ T }{T: T{z: 1}}
   160  	if x := anon.f(); x != 1 {
   161  		panic(x)
   162  	}
   163  	var i I = anon
   164  	if x := i.f(); x != 1 {
   165  		panic(x)
   166  	}
   167  	// NB. precise output of reflect.Type.String is undefined.
   168  	if x := reflect.TypeOf(i).String(); x != "struct { main.T }" && x != "struct{main.T}" {
   169  		panic(x)
   170  	}
   171  
   172  	// fmt.
   173  	const message = "Hello, World!"
   174  	if fmt.Sprintf("%s, %s!", "Hello", "World") != message {
   175  		panic("oops")
   176  	}
   177  
   178  	// Type assertion.
   179  	type S struct {
   180  		f int
   181  	}
   182  	var e empty = S{f: 42}
   183  	switch v := e.(type) {
   184  	case S:
   185  		if v.f != 42 {
   186  			panic(v.f)
   187  		}
   188  	default:
   189  		panic(reflect.TypeOf(v))
   190  	}
   191  	if i, ok := e.(I); ok {
   192  		panic(i)
   193  	}
   194  
   195  	// Switch.
   196  	var x int
   197  	switch x {
   198  	case 1:
   199  		panic(x)
   200  		fallthrough
   201  	case 2, 3:
   202  		panic(x)
   203  	default:
   204  		// ok
   205  	}
   206  	// empty switch
   207  	switch {
   208  	}
   209  	// empty switch
   210  	switch {
   211  	default:
   212  	}
   213  	// empty switch
   214  	switch {
   215  	default:
   216  		fallthrough
   217  	case false:
   218  	}
   219  
   220  	// string -> []rune conversion.
   221  	use([]rune("foo"))
   222  
   223  	// Calls of form x.f().
   224  	type S2 struct {
   225  		f func() int
   226  	}
   227  	S2{f: func() int { return 1 }}.f() // field is a func value
   228  	T{}.f()                            // method call
   229  	i.f()                              // interface method invocation
   230  	(interface {
   231  		f() int
   232  	}(T{})).f() // anon interface method invocation
   233  
   234  	// Map lookup.
   235  	if v, ok := map[string]string{}["foo5"]; v != "" || ok {
   236  		panic("oops")
   237  	}
   238  
   239  	// Regression test: implicit address-taken struct literal
   240  	// inside literal map element.
   241  	_ = map[int]*struct{}{0: {}}
   242  }
   243  
   244  type mybool bool
   245  
   246  func (mybool) f() {}
   247  
   248  func init() {
   249  	type mybool bool
   250  	var b mybool
   251  	var i interface{} = b || b // result preserves types of operands
   252  	_ = i.(mybool)
   253  
   254  	i = false && b // result preserves type of "typed" operand
   255  	_ = i.(mybool)
   256  
   257  	i = b || true // result preserves type of "typed" operand
   258  	_ = i.(mybool)
   259  }
   260  
   261  func init() {
   262  	var x, y int
   263  	var b mybool = x == y // x==y is an untyped bool
   264  	b.f()
   265  }
   266  
   267  // Simple closures.
   268  func init() {
   269  	b := 3
   270  	f := func(a int) int {
   271  		return a + b
   272  	}
   273  	b++
   274  	if x := f(1); x != 5 { // 1+4 == 5
   275  		panic(x)
   276  	}
   277  	b++
   278  	if x := f(2); x != 7 { // 2+5 == 7
   279  		panic(x)
   280  	}
   281  	if b := f(1) < 16 || f(2) < 17; !b {
   282  		panic("oops")
   283  	}
   284  }
   285  
   286  // Shifts.
   287  func init() {
   288  	var i int64 = 1
   289  	var u uint64 = 1 << 32
   290  	if x := i << uint32(u); x != 1 {
   291  		panic(x)
   292  	}
   293  	if x := i << uint64(u); x != 0 {
   294  		panic(x)
   295  	}
   296  }
   297  
   298  // Implicit conversion of delete() key operand.
   299  func init() {
   300  	type I interface{}
   301  	m := make(map[I]bool)
   302  	m[1] = true
   303  	m[I(2)] = true
   304  	if len(m) != 2 {
   305  		panic(m)
   306  	}
   307  	delete(m, I(1))
   308  	delete(m, 2)
   309  	if len(m) != 0 {
   310  		panic(m)
   311  	}
   312  }
   313  
   314  // An I->I conversion always succeeds.
   315  func init() {
   316  	var x I
   317  	if I(x) != I(nil) {
   318  		panic("I->I conversion failed")
   319  	}
   320  }
   321  
   322  // An I->I type-assert fails iff the value is nil.
   323  func init() {
   324  	defer func() {
   325  		r := fmt.Sprint(recover())
   326  		// Exact error varies by toolchain.
   327  		if r != "runtime error: interface conversion: interface is nil, not main.I" &&
   328  			r != "interface conversion: interface is nil, not main.I" {
   329  			panic("I->I type assertion succeeded for nil value")
   330  		}
   331  	}()
   332  	var x I
   333  	_ = x.(I)
   334  }
   335  
   336  //////////////////////////////////////////////////////////////////////
   337  // Variadic bridge methods and interface thunks.
   338  
   339  type VT int
   340  
   341  var vcount = 0
   342  
   343  func (VT) f(x int, y ...string) {
   344  	vcount++
   345  	if x != 1 {
   346  		panic(x)
   347  	}
   348  	if len(y) != 2 || y[0] != "foo" || y[1] != "bar" {
   349  		panic(y)
   350  	}
   351  }
   352  
   353  type VS struct {
   354  	VT
   355  }
   356  
   357  type VI interface {
   358  	f(x int, y ...string)
   359  }
   360  
   361  func init() {
   362  	foobar := []string{"foo", "bar"}
   363  	var s VS
   364  	s.f(1, "foo", "bar")
   365  	s.f(1, foobar...)
   366  	if vcount != 2 {
   367  		panic("s.f not called twice")
   368  	}
   369  
   370  	fn := VI.f
   371  	fn(s, 1, "foo", "bar")
   372  	fn(s, 1, foobar...)
   373  	if vcount != 4 {
   374  		panic("I.f not called twice")
   375  	}
   376  }
   377  
   378  // Multiple labels on same statement.
   379  func multipleLabels() {
   380  	var trace []int
   381  	i := 0
   382  one:
   383  two:
   384  	for ; i < 3; i++ {
   385  		trace = append(trace, i)
   386  		switch i {
   387  		case 0:
   388  			continue two
   389  		case 1:
   390  			i++
   391  			goto one
   392  		case 2:
   393  			break two
   394  		}
   395  	}
   396  	if x := fmt.Sprint(trace); x != "[0 1 2]" {
   397  		panic(x)
   398  	}
   399  }
   400  
   401  func init() {
   402  	multipleLabels()
   403  }
   404  
   405  func init() {
   406  	// Struct equivalence ignores blank fields.
   407  	type s struct{ x, _, z int }
   408  	s1 := s{x: 1, z: 3}
   409  	s2 := s{x: 1, z: 3}
   410  	if s1 != s2 {
   411  		panic("not equal")
   412  	}
   413  }
   414  
   415  func init() {
   416  	// A slice var can be compared to const []T nil.
   417  	var i interface{} = []string{"foo"}
   418  	var j interface{} = []string(nil)
   419  	if i.([]string) == nil {
   420  		panic("expected i non-nil")
   421  	}
   422  	if j.([]string) != nil {
   423  		panic("expected j nil")
   424  	}
   425  	// But two slices cannot be compared, even if one is nil.
   426  	defer func() {
   427  		r := fmt.Sprint(recover())
   428  		if r != "runtime error: comparing uncomparable type []string" {
   429  			panic("want panic from slice comparison, got " + r)
   430  		}
   431  	}()
   432  	_ = i == j // interface comparison recurses on types
   433  }
   434  
   435  func init() {
   436  	// Regression test for SSA renaming bug.
   437  	var ints []int
   438  	for _ = range "foo" {
   439  		var x int
   440  		x++
   441  		ints = append(ints, x)
   442  	}
   443  	if fmt.Sprint(ints) != "[1 1 1]" {
   444  		panic(ints)
   445  	}
   446  }
   447  
   448  // Regression test for issue 6949:
   449  // []byte("foo") is not a constant since it allocates memory.
   450  func init() {
   451  	var r string
   452  	for i, b := range "ABC" {
   453  		x := []byte("abc")
   454  		x[i] = byte(b)
   455  		r += string(x)
   456  	}
   457  	if r != "AbcaBcabC" {
   458  		panic(r)
   459  	}
   460  }
   461  
   462  // Test of 3-operand x[lo:hi:max] slice.
   463  func init() {
   464  	s := []int{0, 1, 2, 3}
   465  	lenCapLoHi := func(x []int) [4]int { return [4]int{len(x), cap(x), x[0], x[len(x)-1]} }
   466  	if got := lenCapLoHi(s[1:3]); got != [4]int{2, 3, 1, 2} {
   467  		panic(got)
   468  	}
   469  	if got := lenCapLoHi(s[1:3:3]); got != [4]int{2, 2, 1, 2} {
   470  		panic(got)
   471  	}
   472  	max := 3
   473  	if "a"[0] == 'a' {
   474  		max = 2 // max is non-constant, even in SSA form
   475  	}
   476  	if got := lenCapLoHi(s[1:2:max]); got != [4]int{1, 1, 1, 1} {
   477  		panic(got)
   478  	}
   479  }
   480  
   481  var one = 1 // not a constant
   482  
   483  // Test makeslice.
   484  func init() {
   485  	check := func(s []string, wantLen, wantCap int) {
   486  		if len(s) != wantLen {
   487  			panic(len(s))
   488  		}
   489  		if cap(s) != wantCap {
   490  			panic(cap(s))
   491  		}
   492  	}
   493  	//                                       SSA form:
   494  	check(make([]string, 10), 10, 10)     // new([10]string)[:10]
   495  	check(make([]string, one), 1, 1)      // make([]string, one, one)
   496  	check(make([]string, 0, 10), 0, 10)   // new([10]string)[:0]
   497  	check(make([]string, 0, one), 0, 1)   // make([]string, 0, one)
   498  	check(make([]string, one, 10), 1, 10) // new([10]string)[:one]
   499  	check(make([]string, one, one), 1, 1) // make([]string, one, one)
   500  }
   501  
   502  // Test that a nice error is issued by indirection wrappers.
   503  func init() {
   504  	var ptr *T
   505  	var i I = ptr
   506  
   507  	defer func() {
   508  		r := fmt.Sprint(recover())
   509  		// Exact error varies by toolchain:
   510  		if r != "runtime error: value method (main.T).f called using nil *main.T pointer" &&
   511  			r != "value method main.T.f called using nil *T pointer" {
   512  			panic("want panic from call with nil receiver, got " + r)
   513  		}
   514  	}()
   515  	i.f()
   516  	panic("unreachable")
   517  }
   518  
   519  // Regression test for a subtle bug in which copying values would causes
   520  // subcomponents of aggregate variables to change address, breaking
   521  // aliases.
   522  func init() {
   523  	type T struct{ f int }
   524  	var x T
   525  	p := &x.f
   526  	x = T{}
   527  	*p = 1
   528  	if x.f != 1 {
   529  		panic("lost store")
   530  	}
   531  	if p != &x.f {
   532  		panic("unstable address")
   533  	}
   534  }