2 * Copyright (c) 2008, 2009, 2010, 2013 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(%zu)", 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]);
321 run_test(test_hindex_insert_delete);
322 run_test(test_hindex_for_each_safe);
323 run_test(test_hindex_reserve_shrink);