github.com/activestate/go@v0.0.0-20170614201249-0b81c023a722/test/range.go (about)

     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  	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  	}
   300  }
   301  
   302  func 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 {
   313  		println("wrong sum ranging over makestring", s)
   314  		panic("fail")
   315  	}
   316  }
   317  
   318  func 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  
   334  // test that range over map only evaluates
   335  // the expression after "range" once.
   336  
   337  func makemap() map[int]int {
   338  	nmake++
   339  	return map[int]int{0: 'a', 1: 'b', 2: 'c', 3: 'd', 4: '☺'}
   340  }
   341  
   342  func 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'+'☺' {
   353  		println("wrong sum ranging over makemap", s)
   354  		panic("fail")
   355  	}
   356  }
   357  
   358  func 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 {
   369  		println("wrong sum ranging over makemap", s)
   370  		panic("fail")
   371  	}
   372  }
   373  
   374  func 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  
   390  // test that range evaluates the index and value expressions
   391  // exactly once per iteration.
   392  
   393  var ncalls = 0
   394  
   395  func getvar(p *int) *int {
   396  	ncalls++
   397  	return p
   398  }
   399  
   400  func 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 {
   409  		println("wrong number of calls:", ncalls, "!= 4")
   410  		panic("fail")
   411  	}
   412  	if si != 1 || sv != 3 {
   413  		println("wrong sum in testcalls", si, sv)
   414  		panic("fail")
   415  	}
   416  
   417  	ncalls = 0
   418  	for *getvar(&i), *getvar(&v) = range [0]int{} {
   419  		println("loop ran on empty array")
   420  		panic("fail")
   421  	}
   422  	if ncalls != 0 {
   423  		println("wrong number of calls:", ncalls, "!= 0")
   424  		panic("fail")
   425  	}
   426  }
   427  
   428  func main() {
   429  	testchan()
   430  	testarray()
   431  	testarray1()
   432  	testarray2()
   433  	testarrayptr()
   434  	testarrayptr1()
   435  	testarrayptr2()
   436  	testslice()
   437  	testslice1()
   438  	testslice2()
   439  	testslice3()
   440  	teststring()
   441  	teststring1()
   442  	teststring2()
   443  	testmap()
   444  	testmap1()
   445  	testmap2()
   446  	testcalls()
   447  }