github.com/stingnevermore/go@v0.0.0-20180120041312-3810f5bfed72/test/range.go (about) 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 }