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