add a crude test_tcp, fix some tcp_server bugs, add missing service_destroy function
authorTero Marttila <terom@fixme.fi>
Thu, 07 May 2009 18:48:38 +0300
changeset 185 259b5841a0e6
parent 184 2ab01ab33cfa
child 186 33ef336dbb4b
add a crude test_tcp, fix some tcp_server bugs, add missing service_destroy function
src/service.c
src/tcp_server.c
src/test/tcp.c
src/test/test_list.inc
--- a/src/service.c	Thu May 07 18:11:50 2009 +0300
+++ b/src/service.c	Thu May 07 18:48:38 2009 +0300
@@ -23,3 +23,13 @@
     // just call the user callback
     service->info.cb_tbl->on_error(service, err, service->info.cb_arg);
 }
+
+void service_destroy (service_t *service)
+{
+    const struct service_type *type = object_type(&service->base_obj, &service_type_type);
+
+    // invoke method
+    type->methods.deinit(service);
+
+    free(service); 
+}
--- a/src/tcp_server.c	Thu May 07 18:11:50 2009 +0300
+++ b/src/tcp_server.c	Thu May 07 18:48:38 2009 +0300
@@ -19,7 +19,7 @@
  */
 const struct service_type tcp_server_type = {
     .base_type = {
-        .parent = NULL,
+        .parent = &service_type_type,
     },
     .methods = {
         .deinit = tcp_server__deinit,
@@ -99,7 +99,7 @@
     evutil_socket_t sock;
 
     // create the sock
-    if ((sock = tcp_sock_create(addr, err)))
+    if ((sock = tcp_sock_create(addr, err)) < 0)
         goto error;
 
     // bind it
@@ -245,6 +245,8 @@
     // ok
     *service_ptr = &serv->base_service;
 
+    return SUCCESS;
+
 error:
     tcp_server_destroy(serv);
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/test/tcp.c	Thu May 07 18:48:38 2009 +0300
@@ -0,0 +1,191 @@
+/*
+ * Test interoperability of tcp_client/tcp_server
+ */
+#include "../tcp.h"
+#include "test.h"
+
+struct test_tcp_ctx {
+    service_t *service;
+    bool on_service_error;
+    bool on_client_connect;
+    bool on_service_client_error;
+
+    transport_t *service_client, *client;
+
+    char data;
+
+    bool eof;
+};
+
+static void on_service_error (service_t *service, const error_t *err, void *arg)
+{
+    struct test_tcp_ctx *ctx = arg;
+
+    log_debug("%s", error_msg(err));
+
+    assert(service == ctx->service);
+    assert(!ctx->on_service_error);
+   
+    ctx->on_service_error = true;
+}
+
+static void on_service_client_connect (transport_t *transport, void *arg)
+{
+    struct test_tcp_ctx *ctx = arg;
+
+    log_debug("%p", transport);
+
+    assert(!ctx->service_client);
+
+    ctx->service_client = transport;
+}
+
+static void on_service_client_read (transport_t *transport, void *arg)
+{
+    struct test_tcp_ctx *ctx = arg;
+    char byte;
+    int ret;
+    error_t err;
+
+    log_debug("%p", transport);
+
+    assert(ctx->service_client == transport);
+
+    if ((ret = transport_read(transport, &byte, sizeof(byte), &err)) == 1) {
+        assert(byte == ctx->data);
+
+        ctx->data = 0;
+
+    } else if (ERROR_CODE(&err) == ERR_EOF) {
+        assert(ctx->eof);
+
+        ctx->eof = false;
+
+    } else {
+        FATAL_ERROR(&err, "xxx");
+    }
+}
+
+static void on_service_client_error (transport_t *transport, const error_t *err, void *arg)
+{
+    struct test_tcp_ctx *ctx = arg;
+
+    log_debug("%p: %s", transport, error_msg(err));
+    
+    assert(ctx->service_client = transport);
+
+    ctx->on_service_client_error = true;
+}
+
+static void on_client_connect (transport_t *transport, void *arg)
+{
+    struct test_tcp_ctx *ctx = arg;
+
+    log_debug("%p", transport);
+
+    assert(transport == ctx->client);
+
+    ctx->on_client_connect = true;
+}
+
+static void on_client_read (transport_t *transport, void *arg)
+{
+    struct test_tcp_ctx *ctx = arg;
+    char byte;
+    int ret;
+    error_t err;
+
+    log_debug("%p", transport);
+
+    assert(transport == ctx->client);
+
+    if ((ret = transport_read(transport, &byte, sizeof(byte), &err)) == 1) {
+        assert(byte == ctx->data);
+
+        ctx->data = 0;
+
+    } else if (ERROR_CODE(&err) == ERR_EOF) {
+        assert(ctx->eof);
+        
+        ctx->eof = false;
+
+    } else {
+        FATAL_ERROR(&err, "xxx");
+    }
+}
+
+static void on_client_error (transport_t *transport, const error_t *err, void *arg)
+{
+    struct test_tcp_ctx *ctx = arg;
+
+    log_debug("%p", transport);
+
+    assert(transport == ctx->client);
+
+    // XXX
+}
+
+static struct service_callbacks test_tcp_service_callbacks = {
+    .on_error   = on_service_error,
+};
+
+static struct transport_callbacks test_tcp_service_transport_callbacks = {
+    .on_connect = on_service_client_connect,
+    .on_read    = on_service_client_read,
+    .on_write   = NULL,
+    .on_error   = on_service_client_error,
+};
+
+static struct transport_callbacks test_tcp_client_callbacks = {
+    .on_connect = on_client_connect,
+    .on_read    = on_client_read,
+    .on_error   = on_client_error,
+};
+
+void test_tcp (void)
+{
+    struct test_tcp_ctx ctx; memset(&ctx, 0, sizeof(ctx));
+    struct service_info serv_info = { 
+        &test_tcp_service_callbacks, &ctx, 
+        { &test_tcp_service_transport_callbacks, &ctx, TRANSPORT_READ } 
+    };
+    struct transport_info client_info = {
+        &test_tcp_client_callbacks, &ctx, TRANSPORT_READ
+    };
+    struct event_base *ev_base = _test_ctx.ev_base;
+    error_t err;
+    
+    // create the service
+    assert_success(tcp_listen(&serv_info, &ctx.service, "localhost", "3232", &err));
+    
+    // connect client -> server
+    assert_success(tcp_connect(&client_info, &ctx.client, "localhost", "3232", &err));
+    event_base_loop(ev_base, EVLOOP_ONCE);
+    assert(ctx.service_client);
+    assert(ctx.on_client_connect);
+
+    // send client -> server
+    ctx.data = 'A';
+
+    assert(transport_write(ctx.client, &ctx.data, sizeof(ctx.data), &err) == 1);
+    event_base_loop(ev_base, EVLOOP_ONCE);
+    assert(!ctx.data);
+    
+    // send server -> client
+    ctx.data = 'B';
+
+    assert(transport_write(ctx.service_client, &ctx.data, sizeof(ctx.data), &err) == 1);
+    event_base_loop(ev_base, EVLOOP_ONCE);
+    assert(!ctx.data);
+    
+    // close client-side connection
+    ctx.eof = true;
+    transport_destroy(ctx.client);
+    event_base_loop(ev_base, EVLOOP_ONCE);
+    assert(ctx.on_service_client_error || !ctx.eof);
+
+    // cleanup
+    transport_destroy(ctx.service_client);
+    service_destroy(ctx.service);
+}
+
--- a/src/test/test_list.inc	Thu May 07 18:11:50 2009 +0300
+++ b/src/test/test_list.inc	Thu May 07 18:48:38 2009 +0300
@@ -31,6 +31,8 @@
 
 TEST ( transport_test               )
 
+TEST ( tcp                          )
+
 TEST ( line_proto                   )
 
 TEST ( irc_queue                    )