blob: bae7a1c3c9dea2a6916b5469039ee4859de707a5 [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 }
280}
281
282func 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 {
Alan Donovan1c1096e2013-02-11 18:20:52 -0500293 println("wrong sum ranging over makestring", s)
Russ Cox81c3e8c2010-07-01 18:04:25 -0700294 panic("fail")
295 }
296}
297
Russ Cox8d504c42014-07-16 19:27:10 -0400298func 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
Russ Cox81c3e8c2010-07-01 18:04:25 -0700314// test that range over map only evaluates
315// the expression after "range" once.
316
317func makemap() map[int]int {
318 nmake++
Russ Coxdb339592011-10-25 22:20:02 -0700319 return map[int]int{0: 'a', 1: 'b', 2: 'c', 3: 'd', 4: '☺'}
Russ Cox81c3e8c2010-07-01 18:04:25 -0700320}
321
322func 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'+'☺' {
Alan Donovan1c1096e2013-02-11 18:20:52 -0500333 println("wrong sum ranging over makemap", s)
Russ Cox81c3e8c2010-07-01 18:04:25 -0700334 panic("fail")
335 }
336}
337
338func 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 {
Alan Donovan1c1096e2013-02-11 18:20:52 -0500349 println("wrong sum ranging over makemap", s)
Russ Cox81c3e8c2010-07-01 18:04:25 -0700350 panic("fail")
351 }
352}
353
Russ Cox8d504c42014-07-16 19:27:10 -0400354func 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
Ian Lance Taylorff68f962010-01-15 10:40:30 -0800370// test that range evaluates the index and value expressions
371// exactly once per iteration.
372
373var ncalls = 0
Rob Pike325cf8e2010-03-24 16:46:53 -0700374
Ian Lance Taylorff68f962010-01-15 10:40:30 -0800375func getvar(p *int) *int {
376 ncalls++
377 return p
378}
379
380func 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 {
Rob Pike325cf8e2010-03-24 16:46:53 -0700389 println("wrong number of calls:", ncalls, "!= 4")
390 panic("fail")
Ian Lance Taylorff68f962010-01-15 10:40:30 -0800391 }
392 if si != 1 || sv != 3 {
Rob Pike325cf8e2010-03-24 16:46:53 -0700393 println("wrong sum in testcalls", si, sv)
394 panic("fail")
Ian Lance Taylorff68f962010-01-15 10:40:30 -0800395 }
396
397 ncalls = 0
398 for *getvar(&i), *getvar(&v) = range [0]int{} {
Rob Pike325cf8e2010-03-24 16:46:53 -0700399 println("loop ran on empty array")
400 panic("fail")
Ian Lance Taylorff68f962010-01-15 10:40:30 -0800401 }
402 if ncalls != 0 {
Rob Pike325cf8e2010-03-24 16:46:53 -0700403 println("wrong number of calls:", ncalls, "!= 0")
404 panic("fail")
Ian Lance Taylorff68f962010-01-15 10:40:30 -0800405 }
406}
407
Russ Cox54aa8352009-03-20 11:32:58 -0700408func main() {
Rob Pike325cf8e2010-03-24 16:46:53 -0700409 testchan()
410 testarray()
Russ Cox81c3e8c2010-07-01 18:04:25 -0700411 testarray1()
Russ Cox8d504c42014-07-16 19:27:10 -0400412 testarray2()
Russ Cox81c3e8c2010-07-01 18:04:25 -0700413 testarrayptr()
414 testarrayptr1()
Russ Cox8d504c42014-07-16 19:27:10 -0400415 testarrayptr2()
Russ Cox81c3e8c2010-07-01 18:04:25 -0700416 testslice()
417 testslice1()
Russ Cox8d504c42014-07-16 19:27:10 -0400418 testslice2()
Martin Möhrmannb6796652016-10-27 23:31:38 +0200419 testslice3()
Russ Cox81c3e8c2010-07-01 18:04:25 -0700420 teststring()
421 teststring1()
Russ Cox8d504c42014-07-16 19:27:10 -0400422 teststring2()
Russ Cox81c3e8c2010-07-01 18:04:25 -0700423 testmap()
424 testmap1()
Russ Cox8d504c42014-07-16 19:27:10 -0400425 testmap2()
Rob Pike325cf8e2010-03-24 16:46:53 -0700426 testcalls()
Russ Cox54aa8352009-03-20 11:32:58 -0700427}