Copyright consolidation 02/10
[openssl.git] / test / asynctest.c
1 /*
2  * Copyright 2015-2016 The OpenSSL Project Authors. All Rights Reserved.
3  *
4  * Licensed under the OpenSSL license (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
8  */
9
10 #include <stdio.h>
11 #include <string.h>
12 #include <openssl/async.h>
13 #include <openssl/crypto.h>
14 #include <../apps/apps.h>
15
16 static int ctr = 0;
17 static ASYNC_JOB *currjob = NULL;
18
19 static int only_pause(void *args)
20 {
21     ASYNC_pause_job();
22
23     return 1;
24 }
25
26 static int add_two(void *args)
27 {
28     ctr++;
29     ASYNC_pause_job();
30     ctr++;
31
32     return 2;
33 }
34
35 static int save_current(void *args)
36 {
37     currjob = ASYNC_get_current_job();
38     ASYNC_pause_job();
39
40     return 1;
41 }
42
43 #define MAGIC_WAIT_FD   ((OSSL_ASYNC_FD)99)
44 static int waitfd(void *args)
45 {
46     ASYNC_JOB *job;
47     ASYNC_WAIT_CTX *waitctx;
48     ASYNC_pause_job();
49     job = ASYNC_get_current_job();
50     if (job == NULL)
51         return 0;
52     waitctx = ASYNC_get_wait_ctx(job);
53     if (waitctx == NULL)
54         return 0;
55     if(!ASYNC_WAIT_CTX_set_wait_fd(waitctx, waitctx, MAGIC_WAIT_FD, NULL, NULL))
56         return 0;
57     ASYNC_pause_job();
58
59     if (!ASYNC_WAIT_CTX_clear_fd(waitctx, waitctx))
60         return 0;
61
62     return 1;
63 }
64
65 static int blockpause(void *args)
66 {
67     ASYNC_block_pause();
68     ASYNC_pause_job();
69     ASYNC_unblock_pause();
70     ASYNC_pause_job();
71
72     return 1;
73 }
74
75 static int test_ASYNC_init_thread()
76 {
77     ASYNC_JOB *job1 = NULL, *job2 = NULL, *job3 = NULL;
78     int funcret1, funcret2, funcret3;
79     ASYNC_WAIT_CTX *waitctx = NULL;
80
81     if (       !ASYNC_init_thread(2, 0)
82             || (waitctx = ASYNC_WAIT_CTX_new()) == NULL
83             || ASYNC_start_job(&job1, waitctx, &funcret1, only_pause, NULL, 0)
84                 != ASYNC_PAUSE
85             || ASYNC_start_job(&job2, waitctx, &funcret2, only_pause, NULL, 0)
86                 != ASYNC_PAUSE
87             || ASYNC_start_job(&job3, waitctx, &funcret3, only_pause, NULL, 0)
88                 != ASYNC_NO_JOBS
89             || ASYNC_start_job(&job1, waitctx, &funcret1, only_pause, NULL, 0)
90                 != ASYNC_FINISH
91             || ASYNC_start_job(&job3, waitctx, &funcret3, only_pause, NULL, 0)
92                 != ASYNC_PAUSE
93             || ASYNC_start_job(&job2, waitctx, &funcret2, only_pause, NULL, 0)
94                 != ASYNC_FINISH
95             || ASYNC_start_job(&job3, waitctx, &funcret3, only_pause, NULL, 0)
96                 != ASYNC_FINISH
97             || funcret1 != 1
98             || funcret2 != 1
99             || funcret3 != 1) {
100         fprintf(stderr, "test_ASYNC_init_thread() failed\n");
101         ASYNC_WAIT_CTX_free(waitctx);
102         ASYNC_cleanup_thread();
103         return 0;
104     }
105
106     ASYNC_WAIT_CTX_free(waitctx);
107     ASYNC_cleanup_thread();
108     return 1;
109 }
110
111 static int test_ASYNC_start_job()
112 {
113     ASYNC_JOB *job = NULL;
114     int funcret;
115     ASYNC_WAIT_CTX *waitctx = NULL;
116
117     ctr = 0;
118
119     if (       !ASYNC_init_thread(1, 0)
120             || (waitctx = ASYNC_WAIT_CTX_new()) == NULL
121             || ASYNC_start_job(&job, waitctx, &funcret, add_two, NULL, 0)
122                != ASYNC_PAUSE
123             || ctr != 1
124             || ASYNC_start_job(&job, waitctx, &funcret, add_two, NULL, 0)
125                != ASYNC_FINISH
126             || ctr != 2
127             || funcret != 2) {
128         fprintf(stderr, "test_ASYNC_start_job() failed\n");
129         ASYNC_WAIT_CTX_free(waitctx);
130         ASYNC_cleanup_thread();
131         return 0;
132     }
133
134     ASYNC_WAIT_CTX_free(waitctx);
135     ASYNC_cleanup_thread();
136     return 1;
137 }
138
139 static int test_ASYNC_get_current_job()
140 {
141     ASYNC_JOB *job = NULL;
142     int funcret;
143     ASYNC_WAIT_CTX *waitctx = NULL;
144
145     currjob = NULL;
146
147     if (       !ASYNC_init_thread(1, 0)
148             || (waitctx = ASYNC_WAIT_CTX_new()) == NULL
149             || ASYNC_start_job(&job, waitctx, &funcret, save_current, NULL, 0)
150                 != ASYNC_PAUSE
151             || currjob != job
152             || ASYNC_start_job(&job, waitctx, &funcret, save_current, NULL, 0)
153                 != ASYNC_FINISH
154             || funcret != 1) {
155         fprintf(stderr, "test_ASYNC_get_current_job() failed\n");
156         ASYNC_WAIT_CTX_free(waitctx);
157         ASYNC_cleanup_thread();
158         return 0;
159     }
160
161     ASYNC_WAIT_CTX_free(waitctx);
162     ASYNC_cleanup_thread();
163     return 1;
164 }
165
166 static int test_ASYNC_WAIT_CTX_get_all_fds()
167 {
168     ASYNC_JOB *job = NULL;
169     int funcret;
170     ASYNC_WAIT_CTX *waitctx = NULL;
171     OSSL_ASYNC_FD fd = OSSL_BAD_ASYNC_FD, delfd = OSSL_BAD_ASYNC_FD;
172     size_t numfds, numdelfds;
173
174     if (       !ASYNC_init_thread(1, 0)
175             || (waitctx = ASYNC_WAIT_CTX_new()) == NULL
176                /* On first run we're not expecting any wait fds */
177             || ASYNC_start_job(&job, waitctx, &funcret, waitfd, NULL, 0)
178                 != ASYNC_PAUSE
179             || !ASYNC_WAIT_CTX_get_all_fds(waitctx, NULL, &numfds)
180             || numfds != 0
181             || !ASYNC_WAIT_CTX_get_changed_fds(waitctx, NULL, &numfds, NULL,
182                                                &numdelfds)
183             || numfds != 0
184             || numdelfds != 0
185                /* On second run we're expecting one added fd */
186             || ASYNC_start_job(&job, waitctx, &funcret, waitfd, NULL, 0)
187                 != ASYNC_PAUSE
188             || !ASYNC_WAIT_CTX_get_all_fds(waitctx, NULL, &numfds)
189             || numfds != 1
190             || !ASYNC_WAIT_CTX_get_all_fds(waitctx, &fd, &numfds)
191             || fd != MAGIC_WAIT_FD
192             || (fd = OSSL_BAD_ASYNC_FD, 0) /* Assign to something else */
193             || !ASYNC_WAIT_CTX_get_changed_fds(waitctx, NULL, &numfds, NULL,
194                                               &numdelfds)
195             || numfds != 1
196             || numdelfds != 0
197             || !ASYNC_WAIT_CTX_get_changed_fds(waitctx, &fd, &numfds, NULL,
198                                                &numdelfds)
199             || fd != MAGIC_WAIT_FD
200                /* On final run we expect one deleted fd */
201             || ASYNC_start_job(&job, waitctx, &funcret, waitfd, NULL, 0)
202                 != ASYNC_FINISH
203             || !ASYNC_WAIT_CTX_get_all_fds(waitctx, NULL, &numfds)
204             || numfds != 0
205             || !ASYNC_WAIT_CTX_get_changed_fds(waitctx, NULL, &numfds, NULL,
206                                                &numdelfds)
207             || numfds != 0
208             || numdelfds != 1
209             || !ASYNC_WAIT_CTX_get_changed_fds(waitctx, NULL, &numfds, &delfd,
210                                                &numdelfds)
211             || delfd != MAGIC_WAIT_FD
212             || funcret != 1) {
213         fprintf(stderr, "test_ASYNC_get_wait_fd() failed\n");
214         ASYNC_WAIT_CTX_free(waitctx);
215         ASYNC_cleanup_thread();
216         return 0;
217     }
218
219     ASYNC_WAIT_CTX_free(waitctx);
220     ASYNC_cleanup_thread();
221     return 1;
222 }
223
224 static int test_ASYNC_block_pause()
225 {
226     ASYNC_JOB *job = NULL;
227     int funcret;
228     ASYNC_WAIT_CTX *waitctx = NULL;
229
230     if (       !ASYNC_init_thread(1, 0)
231             || (waitctx = ASYNC_WAIT_CTX_new()) == NULL
232             || ASYNC_start_job(&job, waitctx, &funcret, blockpause, NULL, 0)
233                 != ASYNC_PAUSE
234             || ASYNC_start_job(&job, waitctx, &funcret, blockpause, NULL, 0)
235                 != ASYNC_FINISH
236             || funcret != 1) {
237         fprintf(stderr, "test_ASYNC_block_pause() failed\n");
238         ASYNC_WAIT_CTX_free(waitctx);
239         ASYNC_cleanup_thread();
240         return 0;
241     }
242
243     ASYNC_WAIT_CTX_free(waitctx);
244     ASYNC_cleanup_thread();
245     return 1;
246 }
247
248 int main(int argc, char **argv)
249 {
250     if (!ASYNC_is_capable()) {
251         fprintf(stderr,
252                 "OpenSSL build is not ASYNC capable - skipping async tests\n");
253     } else {
254         CRYPTO_set_mem_debug(1);
255         CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);
256
257         if (       !test_ASYNC_init_thread()
258                 || !test_ASYNC_start_job()
259                 || !test_ASYNC_get_current_job()
260                 || !test_ASYNC_WAIT_CTX_get_all_fds()
261                 || !test_ASYNC_block_pause()) {
262             return 1;
263         }
264     }
265     printf("PASS\n");
266     return 0;
267 }