Skip to content

Commit 968e43d

Browse files
committed
utils: add map iteration iterator
1 parent 8ee7a3c commit 968e43d

File tree

4 files changed

+325
-106
lines changed

4 files changed

+325
-106
lines changed

tests/unit/s2n_map_test.c

Lines changed: 223 additions & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -19,159 +19,277 @@
1919

2020
#include "api/s2n.h"
2121
#include "s2n_test.h"
22+
#include "utils/s2n_map_internal.h"
23+
24+
DEFINE_POINTER_CLEANUP_FUNC(struct s2n_map_iterator *, s2n_map_iterator_free);
2225

2326
int main(int argc, char **argv)
2427
{
25-
char keystr[sizeof("ffff")];
26-
char valstr[sizeof("16384")];
27-
struct s2n_map *empty, *map;
28-
struct s2n_blob key = { 0 };
29-
struct s2n_blob val = { 0 };
30-
bool key_found;
28+
/* s2n_map test */
29+
{
30+
char keystr[sizeof("ffff")];
31+
char valstr[sizeof("16384")];
32+
uint32_t size;
33+
struct s2n_map *empty, *map;
34+
struct s2n_blob key = { 0 };
35+
struct s2n_blob val = { 0 };
36+
bool key_found;
37+
38+
BEGIN_TEST();
39+
EXPECT_SUCCESS(s2n_disable_tls13_in_test());
40+
41+
EXPECT_NOT_NULL(empty = s2n_map_new());
42+
EXPECT_OK(s2n_map_size(empty, &size));
43+
EXPECT_EQUAL(size, 0);
44+
45+
/* Try a lookup on an empty map. Expect an error because the map is still mutable. */
46+
EXPECT_SUCCESS(snprintf(keystr, sizeof(keystr), "%04x", 1234));
47+
key.data = (void *) keystr;
48+
key.size = strlen(keystr) + 1;
49+
EXPECT_ERROR(s2n_map_lookup(empty, &key, &val, &key_found));
3150

32-
BEGIN_TEST();
33-
EXPECT_SUCCESS(s2n_disable_tls13_in_test());
51+
EXPECT_SUCCESS(snprintf(valstr, sizeof(valstr), "%05d", 1234));
52+
val.data = (void *) valstr;
53+
val.size = strlen(valstr) + 1;
3454

35-
EXPECT_NOT_NULL(empty = s2n_map_new());
55+
/* Try to add/put key with zero-size data. Expect failures */
56+
key.size = 0;
57+
EXPECT_ERROR(s2n_map_add(empty, &key, &val));
58+
EXPECT_ERROR(s2n_map_put(empty, &key, &val));
59+
key.size = strlen(keystr) + 1;
3660

37-
/* Try a lookup on an empty map. Expect an error because the map is still mutable. */
38-
EXPECT_SUCCESS(snprintf(keystr, sizeof(keystr), "%04x", 1234));
39-
key.data = (void *) keystr;
40-
key.size = strlen(keystr) + 1;
41-
EXPECT_ERROR(s2n_map_lookup(empty, &key, &val, &key_found));
61+
/* Make the empty map complete */
62+
EXPECT_OK(s2n_map_complete(empty));
4263

43-
EXPECT_SUCCESS(snprintf(valstr, sizeof(valstr), "%05d", 1234));
44-
val.data = (void *) valstr;
45-
val.size = strlen(valstr) + 1;
64+
/* Lookup and expect no result */
65+
EXPECT_OK(s2n_map_lookup(empty, &key, &val, &key_found));
66+
EXPECT_EQUAL(key_found, false);
4667

47-
/* Try to add/put key with zero-size data. Expect failures */
48-
key.size = 0;
49-
EXPECT_ERROR(s2n_map_add(empty, &key, &val));
50-
EXPECT_ERROR(s2n_map_put(empty, &key, &val));
51-
key.size = strlen(keystr) + 1;
68+
/* Done with the empty map */
69+
EXPECT_OK(s2n_map_free(empty));
5270

53-
/* Make the empty map complete */
54-
EXPECT_OK(s2n_map_complete(empty));
71+
/* Expect failure since initial map size is zero */
72+
EXPECT_NULL(map = s2n_map_new_with_initial_capacity(0));
5573

56-
/* Lookup and expect no result */
57-
EXPECT_OK(s2n_map_lookup(empty, &key, &val, &key_found));
58-
EXPECT_EQUAL(key_found, false);
74+
/* Create map with the smallest initial size */
75+
EXPECT_NOT_NULL(map = s2n_map_new_with_initial_capacity(1));
5976

60-
/* Done with the empty map */
61-
EXPECT_OK(s2n_map_free(empty));
77+
/* Insert 8k key value pairs of the form hex(i) -> dec(i) */
78+
for (int i = 0; i < 8192; i++) {
79+
EXPECT_SUCCESS(snprintf(keystr, sizeof(keystr), "%04x", i));
80+
EXPECT_SUCCESS(snprintf(valstr, sizeof(valstr), "%05d", i));
6281

63-
/* Expect failure since initial map size is zero */
64-
EXPECT_NULL(map = s2n_map_new_with_initial_capacity(0));
82+
key.data = (void *) keystr;
83+
key.size = strlen(keystr) + 1;
84+
val.data = (void *) valstr;
85+
val.size = strlen(valstr) + 1;
6586

66-
/* Create map with the smallest initial size */
67-
EXPECT_NOT_NULL(map = s2n_map_new_with_initial_capacity(1));
87+
EXPECT_OK(s2n_map_add(map, &key, &val));
88+
}
89+
EXPECT_OK(s2n_map_size(map, &size));
90+
EXPECT_EQUAL(size, 8192);
6891

69-
/* Insert 8k key value pairs of the form hex(i) -> dec(i) */
70-
for (int i = 0; i < 8192; i++) {
71-
EXPECT_SUCCESS(snprintf(keystr, sizeof(keystr), "%04x", i));
72-
EXPECT_SUCCESS(snprintf(valstr, sizeof(valstr), "%05d", i));
92+
/* Try adding some duplicates */
93+
for (int i = 0; i < 10; i++) {
94+
EXPECT_SUCCESS(snprintf(keystr, sizeof(keystr), "%04x", i));
95+
EXPECT_SUCCESS(snprintf(valstr, sizeof(valstr), "%05d", i));
7396

74-
key.data = (void *) keystr;
75-
key.size = strlen(keystr) + 1;
76-
val.data = (void *) valstr;
77-
val.size = strlen(valstr) + 1;
97+
key.data = (void *) keystr;
98+
key.size = strlen(keystr) + 1;
99+
val.data = (void *) valstr;
100+
val.size = strlen(valstr) + 1;
78101

79-
EXPECT_OK(s2n_map_add(map, &key, &val));
80-
}
102+
EXPECT_ERROR(s2n_map_add(map, &key, &val));
103+
}
104+
EXPECT_OK(s2n_map_size(map, &size));
105+
EXPECT_EQUAL(size, 8192);
106+
107+
/* Try replacing some entries */
108+
for (int i = 0; i < 10; i++) {
109+
EXPECT_SUCCESS(snprintf(keystr, sizeof(keystr), "%04x", i));
110+
EXPECT_SUCCESS(snprintf(valstr, sizeof(valstr), "%05d", i + 1));
81111

82-
/* Try adding some duplicates */
83-
for (int i = 0; i < 10; i++) {
84-
EXPECT_SUCCESS(snprintf(keystr, sizeof(keystr), "%04x", i));
85-
EXPECT_SUCCESS(snprintf(valstr, sizeof(valstr), "%05d", i));
112+
key.data = (void *) keystr;
113+
key.size = strlen(keystr) + 1;
114+
val.data = (void *) valstr;
115+
val.size = strlen(valstr) + 1;
116+
117+
EXPECT_OK(s2n_map_put(map, &key, &val));
118+
}
119+
120+
/* Try a lookup before the map is complete: should fail */
121+
EXPECT_SUCCESS(snprintf(keystr, sizeof(keystr), "%04x", 1));
122+
EXPECT_ERROR(s2n_map_lookup(map, &key, &val, &key_found));
123+
124+
/* Make the map complete */
125+
EXPECT_OK(s2n_map_complete(map));
126+
127+
/* Make sure that add-after-complete fails */
128+
EXPECT_SUCCESS(snprintf(keystr, sizeof(keystr), "%04x", 8193));
129+
EXPECT_SUCCESS(snprintf(valstr, sizeof(valstr), "%05d", 8193));
86130

87131
key.data = (void *) keystr;
88132
key.size = strlen(keystr) + 1;
89133
val.data = (void *) valstr;
90134
val.size = strlen(valstr) + 1;
91135

92136
EXPECT_ERROR(s2n_map_add(map, &key, &val));
93-
}
94137

95-
/* Try replacing some entries */
96-
for (int i = 0; i < 10; i++) {
97-
EXPECT_SUCCESS(snprintf(keystr, sizeof(keystr), "%04x", i));
98-
EXPECT_SUCCESS(snprintf(valstr, sizeof(valstr), "%05d", i + 1));
138+
/* Check for equivalence */
139+
for (int i = 0; i < 8192; i++) {
140+
if (i >= 10) {
141+
EXPECT_SUCCESS(snprintf(keystr, sizeof(keystr), "%04x", i));
142+
EXPECT_SUCCESS(snprintf(valstr, sizeof(valstr), "%05d", i));
143+
} else {
144+
/* The first 10 entries were overwritten with i+1 */
145+
EXPECT_SUCCESS(snprintf(keystr, sizeof(keystr), "%04x", i));
146+
EXPECT_SUCCESS(snprintf(valstr, sizeof(valstr), "%05d", i + 1));
147+
}
148+
149+
key.data = (void *) keystr;
150+
key.size = strlen(keystr) + 1;
151+
152+
EXPECT_OK(s2n_map_lookup(map, &key, &val, &key_found));
153+
EXPECT_EQUAL(key_found, true);
154+
155+
EXPECT_SUCCESS(memcmp(val.data, valstr, strlen(valstr) + 1));
156+
}
157+
158+
/* Check for a key that shouldn't be there */
159+
EXPECT_SUCCESS(snprintf(keystr, sizeof(keystr), "%04x", 8193));
160+
key.data = (void *) keystr;
161+
key.size = strlen(keystr) + 1;
162+
EXPECT_OK(s2n_map_lookup(map, &key, &val, &key_found));
163+
EXPECT_EQUAL(key_found, false);
164+
165+
/* Make the map mutable */
166+
EXPECT_OK(s2n_map_unlock(map));
167+
/* Make sure that add-after-unlock succeeds */
168+
EXPECT_SUCCESS(snprintf(keystr, sizeof(keystr), "%04x", 8193));
169+
EXPECT_SUCCESS(snprintf(valstr, sizeof(valstr), "%05d", 8193));
99170

100171
key.data = (void *) keystr;
101172
key.size = strlen(keystr) + 1;
102173
val.data = (void *) valstr;
103174
val.size = strlen(valstr) + 1;
104175

105-
EXPECT_OK(s2n_map_put(map, &key, &val));
106-
}
176+
EXPECT_OK(s2n_map_add(map, &key, &val));
177+
178+
/* Complete the map again */
179+
EXPECT_OK(s2n_map_complete(map));
180+
181+
/* Check the element added after map unlock */
182+
EXPECT_OK(s2n_map_lookup(map, &key, &val, &key_found));
183+
EXPECT_EQUAL(key_found, true);
184+
EXPECT_SUCCESS(memcmp(val.data, valstr, strlen(valstr) + 1));
185+
186+
EXPECT_OK(s2n_map_free(map));
187+
};
188+
189+
/* s2n_map_iterator test */
190+
{
191+
struct s2n_map *map = s2n_map_new();
192+
EXPECT_NOT_NULL(map);
193+
/* fail to initialize an iterator on a mutable map */
194+
{
195+
DEFER_CLEANUP(struct s2n_map_iterator *iter = NULL, s2n_map_iterator_free_pointer);
196+
EXPECT_ERROR(s2n_map_iterator_new(map, &iter));
197+
};
198+
199+
EXPECT_OK(s2n_map_complete(map));
200+
201+
/* has next is false on an empty map, and next returns an error */
202+
{
203+
DEFER_CLEANUP(struct s2n_map_iterator *iter = NULL, s2n_map_iterator_free_pointer);
204+
EXPECT_OK(s2n_map_iterator_new(map, &iter));
205+
206+
bool has_next = false;
207+
EXPECT_OK(s2n_map_iterator_has_next(iter, &has_next));
208+
EXPECT_FALSE(has_next);
209+
210+
struct s2n_blob value = { 0 };
211+
EXPECT_ERROR(s2n_map_iterator_next(iter, &value));
212+
};
213+
214+
EXPECT_OK(s2n_map_unlock(map));
215+
for (uint8_t i = 0; i < 10; i++) {
216+
struct s2n_blob key = { .size = 1, .data = &i };
217+
struct s2n_blob val = { .size = 1, .data = &i };
218+
EXPECT_OK(s2n_map_put(map, &key, &val));
219+
}
220+
EXPECT_OK(s2n_map_complete(map));
107221

108-
/* Try a lookup before the map is complete: should fail */
109-
EXPECT_SUCCESS(snprintf(keystr, sizeof(keystr), "%04x", 1));
110-
EXPECT_ERROR(s2n_map_lookup(map, &key, &val, &key_found));
222+
/* iterator goes over all elements */
223+
{
224+
bool seen[10] = { 0 };
111225

112-
/* Make the map complete */
113-
EXPECT_OK(s2n_map_complete(map));
226+
DEFER_CLEANUP(struct s2n_map_iterator *iter = NULL, s2n_map_iterator_free_pointer);
227+
EXPECT_OK(s2n_map_iterator_new(map, &iter));
114228

115-
/* Make sure that add-after-complete fails */
116-
EXPECT_SUCCESS(snprintf(keystr, sizeof(keystr), "%04x", 8193));
117-
EXPECT_SUCCESS(snprintf(valstr, sizeof(valstr), "%05d", 8193));
229+
bool has_next = false;
230+
struct s2n_blob value = { 0 };
231+
for (size_t i = 0; i < 10; i++) {
232+
EXPECT_OK(s2n_map_iterator_has_next(iter, &has_next));
233+
EXPECT_TRUE(has_next);
118234

119-
key.data = (void *) keystr;
120-
key.size = strlen(keystr) + 1;
121-
val.data = (void *) valstr;
122-
val.size = strlen(valstr) + 1;
235+
EXPECT_OK(s2n_map_iterator_next(iter, &value));
236+
seen[*value.data] = true;
237+
}
123238

124-
EXPECT_ERROR(s2n_map_add(map, &key, &val));
239+
/* all elements have been iterated over */
240+
EXPECT_OK(s2n_map_iterator_has_next(iter, &has_next));
241+
EXPECT_FALSE(has_next);
125242

126-
/* Check for equivalence */
127-
for (int i = 0; i < 8192; i++) {
128-
if (i >= 10) {
129-
EXPECT_SUCCESS(snprintf(keystr, sizeof(keystr), "%04x", i));
130-
EXPECT_SUCCESS(snprintf(valstr, sizeof(valstr), "%05d", i));
131-
} else {
132-
/* The first 10 entries were overwritten with i+1 */
133-
EXPECT_SUCCESS(snprintf(keystr, sizeof(keystr), "%04x", i));
134-
EXPECT_SUCCESS(snprintf(valstr, sizeof(valstr), "%05d", i + 1));
243+
EXPECT_ERROR(s2n_map_iterator_next(iter, &value));
244+
245+
/* all elements were seen */
246+
for (size_t i = 0; i < 10; i++) {
247+
EXPECT_TRUE(seen[i]);
248+
}
135249
}
136250

137-
key.data = (void *) keystr;
138-
key.size = strlen(keystr) + 1;
251+
EXPECT_OK(s2n_map_free(map));
139252

140-
EXPECT_OK(s2n_map_lookup(map, &key, &val, &key_found));
141-
EXPECT_EQUAL(key_found, true);
253+
/* test first and last slots in table */
254+
{
255+
struct s2n_blob blobs[4] = { 0 };
256+
for (uint8_t i = 0; i < 4; i++) {
257+
s2n_alloc(&blobs[i], 1);
258+
*blobs[i].data = i;
259+
}
142260

143-
EXPECT_SUCCESS(memcmp(val.data, valstr, strlen(valstr) + 1));
144-
}
261+
struct s2n_map *map = s2n_map_new();
262+
EXPECT_NOT_NULL(map);
145263

146-
/* Check for a key that shouldn't be there */
147-
EXPECT_SUCCESS(snprintf(keystr, sizeof(keystr), "%04x", 8193));
148-
key.data = (void *) keystr;
149-
key.size = strlen(keystr) + 1;
150-
EXPECT_OK(s2n_map_lookup(map, &key, &val, &key_found));
151-
EXPECT_EQUAL(key_found, false);
264+
/* set values in map to 0 and 1 */
265+
map->table[0].value = blobs[0];
266+
map->table[0].key = blobs[2];
267+
map->table[map->capacity - 1].value = blobs[1];
268+
map->table[map->capacity - 1].key = blobs[3];
152269

153-
/* Make the map mutable */
154-
EXPECT_OK(s2n_map_unlock(map));
155-
/* Make sure that add-after-unlock succeeds */
156-
EXPECT_SUCCESS(snprintf(keystr, sizeof(keystr), "%04x", 8193));
157-
EXPECT_SUCCESS(snprintf(valstr, sizeof(valstr), "%05d", 8193));
270+
map->size = 2;
271+
EXPECT_OK(s2n_map_complete(map));
158272

159-
key.data = (void *) keystr;
160-
key.size = strlen(keystr) + 1;
161-
val.data = (void *) valstr;
162-
val.size = strlen(valstr) + 1;
273+
DEFER_CLEANUP(struct s2n_map_iterator *iter = NULL, s2n_map_iterator_free_pointer);
274+
EXPECT_OK(s2n_map_iterator_new(map, &iter));
275+
bool seen[2] = { 0 };
163276

164-
EXPECT_OK(s2n_map_add(map, &key, &val));
277+
bool has_next = false;
278+
struct s2n_blob value = { 0 };
279+
for (size_t i = 0; i < 2; i++) {
280+
EXPECT_OK(s2n_map_iterator_has_next(iter, &has_next));
281+
EXPECT_TRUE(has_next);
165282

166-
/* Complete the map again */
167-
EXPECT_OK(s2n_map_complete(map));
283+
EXPECT_OK(s2n_map_iterator_next(iter, &value));
284+
seen[*value.data] = true;
285+
}
168286

169-
/* Check the element added after map unlock */
170-
EXPECT_OK(s2n_map_lookup(map, &key, &val, &key_found));
171-
EXPECT_EQUAL(key_found, true);
172-
EXPECT_SUCCESS(memcmp(val.data, valstr, strlen(valstr) + 1));
287+
/* assert that 0 and 1 were both seen */
288+
EXPECT_TRUE(seen[0] && seen[1]);
173289

174-
EXPECT_OK(s2n_map_free(map));
290+
EXPECT_OK(s2n_map_free(map));
291+
};
292+
};
175293

176294
END_TEST();
177295
}

0 commit comments

Comments
 (0)