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); }
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); }
void test_wait_corner_cases (void) { void *poller = zmq_poller_new (); assert (poller != NULL); zmq_poller_event_t event; int rc = zmq_poller_wait(poller, &event, 0); assert (rc == -1 && errno == EAGAIN); // this can never return since no socket was registered, and should yield an error rc = zmq_poller_wait(poller, &event, -1); assert (rc == -1 && errno == EFAULT); rc = zmq_poller_wait_all (poller, &event, -1, 0); assert (rc == -1 && errno == EINVAL); rc = zmq_poller_wait_all (poller, &event, 0, 0); assert (rc == -1 && errno == EAGAIN); // this can never return since no socket was registered, and should yield an error rc = zmq_poller_wait_all (poller, &event, 0, -1); assert (rc == -1 && errno == EFAULT); rc = zmq_poller_destroy (&poller); assert (rc == 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); }
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)); }
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); }
void zpoller_destroy (zpoller_t **self_p) { assert (self_p); if (*self_p) { zpoller_t *self = *self_p; #ifdef ZMQ_HAVE_POLLER zmq_poller_destroy (&self->zmq_poller); #else zlist_destroy (&self->reader_list); freen (self->poll_readers); freen (self->poll_set); #endif freen (self); *self_p = NULL; } }
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; }
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; }
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 ¤t_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 }
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; events = new zmq_poller_event_t[nitems_]; alloc_assert(events); void *poller = zmq_poller_new (); alloc_assert(poller); 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) { zmq_poller_destroy (&poller); 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) { zmq_poller_destroy (&poller); delete [] events; return rc; } } } // Wait for events rc = zmq_poller_wait_all (poller, events, nitems_, timeout_); if (rc < 0) { zmq_poller_destroy (&poller); 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 || items_[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 zmq_poller_destroy (&poller); delete [] events; return rc; }