github.com/rohankumardubey/syslog-redirector-golang@v0.0.0-20140320174030-4859f03d829a/src/pkg/runtime/mfinal_test.go (about) 1 // Copyright 2011 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package runtime_test 6 7 import ( 8 "runtime" 9 "sync" 10 "sync/atomic" 11 "testing" 12 "time" 13 ) 14 15 type Tintptr *int // assignable to *int 16 type Tint int // *Tint implements Tinter, interface{} 17 18 func (t *Tint) m() {} 19 20 type Tinter interface { 21 m() 22 } 23 24 func TestFinalizerType(t *testing.T) { 25 if runtime.GOARCH != "amd64" { 26 t.Skipf("Skipping on non-amd64 machine") 27 } 28 29 ch := make(chan bool, 10) 30 finalize := func(x *int) { 31 if *x != 97531 { 32 t.Errorf("finalizer %d, want %d", *x, 97531) 33 } 34 ch <- true 35 } 36 37 var finalizerTests = []struct { 38 convert func(*int) interface{} 39 finalizer interface{} 40 }{ 41 {func(x *int) interface{} { return x }, func(v *int) { finalize(v) }}, 42 {func(x *int) interface{} { return Tintptr(x) }, func(v Tintptr) { finalize(v) }}, 43 {func(x *int) interface{} { return Tintptr(x) }, func(v *int) { finalize(v) }}, 44 {func(x *int) interface{} { return (*Tint)(x) }, func(v *Tint) { finalize((*int)(v)) }}, 45 {func(x *int) interface{} { return (*Tint)(x) }, func(v Tinter) { finalize((*int)(v.(*Tint))) }}, 46 } 47 48 for _, tt := range finalizerTests { 49 go func() { 50 v := new(int) 51 *v = 97531 52 runtime.SetFinalizer(tt.convert(v), tt.finalizer) 53 v = nil 54 }() 55 time.Sleep(1 * time.Second) 56 runtime.GC() 57 select { 58 case <-ch: 59 case <-time.After(time.Second * 4): 60 t.Errorf("finalizer for type %T didn't run", tt.finalizer) 61 } 62 } 63 } 64 65 type bigValue struct { 66 fill uint64 67 it bool 68 up string 69 } 70 71 func TestFinalizerInterfaceBig(t *testing.T) { 72 if runtime.GOARCH != "amd64" { 73 t.Skipf("Skipping on non-amd64 machine") 74 } 75 ch := make(chan bool) 76 go func() { 77 v := &bigValue{0xDEADBEEFDEADBEEF, true, "It matters not how strait the gate"} 78 old := *v 79 runtime.SetFinalizer(v, func(v interface{}) { 80 i, ok := v.(*bigValue) 81 if !ok { 82 t.Errorf("finalizer called with type %T, want *bigValue", v) 83 } 84 if *i != old { 85 t.Errorf("finalizer called with %+v, want %+v", *i, old) 86 } 87 close(ch) 88 }) 89 v = nil 90 }() 91 time.Sleep(1 * time.Second) 92 runtime.GC() 93 select { 94 case <-ch: 95 case <-time.After(4 * time.Second): 96 t.Errorf("finalizer for type *bigValue didn't run") 97 } 98 } 99 100 func fin(v *int) { 101 } 102 103 func BenchmarkFinalizer(b *testing.B) { 104 const CallsPerSched = 1000 105 procs := runtime.GOMAXPROCS(-1) 106 N := int32(b.N / CallsPerSched) 107 var wg sync.WaitGroup 108 wg.Add(procs) 109 for p := 0; p < procs; p++ { 110 go func() { 111 var data [CallsPerSched]*int 112 for i := 0; i < CallsPerSched; i++ { 113 data[i] = new(int) 114 } 115 for atomic.AddInt32(&N, -1) >= 0 { 116 runtime.Gosched() 117 for i := 0; i < CallsPerSched; i++ { 118 runtime.SetFinalizer(data[i], fin) 119 } 120 for i := 0; i < CallsPerSched; i++ { 121 runtime.SetFinalizer(data[i], nil) 122 } 123 } 124 wg.Done() 125 }() 126 } 127 wg.Wait() 128 } 129 130 func BenchmarkFinalizerRun(b *testing.B) { 131 const CallsPerSched = 1000 132 procs := runtime.GOMAXPROCS(-1) 133 N := int32(b.N / CallsPerSched) 134 var wg sync.WaitGroup 135 wg.Add(procs) 136 for p := 0; p < procs; p++ { 137 go func() { 138 for atomic.AddInt32(&N, -1) >= 0 { 139 runtime.Gosched() 140 for i := 0; i < CallsPerSched; i++ { 141 v := new(int) 142 runtime.SetFinalizer(v, fin) 143 } 144 runtime.GC() 145 } 146 wg.Done() 147 }() 148 } 149 wg.Wait() 150 }