From e0d320398121de1fb235e800e60069655a9b68da Mon Sep 17 00:00:00 2001 From: Guus Sliepen Date: Sun, 13 Aug 2017 23:08:56 +0200 Subject: [PATCH] Test cornercases of MeshLink channels. - Ensure we can open a channel before starting MeshLink. - Check that opening channels to a peer that has unregistered its accept callback will not result in the poll callback to be called with a non- zero length. --- test/Makefile.am | 15 +++- test/channels-cornercases.c | 145 +++++++++++++++++++++++++++++++++ test/channels-cornercases.test | 4 + 3 files changed, 163 insertions(+), 1 deletion(-) create mode 100644 test/channels-cornercases.c create mode 100755 test/channels-cornercases.test diff --git a/test/Makefile.am b/test/Makefile.am index 630f5d7d..5f8921c9 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -3,6 +3,7 @@ TESTS = \ basicpp.test \ channels.test \ channels-fork.test \ + channels-cornercases.test \ import-export.test \ invite-join.test \ sign-verify.test @@ -11,7 +12,16 @@ dist_check_SCRIPTS = $(TESTS) AM_CPPFLAGS = -I../src -check_PROGRAMS = basic basicpp channels channels-fork import-export invite-join sign-verify echo-fork +check_PROGRAMS = \ + basic \ + basicpp \ + channels \ + channels-fork \ + channels-cornercases \ + import-export \ + invite-join \ + sign-verify \ + echo-fork basic_SOURCES = basic.c basic_LDADD = ../src/libmeshlink.la @@ -25,6 +35,9 @@ channels_LDADD = ../src/libmeshlink.la channels_fork_SOURCES = channels-fork.cpp channels_fork_LDADD = ../src/libmeshlink.la +channels_cornercases_SOURCES = channels-cornercases.cpp utils.cpp utils.h +channels_cornercases_LDADD = ../src/libmeshlink.la + echo_fork_SOURCES = echo-fork.c echo_fork_LDADD = ../src/libmeshlink.la diff --git a/test/channels-cornercases.c b/test/channels-cornercases.c new file mode 100644 index 00000000..e76f735f --- /dev/null +++ b/test/channels-cornercases.c @@ -0,0 +1,145 @@ +#define _GNU_SOURCE + +#include +#include +#include +#include +#include +#include +#include + +#include "../src/meshlink.h" +#include "utils.h" + +volatile bool b_responded = false; +volatile bool b_closed = false; +volatile bool a_nonzero_poll_cb = false; + +void log_cb(meshlink_handle_t *mesh, meshlink_log_level_t level, const char *text) { + static struct timeval tv0; + struct timeval tv; + + if(tv0.tv_sec == 0) + gettimeofday(&tv0, NULL); + gettimeofday(&tv, NULL); + fprintf(stderr, "%u.%.03u ", (unsigned int)(tv.tv_sec - tv0.tv_sec), (unsigned int)tv.tv_usec / 1000); + + if(mesh) + fprintf(stderr, "(%s) ", mesh->name); + fprintf(stderr, "[%d] %s\n", level, text); +} + +void a_receive_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, const void *data, size_t len) { + if(len == 5 && !memcmp(data, "Hello", 5)) + b_responded = true; + else if(len == 0) + b_closed = true; +} + +void b_receive_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, const void *data, size_t len) { + // Send one message back, then close the channel. + if(len) + meshlink_channel_send(mesh, channel, data, len); + + meshlink_channel_close(mesh, channel); +} + +bool reject_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, uint16_t port, const void *data, size_t len) { + return false; +} + +bool accept_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, uint16_t port, const void *data, size_t len) { + meshlink_set_channel_accept_cb(mesh, NULL); + meshlink_set_channel_receive_cb(mesh, channel, b_receive_cb); + if(data) + b_receive_cb(mesh, channel, data, len); + return true; +} + +void poll_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, size_t len) { + meshlink_set_channel_poll_cb(mesh, channel, NULL); + set_sync_flag(channel->priv); +} + +void poll_cb2(meshlink_handle_t *mesh, meshlink_channel_t *channel, size_t len) { + if(len) + a_nonzero_poll_cb = true; +} + +int main(int argc, char *argv[]) { + meshlink_handle_t *a, *b; + open_meshlink_pair(&a, &b, "channels-cornercases"); + //meshlink_set_log_cb(a, MESHLINK_DEBUG, log_cb); + //meshlink_set_log_cb(b, MESHLINK_DEBUG, log_cb); + + // Set the callbacks. + + meshlink_set_channel_accept_cb(a, reject_cb); + meshlink_set_channel_accept_cb(b, accept_cb); + + // Open a channel from a to b before starting the mesh. + + meshlink_node_t *nb = meshlink_get_node(a, "b"); + assert(nb); + + struct sync_flag channel_opened = {}; + pthread_mutex_lock(&channel_opened.mutex); + + meshlink_channel_t *channel = meshlink_channel_open(a, nb, 7, a_receive_cb, NULL, 0); + assert(channel); + + channel->priv = &channel_opened; + meshlink_set_channel_poll_cb(a, channel, poll_cb); + + // Start MeshLink and wait for the channel to become connected. + start_meshlink_pair(a, b); + + assert(wait_sync_flag(&channel_opened, 20)); + + // Re-initialize everything + close_meshlink_pair(a, b, "channels-cornercases"); + b_responded = false; + b_closed = false; + channel_opened.flag = false; + open_meshlink_pair(&a, &b, "channels-cornercases"); + + meshlink_set_channel_accept_cb(a, reject_cb); + meshlink_set_channel_accept_cb(b, accept_cb); + + start_meshlink_pair(a, b); + + // Create a channel to b + nb = meshlink_get_node(a, "b"); + assert(nb); + + channel = meshlink_channel_open(a, nb, 7, a_receive_cb, NULL, 0); + assert(channel); + channel->priv = &channel_opened; + meshlink_set_channel_poll_cb(a, channel, poll_cb); + + assert(wait_sync_flag(&channel_opened, 20)); + + assert(!b_responded); + assert(!b_closed); + + // Send a message to b + + meshlink_channel_send(a, channel, "Hello", 5); + + sleep(1); + + assert(b_responded); + assert(b_closed); + + // Try to create a second channel + + meshlink_channel_t *channel2 = meshlink_channel_open(a, nb, 7, a_receive_cb, NULL, 0); + assert(channel2); + meshlink_set_channel_poll_cb(a, channel2, poll_cb2); + + sleep(1); + + assert(!a_nonzero_poll_cb); + + return 0; +} diff --git a/test/channels-cornercases.test b/test/channels-cornercases.test new file mode 100755 index 00000000..c2ea1adc --- /dev/null +++ b/test/channels-cornercases.test @@ -0,0 +1,4 @@ +#!/bin/sh + +rm -Rf channels-cornercases_conf.* +./channels-cornercases -- 2.39.5