26 * POSSIBILITY OF SUCH DAMAGE. |
26 * POSSIBILITY OF SUCH DAMAGE. |
27 */ |
27 */ |
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 "util_allocator.h" |
32 #include "util_allocator.h" |
32 |
33 |
33 #include <gtest/gtest.h> |
34 #include <gtest/gtest.h> |
34 #include <unordered_map> |
35 #include <unordered_map> |
35 #include <unordered_set> |
36 #include <unordered_set> |
112 } |
113 } |
113 } |
114 } |
114 |
115 |
115 TEST(CxHashMap, Create) { |
116 TEST(CxHashMap, Create) { |
116 CxTestingAllocator allocator; |
117 CxTestingAllocator allocator; |
117 auto map = cxHashMapCreate(&allocator, 0); |
118 auto map = cxHashMapCreate(&allocator, 1, 0); |
118 auto hmap = reinterpret_cast<struct cx_hash_map_s *>(map); |
119 auto hmap = reinterpret_cast<struct cx_hash_map_s *>(map); |
119 EXPECT_GT(hmap->bucket_count, 0); |
120 EXPECT_GT(hmap->bucket_count, 0); |
120 cx_for_n(i, hmap->bucket_count) { |
121 cx_for_n(i, hmap->bucket_count) { |
121 EXPECT_EQ(hmap->buckets[i], nullptr); |
122 EXPECT_EQ(hmap->buckets[i], nullptr); |
122 } |
123 } |
|
124 EXPECT_EQ(map->itemsize, 1); |
123 EXPECT_EQ(map->size, 0); |
125 EXPECT_EQ(map->size, 0); |
124 EXPECT_EQ(map->allocator, &allocator); |
126 EXPECT_EQ(map->allocator, &allocator); |
|
127 EXPECT_FALSE(map->store_pointers); |
|
128 cxMapStorePointers(map); |
|
129 EXPECT_TRUE(map->store_pointers); |
|
130 EXPECT_EQ(map->itemsize, sizeof(void *)); |
|
131 cxMapStoreObjects(map); |
|
132 EXPECT_FALSE(map->store_pointers); |
125 |
133 |
126 cxMapDestroy(map); |
134 cxMapDestroy(map); |
127 EXPECT_TRUE(allocator.verify()); |
135 EXPECT_TRUE(allocator.verify()); |
128 } |
136 } |
129 |
137 |
130 TEST(CxHashMap, BasicOperations) { |
138 TEST(CxHashMap, BasicOperations) { |
131 // create the map |
139 // create the map |
132 CxTestingAllocator allocator; |
140 CxTestingAllocator allocator; |
133 auto map = cxHashMapCreate(&allocator, 8); |
141 auto map = cxHashMapCreateForPointers(&allocator, 8); |
134 |
142 |
135 // create a reference map |
143 // create a reference map |
136 std::unordered_map<std::string, std::string> refmap; |
144 std::unordered_map<std::string, std::string> refmap; |
137 |
145 |
138 // generate operations |
146 // generate operations |
172 EXPECT_TRUE(allocator.verify()); |
180 EXPECT_TRUE(allocator.verify()); |
173 } |
181 } |
174 |
182 |
175 TEST(CxHashMap, RemoveViaIterator) { |
183 TEST(CxHashMap, RemoveViaIterator) { |
176 CxTestingAllocator allocator; |
184 CxTestingAllocator allocator; |
177 auto map = cxHashMapCreate(&allocator, 4); |
185 auto map = cxHashMapCreateForPointers(&allocator, 4); |
178 |
186 |
179 cxMapPut(map, cx_hash_key_str("key 1"), (void *) "val 1"); |
187 cxMapPut(map, cx_hash_key_str("key 1"), (void *) "val 1"); |
180 cxMapPut(map, cx_hash_key_str("key 2"), (void *) "val 2"); |
188 cxMapPut(map, cx_hash_key_str("key 2"), (void *) "val 2"); |
181 cxMapPut(map, cx_hash_key_str("key 3"), (void *) "val 3"); |
189 cxMapPut(map, cx_hash_key_str("key 3"), (void *) "val 3"); |
182 cxMapPut(map, cx_hash_key_str("key 4"), (void *) "val 4"); |
190 cxMapPut(map, cx_hash_key_str("key 4"), (void *) "val 4"); |
201 EXPECT_TRUE(allocator.verify()); |
209 EXPECT_TRUE(allocator.verify()); |
202 } |
210 } |
203 |
211 |
204 TEST(CxHashMap, RehashNotRequired) { |
212 TEST(CxHashMap, RehashNotRequired) { |
205 CxTestingAllocator allocator; |
213 CxTestingAllocator allocator; |
206 auto map = cxHashMapCreate(&allocator, 8); |
214 auto map = cxHashMapCreateForPointers(&allocator, 8); |
207 |
215 |
208 cxMapPut(map, cx_hash_key_str("key 1"), (void *) "val 1"); |
216 cxMapPut(map, cx_hash_key_str("key 1"), (void *) "val 1"); |
209 cxMapPut(map, cx_hash_key_str("key 2"), (void *) "val 2"); |
217 cxMapPut(map, cx_hash_key_str("key 2"), (void *) "val 2"); |
210 cxMapPut(map, cx_hash_key_str("key 3"), (void *) "val 3"); |
218 cxMapPut(map, cx_hash_key_str("key 3"), (void *) "val 3"); |
211 cxMapPut(map, cx_hash_key_str("key 4"), (void *) "val 4"); |
219 cxMapPut(map, cx_hash_key_str("key 4"), (void *) "val 4"); |
221 EXPECT_TRUE(allocator.verify()); |
229 EXPECT_TRUE(allocator.verify()); |
222 } |
230 } |
223 |
231 |
224 TEST(CxHashMap, Rehash) { |
232 TEST(CxHashMap, Rehash) { |
225 CxTestingAllocator allocator; |
233 CxTestingAllocator allocator; |
226 auto map = cxHashMapCreate(&allocator, 8); |
234 auto map = cxHashMapCreateForPointers(&allocator, 8); |
227 |
235 |
228 cxMapPut(map, cx_hash_key_str("key 1"), (void *) "val 1"); |
236 cxMapPut(map, cx_hash_key_str("key 1"), (void *) "val 1"); |
229 cxMapPut(map, cx_hash_key_str("key 2"), (void *) "val 2"); |
237 cxMapPut(map, cx_hash_key_str("key 2"), (void *) "val 2"); |
230 cxMapPut(map, cx_hash_key_str("key 3"), (void *) "val 3"); |
238 cxMapPut(map, cx_hash_key_str("key 3"), (void *) "val 3"); |
231 cxMapPut(map, cx_hash_key_str("key 4"), (void *) "val 4"); |
239 cxMapPut(map, cx_hash_key_str("key 4"), (void *) "val 4"); |
250 EXPECT_TRUE(allocator.verify()); |
258 EXPECT_TRUE(allocator.verify()); |
251 } |
259 } |
252 |
260 |
253 TEST(CxHashMap, Clear) { |
261 TEST(CxHashMap, Clear) { |
254 CxTestingAllocator allocator; |
262 CxTestingAllocator allocator; |
255 auto map = cxHashMapCreate(&allocator, 0); |
263 auto map = cxHashMapCreateForPointers(&allocator, 0); |
256 |
264 |
257 cxMapPut(map, cx_hash_key_str("key 1"), (void *) "val 1"); |
265 cxMapPut(map, cx_hash_key_str("key 1"), (void *) "val 1"); |
258 cxMapPut(map, cx_hash_key_str("key 2"), (void *) "val 2"); |
266 cxMapPut(map, cx_hash_key_str("key 2"), (void *) "val 2"); |
259 cxMapPut(map, cx_hash_key_str("key 3"), (void *) "val 3"); |
267 cxMapPut(map, cx_hash_key_str("key 3"), (void *) "val 3"); |
260 |
268 |
268 EXPECT_EQ(cxMapGet(map, cx_hash_key_str("key 3")), nullptr); |
276 EXPECT_EQ(cxMapGet(map, cx_hash_key_str("key 3")), nullptr); |
269 |
277 |
270 cxMapDestroy(map); |
278 cxMapDestroy(map); |
271 EXPECT_TRUE(allocator.verify()); |
279 EXPECT_TRUE(allocator.verify()); |
272 } |
280 } |
|
281 |
|
282 TEST(CxHashMap, StoreUcxStrings) { |
|
283 // create the map |
|
284 CxTestingAllocator allocator; |
|
285 auto map = cxHashMapCreate(&allocator, sizeof(cxstring), 8); |
|
286 |
|
287 // define some strings |
|
288 cxstring s1 = CX_STR("this"); |
|
289 cxstring s2 = CX_STR("is"); |
|
290 cxstring s3 = CX_STR("a"); |
|
291 cxstring s4 = CX_STR("test"); |
|
292 cxstring s5 = CX_STR("setup"); |
|
293 |
|
294 // put them into the map |
|
295 cxMapPut(map, cx_hash_key_str("s1"), &s1); |
|
296 cxMapPut(map, cx_hash_key_str("s2"), &s2); |
|
297 cxMapPut(map, cx_hash_key_str("s3"), &s3); |
|
298 cxMapPut(map, cx_hash_key_str("s4"), &s4); |
|
299 |
|
300 // overwrite a value |
|
301 cxMapPut(map, cx_hash_key_str("s1"), &s5); |
|
302 |
|
303 // look up a string |
|
304 auto s3p = reinterpret_cast<cxstring *>(cxMapGet(map, cx_hash_key_str("s3"))); |
|
305 EXPECT_EQ(s3p->length, s3.length); |
|
306 EXPECT_EQ(s3p->ptr, s3.ptr); |
|
307 EXPECT_NE(s3p, &s3); |
|
308 |
|
309 // remove a string |
|
310 auto r = cxMapRemove(map, cx_hash_key_str("s2")); |
|
311 EXPECT_EQ(r, nullptr); |
|
312 |
|
313 // iterate |
|
314 auto ref = std::vector{s5.ptr, s3.ptr, s4.ptr}; |
|
315 auto iter = cxMapIteratorValues(map); |
|
316 cx_foreach(cxstring*, s, iter) { |
|
317 auto found = std::find(ref.begin(), ref.end(), s->ptr); |
|
318 ASSERT_NE(found, ref.end()); |
|
319 ref.erase(found); |
|
320 } |
|
321 EXPECT_EQ(ref.size(), 0); |
|
322 |
|
323 cxMapDestroy(map); |
|
324 EXPECT_TRUE(allocator.verify()); |
|
325 } |