1#pragma once
2
3/*
4Copyright (c) 2018 Contributors as noted in the AUTHORS file
5
6This file is part of libzmq, the ZeroMQ core engine in C++.
7
8libzmq is free software; you can redistribute it and/or modify it under
9the terms of the GNU Lesser General Public License (LGPL) as published
10by the Free Software Foundation; either version 3 of the License, or
11(at your option) any later version.
12
13As a special exception, the Contributors give you permission to link
14this library with independent modules to produce an executable,
15regardless of the license terms of these independent modules, and to
16copy and distribute the resulting executable under terms of your choice,
17provided that you also meet, for each linked independent module, the
18terms and conditions of the license of that module. An independent
19module is a module which is not derived from or based on this library.
20If you modify this library, you must extend this exception to your
21version of the library.
22
23libzmq is distributed in the hope that it will be useful, but WITHOUT
24ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
25FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
26License for more details.
27
28You should have received a copy of the GNU Lesser General Public License
29along with this program. If not, see <http://www.gnu.org/licenses/>.
30*/
31
32#include "../include/zmq.h"
33
34#include "testutil.hpp"
35
36#include <unity.h>
37
38// Internal helper functions that are not intended to be directly called from
39// tests. They must be declared in the header since they are used by macros.
40
41int test_assert_success_message_errno_helper (int rc_,
42 const char *msg_,
43 const char *expr_,
44 int line);
45
46int test_assert_success_message_raw_errno_helper (int rc_,
47 const char *msg_,
48 const char *expr_,
49 int line);
50
51int test_assert_failure_message_raw_errno_helper (
52 int rc_, int expected_errno_, const char *msg_, const char *expr_, int line);
53
54/////////////////////////////////////////////////////////////////////////////
55// Macros extending Unity's TEST_ASSERT_* macros in a similar fashion.
56/////////////////////////////////////////////////////////////////////////////
57
58// For TEST_ASSERT_SUCCESS_ERRNO, TEST_ASSERT_SUCCESS_MESSAGE_ERRNO and
59// TEST_ASSERT_FAILURE_ERRNO, 'expr' must be an expression evaluating
60// to a result in the style of a libzmq API function, i.e. an integer which
61// is non-negative in case of success, and -1 in case of a failure, and sets
62// the value returned by zmq_errno () to the error code.
63// TEST_ASSERT_SUCCESS_RAW_ERRNO and TEST_ASSERT_FAILURE_RAW_ERRNO are similar,
64// but used with the native socket API functions, and expect that the error
65// code can be retrieved in the native way (i.e. WSAGetLastError on Windows,
66// and errno otherwise).
67
68// Asserts that the libzmq API 'expr' is successful. In case of a failure, the
69// assertion message includes the literal 'expr', the error number as
70// determined by zmq_errno(), and the additional 'msg'.
71// 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// Asserts that the libzmq API 'expr' is successful. In case of a failure, the
76// assertion message includes the literal 'expr' and the error code.
77// A typical use would be:
78// TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (socket, endpoint));
79// In case of success, the result of the macro is the result of 'expr'.
80//
81// If an additional message should be displayed in case of a failure, use
82// 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// Asserts that the socket API 'expr' is successful. In case of a failure, the
87// assertion message includes the literal 'expr' and the error code.
88// A typical use would be:
89// TEST_ASSERT_SUCCESS_RAW_ERRNO (send (fd, buffer, 64, 0));
90// 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// Asserts that the socket API 'expr' is not successful, and the error code is
95// 'error_code'. In case of an unexpected succces, or a failure with an
96// unexpected error code, the assertion message includes the literal 'expr'
97// and, in case of a failure, the actual error code.
98#define TEST_ASSERT_FAILURE_RAW_ERRNO(error_code, expr) \
99 test_assert_failure_message_raw_errno_helper (expr, error_code, NULL, \
100 #expr, __LINE__)
101
102// Asserts that the libzmq API 'expr' is not successful, and the error code is
103// 'error_code'. In case of an unexpected succces, or a failure with an
104// unexpected error code, the assertion message includes the literal 'expr'
105// and, in case of a failure, the actual error code.
106#define TEST_ASSERT_FAILURE_ERRNO(error_code, expr) \
107 { \
108 int _rc = (expr); \
109 TEST_ASSERT_EQUAL_INT (-1, _rc); \
110 TEST_ASSERT_EQUAL_INT (error_code, errno); \
111 }
112
113/////////////////////////////////////////////////////////////////////////////
114// Utility functions for testing sending and receiving.
115/////////////////////////////////////////////////////////////////////////////
116
117// Sends a string via a libzmq socket, and expects the operation to be
118// successful (the meaning of which depends on the socket type and configured
119// options, and might include dropping the message). Otherwise, a Unity test
120// assertion is triggered.
121// 'socket_' must be the libzmq socket to use for sending.
122// 'str_' must be a 0-terminated string.
123// 'flags_' are as documented by the zmq_send function.
124void send_string_expect_success (void *socket_, const char *str_, int flags_);
125
126// Receives a message via a libzmq socket, and expects the operation to be
127// successful, and the message to be a given string. Otherwise, a Unity test
128// assertion is triggered.
129// 'socket_' must be the libzmq socket to use for receiving.
130// 'str_' must be a 0-terminated string.
131// 'flags_' are as documented by the zmq_recv function.
132void recv_string_expect_success (void *socket_, const char *str_, int flags_);
133
134// Sends a byte array via a libzmq socket, and expects the operation to be
135// successful (the meaning of which depends on the socket type and configured
136// options, and might include dropping the message). Otherwise, a Unity test
137// assertion is triggered.
138// 'socket_' must be the libzmq socket to use for sending.
139// 'array_' must be a C uint8_t array. The array size is automatically
140// determined via template argument deduction.
141// 'flags_' are as documented by the zmq_send function.
142template <size_t SIZE>
143void send_array_expect_success (void *socket_,
144 const uint8_t (&array_)[SIZE],
145 int flags_)
146{
147 const int rc = zmq_send (socket_, array_, SIZE, flags_);
148 TEST_ASSERT_EQUAL_INT (static_cast<int> (SIZE), rc);
149}
150
151// Receives a message via a libzmq socket, and expects the operation to be
152// successful, and the message to be a given byte array. Otherwise, a Unity
153// test assertion is triggered.
154// 'socket_' must be the libzmq socket to use for receiving.
155// 'array_' must be a C uint8_t array. The array size is automatically
156// determined via template argument deduction.
157// 'flags_' are as documented by the zmq_recv function.
158template <size_t SIZE>
159void recv_array_expect_success (void *socket_,
160 const uint8_t (&array_)[SIZE],
161 int flags_)
162{
163 char buffer[255];
164 TEST_ASSERT_LESS_OR_EQUAL_MESSAGE (sizeof (buffer), SIZE,
165 "recv_string_expect_success cannot be "
166 "used for strings longer than 255 "
167 "characters");
168
169 const int rc = TEST_ASSERT_SUCCESS_ERRNO (
170 zmq_recv (socket_, buffer, sizeof (buffer), flags_));
171 TEST_ASSERT_EQUAL_INT (static_cast<int> (SIZE), rc);
172 TEST_ASSERT_EQUAL_UINT8_ARRAY (array_, buffer, SIZE);
173}
174
175/////////////////////////////////////////////////////////////////////////////
176// Utility function for handling a test libzmq context, that is set up and
177// torn down for each Unity test case, such that a clean context is available
178// for each test case, and some consistency checks can be performed.
179/////////////////////////////////////////////////////////////////////////////
180
181// Use this is an test executable to perform a default setup and teardown of
182// the test context, which is appropriate for many libzmq test cases.
183#define SETUP_TEARDOWN_TESTCONTEXT \
184 void setUp () { setup_test_context (); } \
185 void tearDown () { teardown_test_context (); }
186
187// The maximum number of sockets that can be managed by the test context.
188#define MAX_TEST_SOCKETS 128
189
190// Expected to be called during Unity's setUp function.
191void setup_test_context ();
192
193// Returns the test context, e.g. to create sockets in another thread using
194// zmq_socket, or set context options.
195void *get_test_context ();
196
197// Expected to be called during Unity's tearDown function. Checks that all
198// sockets created via test_context_socket have been properly closed using
199// test_context_socket_close or test_context_socket_close_zero_linger, and generates a warning otherwise.
200void teardown_test_context ();
201
202// Creates a libzmq socket on the test context, and tracks its lifecycle.
203// You MUST use test_context_socket_close or test_context_socket_close_zero_linger
204// to close a socket created via this function, otherwise undefined behaviour
205// will result.
206// CAUTION: this function is not thread-safe, and may only be used from the
207// main thread.
208void *test_context_socket (int type_);
209
210// Closes a socket created via test_context_socket.
211// CAUTION: this function is not thread-safe, and may only be used from the
212// main thread.
213void *test_context_socket_close (void *socket_);
214
215// Closes a socket created via test_context_socket after setting its linger
216// timeout to 0.
217// CAUTION: this function is not thread-safe, and may only be used from the
218// main thread.
219void *test_context_socket_close_zero_linger (void *socket_);
220
221/////////////////////////////////////////////////////////////////////////////
222// Utility function for handling wildcard binds.
223/////////////////////////////////////////////////////////////////////////////
224
225// All function binds a socket to some wildcard address, and retrieve the bound
226// endpoint via the ZMQ_LAST_ENDPOINT socket option to a given buffer.
227// Triggers a Unity test assertion in case of a failure (including the buffer
228// being too small for the resulting endpoint string).
229
230// Binds to an explicitly given (wildcard) address.
231// TODO redesign such that this function is not necessary to be exposed, but
232// the protocol to use is rather specified via an enum value
233void test_bind (void *socket_,
234 const char *bind_address_,
235 char *my_endpoint_,
236 size_t len_);
237
238// Binds to a tcp endpoint using the ipv4 or ipv6 loopback wildcard address.
239void bind_loopback (void *socket_, int ipv6_, char *my_endpoint_, size_t len_);
240
241typedef void (*bind_function_t) (void *socket_,
242 char *my_endpoint_,
243 size_t len_);
244
245// Binds to a tcp endpoint using the ipv4 loopback wildcard address.
246void bind_loopback_ipv4 (void *socket_, char *my_endpoint_, size_t len_);
247
248// Binds to a tcp endpoint using the ipv6 loopback wildcard address.
249void bind_loopback_ipv6 (void *socket_, char *my_endpoint_, size_t len_);
250
251// Binds to an ipc endpoint using the ipc wildcard address.
252// Note that the returned address cannot be reused to bind a second socket.
253// If you need to do this, use make_random_ipc_endpoint instead.
254void bind_loopback_ipc (void *socket_, char *my_endpoint_, size_t len_);
255
256// Binds to an ipc endpoint using the tipc wildcard address.
257void bind_loopback_tipc (void *socket_, char *my_endpoint_, size_t len_);
258
259#if defined(ZMQ_HAVE_IPC) && !defined(ZMQ_HAVE_GNU)
260// utility function to create a random IPC endpoint, similar to what a ipc://*
261// wildcard binding does, but in a way it can be reused for multiple binds
262// TODO also add a len parameter here
263void make_random_ipc_endpoint (char *out_endpoint_);
264#endif
265