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.
14 type Tintptr
*int // assignable to *int
15 type Tint
int // *Tint implements Tinter, interface{}
19 type Tinter
interface {
23 func TestFinalizerType(t
*testing
.T
) {
24 if runtime
.GOARCH
!= "amd64" {
25 t
.Skipf("Skipping on non-amd64 machine")
27 if runtime
.Compiler
== "gccgo" {
28 t
.Skip("skipping for gccgo")
31 ch
:= make(chan bool, 10)
32 finalize
:= func(x
*int) {
34 t
.Errorf("finalizer %d, want %d", *x
, 97531)
39 var finalizerTests
= []struct {
40 convert
func(*int) interface{}
43 {func(x
*int) interface{} { return x
}, func(v
*int) { finalize(v
) }},
44 {func(x
*int) interface{} { return Tintptr(x
) }, func(v Tintptr
) { finalize(v
) }},
45 {func(x
*int) interface{} { return Tintptr(x
) }, func(v
*int) { finalize(v
) }},
46 {func(x
*int) interface{} { return (*Tint
)(x
) }, func(v
*Tint
) { finalize((*int)(v
)) }},
47 {func(x
*int) interface{} { return (*Tint
)(x
) }, func(v Tinter
) { finalize((*int)(v
.(*Tint
))) }},
50 for i
, tt
:= range finalizerTests
{
51 done
:= make(chan bool, 1)
53 // allocate struct with pointer to avoid hitting tinyalloc.
54 // Otherwise we can't be sure when the allocation will
62 runtime
.SetFinalizer(tt
.convert(v
), tt
.finalizer
)
70 case <-time
.After(time
.Second
* 4):
71 t
.Errorf("#%d: finalizer for type %T didn't run", i
, tt
.finalizer
)
76 type bigValue
struct {
82 func TestFinalizerInterfaceBig(t
*testing
.T
) {
83 if runtime
.GOARCH
!= "amd64" {
84 t
.Skipf("Skipping on non-amd64 machine")
86 if runtime
.Compiler
== "gccgo" {
87 t
.Skip("skipping for gccgo")
90 done
:= make(chan bool, 1)
92 v
:= &bigValue
{0xDEADBEEFDEADBEEF, true, "It matters not how strait the gate"}
94 runtime
.SetFinalizer(v
, func(v
interface{}) {
95 i
, ok
:= v
.(*bigValue
)
97 t
.Errorf("finalizer called with type %T, want *bigValue", v
)
100 t
.Errorf("finalizer called with %+v, want %+v", *i
, old
)
111 case <-time
.After(4 * time
.Second
):
112 t
.Errorf("finalizer for type *bigValue didn't run")
119 // Verify we don't crash at least. golang.org/issue/6857
120 func TestFinalizerZeroSizedStruct(t
*testing
.T
) {
123 runtime
.SetFinalizer(z
, func(*Z
) {})
126 func BenchmarkFinalizer(b
*testing
.B
) {
128 b
.RunParallel(func(pb
*testing
.PB
) {
130 for i
:= 0; i
< Batch
; i
++ {
134 for i
:= 0; i
< Batch
; i
++ {
135 runtime
.SetFinalizer(data
[i
], fin
)
137 for i
:= 0; i
< Batch
; i
++ {
138 runtime
.SetFinalizer(data
[i
], nil)
144 func BenchmarkFinalizerRun(b
*testing
.B
) {
145 b
.RunParallel(func(pb
*testing
.PB
) {
148 runtime
.SetFinalizer(v
, fin
)
153 // One chunk must be exactly one sizeclass in size.
154 // It should be a sizeclass not used much by others, so we
155 // have a greater chance of finding adjacent ones.
156 // size class 19: 320 byte objects, 25 per page, 1 page alloc at a time
159 type objtype
[objsize
]byte
161 func adjChunks() (*objtype
, *objtype
) {
166 for _
, d
:= range s
{
167 if uintptr(unsafe
.Pointer(c
))+unsafe
.Sizeof(*c
) == uintptr(unsafe
.Pointer(d
)) {
170 if uintptr(unsafe
.Pointer(d
))+unsafe
.Sizeof(*c
) == uintptr(unsafe
.Pointer(c
)) {
178 // Make sure an empty slice on the stack doesn't pin the next object in memory.
179 func TestEmptySlice(t
*testing
.T
) {
180 if runtime
.Compiler
== "gccgo" {
181 t
.Skip("skipping for gccgo")
185 // the pointer inside xs points to y.
186 xs
:= x
[objsize
:] // change objsize to objsize-1 and the test passes
188 fin
:= make(chan bool, 1)
189 runtime
.SetFinalizer(y
, func(z
*objtype
) { fin
<- true })
193 case <-time
.After(4 * time
.Second
):
194 t
.Errorf("finalizer of next object in memory didn't run")
196 xsglobal
= xs
// keep empty slice alive until here
201 func adjStringChunk() (string, *objtype
) {
202 b
:= make([]byte, objsize
)
206 p
:= *(*uintptr)(unsafe
.Pointer(&s
))
207 q
:= uintptr(unsafe
.Pointer(t
))
214 // Make sure an empty string on the stack doesn't pin the next object in memory.
215 func TestEmptyString(t
*testing
.T
) {
216 if runtime
.Compiler
== "gccgo" {
217 t
.Skip("skipping for gccgo")
220 x
, y
:= adjStringChunk()
222 ss
:= x
[objsize
:] // change objsize to objsize-1 and the test passes
223 fin
:= make(chan bool, 1)
224 // set finalizer on string contents of y
225 runtime
.SetFinalizer(y
, func(z
*objtype
) { fin
<- true })
229 case <-time
.After(4 * time
.Second
):
230 t
.Errorf("finalizer of next string in memory didn't run")
232 ssglobal
= ss
// keep 0-length string live until here
237 // Test for issue 7656.
238 func TestFinalizerOnGlobal(t
*testing
.T
) {
239 runtime
.SetFinalizer(Foo1
, func(p
*Object1
) {})
240 runtime
.SetFinalizer(Foo2
, func(p
*Object2
) {})
241 runtime
.SetFinalizer(Foo1
, nil)
242 runtime
.SetFinalizer(Foo2
, nil)
245 type Object1
struct {
249 type Object2
struct {
258 func TestDeferKeepAlive(t
*testing
.T
) {
265 type T
*int // needs to be a pointer base type to avoid tinyalloc and its never-finalized behavior.
268 runtime
.SetFinalizer(x
, func(x
*T
) {
271 defer runtime
.KeepAlive(x
)
273 time
.Sleep(time
.Second
)
275 t
.Errorf("finalizer ran prematurely")