lhash_test.c revision 1.1.1.2 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