Home | History | Annotate | Download | only in test
      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 behavior of closures.
      8 
      9 package main
     10 
     11 import "runtime"
     12 
     13 var c = make(chan int)
     14 
     15 func check(a []int) {
     16 	for i := 0; i < len(a); i++ {
     17 		n := <-c
     18 		if n != a[i] {
     19 			println("want", a[i], "got", n, "at", i)
     20 			panic("fail")
     21 		}
     22 	}
     23 }
     24 
     25 func f() {
     26 	var i, j int
     27 
     28 	i = 1
     29 	j = 2
     30 	f := func() {
     31 		c <- i
     32 		i = 4
     33 		g := func() {
     34 			c <- i
     35 			c <- j
     36 		}
     37 		g()
     38 		c <- i
     39 	}
     40 	j = 5
     41 	f()
     42 }
     43 
     44 // Accumulator generator
     45 func accum(n int) func(int) int {
     46 	return func(i int) int {
     47 		n += i
     48 		return n
     49 	}
     50 }
     51 
     52 func g(a, b func(int) int) {
     53 	c <- a(2)
     54 	c <- b(3)
     55 	c <- a(4)
     56 	c <- b(5)
     57 }
     58 
     59 func h() {
     60 	var x8 byte = 100
     61 	var x64 int64 = 200
     62 
     63 	c <- int(x8)
     64 	c <- int(x64)
     65 	f := func(z int) {
     66 		g := func() {
     67 			c <- int(x8)
     68 			c <- int(x64)
     69 			c <- z
     70 		}
     71 		g()
     72 		c <- int(x8)
     73 		c <- int(x64)
     74 		c <- int(z)
     75 	}
     76 	x8 = 101
     77 	x64 = 201
     78 	f(500)
     79 }
     80 
     81 func newfunc() func(int) int { return func(x int) int { return x } }
     82 
     83 func main() {
     84 	runtime.GOMAXPROCS(1)
     85 	var fail bool
     86 
     87 	go f()
     88 	check([]int{1, 4, 5, 4})
     89 
     90 	a := accum(0)
     91 	b := accum(1)
     92 	go g(a, b)
     93 	check([]int{2, 4, 6, 9})
     94 
     95 	go h()
     96 	check([]int{100, 200, 101, 201, 500, 101, 201, 500})
     97 
     98 	memstats := new(runtime.MemStats)
     99 	runtime.ReadMemStats(memstats)
    100 	n0 := memstats.Mallocs
    101 
    102 	x, y := newfunc(), newfunc()
    103 	if x(1) != 1 || y(2) != 2 {
    104 		println("newfunc returned broken funcs")
    105 		fail = true
    106 	}
    107 
    108 	runtime.ReadMemStats(memstats)
    109 	if n0 != memstats.Mallocs {
    110 		println("newfunc allocated unexpectedly")
    111 		fail = true
    112 	}
    113 
    114 	ff(1)
    115 
    116 	if fail {
    117 		panic("fail")
    118 	}
    119 }
    120 
    121 func ff(x int) {
    122 	call(func() {
    123 		_ = x
    124 	})
    125 }
    126 
    127 func call(func()) {
    128 }
    129