testutil.hpp 13.5 KB
Newer Older
Guido Goldstein's avatar
Guido Goldstein committed
1
/*
2
    Copyright (c) 2007-2017 Contributors as noted in the AUTHORS file
Guido Goldstein's avatar
Guido Goldstein committed
3

4
    This file is part of libzmq, the ZeroMQ core engine in C++.
Guido Goldstein's avatar
Guido Goldstein committed
5

6 7 8
    libzmq is free software; you can redistribute it and/or modify it under
    the terms of the GNU Lesser General Public License (LGPL) as published
    by the Free Software Foundation; either version 3 of the License, or
Guido Goldstein's avatar
Guido Goldstein committed
9 10
    (at your option) any later version.

11 12 13 14 15 16 17 18 19 20 21 22 23 24
    As a special exception, the Contributors give you permission to link
    this library with independent modules to produce an executable,
    regardless of the license terms of these independent modules, and to
    copy and distribute the resulting executable under terms of your choice,
    provided that you also meet, for each linked independent module, the
    terms and conditions of the license of that module. An independent
    module is a module which is not derived from or based on this library.
    If you modify this library, you must extend this exception to your
    version of the library.

    libzmq is distributed in the hope that it will be useful, but WITHOUT
    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
    License for more details.
Guido Goldstein's avatar
Guido Goldstein committed
25

26
    You should have received a copy of the GNU Lesser General Public License
Guido Goldstein's avatar
Guido Goldstein committed
27 28 29
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

30 31
#ifndef __TESTUTIL_HPP_INCLUDED__
#define __TESTUTIL_HPP_INCLUDED__
Guido Goldstein's avatar
Guido Goldstein committed
32

33
#if defined ZMQ_CUSTOM_PLATFORM_HPP
34
#include "platform.hpp"
35
#else
36
#include "../src/platform.hpp"
37
#endif
38 39
#include "../include/zmq.h"
#include "../src/stdint.hpp"
40

41 42 43
//  This defines the settle time used in tests; raise this if we
//  get test failures on slower systems due to binds/connects not
//  settled. Tested to work reliably at 1 msec on a fast PC.
44
#define SETTLE_TIME 300 //  In msec
45
//  Commonly used buffer size for ZMQ_LAST_ENDPOINT
46
#define MAX_SOCKET_STRING sizeof ("tcp://[::ffff:127.127.127.127]:65536")
47 48 49 50 51 52 53 54 55

//  We need to test codepaths with non-random bind ports. List them here to
//  keep them unique, to allow parallel test runs.
#define ENDPOINT_0 "tcp://127.0.0.1:5555"
#define ENDPOINT_1 "tcp://127.0.0.1:5556"
#define ENDPOINT_2 "tcp://127.0.0.1:5557"
#define ENDPOINT_3 "tcp://127.0.0.1:5558"
#define ENDPOINT_4 "udp://127.0.0.1:5559"
#define ENDPOINT_5 "udp://127.0.0.1:5560"
56

57
#undef NDEBUG
58
#include <time.h>
59
#include <assert.h>
60
#include <stdarg.h>
61
#include <string>
62
#include <string.h>
63

64
#if defined _WIN32
65 66 67 68
#include "../src/windows.hpp"
#if defined _MSC_VER
#include <crtdbg.h>
#pragma warning(disable : 4996)
69
// iphlpapi is needed for if_nametoindex (not on Windows XP)
70 71 72 73
#if !defined ZMQ_HAVE_WINDOWS_TARGET_XP
#pragma comment(lib, "iphlpapi")
#endif
#endif
74
#else
75 76 77 78 79 80 81 82
#include <pthread.h>
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
83 84
#include <net/if.h>
#include <netdb.h>
85 86 87 88
#if defined(ZMQ_HAVE_AIX)
#include <sys/types.h>
#include <sys/socketvar.h>
#endif
89 90
#endif

91 92 93 94
// duplicated from fd.hpp
#ifdef ZMQ_HAVE_WINDOWS
#define close closesocket
typedef int socket_size_t;
95 96 97 98
const char *as_setsockopt_opt_t (const void *opt)
{
    return static_cast<const char *> (opt);
}
99 100 101 102 103 104 105 106 107 108 109 110 111 112 113
#if defined _MSC_VER && _MSC_VER <= 1400
typedef UINT_PTR fd_t;
enum
{
    retired_fd = (fd_t) (~0)
};
#else
typedef SOCKET fd_t;
enum
{
    retired_fd = (fd_t) INVALID_SOCKET
};
#endif
#else
typedef size_t socket_size_t;
114
const void *as_setsockopt_opt_t (const void *opt_)
115
{
116
    return opt_;
117
}
118 119 120 121 122 123 124
typedef int fd_t;
enum
{
    retired_fd = -1
};
#endif

125
#define LIBZMQ_UNUSED(object) (void) object
126

127 128
//  Bounce a message from client to server and back
//  For REQ/REP or DEALER/DEALER pairs only
129
void bounce (void *server_, void *client_)
Guido Goldstein's avatar
Guido Goldstein committed
130
{
131 132
    const char *content = "12345678ABCDEFGH12345678abcdefgh";

133
    //  Send message from client to server
134
    int rc = zmq_send (client_, content, 32, ZMQ_SNDMORE);
135
    assert (rc == 32);
136
    rc = zmq_send (client_, content, 32, 0);
137
    assert (rc == 32);
138

139
    //  Receive message at server side
140
    char buffer[32];
141
    rc = zmq_recv (server_, buffer, 32, 0);
142
    assert (rc == 32);
143 144
    //  Check that message is still the same
    assert (memcmp (buffer, content, 32) == 0);
145 146
    int rcvmore;
    size_t sz = sizeof (rcvmore);
147
    rc = zmq_getsockopt (server_, ZMQ_RCVMORE, &rcvmore, &sz);
148 149
    assert (rc == 0);
    assert (rcvmore);
150
    rc = zmq_recv (server_, buffer, 32, 0);
151
    assert (rc == 32);
152 153
    //  Check that message is still the same
    assert (memcmp (buffer, content, 32) == 0);
154
    rc = zmq_getsockopt (server_, ZMQ_RCVMORE, &rcvmore, &sz);
155 156
    assert (rc == 0);
    assert (!rcvmore);
157

158
    //  Send two parts back to client
159
    rc = zmq_send (server_, buffer, 32, ZMQ_SNDMORE);
160
    assert (rc == 32);
161
    rc = zmq_send (server_, buffer, 32, 0);
162
    assert (rc == 32);
163

164
    //  Receive the two parts at the client side
165
    rc = zmq_recv (client_, buffer, 32, 0);
166
    assert (rc == 32);
167 168
    //  Check that message is still the same
    assert (memcmp (buffer, content, 32) == 0);
169
    rc = zmq_getsockopt (client_, ZMQ_RCVMORE, &rcvmore, &sz);
170 171
    assert (rc == 0);
    assert (rcvmore);
172
    rc = zmq_recv (client_, buffer, 32, 0);
173
    assert (rc == 32);
174 175
    //  Check that message is still the same
    assert (memcmp (buffer, content, 32) == 0);
176
    rc = zmq_getsockopt (client_, ZMQ_RCVMORE, &rcvmore, &sz);
177 178
    assert (rc == 0);
    assert (!rcvmore);
Guido Goldstein's avatar
Guido Goldstein committed
179 180
}

MinRK's avatar
MinRK committed
181 182
//  Same as bounce, but expect messages to never arrive
//  for security or subscriber reasons.
183
void expect_bounce_fail (void *server_, void *client_)
MinRK's avatar
MinRK committed
184 185
{
    const char *content = "12345678ABCDEFGH12345678abcdefgh";
186
    char buffer[32];
187
    int timeout = 250;
MinRK's avatar
MinRK committed
188 189

    //  Send message from client to server
190
    int rc = zmq_setsockopt (client_, ZMQ_SNDTIMEO, &timeout, sizeof (int));
191
    assert (rc == 0);
192
    rc = zmq_send (client_, content, 32, ZMQ_SNDMORE);
193
    assert ((rc == 32) || ((rc == -1) && (errno == EAGAIN)));
194
    rc = zmq_send (client_, content, 32, 0);
195
    assert ((rc == 32) || ((rc == -1) && (errno == EAGAIN)));
MinRK's avatar
MinRK committed
196 197

    //  Receive message at server side (should not succeed)
198
    rc = zmq_setsockopt (server_, ZMQ_RCVTIMEO, &timeout, sizeof (int));
MinRK's avatar
MinRK committed
199
    assert (rc == 0);
200
    rc = zmq_recv (server_, buffer, 32, 0);
MinRK's avatar
MinRK committed
201
    assert (rc == -1);
202
    assert (zmq_errno () == EAGAIN);
MinRK's avatar
MinRK committed
203

204
    //  Send message from server to client to test other direction
205
    //  If connection failed, send may block, without a timeout
206
    rc = zmq_setsockopt (server_, ZMQ_SNDTIMEO, &timeout, sizeof (int));
207
    assert (rc == 0);
208
    rc = zmq_send (server_, content, 32, ZMQ_SNDMORE);
209
    assert (rc == 32 || (rc == -1 && zmq_errno () == EAGAIN));
210
    rc = zmq_send (server_, content, 32, 0);
211
    assert (rc == 32 || (rc == -1 && zmq_errno () == EAGAIN));
MinRK's avatar
MinRK committed
212

213
    //  Receive message at client side (should not succeed)
214
    rc = zmq_setsockopt (client_, ZMQ_RCVTIMEO, &timeout, sizeof (int));
215
    assert (rc == 0);
216
    rc = zmq_recv (client_, buffer, 32, 0);
MinRK's avatar
MinRK committed
217
    assert (rc == -1);
218
    assert (zmq_errno () == EAGAIN);
MinRK's avatar
MinRK committed
219 220
}

221 222 223
//  Receive 0MQ string from socket and convert into C string
//  Caller must free returned string. Returns NULL if the context
//  is being terminated.
224
char *s_recv (void *socket_)
225 226
{
    char buffer[256];
227
    int size = zmq_recv (socket_, buffer, 255, 0);
228 229 230 231
    if (size == -1)
        return NULL;
    if (size > 255)
        size = 255;
232
    buffer[size] = 0;
233 234 235 236
    return strdup (buffer);
}

//  Convert C string to 0MQ string and send to socket
237
int s_send (void *socket_, const char *string_)
238
{
239
    int size = zmq_send (socket_, string_, strlen (string_), 0);
240 241 242 243
    return size;
}

//  Sends string as 0MQ string, as multipart non-terminal
244
int s_sendmore (void *socket_, const char *string_)
245
{
246
    int size = zmq_send (socket_, string_, strlen (string_), ZMQ_SNDMORE);
247 248 249
    return size;
}

250 251
#define streq(s1, s2) (!strcmp ((s1), (s2)))
#define strneq(s1, s2) (strcmp ((s1), (s2)))
252

253
const char *SEQ_END = (const char *) 1;
254 255 256 257

//  Sends a message composed of frames that are C strings or null frames.
//  The list must be terminated by SEQ_END.
//  Example: s_send_seq (req, "ABC", 0, "DEF", SEQ_END);
258

259
void s_send_seq (void *socket_, ...)
260 261
{
    va_list ap;
262
    va_start (ap, socket_);
263 264 265
    const char *data = va_arg (ap, const char *);
    while (true) {
        const char *prev = data;
266 267 268
        data = va_arg (ap, const char *);
        bool end = data == SEQ_END;

269
        if (!prev) {
270
            int rc = zmq_send (socket_, 0, 0, end ? 0 : ZMQ_SNDMORE);
271
            assert (rc != -1);
272
        } else {
273 274
            int rc = zmq_send (socket_, prev, strlen (prev) + 1,
                               end ? 0 : ZMQ_SNDMORE);
275 276 277 278 279 280 281 282 283 284 285 286
            assert (rc != -1);
        }
        if (end)
            break;
    }
    va_end (ap);
}

//  Receives message a number of frames long and checks that the frames have
//  the given data which can be either C strings or 0 for a null frame.
//  The list must be terminated by SEQ_END.
//  Example: s_recv_seq (rep, "ABC", 0, "DEF", SEQ_END);
287

288
void s_recv_seq (void *socket_, ...)
289 290 291 292 293
{
    zmq_msg_t msg;
    zmq_msg_init (&msg);

    int more;
294
    size_t more_size = sizeof (more);
295 296

    va_list ap;
297
    va_start (ap, socket_);
298
    const char *data = va_arg (ap, const char *);
299

300
    while (true) {
301
        int rc = zmq_msg_recv (&msg, socket_, 0);
302 303 304 305 306
        assert (rc != -1);

        if (!data)
            assert (zmq_msg_size (&msg) == 0);
        else
307
            assert (strcmp (data, (const char *) zmq_msg_data (&msg)) == 0);
308 309 310 311

        data = va_arg (ap, const char *);
        bool end = data == SEQ_END;

312
        rc = zmq_getsockopt (socket_, ZMQ_RCVMORE, &more, &more_size);
313 314 315 316 317 318 319 320 321 322 323
        assert (rc == 0);

        assert (!more == end);
        if (end)
            break;
    }
    va_end (ap);

    zmq_msg_close (&msg);
}

324

325
//  Sets a zero linger period on a socket and closes it.
326
void close_zero_linger (void *socket_)
327 328
{
    int linger = 0;
329
    int rc = zmq_setsockopt (socket_, ZMQ_LINGER, &linger, sizeof (linger));
330
    assert (rc == 0 || errno == ETERM);
331
    rc = zmq_close (socket_);
332 333 334
    assert (rc == 0);
}

335
void setup_test_environment (void)
336 337
{
#if defined _WIN32
338 339 340 341 342
#if defined _MSC_VER
    _set_abort_behavior (0, _WRITE_ABORT_MSG);
    _CrtSetReportMode (_CRT_ASSERT, _CRTDBG_MODE_FILE);
    _CrtSetReportFile (_CRT_ASSERT, _CRTDBG_FILE_STDERR);
#endif
343 344 345
#else
#if defined ZMQ_HAVE_CYGWIN
    // abort test after 121 seconds
346
    alarm (121);
347
#else
348
#if !defined ZMQ_DISABLE_TEST_TIMEOUT
349
    // abort test after 60 seconds
350 351
    alarm (60);
#endif
352
#endif
353
#endif
354 355 356
#if defined __MVS__
    // z/OS UNIX System Services: Ignore SIGPIPE during test runs, as a
    // workaround for no SO_NOGSIGPIPE socket option.
357
    signal (SIGPIPE, SIG_IGN);
358
#endif
359 360
}

361
//  Provide portable millisecond sleep
362 363 364
//  http://www.cplusplus.com/forum/unices/60161/
//  http://en.cppreference.com/w/cpp/thread/sleep_for

365
void msleep (int milliseconds_)
366
{
367
#ifdef ZMQ_HAVE_WINDOWS
368
    Sleep (milliseconds_);
369
#else
370
    usleep (static_cast<useconds_t> (milliseconds_) * 1000);
371 372 373
#endif
}

374 375
// check if IPv6 is available (0/false if not, 1/true if it is)
// only way to reliably check is to actually open a socket and try to bind it
376
int is_ipv6_available (void)
377
{
378
#if defined(ZMQ_HAVE_WINDOWS) && (_WIN32_WINNT < 0x0600)
379 380
    return 0;
#else
381 382 383 384 385 386 387
    int rc, ipv6 = 1;
    struct sockaddr_in6 test_addr;

    memset (&test_addr, 0, sizeof (test_addr));
    test_addr.sin6_family = AF_INET6;
    inet_pton (AF_INET6, "::1", &(test_addr.sin6_addr));

388 389
    fd_t fd = socket (AF_INET6, SOCK_STREAM, IPPROTO_IP);
    if (fd == retired_fd)
390 391
        ipv6 = 0;
    else {
392
#ifdef ZMQ_HAVE_WINDOWS
393 394 395 396
        setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, (const char *) &ipv6,
                    sizeof (int));
        rc = setsockopt (fd, IPPROTO_IPV6, IPV6_V6ONLY, (const char *) &ipv6,
                         sizeof (int));
397 398 399
        if (rc == SOCKET_ERROR)
            ipv6 = 0;
        else {
400
            rc = bind (fd, (struct sockaddr *) &test_addr, sizeof (test_addr));
401 402 403 404
            if (rc == SOCKET_ERROR)
                ipv6 = 0;
        }
#else
405 406
        setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, &ipv6, sizeof (int));
        rc = setsockopt (fd, IPPROTO_IPV6, IPV6_V6ONLY, &ipv6, sizeof (int));
407 408 409
        if (rc != 0)
            ipv6 = 0;
        else {
410
            rc = bind (fd, (struct sockaddr *) &test_addr, sizeof (test_addr));
411 412 413
            if (rc != 0)
                ipv6 = 0;
        }
414
#endif
415 416 417 418
        close (fd);
    }

    return ipv6;
419
#endif // _WIN32_WINNT < 0x0600
420
}
421

422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444
// check if tipc is available (0/false if not, 1/true if it is)
// only way to reliably check is to actually open a socket and try to bind it
// as it depends on a non-default kernel module to be already loaded
int is_tipc_available (void)
{
#ifndef ZMQ_HAVE_TIPC
    return 0;
#else
    int tipc = 0;

    void *ctx = zmq_init (1);
    assert (ctx);
    void *rep = zmq_socket (ctx, ZMQ_REP);
    assert (rep);
    tipc = zmq_bind (rep, "tipc://{5560,0,0}");

    zmq_close (rep);
    zmq_ctx_term (ctx);

    return tipc == 0;
#endif // ZMQ_HAVE_TIPC
}

445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472
//  Wrapper around 'inet_pton' for systems that don't support it (e.g. Windows
//  XP)
int test_inet_pton (int af_, const char *src_, void *dst_)
{
#if defined(ZMQ_HAVE_WINDOWS) && (_WIN32_WINNT < 0x0600)
    if (af_ == AF_INET) {
        struct in_addr *ip4addr = (struct in_addr *) dst_;

        ip4addr->s_addr = inet_addr (src_);

        //  INADDR_NONE is -1 which is also a valid representation for IP
        //  255.255.255.255
        if (ip4addr->s_addr == INADDR_NONE
            && strcmp (src_, "255.255.255.255") != 0) {
            return 0;
        }

        //  Success
        return 1;
    } else {
        //  Not supported.
        return 0;
    }
#else
    return inet_pton (af_, src_, dst_);
#endif
}

Guido Goldstein's avatar
Guido Goldstein committed
473
#endif