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