1
2
3
4
5
6
7
8
9
10 package maps_test
11
12 import (
13 "fmt"
14 "internal/abi"
15 "internal/runtime/maps"
16 "testing"
17 "unsafe"
18 )
19
20 var alwaysFalse bool
21 var escapeSink any
22
23 func escape[T any](x T) T {
24 if alwaysFalse {
25 escapeSink = x
26 }
27 return x
28 }
29
30 const (
31 belowMax = abi.SwissMapGroupSlots * 3 / 2
32 atMax = (2 * abi.SwissMapGroupSlots * maps.MaxAvgGroupLoad) / abi.SwissMapGroupSlots
33 )
34
35 func TestTableGroupCount(t *testing.T) {
36
37
38
39 type mapCount struct {
40 tables int
41 groups uint64
42 }
43
44 type mapCase struct {
45 initialLit mapCount
46 initialHint mapCount
47 after mapCount
48 }
49
50 var testCases = []struct {
51 n int
52 escape mapCase
53
54 }{
55 {
56 n: -(1 << 30),
57 escape: mapCase{
58 initialLit: mapCount{0, 0},
59 initialHint: mapCount{0, 0},
60 after: mapCount{0, 0},
61 },
62 },
63 {
64 n: -1,
65 escape: mapCase{
66 initialLit: mapCount{0, 0},
67 initialHint: mapCount{0, 0},
68 after: mapCount{0, 0},
69 },
70 },
71 {
72 n: 0,
73 escape: mapCase{
74 initialLit: mapCount{0, 0},
75 initialHint: mapCount{0, 0},
76 after: mapCount{0, 0},
77 },
78 },
79 {
80 n: 1,
81 escape: mapCase{
82 initialLit: mapCount{0, 0},
83 initialHint: mapCount{0, 0},
84 after: mapCount{0, 1},
85 },
86 },
87 {
88 n: abi.SwissMapGroupSlots,
89 escape: mapCase{
90 initialLit: mapCount{0, 0},
91 initialHint: mapCount{0, 0},
92 after: mapCount{0, 1},
93 },
94 },
95 {
96 n: abi.SwissMapGroupSlots + 1,
97 escape: mapCase{
98 initialLit: mapCount{0, 0},
99 initialHint: mapCount{1, 2},
100 after: mapCount{1, 2},
101 },
102 },
103 {
104 n: belowMax,
105 escape: mapCase{
106 initialLit: mapCount{0, 0},
107 initialHint: mapCount{1, 2},
108 after: mapCount{1, 2},
109 },
110 },
111 {
112 n: atMax,
113 escape: mapCase{
114 initialLit: mapCount{0, 0},
115 initialHint: mapCount{1, 2},
116 after: mapCount{1, 2},
117 },
118 },
119 {
120 n: atMax + 1,
121 escape: mapCase{
122 initialLit: mapCount{0, 0},
123 initialHint: mapCount{1, 4},
124 after: mapCount{1, 4},
125 },
126 },
127 {
128 n: 2 * belowMax,
129 escape: mapCase{
130 initialLit: mapCount{0, 0},
131 initialHint: mapCount{1, 4},
132 after: mapCount{1, 4},
133 },
134 },
135 {
136 n: 2*atMax + 1,
137 escape: mapCase{
138 initialLit: mapCount{0, 0},
139 initialHint: mapCount{1, 8},
140 after: mapCount{1, 8},
141 },
142 },
143 }
144
145 testMap := func(t *testing.T, m map[int]int, n int, initial, after mapCount) {
146 mm := *(**maps.Map)(unsafe.Pointer(&m))
147
148 gotTab := mm.TableCount()
149 if gotTab != initial.tables {
150 t.Errorf("initial TableCount got %d want %d", gotTab, initial.tables)
151 }
152
153 gotGroup := mm.GroupCount()
154 if gotGroup != initial.groups {
155 t.Errorf("initial GroupCount got %d want %d", gotGroup, initial.groups)
156 }
157
158 for i := 0; i < n; i++ {
159 m[i] = i
160 }
161
162 gotTab = mm.TableCount()
163 if gotTab != after.tables {
164 t.Errorf("after TableCount got %d want %d", gotTab, after.tables)
165 }
166
167 gotGroup = mm.GroupCount()
168 if gotGroup != after.groups {
169 t.Errorf("after GroupCount got %d want %d", gotGroup, after.groups)
170 }
171 }
172
173 t.Run("mapliteral", func(t *testing.T) {
174 for _, tc := range testCases {
175 t.Run(fmt.Sprintf("n=%d", tc.n), func(t *testing.T) {
176 t.Run("escape", func(t *testing.T) {
177 m := escape(map[int]int{})
178 testMap(t, m, tc.n, tc.escape.initialLit, tc.escape.after)
179 })
180 })
181 }
182 })
183 t.Run("nohint", func(t *testing.T) {
184 for _, tc := range testCases {
185 t.Run(fmt.Sprintf("n=%d", tc.n), func(t *testing.T) {
186 t.Run("escape", func(t *testing.T) {
187 m := escape(make(map[int]int))
188 testMap(t, m, tc.n, tc.escape.initialLit, tc.escape.after)
189 })
190 })
191 }
192 })
193 t.Run("makemap", func(t *testing.T) {
194 for _, tc := range testCases {
195 t.Run(fmt.Sprintf("n=%d", tc.n), func(t *testing.T) {
196 t.Run("escape", func(t *testing.T) {
197 m := escape(make(map[int]int, tc.n))
198 testMap(t, m, tc.n, tc.escape.initialHint, tc.escape.after)
199 })
200 })
201 }
202 })
203 t.Run("makemap64", func(t *testing.T) {
204 for _, tc := range testCases {
205 t.Run(fmt.Sprintf("n=%d", tc.n), func(t *testing.T) {
206 t.Run("escape", func(t *testing.T) {
207 m := escape(make(map[int]int, int64(tc.n)))
208 testMap(t, m, tc.n, tc.escape.initialHint, tc.escape.after)
209 })
210 })
211 }
212 })
213 }
214
View as plain text