github.com/huandu/go@v0.0.0-20151114150818-04e615e41150/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 array only evaluates
   114  // the expression after "range" once.
   115  
   116  func makearray() [5]int {
   117  	nmake++
   118  	return [5]int{1, 2, 3, 4, 5}
   119  }
   120  
   121  func testarray() {
   122  	s := 0
   123  	nmake = 0
   124  	for _, v := range makearray() {
   125  		s += v
   126  	}
   127  	if nmake != 1 {
   128  		println("range called makearray", nmake, "times")
   129  		panic("fail")
   130  	}
   131  	if s != 15 {
   132  		println("wrong sum ranging over makearray", s)
   133  		panic("fail")
   134  	}
   135  }
   136  
   137  func 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 {
   148  		println("wrong sum ranging over makearray", s)
   149  		panic("fail")
   150  	}
   151  }
   152  
   153  func 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  
   169  func makearrayptr() *[5]int {
   170  	nmake++
   171  	return &[5]int{1, 2, 3, 4, 5}
   172  }
   173  
   174  func 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 {
   197  		println("wrong sum ranging over makearrayptr", s)
   198  		panic("fail")
   199  	}
   200  }
   201  
   202  func 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 {
   213  		println("wrong sum ranging over makearrayptr", s)
   214  		panic("fail")
   215  	}
   216  }
   217  
   218  func 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  
   234  // test that range over string only evaluates
   235  // the expression after "range" once.
   236  
   237  func makestring() string {
   238  	nmake++
   239  	return "abcd☺"
   240  }
   241  
   242  func teststring() {
   243  	var s rune
   244  	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'+'☺' {
   253  		println("wrong sum ranging over makestring", s)
   254  		panic("fail")
   255  	}
   256  }
   257  
   258  func 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 {
   269  		println("wrong sum ranging over makestring", s)
   270  		panic("fail")
   271  	}
   272  }
   273  
   274  func 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  
   290  // test that range over map only evaluates
   291  // the expression after "range" once.
   292  
   293  func makemap() map[int]int {
   294  	nmake++
   295  	return map[int]int{0: 'a', 1: 'b', 2: 'c', 3: 'd', 4: '☺'}
   296  }
   297  
   298  func 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'+'☺' {
   309  		println("wrong sum ranging over makemap", s)
   310  		panic("fail")
   311  	}
   312  }
   313  
   314  func 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 {
   325  		println("wrong sum ranging over makemap", s)
   326  		panic("fail")
   327  	}
   328  }
   329  
   330  func 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  
   346  // test that range evaluates the index and value expressions
   347  // exactly once per iteration.
   348  
   349  var ncalls = 0
   350  
   351  func getvar(p *int) *int {
   352  	ncalls++
   353  	return p
   354  }
   355  
   356  func 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 {
   365  		println("wrong number of calls:", ncalls, "!= 4")
   366  		panic("fail")
   367  	}
   368  	if si != 1 || sv != 3 {
   369  		println("wrong sum in testcalls", si, sv)
   370  		panic("fail")
   371  	}
   372  
   373  	ncalls = 0
   374  	for *getvar(&i), *getvar(&v) = range [0]int{} {
   375  		println("loop ran on empty array")
   376  		panic("fail")
   377  	}
   378  	if ncalls != 0 {
   379  		println("wrong number of calls:", ncalls, "!= 0")
   380  		panic("fail")
   381  	}
   382  }
   383  
   384  func main() {
   385  	testchan()
   386  	testarray()
   387  	testarray1()
   388  	testarray2()
   389  	testarrayptr()
   390  	testarrayptr1()
   391  	testarrayptr2()
   392  	testslice()
   393  	testslice1()
   394  	testslice2()
   395  	teststring()
   396  	teststring1()
   397  	teststring2()
   398  	testmap()
   399  	testmap1()
   400  	testmap2()
   401  	testcalls()
   402  }