]> git.ipfire.org Git - thirdparty/openssl.git/blame - test/asynctest.c
Refactor the async wait fd logic
[thirdparty/openssl.git] / test / asynctest.c
CommitLineData
5705e050
MC
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
8d35ceb9 64#if (defined(OPENSSL_SYS_UNIX) || defined(OPENSSL_SYS_CYGWIN)) && defined(OPENSSL_THREADS)
5705e050
MC
65# include <unistd.h>
66# if _POSIX_VERSION >= 200112L
67# define ASYNC_POSIX
68# endif
8d35ceb9 69#elif defined(_WIN32)
5705e050
MC
70# define ASYNC_WIN
71#endif
72
73#if !defined(ASYNC_POSIX) && !defined(ASYNC_WIN)
74# define ASYNC_NULL
75#endif
76
7240557b
MC
77#ifndef ASYNC_NULL
78
5705e050
MC
79static int ctr = 0;
80static ASYNC_JOB *currjob = NULL;
81
82static int only_pause(void *args)
83{
84 ASYNC_pause_job();
85
86 return 1;
87}
88
89static int add_two(void *args)
90{
91 ctr++;
92 ASYNC_pause_job();
93 ctr++;
94
95 return 2;
96}
97
98static int save_current(void *args)
99{
100 currjob = ASYNC_get_current_job();
101 ASYNC_pause_job();
102
103 return 1;
104}
105
ff75a257
MC
106#define MAGIC_WAIT_FD ((OSSL_ASYNC_FD)99)
107static int waitfd(void *args)
5705e050 108{
ff75a257
MC
109 ASYNC_JOB *job;
110 ASYNC_WAIT_CTX *waitctx;
5705e050 111 ASYNC_pause_job();
ff75a257
MC
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;
5705e050 120 ASYNC_pause_job();
ff75a257
MC
121
122 if (!ASYNC_WAIT_CTX_clear_fd(waitctx, waitctx))
123 return 0;
5705e050
MC
124
125 return 1;
126}
127
e8dfb5bf
MC
128static 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
7b9f8f7f 138static int test_ASYNC_init_thread()
5705e050
MC
139{
140 ASYNC_JOB *job1 = NULL, *job2 = NULL, *job3 = NULL;
141 int funcret1, funcret2, funcret3;
ff75a257 142 ASYNC_WAIT_CTX *waitctx;
5705e050 143
7b9f8f7f 144 if ( !ASYNC_init_thread(2, 0)
ff75a257
MC
145 || (waitctx = ASYNC_WAIT_CTX_new()) == NULL
146 || ASYNC_start_job(&job1, waitctx, &funcret1, only_pause, NULL, 0)
5705e050 147 != ASYNC_PAUSE
ff75a257 148 || ASYNC_start_job(&job2, waitctx, &funcret2, only_pause, NULL, 0)
5705e050 149 != ASYNC_PAUSE
ff75a257 150 || ASYNC_start_job(&job3, waitctx, &funcret3, only_pause, NULL, 0)
5705e050 151 != ASYNC_NO_JOBS
ff75a257 152 || ASYNC_start_job(&job1, waitctx, &funcret1, only_pause, NULL, 0)
5705e050 153 != ASYNC_FINISH
ff75a257 154 || ASYNC_start_job(&job3, waitctx, &funcret3, only_pause, NULL, 0)
5705e050 155 != ASYNC_PAUSE
ff75a257 156 || ASYNC_start_job(&job2, waitctx, &funcret2, only_pause, NULL, 0)
5705e050 157 != ASYNC_FINISH
ff75a257 158 || ASYNC_start_job(&job3, waitctx, &funcret3, only_pause, NULL, 0)
5705e050
MC
159 != ASYNC_FINISH
160 || funcret1 != 1
161 || funcret2 != 1
162 || funcret3 != 1) {
7b9f8f7f 163 fprintf(stderr, "test_ASYNC_init_thread() failed\n");
ff75a257 164 ASYNC_WAIT_CTX_free(waitctx);
7b9f8f7f 165 ASYNC_cleanup_thread();
5705e050
MC
166 return 0;
167 }
168
ff75a257 169 ASYNC_WAIT_CTX_free(waitctx);
7b9f8f7f 170 ASYNC_cleanup_thread();
5705e050
MC
171 return 1;
172}
173
174static int test_ASYNC_start_job()
175{
176 ASYNC_JOB *job = NULL;
177 int funcret;
ff75a257 178 ASYNC_WAIT_CTX *waitctx;
5705e050
MC
179
180 ctr = 0;
181
7b9f8f7f 182 if ( !ASYNC_init_thread(1, 0)
ff75a257
MC
183 || (waitctx = ASYNC_WAIT_CTX_new()) == NULL
184 || ASYNC_start_job(&job, waitctx, &funcret, add_two, NULL, 0)
185 != ASYNC_PAUSE
5705e050 186 || ctr != 1
ff75a257
MC
187 || ASYNC_start_job(&job, waitctx, &funcret, add_two, NULL, 0)
188 != ASYNC_FINISH
5705e050
MC
189 || ctr != 2
190 || funcret != 2) {
191 fprintf(stderr, "test_ASYNC_start_job() failed\n");
ff75a257 192 ASYNC_WAIT_CTX_free(waitctx);
7b9f8f7f 193 ASYNC_cleanup_thread();
5705e050
MC
194 return 0;
195 }
196
ff75a257 197 ASYNC_WAIT_CTX_free(waitctx);
7b9f8f7f 198 ASYNC_cleanup_thread();
5705e050
MC
199 return 1;
200}
201
202static int test_ASYNC_get_current_job()
203{
204 ASYNC_JOB *job = NULL;
205 int funcret;
ff75a257 206 ASYNC_WAIT_CTX *waitctx;
5705e050
MC
207
208 currjob = NULL;
209
7b9f8f7f 210 if ( !ASYNC_init_thread(1, 0)
ff75a257
MC
211 || (waitctx = ASYNC_WAIT_CTX_new()) == NULL
212 || ASYNC_start_job(&job, waitctx, &funcret, save_current, NULL, 0)
5705e050
MC
213 != ASYNC_PAUSE
214 || currjob != job
ff75a257 215 || ASYNC_start_job(&job, waitctx, &funcret, save_current, NULL, 0)
5705e050
MC
216 != ASYNC_FINISH
217 || funcret != 1) {
218 fprintf(stderr, "test_ASYNC_get_current_job() failed\n");
ff75a257 219 ASYNC_WAIT_CTX_free(waitctx);
7b9f8f7f 220 ASYNC_cleanup_thread();
5705e050
MC
221 return 0;
222 }
223
ff75a257 224 ASYNC_WAIT_CTX_free(waitctx);
7b9f8f7f 225 ASYNC_cleanup_thread();
5705e050
MC
226 return 1;
227}
228
ff75a257 229static int test_ASYNC_WAIT_CTX_get_all_fds()
5705e050
MC
230{
231 ASYNC_JOB *job = NULL;
2b2c78d4 232 int funcret;
ff75a257
MC
233 ASYNC_WAIT_CTX *waitctx;
234 OSSL_ASYNC_FD fd = OSSL_BAD_ASYNC_FD, delfd = OSSL_BAD_ASYNC_FD;
235 size_t numfds, numdelfds;
5705e050 236
7b9f8f7f 237 if ( !ASYNC_init_thread(1, 0)
ff75a257
MC
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)
5705e050 241 != ASYNC_PAUSE
ff75a257
MC
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)
5705e050 250 != ASYNC_PAUSE
ff75a257
MC
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)
5705e050 265 != ASYNC_FINISH
ff75a257
MC
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
5705e050
MC
275 || funcret != 1) {
276 fprintf(stderr, "test_ASYNC_get_wait_fd() failed\n");
ff75a257 277 ASYNC_WAIT_CTX_free(waitctx);
7b9f8f7f 278 ASYNC_cleanup_thread();
5705e050
MC
279 return 0;
280 }
281
ff75a257 282 ASYNC_WAIT_CTX_free(waitctx);
7b9f8f7f 283 ASYNC_cleanup_thread();
5705e050
MC
284 return 1;
285}
e8dfb5bf
MC
286
287static int test_ASYNC_block_pause()
288{
289 ASYNC_JOB *job = NULL;
290 int funcret;
ff75a257 291 ASYNC_WAIT_CTX *waitctx;
e8dfb5bf 292
7b9f8f7f 293 if ( !ASYNC_init_thread(1, 0)
ff75a257
MC
294 || (waitctx = ASYNC_WAIT_CTX_new()) == NULL
295 || ASYNC_start_job(&job, waitctx, &funcret, blockpause, NULL, 0)
e8dfb5bf 296 != ASYNC_PAUSE
ff75a257 297 || ASYNC_start_job(&job, waitctx, &funcret, blockpause, NULL, 0)
e8dfb5bf
MC
298 != ASYNC_FINISH
299 || funcret != 1) {
300 fprintf(stderr, "test_ASYNC_block_pause() failed\n");
ff75a257 301 ASYNC_WAIT_CTX_free(waitctx);
7b9f8f7f 302 ASYNC_cleanup_thread();
e8dfb5bf
MC
303 return 0;
304 }
305
ff75a257 306 ASYNC_WAIT_CTX_free(waitctx);
7b9f8f7f 307 ASYNC_cleanup_thread();
e8dfb5bf
MC
308 return 1;
309}
310
7240557b 311#endif
5705e050
MC
312
313int main(int argc, char **argv)
314{
315
316#ifdef ASYNC_NULL
317 fprintf(stderr, "NULL implementation - skipping async tests\n");
318#else
bbd86bf5 319 CRYPTO_set_mem_debug(1);
5705e050
MC
320 CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);
321
7b9f8f7f 322 if ( !test_ASYNC_init_thread()
5705e050
MC
323 || !test_ASYNC_start_job()
324 || !test_ASYNC_get_current_job()
ff75a257 325 || !test_ASYNC_WAIT_CTX_get_all_fds()
e8dfb5bf 326 || !test_ASYNC_block_pause()) {
5705e050
MC
327 return 1;
328 }
329#endif
330 printf("PASS\n");
331 return 0;
332}