1 1.1 christos /* 2 1.1 christos * Copyright 2017 The OpenSSL Project Authors. All Rights Reserved. 3 1.1 christos * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. 4 1.1 christos * 5 1.1 christos * Licensed under the OpenSSL license (the "License"). You may not use 6 1.1 christos * this file except in compliance with the License. You can obtain a copy 7 1.1 christos * in the file LICENSE in the source distribution or at 8 1.1 christos * https://www.openssl.org/source/license.html 9 1.1 christos */ 10 1.1 christos 11 1.1 christos #include <stdio.h> 12 1.1 christos #include <string.h> 13 1.1 christos 14 1.1 christos #include <openssl/opensslconf.h> 15 1.1 christos #include <openssl/lhash.h> 16 1.1 christos #include <openssl/err.h> 17 1.1 christos #include <openssl/crypto.h> 18 1.1 christos 19 1.1 christos #include "internal/nelem.h" 20 1.1 christos #include "testutil.h" 21 1.1 christos 22 1.1 christos /* 23 1.1 christos * The macros below generate unused functions which error out one of the clang 24 1.1 christos * builds. We disable this check here. 25 1.1 christos */ 26 1.1 christos #ifdef __clang__ 27 1.1 christos #pragma clang diagnostic ignored "-Wunused-function" 28 1.1 christos #endif 29 1.1 christos 30 1.1 christos DEFINE_LHASH_OF(int); 31 1.1 christos 32 1.1 christos static int int_tests[] = { 65537, 13, 1, 3, -5, 6, 7, 4, -10, -12, -14, 22, 9, 33 1.1 christos -17, 16, 17, -23, 35, 37, 173, 11 }; 34 1.1 christos static const unsigned int n_int_tests = OSSL_NELEM(int_tests); 35 1.1 christos static short int_found[OSSL_NELEM(int_tests)]; 36 1.1 christos 37 1.1 christos static unsigned long int int_hash(const int *p) 38 1.1 christos { 39 1.1 christos return 3 & *p; /* To force collisions */ 40 1.1 christos } 41 1.1 christos 42 1.1 christos static int int_cmp(const int *p, const int *q) 43 1.1 christos { 44 1.1 christos return *p != *q; 45 1.1 christos } 46 1.1 christos 47 1.1 christos static int int_find(int n) 48 1.1 christos { 49 1.1 christos unsigned int i; 50 1.1 christos 51 1.1 christos for (i = 0; i < n_int_tests; i++) 52 1.1 christos if (int_tests[i] == n) 53 1.1 christos return i; 54 1.1 christos return -1; 55 1.1 christos } 56 1.1 christos 57 1.1 christos static void int_doall(int *v) 58 1.1 christos { 59 1.1 christos int_found[int_find(*v)]++; 60 1.1 christos } 61 1.1 christos 62 1.1 christos static void int_doall_arg(int *p, short *f) 63 1.1 christos { 64 1.1 christos f[int_find(*p)]++; 65 1.1 christos } 66 1.1 christos 67 1.1 christos IMPLEMENT_LHASH_DOALL_ARG(int, short); 68 1.1 christos 69 1.1 christos static int test_int_lhash(void) 70 1.1 christos { 71 1.1 christos static struct { 72 1.1 christos int data; 73 1.1 christos int null; 74 1.1 christos } dels[] = { 75 1.1 christos { 65537, 0 }, 76 1.1 christos { 173, 0 }, 77 1.1 christos { 999, 1 }, 78 1.1 christos { 37, 0 }, 79 1.1 christos { 1, 0 }, 80 1.1 christos { 34, 1 } 81 1.1 christos }; 82 1.1 christos const unsigned int n_dels = OSSL_NELEM(dels); 83 1.1 christos LHASH_OF(int) *h = lh_int_new(&int_hash, &int_cmp); 84 1.1 christos unsigned int i; 85 1.1 christos int testresult = 0, j, *p; 86 1.1 christos 87 1.1 christos if (!TEST_ptr(h)) 88 1.1 christos goto end; 89 1.1 christos 90 1.1 christos /* insert */ 91 1.1 christos for (i = 0; i < n_int_tests; i++) 92 1.1 christos if (!TEST_ptr_null(lh_int_insert(h, int_tests + i))) { 93 1.1 christos TEST_info("int insert %d", i); 94 1.1 christos goto end; 95 1.1 christos } 96 1.1 christos 97 1.1 christos /* num_items */ 98 1.1 christos if (!TEST_int_eq(lh_int_num_items(h), n_int_tests)) 99 1.1 christos goto end; 100 1.1 christos 101 1.1 christos /* retrieve */ 102 1.1 christos for (i = 0; i < n_int_tests; i++) 103 1.1 christos if (!TEST_int_eq(*lh_int_retrieve(h, int_tests + i), int_tests[i])) { 104 1.1 christos TEST_info("lhash int retrieve value %d", i); 105 1.1 christos goto end; 106 1.1 christos } 107 1.1 christos for (i = 0; i < n_int_tests; i++) 108 1.1 christos if (!TEST_ptr_eq(lh_int_retrieve(h, int_tests + i), int_tests + i)) { 109 1.1 christos TEST_info("lhash int retrieve address %d", i); 110 1.1 christos goto end; 111 1.1 christos } 112 1.1 christos j = 1; 113 1.1 christos if (!TEST_ptr_eq(lh_int_retrieve(h, &j), int_tests + 2)) 114 1.1 christos goto end; 115 1.1 christos 116 1.1 christos /* replace */ 117 1.1 christos j = 13; 118 1.1 christos if (!TEST_ptr(p = lh_int_insert(h, &j))) 119 1.1 christos goto end; 120 1.1 christos if (!TEST_ptr_eq(p, int_tests + 1)) 121 1.1 christos goto end; 122 1.1 christos if (!TEST_ptr_eq(lh_int_retrieve(h, int_tests + 1), &j)) 123 1.1 christos goto end; 124 1.1 christos 125 1.1 christos /* do_all */ 126 1.1 christos memset(int_found, 0, sizeof(int_found)); 127 1.1 christos lh_int_doall(h, &int_doall); 128 1.1 christos for (i = 0; i < n_int_tests; i++) 129 1.1 christos if (!TEST_int_eq(int_found[i], 1)) { 130 1.1 christos TEST_info("lhash int doall %d", i); 131 1.1 christos goto end; 132 1.1 christos } 133 1.1 christos 134 1.1 christos /* do_all_arg */ 135 1.1 christos memset(int_found, 0, sizeof(int_found)); 136 1.1 christos lh_int_doall_short(h, int_doall_arg, int_found); 137 1.1 christos for (i = 0; i < n_int_tests; i++) 138 1.1 christos if (!TEST_int_eq(int_found[i], 1)) { 139 1.1 christos TEST_info("lhash int doall arg %d", i); 140 1.1 christos goto end; 141 1.1 christos } 142 1.1 christos 143 1.1 christos /* delete */ 144 1.1 christos for (i = 0; i < n_dels; i++) { 145 1.1 christos const int b = lh_int_delete(h, &dels[i].data) == NULL; 146 1.1 christos if (!TEST_int_eq(b ^ dels[i].null, 0)) { 147 1.1 christos TEST_info("lhash int delete %d", i); 148 1.1 christos goto end; 149 1.1 christos } 150 1.1 christos } 151 1.1 christos 152 1.1 christos /* error */ 153 1.1 christos if (!TEST_int_eq(lh_int_error(h), 0)) 154 1.1 christos goto end; 155 1.1 christos 156 1.1 christos testresult = 1; 157 1.1 christos end: 158 1.1 christos lh_int_free(h); 159 1.1 christos return testresult; 160 1.1 christos } 161 1.1 christos 162 1.1 christos static unsigned long int stress_hash(const int *p) 163 1.1 christos { 164 1.1 christos return *p; 165 1.1 christos } 166 1.1 christos 167 1.1 christos static int test_stress(void) 168 1.1 christos { 169 1.1 christos LHASH_OF(int) *h = lh_int_new(&stress_hash, &int_cmp); 170 1.1 christos const unsigned int n = 2500000; 171 1.1 christos unsigned int i; 172 1.1 christos int testresult = 0, *p; 173 1.1 christos 174 1.1 christos if (!TEST_ptr(h)) 175 1.1 christos goto end; 176 1.1 christos 177 1.1 christos /* insert */ 178 1.1 christos for (i = 0; i < n; i++) { 179 1.1 christos p = OPENSSL_malloc(sizeof(i)); 180 1.1 christos if (!TEST_ptr(p)) { 181 1.1 christos TEST_info("lhash stress out of memory %d", i); 182 1.1 christos goto end; 183 1.1 christos } 184 1.1 christos *p = 3 * i + 1; 185 1.1 christos lh_int_insert(h, p); 186 1.1 christos } 187 1.1 christos 188 1.1 christos /* num_items */ 189 1.1 christos if (!TEST_int_eq(lh_int_num_items(h), n)) 190 1.1 christos goto end; 191 1.1 christos 192 1.1 christos TEST_info("hash full statistics:"); 193 1.1 christos OPENSSL_LH_stats_bio((OPENSSL_LHASH *)h, bio_err); 194 1.1 christos TEST_note("hash full node usage:"); 195 1.1 christos OPENSSL_LH_node_usage_stats_bio((OPENSSL_LHASH *)h, bio_err); 196 1.1 christos 197 1.1 christos /* delete in a different order */ 198 1.1 christos for (i = 0; i < n; i++) { 199 1.1 christos const int j = (7 * i + 4) % n * 3 + 1; 200 1.1 christos 201 1.1 christos if (!TEST_ptr(p = lh_int_delete(h, &j))) { 202 1.1 christos TEST_info("lhash stress delete %d\n", i); 203 1.1 christos goto end; 204 1.1 christos } 205 1.1 christos if (!TEST_int_eq(*p, j)) { 206 1.1 christos TEST_info("lhash stress bad value %d", i); 207 1.1 christos goto end; 208 1.1 christos } 209 1.1 christos OPENSSL_free(p); 210 1.1 christos } 211 1.1 christos 212 1.1 christos TEST_info("hash empty statistics:"); 213 1.1 christos OPENSSL_LH_stats_bio((OPENSSL_LHASH *)h, bio_err); 214 1.1 christos TEST_note("hash empty node usage:"); 215 1.1 christos OPENSSL_LH_node_usage_stats_bio((OPENSSL_LHASH *)h, bio_err); 216 1.1 christos 217 1.1 christos testresult = 1; 218 1.1 christos end: 219 1.1 christos lh_int_free(h); 220 1.1 christos return testresult; 221 1.1 christos } 222 1.1 christos 223 1.1 christos int setup_tests(void) 224 1.1 christos { 225 1.1 christos ADD_TEST(test_int_lhash); 226 1.1 christos ADD_TEST(test_stress); 227 1.1 christos return 1; 228 1.1 christos } 229