# Source file src/maps/maps_test.go

```     1  // Copyright 2021 The Go Authors. All rights reserved.
2  // Use of this source code is governed by a BSD-style
4
5  package maps
6
7  import (
8  	"math"
9  	"strconv"
10  	"testing"
11  )
12
13  var m1 = map[int]int{1: 2, 2: 4, 4: 8, 8: 16}
14  var m2 = map[int]string{1: "2", 2: "4", 4: "8", 8: "16"}
15
16  func TestEqual(t *testing.T) {
17  	if !Equal(m1, m1) {
18  		t.Errorf("Equal(%v, %v) = false, want true", m1, m1)
19  	}
20  	if Equal(m1, (map[int]int)(nil)) {
21  		t.Errorf("Equal(%v, nil) = true, want false", m1)
22  	}
23  	if Equal((map[int]int)(nil), m1) {
24  		t.Errorf("Equal(nil, %v) = true, want false", m1)
25  	}
26  	if !Equal[map[int]int, map[int]int](nil, nil) {
27  		t.Error("Equal(nil, nil) = false, want true")
28  	}
29  	if ms := map[int]int{1: 2}; Equal(m1, ms) {
30  		t.Errorf("Equal(%v, %v) = true, want false", m1, ms)
31  	}
32
33  	// Comparing NaN for equality is expected to fail.
34  	mf := map[int]float64{1: 0, 2: math.NaN()}
35  	if Equal(mf, mf) {
36  		t.Errorf("Equal(%v, %v) = true, want false", mf, mf)
37  	}
38  }
39
40  // equal is simply ==.
41  func equal[T comparable](v1, v2 T) bool {
42  	return v1 == v2
43  }
44
45  // equalNaN is like == except that all NaNs are equal.
46  func equalNaN[T comparable](v1, v2 T) bool {
47  	isNaN := func(f T) bool { return f != f }
48  	return v1 == v2 || (isNaN(v1) && isNaN(v2))
49  }
50
51  // equalStr compares ints and strings.
52  func equalIntStr(v1 int, v2 string) bool {
53  	return strconv.Itoa(v1) == v2
54  }
55
56  func TestEqualFunc(t *testing.T) {
57  	if !EqualFunc(m1, m1, equal[int]) {
58  		t.Errorf("EqualFunc(%v, %v, equal) = false, want true", m1, m1)
59  	}
60  	if EqualFunc(m1, (map[int]int)(nil), equal[int]) {
61  		t.Errorf("EqualFunc(%v, nil, equal) = true, want false", m1)
62  	}
63  	if EqualFunc((map[int]int)(nil), m1, equal[int]) {
64  		t.Errorf("EqualFunc(nil, %v, equal) = true, want false", m1)
65  	}
66  	if !EqualFunc[map[int]int, map[int]int](nil, nil, equal[int]) {
67  		t.Error("EqualFunc(nil, nil, equal) = false, want true")
68  	}
69  	if ms := map[int]int{1: 2}; EqualFunc(m1, ms, equal[int]) {
70  		t.Errorf("EqualFunc(%v, %v, equal) = true, want false", m1, ms)
71  	}
72
73  	// Comparing NaN for equality is expected to fail.
74  	mf := map[int]float64{1: 0, 2: math.NaN()}
75  	if EqualFunc(mf, mf, equal[float64]) {
76  		t.Errorf("EqualFunc(%v, %v, equal) = true, want false", mf, mf)
77  	}
78  	// But it should succeed using equalNaN.
79  	if !EqualFunc(mf, mf, equalNaN[float64]) {
80  		t.Errorf("EqualFunc(%v, %v, equalNaN) = false, want true", mf, mf)
81  	}
82
83  	if !EqualFunc(m1, m2, equalIntStr) {
84  		t.Errorf("EqualFunc(%v, %v, equalIntStr) = false, want true", m1, m2)
85  	}
86  }
87
88  func TestClone(t *testing.T) {
89  	mc := Clone(m1)
90  	if !Equal(mc, m1) {
91  		t.Errorf("Clone(%v) = %v, want %v", m1, mc, m1)
92  	}
93  	mc[16] = 32
94  	if Equal(mc, m1) {
95  		t.Errorf("Equal(%v, %v) = true, want false", mc, m1)
96  	}
97  }
98
99  func TestCloneNil(t *testing.T) {
100  	var m1 map[string]int
101  	mc := Clone(m1)
102  	if mc != nil {
103  		t.Errorf("Clone(%v) = %v, want %v", m1, mc, m1)
104  	}
105  }
106
107  func TestCopy(t *testing.T) {
108  	mc := Clone(m1)
109  	Copy(mc, mc)
110  	if !Equal(mc, m1) {
111  		t.Errorf("Copy(%v, %v) = %v, want %v", m1, m1, mc, m1)
112  	}
113  	Copy(mc, map[int]int{16: 32})
114  	want := map[int]int{1: 2, 2: 4, 4: 8, 8: 16, 16: 32}
115  	if !Equal(mc, want) {
116  		t.Errorf("Copy result = %v, want %v", mc, want)
117  	}
118
119  	type M1 map[int]bool
120  	type M2 map[int]bool
121  	Copy(make(M1), make(M2))
122  }
123
124  func TestDeleteFunc(t *testing.T) {
125  	mc := Clone(m1)
126  	DeleteFunc(mc, func(int, int) bool { return false })
127  	if !Equal(mc, m1) {
128  		t.Errorf("DeleteFunc(%v, true) = %v, want %v", m1, mc, m1)
129  	}
130  	DeleteFunc(mc, func(k, v int) bool { return k > 3 })
131  	want := map[int]int{1: 2, 2: 4}
132  	if !Equal(mc, want) {
133  		t.Errorf("DeleteFunc result = %v, want %v", mc, want)
134  	}
135  }
136
137  var n map[int]int
138
139  func BenchmarkMapClone(b *testing.B) {
140  	var m = make(map[int]int)
141  	for i := 0; i < 1000000; i++ {
142  		m[i] = i
143  	}
144  	b.ResetTimer()
145  	for i := 0; i < b.N; i++ {
146  		n = Clone(m)
147  	}
148  }
149
150  func TestCloneWithDelete(t *testing.T) {
151  	var m = make(map[int]int)
152  	for i := 0; i < 32; i++ {
153  		m[i] = i
154  	}
155  	for i := 8; i < 32; i++ {
156  		delete(m, i)
157  	}
158  	m2 := Clone(m)
159  	if len(m2) != 8 {
160  		t.Errorf("len2(m2) = %d, want %d", len(m2), 8)
161  	}
162  	for i := 0; i < 8; i++ {
163  		if m2[i] != m[i] {
164  			t.Errorf("m2[%d] = %d, want %d", i, m2[i], m[i])
165  		}
166  	}
167  }
168
169  func TestCloneWithMapAssign(t *testing.T) {
170  	var m = make(map[int]int)
171  	const N = 25
172  	for i := 0; i < N; i++ {
173  		m[i] = i
174  	}
175  	m2 := Clone(m)
176  	if len(m2) != N {
177  		t.Errorf("len2(m2) = %d, want %d", len(m2), N)
178  	}
179  	for i := 0; i < N; i++ {
180  		if m2[i] != m[i] {
181  			t.Errorf("m2[%d] = %d, want %d", i, m2[i], m[i])
182  		}
183  	}
184  }
185
186  func TestCloneLarge(t *testing.T) {
187  	// See issue 64474.
188  	type K [17]float64 // > 128 bytes
189  	type V [17]float64
190
191  	var zero float64
192  	negZero := -zero
193
194  	for tst := 0; tst < 3; tst++ {
195  		// Initialize m with a key and value.
196  		m := map[K]V{}
197  		var k1 K
198  		var v1 V
199  		m[k1] = v1
200
201  		switch tst {
202  		case 0: // nothing, just a 1-entry map
203  		case 1:
204  			// Add more entries to make it 2 buckets
206  			// 7 more fill up 1 bucket
207  			// 1 more to grow to 2 buckets
208  			for i := 0; i < 7+1; i++ {
209  				m[K{float64(i) + 1}] = V{}
210  			}
211  		case 2:
212  			// Capture the map mid-grow
214  			// 7 more fill up 1 bucket
215  			// 5 more (13 total) fill up 2 buckets
216  			// 13 more (26 total) fill up 4 buckets
217  			// 1 more to start the 4->8 bucket grow
218  			for i := 0; i < 7+5+13+1; i++ {
219  				m[K{float64(i) + 1}] = V{}
220  			}
221  		}
222
223  		// Clone m, which should freeze the map's contents.
224  		c := Clone(m)
225
226  		// Update m with new key and value.
227  		k2, v2 := k1, v1
228  		k2[0] = negZero
229  		v2[0] = 1.0
230  		m[k2] = v2
231
232  		// Make sure c still has its old key and value.
233  		for k, v := range c {
234  			if math.Signbit(k[0]) {
235  				t.Errorf("tst%d: sign bit of key changed; got %v want %v", tst, k, k1)
236  			}
237  			if v != v1 {
238  				t.Errorf("tst%d: value changed; got %v want %v", tst, v, v1)
239  			}
240  		}
241  	}
242  }
243
```

View as plain text