1*1a95404fSEmilio G. Cota /* 2*1a95404fSEmilio G. Cota * Copyright (C) 2016, Emilio G. Cota <cota@braap.org> 3*1a95404fSEmilio G. Cota * 4*1a95404fSEmilio G. Cota * License: GNU GPL, version 2 or later. 5*1a95404fSEmilio G. Cota * See the COPYING file in the top-level directory. 6*1a95404fSEmilio G. Cota */ 7*1a95404fSEmilio G. Cota #include "qemu/osdep.h" 8*1a95404fSEmilio G. Cota #include <glib.h> 9*1a95404fSEmilio G. Cota #include "qemu/qht.h" 10*1a95404fSEmilio G. Cota 11*1a95404fSEmilio G. Cota #define N 5000 12*1a95404fSEmilio G. Cota 13*1a95404fSEmilio G. Cota static struct qht ht; 14*1a95404fSEmilio G. Cota static int32_t arr[N * 2]; 15*1a95404fSEmilio G. Cota 16*1a95404fSEmilio G. Cota static bool is_equal(const void *obj, const void *userp) 17*1a95404fSEmilio G. Cota { 18*1a95404fSEmilio G. Cota const int32_t *a = obj; 19*1a95404fSEmilio G. Cota const int32_t *b = userp; 20*1a95404fSEmilio G. Cota 21*1a95404fSEmilio G. Cota return *a == *b; 22*1a95404fSEmilio G. Cota } 23*1a95404fSEmilio G. Cota 24*1a95404fSEmilio G. Cota static void insert(int a, int b) 25*1a95404fSEmilio G. Cota { 26*1a95404fSEmilio G. Cota int i; 27*1a95404fSEmilio G. Cota 28*1a95404fSEmilio G. Cota for (i = a; i < b; i++) { 29*1a95404fSEmilio G. Cota uint32_t hash; 30*1a95404fSEmilio G. Cota 31*1a95404fSEmilio G. Cota arr[i] = i; 32*1a95404fSEmilio G. Cota hash = i; 33*1a95404fSEmilio G. Cota 34*1a95404fSEmilio G. Cota qht_insert(&ht, &arr[i], hash); 35*1a95404fSEmilio G. Cota } 36*1a95404fSEmilio G. Cota } 37*1a95404fSEmilio G. Cota 38*1a95404fSEmilio G. Cota static void rm(int init, int end) 39*1a95404fSEmilio G. Cota { 40*1a95404fSEmilio G. Cota int i; 41*1a95404fSEmilio G. Cota 42*1a95404fSEmilio G. Cota for (i = init; i < end; i++) { 43*1a95404fSEmilio G. Cota uint32_t hash; 44*1a95404fSEmilio G. Cota 45*1a95404fSEmilio G. Cota hash = arr[i]; 46*1a95404fSEmilio G. Cota g_assert_true(qht_remove(&ht, &arr[i], hash)); 47*1a95404fSEmilio G. Cota } 48*1a95404fSEmilio G. Cota } 49*1a95404fSEmilio G. Cota 50*1a95404fSEmilio G. Cota static void check(int a, int b, bool expected) 51*1a95404fSEmilio G. Cota { 52*1a95404fSEmilio G. Cota struct qht_stats stats; 53*1a95404fSEmilio G. Cota int i; 54*1a95404fSEmilio G. Cota 55*1a95404fSEmilio G. Cota for (i = a; i < b; i++) { 56*1a95404fSEmilio G. Cota void *p; 57*1a95404fSEmilio G. Cota uint32_t hash; 58*1a95404fSEmilio G. Cota int32_t val; 59*1a95404fSEmilio G. Cota 60*1a95404fSEmilio G. Cota val = i; 61*1a95404fSEmilio G. Cota hash = i; 62*1a95404fSEmilio G. Cota p = qht_lookup(&ht, is_equal, &val, hash); 63*1a95404fSEmilio G. Cota g_assert_true(!!p == expected); 64*1a95404fSEmilio G. Cota } 65*1a95404fSEmilio G. Cota qht_statistics_init(&ht, &stats); 66*1a95404fSEmilio G. Cota if (stats.used_head_buckets) { 67*1a95404fSEmilio G. Cota g_assert_cmpfloat(qdist_avg(&stats.chain), >=, 1.0); 68*1a95404fSEmilio G. Cota } 69*1a95404fSEmilio G. Cota g_assert_cmpuint(stats.head_buckets, >, 0); 70*1a95404fSEmilio G. Cota qht_statistics_destroy(&stats); 71*1a95404fSEmilio G. Cota } 72*1a95404fSEmilio G. Cota 73*1a95404fSEmilio G. Cota static void count_func(struct qht *ht, void *p, uint32_t hash, void *userp) 74*1a95404fSEmilio G. Cota { 75*1a95404fSEmilio G. Cota unsigned int *curr = userp; 76*1a95404fSEmilio G. Cota 77*1a95404fSEmilio G. Cota (*curr)++; 78*1a95404fSEmilio G. Cota } 79*1a95404fSEmilio G. Cota 80*1a95404fSEmilio G. Cota static void check_n(size_t expected) 81*1a95404fSEmilio G. Cota { 82*1a95404fSEmilio G. Cota struct qht_stats stats; 83*1a95404fSEmilio G. Cota 84*1a95404fSEmilio G. Cota qht_statistics_init(&ht, &stats); 85*1a95404fSEmilio G. Cota g_assert_cmpuint(stats.entries, ==, expected); 86*1a95404fSEmilio G. Cota qht_statistics_destroy(&stats); 87*1a95404fSEmilio G. Cota } 88*1a95404fSEmilio G. Cota 89*1a95404fSEmilio G. Cota static void iter_check(unsigned int count) 90*1a95404fSEmilio G. Cota { 91*1a95404fSEmilio G. Cota unsigned int curr = 0; 92*1a95404fSEmilio G. Cota 93*1a95404fSEmilio G. Cota qht_iter(&ht, count_func, &curr); 94*1a95404fSEmilio G. Cota g_assert_cmpuint(curr, ==, count); 95*1a95404fSEmilio G. Cota } 96*1a95404fSEmilio G. Cota 97*1a95404fSEmilio G. Cota static void qht_do_test(unsigned int mode, size_t init_entries) 98*1a95404fSEmilio G. Cota { 99*1a95404fSEmilio G. Cota qht_init(&ht, 0, mode); 100*1a95404fSEmilio G. Cota 101*1a95404fSEmilio G. Cota insert(0, N); 102*1a95404fSEmilio G. Cota check(0, N, true); 103*1a95404fSEmilio G. Cota check_n(N); 104*1a95404fSEmilio G. Cota check(-N, -1, false); 105*1a95404fSEmilio G. Cota iter_check(N); 106*1a95404fSEmilio G. Cota 107*1a95404fSEmilio G. Cota rm(101, 102); 108*1a95404fSEmilio G. Cota check_n(N - 1); 109*1a95404fSEmilio G. Cota insert(N, N * 2); 110*1a95404fSEmilio G. Cota check_n(N + N - 1); 111*1a95404fSEmilio G. Cota rm(N, N * 2); 112*1a95404fSEmilio G. Cota check_n(N - 1); 113*1a95404fSEmilio G. Cota insert(101, 102); 114*1a95404fSEmilio G. Cota check_n(N); 115*1a95404fSEmilio G. Cota 116*1a95404fSEmilio G. Cota rm(10, 200); 117*1a95404fSEmilio G. Cota check_n(N - 190); 118*1a95404fSEmilio G. Cota insert(150, 200); 119*1a95404fSEmilio G. Cota check_n(N - 190 + 50); 120*1a95404fSEmilio G. Cota insert(10, 150); 121*1a95404fSEmilio G. Cota check_n(N); 122*1a95404fSEmilio G. Cota 123*1a95404fSEmilio G. Cota rm(1, 2); 124*1a95404fSEmilio G. Cota check_n(N - 1); 125*1a95404fSEmilio G. Cota qht_reset_size(&ht, 0); 126*1a95404fSEmilio G. Cota check_n(0); 127*1a95404fSEmilio G. Cota check(0, N, false); 128*1a95404fSEmilio G. Cota 129*1a95404fSEmilio G. Cota qht_destroy(&ht); 130*1a95404fSEmilio G. Cota } 131*1a95404fSEmilio G. Cota 132*1a95404fSEmilio G. Cota static void qht_test(unsigned int mode) 133*1a95404fSEmilio G. Cota { 134*1a95404fSEmilio G. Cota qht_do_test(mode, 0); 135*1a95404fSEmilio G. Cota qht_do_test(mode, 1); 136*1a95404fSEmilio G. Cota qht_do_test(mode, 2); 137*1a95404fSEmilio G. Cota qht_do_test(mode, 8); 138*1a95404fSEmilio G. Cota qht_do_test(mode, 16); 139*1a95404fSEmilio G. Cota qht_do_test(mode, 8192); 140*1a95404fSEmilio G. Cota qht_do_test(mode, 16384); 141*1a95404fSEmilio G. Cota } 142*1a95404fSEmilio G. Cota 143*1a95404fSEmilio G. Cota static void test_default(void) 144*1a95404fSEmilio G. Cota { 145*1a95404fSEmilio G. Cota qht_test(0); 146*1a95404fSEmilio G. Cota } 147*1a95404fSEmilio G. Cota 148*1a95404fSEmilio G. Cota static void test_resize(void) 149*1a95404fSEmilio G. Cota { 150*1a95404fSEmilio G. Cota qht_test(QHT_MODE_AUTO_RESIZE); 151*1a95404fSEmilio G. Cota } 152*1a95404fSEmilio G. Cota 153*1a95404fSEmilio G. Cota int main(int argc, char *argv[]) 154*1a95404fSEmilio G. Cota { 155*1a95404fSEmilio G. Cota g_test_init(&argc, &argv, NULL); 156*1a95404fSEmilio G. Cota g_test_add_func("/qht/mode/default", test_default); 157*1a95404fSEmilio G. Cota g_test_add_func("/qht/mode/resize", test_resize); 158*1a95404fSEmilio G. Cota return g_test_run(); 159*1a95404fSEmilio G. Cota } 160