2 * Copyright 2015-2020 The OpenSSL Project Authors. All Rights Reserved.
4 * Licensed under the Apache License 2.0 (the "License"). You may not use
5 * this file except in compliance with the License. You can obtain a copy
6 * in the file LICENSE in the source distribution or at
7 * https://www.openssl.org/source/license.html
16 #include <openssl/async.h>
17 #include <openssl/crypto.h>
20 static ASYNC_JOB *currjob = NULL;
22 static int only_pause(void *args)
29 static int add_two(void *args)
38 static int save_current(void *args)
40 currjob = ASYNC_get_current_job();
46 static int change_deflt_libctx(void *args)
48 OPENSSL_CTX *libctx = OPENSSL_CTX_new();
49 OPENSSL_CTX *oldctx, *tmpctx;
55 oldctx = OPENSSL_CTX_set0_default(libctx);
58 /* Check the libctx is set up as we expect */
59 tmpctx = OPENSSL_CTX_set0_default(oldctx);
63 /* Set it back again to continue to use our own libctx */
64 oldctx = OPENSSL_CTX_set0_default(libctx);
67 /* Check the libctx is set up as we expect */
68 tmpctx = OPENSSL_CTX_set0_default(oldctx);
74 OPENSSL_CTX_free(libctx);
79 #define MAGIC_WAIT_FD ((OSSL_ASYNC_FD)99)
80 static int waitfd(void *args)
83 ASYNC_WAIT_CTX *waitctx;
84 job = ASYNC_get_current_job();
87 waitctx = ASYNC_get_wait_ctx(job);
91 /* First case: no fd added or removed */
94 /* Second case: one fd added */
95 if (!ASYNC_WAIT_CTX_set_wait_fd(waitctx, waitctx, MAGIC_WAIT_FD, NULL, NULL))
99 /* Third case: all fd removed */
100 if (!ASYNC_WAIT_CTX_clear_fd(waitctx, waitctx))
104 /* Last case: fd added and immediately removed */
105 if (!ASYNC_WAIT_CTX_set_wait_fd(waitctx, waitctx, MAGIC_WAIT_FD, NULL, NULL))
107 if (!ASYNC_WAIT_CTX_clear_fd(waitctx, waitctx))
113 static int blockpause(void *args)
117 ASYNC_unblock_pause();
123 static int test_ASYNC_init_thread(void)
125 ASYNC_JOB *job1 = NULL, *job2 = NULL, *job3 = NULL;
126 int funcret1, funcret2, funcret3;
127 ASYNC_WAIT_CTX *waitctx = NULL;
129 if ( !ASYNC_init_thread(2, 0)
130 || (waitctx = ASYNC_WAIT_CTX_new()) == NULL
131 || ASYNC_start_job(&job1, waitctx, &funcret1, only_pause, NULL, 0)
133 || ASYNC_start_job(&job2, waitctx, &funcret2, only_pause, NULL, 0)
135 || ASYNC_start_job(&job3, waitctx, &funcret3, only_pause, NULL, 0)
137 || ASYNC_start_job(&job1, waitctx, &funcret1, only_pause, NULL, 0)
139 || ASYNC_start_job(&job3, waitctx, &funcret3, only_pause, NULL, 0)
141 || ASYNC_start_job(&job2, waitctx, &funcret2, only_pause, NULL, 0)
143 || ASYNC_start_job(&job3, waitctx, &funcret3, only_pause, NULL, 0)
148 fprintf(stderr, "test_ASYNC_init_thread() failed\n");
149 ASYNC_WAIT_CTX_free(waitctx);
150 ASYNC_cleanup_thread();
154 ASYNC_WAIT_CTX_free(waitctx);
155 ASYNC_cleanup_thread();
159 static int test_callback(void *arg)
161 printf("callback test pass\n");
165 static int test_ASYNC_callback_status(void)
167 ASYNC_WAIT_CTX *waitctx = NULL;
169 ASYNC_callback_fn get_callback;
173 if ( !ASYNC_init_thread(1, 0)
174 || (waitctx = ASYNC_WAIT_CTX_new()) == NULL
175 || ASYNC_WAIT_CTX_set_callback(waitctx, test_callback, (void*)&set_arg)
177 || ASYNC_WAIT_CTX_get_callback(waitctx, &get_callback, &get_arg)
179 || test_callback != get_callback
180 || get_arg != (void*)&set_arg
181 || (*get_callback)(get_arg) != 1
182 || ASYNC_WAIT_CTX_set_status(waitctx, set_status) != 1
183 || set_status != ASYNC_WAIT_CTX_get_status(waitctx)) {
184 fprintf(stderr, "test_ASYNC_callback_status() failed\n");
185 ASYNC_WAIT_CTX_free(waitctx);
186 ASYNC_cleanup_thread();
190 ASYNC_WAIT_CTX_free(waitctx);
191 ASYNC_cleanup_thread();
196 static int test_ASYNC_start_job(void)
198 ASYNC_JOB *job = NULL;
200 ASYNC_WAIT_CTX *waitctx = NULL;
204 if ( !ASYNC_init_thread(1, 0)
205 || (waitctx = ASYNC_WAIT_CTX_new()) == NULL
206 || ASYNC_start_job(&job, waitctx, &funcret, add_two, NULL, 0)
209 || ASYNC_start_job(&job, waitctx, &funcret, add_two, NULL, 0)
213 fprintf(stderr, "test_ASYNC_start_job() failed\n");
214 ASYNC_WAIT_CTX_free(waitctx);
215 ASYNC_cleanup_thread();
219 ASYNC_WAIT_CTX_free(waitctx);
220 ASYNC_cleanup_thread();
224 static int test_ASYNC_get_current_job(void)
226 ASYNC_JOB *job = NULL;
228 ASYNC_WAIT_CTX *waitctx = NULL;
232 if ( !ASYNC_init_thread(1, 0)
233 || (waitctx = ASYNC_WAIT_CTX_new()) == NULL
234 || ASYNC_start_job(&job, waitctx, &funcret, save_current, NULL, 0)
237 || ASYNC_start_job(&job, waitctx, &funcret, save_current, NULL, 0)
240 fprintf(stderr, "test_ASYNC_get_current_job() failed\n");
241 ASYNC_WAIT_CTX_free(waitctx);
242 ASYNC_cleanup_thread();
246 ASYNC_WAIT_CTX_free(waitctx);
247 ASYNC_cleanup_thread();
251 static int test_ASYNC_WAIT_CTX_get_all_fds(void)
253 ASYNC_JOB *job = NULL;
255 ASYNC_WAIT_CTX *waitctx = NULL;
256 OSSL_ASYNC_FD fd = OSSL_BAD_ASYNC_FD, delfd = OSSL_BAD_ASYNC_FD;
257 size_t numfds, numdelfds;
259 if ( !ASYNC_init_thread(1, 0)
260 || (waitctx = ASYNC_WAIT_CTX_new()) == NULL
261 /* On first run we're not expecting any wait fds */
262 || ASYNC_start_job(&job, waitctx, &funcret, waitfd, NULL, 0)
264 || !ASYNC_WAIT_CTX_get_all_fds(waitctx, NULL, &numfds)
266 || !ASYNC_WAIT_CTX_get_changed_fds(waitctx, NULL, &numfds, NULL,
270 /* On second run we're expecting one added fd */
271 || ASYNC_start_job(&job, waitctx, &funcret, waitfd, NULL, 0)
273 || !ASYNC_WAIT_CTX_get_all_fds(waitctx, NULL, &numfds)
275 || !ASYNC_WAIT_CTX_get_all_fds(waitctx, &fd, &numfds)
276 || fd != MAGIC_WAIT_FD
277 || (fd = OSSL_BAD_ASYNC_FD, 0) /* Assign to something else */
278 || !ASYNC_WAIT_CTX_get_changed_fds(waitctx, NULL, &numfds, NULL,
282 || !ASYNC_WAIT_CTX_get_changed_fds(waitctx, &fd, &numfds, NULL,
284 || fd != MAGIC_WAIT_FD
285 /* On third run we expect one deleted fd */
286 || ASYNC_start_job(&job, waitctx, &funcret, waitfd, NULL, 0)
288 || !ASYNC_WAIT_CTX_get_all_fds(waitctx, NULL, &numfds)
290 || !ASYNC_WAIT_CTX_get_changed_fds(waitctx, NULL, &numfds, NULL,
294 || !ASYNC_WAIT_CTX_get_changed_fds(waitctx, NULL, &numfds, &delfd,
296 || delfd != MAGIC_WAIT_FD
297 /* On last run we are not expecting any wait fd */
298 || ASYNC_start_job(&job, waitctx, &funcret, waitfd, NULL, 0)
300 || !ASYNC_WAIT_CTX_get_all_fds(waitctx, NULL, &numfds)
302 || !ASYNC_WAIT_CTX_get_changed_fds(waitctx, NULL, &numfds, NULL,
307 fprintf(stderr, "test_ASYNC_get_wait_fd() failed\n");
308 ASYNC_WAIT_CTX_free(waitctx);
309 ASYNC_cleanup_thread();
313 ASYNC_WAIT_CTX_free(waitctx);
314 ASYNC_cleanup_thread();
318 static int test_ASYNC_block_pause(void)
320 ASYNC_JOB *job = NULL;
322 ASYNC_WAIT_CTX *waitctx = NULL;
324 if ( !ASYNC_init_thread(1, 0)
325 || (waitctx = ASYNC_WAIT_CTX_new()) == NULL
326 || ASYNC_start_job(&job, waitctx, &funcret, blockpause, NULL, 0)
328 || ASYNC_start_job(&job, waitctx, &funcret, blockpause, NULL, 0)
331 fprintf(stderr, "test_ASYNC_block_pause() failed\n");
332 ASYNC_WAIT_CTX_free(waitctx);
333 ASYNC_cleanup_thread();
337 ASYNC_WAIT_CTX_free(waitctx);
338 ASYNC_cleanup_thread();
342 static int test_ASYNC_start_job_with_libctx(void)
344 ASYNC_JOB *job = NULL;
346 ASYNC_WAIT_CTX *waitctx = NULL;
347 OPENSSL_CTX *libctx = OPENSSL_CTX_new();
348 OPENSSL_CTX *oldctx, *tmpctx, *globalctx;
351 if (libctx == NULL) {
353 "test_ASYNC_start_job_with_libctx() failed to create libctx\n");
357 globalctx = oldctx = OPENSSL_CTX_set0_default(libctx);
359 if ((waitctx = ASYNC_WAIT_CTX_new()) == NULL
360 || ASYNC_start_job(&job, waitctx, &funcret, change_deflt_libctx,
364 "test_ASYNC_start_job_with_libctx() failed to start job\n");
368 /* Reset the libctx temporarily to find out what it is*/
369 tmpctx = OPENSSL_CTX_set0_default(oldctx);
370 oldctx = OPENSSL_CTX_set0_default(tmpctx);
371 if (tmpctx != libctx) {
373 "test_ASYNC_start_job_with_libctx() failed - unexpected libctx\n");
377 if (ASYNC_start_job(&job, waitctx, &funcret, change_deflt_libctx, NULL, 0)
380 "test_ASYNC_start_job_with_libctx() - restarting job failed\n");
384 /* Reset the libctx and continue with the global default libctx */
385 tmpctx = OPENSSL_CTX_set0_default(oldctx);
386 if (tmpctx != libctx) {
388 "test_ASYNC_start_job_with_libctx() failed - unexpected libctx\n");
392 if (ASYNC_start_job(&job, waitctx, &funcret, change_deflt_libctx, NULL, 0)
396 "test_ASYNC_start_job_with_libctx() - finishing job failed\n");
400 /* Reset the libctx temporarily to find out what it is*/
401 tmpctx = OPENSSL_CTX_set0_default(libctx);
402 OPENSSL_CTX_set0_default(tmpctx);
403 if (tmpctx != globalctx) {
405 "test_ASYNC_start_job_with_libctx() failed - global libctx check failed\n");
411 ASYNC_WAIT_CTX_free(waitctx);
412 OPENSSL_CTX_free(libctx);
416 int main(int argc, char **argv)
418 if (!ASYNC_is_capable()) {
420 "OpenSSL build is not ASYNC capable - skipping async tests\n");
422 if (!test_ASYNC_init_thread()
423 || !test_ASYNC_callback_status()
424 || !test_ASYNC_start_job()
425 || !test_ASYNC_get_current_job()
426 || !test_ASYNC_WAIT_CTX_get_all_fds()
427 || !test_ASYNC_block_pause()
428 || !test_ASYNC_start_job_with_libctx()) {