2 * Copyright (C) 2016, Emilio G. Cota <cota@braap.org>
4 * License: GNU GPL, version 2 or later.
5 * See the COPYING file in the top-level directory.
7 #include "qemu/osdep.h"
14 static int32_t arr
[N
* 2];
16 static bool is_equal(const void *ap
, const void *bp
)
18 const int32_t *a
= ap
;
19 const int32_t *b
= bp
;
24 static void insert(int a
, int b
)
28 for (i
= a
; i
< b
; i
++) {
36 inserted
= qht_insert(&ht
, &arr
[i
], hash
, NULL
);
37 g_assert_true(inserted
);
38 inserted
= qht_insert(&ht
, &arr
[i
], hash
, &existing
);
39 g_assert_false(inserted
);
40 g_assert_true(existing
== &arr
[i
]);
44 static void do_rm(int init
, int end
, bool exist
)
48 for (i
= init
; i
< end
; i
++) {
53 g_assert_true(qht_remove(&ht
, &arr
[i
], hash
));
55 g_assert_false(qht_remove(&ht
, &arr
[i
], hash
));
60 static void rm(int init
, int end
)
62 do_rm(init
, end
, true);
65 static void rm_nonexist(int init
, int end
)
67 do_rm(init
, end
, false);
70 static void check(int a
, int b
, bool expected
)
72 struct qht_stats stats
;
76 for (i
= a
; i
< b
; i
++) {
83 /* test both lookup variants; results should be the same */
85 p
= qht_lookup(&ht
, &val
, hash
);
87 p
= qht_lookup_custom(&ht
, &val
, hash
, is_equal
);
89 g_assert_true(!!p
== expected
);
93 qht_statistics_init(&ht
, &stats
);
94 if (stats
.used_head_buckets
) {
95 g_assert_cmpfloat(qdist_avg(&stats
.chain
), >=, 1.0);
97 g_assert_cmpuint(stats
.head_buckets
, >, 0);
98 qht_statistics_destroy(&stats
);
101 static void count_func(void *p
, uint32_t hash
, void *userp
)
103 unsigned int *curr
= userp
;
108 static void check_n(size_t expected
)
110 struct qht_stats stats
;
112 qht_statistics_init(&ht
, &stats
);
113 g_assert_cmpuint(stats
.entries
, ==, expected
);
114 qht_statistics_destroy(&stats
);
117 static void iter_check(unsigned int count
)
119 unsigned int curr
= 0;
121 qht_iter(&ht
, count_func
, &curr
);
122 g_assert_cmpuint(curr
, ==, count
);
125 static void sum_func(void *p
, uint32_t hash
, void *userp
)
127 uint32_t *sum
= userp
;
128 uint32_t a
= *(uint32_t *)p
;
133 static void iter_sum_check(unsigned int expected
)
135 unsigned int sum
= 0;
137 qht_iter(&ht
, sum_func
, &sum
);
138 g_assert_cmpuint(sum
, ==, expected
);
141 static bool rm_mod_func(void *p
, uint32_t hash
, void *userp
)
143 uint32_t a
= *(uint32_t *)p
;
144 unsigned int mod
= *(unsigned int *)userp
;
149 static void iter_rm_mod(unsigned int mod
)
151 qht_iter_remove(&ht
, rm_mod_func
, &mod
);
154 static void iter_rm_mod_check(unsigned int mod
)
156 unsigned int expected
= 0;
159 for (i
= 0; i
< N
; i
++) {
165 iter_sum_check(expected
);
168 static void qht_do_test(unsigned int mode
, size_t init_entries
)
170 /* under KVM we might fetch stats from an uninitialized qht */
173 qht_init(&ht
, is_equal
, 0, mode
);
176 * Test that we successfully delete the last element in a bucket.
177 * This is a hard-to-reach code path when resizing is on, but without
178 * resizing we can easily hit it if init_entries <= 1.
179 * Given that the number of elements per bucket can be 4 or 6 depending on
180 * the host's pointer size, test the removal of the 4th and 6th elements.
192 if (!(mode
& QHT_MODE_AUTO_RESIZE
)) {
193 qht_resize(&ht
, init_entries
* 4 + 4);
201 check(-N
, -1, false);
216 check_n(N
- 190 + 50);
222 rm_nonexist(N
, N
+ 32);
224 iter_rm_mod_check(10);
226 qht_reset_size(&ht
, 0);
233 static void qht_test(unsigned int mode
)
235 qht_do_test(mode
, 0);
236 qht_do_test(mode
, 1);
237 qht_do_test(mode
, 2);
238 qht_do_test(mode
, 8);
239 qht_do_test(mode
, 16);
240 qht_do_test(mode
, 8192);
241 qht_do_test(mode
, 16384);
244 static void test_default(void)
249 static void test_resize(void)
251 qht_test(QHT_MODE_AUTO_RESIZE
);
254 int main(int argc
, char *argv
[])
256 g_test_init(&argc
, &argv
, NULL
);
257 g_test_add_func("/qht/mode/default", test_default
);
258 g_test_add_func("/qht/mode/resize", test_resize
);