diff options
Diffstat (limited to 'src/pkg/runtime/mfinal_test.go')
-rw-r--r-- | src/pkg/runtime/mfinal_test.go | 86 |
1 files changed, 86 insertions, 0 deletions
diff --git a/src/pkg/runtime/mfinal_test.go b/src/pkg/runtime/mfinal_test.go index de632717a..6efef9bb0 100644 --- a/src/pkg/runtime/mfinal_test.go +++ b/src/pkg/runtime/mfinal_test.go @@ -9,8 +9,94 @@ import ( "sync" "sync/atomic" "testing" + "time" ) +type Tintptr *int // assignable to *int +type Tint int // *Tint implements Tinter, interface{} + +func (t *Tint) m() {} + +type Tinter interface { + m() +} + +func TestFinalizerType(t *testing.T) { + if runtime.GOARCH != "amd64" { + t.Skipf("Skipping on non-amd64 machine") + } + + ch := make(chan bool, 10) + finalize := func(x *int) { + if *x != 97531 { + t.Errorf("finalizer %d, want %d", *x, 97531) + } + ch <- true + } + + var finalizerTests = []struct { + convert func(*int) interface{} + finalizer interface{} + }{ + {func(x *int) interface{} { return x }, func(v *int) { finalize(v) }}, + {func(x *int) interface{} { return Tintptr(x) }, func(v Tintptr) { finalize(v) }}, + {func(x *int) interface{} { return Tintptr(x) }, func(v *int) { finalize(v) }}, + {func(x *int) interface{} { return (*Tint)(x) }, func(v *Tint) { finalize((*int)(v)) }}, + {func(x *int) interface{} { return (*Tint)(x) }, func(v Tinter) { finalize((*int)(v.(*Tint))) }}, + } + + for _, tt := range finalizerTests { + go func() { + v := new(int) + *v = 97531 + runtime.SetFinalizer(tt.convert(v), tt.finalizer) + v = nil + }() + time.Sleep(1 * time.Second) + runtime.GC() + select { + case <-ch: + case <-time.After(time.Second * 4): + t.Errorf("finalizer for type %T didn't run", tt.finalizer) + } + } +} + +type bigValue struct { + fill uint64 + it bool + up string +} + +func TestFinalizerInterfaceBig(t *testing.T) { + if runtime.GOARCH != "amd64" { + t.Skipf("Skipping on non-amd64 machine") + } + ch := make(chan bool) + go func() { + v := &bigValue{0xDEADBEEFDEADBEEF, true, "It matters not how strait the gate"} + old := *v + runtime.SetFinalizer(v, func(v interface{}) { + i, ok := v.(*bigValue) + if !ok { + t.Errorf("finalizer called with type %T, want *bigValue", v) + } + if *i != old { + t.Errorf("finalizer called with %+v, want %+v", *i, old) + } + close(ch) + }) + v = nil + }() + time.Sleep(1 * time.Second) + runtime.GC() + select { + case <-ch: + case <-time.After(4 * time.Second): + t.Errorf("finalizer for type *bigValue didn't run") + } +} + func fin(v *int) { } |