70 ) { |
70 ) { |
71 // verify key iterator |
71 // verify key iterator |
72 { |
72 { |
73 auto keyiter = cxMapIteratorKeys(map); |
73 auto keyiter = cxMapIteratorKeys(map); |
74 std::unordered_set<std::string> keys; |
74 std::unordered_set<std::string> keys; |
75 cx_foreach(CxDataPtr*, elem, keyiter) { |
75 cx_foreach(CxHashKey*, elem, keyiter) { |
76 // we use that our test keys contain NULL-terminated strings |
76 // we use that our test keys contain NULL-terminated strings |
77 keys.insert(std::string(reinterpret_cast<const char *>(elem->data))); |
77 keys.insert(std::string(elem->data.cstr)); |
78 } |
78 } |
79 EXPECT_EQ(keyiter.index, map->size); |
79 EXPECT_EQ(keyiter.index, map->size); |
80 ASSERT_EQ(keys.size(), map->size); |
80 ASSERT_EQ(keys.size(), map->size); |
81 for (auto &&k: keys) { |
81 for (auto &&k: keys) { |
82 EXPECT_NE(refmap.find(k), refmap.end()); |
82 EXPECT_NE(refmap.find(k), refmap.end()); |
101 // verify pair iterator |
101 // verify pair iterator |
102 { |
102 { |
103 auto pairiter = cxMapIterator(map); |
103 auto pairiter = cxMapIterator(map); |
104 std::unordered_map<std::string, std::string> pairs; |
104 std::unordered_map<std::string, std::string> pairs; |
105 cx_foreach(CxMapEntry*, entry, pairiter) { |
105 cx_foreach(CxMapEntry*, entry, pairiter) { |
106 pairs[std::string((char const *) entry->key->data)] = std::string((char *) entry->value); |
106 pairs[std::string(entry->key->data.cstr)] = std::string((char *) entry->value); |
107 } |
107 } |
108 EXPECT_EQ(pairiter.index, map->size); |
108 EXPECT_EQ(pairiter.index, map->size); |
109 ASSERT_EQ(pairs.size(), refmap.size()); |
109 ASSERT_EQ(pairs.size(), refmap.size()); |
110 for (auto &&p: pairs) { |
110 for (auto &&p: pairs) { |
111 ASSERT_EQ(p.second, refmap.at(p.first)); |
111 ASSERT_EQ(p.second, refmap.at(p.first)); |
142 // verify iterators for empty map |
142 // verify iterators for empty map |
143 verify_map_contents(map, refmap); |
143 verify_map_contents(map, refmap); |
144 |
144 |
145 // execute operations and verify results |
145 // execute operations and verify results |
146 for (auto &&op: ops) { |
146 for (auto &&op: ops) { |
147 CxDataPtr key = cxMapKeyStr(op.key); |
147 CxHashKey key = cx_hash_key_str(op.key); |
|
148 key.hash = 0; // force the hash map to compute the hash |
148 if (op.op == map_operation::put) { |
149 if (op.op == map_operation::put) { |
149 // execute a put operation and verify that the exact value can be read back |
150 // execute a put operation and verify that the exact value can be read back |
150 refmap[std::string(op.key)] = std::string(op.value); |
151 refmap[std::string(op.key)] = std::string(op.value); |
151 int result = cxMapPut(map, key, (void *) op.value); |
152 int result = cxMapPut(map, key, (void *) op.value); |
152 EXPECT_EQ(result, 0); |
153 EXPECT_EQ(result, 0); |
174 |
175 |
175 TEST(CxHashMap, RemoveViaIterator) { |
176 TEST(CxHashMap, RemoveViaIterator) { |
176 CxTestingAllocator allocator; |
177 CxTestingAllocator allocator; |
177 auto map = cxHashMapCreate(&allocator, 4); |
178 auto map = cxHashMapCreate(&allocator, 4); |
178 |
179 |
179 cxMapPut(map, cxMapKeyStr("key 1"), (void *) "val 1"); |
180 cxMapPut(map, cx_hash_key_str("key 1"), (void *) "val 1"); |
180 cxMapPut(map, cxMapKeyStr("key 2"), (void *) "val 2"); |
181 cxMapPut(map, cx_hash_key_str("key 2"), (void *) "val 2"); |
181 cxMapPut(map, cxMapKeyStr("key 3"), (void *) "val 3"); |
182 cxMapPut(map, cx_hash_key_str("key 3"), (void *) "val 3"); |
182 cxMapPut(map, cxMapKeyStr("key 4"), (void *) "val 4"); |
183 cxMapPut(map, cx_hash_key_str("key 4"), (void *) "val 4"); |
183 cxMapPut(map, cxMapKeyStr("key 5"), (void *) "val 5"); |
184 cxMapPut(map, cx_hash_key_str("key 5"), (void *) "val 5"); |
184 cxMapPut(map, cxMapKeyStr("key 6"), (void *) "val 6"); |
185 cxMapPut(map, cx_hash_key_str("key 6"), (void *) "val 6"); |
185 |
186 |
186 auto iter = cxMapIterator(map); |
187 auto iter = cxMapIterator(map); |
187 cx_foreach(CxMapEntry*, entry, iter) { |
188 cx_foreach(CxMapEntry*, entry, iter) { |
188 if (entry->key->data[4] % 2 == 1) iter.remove = true; |
189 if (entry->key->data.cstr[4] % 2 == 1) iter.remove = true; |
189 } |
190 } |
190 EXPECT_EQ(map->size, 3); |
191 EXPECT_EQ(map->size, 3); |
191 EXPECT_EQ(iter.index, map->size); |
192 EXPECT_EQ(iter.index, map->size); |
192 |
193 |
193 EXPECT_EQ(cxMapGet(map, cxMapKeyStr("key 1")), nullptr); |
194 EXPECT_EQ(cxMapGet(map, cx_hash_key_str("key 1")), nullptr); |
194 EXPECT_NE(cxMapGet(map, cxMapKeyStr("key 2")), nullptr); |
195 EXPECT_NE(cxMapGet(map, cx_hash_key_str("key 2")), nullptr); |
195 EXPECT_EQ(cxMapGet(map, cxMapKeyStr("key 3")), nullptr); |
196 EXPECT_EQ(cxMapGet(map, cx_hash_key_str("key 3")), nullptr); |
196 EXPECT_NE(cxMapGet(map, cxMapKeyStr("key 4")), nullptr); |
197 EXPECT_NE(cxMapGet(map, cx_hash_key_str("key 4")), nullptr); |
197 EXPECT_EQ(cxMapGet(map, cxMapKeyStr("key 5")), nullptr); |
198 EXPECT_EQ(cxMapGet(map, cx_hash_key_str("key 5")), nullptr); |
198 EXPECT_NE(cxMapGet(map, cxMapKeyStr("key 6")), nullptr); |
199 EXPECT_NE(cxMapGet(map, cx_hash_key_str("key 6")), nullptr); |
199 |
200 |
200 cxMapDestroy(map); |
201 cxMapDestroy(map); |
201 EXPECT_TRUE(allocator.verify()); |
202 EXPECT_TRUE(allocator.verify()); |
202 } |
203 } |
203 |
204 |
204 TEST(CxHashMap, RehashNotRequired) { |
205 TEST(CxHashMap, RehashNotRequired) { |
205 CxTestingAllocator allocator; |
206 CxTestingAllocator allocator; |
206 auto map = cxHashMapCreate(&allocator, 8); |
207 auto map = cxHashMapCreate(&allocator, 8); |
207 |
208 |
208 cxMapPut(map, cxMapKeyStr("key 1"), (void *) "val 1"); |
209 cxMapPut(map, cx_hash_key_str("key 1"), (void *) "val 1"); |
209 cxMapPut(map, cxMapKeyStr("key 2"), (void *) "val 2"); |
210 cxMapPut(map, cx_hash_key_str("key 2"), (void *) "val 2"); |
210 cxMapPut(map, cxMapKeyStr("key 3"), (void *) "val 3"); |
211 cxMapPut(map, cx_hash_key_str("key 3"), (void *) "val 3"); |
211 cxMapPut(map, cxMapKeyStr("key 4"), (void *) "val 4"); |
212 cxMapPut(map, cx_hash_key_str("key 4"), (void *) "val 4"); |
212 cxMapPut(map, cxMapKeyStr("key 5"), (void *) "val 5"); |
213 cxMapPut(map, cx_hash_key_str("key 5"), (void *) "val 5"); |
213 cxMapPut(map, cxMapKeyStr("key 6"), (void *) "val 6"); |
214 cxMapPut(map, cx_hash_key_str("key 6"), (void *) "val 6"); |
214 |
215 |
215 // 6/8 does not exceed 0.75, therefore the function should not rehash |
216 // 6/8 does not exceed 0.75, therefore the function should not rehash |
216 int result = cxMapRehash(map); |
217 int result = cxMapRehash(map); |
217 EXPECT_EQ(result, 0); |
218 EXPECT_EQ(result, 0); |
218 EXPECT_EQ(reinterpret_cast<struct cx_hash_map_s *>(map)->bucket_count, 8); |
219 EXPECT_EQ(reinterpret_cast<struct cx_hash_map_s *>(map)->bucket_count, 8); |
223 |
224 |
224 TEST(CxHashMap, Rehash) { |
225 TEST(CxHashMap, Rehash) { |
225 CxTestingAllocator allocator; |
226 CxTestingAllocator allocator; |
226 auto map = cxHashMapCreate(&allocator, 8); |
227 auto map = cxHashMapCreate(&allocator, 8); |
227 |
228 |
228 cxMapPut(map, cxMapKeyStr("key 1"), (void *) "val 1"); |
229 cxMapPut(map, cx_hash_key_str("key 1"), (void *) "val 1"); |
229 cxMapPut(map, cxMapKeyStr("key 2"), (void *) "val 2"); |
230 cxMapPut(map, cx_hash_key_str("key 2"), (void *) "val 2"); |
230 cxMapPut(map, cxMapKeyStr("key 3"), (void *) "val 3"); |
231 cxMapPut(map, cx_hash_key_str("key 3"), (void *) "val 3"); |
231 cxMapPut(map, cxMapKeyStr("key 4"), (void *) "val 4"); |
232 cxMapPut(map, cx_hash_key_str("key 4"), (void *) "val 4"); |
232 cxMapPut(map, cxMapKeyStr("key 5"), (void *) "val 5"); |
233 cxMapPut(map, cx_hash_key_str("key 5"), (void *) "val 5"); |
233 cxMapPut(map, cxMapKeyStr("key 6"), (void *) "val 6"); |
234 cxMapPut(map, cx_hash_key_str("key 6"), (void *) "val 6"); |
234 cxMapPut(map, cxMapKeyStr("key 7"), (void *) "val 7"); |
235 cxMapPut(map, cx_hash_key_str("key 7"), (void *) "val 7"); |
235 |
236 |
236 int result = cxMapRehash(map); |
237 int result = cxMapRehash(map); |
237 EXPECT_EQ(result, 0); |
238 EXPECT_EQ(result, 0); |
238 EXPECT_EQ(reinterpret_cast<struct cx_hash_map_s *>(map)->bucket_count, 17); |
239 EXPECT_EQ(reinterpret_cast<struct cx_hash_map_s *>(map)->bucket_count, 17); |
239 EXPECT_EQ(map->size, 7); |
240 EXPECT_EQ(map->size, 7); |
240 |
241 |
241 EXPECT_EQ(strcmp((char *) cxMapGet(map, cxMapKeyStr("key 1")), "val 1"), 0); |
242 EXPECT_EQ(strcmp((char *) cxMapGet(map, cx_hash_key_str("key 1")), "val 1"), 0); |
242 EXPECT_EQ(strcmp((char *) cxMapGet(map, cxMapKeyStr("key 2")), "val 2"), 0); |
243 EXPECT_EQ(strcmp((char *) cxMapGet(map, cx_hash_key_str("key 2")), "val 2"), 0); |
243 EXPECT_EQ(strcmp((char *) cxMapGet(map, cxMapKeyStr("key 3")), "val 3"), 0); |
244 EXPECT_EQ(strcmp((char *) cxMapGet(map, cx_hash_key_str("key 3")), "val 3"), 0); |
244 EXPECT_EQ(strcmp((char *) cxMapGet(map, cxMapKeyStr("key 4")), "val 4"), 0); |
245 EXPECT_EQ(strcmp((char *) cxMapGet(map, cx_hash_key_str("key 4")), "val 4"), 0); |
245 EXPECT_EQ(strcmp((char *) cxMapGet(map, cxMapKeyStr("key 5")), "val 5"), 0); |
246 EXPECT_EQ(strcmp((char *) cxMapGet(map, cx_hash_key_str("key 5")), "val 5"), 0); |
246 EXPECT_EQ(strcmp((char *) cxMapGet(map, cxMapKeyStr("key 6")), "val 6"), 0); |
247 EXPECT_EQ(strcmp((char *) cxMapGet(map, cx_hash_key_str("key 6")), "val 6"), 0); |
247 EXPECT_EQ(strcmp((char *) cxMapGet(map, cxMapKeyStr("key 7")), "val 7"), 0); |
248 EXPECT_EQ(strcmp((char *) cxMapGet(map, cx_hash_key_str("key 7")), "val 7"), 0); |
248 |
249 |
249 cxMapDestroy(map); |
250 cxMapDestroy(map); |
250 EXPECT_TRUE(allocator.verify()); |
251 EXPECT_TRUE(allocator.verify()); |
251 } |
252 } |