From 8fde91038538d01aaa5b36ebb06b516a8c313364 Mon Sep 17 00:00:00 2001 From: Guus Sliepen Date: Mon, 14 Aug 2017 21:19:41 +0200 Subject: [PATCH] Add a test for a constellation of three nodes. In particular, test whether two nodes that have been introduced to each other via a third node can still continue to communicate with each other when the third node goes offline. --- test/Makefile.am | 5 ++ test/trio.c | 118 +++++++++++++++++++++++++++++++++++++++++++++++ test/trio.test | 4 ++ test/utils.h | 11 ++++- 4 files changed, 137 insertions(+), 1 deletion(-) create mode 100644 test/trio.c create mode 100755 test/trio.test diff --git a/test/Makefile.am b/test/Makefile.am index 5f8921c9..c9a66024 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -1,6 +1,7 @@ TESTS = \ basic.test \ basicpp.test \ + trio.test \ channels.test \ channels-fork.test \ channels-cornercases.test \ @@ -15,6 +16,7 @@ AM_CPPFLAGS = -I../src check_PROGRAMS = \ basic \ basicpp \ + trio \ channels \ channels-fork \ channels-cornercases \ @@ -29,6 +31,9 @@ basic_LDADD = ../src/libmeshlink.la basicpp_SOURCES = basicpp.cpp basicpp_LDADD = ../src/libmeshlink.la +trio_SOURCES = trio.c +trio_LDADD = ../src/libmeshlink.la + channels_SOURCES = channels.cpp channels_LDADD = ../src/libmeshlink.la diff --git a/test/trio.c b/test/trio.c new file mode 100644 index 00000000..0a494c28 --- /dev/null +++ b/test/trio.c @@ -0,0 +1,118 @@ +#define _GNU_SOURCE + +#include +#include +#include +#include +#include + +#include "meshlink.h" +#include "utils.h" + +static 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); +} + +static bool received = false; + +static void receive_cb(meshlink_handle_t *mesh, meshlink_node_t *source, const void *data, size_t len) { + fprintf(stderr, "RECEIVED SOMETHING\n"); + if(len == 5 && !memcmp(data, "Hello", 5)) + received = true; +} + +int main(int argc, char *argv[]) { + // Create three instances. + + const char *name[3] = {"foo", "bar", "baz"}; + meshlink_handle_t *mesh[3]; + char *data[3]; + + for(int i = 0; i < 3; i++) { + char *path; + asprintf(&path, "trio_conf.%d", i); + assert(path); + + mesh[i] = meshlink_open(path, name[i], "trio", DEV_CLASS_BACKBONE); + assert(mesh[i]); + + data[i] = meshlink_export(mesh[i]); + assert(data[i]); + } + + // first node knows the two other nodes + + for(int i = 1; i < 3; i++) { + assert(meshlink_import(mesh[i], data[0])); + assert(meshlink_import(mesh[0], data[i])); + + assert(meshlink_get_node(mesh[i], name[0])); + assert(meshlink_get_node(mesh[0], name[i])); + } + + // second and third node should not know each other yet + + assert(!meshlink_get_node(mesh[1], name[2])); + assert(!meshlink_get_node(mesh[2], name[1])); + + // start the nodes + + for(int i = 0; i < 3; i++) + meshlink_start(mesh[i]); + + // the nodes should now learn about each other + + assert_after(meshlink_get_node(mesh[1], name[2]), 5); + assert_after(meshlink_get_node(mesh[2], name[1]), 5); + + // Send a packet + + meshlink_set_receive_cb(mesh[1], receive_cb); + assert_after((meshlink_send(mesh[2], meshlink_get_node(mesh[2], name[1]), "Hello", 5), received), 15); + + // Stop the first node + + meshlink_stop(mesh[0]); + sleep(1); + + // Communication should still be possible + + assert_after((meshlink_send(mesh[2], meshlink_get_node(mesh[2], name[1]), "Hello", 5), received), 15); + + // Stop the other nodes + + for(int i = 1; i < 3; i++) + meshlink_stop(mesh[i]); + + sleep(1); + + // Start just the other two nodes + + meshlink_set_log_cb(mesh[1], MESHLINK_DEBUG, log_cb); + + for(int i = 1; i < 3; i++) + meshlink_start(mesh[i]); + + assert(meshlink_get_node(mesh[1], name[2])); + assert(meshlink_get_node(mesh[2], name[1])); + + // Communication should still be possible + + received = false; + assert_after((meshlink_send(mesh[2], meshlink_get_node(mesh[2], name[1]), "Hello", 5), received), 25); + + // Clean up. + + for(int i = 0; i < 3; i++) + meshlink_close(mesh[i]); +} diff --git a/test/trio.test b/test/trio.test new file mode 100755 index 00000000..f0639fd4 --- /dev/null +++ b/test/trio.test @@ -0,0 +1,4 @@ +#!/bin/sh + +rm -Rf trio_conf.* +./trio diff --git a/test/utils.h b/test/utils.h index e1073df8..488721dd 100644 --- a/test/utils.h +++ b/test/utils.h @@ -25,5 +25,14 @@ extern void stop_meshlink_pair(meshlink_handle_t *a, meshlink_handle_t *b); /// Stop and cleanup a pair of meshlink instances. extern void close_meshlink_pair(meshlink_handle_t *a, meshlink_handle_t *b, const char *prefix); -#endif +#define assert_after(cond, timeout) do {\ + for(int i = 0; i++ <= timeout;) {\ + if(cond)\ + break;\ + if(i == timeout)\ + assert(cond);\ + sleep(1);\ + }\ +} while(0); +#endif -- 2.39.5