testutil_unity.hpp 12.8 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
int test_assert_success_message_raw_errno_helper (int rc_,
                                                  const char *msg_,
48 49
                                                  const char *expr_,
                                                  int line);
50

51 52
int test_assert_failure_message_raw_errno_helper (
  int rc_, int expected_errno_, const char *msg_, const char *expr_, int line);
53

54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
/////////////////////////////////////////////////////////////////////////////
// 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'.
72
#define TEST_ASSERT_SUCCESS_MESSAGE_ERRNO(expr, msg)                           \
73
    test_assert_success_message_errno_helper (expr, msg, #expr, __LINE__)
74

75 76 77 78 79 80 81 82
// 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.
83
#define TEST_ASSERT_SUCCESS_ERRNO(expr)                                        \
84
    test_assert_success_message_errno_helper (expr, NULL, #expr, __LINE__)
85

86 87 88 89 90
// 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'.
91
#define TEST_ASSERT_SUCCESS_RAW_ERRNO(expr)                                    \
92
    test_assert_success_message_raw_errno_helper (expr, NULL, #expr, __LINE__)
93

94 95 96 97
// 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.
98
#define TEST_ASSERT_FAILURE_RAW_ERRNO(error_code, expr)                        \
99 100
    test_assert_failure_message_raw_errno_helper (expr, error_code, NULL,      \
                                                  #expr, __LINE__)
101

102 103 104 105
// 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.
106 107
#define TEST_ASSERT_FAILURE_ERRNO(error_code, expr)                            \
    {                                                                          \
108 109
        int _rc = (expr);                                                      \
        TEST_ASSERT_EQUAL_INT (-1, _rc);                                       \
110 111 112
        TEST_ASSERT_EQUAL_INT (error_code, errno);                             \
    }

113 114 115 116 117 118 119 120 121 122 123
/////////////////////////////////////////////////////////////////////////////
// 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.
124
void send_string_expect_success (void *socket_, const char *str_, int flags_);
125

126 127 128 129 130 131
// 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.
132
void recv_string_expect_success (void *socket_, const char *str_, int flags_);
133

134 135 136 137 138 139 140 141
// 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.
142 143 144 145 146 147 148 149 150
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);
}

151 152 153 154 155 156 157
// 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.
158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174
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);
}

175 176 177 178 179 180
/////////////////////////////////////////////////////////////////////////////
// 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.
/////////////////////////////////////////////////////////////////////////////

181 182 183 184 185 186
// 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 (); }

187
// The maximum number of sockets that can be managed by the test context.
188 189
#define MAX_TEST_SOCKETS 128

190
// Expected to be called during Unity's setUp function.
191
void setup_test_context ();
192

193 194
// Returns the test context, e.g. to create sockets in another thread using
// zmq_socket, or set context options.
195
void *get_test_context ();
196

197 198 199
// 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.
200
void teardown_test_context ();
201

202 203 204 205 206 207
// 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.
208
void *test_context_socket (int type_);
209

210 211 212
// Closes a socket created via test_context_socket.
// CAUTION: this function is not thread-safe, and may only be used from the
// main thread.
213
void *test_context_socket_close (void *socket_);
214

215 216 217 218
// 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.
219
void *test_context_socket_close_zero_linger (void *socket_);
220

221 222 223 224 225 226 227 228 229 230 231 232
/////////////////////////////////////////////////////////////////////////////
// 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
233 234 235
void test_bind (void *socket_,
                const char *bind_address_,
                char *my_endpoint_,
236
                size_t len_);
237

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

241 242 243 244
typedef void (*bind_function_t) (void *socket_,
                                 char *my_endpoint_,
                                 size_t len_);

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

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

251 252 253
// 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.
254
void bind_loopback_ipc (void *socket_, char *my_endpoint_, size_t len_);
255

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

259
#if defined(ZMQ_HAVE_IPC) && !defined(ZMQ_HAVE_GNU)
260 261
// 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
262
// TODO also add a len parameter here
263
void make_random_ipc_endpoint (char *out_endpoint_);
264
#endif