]> git.proxmox.com Git - mirror_ovs.git/blame - tests/test-hindex.c
datapath: Use RCU lock for dp dump operation.
[mirror_ovs.git] / tests / test-hindex.c
CommitLineData
822b7f52
BP
1/*
2 * Copyright (c) 2008, 2009, 2010, 2013 Nicira, Inc.
3 *
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:
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
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.
15 */
16
17/* A non-exhaustive test for some of the functions and macros declared in
18 * hindex.h. */
19
20#include <config.h>
21#include "hindex.h"
22#include <string.h>
23#include "hash.h"
b028db44 24#include "random.h"
822b7f52
BP
25#include "util.h"
26
27#undef NDEBUG
28#include <assert.h>
29
30/* Sample hindex element. */
31struct element {
32 int value;
33 struct hindex_node node;
34};
35
36typedef size_t hash_func(int value);
37
38static int
39compare_ints(const void *a_, const void *b_)
40{
41 const int *a = a_;
42 const int *b = b_;
43 return *a < *b ? -1 : *a > *b;
44}
45
46/* Verifies that 'hindex' contains exactly the 'n' values in 'values'. */
47static void
48check_hindex(struct hindex *hindex, const int values[], size_t n,
49 hash_func *hash)
50{
51 int *sort_values, *hindex_values;
52 struct element *e;
53 size_t i;
54
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);
58
59 i = 0;
60 HINDEX_FOR_EACH (e, node, hindex) {
61 assert(i < n);
62 hindex_values[i++] = e->value;
63 }
64 assert(i == n);
65
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);
69
70 for (i = 0; i < n; i++) {
71 assert(sort_values[i] == hindex_values[i]);
72 }
73
74 free(hindex_values);
75 free(sort_values);
76
77 /* Check that all the values are there in lookup. */
78 for (i = 0; i < n; i++) {
79 size_t count = 0;
80
81 HINDEX_FOR_EACH_WITH_HASH (e, node, hash(values[i]), hindex) {
82 count += e->value == values[i];
83 }
84 assert(count == 1);
85 }
86
87 /* Check counters. */
88 assert(hindex_is_empty(hindex) == !n);
89 assert(hindex->n_unique <= n);
90}
91
92/* Puts the 'n' values in 'values' into 'elements', and then puts those
93 * elements into 'hindex'. */
94static void
95make_hindex(struct hindex *hindex, struct element elements[],
96 int values[], size_t n, hash_func *hash)
97{
98 size_t i;
99
100 hindex_init(hindex);
101 for (i = 0; i < n; i++) {
102 elements[i].value = i;
103 hindex_insert(hindex, &elements[i].node, hash(elements[i].value));
104 values[i] = i;
105 }
106}
107
108static void
109shuffle(int *p, size_t n)
110{
111 for (; n > 1; n--, p++) {
b028db44 112 int *q = &p[random_range(n)];
822b7f52
BP
113 int tmp = *p;
114 *p = *q;
115 *q = tmp;
116 }
117}
118
119/* Prints the 'n' values in 'values', plus 'name' as a title. */
120static void OVS_UNUSED
121print_ints(const char *name, const int *values, size_t n)
122{
123 size_t i;
124
125 printf("%s:", name);
126 for (i = 0; i < n; i++) {
127 printf(" %d", values[i]);
128 }
129 printf("\n");
130}
131
132/* Prints the values in 'hindex', plus 'name' as a title. */
133static void OVS_UNUSED
134print_hindex(const char *name, struct hindex *hindex)
135{
136 struct element *e;
137
138 printf("%s:", name);
139 HINDEX_FOR_EACH (e, node, hindex) {
140 printf(" %d(%zu)", e->value, e->node.hash & hindex->mask);
141 }
142 printf("\n");
143}
144
145static size_t
146unique_hash(int value)
147{
148 return value;
149}
150
151static size_t
152good_hash(int value)
153{
154 return hash_int(value, 0x1234abcd);
155}
156
157static size_t
158constant_hash(int value OVS_UNUSED)
159{
160 return 123;
161}
162
163static size_t
164mod4_hash(int value)
165{
166 return value % 4;
167}
168
169static size_t
170mod3_hash(int value)
171{
172 return value % 3;
173}
174
175static size_t
176mod2_hash(int value)
177{
178 return value % 2;
179}
180
181/* Tests basic hindex insertion and deletion. */
182static void
183test_hindex_insert_delete(hash_func *hash)
184{
185 enum { N_ELEMS = 100 };
186
187 struct element elements[N_ELEMS];
188 int values[N_ELEMS];
189 struct hindex hindex;
190 size_t i;
191
192 hindex_init(&hindex);
193 for (i = 0; i < N_ELEMS; i++) {
194 elements[i].value = i;
195 hindex_insert(&hindex, &elements[i].node, hash(i));
196 values[i] = i;
197 check_hindex(&hindex, values, i + 1, hash);
198 }
199 shuffle(values, N_ELEMS);
200 for (i = 0; i < N_ELEMS; i++) {
201 hindex_remove(&hindex, &elements[values[i]].node);
202 check_hindex(&hindex, values + (i + 1), N_ELEMS - (i + 1), hash);
203 }
204 hindex_destroy(&hindex);
205}
206
207/* Tests basic hindex_reserve() and hindex_shrink(). */
208static void
209test_hindex_reserve_shrink(hash_func *hash)
210{
211 enum { N_ELEMS = 32 };
212
213 size_t i;
214
215 for (i = 0; i < N_ELEMS; i++) {
216 struct element elements[N_ELEMS];
217 int values[N_ELEMS];
218 struct hindex hindex;
219 size_t j;
220
221 hindex_init(&hindex);
222 hindex_reserve(&hindex, i);
223 for (j = 0; j < N_ELEMS; j++) {
224 elements[j].value = j;
225 hindex_insert(&hindex, &elements[j].node, hash(j));
226 values[j] = j;
227 check_hindex(&hindex, values, j + 1, hash);
228 }
229 shuffle(values, N_ELEMS);
230 for (j = 0; j < N_ELEMS; j++) {
231 hindex_remove(&hindex, &elements[values[j]].node);
232 hindex_shrink(&hindex);
233 check_hindex(&hindex, values + (j + 1), N_ELEMS - (j + 1), hash);
234 }
235 hindex_destroy(&hindex);
236 }
237}
238
239/* Tests that HINDEX_FOR_EACH_SAFE properly allows for deletion of the current
240 * element of a hindex. */
241static void
242test_hindex_for_each_safe(hash_func *hash)
243{
244 enum { MAX_ELEMS = 10 };
245 size_t n;
246 unsigned long int pattern;
247
248 for (n = 0; n <= MAX_ELEMS; n++) {
249 for (pattern = 0; pattern < 1ul << n; pattern++) {
250 struct element elements[MAX_ELEMS];
251 int values[MAX_ELEMS];
252 struct hindex hindex;
253 struct element *e, *next;
254 size_t n_remaining;
255 int i;
256
257 make_hindex(&hindex, elements, values, n, hash);
258
259 i = 0;
260 n_remaining = n;
261 HINDEX_FOR_EACH_SAFE (e, next, node, &hindex) {
262 assert(i < n);
263 if (pattern & (1ul << e->value)) {
264 size_t j;
265 hindex_remove(&hindex, &e->node);
266 for (j = 0; ; j++) {
267 assert(j < n_remaining);
268 if (values[j] == e->value) {
269 values[j] = values[--n_remaining];
270 break;
271 }
272 }
273 }
274 check_hindex(&hindex, values, n_remaining, hash);
275 i++;
276 }
277 assert(i == n);
278
279 for (i = 0; i < n; i++) {
280 if (pattern & (1ul << i)) {
281 n_remaining++;
282 }
283 }
284 assert(n == n_remaining);
285
286 hindex_destroy(&hindex);
287 }
288 }
289}
290
291static void
292run_test(void (*function)(hash_func *))
293{
294 hash_func *hash_funcs[] = {
295 unique_hash,
296 good_hash,
297 constant_hash,
298 mod4_hash,
299 mod3_hash,
300 mod2_hash,
301 };
302 size_t i;
303
304 for (i = 0; i < ARRAY_SIZE(hash_funcs); i++) {
305 function(hash_funcs[i]);
306 printf(".");
307 fflush(stdout);
308 }
309}
310
311int
312main(void)
313{
314 run_test(test_hindex_insert_delete);
315 run_test(test_hindex_for_each_safe);
316 run_test(test_hindex_reserve_shrink);
317 printf("\n");
318 return 0;
319}
320