tests/test_map.cpp

changeset 691
65baf7f45ac8
parent 690
2c2304622981
child 706
8c6edaccaef1
equal deleted inserted replaced
690:2c2304622981 691:65baf7f45ac8
28 28
29 #include "cx/hash_map.h" 29 #include "cx/hash_map.h"
30 #include "cx/utils.h" 30 #include "cx/utils.h"
31 #include "cx/string.h" 31 #include "cx/string.h"
32 #include "util_allocator.h" 32 #include "util_allocator.h"
33 #include "test_map_generics.h"
33 34
34 #include <gtest/gtest.h> 35 #include <gtest/gtest.h>
35 #include <unordered_map> 36 #include <unordered_map>
36 #include <unordered_set> 37 #include <unordered_set>
37 38
72 // verify key iterator 73 // verify key iterator
73 { 74 {
74 auto keyiter = cxMapIteratorKeys(map); 75 auto keyiter = cxMapIteratorKeys(map);
75 std::unordered_set<std::string> keys; 76 std::unordered_set<std::string> keys;
76 cx_foreach(CxHashKey*, elem, keyiter) { 77 cx_foreach(CxHashKey*, elem, keyiter) {
77 keys.insert(std::string(reinterpret_cast<char const*>(elem->data), elem->len)); 78 keys.insert(std::string(reinterpret_cast<char const *>(elem->data), elem->len));
78 } 79 }
79 EXPECT_EQ(keyiter.index, map->size); 80 EXPECT_EQ(keyiter.index, map->size);
80 ASSERT_EQ(keys.size(), map->size); 81 ASSERT_EQ(keys.size(), map->size);
81 for (auto &&k: keys) { 82 for (auto &&k: keys) {
82 EXPECT_NE(refmap.find(k), refmap.end()); 83 EXPECT_NE(refmap.find(k), refmap.end());
101 // verify pair iterator 102 // verify pair iterator
102 { 103 {
103 auto pairiter = cxMapIterator(map); 104 auto pairiter = cxMapIterator(map);
104 std::unordered_map<std::string, std::string> pairs; 105 std::unordered_map<std::string, std::string> pairs;
105 cx_foreach(CxMapEntry*, entry, pairiter) { 106 cx_foreach(CxMapEntry*, entry, pairiter) {
106 pairs[std::string(reinterpret_cast<char const*>(entry->key->data), entry->key->len)] = std::string((char *) entry->value); 107 pairs[std::string(reinterpret_cast<char const *>(entry->key->data), entry->key->len)] = std::string(
108 (char *) entry->value);
107 } 109 }
108 EXPECT_EQ(pairiter.index, map->size); 110 EXPECT_EQ(pairiter.index, map->size);
109 ASSERT_EQ(pairs.size(), refmap.size()); 111 ASSERT_EQ(pairs.size(), refmap.size());
110 for (auto &&p: pairs) { 112 for (auto &&p: pairs) {
111 ASSERT_EQ(p.second, refmap.at(p.first)); 113 ASSERT_EQ(p.second, refmap.at(p.first));
203 205
204 TEST(CxHashMap, RemoveViaIterator) { 206 TEST(CxHashMap, RemoveViaIterator) {
205 CxTestingAllocator allocator; 207 CxTestingAllocator allocator;
206 auto map = cxHashMapCreate(&allocator, CX_STORE_POINTERS, 4); 208 auto map = cxHashMapCreate(&allocator, CX_STORE_POINTERS, 4);
207 209
208 cxMapPut(map, cx_hash_key_str("key 1"), (void *) "val 1"); 210 cxMapPut(map, "key 1", (void *) "val 1");
209 cxMapPut(map, cx_hash_key_str("key 2"), (void *) "val 2"); 211 cxMapPut(map, "key 2", (void *) "val 2");
210 cxMapPut(map, cx_hash_key_str("key 3"), (void *) "val 3"); 212 cxMapPut(map, "key 3", (void *) "val 3");
211 cxMapPut(map, cx_hash_key_str("key 4"), (void *) "val 4"); 213 cxMapPut(map, "key 4", (void *) "val 4");
212 cxMapPut(map, cx_hash_key_str("key 5"), (void *) "val 5"); 214 cxMapPut(map, "key 5", (void *) "val 5");
213 cxMapPut(map, cx_hash_key_str("key 6"), (void *) "val 6"); 215 cxMapPut(map, "key 6", (void *) "val 6");
214 216
215 auto iter = cxMapMutIterator(map); 217 auto iter = cxMapMutIterator(map);
216 cx_foreach(CxMapEntry*, entry, iter) { 218 cx_foreach(CxMapEntry*, entry, iter) {
217 if (reinterpret_cast<char const*>(entry->key->data)[4] % 2 == 1) cxIteratorFlagRemoval(iter); 219 if (reinterpret_cast<char const *>(entry->key->data)[4] % 2 == 1) cxIteratorFlagRemoval(iter);
218 } 220 }
219 EXPECT_EQ(map->size, 3); 221 EXPECT_EQ(map->size, 3);
220 EXPECT_EQ(iter.index, map->size); 222 EXPECT_EQ(iter.index, map->size);
221 223
222 EXPECT_EQ(cxMapGet(map, cx_hash_key_str("key 1")), nullptr); 224 EXPECT_EQ(cxMapGet(map, "key 1"), nullptr);
223 EXPECT_NE(cxMapGet(map, cx_hash_key_str("key 2")), nullptr); 225 EXPECT_NE(cxMapGet(map, "key 2"), nullptr);
224 EXPECT_EQ(cxMapGet(map, cx_hash_key_str("key 3")), nullptr); 226 EXPECT_EQ(cxMapGet(map, "key 3"), nullptr);
225 EXPECT_NE(cxMapGet(map, cx_hash_key_str("key 4")), nullptr); 227 EXPECT_NE(cxMapGet(map, "key 4"), nullptr);
226 EXPECT_EQ(cxMapGet(map, cx_hash_key_str("key 5")), nullptr); 228 EXPECT_EQ(cxMapGet(map, "key 5"), nullptr);
227 EXPECT_NE(cxMapGet(map, cx_hash_key_str("key 6")), nullptr); 229 EXPECT_NE(cxMapGet(map, "key 6"), nullptr);
228 230
229 cxMapDestroy(map); 231 cxMapDestroy(map);
230 EXPECT_TRUE(allocator.verify()); 232 EXPECT_TRUE(allocator.verify());
231 } 233 }
232 234
233 TEST(CxHashMap, RehashNotRequired) { 235 TEST(CxHashMap, RehashNotRequired) {
234 CxTestingAllocator allocator; 236 CxTestingAllocator allocator;
235 auto map = cxHashMapCreate(&allocator, CX_STORE_POINTERS, 8); 237 auto map = cxHashMapCreate(&allocator, CX_STORE_POINTERS, 8);
236 238
237 cxMapPut(map, cx_hash_key_str("key 1"), (void *) "val 1"); 239 cxMapPut(map, "key 1", (void *) "val 1");
238 cxMapPut(map, cx_hash_key_str("key 2"), (void *) "val 2"); 240 cxMapPut(map, "key 2", (void *) "val 2");
239 cxMapPut(map, cx_hash_key_str("key 3"), (void *) "val 3"); 241 cxMapPut(map, "key 3", (void *) "val 3");
240 cxMapPut(map, cx_hash_key_str("key 4"), (void *) "val 4"); 242 cxMapPut(map, "key 4", (void *) "val 4");
241 cxMapPut(map, cx_hash_key_str("key 5"), (void *) "val 5"); 243 cxMapPut(map, "key 5", (void *) "val 5");
242 cxMapPut(map, cx_hash_key_str("key 6"), (void *) "val 6"); 244 cxMapPut(map, "key 6", (void *) "val 6");
243 245
244 // 6/8 does not exceed 0.75, therefore the function should not rehash 246 // 6/8 does not exceed 0.75, therefore the function should not rehash
245 int result = cxMapRehash(map); 247 int result = cxMapRehash(map);
246 EXPECT_EQ(result, 0); 248 EXPECT_EQ(result, 0);
247 EXPECT_EQ(reinterpret_cast<struct cx_hash_map_s *>(map)->bucket_count, 8); 249 EXPECT_EQ(reinterpret_cast<struct cx_hash_map_s *>(map)->bucket_count, 8);
252 254
253 TEST(CxHashMap, Rehash) { 255 TEST(CxHashMap, Rehash) {
254 CxTestingAllocator allocator; 256 CxTestingAllocator allocator;
255 auto map = cxHashMapCreate(&allocator, CX_STORE_POINTERS, 7); 257 auto map = cxHashMapCreate(&allocator, CX_STORE_POINTERS, 7);
256 258
257 cxMapPut(map, cx_hash_key_str("key 1"), (void *) "val 1"); 259 cxMapPut(map, "key 1", (void *) "val 1");
258 cxMapPut(map, cx_hash_key_str("key 2"), (void *) "val 2"); 260 cxMapPut(map, "key 2", (void *) "val 2");
259 cxMapPut(map, cx_hash_key_str("key 3"), (void *) "val 3"); 261 cxMapPut(map, "key 3", (void *) "val 3");
260 cxMapPut(map, cx_hash_key_str("foo 4"), (void *) "val 4"); 262 cxMapPut(map, "foo 4", (void *) "val 4");
261 cxMapPut(map, cx_hash_key_str("key 5"), (void *) "val 5"); 263 cxMapPut(map, "key 5", (void *) "val 5");
262 cxMapPut(map, cx_hash_key_str("key 6"), (void *) "val 6"); 264 cxMapPut(map, "key 6", (void *) "val 6");
263 cxMapPut(map, cx_hash_key_str("bar 7"), (void *) "val 7"); 265 cxMapPut(map, "bar 7", (void *) "val 7");
264 cxMapPut(map, cx_hash_key_str("key 8"), (void *) "val 8"); 266 cxMapPut(map, "key 8", (void *) "val 8");
265 cxMapPut(map, cx_hash_key_str("key 9"), (void *) "val 9"); 267 cxMapPut(map, "key 9", (void *) "val 9");
266 cxMapPut(map, cx_hash_key_str("key 10"), (void *) "val 10"); 268 cxMapPut(map, "key 10", (void *) "val 10");
267 269
268 int result = cxMapRehash(map); 270 int result = cxMapRehash(map);
269 EXPECT_EQ(result, 0); 271 EXPECT_EQ(result, 0);
270 EXPECT_EQ(reinterpret_cast<struct cx_hash_map_s *>(map)->bucket_count, 25); 272 EXPECT_EQ(reinterpret_cast<struct cx_hash_map_s *>(map)->bucket_count, 25);
271 EXPECT_EQ(map->size, 10); 273 EXPECT_EQ(map->size, 10);
272 274
273 EXPECT_EQ(strcmp((char *) cxMapGet(map, cx_hash_key_str("key 1")), "val 1"), 0); 275 EXPECT_STREQ((char *) cxMapGet(map, "key 1"), "val 1");
274 EXPECT_EQ(strcmp((char *) cxMapGet(map, cx_hash_key_str("key 2")), "val 2"), 0); 276 EXPECT_STREQ((char *) cxMapGet(map, "key 2"), "val 2");
275 EXPECT_EQ(strcmp((char *) cxMapGet(map, cx_hash_key_str("key 3")), "val 3"), 0); 277 EXPECT_STREQ((char *) cxMapGet(map, "key 3"), "val 3");
276 EXPECT_EQ(strcmp((char *) cxMapGet(map, cx_hash_key_str("foo 4")), "val 4"), 0); 278 EXPECT_STREQ((char *) cxMapGet(map, "foo 4"), "val 4");
277 EXPECT_EQ(strcmp((char *) cxMapGet(map, cx_hash_key_str("key 5")), "val 5"), 0); 279 EXPECT_STREQ((char *) cxMapGet(map, "key 5"), "val 5");
278 EXPECT_EQ(strcmp((char *) cxMapGet(map, cx_hash_key_str("key 6")), "val 6"), 0); 280 EXPECT_STREQ((char *) cxMapGet(map, "key 6"), "val 6");
279 EXPECT_EQ(strcmp((char *) cxMapGet(map, cx_hash_key_str("bar 7")), "val 7"), 0); 281 EXPECT_STREQ((char *) cxMapGet(map, "bar 7"), "val 7");
280 EXPECT_EQ(strcmp((char *) cxMapGet(map, cx_hash_key_str("key 8")), "val 8"), 0); 282 EXPECT_STREQ((char *) cxMapGet(map, "key 8"), "val 8");
281 EXPECT_EQ(strcmp((char *) cxMapGet(map, cx_hash_key_str("key 9")), "val 9"), 0); 283 EXPECT_STREQ((char *) cxMapGet(map, "key 9"), "val 9");
282 EXPECT_EQ(strcmp((char *) cxMapGet(map, cx_hash_key_str("key 10")), "val 10"), 0); 284 EXPECT_STREQ((char *) cxMapGet(map, "key 10"), "val 10");
283 285
284 cxMapDestroy(map); 286 cxMapDestroy(map);
285 EXPECT_TRUE(allocator.verify()); 287 EXPECT_TRUE(allocator.verify());
286 } 288 }
287 289
288 TEST(CxHashMap, Clear) { 290 TEST(CxHashMap, Clear) {
289 CxTestingAllocator allocator; 291 CxTestingAllocator allocator;
290 auto map = cxHashMapCreate(&allocator, CX_STORE_POINTERS, 0); 292 auto map = cxHashMapCreate(&allocator, CX_STORE_POINTERS, 0);
291 293
292 cxMapPut(map, cx_hash_key_str("key 1"), (void *) "val 1"); 294 cxMapPut(map, "key 1", (void *) "val 1");
293 cxMapPut(map, cx_hash_key_str("key 2"), (void *) "val 2"); 295 cxMapPut(map, "key 2", (void *) "val 2");
294 cxMapPut(map, cx_hash_key_str("key 3"), (void *) "val 3"); 296 cxMapPut(map, "key 3", (void *) "val 3");
295 297
296 EXPECT_EQ(map->size, 3); 298 EXPECT_EQ(map->size, 3);
297 299
298 cxMapClear(map); 300 cxMapClear(map);
299 301
300 EXPECT_EQ(map->size, 0); 302 EXPECT_EQ(map->size, 0);
301 EXPECT_EQ(cxMapGet(map, cx_hash_key_str("key 1")), nullptr); 303 EXPECT_EQ(cxMapGet(map, "key 1"), nullptr);
302 EXPECT_EQ(cxMapGet(map, cx_hash_key_str("key 2")), nullptr); 304 EXPECT_EQ(cxMapGet(map, "key 2"), nullptr);
303 EXPECT_EQ(cxMapGet(map, cx_hash_key_str("key 3")), nullptr); 305 EXPECT_EQ(cxMapGet(map, "key 3"), nullptr);
304 306
305 cxMapDestroy(map); 307 cxMapDestroy(map);
306 EXPECT_TRUE(allocator.verify()); 308 EXPECT_TRUE(allocator.verify());
307 } 309 }
308 310
317 auto s3 = CX_STR("a"); 319 auto s3 = CX_STR("a");
318 auto s4 = CX_STR("test"); 320 auto s4 = CX_STR("test");
319 auto s5 = CX_STR("setup"); 321 auto s5 = CX_STR("setup");
320 322
321 // put them into the map 323 // put them into the map
322 cxMapPut(map, cx_hash_key_str("s1"), &s1); 324 cxMapPut(map, "s1", &s1);
323 cxMapPut(map, cx_hash_key_str("s2"), &s2); 325 cxMapPut(map, "s2", &s2);
324 cxMapPut(map, cx_hash_key_str("s3"), &s3); 326 cxMapPut(map, "s3", &s3);
325 cxMapPut(map, cx_hash_key_str("s4"), &s4); 327 cxMapPut(map, "s4", &s4);
326 328
327 // overwrite a value 329 // overwrite a value
328 cxMapPut(map, cx_hash_key_str("s1"), &s5); 330 cxMapPut(map, "s1", &s5);
329 331
330 // look up a string 332 // look up a string
331 auto s3p = reinterpret_cast<cxstring *>(cxMapGet(map, cx_hash_key_str("s3"))); 333 auto s3p = reinterpret_cast<cxstring *>(cxMapGet(map, "s3"));
332 EXPECT_EQ(s3p->length, s3.length); 334 EXPECT_EQ(s3p->length, s3.length);
333 EXPECT_EQ(s3p->ptr, s3.ptr); 335 EXPECT_EQ(s3p->ptr, s3.ptr);
334 EXPECT_NE(s3p, &s3); 336 EXPECT_NE(s3p, &s3);
335 337
336 // remove a string 338 // remove a string
337 cxMapRemove(map, cx_hash_key_str("s2")); 339 cxMapRemove(map, "s2");
338 340
339 // iterate 341 // iterate
340 auto ref = std::vector{s5.ptr, s3.ptr, s4.ptr}; 342 auto ref = std::vector{s5.ptr, s3.ptr, s4.ptr};
341 auto iter = cxMapIteratorValues(map); 343 auto iter = cxMapIteratorValues(map);
342 cx_foreach(cxstring*, s, iter) { 344 cx_foreach(cxstring*, s, iter) {
403 cxMapPut(map, k5, (void *) v5); 405 cxMapPut(map, k5, (void *) v5);
404 406
405 { 407 {
406 auto iter = cxMapMutIteratorKeys(map); 408 auto iter = cxMapMutIteratorKeys(map);
407 cx_foreach(CxHashKey*, key, iter) { 409 cx_foreach(CxHashKey*, key, iter) {
408 if (reinterpret_cast<char const*>(key->data)[4] == '1') cxIteratorFlagRemoval(iter); 410 if (reinterpret_cast<char const *>(key->data)[4] == '1') cxIteratorFlagRemoval(iter);
409 } 411 }
410 } 412 }
411 { 413 {
412 auto iter = cxMapMutIteratorValues(map); 414 auto iter = cxMapMutIteratorValues(map);
413 cx_foreach(char*, v, iter) { 415 cx_foreach(char*, v, iter) {
445 auto map = cxHashMapCreate(&allocator, CX_STORE_POINTERS, 0); 447 auto map = cxHashMapCreate(&allocator, CX_STORE_POINTERS, 0);
446 map->advanced_destructor = test_advanced_destructor; 448 map->advanced_destructor = test_advanced_destructor;
447 verify_any_destructor(map); 449 verify_any_destructor(map);
448 EXPECT_TRUE(allocator.verify()); 450 EXPECT_TRUE(allocator.verify());
449 } 451 }
452
453 TEST(CxHashMap, Generics) {
454 CxTestingAllocator allocator;
455 auto map = test_map_generics_step_1(&allocator);
456
457 EXPECT_EQ(map->size, 3);
458 EXPECT_STREQ((char *) cxMapGet(map, "test"), "test");
459 EXPECT_STREQ((char *) cxMapGet(map, "foo"), "bar");
460 EXPECT_STREQ((char *) cxMapGet(map, "hallo"), "welt");
461
462 test_map_generics_step_2(map);
463
464 EXPECT_EQ(map->size, 2);
465 EXPECT_STREQ((char *) cxMapGet(map, "key"), "value");
466 EXPECT_STREQ((char *) cxMapGet(map, "foo"), "bar");
467
468 test_map_generics_step_3(map);
469
470 EXPECT_EQ(map->size, 0);
471
472 cxMapDestroy(map);
473 EXPECT_TRUE(allocator.verify());
474 }

mercurial