Exemplo n.º 1
1
void test_null_event_pointers (void *ctx)
{
    void *socket = zmq_socket (ctx, ZMQ_PAIR);
    assert (socket != NULL);

    void *poller = zmq_poller_new ();
    assert (poller != NULL);

    int rc = zmq_poller_add (poller, socket, NULL, ZMQ_POLLIN);
    assert (rc == 0);

    rc = zmq_poller_wait (poller, NULL, 0);
    assert (rc == -1 && errno == EFAULT);

    rc = zmq_poller_wait_all (poller, NULL, 1, 0);
    assert (rc == -1 && errno == EFAULT);

    //  TODO this causes an assertion, which is not consistent if the number 
    //  of events may be 0, the pointer should be allowed to by NULL in that 
    //  case too
#if 0
    rc = zmq_poller_wait_all (poller, NULL, 0, 0);
    assert (rc == 0);
#endif

    rc = zmq_poller_destroy (&poller);
    assert (rc == 0);

    rc = zmq_close (socket);
    assert (rc == 0);
}
Exemplo n.º 2
0
void test_null_poller_pointers (void *ctx)
{
    int rc = zmq_poller_destroy (NULL);
    assert (rc == -1 && errno == EFAULT);
    void *null_poller = NULL;
    rc = zmq_poller_destroy (&null_poller);
    assert (rc == -1 && errno == EFAULT);

    void *socket = zmq_socket (ctx, ZMQ_PAIR);
    assert (socket != NULL);

    rc = zmq_poller_add (NULL, socket, NULL, ZMQ_POLLIN);
    assert (rc == -1 && errno == EFAULT);
    rc = zmq_poller_add (&null_poller, socket, NULL, ZMQ_POLLIN);
    assert (rc == -1 && errno == EFAULT);

    rc = zmq_poller_modify (NULL, socket, ZMQ_POLLIN);
    assert (rc == -1 && errno == EFAULT);
    rc = zmq_poller_modify (&null_poller, socket, ZMQ_POLLIN);
    assert (rc == -1 && errno == EFAULT);

    rc = zmq_poller_remove (NULL, socket);
    assert (rc == -1 && errno == EFAULT);
    rc = zmq_poller_remove (&null_poller, socket);
    assert (rc == -1 && errno == EFAULT);

    fd_t fd;
    size_t fd_size = sizeof fd;
    rc = zmq_getsockopt(socket, ZMQ_FD, &fd, &fd_size);
    assert (rc == 0);

    rc = zmq_poller_add_fd (NULL, fd, NULL, ZMQ_POLLIN);
    assert (rc == -1 && errno == EFAULT);
    rc = zmq_poller_add_fd (&null_poller, fd, NULL, ZMQ_POLLIN);
    assert (rc == -1 && errno == EFAULT);

    rc = zmq_poller_modify_fd (NULL, fd, ZMQ_POLLIN);
    assert (rc == -1 && errno == EFAULT);
    rc = zmq_poller_modify_fd (&null_poller, fd, ZMQ_POLLIN);
    assert (rc == -1 && errno == EFAULT);

    rc = zmq_poller_remove_fd (NULL, fd);
    assert (rc == -1 && errno == EFAULT);
    rc = zmq_poller_remove_fd (&null_poller, fd);
    assert (rc == -1 && errno == EFAULT);

    zmq_poller_event_t event;
    rc = zmq_poller_wait (NULL, &event, 0);
    assert (rc == -1 && errno == EFAULT);
    rc = zmq_poller_wait (&null_poller, &event, 0);
    assert (rc == -1 && errno == EFAULT);

    rc = zmq_poller_wait_all (NULL, &event, 1, 0);
    assert (rc == -1 && errno == EFAULT);
    rc = zmq_poller_wait_all (&null_poller, &event, 1, 0);
    assert (rc == -1 && errno == EFAULT);

    rc = zmq_close (socket);
    assert (rc == 0);
}
Exemplo n.º 3
0
void test_add_modify_remove_corner_cases(void *ctx)
{
    void *poller = zmq_poller_new ();
    assert (poller != NULL);

    void *zeromq_socket = zmq_socket (ctx, ZMQ_PAIR);
    assert (zeromq_socket != NULL);

    int rc = zmq_poller_add (poller, zeromq_socket, NULL, ZMQ_POLLIN);
    assert (rc == 0);

    //  attempt to add the same socket twice
    rc = zmq_poller_add (poller, zeromq_socket, NULL, ZMQ_POLLIN);
    assert (rc == -1 && errno == EINVAL);

    rc = zmq_poller_remove (poller, zeromq_socket);
    assert (rc == 0);

    //  attempt to remove socket that is not present
    rc = zmq_poller_remove (poller, zeromq_socket);
    assert (rc == -1 && errno == EINVAL);

    //  attempt to modify socket that is not present
    rc = zmq_poller_modify (poller, zeromq_socket, ZMQ_POLLIN);
    assert (rc == -1 && errno == EINVAL);

    //  add a socket with no events
    //  TODO should this really be legal? it does not make any sense...
    rc = zmq_poller_add (poller, zeromq_socket, NULL, 0);
    assert (rc == 0);

    fd_t plain_socket = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
    rc = zmq_poller_add_fd (poller, plain_socket, NULL, ZMQ_POLLIN);
    assert (rc == 0);

    //  attempt to add the same plain socket twice
    rc = zmq_poller_add_fd (poller, plain_socket, NULL, ZMQ_POLLIN);
    assert (rc == -1 && errno == EINVAL);

    rc = zmq_poller_remove_fd (poller, plain_socket);
    assert (rc == 0);

    //  attempt to remove plain socket that is not present
    rc = zmq_poller_remove_fd (poller, plain_socket);
    assert (rc == -1 && errno == EINVAL);

    //  attempt to modify plain socket that is not present
    rc = zmq_poller_modify_fd (poller, plain_socket, ZMQ_POLLIN);
    assert (rc == -1 && errno == EINVAL);

    rc = zmq_poller_destroy (&poller);
    assert (rc == 0);

    rc = zmq_close (zeromq_socket);
    assert (rc == 0);

    rc = close (plain_socket);
    assert (rc == 0);
}
Exemplo n.º 4
0
void test_null_socket_pointers ()
{
    void *poller = zmq_poller_new ();
    assert (poller != NULL);

    int rc = zmq_poller_add (poller, NULL, NULL, ZMQ_POLLIN);
    assert (rc == -1 && errno == ENOTSOCK);

    rc = zmq_poller_modify (poller, NULL, ZMQ_POLLIN);
    assert (rc == -1 && errno == ENOTSOCK);

    rc = zmq_poller_remove (poller, NULL);
    assert (rc == -1 && errno == ENOTSOCK);

    fd_t null_socket_fd = retired_fd;
    
    rc = zmq_poller_add_fd (poller, null_socket_fd, NULL, ZMQ_POLLIN);
    assert (rc == -1 && errno == EBADF);

    rc = zmq_poller_modify_fd (poller, null_socket_fd, ZMQ_POLLIN);
    assert (rc == -1 && errno == EBADF);

    rc = zmq_poller_remove_fd (poller, null_socket_fd);
    assert (rc == -1 && errno == EBADF);

    rc = zmq_poller_destroy (&poller);
    assert (rc == 0);
}
Exemplo n.º 5
0
void run_poller (void *data_)
{
    struct poller_test_data_t *poller_test_data =
      (struct poller_test_data_t *) data_;

    void *socket =
      zmq_socket (poller_test_data->ctx, poller_test_data->socket_type);
    TEST_ASSERT_NOT_NULL (socket);

    void *poller = zmq_poller_new ();
    TEST_ASSERT_NOT_NULL (poller);

    TEST_ASSERT_SUCCESS_ERRNO (
      zmq_poller_add (poller, socket, NULL, ZMQ_POLLIN));

    zmq_atomic_counter_set (poller_test_data->counter, 1);

    zmq_poller_event_t event;
    TEST_ASSERT_FAILURE_ERRNO (ETERM, zmq_poller_wait (poller, &event, -1));

    TEST_ASSERT_SUCCESS_ERRNO (zmq_poller_destroy (&poller));

    // Close the socket
    TEST_ASSERT_SUCCESS_ERRNO (zmq_close (socket));
}
Exemplo n.º 6
0
int
zpoller_add (zpoller_t *self, void *reader)
{
    assert (self);
    assert (reader);
    int rc = 0;
#ifdef ZMQ_HAVE_POLLER
    void *socket = zsock_resolve (reader);
    if (socket)
        rc = zmq_poller_add (self->zmq_poller, socket, reader, ZMQ_POLLIN);
    else
        rc = zmq_poller_add_fd (self->zmq_poller, *(SOCKET *) reader, reader, ZMQ_POLLIN);
#else
    zlist_append (self->reader_list, reader);
    self->need_rebuild = true;
#endif
    return rc;
}
Exemplo n.º 7
0
int main (void)
{
    setup_test_environment ();

    void *ctx = zmq_ctx_new ();
    assert (ctx);

    //  Create few sockets
    void *vent = zmq_socket (ctx, ZMQ_PUSH);
    assert (vent);
    int rc = zmq_bind (vent, "tcp://127.0.0.1:55556");
    assert (rc == 0);

    void *sink = zmq_socket (ctx, ZMQ_PULL);
    assert (sink);
    rc = zmq_connect (sink, "tcp://127.0.0.1:55556");
    assert (rc == 0);

    void *bowl = zmq_socket (ctx, ZMQ_PULL);
    assert (bowl);

#if defined(ZMQ_SERVER) && defined(ZMQ_CLIENT)
    void *server = zmq_socket (ctx, ZMQ_SERVER);
    assert (server);
    rc = zmq_bind (server, "tcp://127.0.0.1:55557");
    assert (rc == 0);

    void *client = zmq_socket (ctx, ZMQ_CLIENT);
    assert (client);
#endif

    //  Set up poller
    void* poller = zmq_poller_new ();
    zmq_poller_event_t event;

    // waiting on poller with no registered sockets should report error
    rc = zmq_poller_wait(poller, &event, 0);
    assert (rc == -1);
    assert (errno == ETIMEDOUT);

    // register sink
    rc = zmq_poller_add (poller, sink, sink, ZMQ_POLLIN);
    assert (rc == 0);
    
    //  Send a message
    char data[1] = {'H'};
    rc = zmq_send_const (vent, data, 1, 0);
    assert (rc == 1);   

    //  We expect a message only on the sink
    rc = zmq_poller_wait (poller, &event, -1);
    assert (rc == 0);
    assert (event.socket == sink);
    assert (event.user_data == sink);
    rc = zmq_recv (sink, data, 1, 0);
    assert (rc == 1);

    //  We expect timed out
    rc = zmq_poller_wait (poller, &event, 0);
    assert (rc == -1);
    assert (errno == ETIMEDOUT);

    //  Stop polling sink
    rc = zmq_poller_remove (poller, sink);
    assert (rc == 0);

    //  Check we can poll an FD
    rc = zmq_connect (bowl, "tcp://127.0.0.1:55556");
    assert (rc == 0);

#if defined _WIN32
    SOCKET fd;
    size_t fd_size = sizeof (SOCKET);
#else 
    int fd;
    size_t fd_size = sizeof (int);
#endif

    rc = zmq_getsockopt (bowl, ZMQ_FD, &fd, &fd_size);
    assert (rc == 0);
    rc = zmq_poller_add_fd (poller, fd, bowl, ZMQ_POLLIN);
    assert (rc == 0);
    rc = zmq_poller_wait (poller, &event, 500);
    assert (rc == 0);
    assert (event.socket == NULL);
    assert (event.fd == fd);
    assert (event.user_data == bowl);
    zmq_poller_remove_fd (poller, fd);

#if defined(ZMQ_SERVER) && defined(ZMQ_CLIENT)
    //  Polling on thread safe sockets
    rc = zmq_poller_add (poller, server, NULL, ZMQ_POLLIN);
    assert (rc == 0);
    rc = zmq_connect (client, "tcp://127.0.0.1:55557");
    assert (rc == 0);
    rc = zmq_send_const (client, data, 1, 0);
    assert (rc == 1);
    rc = zmq_poller_wait (poller, &event, 500);
    assert (rc == 0);
    assert (event.socket == server);
    assert (event.user_data == NULL); 
    rc = zmq_recv (server, data, 1, 0);
    assert (rc == 1);    

    //  Polling on pollout
    rc = zmq_poller_modify (poller, server, ZMQ_POLLOUT | ZMQ_POLLIN); 
    assert (rc == 0);
    rc = zmq_poller_wait (poller, &event, 0);
    assert (rc == 0);
    assert (event.socket == server);
    assert (event.user_data == NULL);
    assert (event.events == ZMQ_POLLOUT);
#endif

    //  Destory sockets, poller and ctx    
    rc = zmq_close (sink);
    assert (rc == 0);
    rc = zmq_close (vent);
    assert (rc == 0);
    rc = zmq_close (bowl);
    assert (rc == 0);
#if defined(ZMQ_SERVER) && defined(ZMQ_CLIENT)
    rc = zmq_close (server);
    assert (rc == 0);
    rc = zmq_close (client);
    assert (rc == 0);
#endif

    // Test error - null poller pointers
    rc = zmq_poller_destroy (NULL);
    assert (rc == -1 && errno == EFAULT);
    void *null_poller = NULL;
    rc = zmq_poller_destroy (&null_poller);
    assert (rc == -1 && errno == EFAULT);

    rc = zmq_poller_destroy (&poller);
    assert(rc == 0);
    rc = zmq_ctx_term (ctx);
    assert (rc == 0);

    return 0;
}
Exemplo n.º 8
0
int main (void)
{
    size_t len = MAX_SOCKET_STRING;
    char my_endpoint_0[MAX_SOCKET_STRING];
    char my_endpoint_1[MAX_SOCKET_STRING];

    setup_test_environment ();

    void *ctx = zmq_ctx_new ();
    assert (ctx);

    //  Create few sockets
    void *vent = zmq_socket (ctx, ZMQ_PUSH);
    assert (vent);
    int rc = zmq_bind (vent, "tcp://127.0.0.1:*");
    assert (rc == 0);
    rc = zmq_getsockopt (vent, ZMQ_LAST_ENDPOINT, my_endpoint_0, &len);
    assert (rc == 0);

    void *sink = zmq_socket (ctx, ZMQ_PULL);
    assert (sink);
    rc = zmq_connect (sink, my_endpoint_0);
    assert (rc == 0);

    void *bowl = zmq_socket (ctx, ZMQ_PULL);
    assert (bowl);

#if defined(ZMQ_SERVER) && defined(ZMQ_CLIENT)
    void *server = zmq_socket (ctx, ZMQ_SERVER);
    assert (server);
    rc = zmq_bind (server, "tcp://127.0.0.1:*");
    assert (rc == 0);
    len = MAX_SOCKET_STRING;
    rc = zmq_getsockopt (server, ZMQ_LAST_ENDPOINT, my_endpoint_1, &len);
    assert (rc == 0);

    void *client = zmq_socket (ctx, ZMQ_CLIENT);
    assert (client);
#endif

    //  Set up poller
    void *poller = zmq_poller_new ();
    zmq_poller_event_t event;

    // waiting on poller with no registered sockets should report error
    rc = zmq_poller_wait (poller, &event, 0);
    assert (rc == -1);
    assert (errno == EAGAIN);

    // register sink
    rc = zmq_poller_add (poller, sink, sink, ZMQ_POLLIN);
    assert (rc == 0);

    //  Send a message
    char data[1] = {'H'};
    rc = zmq_send_const (vent, data, 1, 0);
    assert (rc == 1);

    //  We expect a message only on the sink
    rc = zmq_poller_wait (poller, &event, -1);
    assert (rc == 0);
    assert (event.socket == sink);
    assert (event.user_data == sink);
    rc = zmq_recv (sink, data, 1, 0);
    assert (rc == 1);

    //  We expect timed out
    rc = zmq_poller_wait (poller, &event, 0);
    assert (rc == -1);
    assert (errno == EAGAIN);

    //  Stop polling sink
    rc = zmq_poller_remove (poller, sink);
    assert (rc == 0);

    //  Check we can poll an FD
    rc = zmq_connect (bowl, my_endpoint_0);
    assert (rc == 0);

    fd_t fd;
    size_t fd_size = sizeof (fd);

    rc = zmq_getsockopt (bowl, ZMQ_FD, &fd, &fd_size);
    assert (rc == 0);
    rc = zmq_poller_add_fd (poller, fd, bowl, ZMQ_POLLIN);
    assert (rc == 0);
    rc = zmq_poller_wait (poller, &event, 500);
    assert (rc == 0);
    assert (event.socket == NULL);
    assert (event.fd == fd);
    assert (event.user_data == bowl);
    zmq_poller_remove_fd (poller, fd);

#if defined(ZMQ_SERVER) && defined(ZMQ_CLIENT)
    //  Polling on thread safe sockets
    rc = zmq_poller_add (poller, server, NULL, ZMQ_POLLIN);
    assert (rc == 0);
    rc = zmq_connect (client, my_endpoint_1);
    assert (rc == 0);
    rc = zmq_send_const (client, data, 1, 0);
    assert (rc == 1);
    rc = zmq_poller_wait (poller, &event, 500);
    assert (rc == 0);
    assert (event.socket == server);
    assert (event.user_data == NULL);
    rc = zmq_recv (server, data, 1, 0);
    assert (rc == 1);

    //  Polling on pollout
    rc = zmq_poller_modify (poller, server, ZMQ_POLLOUT | ZMQ_POLLIN);
    assert (rc == 0);
    rc = zmq_poller_wait (poller, &event, 0);
    assert (rc == 0);
    assert (event.socket == server);
    assert (event.user_data == NULL);
    assert (event.events == ZMQ_POLLOUT);

    //  Stop polling server
    rc = zmq_poller_remove (poller, server);
    assert (rc == 0);
#endif

    //  Destroy sockets, poller and ctx
    rc = zmq_close (sink);
    assert (rc == 0);
    rc = zmq_close (vent);
    assert (rc == 0);
    rc = zmq_close (bowl);
    assert (rc == 0);
#if defined(ZMQ_SERVER) && defined(ZMQ_CLIENT)
    rc = zmq_close (server);
    assert (rc == 0);
    rc = zmq_close (client);
    assert (rc == 0);
#endif

    test_null_poller_pointers (ctx);
    test_null_socket_pointers ();
    test_null_event_pointers (ctx);

    test_add_modify_remove_corner_cases (ctx);
    test_wait_corner_cases ();

    rc = zmq_poller_destroy (&poller);
    assert (rc == 0);
    rc = zmq_ctx_term (ctx);
    assert (rc == 0);

    return 0;
}
Exemplo n.º 9
0
inline int zmq_poller_poll (zmq_pollitem_t *items_, int nitems_, long timeout_)
{
    // implement zmq_poll on top of zmq_poller
    int rc;
    zmq_poller_event_t *events;
    zmq::socket_poller_t poller;
    events = new (std::nothrow) zmq_poller_event_t[nitems_];
    alloc_assert(events);

    bool repeat_items = false;
    //  Register sockets with poller
    for (int i = 0; i < nitems_; i++) {
        items_[i].revents = 0;

        bool modify = false;
        short e = items_[i].events;
        if (items_[i].socket) {
            //  Poll item is a 0MQ socket.
            for (int j = 0; j < i; ++j) {
                // Check for repeat entries
                if (items_[j].socket == items_[i].socket) {
                    repeat_items = true;
                    modify = true;
                    e |= items_[j].events;
                }
            }
            if (modify) {
                rc = zmq_poller_modify (&poller, items_[i].socket, e);
            } else {
                rc = zmq_poller_add (&poller, items_[i].socket, NULL, e);
            }
            if (rc < 0) {
                delete [] events;
                return rc;
            }
        } else {
            //  Poll item is a raw file descriptor.
            for (int j = 0; j < i; ++j) {
                // Check for repeat entries
                if (!items_[j].socket && items_[j].fd == items_[i].fd) {
                    repeat_items = true;
                    modify = true;
                    e |= items_[j].events;
                }
            }
            if (modify) {
                rc = zmq_poller_modify_fd (&poller, items_[i].fd, e);
            } else {
                rc = zmq_poller_add_fd (&poller, items_[i].fd, NULL, e);
            }
            if (rc < 0) {
                delete [] events;
                return rc;
            }
        }
    }

    //  Wait for events
    rc = zmq_poller_wait_all (&poller, events, nitems_, timeout_);
    if (rc < 0) {
        delete [] events;
        if (zmq_errno() == ETIMEDOUT) {
            return 0;
        }
        return rc;
    }

    //  Transform poller events into zmq_pollitem events.
    //  items_ contains all items, while events only contains fired events.
    //  If no sockets are repeated (likely), the two are still co-ordered, so step through the items
    //  checking for matches only on the first event.
    //  If there are repeat items, they cannot be assumed to be co-ordered,
    //  so each pollitem must check fired events from the beginning.
    int j_start = 0, found_events = rc;
    for (int i = 0; i < nitems_; i++) {
        for (int j = j_start; j < found_events; ++j) {
            if (
                (items_[i].socket && items_[i].socket == events[j].socket) ||
                (!(items_[i].socket || events[j].socket) && items_[i].fd == events[j].fd)
            ) {
                items_[i].revents = events[j].events & items_[i].events;
                if (!repeat_items) {
                    // no repeats, we can ignore events we've already seen
                    j_start++;
                }
                break;
            }
            if (!repeat_items) {
                // no repeats, never have to look at j > j_start
                break;
            }
        }
    }

    //  Cleanup
    delete [] events;
    return rc;
}
Exemplo n.º 10
0
void test_get_peer_state ()
{
#ifdef ZMQ_BUILD_DRAFT_API
    void *router = test_context_socket (ZMQ_ROUTER);

    int mandatory = 1;
    TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (router, ZMQ_ROUTER_MANDATORY,
                                               &mandatory, sizeof (mandatory)));

    const char *my_endpoint = "inproc://test_get_peer_state";
    TEST_ASSERT_SUCCESS_ERRNO (zmq_bind (router, my_endpoint));

    void *dealer1 = test_context_socket (ZMQ_DEALER);
    void *dealer2 = test_context_socket (ZMQ_DEALER);

    //  Lower HWMs to allow doing the test with fewer messages
    const int hwm = 100;
    TEST_ASSERT_SUCCESS_ERRNO (
      zmq_setsockopt (router, ZMQ_SNDHWM, &hwm, sizeof (int)));
    TEST_ASSERT_SUCCESS_ERRNO (
      zmq_setsockopt (dealer1, ZMQ_RCVHWM, &hwm, sizeof (int)));
    TEST_ASSERT_SUCCESS_ERRNO (
      zmq_setsockopt (dealer2, ZMQ_RCVHWM, &hwm, sizeof (int)));

    const char *dealer1_routing_id = "X";
    const char *dealer2_routing_id = "Y";

    //  Name dealer1 "X" and connect it to our router
    TEST_ASSERT_SUCCESS_ERRNO (
      zmq_setsockopt (dealer1, ZMQ_ROUTING_ID, dealer1_routing_id, 1));
    TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (dealer1, my_endpoint));

    //  Name dealer2 "Y" and connect it to our router
    TEST_ASSERT_SUCCESS_ERRNO (
      zmq_setsockopt (dealer2, ZMQ_ROUTING_ID, dealer2_routing_id, 1));
    TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (dealer2, my_endpoint));

    //  Get message from both dealers to know when connection is ready
    send_string_expect_success (dealer1, "Hello", 0);
    recv_string_expect_success (router, dealer1_routing_id, 0);
    recv_string_expect_success (router, "Hello", 0);

    send_string_expect_success (dealer2, "Hello", 0);
    recv_string_expect_success (router, dealer2_routing_id, 0);
    recv_string_expect_success (router, "Hello", 0);

    void *poller = zmq_poller_new ();
    TEST_ASSERT_NOT_NULL (poller);

    //  Poll on router and dealer1, but not on dealer2
    TEST_ASSERT_SUCCESS_ERRNO (
      zmq_poller_add (poller, router, NULL, ZMQ_POLLOUT));
    TEST_ASSERT_SUCCESS_ERRNO (
      zmq_poller_add (poller, dealer1, NULL, ZMQ_POLLIN));

    const unsigned int count = 10000;
    const unsigned int event_size = 2;
    bool dealer2_blocked = false;
    unsigned int dealer1_sent = 0, dealer2_sent = 0, dealer1_received = 0;
    zmq_poller_event_t events[event_size];
    for (unsigned int iteration = 0; iteration < count; ++iteration) {
        TEST_ASSERT_SUCCESS_ERRNO (
          zmq_poller_wait_all (poller, events, event_size, -1));
        for (unsigned int event_no = 0; event_no < event_size; ++event_no) {
            const zmq_poller_event_t &current_event = events[event_no];
            if (current_event.socket == router
                && current_event.events & ZMQ_POLLOUT) {
                if (send_msg_to_peer_if_ready (router, dealer1_routing_id))
                    ++dealer1_sent;

                if (send_msg_to_peer_if_ready (router, dealer2_routing_id))
                    ++dealer2_sent;
                else
                    dealer2_blocked = true;
            }
            if (current_event.socket == dealer1
                && current_event.events & ZMQ_POLLIN) {
                recv_string_expect_success (dealer1, "Hello", ZMQ_DONTWAIT);
                int more;
                size_t more_size = sizeof (more);
                TEST_ASSERT_SUCCESS_ERRNO (
                  zmq_getsockopt (dealer1, ZMQ_RCVMORE, &more, &more_size));
                TEST_ASSERT_FALSE (more);

                ++dealer1_received;
            }
            // never read from dealer2, so its pipe becomes full eventually
        }
    }
    printf ("dealer1_sent = %u, dealer2_sent = %u, dealer1_received = %u\n",
            dealer1_sent, dealer2_sent, dealer1_received);
    TEST_ASSERT_TRUE (dealer2_blocked);
    zmq_poller_destroy (&poller);

    test_context_socket_close (router);
    test_context_socket_close (dealer1);
    test_context_socket_close (dealer2);
#endif
}