Home | History | Annotate | Download | only in test
      1 // run
      2 
      3 // Copyright 2009 The Go Authors. All rights reserved.
      4 // Use of this source code is governed by a BSD-style
      5 // license that can be found in the LICENSE file.
      6 
      7 // Test the 'for range' construct.
      8 
      9 package main
     10 
     11 // test range over channels
     12 
     13 func gen(c chan int, lo, hi int) {
     14 	for i := lo; i <= hi; i++ {
     15 		c <- i
     16 	}
     17 	close(c)
     18 }
     19 
     20 func seq(lo, hi int) chan int {
     21 	c := make(chan int)
     22 	go gen(c, lo, hi)
     23 	return c
     24 }
     25 
     26 const alphabet = "abcdefghijklmnopqrstuvwxyz"
     27 
     28 func testblankvars() {
     29 	n := 0
     30 	for range alphabet {
     31 		n++
     32 	}
     33 	if n != 26 {
     34 		println("for range: wrong count", n, "want 26")
     35 		panic("fail")
     36 	}
     37 	n = 0
     38 	for _ = range alphabet {
     39 		n++
     40 	}
     41 	if n != 26 {
     42 		println("for _ = range: wrong count", n, "want 26")
     43 		panic("fail")
     44 	}
     45 	n = 0
     46 	for _, _ = range alphabet {
     47 		n++
     48 	}
     49 	if n != 26 {
     50 		println("for _, _ = range: wrong count", n, "want 26")
     51 		panic("fail")
     52 	}
     53 	s := 0
     54 	for i, _ := range alphabet {
     55 		s += i
     56 	}
     57 	if s != 325 {
     58 		println("for i, _ := range: wrong sum", s, "want 325")
     59 		panic("fail")
     60 	}
     61 	r := rune(0)
     62 	for _, v := range alphabet {
     63 		r += v
     64 	}
     65 	if r != 2847 {
     66 		println("for _, v := range: wrong sum", r, "want 2847")
     67 		panic("fail")
     68 	}
     69 }
     70 
     71 func testchan() {
     72 	s := ""
     73 	for i := range seq('a', 'z') {
     74 		s += string(i)
     75 	}
     76 	if s != alphabet {
     77 		println("Wanted lowercase alphabet; got", s)
     78 		panic("fail")
     79 	}
     80 	n := 0
     81 	for range seq('a', 'z') {
     82 		n++
     83 	}
     84 	if n != 26 {
     85 		println("testchan wrong count", n, "want 26")
     86 		panic("fail")
     87 	}
     88 }
     89 
     90 // test that range over slice only evaluates
     91 // the expression after "range" once.
     92 
     93 var nmake = 0
     94 
     95 func makeslice() []int {
     96 	nmake++
     97 	return []int{1, 2, 3, 4, 5}
     98 }
     99 
    100 func testslice() {
    101 	s := 0
    102 	nmake = 0
    103 	for _, v := range makeslice() {
    104 		s += v
    105 	}
    106 	if nmake != 1 {
    107 		println("range called makeslice", nmake, "times")
    108 		panic("fail")
    109 	}
    110 	if s != 15 {
    111 		println("wrong sum ranging over makeslice", s)
    112 		panic("fail")
    113 	}
    114 
    115 	x := []int{10, 20}
    116 	y := []int{99}
    117 	i := 1
    118 	for i, x[i] = range y {
    119 		break
    120 	}
    121 	if i != 0 || x[0] != 10 || x[1] != 99 {
    122 		println("wrong parallel assignment", i, x[0], x[1])
    123 		panic("fail")
    124 	}
    125 }
    126 
    127 func testslice1() {
    128 	s := 0
    129 	nmake = 0
    130 	for i := range makeslice() {
    131 		s += i
    132 	}
    133 	if nmake != 1 {
    134 		println("range called makeslice", nmake, "times")
    135 		panic("fail")
    136 	}
    137 	if s != 10 {
    138 		println("wrong sum ranging over makeslice", s)
    139 		panic("fail")
    140 	}
    141 }
    142 
    143 func testslice2() {
    144 	n := 0
    145 	nmake = 0
    146 	for range makeslice() {
    147 		n++
    148 	}
    149 	if nmake != 1 {
    150 		println("range called makeslice", nmake, "times")
    151 		panic("fail")
    152 	}
    153 	if n != 5 {
    154 		println("wrong count ranging over makeslice", n)
    155 		panic("fail")
    156 	}
    157 }
    158 
    159 // test that range over []byte(string) only evaluates
    160 // the expression after "range" once.
    161 
    162 func makenumstring() string {
    163 	nmake++
    164 	return "\x01\x02\x03\x04\x05"
    165 }
    166 
    167 func testslice3() {
    168 	s := byte(0)
    169 	nmake = 0
    170 	for _, v := range []byte(makenumstring()) {
    171 		s += v
    172 	}
    173 	if nmake != 1 {
    174 		println("range called makenumstring", nmake, "times")
    175 		panic("fail")
    176 	}
    177 	if s != 15 {
    178 		println("wrong sum ranging over []byte(makenumstring)", s)
    179 		panic("fail")
    180 	}
    181 }
    182 
    183 // test that range over array only evaluates
    184 // the expression after "range" once.
    185 
    186 func makearray() [5]int {
    187 	nmake++
    188 	return [5]int{1, 2, 3, 4, 5}
    189 }
    190 
    191 func testarray() {
    192 	s := 0
    193 	nmake = 0
    194 	for _, v := range makearray() {
    195 		s += v
    196 	}
    197 	if nmake != 1 {
    198 		println("range called makearray", nmake, "times")
    199 		panic("fail")
    200 	}
    201 	if s != 15 {
    202 		println("wrong sum ranging over makearray", s)
    203 		panic("fail")
    204 	}
    205 }
    206 
    207 func testarray1() {
    208 	s := 0
    209 	nmake = 0
    210 	for i := range makearray() {
    211 		s += i
    212 	}
    213 	if nmake != 1 {
    214 		println("range called makearray", nmake, "times")
    215 		panic("fail")
    216 	}
    217 	if s != 10 {
    218 		println("wrong sum ranging over makearray", s)
    219 		panic("fail")
    220 	}
    221 }
    222 
    223 func testarray2() {
    224 	n := 0
    225 	nmake = 0
    226 	for range makearray() {
    227 		n++
    228 	}
    229 	if nmake != 1 {
    230 		println("range called makearray", nmake, "times")
    231 		panic("fail")
    232 	}
    233 	if n != 5 {
    234 		println("wrong count ranging over makearray", n)
    235 		panic("fail")
    236 	}
    237 }
    238 
    239 func makearrayptr() *[5]int {
    240 	nmake++
    241 	return &[5]int{1, 2, 3, 4, 5}
    242 }
    243 
    244 func testarrayptr() {
    245 	nmake = 0
    246 	x := len(makearrayptr())
    247 	if x != 5 || nmake != 1 {
    248 		println("len called makearrayptr", nmake, "times and got len", x)
    249 		panic("fail")
    250 	}
    251 	nmake = 0
    252 	x = cap(makearrayptr())
    253 	if x != 5 || nmake != 1 {
    254 		println("cap called makearrayptr", nmake, "times and got len", x)
    255 		panic("fail")
    256 	}
    257 	s := 0
    258 	nmake = 0
    259 	for _, v := range makearrayptr() {
    260 		s += v
    261 	}
    262 	if nmake != 1 {
    263 		println("range called makearrayptr", nmake, "times")
    264 		panic("fail")
    265 	}
    266 	if s != 15 {
    267 		println("wrong sum ranging over makearrayptr", s)
    268 		panic("fail")
    269 	}
    270 }
    271 
    272 func testarrayptr1() {
    273 	s := 0
    274 	nmake = 0
    275 	for i := range makearrayptr() {
    276 		s += i
    277 	}
    278 	if nmake != 1 {
    279 		println("range called makearrayptr", nmake, "times")
    280 		panic("fail")
    281 	}
    282 	if s != 10 {
    283 		println("wrong sum ranging over makearrayptr", s)
    284 		panic("fail")
    285 	}
    286 }
    287 
    288 func testarrayptr2() {
    289 	n := 0
    290 	nmake = 0
    291 	for range makearrayptr() {
    292 		n++
    293 	}
    294 	if nmake != 1 {
    295 		println("range called makearrayptr", nmake, "times")
    296 		panic("fail")
    297 	}
    298 	if n != 5 {
    299 		println("wrong count ranging over makearrayptr", n)
    300 		panic("fail")
    301 	}
    302 }
    303 
    304 // test that range over string only evaluates
    305 // the expression after "range" once.
    306 
    307 func makestring() string {
    308 	nmake++
    309 	return "abcd"
    310 }
    311 
    312 func teststring() {
    313 	var s rune
    314 	nmake = 0
    315 	for _, v := range makestring() {
    316 		s += v
    317 	}
    318 	if nmake != 1 {
    319 		println("range called makestring", nmake, "times")
    320 		panic("fail")
    321 	}
    322 	if s != 'a'+'b'+'c'+'d'+'' {
    323 		println("wrong sum ranging over makestring", s)
    324 		panic("fail")
    325 	}
    326 
    327 	x := []rune{'a', 'b'}
    328 	i := 1
    329 	for i, x[i] = range "c" {
    330 		break
    331 	}
    332 	if i != 0 || x[0] != 'a' || x[1] != 'c' {
    333 		println("wrong parallel assignment", i, x[0], x[1])
    334 		panic("fail")
    335 	}
    336 
    337 	y := []int{1, 2, 3}
    338 	r := rune(1)
    339 	for y[r], r = range "\x02" {
    340 		break
    341 	}
    342 	if r != 2 || y[0] != 1 || y[1] != 0 || y[2] != 3 {
    343 		println("wrong parallel assignment", r, y[0], y[1], y[2])
    344 		panic("fail")
    345 	}
    346 }
    347 
    348 func teststring1() {
    349 	s := 0
    350 	nmake = 0
    351 	for i := range makestring() {
    352 		s += i
    353 	}
    354 	if nmake != 1 {
    355 		println("range called makestring", nmake, "times")
    356 		panic("fail")
    357 	}
    358 	if s != 10 {
    359 		println("wrong sum ranging over makestring", s)
    360 		panic("fail")
    361 	}
    362 }
    363 
    364 func teststring2() {
    365 	n := 0
    366 	nmake = 0
    367 	for range makestring() {
    368 		n++
    369 	}
    370 	if nmake != 1 {
    371 		println("range called makestring", nmake, "times")
    372 		panic("fail")
    373 	}
    374 	if n != 5 {
    375 		println("wrong count ranging over makestring", n)
    376 		panic("fail")
    377 	}
    378 }
    379 
    380 // test that range over map only evaluates
    381 // the expression after "range" once.
    382 
    383 func makemap() map[int]int {
    384 	nmake++
    385 	return map[int]int{0: 'a', 1: 'b', 2: 'c', 3: 'd', 4: ''}
    386 }
    387 
    388 func testmap() {
    389 	s := 0
    390 	nmake = 0
    391 	for _, v := range makemap() {
    392 		s += v
    393 	}
    394 	if nmake != 1 {
    395 		println("range called makemap", nmake, "times")
    396 		panic("fail")
    397 	}
    398 	if s != 'a'+'b'+'c'+'d'+'' {
    399 		println("wrong sum ranging over makemap", s)
    400 		panic("fail")
    401 	}
    402 }
    403 
    404 func testmap1() {
    405 	s := 0
    406 	nmake = 0
    407 	for i := range makemap() {
    408 		s += i
    409 	}
    410 	if nmake != 1 {
    411 		println("range called makemap", nmake, "times")
    412 		panic("fail")
    413 	}
    414 	if s != 10 {
    415 		println("wrong sum ranging over makemap", s)
    416 		panic("fail")
    417 	}
    418 }
    419 
    420 func testmap2() {
    421 	n := 0
    422 	nmake = 0
    423 	for range makemap() {
    424 		n++
    425 	}
    426 	if nmake != 1 {
    427 		println("range called makemap", nmake, "times")
    428 		panic("fail")
    429 	}
    430 	if n != 5 {
    431 		println("wrong count ranging over makemap", n)
    432 		panic("fail")
    433 	}
    434 }
    435 
    436 // test that range evaluates the index and value expressions
    437 // exactly once per iteration.
    438 
    439 var ncalls = 0
    440 
    441 func getvar(p *int) *int {
    442 	ncalls++
    443 	return p
    444 }
    445 
    446 func testcalls() {
    447 	var i, v int
    448 	si := 0
    449 	sv := 0
    450 	for *getvar(&i), *getvar(&v) = range [2]int{1, 2} {
    451 		si += i
    452 		sv += v
    453 	}
    454 	if ncalls != 4 {
    455 		println("wrong number of calls:", ncalls, "!= 4")
    456 		panic("fail")
    457 	}
    458 	if si != 1 || sv != 3 {
    459 		println("wrong sum in testcalls", si, sv)
    460 		panic("fail")
    461 	}
    462 
    463 	ncalls = 0
    464 	for *getvar(&i), *getvar(&v) = range [0]int{} {
    465 		println("loop ran on empty array")
    466 		panic("fail")
    467 	}
    468 	if ncalls != 0 {
    469 		println("wrong number of calls:", ncalls, "!= 0")
    470 		panic("fail")
    471 	}
    472 }
    473 
    474 func main() {
    475 	testblankvars()
    476 	testchan()
    477 	testarray()
    478 	testarray1()
    479 	testarray2()
    480 	testarrayptr()
    481 	testarrayptr1()
    482 	testarrayptr2()
    483 	testslice()
    484 	testslice1()
    485 	testslice2()
    486 	testslice3()
    487 	teststring()
    488 	teststring1()
    489 	teststring2()
    490 	testmap()
    491 	testmap1()
    492 	testmap2()
    493 	testcalls()
    494 }
    495