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 7package main 8 9import ( 10 "fmt" 11 "reflect" 12) 13 14func init() { 15 // Call of variadic function with (implicit) empty slice. 16 if x := fmt.Sprint(); x != "" { 17 panic(x) 18 } 19} 20 21type empty interface{} 22 23type I interface { 24 f() int 25} 26 27type T struct{ z int } 28 29func (t T) f() int { return t.z } 30 31func use(interface{}) {} 32 33var counter = 2 34 35// Test initialization, including init blocks containing 'return'. 36// Assertion is in main. 37func init() { 38 counter *= 3 39 return 40 counter *= 3 41} 42 43func init() { 44 counter *= 5 45 return 46 counter *= 5 47} 48 49// Recursion. 50func fib(x int) int { 51 if x < 2 { 52 return x 53 } 54 return fib(x-1) + fib(x-2) 55} 56 57func 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. 65func 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. 81func 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 115func 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 244type mybool bool 245 246func (mybool) f() {} 247 248func 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 261func 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. 268func 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. 287func 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. 299func 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. 315func 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. 323func 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 339type VT int 340 341var vcount = 0 342 343func (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 353type VS struct { 354 VT 355} 356 357type VI interface { 358 f(x int, y ...string) 359} 360 361func 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. 379func multipleLabels() { 380 var trace []int 381 i := 0 382one: 383two: 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 401func init() { 402 multipleLabels() 403} 404 405func 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 415func 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 435func 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. 450func 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. 463func 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 481var one = 1 // not a constant 482 483// Test makeslice. 484func 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. 503func 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. 522func 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} 535