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); |