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