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