libzmq  master
ZeroMQ C++ Core Engine (LIBZMQ)
testutil.hpp
Go to the documentation of this file.
1 /*
2  Copyright (c) 2007-2016 Contributors as noted in the AUTHORS file
3 
4  This file is part of libzmq, the ZeroMQ core engine in C++.
5 
6  libzmq is free software; you can redistribute it and/or modify it under
7  the terms of the GNU Lesser General Public License (LGPL) as published
8  by the Free Software Foundation; either version 3 of the License, or
9  (at your option) any later version.
10 
11  As a special exception, the Contributors give you permission to link
12  this library with independent modules to produce an executable,
13  regardless of the license terms of these independent modules, and to
14  copy and distribute the resulting executable under terms of your choice,
15  provided that you also meet, for each linked independent module, the
16  terms and conditions of the license of that module. An independent
17  module is a module which is not derived from or based on this library.
18  If you modify this library, you must extend this exception to your
19  version of the library.
20 
21  libzmq is distributed in the hope that it will be useful, but WITHOUT
22  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
23  FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
24  License for more details.
25 
26  You should have received a copy of the GNU Lesser General Public License
27  along with this program. If not, see <http://www.gnu.org/licenses/>.
28 */
29 
30 #ifndef __TESTUTIL_HPP_INCLUDED__
31 #define __TESTUTIL_HPP_INCLUDED__
32 
33 #if defined ZMQ_CUSTOM_PLATFORM_HPP
34 # include "platform.hpp"
35 #else
36 # include "../src/platform.hpp"
37 #endif
38 #include "../include/zmq.h"
39 #include "../src/stdint.hpp"
40 
41 // This defines the settle time used in tests; raise this if we
42 // get test failures on slower systems due to binds/connects not
43 // settled. Tested to work reliably at 1 msec on a fast PC.
44 #define SETTLE_TIME 300 // In msec
45 
46 #undef NDEBUG
47 #include <time.h>
48 #include <assert.h>
49 #include <stdarg.h>
50 #include <string>
51 #include <string.h>
52 
53 #if defined _WIN32
54 # include "windows.hpp"
55 # if defined _MSC_VER
56 # include <crtdbg.h>
57 # pragma warning(disable:4996)
58 # endif
59 #else
60 # include <pthread.h>
61 # include <unistd.h>
62 # include <signal.h>
63 # include <stdlib.h>
64 # include <sys/wait.h>
65 # include <sys/socket.h>
66 # include <netinet/in.h>
67 # include <arpa/inet.h>
68 #endif
69 
70 // Bounce a message from client to server and back
71 // For REQ/REP or DEALER/DEALER pairs only
72 void
73 bounce (void *server, void *client)
74 {
75  const char *content = "12345678ABCDEFGH12345678abcdefgh";
76 
77  // Send message from client to server
78  int rc = zmq_send (client, content, 32, ZMQ_SNDMORE);
79  assert (rc == 32);
80  rc = zmq_send (client, content, 32, 0);
81  assert (rc == 32);
82 
83  // Receive message at server side
84  char buffer [32];
85  rc = zmq_recv (server, buffer, 32, 0);
86  assert (rc == 32);
87  // Check that message is still the same
88  assert (memcmp (buffer, content, 32) == 0);
89  int rcvmore;
90  size_t sz = sizeof (rcvmore);
91  rc = zmq_getsockopt (server, ZMQ_RCVMORE, &rcvmore, &sz);
92  assert (rc == 0);
93  assert (rcvmore);
94  rc = zmq_recv (server, buffer, 32, 0);
95  assert (rc == 32);
96  // Check that message is still the same
97  assert (memcmp (buffer, content, 32) == 0);
98  rc = zmq_getsockopt (server, ZMQ_RCVMORE, &rcvmore, &sz);
99  assert (rc == 0);
100  assert (!rcvmore);
101 
102  // Send two parts back to client
103  rc = zmq_send (server, buffer, 32, ZMQ_SNDMORE);
104  assert (rc == 32);
105  rc = zmq_send (server, buffer, 32, 0);
106  assert (rc == 32);
107 
108  // Receive the two parts at the client side
109  rc = zmq_recv (client, buffer, 32, 0);
110  assert (rc == 32);
111  // Check that message is still the same
112  assert (memcmp (buffer, content, 32) == 0);
113  rc = zmq_getsockopt (client, ZMQ_RCVMORE, &rcvmore, &sz);
114  assert (rc == 0);
115  assert (rcvmore);
116  rc = zmq_recv (client, buffer, 32, 0);
117  assert (rc == 32);
118  // Check that message is still the same
119  assert (memcmp (buffer, content, 32) == 0);
120  rc = zmq_getsockopt (client, ZMQ_RCVMORE, &rcvmore, &sz);
121  assert (rc == 0);
122  assert (!rcvmore);
123 }
124 
125 // Same as bounce, but expect messages to never arrive
126 // for security or subscriber reasons.
127 void
128 expect_bounce_fail (void *server, void *client)
129 {
130  const char *content = "12345678ABCDEFGH12345678abcdefgh";
131  char buffer [32];
132  int timeout = 250;
133 
134  // Send message from client to server
135  int rc = zmq_setsockopt (client, ZMQ_SNDTIMEO, &timeout, sizeof (int));
136  assert (rc == 0);
137  rc = zmq_send (client, content, 32, ZMQ_SNDMORE);
138  assert ((rc == 32) || ((rc == -1) && (errno == EAGAIN)));
139  rc = zmq_send (client, content, 32, 0);
140  assert ((rc == 32) || ((rc == -1) && (errno == EAGAIN)));
141 
142  // Receive message at server side (should not succeed)
143  rc = zmq_setsockopt (server, ZMQ_RCVTIMEO, &timeout, sizeof (int));
144  assert (rc == 0);
145  rc = zmq_recv (server, buffer, 32, 0);
146  assert (rc == -1);
147  assert (zmq_errno () == EAGAIN);
148 
149  // Send message from server to client to test other direction
150  // If connection failed, send may block, without a timeout
151  rc = zmq_setsockopt (server, ZMQ_SNDTIMEO, &timeout, sizeof (int));
152  assert (rc == 0);
153  rc = zmq_send (server, content, 32, ZMQ_SNDMORE);
154  assert (rc == 32 || (rc == -1 && zmq_errno () == EAGAIN));
155  rc = zmq_send (server, content, 32, 0);
156  assert (rc == 32 || (rc == -1 && zmq_errno () == EAGAIN));
157 
158  // Receive message at client side (should not succeed)
159  rc = zmq_setsockopt (client, ZMQ_RCVTIMEO, &timeout, sizeof (int));
160  assert (rc == 0);
161  rc = zmq_recv (client, buffer, 32, 0);
162  assert (rc == -1);
163  assert (zmq_errno () == EAGAIN);
164 }
165 
166 // Receive 0MQ string from socket and convert into C string
167 // Caller must free returned string. Returns NULL if the context
168 // is being terminated.
169 char *
170 s_recv (void *socket) {
171  char buffer [256];
172  int size = zmq_recv (socket, buffer, 255, 0);
173  if (size == -1)
174  return NULL;
175  if (size > 255)
176  size = 255;
177  buffer [size] = 0;
178  return strdup (buffer);
179 }
180 
181 // Convert C string to 0MQ string and send to socket
182 int
183 s_send (void *socket, const char *string) {
184  int size = zmq_send (socket, string, strlen (string), 0);
185  return size;
186 }
187 
188 // Sends string as 0MQ string, as multipart non-terminal
189 int
190 s_sendmore (void *socket, const char *string) {
191  int size = zmq_send (socket, string, strlen (string), ZMQ_SNDMORE);
192  return size;
193 }
194 
195 #define streq(s1,s2) (!strcmp ((s1), (s2)))
196 #define strneq(s1,s2) (strcmp ((s1), (s2)))
197 
198 const char *SEQ_END = (const char *) 1;
199 
200 // Sends a message composed of frames that are C strings or null frames.
201 // The list must be terminated by SEQ_END.
202 // Example: s_send_seq (req, "ABC", 0, "DEF", SEQ_END);
203 
204 void
205 s_send_seq (void *socket, ...)
206 {
207  va_list ap;
208  va_start (ap, socket);
209  const char * data = va_arg (ap, const char *);
210  while (true)
211  {
212  const char * prev = data;
213  data = va_arg (ap, const char *);
214  bool end = data == SEQ_END;
215 
216  if (!prev) {
217  int rc = zmq_send (socket, 0, 0, end ? 0 : ZMQ_SNDMORE);
218  assert (rc != -1);
219  }
220  else {
221  int rc = zmq_send (socket, prev, strlen (prev)+1, end ? 0 : ZMQ_SNDMORE);
222  assert (rc != -1);
223  }
224  if (end)
225  break;
226  }
227  va_end (ap);
228 }
229 
230 // Receives message a number of frames long and checks that the frames have
231 // the given data which can be either C strings or 0 for a null frame.
232 // The list must be terminated by SEQ_END.
233 // Example: s_recv_seq (rep, "ABC", 0, "DEF", SEQ_END);
234 
235 void
236 s_recv_seq (void *socket, ...)
237 {
238  zmq_msg_t msg;
239  zmq_msg_init (&msg);
240 
241  int more;
242  size_t more_size = sizeof(more);
243 
244  va_list ap;
245  va_start (ap, socket);
246  const char * data = va_arg (ap, const char *);
247 
248  while (true) {
249  int rc = zmq_msg_recv (&msg, socket, 0);
250  assert (rc != -1);
251 
252  if (!data)
253  assert (zmq_msg_size (&msg) == 0);
254  else
255  assert (strcmp (data, (const char *)zmq_msg_data (&msg)) == 0);
256 
257  data = va_arg (ap, const char *);
258  bool end = data == SEQ_END;
259 
260  rc = zmq_getsockopt (socket, ZMQ_RCVMORE, &more, &more_size);
261  assert (rc == 0);
262 
263  assert (!more == end);
264  if (end)
265  break;
266  }
267  va_end (ap);
268 
269  zmq_msg_close (&msg);
270 }
271 
272 
273 // Sets a zero linger period on a socket and closes it.
274 void
275 close_zero_linger (void *socket)
276 {
277  int linger = 0;
278  int rc = zmq_setsockopt (socket, ZMQ_LINGER, &linger, sizeof(linger));
279  assert (rc == 0 || errno == ETERM);
280  rc = zmq_close (socket);
281  assert (rc == 0);
282 }
283 
284 void
286 {
287 #if defined _WIN32
288 # if defined _MSC_VER
289  _set_abort_behavior( 0, _WRITE_ABORT_MSG);
290  _CrtSetReportMode( _CRT_ASSERT, _CRTDBG_MODE_FILE );
291  _CrtSetReportFile( _CRT_ASSERT, _CRTDBG_FILE_STDERR );
292 # endif
293 #else
294 #if defined ZMQ_HAVE_CYGWIN
295  // abort test after 121 seconds
296  alarm(121);
297 #else
298 # if !defined ZMQ_DISABLE_TEST_TIMEOUT
299  // abort test after 60 seconds
300  alarm(60);
301 # endif
302 #endif
303 #endif
304 #if defined __MVS__
305  // z/OS UNIX System Services: Ignore SIGPIPE during test runs, as a
306  // workaround for no SO_NOGSIGPIPE socket option.
307  signal(SIGPIPE, SIG_IGN);
308 #endif
309 }
310 
311 // Provide portable millisecond sleep
312 // http://www.cplusplus.com/forum/unices/60161/
313 // http://en.cppreference.com/w/cpp/thread/sleep_for
314 
315 void
316 msleep (int milliseconds)
317 {
318 #ifdef ZMQ_HAVE_WINDOWS
319  Sleep (milliseconds);
320 #else
321  usleep (static_cast <useconds_t> (milliseconds) * 1000);
322 #endif
323 }
324 
325 // check if IPv6 is available (0/false if not, 1/true if it is)
326 // only way to reliably check is to actually open a socket and try to bind it
327 int
329 {
330  int rc, ipv6 = 1;
331  struct sockaddr_in6 test_addr;
332 
333  memset (&test_addr, 0, sizeof (test_addr));
334  test_addr.sin6_family = AF_INET6;
335  inet_pton (AF_INET6, "::1", &(test_addr.sin6_addr));
336 
337 #ifdef ZMQ_HAVE_WINDOWS
338  SOCKET fd = socket (AF_INET6, SOCK_STREAM, IPPROTO_IP);
339  if (fd == INVALID_SOCKET)
340  ipv6 = 0;
341  else {
342  setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const char *)&ipv6, sizeof(int));
343  rc = setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (const char *)&ipv6, sizeof(int));
344  if (rc == SOCKET_ERROR)
345  ipv6 = 0;
346  else {
347  rc = bind (fd, (struct sockaddr *)&test_addr, sizeof (test_addr));
348  if (rc == SOCKET_ERROR)
349  ipv6 = 0;
350  }
351  closesocket (fd);
352  }
353 #else
354  int fd = socket (AF_INET6, SOCK_STREAM, IPPROTO_IP);
355  if (fd == -1)
356  ipv6 = 0;
357  else {
358  setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &ipv6, sizeof(int));
359  rc = setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &ipv6, sizeof(int));
360  if (rc != 0)
361  ipv6 = 0;
362  else {
363  rc = bind (fd, (struct sockaddr *)&test_addr, sizeof (test_addr));
364  if (rc != 0)
365  ipv6 = 0;
366  }
367  close (fd);
368  }
369 #endif
370 
371  return ipv6;
372 }
373 
374 #endif
#define size
void msleep(int milliseconds)
Definition: testutil.hpp:316
ZMQ_EXPORT int zmq_setsockopt(void *s, int option, const void *optval, size_t optvallen)
Definition: zmq.cpp:265
int s_sendmore(void *socket, const char *string)
Definition: testutil.hpp:190
#define ZMQ_SNDMORE
Definition: zmq.h:346
Definition: command.hpp:84
int is_ipv6_available(void)
Definition: testutil.hpp:328
void setup_test_environment(void)
Definition: testutil.hpp:285
ZMQ_EXPORT int zmq_recv(void *s, void *buf, size_t len, int flags)
Definition: zmq.cpp:507
void expect_bounce_fail(void *server, void *client)
Definition: testutil.hpp:128
ZMQ_EXPORT int zmq_errno(void)
Definition: zmq.cpp:107
ZMQ_EXPORT void * zmq_msg_data(zmq_msg_t *msg)
Definition: zmq.cpp:666
#define ZMQ_LINGER
Definition: zmq.h:276
#define ZMQ_SNDTIMEO
Definition: zmq.h:285
#define ETERM
Definition: zmq.h:169
ZMQ_EXPORT int zmq_getsockopt(void *s, int option, void *optval, size_t *optvallen)
Definition: zmq.cpp:277
ZMQ_EXPORT int zmq_close(void *s)
Definition: zmq.cpp:255
ZMQ_EXPORT int zmq_msg_recv(zmq_msg_t *msg, void *s, int flags)
Definition: zmq.cpp:640
Definition: zmq.h:221
#define ZMQ_RCVMORE
Definition: zmq.h:272
char * s_recv(void *socket)
Definition: testutil.hpp:170
ZMQ_EXPORT int zmq_send(void *s, const void *buf, size_t len, int flags)
Definition: zmq.cpp:387
void close_zero_linger(void *socket)
Definition: testutil.hpp:275
void bounce(void *server, void *client)
Definition: testutil.hpp:73
void s_recv_seq(void *socket,...)
Definition: testutil.hpp:236
const char * SEQ_END
Definition: testutil.hpp:198
int s_send(void *socket, const char *string)
Definition: testutil.hpp:183
ZMQ_EXPORT int zmq_msg_close(zmq_msg_t *msg)
Definition: zmq.cpp:651
void s_send_seq(void *socket,...)
Definition: testutil.hpp:205
ZMQ_EXPORT size_t zmq_msg_size(zmq_msg_t *msg)
Definition: zmq.cpp:671
#define ZMQ_RCVTIMEO
Definition: zmq.h:284
ZMQ_EXPORT int zmq_msg_init(zmq_msg_t *msg)
Definition: zmq.cpp:613