From: Lakshminarayana Gurram <38289425+lakshminarayanagurram@users.noreply.github.com> Date: Tue, 5 Mar 2019 12:19:48 +0000 (+0530) Subject: Add blackbox test cases for submesh X-Git-Url: https://git.meshlink.io/?a=commitdiff_plain;h=4108810af455f463dfbcdac0e2e0b2ba0312bf26;p=meshlink Add blackbox test cases for submesh --- diff --git a/configure.ac b/configure.ac index 2309d358..c1baec17 100644 --- a/configure.ac +++ b/configure.ac @@ -167,6 +167,10 @@ AC_CONFIG_FILES([ test/blackbox/test_case_meta_conn_03/Makefile test/blackbox/test_case_meta_conn_04/Makefile test/blackbox/test_case_meta_conn_05/Makefile + test/blackbox/test_cases_submesh01/Makefile + test/blackbox/test_cases_submesh02/Makefile + test/blackbox/test_cases_submesh03/Makefile + test/blackbox/test_cases_submesh04/Makefile examples/Makefile ]) diff --git a/test/blackbox/Makefile.am b/test/blackbox/Makefile.am index 5f1c6430..df5792bd 100644 --- a/test/blackbox/Makefile.am +++ b/test/blackbox/Makefile.am @@ -13,7 +13,12 @@ SUBDIRS = \ test_case_meta_conn_02 \ test_case_meta_conn_03 \ test_case_meta_conn_04 \ - test_case_meta_conn_05 + test_case_meta_conn_05 \ + test_cases_submesh01 \ + test_cases_submesh02 \ + test_cases_submesh03 \ + test_cases_submesh04 + gen_invite_SOURCES = util/gen_invite.c common/common_handlers.c common/test_step.c common/mesh_event_handler.c gen_invite_LDADD = ../../src/libmeshlink.la diff --git a/test/blackbox/common/containers.c b/test/blackbox/common/containers.c index 6d27151c..99cdbdfe 100644 --- a/test/blackbox/common/containers.c +++ b/test/blackbox/common/containers.c @@ -70,7 +70,7 @@ void rename_container(const char *old_name, const char *new_name) { } char *run_in_container(const char *cmd, const char *container_name, bool daemonize) { - char container_find_name[100]; + char container_find_name[1000]; struct lxc_container *container; assert(cmd); @@ -377,6 +377,23 @@ char *invite_in_container(const char *inviter, const char *invitee) { return invite_url; } +/* Run the gen_invite command inside the 'inviter' container to generate an invite + for 'invitee' belonging to pparticular submesh, and return the generated invite + which is output on the terminal */ +char *submesh_invite_in_container(const char *inviter, const char *invitee, const char *submesh) { + char invite_command[200]; + char *invite_url; + + assert(snprintf(invite_command, sizeof(invite_command), + "LD_LIBRARY_PATH=/home/ubuntu/test/.libs /home/ubuntu/test/gen_invite %s %s %s " + "2> gen_invite.log", inviter, invitee, submesh) >= 0); + assert(invite_url = run_in_container(invite_command, inviter, false)); + PRINT_TEST_CASE_MSG("Invite Generated from '%s' to '%s': %s\n", inviter, + invitee, invite_url); + + return invite_url; +} + /* Run the node_sim_ program inside the 'node''s container */ void node_sim_in_container(const char *node, const char *device_class, const char *invite_url) { char *node_sim_command; @@ -419,7 +436,7 @@ void node_sim_in_container_event(const char *node, const char *device_class, /* Run the node_step.sh script inside the 'node''s container to send the 'sig' signal to the node_sim program in the container */ void node_step_in_container(const char *node, const char *sig) { - char node_step_command[200]; + char node_step_command[1000]; assert(snprintf(node_step_command, sizeof(node_step_command), "/home/ubuntu/test/node_step.sh lt-node_sim_%s %s 1>&2 2> node_step.log", diff --git a/test/blackbox/common/mesh_event_handler.c b/test/blackbox/common/mesh_event_handler.c index 1b7ebe92..bb5faf1c 100644 --- a/test/blackbox/common/mesh_event_handler.c +++ b/test/blackbox/common/mesh_event_handler.c @@ -38,6 +38,16 @@ #define SERVER_LISTEN_PORT "9000" /* Port number that is binded with mesh event server socket */ #define UDP_BUFF_MAX 2000 +const char *event_status[] = { + [NODE_STARTED] = "Node Started", + [NODE_JOINED] = "Node Joined", + [ERR_NETWORK] = "Network Error", + [CHANNEL_OPENED] = "Channel Opened", + [CHANNEL_DATA_RECIEVED] = "Channel Data Received", + [SIG_ABORT] = "SIG_ABORT Received", + [MESH_EVENT_COMPLETED] = "MESH_EVENT_COMPLETED Received" +}; + // TODO: Implement mesh event handling with reentrancy . static struct sockaddr_in server_addr; static int client_fd = -1; @@ -269,5 +279,4 @@ void mesh_event_destroy(void) { mesh_events_flush(); event_receive_thread_running = false; pthread_cancel(event_receive_thread); -} - +} \ No newline at end of file diff --git a/test/blackbox/common/mesh_event_handler.h b/test/blackbox/common/mesh_event_handler.h index 7e497a35..e21ef508 100644 --- a/test/blackbox/common/mesh_event_handler.h +++ b/test/blackbox/common/mesh_event_handler.h @@ -72,10 +72,12 @@ typedef enum { INCOMING_META_CONN, OUTGOING_META_CONN, AUTO_DISCONN, - + MESH_EVENT_COMPLETED, MAX_EVENT // Maximum event enum } mesh_event_t; +extern const char *event_status[]; + /// mesh event UDP packet typedef struct mesh_event_payload { void *payload; diff --git a/test/blackbox/common/test_step.c b/test/blackbox/common/test_step.c index fbaab897..be0416d9 100644 --- a/test/blackbox/common/test_step.c +++ b/test/blackbox/common/test_step.c @@ -51,8 +51,8 @@ meshlink_handle_t *execute_open(char *node_name, char *dev_class) { return mesh_handle; } -char *execute_invite(char *invitee) { - char *invite_url = meshlink_invite_ex(mesh_handle, NULL, invitee, MESHLINK_INVITE_LOCAL | MESHLINK_INVITE_NUMERIC); +char *execute_invite(char *invitee, meshlink_submesh_t *submesh) { + char *invite_url = meshlink_invite_ex(mesh_handle, submesh, invitee, MESHLINK_INVITE_LOCAL | MESHLINK_INVITE_NUMERIC); PRINT_TEST_CASE_MSG("meshlink_invite status: %s\n", meshlink_strerror(meshlink_errno)); assert(invite_url); diff --git a/test/blackbox/common/test_step.h b/test/blackbox/common/test_step.h index 7a32dff0..1704d346 100644 --- a/test/blackbox/common/test_step.h +++ b/test/blackbox/common/test_step.h @@ -23,7 +23,7 @@ #include "../../../src/meshlink.h" meshlink_handle_t *execute_open(char *node_name, char *dev_class); -char *execute_invite(char *invitee); +char *execute_invite(char *invitee, meshlink_submesh_t *submesh); void execute_join(char *invite_url); void execute_start(void); void execute_stop(void); diff --git a/test/blackbox/run_blackbox_tests/Makefile.am b/test/blackbox/run_blackbox_tests/Makefile.am index 7fe23225..00aa9b89 100644 --- a/test/blackbox/run_blackbox_tests/Makefile.am +++ b/test/blackbox/run_blackbox_tests/Makefile.am @@ -56,7 +56,11 @@ run_blackbox_tests_SOURCES = \ ../test_case_channel_blacklist_01/node_sim_nut_01.c \ ../test_case_channel_blacklist_01/node_sim_peer_01.c \ ../test_case_channel_blacklist_01/node_sim_relay_01.c \ - test_cases_channel_blacklist.c + test_cases_channel_blacklist.c \ + test_cases_submesh01.c \ + test_cases_submesh02.c \ + test_cases_submesh03.c \ + test_cases_submesh04.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/execute_tests.c b/test/blackbox/run_blackbox_tests/execute_tests.c index 2f9730e1..7232911e 100644 --- a/test/blackbox/run_blackbox_tests/execute_tests.c +++ b/test/blackbox/run_blackbox_tests/execute_tests.c @@ -79,3 +79,48 @@ int teardown_test(void **state) { return EXIT_SUCCESS; } + +bool change_state(node_status_t *status, mesh_event_t currentEv) { + + if(status->current_index == status->max_events) { + return false; + } + + if(currentEv == status->expected_events[status->current_index]) { + status->current_index = status->current_index + 1; + + return true; + } else { + return false; + } +} + +void signal_node_start(node_status_t *node_status, int start, int end, char *node_ids[]) { + int i, index; + + for(i = start; i <= end; i++) { + index = node_status[i].current_index; + + if(index < 1 || NODE_JOINED != node_status[i].expected_events[index - 1]) { + return; + } + } + + + for(i = start; i <= end; i++) { + fprintf(stderr, "\tSending signals to '%s'\n", node_ids[i]); + node_step_in_container(node_ids[i], "SIGIO"); + } + + return; +} + +bool check_nodes_finished(node_status_t *node_status, int length) { + for(int i = 0; i < length; i++) { + if(node_status[i].current_index != node_status[i].max_events) { + return false; + } + } + + return true; +} diff --git a/test/blackbox/run_blackbox_tests/execute_tests.h b/test/blackbox/run_blackbox_tests/execute_tests.h index 03880f53..bdf28ea5 100644 --- a/test/blackbox/run_blackbox_tests/execute_tests.h +++ b/test/blackbox/run_blackbox_tests/execute_tests.h @@ -21,6 +21,13 @@ */ #include +#include "../common/mesh_event_handler.h" + +typedef struct { + const mesh_event_t *expected_events; + int current_index; + int max_events; +} node_status_t; typedef bool (*test_step_func_t)(void); @@ -28,4 +35,36 @@ int setup_test(void **state); void execute_test(test_step_func_t step_func, void **state); int teardown_test(void **state); +/// Changes the state of the node state machine. +/** This function changes the current state of the node + * + * @param status Pointer to status handle of that node. + * @param currentEv Current event triggered by the node. + * + * @return This function returns true if state change is successful else returns false + */ +extern bool change_state(node_status_t *status, mesh_event_t currentEv); + +/// Sends SIGIO signal to all the nodes in the container. +/** This function Triggers SIGIO signal to all the target applications running inside the container + * + * @param status Pointer to array of status handles of target nodes. + * @param start Starting index from which to start in the array. + * @param end Ending index of the array + * @param node_ids Pointer to array of node id strings + * + * @return Void + */ +extern void signal_node_start(node_status_t *node_status, int start, int end, char *node_ids[]); + +/// Checks for the completion of nodes state machines. +/** This function checks wheather the nodes state machines have reached their maximum state indexes + * + * @param status Pointer to array of status handles of target nodes. + * @param length Number of nodes to check. + * + * @return This function returns true if all the nodes reached their max states + */ +extern bool check_nodes_finished(node_status_t *node_status, int length); + #endif // TEST_STEP_H diff --git a/test/blackbox/run_blackbox_tests/run_blackbox_tests.c b/test/blackbox/run_blackbox_tests/run_blackbox_tests.c index c5b5c59e..df23d5ae 100644 --- a/test/blackbox/run_blackbox_tests/run_blackbox_tests.c +++ b/test/blackbox/run_blackbox_tests/run_blackbox_tests.c @@ -66,6 +66,10 @@ #include "test_cases_channel_conn.h" #include "test_cases_get_all_nodes_by_dev_class.h" +#include "test_cases_submesh01.h" +#include "test_cases_submesh02.h" +#include "test_cases_submesh03.h" +#include "test_cases_submesh04.h" #include "../common/containers.h" #include "../common/common_handlers.h" @@ -85,7 +89,8 @@ int main(int argc, char *argv[]) { int failed_tests = 0; - /*failed_tests += test_meta_conn(); + /* + failed_tests += test_meta_conn(); failed_tests += test_meshlink_set_status_cb(); failed_tests += test_meshlink_join(); failed_tests += test_meshlink_set_channel_poll_cb(); @@ -126,8 +131,13 @@ int main(int argc, char *argv[]) { failed_tests += test_meshlink_channel_open(); failed_tests += test_meshlink_channel_close(); - failed_tests += test_meshlink_channel_conn();*/ + 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_optimal_pmtu(); diff --git a/test/blackbox/run_blackbox_tests/test_cases_submesh01.c b/test/blackbox/run_blackbox_tests/test_cases_submesh01.c new file mode 100644 index 00000000..00f41525 --- /dev/null +++ b/test/blackbox/run_blackbox_tests/test_cases_submesh01.c @@ -0,0 +1,191 @@ +/* + test_cases_submesh.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. +*/ +#include +#include +#include +#include +#include +#include "execute_tests.h" +#include "test_cases_submesh01.h" +#include "pthread.h" +#include "../common/containers.h" +#include "../common/test_step.h" +#include "../common/common_handlers.h" +#include "../common/mesh_event_handler.h" + +#define CORENODE1_ID "0" +#define APP1NODE1_ID "1" +#define APP2NODE1_ID "2" +#define CORENODE2_ID "3" +#define APP1NODE2_ID "4" +#define APP2NODE2_ID "5" + +#define INIT_ST 0 + +static bool test_case_status = false; + +static void test_case_submesh_01(void **state); +static bool test_steps_submesh_01(void); + +static char event_node_name[][10] = {"CORENODE1", "APP1NODE1", "APP2NODE1", "CORENODE2", + "APP1NODE2", "APP2NODE2" + }; +static const char *node_ids[] = { "corenode1", "app1node1", "app2node1", "corenode2", + "app1node2", "app2node2" + }; + +static mesh_event_t core_node1[] = { NODE_STARTED, CHANNEL_OPENED, CHANNEL_DATA_RECIEVED}; + +static mesh_event_t core_node2[] = { NODE_STARTED, NODE_JOINED, CHANNEL_OPENED, CHANNEL_DATA_RECIEVED}; + +static mesh_event_t app1_node1[] = { NODE_STARTED, NODE_JOINED, CHANNEL_OPENED, CHANNEL_DATA_RECIEVED}; + +static mesh_event_t app2_node1[] = { NODE_STARTED, NODE_JOINED, CHANNEL_OPENED, CHANNEL_DATA_RECIEVED}; + +static mesh_event_t app1_node2[] = { NODE_STARTED, NODE_JOINED, CHANNEL_OPENED, CHANNEL_DATA_RECIEVED, CHANNEL_OPENED, CHANNEL_DATA_RECIEVED, MESH_EVENT_COMPLETED}; + +static mesh_event_t app2_node2[] = { NODE_STARTED, NODE_JOINED, CHANNEL_OPENED, CHANNEL_DATA_RECIEVED, CHANNEL_OPENED, CHANNEL_DATA_RECIEVED, MESH_EVENT_COMPLETED}; + +/* State structure for SubMesh Test Case #1 */ +static char *test_case_submesh_1_nodes[] = { "corenode1", "app1node1", "app2node1", "corenode2", "app1node2", "app2node2" }; +static black_box_state_t test_case_submesh_1_state = { + .test_case_name = "test_cases_submesh01", + .node_names = test_case_submesh_1_nodes, + .num_nodes = 6 +}; + +static int black_box_group0_setup(void **state) { + const char *nodes[] = { "corenode1", "app1node1", "app2node1", "corenode2", "app1node2", "app2node2" }; + int num_nodes = sizeof(nodes) / sizeof(nodes[0]); + + PRINT_TEST_CASE_MSG("Creating Containers\n"); + destroy_containers(); + create_containers(nodes, num_nodes); + + return 0; +} + +static int black_box_group0_teardown(void **state) { + PRINT_TEST_CASE_MSG("Destroying Containers\n"); + destroy_containers(); + + return 0; +} + +static int black_box_all_nodes_setup(void **state) { + const char *nodes[] = { "corenode1" }; + int num_nodes = sizeof(nodes) / sizeof(nodes[0]); + + PRINT_TEST_CASE_MSG("Creating Containers\n"); + destroy_containers(); + create_containers(nodes, num_nodes); + PRINT_TEST_CASE_MSG("Created Containers\n"); + return 0; +} + +static bool event_cb(mesh_event_payload_t payload) { + static node_status_t node_status[6] = { + {core_node1, 0, 3, false}, + {app1_node1, 0, 4, false}, + {app2_node1, 0, 4, false}, + {core_node2, 0, 4, false}, + {app1_node2, 0, 7, false}, + {app2_node2, 0, 7, false} + }; + + fprintf(stderr, "%s(%lu) : %s\n", event_node_name[payload.client_id], time(NULL), event_status[payload.mesh_event]); + assert(change_state(&node_status[payload.client_id], payload.mesh_event)); + + if(payload.mesh_event == NODE_JOINED) { + signal_node_start(node_status, 1, 5, node_ids); + } + + if(check_nodes_finished(node_status, 6)) { + test_case_status = true; + return true; + } + + return false; +} + +/* Execute SubMesh Test Case # 1 */ +static void test_case_submesh_01(void **state) { + execute_test(test_steps_submesh_01, state); +} + +/* Test Steps for SubMesh Test Case # 1 + + Test Steps: + 1. Run corenode1, app1node1, app2node1, corenode2, app1node2 and app2node2 + 2. Generate invites to app1node1, app2node1, corenode2, app1node2 and app2node2 + from corenode1 to join corenode1. + 3. After Join is successful start channels from all nodes and exchange data on channels + 4. Try to fetch the node handle of one sub-mesh node from node in another sub-mesh + + Expected Result: + Channels should be formed between nodes of sub-mesh & coremesh, nodes with in sub-mesh + and should be able to exchange data. But node in one sub-mesh should not get the details + of node in another sub-mesh. +*/ +static bool test_steps_submesh_01(void) { + char *invite_corenode2, *invite_app1node1, *invite_app2node1, *invite_app1node2, *invite_app2node2; + bool result = false; + int i; + char *import; + pthread_t thread1, thread2; + + import = mesh_event_sock_create(eth_if_name); + invite_corenode2 = invite_in_container("corenode1", "corenode2"); + invite_app1node1 = submesh_invite_in_container("corenode1", "app1node1", "app1"); + invite_app2node1 = submesh_invite_in_container("corenode1", "app2node1", "app2"); + invite_app1node2 = submesh_invite_in_container("corenode1", "app1node2", "app1"); + invite_app2node2 = submesh_invite_in_container("corenode1", "app2node2", "app2"); + + node_sim_in_container_event("corenode1", "1", NULL, CORENODE1_ID, import); + node_sim_in_container_event("corenode2", "1", invite_corenode2, CORENODE2_ID, import); + node_sim_in_container_event("app1node1", "1", invite_app1node1, APP1NODE1_ID, import); + node_sim_in_container_event("app2node1", "1", invite_app2node1, APP2NODE1_ID, import); + node_sim_in_container_event("app1node2", "1", invite_app1node2, APP1NODE2_ID, import); + node_sim_in_container_event("app2node2", "1", invite_app2node2, APP2NODE2_ID, import); + + PRINT_TEST_CASE_MSG("Waiting for nodes to get connected with corenode1\n"); + + assert(wait_for_event(event_cb, 240)); + assert(test_case_status); + + free(invite_corenode2); + free(invite_app1node1); + free(invite_app2node1); + free(invite_app1node2); + free(invite_app2node2); + + mesh_event_destroy(); + + return true; +} + +int test_cases_submesh01(void) { + const struct CMUnitTest blackbox_group0_tests[] = { + cmocka_unit_test_prestate_setup_teardown(test_case_submesh_01, setup_test, teardown_test, + (void *)&test_case_submesh_1_state) + }; + total_tests += sizeof(blackbox_group0_tests) / sizeof(blackbox_group0_tests[0]); + + return cmocka_run_group_tests(blackbox_group0_tests, black_box_group0_setup, black_box_group0_teardown); +} \ No newline at end of file diff --git a/test/blackbox/run_blackbox_tests/test_cases_submesh01.h b/test/blackbox/run_blackbox_tests/test_cases_submesh01.h new file mode 100644 index 00000000..d4ebccac --- /dev/null +++ b/test/blackbox/run_blackbox_tests/test_cases_submesh01.h @@ -0,0 +1,30 @@ +#ifndef TEST_CASES_SUBMESH_H +#define TEST_CASES_SUBMESH_H + +/* + test_cases_submesh01.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 +#include "../common/mesh_event_handler.h" + +extern int total_tests; +extern int test_cases_submesh01(void); + +#endif // TEST_CASES_SUBMESH_H \ No newline at end of file diff --git a/test/blackbox/run_blackbox_tests/test_cases_submesh02.c b/test/blackbox/run_blackbox_tests/test_cases_submesh02.c new file mode 100644 index 00000000..018adbf8 --- /dev/null +++ b/test/blackbox/run_blackbox_tests/test_cases_submesh02.c @@ -0,0 +1,194 @@ +/* + test_cases_submesh02.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. +*/ +#include +#include +#include +#include +#include +#include "execute_tests.h" +#include "test_cases_submesh02.h" +#include "pthread.h" +#include "../common/containers.h" +#include "../common/test_step.h" +#include "../common/common_handlers.h" +#include "../common/mesh_event_handler.h" + +#define CORENODE1_ID "0" +#define APP1NODE1_ID "1" +#define APP2NODE1_ID "2" +#define CORENODE2_ID "3" +#define APP1NODE2_ID "4" +#define APP2NODE2_ID "5" + +#define INIT_ST 0 + +static bool test_case_status = false; + +static void test_case_submesh_02(void **state); +static bool test_steps_submesh_02(void); + +static char event_node_name[][10] = {"CORENODE1", "APP1NODE1", "APP2NODE1", "CORENODE2", + "APP1NODE2", "APP2NODE2" + }; +static const char *node_ids[] = { "corenode1", "app1node1", "app2node1", "corenode2", + "app1node2", "app2node2" + }; + +static mesh_event_t core_node1[] = { NODE_STARTED, CHANNEL_OPENED, CHANNEL_DATA_RECIEVED}; + +static mesh_event_t core_node2[] = { NODE_STARTED, NODE_JOINED, CHANNEL_OPENED, CHANNEL_DATA_RECIEVED}; + +static mesh_event_t app1_node1[] = { NODE_STARTED, NODE_JOINED, CHANNEL_OPENED, CHANNEL_DATA_RECIEVED}; + +static mesh_event_t app2_node1[] = { NODE_STARTED, NODE_JOINED, CHANNEL_OPENED, CHANNEL_DATA_RECIEVED}; + +static mesh_event_t app1_node2[] = { NODE_STARTED, NODE_JOINED, CHANNEL_OPENED, CHANNEL_DATA_RECIEVED, CHANNEL_OPENED, CHANNEL_DATA_RECIEVED, MESH_EVENT_COMPLETED}; + +static mesh_event_t app2_node2[] = { NODE_STARTED, NODE_JOINED, CHANNEL_OPENED, CHANNEL_DATA_RECIEVED, CHANNEL_OPENED, CHANNEL_DATA_RECIEVED, MESH_EVENT_COMPLETED}; + +/* State structure for SubMesh Test Case #1 */ +static char *test_case_submesh_2_nodes[] = { "corenode1", "app1node1", "app2node1", "corenode2", "app1node2", "app2node2" }; +static black_box_state_t test_case_submesh_2_state = { + .test_case_name = "test_cases_submesh02", + .node_names = test_case_submesh_2_nodes, + .num_nodes = 6 +}; + +static int black_box_group0_setup(void **state) { + const char *nodes[] = { "corenode1", "app1node1", "app2node1", "corenode2", "app1node2", "app2node2" }; + int num_nodes = sizeof(nodes) / sizeof(nodes[0]); + + PRINT_TEST_CASE_MSG("Creating Containers\n"); + destroy_containers(); + create_containers(nodes, num_nodes); + + return 0; +} + +static int black_box_group0_teardown(void **state) { + PRINT_TEST_CASE_MSG("Destroying Containers\n"); + destroy_containers(); + + return 0; +} + +static int black_box_all_nodes_setup(void **state) { + const char *nodes[] = { "corenode1" }; + int num_nodes = sizeof(nodes) / sizeof(nodes[0]); + + PRINT_TEST_CASE_MSG("Creating Containers\n"); + destroy_containers(); + create_containers(nodes, num_nodes); + PRINT_TEST_CASE_MSG("Created Containers\n"); + return 0; +} + +static bool event_cb(mesh_event_payload_t payload) { + static node_status_t node_status[6] = { + {core_node1, 0, 3, false}, + {app1_node1, 0, 4, false}, + {app2_node1, 0, 4, false}, + {core_node2, 0, 4, false}, + {app1_node2, 0, 7, false}, + {app2_node2, 0, 7, false} + }; + + fprintf(stderr, "%s(%lu) : %s\n", event_node_name[payload.client_id], time(NULL), event_status[payload.mesh_event]); + assert(change_state(&node_status[payload.client_id], payload.mesh_event)); + + if(payload.mesh_event == NODE_JOINED) { + signal_node_start(node_status, 1, 5, node_ids); + } + + if(check_nodes_finished(node_status, 6)) { + test_case_status = true; + return true; + } + + return false; +} + +/* Execute SubMesh Test Case # 2 */ +static void test_case_submesh_02(void **state) { + execute_test(test_steps_submesh_02, state); +} + +/* Test Steps for SubMesh Test Case # 2 + + Test Steps: + 1. Run corenode1, app1node1, app2node1, corenode2, app1node2 and app2node2 + 2. Generate invites to app1node1, app2node1, corenode2, app1node2 and app2node2 + from corenode1 to join corenode1. + 3. After Join is successful start channels from all nodes and exchange data on channels + 4. Try to fetch the list of all nodes and check if the nodes in other submesh doesnot + appear in the list. + 5. Try fetch all the nodes with a submesh handle and check only if both the nodes joining + the submesh are present. + + Expected Result: + Channels should be formed between nodes of sub-mesh & coremesh, nodes with in sub-mesh + and should be able to exchange data. Lis of all nodes should only conatin four nodes + and the list of submesh should only conatin two nodes of that submesh. +*/ +static bool test_steps_submesh_02(void) { + char *invite_corenode2, *invite_app1node1, *invite_app2node1, *invite_app1node2, *invite_app2node2; + bool result = false; + int i; + char *import; + pthread_t thread1, thread2; + + import = mesh_event_sock_create(eth_if_name); + invite_corenode2 = invite_in_container("corenode1", "corenode2"); + invite_app1node1 = submesh_invite_in_container("corenode1", "app1node1", "app1"); + invite_app2node1 = submesh_invite_in_container("corenode1", "app2node1", "app2"); + invite_app1node2 = submesh_invite_in_container("corenode1", "app1node2", "app1"); + invite_app2node2 = submesh_invite_in_container("corenode1", "app2node2", "app2"); + + node_sim_in_container_event("corenode1", "1", NULL, CORENODE1_ID, import); + node_sim_in_container_event("corenode2", "1", invite_corenode2, CORENODE2_ID, import); + node_sim_in_container_event("app1node1", "1", invite_app1node1, APP1NODE1_ID, import); + node_sim_in_container_event("app2node1", "1", invite_app2node1, APP2NODE1_ID, import); + node_sim_in_container_event("app1node2", "1", invite_app1node2, APP1NODE2_ID, import); + node_sim_in_container_event("app2node2", "1", invite_app2node2, APP2NODE2_ID, import); + + PRINT_TEST_CASE_MSG("Waiting for nodes to get connected with corenode1\n"); + + assert(wait_for_event(event_cb, 240)); + assert(test_case_status); + + free(invite_corenode2); + free(invite_app1node1); + free(invite_app2node1); + free(invite_app1node2); + free(invite_app2node2); + + mesh_event_destroy(); + + return true; +} + +int test_cases_submesh02(void) { + const struct CMUnitTest blackbox_group0_tests[] = { + cmocka_unit_test_prestate_setup_teardown(test_case_submesh_02, setup_test, teardown_test, + (void *)&test_case_submesh_2_state) + }; + total_tests += sizeof(blackbox_group0_tests) / sizeof(blackbox_group0_tests[0]); + + return cmocka_run_group_tests(blackbox_group0_tests, black_box_group0_setup, black_box_group0_teardown); +} \ No newline at end of file diff --git a/test/blackbox/run_blackbox_tests/test_cases_submesh02.h b/test/blackbox/run_blackbox_tests/test_cases_submesh02.h new file mode 100644 index 00000000..a5710381 --- /dev/null +++ b/test/blackbox/run_blackbox_tests/test_cases_submesh02.h @@ -0,0 +1,30 @@ +#ifndef TEST_CASES_SUBMESH02_H +#define TEST_CASES_SUBMESH02_H + +/* + test_cases_submesh02.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 +#include "../common/mesh_event_handler.h" + +extern int total_tests; +extern int test_cases_submesh02(void); + +#endif // TEST_CASES_SUBMESH02_H \ No newline at end of file diff --git a/test/blackbox/run_blackbox_tests/test_cases_submesh03.c b/test/blackbox/run_blackbox_tests/test_cases_submesh03.c new file mode 100644 index 00000000..76b6ef9e --- /dev/null +++ b/test/blackbox/run_blackbox_tests/test_cases_submesh03.c @@ -0,0 +1,189 @@ +/* + test_cases_submesh03.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. +*/ +#include +#include +#include +#include +#include +#include "execute_tests.h" +#include "test_cases_submesh03.h" +#include "pthread.h" +#include "../common/containers.h" +#include "../common/test_step.h" +#include "../common/common_handlers.h" +#include "../common/mesh_event_handler.h" + +#define CORENODE1_ID "0" +#define APP1NODE1_ID "1" +#define APP1NODE2_ID "2" + +#define INIT_ST 0 + +static bool test_case_status = false; + +static void test_case_submesh_03(void **state); +static bool test_steps_submesh_03(void); + +static char event_node_name[][10] = {"CORENODE1", "APP1NODE1", "APP1NODE2"}; +static const char *node_ids[] = { "corenode1", "app1node1", "app1node2" }; + +static mesh_event_t core_node1[] = { NODE_STARTED, CHANNEL_OPENED, CHANNEL_DATA_RECIEVED}; + +static mesh_event_t app1_node1[] = { NODE_STARTED, NODE_JOINED, CHANNEL_OPENED, CHANNEL_DATA_RECIEVED}; + +static mesh_event_t app1_node2[] = { NODE_STARTED, NODE_JOINED, CHANNEL_OPENED, CHANNEL_DATA_RECIEVED, CHANNEL_OPENED, CHANNEL_DATA_RECIEVED, MESH_EVENT_COMPLETED}; + +static node_status_t node_status[3] = { + {core_node1, 0, 3, false}, + {app1_node1, 0, 4, false}, + {app1_node2, 0, 7, false} +}; + +/* State structure for SubMesh Test Case #3 */ +static char *test_case_submesh_3_nodes[] = { "corenode1", "app1node1", "app1node2" }; +static black_box_state_t test_case_submesh_3_state = { + .test_case_name = "test_cases_submesh03", + .node_names = test_case_submesh_3_nodes, + .num_nodes = 3 +}; + +static int black_box_group0_setup(void **state) { + const char *nodes[] = { "corenode1", "app1node1", "app1node2" }; + int num_nodes = sizeof(nodes) / sizeof(nodes[0]); + + PRINT_TEST_CASE_MSG("Creating Containers\n"); + destroy_containers(); + create_containers(nodes, num_nodes); + + return 0; +} + +static int black_box_group0_teardown(void **state) { + PRINT_TEST_CASE_MSG("Destroying Containers\n"); + destroy_containers(); + + return 0; +} + +static int black_box_all_nodes_setup(void **state) { + const char *nodes[] = { "corenode1" }; + int num_nodes = sizeof(nodes) / sizeof(nodes[0]); + + PRINT_TEST_CASE_MSG("Creating Containers\n"); + destroy_containers(); + create_containers(nodes, num_nodes); + PRINT_TEST_CASE_MSG("Created Containers\n"); + return 0; +} + +static void restart_all_nodes(char *import) { + int i; + + for(i = 0; i < 3; i++) { + node_step_in_container(node_ids[i], "SIGTERM"); + node_status[i].current_index = 0; + } + + sleep(5); + + node_sim_in_container_event("corenode1", "1", NULL, CORENODE1_ID, import); + node_sim_in_container_event("app1node1", "1", NULL, APP1NODE1_ID, import); + node_sim_in_container_event("app1node2", "1", NULL, APP1NODE2_ID, import); +} + +static bool event_cb(mesh_event_payload_t payload) { + + fprintf(stderr, "%s(%lu) : %s\n", event_node_name[payload.client_id], time(NULL), event_status[payload.mesh_event]); + assert(change_state(&node_status[payload.client_id], payload.mesh_event)); + + if(payload.mesh_event == NODE_JOINED) { + signal_node_start(node_status, 1, 2, node_ids); + } + + if(check_nodes_finished(node_status, 3)) { + test_case_status = true; + return true; + } + + return false; +} + +/* Execute SubMesh Test Case # 3 */ +static void test_case_submesh_03(void **state) { + execute_test(test_steps_submesh_03, state); +} + +/* Test Steps for SubMesh Test Case # 3 + + Test Steps: + 1. Run corenode1, app1node1, and app1node2 + 2. Generate invites to app1node1, and app1node2 + from corenode1 to join corenode1. + 3. After Join is successful start channels from all nodes and exchange data on channels + 4. Try to restart all the nodes at the same time. + + Expected Result: + Channels should be formed between nodes of sub-mesh & coremesh, nodes with in sub-mesh + and should be able to exchange data even after restart. +*/ +static bool test_steps_submesh_03(void) { + char *invite_app1node1, *invite_app1node2; + bool result = false; + int i; + char *import; + pthread_t thread1, thread2; + + import = mesh_event_sock_create(eth_if_name); + invite_app1node1 = invite_in_container("corenode1", "app1node1"); + invite_app1node2 = invite_in_container("corenode1", "app1node2"); + + node_sim_in_container_event("corenode1", "1", NULL, CORENODE1_ID, import); + node_sim_in_container_event("app1node1", "1", invite_app1node1, APP1NODE1_ID, import); + node_sim_in_container_event("app1node2", "1", invite_app1node2, APP1NODE2_ID, import); + + PRINT_TEST_CASE_MSG("Waiting for nodes to get connected with corenode1\n"); + + assert(wait_for_event(event_cb, 120)); + assert(test_case_status); + + test_case_status = false; + + restart_all_nodes(import); + PRINT_TEST_CASE_MSG("Waiting for nodes to get restarted\n"); + + assert(wait_for_event(event_cb, 120)); + assert(test_case_status); + + free(invite_app1node1); + free(invite_app1node2); + + mesh_event_destroy(); + + return true; +} + +int test_cases_submesh03(void) { + const struct CMUnitTest blackbox_group0_tests[] = { + cmocka_unit_test_prestate_setup_teardown(test_case_submesh_03, setup_test, teardown_test, + (void *)&test_case_submesh_3_state) + }; + total_tests += sizeof(blackbox_group0_tests) / sizeof(blackbox_group0_tests[0]); + + return cmocka_run_group_tests(blackbox_group0_tests, black_box_group0_setup, black_box_group0_teardown); +} \ No newline at end of file diff --git a/test/blackbox/run_blackbox_tests/test_cases_submesh03.h b/test/blackbox/run_blackbox_tests/test_cases_submesh03.h new file mode 100644 index 00000000..432c1e00 --- /dev/null +++ b/test/blackbox/run_blackbox_tests/test_cases_submesh03.h @@ -0,0 +1,30 @@ +#ifndef TEST_CASES_SUBMESH03_H +#define TEST_CASES_SUBMESH03_H + +/* + test_cases_submesh03.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 +#include "../common/mesh_event_handler.h" + +extern int total_tests; +extern int test_cases_submesh03(void); + +#endif // TEST_CASES_SUBMESH03_H \ No newline at end of file diff --git a/test/blackbox/run_blackbox_tests/test_cases_submesh04.c b/test/blackbox/run_blackbox_tests/test_cases_submesh04.c new file mode 100644 index 00000000..96c117a5 --- /dev/null +++ b/test/blackbox/run_blackbox_tests/test_cases_submesh04.c @@ -0,0 +1,168 @@ +/* + test_cases_submesh05.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. +*/ +#include +#include +#include +#include +#include +#include "execute_tests.h" +#include "test_cases_submesh04.h" +#include "pthread.h" +#include "../common/containers.h" +#include "../common/test_step.h" +#include "../common/common_handlers.h" +#include "../common/mesh_event_handler.h" + +#define CORENODE1_ID "0" +#define APP1NODE1_ID "1" +#define APP1NODE2_ID "2" + +#define INIT_ST 0 + +static bool test_case_status = false; + +static void test_case_submesh_04(void **state); +static bool test_steps_submesh_04(void); + +static char event_node_name[][10] = {"CORENODE1", "APP1NODE1", "APP1NODE2"}; +static const char *node_ids[] = { "corenode1", "app1node1", "app1node2" }; + +static mesh_event_t core_node1[] = { NODE_STARTED, CHANNEL_OPENED, CHANNEL_DATA_RECIEVED }; + +static mesh_event_t app1_node1[] = { NODE_STARTED, NODE_JOINED, CHANNEL_OPENED, CHANNEL_DATA_RECIEVED }; + +static mesh_event_t app1_node2[] = { NODE_STARTED, NODE_JOINED, CHANNEL_OPENED, CHANNEL_DATA_RECIEVED, CHANNEL_OPENED, CHANNEL_DATA_RECIEVED, MESH_EVENT_COMPLETED}; + +/* State structure for SubMesh Test Case #4 */ +static char *test_case_submesh_4_nodes[] = { "corenode1", "app1node1", "app1node2" }; +static black_box_state_t test_case_submesh_4_state = { + .test_case_name = "test_cases_submesh04", + .node_names = test_case_submesh_4_nodes, + .num_nodes = 3 +}; + +static int black_box_group0_setup(void **state) { + const char *nodes[] = { "corenode1", "app1node1", "app1node2" }; + int num_nodes = sizeof(nodes) / sizeof(nodes[0]); + + PRINT_TEST_CASE_MSG("Creating Containers\n"); + destroy_containers(); + create_containers(nodes, num_nodes); + + return 0; +} + +static int black_box_group0_teardown(void **state) { + PRINT_TEST_CASE_MSG("Destroying Containers\n"); + destroy_containers(); + + return 0; +} + +static int black_box_all_nodes_setup(void **state) { + const char *nodes[] = { "corenode1" }; + int num_nodes = sizeof(nodes) / sizeof(nodes[0]); + + PRINT_TEST_CASE_MSG("Creating Containers\n"); + destroy_containers(); + create_containers(nodes, num_nodes); + PRINT_TEST_CASE_MSG("Created Containers\n"); + return 0; +} + +static bool event_cb(mesh_event_payload_t payload) { + static node_status_t node_status[3] = { + {core_node1, 0, 3, false}, + {app1_node1, 0, 4, false}, + {app1_node2, 0, 7, false} + }; + + fprintf(stderr, "%s(%lu) : %s\n", event_node_name[payload.client_id], time(NULL), event_status[payload.mesh_event]); + assert(change_state(&node_status[payload.client_id], payload.mesh_event)); + + if(payload.mesh_event == NODE_JOINED) { + signal_node_start(node_status, 1, 2, node_ids); + } + + if(check_nodes_finished(node_status, 3)) { + test_case_status = true; + return true; + } + + return false; +} + +/* Execute SubMesh Test Case # 4 */ +static void test_case_submesh_04(void **state) { + execute_test(test_steps_submesh_04, state); +} + +/* Test Steps for SubMesh Test Case # 4 + + Test Steps: + 1. Run corenode1, app1node1, and app1node2 + 2. Generate invites to app1node1, app1node2 + from corenode1 to join corenode1. + 3. After Join is successful start channels from all nodes and exchange data on channels + 4. Black list a node in the submesh and check if it is successful + 5. White list the node and it should be form all the connections again + + Expected Result: + Channels should be formed between nodes of sub-mesh & coremesh, nodes with in sub-mesh + and should be able to exchange data. When black listed, other node should not get any + from the black listed node. When white listed again it has to form the connections as + they were previously before black listing. +*/ +static bool test_steps_submesh_04(void) { + char *invite_app1node1, *invite_app1node2; + bool result = false; + int i; + char *import; + pthread_t thread1, thread2; + + import = mesh_event_sock_create(eth_if_name); + invite_app1node1 = invite_in_container("corenode1", "app1node1"); + invite_app1node2 = invite_in_container("corenode1", "app1node2"); + + node_sim_in_container_event("corenode1", "1", NULL, CORENODE1_ID, import); + node_sim_in_container_event("app1node1", "1", invite_app1node1, APP1NODE1_ID, import); + node_sim_in_container_event("app1node2", "1", invite_app1node2, APP1NODE2_ID, import); + + PRINT_TEST_CASE_MSG("Waiting for nodes to get connected with corenode1\n"); + + assert(wait_for_event(event_cb, 120)); + assert(test_case_status); + + free(invite_app1node1); + free(invite_app1node2); + + mesh_event_destroy(); + + return true; +} + +int test_cases_submesh04(void) { + const struct CMUnitTest blackbox_group0_tests[] = { + cmocka_unit_test_prestate_setup_teardown(test_case_submesh_04, setup_test, teardown_test, + (void *)&test_case_submesh_4_state) + }; + total_tests += sizeof(blackbox_group0_tests) / sizeof(blackbox_group0_tests[0]); + + return cmocka_run_group_tests(blackbox_group0_tests, black_box_group0_setup, black_box_group0_teardown); +} \ No newline at end of file diff --git a/test/blackbox/run_blackbox_tests/test_cases_submesh04.h b/test/blackbox/run_blackbox_tests/test_cases_submesh04.h new file mode 100644 index 00000000..be7a22bf --- /dev/null +++ b/test/blackbox/run_blackbox_tests/test_cases_submesh04.h @@ -0,0 +1,30 @@ +#ifndef TEST_CASES_SUBMESH04_H +#define TEST_CASES_SUBMESH04_H + +/* + test_cases_submesh04.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 +#include "../common/mesh_event_handler.h" + +extern int total_tests; +extern int test_cases_submesh04(void); + +#endif // TEST_CASES_SUBMESH04_H \ No newline at end of file diff --git a/test/blackbox/test_case_channel_conn_01/Makefile.am b/test/blackbox/test_case_channel_conn_01/Makefile.am index 4cca831a..177c575f 100644 --- a/test/blackbox/test_case_channel_conn_01/Makefile.am +++ b/test/blackbox/test_case_channel_conn_01/Makefile.am @@ -6,4 +6,4 @@ node_sim_peer_CFLAGS = -D_GNU_SOURCE node_sim_nut_SOURCES = node_sim_nut.c ../common/common_handlers.c ../common/test_step.c ../common/mesh_event_handler.c ../../utils.c node_sim_nut_LDADD = ../../../src/libmeshlink.la -node_sim_nut_CFLAGS = -D_GNU_SOURCE +node_sim_nut_CFLAGS = -D_GNU_SOURCE \ No newline at end of file diff --git a/test/blackbox/test_case_meta_conn_04/node_sim_nut.c b/test/blackbox/test_case_meta_conn_04/node_sim_nut.c index 7f4ddd90..358eadcd 100644 --- a/test/blackbox/test_case_meta_conn_04/node_sim_nut.c +++ b/test/blackbox/test_case_meta_conn_04/node_sim_nut.c @@ -100,7 +100,7 @@ int main(int argc, char *argv[]) { if(!argv[CMD_LINE_ARG_INVITEURL]) { fprintf(stderr, "Generating Inviation to PEER\n"); - invite_peer = execute_invite("peer"); + invite_peer = execute_invite("peer", NULL); assert(invite_peer != NULL); if(!mesh_event_sock_send(clientId, NODE_INVITATION, invite_peer, strlen(invite_peer) + 1)) { diff --git a/test/blackbox/test_case_meta_conn_05/node_sim_nut.c b/test/blackbox/test_case_meta_conn_05/node_sim_nut.c index 8741ffa7..e0459e09 100644 --- a/test/blackbox/test_case_meta_conn_05/node_sim_nut.c +++ b/test/blackbox/test_case_meta_conn_05/node_sim_nut.c @@ -103,7 +103,7 @@ int main(int argc, char *argv[]) { } fprintf(stderr, "Generating Inviation to PEER\n"); - invite_peer = execute_invite("peer"); + invite_peer = execute_invite("peer", NULL); assert(invite_peer != NULL); if(!mesh_event_sock_send(clientId, NODE_INVITATION, invite_peer, strlen(invite_peer) + 1)) { diff --git a/test/blackbox/test_cases_submesh01/Makefile.am b/test/blackbox/test_cases_submesh01/Makefile.am new file mode 100644 index 00000000..bb0ff44b --- /dev/null +++ b/test/blackbox/test_cases_submesh01/Makefile.am @@ -0,0 +1,25 @@ +check_PROGRAMS = node_sim_corenode1 node_sim_corenode2 node_sim_app1node1 node_sim_app1node2 node_sim_app2node1 node_sim_app2node2 + +node_sim_corenode1_SOURCES = node_sim_corenode1.c ../common/common_handlers.c ../common/test_step.c ../common/mesh_event_handler.c ../../utils.c +node_sim_corenode1_LDADD = ../../../src/libmeshlink.la +node_sim_corenode1_CFLAGS = -D_GNU_SOURCE + +node_sim_corenode2_SOURCES = node_sim_corenode2.c ../common/common_handlers.c ../common/test_step.c ../common/mesh_event_handler.c ../../utils.c +node_sim_corenode2_LDADD = ../../../src/libmeshlink.la +node_sim_corenode2_CFLAGS = -D_GNU_SOURCE + +node_sim_app1node1_SOURCES = node_sim_app1node1.c ../common/common_handlers.c ../common/test_step.c ../common/mesh_event_handler.c ../../utils.c +node_sim_app1node1_LDADD = ../../../src/libmeshlink.la +node_sim_app1node1_CFLAGS = -D_GNU_SOURCE + +node_sim_app1node2_SOURCES = node_sim_app1node2.c ../common/common_handlers.c ../common/test_step.c ../common/mesh_event_handler.c ../../utils.c +node_sim_app1node2_LDADD = ../../../src/libmeshlink.la +node_sim_app1node2_CFLAGS = -D_GNU_SOURCE + +node_sim_app2node1_SOURCES = node_sim_app2node1.c ../common/common_handlers.c ../common/test_step.c ../common/mesh_event_handler.c ../../utils.c +node_sim_app2node1_LDADD = ../../../src/libmeshlink.la +node_sim_app2node1_CFLAGS = -D_GNU_SOURCE + +node_sim_app2node2_SOURCES = node_sim_app2node2.c ../common/common_handlers.c ../common/test_step.c ../common/mesh_event_handler.c ../../utils.c +node_sim_app2node2_LDADD = ../../../src/libmeshlink.la +node_sim_app2node2_CFLAGS = -D_GNU_SOURCE diff --git a/test/blackbox/test_cases_submesh01/node_sim_app1node1.c b/test/blackbox/test_cases_submesh01/node_sim_app1node1.c new file mode 100644 index 00000000..50cf4fe1 --- /dev/null +++ b/test/blackbox/test_cases_submesh01/node_sim_app1node1.c @@ -0,0 +1,221 @@ +/* + node_sim_peer.c -- Implementation of Node Simulation for Meshlink Testing + for meta connection test case 01 - re-connection of + two nodes when relay node goes down + 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 +#include +#include +#include +#include +#include +#include +#include "../common/common_handlers.h" +#include "../common/test_step.h" +#include "../common/mesh_event_handler.h" +#include "../../utils.h" + +#define CMD_LINE_ARG_NODENAME 1 +#define CMD_LINE_ARG_DEVCLASS 2 +#define CMD_LINE_ARG_CLIENTID 3 +#define CMD_LINE_ARG_IMPORTSTR 4 +#define CMD_LINE_ARG_INVITEURL 5 +#define CHANNEL_PORT 1234 + +static void channel_receive_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, const void *dat, size_t len); +static bool channel_accept(meshlink_handle_t *mesh, meshlink_channel_t *channel, uint16_t port, const void *dat, size_t len); + +static int client_id = -1; +static meshlink_handle_t *mesh = NULL; + +static struct sync_flag peer_reachable = {.mutex = PTHREAD_MUTEX_INITIALIZER, .cond = PTHREAD_COND_INITIALIZER, .flag = false}; +static struct sync_flag start_test = {.mutex = PTHREAD_MUTEX_INITIALIZER, .cond = PTHREAD_COND_INITIALIZER, .flag = false}; +static struct sync_flag channel_opened = {.mutex = PTHREAD_MUTEX_INITIALIZER, .cond = PTHREAD_COND_INITIALIZER, .flag = false}; +static struct sync_flag channel_data_recieved = {.mutex = PTHREAD_MUTEX_INITIALIZER, .cond = PTHREAD_COND_INITIALIZER, .flag = false}; + +static void send_event(mesh_event_t event) { + int attempts; + + for(attempts = 0; attempts < 5; attempts += 1) { + if(mesh_event_sock_send(client_id, event, NULL, 0)) { + break; + } + } + + assert(attempts < 5); + + return; +} + +static bool channel_accept(meshlink_handle_t *mesh, meshlink_channel_t *channel, uint16_t port, const void *dat, size_t len) { + (void)dat; + (void)len; + + assert(port == CHANNEL_PORT); + + fprintf(stderr, "\tapp1node1 got channel request from %s\n", channel->node->name); + + if(!strcmp(channel->node->name, "corenode1")) { + fprintf(stderr, "\tapp1node1 accepting channel request from %s at %lu\n", channel->node->name, time(NULL)); + meshlink_set_channel_receive_cb(mesh, channel, channel_receive_cb); + mesh->priv = channel; + + return true; + } else if(!strcmp(channel->node->name, "app1node2")) { + fprintf(stderr, "\tapp1node1 accepting channel request from %s at %lu\n", channel->node->name, time(NULL)); + meshlink_set_channel_receive_cb(mesh, channel, channel_receive_cb); + mesh->priv = channel; + + return true; + } + + fprintf(stderr, "\tapp1node1 rejecting channel request from %s at %lu\n", channel->node->name, time(NULL)); + return false; +} + +/* channel receive callback */ +static void channel_receive_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, const void *dat, size_t len) { + char data[100] = {0}; + char *message = "Channel Message"; + + if(len == 0) { + fprintf(stderr, "\tapp1node1 got error from %s at %lu\n", channel->node->name, time(NULL)); + send_event(ERR_NETWORK); + return; + } + + memcpy(data, dat, len); + + fprintf(stderr, "\tapp1node1 got message from %s as %s\n", channel->node->name, data); + + if(!strcmp(channel->node->name, "corenode1")) { + if(!memcmp(dat, "Channel Message", len)) { + set_sync_flag(&channel_data_recieved, true); + } else if(!memcmp(dat, "failure", 7)) { + assert(false); + } + } else if(!strcmp(channel->node->name, "app1node2")) { + if(!memcmp(dat, "Channel Message", len)) { + assert(meshlink_channel_send(mesh, channel, message, strlen(message)) >= 0); + } else if(!memcmp(dat, "failure", 7)) { + assert(false); + } + } + + return; +} + +static void poll_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, size_t len) { + char *message = "Channel Message"; + char *node = (char *)channel->node->name; + (void)len; + meshlink_set_channel_poll_cb(mesh, channel, NULL); + fprintf(stderr, "\tapp1node1's Channel request has been accepted by %s at : %lu\n", node, time(NULL)); + + if(0 == strcmp("corenode1", node)) { + set_sync_flag(&channel_opened, true); + } + + assert(meshlink_channel_send(mesh, channel, message, strlen(message)) >= 0); + return; +} + + +static void node_status_cb(meshlink_handle_t *mesh, meshlink_node_t *node, + bool reachable) { + if(!strcasecmp(node->name, "corenode1")) { + if(reachable) { + fprintf(stderr, "\tNode corenode1 became reachable\n"); + set_sync_flag(&peer_reachable, true); + } + } + + return; +} + +void mesh_start_test_handler(int a) { + fprintf(stderr, "Starting test in app1node1\n"); + set_sync_flag(&start_test, true); +} + +int main(int argc, char *argv[]) { + struct timeval main_loop_wait = { 2, 0 }; + meshlink_channel_t *channel = NULL; + meshlink_node_t *core_node = NULL; + + fprintf(stderr, "\tMesh node 'app1node1' starting up........\n"); + + // Import mesh event handler + + if((argv[CMD_LINE_ARG_CLIENTID]) && (argv[CMD_LINE_ARG_IMPORTSTR])) { + client_id = atoi(argv[CMD_LINE_ARG_CLIENTID]); + mesh_event_sock_connect(argv[CMD_LINE_ARG_IMPORTSTR]); + } + + // Setup required signals + + setup_signals(); + signal(SIGIO, mesh_start_test_handler); + + // Run peer node instance + + mesh = meshlink_open("app1node1conf", argv[CMD_LINE_ARG_NODENAME], + "test_channel_conn", atoi(argv[CMD_LINE_ARG_DEVCLASS])); + assert(mesh); + meshlink_set_log_cb(mesh, MESHLINK_DEBUG, meshlink_callback_logger); + meshlink_set_channel_accept_cb(mesh, channel_accept); + meshlink_set_node_status_cb(mesh, node_status_cb); + + if(argv[CMD_LINE_ARG_INVITEURL]) { + assert(meshlink_join(mesh, argv[CMD_LINE_ARG_INVITEURL])); + } + + assert(meshlink_start(mesh)); + + send_event(NODE_STARTED); + + // Wait for peer node to join + + assert(wait_sync_flag(&peer_reachable, 15)); + send_event(NODE_JOINED); + + while(false == wait_sync_flag(&start_test, 10)); + + // Open a channel to peer node + core_node = meshlink_get_node(mesh, "corenode1"); + assert(core_node); + fprintf(stderr, "\tapp1node1 Sending Channel request to corenode1 at : %lu\n", time(NULL)); + channel = meshlink_channel_open(mesh, core_node, CHANNEL_PORT, + channel_receive_cb, NULL, 0); + meshlink_set_channel_poll_cb(mesh, channel, poll_cb); + assert(wait_sync_flag(&channel_opened, 100)); + send_event(CHANNEL_OPENED); + + assert(wait_sync_flag(&channel_data_recieved, 100)); + send_event(CHANNEL_DATA_RECIEVED); + + // All test steps executed - wait for signals to stop/start or close the mesh + + while(test_running) { + select(1, NULL, NULL, NULL, &main_loop_wait); + } + + meshlink_close(mesh); + + return EXIT_SUCCESS; +} \ No newline at end of file diff --git a/test/blackbox/test_cases_submesh01/node_sim_app1node2.c b/test/blackbox/test_cases_submesh01/node_sim_app1node2.c new file mode 100644 index 00000000..bb8697bf --- /dev/null +++ b/test/blackbox/test_cases_submesh01/node_sim_app1node2.c @@ -0,0 +1,243 @@ +/* + node_sim_peer.c -- Implementation of Node Simulation for Meshlink Testing + for meta connection test case 01 - re-connection of + two nodes when relay node goes down + 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 +#include +#include +#include +#include +#include +#include +#include "../common/common_handlers.h" +#include "../common/test_step.h" +#include "../common/mesh_event_handler.h" +#include "../../utils.h" + +#define CMD_LINE_ARG_NODENAME 1 +#define CMD_LINE_ARG_DEVCLASS 2 +#define CMD_LINE_ARG_CLIENTID 3 +#define CMD_LINE_ARG_IMPORTSTR 4 +#define CMD_LINE_ARG_INVITEURL 5 +#define CHANNEL_PORT 1234 + +static void channel_receive_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, const void *dat, size_t len); +static bool channel_accept(meshlink_handle_t *mesh, meshlink_channel_t *channel, uint16_t port, const void *dat, size_t len); + +static int client_id = -1; +static meshlink_handle_t *mesh = NULL; + +static struct sync_flag peer_reachable = {.mutex = PTHREAD_MUTEX_INITIALIZER, .cond = PTHREAD_COND_INITIALIZER, .flag = false}; +static struct sync_flag start_test = {.mutex = PTHREAD_MUTEX_INITIALIZER, .cond = PTHREAD_COND_INITIALIZER, .flag = false}; +static struct sync_flag app_reachable = {.mutex = PTHREAD_MUTEX_INITIALIZER, .cond = PTHREAD_COND_INITIALIZER, .flag = false}; +static struct sync_flag channel_opened = {.mutex = PTHREAD_MUTEX_INITIALIZER, .cond = PTHREAD_COND_INITIALIZER, .flag = false}; +static struct sync_flag channel_data_recieved = {.mutex = PTHREAD_MUTEX_INITIALIZER, .cond = PTHREAD_COND_INITIALIZER, .flag = false}; + +static void send_event(mesh_event_t event) { + int attempts; + + for(attempts = 0; attempts < 5; attempts += 1) { + if(mesh_event_sock_send(client_id, event, NULL, 0)) { + break; + } + } + + assert(attempts < 5); + + return; +} + +static bool channel_accept(meshlink_handle_t *mesh, meshlink_channel_t *channel, uint16_t port, const void *dat, size_t len) { + (void)dat; + (void)len; + + assert(port == CHANNEL_PORT); + + fprintf(stderr, "\tapp1node2 got channel request from %s\n", channel->node->name); + + if(!strcmp(channel->node->name, "corenode1")) { + meshlink_set_channel_receive_cb(mesh, channel, channel_receive_cb); + mesh->priv = channel; + + return true; + } + + return false; +} + +/* channel receive callback */ +static void channel_receive_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, const void *dat, size_t len) { + char data[100] = {0}; + + if(len == 0) { + fprintf(stderr, "\tapp1node2 got error from %s at %lu\n", channel->node->name, time(NULL)); + send_event(ERR_NETWORK); + return; + } + + memcpy(data, dat, len); + + fprintf(stderr, "\tapp1node2 got message from %s as %s\n", channel->node->name, data); + + if(!strcmp(channel->node->name, "corenode1")) { + if(!memcmp(dat, "Channel Message", len)) { + set_sync_flag(&channel_data_recieved, true); + } else if(!memcmp(dat, "failure", 7)) { + assert(false); + } + } else if(!strcmp(channel->node->name, "app1node1")) { + if(!memcmp(dat, "Channel Message", len)) { + set_sync_flag(&channel_data_recieved, true); + } else if(!memcmp(dat, "failure", 7)) { + assert(false); + } + } else { + assert(false); + } + + return; +} + +static void poll_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, size_t len) { + char *message = "Channel Message"; + char *node = (char *)channel->node->name; + (void)len; + meshlink_set_channel_poll_cb(mesh, channel, NULL); + fprintf(stderr, "\tapp1node2's Channel request has been accepted by %s at : %lu\n", node, time(NULL)); + set_sync_flag(&channel_opened, true); + assert(meshlink_channel_send(mesh, channel, message, strlen(message)) >= 0); + return; +} + + +static void node_status_cb(meshlink_handle_t *mesh, meshlink_node_t *node, + bool reachable) { + if(!strcasecmp(node->name, "corenode1")) { + if(reachable) { + fprintf(stderr, "\tNode corenode1 became reachable\n"); + set_sync_flag(&peer_reachable, true); + } + } else if(!strcasecmp(node->name, "app1node1")) { + if(reachable) { + fprintf(stderr, "\tNode app1node1 became reachable\n"); + set_sync_flag(&app_reachable, true); + } + } + + return; +} + +void mesh_start_test_handler(int a) { + fprintf(stderr, "Starting test in app1node2\n"); + set_sync_flag(&start_test, true); +} + +int main(int argc, char *argv[]) { + struct timeval main_loop_wait = { 2, 0 }; + meshlink_channel_t *channel = NULL; + meshlink_node_t *core_node = NULL; + + fprintf(stderr, "\tMesh node 'app1node2' starting up........\n"); + + // Import mesh event handler + + if((argv[CMD_LINE_ARG_CLIENTID]) && (argv[CMD_LINE_ARG_IMPORTSTR])) { + client_id = atoi(argv[CMD_LINE_ARG_CLIENTID]); + mesh_event_sock_connect(argv[CMD_LINE_ARG_IMPORTSTR]); + } + + // Setup required signals + + setup_signals(); + signal(SIGIO, mesh_start_test_handler); + + // Run peer node instance + + mesh = meshlink_open("app1node2conf", argv[CMD_LINE_ARG_NODENAME], + "test_channel_conn", atoi(argv[CMD_LINE_ARG_DEVCLASS])); + assert(mesh); + meshlink_set_log_cb(mesh, MESHLINK_DEBUG, meshlink_callback_logger); + meshlink_set_channel_accept_cb(mesh, channel_accept); + meshlink_set_node_status_cb(mesh, node_status_cb); + + if(argv[CMD_LINE_ARG_INVITEURL]) { + assert(meshlink_join(mesh, argv[CMD_LINE_ARG_INVITEURL])); + } + + assert(meshlink_start(mesh)); + + send_event(NODE_STARTED); + + // Wait for peer node to join + + assert(wait_sync_flag(&peer_reachable, 15)); + send_event(NODE_JOINED); + + while(false == wait_sync_flag(&start_test, 10)); + + // Open a channel to peer node + core_node = meshlink_get_node(mesh, "corenode1"); + assert(core_node); + fprintf(stderr, "\tapp1node2 Sending Channel request to corenode1 at : %lu\n", time(NULL)); + channel = meshlink_channel_open(mesh, core_node, CHANNEL_PORT, + channel_receive_cb, NULL, 0); + meshlink_set_channel_poll_cb(mesh, channel, poll_cb); + assert(wait_sync_flag(&channel_opened, 15)); + send_event(CHANNEL_OPENED); + + assert(wait_sync_flag(&channel_data_recieved, 30)); + send_event(CHANNEL_DATA_RECIEVED); + + // Open a channel to peer node + channel_opened.flag = false; + channel_data_recieved.flag = false; + + assert(wait_sync_flag(&app_reachable, 60)); + + core_node = meshlink_get_node(mesh, "app1node1"); + assert(core_node); + fprintf(stderr, "\tapp1node2 Sending Channel request to app1node1 at : %lu\n", time(NULL)); + channel = meshlink_channel_open(mesh, core_node, CHANNEL_PORT, + channel_receive_cb, NULL, 0); + meshlink_set_channel_poll_cb(mesh, channel, poll_cb); + assert(wait_sync_flag(&channel_opened, 100)); + send_event(CHANNEL_OPENED); + + assert(wait_sync_flag(&channel_data_recieved, 100)); + send_event(CHANNEL_DATA_RECIEVED); + + core_node = meshlink_get_node(mesh, "app2node1"); + + if(NULL != core_node) { + send_event(SIG_ABORT); + assert(false); + } + + send_event(MESH_EVENT_COMPLETED); + + // All test steps executed - wait for signals to stop/start or close the mesh + + while(test_running) { + select(1, NULL, NULL, NULL, &main_loop_wait); + } + + meshlink_close(mesh); + + return EXIT_SUCCESS; +} \ No newline at end of file diff --git a/test/blackbox/test_cases_submesh01/node_sim_app2node1.c b/test/blackbox/test_cases_submesh01/node_sim_app2node1.c new file mode 100644 index 00000000..ced45aeb --- /dev/null +++ b/test/blackbox/test_cases_submesh01/node_sim_app2node1.c @@ -0,0 +1,220 @@ +/* + node_sim_peer.c -- Implementation of Node Simulation for Meshlink Testing + for meta connection test case 01 - re-connection of + two nodes when relay node goes down + 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 +#include +#include +#include +#include +#include +#include +#include "../common/common_handlers.h" +#include "../common/test_step.h" +#include "../common/mesh_event_handler.h" +#include "../../utils.h" + +#define CMD_LINE_ARG_NODENAME 1 +#define CMD_LINE_ARG_DEVCLASS 2 +#define CMD_LINE_ARG_CLIENTID 3 +#define CMD_LINE_ARG_IMPORTSTR 4 +#define CMD_LINE_ARG_INVITEURL 5 +#define CHANNEL_PORT 1234 + +static void channel_receive_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, const void *dat, size_t len); +static bool channel_accept(meshlink_handle_t *mesh, meshlink_channel_t *channel, uint16_t port, const void *dat, size_t len); + +static int client_id = -1; +static meshlink_handle_t *mesh = NULL; + +static struct sync_flag peer_reachable = {.mutex = PTHREAD_MUTEX_INITIALIZER, .cond = PTHREAD_COND_INITIALIZER, .flag = false}; +static struct sync_flag start_test = {.mutex = PTHREAD_MUTEX_INITIALIZER, .cond = PTHREAD_COND_INITIALIZER, .flag = false}; +static struct sync_flag channel_opened = {.mutex = PTHREAD_MUTEX_INITIALIZER, .cond = PTHREAD_COND_INITIALIZER, .flag = false}; +static struct sync_flag channel_data_recieved = {.mutex = PTHREAD_MUTEX_INITIALIZER, .cond = PTHREAD_COND_INITIALIZER, .flag = false}; + +static void send_event(mesh_event_t event) { + int attempts; + + for(attempts = 0; attempts < 5; attempts += 1) { + if(mesh_event_sock_send(client_id, event, NULL, 0)) { + break; + } + } + + assert(attempts < 5); + + return; +} + +static bool channel_accept(meshlink_handle_t *mesh, meshlink_channel_t *channel, uint16_t port, const void *dat, size_t len) { + (void)dat; + (void)len; + + assert(port == CHANNEL_PORT); + + fprintf(stderr, "\tapp2node1 got channel request from %s\n", channel->node->name); + + if(!strcmp(channel->node->name, "corenode1")) { + meshlink_set_channel_receive_cb(mesh, channel, channel_receive_cb); + mesh->priv = channel; + + return true; + } else if(!strcmp(channel->node->name, "app2node2")) { + fprintf(stderr, "\tapp2node1 accepting channel request from %s at %lu\n", channel->node->name, time(NULL)); + meshlink_set_channel_receive_cb(mesh, channel, channel_receive_cb); + mesh->priv = channel; + + return true; + } + + fprintf(stderr, "\tapp2node1 rejecting channel request from %s at %lu\n", channel->node->name, time(NULL)); + + return false; +} + +/* channel receive callback */ +static void channel_receive_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, const void *dat, size_t len) { + char *message = "Channel Message"; + char data[100] = {0}; + + if(len == 0) { + send_event(ERR_NETWORK); + return; + } + + memcpy(data, dat, len); + + fprintf(stderr, "\tapp2node1 got message from %s as %s\n", channel->node->name, data); + + if(!strcmp(channel->node->name, "corenode1")) { + if(!memcmp(dat, "Channel Message", len)) { + set_sync_flag(&channel_data_recieved, true); + } else if(!memcmp(dat, "failure", 7)) { + assert(false); + } + } else if(!strcmp(channel->node->name, "app2node2")) { + if(!memcmp(dat, "Channel Message", len)) { + assert(meshlink_channel_send(mesh, channel, message, strlen(message)) >= 0); + } else if(!memcmp(dat, "failure", 7)) { + assert(false); + } + } + + return; +} + +static void poll_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, size_t len) { + char *message = "Channel Message"; + char *node = (char *)channel->node->name; + (void)len; + meshlink_set_channel_poll_cb(mesh, channel, NULL); + fprintf(stderr, "\tapp2node1's Channel request has been accepted by corenode1 at : %lu\n", time(NULL)); + + if(0 == strcmp("corenode1", node)) { + set_sync_flag(&channel_opened, true); + } + + assert(meshlink_channel_send(mesh, channel, message, strlen(message)) >= 0); + return; +} + + +static void node_status_cb(meshlink_handle_t *mesh, meshlink_node_t *node, + bool reachable) { + if(!strcasecmp(node->name, "corenode1")) { + if(reachable) { + fprintf(stderr, "\tNode corenode1 became reachable\n"); + set_sync_flag(&peer_reachable, true); + } + } + + return; +} + +void mesh_start_test_handler(int a) { + fprintf(stderr, "Starting test in app2node1\n"); + set_sync_flag(&start_test, true); +} + +int main(int argc, char *argv[]) { + struct timeval main_loop_wait = { 2, 0 }; + meshlink_channel_t *channel = NULL; + meshlink_node_t *core_node = NULL; + + fprintf(stderr, "\tMesh node 'app2node1' starting up........\n"); + + // Import mesh event handler + + if((argv[CMD_LINE_ARG_CLIENTID]) && (argv[CMD_LINE_ARG_IMPORTSTR])) { + client_id = atoi(argv[CMD_LINE_ARG_CLIENTID]); + mesh_event_sock_connect(argv[CMD_LINE_ARG_IMPORTSTR]); + } + + // Setup required signals + + setup_signals(); + signal(SIGIO, mesh_start_test_handler); + + // Run peer node instance + + mesh = meshlink_open("app2node1conf", argv[CMD_LINE_ARG_NODENAME], + "test_channel_conn", atoi(argv[CMD_LINE_ARG_DEVCLASS])); + assert(mesh); + meshlink_set_log_cb(mesh, MESHLINK_DEBUG, meshlink_callback_logger); + meshlink_set_channel_accept_cb(mesh, channel_accept); + meshlink_set_node_status_cb(mesh, node_status_cb); + + if(argv[CMD_LINE_ARG_INVITEURL]) { + assert(meshlink_join(mesh, argv[CMD_LINE_ARG_INVITEURL])); + } + + assert(meshlink_start(mesh)); + + send_event(NODE_STARTED); + + // Wait for peer node to join + + assert(wait_sync_flag(&peer_reachable, 15)); + send_event(NODE_JOINED); + + while(false == wait_sync_flag(&start_test, 10)); + + // Open a channel to peer node + core_node = meshlink_get_node(mesh, "corenode1"); + assert(core_node); + fprintf(stderr, "\tapp2node1 Sending Channel request to corenode1 at : %lu\n", time(NULL)); + channel = meshlink_channel_open(mesh, core_node, CHANNEL_PORT, + channel_receive_cb, NULL, 0); + meshlink_set_channel_poll_cb(mesh, channel, poll_cb); + assert(wait_sync_flag(&channel_opened, 15)); + send_event(CHANNEL_OPENED); + + assert(wait_sync_flag(&channel_data_recieved, 30)); + send_event(CHANNEL_DATA_RECIEVED); + + // All test steps executed - wait for signals to stop/start or close the mesh + + while(test_running) { + select(1, NULL, NULL, NULL, &main_loop_wait); + } + + meshlink_close(mesh); + + return EXIT_SUCCESS; +} \ No newline at end of file diff --git a/test/blackbox/test_cases_submesh01/node_sim_app2node2.c b/test/blackbox/test_cases_submesh01/node_sim_app2node2.c new file mode 100644 index 00000000..4323988b --- /dev/null +++ b/test/blackbox/test_cases_submesh01/node_sim_app2node2.c @@ -0,0 +1,243 @@ +/* + node_sim_peer.c -- Implementation of Node Simulation for Meshlink Testing + for meta connection test case 01 - re-connection of + two nodes when relay node goes down + 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 +#include +#include +#include +#include +#include +#include +#include "../common/common_handlers.h" +#include "../common/test_step.h" +#include "../common/mesh_event_handler.h" +#include "../../utils.h" + +#define CMD_LINE_ARG_NODENAME 1 +#define CMD_LINE_ARG_DEVCLASS 2 +#define CMD_LINE_ARG_CLIENTID 3 +#define CMD_LINE_ARG_IMPORTSTR 4 +#define CMD_LINE_ARG_INVITEURL 5 +#define CHANNEL_PORT 1234 + +static void channel_receive_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, const void *dat, size_t len); +static bool channel_accept(meshlink_handle_t *mesh, meshlink_channel_t *channel, uint16_t port, const void *dat, size_t len); + +static int client_id = -1; +static meshlink_handle_t *mesh = NULL; + +static struct sync_flag peer_reachable = {.mutex = PTHREAD_MUTEX_INITIALIZER, .cond = PTHREAD_COND_INITIALIZER, .flag = false}; +static struct sync_flag start_test = {.mutex = PTHREAD_MUTEX_INITIALIZER, .cond = PTHREAD_COND_INITIALIZER, .flag = false}; +static struct sync_flag app_reachable = {.mutex = PTHREAD_MUTEX_INITIALIZER, .cond = PTHREAD_COND_INITIALIZER, .flag = false}; +static struct sync_flag channel_opened = {.mutex = PTHREAD_MUTEX_INITIALIZER, .cond = PTHREAD_COND_INITIALIZER, .flag = false}; +static struct sync_flag channel_data_recieved = {.mutex = PTHREAD_MUTEX_INITIALIZER, .cond = PTHREAD_COND_INITIALIZER, .flag = false}; + +static void send_event(mesh_event_t event) { + int attempts; + + for(attempts = 0; attempts < 5; attempts += 1) { + if(mesh_event_sock_send(client_id, event, NULL, 0)) { + break; + } + } + + assert(attempts < 5); + + return; +} + +static bool channel_accept(meshlink_handle_t *mesh, meshlink_channel_t *channel, uint16_t port, const void *dat, size_t len) { + (void)dat; + (void)len; + + assert(port == CHANNEL_PORT); + + fprintf(stderr, "\tapp2node2 got channel request from %s\n", channel->node->name); + + if(!strcmp(channel->node->name, "corenode1")) { + meshlink_set_channel_receive_cb(mesh, channel, channel_receive_cb); + mesh->priv = channel; + + return true; + } + + return false; +} + +/* channel receive callback */ +static void channel_receive_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, const void *dat, size_t len) { + char data[100] = {0}; + + if(len == 0) { + fprintf(stderr, "\tapp2node2 got error from %s at %lu\n", channel->node->name, time(NULL)); + send_event(ERR_NETWORK); + return; + } + + memcpy(data, dat, len); + + fprintf(stderr, "\tapp2node2 got message from %s as %s\n", channel->node->name, data); + + if(!strcmp(channel->node->name, "corenode1")) { + if(!memcmp(dat, "Channel Message", len)) { + set_sync_flag(&channel_data_recieved, true); + } else if(!memcmp(dat, "failure", 7)) { + assert(false); + } + } else if(!strcmp(channel->node->name, "app2node1")) { + if(!memcmp(dat, "Channel Message", len)) { + set_sync_flag(&channel_data_recieved, true); + } else if(!memcmp(dat, "failure", 7)) { + assert(false); + } + } else { + assert(false); + } + + return; +} + +static void poll_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, size_t len) { + char *message = "Channel Message"; + char *node = (char *)channel->node->name; + (void)len; + meshlink_set_channel_poll_cb(mesh, channel, NULL); + fprintf(stderr, "\tapp2node2's Channel request has been accepted by %s at : %lu\n", node, time(NULL)); + set_sync_flag(&channel_opened, true); + assert(meshlink_channel_send(mesh, channel, message, strlen(message)) >= 0); + return; +} + + +static void node_status_cb(meshlink_handle_t *mesh, meshlink_node_t *node, + bool reachable) { + if(!strcasecmp(node->name, "corenode1")) { + if(reachable) { + fprintf(stderr, "\tNode corenode1 became reachable\n"); + set_sync_flag(&peer_reachable, true); + } + } else if(!strcasecmp(node->name, "app2node1")) { + if(reachable) { + fprintf(stderr, "\tNode app2node1 became reachable\n"); + set_sync_flag(&app_reachable, true); + } + } + + return; +} + +void mesh_start_test_handler(int a) { + fprintf(stderr, "Starting test in app2node2\n"); + set_sync_flag(&start_test, true); +} + +int main(int argc, char *argv[]) { + struct timeval main_loop_wait = { 2, 0 }; + meshlink_channel_t *channel = NULL; + meshlink_node_t *core_node = NULL; + + fprintf(stderr, "\tMesh node 'app2node2' starting up........\n"); + + // Import mesh event handler + + if((argv[CMD_LINE_ARG_CLIENTID]) && (argv[CMD_LINE_ARG_IMPORTSTR])) { + client_id = atoi(argv[CMD_LINE_ARG_CLIENTID]); + mesh_event_sock_connect(argv[CMD_LINE_ARG_IMPORTSTR]); + } + + // Setup required signals + + setup_signals(); + signal(SIGIO, mesh_start_test_handler); + + // Run peer node instance + + mesh = meshlink_open("app2node2conf", argv[CMD_LINE_ARG_NODENAME], + "test_channel_conn", atoi(argv[CMD_LINE_ARG_DEVCLASS])); + assert(mesh); + meshlink_set_log_cb(mesh, MESHLINK_DEBUG, meshlink_callback_logger); + meshlink_set_channel_accept_cb(mesh, channel_accept); + meshlink_set_node_status_cb(mesh, node_status_cb); + + if(argv[CMD_LINE_ARG_INVITEURL]) { + assert(meshlink_join(mesh, argv[CMD_LINE_ARG_INVITEURL])); + } + + assert(meshlink_start(mesh)); + + send_event(NODE_STARTED); + + // Wait for peer node to join + + assert(wait_sync_flag(&peer_reachable, 15)); + send_event(NODE_JOINED); + + while(false == wait_sync_flag(&start_test, 10)); + + // Open a channel to peer node + core_node = meshlink_get_node(mesh, "corenode1"); + assert(core_node); + fprintf(stderr, "\tapp2node2 Sending Channel request to corenode1 at : %lu\n", time(NULL)); + channel = meshlink_channel_open(mesh, core_node, CHANNEL_PORT, + channel_receive_cb, NULL, 0); + meshlink_set_channel_poll_cb(mesh, channel, poll_cb); + assert(wait_sync_flag(&channel_opened, 30)); + send_event(CHANNEL_OPENED); + + assert(wait_sync_flag(&channel_data_recieved, 30)); + send_event(CHANNEL_DATA_RECIEVED); + + // Open a channel to peer node + channel_opened.flag = false; + channel_data_recieved.flag = false; + + assert(wait_sync_flag(&app_reachable, 60)); + + core_node = meshlink_get_node(mesh, "app2node1"); + assert(core_node); + fprintf(stderr, "\tapp2node2 Sending Channel request to app2node1 at : %lu\n", time(NULL)); + channel = meshlink_channel_open(mesh, core_node, CHANNEL_PORT, + channel_receive_cb, NULL, 0); + meshlink_set_channel_poll_cb(mesh, channel, poll_cb); + assert(wait_sync_flag(&channel_opened, 30)); + send_event(CHANNEL_OPENED); + + assert(wait_sync_flag(&channel_data_recieved, 30)); + send_event(CHANNEL_DATA_RECIEVED); + + core_node = meshlink_get_node(mesh, "app1node1"); + + if(NULL != core_node) { + send_event(SIG_ABORT); + assert(false); + } + + send_event(MESH_EVENT_COMPLETED); + + // All test steps executed - wait for signals to stop/start or close the mesh + + while(test_running) { + select(1, NULL, NULL, NULL, &main_loop_wait); + } + + meshlink_close(mesh); + + return EXIT_SUCCESS; +} \ No newline at end of file diff --git a/test/blackbox/test_cases_submesh01/node_sim_corenode1.c b/test/blackbox/test_cases_submesh01/node_sim_corenode1.c new file mode 100644 index 00000000..842e5d71 --- /dev/null +++ b/test/blackbox/test_cases_submesh01/node_sim_corenode1.c @@ -0,0 +1,188 @@ +/* + node_sim.c -- Implementation of Node Simulation for Meshlink Testing + for meta connection test case 01 - re-connection of + two nodes when relay node goes down + 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 +#include +#include +#include +#include +#include "../common/common_handlers.h" +#include "../common/test_step.h" +#include "../common/mesh_event_handler.h" +#include "../../utils.h" + +#define CMD_LINE_ARG_NODENAME 1 +#define CMD_LINE_ARG_DEVCLASS 2 +#define CMD_LINE_ARG_CLIENTID 3 +#define CMD_LINE_ARG_IMPORTSTR 4 +#define CMD_LINE_ARG_INVITEURL 5 +#define CHANNEL_PORT 1234 + +static bool conn_status = false; +static int client_id = -1; + +static struct sync_flag peer_reachable = {.mutex = PTHREAD_MUTEX_INITIALIZER, .cond = PTHREAD_COND_INITIALIZER, .flag = false}; +static struct sync_flag channel_opened = {.mutex = PTHREAD_MUTEX_INITIALIZER, .cond = PTHREAD_COND_INITIALIZER, .flag = false}; +static struct sync_flag channel_data_recieved = {.mutex = PTHREAD_MUTEX_INITIALIZER, .cond = PTHREAD_COND_INITIALIZER, .flag = false}; + +static meshlink_handle_t *mesh = NULL; + +static void mesh_send_message_handler(char *destination); + +static void send_event(mesh_event_t event) { + int attempts; + + for(attempts = 0; attempts < 5; attempts += 1) { + if(mesh_event_sock_send(client_id, event, NULL, 0)) { + break; + } + } + + assert(attempts < 5); + + return; +} + +/* channel receive callback */ +static void channel_receive_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, const void *dat, size_t len) { + char data[100] = {0}; + + if(len == 0) { + send_event(ERR_NETWORK); + return; + } + + memcpy(data, dat, len); + + fprintf(stderr, "corenode1 got message from %s as %s\n", channel->node->name, data); + + if(!memcmp(dat, "Channel Message", len)) { + mesh_send_message_handler(channel->node->name); + + if(0 == strcmp("corenode2", channel->node->name)) { + set_sync_flag(&channel_data_recieved, true); + } + } else if(!memcmp(dat, "failure", 7)) { + assert(false); + } + + return; +} + +static void node_status_cb(meshlink_handle_t *mesh, meshlink_node_t *node, + bool reachable) { + if(reachable) { + fprintf(stderr, "Node %s became reachable\n", node->name); + } else { + fprintf(stderr, "Node %s is unreachable\n", node->name); + } + + return; +} + +static void poll_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, size_t len) { + char *message = "Channel Message"; + char *node = channel->node->name; + (void)len; + meshlink_set_channel_poll_cb(mesh, channel, NULL); + fprintf(stderr, "corenode1's Channel request has been accepted by %s at : %lu\n", node, time(NULL)); + + if(0 == strcmp("corenode2", node)) { + set_sync_flag(&channel_opened, true); + } + + assert(meshlink_channel_send(mesh, channel, message, strlen(message)) >= 0); + return; +} + +/* channel receive callback */ +static bool channel_accept(meshlink_handle_t *mesh, meshlink_channel_t *channel, uint16_t port, const void *dat, size_t len) { + (void)dat; + (void)len; + + assert(port == CHANNEL_PORT); + + fprintf(stderr, "corenode1 got channel request from %s\n", channel->node->name); + meshlink_set_channel_receive_cb(mesh, channel, channel_receive_cb); + + return true; +} + +void mesh_send_message_handler(char *destination) { + meshlink_channel_t *channel = NULL; + meshlink_node_t *target_node = NULL; + + // Open a channel to destination node + target_node = meshlink_get_node(mesh, destination); + assert(target_node); + fprintf(stderr, "corenode1 Sending Channel request to %s at : %lu\n", destination, time(NULL)); + channel = meshlink_channel_open(mesh, target_node, CHANNEL_PORT, + channel_receive_cb, NULL, 0); + meshlink_set_channel_poll_cb(mesh, channel, poll_cb); +} + +int main(int argc, char *argv[]) { + struct timeval main_loop_wait = { 5, 0 }; + int i; + + // Import mesh event handler + + fprintf(stderr, "Mesh node 'corenode1' starting up........\n"); + + if((argv[CMD_LINE_ARG_CLIENTID]) && (argv[CMD_LINE_ARG_IMPORTSTR])) { + client_id = atoi(argv[CMD_LINE_ARG_CLIENTID]); + mesh_event_sock_connect(argv[CMD_LINE_ARG_IMPORTSTR]); + } + + setup_signals(); + + // Execute test steps + + mesh = meshlink_open("testconf", argv[CMD_LINE_ARG_NODENAME], + "test_channel_conn", atoi(argv[CMD_LINE_ARG_DEVCLASS])); + assert(mesh); + meshlink_set_log_cb(mesh, MESHLINK_DEBUG, meshlink_callback_logger); + meshlink_set_channel_accept_cb(mesh, channel_accept); + meshlink_set_node_status_cb(mesh, node_status_cb); + + if(argv[CMD_LINE_ARG_INVITEURL]) { + assert(meshlink_join(mesh, argv[CMD_LINE_ARG_INVITEURL])); + } + + assert(meshlink_start(mesh)); + + send_event(NODE_STARTED); + + assert(wait_sync_flag(&channel_opened, 10)); + send_event(CHANNEL_OPENED); + + assert(wait_sync_flag(&channel_data_recieved, 10)); + send_event(CHANNEL_DATA_RECIEVED); + + // All test steps executed - wait for signals to stop/start or close the mesh + + while(test_running) { + select(1, NULL, NULL, NULL, &main_loop_wait); + } + + meshlink_close(mesh); + + return 0; +} diff --git a/test/blackbox/test_cases_submesh01/node_sim_corenode2.c b/test/blackbox/test_cases_submesh01/node_sim_corenode2.c new file mode 100644 index 00000000..a7b4760b --- /dev/null +++ b/test/blackbox/test_cases_submesh01/node_sim_corenode2.c @@ -0,0 +1,200 @@ +/* + node_sim_peer.c -- Implementation of Node Simulation for Meshlink Testing + for meta connection test case 01 - re-connection of + two nodes when relay node goes down + 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 +#include +#include +#include +#include +#include +#include +#include "../common/common_handlers.h" +#include "../common/test_step.h" +#include "../common/mesh_event_handler.h" +#include "../../utils.h" + +#define CMD_LINE_ARG_NODENAME 1 +#define CMD_LINE_ARG_DEVCLASS 2 +#define CMD_LINE_ARG_CLIENTID 3 +#define CMD_LINE_ARG_IMPORTSTR 4 +#define CMD_LINE_ARG_INVITEURL 5 +#define CHANNEL_PORT 1234 + +static void channel_receive_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, const void *dat, size_t len); +static bool channel_accept(meshlink_handle_t *mesh, meshlink_channel_t *channel, uint16_t port, const void *dat, size_t len); + +static int client_id = -1; +static meshlink_handle_t *mesh = NULL; + +static struct sync_flag peer_reachable = {.mutex = PTHREAD_MUTEX_INITIALIZER, .cond = PTHREAD_COND_INITIALIZER, .flag = false}; +static struct sync_flag start_test = {.mutex = PTHREAD_MUTEX_INITIALIZER, .cond = PTHREAD_COND_INITIALIZER, .flag = false}; +static struct sync_flag channel_opened = {.mutex = PTHREAD_MUTEX_INITIALIZER, .cond = PTHREAD_COND_INITIALIZER, .flag = false}; +static struct sync_flag channel_data_recieved = {.mutex = PTHREAD_MUTEX_INITIALIZER, .cond = PTHREAD_COND_INITIALIZER, .flag = false}; + +static void send_event(mesh_event_t event) { + int attempts; + + for(attempts = 0; attempts < 5; attempts += 1) { + if(mesh_event_sock_send(client_id, event, NULL, 0)) { + break; + } + } + + assert(attempts < 5); + + return; +} + +static bool channel_accept(meshlink_handle_t *mesh, meshlink_channel_t *channel, uint16_t port, const void *dat, size_t len) { + (void)dat; + (void)len; + + assert(port == CHANNEL_PORT); + + fprintf(stderr, "corenode2 got channel request from %s", channel->node->name); + + if(!strcmp(channel->node->name, "corenode1")) { + meshlink_set_channel_receive_cb(mesh, channel, channel_receive_cb); + mesh->priv = channel; + + return true; + } + + return false; +} + +/* channel receive callback */ +static void channel_receive_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, const void *dat, size_t len) { + char data[100] = {0}; + + if(len == 0) { + send_event(ERR_NETWORK); + return; + } + + memcpy(data, dat, len); + + fprintf(stderr, "corenode2 got message from %s as %s", channel->node->name, data); + + if(!strcmp(channel->node->name, "corenode1")) { + if(!memcmp(dat, "Channel Message", len)) { + set_sync_flag(&channel_data_recieved, true); + } else if(!memcmp(dat, "failure", 7)) { + assert(false); + } + } + + return; +} + +static void poll_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, size_t len) { + char *message = "Channel Message"; + (void)len; + meshlink_set_channel_poll_cb(mesh, channel, NULL); + fprintf(stderr, "corenode2's Channel request has been accepted by corenode1 at : %lu", time(NULL)); + set_sync_flag(&channel_opened, true); + assert(meshlink_channel_send(mesh, channel, message, strlen(message)) >= 0); + return; +} + + +static void node_status_cb(meshlink_handle_t *mesh, meshlink_node_t *node, + bool reachable) { + if(!strcasecmp(node->name, "corenode1")) { + if(reachable) { + fprintf(stderr, "Node corenode2 became reachable"); + set_sync_flag(&peer_reachable, true); + } + } + + return; +} + +void mesh_start_test_handler(int a) { + fprintf(stderr, "Starting test in corenode2\n"); + set_sync_flag(&start_test, true); +} + +int main(int argc, char *argv[]) { + struct timeval main_loop_wait = { 2, 0 }; + meshlink_channel_t *channel = NULL; + meshlink_node_t *core_node = NULL; + + fprintf(stderr, "Mesh node 'corenode2' starting up........\n"); + + // Import mesh event handler + + if((argv[CMD_LINE_ARG_CLIENTID]) && (argv[CMD_LINE_ARG_IMPORTSTR])) { + client_id = atoi(argv[CMD_LINE_ARG_CLIENTID]); + mesh_event_sock_connect(argv[CMD_LINE_ARG_IMPORTSTR]); + } + + // Setup required signals + + setup_signals(); + signal(SIGIO, mesh_start_test_handler); + + // Run peer node instance + + mesh = meshlink_open("corenode1conf", argv[CMD_LINE_ARG_NODENAME], + "test_channel_conn", atoi(argv[CMD_LINE_ARG_DEVCLASS])); + assert(mesh); + meshlink_set_log_cb(mesh, MESHLINK_DEBUG, meshlink_callback_logger); + meshlink_set_channel_accept_cb(mesh, channel_accept); + meshlink_set_node_status_cb(mesh, node_status_cb); + + if(argv[CMD_LINE_ARG_INVITEURL]) { + assert(meshlink_join(mesh, argv[CMD_LINE_ARG_INVITEURL])); + } + + assert(meshlink_start(mesh)); + + send_event(NODE_STARTED); + + // Wait for peer node to join + + assert(wait_sync_flag(&peer_reachable, 15)); + send_event(NODE_JOINED); + + while(false == wait_sync_flag(&start_test, 10)); + + // Open a channel to peer node + core_node = meshlink_get_node(mesh, "corenode1"); + assert(core_node); + fprintf(stderr, "corenode2 Sending Channel request to corenode1 at : %lu", time(NULL)); + channel = meshlink_channel_open(mesh, core_node, CHANNEL_PORT, + channel_receive_cb, NULL, 0); + meshlink_set_channel_poll_cb(mesh, channel, poll_cb); + assert(wait_sync_flag(&channel_opened, 15)); + send_event(CHANNEL_OPENED); + + assert(wait_sync_flag(&channel_data_recieved, 10)); + send_event(CHANNEL_DATA_RECIEVED); + + // All test steps executed - wait for signals to stop/start or close the mesh + + while(test_running) { + select(1, NULL, NULL, NULL, &main_loop_wait); + } + + meshlink_close(mesh); + + return EXIT_SUCCESS; +} \ No newline at end of file diff --git a/test/blackbox/test_cases_submesh02/Makefile.am b/test/blackbox/test_cases_submesh02/Makefile.am new file mode 100644 index 00000000..bb0ff44b --- /dev/null +++ b/test/blackbox/test_cases_submesh02/Makefile.am @@ -0,0 +1,25 @@ +check_PROGRAMS = node_sim_corenode1 node_sim_corenode2 node_sim_app1node1 node_sim_app1node2 node_sim_app2node1 node_sim_app2node2 + +node_sim_corenode1_SOURCES = node_sim_corenode1.c ../common/common_handlers.c ../common/test_step.c ../common/mesh_event_handler.c ../../utils.c +node_sim_corenode1_LDADD = ../../../src/libmeshlink.la +node_sim_corenode1_CFLAGS = -D_GNU_SOURCE + +node_sim_corenode2_SOURCES = node_sim_corenode2.c ../common/common_handlers.c ../common/test_step.c ../common/mesh_event_handler.c ../../utils.c +node_sim_corenode2_LDADD = ../../../src/libmeshlink.la +node_sim_corenode2_CFLAGS = -D_GNU_SOURCE + +node_sim_app1node1_SOURCES = node_sim_app1node1.c ../common/common_handlers.c ../common/test_step.c ../common/mesh_event_handler.c ../../utils.c +node_sim_app1node1_LDADD = ../../../src/libmeshlink.la +node_sim_app1node1_CFLAGS = -D_GNU_SOURCE + +node_sim_app1node2_SOURCES = node_sim_app1node2.c ../common/common_handlers.c ../common/test_step.c ../common/mesh_event_handler.c ../../utils.c +node_sim_app1node2_LDADD = ../../../src/libmeshlink.la +node_sim_app1node2_CFLAGS = -D_GNU_SOURCE + +node_sim_app2node1_SOURCES = node_sim_app2node1.c ../common/common_handlers.c ../common/test_step.c ../common/mesh_event_handler.c ../../utils.c +node_sim_app2node1_LDADD = ../../../src/libmeshlink.la +node_sim_app2node1_CFLAGS = -D_GNU_SOURCE + +node_sim_app2node2_SOURCES = node_sim_app2node2.c ../common/common_handlers.c ../common/test_step.c ../common/mesh_event_handler.c ../../utils.c +node_sim_app2node2_LDADD = ../../../src/libmeshlink.la +node_sim_app2node2_CFLAGS = -D_GNU_SOURCE diff --git a/test/blackbox/test_cases_submesh02/node_sim_app1node1.c b/test/blackbox/test_cases_submesh02/node_sim_app1node1.c new file mode 100644 index 00000000..d5423578 --- /dev/null +++ b/test/blackbox/test_cases_submesh02/node_sim_app1node1.c @@ -0,0 +1,221 @@ +/* + node_sim_peer.c -- Implementation of Node Simulation for Meshlink Testing + for meta connection test case 01 - re-connection of + two nodes when relay node goes down + 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 +#include +#include +#include +#include +#include +#include +#include "../common/common_handlers.h" +#include "../common/test_step.h" +#include "../common/mesh_event_handler.h" +#include "../../utils.h" + +#define CMD_LINE_ARG_NODENAME 1 +#define CMD_LINE_ARG_DEVCLASS 2 +#define CMD_LINE_ARG_CLIENTID 3 +#define CMD_LINE_ARG_IMPORTSTR 4 +#define CMD_LINE_ARG_INVITEURL 5 +#define CHANNEL_PORT 1234 + +static void channel_receive_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, const void *dat, size_t len); +static bool channel_accept(meshlink_handle_t *mesh, meshlink_channel_t *channel, uint16_t port, const void *dat, size_t len); + +static int client_id = -1; +static meshlink_handle_t *mesh = NULL; + +static struct sync_flag peer_reachable = {.mutex = PTHREAD_MUTEX_INITIALIZER, .cond = PTHREAD_COND_INITIALIZER, .flag = false}; +static struct sync_flag start_test = {.mutex = PTHREAD_MUTEX_INITIALIZER, .cond = PTHREAD_COND_INITIALIZER, .flag = false}; +static struct sync_flag channel_opened = {.mutex = PTHREAD_MUTEX_INITIALIZER, .cond = PTHREAD_COND_INITIALIZER, .flag = false}; +static struct sync_flag channel_data_recieved = {.mutex = PTHREAD_MUTEX_INITIALIZER, .cond = PTHREAD_COND_INITIALIZER, .flag = false}; + +static void send_event(mesh_event_t event) { + int attempts; + + for(attempts = 0; attempts < 5; attempts += 1) { + if(mesh_event_sock_send(client_id, event, NULL, 0)) { + break; + } + } + + assert(attempts < 5); + + return; +} + +static bool channel_accept(meshlink_handle_t *mesh, meshlink_channel_t *channel, uint16_t port, const void *dat, size_t len) { + (void)dat; + (void)len; + + assert(port == CHANNEL_PORT); + + fprintf(stderr, "\tapp1node1 got channel request from %s\n", channel->node->name); + + if(!strcmp(channel->node->name, "corenode1")) { + fprintf(stderr, "\tapp1node1 accepting channel request from %s at %lu\n", channel->node->name, time(NULL)); + meshlink_set_channel_receive_cb(mesh, channel, channel_receive_cb); + mesh->priv = channel; + + return true; + } else if(!strcmp(channel->node->name, "app1node2")) { + fprintf(stderr, "\tapp1node1 accepting channel request from %s at %lu\n", channel->node->name, time(NULL)); + meshlink_set_channel_receive_cb(mesh, channel, channel_receive_cb); + mesh->priv = channel; + + return true; + } + + fprintf(stderr, "\tapp1node1 rejecting channel request from %s at %lu\n", channel->node->name, time(NULL)); + return false; +} + +/* channel receive callback */ +static void channel_receive_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, const void *dat, size_t len) { + char data[100] = {0}; + char *message = "Channel Message"; + + if(len == 0) { + fprintf(stderr, "\tapp1node1 got error from %s at %lu\n", channel->node->name, time(NULL)); + send_event(ERR_NETWORK); + return; + } + + memcpy(data, dat, len); + + fprintf(stderr, "\tapp1node1 got message from %s as %s\n", channel->node->name, data); + + if(!strcmp(channel->node->name, "corenode1")) { + if(!memcmp(dat, "Channel Message", len)) { + set_sync_flag(&channel_data_recieved, true); + } else if(!memcmp(dat, "failure", 7)) { + assert(false); + } + } else if(!strcmp(channel->node->name, "app1node2")) { + if(!memcmp(dat, "Channel Message", len)) { + assert(meshlink_channel_send(mesh, channel, message, strlen(message)) >= 0); + } else if(!memcmp(dat, "failure", 7)) { + assert(false); + } + } + + return; +} + +static void poll_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, size_t len) { + char *message = "Channel Message"; + char *node = (char *)channel->node->name; + (void)len; + meshlink_set_channel_poll_cb(mesh, channel, NULL); + fprintf(stderr, "\tapp1node1's Channel request has been accepted by %s at : %lu\n", node, time(NULL)); + + if(0 == strcmp("corenode1", node)) { + set_sync_flag(&channel_opened, true); + } + + assert(meshlink_channel_send(mesh, channel, message, strlen(message)) >= 0); + return; +} + + +static void node_status_cb(meshlink_handle_t *mesh, meshlink_node_t *node, + bool reachable) { + if(!strcasecmp(node->name, "corenode1")) { + if(reachable) { + fprintf(stderr, "\tNode corenode1 became reachable\n"); + set_sync_flag(&peer_reachable, true); + } + } + + return; +} + +void mesh_start_test_handler(int a) { + fprintf(stderr, "Starting test in app1node1\n"); + set_sync_flag(&start_test, true); +} + +int main(int argc, char *argv[]) { + struct timeval main_loop_wait = { 2, 0 }; + meshlink_channel_t *channel = NULL; + meshlink_node_t *core_node = NULL; + + fprintf(stderr, "\tMesh node 'app1node1' starting up........\n"); + + // Import mesh event handler + + if((argv[CMD_LINE_ARG_CLIENTID]) && (argv[CMD_LINE_ARG_IMPORTSTR])) { + client_id = atoi(argv[CMD_LINE_ARG_CLIENTID]); + mesh_event_sock_connect(argv[CMD_LINE_ARG_IMPORTSTR]); + } + + // Setup required signals + + setup_signals(); + signal(SIGIO, mesh_start_test_handler); + + // Run peer node instance + + mesh = meshlink_open("app1node1conf", argv[CMD_LINE_ARG_NODENAME], + "test_channel_conn", atoi(argv[CMD_LINE_ARG_DEVCLASS])); + assert(mesh); + meshlink_set_log_cb(mesh, MESHLINK_DEBUG, meshlink_callback_logger); + meshlink_set_channel_accept_cb(mesh, channel_accept); + meshlink_set_node_status_cb(mesh, node_status_cb); + + if(argv[CMD_LINE_ARG_INVITEURL]) { + assert(meshlink_join(mesh, argv[CMD_LINE_ARG_INVITEURL])); + } + + assert(meshlink_start(mesh)); + + send_event(NODE_STARTED); + + // Wait for peer node to join + + assert(wait_sync_flag(&peer_reachable, 15)); + send_event(NODE_JOINED); + + while(false == wait_sync_flag(&start_test, 10)); + + // Open a channel to peer node + core_node = meshlink_get_node(mesh, "corenode1"); + assert(core_node); + fprintf(stderr, "\tapp1node1 Sending Channel request to corenode1 at : %lu\n", time(NULL)); + channel = meshlink_channel_open(mesh, core_node, CHANNEL_PORT, + channel_receive_cb, NULL, 0); + meshlink_set_channel_poll_cb(mesh, channel, poll_cb); + assert(wait_sync_flag(&channel_opened, 15)); + send_event(CHANNEL_OPENED); + + assert(wait_sync_flag(&channel_data_recieved, 30)); + send_event(CHANNEL_DATA_RECIEVED); + + // All test steps executed - wait for signals to stop/start or close the mesh + + while(test_running) { + select(1, NULL, NULL, NULL, &main_loop_wait); + } + + meshlink_close(mesh); + + return EXIT_SUCCESS; +} \ No newline at end of file diff --git a/test/blackbox/test_cases_submesh02/node_sim_app1node2.c b/test/blackbox/test_cases_submesh02/node_sim_app1node2.c new file mode 100644 index 00000000..3656b299 --- /dev/null +++ b/test/blackbox/test_cases_submesh02/node_sim_app1node2.c @@ -0,0 +1,271 @@ +/* + node_sim_peer.c -- Implementation of Node Simulation for Meshlink Testing + for meta connection test case 01 - re-connection of + two nodes when relay node goes down + 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 +#include +#include +#include +#include +#include +#include +#include "../common/common_handlers.h" +#include "../common/test_step.h" +#include "../common/mesh_event_handler.h" +#include "../../utils.h" + +#define CMD_LINE_ARG_NODENAME 1 +#define CMD_LINE_ARG_DEVCLASS 2 +#define CMD_LINE_ARG_CLIENTID 3 +#define CMD_LINE_ARG_IMPORTSTR 4 +#define CMD_LINE_ARG_INVITEURL 5 +#define CHANNEL_PORT 1234 + +static void channel_receive_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, const void *dat, size_t len); +static bool channel_accept(meshlink_handle_t *mesh, meshlink_channel_t *channel, uint16_t port, const void *dat, size_t len); + +static int client_id = -1; +static meshlink_handle_t *mesh = NULL; + +static struct sync_flag peer_reachable = {.mutex = PTHREAD_MUTEX_INITIALIZER, .cond = PTHREAD_COND_INITIALIZER, .flag = false}; +static struct sync_flag start_test = {.mutex = PTHREAD_MUTEX_INITIALIZER, .cond = PTHREAD_COND_INITIALIZER, .flag = false}; +static struct sync_flag app_reachable = {.mutex = PTHREAD_MUTEX_INITIALIZER, .cond = PTHREAD_COND_INITIALIZER, .flag = false}; +static struct sync_flag channel_opened = {.mutex = PTHREAD_MUTEX_INITIALIZER, .cond = PTHREAD_COND_INITIALIZER, .flag = false}; +static struct sync_flag channel_data_recieved = {.mutex = PTHREAD_MUTEX_INITIALIZER, .cond = PTHREAD_COND_INITIALIZER, .flag = false}; + +static void send_event(mesh_event_t event) { + int attempts; + + for(attempts = 0; attempts < 5; attempts += 1) { + if(mesh_event_sock_send(client_id, event, NULL, 0)) { + break; + } + } + + assert(attempts < 5); + + return; +} + +static bool channel_accept(meshlink_handle_t *mesh, meshlink_channel_t *channel, uint16_t port, const void *dat, size_t len) { + (void)dat; + (void)len; + + assert(port == CHANNEL_PORT); + + fprintf(stderr, "\tapp1node2 got channel request from %s\n", channel->node->name); + + if(!strcmp(channel->node->name, "corenode1")) { + meshlink_set_channel_receive_cb(mesh, channel, channel_receive_cb); + mesh->priv = channel; + + return true; + } + + return false; +} + +/* channel receive callback */ +static void channel_receive_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, const void *dat, size_t len) { + char data[100] = {0}; + + if(len == 0) { + fprintf(stderr, "\tapp1node2 got error from %s at %lu\n", channel->node->name, time(NULL)); + send_event(ERR_NETWORK); + return; + } + + memcpy(data, dat, len); + + fprintf(stderr, "\tapp1node2 got message from %s as %s\n", channel->node->name, data); + + if(!strcmp(channel->node->name, "corenode1")) { + if(!memcmp(dat, "Channel Message", len)) { + set_sync_flag(&channel_data_recieved, true); + } else if(!memcmp(dat, "failure", 7)) { + assert(false); + } + } else if(!strcmp(channel->node->name, "app1node1")) { + if(!memcmp(dat, "Channel Message", len)) { + set_sync_flag(&channel_data_recieved, true); + } else if(!memcmp(dat, "failure", 7)) { + assert(false); + } + } else { + assert(false); + } + + return; +} + +static void poll_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, size_t len) { + char *message = "Channel Message"; + char *node = (char *)channel->node->name; + (void)len; + meshlink_set_channel_poll_cb(mesh, channel, NULL); + fprintf(stderr, "\tapp1node2's Channel request has been accepted by %s at : %lu\n", node, time(NULL)); + set_sync_flag(&channel_opened, true); + assert(meshlink_channel_send(mesh, channel, message, strlen(message)) >= 0); + return; +} + + +static void node_status_cb(meshlink_handle_t *mesh, meshlink_node_t *node, + bool reachable) { + if(!strcasecmp(node->name, "corenode1")) { + if(reachable) { + fprintf(stderr, "\tNode corenode1 became reachable\n"); + set_sync_flag(&peer_reachable, true); + } + } else if(!strcasecmp(node->name, "app1node1")) { + if(reachable) { + fprintf(stderr, "\tNode app1node1 became reachable\n"); + set_sync_flag(&app_reachable, true); + } + } + + return; +} + +void mesh_start_test_handler(int a) { + fprintf(stderr, "Starting test in app1node2\n"); + set_sync_flag(&start_test, true); +} + +int main(int argc, char *argv[]) { + size_t num_nodes, i; + struct timeval main_loop_wait = { 2, 0 }; + meshlink_channel_t *channel = NULL; + meshlink_node_t *core_node = NULL; + meshlink_node_t **node_handles = NULL; + + fprintf(stderr, "\tMesh node 'app1node2' starting up........\n"); + + // Import mesh event handler + + if((argv[CMD_LINE_ARG_CLIENTID]) && (argv[CMD_LINE_ARG_IMPORTSTR])) { + client_id = atoi(argv[CMD_LINE_ARG_CLIENTID]); + mesh_event_sock_connect(argv[CMD_LINE_ARG_IMPORTSTR]); + } + + // Setup required signals + + setup_signals(); + signal(SIGIO, mesh_start_test_handler); + + // Run peer node instance + + mesh = meshlink_open("app1node2conf", argv[CMD_LINE_ARG_NODENAME], + "test_channel_conn", atoi(argv[CMD_LINE_ARG_DEVCLASS])); + assert(mesh); + meshlink_set_log_cb(mesh, MESHLINK_DEBUG, meshlink_callback_logger); + meshlink_set_channel_accept_cb(mesh, channel_accept); + meshlink_set_node_status_cb(mesh, node_status_cb); + + if(argv[CMD_LINE_ARG_INVITEURL]) { + assert(meshlink_join(mesh, argv[CMD_LINE_ARG_INVITEURL])); + } + + assert(meshlink_start(mesh)); + + send_event(NODE_STARTED); + + // Wait for peer node to join + + assert(wait_sync_flag(&peer_reachable, 15)); + send_event(NODE_JOINED); + + while(false == wait_sync_flag(&start_test, 10)); + + // Open a channel to peer node + core_node = meshlink_get_node(mesh, "corenode1"); + assert(core_node); + fprintf(stderr, "\tapp1node2 Sending Channel request to corenode1 at : %lu\n", time(NULL)); + channel = meshlink_channel_open(mesh, core_node, CHANNEL_PORT, + channel_receive_cb, NULL, 0); + meshlink_set_channel_poll_cb(mesh, channel, poll_cb); + assert(wait_sync_flag(&channel_opened, 15)); + send_event(CHANNEL_OPENED); + + assert(wait_sync_flag(&channel_data_recieved, 30)); + send_event(CHANNEL_DATA_RECIEVED); + + // Open a channel to peer node + channel_opened.flag = false; + channel_data_recieved.flag = false; + + assert(wait_sync_flag(&app_reachable, 60)); + + core_node = meshlink_get_node(mesh, "app1node1"); + assert(core_node); + fprintf(stderr, "\tapp1node2 Sending Channel request to app1node1 at : %lu\n", time(NULL)); + channel = meshlink_channel_open(mesh, core_node, CHANNEL_PORT, + channel_receive_cb, NULL, 0); + meshlink_set_channel_poll_cb(mesh, channel, poll_cb); + assert(wait_sync_flag(&channel_opened, 30)); + send_event(CHANNEL_OPENED); + + assert(wait_sync_flag(&channel_data_recieved, 30)); + send_event(CHANNEL_DATA_RECIEVED); + + num_nodes = 0; + node_handles = meshlink_get_all_nodes(mesh, NULL, &num_nodes); + fprintf(stderr, "\tGot %d nodes in list with error : %s\n", num_nodes, meshlink_strerror(meshlink_errno)); + assert(node_handles); + assert((num_nodes == 4)); + + for(i = 0; i < num_nodes; i++) { + fprintf(stderr, "\tChecking the node : %s\n", node_handles[i]->name); + + if((0 == strcmp(node_handles[i]->name, "app2node1")) || (0 == strcmp(node_handles[i]->name, "app2node2"))) { + send_event(SIG_ABORT); + assert(false); + } + } + + meshlink_node_t *node = meshlink_get_self(mesh); + assert(node); + meshlink_submesh_t *submesh = meshlink_get_node_submesh(mesh, node); + assert(submesh); + + node_handles = meshlink_get_all_nodes_by_submesh(mesh, submesh, node_handles, &num_nodes); + assert(node_handles); + assert((num_nodes == 2)); + + for(i = 0; i < num_nodes; i++) { + fprintf(stderr, "\tChecking the node : %s\n", node_handles[i]->name); + + if((0 == strcmp(node_handles[i]->name, "app2node1")) || (0 == strcmp(node_handles[i]->name, "app2node2"))) { + send_event(SIG_ABORT); + assert(false); + } + } + + send_event(MESH_EVENT_COMPLETED); + + // All test steps executed - wait for signals to stop/start or close the mesh + + while(test_running) { + select(1, NULL, NULL, NULL, &main_loop_wait); + } + + meshlink_close(mesh); + + return EXIT_SUCCESS; +} \ No newline at end of file diff --git a/test/blackbox/test_cases_submesh02/node_sim_app2node1.c b/test/blackbox/test_cases_submesh02/node_sim_app2node1.c new file mode 100644 index 00000000..ced45aeb --- /dev/null +++ b/test/blackbox/test_cases_submesh02/node_sim_app2node1.c @@ -0,0 +1,220 @@ +/* + node_sim_peer.c -- Implementation of Node Simulation for Meshlink Testing + for meta connection test case 01 - re-connection of + two nodes when relay node goes down + 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 +#include +#include +#include +#include +#include +#include +#include "../common/common_handlers.h" +#include "../common/test_step.h" +#include "../common/mesh_event_handler.h" +#include "../../utils.h" + +#define CMD_LINE_ARG_NODENAME 1 +#define CMD_LINE_ARG_DEVCLASS 2 +#define CMD_LINE_ARG_CLIENTID 3 +#define CMD_LINE_ARG_IMPORTSTR 4 +#define CMD_LINE_ARG_INVITEURL 5 +#define CHANNEL_PORT 1234 + +static void channel_receive_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, const void *dat, size_t len); +static bool channel_accept(meshlink_handle_t *mesh, meshlink_channel_t *channel, uint16_t port, const void *dat, size_t len); + +static int client_id = -1; +static meshlink_handle_t *mesh = NULL; + +static struct sync_flag peer_reachable = {.mutex = PTHREAD_MUTEX_INITIALIZER, .cond = PTHREAD_COND_INITIALIZER, .flag = false}; +static struct sync_flag start_test = {.mutex = PTHREAD_MUTEX_INITIALIZER, .cond = PTHREAD_COND_INITIALIZER, .flag = false}; +static struct sync_flag channel_opened = {.mutex = PTHREAD_MUTEX_INITIALIZER, .cond = PTHREAD_COND_INITIALIZER, .flag = false}; +static struct sync_flag channel_data_recieved = {.mutex = PTHREAD_MUTEX_INITIALIZER, .cond = PTHREAD_COND_INITIALIZER, .flag = false}; + +static void send_event(mesh_event_t event) { + int attempts; + + for(attempts = 0; attempts < 5; attempts += 1) { + if(mesh_event_sock_send(client_id, event, NULL, 0)) { + break; + } + } + + assert(attempts < 5); + + return; +} + +static bool channel_accept(meshlink_handle_t *mesh, meshlink_channel_t *channel, uint16_t port, const void *dat, size_t len) { + (void)dat; + (void)len; + + assert(port == CHANNEL_PORT); + + fprintf(stderr, "\tapp2node1 got channel request from %s\n", channel->node->name); + + if(!strcmp(channel->node->name, "corenode1")) { + meshlink_set_channel_receive_cb(mesh, channel, channel_receive_cb); + mesh->priv = channel; + + return true; + } else if(!strcmp(channel->node->name, "app2node2")) { + fprintf(stderr, "\tapp2node1 accepting channel request from %s at %lu\n", channel->node->name, time(NULL)); + meshlink_set_channel_receive_cb(mesh, channel, channel_receive_cb); + mesh->priv = channel; + + return true; + } + + fprintf(stderr, "\tapp2node1 rejecting channel request from %s at %lu\n", channel->node->name, time(NULL)); + + return false; +} + +/* channel receive callback */ +static void channel_receive_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, const void *dat, size_t len) { + char *message = "Channel Message"; + char data[100] = {0}; + + if(len == 0) { + send_event(ERR_NETWORK); + return; + } + + memcpy(data, dat, len); + + fprintf(stderr, "\tapp2node1 got message from %s as %s\n", channel->node->name, data); + + if(!strcmp(channel->node->name, "corenode1")) { + if(!memcmp(dat, "Channel Message", len)) { + set_sync_flag(&channel_data_recieved, true); + } else if(!memcmp(dat, "failure", 7)) { + assert(false); + } + } else if(!strcmp(channel->node->name, "app2node2")) { + if(!memcmp(dat, "Channel Message", len)) { + assert(meshlink_channel_send(mesh, channel, message, strlen(message)) >= 0); + } else if(!memcmp(dat, "failure", 7)) { + assert(false); + } + } + + return; +} + +static void poll_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, size_t len) { + char *message = "Channel Message"; + char *node = (char *)channel->node->name; + (void)len; + meshlink_set_channel_poll_cb(mesh, channel, NULL); + fprintf(stderr, "\tapp2node1's Channel request has been accepted by corenode1 at : %lu\n", time(NULL)); + + if(0 == strcmp("corenode1", node)) { + set_sync_flag(&channel_opened, true); + } + + assert(meshlink_channel_send(mesh, channel, message, strlen(message)) >= 0); + return; +} + + +static void node_status_cb(meshlink_handle_t *mesh, meshlink_node_t *node, + bool reachable) { + if(!strcasecmp(node->name, "corenode1")) { + if(reachable) { + fprintf(stderr, "\tNode corenode1 became reachable\n"); + set_sync_flag(&peer_reachable, true); + } + } + + return; +} + +void mesh_start_test_handler(int a) { + fprintf(stderr, "Starting test in app2node1\n"); + set_sync_flag(&start_test, true); +} + +int main(int argc, char *argv[]) { + struct timeval main_loop_wait = { 2, 0 }; + meshlink_channel_t *channel = NULL; + meshlink_node_t *core_node = NULL; + + fprintf(stderr, "\tMesh node 'app2node1' starting up........\n"); + + // Import mesh event handler + + if((argv[CMD_LINE_ARG_CLIENTID]) && (argv[CMD_LINE_ARG_IMPORTSTR])) { + client_id = atoi(argv[CMD_LINE_ARG_CLIENTID]); + mesh_event_sock_connect(argv[CMD_LINE_ARG_IMPORTSTR]); + } + + // Setup required signals + + setup_signals(); + signal(SIGIO, mesh_start_test_handler); + + // Run peer node instance + + mesh = meshlink_open("app2node1conf", argv[CMD_LINE_ARG_NODENAME], + "test_channel_conn", atoi(argv[CMD_LINE_ARG_DEVCLASS])); + assert(mesh); + meshlink_set_log_cb(mesh, MESHLINK_DEBUG, meshlink_callback_logger); + meshlink_set_channel_accept_cb(mesh, channel_accept); + meshlink_set_node_status_cb(mesh, node_status_cb); + + if(argv[CMD_LINE_ARG_INVITEURL]) { + assert(meshlink_join(mesh, argv[CMD_LINE_ARG_INVITEURL])); + } + + assert(meshlink_start(mesh)); + + send_event(NODE_STARTED); + + // Wait for peer node to join + + assert(wait_sync_flag(&peer_reachable, 15)); + send_event(NODE_JOINED); + + while(false == wait_sync_flag(&start_test, 10)); + + // Open a channel to peer node + core_node = meshlink_get_node(mesh, "corenode1"); + assert(core_node); + fprintf(stderr, "\tapp2node1 Sending Channel request to corenode1 at : %lu\n", time(NULL)); + channel = meshlink_channel_open(mesh, core_node, CHANNEL_PORT, + channel_receive_cb, NULL, 0); + meshlink_set_channel_poll_cb(mesh, channel, poll_cb); + assert(wait_sync_flag(&channel_opened, 15)); + send_event(CHANNEL_OPENED); + + assert(wait_sync_flag(&channel_data_recieved, 30)); + send_event(CHANNEL_DATA_RECIEVED); + + // All test steps executed - wait for signals to stop/start or close the mesh + + while(test_running) { + select(1, NULL, NULL, NULL, &main_loop_wait); + } + + meshlink_close(mesh); + + return EXIT_SUCCESS; +} \ No newline at end of file diff --git a/test/blackbox/test_cases_submesh02/node_sim_app2node2.c b/test/blackbox/test_cases_submesh02/node_sim_app2node2.c new file mode 100644 index 00000000..b87a4848 --- /dev/null +++ b/test/blackbox/test_cases_submesh02/node_sim_app2node2.c @@ -0,0 +1,274 @@ +/* + node_sim_peer.c -- Implementation of Node Simulation for Meshlink Testing + for meta connection test case 01 - re-connection of + two nodes when relay node goes down + 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 +#include +#include +#include +#include +#include +#include +#include "../common/common_handlers.h" +#include "../common/test_step.h" +#include "../common/mesh_event_handler.h" +#include "../../utils.h" + +#define CMD_LINE_ARG_NODENAME 1 +#define CMD_LINE_ARG_DEVCLASS 2 +#define CMD_LINE_ARG_CLIENTID 3 +#define CMD_LINE_ARG_IMPORTSTR 4 +#define CMD_LINE_ARG_INVITEURL 5 +#define CHANNEL_PORT 1234 + +static void channel_receive_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, const void *dat, size_t len); +static bool channel_accept(meshlink_handle_t *mesh, meshlink_channel_t *channel, uint16_t port, const void *dat, size_t len); + +static int client_id = -1; +static meshlink_handle_t *mesh = NULL; + +static struct sync_flag peer_reachable = {.mutex = PTHREAD_MUTEX_INITIALIZER, .cond = PTHREAD_COND_INITIALIZER, .flag = false}; +static struct sync_flag start_test = {.mutex = PTHREAD_MUTEX_INITIALIZER, .cond = PTHREAD_COND_INITIALIZER, .flag = false}; +static struct sync_flag app_reachable = {.mutex = PTHREAD_MUTEX_INITIALIZER, .cond = PTHREAD_COND_INITIALIZER, .flag = false}; +static struct sync_flag channel_opened = {.mutex = PTHREAD_MUTEX_INITIALIZER, .cond = PTHREAD_COND_INITIALIZER, .flag = false}; +static struct sync_flag channel_data_recieved = {.mutex = PTHREAD_MUTEX_INITIALIZER, .cond = PTHREAD_COND_INITIALIZER, .flag = false}; + +static void send_event(mesh_event_t event) { + int attempts; + + for(attempts = 0; attempts < 5; attempts += 1) { + if(mesh_event_sock_send(client_id, event, NULL, 0)) { + break; + } + } + + assert(attempts < 5); + + return; +} + +static bool channel_accept(meshlink_handle_t *mesh, meshlink_channel_t *channel, uint16_t port, const void *dat, size_t len) { + (void)dat; + (void)len; + + assert(port == CHANNEL_PORT); + + fprintf(stderr, "\tapp2node2 got channel request from %s\n", channel->node->name); + + if(!strcmp(channel->node->name, "corenode1")) { + meshlink_set_channel_receive_cb(mesh, channel, channel_receive_cb); + mesh->priv = channel; + + return true; + } + + return false; +} + +/* channel receive callback */ +static void channel_receive_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, const void *dat, size_t len) { + char data[100] = {0}; + + if(len == 0) { + fprintf(stderr, "\tapp2node2 got error from %s at %lu\n", channel->node->name, time(NULL)); + send_event(ERR_NETWORK); + return; + } + + memcpy(data, dat, len); + + fprintf(stderr, "\tapp2node2 got message from %s as %s\n", channel->node->name, data); + + if(!strcmp(channel->node->name, "corenode1")) { + if(!memcmp(dat, "Channel Message", len)) { + set_sync_flag(&channel_data_recieved, true); + } else if(!memcmp(dat, "failure", 7)) { + assert(false); + } + } else if(!strcmp(channel->node->name, "app2node1")) { + if(!memcmp(dat, "Channel Message", len)) { + set_sync_flag(&channel_data_recieved, true); + } else if(!memcmp(dat, "failure", 7)) { + assert(false); + } + } else { + assert(false); + } + + return; +} + +static void poll_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, size_t len) { + char *message = "Channel Message"; + char *node = (char *)channel->node->name; + (void)len; + meshlink_set_channel_poll_cb(mesh, channel, NULL); + fprintf(stderr, "\tapp2node2's Channel request has been accepted by %s at : %lu\n", node, time(NULL)); + set_sync_flag(&channel_opened, true); + assert(meshlink_channel_send(mesh, channel, message, strlen(message)) >= 0); + return; +} + + +static void node_status_cb(meshlink_handle_t *mesh, meshlink_node_t *node, + bool reachable) { + if(!strcasecmp(node->name, "corenode1")) { + if(reachable) { + fprintf(stderr, "\tNode corenode1 became reachable\n"); + set_sync_flag(&peer_reachable, true); + } + } else if(!strcasecmp(node->name, "app2node1")) { + if(reachable) { + fprintf(stderr, "\tNode app2node1 became reachable\n"); + set_sync_flag(&app_reachable, true); + } + } + + return; +} + +void mesh_start_test_handler(int a) { + fprintf(stderr, "Starting test in app2node2\n"); + set_sync_flag(&start_test, true); +} + +int main(int argc, char *argv[]) { + size_t num_nodes, i; + struct timeval main_loop_wait = { 2, 0 }; + meshlink_channel_t *channel = NULL; + meshlink_node_t *core_node = NULL; + meshlink_node_t **node_handles = NULL; + + fprintf(stderr, "\tMesh node 'app2node2' starting up........\n"); + + // Import mesh event handler + + if((argv[CMD_LINE_ARG_CLIENTID]) && (argv[CMD_LINE_ARG_IMPORTSTR])) { + client_id = atoi(argv[CMD_LINE_ARG_CLIENTID]); + mesh_event_sock_connect(argv[CMD_LINE_ARG_IMPORTSTR]); + } + + // Setup required signals + + setup_signals(); + signal(SIGIO, mesh_start_test_handler); + + // Run peer node instance + + mesh = meshlink_open("app2node2conf", argv[CMD_LINE_ARG_NODENAME], + "test_channel_conn", atoi(argv[CMD_LINE_ARG_DEVCLASS])); + assert(mesh); + meshlink_set_log_cb(mesh, MESHLINK_DEBUG, meshlink_callback_logger); + meshlink_set_channel_accept_cb(mesh, channel_accept); + meshlink_set_node_status_cb(mesh, node_status_cb); + + if(argv[CMD_LINE_ARG_INVITEURL]) { + assert(meshlink_join(mesh, argv[CMD_LINE_ARG_INVITEURL])); + } + + assert(meshlink_start(mesh)); + + send_event(NODE_STARTED); + + // Wait for peer node to join + + assert(wait_sync_flag(&peer_reachable, 15)); + send_event(NODE_JOINED); + + while(false == wait_sync_flag(&start_test, 10)); + + // Open a channel to peer node + core_node = meshlink_get_node(mesh, "corenode1"); + assert(core_node); + fprintf(stderr, "\tapp2node2 Sending Channel request to corenode1 at : %lu\n", time(NULL)); + channel = meshlink_channel_open(mesh, core_node, CHANNEL_PORT, + channel_receive_cb, NULL, 0); + meshlink_set_channel_poll_cb(mesh, channel, poll_cb); + assert(wait_sync_flag(&channel_opened, 30)); + send_event(CHANNEL_OPENED); + + assert(wait_sync_flag(&channel_data_recieved, 30)); + send_event(CHANNEL_DATA_RECIEVED); + + // Open a channel to peer node + channel_opened.flag = false; + channel_data_recieved.flag = false; + + assert(wait_sync_flag(&app_reachable, 60)); + + core_node = meshlink_get_node(mesh, "app2node1"); + assert(core_node); + fprintf(stderr, "\tapp2node2 Sending Channel request to app2node1 at : %lu\n", time(NULL)); + channel = meshlink_channel_open(mesh, core_node, CHANNEL_PORT, + channel_receive_cb, NULL, 0); + meshlink_set_channel_poll_cb(mesh, channel, poll_cb); + assert(wait_sync_flag(&channel_opened, 15)); + send_event(CHANNEL_OPENED); + + assert(wait_sync_flag(&channel_data_recieved, 30)); + send_event(CHANNEL_DATA_RECIEVED); + + num_nodes = 0; + node_handles = meshlink_get_all_nodes(mesh, NULL, &num_nodes); + fprintf(stderr, "\tGot %d nodes in list with error : %s\n", num_nodes, meshlink_strerror(meshlink_errno)); + assert(node_handles); + assert((num_nodes == 4)); + + for(i = 0; i < num_nodes; i++) { + fprintf(stderr, "\tChecking the node : %s\n", node_handles[i]->name); + + if(0 == strcmp(node_handles[i]->name, "app1node1")) { + send_event(SIG_ABORT); + assert(false); + } else if(0 == strcmp(node_handles[i]->name, "app1node2")) { + send_event(SIG_ABORT); + assert(false); + } + } + + meshlink_node_t *node = meshlink_get_self(mesh); + assert(node); + meshlink_submesh_t *submesh = meshlink_get_node_submesh(mesh, node); + assert(submesh); + + node_handles = meshlink_get_all_nodes_by_submesh(mesh, submesh, node_handles, &num_nodes); + assert(node_handles); + assert((num_nodes == 2)); + + for(i = 0; i < num_nodes; i++) { + fprintf(stderr, "\tChecking the node : %s\n", node_handles[i]->name); + + if((0 == strcmp(node_handles[i]->name, "app1node1")) || (0 == strcmp(node_handles[i]->name, "app1node2"))) { + send_event(SIG_ABORT); + assert(false); + } + } + + send_event(MESH_EVENT_COMPLETED); + + // All test steps executed - wait for signals to stop/start or close the mesh + + while(test_running) { + select(1, NULL, NULL, NULL, &main_loop_wait); + } + + meshlink_close(mesh); + + return EXIT_SUCCESS; +} \ No newline at end of file diff --git a/test/blackbox/test_cases_submesh02/node_sim_corenode1.c b/test/blackbox/test_cases_submesh02/node_sim_corenode1.c new file mode 100644 index 00000000..842e5d71 --- /dev/null +++ b/test/blackbox/test_cases_submesh02/node_sim_corenode1.c @@ -0,0 +1,188 @@ +/* + node_sim.c -- Implementation of Node Simulation for Meshlink Testing + for meta connection test case 01 - re-connection of + two nodes when relay node goes down + 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 +#include +#include +#include +#include +#include "../common/common_handlers.h" +#include "../common/test_step.h" +#include "../common/mesh_event_handler.h" +#include "../../utils.h" + +#define CMD_LINE_ARG_NODENAME 1 +#define CMD_LINE_ARG_DEVCLASS 2 +#define CMD_LINE_ARG_CLIENTID 3 +#define CMD_LINE_ARG_IMPORTSTR 4 +#define CMD_LINE_ARG_INVITEURL 5 +#define CHANNEL_PORT 1234 + +static bool conn_status = false; +static int client_id = -1; + +static struct sync_flag peer_reachable = {.mutex = PTHREAD_MUTEX_INITIALIZER, .cond = PTHREAD_COND_INITIALIZER, .flag = false}; +static struct sync_flag channel_opened = {.mutex = PTHREAD_MUTEX_INITIALIZER, .cond = PTHREAD_COND_INITIALIZER, .flag = false}; +static struct sync_flag channel_data_recieved = {.mutex = PTHREAD_MUTEX_INITIALIZER, .cond = PTHREAD_COND_INITIALIZER, .flag = false}; + +static meshlink_handle_t *mesh = NULL; + +static void mesh_send_message_handler(char *destination); + +static void send_event(mesh_event_t event) { + int attempts; + + for(attempts = 0; attempts < 5; attempts += 1) { + if(mesh_event_sock_send(client_id, event, NULL, 0)) { + break; + } + } + + assert(attempts < 5); + + return; +} + +/* channel receive callback */ +static void channel_receive_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, const void *dat, size_t len) { + char data[100] = {0}; + + if(len == 0) { + send_event(ERR_NETWORK); + return; + } + + memcpy(data, dat, len); + + fprintf(stderr, "corenode1 got message from %s as %s\n", channel->node->name, data); + + if(!memcmp(dat, "Channel Message", len)) { + mesh_send_message_handler(channel->node->name); + + if(0 == strcmp("corenode2", channel->node->name)) { + set_sync_flag(&channel_data_recieved, true); + } + } else if(!memcmp(dat, "failure", 7)) { + assert(false); + } + + return; +} + +static void node_status_cb(meshlink_handle_t *mesh, meshlink_node_t *node, + bool reachable) { + if(reachable) { + fprintf(stderr, "Node %s became reachable\n", node->name); + } else { + fprintf(stderr, "Node %s is unreachable\n", node->name); + } + + return; +} + +static void poll_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, size_t len) { + char *message = "Channel Message"; + char *node = channel->node->name; + (void)len; + meshlink_set_channel_poll_cb(mesh, channel, NULL); + fprintf(stderr, "corenode1's Channel request has been accepted by %s at : %lu\n", node, time(NULL)); + + if(0 == strcmp("corenode2", node)) { + set_sync_flag(&channel_opened, true); + } + + assert(meshlink_channel_send(mesh, channel, message, strlen(message)) >= 0); + return; +} + +/* channel receive callback */ +static bool channel_accept(meshlink_handle_t *mesh, meshlink_channel_t *channel, uint16_t port, const void *dat, size_t len) { + (void)dat; + (void)len; + + assert(port == CHANNEL_PORT); + + fprintf(stderr, "corenode1 got channel request from %s\n", channel->node->name); + meshlink_set_channel_receive_cb(mesh, channel, channel_receive_cb); + + return true; +} + +void mesh_send_message_handler(char *destination) { + meshlink_channel_t *channel = NULL; + meshlink_node_t *target_node = NULL; + + // Open a channel to destination node + target_node = meshlink_get_node(mesh, destination); + assert(target_node); + fprintf(stderr, "corenode1 Sending Channel request to %s at : %lu\n", destination, time(NULL)); + channel = meshlink_channel_open(mesh, target_node, CHANNEL_PORT, + channel_receive_cb, NULL, 0); + meshlink_set_channel_poll_cb(mesh, channel, poll_cb); +} + +int main(int argc, char *argv[]) { + struct timeval main_loop_wait = { 5, 0 }; + int i; + + // Import mesh event handler + + fprintf(stderr, "Mesh node 'corenode1' starting up........\n"); + + if((argv[CMD_LINE_ARG_CLIENTID]) && (argv[CMD_LINE_ARG_IMPORTSTR])) { + client_id = atoi(argv[CMD_LINE_ARG_CLIENTID]); + mesh_event_sock_connect(argv[CMD_LINE_ARG_IMPORTSTR]); + } + + setup_signals(); + + // Execute test steps + + mesh = meshlink_open("testconf", argv[CMD_LINE_ARG_NODENAME], + "test_channel_conn", atoi(argv[CMD_LINE_ARG_DEVCLASS])); + assert(mesh); + meshlink_set_log_cb(mesh, MESHLINK_DEBUG, meshlink_callback_logger); + meshlink_set_channel_accept_cb(mesh, channel_accept); + meshlink_set_node_status_cb(mesh, node_status_cb); + + if(argv[CMD_LINE_ARG_INVITEURL]) { + assert(meshlink_join(mesh, argv[CMD_LINE_ARG_INVITEURL])); + } + + assert(meshlink_start(mesh)); + + send_event(NODE_STARTED); + + assert(wait_sync_flag(&channel_opened, 10)); + send_event(CHANNEL_OPENED); + + assert(wait_sync_flag(&channel_data_recieved, 10)); + send_event(CHANNEL_DATA_RECIEVED); + + // All test steps executed - wait for signals to stop/start or close the mesh + + while(test_running) { + select(1, NULL, NULL, NULL, &main_loop_wait); + } + + meshlink_close(mesh); + + return 0; +} diff --git a/test/blackbox/test_cases_submesh02/node_sim_corenode2.c b/test/blackbox/test_cases_submesh02/node_sim_corenode2.c new file mode 100644 index 00000000..a7b4760b --- /dev/null +++ b/test/blackbox/test_cases_submesh02/node_sim_corenode2.c @@ -0,0 +1,200 @@ +/* + node_sim_peer.c -- Implementation of Node Simulation for Meshlink Testing + for meta connection test case 01 - re-connection of + two nodes when relay node goes down + 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 +#include +#include +#include +#include +#include +#include +#include "../common/common_handlers.h" +#include "../common/test_step.h" +#include "../common/mesh_event_handler.h" +#include "../../utils.h" + +#define CMD_LINE_ARG_NODENAME 1 +#define CMD_LINE_ARG_DEVCLASS 2 +#define CMD_LINE_ARG_CLIENTID 3 +#define CMD_LINE_ARG_IMPORTSTR 4 +#define CMD_LINE_ARG_INVITEURL 5 +#define CHANNEL_PORT 1234 + +static void channel_receive_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, const void *dat, size_t len); +static bool channel_accept(meshlink_handle_t *mesh, meshlink_channel_t *channel, uint16_t port, const void *dat, size_t len); + +static int client_id = -1; +static meshlink_handle_t *mesh = NULL; + +static struct sync_flag peer_reachable = {.mutex = PTHREAD_MUTEX_INITIALIZER, .cond = PTHREAD_COND_INITIALIZER, .flag = false}; +static struct sync_flag start_test = {.mutex = PTHREAD_MUTEX_INITIALIZER, .cond = PTHREAD_COND_INITIALIZER, .flag = false}; +static struct sync_flag channel_opened = {.mutex = PTHREAD_MUTEX_INITIALIZER, .cond = PTHREAD_COND_INITIALIZER, .flag = false}; +static struct sync_flag channel_data_recieved = {.mutex = PTHREAD_MUTEX_INITIALIZER, .cond = PTHREAD_COND_INITIALIZER, .flag = false}; + +static void send_event(mesh_event_t event) { + int attempts; + + for(attempts = 0; attempts < 5; attempts += 1) { + if(mesh_event_sock_send(client_id, event, NULL, 0)) { + break; + } + } + + assert(attempts < 5); + + return; +} + +static bool channel_accept(meshlink_handle_t *mesh, meshlink_channel_t *channel, uint16_t port, const void *dat, size_t len) { + (void)dat; + (void)len; + + assert(port == CHANNEL_PORT); + + fprintf(stderr, "corenode2 got channel request from %s", channel->node->name); + + if(!strcmp(channel->node->name, "corenode1")) { + meshlink_set_channel_receive_cb(mesh, channel, channel_receive_cb); + mesh->priv = channel; + + return true; + } + + return false; +} + +/* channel receive callback */ +static void channel_receive_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, const void *dat, size_t len) { + char data[100] = {0}; + + if(len == 0) { + send_event(ERR_NETWORK); + return; + } + + memcpy(data, dat, len); + + fprintf(stderr, "corenode2 got message from %s as %s", channel->node->name, data); + + if(!strcmp(channel->node->name, "corenode1")) { + if(!memcmp(dat, "Channel Message", len)) { + set_sync_flag(&channel_data_recieved, true); + } else if(!memcmp(dat, "failure", 7)) { + assert(false); + } + } + + return; +} + +static void poll_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, size_t len) { + char *message = "Channel Message"; + (void)len; + meshlink_set_channel_poll_cb(mesh, channel, NULL); + fprintf(stderr, "corenode2's Channel request has been accepted by corenode1 at : %lu", time(NULL)); + set_sync_flag(&channel_opened, true); + assert(meshlink_channel_send(mesh, channel, message, strlen(message)) >= 0); + return; +} + + +static void node_status_cb(meshlink_handle_t *mesh, meshlink_node_t *node, + bool reachable) { + if(!strcasecmp(node->name, "corenode1")) { + if(reachable) { + fprintf(stderr, "Node corenode2 became reachable"); + set_sync_flag(&peer_reachable, true); + } + } + + return; +} + +void mesh_start_test_handler(int a) { + fprintf(stderr, "Starting test in corenode2\n"); + set_sync_flag(&start_test, true); +} + +int main(int argc, char *argv[]) { + struct timeval main_loop_wait = { 2, 0 }; + meshlink_channel_t *channel = NULL; + meshlink_node_t *core_node = NULL; + + fprintf(stderr, "Mesh node 'corenode2' starting up........\n"); + + // Import mesh event handler + + if((argv[CMD_LINE_ARG_CLIENTID]) && (argv[CMD_LINE_ARG_IMPORTSTR])) { + client_id = atoi(argv[CMD_LINE_ARG_CLIENTID]); + mesh_event_sock_connect(argv[CMD_LINE_ARG_IMPORTSTR]); + } + + // Setup required signals + + setup_signals(); + signal(SIGIO, mesh_start_test_handler); + + // Run peer node instance + + mesh = meshlink_open("corenode1conf", argv[CMD_LINE_ARG_NODENAME], + "test_channel_conn", atoi(argv[CMD_LINE_ARG_DEVCLASS])); + assert(mesh); + meshlink_set_log_cb(mesh, MESHLINK_DEBUG, meshlink_callback_logger); + meshlink_set_channel_accept_cb(mesh, channel_accept); + meshlink_set_node_status_cb(mesh, node_status_cb); + + if(argv[CMD_LINE_ARG_INVITEURL]) { + assert(meshlink_join(mesh, argv[CMD_LINE_ARG_INVITEURL])); + } + + assert(meshlink_start(mesh)); + + send_event(NODE_STARTED); + + // Wait for peer node to join + + assert(wait_sync_flag(&peer_reachable, 15)); + send_event(NODE_JOINED); + + while(false == wait_sync_flag(&start_test, 10)); + + // Open a channel to peer node + core_node = meshlink_get_node(mesh, "corenode1"); + assert(core_node); + fprintf(stderr, "corenode2 Sending Channel request to corenode1 at : %lu", time(NULL)); + channel = meshlink_channel_open(mesh, core_node, CHANNEL_PORT, + channel_receive_cb, NULL, 0); + meshlink_set_channel_poll_cb(mesh, channel, poll_cb); + assert(wait_sync_flag(&channel_opened, 15)); + send_event(CHANNEL_OPENED); + + assert(wait_sync_flag(&channel_data_recieved, 10)); + send_event(CHANNEL_DATA_RECIEVED); + + // All test steps executed - wait for signals to stop/start or close the mesh + + while(test_running) { + select(1, NULL, NULL, NULL, &main_loop_wait); + } + + meshlink_close(mesh); + + return EXIT_SUCCESS; +} \ No newline at end of file diff --git a/test/blackbox/test_cases_submesh03/Makefile.am b/test/blackbox/test_cases_submesh03/Makefile.am new file mode 100644 index 00000000..7a7004ac --- /dev/null +++ b/test/blackbox/test_cases_submesh03/Makefile.am @@ -0,0 +1,13 @@ +check_PROGRAMS = node_sim_corenode1 node_sim_app1node1 node_sim_app1node2 + +node_sim_corenode1_SOURCES = node_sim_corenode1.c ../common/common_handlers.c ../common/test_step.c ../common/mesh_event_handler.c ../../utils.c +node_sim_corenode1_LDADD = ../../../src/libmeshlink.la +node_sim_corenode1_CFLAGS = -D_GNU_SOURCE + +node_sim_app1node1_SOURCES = node_sim_app1node1.c ../common/common_handlers.c ../common/test_step.c ../common/mesh_event_handler.c ../../utils.c +node_sim_app1node1_LDADD = ../../../src/libmeshlink.la +node_sim_app1node1_CFLAGS = -D_GNU_SOURCE + +node_sim_app1node2_SOURCES = node_sim_app1node2.c ../common/common_handlers.c ../common/test_step.c ../common/mesh_event_handler.c ../../utils.c +node_sim_app1node2_LDADD = ../../../src/libmeshlink.la +node_sim_app1node2_CFLAGS = -D_GNU_SOURCE diff --git a/test/blackbox/test_cases_submesh03/node_sim_app1node1.c b/test/blackbox/test_cases_submesh03/node_sim_app1node1.c new file mode 100644 index 00000000..d5423578 --- /dev/null +++ b/test/blackbox/test_cases_submesh03/node_sim_app1node1.c @@ -0,0 +1,221 @@ +/* + node_sim_peer.c -- Implementation of Node Simulation for Meshlink Testing + for meta connection test case 01 - re-connection of + two nodes when relay node goes down + 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 +#include +#include +#include +#include +#include +#include +#include "../common/common_handlers.h" +#include "../common/test_step.h" +#include "../common/mesh_event_handler.h" +#include "../../utils.h" + +#define CMD_LINE_ARG_NODENAME 1 +#define CMD_LINE_ARG_DEVCLASS 2 +#define CMD_LINE_ARG_CLIENTID 3 +#define CMD_LINE_ARG_IMPORTSTR 4 +#define CMD_LINE_ARG_INVITEURL 5 +#define CHANNEL_PORT 1234 + +static void channel_receive_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, const void *dat, size_t len); +static bool channel_accept(meshlink_handle_t *mesh, meshlink_channel_t *channel, uint16_t port, const void *dat, size_t len); + +static int client_id = -1; +static meshlink_handle_t *mesh = NULL; + +static struct sync_flag peer_reachable = {.mutex = PTHREAD_MUTEX_INITIALIZER, .cond = PTHREAD_COND_INITIALIZER, .flag = false}; +static struct sync_flag start_test = {.mutex = PTHREAD_MUTEX_INITIALIZER, .cond = PTHREAD_COND_INITIALIZER, .flag = false}; +static struct sync_flag channel_opened = {.mutex = PTHREAD_MUTEX_INITIALIZER, .cond = PTHREAD_COND_INITIALIZER, .flag = false}; +static struct sync_flag channel_data_recieved = {.mutex = PTHREAD_MUTEX_INITIALIZER, .cond = PTHREAD_COND_INITIALIZER, .flag = false}; + +static void send_event(mesh_event_t event) { + int attempts; + + for(attempts = 0; attempts < 5; attempts += 1) { + if(mesh_event_sock_send(client_id, event, NULL, 0)) { + break; + } + } + + assert(attempts < 5); + + return; +} + +static bool channel_accept(meshlink_handle_t *mesh, meshlink_channel_t *channel, uint16_t port, const void *dat, size_t len) { + (void)dat; + (void)len; + + assert(port == CHANNEL_PORT); + + fprintf(stderr, "\tapp1node1 got channel request from %s\n", channel->node->name); + + if(!strcmp(channel->node->name, "corenode1")) { + fprintf(stderr, "\tapp1node1 accepting channel request from %s at %lu\n", channel->node->name, time(NULL)); + meshlink_set_channel_receive_cb(mesh, channel, channel_receive_cb); + mesh->priv = channel; + + return true; + } else if(!strcmp(channel->node->name, "app1node2")) { + fprintf(stderr, "\tapp1node1 accepting channel request from %s at %lu\n", channel->node->name, time(NULL)); + meshlink_set_channel_receive_cb(mesh, channel, channel_receive_cb); + mesh->priv = channel; + + return true; + } + + fprintf(stderr, "\tapp1node1 rejecting channel request from %s at %lu\n", channel->node->name, time(NULL)); + return false; +} + +/* channel receive callback */ +static void channel_receive_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, const void *dat, size_t len) { + char data[100] = {0}; + char *message = "Channel Message"; + + if(len == 0) { + fprintf(stderr, "\tapp1node1 got error from %s at %lu\n", channel->node->name, time(NULL)); + send_event(ERR_NETWORK); + return; + } + + memcpy(data, dat, len); + + fprintf(stderr, "\tapp1node1 got message from %s as %s\n", channel->node->name, data); + + if(!strcmp(channel->node->name, "corenode1")) { + if(!memcmp(dat, "Channel Message", len)) { + set_sync_flag(&channel_data_recieved, true); + } else if(!memcmp(dat, "failure", 7)) { + assert(false); + } + } else if(!strcmp(channel->node->name, "app1node2")) { + if(!memcmp(dat, "Channel Message", len)) { + assert(meshlink_channel_send(mesh, channel, message, strlen(message)) >= 0); + } else if(!memcmp(dat, "failure", 7)) { + assert(false); + } + } + + return; +} + +static void poll_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, size_t len) { + char *message = "Channel Message"; + char *node = (char *)channel->node->name; + (void)len; + meshlink_set_channel_poll_cb(mesh, channel, NULL); + fprintf(stderr, "\tapp1node1's Channel request has been accepted by %s at : %lu\n", node, time(NULL)); + + if(0 == strcmp("corenode1", node)) { + set_sync_flag(&channel_opened, true); + } + + assert(meshlink_channel_send(mesh, channel, message, strlen(message)) >= 0); + return; +} + + +static void node_status_cb(meshlink_handle_t *mesh, meshlink_node_t *node, + bool reachable) { + if(!strcasecmp(node->name, "corenode1")) { + if(reachable) { + fprintf(stderr, "\tNode corenode1 became reachable\n"); + set_sync_flag(&peer_reachable, true); + } + } + + return; +} + +void mesh_start_test_handler(int a) { + fprintf(stderr, "Starting test in app1node1\n"); + set_sync_flag(&start_test, true); +} + +int main(int argc, char *argv[]) { + struct timeval main_loop_wait = { 2, 0 }; + meshlink_channel_t *channel = NULL; + meshlink_node_t *core_node = NULL; + + fprintf(stderr, "\tMesh node 'app1node1' starting up........\n"); + + // Import mesh event handler + + if((argv[CMD_LINE_ARG_CLIENTID]) && (argv[CMD_LINE_ARG_IMPORTSTR])) { + client_id = atoi(argv[CMD_LINE_ARG_CLIENTID]); + mesh_event_sock_connect(argv[CMD_LINE_ARG_IMPORTSTR]); + } + + // Setup required signals + + setup_signals(); + signal(SIGIO, mesh_start_test_handler); + + // Run peer node instance + + mesh = meshlink_open("app1node1conf", argv[CMD_LINE_ARG_NODENAME], + "test_channel_conn", atoi(argv[CMD_LINE_ARG_DEVCLASS])); + assert(mesh); + meshlink_set_log_cb(mesh, MESHLINK_DEBUG, meshlink_callback_logger); + meshlink_set_channel_accept_cb(mesh, channel_accept); + meshlink_set_node_status_cb(mesh, node_status_cb); + + if(argv[CMD_LINE_ARG_INVITEURL]) { + assert(meshlink_join(mesh, argv[CMD_LINE_ARG_INVITEURL])); + } + + assert(meshlink_start(mesh)); + + send_event(NODE_STARTED); + + // Wait for peer node to join + + assert(wait_sync_flag(&peer_reachable, 15)); + send_event(NODE_JOINED); + + while(false == wait_sync_flag(&start_test, 10)); + + // Open a channel to peer node + core_node = meshlink_get_node(mesh, "corenode1"); + assert(core_node); + fprintf(stderr, "\tapp1node1 Sending Channel request to corenode1 at : %lu\n", time(NULL)); + channel = meshlink_channel_open(mesh, core_node, CHANNEL_PORT, + channel_receive_cb, NULL, 0); + meshlink_set_channel_poll_cb(mesh, channel, poll_cb); + assert(wait_sync_flag(&channel_opened, 15)); + send_event(CHANNEL_OPENED); + + assert(wait_sync_flag(&channel_data_recieved, 30)); + send_event(CHANNEL_DATA_RECIEVED); + + // All test steps executed - wait for signals to stop/start or close the mesh + + while(test_running) { + select(1, NULL, NULL, NULL, &main_loop_wait); + } + + meshlink_close(mesh); + + return EXIT_SUCCESS; +} \ No newline at end of file diff --git a/test/blackbox/test_cases_submesh03/node_sim_app1node2.c b/test/blackbox/test_cases_submesh03/node_sim_app1node2.c new file mode 100644 index 00000000..39d998e1 --- /dev/null +++ b/test/blackbox/test_cases_submesh03/node_sim_app1node2.c @@ -0,0 +1,255 @@ +/* + node_sim_peer.c -- Implementation of Node Simulation for Meshlink Testing + for meta connection test case 01 - re-connection of + two nodes when relay node goes down + 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 +#include +#include +#include +#include +#include +#include +#include "../common/common_handlers.h" +#include "../common/test_step.h" +#include "../common/mesh_event_handler.h" +#include "../../utils.h" + +#define CMD_LINE_ARG_NODENAME 1 +#define CMD_LINE_ARG_DEVCLASS 2 +#define CMD_LINE_ARG_CLIENTID 3 +#define CMD_LINE_ARG_IMPORTSTR 4 +#define CMD_LINE_ARG_INVITEURL 5 +#define CHANNEL_PORT 1234 + +static void channel_receive_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, const void *dat, size_t len); +static bool channel_accept(meshlink_handle_t *mesh, meshlink_channel_t *channel, uint16_t port, const void *dat, size_t len); + +static int client_id = -1; +static meshlink_handle_t *mesh = NULL; + +static struct sync_flag peer_reachable = {.mutex = PTHREAD_MUTEX_INITIALIZER, .cond = PTHREAD_COND_INITIALIZER, .flag = false}; +static struct sync_flag start_test = {.mutex = PTHREAD_MUTEX_INITIALIZER, .cond = PTHREAD_COND_INITIALIZER, .flag = false}; +static struct sync_flag app_reachable = {.mutex = PTHREAD_MUTEX_INITIALIZER, .cond = PTHREAD_COND_INITIALIZER, .flag = false}; +static struct sync_flag channel_opened = {.mutex = PTHREAD_MUTEX_INITIALIZER, .cond = PTHREAD_COND_INITIALIZER, .flag = false}; +static struct sync_flag channel_data_recieved = {.mutex = PTHREAD_MUTEX_INITIALIZER, .cond = PTHREAD_COND_INITIALIZER, .flag = false}; + +static void send_event(mesh_event_t event) { + int attempts; + + for(attempts = 0; attempts < 5; attempts += 1) { + if(mesh_event_sock_send(client_id, event, NULL, 0)) { + break; + } + } + + assert(attempts < 5); + + return; +} + +static bool channel_accept(meshlink_handle_t *mesh, meshlink_channel_t *channel, uint16_t port, const void *dat, size_t len) { + (void)dat; + (void)len; + + assert(port == CHANNEL_PORT); + + fprintf(stderr, "\tapp1node2 got channel request from %s\n", channel->node->name); + + if(!strcmp(channel->node->name, "corenode1")) { + meshlink_set_channel_receive_cb(mesh, channel, channel_receive_cb); + mesh->priv = channel; + + return true; + } + + return false; +} + +/* channel receive callback */ +static void channel_receive_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, const void *dat, size_t len) { + char data[100] = {0}; + + if(len == 0) { + fprintf(stderr, "\tapp1node2 got error from %s at %lu\n", channel->node->name, time(NULL)); + send_event(ERR_NETWORK); + return; + } + + memcpy(data, dat, len); + + fprintf(stderr, "\tapp1node2 got message from %s as %s\n", channel->node->name, data); + + if(!strcmp(channel->node->name, "corenode1")) { + if(!memcmp(dat, "Channel Message", len)) { + set_sync_flag(&channel_data_recieved, true); + } else if(!memcmp(dat, "failure", 7)) { + assert(false); + } + } else if(!strcmp(channel->node->name, "app1node1")) { + if(!memcmp(dat, "Channel Message", len)) { + set_sync_flag(&channel_data_recieved, true); + } else if(!memcmp(dat, "failure", 7)) { + assert(false); + } + } else { + assert(false); + } + + return; +} + +static void poll_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, size_t len) { + char *message = "Channel Message"; + char *node = (char *)channel->node->name; + (void)len; + meshlink_set_channel_poll_cb(mesh, channel, NULL); + fprintf(stderr, "\tapp1node2's Channel request has been accepted by %s at : %lu\n", node, time(NULL)); + set_sync_flag(&channel_opened, true); + assert(meshlink_channel_send(mesh, channel, message, strlen(message)) >= 0); + return; +} + + +static void node_status_cb(meshlink_handle_t *mesh, meshlink_node_t *node, + bool reachable) { + if(!strcasecmp(node->name, "corenode1")) { + if(reachable) { + fprintf(stderr, "\tNode corenode1 became reachable\n"); + set_sync_flag(&peer_reachable, true); + } + } else if(!strcasecmp(node->name, "app1node1")) { + if(reachable) { + fprintf(stderr, "\tNode app1node1 became reachable\n"); + set_sync_flag(&app_reachable, true); + } + } + + return; +} + +void mesh_start_test_handler(int a) { + fprintf(stderr, "Starting test in app1node2\n"); + set_sync_flag(&start_test, true); +} + +int main(int argc, char *argv[]) { + size_t num_nodes, i; + struct timeval main_loop_wait = { 2, 0 }; + meshlink_channel_t *channel = NULL; + meshlink_node_t *core_node = NULL; + meshlink_node_t **node_handles = NULL; + + fprintf(stderr, "\tMesh node 'app1node2' starting up........\n"); + + // Import mesh event handler + + if((argv[CMD_LINE_ARG_CLIENTID]) && (argv[CMD_LINE_ARG_IMPORTSTR])) { + client_id = atoi(argv[CMD_LINE_ARG_CLIENTID]); + mesh_event_sock_connect(argv[CMD_LINE_ARG_IMPORTSTR]); + } + + // Setup required signals + + setup_signals(); + signal(SIGIO, mesh_start_test_handler); + + // Run peer node instance + + mesh = meshlink_open("app1node2conf", argv[CMD_LINE_ARG_NODENAME], + "test_channel_conn", atoi(argv[CMD_LINE_ARG_DEVCLASS])); + assert(mesh); + meshlink_set_log_cb(mesh, MESHLINK_DEBUG, meshlink_callback_logger); + meshlink_set_channel_accept_cb(mesh, channel_accept); + meshlink_set_node_status_cb(mesh, node_status_cb); + + if(argv[CMD_LINE_ARG_INVITEURL]) { + assert(meshlink_join(mesh, argv[CMD_LINE_ARG_INVITEURL])); + } + + assert(meshlink_start(mesh)); + + send_event(NODE_STARTED); + + // Wait for peer node to join + + assert(wait_sync_flag(&peer_reachable, 15)); + send_event(NODE_JOINED); + + while(false == wait_sync_flag(&start_test, 10)); + + // Open a channel to peer node + core_node = meshlink_get_node(mesh, "corenode1"); + assert(core_node); + fprintf(stderr, "\tapp1node2 Sending Channel request to corenode1 at : %lu\n", time(NULL)); + channel = meshlink_channel_open(mesh, core_node, CHANNEL_PORT, + channel_receive_cb, NULL, 0); + meshlink_set_channel_poll_cb(mesh, channel, poll_cb); + assert(wait_sync_flag(&channel_opened, 15)); + send_event(CHANNEL_OPENED); + + assert(wait_sync_flag(&channel_data_recieved, 30)); + send_event(CHANNEL_DATA_RECIEVED); + + // Open a channel to peer node + channel_opened.flag = false; + channel_data_recieved.flag = false; + + assert(wait_sync_flag(&app_reachable, 60)); + + core_node = meshlink_get_node(mesh, "app1node1"); + assert(core_node); + fprintf(stderr, "\tapp1node2 Sending Channel request to app1node1 at : %lu\n", time(NULL)); + channel = meshlink_channel_open(mesh, core_node, CHANNEL_PORT, + channel_receive_cb, NULL, 0); + meshlink_set_channel_poll_cb(mesh, channel, poll_cb); + assert(wait_sync_flag(&channel_opened, 15)); + send_event(CHANNEL_OPENED); + + assert(wait_sync_flag(&channel_data_recieved, 30)); + send_event(CHANNEL_DATA_RECIEVED); + + num_nodes = 0; + node_handles = meshlink_get_all_nodes(mesh, NULL, &num_nodes); + fprintf(stderr, "\tGot %lu nodes in list with error : %s\n", num_nodes, meshlink_strerror(meshlink_errno)); + assert(node_handles); + + for(i = 0; i < num_nodes; i++) { + fprintf(stderr, "\tChecking the node : %s\n", node_handles[i]->name); + + if(0 == strcmp(node_handles[i]->name, "app2node1")) { + send_event(SIG_ABORT); + assert(false); + } else if(0 == strcmp(node_handles[i]->name, "app2node2")) { + send_event(SIG_ABORT); + assert(false); + } + } + + send_event(MESH_EVENT_COMPLETED); + + // All test steps executed - wait for signals to stop/start or close the mesh + + while(test_running) { + select(1, NULL, NULL, NULL, &main_loop_wait); + } + + meshlink_close(mesh); + + return EXIT_SUCCESS; +} diff --git a/test/blackbox/test_cases_submesh03/node_sim_corenode1.c b/test/blackbox/test_cases_submesh03/node_sim_corenode1.c new file mode 100644 index 00000000..5648d280 --- /dev/null +++ b/test/blackbox/test_cases_submesh03/node_sim_corenode1.c @@ -0,0 +1,188 @@ +/* + node_sim.c -- Implementation of Node Simulation for Meshlink Testing + for meta connection test case 01 - re-connection of + two nodes when relay node goes down + 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 +#include +#include +#include +#include +#include "../common/common_handlers.h" +#include "../common/test_step.h" +#include "../common/mesh_event_handler.h" +#include "../../utils.h" + +#define CMD_LINE_ARG_NODENAME 1 +#define CMD_LINE_ARG_DEVCLASS 2 +#define CMD_LINE_ARG_CLIENTID 3 +#define CMD_LINE_ARG_IMPORTSTR 4 +#define CMD_LINE_ARG_INVITEURL 5 +#define CHANNEL_PORT 1234 + +static bool conn_status = false; +static int client_id = -1; + +static struct sync_flag peer_reachable = {.mutex = PTHREAD_MUTEX_INITIALIZER, .cond = PTHREAD_COND_INITIALIZER, .flag = false}; +static struct sync_flag channel_opened = {.mutex = PTHREAD_MUTEX_INITIALIZER, .cond = PTHREAD_COND_INITIALIZER, .flag = false}; +static struct sync_flag channel_data_recieved = {.mutex = PTHREAD_MUTEX_INITIALIZER, .cond = PTHREAD_COND_INITIALIZER, .flag = false}; + +static meshlink_handle_t *mesh = NULL; + +static void mesh_send_message_handler(char *destination); + +static void send_event(mesh_event_t event) { + int attempts; + + for(attempts = 0; attempts < 5; attempts += 1) { + if(mesh_event_sock_send(client_id, event, NULL, 0)) { + break; + } + } + + assert(attempts < 5); + + return; +} + +/* channel receive callback */ +static void channel_receive_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, const void *dat, size_t len) { + char data[100] = {0}; + + if(len == 0) { + send_event(ERR_NETWORK); + return; + } + + memcpy(data, dat, len); + + fprintf(stderr, "corenode1 got message from %s as %s\n", channel->node->name, data); + + if(!memcmp(dat, "Channel Message", len)) { + mesh_send_message_handler((char *)channel->node->name); + + if(0 == strcmp("app1node1", channel->node->name)) { + set_sync_flag(&channel_data_recieved, true); + } + } else if(!memcmp(dat, "failure", 7)) { + assert(false); + } + + return; +} + +static void node_status_cb(meshlink_handle_t *mesh, meshlink_node_t *node, + bool reachable) { + if(reachable) { + fprintf(stderr, "Node %s became reachable\n", node->name); + } else { + fprintf(stderr, "Node %s is unreachable\n", node->name); + } + + return; +} + +static void poll_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, size_t len) { + char *message = "Channel Message"; + char *node = (char *)channel->node->name; + (void)len; + meshlink_set_channel_poll_cb(mesh, channel, NULL); + fprintf(stderr, "corenode1's Channel request has been accepted by %s at : %lu\n", node, time(NULL)); + + if(0 == strcmp("app1node1", node)) { + set_sync_flag(&channel_opened, true); + } + + assert(meshlink_channel_send(mesh, channel, message, strlen(message)) >= 0); + return; +} + +/* channel receive callback */ +static bool channel_accept(meshlink_handle_t *mesh, meshlink_channel_t *channel, uint16_t port, const void *dat, size_t len) { + (void)dat; + (void)len; + + assert(port == CHANNEL_PORT); + + fprintf(stderr, "corenode1 got channel request from %s\n", channel->node->name); + meshlink_set_channel_receive_cb(mesh, channel, channel_receive_cb); + + return true; +} + +void mesh_send_message_handler(char *destination) { + meshlink_channel_t *channel = NULL; + meshlink_node_t *target_node = NULL; + + // Open a channel to destination node + target_node = meshlink_get_node(mesh, destination); + assert(target_node); + fprintf(stderr, "corenode1 Sending Channel request to %s at : %lu\n", destination, time(NULL)); + channel = meshlink_channel_open(mesh, target_node, CHANNEL_PORT, + channel_receive_cb, NULL, 0); + meshlink_set_channel_poll_cb(mesh, channel, poll_cb); +} + +int main(int argc, char *argv[]) { + struct timeval main_loop_wait = { 5, 0 }; + int i; + + // Import mesh event handler + + fprintf(stderr, "Mesh node 'corenode1' starting up........\n"); + + if((argv[CMD_LINE_ARG_CLIENTID]) && (argv[CMD_LINE_ARG_IMPORTSTR])) { + client_id = atoi(argv[CMD_LINE_ARG_CLIENTID]); + mesh_event_sock_connect(argv[CMD_LINE_ARG_IMPORTSTR]); + } + + setup_signals(); + + // Execute test steps + + mesh = meshlink_open("testconf", argv[CMD_LINE_ARG_NODENAME], + "test_channel_conn", atoi(argv[CMD_LINE_ARG_DEVCLASS])); + assert(mesh); + meshlink_set_log_cb(mesh, MESHLINK_DEBUG, meshlink_callback_logger); + meshlink_set_channel_accept_cb(mesh, channel_accept); + meshlink_set_node_status_cb(mesh, node_status_cb); + + if(argv[CMD_LINE_ARG_INVITEURL]) { + assert(meshlink_join(mesh, argv[CMD_LINE_ARG_INVITEURL])); + } + + assert(meshlink_start(mesh)); + + send_event(NODE_STARTED); + + assert(wait_sync_flag(&channel_opened, 10)); + send_event(CHANNEL_OPENED); + + assert(wait_sync_flag(&channel_data_recieved, 10)); + send_event(CHANNEL_DATA_RECIEVED); + + // All test steps executed - wait for signals to stop/start or close the mesh + + while(test_running) { + select(1, NULL, NULL, NULL, &main_loop_wait); + } + + meshlink_close(mesh); + + return 0; +} diff --git a/test/blackbox/test_cases_submesh04/Makefile.am b/test/blackbox/test_cases_submesh04/Makefile.am new file mode 100644 index 00000000..7a7004ac --- /dev/null +++ b/test/blackbox/test_cases_submesh04/Makefile.am @@ -0,0 +1,13 @@ +check_PROGRAMS = node_sim_corenode1 node_sim_app1node1 node_sim_app1node2 + +node_sim_corenode1_SOURCES = node_sim_corenode1.c ../common/common_handlers.c ../common/test_step.c ../common/mesh_event_handler.c ../../utils.c +node_sim_corenode1_LDADD = ../../../src/libmeshlink.la +node_sim_corenode1_CFLAGS = -D_GNU_SOURCE + +node_sim_app1node1_SOURCES = node_sim_app1node1.c ../common/common_handlers.c ../common/test_step.c ../common/mesh_event_handler.c ../../utils.c +node_sim_app1node1_LDADD = ../../../src/libmeshlink.la +node_sim_app1node1_CFLAGS = -D_GNU_SOURCE + +node_sim_app1node2_SOURCES = node_sim_app1node2.c ../common/common_handlers.c ../common/test_step.c ../common/mesh_event_handler.c ../../utils.c +node_sim_app1node2_LDADD = ../../../src/libmeshlink.la +node_sim_app1node2_CFLAGS = -D_GNU_SOURCE diff --git a/test/blackbox/test_cases_submesh04/node_sim_app1node1.c b/test/blackbox/test_cases_submesh04/node_sim_app1node1.c new file mode 100644 index 00000000..d5423578 --- /dev/null +++ b/test/blackbox/test_cases_submesh04/node_sim_app1node1.c @@ -0,0 +1,221 @@ +/* + node_sim_peer.c -- Implementation of Node Simulation for Meshlink Testing + for meta connection test case 01 - re-connection of + two nodes when relay node goes down + 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 +#include +#include +#include +#include +#include +#include +#include "../common/common_handlers.h" +#include "../common/test_step.h" +#include "../common/mesh_event_handler.h" +#include "../../utils.h" + +#define CMD_LINE_ARG_NODENAME 1 +#define CMD_LINE_ARG_DEVCLASS 2 +#define CMD_LINE_ARG_CLIENTID 3 +#define CMD_LINE_ARG_IMPORTSTR 4 +#define CMD_LINE_ARG_INVITEURL 5 +#define CHANNEL_PORT 1234 + +static void channel_receive_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, const void *dat, size_t len); +static bool channel_accept(meshlink_handle_t *mesh, meshlink_channel_t *channel, uint16_t port, const void *dat, size_t len); + +static int client_id = -1; +static meshlink_handle_t *mesh = NULL; + +static struct sync_flag peer_reachable = {.mutex = PTHREAD_MUTEX_INITIALIZER, .cond = PTHREAD_COND_INITIALIZER, .flag = false}; +static struct sync_flag start_test = {.mutex = PTHREAD_MUTEX_INITIALIZER, .cond = PTHREAD_COND_INITIALIZER, .flag = false}; +static struct sync_flag channel_opened = {.mutex = PTHREAD_MUTEX_INITIALIZER, .cond = PTHREAD_COND_INITIALIZER, .flag = false}; +static struct sync_flag channel_data_recieved = {.mutex = PTHREAD_MUTEX_INITIALIZER, .cond = PTHREAD_COND_INITIALIZER, .flag = false}; + +static void send_event(mesh_event_t event) { + int attempts; + + for(attempts = 0; attempts < 5; attempts += 1) { + if(mesh_event_sock_send(client_id, event, NULL, 0)) { + break; + } + } + + assert(attempts < 5); + + return; +} + +static bool channel_accept(meshlink_handle_t *mesh, meshlink_channel_t *channel, uint16_t port, const void *dat, size_t len) { + (void)dat; + (void)len; + + assert(port == CHANNEL_PORT); + + fprintf(stderr, "\tapp1node1 got channel request from %s\n", channel->node->name); + + if(!strcmp(channel->node->name, "corenode1")) { + fprintf(stderr, "\tapp1node1 accepting channel request from %s at %lu\n", channel->node->name, time(NULL)); + meshlink_set_channel_receive_cb(mesh, channel, channel_receive_cb); + mesh->priv = channel; + + return true; + } else if(!strcmp(channel->node->name, "app1node2")) { + fprintf(stderr, "\tapp1node1 accepting channel request from %s at %lu\n", channel->node->name, time(NULL)); + meshlink_set_channel_receive_cb(mesh, channel, channel_receive_cb); + mesh->priv = channel; + + return true; + } + + fprintf(stderr, "\tapp1node1 rejecting channel request from %s at %lu\n", channel->node->name, time(NULL)); + return false; +} + +/* channel receive callback */ +static void channel_receive_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, const void *dat, size_t len) { + char data[100] = {0}; + char *message = "Channel Message"; + + if(len == 0) { + fprintf(stderr, "\tapp1node1 got error from %s at %lu\n", channel->node->name, time(NULL)); + send_event(ERR_NETWORK); + return; + } + + memcpy(data, dat, len); + + fprintf(stderr, "\tapp1node1 got message from %s as %s\n", channel->node->name, data); + + if(!strcmp(channel->node->name, "corenode1")) { + if(!memcmp(dat, "Channel Message", len)) { + set_sync_flag(&channel_data_recieved, true); + } else if(!memcmp(dat, "failure", 7)) { + assert(false); + } + } else if(!strcmp(channel->node->name, "app1node2")) { + if(!memcmp(dat, "Channel Message", len)) { + assert(meshlink_channel_send(mesh, channel, message, strlen(message)) >= 0); + } else if(!memcmp(dat, "failure", 7)) { + assert(false); + } + } + + return; +} + +static void poll_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, size_t len) { + char *message = "Channel Message"; + char *node = (char *)channel->node->name; + (void)len; + meshlink_set_channel_poll_cb(mesh, channel, NULL); + fprintf(stderr, "\tapp1node1's Channel request has been accepted by %s at : %lu\n", node, time(NULL)); + + if(0 == strcmp("corenode1", node)) { + set_sync_flag(&channel_opened, true); + } + + assert(meshlink_channel_send(mesh, channel, message, strlen(message)) >= 0); + return; +} + + +static void node_status_cb(meshlink_handle_t *mesh, meshlink_node_t *node, + bool reachable) { + if(!strcasecmp(node->name, "corenode1")) { + if(reachable) { + fprintf(stderr, "\tNode corenode1 became reachable\n"); + set_sync_flag(&peer_reachable, true); + } + } + + return; +} + +void mesh_start_test_handler(int a) { + fprintf(stderr, "Starting test in app1node1\n"); + set_sync_flag(&start_test, true); +} + +int main(int argc, char *argv[]) { + struct timeval main_loop_wait = { 2, 0 }; + meshlink_channel_t *channel = NULL; + meshlink_node_t *core_node = NULL; + + fprintf(stderr, "\tMesh node 'app1node1' starting up........\n"); + + // Import mesh event handler + + if((argv[CMD_LINE_ARG_CLIENTID]) && (argv[CMD_LINE_ARG_IMPORTSTR])) { + client_id = atoi(argv[CMD_LINE_ARG_CLIENTID]); + mesh_event_sock_connect(argv[CMD_LINE_ARG_IMPORTSTR]); + } + + // Setup required signals + + setup_signals(); + signal(SIGIO, mesh_start_test_handler); + + // Run peer node instance + + mesh = meshlink_open("app1node1conf", argv[CMD_LINE_ARG_NODENAME], + "test_channel_conn", atoi(argv[CMD_LINE_ARG_DEVCLASS])); + assert(mesh); + meshlink_set_log_cb(mesh, MESHLINK_DEBUG, meshlink_callback_logger); + meshlink_set_channel_accept_cb(mesh, channel_accept); + meshlink_set_node_status_cb(mesh, node_status_cb); + + if(argv[CMD_LINE_ARG_INVITEURL]) { + assert(meshlink_join(mesh, argv[CMD_LINE_ARG_INVITEURL])); + } + + assert(meshlink_start(mesh)); + + send_event(NODE_STARTED); + + // Wait for peer node to join + + assert(wait_sync_flag(&peer_reachable, 15)); + send_event(NODE_JOINED); + + while(false == wait_sync_flag(&start_test, 10)); + + // Open a channel to peer node + core_node = meshlink_get_node(mesh, "corenode1"); + assert(core_node); + fprintf(stderr, "\tapp1node1 Sending Channel request to corenode1 at : %lu\n", time(NULL)); + channel = meshlink_channel_open(mesh, core_node, CHANNEL_PORT, + channel_receive_cb, NULL, 0); + meshlink_set_channel_poll_cb(mesh, channel, poll_cb); + assert(wait_sync_flag(&channel_opened, 15)); + send_event(CHANNEL_OPENED); + + assert(wait_sync_flag(&channel_data_recieved, 30)); + send_event(CHANNEL_DATA_RECIEVED); + + // All test steps executed - wait for signals to stop/start or close the mesh + + while(test_running) { + select(1, NULL, NULL, NULL, &main_loop_wait); + } + + meshlink_close(mesh); + + return EXIT_SUCCESS; +} \ No newline at end of file diff --git a/test/blackbox/test_cases_submesh04/node_sim_app1node2.c b/test/blackbox/test_cases_submesh04/node_sim_app1node2.c new file mode 100644 index 00000000..14729f5e --- /dev/null +++ b/test/blackbox/test_cases_submesh04/node_sim_app1node2.c @@ -0,0 +1,288 @@ +/* + node_sim_peer.c -- Implementation of Node Simulation for Meshlink Testing + for meta connection test case 01 - re-connection of + two nodes when relay node goes down + 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 +#include +#include +#include +#include +#include +#include +#include "../common/common_handlers.h" +#include "../common/test_step.h" +#include "../common/mesh_event_handler.h" +#include "../../utils.h" + +#define CMD_LINE_ARG_NODENAME 1 +#define CMD_LINE_ARG_DEVCLASS 2 +#define CMD_LINE_ARG_CLIENTID 3 +#define CMD_LINE_ARG_IMPORTSTR 4 +#define CMD_LINE_ARG_INVITEURL 5 +#define CHANNEL_PORT 1234 + +static void channel_receive_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, const void *dat, size_t len); +static bool channel_accept(meshlink_handle_t *mesh, meshlink_channel_t *channel, uint16_t port, const void *dat, size_t len); + +static int client_id = -1; +static meshlink_handle_t *mesh = NULL; + +static struct sync_flag peer_reachable = {.mutex = PTHREAD_MUTEX_INITIALIZER, .cond = PTHREAD_COND_INITIALIZER, .flag = false}; +static struct sync_flag start_test = {.mutex = PTHREAD_MUTEX_INITIALIZER, .cond = PTHREAD_COND_INITIALIZER, .flag = false}; +static struct sync_flag app_reachable = {.mutex = PTHREAD_MUTEX_INITIALIZER, .cond = PTHREAD_COND_INITIALIZER, .flag = false}; +static struct sync_flag channel_opened = {.mutex = PTHREAD_MUTEX_INITIALIZER, .cond = PTHREAD_COND_INITIALIZER, .flag = false}; +static struct sync_flag channel_data_recieved = {.mutex = PTHREAD_MUTEX_INITIALIZER, .cond = PTHREAD_COND_INITIALIZER, .flag = false}; +static meshlink_channel_t *ch_app1node1 = NULL; + +static void send_event(mesh_event_t event) { + int attempts; + + for(attempts = 0; attempts < 5; attempts += 1) { + if(mesh_event_sock_send(client_id, event, NULL, 0)) { + break; + } + } + + assert(attempts < 5); + + return; +} + +static bool channel_accept(meshlink_handle_t *mesh, meshlink_channel_t *channel, uint16_t port, const void *dat, size_t len) { + (void)dat; + (void)len; + + assert(port == CHANNEL_PORT); + + fprintf(stderr, "\tapp1node2 got channel request from %s\n", channel->node->name); + + if(!strcmp(channel->node->name, "corenode1")) { + meshlink_set_channel_receive_cb(mesh, channel, channel_receive_cb); + mesh->priv = channel; + + return true; + } + + return false; +} + +/* channel receive callback */ +static void channel_receive_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, const void *dat, size_t len) { + char data[100] = {0}; + + if(len == 0) { + fprintf(stderr, "\tapp1node2 got error from %s at %lu\n", channel->node->name, time(NULL)); + send_event(ERR_NETWORK); + return; + } + + memcpy(data, dat, len); + + fprintf(stderr, "\tapp1node2 got message from %s as %s\n", channel->node->name, data); + + if(!strcmp(channel->node->name, "corenode1")) { + if(!memcmp(dat, "Channel Message", len)) { + set_sync_flag(&channel_data_recieved, true); + } else if(!memcmp(dat, "failure", 7)) { + assert(false); + } + } else if(!strcmp(channel->node->name, "app1node1")) { + if(!memcmp(dat, "Channel Message", len)) { + ch_app1node1 = channel; + set_sync_flag(&channel_data_recieved, true); + } else if(!memcmp(dat, "failure", 7)) { + assert(false); + } + } else { + assert(false); + } + + return; +} + +static void poll_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, size_t len) { + char *message = "Channel Message"; + char *node = (char *)channel->node->name; + (void)len; + meshlink_set_channel_poll_cb(mesh, channel, NULL); + fprintf(stderr, "\tapp1node2's Channel request has been accepted by %s at : %lu\n", node, time(NULL)); + set_sync_flag(&channel_opened, true); + assert(meshlink_channel_send(mesh, channel, message, strlen(message)) >= 0); + return; +} + + +static void node_status_cb(meshlink_handle_t *mesh, meshlink_node_t *node, + bool reachable) { + if(!strcasecmp(node->name, "corenode1")) { + if(reachable) { + fprintf(stderr, "\tNode corenode1 became reachable\n"); + set_sync_flag(&peer_reachable, true); + } + } else if(!strcasecmp(node->name, "app1node1")) { + if(reachable) { + fprintf(stderr, "\tNode app1node1 became reachable\n"); + set_sync_flag(&app_reachable, true); + } + } + + return; +} + +void mesh_start_test_handler(int a) { + fprintf(stderr, "Starting test in app1node2\n"); + set_sync_flag(&start_test, true); +} + +int main(int argc, char *argv[]) { + size_t num_nodes, i; + struct timeval main_loop_wait = { 2, 0 }; + meshlink_channel_t *channel = NULL; + meshlink_node_t *core_node = NULL; + meshlink_node_t **node_handles = NULL; + ssize_t retvalue = -1; + + fprintf(stderr, "\tMesh node 'app1node2' starting up........\n"); + + // Import mesh event handler + + if((argv[CMD_LINE_ARG_CLIENTID]) && (argv[CMD_LINE_ARG_IMPORTSTR])) { + client_id = atoi(argv[CMD_LINE_ARG_CLIENTID]); + mesh_event_sock_connect(argv[CMD_LINE_ARG_IMPORTSTR]); + } + + // Setup required signals + + setup_signals(); + signal(SIGIO, mesh_start_test_handler); + + // Run peer node instance + + mesh = meshlink_open("app1node2conf", argv[CMD_LINE_ARG_NODENAME], + "test_channel_conn", atoi(argv[CMD_LINE_ARG_DEVCLASS])); + assert(mesh); + meshlink_set_log_cb(mesh, MESHLINK_DEBUG, meshlink_callback_logger); + meshlink_set_channel_accept_cb(mesh, channel_accept); + meshlink_set_node_status_cb(mesh, node_status_cb); + + if(argv[CMD_LINE_ARG_INVITEURL]) { + assert(meshlink_join(mesh, argv[CMD_LINE_ARG_INVITEURL])); + } + + assert(meshlink_start(mesh)); + + send_event(NODE_STARTED); + + // Wait for peer node to join + + assert(wait_sync_flag(&peer_reachable, 15)); + send_event(NODE_JOINED); + + while(false == wait_sync_flag(&start_test, 10)); + + // Open a channel to peer node + core_node = meshlink_get_node(mesh, "corenode1"); + assert(core_node); + fprintf(stderr, "\tapp1node2 Sending Channel request to corenode1 at : %lu\n", time(NULL)); + channel = meshlink_channel_open(mesh, core_node, CHANNEL_PORT, + channel_receive_cb, NULL, 0); + meshlink_set_channel_poll_cb(mesh, channel, poll_cb); + assert(wait_sync_flag(&channel_opened, 15)); + send_event(CHANNEL_OPENED); + + assert(wait_sync_flag(&channel_data_recieved, 30)); + send_event(CHANNEL_DATA_RECIEVED); + + // Open a channel to peer node + channel_opened.flag = false; + channel_data_recieved.flag = false; + + assert(wait_sync_flag(&app_reachable, 60)); + + core_node = meshlink_get_node(mesh, "app1node1"); + assert(core_node); + fprintf(stderr, "\tapp1node2 Sending Channel request to app1node1 at : %lu\n", time(NULL)); + channel = meshlink_channel_open(mesh, core_node, CHANNEL_PORT, + channel_receive_cb, NULL, 0); + meshlink_set_channel_poll_cb(mesh, channel, poll_cb); + assert(wait_sync_flag(&channel_opened, 15)); + send_event(CHANNEL_OPENED); + + assert(wait_sync_flag(&channel_data_recieved, 30)); + send_event(CHANNEL_DATA_RECIEVED); + + num_nodes = 0; + node_handles = meshlink_get_all_nodes(mesh, NULL, &num_nodes); + fprintf(stderr, "\tGot %lu nodes in list with error : %s\n", num_nodes, meshlink_strerror(meshlink_errno)); + assert(node_handles); + + for(i = 0; i < num_nodes; i++) { + fprintf(stderr, "\tChecking the node : %s\n", node_handles[i]->name); + + if(0 == strcmp(node_handles[i]->name, "app2node1")) { + send_event(SIG_ABORT); + assert(false); + } else if(0 == strcmp(node_handles[i]->name, "app2node2")) { + send_event(SIG_ABORT); + assert(false); + } + } + + meshlink_node_t *app1_node1 = meshlink_get_node(mesh, "app1node1"); + + if(!app1_node1) { + send_event(SIG_ABORT); + assert(app1_node1); + } + + channel_data_recieved.flag = false; + meshlink_blacklist(mesh, app1_node1); + + sleep(2); + + meshlink_channel_send(mesh, ch_app1node1, "test", 5); + + wait_sync_flag(&channel_data_recieved, 30); + + if(true == channel_data_recieved.flag) { + send_event(SIG_ABORT); + assert(false); + } + + channel_data_recieved.flag = false; + meshlink_whitelist(mesh, app1_node1); + + sleep(2); + + meshlink_channel_send(mesh, ch_app1node1, "Channel Message", strlen("Channel Message")); + + assert(wait_sync_flag(&channel_data_recieved, 60)); + + send_event(MESH_EVENT_COMPLETED); + + // All test steps executed - wait for signals to stop/start or close the mesh + + while(test_running) { + select(1, NULL, NULL, NULL, &main_loop_wait); + } + + meshlink_close(mesh); + + return EXIT_SUCCESS; +} diff --git a/test/blackbox/test_cases_submesh04/node_sim_corenode1.c b/test/blackbox/test_cases_submesh04/node_sim_corenode1.c new file mode 100644 index 00000000..d37c54a9 --- /dev/null +++ b/test/blackbox/test_cases_submesh04/node_sim_corenode1.c @@ -0,0 +1,188 @@ +/* + node_sim.c -- Implementation of Node Simulation for Meshlink Testing + for meta connection test case 01 - re-connection of + two nodes when relay node goes down + 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 +#include +#include +#include +#include +#include "../common/common_handlers.h" +#include "../common/test_step.h" +#include "../common/mesh_event_handler.h" +#include "../../utils.h" + +#define CMD_LINE_ARG_NODENAME 1 +#define CMD_LINE_ARG_DEVCLASS 2 +#define CMD_LINE_ARG_CLIENTID 3 +#define CMD_LINE_ARG_IMPORTSTR 4 +#define CMD_LINE_ARG_INVITEURL 5 +#define CHANNEL_PORT 1234 + +static bool conn_status = false; +static int client_id = -1; + +static struct sync_flag peer_reachable = {.mutex = PTHREAD_MUTEX_INITIALIZER, .cond = PTHREAD_COND_INITIALIZER, .flag = false}; +static struct sync_flag channel_opened = {.mutex = PTHREAD_MUTEX_INITIALIZER, .cond = PTHREAD_COND_INITIALIZER, .flag = false}; +static struct sync_flag channel_data_recieved = {.mutex = PTHREAD_MUTEX_INITIALIZER, .cond = PTHREAD_COND_INITIALIZER, .flag = false}; + +static meshlink_handle_t *mesh = NULL; + +static void mesh_send_message_handler(char *destination); + +static void send_event(mesh_event_t event) { + int attempts; + + for(attempts = 0; attempts < 5; attempts += 1) { + if(mesh_event_sock_send(client_id, event, NULL, 0)) { + break; + } + } + + assert(attempts < 5); + + return; +} + +/* channel receive callback */ +static void channel_receive_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, const void *dat, size_t len) { + char data[100] = {0}; + + if(len == 0) { + send_event(ERR_NETWORK); + return; + } + + memcpy(data, dat, len); + + fprintf(stderr, "corenode1 got message from %s as %s\n", channel->node->name, data); + + if(!memcmp(dat, "Channel Message", len)) { + mesh_send_message_handler((char *)channel->node->name); + + if(0 == strcmp("app1node2", channel->node->name)) { + set_sync_flag(&channel_data_recieved, true); + } + } else if(!memcmp(dat, "failure", 7)) { + assert(false); + } + + return; +} + +static void node_status_cb(meshlink_handle_t *mesh, meshlink_node_t *node, + bool reachable) { + if(reachable) { + fprintf(stderr, "Node %s became reachable\n", node->name); + } else { + fprintf(stderr, "Node %s is unreachable\n", node->name); + } + + return; +} + +static void poll_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, size_t len) { + char *message = "Channel Message"; + char *node = (char *)channel->node->name; + (void)len; + meshlink_set_channel_poll_cb(mesh, channel, NULL); + fprintf(stderr, "corenode1's Channel request has been accepted by %s at : %lu\n", node, time(NULL)); + + if(0 == strcmp("app1node2", node)) { + set_sync_flag(&channel_opened, true); + } + + assert(meshlink_channel_send(mesh, channel, message, strlen(message)) >= 0); + return; +} + +/* channel receive callback */ +static bool channel_accept(meshlink_handle_t *mesh, meshlink_channel_t *channel, uint16_t port, const void *dat, size_t len) { + (void)dat; + (void)len; + + assert(port == CHANNEL_PORT); + + fprintf(stderr, "corenode1 got channel request from %s\n", channel->node->name); + meshlink_set_channel_receive_cb(mesh, channel, channel_receive_cb); + + return true; +} + +void mesh_send_message_handler(char *destination) { + meshlink_channel_t *channel = NULL; + meshlink_node_t *target_node = NULL; + + // Open a channel to destination node + target_node = meshlink_get_node(mesh, destination); + assert(target_node); + fprintf(stderr, "corenode1 Sending Channel request to %s at : %lu\n", destination, time(NULL)); + channel = meshlink_channel_open(mesh, target_node, CHANNEL_PORT, + channel_receive_cb, NULL, 0); + meshlink_set_channel_poll_cb(mesh, channel, poll_cb); +} + +int main(int argc, char *argv[]) { + struct timeval main_loop_wait = { 5, 0 }; + int i; + + // Import mesh event handler + + fprintf(stderr, "Mesh node 'corenode1' starting up........\n"); + + if((argv[CMD_LINE_ARG_CLIENTID]) && (argv[CMD_LINE_ARG_IMPORTSTR])) { + client_id = atoi(argv[CMD_LINE_ARG_CLIENTID]); + mesh_event_sock_connect(argv[CMD_LINE_ARG_IMPORTSTR]); + } + + setup_signals(); + + // Execute test steps + + mesh = meshlink_open("testconf", argv[CMD_LINE_ARG_NODENAME], + "test_channel_conn", atoi(argv[CMD_LINE_ARG_DEVCLASS])); + assert(mesh); + meshlink_set_log_cb(mesh, MESHLINK_DEBUG, meshlink_callback_logger); + meshlink_set_channel_accept_cb(mesh, channel_accept); + meshlink_set_node_status_cb(mesh, node_status_cb); + + if(argv[CMD_LINE_ARG_INVITEURL]) { + assert(meshlink_join(mesh, argv[CMD_LINE_ARG_INVITEURL])); + } + + assert(meshlink_start(mesh)); + + send_event(NODE_STARTED); + + assert(wait_sync_flag(&channel_opened, 50)); + send_event(CHANNEL_OPENED); + + assert(wait_sync_flag(&channel_data_recieved, 50)); + send_event(CHANNEL_DATA_RECIEVED); + + // All test steps executed - wait for signals to stop/start or close the mesh + + while(test_running) { + select(1, NULL, NULL, NULL, &main_loop_wait); + } + + meshlink_close(mesh); + + return 0; +} diff --git a/test/blackbox/util/gen_invite.c b/test/blackbox/util/gen_invite.c index 1517be8a..beb7401f 100644 --- a/test/blackbox/util/gen_invite.c +++ b/test/blackbox/util/gen_invite.c @@ -24,33 +24,23 @@ #define CMD_LINE_ARG_NODENAME 1 #define CMD_LINE_ARG_INVITEE 2 - -void logger_cb(meshlink_handle_t *mesh, meshlink_log_level_t level, - const char *text) { - (void)mesh; - (void)level; - - fprintf(stderr, "meshlink>> %s\n", text); -} +#define CMD_LINE_ARG_SUBMESH 3 int main(int argc, char *argv[]) { char *invite = NULL; + meshlink_submesh_t *s = NULL; /* Start mesh, generate an invite and print out the invite */ - /* Set up logging for Meshlink */ - meshlink_set_log_cb(NULL, MESHLINK_DEBUG, logger_cb); - - /* Create meshlink instance */ - meshlink_handle_t *mesh = meshlink_open("testconf", argv[1], "node_sim", DEV_CLASS_STATIONARY); - assert(mesh); - - /* Set up logging for Meshlink with the newly acquired Mesh Handle */ - meshlink_set_log_cb(mesh, MESHLINK_DEBUG, logger_cb); - meshlink_enable_discovery(mesh, false); - assert(meshlink_start(mesh)); - invite = meshlink_invite_ex(mesh, NULL, argv[2], MESHLINK_INVITE_LOCAL | MESHLINK_INVITE_NUMERIC); + meshlink_handle_t *mesh = execute_open(argv[CMD_LINE_ARG_NODENAME], "1"); + execute_start(); + + if(argc > CMD_LINE_ARG_SUBMESH) { + s = meshlink_submesh_open(mesh, argv[CMD_LINE_ARG_SUBMESH]); + } + + invite = execute_invite(argv[CMD_LINE_ARG_INVITEE], s); printf("%s\n", invite); - meshlink_close(mesh); + execute_close(); return EXIT_SUCCESS; }