blob: af89edac54b1814835ef7a926049c281435b868f [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
Russ Cox81c3e8c2010-07-01 18:04:25 -0700113// test that range over array only evaluates
114// the expression after "range" once.
115
116func makearray() [5]int {
117 nmake++
118 return [5]int{1, 2, 3, 4, 5}
119}
120
Russ Cox54aa8352009-03-20 11:32:58 -0700121func testarray() {
Rob Pike325cf8e2010-03-24 16:46:53 -0700122 s := 0
Russ Cox81c3e8c2010-07-01 18:04:25 -0700123 nmake = 0
Russ Coxae54cf72009-09-15 12:42:24 -0700124 for _, v := range makearray() {
Rob Pike325cf8e2010-03-24 16:46:53 -0700125 s += v
Russ Cox54aa8352009-03-20 11:32:58 -0700126 }
127 if nmake != 1 {
Rob Pike325cf8e2010-03-24 16:46:53 -0700128 println("range called makearray", nmake, "times")
129 panic("fail")
Russ Cox54aa8352009-03-20 11:32:58 -0700130 }
131 if s != 15 {
Alan Donovan1c1096e2013-02-11 18:20:52 -0500132 println("wrong sum ranging over makearray", s)
Rob Pike325cf8e2010-03-24 16:46:53 -0700133 panic("fail")
Russ Cox54aa8352009-03-20 11:32:58 -0700134 }
135}
136
Russ Cox81c3e8c2010-07-01 18:04:25 -0700137func testarray1() {
138 s := 0
139 nmake = 0
140 for i := range makearray() {
141 s += i
142 }
143 if nmake != 1 {
144 println("range called makearray", nmake, "times")
145 panic("fail")
146 }
147 if s != 10 {
Alan Donovan1c1096e2013-02-11 18:20:52 -0500148 println("wrong sum ranging over makearray", s)
Russ Cox81c3e8c2010-07-01 18:04:25 -0700149 panic("fail")
150 }
151}
152
Russ Cox8d504c42014-07-16 19:27:10 -0400153func testarray2() {
154 n := 0
155 nmake = 0
156 for range makearray() {
157 n++
158 }
159 if nmake != 1 {
160 println("range called makearray", nmake, "times")
161 panic("fail")
162 }
163 if n != 5 {
164 println("wrong count ranging over makearray", n)
165 panic("fail")
166 }
167}
168
Russ Cox81c3e8c2010-07-01 18:04:25 -0700169func makearrayptr() *[5]int {
170 nmake++
171 return &[5]int{1, 2, 3, 4, 5}
172}
173
174func testarrayptr() {
175 nmake = 0
176 x := len(makearrayptr())
177 if x != 5 || nmake != 1 {
178 println("len called makearrayptr", nmake, "times and got len", x)
179 panic("fail")
180 }
181 nmake = 0
182 x = cap(makearrayptr())
183 if x != 5 || nmake != 1 {
184 println("cap called makearrayptr", nmake, "times and got len", x)
185 panic("fail")
186 }
187 s := 0
188 nmake = 0
189 for _, v := range makearrayptr() {
190 s += v
191 }
192 if nmake != 1 {
193 println("range called makearrayptr", nmake, "times")
194 panic("fail")
195 }
196 if s != 15 {
Alan Donovan1c1096e2013-02-11 18:20:52 -0500197 println("wrong sum ranging over makearrayptr", s)
Russ Cox81c3e8c2010-07-01 18:04:25 -0700198 panic("fail")
199 }
200}
201
202func testarrayptr1() {
203 s := 0
204 nmake = 0
205 for i := range makearrayptr() {
206 s += i
207 }
208 if nmake != 1 {
209 println("range called makearrayptr", nmake, "times")
210 panic("fail")
211 }
212 if s != 10 {
Alan Donovan1c1096e2013-02-11 18:20:52 -0500213 println("wrong sum ranging over makearrayptr", s)
Russ Cox81c3e8c2010-07-01 18:04:25 -0700214 panic("fail")
215 }
216}
217
Russ Cox8d504c42014-07-16 19:27:10 -0400218func testarrayptr2() {
219 n := 0
220 nmake = 0
221 for range makearrayptr() {
222 n++
223 }
224 if nmake != 1 {
225 println("range called makearrayptr", nmake, "times")
226 panic("fail")
227 }
228 if n != 5 {
229 println("wrong count ranging over makearrayptr", n)
230 panic("fail")
231 }
232}
233
Russ Cox81c3e8c2010-07-01 18:04:25 -0700234// test that range over string only evaluates
235// the expression after "range" once.
236
237func makestring() string {
238 nmake++
239 return "abcd☺"
240}
241
242func teststring() {
Russ Coxdb339592011-10-25 22:20:02 -0700243 var s rune
Russ Cox81c3e8c2010-07-01 18:04:25 -0700244 nmake = 0
245 for _, v := range makestring() {
246 s += v
247 }
248 if nmake != 1 {
249 println("range called makestring", nmake, "times")
250 panic("fail")
251 }
252 if s != 'a'+'b'+'c'+'d'+'☺' {
Alan Donovan1c1096e2013-02-11 18:20:52 -0500253 println("wrong sum ranging over makestring", s)
Russ Cox81c3e8c2010-07-01 18:04:25 -0700254 panic("fail")
255 }
256}
257
258func teststring1() {
259 s := 0
260 nmake = 0
261 for i := range makestring() {
262 s += i
263 }
264 if nmake != 1 {
265 println("range called makestring", nmake, "times")
266 panic("fail")
267 }
268 if s != 10 {
Alan Donovan1c1096e2013-02-11 18:20:52 -0500269 println("wrong sum ranging over makestring", s)
Russ Cox81c3e8c2010-07-01 18:04:25 -0700270 panic("fail")
271 }
272}
273
Russ Cox8d504c42014-07-16 19:27:10 -0400274func teststring2() {
275 n := 0
276 nmake = 0
277 for range makestring() {
278 n++
279 }
280 if nmake != 1 {
281 println("range called makestring", nmake, "times")
282 panic("fail")
283 }
284 if n != 5 {
285 println("wrong count ranging over makestring", n)
286 panic("fail")
287 }
288}
289
Russ Cox81c3e8c2010-07-01 18:04:25 -0700290// test that range over map only evaluates
291// the expression after "range" once.
292
293func makemap() map[int]int {
294 nmake++
Russ Coxdb339592011-10-25 22:20:02 -0700295 return map[int]int{0: 'a', 1: 'b', 2: 'c', 3: 'd', 4: '☺'}
Russ Cox81c3e8c2010-07-01 18:04:25 -0700296}
297
298func testmap() {
299 s := 0
300 nmake = 0
301 for _, v := range makemap() {
302 s += v
303 }
304 if nmake != 1 {
305 println("range called makemap", nmake, "times")
306 panic("fail")
307 }
308 if s != 'a'+'b'+'c'+'d'+'☺' {
Alan Donovan1c1096e2013-02-11 18:20:52 -0500309 println("wrong sum ranging over makemap", s)
Russ Cox81c3e8c2010-07-01 18:04:25 -0700310 panic("fail")
311 }
312}
313
314func testmap1() {
315 s := 0
316 nmake = 0
317 for i := range makemap() {
318 s += i
319 }
320 if nmake != 1 {
321 println("range called makemap", nmake, "times")
322 panic("fail")
323 }
324 if s != 10 {
Alan Donovan1c1096e2013-02-11 18:20:52 -0500325 println("wrong sum ranging over makemap", s)
Russ Cox81c3e8c2010-07-01 18:04:25 -0700326 panic("fail")
327 }
328}
329
Russ Cox8d504c42014-07-16 19:27:10 -0400330func testmap2() {
331 n := 0
332 nmake = 0
333 for range makemap() {
334 n++
335 }
336 if nmake != 1 {
337 println("range called makemap", nmake, "times")
338 panic("fail")
339 }
340 if n != 5 {
341 println("wrong count ranging over makemap", n)
342 panic("fail")
343 }
344}
345
Ian Lance Taylorff68f962010-01-15 10:40:30 -0800346// test that range evaluates the index and value expressions
347// exactly once per iteration.
348
349var ncalls = 0
Rob Pike325cf8e2010-03-24 16:46:53 -0700350
Ian Lance Taylorff68f962010-01-15 10:40:30 -0800351func getvar(p *int) *int {
352 ncalls++
353 return p
354}
355
356func testcalls() {
357 var i, v int
358 si := 0
359 sv := 0
360 for *getvar(&i), *getvar(&v) = range [2]int{1, 2} {
361 si += i
362 sv += v
363 }
364 if ncalls != 4 {
Rob Pike325cf8e2010-03-24 16:46:53 -0700365 println("wrong number of calls:", ncalls, "!= 4")
366 panic("fail")
Ian Lance Taylorff68f962010-01-15 10:40:30 -0800367 }
368 if si != 1 || sv != 3 {
Rob Pike325cf8e2010-03-24 16:46:53 -0700369 println("wrong sum in testcalls", si, sv)
370 panic("fail")
Ian Lance Taylorff68f962010-01-15 10:40:30 -0800371 }
372
373 ncalls = 0
374 for *getvar(&i), *getvar(&v) = range [0]int{} {
Rob Pike325cf8e2010-03-24 16:46:53 -0700375 println("loop ran on empty array")
376 panic("fail")
Ian Lance Taylorff68f962010-01-15 10:40:30 -0800377 }
378 if ncalls != 0 {
Rob Pike325cf8e2010-03-24 16:46:53 -0700379 println("wrong number of calls:", ncalls, "!= 0")
380 panic("fail")
Ian Lance Taylorff68f962010-01-15 10:40:30 -0800381 }
382}
383
Russ Cox54aa8352009-03-20 11:32:58 -0700384func main() {
Rob Pike325cf8e2010-03-24 16:46:53 -0700385 testchan()
386 testarray()
Russ Cox81c3e8c2010-07-01 18:04:25 -0700387 testarray1()
Russ Cox8d504c42014-07-16 19:27:10 -0400388 testarray2()
Russ Cox81c3e8c2010-07-01 18:04:25 -0700389 testarrayptr()
390 testarrayptr1()
Russ Cox8d504c42014-07-16 19:27:10 -0400391 testarrayptr2()
Russ Cox81c3e8c2010-07-01 18:04:25 -0700392 testslice()
393 testslice1()
Russ Cox8d504c42014-07-16 19:27:10 -0400394 testslice2()
Russ Cox81c3e8c2010-07-01 18:04:25 -0700395 teststring()
396 teststring1()
Russ Cox8d504c42014-07-16 19:27:10 -0400397 teststring2()
Russ Cox81c3e8c2010-07-01 18:04:25 -0700398 testmap()
399 testmap1()
Russ Cox8d504c42014-07-16 19:27:10 -0400400 testmap2()
Rob Pike325cf8e2010-03-24 16:46:53 -0700401 testcalls()
Russ Cox54aa8352009-03-20 11:32:58 -0700402}