Add ASYNC tests
[openssl.git] / test / asynctest.c
1 /* test/asynctest.c */
2 /*
3  * Written by Matt Caswell for the OpenSSL project.
4  */
5 /* ====================================================================
6  * Copyright (c) 2015 The OpenSSL Project.  All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in
17  *    the documentation and/or other materials provided with the
18  *    distribution.
19  *
20  * 3. All advertising materials mentioning features or use of this
21  *    software must display the following acknowledgment:
22  *    "This product includes software developed by the OpenSSL Project
23  *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
24  *
25  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26  *    endorse or promote products derived from this software without
27  *    prior written permission. For written permission, please contact
28  *    openssl-core@openssl.org.
29  *
30  * 5. Products derived from this software may not be called "OpenSSL"
31  *    nor may "OpenSSL" appear in their names without prior written
32  *    permission of the OpenSSL Project.
33  *
34  * 6. Redistributions of any form whatsoever must retain the following
35  *    acknowledgment:
36  *    "This product includes software developed by the OpenSSL Project
37  *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
38  *
39  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
43  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50  * OF THE POSSIBILITY OF SUCH DAMAGE.
51  * ====================================================================
52  *
53  * This product includes cryptographic software written by Eric Young
54  * (eay@cryptsoft.com).  This product includes software written by Tim
55  * Hudson (tjh@cryptsoft.com).
56  *
57  */
58
59 #include <stdio.h>
60 #include <string.h>
61 #include <openssl/async.h>
62 #include <openssl/crypto.h>
63 #include <../apps/apps.h>
64
65 #ifdef OPENSSL_SYS_UNIX
66 # include <unistd.h>
67 # if _POSIX_VERSION >= 200112L
68 #  define ASYNC_POSIX
69 # endif
70 #elif (defined(_WIN32) || defined(__CYGWIN__)) && defined(_WINDLL)
71 # define ASYNC_WIN
72 #endif
73
74 #if !defined(ASYNC_POSIX) && !defined(ASYNC_WIN)
75 # define ASYNC_NULL
76 #endif
77
78 static int ctr = 0;
79 static ASYNC_JOB *currjob = NULL;
80
81 static int only_pause(void *args)
82 {
83     ASYNC_pause_job();
84
85     return 1;
86 }
87
88 static int add_two(void *args)
89 {
90     ctr++;
91     ASYNC_pause_job();
92     ctr++;
93
94     return 2;
95 }
96
97 static int save_current(void *args)
98 {
99     currjob = ASYNC_get_current_job();
100     ASYNC_pause_job();
101
102     return 1;
103 }
104
105 static int wake(void *args)
106 {
107     ASYNC_pause_job();
108     ASYNC_wake(ASYNC_get_current_job());
109     ASYNC_pause_job();
110     ASYNC_clear_wake(ASYNC_get_current_job());
111
112     return 1;
113 }
114
115 static int test_ASYNC_init_pool()
116 {
117     ASYNC_JOB *job1 = NULL, *job2 = NULL, *job3 = NULL;
118     int funcret1, funcret2, funcret3;
119
120     if (       !ASYNC_init_pool(2, 0)
121             || ASYNC_start_job(&job1, &funcret1, only_pause, NULL, 0)
122                 != ASYNC_PAUSE
123             || ASYNC_start_job(&job2, &funcret2, only_pause, NULL, 0)
124                 != ASYNC_PAUSE
125             || ASYNC_start_job(&job3, &funcret3, only_pause, NULL, 0)
126                 != ASYNC_NO_JOBS
127             || ASYNC_start_job(&job1, &funcret1, only_pause, NULL, 0)
128                 != ASYNC_FINISH
129             || ASYNC_start_job(&job3, &funcret3, only_pause, NULL, 0)
130                 != ASYNC_PAUSE
131             || ASYNC_start_job(&job2, &funcret2, only_pause, NULL, 0)
132                 != ASYNC_FINISH
133             || ASYNC_start_job(&job3, &funcret3, only_pause, NULL, 0)
134                 != ASYNC_FINISH
135             || funcret1 != 1
136             || funcret2 != 1
137             || funcret3 != 1) {
138         fprintf(stderr, "test_ASYNC_init_pool() failed\n");
139         ASYNC_free_pool();
140         return 0;
141     }
142
143     ASYNC_free_pool();
144     return 1;
145 }
146
147 static int test_ASYNC_start_job()
148 {
149     ASYNC_JOB *job = NULL;
150     int funcret;
151
152     ctr = 0;
153
154     if (       !ASYNC_init_pool(1, 0)
155             || ASYNC_start_job(&job, &funcret, add_two, NULL, 0) != ASYNC_PAUSE
156             || ctr != 1
157             || ASYNC_start_job(&job, &funcret, add_two, NULL, 0) != ASYNC_FINISH
158             || ctr != 2
159             || funcret != 2) {
160         fprintf(stderr, "test_ASYNC_start_job() failed\n");
161         ASYNC_free_pool();
162         return 0;
163     }
164
165     ASYNC_free_pool();
166     return 1;
167 }
168
169 static int test_ASYNC_get_current_job()
170 {
171     ASYNC_JOB *job = NULL;
172     int funcret;
173
174     currjob = NULL;
175
176     if (       !ASYNC_init_pool(1, 0)
177             || ASYNC_start_job(&job, &funcret, save_current, NULL, 0)
178                 != ASYNC_PAUSE
179             || currjob != job
180             || ASYNC_start_job(&job, &funcret, save_current, NULL, 0)
181                 != ASYNC_FINISH
182             || funcret != 1) {
183         fprintf(stderr, "test_ASYNC_get_current_job() failed\n");
184         ASYNC_free_pool();
185         return 0;
186     }
187
188     ASYNC_free_pool();
189     return 1;
190 }
191
192 static int hasdata(int fd)
193 {
194     fd_set checkfds;
195     struct timeval tv;
196     FD_ZERO(&checkfds);
197     openssl_fdset(fd, &checkfds);
198     memset(&tv, 0, sizeof tv);
199     if (select(fd + 1, (void *)&checkfds, NULL, NULL, &tv) < 0)
200         return -1;
201     if (FD_ISSET(fd, &checkfds))
202         return 1;
203     return 0;
204 }
205
206 static int test_ASYNC_get_wait_fd()
207 {
208     ASYNC_JOB *job = NULL;
209     int funcret, fd;
210
211     currjob = NULL;
212
213     if (       !ASYNC_init_pool(1, 0)
214             || ASYNC_start_job(&job, &funcret, wake, NULL, 0)
215                 != ASYNC_PAUSE
216             || (fd = ASYNC_get_wait_fd(job)) < 0
217             || hasdata(fd) != 0
218             || ASYNC_start_job(&job, &funcret, save_current, NULL, 0)
219                 != ASYNC_PAUSE
220             || hasdata(fd) != 1
221             || (ASYNC_clear_wake(job), 0)
222             || hasdata(fd) != 0
223             || (ASYNC_wake(job), 0)
224             || hasdata(fd) != 1
225             || ASYNC_start_job(&job, &funcret, save_current, NULL, 0)
226                 != ASYNC_FINISH
227             || funcret != 1) {
228         fprintf(stderr, "test_ASYNC_get_wait_fd() failed\n");
229         ASYNC_free_pool();
230         return 0;
231     }
232
233     ASYNC_free_pool();
234     return 1;
235 }
236
237 int main(int argc, char **argv)
238 {
239
240 #ifdef ASYNC_NULL
241     fprintf(stderr, "NULL implementation - skipping async tests\n");
242 #else
243     CRYPTO_malloc_debug_init();
244     CRYPTO_set_mem_debug_options(V_CRYPTO_MDEBUG_ALL);
245     CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);
246
247     if (       !test_ASYNC_init_pool()
248             || !test_ASYNC_start_job()
249             || !test_ASYNC_get_current_job()
250             || !test_ASYNC_get_wait_fd()) {
251         return 1;
252     }
253 #endif
254     printf("PASS\n");
255     return 0;
256 }