2 * Copyright (c) 2008, 2009, 2010, 2013, 2014 Nicira, Inc.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at:
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 /* A non-exhaustive test for some of the functions and macros declared in
30 /* Sample hindex element. */
33 struct hindex_node node
;
36 typedef size_t hash_func(int value
);
39 compare_ints(const void *a_
, const void *b_
)
43 return *a
< *b
? -1 : *a
> *b
;
46 /* Verifies that 'hindex' contains exactly the 'n' values in 'values'. */
48 check_hindex(struct hindex
*hindex
, const int values
[], size_t n
,
51 int *sort_values
, *hindex_values
;
55 /* Check that all the values are there in iteration. */
56 sort_values
= xmalloc(sizeof *sort_values
* n
);
57 hindex_values
= xmalloc(sizeof *sort_values
* n
);
60 HINDEX_FOR_EACH (e
, node
, hindex
) {
62 hindex_values
[i
++] = e
->value
;
66 memcpy(sort_values
, values
, sizeof *sort_values
* n
);
67 qsort(sort_values
, n
, sizeof *sort_values
, compare_ints
);
68 qsort(hindex_values
, n
, sizeof *hindex_values
, compare_ints
);
70 for (i
= 0; i
< n
; i
++) {
71 assert(sort_values
[i
] == hindex_values
[i
]);
77 /* Check that all the values are there in lookup. */
78 for (i
= 0; i
< n
; i
++) {
81 HINDEX_FOR_EACH_WITH_HASH (e
, node
, hash(values
[i
]), hindex
) {
82 count
+= e
->value
== values
[i
];
88 assert(hindex_is_empty(hindex
) == !n
);
89 assert(hindex
->n_unique
<= n
);
92 /* Puts the 'n' values in 'values' into 'elements', and then puts those
93 * elements into 'hindex'. */
95 make_hindex(struct hindex
*hindex
, struct element elements
[],
96 int values
[], size_t n
, hash_func
*hash
)
101 for (i
= 0; i
< n
; i
++) {
102 elements
[i
].value
= i
;
103 hindex_insert(hindex
, &elements
[i
].node
, hash(elements
[i
].value
));
109 shuffle(int *p
, size_t n
)
111 for (; n
> 1; n
--, p
++) {
112 int *q
= &p
[random_range(n
)];
119 /* Prints the 'n' values in 'values', plus 'name' as a title. */
120 static void OVS_UNUSED
121 print_ints(const char *name
, const int *values
, size_t n
)
126 for (i
= 0; i
< n
; i
++) {
127 printf(" %d", values
[i
]);
132 /* Prints the values in 'hindex', plus 'name' as a title. */
133 static void OVS_UNUSED
134 print_hindex(const char *name
, struct hindex
*hindex
)
139 HINDEX_FOR_EACH (e
, node
, hindex
) {
140 printf(" %d(%"PRIuSIZE
")", e
->value
, e
->node
.hash
& hindex
->mask
);
146 unique_hash(int value
)
154 return hash_int(value
, 0x1234abcd);
158 constant_hash(int value OVS_UNUSED
)
182 multipart_hash(int value
)
184 return (mod4_hash(value
) << 16) | (constant_hash(value
) & 0xFFFF);
187 /* Tests basic hindex insertion and deletion. */
189 test_hindex_insert_delete(hash_func
*hash
)
191 enum { N_ELEMS
= 100 };
193 struct element elements
[N_ELEMS
];
195 struct hindex hindex
;
198 hindex_init(&hindex
);
199 for (i
= 0; i
< N_ELEMS
; i
++) {
200 elements
[i
].value
= i
;
201 hindex_insert(&hindex
, &elements
[i
].node
, hash(i
));
203 check_hindex(&hindex
, values
, i
+ 1, hash
);
205 shuffle(values
, N_ELEMS
);
206 for (i
= 0; i
< N_ELEMS
; i
++) {
207 hindex_remove(&hindex
, &elements
[values
[i
]].node
);
208 check_hindex(&hindex
, values
+ (i
+ 1), N_ELEMS
- (i
+ 1), hash
);
210 hindex_destroy(&hindex
);
213 /* Tests basic hindex_reserve() and hindex_shrink(). */
215 test_hindex_reserve_shrink(hash_func
*hash
)
217 enum { N_ELEMS
= 32 };
221 for (i
= 0; i
< N_ELEMS
; i
++) {
222 struct element elements
[N_ELEMS
];
224 struct hindex hindex
;
227 hindex_init(&hindex
);
228 hindex_reserve(&hindex
, i
);
229 for (j
= 0; j
< N_ELEMS
; j
++) {
230 elements
[j
].value
= j
;
231 hindex_insert(&hindex
, &elements
[j
].node
, hash(j
));
233 check_hindex(&hindex
, values
, j
+ 1, hash
);
235 shuffle(values
, N_ELEMS
);
236 for (j
= 0; j
< N_ELEMS
; j
++) {
237 hindex_remove(&hindex
, &elements
[values
[j
]].node
);
238 hindex_shrink(&hindex
);
239 check_hindex(&hindex
, values
+ (j
+ 1), N_ELEMS
- (j
+ 1), hash
);
241 hindex_destroy(&hindex
);
245 /* Tests that HINDEX_FOR_EACH_SAFE properly allows for deletion of the current
246 * element of a hindex. */
248 test_hindex_for_each_safe(hash_func
*hash
)
250 enum { MAX_ELEMS
= 10 };
252 unsigned long int pattern
;
254 for (n
= 0; n
<= MAX_ELEMS
; n
++) {
255 for (pattern
= 0; pattern
< 1ul << n
; pattern
++) {
256 struct element elements
[MAX_ELEMS
];
257 int values
[MAX_ELEMS
];
258 struct hindex hindex
;
259 struct element
*e
, *next
;
263 make_hindex(&hindex
, elements
, values
, n
, hash
);
267 HINDEX_FOR_EACH_SAFE (e
, next
, node
, &hindex
) {
269 if (pattern
& (1ul << e
->value
)) {
271 hindex_remove(&hindex
, &e
->node
);
273 assert(j
< n_remaining
);
274 if (values
[j
] == e
->value
) {
275 values
[j
] = values
[--n_remaining
];
280 check_hindex(&hindex
, values
, n_remaining
, hash
);
285 for (i
= 0; i
< n
; i
++) {
286 if (pattern
& (1ul << i
)) {
290 assert(n
== n_remaining
);
292 hindex_destroy(&hindex
);
298 run_test(void (*function
)(hash_func
*))
300 hash_func
*hash_funcs
[] = {
311 for (i
= 0; i
< ARRAY_SIZE(hash_funcs
); i
++) {
312 function(hash_funcs
[i
]);
319 test_hindex_main(int argc OVS_UNUSED
, char *argv
[] OVS_UNUSED
)
321 run_test(test_hindex_insert_delete
);
322 run_test(test_hindex_for_each_safe
);
323 run_test(test_hindex_reserve_shrink
);
327 OVSTEST_REGISTER("test-hindex", test_hindex_main
);