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 }