1 1.1 christos /* 2 1.1.1.2 christos * Copyright 2017-2020 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.1.2 christos * Licensed under the Apache License 2.0 (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.1.2 christos static short int_not_found; 37 1.1 christos 38 1.1 christos static unsigned long int int_hash(const int *p) 39 1.1 christos { 40 1.1 christos return 3 & *p; /* To force collisions */ 41 1.1 christos } 42 1.1 christos 43 1.1 christos static int int_cmp(const int *p, const int *q) 44 1.1 christos { 45 1.1 christos return *p != *q; 46 1.1 christos } 47 1.1 christos 48 1.1 christos static int int_find(int n) 49 1.1 christos { 50 1.1 christos unsigned int i; 51 1.1 christos 52 1.1 christos for (i = 0; i < n_int_tests; i++) 53 1.1 christos if (int_tests[i] == n) 54 1.1 christos return i; 55 1.1 christos return -1; 56 1.1 christos } 57 1.1 christos 58 1.1 christos static void int_doall(int *v) 59 1.1 christos { 60 1.1.1.2 christos const int n = int_find(*v); 61 1.1.1.2 christos 62 1.1.1.2 christos if (n < 0) 63 1.1.1.2 christos int_not_found++; 64 1.1.1.2 christos else 65 1.1.1.2 christos int_found[n]++; 66 1.1 christos } 67 1.1 christos 68 1.1 christos static void int_doall_arg(int *p, short *f) 69 1.1 christos { 70 1.1.1.2 christos const int n = int_find(*p); 71 1.1.1.2 christos 72 1.1.1.2 christos if (n < 0) 73 1.1.1.2 christos int_not_found++; 74 1.1.1.2 christos else 75 1.1.1.2 christos f[n]++; 76 1.1 christos } 77 1.1 christos 78 1.1 christos IMPLEMENT_LHASH_DOALL_ARG(int, short); 79 1.1 christos 80 1.1 christos static int test_int_lhash(void) 81 1.1 christos { 82 1.1 christos static struct { 83 1.1 christos int data; 84 1.1 christos int null; 85 1.1 christos } dels[] = { 86 1.1 christos { 65537, 0 }, 87 1.1 christos { 173, 0 }, 88 1.1 christos { 999, 1 }, 89 1.1 christos { 37, 0 }, 90 1.1 christos { 1, 0 }, 91 1.1 christos { 34, 1 } 92 1.1 christos }; 93 1.1 christos const unsigned int n_dels = OSSL_NELEM(dels); 94 1.1 christos LHASH_OF(int) *h = lh_int_new(&int_hash, &int_cmp); 95 1.1 christos unsigned int i; 96 1.1 christos int testresult = 0, j, *p; 97 1.1 christos 98 1.1 christos if (!TEST_ptr(h)) 99 1.1 christos goto end; 100 1.1 christos 101 1.1 christos /* insert */ 102 1.1 christos for (i = 0; i < n_int_tests; i++) 103 1.1 christos if (!TEST_ptr_null(lh_int_insert(h, int_tests + i))) { 104 1.1 christos TEST_info("int insert %d", i); 105 1.1 christos goto end; 106 1.1 christos } 107 1.1 christos 108 1.1 christos /* num_items */ 109 1.1 christos if (!TEST_int_eq(lh_int_num_items(h), n_int_tests)) 110 1.1 christos goto end; 111 1.1 christos 112 1.1 christos /* retrieve */ 113 1.1 christos for (i = 0; i < n_int_tests; i++) 114 1.1 christos if (!TEST_int_eq(*lh_int_retrieve(h, int_tests + i), int_tests[i])) { 115 1.1 christos TEST_info("lhash int retrieve value %d", i); 116 1.1 christos goto end; 117 1.1 christos } 118 1.1 christos for (i = 0; i < n_int_tests; i++) 119 1.1 christos if (!TEST_ptr_eq(lh_int_retrieve(h, int_tests + i), int_tests + i)) { 120 1.1 christos TEST_info("lhash int retrieve address %d", i); 121 1.1 christos goto end; 122 1.1 christos } 123 1.1 christos j = 1; 124 1.1 christos if (!TEST_ptr_eq(lh_int_retrieve(h, &j), int_tests + 2)) 125 1.1 christos goto end; 126 1.1 christos 127 1.1 christos /* replace */ 128 1.1 christos j = 13; 129 1.1 christos if (!TEST_ptr(p = lh_int_insert(h, &j))) 130 1.1 christos goto end; 131 1.1 christos if (!TEST_ptr_eq(p, int_tests + 1)) 132 1.1 christos goto end; 133 1.1 christos if (!TEST_ptr_eq(lh_int_retrieve(h, int_tests + 1), &j)) 134 1.1 christos goto end; 135 1.1 christos 136 1.1 christos /* do_all */ 137 1.1 christos memset(int_found, 0, sizeof(int_found)); 138 1.1.1.2 christos int_not_found = 0; 139 1.1 christos lh_int_doall(h, &int_doall); 140 1.1.1.2 christos if (!TEST_int_eq(int_not_found, 0)) { 141 1.1.1.2 christos TEST_info("lhash int doall encountered a not found condition"); 142 1.1.1.2 christos goto end; 143 1.1.1.2 christos } 144 1.1 christos for (i = 0; i < n_int_tests; i++) 145 1.1 christos if (!TEST_int_eq(int_found[i], 1)) { 146 1.1 christos TEST_info("lhash int doall %d", i); 147 1.1 christos goto end; 148 1.1 christos } 149 1.1 christos 150 1.1 christos /* do_all_arg */ 151 1.1 christos memset(int_found, 0, sizeof(int_found)); 152 1.1.1.2 christos int_not_found = 0; 153 1.1 christos lh_int_doall_short(h, int_doall_arg, int_found); 154 1.1.1.2 christos if (!TEST_int_eq(int_not_found, 0)) { 155 1.1.1.2 christos TEST_info("lhash int doall arg encountered a not found condition"); 156 1.1.1.2 christos goto end; 157 1.1.1.2 christos } 158 1.1 christos for (i = 0; i < n_int_tests; i++) 159 1.1 christos if (!TEST_int_eq(int_found[i], 1)) { 160 1.1 christos TEST_info("lhash int doall arg %d", i); 161 1.1 christos goto end; 162 1.1 christos } 163 1.1 christos 164 1.1 christos /* delete */ 165 1.1 christos for (i = 0; i < n_dels; i++) { 166 1.1 christos const int b = lh_int_delete(h, &dels[i].data) == NULL; 167 1.1 christos if (!TEST_int_eq(b ^ dels[i].null, 0)) { 168 1.1 christos TEST_info("lhash int delete %d", i); 169 1.1 christos goto end; 170 1.1 christos } 171 1.1 christos } 172 1.1 christos 173 1.1 christos /* error */ 174 1.1 christos if (!TEST_int_eq(lh_int_error(h), 0)) 175 1.1 christos goto end; 176 1.1 christos 177 1.1 christos testresult = 1; 178 1.1 christos end: 179 1.1 christos lh_int_free(h); 180 1.1 christos return testresult; 181 1.1 christos } 182 1.1 christos 183 1.1 christos static unsigned long int stress_hash(const int *p) 184 1.1 christos { 185 1.1 christos return *p; 186 1.1 christos } 187 1.1 christos 188 1.1 christos static int test_stress(void) 189 1.1 christos { 190 1.1 christos LHASH_OF(int) *h = lh_int_new(&stress_hash, &int_cmp); 191 1.1 christos const unsigned int n = 2500000; 192 1.1 christos unsigned int i; 193 1.1 christos int testresult = 0, *p; 194 1.1 christos 195 1.1 christos if (!TEST_ptr(h)) 196 1.1 christos goto end; 197 1.1 christos 198 1.1 christos /* insert */ 199 1.1 christos for (i = 0; i < n; i++) { 200 1.1 christos p = OPENSSL_malloc(sizeof(i)); 201 1.1 christos if (!TEST_ptr(p)) { 202 1.1 christos TEST_info("lhash stress out of memory %d", i); 203 1.1 christos goto end; 204 1.1 christos } 205 1.1 christos *p = 3 * i + 1; 206 1.1 christos lh_int_insert(h, p); 207 1.1 christos } 208 1.1 christos 209 1.1 christos /* num_items */ 210 1.1 christos if (!TEST_int_eq(lh_int_num_items(h), n)) 211 1.1 christos goto end; 212 1.1 christos 213 1.1 christos TEST_info("hash full statistics:"); 214 1.1 christos OPENSSL_LH_stats_bio((OPENSSL_LHASH *)h, bio_err); 215 1.1 christos TEST_note("hash full node usage:"); 216 1.1 christos OPENSSL_LH_node_usage_stats_bio((OPENSSL_LHASH *)h, bio_err); 217 1.1 christos 218 1.1 christos /* delete in a different order */ 219 1.1 christos for (i = 0; i < n; i++) { 220 1.1 christos const int j = (7 * i + 4) % n * 3 + 1; 221 1.1 christos 222 1.1 christos if (!TEST_ptr(p = lh_int_delete(h, &j))) { 223 1.1 christos TEST_info("lhash stress delete %d\n", i); 224 1.1 christos goto end; 225 1.1 christos } 226 1.1 christos if (!TEST_int_eq(*p, j)) { 227 1.1 christos TEST_info("lhash stress bad value %d", i); 228 1.1 christos goto end; 229 1.1 christos } 230 1.1 christos OPENSSL_free(p); 231 1.1 christos } 232 1.1 christos 233 1.1 christos TEST_info("hash empty statistics:"); 234 1.1 christos OPENSSL_LH_stats_bio((OPENSSL_LHASH *)h, bio_err); 235 1.1 christos TEST_note("hash empty node usage:"); 236 1.1 christos OPENSSL_LH_node_usage_stats_bio((OPENSSL_LHASH *)h, bio_err); 237 1.1 christos 238 1.1 christos testresult = 1; 239 1.1 christos end: 240 1.1 christos lh_int_free(h); 241 1.1 christos return testresult; 242 1.1 christos } 243 1.1 christos 244 1.1 christos int setup_tests(void) 245 1.1 christos { 246 1.1 christos ADD_TEST(test_int_lhash); 247 1.1 christos ADD_TEST(test_stress); 248 1.1 christos return 1; 249 1.1 christos } 250