Esempio n. 1
0
void test_bind_before_connect ()
{
    // Bind first
    void *bind_socket = test_context_socket (ZMQ_PAIR);
    TEST_ASSERT_SUCCESS_ERRNO (zmq_bind (bind_socket, "inproc://bbc"));

    // Now connect
    void *connect_socket = test_context_socket (ZMQ_PAIR);
    TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (connect_socket, "inproc://bbc"));

    // Queue up some data
    send_string_expect_success (connect_socket, "foobar", 0);

    // Read pending message
    recv_string_expect_success (bind_socket, "foobar", 0);

    // Cleanup
    test_context_socket_close (connect_socket);
    test_context_socket_close (bind_socket);
}
Esempio n. 2
0
static void test_stream_to_dealer ()
{
    int rc;
    char my_endpoint[MAX_SOCKET_STRING];

    //  We'll be using this socket in raw mode
    void *stream = test_context_socket (ZMQ_STREAM);

    int zero = 0;
    TEST_ASSERT_SUCCESS_ERRNO (
      zmq_setsockopt (stream, ZMQ_LINGER, &zero, sizeof (zero)));
    int enabled = 1;
    TEST_ASSERT_SUCCESS_ERRNO (
      zmq_setsockopt (stream, ZMQ_STREAM_NOTIFY, &enabled, sizeof (enabled)));
    bind_loopback_ipv4 (stream, my_endpoint, sizeof my_endpoint);

    //  We'll be using this socket as the other peer
    void *dealer = test_context_socket (ZMQ_DEALER);
    TEST_ASSERT_SUCCESS_ERRNO (
      zmq_setsockopt (dealer, ZMQ_LINGER, &zero, sizeof (zero)));
    TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (dealer, my_endpoint));

    //  Send a message on the dealer socket
    send_string_expect_success (dealer, "Hello", 0);

    //  Connecting sends a zero message
    //  First frame is routing id
    zmq_msg_t routing_id;
    TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_init (&routing_id));
    TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_recv (&routing_id, stream, 0));
    TEST_ASSERT_TRUE (zmq_msg_more (&routing_id));

    //  Verify the existence of Peer-Address metadata
    char const *peer_address = zmq_msg_gets (&routing_id, "Peer-Address");
    TEST_ASSERT_NOT_NULL (peer_address);
    TEST_ASSERT_EQUAL_STRING ("127.0.0.1", peer_address);

    //  Second frame is zero
    byte buffer[255];
    TEST_ASSERT_EQUAL_INT (
      0, TEST_ASSERT_SUCCESS_ERRNO (zmq_recv (stream, buffer, 255, 0)));

    //  Verify the existence of Peer-Address metadata
    peer_address = zmq_msg_gets (&routing_id, "Peer-Address");
    TEST_ASSERT_NOT_NULL (peer_address);
    TEST_ASSERT_EQUAL_STRING ("127.0.0.1", peer_address);

    //  Real data follows
    //  First frame is routing id
    TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_recv (&routing_id, stream, 0));
    TEST_ASSERT_TRUE (zmq_msg_more (&routing_id));

    //  Verify the existence of Peer-Address metadata
    peer_address = zmq_msg_gets (&routing_id, "Peer-Address");
    TEST_ASSERT_NOT_NULL (peer_address);
    TEST_ASSERT_EQUAL_STRING ("127.0.0.1", peer_address);

    //  Second frame is greeting signature
    recv_array_expect_success (stream, greeting.signature, 0);

    //  Send our own protocol greeting
    TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_send (&routing_id, stream, ZMQ_SNDMORE));
    TEST_ASSERT_EQUAL_INT (
      sizeof (greeting), TEST_ASSERT_SUCCESS_ERRNO (
                           zmq_send (stream, &greeting, sizeof (greeting), 0)));

    //  Now we expect the data from the DEALER socket
    //  We want the rest of greeting along with the Ready command
    int bytes_read = 0;
    while (bytes_read < 97) {
        //  First frame is the routing id of the connection (each time)
        TEST_ASSERT_GREATER_THAN_INT (
          0, TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_recv (&routing_id, stream, 0)));
        TEST_ASSERT_TRUE (zmq_msg_more (&routing_id));
        //  Second frame contains the next chunk of data
        TEST_ASSERT_SUCCESS_ERRNO (
          rc = zmq_recv (stream, buffer + bytes_read, 255 - bytes_read, 0));
        bytes_read += rc;
    }

    //  First two bytes are major and minor version numbers.
    TEST_ASSERT_EQUAL_INT (3, buffer[0]); //  ZMTP/3.0
    TEST_ASSERT_EQUAL_INT (0, buffer[1]);

    //  Mechanism is "NULL"
    TEST_ASSERT_EQUAL_INT8_ARRAY (buffer + 2,
                                  "NULL\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 20);
    TEST_ASSERT_EQUAL_INT8_ARRAY (buffer + 54, "\4\51\5READY", 8);
    TEST_ASSERT_EQUAL_INT8_ARRAY (buffer + 62, "\13Socket-Type\0\0\0\6DEALER",
                                  22);
    TEST_ASSERT_EQUAL_INT8_ARRAY (buffer + 84, "\10Identity\0\0\0\0", 13);

    //  Announce we are ready
    memcpy (buffer, "\4\51\5READY", 8);
    memcpy (buffer + 8, "\13Socket-Type\0\0\0\6ROUTER", 22);
    memcpy (buffer + 30, "\10Identity\0\0\0\0", 13);

    //  Send Ready command
    TEST_ASSERT_GREATER_THAN_INT (0, TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_send (
                                       &routing_id, stream, ZMQ_SNDMORE)));
    TEST_ASSERT_EQUAL_INT (
      43, TEST_ASSERT_SUCCESS_ERRNO (zmq_send (stream, buffer, 43, 0)));

    //  Now we expect the data from the DEALER socket
    //  First frame is, again, the routing id of the connection
    TEST_ASSERT_GREATER_THAN_INT (
      0, TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_recv (&routing_id, stream, 0)));
    TEST_ASSERT_TRUE (zmq_msg_more (&routing_id));

    //  Third frame contains Hello message from DEALER
    TEST_ASSERT_EQUAL_INT (7, TEST_ASSERT_SUCCESS_ERRNO (
                                zmq_recv (stream, buffer, sizeof buffer, 0)));

    //  Then we have a 5-byte message "Hello"
    TEST_ASSERT_EQUAL_INT (0, buffer[0]); //  Flags = 0
    TEST_ASSERT_EQUAL_INT (5, buffer[1]); //  Size = 5
    TEST_ASSERT_EQUAL_INT8_ARRAY (buffer + 2, "Hello", 5);

    //  Send "World" back to DEALER
    TEST_ASSERT_GREATER_THAN_INT (0, TEST_ASSERT_SUCCESS_ERRNO (zmq_msg_send (
                                       &routing_id, stream, ZMQ_SNDMORE)));
    byte world[] = {0, 5, 'W', 'o', 'r', 'l', 'd'};
    TEST_ASSERT_EQUAL_INT (
      sizeof (world),
      TEST_ASSERT_SUCCESS_ERRNO (zmq_send (stream, world, sizeof (world), 0)));

    //  Expect response on DEALER socket
    recv_string_expect_success (dealer, "World", 0);

    //  Test large messages over STREAM socket
