Source file test/range.go

     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  const alphabet = "abcdefghijklmnopqrstuvwxyz"
    27  
    28  func 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  
    71  func testchan() {
    72  	s := ""
    73  	for i := range seq('a', 'z') {
    74  		s += string(i)
    75  	}
    76  	if s != alphabet {
    77  		println("Wanted lowercase alphabet; got", s)
    78  		panic("fail")
    79  	}
    80  	n := 0
    81  	for range seq('a', 'z') {
    82  		n++
    83  	}
    84  	if n != 26 {
    85  		println("testchan wrong count", n, "want 26")
    86  		panic("fail")
    87  	}
    88  }
    89  
    90  // test that range over slice only evaluates
    91  // the expression after "range" once.
    92  
    93  var nmake = 0
    94  
    95  func makeslice() []int {
    96  	nmake++
    97  	return []int{1, 2, 3, 4, 5}
    98  }
    99  
   100  func 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 {
   111  		println("wrong sum ranging over makeslice", s)
   112  		panic("fail")
   113  	}
   114  
   115  	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  	}
   125  }
   126  
   127  func 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 {
   138  		println("wrong sum ranging over makeslice", s)
   139  		panic("fail")
   140  	}
   141  }
   142  
   143  func 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  
   159  // test that range over []byte(string) only evaluates
   160  // the expression after "range" once.
   161  
   162  func makenumstring() string {
   163  	nmake++
   164  	return "\x01\x02\x03\x04\x05"
   165  }
   166  
   167  func 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  
   183  // test that range over array only evaluates
   184  // the expression after "range" once.
   185  
   186  func makearray() [5]int {
   187  	nmake++
   188  	return [5]int{1, 2, 3, 4, 5}
   189  }
   190  
   191  func testarray() {
   192  	s := 0
   193  	nmake = 0
   194  	for _, v := range makearray() {
   195  		s += v
   196  	}
   197  	if nmake != 1 {
   198  		println("range called makearray", nmake, "times")
   199  		panic("fail")
   200  	}
   201  	if s != 15 {
   202  		println("wrong sum ranging over makearray", s)
   203  		panic("fail")
   204  	}
   205  }
   206  
   207  func 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 {
   218  		println("wrong sum ranging over makearray", s)
   219  		panic("fail")
   220  	}
   221  }
   222  
   223  func 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  
   239  func makearrayptr() *[5]int {
   240  	nmake++
   241  	return &[5]int{1, 2, 3, 4, 5}
   242  }
   243  
   244  func 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 {
   267  		println("wrong sum ranging over makearrayptr", s)
   268  		panic("fail")
   269  	}
   270  }
   271  
   272  func 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 {
   283  		println("wrong sum ranging over makearrayptr", s)
   284  		panic("fail")
   285  	}
   286  }
   287  
   288  func 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  
   304  // test that range over string only evaluates
   305  // the expression after "range" once.
   306  
   307  func makestring() string {
   308  	nmake++
   309  	return "abcd☺"
   310  }
   311  
   312  func teststring() {
   313  	var s rune
   314  	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'+'☺' {
   323  		println("wrong sum ranging over makestring", s)
   324  		panic("fail")
   325  	}
   326  
   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  	}
   346  }
   347  
   348  func 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 {
   359  		println("wrong sum ranging over makestring", s)
   360  		panic("fail")
   361  	}
   362  }
   363  
   364  func 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  
   380  // test that range over map only evaluates
   381  // the expression after "range" once.
   382  
   383  func makemap() map[int]int {
   384  	nmake++
   385  	return map[int]int{0: 'a', 1: 'b', 2: 'c', 3: 'd', 4: '☺'}
   386  }
   387  
   388  func 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'+'☺' {
   399  		println("wrong sum ranging over makemap", s)
   400  		panic("fail")
   401  	}
   402  }
   403  
   404  func 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 {
   415  		println("wrong sum ranging over makemap", s)
   416  		panic("fail")
   417  	}
   418  }
   419  
   420  func 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  
   436  // test that range evaluates the index and value expressions
   437  // exactly once per iteration.
   438  
   439  var ncalls = 0
   440  
   441  func getvar(p *int) *int {
   442  	ncalls++
   443  	return p
   444  }
   445  
   446  func 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 {
   455  		println("wrong number of calls:", ncalls, "!= 4")
   456  		panic("fail")
   457  	}
   458  	if si != 1 || sv != 3 {
   459  		println("wrong sum in testcalls", si, sv)
   460  		panic("fail")
   461  	}
   462  
   463  	ncalls = 0
   464  	for *getvar(&i), *getvar(&v) = range [0]int{} {
   465  		println("loop ran on empty array")
   466  		panic("fail")
   467  	}
   468  	if ncalls != 0 {
   469  		println("wrong number of calls:", ncalls, "!= 0")
   470  		panic("fail")
   471  	}
   472  }
   473  
   474  func main() {
   475  	testblankvars()
   476  	testchan()
   477  	testarray()
   478  	testarray1()
   479  	testarray2()
   480  	testarrayptr()
   481  	testarrayptr1()
   482  	testarrayptr2()
   483  	testslice()
   484  	testslice1()
   485  	testslice2()
   486  	testslice3()
   487  	teststring()
   488  	teststring1()
   489  	teststring2()
   490  	testmap()
   491  	testmap1()
   492  	testmap2()
   493  	testcalls()
   494  }
   495  

View as plain text