github.com/hdt3213/godis@v1.2.9/datastruct/dict/concurrent_test.go (about) 1 package dict 2 3 import ( 4 "github.com/hdt3213/godis/lib/utils" 5 "strconv" 6 "sync" 7 "testing" 8 ) 9 10 func TestConcurrentPut(t *testing.T) { 11 d := MakeConcurrent(0) 12 count := 100 13 var wg sync.WaitGroup 14 wg.Add(count) 15 for i := 0; i < count; i++ { 16 go func(i int) { 17 // insert 18 key := "k" + strconv.Itoa(i) 19 ret := d.Put(key, i) 20 if ret != 1 { // insert 1 21 t.Error("put test failed: expected result 1, actual: " + strconv.Itoa(ret) + ", key: " + key) 22 } 23 val, ok := d.Get(key) 24 if ok { 25 intVal, _ := val.(int) 26 if intVal != i { 27 t.Error("put test failed: expected " + strconv.Itoa(i) + ", actual: " + strconv.Itoa(intVal) + ", key: " + key) 28 } 29 } else { 30 _, ok := d.Get(key) 31 t.Error("put test failed: expected true, actual: false, key: " + key + ", retry: " + strconv.FormatBool(ok)) 32 } 33 wg.Done() 34 }(i) 35 } 36 wg.Wait() 37 } 38 39 func TestConcurrentPutWithLock(t *testing.T) { 40 d := MakeConcurrent(0) 41 count := 100 42 var wg sync.WaitGroup 43 wg.Add(count) 44 45 for i := 0; i < count; i++ { 46 go func(i int) { 47 // insert 48 key := "k" + strconv.Itoa(i) 49 keys := []string{key} 50 d.RWLocks(keys, nil) 51 ret := d.PutWithLock(key, i) 52 if ret != 1 { // insert 1 53 t.Error("put test failed: expected result 1, actual: " + strconv.Itoa(ret) + ", key: " + key) 54 } 55 val, ok := d.GetWithLock(key) 56 if ok { 57 intVal, _ := val.(int) 58 if intVal != i { 59 t.Error("put test failed: expected " + strconv.Itoa(i) + ", actual: " + strconv.Itoa(intVal) + ", key: " + key) 60 } 61 } else { 62 _, ok := d.GetWithLock(key) 63 t.Error("put test failed: expected true, actual: false, key: " + key + ", retry: " + strconv.FormatBool(ok)) 64 } 65 wg.Done() 66 d.RWUnLocks(keys, nil) 67 }(i) 68 } 69 wg.Wait() 70 } 71 72 func TestConcurrentPutIfAbsent(t *testing.T) { 73 d := MakeConcurrent(0) 74 count := 100 75 var wg sync.WaitGroup 76 wg.Add(count) 77 for i := 0; i < count; i++ { 78 go func(i int) { 79 // insert 80 key := "k" + strconv.Itoa(i) 81 ret := d.PutIfAbsent(key, i) 82 if ret != 1 { // insert 1 83 t.Error("put test failed: expected result 1, actual: " + strconv.Itoa(ret) + ", key: " + key) 84 } 85 val, ok := d.Get(key) 86 if ok { 87 intVal, _ := val.(int) 88 if intVal != i { 89 t.Error("put test failed: expected " + strconv.Itoa(i) + ", actual: " + strconv.Itoa(intVal) + 90 ", key: " + key) 91 } 92 } else { 93 _, ok := d.Get(key) 94 t.Error("put test failed: expected true, actual: false, key: " + key + ", retry: " + strconv.FormatBool(ok)) 95 } 96 97 // update 98 ret = d.PutIfAbsent(key, i*10) 99 if ret != 0 { // no update 100 t.Error("put test failed: expected result 0, actual: " + strconv.Itoa(ret)) 101 } 102 val, ok = d.Get(key) 103 if ok { 104 intVal, _ := val.(int) 105 if intVal != i { 106 t.Error("put test failed: expected " + strconv.Itoa(i) + ", actual: " + strconv.Itoa(intVal) + ", key: " + key) 107 } 108 } else { 109 t.Error("put test failed: expected true, actual: false, key: " + key) 110 } 111 wg.Done() 112 }(i) 113 } 114 wg.Wait() 115 } 116 117 func TestConcurrentPutIfAbsentWithLock(t *testing.T) { 118 d := MakeConcurrent(0) 119 count := 100 120 var wg sync.WaitGroup 121 wg.Add(count) 122 123 for i := 0; i < count; i++ { 124 go func(i int) { 125 // insert 126 key := "k" + strconv.Itoa(i) 127 keys := []string{key} 128 d.RWLocks(keys, nil) 129 ret := d.PutIfAbsentWithLock(key, i) 130 if ret != 1 { // insert 1 131 t.Error("put test failed: expected result 1, actual: " + strconv.Itoa(ret) + ", key: " + key) 132 } 133 val, ok := d.GetWithLock(key) 134 if ok { 135 intVal, _ := val.(int) 136 if intVal != i { 137 t.Error("put test failed: expected " + strconv.Itoa(i) + ", actual: " + strconv.Itoa(intVal) + 138 ", key: " + key) 139 } 140 } else { 141 _, ok := d.GetWithLock(key) 142 t.Error("put test failed: expected true, actual: false, key: " + key + ", retry: " + strconv.FormatBool(ok)) 143 } 144 145 // update 146 ret = d.PutIfAbsentWithLock(key, i*10) 147 if ret != 0 { // no update 148 t.Error("put test failed: expected result 0, actual: " + strconv.Itoa(ret)) 149 } 150 val, ok = d.GetWithLock(key) 151 if ok { 152 intVal, _ := val.(int) 153 if intVal != i { 154 t.Error("put test failed: expected " + strconv.Itoa(i) + ", actual: " + strconv.Itoa(intVal) + ", key: " + key) 155 } 156 } else { 157 t.Error("put test failed: expected true, actual: false, key: " + key) 158 } 159 d.RWUnLocks(keys, nil) 160 wg.Done() 161 }(i) 162 } 163 wg.Wait() 164 } 165 166 func TestConcurrentPutIfExists(t *testing.T) { 167 d := MakeConcurrent(0) 168 count := 100 169 var wg sync.WaitGroup 170 wg.Add(count) 171 172 for i := 0; i < count; i++ { 173 go func(i int) { 174 // insert 175 key := "k" + strconv.Itoa(i) 176 // insert 177 ret := d.PutIfExists(key, i) 178 if ret != 0 { // insert 179 t.Error("put test failed: expected result 0, actual: " + strconv.Itoa(ret)) 180 } 181 182 d.Put(key, i) 183 d.PutIfExists(key, 10*i) 184 val, ok := d.Get(key) 185 if ok { 186 intVal, _ := val.(int) 187 if intVal != 10*i { 188 t.Error("put test failed: expected " + strconv.Itoa(10*i) + ", actual: " + strconv.Itoa(intVal)) 189 } 190 } else { 191 _, ok := d.Get(key) 192 t.Error("put test failed: expected true, actual: false, key: " + key + ", retry: " + strconv.FormatBool(ok)) 193 } 194 wg.Done() 195 }(i) 196 } 197 wg.Wait() 198 } 199 200 func TestConcurrentPutIfExistsWithLock(t *testing.T) { 201 d := MakeConcurrent(0) 202 count := 100 203 var wg sync.WaitGroup 204 wg.Add(count) 205 206 for i := 0; i < count; i++ { 207 go func(i int) { 208 // insert 209 key := "k" + strconv.Itoa(i) 210 keys := []string{key} 211 d.RWLocks(keys, nil) 212 // insert 213 ret := d.PutIfExistsWithLock(key, i) 214 if ret != 0 { // insert 215 t.Error("put test failed: expected result 0, actual: " + strconv.Itoa(ret)) 216 } 217 d.PutWithLock(key, i) 218 d.PutIfExistsWithLock(key, 10*i) 219 val, ok := d.GetWithLock(key) 220 if ok { 221 intVal, _ := val.(int) 222 if intVal != 10*i { 223 t.Error("put test failed: expected " + strconv.Itoa(10*i) + ", actual: " + strconv.Itoa(intVal)) 224 } 225 } else { 226 _, ok := d.GetWithLock(key) 227 t.Error("put test failed: expected true, actual: false, key: " + key + ", retry: " + strconv.FormatBool(ok)) 228 } 229 d.RWUnLocks(keys, nil) 230 wg.Done() 231 }(i) 232 } 233 wg.Wait() 234 } 235 236 func TestConcurrentRemove(t *testing.T) { 237 d := MakeConcurrent(0) 238 totalCount := 100 239 // remove head node 240 for i := 0; i < totalCount; i++ { 241 // insert 242 key := "k" + strconv.Itoa(i) 243 d.Put(key, i) 244 } 245 if d.Len() != totalCount { 246 t.Error("put test failed: expected len is 100, actual: " + strconv.Itoa(d.Len())) 247 } 248 for i := 0; i < totalCount; i++ { 249 key := "k" + strconv.Itoa(i) 250 251 val, ok := d.Get(key) 252 if ok { 253 intVal, _ := val.(int) 254 if intVal != i { 255 t.Error("put test failed: expected " + strconv.Itoa(i) + ", actual: " + strconv.Itoa(intVal)) 256 } 257 } else { 258 t.Error("put test failed: expected true, actual: false") 259 } 260 261 ret := d.Remove(key) 262 if ret != 1 { 263 t.Error("remove test failed: expected result 1, actual: " + strconv.Itoa(ret) + ", key:" + key) 264 } 265 if d.Len() != totalCount-i-1 { 266 t.Error("put test failed: expected len is 99, actual: " + strconv.Itoa(d.Len())) 267 } 268 _, ok = d.Get(key) 269 if ok { 270 t.Error("remove test failed: expected true, actual false") 271 } 272 ret = d.Remove(key) 273 if ret != 0 { 274 t.Error("remove test failed: expected result 0 actual: " + strconv.Itoa(ret)) 275 } 276 if d.Len() != totalCount-i-1 { 277 t.Error("put test failed: expected len is 99, actual: " + strconv.Itoa(d.Len())) 278 } 279 } 280 281 // remove tail node 282 d = MakeConcurrent(0) 283 for i := 0; i < 100; i++ { 284 // insert 285 key := "k" + strconv.Itoa(i) 286 d.Put(key, i) 287 } 288 for i := 9; i >= 0; i-- { 289 key := "k" + strconv.Itoa(i) 290 291 val, ok := d.Get(key) 292 if ok { 293 intVal, _ := val.(int) 294 if intVal != i { 295 t.Error("put test failed: expected " + strconv.Itoa(i) + ", actual: " + strconv.Itoa(intVal)) 296 } 297 } else { 298 t.Error("put test failed: expected true, actual: false") 299 } 300 301 ret := d.Remove(key) 302 if ret != 1 { 303 t.Error("remove test failed: expected result 1, actual: " + strconv.Itoa(ret)) 304 } 305 _, ok = d.Get(key) 306 if ok { 307 t.Error("remove test failed: expected true, actual false") 308 } 309 ret = d.Remove(key) 310 if ret != 0 { 311 t.Error("remove test failed: expected result 0 actual: " + strconv.Itoa(ret)) 312 } 313 } 314 315 // remove middle node 316 d = MakeConcurrent(0) 317 d.Put("head", 0) 318 for i := 0; i < 10; i++ { 319 // insert 320 key := "k" + strconv.Itoa(i) 321 d.Put(key, i) 322 } 323 d.Put("tail", 0) 324 for i := 9; i >= 0; i-- { 325 key := "k" + strconv.Itoa(i) 326 327 val, ok := d.Get(key) 328 if ok { 329 intVal, _ := val.(int) 330 if intVal != i { 331 t.Error("put test failed: expected " + strconv.Itoa(i) + ", actual: " + strconv.Itoa(intVal)) 332 } 333 } else { 334 t.Error("put test failed: expected true, actual: false") 335 } 336 337 ret := d.Remove(key) 338 if ret != 1 { 339 t.Error("remove test failed: expected result 1, actual: " + strconv.Itoa(ret)) 340 } 341 _, ok = d.Get(key) 342 if ok { 343 t.Error("remove test failed: expected true, actual false") 344 } 345 ret = d.Remove(key) 346 if ret != 0 { 347 t.Error("remove test failed: expected result 0 actual: " + strconv.Itoa(ret)) 348 } 349 } 350 } 351 352 func TestConcurrentRemoveWithLock(t *testing.T) { 353 d := MakeConcurrent(0) 354 totalCount := 100 355 // remove head node 356 for i := 0; i < totalCount; i++ { 357 // insert 358 key := "k" + strconv.Itoa(i) 359 d.PutWithLock(key, i) 360 } 361 if d.Len() != totalCount { 362 t.Error("put test failed: expected len is 100, actual: " + strconv.Itoa(d.Len())) 363 } 364 for i := 0; i < totalCount; i++ { 365 key := "k" + strconv.Itoa(i) 366 367 val, ok := d.GetWithLock(key) 368 if ok { 369 intVal, _ := val.(int) 370 if intVal != i { 371 t.Error("put test failed: expected " + strconv.Itoa(i) + ", actual: " + strconv.Itoa(intVal)) 372 } 373 } else { 374 t.Error("put test failed: expected true, actual: false") 375 } 376 377 ret := d.RemoveWithLock(key) 378 if ret != 1 { 379 t.Error("remove test failed: expected result 1, actual: " + strconv.Itoa(ret) + ", key:" + key) 380 } 381 if d.Len() != totalCount-i-1 { 382 t.Error("put test failed: expected len is 99, actual: " + strconv.Itoa(d.Len())) 383 } 384 _, ok = d.GetWithLock(key) 385 if ok { 386 t.Error("remove test failed: expected true, actual false") 387 } 388 ret = d.RemoveWithLock(key) 389 if ret != 0 { 390 t.Error("remove test failed: expected result 0 actual: " + strconv.Itoa(ret)) 391 } 392 if d.Len() != totalCount-i-1 { 393 t.Error("put test failed: expected len is 99, actual: " + strconv.Itoa(d.Len())) 394 } 395 } 396 397 // remove tail node 398 d = MakeConcurrent(0) 399 for i := 0; i < 100; i++ { 400 // insert 401 key := "k" + strconv.Itoa(i) 402 d.PutWithLock(key, i) 403 } 404 for i := 9; i >= 0; i-- { 405 key := "k" + strconv.Itoa(i) 406 407 val, ok := d.GetWithLock(key) 408 if ok { 409 intVal, _ := val.(int) 410 if intVal != i { 411 t.Error("put test failed: expected " + strconv.Itoa(i) + ", actual: " + strconv.Itoa(intVal)) 412 } 413 } else { 414 t.Error("put test failed: expected true, actual: false") 415 } 416 417 ret := d.RemoveWithLock(key) 418 if ret != 1 { 419 t.Error("remove test failed: expected result 1, actual: " + strconv.Itoa(ret)) 420 } 421 _, ok = d.GetWithLock(key) 422 if ok { 423 t.Error("remove test failed: expected true, actual false") 424 } 425 ret = d.RemoveWithLock(key) 426 if ret != 0 { 427 t.Error("remove test failed: expected result 0 actual: " + strconv.Itoa(ret)) 428 } 429 } 430 431 // remove middle node 432 d = MakeConcurrent(0) 433 d.Put("head", 0) 434 for i := 0; i < 10; i++ { 435 // insert 436 key := "k" + strconv.Itoa(i) 437 d.PutWithLock(key, i) 438 } 439 d.PutWithLock("tail", 0) 440 for i := 9; i >= 0; i-- { 441 key := "k" + strconv.Itoa(i) 442 443 val, ok := d.Get(key) 444 if ok { 445 intVal, _ := val.(int) 446 if intVal != i { 447 t.Error("put test failed: expected " + strconv.Itoa(i) + ", actual: " + strconv.Itoa(intVal)) 448 } 449 } else { 450 t.Error("put test failed: expected true, actual: false") 451 } 452 453 ret := d.RemoveWithLock(key) 454 if ret != 1 { 455 t.Error("remove test failed: expected result 1, actual: " + strconv.Itoa(ret)) 456 } 457 _, ok = d.GetWithLock(key) 458 if ok { 459 t.Error("remove test failed: expected true, actual false") 460 } 461 ret = d.RemoveWithLock(key) 462 if ret != 0 { 463 t.Error("remove test failed: expected result 0 actual: " + strconv.Itoa(ret)) 464 } 465 } 466 } 467 468 //change t.Error remove->forEach 469 func TestConcurrentForEach(t *testing.T) { 470 d := MakeConcurrent(0) 471 size := 100 472 for i := 0; i < size; i++ { 473 // insert 474 key := "k" + strconv.Itoa(i) 475 d.Put(key, i) 476 } 477 i := 0 478 d.ForEach(func(key string, value interface{}) bool { 479 intVal, _ := value.(int) 480 expectedKey := "k" + strconv.Itoa(intVal) 481 if key != expectedKey { 482 t.Error("forEach test failed: expected " + expectedKey + ", actual: " + key) 483 } 484 i++ 485 return true 486 }) 487 if i != size { 488 t.Error("forEach test failed: expected " + strconv.Itoa(size) + ", actual: " + strconv.Itoa(i)) 489 } 490 } 491 492 func TestConcurrentRandomKey(t *testing.T) { 493 d := MakeConcurrent(0) 494 count := 100 495 for i := 0; i < count; i++ { 496 key := "k" + strconv.Itoa(i) 497 d.Put(key, i) 498 } 499 fetchSize := 10 500 result := d.RandomKeys(fetchSize) 501 if len(result) != fetchSize { 502 t.Errorf("expect %d random keys acturally %d", fetchSize, len(result)) 503 } 504 result = d.RandomDistinctKeys(fetchSize) 505 distinct := make(map[string]struct{}) 506 for _, key := range result { 507 distinct[key] = struct{}{} 508 } 509 if len(result) != fetchSize { 510 t.Errorf("expect %d random keys acturally %d", fetchSize, len(result)) 511 } 512 if len(result) > len(distinct) { 513 t.Errorf("get duplicated keys in result") 514 } 515 } 516 517 func TestConcurrentDict_Keys(t *testing.T) { 518 d := MakeConcurrent(0) 519 size := 10 520 for i := 0; i < size; i++ { 521 d.Put(utils.RandString(5), utils.RandString(5)) 522 } 523 if len(d.Keys()) != size { 524 t.Errorf("expect %d keys, actual: %d", size, len(d.Keys())) 525 } 526 }