Source file
src/unique/handle_test.go
1
2
3
4
5 package unique
6
7 import (
8 "fmt"
9 "internal/abi"
10 "reflect"
11 "runtime"
12 "testing"
13 )
14
15
16
17 type testString string
18 type testIntArray [4]int
19 type testEface any
20 type testStringArray [3]string
21 type testStringStruct struct {
22 a string
23 }
24 type testStringStructArrayStruct struct {
25 s [2]testStringStruct
26 }
27 type testStruct struct {
28 z float64
29 b string
30 }
31
32 func TestHandle(t *testing.T) {
33 testHandle[testString](t, "foo")
34 testHandle[testString](t, "bar")
35 testHandle[testString](t, "")
36 testHandle[testIntArray](t, [4]int{7, 77, 777, 7777})
37 testHandle[testEface](t, nil)
38 testHandle[testStringArray](t, [3]string{"a", "b", "c"})
39 testHandle[testStringStruct](t, testStringStruct{"x"})
40 testHandle[testStringStructArrayStruct](t, testStringStructArrayStruct{
41 s: [2]testStringStruct{testStringStruct{"y"}, testStringStruct{"z"}},
42 })
43 testHandle[testStruct](t, testStruct{0.5, "184"})
44 }
45
46 func testHandle[T comparable](t *testing.T, value T) {
47 name := reflect.TypeFor[T]().Name()
48 t.Run(fmt.Sprintf("%s/%#v", name, value), func(t *testing.T) {
49 t.Parallel()
50
51 v0 := Make(value)
52 v1 := Make(value)
53
54 if v0.Value() != v1.Value() {
55 t.Error("v0.Value != v1.Value")
56 }
57 if v0.Value() != value {
58 t.Errorf("v0.Value not %#v", value)
59 }
60 if v0 != v1 {
61 t.Error("v0 != v1")
62 }
63
64 drainMaps(t)
65 checkMapsFor(t, value)
66 })
67 }
68
69
70 func drainMaps(t *testing.T) {
71 t.Helper()
72
73 wait := make(chan struct{}, 1)
74
75
76
77
78
79 cleanupMu.Lock()
80 cleanupNotify = append(cleanupNotify, func() {
81 select {
82 case wait <- struct{}{}:
83 default:
84 }
85 })
86
87 runtime.GC()
88 cleanupMu.Unlock()
89
90
91 <-wait
92 }
93
94 func checkMapsFor[T comparable](t *testing.T, value T) {
95
96 typ := abi.TypeOf(value)
97 a, ok := uniqueMaps.Load(typ)
98 if !ok {
99 return
100 }
101 m := a.(*uniqueMap[T])
102 wp, ok := m.Load(value)
103 if !ok {
104 return
105 }
106 if wp.Strong() != nil {
107 t.Errorf("value %v still referenced a handle (or tiny block?) ", value)
108 return
109 }
110 t.Errorf("failed to drain internal maps of %v", value)
111 }
112
View as plain text