Source file
src/weak/pointer_test.go
1
2
3
4
5 package weak_test
6
7 import (
8 "context"
9 "runtime"
10 "sync"
11 "testing"
12 "time"
13 "weak"
14 )
15
16 type T struct {
17
18
19 t *T
20 a int
21 }
22
23 func TestPointer(t *testing.T) {
24 var zero weak.Pointer[T]
25 if zero.Value() != nil {
26 t.Error("Value of zero value of weak.Pointer is not nil")
27 }
28 zeroNil := weak.Make[T](nil)
29 if zeroNil.Value() != nil {
30 t.Error("Value of weak.Make[T](nil) is not nil")
31 }
32
33 bt := new(T)
34 wt := weak.Make(bt)
35 if st := wt.Value(); st != bt {
36 t.Fatalf("weak pointer is not the same as strong pointer: %p vs. %p", st, bt)
37 }
38
39 runtime.GC()
40
41 if st := wt.Value(); st != bt {
42 t.Fatalf("weak pointer is not the same as strong pointer after GC: %p vs. %p", st, bt)
43 }
44
45 runtime.GC()
46
47 if st := wt.Value(); st != nil {
48 t.Fatalf("expected weak pointer to be nil, got %p", st)
49 }
50 }
51
52 func TestPointerEquality(t *testing.T) {
53 var zero weak.Pointer[T]
54 zeroNil := weak.Make[T](nil)
55 if zero != zeroNil {
56 t.Error("weak.Make[T](nil) != zero value of weak.Pointer[T]")
57 }
58
59 bt := make([]*T, 10)
60 wt := make([]weak.Pointer[T], 10)
61 wo := make([]weak.Pointer[int], 10)
62 for i := range bt {
63 bt[i] = new(T)
64 wt[i] = weak.Make(bt[i])
65 wo[i] = weak.Make(&bt[i].a)
66 }
67 for i := range bt {
68 st := wt[i].Value()
69 if st != bt[i] {
70 t.Fatalf("weak pointer is not the same as strong pointer: %p vs. %p", st, bt[i])
71 }
72 if wp := weak.Make(st); wp != wt[i] {
73 t.Fatalf("new weak pointer not equal to existing weak pointer: %v vs. %v", wp, wt[i])
74 }
75 if wp := weak.Make(&st.a); wp != wo[i] {
76 t.Fatalf("new weak pointer not equal to existing weak pointer: %v vs. %v", wp, wo[i])
77 }
78 if i == 0 {
79 continue
80 }
81 if wt[i] == wt[i-1] {
82 t.Fatalf("expected weak pointers to not be equal to each other, but got %v", wt[i])
83 }
84 }
85
86 runtime.GC()
87 for i := range bt {
88 st := wt[i].Value()
89 if st != bt[i] {
90 t.Fatalf("weak pointer is not the same as strong pointer: %p vs. %p", st, bt[i])
91 }
92 if wp := weak.Make(st); wp != wt[i] {
93 t.Fatalf("new weak pointer not equal to existing weak pointer: %v vs. %v", wp, wt[i])
94 }
95 if wp := weak.Make(&st.a); wp != wo[i] {
96 t.Fatalf("new weak pointer not equal to existing weak pointer: %v vs. %v", wp, wo[i])
97 }
98 if i == 0 {
99 continue
100 }
101 if wt[i] == wt[i-1] {
102 t.Fatalf("expected weak pointers to not be equal to each other, but got %v", wt[i])
103 }
104 }
105 bt = nil
106
107 runtime.GC()
108 for i := range bt {
109 st := wt[i].Value()
110 if st != nil {
111 t.Fatalf("expected weak pointer to be nil, got %p", st)
112 }
113 if i == 0 {
114 continue
115 }
116 if wt[i] == wt[i-1] {
117 t.Fatalf("expected weak pointers to not be equal to each other, but got %v", wt[i])
118 }
119 }
120 }
121
122 func TestPointerFinalizer(t *testing.T) {
123 bt := new(T)
124 wt := weak.Make(bt)
125 done := make(chan struct{}, 1)
126 runtime.SetFinalizer(bt, func(bt *T) {
127 if wt.Value() != nil {
128 t.Errorf("weak pointer did not go nil before finalizer ran")
129 }
130 done <- struct{}{}
131 })
132
133
134 runtime.GC()
135 if wt.Value() == nil {
136 t.Errorf("weak pointer went nil too soon")
137 }
138 runtime.KeepAlive(bt)
139
140
141
142
143 runtime.GC()
144 if wt.Value() != nil {
145 t.Errorf("weak pointer did not go nil when finalizer was enqueued")
146 }
147
148
149 <-done
150
151
152 runtime.GC()
153 if wt.Value() != nil {
154 t.Errorf("weak pointer is non-nil even after finalization: %v", wt)
155 }
156 }
157
158
159
160
161
162
163
164
165 func TestIssue69210(t *testing.T) {
166 if testing.Short() {
167 t.Skip("this is a stress test that takes seconds to run on its own")
168 }
169 ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second)
170 defer cancel()
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194 var wg sync.WaitGroup
195 wg.Add(1)
196 go func() {
197 defer wg.Done()
198 for {
199 runtime.GC()
200
201 select {
202 case <-ctx.Done():
203 return
204 default:
205 }
206 }
207 }()
208 for range max(runtime.GOMAXPROCS(-1)-1, 1) {
209 wg.Add(1)
210 go func() {
211 defer wg.Done()
212 for {
213 for range 5 {
214 bt := new(T)
215 wt := weak.Make(bt)
216 bt = nil
217 time.Sleep(1 * time.Millisecond)
218 bt = wt.Value()
219 if bt != nil {
220 time.Sleep(4 * time.Millisecond)
221 bt.t = bt
222 bt.a = 12
223 }
224 runtime.KeepAlive(bt)
225 }
226 select {
227 case <-ctx.Done():
228 return
229 default:
230 }
231 }
232 }()
233 }
234 wg.Wait()
235 }
236
237 func TestIssue70739(t *testing.T) {
238 x := make([]*int, 4<<16)
239 wx1 := weak.Make(&x[1<<16])
240 wx2 := weak.Make(&x[1<<16])
241 if wx1 != wx2 {
242 t.Fatal("failed to look up special and made duplicate weak handle; see issue #70739")
243 }
244 }
245
View as plain text