From 9033d75df3c0f23711eb4edff186c856cdd4f249 Mon Sep 17 00:00:00 2001 From: Guus Sliepen Date: Fri, 23 Apr 2021 17:58:19 +0200 Subject: [PATCH] Add a test case for meshlink_channel_abort() in combination with AIO. --- test/Makefile.am | 5 ++ test/channels-aio-abort.c | 125 ++++++++++++++++++++++++++++++++++++++ test/channels.c | 2 +- 3 files changed, 131 insertions(+), 1 deletion(-) create mode 100644 test/channels-aio-abort.c diff --git a/test/Makefile.am b/test/Makefile.am index 0e5c141f..65834bb6 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -4,6 +4,7 @@ TESTS = \ blacklist \ channels \ channels-aio \ + channels-aio-abort \ channels-aio-cornercases \ channels-aio-fd \ channels-buffer-storage \ @@ -46,6 +47,7 @@ check_PROGRAMS = \ blacklist \ channels \ channels-aio \ + channels-aio-abort \ channels-aio-cornercases \ channels-aio-fd \ channels-buffer-storage \ @@ -91,6 +93,9 @@ channels_LDADD = $(top_builddir)/src/libmeshlink.la channels_aio_SOURCES = channels-aio.c utils.c utils.h channels_aio_LDADD = $(top_builddir)/src/libmeshlink.la +channels_aio_abort_SOURCES = channels-aio-abort.c utils.c utils.h +channels_aio_abort_LDADD = $(top_builddir)/src/libmeshlink.la + channels_aio_cornercases_SOURCES = channels-aio-cornercases.c utils.c utils.h channels_aio_cornercases_LDADD = $(top_builddir)/src/libmeshlink.la diff --git a/test/channels-aio-abort.c b/test/channels-aio-abort.c new file mode 100644 index 00000000..19a25667 --- /dev/null +++ b/test/channels-aio-abort.c @@ -0,0 +1,125 @@ +#ifdef NDEBUG +#undef NDEBUG +#endif + +#define _POSIX_C_SOURCE 200809L + +#include +#include +#include +#include +#include +#include + +#include "meshlink.h" +#include "utils.h" + +static const size_t size = 2000000; // size of data to transfer + +struct aio_info { + char *data; + int callbacks; + size_t size; + struct timespec ts; + struct sync_flag flag; +}; + +static void aio_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, const void *data, size_t len, void *priv) { + fprintf(stderr, "%s aio_cb %s %p %zu\n", mesh->name, channel->node->name, data, len); + (void)mesh; + (void)channel; + (void)data; + (void)len; + + struct aio_info *info = priv; + clock_gettime(CLOCK_MONOTONIC, &info->ts); + info->callbacks++; + info->size += len; + set_sync_flag(&info->flag, true); + meshlink_channel_abort(mesh, channel); + free(info->data); +} + +static bool accept_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, uint16_t port, const void *data, size_t len) { + fprintf(stderr, "%s accept %s\n", mesh->name, channel->node->name); + assert(port == 1); + assert(!data); + assert(!len); + + struct aio_info *info = mesh->priv; + + assert(meshlink_channel_aio_receive(mesh, channel, info->data, size / 2, aio_cb, info)); + + return true; +} + +int main(void) { + meshlink_set_log_cb(NULL, MESHLINK_WARNING, log_cb); + + struct aio_info in_info; + struct aio_info out_info; + + memset(&in_info, 0, sizeof(in_info)); + memset(&out_info, 0, sizeof(out_info)); + + init_sync_flag(&in_info.flag); + init_sync_flag(&out_info.flag); + + in_info.data = calloc(1, size / 2); + assert(in_info.data); + out_info.data = calloc(1, size); + assert(out_info.data); + + // Open two new meshlink instance. + + meshlink_handle_t *mesh_a, *mesh_b; + open_meshlink_pair(&mesh_a, &mesh_b, "channels_aio_abort"); + + // Set the callbacks. + + mesh_b->priv = &in_info; + meshlink_set_channel_accept_cb(mesh_b, accept_cb); + + // Start both instances + + start_meshlink_pair(mesh_a, mesh_b); + + // Open channel from a to b. + + meshlink_node_t *b = meshlink_get_node(mesh_a, "b"); + assert(b); + meshlink_channel_t *channel = meshlink_channel_open(mesh_a, b, 1, NULL, NULL, 0); + assert(channel); + + // Send data, receiver aborts halfway + + assert(meshlink_channel_aio_send(mesh_a, channel, out_info.data, size, aio_cb, &out_info)); + + // Wait for everyone to finish. + + assert(wait_sync_flag(&out_info.flag, 10)); + assert(wait_sync_flag(&in_info.flag, 10)); + + // Open a new data, now sender aborts halfway + + init_sync_flag(&in_info.flag); + init_sync_flag(&out_info.flag); + + in_info.data = calloc(1, size / 2); + assert(in_info.data); + out_info.data = calloc(1, size / 4); + assert(out_info.data); + + channel = meshlink_channel_open(mesh_a, b, 1, NULL, NULL, 0); + assert(channel); + assert(meshlink_channel_aio_send(mesh_a, channel, out_info.data, size / 4, aio_cb, &out_info)); + + // Wait for everyone to finish. + + assert(wait_sync_flag(&out_info.flag, 10)); + assert(wait_sync_flag(&in_info.flag, 10)); + + // Clean up. + + close_meshlink_pair(mesh_a, mesh_b); +} diff --git a/test/channels.c b/test/channels.c index bc26ee59..f8946d46 100644 --- a/test/channels.c +++ b/test/channels.c @@ -94,7 +94,7 @@ int main(void) { meshlink_set_channel_poll_cb(mesh_a, channel, poll_cb); assert(wait_sync_flag(&b_responded, 20)); - meshlink_channel_close(mesh_a, channel); + meshlink_channel_abort(mesh_a, channel); // Clean up. -- 2.39.2