1 #include <catch2/catch_all.hpp>
7 #if (__cplusplus >= 201703L)
9 "socket_t should be nothrow swappable");
24 TEST_CASE(
"socket create assign",
"[socket]")
28 CHECK(
static_cast<bool>(socket));
29 CHECK(socket.handle() !=
nullptr);
31 CHECK(!
static_cast<bool>(socket));
32 CHECK(socket.handle() ==
nullptr);
35 TEST_CASE(
"socket create by enum and destroy",
"[socket]")
47 swap(socket1, socket2);
57 socket.set(zmq::sockopt::immediate, 0);
58 socket.set(zmq::sockopt::immediate,
false);
59 CHECK(socket.get(zmq::sockopt::immediate) ==
false);
61 CHECK_THROWS_AS(socket.set(zmq::sockopt::immediate, 80),
zmq::error_t);
64 socket.set(zmq::sockopt::linger, 55);
65 CHECK(socket.get(zmq::sockopt::linger) == 55);
69 socket.set(zmq::sockopt::routing_id,
"foobar");
70 socket.set(zmq::sockopt::routing_id,
zmq::buffer(
id));
71 socket.set(zmq::sockopt::routing_id,
id);
72 #if CPPZMQ_HAS_STRING_VIEW
73 socket.set(zmq::sockopt::routing_id, std::string_view{
id});
80 auto stropt = socket.get(zmq::sockopt::routing_id);
85 CHECK_THROWS_AS(socket.get(zmq::sockopt::routing_id,
zmq::buffer(id_ret_small)),
91 void check_array_opt(
T opt,
94 bool set_only =
false)
97 INFO(
"setting " + info);
102 INFO(
"getting " + info);
103 auto s =
sock.get(opt);
110 INFO(
"getting " + info);
114 #if ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 0, 0)
117 std::vector<uint8_t> bin_val(32);
118 const auto dret =
zmq_z85_decode(bin_val.data(), str_val.c_str());
119 CHECK(dret !=
nullptr);
121 sock.set(opt, str_val);
123 auto sv =
sock.get(opt);
124 CHECK(sv == str_val);
126 auto bv =
sock.get(opt, 32);
127 REQUIRE(bv.size() == bin_val.size());
128 CHECK(std::memcmp(bv.data(), bin_val.data(), bin_val.size()) == 0);
132 TEST_CASE(
"socket check array options",
"[socket]")
139 #ifdef ZMQ_BINDTODEVICE
143 #ifdef ZMQ_CONNECT_ROUTING_ID
144 check_array_opt(zmq::sockopt::connect_routing_id, router,
"connect_routing_id",
147 #ifdef ZMQ_LAST_ENDPOINT
148 check_array_opt_get(zmq::sockopt::last_endpoint, router,
"last_endpoint");
153 #ifdef ZMQ_PLAIN_PASSWORD
154 check_array_opt(zmq::sockopt::plain_password, router,
"plain_password");
156 #ifdef ZMQ_PLAIN_USERNAME
157 check_array_opt(zmq::sockopt::plain_username, router,
"plain_username");
159 #ifdef ZMQ_ROUTING_ID
160 check_array_opt(zmq::sockopt::routing_id, router,
"routing_id");
162 #ifdef ZMQ_SOCKS_PROXY
163 check_array_opt(zmq::sockopt::socks_proxy, router,
"socks_proxy");
166 check_array_opt(zmq::sockopt::subscribe, sub,
"subscribe",
true);
168 #ifdef ZMQ_UNSUBSCRIBE
169 check_array_opt(zmq::sockopt::unsubscribe, sub,
"unsubscribe",
true);
171 #ifdef ZMQ_XPUB_WELCOME_MSG
172 check_array_opt(zmq::sockopt::xpub_welcome_msg, xpub,
"xpub_welcome_msg",
true);
174 #ifdef ZMQ_ZAP_DOMAIN
175 check_array_opt(zmq::sockopt::zap_domain, router,
"zap_domain");
179 #if ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 0, 0) && defined(ZMQ_HAS_CAPABILITIES)
181 const std::string spk =
"rq:rM>}U?@Lns47E1%kR.o@n%FcmmsL/@{H8]yf7";
182 const std::string ssk =
"JTKVSB%%)wK0E.X)V>+}o?pNmC{O&4W4b!Ni{Lh6";
183 const std::string cpk =
"Yne@$w-vo<fVvi]a<NY6T1ed:M$fCG*[IaLV{hID";
184 const std::string csk =
"D:)Q[IlAW!ahhC2ac:9*A}h:p?([4%wOTJ%JR%cs";
186 zmq::socket_t curve_server(context, zmq::socket_type::router);
187 curve_server.set(zmq::sockopt::curve_server,
true);
188 CHECK(curve_server.get(zmq::sockopt::curve_server));
189 check_bin_z85(zmq::sockopt::curve_secretkey, curve_server, ssk);
191 zmq::socket_t curve_client(context, zmq::socket_type::router);
192 curve_client.set(zmq::sockopt::curve_server,
false);
193 CHECK_FALSE(curve_client.get(zmq::sockopt::curve_server));
194 check_bin_z85(zmq::sockopt::curve_serverkey, curve_client, spk);
195 check_bin_z85(zmq::sockopt::curve_publickey, curve_client, cpk);
196 check_bin_z85(zmq::sockopt::curve_secretkey, curve_client, csk);
201 #if ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 1, 0) && defined(ZMQ_HAS_CAPABILITIES)
202 if (
zmq_has(
"gssapi") == 1 &&
false)
205 gss_server.set(zmq::sockopt::gssapi_server,
true);
206 CHECK(gss_server.get(zmq::sockopt::gssapi_server) == 1);
207 gss_server.set(zmq::sockopt::gssapi_plaintext,
false);
208 CHECK(gss_server.get(zmq::sockopt::gssapi_plaintext) == 0);
209 check_array_opt(zmq::sockopt::gssapi_principal, gss_server,
213 CHECK(gss_client.get(zmq::sockopt::gssapi_server) == 0);
214 check_array_opt(zmq::sockopt::gssapi_principal, gss_client,
216 check_array_opt(zmq::sockopt::gssapi_service_principal, gss_client,
217 "gssapi_service_principal");
222 template<
class T,
class Opt>
223 void check_integral_opt(Opt opt,
226 bool set_only =
false)
229 INFO(
"setting " + info);
234 INFO(
"getting " + info);
235 auto s =
sock.get(opt);
239 template<
class T,
class Opt>
242 INFO(
"getting " + info);
246 TEST_CASE(
"socket check integral options",
"[socket]")
252 #ifdef ZMQ_STREAM_NOTIFY
257 check_integral_opt<uint64_t>(zmq::sockopt::affinity, router,
"affinity");
260 check_integral_opt<int>(zmq::sockopt::backlog, router,
"backlog");
263 check_integral_opt<int>(zmq::sockopt::conflate, router,
"conflate");
265 #ifdef ZMQ_CONNECT_TIMEOUT
266 check_integral_opt<int>(zmq::sockopt::connect_timeout, router,
270 check_integral_opt_get<int>(zmq::sockopt::events, router,
"events");
273 check_integral_opt_get<zmq::fd_t>(zmq::sockopt::fd, router,
"fd");
275 #ifdef ZMQ_HANDSHAKE_IVL
276 check_integral_opt<int>(zmq::sockopt::handshake_ivl, router,
"handshake_ivl");
278 #ifdef ZMQ_HEARTBEAT_IVL
279 check_integral_opt<int>(zmq::sockopt::heartbeat_ivl, router,
"heartbeat_ivl");
281 #ifdef ZMQ_HEARTBEAT_TIMEOUT
282 check_integral_opt<int>(zmq::sockopt::heartbeat_timeout, router,
283 "heartbeat_timeout");
285 #ifdef ZMQ_HEARTBEAT_TTL
286 router.set(zmq::sockopt::heartbeat_ttl, 100);
287 CHECK(router.get(zmq::sockopt::heartbeat_ttl) == 100);
290 check_integral_opt<int>(zmq::sockopt::immediate, router,
"immediate");
292 #ifdef ZMQ_INVERT_MATCHING
293 check_integral_opt<int>(zmq::sockopt::invert_matching, router,
297 check_integral_opt<int>(zmq::sockopt::ipv6, router,
"ipv6");
300 check_integral_opt<int>(zmq::sockopt::linger, router,
"linger");
302 #ifdef ZMQ_MAXMSGSIZE
303 check_integral_opt<int64_t>(zmq::sockopt::maxmsgsize, router,
"maxmsgsize");
306 check_integral_opt_get<int>(zmq::sockopt::mechanism, router,
"mechanism");
308 #ifdef ZMQ_MULTICAST_HOPS
309 check_integral_opt<int>(zmq::sockopt::multicast_hops, router,
"multicast_hops");
311 #ifdef ZMQ_MULTICAST_LOOP
312 check_integral_opt<int>(zmq::sockopt::multicast_loop, router,
"multicast_loop");
314 #ifdef ZMQ_MULTICAST_MAXTPDU
315 check_integral_opt<int>(zmq::sockopt::multicast_maxtpdu, router,
316 "multicast_maxtpdu");
318 #ifdef ZMQ_PLAIN_SERVER
319 check_integral_opt<int>(zmq::sockopt::plain_server, router,
"plain_server");
322 check_integral_opt<int>(zmq::sockopt::use_fd, router,
"use_fd");
324 #ifdef ZMQ_PROBE_ROUTER
325 check_integral_opt<int>(zmq::sockopt::probe_router, router,
"probe_router",
329 check_integral_opt<int>(zmq::sockopt::rate, router,
"rate");
332 check_integral_opt<int>(zmq::sockopt::rcvbuf, router,
"rcvbuf");
335 check_integral_opt<int>(zmq::sockopt::rcvhwm, router,
"rcvhwm");
338 check_integral_opt_get<int>(zmq::sockopt::rcvmore, router,
"rcvmore");
341 check_integral_opt<int>(zmq::sockopt::rcvtimeo, router,
"rcvtimeo");
343 #ifdef ZMQ_RECONNECT_IVL
344 check_integral_opt<int>(zmq::sockopt::reconnect_ivl, router,
"reconnect_ivl");
346 #ifdef ZMQ_RECONNECT_IVL_MAX
347 check_integral_opt<int>(zmq::sockopt::reconnect_ivl_max, router,
348 "reconnect_ivl_max");
350 #ifdef ZMQ_RECOVERY_IVL
351 check_integral_opt<int>(zmq::sockopt::recovery_ivl, router,
"recovery_ivl");
353 #ifdef ZMQ_REQ_CORRELATE
354 check_integral_opt<int>(zmq::sockopt::req_correlate,
req,
"req_correlate",
true);
356 #ifdef ZMQ_REQ_RELAXED
357 check_integral_opt<int>(zmq::sockopt::req_relaxed,
req,
"req_relaxed",
true);
359 #ifdef ZMQ_ROUTER_HANDOVER
360 check_integral_opt<int>(zmq::sockopt::router_handover, router,
"router_handover",
363 #ifdef ZMQ_ROUTER_MANDATORY
364 check_integral_opt<int>(zmq::sockopt::router_mandatory, router,
365 "router_mandatory",
true);
367 #ifdef ZMQ_ROUTER_RAW
368 check_integral_opt<int>(zmq::sockopt::router_raw, router,
"router_raw",
371 #ifdef ZMQ_ROUTER_NOTIFY
372 check_integral_opt<int>(zmq::sockopt::router_notify, router,
"router_notify");
375 check_integral_opt<int>(zmq::sockopt::sndbuf, router,
"sndbuf");
378 check_integral_opt<int>(zmq::sockopt::sndhwm, router,
"sndhwm");
381 check_integral_opt<int>(zmq::sockopt::sndtimeo, router,
"sndtimeo");
383 #ifdef ZMQ_STREAM_NOTIFY
384 check_integral_opt<int>(zmq::sockopt::stream_notify,
stream,
"stream_notify",
387 #ifdef ZMQ_TCP_KEEPALIVE
388 check_integral_opt<int>(zmq::sockopt::tcp_keepalive, router,
"tcp_keepalive");
390 #ifdef ZMQ_TCP_KEEPALIVE_CNT
391 check_integral_opt<int>(zmq::sockopt::tcp_keepalive_cnt, router,
392 "tcp_keepalive_cnt");
394 #ifdef ZMQ_TCP_KEEPALIVE_IDLE
395 check_integral_opt<int>(zmq::sockopt::tcp_keepalive_idle, router,
396 "tcp_keepalive_idle");
398 #ifdef ZMQ_TCP_KEEPALIVE_INTVL
399 check_integral_opt<int>(zmq::sockopt::tcp_keepalive_intvl, router,
400 "tcp_keepalive_intvl");
403 check_integral_opt<int>(zmq::sockopt::tcp_maxrt, router,
"tcp_maxrt");
405 #ifdef ZMQ_THREAD_SAFE
406 check_integral_opt_get<bool>(zmq::sockopt::thread_safe, router,
"thread_safe");
409 check_integral_opt<int>(zmq::sockopt::tos, router,
"tos");
414 check_integral_opt_get<zmq::socket_type>(zmq::sockopt::socket_type, router,
"socket_type");
419 #ifdef ZMQ_VMCI_BUFFER_SIZE
420 check_integral_opt<uint64_t>(zmq::sockopt::vmci_buffer_size, router,
423 #ifdef ZMQ_VMCI_BUFFER_MIN_SIZE
424 check_integral_opt<uint64_t>(zmq::sockopt::vmci_buffer_min_size, router,
425 "vmci_buffer_min_size");
427 #ifdef ZMQ_VMCI_BUFFER_MAX_SIZE
428 check_integral_opt<uint64_t>(zmq::sockopt::vmci_buffer_max_size, router,
429 "vmci_buffer_max_size");
431 #ifdef ZMQ_VMCI_CONNECT_TIMEOUT
432 check_integral_opt<int>(zmq::sockopt::vmci_connect_timeout, router,
433 "vmci_connect_timeout");
437 #ifdef ZMQ_XPUB_VERBOSE
438 check_integral_opt<int>(zmq::sockopt::xpub_verbose, xpub,
"xpub_verbose",
true);
440 #ifdef ZMQ_XPUB_VERBOSER
441 check_integral_opt<int>(zmq::sockopt::xpub_verboser, xpub,
"xpub_verboser",
444 #ifdef ZMQ_XPUB_MANUAL
445 check_integral_opt<int>(zmq::sockopt::xpub_manual, xpub,
"xpub_manual",
true);
447 #ifdef ZMQ_XPUB_NODROP
448 check_integral_opt<int>(zmq::sockopt::xpub_nodrop, xpub,
"xpub_nodrop",
true);
450 #ifdef ZMQ_ZAP_ENFORCE_DOMAIN
451 check_integral_opt<int>(zmq::sockopt::zap_enforce_domain, router,
452 "zap_enforce_domain");
460 CHECK((zmq::recv_flags::dontwait | zmq::recv_flags::none)
462 CHECK((zmq::recv_flags::dontwait & zmq::recv_flags::none)
464 CHECK((zmq::recv_flags::dontwait ^ zmq::recv_flags::none)
466 CHECK(~zmq::recv_flags::dontwait ==
static_cast<zmq::recv_flags
>(~
ZMQ_DONTWAIT));
468 CHECK((zmq::send_flags::dontwait | zmq::send_flags::sndmore)
470 CHECK((zmq::send_flags::dontwait & zmq::send_flags::sndmore)
472 CHECK((zmq::send_flags::dontwait ^ zmq::send_flags::sndmore)
474 CHECK(~zmq::send_flags::dontwait ==
static_cast<zmq::send_flags
>(~
ZMQ_DONTWAIT));
477 TEST_CASE(
"socket readme example",
"[socket]")
481 sock.bind(
"inproc://test");
482 sock.send(zmq::str_buffer(
"Hello, world"), zmq::send_flags::dontwait);
486 TEST_CASE(
"socket sends and receives const buffer",
"[socket]")
492 sender.
connect(
"inproc://test");
493 const char *
str =
"Hi";
500 CHECK(!res->truncated());
501 CHECK(2 == res->size);
512 TEST_CASE(
"socket send none sndmore",
"[socket]")
516 s.bind(
"inproc://test");
518 std::vector<char>
buf(4);
527 TEST_CASE(
"socket send dontwait",
"[socket]")
531 s.bind(
"inproc://test");
533 std::vector<char>
buf(4);
537 s.send(
zmq::buffer(
buf), zmq::send_flags::dontwait | zmq::send_flags::sndmore);
541 auto resm =
s.send(msg, zmq::send_flags::dontwait);
546 TEST_CASE(
"socket send exception",
"[socket]")
550 s.bind(
"inproc://test");
552 std::vector<char>
buf(4);
556 TEST_CASE(
"socket recv none",
"[socket]")
561 s2.bind(
"inproc://test");
562 s.connect(
"inproc://test");
564 std::vector<char> sbuf(4);
567 CHECK(res_send.has_value());
569 std::vector<char>
buf(2);
571 CHECK(res.has_value());
572 CHECK(res->truncated());
573 CHECK(res->untruncated_size == sbuf.size());
577 CHECK(res_send2.has_value());
578 std::vector<char> buf2(10);
580 CHECK(res2.has_value());
581 CHECK(!res2->truncated());
582 CHECK(res2->untruncated_size == sbuf.size());
583 CHECK(res2->size == sbuf.size());
586 TEST_CASE(
"socket send recv message_t",
"[socket]")
591 s2.bind(
"inproc://test");
592 s.connect(
"inproc://test");
595 const auto res_send = s2.send(smsg, zmq::send_flags::none);
597 CHECK(*res_send == 10);
598 CHECK(smsg.size() == 0);
601 const auto res =
s.recv(rmsg);
604 CHECK(res.value() == 10);
608 TEST_CASE(
"socket send recv message_t by pointer",
"[socket]")
613 s2.bind(
"inproc://test");
614 s.connect(
"inproc://test");
617 const auto res_send = s2.send(smsg, zmq::send_flags::none);
619 CHECK(*res_send == 10);
620 CHECK(smsg.size() == 0);
623 const bool res =
s.recv(&rmsg);
627 TEST_CASE(
"socket recv dontwait",
"[socket]")
631 s.bind(
"inproc://test");
633 std::vector<char>
buf(4);
634 constexpr
auto flags = zmq::recv_flags::none | zmq::recv_flags::dontwait;
639 auto resm =
s.recv(msg,
flags);
641 CHECK_THROWS_AS(resm.value(), std::exception);
645 TEST_CASE(
"socket recv exception",
"[socket]")
649 s.bind(
"inproc://test");
651 std::vector<char>
buf(4);
661 front.bind(
"inproc://test1");
662 back.bind(
"inproc://test2");
663 capture.bind(
"inproc://test3");
664 auto f = std::async(std::launch::async, [&]() {
665 auto s1 = std::move(front);
666 auto s2 = std::move(back);
680 TEST_CASE(
"socket proxy steerable",
"[socket]")
686 front.bind(
"inproc://test1");
687 back.bind(
"inproc://test2");
688 control.connect(
"inproc://test3");
689 auto f = std::async(std::launch::async, [&]() {
690 auto s1 = std::move(front);
691 auto s2 = std::move(back);
692 auto s3 = std::move(control);