github.com/lrita/cmap@v0.0.0-20231108122212-cb084a67f554/map_test.go (about) 1 //go:build go1.18 2 // +build go1.18 3 4 package cmap_test 5 6 import ( 7 "math/rand" 8 "runtime" 9 "sync" 10 "testing" 11 "testing/quick" 12 13 "github.com/lrita/cmap" 14 ) 15 16 type StringMap struct { 17 m cmap.Map[string, interface{}] 18 } 19 20 func (m *StringMap) Load(k interface{}) (interface{}, bool) { 21 return m.m.Load(k.(string)) 22 } 23 24 func (m *StringMap) Store(key, value interface{}) { 25 m.m.Store(key.(string), value) 26 } 27 28 func (m *StringMap) LoadOrStore(key, value interface{}) (actual interface{}, loaded bool) { 29 return m.m.LoadOrStore(key.(string), value) 30 } 31 32 func (m *StringMap) Delete(key interface{}) { 33 m.m.Delete(key.(string)) 34 } 35 36 func (m *StringMap) Range(fn func(key, value interface{}) bool) { 37 m.m.Range(func(k string, v interface{}) bool { 38 return fn(k, v) 39 }) 40 } 41 42 func applyGMap(calls []mapCall) ([]mapResult, map[interface{}]interface{}) { 43 return applyCalls(new(StringMap), calls) 44 } 45 46 func TestGMapMatchesRWMutex(t *testing.T) { 47 if err := quick.CheckEqual(applyGMap, applyRWMutexMap, nil); err != nil { 48 t.Error(err) 49 } 50 } 51 52 func TestGMapMatchesDeepCopy(t *testing.T) { 53 if err := quick.CheckEqual(applyGMap, applyDeepCopyMap, nil); err != nil { 54 t.Error(err) 55 } 56 } 57 58 func TestGMapConcurrentRange(t *testing.T) { 59 const mapSize = 1 << 10 60 61 m := new(cmap.Map[int64, any]) 62 for n := int64(1); n <= mapSize; n++ { 63 m.Store(n, int64(n)) 64 } 65 66 done := make(chan struct{}) 67 var wg sync.WaitGroup 68 defer func() { 69 close(done) 70 wg.Wait() 71 }() 72 for g := int64(runtime.GOMAXPROCS(0)); g > 0; g-- { 73 r := rand.New(rand.NewSource(g)) 74 wg.Add(1) 75 go func(g int64) { 76 defer wg.Done() 77 for i := int64(0); ; i++ { 78 select { 79 case <-done: 80 return 81 default: 82 } 83 for n := int64(1); n < mapSize; n++ { 84 if r.Int63n(mapSize) == 0 { 85 m.Store(n, n*i*g) 86 } else { 87 m.Load(n) 88 } 89 } 90 } 91 }(g) 92 } 93 94 iters := 1 << 10 95 if testing.Short() { 96 iters = 16 97 } 98 for n := iters; n > 0; n-- { 99 seen := make(map[int64]bool, mapSize) 100 101 m.Range(func(ki int64, vi interface{}) bool { 102 k, v := ki, vi.(int64) 103 if v%k != 0 { 104 t.Fatalf("while Storing multiples of %v, Range saw value %v", k, v) 105 } 106 if seen[k] { 107 t.Fatalf("Range visited key %v twice", k) 108 } 109 seen[k] = true 110 return true 111 }) 112 113 if len(seen) != mapSize { 114 t.Fatalf("Range visited %v elements of %v-element Map", len(seen), mapSize) 115 } 116 } 117 } 118 119 func TestGMapCreation(t *testing.T) { 120 m := cmap.Map[int, int]{} 121 122 if m.Count() != 0 { 123 t.Error("new map should be empty.") 124 } 125 if !m.IsEmpty() { 126 t.Error("new map should be empty.") 127 } 128 } 129 130 func TestGMapStoreOperationDuplicatedKey(t *testing.T) { 131 m := cmap.Map[string, interface{}]{} 132 m.Store("t", "") 133 m.Store("t", "") 134 if v := m.Count(); v != 1 { 135 t.Errorf("map Count() should be %d, got %d", 1, v) 136 } 137 m.LoadOrStore("m", "") 138 if v := m.Count(); v != 2 { 139 t.Errorf("map Count() should be %d, got %d", 2, v) 140 } 141 m.Delete("t") 142 if v := m.Count(); v != 1 { 143 t.Errorf("map Count() should be %d, got %d", 1, v) 144 } 145 m.Delete("t") 146 if v := m.Count(); v != 1 { 147 t.Errorf("map Count() should be %d, got %d", 1, v) 148 } 149 } 150 151 func TestGMapStoreAndLoad(t *testing.T) { 152 const mapSize = 1 << 14 153 154 var ( 155 m cmap.Map[int64, interface{}] 156 wg sync.WaitGroup 157 seen = make(map[int64]bool, mapSize) 158 ) 159 160 for n := int64(1); n <= mapSize; n++ { 161 nn := n 162 wg.Add(1) 163 go func() { 164 defer wg.Done() 165 m.Store(nn, nn) 166 }() 167 } 168 169 wg.Wait() 170 171 m.Range(func(ki int64, vi interface{}) bool { 172 k, v := ki, vi.(int64) 173 if v%k != 0 { 174 t.Fatalf("while Storing multiples of %v, Range saw value %v", k, v) 175 } 176 if seen[k] { 177 t.Fatalf("Range visited key %v twice", k) 178 } 179 seen[k] = true 180 return true 181 }) 182 183 if len(seen) != mapSize { 184 t.Fatalf("Range visited %v elements of %v-element Map", len(seen), mapSize) 185 } 186 187 for n := int64(1); n <= mapSize; n++ { 188 nn := n 189 wg.Add(1) 190 go func() { 191 defer wg.Done() 192 m.Delete(nn) 193 }() 194 } 195 196 wg.Wait() 197 198 if !m.IsEmpty() { 199 t.Fatalf("Map should be empty, remained %v", m.Count()) 200 } 201 }