tests/test_hash_map.c

changeset 854
fe0d69d72bcd
parent 853
d4baf4dd55c3
child 855
35bcb3216c0d
equal deleted inserted replaced
853:d4baf4dd55c3 854:fe0d69d72bcd
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->item_size == 1); 45 CX_TEST_ASSERT(map->base.item_size == 1);
46 CX_TEST_ASSERT(map->size == 0); 46 CX_TEST_ASSERT(map->base.size == 0);
47 CX_TEST_ASSERT(map->allocator == allocator); 47 CX_TEST_ASSERT(map->base.allocator == allocator);
48 CX_TEST_ASSERT(!map->store_pointer); 48 CX_TEST_ASSERT(!map->base.store_pointer);
49 CX_TEST_ASSERT(map->cmpfunc == NULL); 49 CX_TEST_ASSERT(map->base.cmpfunc == NULL);
50 CX_TEST_ASSERT(map->simple_destructor == NULL); 50 CX_TEST_ASSERT(map->base.simple_destructor == NULL);
51 CX_TEST_ASSERT(map->advanced_destructor == NULL); 51 CX_TEST_ASSERT(map->base.advanced_destructor == NULL);
52 CX_TEST_ASSERT(map->destructor_data == NULL); 52 CX_TEST_ASSERT(map->base.destructor_data == NULL);
53 cxMapStorePointers(map); 53 cxMapStorePointers(map);
54 CX_TEST_ASSERT(map->store_pointer); 54 CX_TEST_ASSERT(map->base.store_pointer);
55 CX_TEST_ASSERT(map->item_size == sizeof(void *)); 55 CX_TEST_ASSERT(map->base.item_size == sizeof(void *));
56 cxMapStoreObjects(map); 56 cxMapStoreObjects(map);
57 CX_TEST_ASSERT(!map->store_pointer); 57 CX_TEST_ASSERT(!map->base.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->size == 0); 76 CX_TEST_ASSERT(map->base.size == 0);
77 CX_TEST_ASSERT(map->allocator == allocator); 77 CX_TEST_ASSERT(map->base.allocator == allocator);
78 CX_TEST_ASSERT(map->store_pointer); 78 CX_TEST_ASSERT(map->base.store_pointer);
79 CX_TEST_ASSERT(map->item_size == sizeof(void *)); 79 CX_TEST_ASSERT(map->base.item_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->size == 10); 109 CX_TEST_ASSERT(map->base.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->size == 3); 164 CX_TEST_ASSERT(map->base.size == 3);
165 165
166 cxMapClear(map); 166 cxMapClear(map);
167 167
168 CX_TEST_ASSERT(map->size == 0); 168 CX_TEST_ASSERT(map->base.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->size == 3); 211 CX_TEST_ASSERT(map->base.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->size == 3); 247 CX_TEST_ASSERT(map->base.size == 3);
248 CX_TEST_ASSERT(iter.index == map->size); 248 CX_TEST_ASSERT(iter.index == map->base.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->simple_destructor = test_simple_destructor; 351 map->base.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->advanced_destructor = test_advanced_destructor; 364 map->base.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->size == 0); 373 CX_TEST_ASSERT(cxEmptyMap->base.size == 0);
374 } 374 }
375 } 375 }
376 376
377 CX_TEST(test_empty_map_iterator) { 377 CX_TEST(test_empty_map_iterator) {
378 CxMap *map = cxEmptyMap; 378 CxMap *map = cxEmptyMap;
428 CxMap *map = cxHashMapCreate(allocator, sizeof(cxstring), 0); 428 CxMap *map = cxHashMapCreate(allocator, sizeof(cxstring), 0);
429 cxMapPut(map, "test", "test"); 429 cxMapPut(map, "test", "test");
430 cxMapPut(map, cx_mutstr("foo"), "bar"); 430 cxMapPut(map, cx_mutstr("foo"), "bar");
431 cxMapPut(map, cx_str("hallo"), "welt"); 431 cxMapPut(map, cx_str("hallo"), "welt");
432 432
433 CX_TEST_ASSERT(map->size == 3); 433 CX_TEST_ASSERT(map->base.size == 3);
434 CX_TEST_ASSERT(0 == strcmp(cxMapGet(map, "test"), "test")); 434 CX_TEST_ASSERT(0 == strcmp(cxMapGet(map, "test"), "test"));
435 CX_TEST_ASSERT(0 == strcmp(cxMapGet(map, "foo"), "bar")); 435 CX_TEST_ASSERT(0 == strcmp(cxMapGet(map, "foo"), "bar"));
436 CX_TEST_ASSERT(0 == strcmp(cxMapGet(map, "hallo"), "welt")); 436 CX_TEST_ASSERT(0 == strcmp(cxMapGet(map, "hallo"), "welt"));
437 437
438 // note: we don't have a destructor here, so remove and detach are the same 438 // note: we don't have a destructor here, so remove and detach are the same
439 cxMapRemove(map, cx_str("test")); 439 cxMapRemove(map, cx_str("test"));
440 char const *hallo = "hallo"; 440 char const *hallo = "hallo";
441 cxMapDetach(map, hallo); 441 cxMapDetach(map, hallo);
442 cxMapPut(map, cx_hash_key_str("key"), "value"); 442 cxMapPut(map, cx_hash_key_str("key"), "value");
443 443
444 CX_TEST_ASSERT(map->size == 2); 444 CX_TEST_ASSERT(map->base.size == 2);
445 CX_TEST_ASSERT(0 == strcmp(cxMapGet(map, "key"), "value")); 445 CX_TEST_ASSERT(0 == strcmp(cxMapGet(map, "key"), "value"));
446 CX_TEST_ASSERT(0 == strcmp(cxMapGet(map, "foo"), "bar")); 446 CX_TEST_ASSERT(0 == strcmp(cxMapGet(map, "foo"), "bar"));
447 447
448 void *r; 448 void *r;
449 r = cxMapRemoveAndGet(map, "key"); 449 r = cxMapRemoveAndGet(map, "key");
450 r = cxMapRemoveAndGet(map, cx_str("foo")); 450 r = cxMapRemoveAndGet(map, cx_str("foo"));
451 if (r != NULL) map->size = 47; 451 if (r != NULL) map->base.size = 47;
452 452
453 CX_TEST_ASSERT(map->size == 0); 453 CX_TEST_ASSERT(map->base.size == 0);
454 454
455 cxMapDestroy(map); 455 cxMapDestroy(map);
456 CX_TEST_ASSERT(cx_testing_allocator_verify(&talloc)); 456 CX_TEST_ASSERT(cx_testing_allocator_verify(&talloc));
457 } 457 }
458 cx_testing_allocator_destroy(&talloc); 458 cx_testing_allocator_destroy(&talloc);
537 return size; 537 return size;
538 } 538 }
539 539
540 static CX_TEST_SUBROUTINE(verify_map_contents, CxMap *map) { 540 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) 541 // verify that the reference map has same size (i.e. no other keys are mapped)
542 CX_TEST_ASSERT(map->size == test_map_reference_size()); 542 CX_TEST_ASSERT(map->base.size == test_map_reference_size());
543 543
544 // verify key iterator 544 // verify key iterator
545 { 545 {
546 // collect the keys from the map iterator 546 // collect the keys from the map iterator
547 CxIterator keyiter = cxMapIteratorKeys(map); 547 CxIterator keyiter = cxMapIteratorKeys(map);
548 CX_TEST_ASSERT(keyiter.elem_size == sizeof(CxHashKey)); 548 CX_TEST_ASSERT(keyiter.elem_size == sizeof(CxHashKey));
549 CX_TEST_ASSERT(keyiter.elem_count == map->size); 549 CX_TEST_ASSERT(keyiter.elem_count == map->base.size);
550 CxHashKey *keys = calloc(map->size, sizeof(CxHashKey)); 550 CxHashKey *keys = calloc(map->base.size, sizeof(CxHashKey));
551 cx_foreach(CxHashKey*, elem, keyiter) { 551 cx_foreach(CxHashKey*, elem, keyiter) {
552 keys[keyiter.index] = *elem; 552 keys[keyiter.index] = *elem;
553 } 553 }
554 CX_TEST_ASSERT(keyiter.index == map->size); 554 CX_TEST_ASSERT(keyiter.index == map->base.size);
555 // verify that all keys are mapped to values in reference map 555 // verify that all keys are mapped to values in reference map
556 for (size_t i = 0 ; i < map->size ; i++) { 556 for (size_t i = 0 ; i < map->base.size ; i++) {
557 cxmutstr ksz = cx_strdup(cx_strn(keys[i].data, keys[i].len)); 557 cxmutstr ksz = cx_strdup(cx_strn(keys[i].data, keys[i].len));
558 CX_TEST_ASSERT(test_map_reference_get(ksz.ptr) != NULL); 558 CX_TEST_ASSERT(test_map_reference_get(ksz.ptr) != NULL);
559 cx_strfree(&ksz); 559 cx_strfree(&ksz);
560 } 560 }
561 free(keys); 561 free(keys);
564 // verify value iterator 564 // verify value iterator
565 { 565 {
566 // by using that the values in our test data are unique strings 566 // by using that the values in our test data are unique strings
567 // we can re-use a similar approach as above 567 // we can re-use a similar approach as above
568 CxIterator valiter = cxMapIteratorValues(map); 568 CxIterator valiter = cxMapIteratorValues(map);
569 CX_TEST_ASSERT(valiter.elem_size == map->item_size); 569 CX_TEST_ASSERT(valiter.elem_size == map->base.item_size);
570 CX_TEST_ASSERT(valiter.elem_count == map->size); 570 CX_TEST_ASSERT(valiter.elem_count == map->base.size);
571 char const** values = calloc(map->size, sizeof(char const*)); 571 char const** values = calloc(map->base.size, sizeof(char const*));
572 cx_foreach(char const*, elem, valiter) { 572 cx_foreach(char const*, elem, valiter) {
573 values[valiter.index] = elem; 573 values[valiter.index] = elem;
574 } 574 }
575 CX_TEST_ASSERT(valiter.index == map->size); 575 CX_TEST_ASSERT(valiter.index == map->base.size);
576 // verify that all values are present in the reference map 576 // verify that all values are present in the reference map
577 for (size_t i = 0 ; i < map->size ; i++) { 577 for (size_t i = 0 ; i < map->base.size ; i++) {
578 bool found = false; 578 bool found = false;
579 for (size_t j = 0; j < test_map_reference_len ; j++) { 579 for (size_t j = 0; j < test_map_reference_len ; j++) {
580 if (test_map_reference[j].value == values[i]) { 580 if (test_map_reference[j].value == values[i]) {
581 found = true; 581 found = true;
582 break; 582 break;
589 589
590 // verify pair iterator 590 // verify pair iterator
591 { 591 {
592 CxIterator pairiter = cxMapIterator(map); 592 CxIterator pairiter = cxMapIterator(map);
593 CX_TEST_ASSERT(pairiter.elem_size == sizeof(CxMapEntry)); 593 CX_TEST_ASSERT(pairiter.elem_size == sizeof(CxMapEntry));
594 CX_TEST_ASSERT(pairiter.elem_count == map->size); 594 CX_TEST_ASSERT(pairiter.elem_count == map->base.size);
595 struct test_map_kv *pairs = calloc(map->size, sizeof(struct test_map_kv)); 595 struct test_map_kv *pairs = calloc(map->base.size, sizeof(struct test_map_kv));
596 cx_foreach(CxMapEntry*, entry, pairiter) { 596 cx_foreach(CxMapEntry*, entry, pairiter) {
597 CxHashKey const *key = entry->key; 597 CxHashKey const *key = entry->key;
598 pairs[pairiter.index].key = cx_strdup(cx_strn(key->data, key->len)).ptr; 598 pairs[pairiter.index].key = cx_strdup(cx_strn(key->data, key->len)).ptr;
599 pairs[pairiter.index].value = entry->value; 599 pairs[pairiter.index].value = entry->value;
600 } 600 }
601 CX_TEST_ASSERT(pairiter.index == map->size); 601 CX_TEST_ASSERT(pairiter.index == map->base.size);
602 // verify that all pairs are present in the reference map 602 // verify that all pairs are present in the reference map
603 for (size_t i = 0 ; i < map->size ; i++) { 603 for (size_t i = 0 ; i < map->base.size ; i++) {
604 CX_TEST_ASSERT(test_map_reference_get(pairs[i].key) == pairs[i].value); 604 CX_TEST_ASSERT(test_map_reference_get(pairs[i].key) == pairs[i].value);
605 // this was strdup'ed 605 // this was strdup'ed
606 free((void*)pairs[i].key); 606 free((void*)pairs[i].key);
607 } 607 }
608 free(pairs); 608 free(pairs);

mercurial