test_reconnect_options.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297
  1. /*
  2. Copyright (c) 2017 Contributors as noted in the AUTHORS file
  3. This file is part of libzmq, the ZeroMQ core engine in C++.
  4. libzmq is free software; you can redistribute it and/or modify it under
  5. the terms of the GNU Lesser General Public License (LGPL) as published
  6. by the Free Software Foundation; either version 3 of the License, or
  7. (at your option) any later version.
  8. As a special exception, the Contributors give you permission to link
  9. this library with independent modules to produce an executable,
  10. regardless of the license terms of these independent modules, and to
  11. copy and distribute the resulting executable under terms of your choice,
  12. provided that you also meet, for each linked independent module, the
  13. terms and conditions of the license of that module. An independent
  14. module is a module which is not derived from or based on this library.
  15. If you modify this library, you must extend this exception to your
  16. version of the library.
  17. libzmq is distributed in the hope that it will be useful, but WITHOUT
  18. ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  19. FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
  20. License for more details.
  21. You should have received a copy of the GNU Lesser General Public License
  22. along with this program. If not, see <http://www.gnu.org/licenses/>.
  23. */
  24. #include <assert.h>
  25. #include "testutil.hpp"
  26. #include "testutil_unity.hpp"
  27. #include "testutil_monitoring.hpp"
  28. #include <unity.h>
  29. // test behavior with (mostly) default values
  30. void reconnect_default ()
  31. {
  32. // setup pub socket
  33. void *pub = test_context_socket (ZMQ_PUB);
  34. // Bind pub socket
  35. TEST_ASSERT_SUCCESS_ERRNO (zmq_bind (pub, ENDPOINT_0));
  36. // setup sub socket
  37. void *sub = test_context_socket (ZMQ_SUB);
  38. // Monitor all events on sub
  39. TEST_ASSERT_SUCCESS_ERRNO (
  40. zmq_socket_monitor (sub, "inproc://monitor-sub", ZMQ_EVENT_ALL));
  41. // Create socket for collecting monitor events
  42. void *sub_mon = test_context_socket (ZMQ_PAIR);
  43. // Connect so they'll get events
  44. TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (sub_mon, "inproc://monitor-sub"));
  45. // set reconnect interval so only a single reconnect is tried
  46. int interval = 60 * 1000;
  47. TEST_ASSERT_SUCCESS_ERRNO (
  48. zmq_setsockopt (sub, ZMQ_RECONNECT_IVL, &interval, sizeof (interval)));
  49. // connect to pub
  50. TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (sub, ENDPOINT_0));
  51. // confirm that we get following events
  52. expect_monitor_event (sub_mon, ZMQ_EVENT_CONNECT_DELAYED);
  53. expect_monitor_event (sub_mon, ZMQ_EVENT_CONNECTED);
  54. expect_monitor_event (sub_mon, ZMQ_EVENT_HANDSHAKE_SUCCEEDED);
  55. // close the pub socket
  56. test_context_socket_close_zero_linger (pub);
  57. // confirm that we get following events
  58. expect_monitor_event (sub_mon, ZMQ_EVENT_DISCONNECTED);
  59. expect_monitor_event (sub_mon, ZMQ_EVENT_CONNECT_RETRIED);
  60. // ZMQ_EVENT_CONNECT_RETRIED should be last event, because of timeout set above
  61. int event;
  62. char *event_address;
  63. int rc = get_monitor_event_with_timeout (sub_mon, &event, &event_address,
  64. 2 * 1000);
  65. assert (rc == -1);
  66. // Close sub
  67. // TODO why does this use zero_linger?
  68. test_context_socket_close_zero_linger (sub);
  69. // Close monitor
  70. // TODO why does this use zero_linger?
  71. test_context_socket_close_zero_linger (sub_mon);
  72. }
  73. // test successful reconnect
  74. void reconnect_success ()
  75. {
  76. // setup pub socket
  77. void *pub = test_context_socket (ZMQ_PUB);
  78. // Bind pub socket
  79. TEST_ASSERT_SUCCESS_ERRNO (zmq_bind (pub, ENDPOINT_0));
  80. // setup sub socket
  81. void *sub = test_context_socket (ZMQ_SUB);
  82. // Monitor all events on sub
  83. TEST_ASSERT_SUCCESS_ERRNO (
  84. zmq_socket_monitor (sub, "inproc://monitor-sub", ZMQ_EVENT_ALL));
  85. // Create socket for collecting monitor events
  86. void *sub_mon = test_context_socket (ZMQ_PAIR);
  87. // Connect so they'll get events
  88. TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (sub_mon, "inproc://monitor-sub"));
  89. // set reconnect interval so only a single reconnect is tried
  90. int interval = 1 * 1000;
  91. TEST_ASSERT_SUCCESS_ERRNO (
  92. zmq_setsockopt (sub, ZMQ_RECONNECT_IVL, &interval, sizeof (interval)));
  93. // connect to pub
  94. TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (sub, ENDPOINT_0));
  95. // confirm that we get following events
  96. expect_monitor_event (sub_mon, ZMQ_EVENT_CONNECT_DELAYED);
  97. expect_monitor_event (sub_mon, ZMQ_EVENT_CONNECTED);
  98. expect_monitor_event (sub_mon, ZMQ_EVENT_HANDSHAKE_SUCCEEDED);
  99. // close the pub socket
  100. test_context_socket_close_zero_linger (pub);
  101. // confirm that we get following events
  102. expect_monitor_event (sub_mon, ZMQ_EVENT_DISCONNECTED);
  103. expect_monitor_event (sub_mon, ZMQ_EVENT_CONNECT_RETRIED);
  104. // ZMQ_EVENT_CONNECT_RETRIED should be last event, because of timeout set above
  105. int event;
  106. char *event_address;
  107. int rc = get_monitor_event_with_timeout (sub_mon, &event, &event_address,
  108. SETTLE_TIME);
  109. assert (rc == -1);
  110. // Now re-bind pub socket and wait for re-connect
  111. pub = test_context_socket (ZMQ_PUB);
  112. TEST_ASSERT_SUCCESS_ERRNO (zmq_bind (pub, ENDPOINT_0));
  113. msleep (SETTLE_TIME);
  114. // confirm that we get following events
  115. expect_monitor_event (sub_mon, ZMQ_EVENT_CONNECT_DELAYED);
  116. expect_monitor_event (sub_mon, ZMQ_EVENT_CONNECTED);
  117. expect_monitor_event (sub_mon, ZMQ_EVENT_HANDSHAKE_SUCCEEDED);
  118. // ZMQ_EVENT_HANDSHAKE_SUCCEEDED should be last event
  119. rc = get_monitor_event_with_timeout (sub_mon, &event, &event_address,
  120. SETTLE_TIME);
  121. assert (rc == -1);
  122. // Close sub
  123. // TODO why does this use zero_linger?
  124. test_context_socket_close_zero_linger (sub);
  125. test_context_socket_close_zero_linger (pub);
  126. // Close monitor
  127. // TODO why does this use zero_linger?
  128. test_context_socket_close_zero_linger (sub_mon);
  129. }
  130. #ifdef ZMQ_BUILD_DRAFT_API
  131. // test stopping reconnect on connection refused
  132. void reconnect_stop_on_refused ()
  133. {
  134. // setup pub socket
  135. void *pub = test_context_socket (ZMQ_PUB);
  136. // Bind pub socket
  137. TEST_ASSERT_SUCCESS_ERRNO (zmq_bind (pub, ENDPOINT_0));
  138. // setup sub socket
  139. void *sub = test_context_socket (ZMQ_SUB);
  140. // Monitor all events on sub
  141. TEST_ASSERT_SUCCESS_ERRNO (
  142. zmq_socket_monitor (sub, "inproc://monitor-sub", ZMQ_EVENT_ALL));
  143. // Create socket for collecting monitor events
  144. void *sub_mon = test_context_socket (ZMQ_PAIR);
  145. // Connect so they'll get events
  146. TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (sub_mon, "inproc://monitor-sub"));
  147. // set option to stop reconnecting on error
  148. int stopReconnectOnError = ZMQ_RECONNECT_STOP_CONN_REFUSED;
  149. TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (sub, ZMQ_RECONNECT_STOP,
  150. &stopReconnectOnError,
  151. sizeof (stopReconnectOnError)));
  152. // connect to pub
  153. TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (sub, ENDPOINT_0));
  154. // confirm that we get following events
  155. expect_monitor_event (sub_mon, ZMQ_EVENT_CONNECT_DELAYED);
  156. expect_monitor_event (sub_mon, ZMQ_EVENT_CONNECTED);
  157. expect_monitor_event (sub_mon, ZMQ_EVENT_HANDSHAKE_SUCCEEDED);
  158. // close the pub socket
  159. test_context_socket_close_zero_linger (pub);
  160. // confirm that we get following events
  161. expect_monitor_event (sub_mon, ZMQ_EVENT_DISCONNECTED);
  162. expect_monitor_event (sub_mon, ZMQ_EVENT_CONNECT_RETRIED);
  163. expect_monitor_event (sub_mon, ZMQ_EVENT_CONNECT_DELAYED);
  164. expect_monitor_event (sub_mon, ZMQ_EVENT_CLOSED);
  165. // ZMQ_EVENT_CLOSED should be last event, because of ZMQ_RECONNECT_STOP set above
  166. int event = 0;
  167. char *event_address;
  168. int rc = get_monitor_event_with_timeout (sub_mon, &event, &event_address,
  169. 2 * 1000);
  170. int limit = 0;
  171. while ((rc != -1) && (++limit < 1000)) {
  172. print_unexpected_event_stderr (event, rc, 0, -1);
  173. rc = get_monitor_event_with_timeout (sub_mon, &event, &event_address,
  174. 2 * 1000);
  175. }
  176. // Close sub
  177. // TODO why does this use zero_linger?
  178. test_context_socket_close_zero_linger (sub);
  179. // Close monitor
  180. // TODO why does this use zero_linger?
  181. test_context_socket_close_zero_linger (sub_mon);
  182. }
  183. #endif
  184. #ifdef ZMQ_BUILD_DRAFT_API
  185. // test stopping reconnect on connection refused
  186. void reconnect_stop_on_handshake_failed ()
  187. {
  188. char bind_address[MAX_SOCKET_STRING];
  189. size_t addr_length = sizeof (bind_address);
  190. void *dummy = test_context_socket (ZMQ_STREAM);
  191. TEST_ASSERT_SUCCESS_ERRNO (zmq_bind (dummy, "tcp://127.0.0.1:0"));
  192. TEST_ASSERT_SUCCESS_ERRNO (
  193. zmq_getsockopt (dummy, ZMQ_LAST_ENDPOINT, bind_address, &addr_length));
  194. // setup sub socket
  195. void *sub = test_context_socket (ZMQ_SUB);
  196. // Monitor all events on sub
  197. TEST_ASSERT_SUCCESS_ERRNO (
  198. zmq_socket_monitor (sub, "inproc://monitor-sub", ZMQ_EVENT_ALL));
  199. // Create socket for collecting monitor events
  200. void *sub_mon = test_context_socket (ZMQ_PAIR);
  201. // Connect so they'll get events
  202. TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (sub_mon, "inproc://monitor-sub"));
  203. // set handshake interval (i.e., timeout) to a more reasonable value
  204. int handshakeInterval = 1000;
  205. TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (
  206. sub, ZMQ_HANDSHAKE_IVL, &handshakeInterval, sizeof (handshakeInterval)));
  207. // set option to stop reconnecting on failed handshake
  208. int stopReconnectOnError = ZMQ_RECONNECT_STOP_HANDSHAKE_FAILED;
  209. TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (sub, ZMQ_RECONNECT_STOP,
  210. &stopReconnectOnError,
  211. sizeof (stopReconnectOnError)));
  212. // connect to dummy stream socket above
  213. TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (sub, bind_address));
  214. #if 1
  215. // ZMQ_EVENT_DISCONNECTED should be last event, because of ZMQ_RECONNECT_STOP set above
  216. expect_monitor_event (sub_mon, ZMQ_EVENT_CONNECT_DELAYED);
  217. expect_monitor_event (sub_mon, ZMQ_EVENT_CONNECTED);
  218. expect_monitor_event (sub_mon, ZMQ_EVENT_HANDSHAKE_FAILED_NO_DETAIL);
  219. expect_monitor_event (sub_mon, ZMQ_EVENT_DISCONNECTED);
  220. #else
  221. print_events (sub_mon, 2 * 1000, 1000);
  222. #endif
  223. // Close sub
  224. // TODO why does this use zero_linger?
  225. test_context_socket_close_zero_linger (sub);
  226. test_context_socket_close_zero_linger (dummy);
  227. // Close monitor
  228. // TODO why does this use zero_linger?
  229. test_context_socket_close_zero_linger (sub_mon);
  230. }
  231. #endif
  232. void setUp ()
  233. {
  234. setup_test_context ();
  235. }
  236. void tearDown ()
  237. {
  238. teardown_test_context ();
  239. }
  240. int main (void)
  241. {
  242. setup_test_environment ();
  243. UNITY_BEGIN ();
  244. RUN_TEST (reconnect_default);
  245. RUN_TEST (reconnect_success);
  246. #ifdef ZMQ_BUILD_DRAFT_API
  247. RUN_TEST (reconnect_stop_on_refused);
  248. RUN_TEST (reconnect_stop_on_handshake_failed);
  249. #endif
  250. return UNITY_END ();
  251. }