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  }