Asterisk - The Open Source Telephony Project GIT-master-f36a736
Macros | Functions | Variables
test_poll.c File Reference

Poll Tests. More...

#include "asterisk.h"
#include <signal.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include "asterisk/utils.h"
#include "asterisk/module.h"
#include "asterisk/test.h"
#include "asterisk/poll-compat.h"
Include dependency graph for test_poll.c:

Go to the source code of this file.

Macros

#define FDNO   3
 
#define RESET   for (i = 0; i < 4; i++) { pfd[i].revents = 0; }
 

Functions

static void __reg_module (void)
 
static void __unreg_module (void)
 
struct ast_moduleAST_MODULE_SELF_SYM (void)
 
 AST_TEST_DEFINE (poll_test)
 
static void * failsafe_cancel (void *vparent)
 
static int load_module (void)
 
static int unload_module (void)
 

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Poll test" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, .support_level = AST_MODULE_SUPPORT_CORE, }
 
static const struct ast_module_infoast_module_info = &__mod_info
 

Detailed Description

Poll Tests.

Author
Tilghman Lesher <tlesher AT digium DOT com> 

Verify that the various poll implementations work as desired (ast_poll, ast_poll2)

Definition in file test_poll.c.

Macro Definition Documentation

◆ FDNO

#define FDNO   3

◆ RESET

#define RESET   for (i = 0; i < 4; i++) { pfd[i].revents = 0; }

Definition at line 63 of file test_poll.c.

Function Documentation

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 246 of file test_poll.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 246 of file test_poll.c.

◆ AST_MODULE_SELF_SYM()

struct ast_module * AST_MODULE_SELF_SYM ( void  )

Definition at line 246 of file test_poll.c.

◆ AST_TEST_DEFINE()

AST_TEST_DEFINE ( poll_test  )

Definition at line 64 of file test_poll.c.

65{
66#define FDNO 3
67 int fd[2], res = AST_TEST_PASS, i, res2;
68 int rdblocker[2];
69#if FDNO > 3
70 int wrblocker[2], consec_interrupt = 0;
71#endif
72 struct pollfd pfd[4] = { { .events = POLLOUT, }, { .events = POLLIN, }, { .events = POLLIN }, { .events = POLLOUT } };
73 pthread_t failsafe_tid;
74 struct timeval tv = { 0, 0 };
75#if FDNO > 3
76 char garbage[256] =
77 "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ@/"
78 "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ@/"
79 "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ@/"
80 "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ@/";
81#endif
82
83 switch (cmd) {
84 case TEST_INIT:
85 info->name = "poll_test";
86 info->category = "/main/poll/";
87 info->summary = "unit test for the ast_poll() API";
88 info->description =
89 "Verifies behavior for the ast_poll() API call";
90 return AST_TEST_NOT_RUN;
91 case TEST_EXECUTE:
92 break;
93 }
94
95 ast_test_status_update(test, "Creating handle that should NEVER block on write\n");
96 if ((fd[0] = open("/dev/null", O_WRONLY)) < 0) {
97 ast_test_status_update(test, "Unable to open a writable handle to /dev/null: %s\n", strerror(errno));
98 return AST_TEST_FAIL;
99 }
100
101 ast_test_status_update(test, "Creating handle that should NEVER block on read\n");
102 if ((fd[1] = open("/dev/zero", O_RDONLY)) < 0) {
103 ast_test_status_update(test, "Unable to open a readable handle to /dev/zero: %s\n", strerror(errno));
104 close(fd[0]);
105 return AST_TEST_FAIL;
106 }
107
108 ast_test_status_update(test, "Creating handle that should block on read\n");
109 if (pipe(rdblocker) < 0) {
110 ast_test_status_update(test, "Unable to open a pipe: %s\n", strerror(errno));
111 close(fd[0]);
112 close(fd[1]);
113 return AST_TEST_FAIL;
114 }
115
116#if FDNO > 3
117 ast_test_status_update(test, "Creating handle that should block on write\n");
118 if (pipe(wrblocker) < 0) {
119 ast_test_status_update(test, "Unable to open a pipe: %s\n", strerror(errno));
120 close(fd[0]);
121 close(fd[1]);
122 close(rdblocker[0]);
123 close(rdblocker[1]);
124 return AST_TEST_FAIL;
125 }
126
127 ast_test_status_update(test, "Starting thread to ensure we don't block forever\n");
128 if (ast_pthread_create_background(&failsafe_tid, NULL, failsafe_cancel, (void *) (long) pthread_self())) {
129 ast_test_status_update(test, "Unable to start failsafe thread\n");
130 close(fd[0]);
131 close(fd[1]);
132 close(fd[2]);
133 close(rdblocker[0]);
134 close(rdblocker[1]);
135 close(wrblocker[0]);
136 close(wrblocker[1]);
137 return AST_TEST_FAIL;
138 }
139
140 /* Fill the pipe full of data */
141 ast_test_status_update(test, "Making pipe block on write\n");
142 for (i = 0; i < 4096; i++) { /* 1MB of data should be more than enough for any pipe */
143 errno = 0;
144 if (write(wrblocker[1], garbage, sizeof(garbage)) < sizeof(garbage)) {
145 ast_test_status_update(test, "Got %d\n", errno);
146 if (errno == EINTR && ++consec_interrupt > 1) {
147 break;
148 }
149 } else {
150 consec_interrupt = 0;
151 }
152 }
153
154 ast_test_status_update(test, "Cancelling failsafe thread.\n");
155 pthread_cancel(failsafe_tid);
156 pthread_kill(failsafe_tid, SIGURG);
157 pthread_join(failsafe_tid, NULL);
158#endif
159
160 pfd[0].fd = fd[0];
161 pfd[1].fd = fd[1];
162 pfd[2].fd = rdblocker[0];
163#if FDNO > 3
164 pfd[3].fd = wrblocker[1];
165#endif
166
167 /* Need to ensure the infinite timeout doesn't stall the process */
168 ast_test_status_update(test, "Starting thread to ensure we don't block forever\n");
169 if (ast_pthread_create_background(&failsafe_tid, NULL, failsafe_cancel, (void *) (long) pthread_self())) {
170 ast_test_status_update(test, "Unable to start failsafe thread\n");
171 close(fd[0]);
172 close(fd[1]);
173 close(rdblocker[0]);
174 close(rdblocker[1]);
175#if FDNO > 3
176 close(wrblocker[0]);
177 close(wrblocker[1]);
178#endif
179 return AST_TEST_FAIL;
180 }
181
182 RESET;
183 if ((res2 = ast_poll(pfd, FDNO, -1)) != 2) {
184 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) : "");
185 res = AST_TEST_FAIL;
186 }
187
188 RESET;
189 if ((res2 = ast_poll2(pfd, FDNO, NULL)) != 2) {
190 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) : "");
191 res = AST_TEST_FAIL;
192 }
193
194 ast_test_status_update(test, "Cancelling failsafe thread.\n");
195 pthread_cancel(failsafe_tid);
196 pthread_kill(failsafe_tid, SIGURG);
197 pthread_join(failsafe_tid, NULL);
198
199 RESET;
200 if (ast_poll(pfd, FDNO, 0) != 2) {
201 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) : "");
202 res = AST_TEST_FAIL;
203 }
204
205 RESET;
206 if (ast_poll2(pfd, FDNO, &tv) != 2) {
207 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) : "");
208 res = AST_TEST_FAIL;
209 }
210
211 RESET;
212 if (ast_poll(pfd, FDNO, 1) != 2) {
213 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) : "");
214 res = AST_TEST_FAIL;
215 }
216
217 tv.tv_usec = 1000;
218 if (ast_poll2(pfd, FDNO, &tv) != 2) {
219 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) : "");
220 res = AST_TEST_FAIL;
221 }
222
223 close(fd[0]);
224 close(fd[1]);
225 close(rdblocker[0]);
226 close(rdblocker[1]);
227#if FDNO > 3
228 close(wrblocker[0]);
229 close(wrblocker[1]);
230#endif
231 return res;
232}
int errno
def info(msg)
int ast_poll2(struct pollfd *pArray, unsigned long n_fds, struct timeval *tv)
Same as poll(2), except the time is specified in microseconds and the tv argument is modified to indi...
Definition: poll.c:268
#define ast_poll(a, b, c)
Definition: poll-compat.h:88
#define NULL
Definition: resample.c:96
@ TEST_INIT
Definition: test.h:200
@ TEST_EXECUTE
Definition: test.h:201
#define ast_test_status_update(a, b, c...)
Definition: test.h:129
@ AST_TEST_PASS
Definition: test.h:195
@ AST_TEST_FAIL
Definition: test.h:196
@ AST_TEST_NOT_RUN
Definition: test.h:194
static void * failsafe_cancel(void *vparent)
Definition: test_poll.c:47
#define FDNO
#define RESET
Definition: test_poll.c:63
#define ast_pthread_create_background(a, b, c, d)
Definition: utils.h:592

