Asterisk - The Open Source Telephony Project  18.5.0
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

Referenced by AST_TEST_DEFINE().

◆ RESET

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

Definition at line 63 of file test_poll.c.

Referenced by AST_TEST_DEFINE().

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.

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.

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 }
#define FDNO
#define RESET
Definition: test_poll.c:63
#define NULL
Definition: resample.c:96
#define ast_pthread_create_background(a, b, c, d)
Definition: utils.h:567
#define ast_test_status_update(a, b, c...)
Definition: test.h:129
#define ast_poll(a, b, c)
Definition: poll-compat.h:88
def info(msg)
int errno
static void * failsafe_cancel(void *vparent)
Definition: test_poll.c:47
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

◆ failsafe_cancel()

static void* failsafe_cancel ( void *  vparent)
static

Definition at line 47 of file test_poll.c.

References NULL.

Referenced by AST_TEST_DEFINE().

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 }
#define NULL
Definition: resample.c:96

◆ load_module()

static int load_module ( void  )
static

Definition at line 240 of file test_poll.c.

References AST_MODULE_LOAD_SUCCESS, and AST_TEST_REGISTER.

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

◆ unload_module()

static int unload_module ( void  )
static

Definition at line 234 of file test_poll.c.

References AST_TEST_UNREGISTER.

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

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.