test_xpub_manual.cpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539
  1. /*
  2. Copyright (c) 2007-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 "testutil.hpp"
  25. #include "testutil_unity.hpp"
  26. SETUP_TEARDOWN_TESTCONTEXT
  27. void test_basic ()
  28. {
  29. // Create a publisher
  30. void *pub = test_context_socket (ZMQ_XPUB);
  31. int manual = 1;
  32. TEST_ASSERT_SUCCESS_ERRNO (
  33. zmq_setsockopt (pub, ZMQ_XPUB_MANUAL, &manual, 4));
  34. TEST_ASSERT_SUCCESS_ERRNO (zmq_bind (pub, "inproc://soname"));
  35. // Create a subscriber
  36. void *sub = test_context_socket (ZMQ_XSUB);
  37. TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (sub, "inproc://soname"));
  38. // Subscribe for A
  39. const char subscription[] = {1, 'A', 0};
  40. send_string_expect_success (sub, subscription, 0);
  41. // Receive subscriptions from subscriber
  42. recv_string_expect_success (pub, subscription, 0);
  43. // Subscribe socket for B instead
  44. TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (pub, ZMQ_SUBSCRIBE, "B", 1));
  45. // Sending A message and B Message
  46. send_string_expect_success (pub, "A", 0);
  47. send_string_expect_success (pub, "B", 0);
  48. recv_string_expect_success (sub, "B", ZMQ_DONTWAIT);
  49. // Clean up.
  50. test_context_socket_close (pub);
  51. test_context_socket_close (sub);
  52. }
  53. void test_unsubscribe_manual ()
  54. {
  55. // Create a publisher
  56. void *pub = test_context_socket (ZMQ_XPUB);
  57. TEST_ASSERT_SUCCESS_ERRNO (zmq_bind (pub, "inproc://soname"));
  58. // set pub socket options
  59. int manual = 1;
  60. TEST_ASSERT_SUCCESS_ERRNO (
  61. zmq_setsockopt (pub, ZMQ_XPUB_MANUAL, &manual, sizeof (manual)));
  62. // Create a subscriber
  63. void *sub = test_context_socket (ZMQ_XSUB);
  64. TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (sub, "inproc://soname"));
  65. // Subscribe for A
  66. const uint8_t subscription1[] = {1, 'A'};
  67. send_array_expect_success (sub, subscription1, 0);
  68. // Subscribe for B
  69. const uint8_t subscription2[] = {1, 'B'};
  70. send_array_expect_success (sub, subscription2, 0);
  71. char buffer[3];
  72. // Receive subscription "A" from subscriber
  73. recv_array_expect_success (pub, subscription1, 0);
  74. // Subscribe socket for XA instead
  75. TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (pub, ZMQ_SUBSCRIBE, "XA", 2));
  76. // Receive subscription "B" from subscriber
  77. recv_array_expect_success (pub, subscription2, 0);
  78. // Subscribe socket for XB instead
  79. TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (pub, ZMQ_SUBSCRIBE, "XB", 2));
  80. // Unsubscribe from A
  81. const uint8_t unsubscription1[2] = {0, 'A'};
  82. send_array_expect_success (sub, unsubscription1, 0);
  83. // Receive unsubscription "A" from subscriber
  84. recv_array_expect_success (pub, unsubscription1, 0);
  85. // Unsubscribe socket from XA instead
  86. TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (pub, ZMQ_UNSUBSCRIBE, "XA", 2));
  87. // Sending messages XA, XB
  88. send_string_expect_success (pub, "XA", 0);
  89. send_string_expect_success (pub, "XB", 0);
  90. // Subscriber should receive XB only
  91. recv_string_expect_success (sub, "XB", ZMQ_DONTWAIT);
  92. // Close subscriber
  93. test_context_socket_close (sub);
  94. // Receive unsubscription "B"
  95. const char unsubscription2[2] = {0, 'B'};
  96. TEST_ASSERT_EQUAL_INT (
  97. sizeof unsubscription2,
  98. TEST_ASSERT_SUCCESS_ERRNO (zmq_recv (pub, buffer, sizeof buffer, 0)));
  99. TEST_ASSERT_EQUAL_INT8_ARRAY (unsubscription2, buffer,
  100. sizeof unsubscription2);
  101. // Unsubscribe socket from XB instead
  102. TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (pub, ZMQ_UNSUBSCRIBE, "XB", 2));
  103. // Clean up.
  104. test_context_socket_close (pub);
  105. }
  106. void test_xpub_proxy_unsubscribe_on_disconnect ()
  107. {
  108. const uint8_t topic_buff[] = {"1"};
  109. const uint8_t payload_buff[] = {"X"};
  110. char my_endpoint_backend[MAX_SOCKET_STRING];
  111. char my_endpoint_frontend[MAX_SOCKET_STRING];
  112. int manual = 1;
  113. // proxy frontend
  114. void *xsub_proxy = test_context_socket (ZMQ_XSUB);
  115. bind_loopback_ipv4 (xsub_proxy, my_endpoint_frontend,
  116. sizeof my_endpoint_frontend);
  117. // proxy backend
  118. void *xpub_proxy = test_context_socket (ZMQ_XPUB);
  119. TEST_ASSERT_SUCCESS_ERRNO (
  120. zmq_setsockopt (xpub_proxy, ZMQ_XPUB_MANUAL, &manual, 4));
  121. bind_loopback_ipv4 (xpub_proxy, my_endpoint_backend,
  122. sizeof my_endpoint_backend);
  123. // publisher
  124. void *pub = test_context_socket (ZMQ_PUB);
  125. TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (pub, my_endpoint_frontend));
  126. // first subscriber subscribes
  127. void *sub1 = test_context_socket (ZMQ_SUB);
  128. TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (sub1, my_endpoint_backend));
  129. TEST_ASSERT_SUCCESS_ERRNO (
  130. zmq_setsockopt (sub1, ZMQ_SUBSCRIBE, topic_buff, 1));
  131. // wait
  132. msleep (SETTLE_TIME);
  133. // proxy reroutes and confirms subscriptions
  134. const uint8_t subscription[2] = {1, *topic_buff};
  135. recv_array_expect_success (xpub_proxy, subscription, ZMQ_DONTWAIT);
  136. TEST_ASSERT_SUCCESS_ERRNO (
  137. zmq_setsockopt (xpub_proxy, ZMQ_SUBSCRIBE, topic_buff, 1));
  138. send_array_expect_success (xsub_proxy, subscription, 0);
  139. // second subscriber subscribes
  140. void *sub2 = test_context_socket (ZMQ_SUB);
  141. TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (sub2, my_endpoint_backend));
  142. TEST_ASSERT_SUCCESS_ERRNO (
  143. zmq_setsockopt (sub2, ZMQ_SUBSCRIBE, topic_buff, 1));
  144. // wait
  145. msleep (SETTLE_TIME);
  146. // proxy reroutes
  147. recv_array_expect_success (xpub_proxy, subscription, ZMQ_DONTWAIT);
  148. TEST_ASSERT_SUCCESS_ERRNO (
  149. zmq_setsockopt (xpub_proxy, ZMQ_SUBSCRIBE, topic_buff, 1));
  150. send_array_expect_success (xsub_proxy, subscription, 0);
  151. // wait
  152. msleep (SETTLE_TIME);
  153. // let publisher send a msg
  154. send_array_expect_success (pub, topic_buff, ZMQ_SNDMORE);
  155. send_array_expect_success (pub, payload_buff, 0);
  156. // wait
  157. msleep (SETTLE_TIME);
  158. // proxy reroutes data messages to subscribers
  159. recv_array_expect_success (xsub_proxy, topic_buff, ZMQ_DONTWAIT);
  160. recv_array_expect_success (xsub_proxy, payload_buff, ZMQ_DONTWAIT);
  161. send_array_expect_success (xpub_proxy, topic_buff, ZMQ_SNDMORE);
  162. send_array_expect_success (xpub_proxy, payload_buff, 0);
  163. // wait
  164. msleep (SETTLE_TIME);
  165. // each subscriber should now get a message
  166. recv_array_expect_success (sub2, topic_buff, ZMQ_DONTWAIT);
  167. recv_array_expect_success (sub2, payload_buff, ZMQ_DONTWAIT);
  168. recv_array_expect_success (sub1, topic_buff, ZMQ_DONTWAIT);
  169. recv_array_expect_success (sub1, payload_buff, ZMQ_DONTWAIT);
  170. // Disconnect both subscribers
  171. test_context_socket_close (sub1);
  172. test_context_socket_close (sub2);
  173. // wait
  174. msleep (SETTLE_TIME);
  175. // unsubscribe messages are passed from proxy to publisher
  176. const uint8_t unsubscription[] = {0, *topic_buff};
  177. recv_array_expect_success (xpub_proxy, unsubscription, 0);
  178. TEST_ASSERT_SUCCESS_ERRNO (
  179. zmq_setsockopt (xpub_proxy, ZMQ_UNSUBSCRIBE, topic_buff, 1));
  180. send_array_expect_success (xsub_proxy, unsubscription, 0);
  181. // should receive another unsubscribe msg
  182. recv_array_expect_success (xpub_proxy, unsubscription, 0);
  183. TEST_ASSERT_SUCCESS_ERRNO (
  184. zmq_setsockopt (xpub_proxy, ZMQ_UNSUBSCRIBE, topic_buff, 1));
  185. send_array_expect_success (xsub_proxy, unsubscription, 0);
  186. // wait
  187. msleep (SETTLE_TIME);
  188. // let publisher send a msg
  189. send_array_expect_success (pub, topic_buff, ZMQ_SNDMORE);
  190. send_array_expect_success (pub, payload_buff, 0);
  191. // wait
  192. msleep (SETTLE_TIME);
  193. // nothing should come to the proxy
  194. char buffer[1];
  195. TEST_ASSERT_FAILURE_ERRNO (
  196. EAGAIN, zmq_recv (xsub_proxy, buffer, sizeof buffer, ZMQ_DONTWAIT));
  197. test_context_socket_close (pub);
  198. test_context_socket_close (xpub_proxy);
  199. test_context_socket_close (xsub_proxy);
  200. }
  201. void test_missing_subscriptions ()
  202. {
  203. const char *topic1 = "1";
  204. const char *topic2 = "2";
  205. const char *payload = "X";
  206. char my_endpoint_backend[MAX_SOCKET_STRING];
  207. char my_endpoint_frontend[MAX_SOCKET_STRING];
  208. int manual = 1;
  209. // proxy frontend
  210. void *xsub_proxy = test_context_socket (ZMQ_XSUB);
  211. bind_loopback_ipv4 (xsub_proxy, my_endpoint_frontend,
  212. sizeof my_endpoint_frontend);
  213. // proxy backend
  214. void *xpub_proxy = test_context_socket (ZMQ_XPUB);
  215. TEST_ASSERT_SUCCESS_ERRNO (
  216. zmq_setsockopt (xpub_proxy, ZMQ_XPUB_MANUAL, &manual, 4));
  217. bind_loopback_ipv4 (xpub_proxy, my_endpoint_backend,
  218. sizeof my_endpoint_backend);
  219. // publisher
  220. void *pub = test_context_socket (ZMQ_PUB);
  221. TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (pub, my_endpoint_frontend));
  222. // Here's the problem: because subscribers subscribe in quick succession,
  223. // the proxy is unable to confirm the first subscription before receiving
  224. // the second. This causes the first subscription to get lost.
  225. // first subscriber
  226. void *sub1 = test_context_socket (ZMQ_SUB);
  227. TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (sub1, my_endpoint_backend));
  228. TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (sub1, ZMQ_SUBSCRIBE, topic1, 1));
  229. // wait
  230. msleep (SETTLE_TIME);
  231. // proxy now reroutes and confirms subscriptions
  232. const uint8_t subscription1[] = {1, static_cast<uint8_t> (topic1[0])};
  233. recv_array_expect_success (xpub_proxy, subscription1, ZMQ_DONTWAIT);
  234. TEST_ASSERT_SUCCESS_ERRNO (
  235. zmq_setsockopt (xpub_proxy, ZMQ_SUBSCRIBE, topic1, 1));
  236. send_array_expect_success (xsub_proxy, subscription1, 0);
  237. // second subscriber
  238. void *sub2 = test_context_socket (ZMQ_SUB);
  239. TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (sub2, my_endpoint_backend));
  240. TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (sub2, ZMQ_SUBSCRIBE, topic2, 1));
  241. // wait
  242. msleep (SETTLE_TIME);
  243. const uint8_t subscription2[] = {1, static_cast<uint8_t> (topic2[0])};
  244. recv_array_expect_success (xpub_proxy, subscription2, ZMQ_DONTWAIT);
  245. TEST_ASSERT_SUCCESS_ERRNO (
  246. zmq_setsockopt (xpub_proxy, ZMQ_SUBSCRIBE, topic2, 1));
  247. send_array_expect_success (xsub_proxy, subscription2, 0);
  248. // wait
  249. msleep (SETTLE_TIME);
  250. // let publisher send 2 msgs, each with its own topic_buff
  251. send_string_expect_success (pub, topic1, ZMQ_SNDMORE);
  252. send_string_expect_success (pub, payload, 0);
  253. send_string_expect_success (pub, topic2, ZMQ_SNDMORE);
  254. send_string_expect_success (pub, payload, 0);
  255. // wait
  256. msleep (SETTLE_TIME);
  257. // proxy reroutes data messages to subscribers
  258. recv_string_expect_success (xsub_proxy, topic1, ZMQ_DONTWAIT);
  259. recv_string_expect_success (xsub_proxy, payload, ZMQ_DONTWAIT);
  260. send_string_expect_success (xpub_proxy, topic1, ZMQ_SNDMORE);
  261. send_string_expect_success (xpub_proxy, payload, 0);
  262. recv_string_expect_success (xsub_proxy, topic2, ZMQ_DONTWAIT);
  263. recv_string_expect_success (xsub_proxy, payload, ZMQ_DONTWAIT);
  264. send_string_expect_success (xpub_proxy, topic2, ZMQ_SNDMORE);
  265. send_string_expect_success (xpub_proxy, payload, 0);
  266. // wait
  267. msleep (SETTLE_TIME);
  268. // each subscriber should now get a message
  269. recv_string_expect_success (sub2, topic2, ZMQ_DONTWAIT);
  270. recv_string_expect_success (sub2, payload, ZMQ_DONTWAIT);
  271. recv_string_expect_success (sub1, topic1, ZMQ_DONTWAIT);
  272. recv_string_expect_success (sub1, payload, ZMQ_DONTWAIT);
  273. // Clean up
  274. test_context_socket_close (sub1);
  275. test_context_socket_close (sub2);
  276. test_context_socket_close (pub);
  277. test_context_socket_close (xpub_proxy);
  278. test_context_socket_close (xsub_proxy);
  279. }
  280. void test_unsubscribe_cleanup ()
  281. {
  282. char my_endpoint[MAX_SOCKET_STRING];
  283. // Create a publisher
  284. void *pub = test_context_socket (ZMQ_XPUB);
  285. int manual = 1;
  286. TEST_ASSERT_SUCCESS_ERRNO (
  287. zmq_setsockopt (pub, ZMQ_XPUB_MANUAL, &manual, 4));
  288. bind_loopback_ipv4 (pub, my_endpoint, sizeof my_endpoint);
  289. // Create a subscriber
  290. void *sub = test_context_socket (ZMQ_XSUB);
  291. TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (sub, my_endpoint));
  292. // Subscribe for A
  293. const uint8_t subscription1[2] = {1, 'A'};
  294. send_array_expect_success (sub, subscription1, 0);
  295. // Receive subscriptions from subscriber
  296. recv_array_expect_success (pub, subscription1, 0);
  297. TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (pub, ZMQ_SUBSCRIBE, "XA", 2));
  298. // send 2 messages
  299. send_string_expect_success (pub, "XA", 0);
  300. send_string_expect_success (pub, "XB", 0);
  301. // receive the single message
  302. recv_string_expect_success (sub, "XA", 0);
  303. // should be nothing left in the queue
  304. char buffer[2];
  305. TEST_ASSERT_FAILURE_ERRNO (
  306. EAGAIN, zmq_recv (sub, buffer, sizeof buffer, ZMQ_DONTWAIT));
  307. // close the socket
  308. test_context_socket_close (sub);
  309. // closing the socket will result in an unsubscribe event
  310. const uint8_t unsubscription[2] = {0, 'A'};
  311. recv_array_expect_success (pub, unsubscription, 0);
  312. // this doesn't really do anything
  313. // there is no last_pipe set it will just fail silently
  314. TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (pub, ZMQ_UNSUBSCRIBE, "XA", 2));
  315. // reconnect
  316. sub = test_context_socket (ZMQ_XSUB);
  317. TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (sub, my_endpoint));
  318. // send a subscription for B
  319. const uint8_t subscription2[2] = {1, 'B'};
  320. send_array_expect_success (sub, subscription2, 0);
  321. // receive the subscription, overwrite it to XB
  322. recv_array_expect_success (pub, subscription2, 0);
  323. TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (pub, ZMQ_SUBSCRIBE, "XB", 2));
  324. // send 2 messages
  325. send_string_expect_success (pub, "XA", 0);
  326. send_string_expect_success (pub, "XB", 0);
  327. // receive the single message
  328. recv_string_expect_success (sub, "XB", 0);
  329. // should be nothing left in the queue
  330. TEST_ASSERT_FAILURE_ERRNO (
  331. EAGAIN, zmq_recv (sub, buffer, sizeof buffer, ZMQ_DONTWAIT));
  332. // Clean up.
  333. test_context_socket_close (pub);
  334. test_context_socket_close (sub);
  335. }
  336. void test_user_message ()
  337. {
  338. // Create a publisher
  339. void *pub = test_context_socket (ZMQ_XPUB);
  340. TEST_ASSERT_SUCCESS_ERRNO (zmq_bind (pub, "inproc://soname"));
  341. // Create a subscriber
  342. void *sub = test_context_socket (ZMQ_XSUB);
  343. TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (sub, "inproc://soname"));
  344. // Send some data that is neither sub nor unsub
  345. const char subscription[] = {2, 'A', 0};
  346. send_string_expect_success (sub, subscription, 0);
  347. // Receive subscriptions from subscriber
  348. recv_string_expect_success (pub, subscription, 0);
  349. // Clean up.
  350. test_context_socket_close (pub);
  351. test_context_socket_close (sub);
  352. }
  353. #ifdef ZMQ_ONLY_FIRST_SUBSCRIBE
  354. void test_user_message_multi ()
  355. {
  356. const int only_first_subscribe = 1;
  357. // Create a publisher
  358. void *pub = test_context_socket (ZMQ_XPUB);
  359. TEST_ASSERT_SUCCESS_ERRNO (zmq_bind (pub, "inproc://soname"));
  360. TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (pub, ZMQ_ONLY_FIRST_SUBSCRIBE,
  361. &only_first_subscribe,
  362. sizeof (only_first_subscribe)));
  363. // Create a subscriber
  364. void *sub = test_context_socket (ZMQ_XSUB);
  365. TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (sub, "inproc://soname"));
  366. TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (sub, ZMQ_ONLY_FIRST_SUBSCRIBE,
  367. &only_first_subscribe,
  368. sizeof (only_first_subscribe)));
  369. // Send some data that is neither sub nor unsub
  370. const uint8_t msg_common[] = {'A', 'B', 'C'};
  371. // Message starts with 0 but should still treated as user
  372. const uint8_t msg_0a[] = {0, 'B', 'C'};
  373. const uint8_t msg_0b[] = {0, 'C', 'D'};
  374. // Message starts with 1 but should still treated as user
  375. const uint8_t msg_1a[] = {1, 'B', 'C'};
  376. const uint8_t msg_1b[] = {1, 'C', 'D'};
  377. // Test second message starting with 0
  378. send_array_expect_success (sub, msg_common, ZMQ_SNDMORE);
  379. send_array_expect_success (sub, msg_0a, 0);
  380. // Receive messages from subscriber
  381. recv_array_expect_success (pub, msg_common, 0);
  382. recv_array_expect_success (pub, msg_0a, 0);
  383. // Test second message starting with 1
  384. send_array_expect_success (sub, msg_common, ZMQ_SNDMORE);
  385. send_array_expect_success (sub, msg_1a, 0);
  386. // Receive messages from subscriber
  387. recv_array_expect_success (pub, msg_common, 0);
  388. recv_array_expect_success (pub, msg_1a, 0);
  389. // Test first message starting with 1
  390. send_array_expect_success (sub, msg_1a, ZMQ_SNDMORE);
  391. send_array_expect_success (sub, msg_1b, 0);
  392. recv_array_expect_success (pub, msg_1a, 0);
  393. recv_array_expect_success (pub, msg_1b, 0);
  394. send_array_expect_success (sub, msg_0a, ZMQ_SNDMORE);
  395. send_array_expect_success (sub, msg_0b, 0);
  396. recv_array_expect_success (pub, msg_0a, 0);
  397. recv_array_expect_success (pub, msg_0b, 0);
  398. // Clean up.
  399. test_context_socket_close (pub);
  400. test_context_socket_close (sub);
  401. }
  402. #endif
  403. int main ()
  404. {
  405. setup_test_environment ();
  406. UNITY_BEGIN ();
  407. RUN_TEST (test_basic);
  408. RUN_TEST (test_unsubscribe_manual);
  409. RUN_TEST (test_xpub_proxy_unsubscribe_on_disconnect);
  410. RUN_TEST (test_missing_subscriptions);
  411. RUN_TEST (test_unsubscribe_cleanup);
  412. RUN_TEST (test_user_message);
  413. #ifdef ZMQ_ONLY_FIRST_SUBSCRIBE
  414. RUN_TEST (test_user_message_multi);
  415. #endif
  416. return UNITY_END ();
  417. }