1/* Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements.  See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache License, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License.  You may obtain a copy of the License at
7 *
8 *     http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "testutil.h"
18#include "apr_strings.h"
19#include "apr_errno.h"
20#include "apr_general.h"
21#include "apr_lib.h"
22#include "apr_network_io.h"
23#include "apr_poll.h"
24
25#define SMALL_NUM_SOCKETS 3
26/* We can't use 64 here, because some platforms *ahem* Solaris *ahem* have
27 * a default limit of 64 open file descriptors per process.  If we use
28 * 64, the test will fail even though the code is correct.
29 */
30#define LARGE_NUM_SOCKETS 50
31
32static apr_socket_t *s[LARGE_NUM_SOCKETS];
33static apr_sockaddr_t *sa[LARGE_NUM_SOCKETS];
34static apr_pollset_t *pollset;
35static apr_pollcb_t *pollcb;
36
37/* ###: tests surrounded by ifdef OLD_POLL_INTERFACE either need to be
38 * converted to use the pollset interface or removed. */
39
40#ifdef OLD_POLL_INTERFACE
41static apr_pollfd_t *pollarray;
42static apr_pollfd_t *pollarray_large;
43#endif
44
45static void make_socket(apr_socket_t **sock, apr_sockaddr_t **sa,
46                        apr_port_t port, apr_pool_t *p, abts_case *tc)
47{
48    apr_status_t rv;
49
50    rv = apr_sockaddr_info_get(sa, "127.0.0.1", APR_UNSPEC, port, 0, p);
51    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
52
53    rv = apr_socket_create(sock, (*sa)->family, SOCK_DGRAM, 0, p);
54    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
55
56    rv = apr_socket_bind((*sock), (*sa));
57    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
58}
59
60#ifdef OLD_POLL_INTERFACE
61static void check_sockets(const apr_pollfd_t *pollarray,
62                          apr_socket_t **sockarray, int which, int pollin,
63                          abts_case *tc)
64{
65    apr_status_t rv;
66    apr_int16_t event;
67    char *str;
68
69    rv = apr_poll_revents_get(&event, sockarray[which],
70                              (apr_pollfd_t *)pollarray);
71    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
72    if (pollin) {
73        str = apr_psprintf(p, "Socket %d not signalled when it should be",
74                           which);
75        ABTS_ASSERT(tc, str, event & APR_POLLIN);
76    } else {
77        str = apr_psprintf(p, "Socket %d signalled when it should not be",
78                           which);
79        ABTS_ASSERT(tc, str, !(event & APR_POLLIN));
80    }
81}
82#endif
83
84static void send_msg(apr_socket_t **sockarray, apr_sockaddr_t **sas, int which,
85                     abts_case *tc)
86{
87    apr_size_t len = 5;
88    apr_status_t rv;
89
90    ABTS_PTR_NOTNULL(tc, sockarray[which]);
91
92    rv = apr_socket_sendto(sockarray[which], sas[which], 0, "hello", &len);
93    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
94    ABTS_SIZE_EQUAL(tc, strlen("hello"), len);
95}
96
97static void recv_msg(apr_socket_t **sockarray, int which, apr_pool_t *p,
98                     abts_case *tc)
99{
100    apr_size_t buflen = 5;
101    char *buffer = apr_pcalloc(p, sizeof(char) * (buflen + 1));
102    apr_sockaddr_t *recsa;
103    apr_status_t rv;
104
105    ABTS_PTR_NOTNULL(tc, sockarray[which]);
106
107    apr_sockaddr_info_get(&recsa, "127.0.0.1", APR_UNSPEC, 7770, 0, p);
108
109    rv = apr_socket_recvfrom(recsa, sockarray[which], 0, buffer, &buflen);
110    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
111    ABTS_SIZE_EQUAL(tc, strlen("hello"), buflen);
112    ABTS_STR_EQUAL(tc, "hello", buffer);
113}
114
115
116static void create_all_sockets(abts_case *tc, void *data)
117{
118    int i;
119
120    for (i = 0; i < LARGE_NUM_SOCKETS; i++){
121        make_socket(&s[i], &sa[i], 7777 + i, p, tc);
122    }
123}
124
125#ifdef OLD_POLL_INTERFACE
126static void setup_small_poll(abts_case *tc, void *data)
127{
128    apr_status_t rv;
129    int i;
130
131    rv = apr_poll_setup(&pollarray, SMALL_NUM_SOCKETS, p);
132    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
133
134    for (i = 0; i < SMALL_NUM_SOCKETS;i++){
135        ABTS_INT_EQUAL(tc, 0, pollarray[i].reqevents);
136        ABTS_INT_EQUAL(tc, 0, pollarray[i].rtnevents);
137
138        rv = apr_poll_socket_add(pollarray, s[i], APR_POLLIN);
139        ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
140        ABTS_PTR_EQUAL(tc, s[i], pollarray[i].desc.s);
141    }
142}
143
144static void setup_large_poll(abts_case *tc, void *data)
145{
146    apr_status_t rv;
147    int i;
148
149    rv = apr_poll_setup(&pollarray_large, LARGE_NUM_SOCKETS, p);
150    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
151
152    for (i = 0; i < LARGE_NUM_SOCKETS;i++){
153        ABTS_INT_EQUAL(tc, 0, pollarray_large[i].reqevents);
154        ABTS_INT_EQUAL(tc, 0, pollarray_large[i].rtnevents);
155
156        rv = apr_poll_socket_add(pollarray_large, s[i], APR_POLLIN);
157        ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
158        ABTS_PTR_EQUAL(tc, s[i], pollarray_large[i].desc.s);
159    }
160}
161
162static void nomessage(abts_case *tc, void *data)
163{
164    apr_status_t rv;
165    int srv = SMALL_NUM_SOCKETS;
166
167    rv = apr_poll(pollarray, SMALL_NUM_SOCKETS, &srv, 2 * APR_USEC_PER_SEC);
168    ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_TIMEUP(rv));
169    check_sockets(pollarray, s, 0, 0, tc);
170    check_sockets(pollarray, s, 1, 0, tc);
171    check_sockets(pollarray, s, 2, 0, tc);
172}
173
174static void send_2(abts_case *tc, void *data)
175{
176    apr_status_t rv;
177    int srv = SMALL_NUM_SOCKETS;
178
179    send_msg(s, sa, 2, tc);
180
181    rv = apr_poll(pollarray, SMALL_NUM_SOCKETS, &srv, 2 * APR_USEC_PER_SEC);
182    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
183    check_sockets(pollarray, s, 0, 0, tc);
184    check_sockets(pollarray, s, 1, 0, tc);
185    check_sockets(pollarray, s, 2, 1, tc);
186}
187
188static void recv_2_send_1(abts_case *tc, void *data)
189{
190    apr_status_t rv;
191    int srv = SMALL_NUM_SOCKETS;
192
193    recv_msg(s, 2, p, tc);
194    send_msg(s, sa, 1, tc);
195
196    rv = apr_poll(pollarray, SMALL_NUM_SOCKETS, &srv, 2 * APR_USEC_PER_SEC);
197    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
198    check_sockets(pollarray, s, 0, 0, tc);
199    check_sockets(pollarray, s, 1, 1, tc);
200    check_sockets(pollarray, s, 2, 0, tc);
201}
202
203static void send_2_signaled_1(abts_case *tc, void *data)
204{
205    apr_status_t rv;
206    int srv = SMALL_NUM_SOCKETS;
207
208    send_msg(s, sa, 2, tc);
209
210    rv = apr_poll(pollarray, SMALL_NUM_SOCKETS, &srv, 2 * APR_USEC_PER_SEC);
211    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
212    check_sockets(pollarray, s, 0, 0, tc);
213    check_sockets(pollarray, s, 1, 1, tc);
214    check_sockets(pollarray, s, 2, 1, tc);
215}
216
217static void recv_1_send_0(abts_case *tc, void *data)
218{
219    apr_status_t rv;
220    int srv = SMALL_NUM_SOCKETS;
221
222    recv_msg(s, 1, p, tc);
223    send_msg(s, sa, 0, tc);
224
225    rv = apr_poll(pollarray, SMALL_NUM_SOCKETS, &srv, 2 * APR_USEC_PER_SEC);
226    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
227    check_sockets(pollarray, s, 0, 1, tc);
228    check_sockets(pollarray, s, 1, 0, tc);
229    check_sockets(pollarray, s, 2, 1, tc);
230}
231
232static void clear_all_signalled(abts_case *tc, void *data)
233{
234    apr_status_t rv;
235    int srv = SMALL_NUM_SOCKETS;
236
237    recv_msg(s, 0, p, tc);
238    recv_msg(s, 2, p, tc);
239
240    rv = apr_poll(pollarray, SMALL_NUM_SOCKETS, &srv, 2 * APR_USEC_PER_SEC);
241    ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_TIMEUP(rv));
242    check_sockets(pollarray, s, 0, 0, tc);
243    check_sockets(pollarray, s, 1, 0, tc);
244    check_sockets(pollarray, s, 2, 0, tc);
245}
246
247static void send_large_pollarray(abts_case *tc, void *data)
248{
249    apr_status_t rv;
250    int lrv = LARGE_NUM_SOCKETS;
251    int i;
252
253    send_msg(s, sa, LARGE_NUM_SOCKETS - 1, tc);
254
255    rv = apr_poll(pollarray_large, LARGE_NUM_SOCKETS, &lrv,
256                  2 * APR_USEC_PER_SEC);
257    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
258
259    for (i = 0; i < LARGE_NUM_SOCKETS; i++) {
260        if (i == (LARGE_NUM_SOCKETS - 1)) {
261            check_sockets(pollarray_large, s, i, 1, tc);
262        }
263        else {
264            check_sockets(pollarray_large, s, i, 0, tc);
265        }
266    }
267}
268
269static void recv_large_pollarray(abts_case *tc, void *data)
270{
271    apr_status_t rv;
272    int lrv = LARGE_NUM_SOCKETS;
273    int i;
274
275    recv_msg(s, LARGE_NUM_SOCKETS - 1, p, tc);
276
277    rv = apr_poll(pollarray_large, LARGE_NUM_SOCKETS, &lrv,
278                  2 * APR_USEC_PER_SEC);
279    ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_TIMEUP(rv));
280
281    for (i = 0; i < LARGE_NUM_SOCKETS; i++) {
282        check_sockets(pollarray_large, s, i, 0, tc);
283    }
284}
285#endif
286
287static void setup_pollset(abts_case *tc, void *data)
288{
289    apr_status_t rv;
290    rv = apr_pollset_create(&pollset, LARGE_NUM_SOCKETS, p, 0);
291    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
292}
293
294static void multi_event_pollset(abts_case *tc, void *data)
295{
296    apr_status_t rv;
297    apr_pollfd_t socket_pollfd;
298    int lrv;
299    const apr_pollfd_t *descs = NULL;
300
301    ABTS_PTR_NOTNULL(tc, s[0]);
302    socket_pollfd.desc_type = APR_POLL_SOCKET;
303    socket_pollfd.reqevents = APR_POLLIN | APR_POLLOUT;
304    socket_pollfd.desc.s = s[0];
305    socket_pollfd.client_data = s[0];
306    rv = apr_pollset_add(pollset, &socket_pollfd);
307    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
308
309    send_msg(s, sa, 0, tc);
310
311    rv = apr_pollset_poll(pollset, -1, &lrv, &descs);
312    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
313    if (lrv == 1) {
314        int ev = descs[0].rtnevents;
315        ABTS_PTR_EQUAL(tc, s[0], descs[0].desc.s);
316        ABTS_PTR_EQUAL(tc, s[0],  descs[0].client_data);
317        ABTS_ASSERT(tc, "either or both of APR_POLLIN, APR_POLLOUT returned",
318                    ((ev & APR_POLLIN) != 0) || ((ev & APR_POLLOUT) != 0));
319    }
320    else if (lrv == 2) {
321        ABTS_PTR_EQUAL(tc, s[0], descs[0].desc.s);
322        ABTS_PTR_EQUAL(tc, s[0], descs[0].client_data);
323        ABTS_PTR_EQUAL(tc, s[0], descs[1].desc.s);
324        ABTS_PTR_EQUAL(tc, s[0], descs[1].client_data);
325        ABTS_ASSERT(tc, "returned events incorrect",
326                    ((descs[0].rtnevents | descs[1].rtnevents)
327                     == (APR_POLLIN | APR_POLLOUT))
328                    && descs[0].rtnevents != descs[1].rtnevents);
329    }
330    else {
331        ABTS_ASSERT(tc, "either one or two events returned",
332                    lrv == 1 || lrv == 2);
333    }
334
335    recv_msg(s, 0, p, tc);
336
337    rv = apr_pollset_poll(pollset, 0, &lrv, &descs);
338    ABTS_INT_EQUAL(tc, 0, APR_STATUS_IS_TIMEUP(rv));
339    ABTS_INT_EQUAL(tc, 1, lrv);
340    ABTS_PTR_EQUAL(tc, s[0], descs[0].desc.s);
341    ABTS_INT_EQUAL(tc, APR_POLLOUT, descs[0].rtnevents);
342    ABTS_PTR_EQUAL(tc, s[0],  descs[0].client_data);
343
344    rv = apr_pollset_remove(pollset, &socket_pollfd);
345    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
346}
347
348static void add_sockets_pollset(abts_case *tc, void *data)
349{
350    apr_status_t rv;
351    int i;
352
353    for (i = 0; i < LARGE_NUM_SOCKETS;i++){
354        apr_pollfd_t socket_pollfd;
355
356        ABTS_PTR_NOTNULL(tc, s[i]);
357
358        socket_pollfd.desc_type = APR_POLL_SOCKET;
359        socket_pollfd.reqevents = APR_POLLIN;
360        socket_pollfd.desc.s = s[i];
361        socket_pollfd.client_data = s[i];
362        rv = apr_pollset_add(pollset, &socket_pollfd);
363        ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
364    }
365}
366
367static void nomessage_pollset(abts_case *tc, void *data)
368{
369    apr_status_t rv;
370    int lrv;
371    const apr_pollfd_t *descs = NULL;
372
373    rv = apr_pollset_poll(pollset, 0, &lrv, &descs);
374    ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_TIMEUP(rv));
375    ABTS_INT_EQUAL(tc, 0, lrv);
376    ABTS_PTR_EQUAL(tc, NULL, descs);
377}
378
379static void send0_pollset(abts_case *tc, void *data)
380{
381    apr_status_t rv;
382    const apr_pollfd_t *descs = NULL;
383    int num;
384
385    send_msg(s, sa, 0, tc);
386    rv = apr_pollset_poll(pollset, -1, &num, &descs);
387    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
388    ABTS_INT_EQUAL(tc, 1, num);
389    ABTS_PTR_NOTNULL(tc, descs);
390
391    ABTS_PTR_EQUAL(tc, s[0], descs[0].desc.s);
392    ABTS_PTR_EQUAL(tc, s[0], descs[0].client_data);
393}
394
395static void recv0_pollset(abts_case *tc, void *data)
396{
397    apr_status_t rv;
398    int lrv;
399    const apr_pollfd_t *descs = NULL;
400
401    recv_msg(s, 0, p, tc);
402    rv = apr_pollset_poll(pollset, 0, &lrv, &descs);
403    ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_TIMEUP(rv));
404    ABTS_INT_EQUAL(tc, 0, lrv);
405    ABTS_PTR_EQUAL(tc, NULL, descs);
406}
407
408static void send_middle_pollset(abts_case *tc, void *data)
409{
410    apr_status_t rv;
411    const apr_pollfd_t *descs = NULL;
412    int num;
413
414    send_msg(s, sa, 2, tc);
415    send_msg(s, sa, 5, tc);
416    rv = apr_pollset_poll(pollset, -1, &num, &descs);
417    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
418    ABTS_PTR_NOTNULL(tc, descs);
419    ABTS_ASSERT(tc, "either one or two events returned",
420                num == 1 || num == 2);
421
422    /* The poll might only see the first sent message, in which
423     * case we just don't bother checking this assertion */
424    if (num == 2) {
425        ABTS_ASSERT(tc, "Incorrect socket in result set",
426                    ((descs[0].desc.s == s[2]) && (descs[1].desc.s == s[5])) ||
427                    ((descs[0].desc.s == s[5]) && (descs[1].desc.s == s[2])));
428    }
429}
430
431static void clear_middle_pollset(abts_case *tc, void *data)
432{
433    apr_status_t rv;
434    int lrv;
435    const apr_pollfd_t *descs = NULL;
436
437    recv_msg(s, 2, p, tc);
438    recv_msg(s, 5, p, tc);
439
440    rv = apr_pollset_poll(pollset, 0, &lrv, &descs);
441    ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_TIMEUP(rv));
442    ABTS_INT_EQUAL(tc, 0, lrv);
443    ABTS_PTR_EQUAL(tc, NULL, descs);
444}
445
446static void send_last_pollset(abts_case *tc, void *data)
447{
448    apr_status_t rv;
449    const apr_pollfd_t *descs = NULL;
450    int num;
451
452    send_msg(s, sa, LARGE_NUM_SOCKETS - 1, tc);
453    rv = apr_pollset_poll(pollset, -1, &num, &descs);
454    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
455    ABTS_INT_EQUAL(tc, 1, num);
456    ABTS_PTR_NOTNULL(tc, descs);
457
458    ABTS_PTR_EQUAL(tc, s[LARGE_NUM_SOCKETS - 1], descs[0].desc.s);
459    ABTS_PTR_EQUAL(tc, s[LARGE_NUM_SOCKETS - 1], descs[0].client_data);
460}
461
462static void clear_last_pollset(abts_case *tc, void *data)
463{
464    apr_status_t rv;
465    int lrv;
466    const apr_pollfd_t *descs = NULL;
467
468    recv_msg(s, LARGE_NUM_SOCKETS - 1, p, tc);
469
470    rv = apr_pollset_poll(pollset, 0, &lrv, &descs);
471    ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_TIMEUP(rv));
472    ABTS_INT_EQUAL(tc, 0, lrv);
473    ABTS_PTR_EQUAL(tc, NULL, descs);
474}
475
476static void close_all_sockets(abts_case *tc, void *data)
477{
478    apr_status_t rv;
479    int i;
480
481    for (i = 0; i < LARGE_NUM_SOCKETS; i++){
482        rv = apr_socket_close(s[i]);
483        ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
484    }
485}
486
487static void pollset_remove(abts_case *tc, void *data)
488{
489    apr_status_t rv;
490    apr_pollset_t *pollset;
491    const apr_pollfd_t *hot_files;
492    apr_pollfd_t pfd;
493    apr_int32_t num;
494
495    rv = apr_pollset_create(&pollset, 5, p, 0);
496    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
497
498    pfd.p = p;
499    pfd.desc_type = APR_POLL_SOCKET;
500    pfd.reqevents = APR_POLLOUT;
501
502    pfd.desc.s = s[0];
503    pfd.client_data = (void *)1;
504    rv = apr_pollset_add(pollset, &pfd);
505    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
506
507    pfd.desc.s = s[1];
508    pfd.client_data = (void *)2;
509    rv = apr_pollset_add(pollset, &pfd);
510    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
511
512    pfd.desc.s = s[2];
513    pfd.client_data = (void *)3;
514    rv = apr_pollset_add(pollset, &pfd);
515    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
516
517    pfd.desc.s = s[3];
518    pfd.client_data = (void *)4;
519    rv = apr_pollset_add(pollset, &pfd);
520    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
521
522    rv = apr_pollset_poll(pollset, 1000, &num, &hot_files);
523    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
524    ABTS_INT_EQUAL(tc, 4, num);
525
526    /* now remove the pollset element referring to desc s[1] */
527    pfd.desc.s = s[1];
528    pfd.client_data = (void *)999; /* not used on this call */
529    rv = apr_pollset_remove(pollset, &pfd);
530    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
531
532    /* this time only three should match */
533    rv = apr_pollset_poll(pollset, 1000, &num, &hot_files);
534    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
535    ABTS_INT_EQUAL(tc, 3, num);
536    ABTS_PTR_EQUAL(tc, (void *)1, hot_files[0].client_data);
537    ABTS_PTR_EQUAL(tc, s[0], hot_files[0].desc.s);
538    ABTS_PTR_EQUAL(tc, (void *)3, hot_files[1].client_data);
539    ABTS_PTR_EQUAL(tc, s[2], hot_files[1].desc.s);
540    ABTS_PTR_EQUAL(tc, (void *)4, hot_files[2].client_data);
541    ABTS_PTR_EQUAL(tc, s[3], hot_files[2].desc.s);
542
543    /* now remove the pollset elements referring to desc s[2] */
544    pfd.desc.s = s[2];
545    pfd.client_data = (void *)999; /* not used on this call */
546    rv = apr_pollset_remove(pollset, &pfd);
547    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
548
549    /* this time only two should match */
550    rv = apr_pollset_poll(pollset, 1000, &num, &hot_files);
551    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
552    ABTS_INT_EQUAL(tc, 2, num);
553    ABTS_ASSERT(tc, "Incorrect socket in result set",
554            ((hot_files[0].desc.s == s[0]) && (hot_files[1].desc.s == s[3]))  ||
555            ((hot_files[0].desc.s == s[3]) && (hot_files[1].desc.s == s[0])));
556    ABTS_ASSERT(tc, "Incorrect client data in result set",
557            ((hot_files[0].client_data == (void *)1) &&
558             (hot_files[1].client_data == (void *)4)) ||
559            ((hot_files[0].client_data == (void *)4) &&
560             (hot_files[1].client_data == (void *)1)));
561}
562
563#define POLLCB_PREREQ \
564    do { \
565        if (pollcb == NULL) { \
566            ABTS_NOT_IMPL(tc, "pollcb interface not supported"); \
567            return; \
568        } \
569    } while (0)
570
571static void setup_pollcb(abts_case *tc, void *data)
572{
573    apr_status_t rv;
574    rv = apr_pollcb_create(&pollcb, LARGE_NUM_SOCKETS, p, 0);
575    if (rv == APR_ENOTIMPL) {
576        pollcb = NULL;
577        ABTS_NOT_IMPL(tc, "pollcb interface not supported");
578    }
579    else {
580        ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
581    }
582}
583
584typedef struct pollcb_baton_t {
585    abts_case *tc;
586    int count;
587} pollcb_baton_t;
588
589static apr_status_t trigger_pollcb_cb(void* baton, apr_pollfd_t *descriptor)
590{
591    pollcb_baton_t* pcb = (pollcb_baton_t*) baton;
592    ABTS_PTR_EQUAL(pcb->tc, s[0], descriptor->desc.s);
593    ABTS_PTR_EQUAL(pcb->tc, s[0], descriptor->client_data);
594    pcb->count++;
595    return APR_SUCCESS;
596}
597
598static void trigger_pollcb(abts_case *tc, void *data)
599{
600    apr_status_t rv;
601    apr_pollfd_t socket_pollfd;
602    pollcb_baton_t pcb;
603
604    POLLCB_PREREQ;
605
606    ABTS_PTR_NOTNULL(tc, s[0]);
607    socket_pollfd.desc_type = APR_POLL_SOCKET;
608    socket_pollfd.reqevents = APR_POLLIN;
609    socket_pollfd.desc.s = s[0];
610    socket_pollfd.client_data = s[0];
611    rv = apr_pollcb_add(pollcb, &socket_pollfd);
612    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
613
614    send_msg(s, sa, 0, tc);
615    pcb.tc = tc;
616    pcb.count = 0;
617    rv = apr_pollcb_poll(pollcb, -1, trigger_pollcb_cb, &pcb);
618    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
619    ABTS_INT_EQUAL(tc, 1, pcb.count);
620
621    rv = apr_pollcb_remove(pollcb, &socket_pollfd);
622    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
623}
624
625static void timeout_pollcb(abts_case *tc, void *data)
626{
627    apr_status_t rv;
628    pollcb_baton_t pcb;
629
630    POLLCB_PREREQ;
631
632    pcb.count = 0;
633    pcb.tc = tc;
634
635    rv = apr_pollcb_poll(pollcb, 1, trigger_pollcb_cb, &pcb);
636    ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_TIMEUP(rv));
637    ABTS_INT_EQUAL(tc, 0, pcb.count);
638}
639
640static void timeout_pollin_pollcb(abts_case *tc, void *data)
641{
642    apr_status_t rv;
643    pollcb_baton_t pcb;
644    apr_pollfd_t socket_pollfd;
645
646    POLLCB_PREREQ;
647
648    recv_msg(s, 0, p, tc);
649
650    ABTS_PTR_NOTNULL(tc, s[0]);
651    socket_pollfd.desc_type = APR_POLL_SOCKET;
652    socket_pollfd.reqevents = APR_POLLIN;
653    socket_pollfd.desc.s = s[0];
654    socket_pollfd.client_data = s[0];
655    rv = apr_pollcb_add(pollcb, &socket_pollfd);
656    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
657
658    pcb.count = 0;
659    pcb.tc = tc;
660
661    rv = apr_pollcb_poll(pollcb, 1, trigger_pollcb_cb, &pcb);
662    ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_TIMEUP(rv));
663    ABTS_INT_EQUAL(tc, 0, pcb.count);
664
665    rv = apr_pollcb_remove(pollcb, &socket_pollfd);
666    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
667}
668
669static void pollset_default(abts_case *tc, void *data)
670{
671    apr_status_t rv1, rv2;
672    apr_pollset_t *pollset;
673
674    /* verify that APR will successfully create a pollset if an invalid method
675     * is specified as long as APR_POLLSET_NODEFAULT isn't specified
676     * (no platform has both APR_POLLSET_PORT and APR_POLLSET_KQUEUE, so at
677     * least one create call will succeed after having to switch to the default
678     * type)
679     */
680    rv1 = apr_pollset_create_ex(&pollset, 1, p, 0, APR_POLLSET_PORT);
681
682    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv1);
683    ABTS_PTR_NOTNULL(tc, pollset);
684
685    rv1 = apr_pollset_create_ex(&pollset, 1, p, 0, APR_POLLSET_KQUEUE);
686    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv1);
687    ABTS_PTR_NOTNULL(tc, pollset);
688
689    /* verify that APR will fail to create a pollset if an invalid method is
690     * specified along with APR_POLLSET_NODEFAULT
691     * (no platform has both APR_POLLSET_PORT and APR_POLLSET_KQUEUE, so at
692     * least one create call will fail since it can't switch to the default
693     * type)
694     */
695    rv1 = apr_pollset_create_ex(&pollset, 1, p, APR_POLLSET_NODEFAULT,
696                               APR_POLLSET_PORT);
697
698    if (rv1 == APR_SUCCESS) {
699        ABTS_PTR_NOTNULL(tc, pollset);
700    }
701
702    rv2 = apr_pollset_create_ex(&pollset, 1, p, APR_POLLSET_NODEFAULT,
703                               APR_POLLSET_KQUEUE);
704    if (rv2 == APR_SUCCESS) {
705        ABTS_PTR_NOTNULL(tc, pollset);
706    }
707
708    ABTS_ASSERT(tc,
709                "failure using APR_POLLSET_NODEFAULT with unsupported method",
710                rv1 != APR_SUCCESS || rv2 != APR_SUCCESS);
711}
712
713static void pollcb_default(abts_case *tc, void *data)
714{
715    apr_status_t rv1, rv2;
716    apr_pollcb_t *pollcb;
717
718    /* verify that APR will successfully create a pollcb if an invalid method
719     * is specified as long as APR_POLLSET_NODEFAULT isn't specified
720     * (no platform has both APR_POLLSET_PORT and APR_POLLSET_KQUEUE, so at
721     * least one create call will succeed after having to switch to the default
722     * type)
723     */
724    rv1 = apr_pollcb_create_ex(&pollcb, 1, p, 0, APR_POLLSET_PORT);
725    if (rv1 == APR_ENOTIMPL) {
726        ABTS_NOT_IMPL(tc, "pollcb interface not supported");
727        return;
728    }
729
730    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv1);
731    ABTS_PTR_NOTNULL(tc, pollcb);
732
733    rv1 = apr_pollcb_create_ex(&pollcb, 1, p, 0, APR_POLLSET_KQUEUE);
734    ABTS_INT_EQUAL(tc, APR_SUCCESS, rv1);
735    ABTS_PTR_NOTNULL(tc, pollcb);
736
737    /* verify that APR will fail to create a pollcb if an invalid method is
738     * specified along with APR_POLLSET_NODEFAULT
739     * (no platform has both APR_POLLSET_PORT and APR_POLLSET_KQUEUE, so at
740     * least one create call will fail since it can't switch to the default
741     * type)
742     */
743    rv1 = apr_pollcb_create_ex(&pollcb, 1, p, APR_POLLSET_NODEFAULT,
744                               APR_POLLSET_PORT);
745
746    if (rv1 == APR_SUCCESS) {
747        ABTS_PTR_NOTNULL(tc, pollcb);
748    }
749
750    rv2 = apr_pollcb_create_ex(&pollcb, 1, p, APR_POLLSET_NODEFAULT,
751                               APR_POLLSET_KQUEUE);
752    if (rv2 == APR_SUCCESS) {
753        ABTS_PTR_NOTNULL(tc, pollcb);
754    }
755
756    ABTS_ASSERT(tc,
757                "failure using APR_POLLSET_NODEFAULT with unsupported method",
758                rv1 != APR_SUCCESS || rv2 != APR_SUCCESS);
759
760
761    /* verify basic behavior for another method fallback case (this caused
762     * APR to crash before r834029)
763     */
764
765    rv1 = apr_pollcb_create_ex(&pollcb, 1, p, 0, APR_POLLSET_POLL);
766    if (rv1 != APR_ENOTIMPL) {
767        ABTS_INT_EQUAL(tc, rv1, APR_SUCCESS);
768        ABTS_PTR_NOTNULL(tc, pollcb);
769    }
770}
771
772static void justsleep(abts_case *tc, void *data)
773{
774    apr_int32_t nsds;
775    const apr_pollfd_t *hot_files;
776    apr_pollset_t *pollset;
777    apr_status_t rv;
778    apr_time_t t1, t2;
779    int i;
780    apr_pollset_method_e methods[] = {
781        APR_POLLSET_DEFAULT,
782        APR_POLLSET_SELECT,
783        APR_POLLSET_KQUEUE,
784        APR_POLLSET_PORT,
785        APR_POLLSET_EPOLL,
786        APR_POLLSET_POLL};
787
788    nsds = 1;
789    t1 = apr_time_now();
790    rv = apr_poll(NULL, 0, &nsds, apr_time_from_msec(200));
791    t2 = apr_time_now();
792    ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_TIMEUP(rv));
793    ABTS_INT_EQUAL(tc, 0, nsds);
794    ABTS_ASSERT(tc,
795                "apr_poll() didn't sleep",
796                (t2 - t1) > apr_time_from_msec(100));
797
798    for (i = 0; i < sizeof methods / sizeof methods[0]; i++) {
799        rv = apr_pollset_create_ex(&pollset, 5, p, 0, methods[i]);
800        if (rv != APR_ENOTIMPL) {
801            ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
802
803            nsds = 1;
804            t1 = apr_time_now();
805            rv = apr_pollset_poll(pollset, apr_time_from_msec(200), &nsds,
806                                  &hot_files);
807            t2 = apr_time_now();
808            ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_TIMEUP(rv));
809            ABTS_INT_EQUAL(tc, 0, nsds);
810            ABTS_ASSERT(tc,
811                        "apr_pollset_poll() didn't sleep",
812                        (t2 - t1) > apr_time_from_msec(100));
813
814            rv = apr_pollset_destroy(pollset);
815            ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
816        }
817
818        rv = apr_pollcb_create_ex(&pollcb, 5, p, 0, methods[0]);
819        if (rv != APR_ENOTIMPL) {
820            ABTS_INT_EQUAL(tc, APR_SUCCESS, rv);
821
822            t1 = apr_time_now();
823            rv = apr_pollcb_poll(pollcb, apr_time_from_msec(200), NULL, NULL);
824            t2 = apr_time_now();
825            ABTS_INT_EQUAL(tc, 1, APR_STATUS_IS_TIMEUP(rv));
826            ABTS_ASSERT(tc,
827                        "apr_pollcb_poll() didn't sleep",
828                        (t2 - t1) > apr_time_from_msec(100));
829
830            /* no apr_pollcb_destroy() */
831        }
832    }
833}
834
835abts_suite *testpoll(abts_suite *suite)
836{
837    suite = ADD_SUITE(suite)
838
839    abts_run_test(suite, create_all_sockets, NULL);
840
841#ifdef OLD_POLL_INTERFACE
842    abts_run_test(suite, setup_small_poll, NULL);
843    abts_run_test(suite, setup_large_poll, NULL);
844    abts_run_test(suite, nomessage, NULL);
845    abts_run_test(suite, send_2, NULL);
846    abts_run_test(suite, recv_2_send_1, NULL);
847    abts_run_test(suite, send_2_signaled_1, NULL);
848    abts_run_test(suite, recv_1_send_0, NULL);
849    abts_run_test(suite, clear_all_signalled, NULL);
850    abts_run_test(suite, send_large_pollarray, NULL);
851    abts_run_test(suite, recv_large_pollarray, NULL);
852#endif
853
854    abts_run_test(suite, setup_pollset, NULL);
855    abts_run_test(suite, multi_event_pollset, NULL);
856    abts_run_test(suite, add_sockets_pollset, NULL);
857    abts_run_test(suite, nomessage_pollset, NULL);
858    abts_run_test(suite, send0_pollset, NULL);
859    abts_run_test(suite, recv0_pollset, NULL);
860    abts_run_test(suite, send_middle_pollset, NULL);
861    abts_run_test(suite, clear_middle_pollset, NULL);
862    abts_run_test(suite, send_last_pollset, NULL);
863    abts_run_test(suite, clear_last_pollset, NULL);
864    abts_run_test(suite, pollset_remove, NULL);
865    abts_run_test(suite, close_all_sockets, NULL);
866    abts_run_test(suite, create_all_sockets, NULL);
867    abts_run_test(suite, setup_pollcb, NULL);
868    abts_run_test(suite, trigger_pollcb, NULL);
869    abts_run_test(suite, timeout_pollcb, NULL);
870    abts_run_test(suite, timeout_pollin_pollcb, NULL);
871    abts_run_test(suite, close_all_sockets, NULL);
872    abts_run_test(suite, pollset_default, NULL);
873    abts_run_test(suite, pollcb_default, NULL);
874    abts_run_test(suite, justsleep, NULL);
875    return suite;
876}
877
878