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 }