testutil_unity.hpp 13.7 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
#pragma once

/*
Copyright (c) 2018 Contributors as noted in the AUTHORS file

This file is part of libzmq, the ZeroMQ core engine in C++.

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
(at your option) any later version.

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.

You should have received a copy of the GNU Lesser General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "../include/zmq.h"

34 35
#include "testutil.hpp"

36 37
#include <unity.h>

38 39 40
// Internal helper functions that are not intended to be directly called from
// tests. They must be declared in the header since they are used by macros.

41 42
int test_assert_success_message_errno_helper (int rc_,
                                              const char *msg_,
43 44
                                              const char *expr_,
                                              int line);
45

46 47 48 49 50 51 52
int test_assert_success_message_raw_errno_helper (
  int rc_, const char *msg_, const char *expr_, int line, bool zero_ = false);

int test_assert_success_message_raw_zero_errno_helper (int rc_,
                                                       const char *msg_,
                                                       const char *expr_,
                                                       int line);
53

54 55
int test_assert_failure_message_raw_errno_helper (
  int rc_, int expected_errno_, const char *msg_, const char *expr_, int line);
56

57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74
/////////////////////////////////////////////////////////////////////////////
// Macros extending Unity's TEST_ASSERT_* macros in a similar fashion.
/////////////////////////////////////////////////////////////////////////////

// For TEST_ASSERT_SUCCESS_ERRNO, TEST_ASSERT_SUCCESS_MESSAGE_ERRNO and
// TEST_ASSERT_FAILURE_ERRNO, 'expr' must be an expression evaluating
// to a result in the style of a libzmq API function, i.e. an integer which
// is non-negative in case of success, and -1 in case of a failure, and sets
// the value returned by zmq_errno () to the error code.
// TEST_ASSERT_SUCCESS_RAW_ERRNO and TEST_ASSERT_FAILURE_RAW_ERRNO are similar,
// but used with the native socket API functions, and expect that the error
// code can be retrieved in the native way (i.e. WSAGetLastError on Windows,
// and errno otherwise).

// Asserts that the libzmq API 'expr' is successful. In case of a failure, the
// assertion message includes the literal 'expr', the error number as
// determined by zmq_errno(), and the additional 'msg'.
// In case of success, the result of the macro is the result of 'expr'.
75
#define TEST_ASSERT_SUCCESS_MESSAGE_ERRNO(expr, msg)                           \
76
    test_assert_success_message_errno_helper (expr, msg, #expr, __LINE__)
77

78 79 80 81 82 83 84 85
// Asserts that the libzmq API 'expr' is successful. In case of a failure, the
// assertion message includes the literal 'expr' and the error code.
// A typical use would be:
//   TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (socket, endpoint));
// In case of success, the result of the macro is the result of 'expr'.
//
// If an additional message should be displayed in case of a failure, use
// TEST_ASSERT_SUCCESS_MESSAGE_ERRNO.
86
#define TEST_ASSERT_SUCCESS_ERRNO(expr)                                        \
87
    test_assert_success_message_errno_helper (expr, NULL, #expr, __LINE__)
88

89 90 91 92 93
// Asserts that the socket API 'expr' is successful. In case of a failure, the
// assertion message includes the literal 'expr' and the error code.
// A typical use would be:
//   TEST_ASSERT_SUCCESS_RAW_ERRNO (send (fd, buffer, 64, 0));
// In case of success, the result of the macro is the result of 'expr'.
94 95
// Success is strictly defined by a return value different from -1, as opposed
// to checking that it is 0, like TEST_ASSERT_FAILURE_RAW_ZERO_ERRNO does.
96
#define TEST_ASSERT_SUCCESS_RAW_ERRNO(expr)                                    \
97
    test_assert_success_message_raw_errno_helper (expr, NULL, #expr, __LINE__)
98

99 100 101 102 103 104 105 106 107 108 109
// Asserts that the socket API 'expr' is successful. In case of a failure, the
// assertion message includes the literal 'expr' and the error code.
// A typical use would be:
//   TEST_ASSERT_SUCCESS_RAW_ZERO_ERRNO (send (fd, buffer, 64, 0));
// In case of success, the result of the macro is the result of 'expr'.
// Success is strictly defined by a return value of 0, as opposed to checking
// that it is not -1, like TEST_ASSERT_FAILURE_RAW_ERRNO does.
#define TEST_ASSERT_SUCCESS_RAW_ZERO_ERRNO(expr)                               \
    test_assert_success_message_raw_zero_errno_helper (expr, NULL, #expr,      \
                                                       __LINE__)

110 111 112 113
// Asserts that the socket API 'expr' is not successful, and the error code is
// 'error_code'. In case of an unexpected succces, or a failure with an
// unexpected error code, the assertion message includes the literal 'expr'
// and, in case of a failure, the actual error code.
114
#define TEST_ASSERT_FAILURE_RAW_ERRNO(error_code, expr)                        \
115 116
    test_assert_failure_message_raw_errno_helper (expr, error_code, NULL,      \
                                                  #expr, __LINE__)
117

118 119 120 121
// Asserts that the libzmq API 'expr' is not successful, and the error code is
// 'error_code'. In case of an unexpected succces, or a failure with an
// unexpected error code, the assertion message includes the literal 'expr'
// and, in case of a failure, the actual error code.
122 123
#define TEST_ASSERT_FAILURE_ERRNO(error_code, expr)                            \
    {                                                                          \
124 125
        int _rc = (expr);                                                      \
        TEST_ASSERT_EQUAL_INT (-1, _rc);                                       \
126 127 128
        TEST_ASSERT_EQUAL_INT (error_code, errno);                             \
    }

129 130 131 132 133 134 135 136 137 138 139
/////////////////////////////////////////////////////////////////////////////
// Utility functions for testing sending and receiving.
/////////////////////////////////////////////////////////////////////////////

// Sends a string via a libzmq socket, and expects the operation to be
// successful (the meaning of which depends on the socket type and configured
// options, and might include dropping the message). Otherwise, a Unity test
// assertion is triggered.
// 'socket_' must be the libzmq socket to use for sending.
// 'str_' must be a 0-terminated string.
// 'flags_' are as documented by the zmq_send function.
140
void send_string_expect_success (void *socket_, const char *str_, int flags_);
141

142 143 144 145 146 147
// Receives a message via a libzmq socket, and expects the operation to be
// successful, and the message to be a given string. Otherwise, a Unity test
// assertion is triggered.
// 'socket_' must be the libzmq socket to use for receiving.
// 'str_' must be a 0-terminated string.
// 'flags_' are as documented by the zmq_recv function.
148
void recv_string_expect_success (void *socket_, const char *str_, int flags_);
149

150 151 152 153 154 155 156 157
// Sends a byte array via a libzmq socket, and expects the operation to be
// successful (the meaning of which depends on the socket type and configured
// options, and might include dropping the message). Otherwise, a Unity test
// assertion is triggered.
// 'socket_' must be the libzmq socket to use for sending.
// 'array_' must be a C uint8_t array. The array size is automatically
// determined via template argument deduction.
// 'flags_' are as documented by the zmq_send function.
158 159 160 161 162 163 164 165 166
template <size_t SIZE>
void send_array_expect_success (void *socket_,
                                const uint8_t (&array_)[SIZE],
                                int flags_)
{
    const int rc = zmq_send (socket_, array_, SIZE, flags_);
    TEST_ASSERT_EQUAL_INT (static_cast<int> (SIZE), rc);
}

167 168 169 170 171 172 173
// Receives a message via a libzmq socket, and expects the operation to be
// successful, and the message to be a given byte array. Otherwise, a Unity
// test assertion is triggered.
// 'socket_' must be the libzmq socket to use for receiving.
// 'array_' must be a C uint8_t array. The array size is automatically
// determined via template argument deduction.
// 'flags_' are as documented by the zmq_recv function.
174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190
template <size_t SIZE>
void recv_array_expect_success (void *socket_,
                                const uint8_t (&array_)[SIZE],
                                int flags_)
{
    char buffer[255];
    TEST_ASSERT_LESS_OR_EQUAL_MESSAGE (sizeof (buffer), SIZE,
                                       "recv_string_expect_success cannot be "
                                       "used for strings longer than 255 "
                                       "characters");

    const int rc = TEST_ASSERT_SUCCESS_ERRNO (
      zmq_recv (socket_, buffer, sizeof (buffer), flags_));
    TEST_ASSERT_EQUAL_INT (static_cast<int> (SIZE), rc);
    TEST_ASSERT_EQUAL_UINT8_ARRAY (array_, buffer, SIZE);
}

191 192 193 194 195 196
/////////////////////////////////////////////////////////////////////////////
// Utility function for handling a test libzmq context, that is set up and
// torn down for each Unity test case, such that a clean context is available
// for each test case, and some consistency checks can be performed.
/////////////////////////////////////////////////////////////////////////////

197 198 199 200 201 202
// Use this is an test executable to perform a default setup and teardown of
// the test context, which is appropriate for many libzmq test cases.
#define SETUP_TEARDOWN_TESTCONTEXT                                             \
    void setUp () { setup_test_context (); }                                   \
    void tearDown () { teardown_test_context (); }

203
// The maximum number of sockets that can be managed by the test context.
204 205
#define MAX_TEST_SOCKETS 128

206
// Expected to be called during Unity's setUp function.
207
void setup_test_context ();
208

209 210
// Returns the test context, e.g. to create sockets in another thread using
// zmq_socket, or set context options.
211
void *get_test_context ();
212

213 214 215
// Expected to be called during Unity's tearDown function. Checks that all
// sockets created via test_context_socket have been properly closed using
// test_context_socket_close or test_context_socket_close_zero_linger, and generates a warning otherwise.
216
void teardown_test_context ();
217

218 219 220 221 222 223
// Creates a libzmq socket on the test context, and tracks its lifecycle.
// You MUST use test_context_socket_close or test_context_socket_close_zero_linger
// to close a socket created via this function, otherwise undefined behaviour
// will result.
// CAUTION: this function is not thread-safe, and may only be used from the
// main thread.
224
void *test_context_socket (int type_);
225

226 227 228
// Closes a socket created via test_context_socket.
// CAUTION: this function is not thread-safe, and may only be used from the
// main thread.
229
void *test_context_socket_close (void *socket_);
230

231 232 233 234
// Closes a socket created via test_context_socket after setting its linger
// timeout to 0.
// CAUTION: this function is not thread-safe, and may only be used from the
// main thread.
235
void *test_context_socket_close_zero_linger (void *socket_);
236

237 238 239 240 241 242 243 244 245 246 247 248
/////////////////////////////////////////////////////////////////////////////
// Utility function for handling wildcard binds.
/////////////////////////////////////////////////////////////////////////////

// All function binds a socket to some wildcard address, and retrieve the bound
// endpoint via the ZMQ_LAST_ENDPOINT socket option to a given buffer.
// Triggers a Unity test assertion in case of a failure (including the buffer
// being too small for the resulting endpoint string).

// Binds to an explicitly given (wildcard) address.
// TODO redesign such that this function is not necessary to be exposed, but
// the protocol to use is rather specified via an enum value
249 250 251
void test_bind (void *socket_,
                const char *bind_address_,
                char *my_endpoint_,
252
                size_t len_);
253

254
// Binds to a tcp endpoint using the ipv4 or ipv6 loopback wildcard address.
255
void bind_loopback (void *socket_, int ipv6_, char *my_endpoint_, size_t len_);
256

257 258 259 260
typedef void (*bind_function_t) (void *socket_,
                                 char *my_endpoint_,
                                 size_t len_);

261
// Binds to a tcp endpoint using the ipv4 loopback wildcard address.
262
void bind_loopback_ipv4 (void *socket_, char *my_endpoint_, size_t len_);
263

264
// Binds to a tcp endpoint using the ipv6 loopback wildcard address.
265
void bind_loopback_ipv6 (void *socket_, char *my_endpoint_, size_t len_);
266

267 268 269
// Binds to an ipc endpoint using the ipc wildcard address.
// Note that the returned address cannot be reused to bind a second socket.
// If you need to do this, use make_random_ipc_endpoint instead.
270
void bind_loopback_ipc (void *socket_, char *my_endpoint_, size_t len_);
271

272
// Binds to an ipc endpoint using the tipc wildcard address.
273
void bind_loopback_tipc (void *socket_, char *my_endpoint_, size_t len_);
274

275
#if defined(ZMQ_HAVE_IPC) && !defined(ZMQ_HAVE_GNU)
276 277
// utility function to create a random IPC endpoint, similar to what a ipc://*
// wildcard binding does, but in a way it can be reused for multiple binds
278
// TODO also add a len parameter here
279
void make_random_ipc_endpoint (char *out_endpoint_);
280
#endif