blob: afdac57fa357fae4e45fd8f0ad8fef7c6ed484b3 [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
26func testchan() {
Rob Pike325cf8e2010-03-24 16:46:53 -070027 s := ""
Russ Cox54aa8352009-03-20 11:32:58 -070028 for i := range seq('a', 'z') {
Rob Pike325cf8e2010-03-24 16:46:53 -070029 s += string(i)
Russ Cox54aa8352009-03-20 11:32:58 -070030 }
31 if s != "abcdefghijklmnopqrstuvwxyz" {
Rob Pike325cf8e2010-03-24 16:46:53 -070032 println("Wanted lowercase alphabet; got", s)
33 panic("fail")
Russ Cox54aa8352009-03-20 11:32:58 -070034 }
Russ Cox8d504c42014-07-16 19:27:10 -040035 n := 0
36 for range seq('a', 'z') {
37 n++
38 }
39 if n != 26 {
40 println("testchan wrong count", n, "want 26")
41 }
Russ Cox54aa8352009-03-20 11:32:58 -070042}
43
Russ Cox81c3e8c2010-07-01 18:04:25 -070044// test that range over slice only evaluates
Russ Cox54aa8352009-03-20 11:32:58 -070045// the expression after "range" once.
46
Rob Pike325cf8e2010-03-24 16:46:53 -070047var nmake = 0
48
Russ Cox81c3e8c2010-07-01 18:04:25 -070049func makeslice() []int {
Rob Pike325cf8e2010-03-24 16:46:53 -070050 nmake++
51 return []int{1, 2, 3, 4, 5}
Russ Cox54aa8352009-03-20 11:32:58 -070052}
53
Russ Cox81c3e8c2010-07-01 18:04:25 -070054func 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 {
Alan Donovan1c1096e2013-02-11 18:20:52 -050065 println("wrong sum ranging over makeslice", s)
Russ Cox81c3e8c2010-07-01 18:04:25 -070066 panic("fail")
67 }
Alan Donovan1c1096e2013-02-11 18:20:52 -050068
Russ Cox51072eb2012-05-24 23:05:36 -040069 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 }
Russ Cox81c3e8c2010-07-01 18:04:25 -070079}
80
81func 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 {
Alan Donovan1c1096e2013-02-11 18:20:52 -050092 println("wrong sum ranging over makeslice", s)
Russ Cox81c3e8c2010-07-01 18:04:25 -070093 panic("fail")
94 }
95}
96
Russ Cox8d504c42014-07-16 19:27:10 -040097func 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
Martin Möhrmannb6796652016-10-27 23:31:38 +0200113// test that range over []byte(string) only evaluates
114// the expression after "range" once.
115
116func makenumstring() string {
117 nmake++
118 return "\x01\x02\x03\x04\x05"
119}
120
121func 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
Russ Cox81c3e8c2010-07-01 18:04:25 -0700137// test that range over array only evaluates
138// the expression after "range" once.
139
140func makearray() [5]int {
141 nmake++
142 return [5]int{1, 2, 3, 4, 5}
143}
144
Russ Cox54aa8352009-03-20 11:32:58 -0700145func testarray() {
Rob Pike325cf8e2010-03-24 16:46:53 -0700146 s := 0
Russ Cox81c3e8c2010-07-01 18:04:25 -0700147 nmake = 0
Russ Coxae54cf72009-09-15 12:42:24 -0700148 for _, v := range makearray() {
Rob Pike325cf8e2010-03-24 16:46:53 -0700149 s += v
Russ Cox54aa8352009-03-20 11:32:58 -0700150 }
151 if nmake != 1 {
Rob Pike325cf8e2010-03-24 16:46:53 -0700152 println("range called makearray", nmake, "times")
153 panic("fail")
Russ Cox54aa8352009-03-20 11:32:58 -0700154 }
155 if s != 15 {
Alan Donovan1c1096e2013-02-11 18:20:52 -0500156 println("wrong sum ranging over makearray", s)
Rob Pike325cf8e2010-03-24 16:46:53 -0700157 panic("fail")
Russ Cox54aa8352009-03-20 11:32:58 -0700158 }
159}
160
Russ Cox81c3e8c2010-07-01 18:04:25 -0700161func 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 {
Alan Donovan1c1096e2013-02-11 18:20:52 -0500172 println("wrong sum ranging over makearray", s)
Russ Cox81c3e8c2010-07-01 18:04:25 -0700173 panic("fail")
174 }
175}
176
Russ Cox8d504c42014-07-16 19:27:10 -0400177func 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
Russ Cox81c3e8c2010-07-01 18:04:25 -0700193func makearrayptr() *[5]int {
194 nmake++
195 return &[5]int{1, 2, 3, 4, 5}
196}
197
198func 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 {
Alan Donovan1c1096e2013-02-11 18:20:52 -0500221 println("wrong sum ranging over makearrayptr", s)
Russ Cox81c3e8c2010-07-01 18:04:25 -0700222 panic("fail")
223 }
224}
225
226func 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 {
Alan Donovan1c1096e2013-02-11 18:20:52 -0500237 println("wrong sum ranging over makearrayptr", s)
Russ Cox81c3e8c2010-07-01 18:04:25 -0700238 panic("fail")
239 }
240}
241
Russ Cox8d504c42014-07-16 19:27:10 -0400242func 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
Russ Cox81c3e8c2010-07-01 18:04:25 -0700258// test that range over string only evaluates
259// the expression after "range" once.
260
261func makestring() string {
262 nmake++
263 return "abcd☺"
264}
265
266func teststring() {
Russ Coxdb339592011-10-25 22:20:02 -0700267 var s rune
Russ Cox81c3e8c2010-07-01 18:04:25 -0700268 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'+'☺' {
Alan Donovan1c1096e2013-02-11 18:20:52 -0500277 println("wrong sum ranging over makestring", s)
Russ Cox81c3e8c2010-07-01 18:04:25 -0700278 panic("fail")
279 }
Martin Möhrmanna8f07312016-12-19 00:06:46 +0100280
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 }
Russ Cox81c3e8c2010-07-01 18:04:25 -0700300}
301
302func 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 {
Alan Donovan1c1096e2013-02-11 18:20:52 -0500313 println("wrong sum ranging over makestring", s)
Russ Cox81c3e8c2010-07-01 18:04:25 -0700314 panic("fail")
315 }
316}
317
Russ Cox8d504c42014-07-16 19:27:10 -0400318func 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
Russ Cox81c3e8c2010-07-01 18:04:25 -0700334// test that range over map only evaluates
335// the expression after "range" once.
336
337func makemap() map[int]int {
338 nmake++
Russ Coxdb339592011-10-25 22:20:02 -0700339 return map[int]int{0: 'a', 1: 'b', 2: 'c', 3: 'd', 4: '☺'}
Russ Cox81c3e8c2010-07-01 18:04:25 -0700340}
341
342func 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'+'☺' {
Alan Donovan1c1096e2013-02-11 18:20:52 -0500353 println("wrong sum ranging over makemap", s)
Russ Cox81c3e8c2010-07-01 18:04:25 -0700354 panic("fail")
355 }
356}
357
358func 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 {
Alan Donovan1c1096e2013-02-11 18:20:52 -0500369 println("wrong sum ranging over makemap", s)
Russ Cox81c3e8c2010-07-01 18:04:25 -0700370 panic("fail")
371 }
372}
373
Russ Cox8d504c42014-07-16 19:27:10 -0400374func 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
Ian Lance Taylorff68f962010-01-15 10:40:30 -0800390// test that range evaluates the index and value expressions
391// exactly once per iteration.
392
393var ncalls = 0
Rob Pike325cf8e2010-03-24 16:46:53 -0700394
Ian Lance Taylorff68f962010-01-15 10:40:30 -0800395func getvar(p *int) *int {
396 ncalls++
397 return p
398}
399
400func 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 {
Rob Pike325cf8e2010-03-24 16:46:53 -0700409 println("wrong number of calls:", ncalls, "!= 4")
410 panic("fail")
Ian Lance Taylorff68f962010-01-15 10:40:30 -0800411 }
412 if si != 1 || sv != 3 {
Rob Pike325cf8e2010-03-24 16:46:53 -0700413 println("wrong sum in testcalls", si, sv)
414 panic("fail")
Ian Lance Taylorff68f962010-01-15 10:40:30 -0800415 }
416
417 ncalls = 0
418 for *getvar(&i), *getvar(&v) = range [0]int{} {
Rob Pike325cf8e2010-03-24 16:46:53 -0700419 println("loop ran on empty array")
420 panic("fail")
Ian Lance Taylorff68f962010-01-15 10:40:30 -0800421 }
422 if ncalls != 0 {
Rob Pike325cf8e2010-03-24 16:46:53 -0700423 println("wrong number of calls:", ncalls, "!= 0")
424 panic("fail")
Ian Lance Taylorff68f962010-01-15 10:40:30 -0800425 }
426}
427
Russ Cox54aa8352009-03-20 11:32:58 -0700428func main() {
Rob Pike325cf8e2010-03-24 16:46:53 -0700429 testchan()
430 testarray()
Russ Cox81c3e8c2010-07-01 18:04:25 -0700431 testarray1()
Russ Cox8d504c42014-07-16 19:27:10 -0400432 testarray2()
Russ Cox81c3e8c2010-07-01 18:04:25 -0700433 testarrayptr()
434 testarrayptr1()
Russ Cox8d504c42014-07-16 19:27:10 -0400435 testarrayptr2()
Russ Cox81c3e8c2010-07-01 18:04:25 -0700436 testslice()
437 testslice1()
Russ Cox8d504c42014-07-16 19:27:10 -0400438 testslice2()
Martin Möhrmannb6796652016-10-27 23:31:38 +0200439 testslice3()
Russ Cox81c3e8c2010-07-01 18:04:25 -0700440 teststring()
441 teststring1()
Russ Cox8d504c42014-07-16 19:27:10 -0400442 teststring2()
Russ Cox81c3e8c2010-07-01 18:04:25 -0700443 testmap()
444 testmap1()
Russ Cox8d504c42014-07-16 19:27:10 -0400445 testmap2()
Rob Pike325cf8e2010-03-24 16:46:53 -0700446 testcalls()
Russ Cox54aa8352009-03-20 11:32:58 -0700447}