github.com/arnodel/golua@v0.0.0-20230215163904-e0b5347eaaa1/runtime/internal/luagc/clonepool_test.go (about)

     1  package luagc
     2  
     3  import (
     4  	"reflect"
     5  	"testing"
     6  )
     7  
     8  func TestClonePoolNoGC(t *testing.T) {
     9  	// This checks that RefPool behaves at least like SafePool (no GC)
    10  	p := NewClonePool()
    11  
    12  	n1 := newIntPtr(1)
    13  	n2 := newIntPtr(2)
    14  	n3 := newIntPtr(3)
    15  
    16  	p.Mark(n1, Finalize)
    17  	p.Mark(n2, Finalize|Release)
    18  	p.Mark(n3, Release)
    19  	p.Mark(n1, Finalize)
    20  
    21  	if n := len(p.ExtractPendingFinalize()); n != 0 {
    22  		t.Fatalf("Expected no pending finalize, got %d", n)
    23  	}
    24  	if n := len(p.ExtractPendingRelease()); n != 0 {
    25  		t.Fatalf("Expected no pending release, got %d", n)
    26  	}
    27  	mf := p.ExtractAllMarkedFinalize()
    28  	if !reflect.DeepEqual(mf, []Value{n1, n2}) {
    29  		t.Fatalf("Incorrect marked finalize: %+v", mf)
    30  	}
    31  	if n := len(p.ExtractAllMarkedFinalize()); n != 0 {
    32  		t.Fatalf("Expected no marked finalize, got %d", n)
    33  	}
    34  	mr := p.ExtractAllMarkedRelease()
    35  	if !reflect.DeepEqual(mr, []Value{n3, n2}) {
    36  		t.Fatalf("Incorrect marked release: %+v", mf)
    37  	}
    38  	if n := len(p.ExtractAllMarkedRelease()); n != 0 {
    39  		t.Fatalf("Expected no marked release, got %d", n)
    40  	}
    41  
    42  	if p.Get(n1) != nil {
    43  		t.Fatalf("It should not be possible to get weak refs")
    44  	}
    45  }
    46  
    47  func TestClonePoolGC(t *testing.T) {
    48  	// This tests that GC can remove unreachable refs, but doesn't exercise the
    49  	// fact that GC normally happens in a separate goroutine.  As all operations
    50  	// on the pool are protected by a mutex, this should still be a valuable
    51  	// test.
    52  	c := installTestCollector()
    53  	p := NewClonePool()
    54  
    55  	n1 := newIntPtr(1)
    56  	n2 := newIntPtr(2)
    57  	n3 := newIntPtr(3)
    58  	n4 := newIntPtr(4)
    59  
    60  	p.Mark(n1, Finalize)
    61  	p.Mark(n2, Finalize|Release)
    62  	p.Mark(n3, Release)
    63  	p.Mark(n1, Finalize)
    64  	p.Mark(n4, Finalize|Release)
    65  	p.Mark(n4, 0)
    66  
    67  	c.GC(n2, n1, n3, n4)
    68  
    69  	mf := p.ExtractPendingFinalize()
    70  	if !reflect.DeepEqual(mf, []Value{n1, n2}) {
    71  		t.Fatalf("GC1: Incorrect pending finalize: %+v", mf)
    72  	}
    73  	mr := p.ExtractPendingRelease()
    74  	if !reflect.DeepEqual(mr, []Value{n3}) {
    75  		t.Fatalf("GC1: Incorrect pending release: %+v", mr)
    76  	}
    77  
    78  	c.GC(mf...)
    79  	c.GC(mr...)
    80  
    81  	mf = p.ExtractPendingFinalize()
    82  	if n := len(mf); n != 0 {
    83  		t.Fatalf("GC2: Expected no pending finalize, got %d", n)
    84  	}
    85  	mr = p.ExtractPendingRelease()
    86  	if !reflect.DeepEqual(mr, []Value{n2}) {
    87  		t.Fatalf("GC2: Incorrect pending release: %+v", mf)
    88  	}
    89  
    90  	c.GC(mf...)
    91  	c.GC(mr...)
    92  
    93  	mf = p.ExtractPendingFinalize()
    94  	if n := len(mf); n != 0 {
    95  		t.Fatalf("GC3: Expected no pending finalize, got %d", n)
    96  	}
    97  	mr = p.ExtractPendingRelease()
    98  	if n := len(mr); n != 0 {
    99  		t.Fatalf("GC3: Expected no pending release, got %d", n)
   100  	}
   101  
   102  	p.Mark(n4, Release)
   103  
   104  	mf = p.ExtractAllMarkedFinalize()
   105  	if n := len(mf); n != 0 {
   106  		t.Fatalf("GC3: Expected no marked finalize, got %d", n)
   107  	}
   108  	mr = p.ExtractAllMarkedRelease()
   109  	if n := len(mr); n != 1 {
   110  		t.Fatalf("GC3: Expected 1 marked release, got %d", n)
   111  	}
   112  
   113  	// The Go finalizer for n4 should run but find no pendingRef, so abort
   114  	// early.  It's not easy to test for that.
   115  	if c.FinalizerCount() != 1 {
   116  		t.Fatalf("Expected one finalizer to remain before last GC")
   117  	}
   118  	c.GC(n4)
   119  	if c.FinalizerCount() != 0 {
   120  		t.Fatalf("Expected no finazlier to remain after last GC")
   121  	}
   122  	mr = p.ExtractPendingRelease()
   123  	if n := len(mr); n != 0 {
   124  		t.Fatalf("Last GC: Expected 0 marked release, got %d", n)
   125  	}
   126  }