From 99ab0b58b4a20473670b442981eeed417dde1582 Mon Sep 17 00:00:00 2001 From: Lakshminarayana Gurram <38289425+lakshminarayanagurram@users.noreply.github.com> Date: Tue, 16 Apr 2019 12:09:35 +0530 Subject: [PATCH] Add condition check in auto connect for blacklisted nodes * Add condition check in auto connect for blacklisted nodes * Add test vector to test autoconnect --- src/net.c | 7 +- test/blackbox/run_blackbox_tests/Makefile.am | 3 +- .../run_blackbox_tests/run_blackbox_tests.c | 6 +- .../test_cases_autoconnect.c | 158 ++++++++++++++++++ .../test_cases_autoconnect.h | 28 ++++ test/trio.c | 4 +- test/utils.c | 11 +- test/utils.h | 1 + 8 files changed, 210 insertions(+), 8 deletions(-) create mode 100644 test/blackbox/run_blackbox_tests/test_cases_autoconnect.c create mode 100644 test/blackbox/run_blackbox_tests/test_cases_autoconnect.h diff --git a/src/net.c b/src/net.c index 9d5e8171..2a27350b 100644 --- a/src/net.c +++ b/src/net.c @@ -404,7 +404,7 @@ static void periodic_handler(event_loop_t *loop, void *data) { for splay_each(node_t, n, mesh->nodes) { logger(mesh, MESHLINK_DEBUG, "* n->devclass = %d", n->devclass); - if(n != mesh->self && n->devclass <= mesh->devclass && !n->connection && (n->last_connect_try == 0 || (time(NULL) - n->last_connect_try) > retry_timeout)) { + if(n != mesh->self && n->devclass <= mesh->devclass && !n->connection && !n->status.blacklisted && (n->last_connect_try == 0 || (time(NULL) - n->last_connect_try) > retry_timeout)) { splay_insert(nodes, n); } } @@ -438,7 +438,7 @@ static void periodic_handler(event_loop_t *loop, void *data) { splay_tree_t *nodes = splay_alloc_tree(node_compare_lsc_desc, NULL); for splay_each(node_t, n, mesh->nodes) { - if(n != mesh->self && n->devclass == devclass && !n->connection && (n->last_connect_try == 0 || (time(NULL) - n->last_connect_try) > retry_timeout)) { + if(n != mesh->self && n->devclass == devclass && !n->connection && !n->status.blacklisted && (n->last_connect_try == 0 || (time(NULL) - n->last_connect_try) > retry_timeout)) { splay_insert(nodes, n); } } @@ -469,7 +469,7 @@ static void periodic_handler(event_loop_t *loop, void *data) { splay_tree_t *nodes = splay_alloc_tree(node_compare_devclass_asc_lsc_desc, NULL); for splay_each(node_t, n, mesh->nodes) { - if(n != mesh->self && n->devclass <= mesh->devclass && !n->status.reachable && (n->last_connect_try == 0 || (time(NULL) - n->last_connect_try) > retry_timeout)) { + if(n != mesh->self && n->devclass <= mesh->devclass && !n->status.reachable && !n->status.blacklisted && (n->last_connect_try == 0 || (time(NULL) - n->last_connect_try) > retry_timeout)) { splay_insert(nodes, n); } } @@ -489,6 +489,7 @@ static void periodic_handler(event_loop_t *loop, void *data) { if(connect_to && !connect_to->connection) { connect_to->last_connect_try = time(NULL); + logger(mesh, MESHLINK_DEBUG, "Autoconnect trying to connect to %s", connect_to->name); /* check if there is already a connection attempt to this node */ bool found = false; diff --git a/test/blackbox/run_blackbox_tests/Makefile.am b/test/blackbox/run_blackbox_tests/Makefile.am index 00aa9b89..0fa653b1 100644 --- a/test/blackbox/run_blackbox_tests/Makefile.am +++ b/test/blackbox/run_blackbox_tests/Makefile.am @@ -60,7 +60,8 @@ run_blackbox_tests_SOURCES = \ test_cases_submesh01.c \ test_cases_submesh02.c \ test_cases_submesh03.c \ - test_cases_submesh04.c + test_cases_submesh04.c \ + test_cases_autoconnect.c run_blackbox_tests_LDADD = ../../../src/libmeshlink.la $(LXC_LIBS) $(CMOCKA_LIBS) run_blackbox_tests_CFLAGS = -D_GNU_SOURCE $(LXC_CFLAGS) $(CMOCKA_CFLAGS) diff --git a/test/blackbox/run_blackbox_tests/run_blackbox_tests.c b/test/blackbox/run_blackbox_tests/run_blackbox_tests.c index df23d5ae..edf0f95d 100644 --- a/test/blackbox/run_blackbox_tests/run_blackbox_tests.c +++ b/test/blackbox/run_blackbox_tests/run_blackbox_tests.c @@ -71,6 +71,8 @@ #include "test_cases_submesh03.h" #include "test_cases_submesh04.h" +#include "test_cases_autoconnect.h" + #include "../common/containers.h" #include "../common/common_handlers.h" @@ -133,11 +135,13 @@ int main(int argc, char *argv[]) { failed_tests += test_meshlink_channel_conn(); failed_tests += test_optimal_pmtu(); - */ + failed_tests += test_cases_submesh01(); failed_tests += test_cases_submesh02(); failed_tests += test_cases_submesh03(); failed_tests += test_cases_submesh04(); + */ + failed_tests += test_meshlink_autoconnect(); failed_tests += test_optimal_pmtu(); diff --git a/test/blackbox/run_blackbox_tests/test_cases_autoconnect.c b/test/blackbox/run_blackbox_tests/test_cases_autoconnect.c new file mode 100644 index 00000000..18991279 --- /dev/null +++ b/test/blackbox/run_blackbox_tests/test_cases_autoconnect.c @@ -0,0 +1,158 @@ +/* + test_cases_blacklist.c -- Execution of specific meshlink black box test cases + Copyright (C) 2018 Guus Sliepen + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +/* Modify this to change the logging level of Meshlink */ +#define TEST_MESHLINK_LOG_LEVEL MESHLINK_DEBUG + +#include "execute_tests.h" +#include "test_cases_autoconnect.h" +#include +#include "../common/test_step.h" +#include "../common/common_handlers.h" +#include "../../utils.h" +#include +#include +#include +#include +#include +#include + +static void test_case_autoconnect(void **state); +static bool test_steps_mesh_autoconnect(void); +static meshlink_handle_t *mesh1, *mesh2; + +/* State structure for meshlink_blacklist Test Case #1 */ +static black_box_state_t test_mesh_autoconnect_state = { + .test_case_name = "test_case_mesh_autoconnect", +}; +struct sync_flag test_autoconnect_m1n1_reachable = {.mutex = PTHREAD_MUTEX_INITIALIZER, .cond = PTHREAD_COND_INITIALIZER, .flag = false}; +struct sync_flag test_autoconnect_blacklisted = {.mutex = PTHREAD_MUTEX_INITIALIZER, .cond = PTHREAD_COND_INITIALIZER, .flag = false}; +struct sync_flag test_autoconnect_successful = {.mutex = PTHREAD_MUTEX_INITIALIZER, .cond = PTHREAD_COND_INITIALIZER, .flag = false}; + +/* Execute meshlink_blacklist Test Case # 1*/ +void test_case_autoconnect(void **state) { + execute_test(test_steps_mesh_autoconnect, state); +} + +void callback_logger(meshlink_handle_t *mesh, meshlink_log_level_t level, + const char *text) { + (void)level; + + fprintf(stderr, "%s: {%s}\n", mesh->name, text); + + if((check_sync_flag(&test_autoconnect_blacklisted) == true) && (strcmp("m1n2", mesh->name) == 0) && (strcmp("* could not find node for initial connect", text) == 0)) { + fprintf(stderr, "Test case successful\n"); + set_sync_flag(&test_autoconnect_successful, true); + } else if((check_sync_flag(&test_autoconnect_blacklisted) == true) && (strcmp("m1n2", mesh->name) == 0)) { + assert(strcmp(text, "Autoconnect trying to connect to m1n1") != 0); + } + +} + +static void receive(meshlink_handle_t *mesh, meshlink_node_t *src, const void *data, size_t len) { + (void)mesh; + (void)src; + (void)data; + assert(len); +} + +static bool bar_reachable; + +static void status_cb(meshlink_handle_t *mesh, meshlink_node_t *node, bool reachable) { + (void)mesh; + fprintf(stderr, "Status of node {%s} is %d\n", node->name, reachable); + + if(!strcmp(node->name, "m1n1") && reachable) { + set_sync_flag(&test_autoconnect_m1n1_reachable, true); + } +} + + +/* Test Steps for meshlink_blacklist Test Case # 1 + + Test Steps: + 1. Open both the node instances + 2. Join bar node with foo and Send & Receive data + 3. Blacklist bar and Send & Receive data + + Expected Result: + When default blacklist is disabled, foo node should receive data from bar + but when enabled foo node should not receive data +*/ +bool test_steps_mesh_autoconnect(void) { + char *invite = NULL; + meshlink_node_t *node = NULL; + + meshlink_destroy("m1n1"); + meshlink_destroy("m1n2"); + + // Open two new meshlink instance. + mesh1 = meshlink_open("m1n1", "m1n1", "autoconnect", DEV_CLASS_BACKBONE); + assert(mesh1 != NULL); + meshlink_set_log_cb(mesh1, TEST_MESHLINK_LOG_LEVEL, callback_logger); + + mesh2 = meshlink_open("m1n2", "m1n2", "autoconnect", DEV_CLASS_STATIONARY); + assert(mesh2 != NULL); + meshlink_set_log_cb(mesh2, TEST_MESHLINK_LOG_LEVEL, callback_logger); + meshlink_set_receive_cb(mesh1, receive); + + // Start both instances + meshlink_set_node_status_cb(mesh1, status_cb); + assert(meshlink_start(mesh1)); + + invite = meshlink_invite(mesh1, NULL, "m1n2"); + assert(invite); + + assert(meshlink_join(mesh2, invite)); + + meshlink_set_node_status_cb(mesh2, status_cb); + assert(meshlink_start(mesh2)); + + assert(wait_sync_flag(&test_autoconnect_m1n1_reachable, 30)); + + node = meshlink_get_node(mesh2, "m1n1"); + meshlink_blacklist(mesh2, node); + set_sync_flag(&test_autoconnect_blacklisted, true); + + assert(wait_sync_flag(&test_autoconnect_successful, 60)); + + // Clean up. + meshlink_close(mesh1); + fprintf(stderr, "Meshlink node1 closed\n"); + meshlink_close(mesh2); + fprintf(stderr, "Meshlink node2 closed\n"); + + meshlink_destroy("m1n1"); + meshlink_destroy("m1n2"); + fprintf(stderr, "Meshlink nodes destroyed\n"); + + return true; +} + +int test_meshlink_autoconnect(void) { + const struct CMUnitTest blackbox_blacklist_tests[] = { + cmocka_unit_test_prestate_setup_teardown(test_case_autoconnect, NULL, NULL, + (void *)&test_mesh_autoconnect_state) + }; + + total_tests += sizeof(blackbox_blacklist_tests) / sizeof(blackbox_blacklist_tests[0]); + + return cmocka_run_group_tests(blackbox_blacklist_tests, NULL, NULL); +} + diff --git a/test/blackbox/run_blackbox_tests/test_cases_autoconnect.h b/test/blackbox/run_blackbox_tests/test_cases_autoconnect.h new file mode 100644 index 00000000..10b4911f --- /dev/null +++ b/test/blackbox/run_blackbox_tests/test_cases_autoconnect.h @@ -0,0 +1,28 @@ +#ifndef TEST_CASES_AUTOCONNECT_H +#define TEST_CASES_AUTOCONNECT_H + +/* + test_cases_autoconnect.h -- Declarations for Individual Test Case implementation functions + Copyright (C) 2018 Guus Sliepen + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include + +extern int test_meshlink_autoconnect(void); +extern int total_tests; + +#endif diff --git a/test/trio.c b/test/trio.c index 522020fe..79013a6f 100644 --- a/test/trio.c +++ b/test/trio.c @@ -53,8 +53,8 @@ int main() { for(int i = 0; i < 3; i++) { char *path; - int ret_val; - (void)ret_val; + int ret_val; + (void)ret_val; ret_val = asprintf(&path, "trio_conf.%d", i); assert(path); diff --git a/test/utils.c b/test/utils.c index a2b7b143..9a9bd211 100644 --- a/test/utils.c +++ b/test/utils.c @@ -15,6 +15,14 @@ void set_sync_flag(struct sync_flag *s, bool value) { pthread_mutex_unlock(&s->mutex); } +bool check_sync_flag(struct sync_flag *s) { + bool flag; + pthread_mutex_lock(&s->mutex); + flag = s->flag; + pthread_mutex_unlock(&s->mutex); + return flag; +} + bool wait_sync_flag(struct sync_flag *s, int seconds) { struct timespec timeout; clock_gettime(CLOCK_REALTIME, &timeout); @@ -22,10 +30,11 @@ bool wait_sync_flag(struct sync_flag *s, int seconds) { pthread_mutex_lock(&s->mutex); - while(!s->flag) + while(!s->flag) { if(!pthread_cond_timedwait(&s->cond, &s->mutex, &timeout) || errno != EINTR) { break; } + } pthread_mutex_unlock(&s->mutex); diff --git a/test/utils.h b/test/utils.h index 27bb38c3..a657dffa 100644 --- a/test/utils.h +++ b/test/utils.h @@ -11,6 +11,7 @@ struct sync_flag { }; extern void set_sync_flag(struct sync_flag *s, bool value); +extern bool check_sync_flag(struct sync_flag *s); extern bool wait_sync_flag(struct sync_flag *s, int seconds); /// Create a pair of meshlink instances that are already joined together. -- 2.39.2