#define size 64000
    uint8_t msgout[size];
    memset (msgout, 0xAB, size);
    zmq_send (dealer, msgout, size, 0);

    uint8_t msgin[9 + size];
    memset (msgin, 0, 9 + size);
    bytes_read = 0;
    while (bytes_read < 9 + size) {
        //  Get routing id frame
        TEST_ASSERT_GREATER_THAN_INT (
          0, TEST_ASSERT_SUCCESS_ERRNO (zmq_recv (stream, buffer, 256, 0)));
        //  Get next chunk
        TEST_ASSERT_GREATER_THAN_INT (
          0,
          TEST_ASSERT_SUCCESS_ERRNO (rc = zmq_recv (stream, msgin + bytes_read,
                                                    9 + size - bytes_read, 0)));
        bytes_read += rc;
    }
    for (int byte_nbr = 0; byte_nbr < size; byte_nbr++) {
        TEST_ASSERT_EQUAL_UINT8 (0xAB, msgin[9 + byte_nbr]);
    }
    test_context_socket_close (dealer);
    test_context_socket_close (stream);
}
Esempio n. 3
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
}
void test_send_one_connected_one_unconnected_with_delay ()
{
    int val;

    // TEST 2
    // This time we will do the same thing, connect two pipes,
    // one of which will succeed in connecting to a bound
    // receiver, the other of which will fail. However, we will
    // also set the delay attach on connect flag, which should
    // cause the pipe attachment to be delayed until the connection
    // succeeds.

    // Bind the valid socket
    void *to = test_context_socket (ZMQ_PULL);
    TEST_ASSERT_SUCCESS_ERRNO (zmq_bind (to, "tipc://{5560,0,0}"));

    val = 0;
    TEST_ASSERT_SUCCESS_ERRNO (
      zmq_setsockopt (to, ZMQ_LINGER, &val, sizeof (val)));

    // Create a socket pushing to two endpoints - all messages should arrive.
    void *from = test_context_socket (ZMQ_PUSH);

    val = 0;
    TEST_ASSERT_SUCCESS_ERRNO (
      zmq_setsockopt (from, ZMQ_LINGER, &val, sizeof (val)));

    // Set the key flag
    val = 1;
    TEST_ASSERT_SUCCESS_ERRNO (
      zmq_setsockopt (from, ZMQ_DELAY_ATTACH_ON_CONNECT, &val, sizeof (val)));

    // Connect to the invalid socket
    TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (from, "tipc://{5561,0}@0.0.0"));
    // Connect to the valid socket
    TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (from, "tipc://{5560,0}@0.0.0"));

    // Send 10 messages, all should be routed to the connected pipe
    const int send_count = 10;
    for (int i = 0; i < send_count; ++i) {
        send_string_expect_success (from, "Hello", 0);
    }
    int timeout = SETTLE_TIME;
    TEST_ASSERT_SUCCESS_ERRNO (
      zmq_setsockopt (to, ZMQ_RCVTIMEO, &timeout, sizeof (int)));

    int seen = 0;
    while (true) {
        char buffer[16];
        int rc = zmq_recv (to, &buffer, sizeof (buffer), 0);
        if (rc == -1) {
            TEST_ASSERT_EQUAL_INT (EAGAIN, zmq_errno ());
            break; //  Break when we didn't get a message
        }
        seen++;
    }
    TEST_ASSERT_EQUAL_INT (send_count, seen);

    test_context_socket_close (from);
    test_context_socket_close (to);
}
Esempio n. 5
0
void test_router_2_router (bool named_)
{
    char buff[256];
    const char msg[] = "hi 1";
    const int zero = 0;
    char my_endpoint[MAX_SOCKET_STRING];

    //  Create bind socket.
    void *rbind = test_context_socket (ZMQ_ROUTER);
    TEST_ASSERT_SUCCESS_ERRNO (
      zmq_setsockopt (rbind, ZMQ_LINGER, &zero, sizeof (zero)));
    bind_loopback_ipv4 (rbind, my_endpoint, sizeof my_endpoint);

    //  Create connection socket.
    void *rconn1 = test_context_socket (ZMQ_ROUTER);
    TEST_ASSERT_SUCCESS_ERRNO (
      zmq_setsockopt (rconn1, ZMQ_LINGER, &zero, sizeof (zero)));

    //  If we're in named mode, set some identities.
    if (named_) {
        TEST_ASSERT_SUCCESS_ERRNO (
          zmq_setsockopt (rbind, ZMQ_ROUTING_ID, x_routing_id, 1));
        TEST_ASSERT_SUCCESS_ERRNO (
          zmq_setsockopt (rconn1, ZMQ_ROUTING_ID, y_routing_id, 1));
    }

    //  Make call to connect using a connect_routing_id.
    TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (rconn1, ZMQ_CONNECT_ROUTING_ID,
                                               rconn1routing_id,
                                               strlen (rconn1routing_id)));
    TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (rconn1, my_endpoint));
    /*  Uncomment to test assert on duplicate routing id
    //  Test duplicate connect attempt.
    TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (rconn1, ZMQ_CONNECT_ROUTING_ID, rconn1routing_id, strlen (rconn1routing_id)));
    TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (rconn1, bindip));
*/
    //  Send some data.

    send_string_expect_success (rconn1, rconn1routing_id, ZMQ_SNDMORE);
    send_string_expect_success (rconn1, msg, 0);

    //  Receive the name.
    const int routing_id_len = zmq_recv (rbind, buff, 256, 0);
    if (named_) {
        TEST_ASSERT_EQUAL_INT (strlen (y_routing_id), routing_id_len);
        TEST_ASSERT_EQUAL_STRING_LEN (y_routing_id, buff, routing_id_len);
    } else {
        TEST_ASSERT_TRUE (routing_id_len && 0 == buff[0]);
    }

    //  Receive the data.
    recv_string_expect_success (rbind, msg, 0);

    //  Send some data back.
    const int ret = zmq_send (rbind, buff, routing_id_len, ZMQ_SNDMORE);
    TEST_ASSERT_EQUAL_INT (routing_id_len, ret);
    send_string_expect_success (rbind, "ok", 0);

    //  If bound socket identity naming a problem, we'll likely see something funky here.
    recv_string_expect_success (rconn1, rconn1routing_id, 0);
    recv_string_expect_success (rconn1, "ok", 0);

    TEST_ASSERT_SUCCESS_ERRNO (zmq_unbind (rbind, my_endpoint));
    test_context_socket_close (rbind);
    test_context_socket_close (rconn1);
}
Esempio n. 6
0
void test_router_2_router_while_receiving ()
{
    char buff[256];
    const char msg[] = "hi 1";
    const int zero = 0;
    char x_endpoint[MAX_SOCKET_STRING];
    char z_endpoint[MAX_SOCKET_STRING];

    //  Create xbind socket.
    void *xbind = test_context_socket (ZMQ_ROUTER);
    TEST_ASSERT_SUCCESS_ERRNO (
      zmq_setsockopt (xbind, ZMQ_LINGER, &zero, sizeof (zero)));
    bind_loopback_ipv4 (xbind, x_endpoint, sizeof x_endpoint);

    //  Create zbind socket.
    void *zbind = test_context_socket (ZMQ_ROUTER);
    TEST_ASSERT_SUCCESS_ERRNO (
      zmq_setsockopt (zbind, ZMQ_LINGER, &zero, sizeof (zero)));
    bind_loopback_ipv4 (zbind, z_endpoint, sizeof z_endpoint);

    //  Create connection socket.
    void *yconn = test_context_socket (ZMQ_ROUTER);
    TEST_ASSERT_SUCCESS_ERRNO (
      zmq_setsockopt (yconn, ZMQ_LINGER, &zero, sizeof (zero)));

    // set identities for each socket
    TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (
      xbind, ZMQ_ROUTING_ID, x_routing_id, strlen (x_routing_id)));
    TEST_ASSERT_SUCCESS_ERRNO (
      zmq_setsockopt (yconn, ZMQ_ROUTING_ID, y_routing_id, 2));
    TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (
      zbind, ZMQ_ROUTING_ID, z_routing_id, strlen (z_routing_id)));

    //  Connect Y to X using a routing id
    TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (
      yconn, ZMQ_CONNECT_ROUTING_ID, x_routing_id, strlen (x_routing_id)));
    TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (yconn, x_endpoint));

    //  Send some data from Y to X.
    send_string_expect_success (yconn, x_routing_id, ZMQ_SNDMORE);
    send_string_expect_success (yconn, msg, 0);

    // wait for the Y->X message to be received
    msleep (SETTLE_TIME);

    // Now X tries to connect to Z and send a message
    TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (
      xbind, ZMQ_CONNECT_ROUTING_ID, z_routing_id, strlen (z_routing_id)));
    TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (xbind, z_endpoint));

    //  Try to send some data from X to Z.
    send_string_expect_success (xbind, z_routing_id, ZMQ_SNDMORE);
    send_string_expect_success (xbind, msg, 0);

    // wait for the X->Z message to be received (so that our non-blocking check will actually
    // fail if the message is routed to Y)
    msleep (SETTLE_TIME);

    // nothing should have been received on the Y socket
    TEST_ASSERT_FAILURE_ERRNO (EAGAIN,
                               zmq_recv (yconn, buff, 256, ZMQ_DONTWAIT));

    // the message should have been received on the Z socket
    recv_string_expect_success (zbind, x_routing_id, 0);
    recv_string_expect_success (zbind, msg, 0);

    TEST_ASSERT_SUCCESS_ERRNO (zmq_unbind (xbind, x_endpoint));
    TEST_ASSERT_SUCCESS_ERRNO (zmq_unbind (zbind, z_endpoint));

    test_context_socket_close (yconn);
    test_context_socket_close (xbind);
    test_context_socket_close (zbind);
}
Esempio n. 7
0
int test_blocking (int send_hwm_, int msg_cnt_, const char *endpoint)
{
    size_t len = SOCKET_STRING_LEN;
    char pub_endpoint[SOCKET_STRING_LEN];

    // Set up bind socket
    void *pub_socket = test_context_socket (ZMQ_XPUB);
    TEST_ASSERT_SUCCESS_ERRNO (zmq_bind (pub_socket, endpoint));
    TEST_ASSERT_SUCCESS_ERRNO (
      zmq_getsockopt (pub_socket, ZMQ_LAST_ENDPOINT, pub_endpoint, &len));

    // Set up connect socket
    void *sub_socket = test_context_socket (ZMQ_SUB);
    TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (sub_socket, pub_endpoint));

    //set a hwm on publisher
    TEST_ASSERT_SUCCESS_ERRNO (
      zmq_setsockopt (pub_socket, ZMQ_SNDHWM, &send_hwm_, sizeof (send_hwm_)));
    int wait = 1;
    TEST_ASSERT_SUCCESS_ERRNO (
      zmq_setsockopt (pub_socket, ZMQ_XPUB_NODROP, &wait, sizeof (wait)));
    int timeout_ms = 10;
    TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (
      sub_socket, ZMQ_RCVTIMEO, &timeout_ms, sizeof (timeout_ms)));
    TEST_ASSERT_SUCCESS_ERRNO (
      zmq_setsockopt (sub_socket, ZMQ_SUBSCRIBE, 0, 0));

    // Wait before starting TX operations till 1 subscriber has subscribed
    // (in this test there's 1 subscriber only)
    const char subscription_to_all_topics[] = {1, 0};
    recv_string_expect_success (pub_socket, subscription_to_all_topics, 0);

    // Send until we block
    int send_count = 0;
    int recv_count = 0;
    int blocked_count = 0;
    int is_termination = 0;
    while (send_count < msg_cnt_) {
        const int rc = zmq_send (pub_socket, NULL, 0, ZMQ_DONTWAIT);
        if (rc == 0) {
            ++send_count;
        } else if (-1 == rc) {
            // if the PUB socket blocks due to HWM, errno should be EAGAIN:
            blocked_count++;
            TEST_ASSERT_EQUAL_INT (EAGAIN, errno);
            recv_count += receive (sub_socket, &is_termination);
        }
    }

    // if send_hwm_ < msg_cnt_, we should block at least once:
    TEST_ASSERT (blocked_count > 0);

    // dequeue SUB socket again, to make sure XPUB has space to send the termination message
    recv_count += receive (sub_socket, &is_termination);

    // send termination message
    send_string_expect_success (pub_socket, "end", 0);

    // now block on the SUB side till we get the termination message
    while (is_termination == 0)
        recv_count += receive (sub_socket, &is_termination);

    // remove termination message from the count:
    recv_count--;

    TEST_ASSERT_EQUAL_INT (send_count, recv_count);

    // Clean up
    test_context_socket_close (sub_socket);
    test_context_socket_close (pub_socket);

    return recv_count;
}
Esempio n. 8
0
void test_xpub_verboser_two_subs ()
{
    void *pub, *sub0, *sub1;
    create_xpub_with_2_subs (&pub, &sub0, &sub1);
    create_duplicate_subscription (pub, sub0, sub1);

    //  Unsubscribe for A, this time it exists in XPUB
    TEST_ASSERT_SUCCESS_ERRNO (
      zmq_setsockopt (sub0, ZMQ_UNSUBSCRIBE, topic_a, 1));

    //  sub1 is still subscribed, so no notification
    TEST_ASSERT_FAILURE_ERRNO (EAGAIN, zmq_recv (pub, NULL, 0, ZMQ_DONTWAIT));

    //  Unsubscribe the second socket to trigger the notification
    TEST_ASSERT_SUCCESS_ERRNO (
      zmq_setsockopt (sub1, ZMQ_UNSUBSCRIBE, topic_a, 1));

    // Receive unsubscriptions since all sockets are gone
    recv_array_expect_success (pub, unsubscribe_a_msg, 0);

    //  Make really sure there is only one notification
    TEST_ASSERT_FAILURE_ERRNO (EAGAIN, zmq_recv (pub, NULL, 0, ZMQ_DONTWAIT));

    int verbose = 1;
    TEST_ASSERT_SUCCESS_ERRNO (
      zmq_setsockopt (pub, ZMQ_XPUB_VERBOSER, &verbose, sizeof (int)));

    // Subscribe socket for A again
    TEST_ASSERT_SUCCESS_ERRNO (
      zmq_setsockopt (sub0, ZMQ_SUBSCRIBE, topic_a, 1));

    // Subscribe socket for A again
    TEST_ASSERT_SUCCESS_ERRNO (
      zmq_setsockopt (sub1, ZMQ_SUBSCRIBE, topic_a, 1));

    // Receive subscriptions from subscriber, did not exist anymore
    recv_array_expect_success (pub, subscribe_a_msg, 0);

    //  VERBOSER is set, so subs from both sockets are received
    recv_array_expect_success (pub, subscribe_a_msg, 0);

    // Sending A message to make sure everything still works
    send_string_expect_success (pub, topic_a, 0);

    recv_string_expect_success (sub0, topic_a, 0);
    recv_string_expect_success (sub1, topic_a, 0);

    //  Unsubscribe for A
    TEST_ASSERT_SUCCESS_ERRNO (
      zmq_setsockopt (sub1, ZMQ_UNSUBSCRIBE, topic_a, 1));

    // Receive unsubscriptions from first subscriber due to VERBOSER
    recv_array_expect_success (pub, unsubscribe_a_msg, 0);

    //  Unsubscribe for A again from the other socket
    TEST_ASSERT_SUCCESS_ERRNO (
      zmq_setsockopt (sub0, ZMQ_UNSUBSCRIBE, topic_a, 1));

    // Receive unsubscriptions from first subscriber due to VERBOSER
    recv_array_expect_success (pub, unsubscribe_a_msg, 0);

    //  Unsubscribe again to make sure it gets filtered now
    TEST_ASSERT_SUCCESS_ERRNO (
      zmq_setsockopt (sub1, ZMQ_UNSUBSCRIBE, topic_a, 1));

    //  Unmatched, so XSUB filters even with VERBOSER
    TEST_ASSERT_FAILURE_ERRNO (EAGAIN, zmq_recv (pub, NULL, 0, ZMQ_DONTWAIT));

    //  Clean up.
    test_context_socket_close (pub);
    test_context_socket_close (sub0);
    test_context_socket_close (sub1);
}
Esempio n. 9
0
void test_xpub_verboser_one_sub ()
{
    //  Create a publisher
    void *pub = test_context_socket (ZMQ_XPUB);
    TEST_ASSERT_SUCCESS_ERRNO (zmq_bind (pub, test_endpoint));

    //  Create a subscriber
    void *sub = test_context_socket (ZMQ_SUB);
    TEST_ASSERT_SUCCESS_ERRNO (zmq_connect (sub, test_endpoint));

    //  Unsubscribe for A, does not exist yet
    TEST_ASSERT_SUCCESS_ERRNO (
      zmq_setsockopt (sub, ZMQ_UNSUBSCRIBE, topic_a, 1));

    //  Does not exist, so it will be filtered out by XSUB
    TEST_ASSERT_FAILURE_ERRNO (EAGAIN, zmq_recv (pub, NULL, 0, ZMQ_DONTWAIT));

    //  Subscribe for A
    TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (sub, ZMQ_SUBSCRIBE, topic_a, 1));

    // Receive subscriptions from subscriber
    recv_array_expect_success (pub, subscribe_a_msg, 0);

    //  Subscribe again for A again, XSUB will increase refcount
    TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (sub, ZMQ_SUBSCRIBE, topic_a, 1));

    //  This time it is duplicated, so it will be filtered out by XPUB
    TEST_ASSERT_FAILURE_ERRNO (EAGAIN, zmq_recv (pub, NULL, 0, ZMQ_DONTWAIT));

    //  Unsubscribe for A, this time it exists in XPUB
    TEST_ASSERT_SUCCESS_ERRNO (
      zmq_setsockopt (sub, ZMQ_UNSUBSCRIBE, topic_a, 1));

    //  XSUB refcounts and will not actually send unsub to PUB until the number
    //  of unsubs match the earlier subs
    TEST_ASSERT_SUCCESS_ERRNO (
      zmq_setsockopt (sub, ZMQ_UNSUBSCRIBE, topic_a, 1));

    // Receive unsubscriptions from subscriber
    recv_array_expect_success (pub, unsubscribe_a_msg, 0);

    //  XSUB only sends the last and final unsub, so XPUB will only receive 1
    TEST_ASSERT_FAILURE_ERRNO (EAGAIN, zmq_recv (pub, NULL, 0, ZMQ_DONTWAIT));

    //  Unsubscribe for A, does not exist anymore
    TEST_ASSERT_SUCCESS_ERRNO (
      zmq_setsockopt (sub, ZMQ_UNSUBSCRIBE, topic_a, 1));

    //  Does not exist, so it will be filtered out by XSUB
    TEST_ASSERT_FAILURE_ERRNO (EAGAIN, zmq_recv (pub, NULL, 0, ZMQ_DONTWAIT));

    int verbose = 1;
    TEST_ASSERT_SUCCESS_ERRNO (
      zmq_setsockopt (pub, ZMQ_XPUB_VERBOSER, &verbose, sizeof (int)));

    // Subscribe socket for A again
    TEST_ASSERT_SUCCESS_ERRNO (zmq_setsockopt (sub, ZMQ_SUBSCRIBE, topic_a, 1));

    // Receive subscriptions from subscriber, did not exist anymore
    recv_array_expect_success (pub, subscribe_a_msg, 0);

    // Sending A message to make sure everything still works
    send_string_expect_success (pub, topic_a, 0);

    recv_string_expect_success (sub, topic_a, 0);

    //  Unsubscribe for A, this time it exists
    TEST_ASSERT_SUCCESS_ERRNO (
      zmq_setsockopt (sub, ZMQ_UNSUBSCRIBE, topic_a, 1));

    // Receive unsubscriptions from subscriber
    recv_array_expect_success (pub, unsubscribe_a_msg, 0);

    //  Unsubscribe for A again, it does not exist anymore so XSUB will filter
    TEST_ASSERT_SUCCESS_ERRNO (
      zmq_setsockopt (sub, ZMQ_UNSUBSCRIBE, topic_a, 1));

    //  XSUB only sends unsub if it matched it in its trie, IOW: it will only
    //  send it if it existed in the first place even with XPUB_VERBBOSER
    TEST_ASSERT_FAILURE_ERRNO (EAGAIN, zmq_recv (pub, NULL, 0, ZMQ_DONTWAIT));

    //  Clean up.
    test_context_socket_close (pub);
    test_context_socket_close (sub);
}