]>
Commit | Line | Data |
---|---|---|
5705e050 | 1 | /* |
e39e295e | 2 | * Copyright 2015-2020 The OpenSSL Project Authors. All Rights Reserved. |
5705e050 | 3 | * |
909f1a2e | 4 | * Licensed under the Apache License 2.0 (the "License"). You may not use |
440e5d80 RS |
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 | |
5705e050 MC |
8 | */ |
9 | ||
f1f5ee17 AP |
10 | #ifdef _WIN32 |
11 | # include <windows.h> | |
12 | #endif | |
13 | ||
5705e050 MC |
14 | #include <stdio.h> |
15 | #include <string.h> | |
16 | #include <openssl/async.h> | |
17 | #include <openssl/crypto.h> | |
5705e050 | 18 | |
5705e050 MC |
19 | static int ctr = 0; |
20 | static ASYNC_JOB *currjob = NULL; | |
21 | ||
22 | static int only_pause(void *args) | |
23 | { | |
24 | ASYNC_pause_job(); | |
25 | ||
26 | return 1; | |
27 | } | |
28 | ||
29 | static int add_two(void *args) | |
30 | { | |
31 | ctr++; | |
32 | ASYNC_pause_job(); | |
33 | ctr++; | |
34 | ||
35 | return 2; | |
36 | } | |
37 | ||
38 | static int save_current(void *args) | |
39 | { | |
40 | currjob = ASYNC_get_current_job(); | |
41 | ASYNC_pause_job(); | |
42 | ||
43 | return 1; | |
44 | } | |
45 | ||
92db29e5 MC |
46 | static int change_deflt_libctx(void *args) |
47 | { | |
48 | OPENSSL_CTX *libctx = OPENSSL_CTX_new(); | |
49 | OPENSSL_CTX *oldctx, *tmpctx; | |
50 | int ret = 0; | |
51 | ||
52 | if (libctx == NULL) | |
53 | return 0; | |
54 | ||
55 | oldctx = OPENSSL_CTX_set0_default(libctx); | |
56 | ASYNC_pause_job(); | |
57 | ||
58 | /* Check the libctx is set up as we expect */ | |
59 | tmpctx = OPENSSL_CTX_set0_default(oldctx); | |
60 | if (tmpctx != libctx) | |
61 | goto err; | |
62 | ||
63 | /* Set it back again to continue to use our own libctx */ | |
64 | oldctx = OPENSSL_CTX_set0_default(libctx); | |
65 | ASYNC_pause_job(); | |
66 | ||
67 | /* Check the libctx is set up as we expect */ | |
68 | tmpctx = OPENSSL_CTX_set0_default(oldctx); | |
69 | if (tmpctx != libctx) | |
70 | goto err; | |
71 | ||
72 | ret = 1; | |
73 | err: | |
74 | OPENSSL_CTX_free(libctx); | |
75 | return ret; | |
76 | } | |
77 | ||
78 | ||
ff75a257 MC |
79 | #define MAGIC_WAIT_FD ((OSSL_ASYNC_FD)99) |
80 | static int waitfd(void *args) | |
5705e050 | 81 | { |
ff75a257 MC |
82 | ASYNC_JOB *job; |
83 | ASYNC_WAIT_CTX *waitctx; | |
ff75a257 MC |
84 | job = ASYNC_get_current_job(); |
85 | if (job == NULL) | |
86 | return 0; | |
87 | waitctx = ASYNC_get_wait_ctx(job); | |
88 | if (waitctx == NULL) | |
89 | return 0; | |
f44e6364 AG |
90 | |
91 | /* First case: no fd added or removed */ | |
92 | ASYNC_pause_job(); | |
93 | ||
94 | /* Second case: one fd added */ | |
e8aa8b6c | 95 | if (!ASYNC_WAIT_CTX_set_wait_fd(waitctx, waitctx, MAGIC_WAIT_FD, NULL, NULL)) |
ff75a257 | 96 | return 0; |
5705e050 | 97 | ASYNC_pause_job(); |
ff75a257 | 98 | |
f44e6364 AG |
99 | /* Third case: all fd removed */ |
100 | if (!ASYNC_WAIT_CTX_clear_fd(waitctx, waitctx)) | |
101 | return 0; | |
102 | ASYNC_pause_job(); | |
103 | ||
104 | /* Last case: fd added and immediately removed */ | |
105 | if (!ASYNC_WAIT_CTX_set_wait_fd(waitctx, waitctx, MAGIC_WAIT_FD, NULL, NULL)) | |
106 | return 0; | |
ff75a257 MC |
107 | if (!ASYNC_WAIT_CTX_clear_fd(waitctx, waitctx)) |
108 | return 0; | |
5705e050 MC |
109 | |
110 | return 1; | |
111 | } | |
112 | ||
e8dfb5bf MC |
113 | static int blockpause(void *args) |
114 | { | |
115 | ASYNC_block_pause(); | |
116 | ASYNC_pause_job(); | |
117 | ASYNC_unblock_pause(); | |
118 | ASYNC_pause_job(); | |
119 | ||
120 | return 1; | |
121 | } | |
122 | ||
3cb7c5cf | 123 | static int test_ASYNC_init_thread(void) |
5705e050 MC |
124 | { |
125 | ASYNC_JOB *job1 = NULL, *job2 = NULL, *job3 = NULL; | |
126 | int funcret1, funcret2, funcret3; | |
174a74ef | 127 | ASYNC_WAIT_CTX *waitctx = NULL; |
5705e050 | 128 | |
7b9f8f7f | 129 | if ( !ASYNC_init_thread(2, 0) |
ff75a257 MC |
130 | || (waitctx = ASYNC_WAIT_CTX_new()) == NULL |
131 | || ASYNC_start_job(&job1, waitctx, &funcret1, only_pause, NULL, 0) | |
5705e050 | 132 | != ASYNC_PAUSE |
ff75a257 | 133 | || ASYNC_start_job(&job2, waitctx, &funcret2, only_pause, NULL, 0) |
5705e050 | 134 | != ASYNC_PAUSE |
ff75a257 | 135 | || ASYNC_start_job(&job3, waitctx, &funcret3, only_pause, NULL, 0) |
5705e050 | 136 | != ASYNC_NO_JOBS |
ff75a257 | 137 | || ASYNC_start_job(&job1, waitctx, &funcret1, only_pause, NULL, 0) |
5705e050 | 138 | != ASYNC_FINISH |
ff75a257 | 139 | || ASYNC_start_job(&job3, waitctx, &funcret3, only_pause, NULL, 0) |
5705e050 | 140 | != ASYNC_PAUSE |
ff75a257 | 141 | || ASYNC_start_job(&job2, waitctx, &funcret2, only_pause, NULL, 0) |
5705e050 | 142 | != ASYNC_FINISH |
ff75a257 | 143 | || ASYNC_start_job(&job3, waitctx, &funcret3, only_pause, NULL, 0) |
5705e050 MC |
144 | != ASYNC_FINISH |
145 | || funcret1 != 1 | |
146 | || funcret2 != 1 | |
147 | || funcret3 != 1) { | |
7b9f8f7f | 148 | fprintf(stderr, "test_ASYNC_init_thread() failed\n"); |
ff75a257 | 149 | ASYNC_WAIT_CTX_free(waitctx); |
7b9f8f7f | 150 | ASYNC_cleanup_thread(); |
5705e050 MC |
151 | return 0; |
152 | } | |
153 | ||
ff75a257 | 154 | ASYNC_WAIT_CTX_free(waitctx); |
7b9f8f7f | 155 | ASYNC_cleanup_thread(); |
5705e050 MC |
156 | return 1; |
157 | } | |
158 | ||
9f5a87fd PY |
159 | static int test_callback(void *arg) |
160 | { | |
161 | printf("callback test pass\n"); | |
162 | return 1; | |
163 | } | |
164 | ||
165 | static int test_ASYNC_callback_status(void) | |
166 | { | |
167 | ASYNC_WAIT_CTX *waitctx = NULL; | |
168 | int set_arg = 100; | |
169 | ASYNC_callback_fn get_callback; | |
170 | void *get_arg; | |
171 | int set_status = 1; | |
172 | ||
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) | |
176 | != 1 | |
177 | || ASYNC_WAIT_CTX_get_callback(waitctx, &get_callback, &get_arg) | |
178 | != 1 | |
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(); | |
187 | return 0; | |
188 | } | |
189 | ||
190 | ASYNC_WAIT_CTX_free(waitctx); | |
191 | ASYNC_cleanup_thread(); | |
192 | return 1; | |
193 | ||
194 | } | |
195 | ||
3cb7c5cf | 196 | static int test_ASYNC_start_job(void) |
5705e050 MC |
197 | { |
198 | ASYNC_JOB *job = NULL; | |
199 | int funcret; | |
174a74ef | 200 | ASYNC_WAIT_CTX *waitctx = NULL; |
5705e050 MC |
201 | |
202 | ctr = 0; | |
203 | ||
7b9f8f7f | 204 | if ( !ASYNC_init_thread(1, 0) |
ff75a257 MC |
205 | || (waitctx = ASYNC_WAIT_CTX_new()) == NULL |
206 | || ASYNC_start_job(&job, waitctx, &funcret, add_two, NULL, 0) | |
207 | != ASYNC_PAUSE | |
5705e050 | 208 | || ctr != 1 |
ff75a257 MC |
209 | || ASYNC_start_job(&job, waitctx, &funcret, add_two, NULL, 0) |
210 | != ASYNC_FINISH | |
5705e050 MC |
211 | || ctr != 2 |
212 | || funcret != 2) { | |
213 | fprintf(stderr, "test_ASYNC_start_job() failed\n"); | |
ff75a257 | 214 | ASYNC_WAIT_CTX_free(waitctx); |
7b9f8f7f | 215 | ASYNC_cleanup_thread(); |
5705e050 MC |
216 | return 0; |
217 | } | |
218 | ||
ff75a257 | 219 | ASYNC_WAIT_CTX_free(waitctx); |
7b9f8f7f | 220 | ASYNC_cleanup_thread(); |
5705e050 MC |
221 | return 1; |
222 | } | |
223 | ||
3cb7c5cf | 224 | static int test_ASYNC_get_current_job(void) |
5705e050 MC |
225 | { |
226 | ASYNC_JOB *job = NULL; | |
227 | int funcret; | |
174a74ef | 228 | ASYNC_WAIT_CTX *waitctx = NULL; |
5705e050 MC |
229 | |
230 | currjob = NULL; | |
231 | ||
7b9f8f7f | 232 | if ( !ASYNC_init_thread(1, 0) |
ff75a257 MC |
233 | || (waitctx = ASYNC_WAIT_CTX_new()) == NULL |
234 | || ASYNC_start_job(&job, waitctx, &funcret, save_current, NULL, 0) | |
5705e050 MC |
235 | != ASYNC_PAUSE |
236 | || currjob != job | |
ff75a257 | 237 | || ASYNC_start_job(&job, waitctx, &funcret, save_current, NULL, 0) |
5705e050 MC |
238 | != ASYNC_FINISH |
239 | || funcret != 1) { | |
240 | fprintf(stderr, "test_ASYNC_get_current_job() failed\n"); | |
ff75a257 | 241 | ASYNC_WAIT_CTX_free(waitctx); |
7b9f8f7f | 242 | ASYNC_cleanup_thread(); |
5705e050 MC |
243 | return 0; |
244 | } | |
245 | ||
ff75a257 | 246 | ASYNC_WAIT_CTX_free(waitctx); |
7b9f8f7f | 247 | ASYNC_cleanup_thread(); |
5705e050 MC |
248 | return 1; |
249 | } | |
250 | ||
3cb7c5cf | 251 | static int test_ASYNC_WAIT_CTX_get_all_fds(void) |
5705e050 MC |
252 | { |
253 | ASYNC_JOB *job = NULL; | |
2b2c78d4 | 254 | int funcret; |
174a74ef | 255 | ASYNC_WAIT_CTX *waitctx = NULL; |
ff75a257 MC |
256 | OSSL_ASYNC_FD fd = OSSL_BAD_ASYNC_FD, delfd = OSSL_BAD_ASYNC_FD; |
257 | size_t numfds, numdelfds; | |
5705e050 | 258 | |
7b9f8f7f | 259 | if ( !ASYNC_init_thread(1, 0) |
ff75a257 MC |
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) | |
5705e050 | 263 | != ASYNC_PAUSE |
ff75a257 MC |
264 | || !ASYNC_WAIT_CTX_get_all_fds(waitctx, NULL, &numfds) |
265 | || numfds != 0 | |
266 | || !ASYNC_WAIT_CTX_get_changed_fds(waitctx, NULL, &numfds, NULL, | |
267 | &numdelfds) | |
268 | || numfds != 0 | |
269 | || numdelfds != 0 | |
270 | /* On second run we're expecting one added fd */ | |
271 | || ASYNC_start_job(&job, waitctx, &funcret, waitfd, NULL, 0) | |
5705e050 | 272 | != ASYNC_PAUSE |
ff75a257 MC |
273 | || !ASYNC_WAIT_CTX_get_all_fds(waitctx, NULL, &numfds) |
274 | || numfds != 1 | |
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, | |
f44e6364 | 279 | &numdelfds) |
ff75a257 MC |
280 | || numfds != 1 |
281 | || numdelfds != 0 | |
282 | || !ASYNC_WAIT_CTX_get_changed_fds(waitctx, &fd, &numfds, NULL, | |
283 | &numdelfds) | |
284 | || fd != MAGIC_WAIT_FD | |
f44e6364 | 285 | /* On third run we expect one deleted fd */ |
ff75a257 | 286 | || ASYNC_start_job(&job, waitctx, &funcret, waitfd, NULL, 0) |
f44e6364 | 287 | != ASYNC_PAUSE |
ff75a257 MC |
288 | || !ASYNC_WAIT_CTX_get_all_fds(waitctx, NULL, &numfds) |
289 | || numfds != 0 | |
290 | || !ASYNC_WAIT_CTX_get_changed_fds(waitctx, NULL, &numfds, NULL, | |
291 | &numdelfds) | |
292 | || numfds != 0 | |
293 | || numdelfds != 1 | |
294 | || !ASYNC_WAIT_CTX_get_changed_fds(waitctx, NULL, &numfds, &delfd, | |
295 | &numdelfds) | |
296 | || delfd != MAGIC_WAIT_FD | |
f44e6364 AG |
297 | /* On last run we are not expecting any wait fd */ |
298 | || ASYNC_start_job(&job, waitctx, &funcret, waitfd, NULL, 0) | |
299 | != ASYNC_FINISH | |
300 | || !ASYNC_WAIT_CTX_get_all_fds(waitctx, NULL, &numfds) | |
301 | || numfds != 0 | |
302 | || !ASYNC_WAIT_CTX_get_changed_fds(waitctx, NULL, &numfds, NULL, | |
303 | &numdelfds) | |
304 | || numfds != 0 | |
305 | || numdelfds != 0 | |
5705e050 MC |
306 | || funcret != 1) { |
307 | fprintf(stderr, "test_ASYNC_get_wait_fd() failed\n"); | |
ff75a257 | 308 | ASYNC_WAIT_CTX_free(waitctx); |
7b9f8f7f | 309 | ASYNC_cleanup_thread(); |
5705e050 MC |
310 | return 0; |
311 | } | |
312 | ||
ff75a257 | 313 | ASYNC_WAIT_CTX_free(waitctx); |
7b9f8f7f | 314 | ASYNC_cleanup_thread(); |
5705e050 MC |
315 | return 1; |
316 | } | |
e8dfb5bf | 317 | |
3cb7c5cf | 318 | static int test_ASYNC_block_pause(void) |
e8dfb5bf MC |
319 | { |
320 | ASYNC_JOB *job = NULL; | |
321 | int funcret; | |
174a74ef | 322 | ASYNC_WAIT_CTX *waitctx = NULL; |
e8dfb5bf | 323 | |
7b9f8f7f | 324 | if ( !ASYNC_init_thread(1, 0) |
ff75a257 MC |
325 | || (waitctx = ASYNC_WAIT_CTX_new()) == NULL |
326 | || ASYNC_start_job(&job, waitctx, &funcret, blockpause, NULL, 0) | |
e8dfb5bf | 327 | != ASYNC_PAUSE |
ff75a257 | 328 | || ASYNC_start_job(&job, waitctx, &funcret, blockpause, NULL, 0) |
e8dfb5bf MC |
329 | != ASYNC_FINISH |
330 | || funcret != 1) { | |
331 | fprintf(stderr, "test_ASYNC_block_pause() failed\n"); | |
ff75a257 | 332 | ASYNC_WAIT_CTX_free(waitctx); |
7b9f8f7f | 333 | ASYNC_cleanup_thread(); |
e8dfb5bf MC |
334 | return 0; |
335 | } | |
336 | ||
ff75a257 | 337 | ASYNC_WAIT_CTX_free(waitctx); |
7b9f8f7f | 338 | ASYNC_cleanup_thread(); |
e8dfb5bf MC |
339 | return 1; |
340 | } | |
341 | ||
d8652be0 | 342 | static int test_ASYNC_start_job_ex(void) |
92db29e5 MC |
343 | { |
344 | ASYNC_JOB *job = NULL; | |
345 | int funcret; | |
346 | ASYNC_WAIT_CTX *waitctx = NULL; | |
347 | OPENSSL_CTX *libctx = OPENSSL_CTX_new(); | |
348 | OPENSSL_CTX *oldctx, *tmpctx, *globalctx; | |
349 | int ret = 0; | |
350 | ||
351 | if (libctx == NULL) { | |
352 | fprintf(stderr, | |
d8652be0 | 353 | "test_ASYNC_start_job_ex() failed to create libctx\n"); |
92db29e5 MC |
354 | goto err; |
355 | } | |
356 | ||
357 | globalctx = oldctx = OPENSSL_CTX_set0_default(libctx); | |
358 | ||
359 | if ((waitctx = ASYNC_WAIT_CTX_new()) == NULL | |
360 | || ASYNC_start_job(&job, waitctx, &funcret, change_deflt_libctx, | |
361 | NULL, 0) | |
362 | != ASYNC_PAUSE) { | |
363 | fprintf(stderr, | |
d8652be0 | 364 | "test_ASYNC_start_job_ex() failed to start job\n"); |
92db29e5 MC |
365 | goto err; |
366 | } | |
367 | ||
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) { | |
372 | fprintf(stderr, | |
d8652be0 | 373 | "test_ASYNC_start_job_ex() failed - unexpected libctx\n"); |
92db29e5 MC |
374 | goto err; |
375 | } | |
376 | ||
377 | if (ASYNC_start_job(&job, waitctx, &funcret, change_deflt_libctx, NULL, 0) | |
378 | != ASYNC_PAUSE) { | |
379 | fprintf(stderr, | |
d8652be0 | 380 | "test_ASYNC_start_job_ex() - restarting job failed\n"); |
92db29e5 MC |
381 | goto err; |
382 | } | |
383 | ||
384 | /* Reset the libctx and continue with the global default libctx */ | |
385 | tmpctx = OPENSSL_CTX_set0_default(oldctx); | |
386 | if (tmpctx != libctx) { | |
387 | fprintf(stderr, | |
d8652be0 | 388 | "test_ASYNC_start_job_ex() failed - unexpected libctx\n"); |
92db29e5 MC |
389 | goto err; |
390 | } | |
391 | ||
392 | if (ASYNC_start_job(&job, waitctx, &funcret, change_deflt_libctx, NULL, 0) | |
393 | != ASYNC_FINISH | |
394 | || funcret != 1) { | |
395 | fprintf(stderr, | |
d8652be0 | 396 | "test_ASYNC_start_job_ex() - finishing job failed\n"); |
92db29e5 MC |
397 | goto err; |
398 | } | |
399 | ||
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) { | |
404 | fprintf(stderr, | |
d8652be0 | 405 | "test_ASYNC_start_job_ex() failed - global libctx check failed\n"); |
92db29e5 MC |
406 | goto err; |
407 | } | |
408 | ||
409 | ret = 1; | |
410 | err: | |
411 | ASYNC_WAIT_CTX_free(waitctx); | |
412 | OPENSSL_CTX_free(libctx); | |
413 | return ret; | |
414 | } | |
415 | ||
5705e050 MC |
416 | int main(int argc, char **argv) |
417 | { | |
c521edc3 MC |
418 | if (!ASYNC_is_capable()) { |
419 | fprintf(stderr, | |
420 | "OpenSSL build is not ASYNC capable - skipping async tests\n"); | |
421 | } else { | |
742ccab3 | 422 | if (!test_ASYNC_init_thread() |
9f5a87fd | 423 | || !test_ASYNC_callback_status() |
c521edc3 MC |
424 | || !test_ASYNC_start_job() |
425 | || !test_ASYNC_get_current_job() | |
426 | || !test_ASYNC_WAIT_CTX_get_all_fds() | |
92db29e5 | 427 | || !test_ASYNC_block_pause() |
d8652be0 | 428 | || !test_ASYNC_start_job_ex()) { |
c521edc3 MC |
429 | return 1; |
430 | } | |
5705e050 | 431 | } |
5705e050 MC |
432 | printf("PASS\n"); |
433 | return 0; | |
434 | } |