2 * Copyright (c) 2020 Apple Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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
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.
21 * @APPLE_LICENSE_HEADER_END@
24 #include <os/collections.h>
28 #include <darwintest.h>
31 #define RANDOM_COUNT 256
34 // Returns a random 32 bit integer
35 static uint32_t random_32() {
36 uint32_t result
= rand();
40 // Returns a random 64 bit integer thats not 0 or ~0
41 static uint64_t random_64() {
42 return (uint64_t)random_32() | ((uint64_t)random_32() << 32);
45 static bool array_contains(uint32_t *array
, int size
, uint32_t entry
) {
46 for (int i
= 0; i
< size
; i
++) {
47 if(array
[i
] == entry
) {
54 // Returns a random 32 bit integer thats not in the array
55 static uint32_t random_32_not_in_array(uint32_t *array
, int size
) {
58 candidate
= random_32();
59 } while (array_contains(array
, size
, candidate
));
63 #define RUN_MAP_RANDOM(MAP, KEY_CONV) \
65 T_LOG("Start run map for " #MAP); \
67 uint32_t keys[RANDOM_COUNT]; \
68 void *vals[RANDOM_COUNT]; \
70 os_map_init(&MAP, NULL); \
72 /* Insert random values for sequential keys to the map */ \
73 for (int i = 0; i < RANDOM_COUNT; i++) { \
74 uint32_t key = random_32_not_in_array(keys, i); \
75 void *val = (void *)random_64(); \
76 T_LOG("Inserting 0x%x, 0x%llx", key, (unsigned long long)val); \
77 os_map_insert(&MAP, KEY_CONV(key), val); \
82 /* Find all the values */ \
83 for (int i = 0; i < RANDOM_COUNT; i++) { \
84 uint32_t key = keys[i]; \
85 void *expected_val = vals[i]; \
86 void *actual_val = os_map_find(&MAP, KEY_CONV(key)); \
87 if (expected_val == actual_val) { \
88 T_PASS("Found 0x%x, 0x%llx", key, \
89 (unsigned long long)expected_val); \
91 T_FAIL("Incorrect find for 0x%x, Expected 0x%llx but got 0x%llx", \
92 key, (unsigned long long)expected_val, \
93 (unsigned long long)actual_val); \
97 /* Find some nonexistant values */ \
98 for (int i = 0; i < RANDOM_COUNT; i++) { \
99 uint32_t key = random_32_not_in_array(keys, RANDOM_COUNT); \
100 void *val = os_map_find(&MAP, KEY_CONV(key)); \
102 T_PASS("Did not find value for nonexistant key 0x%x", \
105 T_FAIL("Found value for nonexistant key 0x%x (0x%llx)", \
106 key, (unsigned long long)val); \
110 /* Remove half of the values */ \
111 for (int i = 0; i < RANDOM_COUNT; i+=2) { \
112 uint32_t key = keys[i]; \
113 os_map_delete(&MAP, KEY_CONV(key)); \
117 /* Find the half that are still there */ \
118 for (int i = 1; i < RANDOM_COUNT; i+=2) { \
119 uint32_t key = keys[i]; \
120 void *expected_val = vals[i]; \
121 void *actual_val = os_map_find(&MAP, KEY_CONV(key)); \
122 if (expected_val == actual_val) { \
123 T_PASS("Found 0x%x, 0x%llx", key, \
124 (unsigned long long)expected_val); \
126 T_FAIL("Incorrect find for 0x%x, Expected 0x%llx but got 0x%llx", \
127 key, (unsigned long long)expected_val, \
128 (unsigned long long)actual_val); \
132 /* Find the half that aren't there */ \
133 for (int i = 0; i < RANDOM_COUNT; i+=2) { \
134 uint32_t key = keys[i]; \
135 void *val = os_map_find(&MAP, KEY_CONV(key)); \
137 T_PASS("Did not find value for nonexistant key 0x%x", \
140 T_FAIL("Found value for nonexistant key 0x%x (0x%llx)", \
141 key, (unsigned long long)val); \
145 os_map_destroy(&MAP); \
148 uint64_t key_conv_32_to_64(uint32_t key
) {
149 return (uint64_t)key
| ((uint64_t)key
<< 32);
152 uint32_t key_conv_32_to_32(uint32_t key
) {
156 const char *key_conv_32_to_string(uint32_t key
) {
157 // TODO: Make this not leak
159 assert(asprintf(&output
, "0x%x", key
) > 0);
160 return (const char *)output
;
163 T_DECL(map_random_64
,
164 "Make sure 64 bit map works for a bunch of random entries",
165 T_META("owner", "Core Darwin Daemons & Tools"))
167 os_map_64_t random_64_map
;
169 RUN_MAP_RANDOM(random_64_map
, key_conv_32_to_64
);
172 T_DECL(map_random_32
,
173 "Make sure 32 bit map works for a bunch of random entries",
174 T_META("owner", "Core Darwin Daemons & Tools"))
176 os_map_32_t random_32_map
;
178 RUN_MAP_RANDOM(random_32_map
, key_conv_32_to_32
);
182 T_DECL(map_random_string
,
183 "Make sure string map works for a bunch of random entries",
184 T_META("owner", "Core Darwin Daemons & Tools"),
185 T_META_CHECK_LEAKS(false))
188 os_map_str_t random_s_map
;
190 RUN_MAP_RANDOM(random_s_map
, key_conv_32_to_string
);