test_immediate.cpp 6.78 KB
Newer Older
1
/*
2
    Copyright (c) 2007-2014 Contributors as noted in the AUTHORS file
3
    
4 5 6 7 8 9 10 11 12 13 14 15 16 17
    This file is part of 0MQ.

    0MQ is free software; you can redistribute it and/or modify it under
    the terms of the GNU Lesser General Public License as published by
    the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.

    0MQ is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
18 19
*/

20
#include "testutil.hpp"
21

22
int main (void)
23
{
24
    setup_test_environment();
25 26 27
    int val;
    int rc;
    char buffer[16];
28 29 30 31 32 33 34
    // TEST 1. 
    // First we're going to attempt to send messages to two
    // pipes, one connected, the other not. We should see
    // the PUSH load balancing to both pipes, and hence half
    // of the messages getting queued, as connect() creates a
    // pipe immediately. 
    
35 36 37 38 39
    void *context = zmq_ctx_new();
    assert (context);
    void *to = zmq_socket(context, ZMQ_PULL);
    assert (to);

40
    // Bind the one valid receiver
41 42 43
    val = 0;
    rc = zmq_setsockopt(to, ZMQ_LINGER, &val, sizeof(val));
    assert (rc == 0);
44
    rc = zmq_bind (to, "tcp://127.0.0.1:6555");
45 46 47 48 49 50 51
    assert (rc == 0);

    // Create a socket pushing to two endpoints - only 1 message should arrive.
    void *from = zmq_socket (context, ZMQ_PUSH);
    assert(from);

    val = 0;
52
    zmq_setsockopt (from, ZMQ_LINGER, &val, sizeof (val));
53
    // This pipe will not connect
54 55
    rc = zmq_connect (from, "tcp://localhost:5556");
    assert (rc == 0);
56
    // This pipe will 
57
    rc = zmq_connect (from, "tcp://localhost:6555");
58 59
    assert (rc == 0);

60 61
    // We send 10 messages, 5 should just get stuck in the queue
    // for the not-yet-connected pipe
62 63 64
    for (int i = 0; i < 10; ++i) {
        rc = zmq_send (from, "Hello", 5, 0);
        assert (rc == 5);
65 66
    }

67 68
    // We now consume from the connected pipe
    // - we should see just 5
69 70 71 72 73 74 75 76 77
    int timeout = 100;
    rc = zmq_setsockopt (to, ZMQ_RCVTIMEO, &timeout, sizeof (int));
    assert (rc == 0);

    int seen = 0;
    while (true) {
        rc = zmq_recv (to, &buffer, sizeof (buffer), 0);
        if (rc == -1)
            break;          //  Break when we didn't get a message
78 79 80 81 82 83 84 85 86 87
        seen++;
    }
    assert (seen == 5);

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

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

Pieter Hintjens's avatar
Pieter Hintjens committed
88
    rc = zmq_ctx_term (context);
89 90
    assert (rc == 0);

91 92 93 94 95 96 97
    // 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. 
98 99
    context = zmq_ctx_new();

100
    // Bind the valid socket
101 102
    to = zmq_socket (context, ZMQ_PULL);
    assert (to);
103
    rc = zmq_bind (to, "tcp://127.0.0.1:5560");
104 105 106 107 108 109 110 111 112 113 114 115 116 117
    assert (rc == 0);

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

    // Create a socket pushing to two endpoints - all messages should arrive.
    from = zmq_socket (context, ZMQ_PUSH);
    assert (from);

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

118
    // Set the key flag
119
    val = 1;
120
    rc = zmq_setsockopt (from, ZMQ_IMMEDIATE, &val, sizeof(val));
121 122
    assert (rc == 0);

123
    // Connect to the invalid socket
124 125
    rc = zmq_connect (from, "tcp://localhost:5561");
    assert (rc == 0);
126
    // Connect to the valid socket
127 128 129
    rc = zmq_connect (from, "tcp://localhost:5560");
    assert (rc == 0);

130
    // Send 10 messages, all should be routed to the connected pipe
131 132 133
    for (int i = 0; i < 10; ++i) {
        rc = zmq_send (from, "Hello", 5, 0);
        assert (rc == 5);
134
    }
135 136 137
    rc = zmq_setsockopt (to, ZMQ_RCVTIMEO, &timeout, sizeof (int));
    assert (rc == 0);
    
138
    seen = 0;
139 140 141 142 143
    while (true) {
        rc = zmq_recv (to, &buffer, sizeof (buffer), 0);
        if (rc == -1)
            break;          //  Break when we didn't get a message
        seen++;
144
    }
145
    assert (seen == 10);
146 147 148 149 150 151 152

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

    rc = zmq_close (to);
    assert (rc == 0);
    
Pieter Hintjens's avatar
Pieter Hintjens committed
153
    rc = zmq_ctx_term (context);
154 155
    assert (rc == 0);

156 157 158
    // TEST 3
    // This time we want to validate that the same blocking behaviour
    // occurs with an existing connection that is broken. We will send
159
    // messages to a connected pipe, disconnect and verify the messages
160
    // block. Then we reconnect and verify messages flow again.
161
    context = zmq_ctx_new ();
162

163 164 165 166 167 168
    void *backend = zmq_socket (context, ZMQ_DEALER);
    assert (backend);
    void *frontend = zmq_socket (context, ZMQ_DEALER);
    assert (frontend);
    int zero = 0;
    rc = zmq_setsockopt (backend, ZMQ_LINGER, &zero, sizeof (zero));
169
    assert (rc == 0);
170
    rc = zmq_setsockopt (frontend, ZMQ_LINGER, &zero, sizeof (zero));
171 172
    assert (rc == 0);

173
    //  Frontend connects to backend using IMMEDIATE
174
    int on = 1;
175
    rc = zmq_setsockopt (frontend, ZMQ_IMMEDIATE, &on, sizeof (on));
176
    assert (rc == 0);
177
    rc = zmq_bind (backend, "tcp://127.0.0.1:5560");
178
    assert (rc == 0);
179
    rc = zmq_connect (frontend, "tcp://localhost:5560");
180
    assert (rc == 0);
181 182 183 184 185 186

    //  Ping backend to frontend so we know when the connection is up
    rc = zmq_send (backend, "Hello", 5, 0);
    assert (rc == 5);
    rc = zmq_recv (frontend, buffer, 255, 0);
    assert (rc == 5);
187
    
188 189 190
    // Send message from frontend to backend
    rc = zmq_send (frontend, "Hello", 5, ZMQ_DONTWAIT);
    assert (rc == 5);
191
    
192
    rc = zmq_close (backend);
193
    assert (rc == 0);
194

195
    //  Give time to process disconnect
196
    msleep (SETTLE_TIME * 10);
197 198
    
    // Send a message, should fail
199
    rc = zmq_send (frontend, "Hello", 5, ZMQ_DONTWAIT);
200
    assert (rc == -1);
201

202 203 204 205
    //  Recreate backend socket
    backend = zmq_socket (context, ZMQ_DEALER);
    assert (backend);
    rc = zmq_setsockopt (backend, ZMQ_LINGER, &zero, sizeof (zero));
206
    assert (rc == 0);
207
    rc = zmq_bind (backend, "tcp://127.0.0.1:5560");
208 209 210 211 212 213 214 215
    assert (rc == 0);

    //  Ping backend to frontend so we know when the connection is up
    rc = zmq_send (backend, "Hello", 5, 0);
    assert (rc == 5);
    rc = zmq_recv (frontend, buffer, 255, 0);
    assert (rc == 5);

216
    // After the reconnect, should succeed
217 218
    rc = zmq_send (frontend, "Hello", 5, ZMQ_DONTWAIT);
    assert (rc == 5);
219
    
220
    rc = zmq_close (backend);
221 222
    assert (rc == 0);
    
223
    rc = zmq_close (frontend);
224 225
    assert (rc == 0);

Pieter Hintjens's avatar
Pieter Hintjens committed
226
    rc = zmq_ctx_term (context);
227
    assert (rc == 0);
228
}