Unit tests: Fix unit test description strings.
[asterisk/asterisk.git] / tests / test_poll.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2010, Digium, Inc.
5  *
6  * Tilghman Lesher <tlesher AT digium DOT com>
7  *
8  * See http://www.asterisk.org for more information about
9  * the Asterisk project. Please do not directly contact
10  * any of the maintainers of this project for assistance;
11  * the project provides a web site, mailing lists and IRC
12  * channels for your use.
13  *
14  * This program is free software, distributed under the terms of
15  * the GNU General Public License Version 2. See the LICENSE file
16  * at the top of the source tree.
17  */
18
19 /*!
20  * \file
21  * \brief Poll Tests
22  *
23  * \author\verbatim Tilghman Lesher <tlesher AT digium DOT com> \endverbatim
24  *
25  * Verify that the various poll implementations work as desired (ast_poll, ast_poll2)
26  * \ingroup tests
27  */
28
29 /*** MODULEINFO
30         <depend>TEST_FRAMEWORK</depend>
31         <support_level>core</support_level>
32  ***/
33
34 #include "asterisk.h"
35 #include <signal.h>
36 #include <sys/types.h>
37 #include <sys/stat.h>
38 #include <fcntl.h>
39 #include <errno.h>
40 #include <unistd.h>
41
42 ASTERISK_REGISTER_FILE()
43
44 #include "asterisk/utils.h"
45 #include "asterisk/module.h"
46 #include "asterisk/test.h"
47 #include "asterisk/poll-compat.h"
48
49 static void *failsafe_cancel(void *vparent)
50 {
51         pthread_t parent = (pthread_t) (long) vparent;
52
53         sleep(1);
54         pthread_testcancel();
55         pthread_kill(parent, SIGURG);
56         sleep(1);
57         pthread_testcancel();
58         pthread_kill(parent, SIGURG);
59         sleep(1);
60         pthread_testcancel();
61         pthread_kill(parent, SIGURG);
62         pthread_exit(NULL);
63 }
64
65 #define RESET for (i = 0; i < 4; i++) { pfd[i].revents = 0; }
66 AST_TEST_DEFINE(poll_test)
67 {
68 #define FDNO 3
69         int fd[2], res = AST_TEST_PASS, i, res2;
70         int rdblocker[2];
71 #if FDNO > 3
72         int wrblocker[2], consec_interrupt = 0;
73 #endif
74         struct pollfd pfd[4] = { { .events = POLLOUT, }, { .events = POLLIN, }, { .events = POLLIN }, { .events = POLLOUT } };
75         pthread_t failsafe_tid;
76         struct timeval tv = { 0, 0 };
77 #if FDNO > 3
78         char garbage[256] =
79                 "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ@/"
80                 "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ@/"
81                 "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ@/"
82                 "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ@/";
83 #endif
84
85         switch (cmd) {
86         case TEST_INIT:
87                 info->name = "poll_test";
88                 info->category = "/main/poll/";
89                 info->summary = "unit test for the ast_poll() API";
90                 info->description =
91                         "Verifies behavior for the ast_poll() API call";
92                 return AST_TEST_NOT_RUN;
93         case TEST_EXECUTE:
94                 break;
95         }
96
97         ast_test_status_update(test, "Creating handle that should NEVER block on write\n");
98         if ((fd[0] = open("/dev/null", O_WRONLY)) < 0) {
99                 ast_test_status_update(test, "Unable to open a writable handle to /dev/null: %s\n", strerror(errno));
100                 return AST_TEST_FAIL;
101         }
102
103         ast_test_status_update(test, "Creating handle that should NEVER block on read\n");
104         if ((fd[1] = open("/dev/zero", O_RDONLY)) < 0) {
105                 ast_test_status_update(test, "Unable to open a readable handle to /dev/zero: %s\n", strerror(errno));
106                 close(fd[0]);
107                 return AST_TEST_FAIL;
108         }
109
110         ast_test_status_update(test, "Creating handle that should block on read\n");
111         if (pipe(rdblocker) < 0) {
112                 ast_test_status_update(test, "Unable to open a pipe: %s\n", strerror(errno));
113                 close(fd[0]);
114                 close(fd[1]);
115                 return AST_TEST_FAIL;
116         }
117
118 #if FDNO > 3
119         ast_test_status_update(test, "Creating handle that should block on write\n");
120         if (pipe(wrblocker) < 0) {
121                 ast_test_status_update(test, "Unable to open a pipe: %s\n", strerror(errno));
122                 close(fd[0]);
123                 close(fd[1]);
124                 close(rdblocker[0]);
125                 close(rdblocker[1]);
126                 return AST_TEST_FAIL;
127         }
128
129         ast_test_status_update(test, "Starting thread to ensure we don't block forever\n");
130         if (ast_pthread_create_background(&failsafe_tid, NULL, failsafe_cancel, (void *) (long) pthread_self())) {
131                 ast_test_status_update(test, "Unable to start failsafe thread\n");
132                 close(fd[0]);
133                 close(fd[1]);
134                 close(fd[2]);
135                 close(rdblocker[0]);
136                 close(rdblocker[1]);
137                 close(wrblocker[0]);
138                 close(wrblocker[1]);
139                 return AST_TEST_FAIL;
140         }
141
142         /* Fill the pipe full of data */
143         ast_test_status_update(test, "Making pipe block on write\n");
144         for (i = 0; i < 4096; i++) { /* 1MB of data should be more than enough for any pipe */
145                 errno = 0;
146                 if (write(wrblocker[1], garbage, sizeof(garbage)) < sizeof(garbage)) {
147                         ast_test_status_update(test, "Got %d\n", errno);
148                         if (errno == EINTR && ++consec_interrupt > 1) {
149                                 break;
150                         }
151                 } else {
152                         consec_interrupt = 0;
153                 }
154         }
155
156         ast_test_status_update(test, "Cancelling failsafe thread.\n");
157         pthread_cancel(failsafe_tid);
158         pthread_kill(failsafe_tid, SIGURG);
159         pthread_join(failsafe_tid, NULL);
160 #endif
161
162         pfd[0].fd = fd[0];
163         pfd[1].fd = fd[1];
164         pfd[2].fd = rdblocker[0];
165 #if FDNO > 3
166         pfd[3].fd = wrblocker[1];
167 #endif
168
169         /* Need to ensure the infinite timeout doesn't stall the process */
170         ast_test_status_update(test, "Starting thread to ensure we don't block forever\n");
171         if (ast_pthread_create_background(&failsafe_tid, NULL, failsafe_cancel, (void *) (long) pthread_self())) {
172                 ast_test_status_update(test, "Unable to start failsafe thread\n");
173                 close(fd[0]);
174                 close(fd[1]);
175                 close(rdblocker[0]);
176                 close(rdblocker[1]);
177 #if FDNO > 3
178                 close(wrblocker[0]);
179                 close(wrblocker[1]);
180 #endif
181                 return AST_TEST_FAIL;
182         }
183
184         RESET;
185         if ((res2 = ast_poll(pfd, FDNO, -1)) != 2) {
186                 ast_test_status_update(test, "ast_poll does not return that only two handles are available (inf timeout): %d, %s\n", res2, res2 == -1 ? strerror(errno) : "");
187                 res = AST_TEST_FAIL;
188         }
189
190         RESET;
191         if ((res2 = ast_poll2(pfd, FDNO, NULL)) != 2) {
192                 ast_test_status_update(test, "ast_poll2 does not return that only two handles are available (inf timeout): %d %s\n", res2, res2 == -1 ? strerror(errno) : "");
193                 res = AST_TEST_FAIL;
194         }
195
196         ast_test_status_update(test, "Cancelling failsafe thread.\n");
197         pthread_cancel(failsafe_tid);
198         pthread_kill(failsafe_tid, SIGURG);
199         pthread_join(failsafe_tid, NULL);
200
201         RESET;
202         if (ast_poll(pfd, FDNO, 0) != 2) {
203                 ast_test_status_update(test, "ast_poll does not return that only two handles are available (0 timeout): %d, %s\n", res2, res2 == -1 ? strerror(errno) : "");
204                 res = AST_TEST_FAIL;
205         }
206
207         RESET;
208         if (ast_poll2(pfd, FDNO, &tv) != 2) {
209                 ast_test_status_update(test, "ast_poll2 does not return that only two handles are available (0 timeout): %d, %s\n", res2, res2 == -1 ? strerror(errno) : "");
210                 res = AST_TEST_FAIL;
211         }
212
213         RESET;
214         if (ast_poll(pfd, FDNO, 1) != 2) {
215                 ast_test_status_update(test, "ast_poll does not return that only two handles are available (1ms timeout): %d, %s\n", res2, res2 == -1 ? strerror(errno) : "");
216                 res = AST_TEST_FAIL;
217         }
218
219         tv.tv_usec = 1000;
220         if (ast_poll2(pfd, FDNO, &tv) != 2) {
221                 ast_test_status_update(test, "ast_poll2 does not return that only two handles are available (1ms timeout): %d, %s\n", res2, res2 == -1 ? strerror(errno) : "");
222                 res = AST_TEST_FAIL;
223         }
224
225         close(fd[0]);
226         close(fd[1]);
227         close(rdblocker[0]);
228         close(rdblocker[1]);
229 #if FDNO > 3
230         close(wrblocker[0]);
231         close(wrblocker[1]);
232 #endif
233         return res;
234 }
235
236 static int unload_module(void)
237 {
238         AST_TEST_UNREGISTER(poll_test);
239         return 0;
240 }
241
242 static int load_module(void)
243 {
244         AST_TEST_REGISTER(poll_test);
245         return AST_MODULE_LOAD_SUCCESS;
246 }
247
248 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Poll test");