Annotation of embedaddon/bird2/lib/hash_test.c, revision 1.1
1.1 ! misho 1: /*
! 2: * BIRD Library -- Hash Tests
! 3: *
! 4: * (c) 2015 CZ.NIC z.s.p.o.
! 5: *
! 6: * Can be freely distributed and used under the terms of the GNU GPL.
! 7: */
! 8:
! 9: #undef LOCAL_DEBUG
! 10:
! 11: #include "test/birdtest.h"
! 12:
! 13: #include "lib/hash.h"
! 14:
! 15: struct test_node {
! 16: struct test_node *next; /* Hash chain */
! 17: u32 key;
! 18: };
! 19:
! 20: #define TEST_KEY(n) n->key
! 21: #define TEST_NEXT(n) n->next
! 22: #define TEST_EQ(n1,n2) n1 == n2
! 23: #define TEST_FN(n) (n) ^ u32_hash((n))
! 24: #define TEST_ORDER 13
! 25: #define TEST_PARAMS /TEST_ORDER, *2, 2, 2, TEST_ORDER, 20
! 26: #define TEST_REHASH test_rehash
! 27:
! 28: HASH_DEFINE_REHASH_FN(TEST, struct test_node);
! 29:
! 30: HASH(struct test_node) hash;
! 31: struct pool *my_pool;
! 32:
! 33: #define MAX_NUM (1 << TEST_ORDER)
! 34:
! 35: struct test_node nodes[MAX_NUM];
! 36:
! 37: static void
! 38: print_rate_of_fulfilment(void)
! 39: {
! 40: int i;
! 41: int num_stacked_items = 0;
! 42:
! 43: for (i = 0; i < MAX_NUM; i++)
! 44: if (!hash.data[i])
! 45: num_stacked_items++;
! 46:
! 47: double percent_stacked_items = ((double)num_stacked_items/(double)MAX_NUM)*100.;
! 48: bt_debug("%d (%.2f %%) chained of %d hashes \n", num_stacked_items, percent_stacked_items, MAX_NUM);
! 49: }
! 50:
! 51: #ifdef LOCAL_DEBUG
! 52: static void
! 53: dump_nodes(void)
! 54: {
! 55: int i;
! 56: for (i = 0; i < MAX_NUM; i++)
! 57: bt_debug("nodes[%3d] is at address %14p has .key %3d, .next %14p \n", i, &nodes[i], nodes[i].key, nodes[i].next);
! 58: }
! 59: #endif
! 60:
! 61: static void
! 62: init_hash_(uint order)
! 63: {
! 64: resource_init();
! 65: my_pool = rp_new(&root_pool, "Test pool");
! 66:
! 67: HASH_INIT(hash, my_pool, order);
! 68:
! 69: int i;
! 70: for (i = 0; i < MAX_NUM; i++)
! 71: {
! 72: nodes[i].key = i;
! 73: nodes[i].next = NULL;
! 74: }
! 75:
! 76: bt_debug("MAX_NUM %d \n", MAX_NUM);
! 77: }
! 78:
! 79: static void
! 80: init_hash(void)
! 81: {
! 82: init_hash_(TEST_ORDER);
! 83: }
! 84:
! 85: static void
! 86: validate_filled_hash(void)
! 87: {
! 88: int i;
! 89: struct test_node *node;
! 90: for (i = 0; i < MAX_NUM; i++)
! 91: {
! 92: node = HASH_FIND(hash, TEST, nodes[i].key);
! 93: bt_assert_msg(node->key == nodes[i].key, "Hash should be filled, to find (%p) the node[%d] (%p) with .key = %u, .next %p", node, i, &nodes[i], nodes[i].key, nodes[i].next);
! 94: }
! 95:
! 96: print_rate_of_fulfilment();
! 97: }
! 98:
! 99: static void
! 100: validate_empty_hash(void)
! 101: {
! 102: int i;
! 103: struct test_node *node;
! 104: for (i = 0; i < MAX_NUM; i++)
! 105: {
! 106: node = HASH_FIND(hash, TEST, nodes[i].key);
! 107: bt_assert_msg(node == NULL, "Hash should be empty, to find (%p) the node[%d] (%p) with .key %u, .next %p", node, i, &nodes[i], nodes[i].key, nodes[i].next);
! 108: }
! 109: }
! 110:
! 111: static void
! 112: fill_hash(void)
! 113: {
! 114: int i;
! 115: struct test_node *node;
! 116:
! 117: for (i = 0; i < MAX_NUM; i++)
! 118: {
! 119: nodes[i].key = i;
! 120: node = &nodes[i];
! 121: HASH_INSERT(hash, TEST, node);
! 122: }
! 123: }
! 124:
! 125: static int
! 126: t_insert_find(void)
! 127: {
! 128: init_hash();
! 129: fill_hash();
! 130: validate_filled_hash();
! 131:
! 132: return 1;
! 133: }
! 134:
! 135: static int
! 136: t_insert_find_random(void)
! 137: {
! 138: init_hash();
! 139:
! 140: int i;
! 141: struct test_node *node;
! 142: for (i = 0; i < MAX_NUM; i++)
! 143: {
! 144: nodes[i].key = bt_random();
! 145: node = &nodes[i];
! 146: HASH_INSERT(hash, TEST, node);
! 147: }
! 148:
! 149: validate_filled_hash();
! 150:
! 151: return 1;
! 152: }
! 153:
! 154: static int
! 155: t_insert2_find(void)
! 156: {
! 157: init_hash_(1);
! 158:
! 159: int i;
! 160: struct test_node *node;
! 161: for (i = 0; i < MAX_NUM; i++)
! 162: {
! 163: nodes[i].key = i;
! 164: node = &nodes[i];
! 165: HASH_INSERT2(hash, TEST, my_pool, node);
! 166: }
! 167: bt_assert_msg(hash.order != 1, "The hash should auto-resize from order 2^1. The order of the hash is 2^%u.", hash.order);
! 168:
! 169: validate_filled_hash();
! 170:
! 171: return 1;
! 172: }
! 173:
! 174: static int
! 175: t_walk(void)
! 176: {
! 177: init_hash();
! 178: fill_hash();
! 179:
! 180: uint i;
! 181: uint check[MAX_NUM];
! 182: for (i = 0; i < MAX_NUM; i++)
! 183: check[i] = 0;
! 184:
! 185: HASH_WALK(hash, next, n)
! 186: {
! 187: check[n->key]++;
! 188: }
! 189: HASH_WALK_END;
! 190:
! 191: for (i = 0; i < MAX_NUM; i++)
! 192: bt_assert(check[i] == 1);
! 193:
! 194: return 1;
! 195: }
! 196:
! 197: static int
! 198: t_walk_delsafe_delete(void)
! 199: {
! 200: init_hash();
! 201: fill_hash();
! 202:
! 203: HASH_WALK_DELSAFE(hash, next, n)
! 204: {
! 205: HASH_DELETE(hash, TEST, n->key);
! 206: }
! 207: HASH_WALK_DELSAFE_END;
! 208:
! 209: validate_empty_hash();
! 210:
! 211: return 1;
! 212: }
! 213:
! 214: static int
! 215: t_walk_delsafe_remove(void)
! 216: {
! 217: init_hash();
! 218: fill_hash();
! 219:
! 220: HASH_WALK_DELSAFE(hash, next, n)
! 221: {
! 222: HASH_REMOVE(hash, TEST, n);
! 223: }
! 224: HASH_WALK_DELSAFE_END;
! 225:
! 226: validate_empty_hash();
! 227:
! 228: return 1;
! 229: }
! 230:
! 231: static int
! 232: t_walk_delsafe_delete2(void)
! 233: {
! 234: init_hash();
! 235: fill_hash();
! 236:
! 237: HASH_WALK_DELSAFE(hash, next, n)
! 238: {
! 239: HASH_DELETE2(hash, TEST, my_pool, n->key);
! 240: }
! 241: HASH_WALK_DELSAFE_END;
! 242:
! 243: validate_empty_hash();
! 244:
! 245: return 1;
! 246: }
! 247:
! 248: static int
! 249: t_walk_delsafe_remove2(void)
! 250: {
! 251: init_hash();
! 252: fill_hash();
! 253:
! 254: HASH_WALK_DELSAFE(hash, next, n)
! 255: {
! 256: HASH_REMOVE2(hash, TEST, my_pool, n);
! 257: }
! 258: HASH_WALK_DELSAFE_END;
! 259:
! 260: validate_empty_hash();
! 261:
! 262: return 1;
! 263: }
! 264:
! 265: static int
! 266: t_walk_filter(void)
! 267: {
! 268: init_hash();
! 269: fill_hash();
! 270:
! 271: uint i;
! 272: uint check[MAX_NUM];
! 273: for (i = 0; i < MAX_NUM; i++)
! 274: check[i] = 0;
! 275:
! 276: HASH_WALK_FILTER(hash, next, n, m)
! 277: {
! 278: bt_assert(n == *m);
! 279: check[n->key]++;
! 280: }
! 281: HASH_WALK_FILTER_END;
! 282:
! 283: for (i = 0; i < MAX_NUM; i++)
! 284: bt_assert(check[i] == 1);
! 285:
! 286: return 1;
! 287: }
! 288:
! 289: int
! 290: main(int argc, char *argv[])
! 291: {
! 292: bt_init(argc, argv);
! 293:
! 294: bt_test_suite(t_insert_find, "HASH_INSERT and HASH_FIND");
! 295: bt_test_suite(t_insert_find_random, "HASH_INSERT pseudo-random keys and HASH_FIND");
! 296: bt_test_suite(t_insert2_find, "HASH_INSERT2 and HASH_FIND. HASH_INSERT2 is HASH_INSERT and a smart auto-resize function");
! 297: bt_test_suite(t_walk, "HASH_WALK");
! 298: bt_test_suite(t_walk_delsafe_delete, "HASH_WALK_DELSAFE and HASH_DELETE");
! 299: bt_test_suite(t_walk_delsafe_delete2, "HASH_WALK_DELSAFE and HASH_DELETE2. HASH_DELETE2 is HASH_DELETE and smart auto-resize function");
! 300: bt_test_suite(t_walk_delsafe_remove, "HASH_WALK_DELSAFE and HASH_REMOVE");
! 301: bt_test_suite(t_walk_delsafe_remove2, "HASH_WALK_DELSAFE and HASH_REMOVE2. HASH_REMOVE2 is HASH_REMOVE and smart auto-resize function");
! 302: bt_test_suite(t_walk_filter, "HASH_WALK_FILTER");
! 303:
! 304: return bt_exit_value();
! 305: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>