Serene Runtime 1.0.0
C runtime for the Serene programming language
Loading...
Searching...
No Matches
hashmap_tests.h File Reference
#include <stdio.h>
#include <serene/rt/context.h>
#include <serene/rt/impl/hashmap.h>
#include "acutest.h"
#include "base.h"
Include dependency graph for hashmap_tests.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  hashmap_dummy
 

Macros

#define HMAP_TESTS(X)
 
#define HMAP_TEST_LOG(...)
 

Typedefs

typedef struct hashmap_dummy hashmap_dummy
 

Functions

static void test_hashmap_empty ()
 
void test_hashmap_insert_kv ()
 
static void test_hashmap_make_sure_hash_is_deterministic ()
 
static void test_hashmap_many_insert_and_lookup ()
 
static void test_hashmap_collision_node_lookup ()
 
static void test_hashmap_update ()
 

Macro Definition Documentation

◆ HMAP_TEST_LOG

#define HMAP_TEST_LOG ( ...)
Value:
DBG("HMAP_TEST", __VA_ARGS__)
#define DBG(...)
Definition utils.h:177

Definition at line 39 of file hashmap_tests.h.

◆ HMAP_TESTS

#define HMAP_TESTS ( X)
Value:
X("hashmap::empty", test_hashmap_empty), \
X("hashmap::deterministic_hash_fn", \
X("hashmap::insert_new_kv", test_hashmap_insert_kv), \
X("hashmap::many_insert_and_lookup", \
X("hashmap::collision_lookup", test_hashmap_collision_node_lookup), \
X("hashmap::update", test_hashmap_update)
static void test_hashmap_make_sure_hash_is_deterministic()
static void test_hashmap_empty()
static void test_hashmap_collision_node_lookup()
static void test_hashmap_many_insert_and_lookup()
void test_hashmap_insert_kv()
static void test_hashmap_update()

Definition at line 29 of file hashmap_tests.h.

29#define HMAP_TESTS(X) \
30 X("hashmap::empty", test_hashmap_empty), \
31 X("hashmap::deterministic_hash_fn", \
32 test_hashmap_make_sure_hash_is_deterministic), \
33 X("hashmap::insert_new_kv", test_hashmap_insert_kv), \
34 X("hashmap::many_insert_and_lookup", \
35 test_hashmap_many_insert_and_lookup), \
36 X("hashmap::collision_lookup", test_hashmap_collision_node_lookup), \
37 X("hashmap::update", test_hashmap_update)

Typedef Documentation

◆ hashmap_dummy

typedef struct hashmap_dummy hashmap_dummy

Function Documentation

◆ test_hashmap_collision_node_lookup()

static void test_hashmap_collision_node_lookup ( )
static

Definition at line 179 of file hashmap_tests.h.

179 {
180 MAKE_ENGINE(mm, engine);
181 MAKE_CONTEXT(engine, ctx);
182
183 hmap_t h = hmap_empty(ctx);
184
185 int a = 111;
186 int b = 222;
187
188 hmap_key_t ka = {.data = &a, .len = sizeof(a)};
189 hmap_key_t kb = {.data = &b, .len = sizeof(b)};
190
191 hashmap_dummy va = {.foo = 1, .bar = 10};
192 hashmap_dummy vb = {.foo = 2, .bar = 20};
193
194 // Insert two distinct keys that will almost certainly share the same mocked
195 // hash.
196 hmap_t h1 = hmap_insert(ctx, &h, &ka, &va);
197 hmap_t h2 = hmap_insert(ctx, &h1, &kb, &vb);
198
199 TEST_CHECK(h2.len == 2);
200 TEST_CHECK(h2.root != nullptr);
201 // TEST_CHECK(h2.maybe_error == nullptr);
202
203 void *pa = hmap_lookup(ctx, &h2, &ka, nullptr);
204 void *pb = hmap_lookup(ctx, &h2, &kb, nullptr);
205
206 TEST_CHECK(pa == &va);
207 TEST_CHECK(pb == &vb);
208
209 RELEASE_CONTEXT(ctx);
210 SHUTDOWN_ENGINE(mm, engine);
211}
#define TEST_CHECK(cond)
Definition acutest.h:96
#define RELEASE_CONTEXT(x)
Definition base.h:46
#define SHUTDOWN_ENGINE(mm, engine)
Definition base.h:38
#define MAKE_ENGINE(mm, engine)
Definition base.h:32
#define MAKE_CONTEXT(engine, x)
Definition base.h:42
hmap_t hmap_empty(srn_context_t *ctx)
Create, initialize and return a new hashmap.
Definition hashmap.c:612
void * hmap_lookup(srn_context_t *ctx, const hmap_t *hmap, const hmap_key_t *k, void *default_value)
Lookup the given k in the given hmap and return the value if it's been found.
Definition hashmap.c:622
hmap_t hmap_insert(srn_context_t *ctx, const hmap_t *hmap, hmap_key_t *k, void *v)
Insert the given key k with the value v in the given hash hmap and return the new map.
Definition hashmap.c:618
Note: For key equality we use the memcpy function.
Definition hashmap.h:66
hmap_node_t * root
Definition hashmap.h:98
size_t len
Number of key/value pairs in the map.
Definition hashmap.h:97
Here is the call graph for this function:

◆ test_hashmap_empty()

static void test_hashmap_empty ( )
static

Definition at line 46 of file hashmap_tests.h.

46 {
47 MAKE_ENGINE(mm, engine);
48 MAKE_CONTEXT(engine, ctx);
49
50 auto s = hmap_empty(ctx);
51
52 TEST_CHECK(s.len == 0);
53 TEST_CHECK(s.root == nullptr);
54 // TEST_CHECK(s.maybe_error == nullptr);
55 RELEASE_CONTEXT(ctx);
56 SHUTDOWN_ENGINE(mm, engine);
57}
Here is the call graph for this function:

◆ test_hashmap_insert_kv()

void test_hashmap_insert_kv ( )

Definition at line 59 of file hashmap_tests.h.

59 {
60 MAKE_ENGINE(mm, engine);
61 MAKE_CONTEXT(engine, ctx);
62
63 hashmap_dummy d = {.foo = 10, .bar = 20}; // NOLINT
64 hmap_t h = hmap_empty(ctx);
65
66 int key = 1236;
67 int key_missing = 342;
68
69 hmap_key_t k = {.data = &key, .len = sizeof(key)};
70 hmap_key_t k_missing = {.data = &key_missing, .len = sizeof(key_missing)};
71
72 hmap_t h1 = hmap_insert(ctx, &h, &k, &d);
73
74 void *dptr = hmap_lookup(ctx, &h1, &k, nullptr);
75 TEST_CHECK(dptr != nullptr);
76 TEST_CHECK(dptr == &d);
77
78 int default_v = 999;
79 void *dptr_missing = hmap_lookup(ctx, &h1, &k_missing, &default_v);
80 TEST_CHECK(dptr_missing != nullptr);
81 TEST_CHECK(*(int *)dptr_missing == 999);
82
83 (void)h1;
84
85 RELEASE_CONTEXT(ctx);
86 SHUTDOWN_ENGINE(mm, engine);
87}
Here is the call graph for this function:

◆ test_hashmap_make_sure_hash_is_deterministic()

static void test_hashmap_make_sure_hash_is_deterministic ( )
static

Definition at line 89 of file hashmap_tests.h.

89 {
90 MAKE_ENGINE(mm, engine);
91 MAKE_CONTEXT(engine, ctx);
92
93 int x = 10;
94
95 for (int i = 0; i < 100; i++) {
96 uint32_t h1 = hmap_hash(ctx, &x, sizeof(x));
97 uint32_t h2 = hmap_hash(ctx, &x, sizeof(x));
98 TEST_CHECK(h1 == h2);
99 }
100
101 RELEASE_CONTEXT(ctx);
102 SHUTDOWN_ENGINE(mm, engine);
103}
hmap_hash_t hmap_hash(srn_context_t *ctx, const void *data, size_t len)
This is a simple hack to mock the hash function during tests to force a high collision hashing functi...
Definition hashmap.c:78
Here is the call graph for this function:

◆ test_hashmap_many_insert_and_lookup()

static void test_hashmap_many_insert_and_lookup ( )
static

Definition at line 104 of file hashmap_tests.h.

104 {
105 MAKE_ENGINE(mm, engine);
106 MAKE_CONTEXT(engine, ctx);
107
108 constexpr int N = 4096;
109
110 // IMPORTANT: hmap stores pointers to hmap_key_t, so these must outlive
111 // inserts.
112 int *keys = ALLOCN(ctx, int, N);
113 hmap_key_t *ks = ALLOCN(ctx, hmap_key_t, N);
114 hashmap_dummy *vals = ALLOCN(ctx, hashmap_dummy, N);
115
116 hmap_t h = hmap_empty(ctx);
117
118 for (int i = 0; i < N; ++i) {
119 keys[i] = i;
120 ks[i].data = &keys[i];
121 ks[i].len = sizeof(keys[i]);
122
123 vals[i].foo = i;
124 vals[i].bar = i * 10;
125
126 h = hmap_insert(ctx, &h, &ks[i], &vals[i]);
127 }
128
129 TEST_CHECK(h.len == (size_t)N);
130 TEST_CHECK(h.root != nullptr);
131 // TEST_CHECK(h.maybe_error == nullptr);
132
133 // Lookup everything
134 for (int i = 0; i < N; ++i) {
135 void *p = hmap_lookup(ctx, &h, &ks[i], nullptr);
136 TEST_CHECK(p != nullptr);
137
139 TEST_ASSERT(d != nullptr);
140 TEST_CHECK(d->foo == i);
141 TEST_CHECK(d->bar == i * 10);
142 }
143
144 // update the keys (effectively inserting new keys)
145 for (int i = 0; i < N; ++i) {
146 vals[i].foo = i + i;
147 vals[i].bar = i * 10 + i;
148
149 h = hmap_insert(ctx, &h, &ks[i], &vals[i]);
150 }
151
152 TEST_CHECK(h.len == (size_t)N);
153 TEST_CHECK(h.root != nullptr);
154 // TEST_CHECK(h.maybe_error == nullptr);
155
156 // Lookup everything again!
157 for (int i = 0; i < N; ++i) {
158 void *p = hmap_lookup(ctx, &h, &ks[i], nullptr);
159 TEST_CHECK(p != nullptr);
160
162 TEST_CHECK(d->foo == i + i);
163 TEST_CHECK(d->bar == i * 10 + i);
164 }
165
166 // Missing key returns default value (since nullptr can be a legit value).
167 int missing_key = 0x7fffff;
168 hmap_key_t kmiss = {.data = &missing_key, .len = sizeof(missing_key)};
169
170 int default_v = 999;
171 void *p = hmap_lookup(ctx, &h, &kmiss, &default_v);
172 TEST_CHECK(p == &default_v);
173 TEST_CHECK(*(int *)p == 999);
174
175 RELEASE_CONTEXT(ctx);
176 SHUTDOWN_ENGINE(mm, engine);
177}
#define TEST_ASSERT(cond)
Definition acutest.h:119
#define ALLOCN(ctx, T, N)
Definition context.h:83
void * data
len 0 -> data == nullptr
Definition hashmap.h:68
size_t len
Definition hashmap.h:69
Here is the call graph for this function:

◆ test_hashmap_update()

static void test_hashmap_update ( )
static

Definition at line 213 of file hashmap_tests.h.

213 {
214 MAKE_ENGINE(mm, engine);
215 MAKE_CONTEXT(engine, ctx);
216
217 hmap_t h = hmap_empty(ctx);
218
219 int a = 111;
220 int b = 222;
221
222 hmap_key_t ka = {.data = &a, .len = sizeof(a)};
223 hmap_key_t kb = {.data = &b, .len = sizeof(b)};
224
225 hashmap_dummy va = {.foo = 1, .bar = 10};
226 hashmap_dummy vb = {.foo = 2, .bar = 20};
227 hashmap_dummy vc = {.foo = 200, .bar = 400};
228
229 // Insert two distinct keys that will almost certainly share the same mocked
230 // hash.
231 hmap_t h1 = hmap_insert(ctx, &h, &ka, &va);
232 hmap_t h2 = hmap_insert(ctx, &h1, &kb, &vb);
233 hmap_t h3 = hmap_insert(ctx, &h2, &ka, &vc);
234
235 TEST_CHECK(h3.len == 2);
236 TEST_CHECK(h3.root != nullptr);
237 // TEST_CHECK(h3.maybe_error == nullptr);
238
239 void *pa = hmap_lookup(ctx, &h3, &ka, nullptr);
240 void *pb = hmap_lookup(ctx, &h3, &kb, nullptr);
241
242 TEST_CHECK(pa == &vc);
243 TEST_CHECK(pb == &vb);
244
245 RELEASE_CONTEXT(ctx);
246 SHUTDOWN_ENGINE(mm, engine);
247}
Here is the call graph for this function: