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 282 func teststring1() { 283 s := 0 284 nmake = 0 285 for i := range makestring() { 286 s += i 287 } 288 if nmake != 1 { 289 println("range called makestring", nmake, "times") 290 panic("fail") 291 } 292 if s != 10 { 293 println("wrong sum ranging over makestring", s) 294 panic("fail") 295 } 296 } 297 298 func teststring2() { 299 n := 0 300 nmake = 0 301 for range makestring() { 302 n++ 303 } 304 if nmake != 1 { 305 println("range called makestring", nmake, "times") 306 panic("fail") 307 } 308 if n != 5 { 309 println("wrong count ranging over makestring", n) 310 panic("fail") 311 } 312 } 313 314 // test that range over map only evaluates 315 // the expression after "range" once. 316 317 func makemap() map[int]int { 318 nmake++ 319 return map[int]int{0: 'a', 1: 'b', 2: 'c', 3: 'd', 4: ''} 320 } 321 322 func testmap() { 323 s := 0 324 nmake = 0 325 for _, v := range makemap() { 326 s += v 327 } 328 if nmake != 1 { 329 println("range called makemap", nmake, "times") 330 panic("fail") 331 } 332 if s != 'a'+'b'+'c'+'d'+'' { 333 println("wrong sum ranging over makemap", s) 334 panic("fail") 335 } 336 } 337 338 func testmap1() { 339 s := 0 340 nmake = 0 341 for i := range makemap() { 342 s += i 343 } 344 if nmake != 1 { 345 println("range called makemap", nmake, "times") 346 panic("fail") 347 } 348 if s != 10 { 349 println("wrong sum ranging over makemap", s) 350 panic("fail") 351 } 352 } 353 354 func testmap2() { 355 n := 0 356 nmake = 0 357 for range makemap() { 358 n++ 359 } 360 if nmake != 1 { 361 println("range called makemap", nmake, "times") 362 panic("fail") 363 } 364 if n != 5 { 365 println("wrong count ranging over makemap", n) 366 panic("fail") 367 } 368 } 369 370 // test that range evaluates the index and value expressions 371 // exactly once per iteration. 372 373 var ncalls = 0 374 375 func getvar(p *int) *int { 376 ncalls++ 377 return p 378 } 379 380 func testcalls() { 381 var i, v int 382 si := 0 383 sv := 0 384 for *getvar(&i), *getvar(&v) = range [2]int{1, 2} { 385 si += i 386 sv += v 387 } 388 if ncalls != 4 { 389 println("wrong number of calls:", ncalls, "!= 4") 390 panic("fail") 391 } 392 if si != 1 || sv != 3 { 393 println("wrong sum in testcalls", si, sv) 394 panic("fail") 395 } 396 397 ncalls = 0 398 for *getvar(&i), *getvar(&v) = range [0]int{} { 399 println("loop ran on empty array") 400 panic("fail") 401 } 402 if ncalls != 0 { 403 println("wrong number of calls:", ncalls, "!= 0") 404 panic("fail") 405 } 406 } 407 408 func main() { 409 testchan() 410 testarray() 411 testarray1() 412 testarray2() 413 testarrayptr() 414 testarrayptr1() 415 testarrayptr2() 416 testslice() 417 testslice1() 418 testslice2() 419 testslice3() 420 teststring() 421 teststring1() 422 teststring2() 423 testmap() 424 testmap1() 425 testmap2() 426 testcalls() 427 } 428