|
19 | 19 |
|
20 | 20 | #include "api/s2n.h"
|
21 | 21 | #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); |
22 | 25 |
|
23 | 26 | int main(int argc, char **argv)
|
24 | 27 | {
|
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)); |
31 | 50 |
|
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; |
34 | 54 |
|
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; |
36 | 60 |
|
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)); |
42 | 63 |
|
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); |
46 | 67 |
|
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)); |
52 | 70 |
|
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)); |
55 | 73 |
|
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)); |
59 | 76 |
|
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)); |
62 | 81 |
|
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; |
65 | 86 |
|
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); |
68 | 91 |
|
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)); |
73 | 96 |
|
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; |
78 | 101 |
|
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)); |
81 | 111 |
|
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)); |
86 | 130 |
|
87 | 131 | key.data = (void *) keystr;
|
88 | 132 | key.size = strlen(keystr) + 1;
|
89 | 133 | val.data = (void *) valstr;
|
90 | 134 | val.size = strlen(valstr) + 1;
|
91 | 135 |
|
92 | 136 | EXPECT_ERROR(s2n_map_add(map, &key, &val));
|
93 |
| - } |
94 | 137 |
|
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)); |
99 | 170 |
|
100 | 171 | key.data = (void *) keystr;
|
101 | 172 | key.size = strlen(keystr) + 1;
|
102 | 173 | val.data = (void *) valstr;
|
103 | 174 | val.size = strlen(valstr) + 1;
|
104 | 175 |
|
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)); |
107 | 221 |
|
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 }; |
111 | 225 |
|
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)); |
114 | 228 |
|
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); |
118 | 234 |
|
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 | + } |
123 | 238 |
|
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); |
125 | 242 |
|
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 | + } |
135 | 249 | }
|
136 | 250 |
|
137 |
| - key.data = (void *) keystr; |
138 |
| - key.size = strlen(keystr) + 1; |
| 251 | + EXPECT_OK(s2n_map_free(map)); |
139 | 252 |
|
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 | + } |
142 | 260 |
|
143 |
| - EXPECT_SUCCESS(memcmp(val.data, valstr, strlen(valstr) + 1)); |
144 |
| - } |
| 261 | + struct s2n_map *map = s2n_map_new(); |
| 262 | + EXPECT_NOT_NULL(map); |
145 | 263 |
|
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]; |
152 | 269 |
|
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)); |
158 | 272 |
|
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 }; |
163 | 276 |
|
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); |
165 | 282 |
|
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 | + } |
168 | 286 |
|
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]); |
173 | 289 |
|
174 |
| - EXPECT_OK(s2n_map_free(map)); |
| 290 | + EXPECT_OK(s2n_map_free(map)); |
| 291 | + }; |
| 292 | + }; |
175 | 293 |
|
176 | 294 | END_TEST();
|
177 | 295 | }
|
0 commit comments