]> git.saurik.com Git - apple/libc.git/blob - tests/collections_basic.c
Libc-1439.100.3.tar.gz
[apple/libc.git] / tests / collections_basic.c
1 /*
2 * Copyright (c) 2020 Apple Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24 #include <stdlib.h>
25 #include <os/collections.h>
26 #include <stdio.h>
27 #include <string.h>
28 #include <unistd.h>
29 #include <darwintest.h>
30
31
32 T_DECL(map_basic_64, "Make sure 64 bit map basics work",
33 T_META("owner", "Core Darwin Daemons & Tools"))
34 {
35 os_map_64_t basic_64_map;
36 __block bool got_cafebabe = false;
37 __block bool got_deadbeaf = false;
38 uint64_t value;
39
40 T_LOG("Start");
41
42 // *** BASIC 64 bit key testing ***
43
44 os_map_init(&basic_64_map, NULL);
45
46 T_ASSERT_EQ(os_map_count(&basic_64_map), 0, "Expect map to be empty");
47
48 os_map_insert(&basic_64_map, 0xCAFECAFE, (void *)0xCAFEBABE);
49 os_map_insert(&basic_64_map, 0xDEADDEAD, (void *)0xDEADBEEF);
50
51 T_ASSERT_EQ(os_map_count(&basic_64_map), 2,
52 "Expect map to have 2 entries");
53
54 os_map_foreach(&basic_64_map, ^bool (uint64_t key, void *value){
55 T_LOG("Foreach called for 0x%llx, 0x%llx",
56 (unsigned long long)key, (unsigned long long)value);
57 if (key == 0xCAFECAFE) {
58 T_ASSERT_EQ(value, (void *)0xCAFEBABE,
59 "Callback expect 0xCAFEBABE");
60 got_cafebabe = true;
61 } else if (key == 0xDEADDEAD) {
62 T_ASSERT_EQ(value, (void *)0xDEADBEEF,
63 "Callback expec 0xDEADBEEF");
64 got_deadbeaf = true;
65 } else {
66 T_FAIL("Got unexpected callback 0x%llx, 0x%llx",
67 (unsigned long long)key,
68 (unsigned long long)value);
69 }
70 return true;
71 });
72
73 if (!got_cafebabe || !got_deadbeaf) {
74 T_FAIL("Failed to get callback");
75 }
76
77 value = (uint64_t)os_map_find(&basic_64_map, 0xDEADDEAD);
78 T_ASSERT_EQ(value, (uint64_t)0xDEADBEEF, "Find 1");
79
80 value = (uint64_t)os_map_find(&basic_64_map, 0xCAFECAFE);
81 T_ASSERT_EQ(value, (uint64_t)0xCAFEBABE, "Find 2");
82
83 value = (uint64_t)os_map_find(&basic_64_map, 0xFF00F0F0);
84 T_ASSERT_EQ(value, (uint64_t)0x0, "Find 3");
85
86
87 os_map_delete(&basic_64_map, 0xDEADDEAD);
88
89 T_ASSERT_EQ(os_map_count(&basic_64_map), 1,
90 "Expect map to have 1 entries");
91
92 value = (uint64_t)os_map_find(&basic_64_map, 0xDEADDEAD);
93 T_ASSERT_EQ(value, (uint64_t)0x0, "After-delete Find 1");
94
95 value = (uint64_t)os_map_find(&basic_64_map, 0xCAFECAFE);
96 T_ASSERT_EQ(value, (uint64_t)0xCAFEBABE, "After-delete find 2");
97
98 os_map_delete(&basic_64_map, 0xCAFECAFE);
99
100 T_ASSERT_EQ(os_map_count(&basic_64_map), 0,
101 "Expect map to be empty");
102
103 value = (uint64_t)os_map_find(&basic_64_map, 0xDEADDEAD);
104 T_ASSERT_EQ(value, (uint64_t)0x0, "After-delete Find 3");
105
106 value = (uint64_t)os_map_find(&basic_64_map, 0xCAFECAFE);
107 T_ASSERT_EQ(value, (uint64_t)0x0, "After-delete find 4");
108
109 os_map_destroy(&basic_64_map);
110 }
111
112 T_DECL(map_basic_32, "Make sure 32 bit map basics work",
113 T_META("owner", "Core Darwin Daemons & Tools"))
114 {
115 os_map_32_t basic_32_map;
116 __block bool got_cafebabe = false;
117 __block bool got_deadbeaf = false;
118 uint64_t value;
119
120 T_LOG("Start");
121
122 os_map_init(&basic_32_map, NULL);
123
124 T_ASSERT_EQ(os_map_count(&basic_32_map), 0, "Expect map to be empty");
125
126 os_map_insert(&basic_32_map, 0xCAFECAFE, (void *)0xCAFEBABE);
127 os_map_insert(&basic_32_map, 0xDEADDEAD, (void *)0xDEADBEEF);
128
129 T_ASSERT_EQ(os_map_count(&basic_32_map), 2,
130 "Expect map to have 2 entries");
131
132 os_map_foreach(&basic_32_map, ^bool (uint32_t key, void *value){
133 T_LOG("Foreach called for 0x%llx, 0x%llx",
134 (unsigned long long)key, (unsigned long long)value);
135 if (key == 0xCAFECAFE) {
136 T_ASSERT_EQ(value, (void *)0xCAFEBABE,
137 "Callback expect 0xCAFEBABE");
138 got_cafebabe = true;
139 } else if (key == 0xDEADDEAD) {
140 T_ASSERT_EQ(value, (void *)0xDEADBEEF,
141 "Callback expec 0xDEADBEEF");
142 got_deadbeaf = true;
143 } else {
144 T_FAIL("Got unexpected callback 0x%llx, 0x%llx",
145 (unsigned long long)key,
146 (unsigned long long)value);
147 }
148 return true;
149 });
150
151 if (!got_cafebabe || !got_deadbeaf) {
152 T_FAIL("Failed to get callback");
153 }
154
155 value = (uint64_t)os_map_find(&basic_32_map, 0xDEADDEAD);
156 T_ASSERT_EQ(value, (uint64_t)0xDEADBEEF, "Find 1");
157
158 value = (uint64_t)os_map_find(&basic_32_map, 0xCAFECAFE);
159 T_ASSERT_EQ(value, (uint64_t)0xCAFEBABE, "Find 2");
160
161 value = (uint64_t)os_map_find(&basic_32_map, 0xFF00F0F0);
162 T_ASSERT_EQ(value, (uint64_t)0x0, "Find 3");
163
164 os_map_delete(&basic_32_map, 0xDEADDEAD);
165
166 T_ASSERT_EQ(os_map_count(&basic_32_map), 1,
167 "Expect map to have 1 entries");
168
169 value = (uint64_t)os_map_find(&basic_32_map, 0xDEADDEAD);
170 T_ASSERT_EQ(value, (uint64_t)0x0, "After-delete Find 1");
171
172 value = (uint64_t)os_map_find(&basic_32_map, 0xCAFECAFE);
173 T_ASSERT_EQ(value, (uint64_t)0xCAFEBABE, "After-delete find 2");
174
175 os_map_delete(&basic_32_map, 0xCAFECAFE);
176
177 T_ASSERT_EQ(os_map_count(&basic_32_map), 0, "Expect map to be empty");
178
179 value = (uint64_t)os_map_find(&basic_32_map, 0xDEADDEAD);
180 T_ASSERT_EQ(value, (uint64_t)0x0, "After-delete Find 3");
181
182 value = (uint64_t)os_map_find(&basic_32_map, 0xCAFECAFE);
183 T_ASSERT_EQ(value, (uint64_t)0x0, "After-delete find 4");
184
185 os_map_destroy(&basic_32_map);
186 }
187
188
189 T_DECL(map_basic_string, "Make sure string map basics work",
190 T_META("owner", "Core Darwin Daemons & Tools"))
191 {
192 os_map_str_t basic_string_map;
193 __block bool got_cafebabe = false;
194 __block bool got_deadbeaf = false;
195 uint64_t value;
196
197 T_LOG("Start");
198
199 os_map_init(&basic_string_map, NULL);
200
201 T_ASSERT_EQ(os_map_count(&basic_string_map), 0,
202 "Expect map to be empty");
203
204 os_map_insert(&basic_string_map, "0xCAFECAFE", (void *)0xCAFEBABE);
205 os_map_insert(&basic_string_map, "0xDEADDEAD", (void *)0xDEADBEEF);
206
207 T_ASSERT_EQ(os_map_count(&basic_string_map), 2,
208 "Expect map to have 2 entries");
209
210 os_map_foreach(&basic_string_map, ^bool (const char *key, void *value){
211 T_LOG("Foreach called for 0x%llx, 0x%llx",
212 (unsigned long long)key, (unsigned long long)value);
213 if (strcmp("0xCAFECAFE", key) == 0) {
214 T_ASSERT_EQ(value, (void *)0xCAFEBABE,
215 "Callback expect 0xCAFEBABE");
216 got_cafebabe = true;
217 } else if (strcmp("0xDEADDEAD", key) == 0) {
218 T_ASSERT_EQ(value, (void *)0xDEADBEEF,
219 "Callback expec 0xDEADBEEF");
220 got_deadbeaf = true;
221 } else {
222 T_FAIL("Got unexpected callback 0x%llx, 0x%llx",
223 (unsigned long long)key,
224 (unsigned long long)value);
225 }
226 return true;
227 });
228
229 if (!got_cafebabe || !got_deadbeaf) {
230 T_FAIL("Failed to get callback");
231 }
232
233 value = (uint64_t)os_map_find(&basic_string_map, "0xDEADDEAD");
234 T_ASSERT_EQ(value, (uint64_t)0xDEADBEEF, "Find 1");
235
236 value = (uint64_t)os_map_find(&basic_string_map, "0xCAFECAFE");
237 T_ASSERT_EQ(value, (uint64_t)0xCAFEBABE, "Find 2");
238
239 value = (uint64_t)os_map_find(&basic_string_map, "0xFF00F0F0");
240 T_ASSERT_EQ(value, (uint64_t)0x0, "Find 3");
241
242
243 os_map_delete(&basic_string_map, "0xDEADDEAD");
244
245 T_ASSERT_EQ(os_map_count(&basic_string_map), 1,
246 "Expect map to have 1 entries");
247
248 value = (uint64_t)os_map_find(&basic_string_map, "0xDEADDEAD");
249 T_ASSERT_EQ(value, (uint64_t)0x0, "After-delete Find 1");
250
251 value = (uint64_t)os_map_find(&basic_string_map, "0xCAFECAFE");
252 T_ASSERT_EQ(value, (uint64_t)0xCAFEBABE, "After-delete find 2");
253
254 os_map_delete(&basic_string_map, "0xCAFECAFE");
255
256 T_ASSERT_EQ(os_map_count(&basic_string_map), 0,
257 "Expect map to be empty");
258
259 value = (uint64_t)os_map_find(&basic_string_map, "0xDEADDEAD");
260 T_ASSERT_EQ(value, (uint64_t)0x0, "After-delete Find 3");
261
262 value = (uint64_t)os_map_find(&basic_string_map, "0xCAFECAFE");
263 T_ASSERT_EQ(value, (uint64_t)0x0, "After-delete find 4");
264
265 os_map_destroy(&basic_string_map);
266 }
267
268 T_DECL(map_entry_string, "Make sure string entry fetching works",
269 T_META("owner", "Core Darwin Daemons & Tools"))
270 {
271
272 os_map_str_t basic_string_map;
273
274 T_LOG("Start");
275
276 os_map_init(&basic_string_map, NULL);
277
278 os_map_insert(&basic_string_map, "CAFE", (void *)0xCAFEBABE);
279
280 // Extra steps are taken to make sure the lookup strings aren't compiled
281 // to the same pointer.
282 volatile char lookup_string_1[5];
283 sprintf(lookup_string_1, "CAFE");
284 volatile char lookup_string_2[5];
285 sprintf(lookup_string_2, "CAFE");
286
287 T_ASSERT_EQ(strcmp(&lookup_string_1, "CAFE"), 0,
288 "Expect lookup strings to be CAFE");
289 T_ASSERT_EQ(strcmp(&lookup_string_2, "CAFE"), 0,
290 "Expect lookup strings to be CAFE");
291 T_ASSERT_NE(&lookup_string_1, &lookup_string_2,
292 "Expect lookup strings to be different");
293
294 const char *entry_string_1 = os_map_entry(&basic_string_map,
295 &lookup_string_1);
296
297 T_ASSERT_NOTNULL(entry_string_1, "Expect entry strings to be nonnull");
298 T_ASSERT_EQ(strcmp(entry_string_1, "CAFE"), 0,
299 "Expect entry strings to be CAFE");
300
301 const char *entry_string_2 = os_map_entry(&basic_string_map,
302 &lookup_string_2);
303
304 T_ASSERT_NE(entry_string_2, NULL, "Expect entry strings to be nonnull");
305 T_ASSERT_EQ(strcmp(entry_string_2, "CAFE"), 0,
306 "Expect entry strings to be CAFE");
307
308 T_ASSERT_EQ(entry_string_1, entry_string_2,
309 "Expect entry strings to be literally equal");
310
311 os_map_destroy(&basic_string_map);
312 }
313
314 T_DECL(map_basic_128, "Make sure 64 bit map basics work",
315 T_META("owner", "Core Darwin Daemons & Tools"))
316 {
317 os_map_128_t basic_128_map;
318 __block bool got_cafebabe = false;
319 __block bool got_deadbeaf = false;
320 uint64_t value;
321
322 T_LOG("Start");
323
324 // *** BASIC 64 bit key testing ***
325
326 os_map_init(&basic_128_map, NULL);
327
328 T_ASSERT_EQ(os_map_count(&basic_128_map), 0, "Expect map to be empty");
329
330 os_map_128_key_t key;
331
332 key.x[0] = 0xCAFECAFE;
333 key.x[1] = 0xBABEBABE;
334 os_map_insert(&basic_128_map, key, (void *)0xCAFEBABE);
335
336 key.x[0] = 0xDEADDEAD;
337 key.x[1] = 0xBEEFBEEF;
338 os_map_insert(&basic_128_map, key, (void *)0xDEADBEEF);
339
340 T_ASSERT_EQ(os_map_count(&basic_128_map), 2, "Expect map to have 2 entries");
341
342 os_map_foreach(&basic_128_map, ^bool (os_map_128_key_t key, void *value){
343 T_LOG("Foreach called for 0x%llx:0x%llx, 0x%llx",
344 (unsigned long long)key.x[0], (unsigned long long)key.x[1],
345 (unsigned long long)value);
346 if (key.x[0] == 0xCAFECAFE && key.x[1] == 0xBABEBABE) {
347 T_ASSERT_EQ(value, (void *)0xCAFEBABE,
348 "Callback expect 0xCAFEBABE");
349 got_cafebabe = true;
350 } else if (key.x[0] == 0xDEADDEAD && key.x[1] == 0xBEEFBEEF) {
351 T_ASSERT_EQ(value, (void *)0xDEADBEEF, "Callback expec 0xDEADBEEF");
352 got_deadbeaf = true;
353 } else {
354 T_FAIL("Got unexpected callback 0x%llx:0x%llx, 0x%llx",
355 (unsigned long long)key.x[0], (unsigned long long)key.x[1],
356 (unsigned long long)value);
357 }
358 return true;
359 });
360
361 if (!got_cafebabe || !got_deadbeaf) {
362 T_FAIL("Failed to get callback");
363 }
364
365 key.x[0] = 0xCAFECAFE;
366 key.x[1] = 0xBABEBABE;
367 value = (uint64_t)os_map_find(&basic_128_map, key);
368 T_ASSERT_EQ(value, (uint64_t)0xCAFEBABE, "Find 1");
369
370 key.x[0] = 0xDEADDEAD;
371 key.x[1] = 0xBEEFBEEF;
372 value = (uint64_t)os_map_find(&basic_128_map, key);
373 T_ASSERT_EQ(value, (uint64_t)0xDEADBEEF, "Find 2");
374
375 key.x[0] = 0xFF00F0F0;
376 key.x[1] = 0xFF00F0F0;
377 value = (uint64_t)os_map_find(&basic_128_map, key);
378 T_ASSERT_EQ(value, (uint64_t)0x0, "Find 3");
379
380 key.x[0] = 0xFF00F0F0;
381 key.x[1] = 0xBABEBABE;
382 value = (uint64_t)os_map_find(&basic_128_map, key);
383 T_ASSERT_EQ(value, (uint64_t)0x0, "Find 4");
384
385 key.x[0] = 0xCAFECAFE;
386 key.x[1] = 0xFF00F0F0;
387 value = (uint64_t)os_map_find(&basic_128_map, key);
388 T_ASSERT_EQ(value, (uint64_t)0x0, "Find 5");
389
390 key.x[0] = 0xDEADDEAD;
391 key.x[1] = 0xBEEFBEEF;
392 os_map_delete(&basic_128_map, key);
393
394 T_ASSERT_EQ(os_map_count(&basic_128_map), 1,
395 "Expect map to have 1 entries");
396
397 key.x[0] = 0xDEADDEAD;
398 key.x[1] = 0xBEEFBEEF;
399 value = (uint64_t)os_map_find(&basic_128_map, key);
400 T_ASSERT_EQ(value, (uint64_t)0x0, "After-delete Find 1");
401
402 key.x[0] = 0xCAFECAFE;
403 key.x[1] = 0xBABEBABE;
404 value = (uint64_t)os_map_find(&basic_128_map, key);
405 T_ASSERT_EQ(value, (uint64_t)0xCAFEBABE, "After-delete find 2");
406
407 key.x[0] = 0xCAFECAFE;
408 key.x[1] = 0xBABEBABE;
409 os_map_delete(&basic_128_map, key);
410
411 T_ASSERT_EQ(os_map_count(&basic_128_map), 0, "Expect map to be empty");
412
413 key.x[0] = 0xDEADDEAD;
414 key.x[1] = 0xBEEFBEEF;
415 value = (uint64_t)os_map_find(&basic_128_map, key);
416 T_ASSERT_EQ(value, (uint64_t)0x0, "After-delete Find 3");
417
418 key.x[0] = 0xCAFECAFE;
419 key.x[1] = 0xBABEBABE;
420 value = (uint64_t)os_map_find(&basic_128_map, key);
421 T_ASSERT_EQ(value, (uint64_t)0x0, "After-delete find 4");
422
423 os_map_destroy(&basic_128_map);
424 }