testutil_unity.hpp 14 KB

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