123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342 |
- #include "testutil.hpp"
- #if defined(ZMQ_BUILD_DRAFT_API) && defined(ZMQ_CPP11) && defined(ZMQ_HAVE_POLLER)
- #include <array>
- #include <memory>
- #ifdef ZMQ_CPP17
- static_assert(std::is_nothrow_swappable_v<zmq::poller_t<>>);
- #endif
- static_assert(sizeof(zmq_poller_event_t) == sizeof(zmq::poller_event<>), "");
- static_assert(sizeof(zmq_poller_event_t) == sizeof(zmq::poller_event<zmq::
- no_user_data>), "");
- static_assert(sizeof(zmq_poller_event_t) == sizeof(zmq::poller_event<int>), "");
- static_assert(alignof(zmq_poller_event_t) == alignof(zmq::poller_event<>), "");
- static_assert(alignof(zmq_poller_event_t) == alignof(zmq::poller_event<int>), "");
- static_assert(!std::is_copy_constructible<zmq::poller_t<>>::value,
- "poller_t should not be copy-constructible");
- static_assert(!std::is_copy_assignable<zmq::poller_t<>>::value,
- "poller_t should not be copy-assignable");
- TEST_CASE("event flags", "[poller]")
- {
- CHECK((zmq::event_flags::pollin | zmq::event_flags::pollout)
- == static_cast<zmq::event_flags>(ZMQ_POLLIN | ZMQ_POLLOUT));
- CHECK((zmq::event_flags::pollin & zmq::event_flags::pollout)
- == static_cast<zmq::event_flags>(ZMQ_POLLIN & ZMQ_POLLOUT));
- CHECK((zmq::event_flags::pollin ^ zmq::event_flags::pollout)
- == static_cast<zmq::event_flags>(ZMQ_POLLIN ^ ZMQ_POLLOUT));
- CHECK(~zmq::event_flags::pollin == static_cast<zmq::event_flags>(~ZMQ_POLLIN));
- }
- TEST_CASE("poller create destroy", "[poller]")
- {
- zmq::poller_t<> a;
- #ifdef ZMQ_CPP17 // CTAD
- zmq::poller_t b;
- zmq::poller_event e;
- #endif
- }
- TEST_CASE("poller move construct empty", "[poller]")
- {
- zmq::poller_t<> a;
- zmq::poller_t<> b = std::move(a);
- }
- TEST_CASE("poller move assign empty", "[poller]")
- {
- zmq::poller_t<> a;
- zmq::poller_t<> b;
- b = std::move(a);
- }
- TEST_CASE("poller swap", "[poller]")
- {
- zmq::poller_t<> a;
- zmq::poller_t<> b;
- using std::swap;
- swap(a, b);
- }
- TEST_CASE("poller move construct non empty", "[poller]")
- {
- zmq::context_t context;
- zmq::socket_t socket{context, zmq::socket_type::router};
- zmq::poller_t<> a;
- a.add(socket, zmq::event_flags::pollin);
- zmq::poller_t<> b = std::move(a);
- }
- TEST_CASE("poller move assign non empty", "[poller]")
- {
- zmq::context_t context;
- zmq::socket_t socket{context, zmq::socket_type::router};
- zmq::poller_t<> a;
- a.add(socket, zmq::event_flags::pollin);
- zmq::poller_t<> b;
- b = std::move(a);
- }
- TEST_CASE("poller add nullptr", "[poller]")
- {
- zmq::context_t context;
- zmq::socket_t socket{context, zmq::socket_type::router};
- zmq::poller_t<void> poller;
- CHECK_NOTHROW(poller.add(socket, zmq::event_flags::pollin, nullptr));
- }
- TEST_CASE("poller add non nullptr", "[poller]")
- {
- zmq::context_t context;
- zmq::socket_t socket{context, zmq::socket_type::router};
- zmq::poller_t<int> poller;
- int i;
- CHECK_NOTHROW(poller.add(socket, zmq::event_flags::pollin, &i));
- }
- #if ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 3, 0)
- // this behaviour was added by https://github.com/zeromq/libzmq/pull/3100
- TEST_CASE("poller add handler invalid events type", "[poller]")
- {
- zmq::context_t context;
- zmq::socket_t socket{context, zmq::socket_type::router};
- zmq::poller_t<> poller;
- short invalid_events_type = 2 << 10;
- CHECK_THROWS_AS(
- poller.add(socket, static_cast<zmq::event_flags>(invalid_events_type)),
- const zmq::error_t&);
- }
- #endif
- TEST_CASE("poller add handler twice throws", "[poller]")
- {
- zmq::context_t context;
- zmq::socket_t socket{context, zmq::socket_type::router};
- zmq::poller_t<> poller;
- poller.add(socket, zmq::event_flags::pollin);
- /// \todo the actual error code should be checked
- CHECK_THROWS_AS(poller.add(socket, zmq::event_flags::pollin),
- const zmq::error_t&);
- }
- TEST_CASE("poller wait with no handlers throws", "[poller]")
- {
- zmq::poller_t<> poller;
- std::vector<zmq::poller_event<>> events;
- /// \todo the actual error code should be checked
- CHECK_THROWS_AS(poller.wait_all(events, std::chrono::milliseconds{10}),
- const zmq::error_t&);
- }
- TEST_CASE("poller remove unregistered throws", "[poller]")
- {
- zmq::context_t context;
- zmq::socket_t socket{context, zmq::socket_type::router};
- zmq::poller_t<> poller;
- /// \todo the actual error code should be checked
- CHECK_THROWS_AS(poller.remove(socket), const zmq::error_t&);
- }
- TEST_CASE("poller remove registered empty", "[poller]")
- {
- zmq::context_t context;
- zmq::socket_t socket{context, zmq::socket_type::router};
- zmq::poller_t<> poller;
- poller.add(socket, zmq::event_flags::pollin);
- CHECK_NOTHROW(poller.remove(socket));
- }
- TEST_CASE("poller remove registered non empty", "[poller]")
- {
- zmq::context_t context;
- zmq::socket_t socket{context, zmq::socket_type::router};
- zmq::poller_t<int> poller;
- int empty{};
- poller.add(socket, zmq::event_flags::pollin, &empty);
- CHECK_NOTHROW(poller.remove(socket));
- }
- const std::string hi_str = "Hi";
- TEST_CASE("poller poll basic", "[poller]")
- {
- common_server_client_setup s;
- CHECK_NOTHROW(s.client.send(zmq::message_t{hi_str}, zmq::send_flags::none));
- zmq::poller_t<int> poller;
- std::vector<zmq::poller_event<int>> events{1};
- int i = 0;
- CHECK_NOTHROW(poller.add(s.server, zmq::event_flags::pollin, &i));
- CHECK(1 == poller.wait_all(events, std::chrono::milliseconds{-1}));
- CHECK(s.server == events[0].socket);
- CHECK(&i == events[0].user_data);
- }
- TEST_CASE("poller add invalid socket throws", "[poller]")
- {
- zmq::context_t context;
- zmq::poller_t<> poller;
- zmq::socket_t a{context, zmq::socket_type::router};
- zmq::socket_t b{std::move(a)};
- CHECK_THROWS_AS(poller.add(a, zmq::event_flags::pollin), const zmq::error_t&);
- }
- TEST_CASE("poller remove invalid socket throws", "[poller]")
- {
- zmq::context_t context;
- zmq::socket_t socket{context, zmq::socket_type::router};
- zmq::poller_t<> poller;
- CHECK_NOTHROW(poller.add(socket, zmq::event_flags::pollin));
- std::vector<zmq::socket_t> sockets;
- sockets.emplace_back(std::move(socket));
- CHECK_THROWS_AS(poller.remove(socket), const zmq::error_t&);
- CHECK_NOTHROW(poller.remove(sockets[0]));
- }
- TEST_CASE("poller modify empty throws", "[poller]")
- {
- zmq::context_t context;
- zmq::socket_t socket{context, zmq::socket_type::push};
- zmq::poller_t<> poller;
- CHECK_THROWS_AS(poller.modify(socket, zmq::event_flags::pollin),
- const zmq::error_t&);
- }
- TEST_CASE("poller modify invalid socket throws", "[poller]")
- {
- zmq::context_t context;
- zmq::socket_t a{context, zmq::socket_type::push};
- zmq::socket_t b{std::move(a)};
- zmq::poller_t<> poller;
- CHECK_THROWS_AS(poller.modify(a, zmq::event_flags::pollin), const zmq::error_t&);
- }
- TEST_CASE("poller modify not added throws", "[poller]")
- {
- zmq::context_t context;
- zmq::socket_t a{context, zmq::socket_type::push};
- zmq::socket_t b{context, zmq::socket_type::push};
- zmq::poller_t<> poller;
- CHECK_NOTHROW(poller.add(a, zmq::event_flags::pollin));
- CHECK_THROWS_AS(poller.modify(b, zmq::event_flags::pollin), const zmq::error_t&);
- }
- TEST_CASE("poller modify simple", "[poller]")
- {
- zmq::context_t context;
- zmq::socket_t a{context, zmq::socket_type::push};
- zmq::poller_t<> poller;
- CHECK_NOTHROW(poller.add(a, zmq::event_flags::pollin));
- CHECK_NOTHROW(
- poller.modify(a, zmq::event_flags::pollin | zmq::event_flags::pollout));
- }
- TEST_CASE("poller poll client server", "[poller]")
- {
- // Setup server and client
- common_server_client_setup s;
- // Setup poller
- zmq::poller_t<zmq::socket_t> poller;
- CHECK_NOTHROW(poller.add(s.server, zmq::event_flags::pollin, &s.server));
- // client sends message
- CHECK_NOTHROW(s.client.send(zmq::message_t{hi_str}, zmq::send_flags::none));
- // wait for message and verify events
- std::vector<zmq::poller_event<zmq::socket_t>> events(1);
- CHECK(1 == poller.wait_all(events, std::chrono::milliseconds{500}));
- CHECK(zmq::event_flags::pollin == events[0].events);
- // Modify server socket with pollout flag
- CHECK_NOTHROW(
- poller.modify(s.server, zmq::event_flags::pollin | zmq::event_flags::pollout
- ));
- CHECK(1 == poller.wait_all(events, std::chrono::milliseconds{500}));
- CHECK((zmq::event_flags::pollin | zmq::event_flags::pollout) == events[0].events)
- ;
- }
- TEST_CASE("poller wait one return", "[poller]")
- {
- // Setup server and client
- common_server_client_setup s;
- // Setup poller
- zmq::poller_t<> poller;
- CHECK_NOTHROW(poller.add(s.server, zmq::event_flags::pollin));
- // client sends message
- CHECK_NOTHROW(s.client.send(zmq::message_t{hi_str}, zmq::send_flags::none));
- // wait for message and verify events
- std::vector<zmq::poller_event<>> events(1);
- CHECK(1 == poller.wait_all(events, std::chrono::milliseconds{500}));
- }
- TEST_CASE("poller wait on move constructed", "[poller]")
- {
- common_server_client_setup s;
- CHECK_NOTHROW(s.client.send(zmq::message_t{hi_str}, zmq::send_flags::none));
- zmq::poller_t<> a;
- CHECK_NOTHROW(a.add(s.server, zmq::event_flags::pollin));
- zmq::poller_t<> b{std::move(a)};
- std::vector<zmq::poller_event<>> events(1);
- /// \todo the actual error code should be checked
- CHECK_THROWS_AS(a.wait_all(events, std::chrono::milliseconds{10}),
- const zmq::error_t&);
- CHECK(1 == b.wait_all(events, std::chrono::milliseconds{-1}));
- }
- TEST_CASE("poller wait on move assigned", "[poller]")
- {
- common_server_client_setup s;
- CHECK_NOTHROW(s.client.send(zmq::message_t{hi_str}, zmq::send_flags::none));
- zmq::poller_t<> a;
- CHECK_NOTHROW(a.add(s.server, zmq::event_flags::pollin));
- zmq::poller_t<> b;
- b = {std::move(a)};
- /// \todo the TEST_CASE error code should be checked
- std::vector<zmq::poller_event<>> events(1);
- CHECK_THROWS_AS(a.wait_all(events, std::chrono::milliseconds{10}),
- const zmq::error_t&);
- CHECK(1 == b.wait_all(events, std::chrono::milliseconds{-1}));
- }
- TEST_CASE("poller remove from handler", "[poller]")
- {
- constexpr size_t ITER_NO = 10;
- // Setup servers and clients
- std::vector<common_server_client_setup> setup_list;
- for (size_t i = 0; i < ITER_NO; ++i)
- setup_list.emplace_back(common_server_client_setup{});
- // Setup poller
- zmq::poller_t<> poller;
- for (size_t i = 0; i < ITER_NO; ++i) {
- CHECK_NOTHROW(poller.add(setup_list[i].server, zmq::event_flags::pollin));
- }
- // Clients send messages
- for (auto &s : setup_list) {
- CHECK_NOTHROW(s.client.send(zmq::message_t{hi_str}, zmq::send_flags::none));
- }
- // Wait for all servers to receive a message
- for (auto &s : setup_list) {
- zmq::pollitem_t items[] = {{s.server, 0, ZMQ_POLLIN, 0}};
- zmq::poll(&items[0], 1);
- }
- // Fire all handlers in one wait
- std::vector<zmq::poller_event<>> events(ITER_NO);
- CHECK(ITER_NO == poller.wait_all(events, std::chrono::milliseconds{-1}));
- }
- #endif
|