tests/test_hash_map.c

changeset 856
6bbbf219251d
parent 855
35bcb3216c0d
child 890
54565fd74e74
equal deleted inserted replaced
855:35bcb3216c0d 856:6bbbf219251d
40 struct cx_hash_map_s *hmap = (struct cx_hash_map_s *) map; 40 struct cx_hash_map_s *hmap = (struct cx_hash_map_s *) map;
41 CX_TEST_ASSERT(hmap->bucket_count > 0); 41 CX_TEST_ASSERT(hmap->bucket_count > 0);
42 for(size_t i = 0 ; i < hmap->bucket_count ; i++) { 42 for(size_t i = 0 ; i < hmap->bucket_count ; i++) {
43 CX_TEST_ASSERT(hmap->buckets[i] == NULL); 43 CX_TEST_ASSERT(hmap->buckets[i] == NULL);
44 } 44 }
45 CX_TEST_ASSERT(map->base.elem_size == 1); 45 CX_TEST_ASSERT(map->collection.elem_size == 1);
46 CX_TEST_ASSERT(map->base.size == 0); 46 CX_TEST_ASSERT(map->collection.size == 0);
47 CX_TEST_ASSERT(map->base.allocator == allocator); 47 CX_TEST_ASSERT(map->collection.allocator == allocator);
48 CX_TEST_ASSERT(!map->base.store_pointer); 48 CX_TEST_ASSERT(!map->collection.store_pointer);
49 CX_TEST_ASSERT(map->base.cmpfunc == NULL); 49 CX_TEST_ASSERT(map->collection.cmpfunc == NULL);
50 CX_TEST_ASSERT(map->base.simple_destructor == NULL); 50 CX_TEST_ASSERT(map->collection.simple_destructor == NULL);
51 CX_TEST_ASSERT(map->base.advanced_destructor == NULL); 51 CX_TEST_ASSERT(map->collection.advanced_destructor == NULL);
52 CX_TEST_ASSERT(map->base.destructor_data == NULL); 52 CX_TEST_ASSERT(map->collection.destructor_data == NULL);
53 cxMapStorePointers(map); 53 cxMapStorePointers(map);
54 CX_TEST_ASSERT(map->base.store_pointer); 54 CX_TEST_ASSERT(map->collection.store_pointer);
55 CX_TEST_ASSERT(map->base.elem_size == sizeof(void *)); 55 CX_TEST_ASSERT(map->collection.elem_size == sizeof(void *));
56 cxMapStoreObjects(map); 56 cxMapStoreObjects(map);
57 CX_TEST_ASSERT(!map->base.store_pointer); 57 CX_TEST_ASSERT(!map->collection.store_pointer);
58 58
59 cxMapDestroy(map); 59 cxMapDestroy(map);
60 CX_TEST_ASSERT(cx_testing_allocator_verify(&talloc)); 60 CX_TEST_ASSERT(cx_testing_allocator_verify(&talloc));
61 } 61 }
62 cx_testing_allocator_destroy(&talloc); 62 cx_testing_allocator_destroy(&talloc);
71 struct cx_hash_map_s *hmap = (struct cx_hash_map_s *) map; 71 struct cx_hash_map_s *hmap = (struct cx_hash_map_s *) map;
72 CX_TEST_ASSERT(hmap->bucket_count > 0); 72 CX_TEST_ASSERT(hmap->bucket_count > 0);
73 for (size_t i = 0; i < hmap->bucket_count; i++) { 73 for (size_t i = 0; i < hmap->bucket_count; i++) {
74 CX_TEST_ASSERT(hmap->buckets[i] == NULL); 74 CX_TEST_ASSERT(hmap->buckets[i] == NULL);
75 } 75 }
76 CX_TEST_ASSERT(map->base.size == 0); 76 CX_TEST_ASSERT(map->collection.size == 0);
77 CX_TEST_ASSERT(map->base.allocator == allocator); 77 CX_TEST_ASSERT(map->collection.allocator == allocator);
78 CX_TEST_ASSERT(map->base.store_pointer); 78 CX_TEST_ASSERT(map->collection.store_pointer);
79 CX_TEST_ASSERT(map->base.elem_size == sizeof(void *)); 79 CX_TEST_ASSERT(map->collection.elem_size == sizeof(void *));
80 80
81 cxMapDestroy(map); 81 cxMapDestroy(map);
82 CX_TEST_ASSERT(cx_testing_allocator_verify(&talloc)); 82 CX_TEST_ASSERT(cx_testing_allocator_verify(&talloc));
83 } 83 }
84 cx_testing_allocator_destroy(&talloc); 84 cx_testing_allocator_destroy(&talloc);
104 104
105 CX_TEST_ASSERT(((struct cx_hash_map_s *)map)->bucket_count == 7); 105 CX_TEST_ASSERT(((struct cx_hash_map_s *)map)->bucket_count == 7);
106 int result = cxMapRehash(map); 106 int result = cxMapRehash(map);
107 CX_TEST_ASSERT(result == 0); 107 CX_TEST_ASSERT(result == 0);
108 CX_TEST_ASSERT(((struct cx_hash_map_s *)map)->bucket_count == 25); 108 CX_TEST_ASSERT(((struct cx_hash_map_s *)map)->bucket_count == 25);
109 CX_TEST_ASSERT(map->base.size == 10); 109 CX_TEST_ASSERT(map->collection.size == 10);
110 110
111 CX_TEST_ASSERT(0 == strcmp(cxMapGet(map, "key 1"), "val 1")); 111 CX_TEST_ASSERT(0 == strcmp(cxMapGet(map, "key 1"), "val 1"));
112 CX_TEST_ASSERT(0 == strcmp(cxMapGet(map, "key 2"), "val 2")); 112 CX_TEST_ASSERT(0 == strcmp(cxMapGet(map, "key 2"), "val 2"));
113 CX_TEST_ASSERT(0 == strcmp(cxMapGet(map, "key 3"), "val 3")); 113 CX_TEST_ASSERT(0 == strcmp(cxMapGet(map, "key 3"), "val 3"));
114 CX_TEST_ASSERT(0 == strcmp(cxMapGet(map, "foo 4"), "val 4")); 114 CX_TEST_ASSERT(0 == strcmp(cxMapGet(map, "foo 4"), "val 4"));
159 159
160 cxMapPut(map, "key 1", (void *) "val 1"); 160 cxMapPut(map, "key 1", (void *) "val 1");
161 cxMapPut(map, "key 2", (void *) "val 2"); 161 cxMapPut(map, "key 2", (void *) "val 2");
162 cxMapPut(map, "key 3", (void *) "val 3"); 162 cxMapPut(map, "key 3", (void *) "val 3");
163 163
164 CX_TEST_ASSERT(map->base.size == 3); 164 CX_TEST_ASSERT(map->collection.size == 3);
165 165
166 cxMapClear(map); 166 cxMapClear(map);
167 167
168 CX_TEST_ASSERT(map->base.size == 0); 168 CX_TEST_ASSERT(map->collection.size == 0);
169 CX_TEST_ASSERT(cxMapGet(map, "key 1") == NULL); 169 CX_TEST_ASSERT(cxMapGet(map, "key 1") == NULL);
170 CX_TEST_ASSERT(cxMapGet(map, "key 2") == NULL); 170 CX_TEST_ASSERT(cxMapGet(map, "key 2") == NULL);
171 CX_TEST_ASSERT(cxMapGet(map, "key 3") == NULL); 171 CX_TEST_ASSERT(cxMapGet(map, "key 3") == NULL);
172 172
173 cxMapDestroy(map); 173 cxMapDestroy(map);
206 CX_TEST_ASSERT(s3p->ptr == s3.ptr); 206 CX_TEST_ASSERT(s3p->ptr == s3.ptr);
207 CX_TEST_ASSERT(s3p != &s3); 207 CX_TEST_ASSERT(s3p != &s3);
208 208
209 // remove a string 209 // remove a string
210 cxMapRemove(map, "s2"); 210 cxMapRemove(map, "s2");
211 CX_TEST_ASSERT(map->base.size == 3); 211 CX_TEST_ASSERT(map->collection.size == 3);
212 212
213 // iterate 213 // iterate
214 bool s3found = false, s4found = false, s5found = false; 214 bool s3found = false, s4found = false, s5found = false;
215 CxIterator iter = cxMapIteratorValues(map); 215 CxIterator iter = cxMapIteratorValues(map);
216 cx_foreach(cxstring*, s, iter) { 216 cx_foreach(cxstring*, s, iter) {
242 242
243 CxIterator iter = cxMapMutIterator(map); 243 CxIterator iter = cxMapMutIterator(map);
244 cx_foreach(CxMapEntry*, entry, iter) { 244 cx_foreach(CxMapEntry*, entry, iter) {
245 if (((char const *)entry->key->data)[4] % 2 == 1) cxIteratorFlagRemoval(iter); 245 if (((char const *)entry->key->data)[4] % 2 == 1) cxIteratorFlagRemoval(iter);
246 } 246 }
247 CX_TEST_ASSERT(map->base.size == 3); 247 CX_TEST_ASSERT(map->collection.size == 3);
248 CX_TEST_ASSERT(iter.index == map->base.size); 248 CX_TEST_ASSERT(iter.index == map->collection.size);
249 249
250 CX_TEST_ASSERT(cxMapGet(map, "key 1") == NULL); 250 CX_TEST_ASSERT(cxMapGet(map, "key 1") == NULL);
251 CX_TEST_ASSERT(cxMapGet(map, "key 2") != NULL); 251 CX_TEST_ASSERT(cxMapGet(map, "key 2") != NULL);
252 CX_TEST_ASSERT(cxMapGet(map, "key 3") == NULL); 252 CX_TEST_ASSERT(cxMapGet(map, "key 3") == NULL);
253 CX_TEST_ASSERT(cxMapGet(map, "key 4") != NULL); 253 CX_TEST_ASSERT(cxMapGet(map, "key 4") != NULL);
346 CxTestingAllocator talloc; 346 CxTestingAllocator talloc;
347 cx_testing_allocator_init(&talloc); 347 cx_testing_allocator_init(&talloc);
348 CxAllocator *allocator = &talloc.base; 348 CxAllocator *allocator = &talloc.base;
349 CX_TEST_DO { 349 CX_TEST_DO {
350 CxMap *map = cxHashMapCreate(allocator, CX_STORE_POINTERS, 0); 350 CxMap *map = cxHashMapCreate(allocator, CX_STORE_POINTERS, 0);
351 map->base.simple_destructor = test_simple_destructor; 351 map->collection.simple_destructor = test_simple_destructor;
352 CX_TEST_CALL_SUBROUTINE(verify_any_destructor, map); 352 CX_TEST_CALL_SUBROUTINE(verify_any_destructor, map);
353 CX_TEST_ASSERT(cx_testing_allocator_verify(&talloc)); 353 CX_TEST_ASSERT(cx_testing_allocator_verify(&talloc));
354 } 354 }
355 cx_testing_allocator_destroy(&talloc); 355 cx_testing_allocator_destroy(&talloc);
356 } 356 }
359 CxTestingAllocator talloc; 359 CxTestingAllocator talloc;
360 cx_testing_allocator_init(&talloc); 360 cx_testing_allocator_init(&talloc);
361 CxAllocator *allocator = &talloc.base; 361 CxAllocator *allocator = &talloc.base;
362 CX_TEST_DO { 362 CX_TEST_DO {
363 CxMap *map = cxHashMapCreate(allocator, CX_STORE_POINTERS, 0); 363 CxMap *map = cxHashMapCreate(allocator, CX_STORE_POINTERS, 0);
364 map->base.advanced_destructor = test_advanced_destructor; 364 map->collection.advanced_destructor = test_advanced_destructor;
365 CX_TEST_CALL_SUBROUTINE(verify_any_destructor, map); 365 CX_TEST_CALL_SUBROUTINE(verify_any_destructor, map);
366 CX_TEST_ASSERT(cx_testing_allocator_verify(&talloc)); 366 CX_TEST_ASSERT(cx_testing_allocator_verify(&talloc));
367 } 367 }
368 cx_testing_allocator_destroy(&talloc); 368 cx_testing_allocator_destroy(&talloc);
369 } 369 }
370 370
371 CX_TEST(test_empty_map_size) { 371 CX_TEST(test_empty_map_size) {
372 CX_TEST_DO { 372 CX_TEST_DO {
373 CX_TEST_ASSERT(cxEmptyMap->base.size == 0); 373 CX_TEST_ASSERT(cxEmptyMap->collection.size == 0);
374 CX_TEST_ASSERT(cxMapSize(cxEmptyMap) == 0);
374 } 375 }
375 } 376 }
376 377
377 CX_TEST(test_empty_map_iterator) { 378 CX_TEST(test_empty_map_iterator) {
378 CxMap *map = cxEmptyMap; 379 CxMap *map = cxEmptyMap;
428 CxMap *map = cxHashMapCreate(allocator, sizeof(cxstring), 0); 429 CxMap *map = cxHashMapCreate(allocator, sizeof(cxstring), 0);
429 cxMapPut(map, "test", "test"); 430 cxMapPut(map, "test", "test");
430 cxMapPut(map, cx_mutstr("foo"), "bar"); 431 cxMapPut(map, cx_mutstr("foo"), "bar");
431 cxMapPut(map, cx_str("hallo"), "welt"); 432 cxMapPut(map, cx_str("hallo"), "welt");
432 433
433 CX_TEST_ASSERT(map->base.size == 3); 434 CX_TEST_ASSERT(map->collection.size == 3);
434 CX_TEST_ASSERT(0 == strcmp(cxMapGet(map, "test"), "test")); 435 CX_TEST_ASSERT(0 == strcmp(cxMapGet(map, "test"), "test"));
435 CX_TEST_ASSERT(0 == strcmp(cxMapGet(map, "foo"), "bar")); 436 CX_TEST_ASSERT(0 == strcmp(cxMapGet(map, "foo"), "bar"));
436 CX_TEST_ASSERT(0 == strcmp(cxMapGet(map, "hallo"), "welt")); 437 CX_TEST_ASSERT(0 == strcmp(cxMapGet(map, "hallo"), "welt"));
437 438
438 // note: we don't have a destructor here, so remove and detach are the same 439 // note: we don't have a destructor here, so remove and detach are the same
439 cxMapRemove(map, cx_str("test")); 440 cxMapRemove(map, cx_str("test"));
440 char const *hallo = "hallo"; 441 char const *hallo = "hallo";
441 cxMapDetach(map, hallo); 442 cxMapDetach(map, hallo);
442 cxMapPut(map, cx_hash_key_str("key"), "value"); 443 cxMapPut(map, cx_hash_key_str("key"), "value");
443 444
444 CX_TEST_ASSERT(map->base.size == 2); 445 CX_TEST_ASSERT(map->collection.size == 2);
445 CX_TEST_ASSERT(0 == strcmp(cxMapGet(map, "key"), "value")); 446 CX_TEST_ASSERT(0 == strcmp(cxMapGet(map, "key"), "value"));
446 CX_TEST_ASSERT(0 == strcmp(cxMapGet(map, "foo"), "bar")); 447 CX_TEST_ASSERT(0 == strcmp(cxMapGet(map, "foo"), "bar"));
447 448
448 void *r; 449 void *r;
449 r = cxMapRemoveAndGet(map, "key"); 450 r = cxMapRemoveAndGet(map, "key");
450 r = cxMapRemoveAndGet(map, cx_str("foo")); 451 r = cxMapRemoveAndGet(map, cx_str("foo"));
451 if (r != NULL) map->base.size = 47; 452 if (r != NULL) map->collection.size = 47;
452 453
453 CX_TEST_ASSERT(map->base.size == 0); 454 CX_TEST_ASSERT(map->collection.size == 0);
454 455
455 cxMapDestroy(map); 456 cxMapDestroy(map);
456 CX_TEST_ASSERT(cx_testing_allocator_verify(&talloc)); 457 CX_TEST_ASSERT(cx_testing_allocator_verify(&talloc));
457 } 458 }
458 cx_testing_allocator_destroy(&talloc); 459 cx_testing_allocator_destroy(&talloc);
537 return size; 538 return size;
538 } 539 }
539 540
540 static CX_TEST_SUBROUTINE(verify_map_contents, CxMap *map) { 541 static CX_TEST_SUBROUTINE(verify_map_contents, CxMap *map) {
541 // verify that the reference map has same size (i.e. no other keys are mapped) 542 // verify that the reference map has same size (i.e. no other keys are mapped)
542 CX_TEST_ASSERT(map->base.size == test_map_reference_size()); 543 CX_TEST_ASSERT(map->collection.size == test_map_reference_size());
543 544
544 // verify key iterator 545 // verify key iterator
545 { 546 {
546 // collect the keys from the map iterator 547 // collect the keys from the map iterator
547 CxIterator keyiter = cxMapIteratorKeys(map); 548 CxIterator keyiter = cxMapIteratorKeys(map);
548 CX_TEST_ASSERT(keyiter.elem_size == sizeof(CxHashKey)); 549 CX_TEST_ASSERT(keyiter.elem_size == sizeof(CxHashKey));
549 CX_TEST_ASSERT(keyiter.elem_count == map->base.size); 550 CX_TEST_ASSERT(keyiter.elem_count == map->collection.size);
550 CxHashKey *keys = calloc(map->base.size, sizeof(CxHashKey)); 551 CxHashKey *keys = calloc(map->collection.size, sizeof(CxHashKey));
551 cx_foreach(CxHashKey*, elem, keyiter) { 552 cx_foreach(CxHashKey*, elem, keyiter) {
552 keys[keyiter.index] = *elem; 553 keys[keyiter.index] = *elem;
553 } 554 }
554 CX_TEST_ASSERT(keyiter.index == map->base.size); 555 CX_TEST_ASSERT(keyiter.index == map->collection.size);
555 // verify that all keys are mapped to values in reference map 556 // verify that all keys are mapped to values in reference map
556 for (size_t i = 0 ; i < map->base.size ; i++) { 557 for (size_t i = 0 ; i < map->collection.size ; i++) {
557 cxmutstr ksz = cx_strdup(cx_strn(keys[i].data, keys[i].len)); 558 cxmutstr ksz = cx_strdup(cx_strn(keys[i].data, keys[i].len));
558 CX_TEST_ASSERT(test_map_reference_get(ksz.ptr) != NULL); 559 CX_TEST_ASSERT(test_map_reference_get(ksz.ptr) != NULL);
559 cx_strfree(&ksz); 560 cx_strfree(&ksz);
560 } 561 }
561 free(keys); 562 free(keys);
564 // verify value iterator 565 // verify value iterator
565 { 566 {
566 // by using that the values in our test data are unique strings 567 // by using that the values in our test data are unique strings
567 // we can re-use a similar approach as above 568 // we can re-use a similar approach as above
568 CxIterator valiter = cxMapIteratorValues(map); 569 CxIterator valiter = cxMapIteratorValues(map);
569 CX_TEST_ASSERT(valiter.elem_size == map->base.elem_size); 570 CX_TEST_ASSERT(valiter.elem_size == map->collection.elem_size);
570 CX_TEST_ASSERT(valiter.elem_count == map->base.size); 571 CX_TEST_ASSERT(valiter.elem_count == map->collection.size);
571 char const** values = calloc(map->base.size, sizeof(char const*)); 572 char const** values = calloc(map->collection.size, sizeof(char const*));
572 cx_foreach(char const*, elem, valiter) { 573 cx_foreach(char const*, elem, valiter) {
573 values[valiter.index] = elem; 574 values[valiter.index] = elem;
574 } 575 }
575 CX_TEST_ASSERT(valiter.index == map->base.size); 576 CX_TEST_ASSERT(valiter.index == map->collection.size);
576 // verify that all values are present in the reference map 577 // verify that all values are present in the reference map
577 for (size_t i = 0 ; i < map->base.size ; i++) { 578 for (size_t i = 0 ; i < map->collection.size ; i++) {
578 bool found = false; 579 bool found = false;
579 for (size_t j = 0; j < test_map_reference_len ; j++) { 580 for (size_t j = 0; j < test_map_reference_len ; j++) {
580 if (test_map_reference[j].value == values[i]) { 581 if (test_map_reference[j].value == values[i]) {
581 found = true; 582 found = true;
582 break; 583 break;
589 590
590 // verify pair iterator 591 // verify pair iterator
591 { 592 {
592 CxIterator pairiter = cxMapIterator(map); 593 CxIterator pairiter = cxMapIterator(map);
593 CX_TEST_ASSERT(pairiter.elem_size == sizeof(CxMapEntry)); 594 CX_TEST_ASSERT(pairiter.elem_size == sizeof(CxMapEntry));
594 CX_TEST_ASSERT(pairiter.elem_count == map->base.size); 595 CX_TEST_ASSERT(pairiter.elem_count == map->collection.size);
595 struct test_map_kv *pairs = calloc(map->base.size, sizeof(struct test_map_kv)); 596 struct test_map_kv *pairs = calloc(map->collection.size, sizeof(struct test_map_kv));
596 cx_foreach(CxMapEntry*, entry, pairiter) { 597 cx_foreach(CxMapEntry*, entry, pairiter) {
597 CxHashKey const *key = entry->key; 598 CxHashKey const *key = entry->key;
598 pairs[pairiter.index].key = cx_strdup(cx_strn(key->data, key->len)).ptr; 599 pairs[pairiter.index].key = cx_strdup(cx_strn(key->data, key->len)).ptr;
599 pairs[pairiter.index].value = entry->value; 600 pairs[pairiter.index].value = entry->value;
600 } 601 }
601 CX_TEST_ASSERT(pairiter.index == map->base.size); 602 CX_TEST_ASSERT(pairiter.index == map->collection.size);
602 // verify that all pairs are present in the reference map 603 // verify that all pairs are present in the reference map
603 for (size_t i = 0 ; i < map->base.size ; i++) { 604 for (size_t i = 0 ; i < map->collection.size ; i++) {
604 CX_TEST_ASSERT(test_map_reference_get(pairs[i].key) == pairs[i].value); 605 CX_TEST_ASSERT(test_map_reference_get(pairs[i].key) == pairs[i].value);
605 // this was strdup'ed 606 // this was strdup'ed
606 free((void*)pairs[i].key); 607 free((void*)pairs[i].key);
607 } 608 }
608 free(pairs); 609 free(pairs);

mercurial