[go: up one dir, main page]

blob: 3da7d170b58634ae907358f184b1ba15e689325e [file] [log] [blame]
Russ Cox57eb06f2012-02-16 23:51:04 -05001// run
Russ Cox54aa8352009-03-20 11:32:58 -07002
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
Rob Pike19bab1d2012-02-24 10:30:39 +11007// Test the 'for range' construct.
8
Russ Cox54aa8352009-03-20 11:32:58 -07009package main
10
11// test range over channels
12
13func gen(c chan int, lo, hi int) {
14 for i := lo; i <= hi; i++ {
Rob Pike325cf8e2010-03-24 16:46:53 -070015 c <- i
Russ Cox54aa8352009-03-20 11:32:58 -070016 }
Rob Pike325cf8e2010-03-24 16:46:53 -070017 close(c)
Russ Cox54aa8352009-03-20 11:32:58 -070018}
19
20func seq(lo, hi int) chan int {
Rob Pike325cf8e2010-03-24 16:46:53 -070021 c := make(chan int)
22 go gen(c, lo, hi)
23 return c
Russ Cox54aa8352009-03-20 11:32:58 -070024}
25
Martin Möhrmann137e4a62017-09-03 08:20:57 +020026const alphabet = "abcdefghijklmnopqrstuvwxyz"
27
28func 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
Russ Cox54aa8352009-03-20 11:32:58 -070071func testchan() {
Rob Pike325cf8e2010-03-24 16:46:53 -070072 s := ""
Russ Cox54aa8352009-03-20 11:32:58 -070073 for i := range seq('a', 'z') {
Rob Pike325cf8e2010-03-24 16:46:53 -070074 s += string(i)
Russ Cox54aa8352009-03-20 11:32:58 -070075 }
Martin Möhrmann137e4a62017-09-03 08:20:57 +020076 if s != alphabet {
Rob Pike325cf8e2010-03-24 16:46:53 -070077 println("Wanted lowercase alphabet; got", s)
78 panic("fail")
Russ Cox54aa8352009-03-20 11:32:58 -070079 }
Russ Cox8d504c42014-07-16 19:27:10 -040080 n := 0
81 for range seq('a', 'z') {
82 n++
83 }
84 if n != 26 {
85 println("testchan wrong count", n, "want 26")
Martin Möhrmann137e4a62017-09-03 08:20:57 +020086 panic("fail")
Russ Cox8d504c42014-07-16 19:27:10 -040087 }
Russ Cox54aa8352009-03-20 11:32:58 -070088}
89
Russ Cox81c3e8c2010-07-01 18:04:25 -070090// test that range over slice only evaluates
Russ Cox54aa8352009-03-20 11:32:58 -070091// the expression after "range" once.
92
Rob Pike325cf8e2010-03-24 16:46:53 -070093var nmake = 0
94
Russ Cox81c3e8c2010-07-01 18:04:25 -070095func makeslice() []int {
Rob Pike325cf8e2010-03-24 16:46:53 -070096 nmake++
97 return []int{1, 2, 3, 4, 5}
Russ Cox54aa8352009-03-20 11:32:58 -070098}
99
Russ Cox81c3e8c2010-07-01 18:04:25 -0700100func 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 {
Alan Donovan1c1096e2013-02-11 18:20:52 -0500111 println("wrong sum ranging over makeslice", s)
Russ Cox81c3e8c2010-07-01 18:04:25 -0700112 panic("fail")
113 }
Alan Donovan1c1096e2013-02-11 18:20:52 -0500114
Russ Cox51072eb2012-05-24 23:05:36 -0400115 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 }
Russ Cox81c3e8c2010-07-01 18:04:25 -0700125}
126
127func 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 {
Alan Donovan1c1096e2013-02-11 18:20:52 -0500138 println("wrong sum ranging over makeslice", s)
Russ Cox81c3e8c2010-07-01 18:04:25 -0700139 panic("fail")
140 }
141}
142
Russ Cox8d504c42014-07-16 19:27:10 -0400143func 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
Martin Möhrmannb6796652016-10-27 23:31:38 +0200159// test that range over []byte(string) only evaluates
160// the expression after "range" once.
161
162func makenumstring() string {
163 nmake++
164 return "\x01\x02\x03\x04\x05"
165}
166
167func 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
Russ Cox81c3e8c2010-07-01 18:04:25 -0700183// test that range over array only evaluates
184// the expression after "range" once.
185
186func makearray() [5]int {
187 nmake++
188 return [5]int{1, 2, 3, 4, 5}
189}
190
Russ Cox54aa8352009-03-20 11:32:58 -0700191func testarray() {
Rob Pike325cf8e2010-03-24 16:46:53 -0700192 s := 0
Russ Cox81c3e8c2010-07-01 18:04:25 -0700193 nmake = 0
Russ Coxae54cf72009-09-15 12:42:24 -0700194 for _, v := range makearray() {
Rob Pike325cf8e2010-03-24 16:46:53 -0700195 s += v
Russ Cox54aa8352009-03-20 11:32:58 -0700196 }
197 if nmake != 1 {
Rob Pike325cf8e2010-03-24 16:46:53 -0700198 println("range called makearray", nmake, "times")
199 panic("fail")
Russ Cox54aa8352009-03-20 11:32:58 -0700200 }
201 if s != 15 {
Alan Donovan1c1096e2013-02-11 18:20:52 -0500202 println("wrong sum ranging over makearray", s)
Rob Pike325cf8e2010-03-24 16:46:53 -0700203 panic("fail")
Russ Cox54aa8352009-03-20 11:32:58 -0700204 }
205}
206
Russ Cox81c3e8c2010-07-01 18:04:25 -0700207func 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 {
Alan Donovan1c1096e2013-02-11 18:20:52 -0500218 println("wrong sum ranging over makearray", s)
Russ Cox81c3e8c2010-07-01 18:04:25 -0700219 panic("fail")
220 }
221}
222
Russ Cox8d504c42014-07-16 19:27:10 -0400223func 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
Russ Cox81c3e8c2010-07-01 18:04:25 -0700239func makearrayptr() *[5]int {
240 nmake++
241 return &[5]int{1, 2, 3, 4, 5}
242}
243
244func 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 {
Alan Donovan1c1096e2013-02-11 18:20:52 -0500267 println("wrong sum ranging over makearrayptr", s)
Russ Cox81c3e8c2010-07-01 18:04:25 -0700268 panic("fail")
269 }
270}
271
272func 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 {
Alan Donovan1c1096e2013-02-11 18:20:52 -0500283 println("wrong sum ranging over makearrayptr", s)
Russ Cox81c3e8c2010-07-01 18:04:25 -0700284 panic("fail")
285 }
286}
287
Russ Cox8d504c42014-07-16 19:27:10 -0400288func 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
Russ Cox81c3e8c2010-07-01 18:04:25 -0700304// test that range over string only evaluates
305// the expression after "range" once.
306
307func makestring() string {
308 nmake++
309 return "abcd☺"
310}
311
312func teststring() {
Russ Coxdb339592011-10-25 22:20:02 -0700313 var s rune
Russ Cox81c3e8c2010-07-01 18:04:25 -0700314 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'+'☺' {
Alan Donovan1c1096e2013-02-11 18:20:52 -0500323 println("wrong sum ranging over makestring", s)
Russ Cox81c3e8c2010-07-01 18:04:25 -0700324 panic("fail")
325 }
Martin Möhrmanna8f07312016-12-19 00:06:46 +0100326
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 }
Russ Cox81c3e8c2010-07-01 18:04:25 -0700346}
347
348func 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 {
Alan Donovan1c1096e2013-02-11 18:20:52 -0500359 println("wrong sum ranging over makestring", s)
Russ Cox81c3e8c2010-07-01 18:04:25 -0700360 panic("fail")
361 }
362}
363
Russ Cox8d504c42014-07-16 19:27:10 -0400364func 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
Russ Cox81c3e8c2010-07-01 18:04:25 -0700380// test that range over map only evaluates
381// the expression after "range" once.
382
383func makemap() map[int]int {
384 nmake++
Russ Coxdb339592011-10-25 22:20:02 -0700385 return map[int]int{0: 'a', 1: 'b', 2: 'c', 3: 'd', 4: '☺'}
Russ Cox81c3e8c2010-07-01 18:04:25 -0700386}
387
388func 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'+'☺' {
Alan Donovan1c1096e2013-02-11 18:20:52 -0500399 println("wrong sum ranging over makemap", s)
Russ Cox81c3e8c2010-07-01 18:04:25 -0700400 panic("fail")
401 }
402}
403
404func 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 {
Alan Donovan1c1096e2013-02-11 18:20:52 -0500415 println("wrong sum ranging over makemap", s)
Russ Cox81c3e8c2010-07-01 18:04:25 -0700416 panic("fail")
417 }
418}
419
Russ Cox8d504c42014-07-16 19:27:10 -0400420func 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
Ian Lance Taylorff68f962010-01-15 10:40:30 -0800436// test that range evaluates the index and value expressions
437// exactly once per iteration.
438
439var ncalls = 0
Rob Pike325cf8e2010-03-24 16:46:53 -0700440
Ian Lance Taylorff68f962010-01-15 10:40:30 -0800441func getvar(p *int) *int {
442 ncalls++
443 return p
444}
445
446func 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 {
Rob Pike325cf8e2010-03-24 16:46:53 -0700455 println("wrong number of calls:", ncalls, "!= 4")
456 panic("fail")
Ian Lance Taylorff68f962010-01-15 10:40:30 -0800457 }
458 if si != 1 || sv != 3 {
Rob Pike325cf8e2010-03-24 16:46:53 -0700459 println("wrong sum in testcalls", si, sv)
460 panic("fail")
Ian Lance Taylorff68f962010-01-15 10:40:30 -0800461 }
462
463 ncalls = 0
464 for *getvar(&i), *getvar(&v) = range [0]int{} {
Rob Pike325cf8e2010-03-24 16:46:53 -0700465 println("loop ran on empty array")
466 panic("fail")
Ian Lance Taylorff68f962010-01-15 10:40:30 -0800467 }
468 if ncalls != 0 {
Rob Pike325cf8e2010-03-24 16:46:53 -0700469 println("wrong number of calls:", ncalls, "!= 0")
470 panic("fail")
Ian Lance Taylorff68f962010-01-15 10:40:30 -0800471 }
472}
473
Russ Cox54aa8352009-03-20 11:32:58 -0700474func main() {
Martin Möhrmann137e4a62017-09-03 08:20:57 +0200475 testblankvars()
Rob Pike325cf8e2010-03-24 16:46:53 -0700476 testchan()
477 testarray()
Russ Cox81c3e8c2010-07-01 18:04:25 -0700478 testarray1()
Russ Cox8d504c42014-07-16 19:27:10 -0400479 testarray2()
Russ Cox81c3e8c2010-07-01 18:04:25 -0700480 testarrayptr()
481 testarrayptr1()
Russ Cox8d504c42014-07-16 19:27:10 -0400482 testarrayptr2()
Russ Cox81c3e8c2010-07-01 18:04:25 -0700483 testslice()
484 testslice1()
Russ Cox8d504c42014-07-16 19:27:10 -0400485 testslice2()
Martin Möhrmannb6796652016-10-27 23:31:38 +0200486 testslice3()
Russ Cox81c3e8c2010-07-01 18:04:25 -0700487 teststring()
488 teststring1()
Russ Cox8d504c42014-07-16 19:27:10 -0400489 teststring2()
Russ Cox81c3e8c2010-07-01 18:04:25 -0700490 testmap()
491 testmap1()
Russ Cox8d504c42014-07-16 19:27:10 -0400492 testmap2()
Rob Pike325cf8e2010-03-24 16:46:53 -0700493 testcalls()
Russ Cox54aa8352009-03-20 11:32:58 -0700494}