1 // Copyright 2013 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
18 // negative zero is a good test because:
19 // 1) 0 and -0 are equal, yet have distinct representations.
20 // 2) 0 is represented as all zeros, -0 isn't.
21 // I'm not sure the language spec actually requires this behavior,
22 // but it's what the current map implementation does.
23 func TestNegativeZero(t
*testing
.T
) {
24 m
:= make(map[float64]bool, 0)
27 m
[math
.Copysign(0.0, -1.0)] = true // should overwrite +0 entry
30 t
.Error("length wrong")
33 /* gccgo fails this test; this is not required by the spec.
35 if math.Copysign(1.0, k) > 0 {
41 m
= make(map[float64]bool, 0)
42 m
[math
.Copysign(0.0, -1.0)] = true
43 m
[+0.0] = true // should overwrite -0.0 entry
46 t
.Error("length wrong")
49 /* gccgo fails this test; this is not required by the spec.
51 if math.Copysign(1.0, k) < 0 {
58 // nan is a good test because nan != nan, and nan has
59 // a randomized hash value.
60 func TestNan(t
*testing
.T
) {
61 m
:= make(map[float64]int, 0)
67 t
.Error("length wrong")
72 t
.Error("nan disappeared")
74 if (v
& (v
- 1)) != 0 {
75 t
.Error("value wrong")
80 t
.Error("values wrong")
84 // Maps aren't actually copied on assignment.
85 func TestAlias(t
*testing
.T
) {
86 m
:= make(map[int]int, 0)
91 t
.Error("alias didn't work")
95 func TestGrowWithNaN(t
*testing
.T
) {
96 t
.Skip("fails with gccgo")
97 m
:= make(map[float64]int, 4)
105 for k
, v
:= range m
{
107 // force a hashtable resize
108 for i
:= 0; i
< 100; i
++ {
118 t
.Log("cnt:", cnt
, "s:", s
)
120 t
.Error("NaN keys lost during grow")
123 t
.Error("NaN values lost during grow")
127 type FloatInt
struct {
132 func TestGrowWithNegativeZero(t
*testing
.T
) {
133 t
.Skip("fails with gccgo")
134 negzero
:= math
.Copysign(0.0, -1.0)
135 m
:= make(map[FloatInt
]int, 4)
136 m
[FloatInt
{0.0, 0}] = 1
137 m
[FloatInt
{0.0, 1}] = 2
138 m
[FloatInt
{0.0, 2}] = 4
139 m
[FloatInt
{0.0, 3}] = 8
144 // The first iteration should return the +0 key.
145 // The subsequent iterations should return the -0 key.
146 // I'm not really sure this is required by the spec,
147 // but it makes sense.
148 // TODO: are we allowed to get the first entry returned again???
149 for k
, v
:= range m
{
152 } // ignore entries added to grow table
154 if math
.Copysign(1.0, k
.x
) < 0 {
156 t
.Error("key/value not updated together 1")
162 t
.Error("key/value not updated together 2", k
, v
)
167 // force a hashtable resize
168 for i
:= 0; i
< 100; i
++ {
169 m
[FloatInt
{3.0, i
}] = 0
171 // then change all the entries
173 m
[FloatInt
{negzero
, 0}] = 1 |
16
174 m
[FloatInt
{negzero
, 1}] = 2 |
16
175 m
[FloatInt
{negzero
, 2}] = 4 |
16
176 m
[FloatInt
{negzero
, 3}] = 8 |
16
181 t
.Error("entry missing", s
)
184 t
.Error("wrong number of entries returned by iterator", cnt
)
187 t
.Error("update to negzero missed by iteration", negcnt
)
191 func TestIterGrowAndDelete(t
*testing
.T
) {
192 m
:= make(map[int]int, 4)
193 for i
:= 0; i
< 100; i
++ {
200 for i
:= 100; i
< 1000; i
++ {
203 // delete all odd keys
204 for i
:= 1; i
< 1000; i
+= 2 {
210 t
.Error("odd value returned")
216 // make sure old bucket arrays don't get GCd while
217 // an iterator is still using them.
218 func TestIterGrowWithGC(t
*testing
.T
) {
219 m
:= make(map[int]int, 4)
220 for i
:= 0; i
< 16; i
++ {
227 bitmask |
= 1 << uint(k
)
231 for i
:= 100; i
< 1000; i
++ {
239 if bitmask
!= 1<<16-1 {
240 t
.Error("missing key", bitmask
)
244 func testConcurrentReadsAfterGrowth(t
*testing
.T
, useReflect
bool) {
245 if runtime
.GOMAXPROCS(-1) == 1 {
246 defer runtime
.GOMAXPROCS(runtime
.GOMAXPROCS(16))
252 numLoop
, numGrowStep
= 2, 500
254 for i
:= 0; i
< numLoop
; i
++ {
255 m
:= make(map[int]int, 0)
256 for gs
:= 0; gs
< numGrowStep
; gs
++ {
258 var wg sync
.WaitGroup
259 wg
.Add(numReader
* 2)
260 for nr
:= 0; nr
< numReader
; nr
++ {
268 for key
:= 0; key
< gs
; key
++ {
276 mv
:= reflect
.ValueOf(m
)
278 for _
, k
:= range keys
{
289 func TestConcurrentReadsAfterGrowth(t
*testing
.T
) {
290 testConcurrentReadsAfterGrowth(t
, false)
293 func TestConcurrentReadsAfterGrowthReflect(t
*testing
.T
) {
294 testConcurrentReadsAfterGrowth(t
, true)
297 func TestBigItems(t
*testing
.T
) {
299 for i
:= 0; i
< 256; i
++ {
302 m
:= make(map[[256]string][256]string, 4)
303 for i
:= 0; i
< 100; i
++ {
304 key
[37] = fmt
.Sprintf("string%02d", i
)
308 var values
[100]string
310 for k
, v
:= range m
{
315 sort
.Strings(keys
[:])
316 sort
.Strings(values
[:])
317 for i
:= 0; i
< 100; i
++ {
318 if keys
[i
] != fmt
.Sprintf("string%02d", i
) {
319 t
.Errorf("#%d: missing key: %v", i
, keys
[i
])
321 if values
[i
] != fmt
.Sprintf("string%02d", i
) {
322 t
.Errorf("#%d: missing value: %v", i
, values
[i
])
330 func TestEmptyKeyAndValue(t
*testing
.T
) {
331 a
:= make(map[int]empty
, 4)
332 b
:= make(map[empty
]int, 4)
333 c
:= make(map[empty
]empty
, 4)
340 t
.Errorf("empty value insert problem")
343 t
.Errorf("empty key returned wrong value")
347 // Tests a map with a single bucket, with same-lengthed short keys
348 // ("quick keys") as well as long keys.
349 func TestSingleBucketMapStringKeys_DupLen(t
*testing
.T
) {
350 testMapLookups(t
, map[string]string{
354 "bar": "barval", // same key length as "foo"
356 strings
.Repeat("x", 128): "longval1",
357 strings
.Repeat("y", 128): "longval2",
361 // Tests a map with a single bucket, with all keys having different lengths.
362 func TestSingleBucketMapStringKeys_NoDupLen(t
*testing
.T
) {
363 testMapLookups(t
, map[string]string{
370 strings
.Repeat("x", 128): "longval",
374 func testMapLookups(t
*testing
.T
, m
map[string]string) {
375 for k
, v
:= range m
{
377 t
.Fatalf("m[%q] = %q; want %q", k
, m
[k
], v
)
382 // Tests whether the iterator returns the right elements when
383 // started in the middle of a grow, when the keys are NaNs.
384 func TestMapNanGrowIterator(t
*testing
.T
) {
385 m
:= make(map[float64]int)
388 // To fill nBuckets buckets takes LOAD * nBuckets keys.
389 nKeys
:= int(nBuckets
* *runtime
.HashLoad
)
391 // Get map to full point with nan keys.
392 for i
:= 0; i
< nKeys
; i
++ {
400 found
:= make(map[int]struct{})
401 for _
, v
:= range m
{
403 if _
, repeat
:= found
[v
]; repeat
{
404 t
.Fatalf("repeat of value %d", v
)
406 found
[v
] = struct{}{}
408 if len(found
) == nKeys
/2 {
409 // Halfway through iteration, finish grow.
410 for i
:= 0; i
< nBuckets
; i
++ {
415 if len(found
) != nKeys
{
416 t
.Fatalf("missing value")