]> git.ipfire.org Git - thirdparty/openssl.git/blob - test/asynctest.c
Refactor the async wait fd logic
[thirdparty/openssl.git] / test / asynctest.c
1 /*
2 * Written by Matt Caswell for the OpenSSL project.
3 */
4 /* ====================================================================
5 * Copyright (c) 2015 The OpenSSL Project. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 *
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in
16 * the documentation and/or other materials provided with the
17 * distribution.
18 *
19 * 3. All advertising materials mentioning features or use of this
20 * software must display the following acknowledgment:
21 * "This product includes software developed by the OpenSSL Project
22 * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
23 *
24 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
25 * endorse or promote products derived from this software without
26 * prior written permission. For written permission, please contact
27 * openssl-core@openssl.org.
28 *
29 * 5. Products derived from this software may not be called "OpenSSL"
30 * nor may "OpenSSL" appear in their names without prior written
31 * permission of the OpenSSL Project.
32 *
33 * 6. Redistributions of any form whatsoever must retain the following
34 * acknowledgment:
35 * "This product includes software developed by the OpenSSL Project
36 * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
37 *
38 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
39 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
40 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
41 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
42 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
43 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
44 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
45 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
46 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
47 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
48 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
49 * OF THE POSSIBILITY OF SUCH DAMAGE.
50 * ====================================================================
51 *
52 * This product includes cryptographic software written by Eric Young
53 * (eay@cryptsoft.com). This product includes software written by Tim
54 * Hudson (tjh@cryptsoft.com).
55 *
56 */
57
58 #include <stdio.h>
59 #include <string.h>
60 #include <openssl/async.h>
61 #include <openssl/crypto.h>
62 #include <../apps/apps.h>
63
64 #if (defined(OPENSSL_SYS_UNIX) || defined(OPENSSL_SYS_CYGWIN)) && defined(OPENSSL_THREADS)
65 # include <unistd.h>
66 # if _POSIX_VERSION >= 200112L
67 # define ASYNC_POSIX
68 # endif
69 #elif defined(_WIN32)
70 # define ASYNC_WIN
71 #endif
72
73 #if !defined(ASYNC_POSIX) && !defined(ASYNC_WIN)
74 # define ASYNC_NULL
75 #endif
76
77 #ifndef ASYNC_NULL
78
79 static int ctr = 0;
80 static ASYNC_JOB *currjob = NULL;
81
82 static int only_pause(void *args)
83 {
84 ASYNC_pause_job();
85
86 return 1;
87 }
88
89 static int add_two(void *args)
90 {
91 ctr++;
92 ASYNC_pause_job();
93 ctr++;
94
95 return 2;
96 }
97
98 static int save_current(void *args)
99 {
100 currjob = ASYNC_get_current_job();
101 ASYNC_pause_job();
102
103 return 1;
104 }
105
106 #define MAGIC_WAIT_FD ((OSSL_ASYNC_FD)99)
107 static int waitfd(void *args)
108 {
109 ASYNC_JOB *job;
110 ASYNC_WAIT_CTX *waitctx;
111 ASYNC_pause_job();
112 job = ASYNC_get_current_job();
113 if (job == NULL)
114 return 0;
115 waitctx = ASYNC_get_wait_ctx(job);
116 if (waitctx == NULL)
117 return 0;
118 if(!ASYNC_WAIT_CTX_set_wait_fd(waitctx, waitctx, MAGIC_WAIT_FD, NULL, NULL))
119 return 0;
120 ASYNC_pause_job();
121
122 if (!ASYNC_WAIT_CTX_clear_fd(waitctx, waitctx))
123 return 0;
124
125 return 1;
126 }
127
128 static int blockpause(void *args)
129 {
130 ASYNC_block_pause();
131 ASYNC_pause_job();
132 ASYNC_unblock_pause();
133 ASYNC_pause_job();
134
135 return 1;
136 }
137
138 static int test_ASYNC_init_thread()
139 {
140 ASYNC_JOB *job1 = NULL, *job2 = NULL, *job3 = NULL;
141 int funcret1, funcret2, funcret3;
142 ASYNC_WAIT_CTX *waitctx;
143
144 if ( !ASYNC_init_thread(2, 0)
145 || (waitctx = ASYNC_WAIT_CTX_new()) == NULL
146 || ASYNC_start_job(&job1, waitctx, &funcret1, only_pause, NULL, 0)
147 != ASYNC_PAUSE
148 || ASYNC_start_job(&job2, waitctx, &funcret2, only_pause, NULL, 0)
149 != ASYNC_PAUSE
150 || ASYNC_start_job(&job3, waitctx, &funcret3, only_pause, NULL, 0)
151 != ASYNC_NO_JOBS
152 || ASYNC_start_job(&job1, waitctx, &funcret1, only_pause, NULL, 0)
153 != ASYNC_FINISH
154 || ASYNC_start_job(&job3, waitctx, &funcret3, only_pause, NULL, 0)
155 != ASYNC_PAUSE
156 || ASYNC_start_job(&job2, waitctx, &funcret2, only_pause, NULL, 0)
157 != ASYNC_FINISH
158 || ASYNC_start_job(&job3, waitctx, &funcret3, only_pause, NULL, 0)
159 != ASYNC_FINISH
160 || funcret1 != 1
161 || funcret2 != 1
162 || funcret3 != 1) {
163 fprintf(stderr, "test_ASYNC_init_thread() failed\n");
164 ASYNC_WAIT_CTX_free(waitctx);
165 ASYNC_cleanup_thread();
166 return 0;
167 }
168
169 ASYNC_WAIT_CTX_free(waitctx);
170 ASYNC_cleanup_thread();
171 return 1;
172 }
173
174 static int test_ASYNC_start_job()
175 {
176 ASYNC_JOB *job = NULL;
177 int funcret;
178 ASYNC_WAIT_CTX *waitctx;
179
180 ctr = 0;
181
182 if ( !ASYNC_init_thread(1, 0)
183 || (waitctx = ASYNC_WAIT_CTX_new()) == NULL
184 || ASYNC_start_job(&job, waitctx, &funcret, add_two, NULL, 0)
185 != ASYNC_PAUSE
186 || ctr != 1
187 || ASYNC_start_job(&job, waitctx, &funcret, add_two, NULL, 0)
188 != ASYNC_FINISH
189 || ctr != 2
190 || funcret != 2) {
191 fprintf(stderr, "test_ASYNC_start_job() failed\n");
192 ASYNC_WAIT_CTX_free(waitctx);
193 ASYNC_cleanup_thread();
194 return 0;
195 }
196
197 ASYNC_WAIT_CTX_free(waitctx);
198 ASYNC_cleanup_thread();
199 return 1;
200 }
201
202 static int test_ASYNC_get_current_job()
203 {
204 ASYNC_JOB *job = NULL;
205 int funcret;
206 ASYNC_WAIT_CTX *waitctx;
207
208 currjob = NULL;
209
210 if ( !ASYNC_init_thread(1, 0)
211 || (waitctx = ASYNC_WAIT_CTX_new()) == NULL
212 || ASYNC_start_job(&job, waitctx, &funcret, save_current, NULL, 0)
213 != ASYNC_PAUSE
214 || currjob != job
215 || ASYNC_start_job(&job, waitctx, &funcret, save_current, NULL, 0)
216 != ASYNC_FINISH
217 || funcret != 1) {
218 fprintf(stderr, "test_ASYNC_get_current_job() failed\n");
219 ASYNC_WAIT_CTX_free(waitctx);
220 ASYNC_cleanup_thread();
221 return 0;
222 }
223
224 ASYNC_WAIT_CTX_free(waitctx);
225 ASYNC_cleanup_thread();
226 return 1;
227 }
228
229 static int test_ASYNC_WAIT_CTX_get_all_fds()
230 {
231 ASYNC_JOB *job = NULL;
232 int funcret;
233 ASYNC_WAIT_CTX *waitctx;
234 OSSL_ASYNC_FD fd = OSSL_BAD_ASYNC_FD, delfd = OSSL_BAD_ASYNC_FD;
235 size_t numfds, numdelfds;
236
237 if ( !ASYNC_init_thread(1, 0)
238 || (waitctx = ASYNC_WAIT_CTX_new()) == NULL
239 /* On first run we're not expecting any wait fds */
240 || ASYNC_start_job(&job, waitctx, &funcret, waitfd, NULL, 0)
241 != ASYNC_PAUSE
242 || !ASYNC_WAIT_CTX_get_all_fds(waitctx, NULL, &numfds)
243 || numfds != 0
244 || !ASYNC_WAIT_CTX_get_changed_fds(waitctx, NULL, &numfds, NULL,
245 &numdelfds)
246 || numfds != 0
247 || numdelfds != 0
248 /* On second run we're expecting one added fd */
249 || ASYNC_start_job(&job, waitctx, &funcret, waitfd, NULL, 0)
250 != ASYNC_PAUSE
251 || !ASYNC_WAIT_CTX_get_all_fds(waitctx, NULL, &numfds)
252 || numfds != 1
253 || !ASYNC_WAIT_CTX_get_all_fds(waitctx, &fd, &numfds)
254 || fd != MAGIC_WAIT_FD
255 || (fd = OSSL_BAD_ASYNC_FD, 0) /* Assign to something else */
256 || !ASYNC_WAIT_CTX_get_changed_fds(waitctx, NULL, &numfds, NULL,
257 &numdelfds)
258 || numfds != 1
259 || numdelfds != 0
260 || !ASYNC_WAIT_CTX_get_changed_fds(waitctx, &fd, &numfds, NULL,
261 &numdelfds)
262 || fd != MAGIC_WAIT_FD
263 /* On final run we expect one deleted fd */
264 || ASYNC_start_job(&job, waitctx, &funcret, waitfd, NULL, 0)
265 != ASYNC_FINISH
266 || !ASYNC_WAIT_CTX_get_all_fds(waitctx, NULL, &numfds)
267 || numfds != 0
268 || !ASYNC_WAIT_CTX_get_changed_fds(waitctx, NULL, &numfds, NULL,
269 &numdelfds)
270 || numfds != 0
271 || numdelfds != 1
272 || !ASYNC_WAIT_CTX_get_changed_fds(waitctx, NULL, &numfds, &delfd,
273 &numdelfds)
274 || delfd != MAGIC_WAIT_FD
275 || funcret != 1) {
276 fprintf(stderr, "test_ASYNC_get_wait_fd() failed\n");
277 ASYNC_WAIT_CTX_free(waitctx);
278 ASYNC_cleanup_thread();
279 return 0;
280 }
281
282 ASYNC_WAIT_CTX_free(waitctx);
283 ASYNC_cleanup_thread();
284 return 1;
285 }
286
287 static int test_ASYNC_block_pause()
288 {
289 ASYNC_JOB *job = NULL;
290 int funcret;
291 ASYNC_WAIT_CTX *waitctx;
292
293 if ( !ASYNC_init_thread(1, 0)
294 || (waitctx = ASYNC_WAIT_CTX_new()) == NULL
295 || ASYNC_start_job(&job, waitctx, &funcret, blockpause, NULL, 0)
296 != ASYNC_PAUSE
297 || ASYNC_start_job(&job, waitctx, &funcret, blockpause, NULL, 0)
298 != ASYNC_FINISH
299 || funcret != 1) {
300 fprintf(stderr, "test_ASYNC_block_pause() failed\n");
301 ASYNC_WAIT_CTX_free(waitctx);
302 ASYNC_cleanup_thread();
303 return 0;
304 }
305
306 ASYNC_WAIT_CTX_free(waitctx);
307 ASYNC_cleanup_thread();
308 return 1;
309 }
310
311 #endif
312
313 int main(int argc, char **argv)
314 {
315
316 #ifdef ASYNC_NULL
317 fprintf(stderr, "NULL implementation - skipping async tests\n");
318 #else
319 CRYPTO_set_mem_debug(1);
320 CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);
321
322 if ( !test_ASYNC_init_thread()
323 || !test_ASYNC_start_job()
324 || !test_ASYNC_get_current_job()
325 || !test_ASYNC_WAIT_CTX_get_all_fds()
326 || !test_ASYNC_block_pause()) {
327 return 1;
328 }
329 #endif
330 printf("PASS\n");
331 return 0;
332 }