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