github.com/sereiner/library@v0.0.0-20200518095232-1fa3e640cc5f/concurrent/cmap/concurrent_map_test.go (about) 1 package cmap 2 3 import ( 4 "encoding/json" 5 "errors" 6 "hash/fnv" 7 "sort" 8 "strconv" 9 "testing" 10 ) 11 12 type Animal struct { 13 name string 14 } 15 16 func TestMapCreation(t *testing.T) { 17 m := New(32) 18 if m == nil { 19 t.Error("map is null.") 20 } 21 22 if m.Count() != 0 { 23 t.Error("new map should be empty.") 24 } 25 } 26 27 func TestInsert(t *testing.T) { 28 m := New(32) 29 elephant := Animal{"elephant"} 30 monkey := Animal{"monkey"} 31 32 m.Set("elephant", elephant) 33 m.Set("monkey", monkey) 34 35 if m.Count() != 2 { 36 t.Error("map should contain exactly two elements.") 37 } 38 } 39 40 func TestInsertAbsent(t *testing.T) { 41 m := New(32) 42 elephant := Animal{"elephant"} 43 monkey := Animal{"monkey"} 44 45 m.SetIfAbsent("elephant", elephant) 46 if ok, _ := m.SetIfAbsent("elephant", monkey); ok { 47 t.Error("map set a new value even the entry is already present") 48 } 49 } 50 func TestSetIfAbsentCb(t *testing.T) { 51 m := New(32) 52 cb := func(i ...interface{}) (interface{}, error) { 53 if i[0].(int) == 1 { 54 return nil, errors.New("ERR") 55 } 56 return i[0], nil 57 } 58 ok, v, err := m.SetIfAbsentCb("1", cb, 1) 59 if err == nil || ok || v != nil { 60 t.Error("SetIfAbsentCb 应返回错误") 61 } 62 ok, v, err = m.SetIfAbsentCb("2", cb, 2) 63 if !ok || v == nil || v.(int) != 2 || err != nil { 64 t.Error("SetIfAbsentCb 应返回正确结果") 65 } 66 if m.Count() != 1 { 67 t.Error("SetIfAbsentCb 未设置成功") 68 } 69 if v, ok := m.Get("2"); !ok || v.(int) != 2 { 70 t.Error("SetIfAbsentCb 设置的值错误") 71 } 72 ok, v, err = m.SetIfAbsentCb("2", cb, 2) 73 74 if ok || v == nil || err != nil { 75 t.Error("SetIfAbsentCb 值已存在时返回结果错误") 76 } 77 78 } 79 80 func TestGet(t *testing.T) { 81 m := New(32) 82 83 // Get a missing element. 84 val, ok := m.Get("Money") 85 86 if ok == true { 87 t.Error("ok should be false when item is missing from map.") 88 } 89 90 if val != nil { 91 t.Error("Missing values should return as null.") 92 } 93 94 elephant := Animal{"elephant"} 95 m.Set("elephant", elephant) 96 97 // Retrieve inserted element. 98 99 tmp, ok := m.Get("elephant") 100 elephant = tmp.(Animal) // Type assertion. 101 102 if ok == false { 103 t.Error("ok should be true for item stored within the map.") 104 } 105 106 if &elephant == nil { 107 t.Error("expecting an element, not null.") 108 } 109 110 if elephant.name != "elephant" { 111 t.Error("item was modified.") 112 } 113 } 114 115 func TestHas(t *testing.T) { 116 m := New(32) 117 118 // Get a missing element. 119 if m.Has("Money") == true { 120 t.Error("element shouldn't exists") 121 } 122 123 elephant := Animal{"elephant"} 124 m.Set("elephant", elephant) 125 126 if m.Has("elephant") == false { 127 t.Error("element exists, expecting Has to return True.") 128 } 129 } 130 131 func TestRemove(t *testing.T) { 132 m := New(32) 133 134 monkey := Animal{"monkey"} 135 m.Set("monkey", monkey) 136 137 m.Remove("monkey") 138 139 if m.Count() != 0 { 140 t.Error("Expecting count to be zero once item was removed.") 141 } 142 143 temp, ok := m.Get("monkey") 144 145 if ok != false { 146 t.Error("Expecting ok to be false for missing items.") 147 } 148 149 if temp != nil { 150 t.Error("Expecting item to be nil after its removal.") 151 } 152 153 // Remove a none existing element. 154 m.Remove("noone") 155 } 156 157 func TestPop(t *testing.T) { 158 m := New(32) 159 160 monkey := Animal{"monkey"} 161 m.Set("monkey", monkey) 162 163 v, exists := m.Pop("monkey") 164 165 if !exists { 166 t.Error("Pop didn't find a monkey.") 167 } 168 169 m1, ok := v.(Animal) 170 171 if !ok || m1 != monkey { 172 t.Error("Pop found something else, but monkey.") 173 } 174 175 v2, exists2 := m.Pop("monkey") 176 m1, ok = v2.(Animal) 177 178 if exists2 || ok || m1 == monkey { 179 t.Error("Pop keeps finding monkey") 180 } 181 182 if m.Count() != 0 { 183 t.Error("Expecting count to be zero once item was Pop'ed.") 184 } 185 186 temp, ok := m.Get("monkey") 187 188 if ok != false { 189 t.Error("Expecting ok to be false for missing items.") 190 } 191 192 if temp != nil { 193 t.Error("Expecting item to be nil after its removal.") 194 } 195 } 196 197 func TestCount(t *testing.T) { 198 m := New(32) 199 for i := 0; i < 100; i++ { 200 m.Set(strconv.Itoa(i), Animal{strconv.Itoa(i)}) 201 } 202 203 if m.Count() != 100 { 204 t.Error("Expecting 100 element within map.") 205 } 206 } 207 208 func TestIsEmpty(t *testing.T) { 209 m := New(32) 210 211 if m.IsEmpty() == false { 212 t.Error("new map should be empty") 213 } 214 215 m.Set("elephant", Animal{"elephant"}) 216 217 if m.IsEmpty() != false { 218 t.Error("map shouldn't be empty.") 219 } 220 } 221 222 func TestIterator(t *testing.T) { 223 m := New(32) 224 225 // Insert 100 elements. 226 for i := 0; i < 100; i++ { 227 m.Set(strconv.Itoa(i), Animal{strconv.Itoa(i)}) 228 } 229 230 counter := 0 231 // Iterate over elements. 232 for item := range m.Iter() { 233 val := item.Val 234 235 if val == nil { 236 t.Error("Expecting an object.") 237 } 238 counter++ 239 } 240 241 if counter != 100 { 242 t.Error("We should have counted 100 elements.") 243 } 244 } 245 246 func TestBufferedIterator(t *testing.T) { 247 m := New(32) 248 249 // Insert 100 elements. 250 for i := 0; i < 100; i++ { 251 m.Set(strconv.Itoa(i), Animal{strconv.Itoa(i)}) 252 } 253 254 counter := 0 255 // Iterate over elements. 256 for item := range m.IterBuffered() { 257 val := item.Val 258 259 if val == nil { 260 t.Error("Expecting an object.") 261 } 262 counter++ 263 } 264 265 if counter != 100 { 266 t.Error("We should have counted 100 elements.") 267 } 268 } 269 270 func TestIterCb(t *testing.T) { 271 m := New(32) 272 273 // Insert 100 elements. 274 for i := 0; i < 100; i++ { 275 m.Set(strconv.Itoa(i), Animal{strconv.Itoa(i)}) 276 } 277 278 counter := 0 279 // Iterate over elements. 280 m.IterCb(func(key string, v interface{}) bool { 281 _, ok := v.(Animal) 282 if !ok { 283 t.Error("Expecting an animal object") 284 } 285 286 counter++ 287 return true 288 }) 289 if counter != 100 { 290 t.Error("We should have counted 100 elements.") 291 } 292 } 293 294 func TestItems(t *testing.T) { 295 m := New(32) 296 297 // Insert 100 elements. 298 for i := 0; i < 100; i++ { 299 m.Set(strconv.Itoa(i), Animal{strconv.Itoa(i)}) 300 } 301 302 items := m.Items() 303 304 if len(items) != 100 { 305 t.Error("We should have counted 100 elements.") 306 } 307 } 308 309 func TestConcurrent(t *testing.T) { 310 m := New(32) 311 ch := make(chan int) 312 const iterations = 1000 313 var a [iterations]int 314 315 // Using go routines insert 1000 ints into our map. 316 go func() { 317 for i := 0; i < iterations/2; i++ { 318 // Add item to map. 319 m.Set(strconv.Itoa(i), i) 320 321 // Retrieve item from map. 322 val, _ := m.Get(strconv.Itoa(i)) 323 324 // Write to channel inserted value. 325 ch <- val.(int) 326 } // Call go routine with current index. 327 }() 328 329 go func() { 330 for i := iterations / 2; i < iterations; i++ { 331 // Add item to map. 332 m.Set(strconv.Itoa(i), i) 333 334 // Retrieve item from map. 335 val, _ := m.Get(strconv.Itoa(i)) 336 337 // Write to channel inserted value. 338 ch <- val.(int) 339 } // Call go routine with current index. 340 }() 341 342 // Wait for all go routines to finish. 343 counter := 0 344 for elem := range ch { 345 a[counter] = elem 346 counter++ 347 if counter == iterations { 348 break 349 } 350 } 351 352 // Sorts array, will make is simpler to verify all inserted values we're returned. 353 sort.Ints(a[0:iterations]) 354 355 // Make sure map contains 1000 elements. 356 if m.Count() != iterations { 357 t.Error("Expecting 1000 elements.") 358 } 359 360 // Make sure all inserted values we're fetched from map. 361 for i := 0; i < iterations; i++ { 362 if i != a[i] { 363 t.Error("missing value", i) 364 } 365 } 366 } 367 368 func TestJsonMarshal(t *testing.T) { 369 expected := "{\"a\":1,\"b\":2}" 370 m := New(2) 371 m.Set("a", 1) 372 m.Set("b", 2) 373 j, err := json.Marshal(m) 374 if err != nil { 375 t.Error(err) 376 } 377 378 if string(j) != expected { 379 t.Error("json", string(j), "differ from expected", expected) 380 return 381 } 382 } 383 384 func TestKeys(t *testing.T) { 385 m := New(32) 386 387 // Insert 100 elements. 388 for i := 0; i < 100; i++ { 389 m.Set(strconv.Itoa(i), Animal{strconv.Itoa(i)}) 390 } 391 392 keys := m.Keys() 393 if len(keys) != 100 { 394 t.Error("We should have counted 100 elements.") 395 } 396 } 397 398 func TestMInsert(t *testing.T) { 399 animals := map[string]interface{}{ 400 "elephant": Animal{"elephant"}, 401 "monkey": Animal{"monkey"}, 402 } 403 m := New(32) 404 m.MSet(animals) 405 406 if m.Count() != 2 { 407 t.Error("map should contain exactly two elements.") 408 } 409 } 410 func TestClear(t *testing.T) { 411 animals := map[string]interface{}{ 412 "elephant": Animal{"elephant"}, 413 "monkey": Animal{"monkey"}, 414 } 415 m := New(32) 416 m.MSet(animals) 417 m.Clear() 418 419 if m.Count() != 0 { 420 t.Error("map should contain 0 element.") 421 } 422 } 423 func TestPopAll(t *testing.T) { 424 animals := map[string]interface{}{ 425 "elephant": Animal{"elephant"}, 426 "monkey": Animal{"monkey"}, 427 } 428 m := New(32) 429 m.MSet(animals) 430 431 nAnimals := m.PopAll() 432 433 if m.Count() != 0 { 434 t.Error("PopAll 后元素个数应为0") 435 } 436 437 if len(nAnimals) != len(animals) { 438 t.Error("PopAll 返回的元素个数错误", len(nAnimals), len(animals)) 439 } 440 for k, v := range nAnimals { 441 if va, ok := animals[k]; !ok || v != va { 442 t.Error("PopAll 返回的元素值错误") 443 } 444 } 445 } 446 447 func TestFnv32(t *testing.T) { 448 key := []byte("ABC") 449 450 hasher := fnv.New32() 451 hasher.Write(key) 452 if fnv32(string(key)) != hasher.Sum32() { 453 t.Errorf("Bundled fnv32 produced %d, expected result from hash/fnv32 is %d", fnv32(string(key)), hasher.Sum32()) 454 } 455 } 456 457 func TestUpsert(t *testing.T) { 458 dolphin := Animal{"dolphin"} 459 whale := Animal{"whale"} 460 tiger := Animal{"tiger"} 461 lion := Animal{"lion"} 462 463 cb := func(exists bool, valueInMap interface{}, newValue interface{}) interface{} { 464 nv := newValue.(Animal) 465 if !exists { 466 return []Animal{nv} 467 } 468 res := valueInMap.([]Animal) 469 return append(res, nv) 470 } 471 472 m := New(32) 473 m.Set("marine", []Animal{dolphin}) 474 m.Upsert("marine", whale, cb) 475 m.Upsert("predator", tiger, cb) 476 m.Upsert("predator", lion, cb) 477 478 if m.Count() != 2 { 479 t.Error("map should contain exactly two elements.") 480 } 481 482 compare := func(a, b []Animal) bool { 483 if a == nil || b == nil { 484 return false 485 } 486 487 if len(a) != len(b) { 488 return false 489 } 490 491 for i, v := range a { 492 if v != b[i] { 493 return false 494 } 495 } 496 return true 497 } 498 499 marineAnimals, ok := m.Get("marine") 500 if !ok || !compare(marineAnimals.([]Animal), []Animal{dolphin, whale}) { 501 t.Error("Set, then Upsert failed") 502 } 503 504 predators, ok := m.Get("predator") 505 if !ok || !compare(predators.([]Animal), []Animal{tiger, lion}) { 506 t.Error("Upsert, then Upsert failed") 507 } 508 }