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