Ejemplo n.º 1
0
void
zpipes_client_destroy (zpipes_client_t **self_p)
{
    assert (self_p);
    if (*self_p) {
        zpipes_client_t *self = *self_p;
        if (self->dealer) {
            zpipes_msg_send_close (self->dealer);
            //  Get reply, ignore it: could be ok or an error depending
            //  on what the client did before.
            zpipes_msg_t *reply = zpipes_msg_recv (self->dealer);
            zpipes_msg_destroy (&reply);
        }
        zsock_destroy (&self->dealer);
        free (self);
        *self_p = NULL;
    }
}
Ejemplo n.º 2
0
void
zpipes_server_test (bool verbose)
{
    printf (" * zpipes_server: \n");
    if (verbose)
        printf ("\n");

    //  @selftest
    //  Prepare test cases
    const char *endpoint = "ipc://@/zpipes/local";
    zactor_t *server = zactor_new (zpipes_server, NULL);
    if (verbose)
        zstr_send (server, "VERBOSE");
    zstr_sendx (server, "BIND", endpoint, NULL);

    zsock_t *writer = zsock_new_dealer (endpoint);
    assert (writer);
    zsock_t *writer2 = zsock_new_dealer (endpoint);
    assert (writer2);
    zsock_t *reader = zsock_new_dealer (endpoint);
    assert (reader);
    zsock_t *reader2 = zsock_new_dealer (endpoint);
    assert (reader2);
    
    zchunk_t *chunk = zchunk_new ("Hello, World", 12);
    int32_t timeout = 100;
    
    //  --------------------------------------------------------------------
    //  Basic tests

    //  Open writer on pipe
    zpipes_msg_send_output (writer, "test pipe");
    if (s_expect_reply (writer, ZPIPES_MSG_OUTPUT_OK))
        assert (false);

    //  Write will timeout if there's no reader
    zpipes_msg_send_write (writer, chunk, timeout);
    if (s_expect_reply (writer, ZPIPES_MSG_WRITE_TIMEOUT))
        assert (false);

    //  Now open reader on pipe
    zpipes_msg_send_input (reader, "test pipe");
    if (s_expect_reply (reader, ZPIPES_MSG_INPUT_OK))
        assert (false);

    //  Read will timeout if there's no data
    zpipes_msg_send_read (reader, 12, timeout);
    if (s_expect_reply (reader, ZPIPES_MSG_READ_TIMEOUT))
        assert (false);

    //  Write should now be successful
    zpipes_msg_send_write (writer, chunk, 0);
    if (s_expect_reply (writer, ZPIPES_MSG_WRITE_OK))
        assert (false);

    //  Read should now be successful
    zpipes_msg_send_read (reader, 12, 0);
    if (s_expect_reply (reader, ZPIPES_MSG_READ_OK))
        assert (false);

    //  Zero read request returns "end of pipe"
    zpipes_msg_send_read (reader, 0, 0);
    if (s_expect_reply (reader, ZPIPES_MSG_READ_END))
        assert (false);

    //  Close writer
    zpipes_msg_send_close (writer);
    if (s_expect_reply (writer, ZPIPES_MSG_CLOSE_OK))
        assert (false);

    //  Any read request returns "end of pipe"
    zpipes_msg_send_read (reader, 12, timeout);
    if (s_expect_reply (reader, ZPIPES_MSG_READ_END))
        assert (false);

    //  Close reader
    zpipes_msg_send_close (reader);
    if (s_expect_reply (reader, ZPIPES_MSG_CLOSE_OK))
        assert (false);

    //  --------------------------------------------------------------------
    //  Test pipelining (request queuing & filtering)

    //  Open reader on pipe
    zpipes_msg_send_input (reader, "test pipe");
    if (s_expect_reply (reader, ZPIPES_MSG_INPUT_OK))
        assert (false);

    //  Open writer on pipe
    zpipes_msg_send_output (writer, "test pipe");
    if (s_expect_reply (writer, ZPIPES_MSG_OUTPUT_OK))
        assert (false);

    //  Pipeline three read requests
    zpipes_msg_send_read (reader, 12, timeout);
    zpipes_msg_send_read (reader, 12, timeout);
    zpipes_msg_send_read (reader, 12, timeout);

    //  First read will return with a timeout
    if (s_expect_reply (reader, ZPIPES_MSG_READ_TIMEOUT))
        assert (false);

    //  Write chunk to pipe
    zpipes_msg_send_write (writer, chunk, 0);
    if (s_expect_reply (writer, ZPIPES_MSG_WRITE_OK))
        assert (false);

    //  Second read will succeed
    if (s_expect_reply (reader, ZPIPES_MSG_READ_OK))
        assert (false);

    //  Send PING, expect PING-OK back
    zpipes_msg_send_ping (reader);
    if (s_expect_reply (reader, ZPIPES_MSG_PING_OK))
        assert (false);

    //  Close writer
    zpipes_msg_send_close (writer);
    if (s_expect_reply (writer, ZPIPES_MSG_CLOSE_OK))
        assert (false);

    //  Third read will report end of pipe
    if (s_expect_reply (reader, ZPIPES_MSG_READ_END))
        assert (false);

    //  Close reader
    zpipes_msg_send_close (reader);
    if (s_expect_reply (reader, ZPIPES_MSG_CLOSE_OK))
        assert (false);

    //  Read now fails as pipe is closed
    zpipes_msg_send_read (reader, 12, timeout);
    if (s_expect_reply (reader, ZPIPES_MSG_INVALID))
        assert (false);

    //  Closing an already closed pipe is an error
    zpipes_msg_send_close (reader);
    if (s_expect_reply (reader, ZPIPES_MSG_INVALID))
        assert (false);

    //  --------------------------------------------------------------------
    //  Test read/close pipelining

    //  Open reader on pipe
    zpipes_msg_send_input (reader, "test pipe");
    if (s_expect_reply (reader, ZPIPES_MSG_INPUT_OK))
        assert (false);

    //  Open writer on pipe
    zpipes_msg_send_output (writer, "test pipe");
    if (s_expect_reply (writer, ZPIPES_MSG_OUTPUT_OK))
        assert (false);

    //  Pipeline two read requests
    zpipes_msg_send_read (reader, 12, timeout);
    zpipes_msg_send_read (reader, 12, timeout);

    //  Send PING, expect PING-OK back
    zpipes_msg_send_ping (reader);
    if (s_expect_reply (reader, ZPIPES_MSG_PING_OK))
        assert (false);

    //  Close reader
    zpipes_msg_send_close (reader);
    
    //  First read now fails
    if (s_expect_reply (reader, ZPIPES_MSG_READ_FAILED))
        assert (false);
    
    if (s_expect_reply (reader, ZPIPES_MSG_CLOSE_OK))
        assert (false);

    //  Second read is now invalid
    if (s_expect_reply (reader, ZPIPES_MSG_INVALID))
        assert (false);
    
    //  Close writer
    zpipes_msg_send_close (writer);
    if (s_expect_reply (writer, ZPIPES_MSG_CLOSE_OK))
        assert (false);

    //  --------------------------------------------------------------------
    //  Test reads and writes of different sizes

    //  Open reader on pipe
    zpipes_msg_send_input (reader, "test pipe");
    if (s_expect_reply (reader, ZPIPES_MSG_INPUT_OK))
        assert (false);

    //  Open writer on pipe
    zpipes_msg_send_output (writer, "test pipe");
    if (s_expect_reply (writer, ZPIPES_MSG_OUTPUT_OK))
        assert (false);

    //  Write chunk to pipe
    zpipes_msg_send_write (writer, chunk, 0);
    if (s_expect_reply (writer, ZPIPES_MSG_WRITE_OK))
        assert (false);

    //  Close writer
    zpipes_msg_send_close (writer);
    if (s_expect_reply (writer, ZPIPES_MSG_CLOSE_OK))
        assert (false);

    //  Read back in several steps
    zpipes_msg_send_read (reader, 1, 0);
    if (s_expect_reply (reader, ZPIPES_MSG_READ_OK))
        assert (false);
    zpipes_msg_send_read (reader, 2, 0);
    if (s_expect_reply (reader, ZPIPES_MSG_READ_OK))
        assert (false);
    zpipes_msg_send_read (reader, 3, 0);
    if (s_expect_reply (reader, ZPIPES_MSG_READ_OK))
        assert (false);
    zpipes_msg_send_read (reader, 3, 0);
    if (s_expect_reply (reader, ZPIPES_MSG_READ_OK))
        assert (false);
    
    //  We get a short read (3 bytes)
    zpipes_msg_send_read (reader, 100, 0);
    if (s_expect_reply (reader, ZPIPES_MSG_READ_OK))
        assert (false);
    
    //  Pipe is now empty
    zpipes_msg_send_read (reader, 100, 0);
    if (s_expect_reply (reader, ZPIPES_MSG_READ_END))
        assert (false);
    
    //  Close reader
    zpipes_msg_send_close (reader);
    if (s_expect_reply (reader, ZPIPES_MSG_CLOSE_OK))
        assert (false);

    //  --------------------------------------------------------------------
    //  Test connection expiry

    //  Set connection timeout to 200 msecs
    zstr_sendx (server, "SET", "server/timeout", "200", NULL);

    //  Open reader on pipe
    zpipes_msg_send_input (reader, "test pipe");
    if (s_expect_reply (reader, ZPIPES_MSG_INPUT_OK))
        assert (false);

    //  Read will expire, we don't expect any response for this command
    zpipes_msg_send_read (reader, 12, 0);

    //  Do nothing for long enough for the timeout to hit
    zclock_sleep (300);

    //  Try again, server should now treat the client as disconnected
    zpipes_msg_send_read (reader, 12, 0);
    if (s_expect_reply (reader, ZPIPES_MSG_INVALID))
        assert (false);

    //  Now check that disconnection erases pipe contents

    //  Open reader on pipe
    zpipes_msg_send_input (reader, "test pipe");
    if (s_expect_reply (reader, ZPIPES_MSG_INPUT_OK))
        assert (false);

    //  Open writer on pipe
    zpipes_msg_send_output (writer, "test pipe");
    if (s_expect_reply (writer, ZPIPES_MSG_OUTPUT_OK))
        assert (false);

    //  Write chunk to pipe
    zpipes_msg_send_write (writer, chunk, 0);
    if (s_expect_reply (writer, ZPIPES_MSG_WRITE_OK))
        assert (false);

    //  Do nothing for long enough for the timeout to hit
    //  Both writer and reader should be disconnected
    zclock_sleep (300);

    //  Open reader on pipe
    zpipes_msg_send_input (reader, "test pipe");
    if (s_expect_reply (reader, ZPIPES_MSG_INPUT_OK))
        assert (false);

    //  Open writer on pipe
    zpipes_msg_send_output (writer, "test pipe");
    if (s_expect_reply (writer, ZPIPES_MSG_OUTPUT_OK))
        assert (false);

    //  This read should timeout, as pipe is empty
    zpipes_msg_send_read (reader, 12, timeout);
    if (s_expect_reply (reader, ZPIPES_MSG_READ_TIMEOUT))
        assert (false);

    //  Close writer
    zpipes_msg_send_close (writer);
    if (s_expect_reply (writer, ZPIPES_MSG_CLOSE_OK))
        assert (false);

    //  Close reader
    zpipes_msg_send_close (reader);
    if (s_expect_reply (reader, ZPIPES_MSG_CLOSE_OK))
        assert (false);
    
    //  --------------------------------------------------------------------
    //  Test writer closing while reader still active

    //  Open writer on pipe
    zpipes_msg_send_output (writer, "test pipe");
    if (s_expect_reply (writer, ZPIPES_MSG_OUTPUT_OK))
        assert (false);

    //  Open reader on pipe
    zpipes_msg_send_input (reader, "test pipe");
    if (s_expect_reply (reader, ZPIPES_MSG_INPUT_OK))
        assert (false);

    //  Write one chunk to pipe
    zpipes_msg_send_write (writer, chunk, 0);
    if (s_expect_reply (writer, ZPIPES_MSG_WRITE_OK))
        assert (false);

    //  Close writer, before reader has read data
    zpipes_msg_send_close (writer);
    if (s_expect_reply (writer, ZPIPES_MSG_CLOSE_OK))
        assert (false);

    //  Open writer on same pipe name
    zpipes_msg_send_output (writer, "test pipe");
    if (s_expect_reply (writer, ZPIPES_MSG_OUTPUT_OK))
        assert (false);

    //  Read should still be successful
    zpipes_msg_send_read (reader, 12, 0);
    if (s_expect_reply (reader, ZPIPES_MSG_READ_OK))
        assert (false);

    //  Create second reader and open pipe for input
    zpipes_msg_send_input (reader2, "test pipe");
    if (s_expect_reply (reader2, ZPIPES_MSG_INPUT_OK))
        assert (false);

    //  Write one chunk to pipe, will go to second instance
    zpipes_msg_send_write (writer, chunk, 0);
    if (s_expect_reply (writer, ZPIPES_MSG_WRITE_OK))
        assert (false);

    //  Pipe is terminated and empty
    zpipes_msg_send_read (reader, 0, 0);
    if (s_expect_reply (reader, ZPIPES_MSG_READ_END))
        assert (false);

    //  Reader2 should be successful
    zpipes_msg_send_read (reader2, 12, 0);
    if (s_expect_reply (reader2, ZPIPES_MSG_READ_OK))
        assert (false);

    //  Close reader 
    zpipes_msg_send_close (reader);
    if (s_expect_reply (reader, ZPIPES_MSG_CLOSE_OK))
        assert (false);

    //  Close writer
    zpipes_msg_send_close (writer);
    if (s_expect_reply (writer, ZPIPES_MSG_CLOSE_OK))
        assert (false);
    
    //  Pipe is terminated and empty
    zpipes_msg_send_read (reader2, 0, 0);
    if (s_expect_reply (reader2, ZPIPES_MSG_READ_END))
        assert (false);

    //  Do that again to be sure it wasn't a coincidence :)
    zpipes_msg_send_read (reader2, 0, 0);
    if (s_expect_reply (reader2, ZPIPES_MSG_READ_END))
        assert (false);

    //  Close reader2
    zpipes_msg_send_close (reader2);
    if (s_expect_reply (reader2, ZPIPES_MSG_CLOSE_OK))
        assert (false);

    //  --------------------------------------------------------------------
    //  Test reader closing while writer still active

    //  Open writer on pipe
    zpipes_msg_send_output (writer, "test pipe");
    if (s_expect_reply (writer, ZPIPES_MSG_OUTPUT_OK))
        assert (false);

    //  Open reader on pipe
    zpipes_msg_send_input (reader, "test pipe");
    if (s_expect_reply (reader, ZPIPES_MSG_INPUT_OK))
        assert (false);

    //  Write one chunk to pipe
    zpipes_msg_send_write (writer, chunk, 0);
    if (s_expect_reply (writer, ZPIPES_MSG_WRITE_OK))
        assert (false);

    //  Read should be successful
    zpipes_msg_send_read (reader, 12, 0);
    if (s_expect_reply (reader, ZPIPES_MSG_READ_OK))
        assert (false);

    //  Close reader
    zpipes_msg_send_close (reader);
    if (s_expect_reply (reader, ZPIPES_MSG_CLOSE_OK))
        assert (false);

    //  Write should fail
    zpipes_msg_send_write (writer, chunk, 0);
    if (s_expect_reply (writer, ZPIPES_MSG_WRITE_FAILED))
        assert (false);

    //  Close writer
    zpipes_msg_send_close (writer);
    if (s_expect_reply (writer, ZPIPES_MSG_CLOSE_OK))
        assert (false);

    //  --------------------------------------------------------------------
    //  Two readers or writers on same pipe are not allowed

    //  Open writer on pipe
    zpipes_msg_send_output (writer, "test pipe");
    if (s_expect_reply (writer, ZPIPES_MSG_OUTPUT_OK))
        assert (false);

    //  Open second writer on pipe
    zpipes_msg_send_output (writer2, "test pipe");
    if (s_expect_reply (writer2, ZPIPES_MSG_OUTPUT_FAILED))
        assert (false);

    //  Open reader on pipe
    zpipes_msg_send_input (reader, "test pipe");
    if (s_expect_reply (reader, ZPIPES_MSG_INPUT_OK))
        assert (false);

    //  Open second reader on pipe
    zpipes_msg_send_input (reader2, "test pipe");
    if (s_expect_reply (reader2, ZPIPES_MSG_INPUT_FAILED))
        assert (false);

    //  Close reader
    zpipes_msg_send_close (reader);
    if (s_expect_reply (reader, ZPIPES_MSG_CLOSE_OK))
        assert (false);

    //  Close writer
    zpipes_msg_send_close (writer);
    if (s_expect_reply (writer, ZPIPES_MSG_CLOSE_OK))
        assert (false);
    
    //  --------------------------------------------------------------------
    //  Test short read when writer closes

    //  Open writer on pipe
    zpipes_msg_send_output (writer, "test pipe");
    if (s_expect_reply (writer, ZPIPES_MSG_OUTPUT_OK))
        assert (false);

    //  Open reader on pipe
    zpipes_msg_send_input (reader, "test pipe");
    if (s_expect_reply (reader, ZPIPES_MSG_INPUT_OK))
        assert (false);

    //  Write one chunk to pipe
    zpipes_msg_send_write (writer, chunk, 0);
    if (s_expect_reply (writer, ZPIPES_MSG_WRITE_OK))
        assert (false);

    //  Try to read large amount of data, will block
    zpipes_msg_send_read (reader, 1000, 0);
    
    //  Close writer
    zpipes_msg_send_close (writer);
    if (s_expect_reply (writer, ZPIPES_MSG_CLOSE_OK))
        assert (false);

    //  Reader should now return short read
    if (s_expect_reply (reader, ZPIPES_MSG_READ_OK))
        assert (false);

    //  Pipe is terminated and empty
    zpipes_msg_send_read (reader, 0, 0);
    if (s_expect_reply (reader, ZPIPES_MSG_READ_END))
        assert (false);

    //  Close reader
    zpipes_msg_send_close (reader);
    if (s_expect_reply (reader, ZPIPES_MSG_CLOSE_OK))
        assert (false);

    //  --------------------------------------------------------------------
    zchunk_destroy (&chunk);
    zactor_destroy (&server);
    zsock_destroy (&reader);
    zsock_destroy (&writer);
    zsock_destroy (&reader2);
    zsock_destroy (&writer2);
    //  @end

    printf ("OK\n");
}