github.com/songzhibin97/gkit@v1.2.13/structure/skipmap/skipmap_test.go (about) 1 // Copyright 2021 ByteDance Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package skipmap 16 17 import ( 18 "github.com/songzhibin97/gkit/sys/fastrand" 19 "math/rand" 20 "reflect" 21 "runtime" 22 "sync" 23 "sync/atomic" 24 "testing" 25 ) 26 27 func TestSkipMap(t *testing.T) { 28 m := NewInt() 29 30 // Correctness. 31 m.Store(123, "123") 32 v, ok := m.Load(123) 33 if !ok || v != "123" || m.Len() != 1 { 34 t.Fatal("invalid") 35 } 36 37 m.Store(123, "456") 38 v, ok = m.Load(123) 39 if !ok || v != "456" || m.Len() != 1 { 40 t.Fatal("invalid") 41 } 42 43 m.Store(123, 456) 44 v, ok = m.Load(123) 45 if !ok || v != 456 || m.Len() != 1 { 46 t.Fatal("invalid") 47 } 48 49 m.Delete(123) 50 v, ok = m.Load(123) 51 if ok || m.Len() != 0 || v != nil { 52 t.Fatal("invalid") 53 } 54 55 v, loaded := m.LoadOrStore(123, 456) 56 if loaded || v != 456 || m.Len() != 1 { 57 t.Fatal("invalid") 58 } 59 60 v, loaded = m.LoadOrStore(123, 789) 61 if !loaded || v != 456 || m.Len() != 1 { 62 t.Fatal("invalid") 63 } 64 65 v, ok = m.Load(123) 66 if !ok || v != 456 || m.Len() != 1 { 67 t.Fatal("invalid") 68 } 69 70 v, ok = m.LoadAndDelete(123) 71 if !ok || v != 456 || m.Len() != 0 { 72 t.Fatal("invalid") 73 } 74 75 _, ok = m.LoadOrStore(123, 456) 76 if ok || m.Len() != 1 { 77 t.Fatal("invalid") 78 } 79 80 m.LoadOrStore(456, 123) 81 if ok || m.Len() != 2 { 82 t.Fatal("invalid") 83 } 84 85 m.Range(func(key int, _ interface{}) bool { 86 if key == 123 { 87 m.Store(123, 123) 88 } else if key == 456 { 89 m.LoadAndDelete(456) 90 } 91 return true 92 }) 93 94 v, ok = m.Load(123) 95 if !ok || v != 123 || m.Len() != 1 { 96 t.Fatal("invalid") 97 } 98 99 // Concurrent. 100 var wg sync.WaitGroup 101 for i := 0; i < 1000; i++ { 102 i := i 103 wg.Add(1) 104 go func() { 105 m.Store(i, int(i+1000)) 106 wg.Done() 107 }() 108 } 109 wg.Wait() 110 wg.Add(1) 111 go func() { 112 m.Delete(600) 113 wg.Done() 114 }() 115 wg.Wait() 116 wg.Add(1) 117 var count int64 118 go func() { 119 m.Range(func(_ int, _ interface{}) bool { 120 atomic.AddInt64(&count, 1) 121 return true 122 }) 123 wg.Done() 124 }() 125 wg.Wait() 126 127 val, ok := m.Load(500) 128 if !ok || reflect.TypeOf(val).Kind().String() != "int" || val.(int) != 1500 { 129 t.Fatal("fail") 130 } 131 132 _, ok = m.Load(600) 133 if ok { 134 t.Fatal("fail") 135 } 136 137 if m.Len() != 999 || int(count) != m.Len() { 138 t.Fatal("fail") 139 } 140 // Correctness 2. 141 var m1 sync.Map 142 m2 := NewUint32() 143 var v1, v2 interface{} 144 var ok1, ok2 bool 145 for i := 0; i < 100000; i++ { 146 rd := fastrand.Uint32n(10) 147 r1, r2 := fastrand.Uint32n(100), fastrand.Uint32n(100) 148 if rd == 0 { 149 m1.Store(r1, r2) 150 m2.Store(r1, r2) 151 } else if rd == 1 { 152 v1, ok1 = m1.LoadAndDelete(r1) 153 v2, ok2 = m2.LoadAndDelete(r1) 154 if ok1 != ok2 || v1 != v2 { 155 t.Fatal(rd, v1, ok1, v2, ok2) 156 } 157 } else if rd == 2 { 158 v1, ok1 = m1.LoadOrStore(r1, r2) 159 v2, ok2 = m2.LoadOrStore(r1, r2) 160 if ok1 != ok2 || v1 != v2 { 161 t.Fatal(rd, v1, ok1, v2, ok2, "input -> ", r1, r2) 162 } 163 } else if rd == 3 { 164 m1.Delete(r1) 165 m2.Delete(r1) 166 } else if rd == 4 { 167 m2.Range(func(key uint32, value interface{}) bool { 168 v, ok := m1.Load(key) 169 if !ok || v != value { 170 t.Fatal(v, ok, key, value) 171 } 172 return true 173 }) 174 } else { 175 v1, ok1 = m1.Load(r1) 176 v2, ok2 = m2.Load(r1) 177 if ok1 != ok2 || v1 != v2 { 178 t.Fatal(rd, v1, ok1, v2, ok2) 179 } 180 } 181 } 182 // Correntness 3. (LoadOrStore) 183 // Only one LoadorStore can successfully insert its key and value. 184 // And the returned value is unique. 185 mp := NewInt() 186 tmpmap := NewInt64() 187 samekey := 123 188 var added int64 189 for i := 1; i < 1000; i++ { 190 wg.Add(1) 191 go func() { 192 v := fastrand.Int63() 193 actual, loaded := mp.LoadOrStore(samekey, v) 194 if !loaded { 195 atomic.AddInt64(&added, 1) 196 } 197 tmpmap.Store(actual.(int64), nil) 198 wg.Done() 199 }() 200 } 201 wg.Wait() 202 if added != 1 { 203 t.Fatal("only one LoadOrStore can successfully insert a key and value") 204 } 205 if tmpmap.Len() != 1 { 206 t.Fatal("only one value can be returned from LoadOrStore") 207 } 208 // Correntness 4. (LoadAndDelete) 209 // Only one LoadAndDelete can successfully get a value. 210 mp = NewInt() 211 tmpmap = NewInt64() 212 samekey = 123 213 added = 0 // int64 214 mp.Store(samekey, 555) 215 for i := 1; i < 1000; i++ { 216 wg.Add(1) 217 go func() { 218 value, loaded := mp.LoadAndDelete(samekey) 219 if loaded { 220 atomic.AddInt64(&added, 1) 221 if value != 555 { 222 panic("invalid") 223 } 224 } 225 wg.Done() 226 }() 227 } 228 wg.Wait() 229 if added != 1 { 230 t.Fatal("Only one LoadAndDelete can successfully get a value") 231 } 232 233 // Correntness 5. (LoadOrStoreLazy) 234 mp = NewInt() 235 tmpmap = NewInt64() 236 samekey = 123 237 added = 0 238 var fcalled int64 239 valuef := func() interface{} { 240 atomic.AddInt64(&fcalled, 1) 241 return fastrand.Int63() 242 } 243 for i := 1; i < 1000; i++ { 244 wg.Add(1) 245 go func() { 246 actual, loaded := mp.LoadOrStoreLazy(samekey, valuef) 247 if !loaded { 248 atomic.AddInt64(&added, 1) 249 } 250 tmpmap.Store(actual.(int64), nil) 251 wg.Done() 252 }() 253 } 254 wg.Wait() 255 if added != 1 || fcalled != 1 { 256 t.Fatal("only one LoadOrStoreLazy can successfully insert a key and value") 257 } 258 if tmpmap.Len() != 1 { 259 t.Fatal("only one value can be returned from LoadOrStoreLazy") 260 } 261 } 262 263 func TestSkipMapDesc(t *testing.T) { 264 m := NewIntDesc() 265 cases := []int{10, 11, 12} 266 for _, v := range cases { 267 m.Store(v, nil) 268 } 269 i := len(cases) - 1 270 m.Range(func(key int, _ interface{}) bool { 271 if key != cases[i] { 272 t.Fail() 273 } 274 i-- 275 return true 276 }) 277 } 278 279 /* Test from sync.Map */ 280 func TestConcurrentRange(t *testing.T) { 281 const mapSize = 1 << 10 282 283 m := NewInt64() 284 for n := int64(1); n <= mapSize; n++ { 285 m.Store(n, int64(n)) 286 } 287 288 done := make(chan struct{}) 289 var wg sync.WaitGroup 290 defer func() { 291 close(done) 292 wg.Wait() 293 }() 294 for g := int64(runtime.GOMAXPROCS(0)); g > 0; g-- { 295 r := rand.New(rand.NewSource(g)) 296 wg.Add(1) 297 go func(g int64) { 298 defer wg.Done() 299 for i := int64(0); ; i++ { 300 select { 301 case <-done: 302 return 303 default: 304 } 305 for n := int64(1); n < mapSize; n++ { 306 if r.Int63n(mapSize) == 0 { 307 m.Store(n, n*i*g) 308 } else { 309 m.Load(n) 310 } 311 } 312 } 313 }(g) 314 } 315 316 iters := 1 << 10 317 if testing.Short() { 318 iters = 16 319 } 320 for n := iters; n > 0; n-- { 321 seen := make(map[int64]bool, mapSize) 322 323 m.Range(func(ki int64, vi interface{}) bool { 324 k, v := ki, vi.(int64) 325 if v%k != 0 { 326 t.Fatalf("while Storing multiples of %v, Range saw value %v", k, v) 327 } 328 if seen[k] { 329 t.Fatalf("Range visited key %v twice", k) 330 } 331 seen[k] = true 332 return true 333 }) 334 335 if len(seen) != mapSize { 336 t.Fatalf("Range visited %v elements of %v-element Map", len(seen), mapSize) 337 } 338 } 339 }