Refactor TLS1-PRF to create the MAC contexts early
[openssl.git] / test / asynctest.c
1 /*
2  * Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved.
3  *
4  * Licensed under the Apache License 2.0 (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 #ifdef _WIN32
11 # include <windows.h>
12 #endif
13
14 #include <stdio.h>
15 #include <string.h>
16 #include <openssl/async.h>
17 #include <openssl/crypto.h>
18
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
46 #define MAGIC_WAIT_FD   ((OSSL_ASYNC_FD)99)
47 static int waitfd(void *args)
48 {
49     ASYNC_JOB *job;
50     ASYNC_WAIT_CTX *waitctx;
51     job = ASYNC_get_current_job();
52     if (job == NULL)
53         return 0;
54     waitctx = ASYNC_get_wait_ctx(job);
55     if (waitctx == NULL)
56         return 0;
57
58     /* First case: no fd added or removed */
59     ASYNC_pause_job();
60
61     /* Second case: one fd added */
62     if (!ASYNC_WAIT_CTX_set_wait_fd(waitctx, waitctx, MAGIC_WAIT_FD, NULL, NULL))
63         return 0;
64     ASYNC_pause_job();
65
66     /* Third case: all fd removed */
67     if (!ASYNC_WAIT_CTX_clear_fd(waitctx, waitctx))
68         return 0;
69     ASYNC_pause_job();
70
71     /* Last case: fd added and immediately removed */
72     if (!ASYNC_WAIT_CTX_set_wait_fd(waitctx, waitctx, MAGIC_WAIT_FD, NULL, NULL))
73         return 0;
74     if (!ASYNC_WAIT_CTX_clear_fd(waitctx, waitctx))
75         return 0;
76
77     return 1;
78 }
79
80 static int blockpause(void *args)
81 {
82     ASYNC_block_pause();
83     ASYNC_pause_job();
84     ASYNC_unblock_pause();
85     ASYNC_pause_job();
86
87     return 1;
88 }
89
90 static int test_ASYNC_init_thread(void)
91 {
92     ASYNC_JOB *job1 = NULL, *job2 = NULL, *job3 = NULL;
93     int funcret1, funcret2, funcret3;
94     ASYNC_WAIT_CTX *waitctx = NULL;
95
96     if (       !ASYNC_init_thread(2, 0)
97             || (waitctx = ASYNC_WAIT_CTX_new()) == NULL
98             || ASYNC_start_job(&job1, waitctx, &funcret1, only_pause, NULL, 0)
99                 != ASYNC_PAUSE
100             || ASYNC_start_job(&job2, waitctx, &funcret2, only_pause, NULL, 0)
101                 != ASYNC_PAUSE
102             || ASYNC_start_job(&job3, waitctx, &funcret3, only_pause, NULL, 0)
103                 != ASYNC_NO_JOBS
104             || ASYNC_start_job(&job1, waitctx, &funcret1, only_pause, NULL, 0)
105                 != ASYNC_FINISH
106             || ASYNC_start_job(&job3, waitctx, &funcret3, only_pause, NULL, 0)
107                 != ASYNC_PAUSE
108             || ASYNC_start_job(&job2, waitctx, &funcret2, only_pause, NULL, 0)
109                 != ASYNC_FINISH
110             || ASYNC_start_job(&job3, waitctx, &funcret3, only_pause, NULL, 0)
111                 != ASYNC_FINISH
112             || funcret1 != 1
113             || funcret2 != 1
114             || funcret3 != 1) {
115         fprintf(stderr, "test_ASYNC_init_thread() failed\n");
116         ASYNC_WAIT_CTX_free(waitctx);
117         ASYNC_cleanup_thread();
118         return 0;
119     }
120
121     ASYNC_WAIT_CTX_free(waitctx);
122     ASYNC_cleanup_thread();
123     return 1;
124 }
125
126 static int test_callback(void *arg)
127 {
128     printf("callback test pass\n");
129     return 1;
130 }
131
132 static int test_ASYNC_callback_status(void)
133 {
134     ASYNC_WAIT_CTX *waitctx = NULL;
135     int set_arg = 100;
136     ASYNC_callback_fn get_callback;
137     void *get_arg;
138     int set_status = 1;
139
140     if (       !ASYNC_init_thread(1, 0)
141             || (waitctx = ASYNC_WAIT_CTX_new()) == NULL
142             || ASYNC_WAIT_CTX_set_callback(waitctx, test_callback, (void*)&set_arg)
143                != 1
144             || ASYNC_WAIT_CTX_get_callback(waitctx, &get_callback, &get_arg)
145                != 1
146             || test_callback != get_callback
147             || get_arg != (void*)&set_arg
148             || (*get_callback)(get_arg) != 1
149             || ASYNC_WAIT_CTX_set_status(waitctx, set_status) != 1
150             || set_status != ASYNC_WAIT_CTX_get_status(waitctx)) {
151         fprintf(stderr, "test_ASYNC_callback_status() failed\n");
152         ASYNC_WAIT_CTX_free(waitctx);
153         ASYNC_cleanup_thread();
154         return 0;
155     }
156
157     ASYNC_WAIT_CTX_free(waitctx);
158     ASYNC_cleanup_thread();
159     return 1;
160
161 }
162
163 static int test_ASYNC_start_job(void)
164 {
165     ASYNC_JOB *job = NULL;
166     int funcret;
167     ASYNC_WAIT_CTX *waitctx = NULL;
168
169     ctr = 0;
170
171     if (       !ASYNC_init_thread(1, 0)
172             || (waitctx = ASYNC_WAIT_CTX_new()) == NULL
173             || ASYNC_start_job(&job, waitctx, &funcret, add_two, NULL, 0)
174                != ASYNC_PAUSE
175             || ctr != 1
176             || ASYNC_start_job(&job, waitctx, &funcret, add_two, NULL, 0)
177                != ASYNC_FINISH
178             || ctr != 2
179             || funcret != 2) {
180         fprintf(stderr, "test_ASYNC_start_job() failed\n");
181         ASYNC_WAIT_CTX_free(waitctx);
182         ASYNC_cleanup_thread();
183         return 0;
184     }
185
186     ASYNC_WAIT_CTX_free(waitctx);
187     ASYNC_cleanup_thread();
188     return 1;
189 }
190
191 static int test_ASYNC_get_current_job(void)
192 {
193     ASYNC_JOB *job = NULL;
194     int funcret;
195     ASYNC_WAIT_CTX *waitctx = NULL;
196
197     currjob = NULL;
198
199     if (       !ASYNC_init_thread(1, 0)
200             || (waitctx = ASYNC_WAIT_CTX_new()) == NULL
201             || ASYNC_start_job(&job, waitctx, &funcret, save_current, NULL, 0)
202                 != ASYNC_PAUSE
203             || currjob != job
204             || ASYNC_start_job(&job, waitctx, &funcret, save_current, NULL, 0)
205                 != ASYNC_FINISH
206             || funcret != 1) {
207         fprintf(stderr, "test_ASYNC_get_current_job() failed\n");
208         ASYNC_WAIT_CTX_free(waitctx);
209         ASYNC_cleanup_thread();
210         return 0;
211     }
212
213     ASYNC_WAIT_CTX_free(waitctx);
214     ASYNC_cleanup_thread();
215     return 1;
216 }
217
218 static int test_ASYNC_WAIT_CTX_get_all_fds(void)
219 {
220     ASYNC_JOB *job = NULL;
221     int funcret;
222     ASYNC_WAIT_CTX *waitctx = NULL;
223     OSSL_ASYNC_FD fd = OSSL_BAD_ASYNC_FD, delfd = OSSL_BAD_ASYNC_FD;
224     size_t numfds, numdelfds;
225
226     if (       !ASYNC_init_thread(1, 0)
227             || (waitctx = ASYNC_WAIT_CTX_new()) == NULL
228                /* On first run we're not expecting any wait fds */
229             || ASYNC_start_job(&job, waitctx, &funcret, waitfd, NULL, 0)
230                 != ASYNC_PAUSE
231             || !ASYNC_WAIT_CTX_get_all_fds(waitctx, NULL, &numfds)
232             || numfds != 0
233             || !ASYNC_WAIT_CTX_get_changed_fds(waitctx, NULL, &numfds, NULL,
234                                                &numdelfds)
235             || numfds != 0
236             || numdelfds != 0
237                /* On second run we're expecting one added fd */
238             || ASYNC_start_job(&job, waitctx, &funcret, waitfd, NULL, 0)
239                 != ASYNC_PAUSE
240             || !ASYNC_WAIT_CTX_get_all_fds(waitctx, NULL, &numfds)
241             || numfds != 1
242             || !ASYNC_WAIT_CTX_get_all_fds(waitctx, &fd, &numfds)
243             || fd != MAGIC_WAIT_FD
244             || (fd = OSSL_BAD_ASYNC_FD, 0) /* Assign to something else */
245             || !ASYNC_WAIT_CTX_get_changed_fds(waitctx, NULL, &numfds, NULL,
246                                                &numdelfds)
247             || numfds != 1
248             || numdelfds != 0
249             || !ASYNC_WAIT_CTX_get_changed_fds(waitctx, &fd, &numfds, NULL,
250                                                &numdelfds)
251             || fd != MAGIC_WAIT_FD
252                /* On third run we expect one deleted fd */
253             || ASYNC_start_job(&job, waitctx, &funcret, waitfd, NULL, 0)
254                 != ASYNC_PAUSE
255             || !ASYNC_WAIT_CTX_get_all_fds(waitctx, NULL, &numfds)
256             || numfds != 0
257             || !ASYNC_WAIT_CTX_get_changed_fds(waitctx, NULL, &numfds, NULL,
258                                                &numdelfds)
259             || numfds != 0
260             || numdelfds != 1
261             || !ASYNC_WAIT_CTX_get_changed_fds(waitctx, NULL, &numfds, &delfd,
262                                                &numdelfds)
263             || delfd != MAGIC_WAIT_FD
264             /* On last run we are not expecting any wait fd */
265             || ASYNC_start_job(&job, waitctx, &funcret, waitfd, NULL, 0)
266                 != ASYNC_FINISH
267             || !ASYNC_WAIT_CTX_get_all_fds(waitctx, NULL, &numfds)
268             || numfds != 0
269             || !ASYNC_WAIT_CTX_get_changed_fds(waitctx, NULL, &numfds, NULL,
270                                                &numdelfds)
271             || numfds != 0
272             || numdelfds != 0
273             || funcret != 1) {
274         fprintf(stderr, "test_ASYNC_get_wait_fd() failed\n");
275         ASYNC_WAIT_CTX_free(waitctx);
276         ASYNC_cleanup_thread();
277         return 0;
278     }
279
280     ASYNC_WAIT_CTX_free(waitctx);
281     ASYNC_cleanup_thread();
282     return 1;
283 }
284
285 static int test_ASYNC_block_pause(void)
286 {
287     ASYNC_JOB *job = NULL;
288     int funcret;
289     ASYNC_WAIT_CTX *waitctx = NULL;
290
291     if (       !ASYNC_init_thread(1, 0)
292             || (waitctx = ASYNC_WAIT_CTX_new()) == NULL
293             || ASYNC_start_job(&job, waitctx, &funcret, blockpause, NULL, 0)
294                 != ASYNC_PAUSE
295             || ASYNC_start_job(&job, waitctx, &funcret, blockpause, NULL, 0)
296                 != ASYNC_FINISH
297             || funcret != 1) {
298         fprintf(stderr, "test_ASYNC_block_pause() failed\n");
299         ASYNC_WAIT_CTX_free(waitctx);
300         ASYNC_cleanup_thread();
301         return 0;
302     }
303
304     ASYNC_WAIT_CTX_free(waitctx);
305     ASYNC_cleanup_thread();
306     return 1;
307 }
308
309 int main(int argc, char **argv)
310 {
311     if (!ASYNC_is_capable()) {
312         fprintf(stderr,
313                 "OpenSSL build is not ASYNC capable - skipping async tests\n");
314     } else {
315         CRYPTO_set_mem_debug(1);
316         CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);
317
318         if (       !test_ASYNC_init_thread()
319                 || !test_ASYNC_callback_status()
320                 || !test_ASYNC_start_job()
321                 || !test_ASYNC_get_current_job()
322                 || !test_ASYNC_WAIT_CTX_get_all_fds()
323                 || !test_ASYNC_block_pause()) {
324             return 1;
325         }
326     }
327     printf("PASS\n");
328     return 0;
329 }