References ast_poll, ast_poll2(), ast_pthread_create_background, AST_TEST_FAIL, AST_TEST_NOT_RUN, AST_TEST_PASS, ast_test_status_update, errno, failsafe_cancel(), FDNO, sip_to_pjsip::info(), NULL, RESET, TEST_EXECUTE, and TEST_INIT.

◆ failsafe_cancel()

static void * failsafe_cancel ( void *  vparent)
static

Definition at line 47 of file test_poll.c.

48{
49 pthread_t parent = (pthread_t) (long) vparent;
50
51 sleep(1);
52 pthread_testcancel();
53 pthread_kill(parent, SIGURG);
54 sleep(1);
55 pthread_testcancel();
56 pthread_kill(parent, SIGURG);
57 sleep(1);
58 pthread_testcancel();
59 pthread_kill(parent, SIGURG);
60 pthread_exit(NULL);
61}

References NULL.

Referenced by AST_TEST_DEFINE().

◆ load_module()

static int load_module ( void  )
static

Definition at line 240 of file test_poll.c.

241{
242 AST_TEST_REGISTER(poll_test);
244}
@ AST_MODULE_LOAD_SUCCESS
Definition: module.h:70
#define AST_TEST_REGISTER(cb)
Definition: test.h:127

References AST_MODULE_LOAD_SUCCESS, and AST_TEST_REGISTER.

◆ unload_module()

static int unload_module ( void  )
static

Definition at line 234 of file test_poll.c.

235{
236 AST_TEST_UNREGISTER(poll_test);
237 return 0;
238}
#define AST_TEST_UNREGISTER(cb)
Definition: test.h:128

References AST_TEST_UNREGISTER.

Variable Documentation

◆ __mod_info

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Poll test" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, .support_level = AST_MODULE_SUPPORT_CORE, }
static

Definition at line 246 of file test_poll.c.

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 246 of file test_poll.c.