Use minimum and maximum protocol version instead of version fixed methods
[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 = NULL;
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 = NULL;
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 = NULL;
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 = NULL;
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 = NULL;
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 }