]> git.meshlink.io Git - meshlink/commitdiff
Add the blackbox container based test suite.
authorElear Solutions Dev <mail@elear.solutions>
Thu, 8 Nov 2018 20:01:10 +0000 (21:01 +0100)
committerGuus Sliepen <guus@meshlink.io>
Thu, 8 Nov 2018 21:23:53 +0000 (22:23 +0100)
This test suite uses LXC containers to simulate various nodes connected
to each other in different network topologies, and allows for realistic
testing of the MeshLink library.

129 files changed:
.gitignore
Makefile.am
configure.ac
test/.gitignore
test/Makefile.am
test/blackbox/.gitignore [new file with mode: 0644]
test/blackbox/Makefile.am [new file with mode: 0644]
test/blackbox/common/common_handlers.c [new file with mode: 0644]
test/blackbox/common/common_handlers.h [new file with mode: 0644]
test/blackbox/common/common_types.h [new file with mode: 0644]
test/blackbox/common/containers.c [new file with mode: 0644]
test/blackbox/common/containers.h [new file with mode: 0644]
test/blackbox/common/mesh_event_handler.c [new file with mode: 0644]
test/blackbox/common/mesh_event_handler.h [new file with mode: 0644]
test/blackbox/common/tcpdump.c [new file with mode: 0644]
test/blackbox/common/tcpdump.h [new file with mode: 0644]
test/blackbox/common/test_step.c [new file with mode: 0644]
test/blackbox/common/test_step.h [new file with mode: 0644]
test/blackbox/run_blackbox_tests/.gitignore [new file with mode: 0644]
test/blackbox/run_blackbox_tests/Makefile.am [new file with mode: 0644]
test/blackbox/run_blackbox_tests/execute_tests.c [new file with mode: 0644]
test/blackbox/run_blackbox_tests/execute_tests.h [new file with mode: 0644]
test/blackbox/run_blackbox_tests/run_blackbox_tests.c [new file with mode: 0644]
test/blackbox/run_blackbox_tests/test_cases.c [new file with mode: 0644]
test/blackbox/run_blackbox_tests/test_cases.h [new file with mode: 0644]
test/blackbox/run_blackbox_tests/test_cases_add_addr.c [new file with mode: 0644]
test/blackbox/run_blackbox_tests/test_cases_add_addr.h [new file with mode: 0644]
test/blackbox/run_blackbox_tests/test_cases_add_ex_addr.c [new file with mode: 0644]
test/blackbox/run_blackbox_tests/test_cases_add_ex_addr.h [new file with mode: 0644]
test/blackbox/run_blackbox_tests/test_cases_blacklist.c [new file with mode: 0644]
test/blackbox/run_blackbox_tests/test_cases_blacklist.h [new file with mode: 0644]
test/blackbox/run_blackbox_tests/test_cases_channel_close.c [new file with mode: 0644]
test/blackbox/run_blackbox_tests/test_cases_channel_close.h [new file with mode: 0644]
test/blackbox/run_blackbox_tests/test_cases_channel_conn.h [new file with mode: 0644]
test/blackbox/run_blackbox_tests/test_cases_channel_ex.c [new file with mode: 0644]
test/blackbox/run_blackbox_tests/test_cases_channel_ex.h [new file with mode: 0644]
test/blackbox/run_blackbox_tests/test_cases_channel_get_flags.c [new file with mode: 0644]
test/blackbox/run_blackbox_tests/test_cases_channel_get_flags.h [new file with mode: 0644]
test/blackbox/run_blackbox_tests/test_cases_channel_open.c [new file with mode: 0644]
test/blackbox/run_blackbox_tests/test_cases_channel_open.h [new file with mode: 0644]
test/blackbox/run_blackbox_tests/test_cases_channel_send.c [new file with mode: 0644]
test/blackbox/run_blackbox_tests/test_cases_channel_send.h [new file with mode: 0644]
test/blackbox/run_blackbox_tests/test_cases_channel_set_accept_cb.c [new file with mode: 0644]
test/blackbox/run_blackbox_tests/test_cases_channel_set_accept_cb.h [new file with mode: 0644]
test/blackbox/run_blackbox_tests/test_cases_channel_set_poll_cb.c [new file with mode: 0644]
test/blackbox/run_blackbox_tests/test_cases_channel_set_poll_cb.h [new file with mode: 0644]
test/blackbox/run_blackbox_tests/test_cases_channel_set_receive_cb.c [new file with mode: 0644]
test/blackbox/run_blackbox_tests/test_cases_channel_set_receive_cb.h [new file with mode: 0644]
test/blackbox/run_blackbox_tests/test_cases_channel_shutdown.c [new file with mode: 0644]
test/blackbox/run_blackbox_tests/test_cases_channel_shutdown.h [new file with mode: 0644]
test/blackbox/run_blackbox_tests/test_cases_default_blacklist.c [new file with mode: 0644]
test/blackbox/run_blackbox_tests/test_cases_default_blacklist.h [new file with mode: 0644]
test/blackbox/run_blackbox_tests/test_cases_destroy.c [new file with mode: 0644]
test/blackbox/run_blackbox_tests/test_cases_destroy.h [new file with mode: 0644]
test/blackbox/run_blackbox_tests/test_cases_export.c [new file with mode: 0644]
test/blackbox/run_blackbox_tests/test_cases_export.h [new file with mode: 0644]
test/blackbox/run_blackbox_tests/test_cases_get_all_nodes.c [new file with mode: 0644]
test/blackbox/run_blackbox_tests/test_cases_get_all_nodes.h [new file with mode: 0644]
test/blackbox/run_blackbox_tests/test_cases_get_ex_addr.c [new file with mode: 0644]
test/blackbox/run_blackbox_tests/test_cases_get_ex_addr.h [new file with mode: 0644]
test/blackbox/run_blackbox_tests/test_cases_get_fingerprint.c [new file with mode: 0644]
test/blackbox/run_blackbox_tests/test_cases_get_fingerprint.h [new file with mode: 0644]
test/blackbox/run_blackbox_tests/test_cases_get_node.c [new file with mode: 0644]
test/blackbox/run_blackbox_tests/test_cases_get_node.h [new file with mode: 0644]
test/blackbox/run_blackbox_tests/test_cases_get_port.c [new file with mode: 0644]
test/blackbox/run_blackbox_tests/test_cases_get_port.h [new file with mode: 0644]
test/blackbox/run_blackbox_tests/test_cases_get_self.c [new file with mode: 0644]
test/blackbox/run_blackbox_tests/test_cases_get_self.h [new file with mode: 0644]
test/blackbox/run_blackbox_tests/test_cases_hint_address.c [new file with mode: 0644]
test/blackbox/run_blackbox_tests/test_cases_hint_address.h [new file with mode: 0644]
test/blackbox/run_blackbox_tests/test_cases_import.c [new file with mode: 0644]
test/blackbox/run_blackbox_tests/test_cases_import.h [new file with mode: 0644]
test/blackbox/run_blackbox_tests/test_cases_invite.c [new file with mode: 0644]
test/blackbox/run_blackbox_tests/test_cases_invite.h [new file with mode: 0644]
test/blackbox/run_blackbox_tests/test_cases_join.c [new file with mode: 0644]
test/blackbox/run_blackbox_tests/test_cases_join.h [new file with mode: 0644]
test/blackbox/run_blackbox_tests/test_cases_open.c [new file with mode: 0644]
test/blackbox/run_blackbox_tests/test_cases_open.h [new file with mode: 0644]
test/blackbox/run_blackbox_tests/test_cases_pmtu.c [new file with mode: 0644]
test/blackbox/run_blackbox_tests/test_cases_pmtu.h [new file with mode: 0644]
test/blackbox/run_blackbox_tests/test_cases_rec_cb.c [new file with mode: 0644]
test/blackbox/run_blackbox_tests/test_cases_rec_cb.h [new file with mode: 0644]
test/blackbox/run_blackbox_tests/test_cases_send.c [new file with mode: 0644]
test/blackbox/run_blackbox_tests/test_cases_send.h [new file with mode: 0644]
test/blackbox/run_blackbox_tests/test_cases_set_log_cb.c [new file with mode: 0644]
test/blackbox/run_blackbox_tests/test_cases_set_log_cb.h [new file with mode: 0644]
test/blackbox/run_blackbox_tests/test_cases_set_port.c [new file with mode: 0644]
test/blackbox/run_blackbox_tests/test_cases_set_port.h [new file with mode: 0644]
test/blackbox/run_blackbox_tests/test_cases_sign.c [new file with mode: 0644]
test/blackbox/run_blackbox_tests/test_cases_sign.h [new file with mode: 0644]
test/blackbox/run_blackbox_tests/test_cases_start.c [new file with mode: 0644]
test/blackbox/run_blackbox_tests/test_cases_start.h [new file with mode: 0644]
test/blackbox/run_blackbox_tests/test_cases_status_cb.c [new file with mode: 0644]
test/blackbox/run_blackbox_tests/test_cases_status_cb.h [new file with mode: 0644]
test/blackbox/run_blackbox_tests/test_cases_stop_close.c [new file with mode: 0644]
test/blackbox/run_blackbox_tests/test_cases_stop_close.h [new file with mode: 0644]
test/blackbox/run_blackbox_tests/test_cases_verify.c [new file with mode: 0644]
test/blackbox/run_blackbox_tests/test_cases_verify.h [new file with mode: 0644]
test/blackbox/run_blackbox_tests/test_cases_whitelist.c [new file with mode: 0644]
test/blackbox/run_blackbox_tests/test_cases_whitelist.h [new file with mode: 0644]
test/blackbox/test_case_meta_conn_01/Makefile.am [new file with mode: 0644]
test/blackbox/test_case_meta_conn_01/node_sim_nut.c [new file with mode: 0644]
test/blackbox/test_case_meta_conn_01/node_sim_peer.c [new file with mode: 0644]
test/blackbox/test_case_meta_conn_01/node_sim_relay.c [new file with mode: 0644]
test/blackbox/test_case_meta_conn_02/Makefile.am [new file with mode: 0644]
test/blackbox/test_case_meta_conn_02/node_sim_nut.c [new file with mode: 0644]
test/blackbox/test_case_meta_conn_02/node_sim_peer.c [new file with mode: 0644]
test/blackbox/test_case_meta_conn_02/node_sim_relay.c [new file with mode: 0644]
test/blackbox/test_case_meta_conn_03/Makefile.am [new file with mode: 0644]
test/blackbox/test_case_meta_conn_03/node_sim_nut.c [new file with mode: 0644]
test/blackbox/test_case_meta_conn_03/node_sim_peer.c [new file with mode: 0644]
test/blackbox/test_case_meta_conn_03/node_sim_relay.c [new file with mode: 0644]
test/blackbox/test_case_meta_conn_04/Makefile.am [new file with mode: 0644]
test/blackbox/test_case_meta_conn_04/node_sim_nut.c [new file with mode: 0644]
test/blackbox/test_case_meta_conn_04/node_sim_peer.c [new file with mode: 0644]
test/blackbox/test_case_meta_conn_04/node_sim_relay.c [new file with mode: 0644]
test/blackbox/test_case_meta_conn_05/Makefile.am [new file with mode: 0644]
test/blackbox/test_case_meta_conn_05/node_sim_nut.c [new file with mode: 0644]
test/blackbox/test_case_meta_conn_05/node_sim_peer.c [new file with mode: 0644]
test/blackbox/test_case_meta_conn_05/node_sim_relay.c [new file with mode: 0644]
test/blackbox/util/build_container.sh [new file with mode: 0755]
test/blackbox/util/gen_invite.c [new file with mode: 0644]
test/blackbox/util/install_node_sim_copy.sh [new file with mode: 0755]
test/blackbox/util/lxc_copy_dir.sh [new file with mode: 0755]
test/blackbox/util/lxc_copy_file.sh [new file with mode: 0755]
test/blackbox/util/lxc_rename.sh [new file with mode: 0755]
test/blackbox/util/lxc_run.sh [new file with mode: 0755]
test/blackbox/util/node_step.sh [new file with mode: 0755]
test/run_blackbox_tests.sh [new file with mode: 0755]

index 1bc77a1423c0f545e51714ffcf14b32e01196cd8..13a8886d66071f3f0573f8138f30dbe8813d1977 100644 (file)
@@ -18,6 +18,7 @@ tags
 /autom4te.cache
 /aclocal.m4
 /aminclude.am
+/ar-lib
 /compile
 /configure
 /depcomp
index 93bc963224fc5a73a60df159c2d42d7874e6dfa2..4220d3c872487fcea41d6fc8fb6c76619ecd3ba7 100644 (file)
@@ -20,4 +20,9 @@ ChangeLog:
        git log > ChangeLog
 
 astyle:
-       astyle --options=.astylerc -nQ src/*.[ch] src/ed25519/e*.[ch] examples/*.[ch] examples/*.cc test/*.[ch]
+       astyle --options=.astylerc -nQ \
+               src/*.[ch] \
+               src/ed25519/e*.[ch] \
+               examples/*.[ch] \
+               examples/*.cc \
+               `find test -name '*.[ch]'`
index e02f5c37050524fbd9485922be2a62042d926fcf..363676eec55e21d22a19f2c0c332d8ca0aacb31a 100644 (file)
@@ -138,6 +138,19 @@ AC_CHECK_DECLS([freeaddrinfo, gai_strerror, getaddrinfo, getnameinfo],
 
 AC_CACHE_SAVE
 
-AC_CONFIG_FILES([Makefile src/Makefile doc/Makefile test/Makefile examples/Makefile])
+AC_CONFIG_FILES([
+        Makefile
+        src/Makefile
+        doc/Makefile
+        test/Makefile
+        test/blackbox/Makefile
+        test/blackbox/run_blackbox_tests/Makefile
+        test/blackbox/test_case_meta_conn_01/Makefile
+        test/blackbox/test_case_meta_conn_02/Makefile
+        test/blackbox/test_case_meta_conn_03/Makefile
+        test/blackbox/test_case_meta_conn_04/Makefile
+        test/blackbox/test_case_meta_conn_05/Makefile
+        examples/Makefile
+])
 
 AC_OUTPUT
index 62e05a88e5c70b15ca6819bca1fd373226064c1f..cbb1c1eeaa0389137f090ef4c6f8a07f51f02b06 100644 (file)
@@ -1,12 +1,14 @@
-*
-!*.*
-.*
-*/
 *.log
 *.trs
-*.o
-/Makefile
-/Makefile.in
-vgcore.*
-core
-core.*
+/basic
+/basicpp
+/channels
+/channels-cornercases
+/channels-fork
+/duplicate
+/echo-fork
+/import-export
+/invite-join
+/sign-verify
+/trio
+/*.[0123456789]
index 0bc98d0cf7bf2c9c8557773dcbdd5b270c3c8071..77fd5ef1828734e739aaa2d66b0b8504dd7f4f99 100644 (file)
@@ -10,6 +10,8 @@ TESTS = \
        sign-verify.test \
        trio.test
 
+SUBDIRS = blackbox
+
 dist_check_SCRIPTS = $(TESTS)
 
 AM_CPPFLAGS = $(PTHREAD_CFLAGS) -I${top_srcdir}/src -iquote. -Wall
diff --git a/test/blackbox/.gitignore b/test/blackbox/.gitignore
new file mode 100644 (file)
index 0000000..4190b42
--- /dev/null
@@ -0,0 +1,5 @@
+gen_invite
+node_sim_peer
+node_sim_nut
+node_sim_relay
+interfaces
diff --git a/test/blackbox/Makefile.am b/test/blackbox/Makefile.am
new file mode 100644 (file)
index 0000000..3afae4b
--- /dev/null
@@ -0,0 +1,13 @@
+check_PROGRAMS = gen_invite
+
+SUBDIRS = \
+       run_blackbox_tests \
+       test_case_meta_conn_01 \
+       test_case_meta_conn_02 \
+       test_case_meta_conn_03 \
+       test_case_meta_conn_04 \
+       test_case_meta_conn_05
+
+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
+gen_invite_CFLAGS = -D_GNU_SOURCE
diff --git a/test/blackbox/common/common_handlers.c b/test/blackbox/common/common_handlers.c
new file mode 100644 (file)
index 0000000..ad32a22
--- /dev/null
@@ -0,0 +1,183 @@
+/*
+    common_handlers.c -- Implementation of common callback handling and signal handling
+                            functions for black box tests
+    Copyright (C) 2018  Guus Sliepen <guus@meshlink.io>
+
+    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 <stdio.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/ioctl.h>
+#include <net/if.h>
+#include <arpa/inet.h>
+#include <sys/socket.h>
+#include <netdb.h>
+#include <ifaddrs.h>
+#include <ctype.h>
+#include "test_step.h"
+#include "common_handlers.h"
+
+char *lxc_bridge = NULL;
+black_box_state_t *state_ptr = NULL;
+
+bool meta_conn_status[10];
+
+bool test_running;
+
+static int meshlink_get_node_in_container(const char *name) {
+       int i;
+
+       for(i = 0; i < state_ptr->num_nodes; i++) {
+               if(!strcasecmp(state_ptr->node_names[i], name)) {
+                       return i;
+                       break;
+               }
+       }
+
+       return -1;
+}
+
+void mesh_close_signal_handler(int a) {
+       test_running = false;
+
+       exit(EXIT_SUCCESS);
+}
+
+void setup_signals(void) {
+       test_running = true;
+       signal(SIGTERM, mesh_close_signal_handler);
+}
+
+/* Return the IP Address of the Interface 'if_name'
+    The caller is responsible for freeing the dynamically allocated string that is returned */
+char *get_ip(const char *if_name) {
+       struct ifaddrs *ifaddr, *ifa;
+       char *ip;
+       int family;
+
+       ip = malloc(NI_MAXHOST);
+       assert(ip);
+       assert(getifaddrs(&ifaddr) != -1);
+
+       for(ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
+               if(ifa->ifa_addr == NULL) {
+                       continue;
+               }
+
+               family = ifa->ifa_addr->sa_family;
+
+               if(family == AF_INET && !strcmp(ifa->ifa_name, if_name)) {
+                       assert(!getnameinfo(ifa->ifa_addr, (family == AF_INET) ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6), ip, NI_MAXHOST, NULL, 0, NI_NUMERICHOST));
+                       break;
+               }
+       }
+
+       return ip;
+}
+
+/* Return the IP Address of the Interface 'if_name'
+    The caller is responsible for freeing the dynamically allocated string that is returned */
+char *get_netmask(const char *if_name) {
+       struct ifaddrs *ifaddr, *ifa;
+       char *ip;
+       int family;
+
+       ip = malloc(NI_MAXHOST);
+       assert(ip);
+       assert(getifaddrs(&ifaddr) != -1);
+
+       for(ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
+               if(ifa->ifa_addr == NULL) {
+                       continue;
+               }
+
+               family = ifa->ifa_addr->sa_family;
+
+               if(family == AF_INET && !strcmp(ifa->ifa_name, if_name)) {
+                       assert(!getnameinfo(ifa->ifa_netmask, (family == AF_INET) ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6), ip, NI_MAXHOST, NULL, 0, NI_NUMERICHOST));
+                       break;
+               }
+       }
+
+       return ip;
+}
+
+/* Change the IP Address of an interface */
+void set_ip(const char *if_name, const char *new_ip) {
+       char set_ip_cmd[100];
+       assert(snprintf(set_ip_cmd, sizeof(set_ip_cmd), "ifconfig %s %s", if_name, new_ip) >= 0);
+       assert(system(set_ip_cmd) == 0);
+}
+
+/* Change the Netmask of an interface */
+void set_netmask(const char *if_name, const char *new_netmask) {
+       char set_mask_cmd[100];
+       assert(snprintf(set_mask_cmd, sizeof(set_mask_cmd), "ifconfig %s netmask %s", if_name, new_netmask) >= 0);
+       assert(system(set_mask_cmd) == 0);
+}
+
+/* Bring a network interface down (before making changes such as the IP Address) */
+void stop_nw_intf(const char *if_name) {
+       char nw_down_cmd[100];
+       assert(snprintf(nw_down_cmd, sizeof(nw_down_cmd), "ifconfig %s down", if_name) >= 0);
+       assert(system(nw_down_cmd) == 0);
+}
+
+/* Bring a network interface up (after bringing it down and making changes such as
+    the IP Address) */
+void start_nw_intf(const char *if_name) {
+       char nw_up_cmd[100];
+       assert(snprintf(nw_up_cmd, sizeof(nw_up_cmd), "ifconfig %s up", if_name) >= 0);
+       assert(system(nw_up_cmd) == 0);
+}
+
+void meshlink_callback_node_status(meshlink_handle_t *mesh, meshlink_node_t *node,
+                                   bool reachable) {
+       (void)mesh;
+       fprintf(stderr, "Node %s became %s\n", node->name, (reachable) ? "reachable" : "unreachable");
+}
+
+void meshlink_callback_logger(meshlink_handle_t *mesh, meshlink_log_level_t level,
+                              const char *text) {
+       (void)mesh;
+       (void)level;
+
+       fprintf(stderr, "meshlink>> %s\n", text);
+
+       if(state_ptr) {
+               bool status;
+               char name[100];
+
+               if(sscanf(text, "Connection with %s activated", name) == 1) {
+                       status = true;
+               } else if(sscanf(text, "Already connected to %s", name) == 1) {
+                       status = true;
+               } else if(sscanf(text, "Connection closed by %s", name) == 1) {
+                       status = false;
+               } else if(sscanf(text, "Closing connection with %s", name) == 1) {
+                       status = false;
+               } else {
+                       return;
+               }
+
+               int i = meshlink_get_node_in_container(name);
+               assert(i != -1);
+               meta_conn_status[i] = status;
+       }
+}
diff --git a/test/blackbox/common/common_handlers.h b/test/blackbox/common/common_handlers.h
new file mode 100644 (file)
index 0000000..7c5fbd2
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+    common_handlers.h -- Declarations of common callback handlers and signal handlers for
+                            black box test cases
+    Copyright (C) 2018  Guus Sliepen <guus@meshlink.io>
+
+    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.
+*/
+
+#ifndef COMMON_HANDLERS_H
+#define COMMON_HANDLERS_H
+
+#include "common_types.h"
+
+#define PRINT_TEST_CASE_HEADER()        if(state_ptr) \
+               fprintf(stderr, "[ %s ]\n", state_ptr->test_case_name)
+#define PRINT_TEST_CASE_MSG(...)        if(state_ptr) \
+               do { \
+                       fprintf(stderr, "[ %s ] ", \
+                               state_ptr->test_case_name); \
+                       fprintf(stderr, __VA_ARGS__); \
+               } while(0)
+
+extern bool meta_conn_status[];
+extern bool node_reachable_status[];
+extern bool test_running;
+
+char *get_ip(const char *if_name);
+char *get_netmask(const char *if_name);
+void stop_nw_intf(const char *if_name);
+void start_nw_intf(const char *if_name);
+void set_ip(const char *if_name, const char *new_ip);
+void set_netmask(const char *if_name, const char *new_ip);
+void mesh_close_signal_handler(int a);
+void mesh_stop_start_signal_handler(int a);
+void setup_signals(void);
+void meshlink_callback_node_status(meshlink_handle_t *mesh, meshlink_node_t *node,
+                                   bool reachable);
+void meshlink_callback_logger(meshlink_handle_t *mesh, meshlink_log_level_t level,
+                              const char *text);
+
+#endif // COMMON_HANDLERS_H
diff --git a/test/blackbox/common/common_types.h b/test/blackbox/common/common_types.h
new file mode 100644 (file)
index 0000000..d0e4d96
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+    common_types.h -- Declarations of common types used in Black Box Testing
+    Copyright (C) 2018  Guus Sliepen <guus@meshlink.io>
+
+    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.
+*/
+
+#ifndef COMMON_TYPES_H
+#define COMMON_TYPES_H
+
+#include <stdbool.h>
+#include "../../../src/meshlink.h"
+
+#define NUT_NODE_NAME "nut"
+
+#define LXC_UTIL_REL_PATH "test/blackbox/util"
+#define LXC_RENAME_SCRIPT "lxc_rename.sh"
+#define LXC_RUN_SCRIPT "lxc_run.sh"
+#define LXC_COPY_SCRIPT "lxc_copy_file.sh"
+#define LXC_BUILD_SCRIPT "build_container.sh"
+
+typedef struct black_box_state {
+       char *test_case_name;
+       char **node_names;
+       int num_nodes;
+       bool test_result;
+} black_box_state_t;
+
+extern char *lxc_bridge;
+
+extern char *eth_if_name;
+
+extern black_box_state_t *state_ptr;
+
+extern char *meshlink_root_path;
+
+/* Meshlink Mesh Handle */
+extern meshlink_handle_t *mesh_handle;
+
+/* Flag to indicate if Mesh is running */
+extern bool mesh_started;
+
+#endif // COMMON_TYPES_H
diff --git a/test/blackbox/common/containers.c b/test/blackbox/common/containers.c
new file mode 100644 (file)
index 0000000..263cbf9
--- /dev/null
@@ -0,0 +1,455 @@
+/*
+    containers.h -- Container Management API
+    Copyright (C) 2018  Guus Sliepen <guus@meshlink.io>
+
+    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 <stdlib.h>
+#include <assert.h>
+#include <string.h>
+#include <unistd.h>
+#include <pthread.h>
+#include "containers.h"
+#include "common_handlers.h"
+
+char *lxc_path = NULL;
+char *choose_arch;
+static char container_ips[10][100];
+
+/* Return the handle to an existing container after finding it by container name */
+struct lxc_container *find_container(const char *name) {
+       struct lxc_container **test_containers;
+       char **container_names;
+       int num_containers, i;
+
+       assert((num_containers = list_all_containers(lxc_path, &container_names,
+                                &test_containers)) != -1);
+
+       for(i = 0; i < num_containers; i++) {
+               if(strcmp(container_names[i], name) == 0) {
+                       return test_containers[i];
+               }
+       }
+
+       return NULL;
+}
+
+/* Rename a Container */
+void rename_container(const char *old_name, const char *new_name) {
+       char rename_command[200];
+       int rename_status;
+       struct lxc_container *old_container;
+
+       /* Stop the old container if its still running */
+       assert(old_container = find_container(old_name));
+       old_container->shutdown(old_container, CONTAINER_SHUTDOWN_TIMEOUT);
+       /* Call stop() in case shutdown() fails - one of these two will always succeed */
+       old_container->stop(old_container);
+       /* Rename the Container */
+       /* TO DO: Perform this operation using the LXC API - currently does not work via the API,
+           need to investigate and determine why it doesn't work, and make it work */
+       assert(snprintf(rename_command, sizeof(rename_command),
+                       "%s/" LXC_UTIL_REL_PATH "/" LXC_RENAME_SCRIPT " %s %s %s", meshlink_root_path, lxc_path,
+                       old_name, new_name) >= 0);
+       rename_status = system(rename_command);
+       PRINT_TEST_CASE_MSG("Container '%s' rename status: %d\n", old_name, rename_status);
+       assert(rename_status == 0);
+}
+
+/* Run 'cmd' inside the Container created for 'node' and return the first line of the output
+    or NULL if there is no output - useful when, for example, a meshlink invite is generated
+    by a node running inside a Container
+    'cmd' is run as a daemon if 'daemonize' is true - this mode is useful for running node
+    simulations in Containers
+    The caller is responsible for freeing the returned string */
+char *run_in_container(const char *cmd, const char *node, bool daemonize) {
+       char attach_command[400];
+       char *attach_argv[4];
+       char container_find_name[100];
+       struct lxc_container *container;
+       FILE *attach_fp;
+       char *output = NULL;
+       size_t output_len;
+       int i;
+
+       assert(snprintf(container_find_name, sizeof(container_find_name), "%s_%s",
+                       state_ptr->test_case_name, node) >= 0);
+       assert(container = find_container(container_find_name));
+
+       /* Run the command within the Container, either as a daemon or foreground process */
+       /* TO DO: Perform this operation using the LXC API - currently does not work using the API
+           Need to determine why it doesn't work, and make it work */
+       if(daemonize) {
+               for(i = 0; i < 3; i++) {
+                       assert(attach_argv[i] = malloc(DAEMON_ARGV_LEN));
+               }
+
+               assert(snprintf(attach_argv[0], DAEMON_ARGV_LEN, "%s/" LXC_UTIL_REL_PATH "/" LXC_RUN_SCRIPT,
+                               meshlink_root_path) >= 0);
+               strncpy(attach_argv[1], cmd, DAEMON_ARGV_LEN);
+               strncpy(attach_argv[2], container->name, DAEMON_ARGV_LEN);
+               attach_argv[3] = NULL;
+
+               /* To daemonize, create a child process and detach it from its parent (this program) */
+               if(fork() == 0) {
+                       assert(daemon(1, 0) != -1);    // Detach from the parent process
+                       assert(execv(attach_argv[0], attach_argv) != -1);   // Run exec() in the child process
+               }
+
+               for(i = 0; i < 3; i++) {
+                       free(attach_argv[i]);
+               }
+       } else {
+               assert(snprintf(attach_command, sizeof(attach_command),
+                               "%s/" LXC_UTIL_REL_PATH "/" LXC_RUN_SCRIPT " \"%s\" %s", meshlink_root_path, cmd,
+                               container->name) >= 0);
+               assert(attach_fp = popen(attach_command, "r"));
+               /* If the command has an output, strip out any trailing carriage returns or newlines and
+                   return it, otherwise return NULL */
+               assert(output = malloc(100));
+               output_len = sizeof(output);
+
+               if(getline(&output, &output_len, attach_fp) != -1) {
+                       i = strlen(output) - 1;
+
+                       while(output[i] == '\n' || output[i] == '\r') {
+                               i--;
+                       }
+
+                       output[i + 1] = '\0';
+               } else {
+                       free(output);
+                       output = NULL;
+               }
+
+               assert(pclose(attach_fp) != -1);
+       }
+
+       return output;
+}
+
+/* Wait for a starting Container to obtain an IP Address, then save that IP for future use */
+void container_wait_ip(int node) {
+       char container_name[100], lxcls_command[200];
+       struct lxc_container *test_container;
+       char *ip;
+       size_t ip_len;
+       int i;
+       bool ip_found;
+       FILE *lxcls_fp;
+
+       assert(snprintf(container_name, sizeof(container_name), "%s_%s", state_ptr->test_case_name,
+                       state_ptr->node_names[node]) >= 0);
+       assert(test_container = find_container(container_name));
+       assert(snprintf(lxcls_command, sizeof(lxcls_command),
+                       "lxc-ls -f | grep %s | tr -s ' ' | cut -d ' ' -f 5", test_container->name) >= 0);
+       PRINT_TEST_CASE_MSG("Waiting for Container '%s' to acquire IP\n", test_container->name);
+       assert(ip = malloc(20));
+       ip_len = sizeof(ip);
+       ip_found = false;
+
+       while(!ip_found) {
+               assert(lxcls_fp = popen(lxcls_command, "r"));   // Run command
+               assert(getline((char **)&ip, &ip_len, lxcls_fp) != -1); // Read its output
+               /* Strip newlines and carriage returns from output */
+               i = strlen(ip) - 1;
+
+               while(ip[i] == '\n' || ip[i] == '\r') {
+                       i--;
+               }
+
+               ip[i + 1] = '\0';
+               ip_found = (strcmp(ip, "-") != 0);  // If the output is not "-", IP has been acquired
+               assert(pclose(lxcls_fp) != -1);
+               sleep(1);
+       }
+
+       strncpy(container_ips[node], ip, sizeof(container_ips[node])); // Save the IP for future use
+       PRINT_TEST_CASE_MSG("Node '%s' has IP Address %s\n", state_ptr->node_names[node],
+                           container_ips[node]);
+
+       free(ip);
+}
+
+/* Create all required test containers */
+void create_containers(const char *node_names[], int num_nodes) {
+       int i;
+       char container_name[100];
+       int create_status, snapshot_status, snap_restore_status;
+       struct lxc_container *first_container;
+
+       for(i = 0; i < num_nodes; i++) {
+               assert(snprintf(container_name, sizeof(container_name), "run_%s", node_names[i]) >= 0);
+
+               /* If this is the first Container, create it otherwise restore the snapshot saved
+                   for the first Container to create an additional Container */
+               if(i == 0) {
+                       assert(first_container = lxc_container_new(container_name, NULL));
+                       assert(!first_container->is_defined(first_container));
+                       create_status = first_container->createl(first_container, "download", NULL, NULL,
+                                       LXC_CREATE_QUIET, "-d", "ubuntu", "-r", "trusty", "-a", choose_arch, NULL);
+                       fprintf(stderr, "Container '%s' create status: %d - %s\n", container_name,
+                               first_container->error_num, first_container->error_string);
+                       assert(create_status);
+                       snapshot_status = first_container->snapshot(first_container, NULL);
+                       fprintf(stderr, "Container '%s' snapshot status: %d - %s\n", container_name,
+                               first_container->error_num, first_container->error_string);
+                       assert(snapshot_status != -1);
+               } else {
+                       snap_restore_status = first_container->snapshot_restore(first_container, "snap0",
+                                             container_name);
+                       fprintf(stderr, "Snapshot restore to Container '%s' status: %d - %s\n", container_name,
+                               first_container->error_num, first_container->error_string);
+                       assert(snap_restore_status);
+               }
+       }
+}
+
+/* Setup Containers required for a test
+    This function should always be invoked in a CMocka context
+    after setting the state of the test case to an instance of black_box_state_t */
+void setup_containers(void **state) {
+       black_box_state_t *test_state = (black_box_state_t *)(*state);
+       int i, confbase_del_status;
+       char build_command[200];
+       struct lxc_container *test_container, *new_container;
+       char container_find_name[100];
+       char container_new_name[100];
+       int create_status, build_status;
+
+       PRINT_TEST_CASE_HEADER();
+
+       for(i = 0; i < test_state->num_nodes; i++) {
+               /* Find the run_<node-name> Container or create it if it doesn't exist */
+               assert(snprintf(container_find_name, sizeof(container_find_name), "run_%s",
+                               test_state->node_names[i]) >= 0);
+
+               if(!(test_container = find_container(container_find_name))) {
+                       assert(test_container = lxc_container_new(container_find_name, NULL));
+                       assert(!test_container->is_defined(test_container));
+                       create_status = test_container->createl(test_container, "download", NULL, NULL,
+                                                               LXC_CREATE_QUIET, "-d", "ubuntu", "-r", "trusty", "-a", choose_arch, NULL);
+                       PRINT_TEST_CASE_MSG("Container '%s' create status: %d - %s\n", container_find_name,
+                                           test_container->error_num, test_container->error_string);
+                       assert(create_status);
+               }
+
+               /* Stop the Container if it's running */
+               test_container->shutdown(test_container, CONTAINER_SHUTDOWN_TIMEOUT);
+               /* Call stop() in case shutdown() fails
+                   One of these two calls will always succeed */
+               test_container->stop(test_container);
+               /* Rename the Container to make it specific to this test case,
+                   if a Container with the target name already exists, skip this step */
+               assert(snprintf(container_new_name, sizeof(container_new_name), "%s_%s",
+                               test_state->test_case_name, test_state->node_names[i]) >= 0);
+
+               if(!(new_container = find_container(container_new_name))) {
+                       rename_container(test_container->name, container_new_name);
+                       assert(new_container = find_container(container_new_name));
+               }
+
+               /* Start the Container */
+               assert(new_container->start(new_container, 0, NULL));
+               /* Build the Container by copying required files into it */
+               assert(snprintf(build_command, sizeof(build_command),
+                               "%s/" LXC_UTIL_REL_PATH "/" LXC_BUILD_SCRIPT " %s %s %s +x >/dev/null",
+                               meshlink_root_path, test_state->test_case_name, test_state->node_names[i],
+                               meshlink_root_path) >= 0);
+               build_status = system(build_command);
+               PRINT_TEST_CASE_MSG("Container '%s' build Status: %d\n", new_container->name,
+                                   build_status);
+               assert(build_status == 0);
+               /* Restart the Container after building it and wait for it to acquire an IP */
+               new_container->shutdown(new_container, CONTAINER_SHUTDOWN_TIMEOUT);
+               new_container->stop(new_container);
+               new_container->start(new_container, 0, NULL);
+               container_wait_ip(i);
+       }
+}
+
+/* Destroy all Containers with names containing 'run_' - Containers saved for debugging will
+    have names beginning with test_case_ ; 'run_' is reserved for temporary Containers
+    intended to be re-used for the next test */
+void destroy_containers(void) {
+       struct lxc_container **test_containers;
+       char **container_names;
+       int num_containers, i;
+
+       assert((num_containers = list_all_containers(lxc_path, &container_names,
+                                &test_containers)) != -1);
+
+       for(i = 0; i < num_containers; i++) {
+               if(strstr(container_names[i], "run_")) {
+                       fprintf(stderr, "Destroying Container '%s'\n", container_names[i]);
+                       /* Stop the Container - it cannot be destroyed till it is stopped */
+                       test_containers[i]->shutdown(test_containers[i], CONTAINER_SHUTDOWN_TIMEOUT);
+                       /* Call stop() in case shutdown() fails
+                           One of these two calls will always succeed */
+                       test_containers[i]->stop(test_containers[i]);
+                       /* Destroy the Container */
+                       test_containers[i]->destroy(test_containers[i]);
+                       /* call destroy_with_snapshots() in case destroy() fails
+                           one of these two calls will always succeed */
+                       test_containers[i]->destroy_with_snapshots(test_containers[i]);
+               }
+       }
+}
+
+/* Restart all the Containers being used in the current test case i.e. Containers with
+    names beginning with <test-case-name>_<node-name> */
+void restart_all_containers(void) {
+       char container_name[100];
+       struct lxc_container *test_container;
+       int i;
+
+       for(i = 0; i < state_ptr->num_nodes; i++) {
+               /* Shutdown, then start the Container, then wait for it to acquire an IP Address */
+               assert(snprintf(container_name, sizeof(container_name), "%s_%s", state_ptr->test_case_name,
+                               state_ptr->node_names[i]) >= 0);
+               assert(test_container = find_container(container_name));
+               test_container->shutdown(test_container, CONTAINER_SHUTDOWN_TIMEOUT);
+               test_container->stop(test_container);
+               test_container->start(test_container, 0, NULL);
+               container_wait_ip(i);
+       }
+}
+
+/* Run the gen_invite command inside the 'inviter' container to generate an invite
+    for 'invitee', and return the generated invite which is output on the terminal */
+char *invite_in_container(const char *inviter, const char *invitee) {
+       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 "
+                       "2> gen_invite.log", inviter, invitee) >= 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_<nodename> 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[200];
+
+       assert(snprintf(node_sim_command, sizeof(node_sim_command),
+                       "LD_LIBRARY_PATH=/home/ubuntu/test/.libs /home/ubuntu/test/node_sim_%s %s %s %s "
+                       "1>&2 2>> node_sim_%s.log", node, node, device_class,
+                       (invite_url) ? invite_url : "", node) >= 0);
+       run_in_container(node_sim_command, node, true);
+       PRINT_TEST_CASE_MSG("node_sim_%s started in Container\n", node);
+}
+
+/* Run the node_sim_<nodename> program inside the 'node''s container with event handling capable*/
+void node_sim_in_container_event(const char *node, const char *device_class,
+                                 const char *invite_url, const char *clientId, const char *import) {
+       char node_sim_command[200];
+
+       assert(snprintf(node_sim_command, sizeof(node_sim_command),
+                       "LD_LIBRARY_PATH=/home/ubuntu/test/.libs /home/ubuntu/test/node_sim_%s %s %s %s %s %s "
+                       "1>&2 2>> node_sim_%s.log", node, node, device_class,
+                       clientId, import, (invite_url) ? invite_url : "", node) >= 0);
+       run_in_container(node_sim_command, node, true);
+       PRINT_TEST_CASE_MSG("node_sim_%s(Client Id :%s) started in Container with event handling\n",
+                           node, clientId);
+       PRINT_TEST_CASE_MSG("node_sim_%s mesh event import string : %s\n",
+                           node, import);
+}
+
+/* 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];
+
+       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",
+                       node, sig) >= 0);
+       run_in_container(node_step_command, node, false);
+       PRINT_TEST_CASE_MSG("Signal %s sent to node_sim_%s\n", sig, node);
+}
+
+/* Change the IP Address of the Container running 'node'
+    Changes begin from X.X.X.254 and continue iteratively till an available address is found */
+void change_ip(int node) {
+       char *gateway_addr;
+       char new_ip[20];
+       char *netmask;
+       char *last_dot_in_ip;
+       int last_ip_byte = 254;
+       FILE *if_fp;
+       char copy_command[200];
+       char container_name[100];
+       struct lxc_container *container;
+       int copy_file_stat;
+
+       /* Get IP Address of LXC Bridge Interface - this will be set up as the Gateway Address
+           of the Static IP assigned to the Container */
+       assert(gateway_addr = get_ip(lxc_bridge));
+       /* Get Netmask of LXC Brdige Interface */
+       assert(netmask = get_netmask(lxc_bridge));
+
+       /* Replace last byte of Container's IP with 254 to form the new Container IP */
+       assert(container_ips[node]);
+       strncpy(new_ip, container_ips[node], sizeof(new_ip));
+       assert(last_dot_in_ip = strrchr(new_ip, '.'));
+       assert(snprintf(last_dot_in_ip + 1, 4, "%d", last_ip_byte) >= 0);
+
+       /* Check that the new IP does not match the Container's existing IP
+           if it does, iterate till it doesn't */
+       /* TO DO: Make sure the IP does not conflict with any other running Container */
+       while(strcmp(new_ip, container_ips[node]) == 0) {
+               last_ip_byte--;
+               assert(snprintf(last_dot_in_ip + 1, 4, "%d", last_ip_byte) >= 0);
+       }
+
+       /* Create new 'interfaces' file for Container */
+       assert(if_fp = fopen("interfaces", "w"));
+       fprintf(if_fp, "auto lo\n");
+       fprintf(if_fp, "iface lo inet loopback\n");
+       fprintf(if_fp, "\n");
+       fprintf(if_fp, "auto eth0\n");
+       fprintf(if_fp, "iface eth0 inet static\n");
+       fprintf(if_fp, "\taddress %s\n", new_ip);
+       fprintf(if_fp, "\tnetmask %s\n", netmask);
+       fprintf(if_fp, "\tgateway %s\n", gateway_addr);
+       assert(fclose(if_fp) != EOF);
+
+       /* Copy 'interfaces' file into Container's /etc/network path */
+       assert(snprintf(copy_command, sizeof(copy_command),
+                       "%s/" LXC_UTIL_REL_PATH "/" LXC_COPY_SCRIPT " interfaces %s_%s /etc/network/interfaces",
+                       meshlink_root_path, state_ptr->test_case_name, state_ptr->node_names[node]) >= 0);
+       copy_file_stat = system(copy_command);
+       PRINT_TEST_CASE_MSG("Container '%s_%s' 'interfaces' file copy status: %d\n",
+                           state_ptr->test_case_name, state_ptr->node_names[node], copy_file_stat);
+       assert(copy_file_stat == 0);
+
+       /* Restart Container to apply new IP Address */
+       assert(snprintf(container_name, sizeof(container_name), "%s_%s", state_ptr->test_case_name,
+                       state_ptr->node_names[node]) >= 0);
+       assert(container = find_container(container_name));
+       container->shutdown(container, CONTAINER_SHUTDOWN_TIMEOUT);
+       /* Call stop() in case shutdown() fails
+           One of these two calls with always succeed */
+       container->stop(container);
+       assert(container->start(container, 0, NULL));
+
+       strncpy(container_ips[node], new_ip, sizeof(new_ip));   // Save the new IP Addres
+       PRINT_TEST_CASE_MSG("Node '%s' IP Address changed to %s\n", state_ptr->node_names[node],
+                           container_ips[node]);
+}
diff --git a/test/blackbox/common/containers.h b/test/blackbox/common/containers.h
new file mode 100644 (file)
index 0000000..49cbb7c
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+    containers.h -- Declarations for Container Management API
+    Copyright (C) 2018  Guus Sliepen <guus@meshlink.io>
+                        Manav Kumar Mehta <manavkumarm@yahoo.com>
+
+    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.
+*/
+
+#ifndef CONTAINERS_H
+#define CONTAINERS_H
+
+#include <lxc/lxccontainer.h>
+
+#define DAEMON_ARGV_LEN 200
+#define CONTAINER_SHUTDOWN_TIMEOUT 5
+
+extern char *lxc_path;
+
+struct lxc_container *find_container(const char *name);
+void rename_container(const char *old_name, const char *new_name);
+char *run_in_container(const char *cmd, const char *node, bool daemonize);
+void container_wait_ip(int node);
+void create_containers(const char *node_names[], int num_nodes);
+void setup_containers(void **state);
+void destroy_containers(void);
+void restart_all_containers(void);
+char *invite_in_container(const char *inviter, const char *invitee);
+void node_sim_in_container(const char *node, const char *device_class, const char *invite_url);
+void node_sim_in_container_event(const char *node, const char *device_class,
+                                 const char *invite_url, const char *clientId, const char *import);
+void node_step_in_container(const char *node, const char *sig);
+void change_ip(int node);
+
+char *get_container_ip(int node);
+
+#endif // CONTAINERS_H
diff --git a/test/blackbox/common/mesh_event_handler.c b/test/blackbox/common/mesh_event_handler.c
new file mode 100644 (file)
index 0000000..0f331d6
--- /dev/null
@@ -0,0 +1,162 @@
+/*
+    mesh_event_handler.c -- handling of mesh events API
+    Copyright (C) 2018  Guus Sliepen <guus@meshlink.io>
+
+    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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <sys/types.h>
+#include <net/if.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <stdbool.h>
+#include <errno.h>
+#include <assert.h>
+#include <fcntl.h>
+#include <time.h>
+#include "mesh_event_handler.h"
+
+#define SERVER_LISTEN_PORT "9000" /* Port number that is binded with mesh event server socket */
+
+// TODO: Implement mesh event handling with reentrant functions(if required).
+static struct sockaddr_in server_addr;
+static int client_fd = -1;
+static int server_fd = -1;
+
+char *mesh_event_sock_create(const char *if_name) {
+       struct sockaddr_in server;
+       char *ip;
+       struct ifreq req_if;
+       struct sockaddr_in *resp_if_addr;
+
+       if(if_name == NULL) {
+               return NULL;
+       }
+
+       server_fd = socket(AF_INET, SOCK_DGRAM, 0);
+
+       if(server_fd < 0) {
+               perror("socket");
+       }
+
+       assert(server_fd >= 0);
+
+       int reuse = 1;
+       assert(setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) != -1);
+
+       memset(&req_if, 0, sizeof(req_if));
+       req_if.ifr_addr.sa_family = AF_INET;
+       strncpy(req_if.ifr_name, if_name, IFNAMSIZ - 1);
+       assert(ioctl(server_fd, SIOCGIFADDR, &req_if) != -1);
+       resp_if_addr = (struct sockaddr_in *) & (req_if.ifr_addr);
+
+       memset(&server, 0, sizeof(server));
+       server.sin_family = AF_INET;
+       server.sin_addr   = resp_if_addr->sin_addr;
+       server.sin_port   = htons(atoi(SERVER_LISTEN_PORT));
+       assert(bind(server_fd, (struct sockaddr *) &server, sizeof(struct sockaddr)) != -1);
+
+       assert(ip = malloc(30));
+       strncpy(ip, inet_ntoa(resp_if_addr->sin_addr), 20);
+       strcat(ip, ":");
+       strcat(ip, SERVER_LISTEN_PORT);
+
+       return ip;
+}
+
+void mesh_event_sock_connect(const char *import) {
+       char *port = NULL;
+
+       assert(import);
+
+       char *ip = strdup(import);
+       assert((port = strchr(ip, ':')) != NULL);
+       *port = '\0';
+       port++;
+
+       memset(&server_addr, 0, sizeof(server_addr));
+       server_addr.sin_family      = AF_INET;
+       server_addr.sin_addr.s_addr = inet_addr(ip);
+       server_addr.sin_port        = htons(atoi(port));
+       client_fd = socket(AF_INET, SOCK_DGRAM, 0);
+       free(ip);
+       assert(client_fd >= 0);
+}
+
+bool mesh_event_sock_send(int client_id, mesh_event_t event, void *payload, size_t payload_length) {
+       mesh_event_payload_t mesh_event_send_packet;
+       ssize_t send_ret;
+
+       // Packing the mesh event
+       assert(client_id >= 0);
+       assert(client_fd >= 0);
+       assert(event >= 0 && event < MAX_EVENT);
+       mesh_event_send_packet.client_id   = client_id;
+       mesh_event_send_packet.mesh_event  = event;
+
+       if((payload == NULL) || (payload_length == 0)) {
+               mesh_event_send_packet.payload_length = 0;
+       } else {
+               mesh_event_send_packet.payload_length = payload_length;
+               memmove(mesh_event_send_packet.payload, payload, payload_length);
+       }
+
+       send_ret = sendto(client_fd, &mesh_event_send_packet, sizeof(mesh_event_send_packet), 0, (const struct sockaddr *) &server_addr, sizeof(server_addr));
+
+       if(send_ret < 0) {
+               perror("sendto status");
+               return false;
+       } else {
+               return true;
+       }
+}
+
+bool wait_for_event(mesh_event_callback_t callback, int t) {
+       struct timeval timeout;
+       struct sockaddr client;
+       socklen_t soc_len;
+       fd_set read_fds;
+       int activity;
+       mesh_event_payload_t mesh_event_rec_packet;
+
+       assert(callback);
+       assert(server_fd >= -1);
+       assert(t >= 0);
+
+       timeout.tv_sec  = t;
+       timeout.tv_usec = 0;
+       FD_ZERO(&read_fds);
+       FD_SET(server_fd, &read_fds);
+
+       while(1) {
+               activity = select(server_fd + 1, &read_fds, NULL, NULL, &timeout);
+               assert(activity != -1);
+
+               if(activity == 0) {
+                       // If no activity happened for the timeout given
+                       return false;
+               } else if(FD_ISSET(server_fd, &read_fds)) {
+                       // Unpacking the mesh event
+                       ssize_t recv_ret = recvfrom(server_fd, &mesh_event_rec_packet, sizeof(mesh_event_rec_packet), 0, &client, &soc_len);
+                       assert(recv_ret == sizeof(mesh_event_rec_packet));
+                       callback(mesh_event_rec_packet);
+                       return true;
+               }
+       }// while
+}
diff --git a/test/blackbox/common/mesh_event_handler.h b/test/blackbox/common/mesh_event_handler.h
new file mode 100644 (file)
index 0000000..4300aff
--- /dev/null
@@ -0,0 +1,141 @@
+/*
+    mesh_event_handler.h
+    Copyright (C) 2018  Guus Sliepen <guus@meshlink.io>
+
+    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.
+*/
+
+#ifndef _MESH_EVENT_HANDLER_H_
+#define _MESH_EVENT_HANDLER_H_
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <sys/types.h>
+#include <net/if.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <stdbool.h>
+#include <errno.h>
+#include <assert.h>
+#include <fcntl.h>
+#include <time.h>
+#include <stdint.h>
+
+/// Maximum length of the mesh event payload
+#define PAYLOAD_MAX_SIZE 1000
+
+/// mesh events
+// TODO: Add more mesh event if required.
+typedef enum {
+       NO_PREFERENCE = 0,
+       META_CONN_SUCCESSFUL,
+       META_CONN,
+       META_DISCONN,
+       META_CONN_CLOSED,
+       NODE_INVITATION,
+       CHANGED_IP_ADDRESS,
+       NODE_UNREACHABLE,
+       NODE_REACHABLE,
+       META_RECONN_SUCCESSFUL,
+       META_RECONN_FAILURE,
+       MESH_DATA_RECEIVED,
+       NODE_STARTED,
+       NODE_RESTARTED,
+       NODE_JOINED,
+       PORT_NO,
+       ERR_NETWORK,
+       MESH_DATA_VERIFED,
+       CHANNEL_OPENED,
+       CHANNEL_REQ_RECIEVED,
+       CHANNEL_CONNECTED,
+       CHANNEL_DATA_RECIEVED,
+       MESH_NODE_DISCOVERED,
+       INCOMING_META_CONN,
+       OUTGOING_META_CONN,
+       AUTO_DISCONN,
+
+       MAX_EVENT           // Maximum event enum
+} mesh_event_t;
+
+/// mesh event UDP packet
+typedef struct mesh_event_payload {
+       uint32_t      client_id;
+       mesh_event_t  mesh_event;
+       uint16_t      payload_length;
+       uint8_t       payload[PAYLOAD_MAX_SIZE];
+} mesh_event_payload_t;
+
+/// callback for handling the mesh event
+/** mesh event callback called from wait_for_event() if the mesh event UDP server gets a mesh event.
+ *
+ *  @param mesh_event_packet    packet containing client-id, mesh event & payload (if any).
+ */
+typedef void (*mesh_event_callback_t)(mesh_event_payload_t mesh_event_packet);
+
+/// Creates an UDP server for listening mesh events.
+/** This function creates an UDP socket, binds it with given interface address and returns a NULL
+ *  terminated string containing server's IP address & port number.
+ *
+ *  @param ifname       Name of the network interface to which the socket has to be created.
+ *
+ *  @return             This function returns a NULL terminated string which has IP address and
+ *                                                                              port number of the server socket. The application should call free() after
+ *                                                                                      it has finished using the exported string.
+ */
+extern char *mesh_event_sock_create(const char *ifname);
+
+/// Waits for the mesh event for about the given timeout.
+/** This function waits for the mesh event that's expected to occur for the given timeout. If a mesh event
+ *  is received then the given callback will be invoked.
+ *
+ *  @param callback     callback which handles the mesh event packet.
+ *  @param timeout      timeout for which the the function has to wait for the event.
+ *
+ *  @return             This function returns true if a mesh event occured else false if timeout exceeded.
+ */
+extern bool wait_for_event(mesh_event_callback_t callback, int timeout);
+
+/// Sends the mesh event to server.
+/** This function sends the mesh event to the server. At the server end it's expected to wait_for_event()
+ *  otherwise the packet will be dropped.
+ *
+ *  @param client_id        Client id by which server can identify the client/node.
+ *  @param event            An enum describing the mesh event.
+ *  @param payload          Payload can also be attached along with the mesh event if any, else NULL can
+ *                          can be specified.
+ *  @param payload_length   Length of the payload if specified else 0 can be specified.
+ *                                                                                                      the maximum payload size can be upto PAYLOAD_MAX_SIZE and if the
+ *                          PAYLOAD_MAX_SIZE macro is changed it should not exceed the UDP datagram size.
+ *
+ *  @return                  This function returns true on success else returns false.
+ */
+extern bool mesh_event_sock_send(int client_id, mesh_event_t event, void *payload, size_t payload_length);
+
+/// Imports the server address, saves it and opens an UDP client socket.
+/** This function creates an UDP socket, binds it with given interface address and returns a NULL
+ *  terminated string containing server's IP address & port number.
+ *
+ *  @param server_address    NULL terminated string that's exported by mesh_event_sock_create() which
+ *                           which contains IP address and port number of the mesh event server.
+ *
+ *  @return                  void
+ */
+extern void mesh_event_sock_connect(const char *server_address);
+
+bool wait_for_event_only(mesh_event_callback_t callback, int t, mesh_event_t event);
+#endif // _MESH_EVENT_HANDLER_H_
diff --git a/test/blackbox/common/tcpdump.c b/test/blackbox/common/tcpdump.c
new file mode 100644 (file)
index 0000000..a0933f7
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+    tcpdump.c -- Implementation of Black Box Test Execution for meshlink
+
+    Copyright (C) 2018  Guus Sliepen <guus@meshlink.io>
+
+    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 <unistd.h>
+#include <sys/prctl.h>
+#include <assert.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <signal.h>
+#include <sys/types.h>
+#include "common_handlers.h"
+#include "tcpdump.h"
+
+pid_t tcpdump_start(char *interface) {
+       pid_t tcpdump_pid;
+       char *argv[] = { "tcpdump", "-i", interface, NULL };
+       // child process have a pipe to the parent process when parent process terminates SIGPIPE kills the tcpdump
+       int pipes[2];
+       pipe(pipes);
+       PRINT_TEST_CASE_MSG("\x1b[32mLaunching TCP Dump ..\x1b[0m\n");
+
+       if((tcpdump_pid = fork()) == 0) {
+               prctl(PR_SET_PDEATHSIG, SIGHUP);
+               close(pipes[1]);
+               // Open log file for TCP Dump
+               int fd = open(TCPDUMP_LOG_FILE, O_WRONLY | O_CREAT | O_TRUNC, 0644);
+               assert(fd != -1);
+               close(STDOUT_FILENO);
+               assert(dup2(fd, STDOUT_FILENO) != -1);
+
+               // Launch TCPDump with port numbers of sleepy, gateway & relay
+               int ret = execvp("/usr/sbin/tcpdump", argv);
+               perror("execvp ");
+               assert(ret != -1);
+       } else {
+               close(pipes[0]);
+               return tcpdump_pid;
+       }
+}
+
+void tcpdump_stop(pid_t tcpdump_pid) {
+       PRINT_TEST_CASE_MSG("\n\x1b[32mStopping TCP Dump.\x1b[0m\n");
+       assert(!kill(tcpdump_pid, SIGTERM));
+}
diff --git a/test/blackbox/common/tcpdump.h b/test/blackbox/common/tcpdump.h
new file mode 100644 (file)
index 0000000..37e92b8
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+    tcpdump.h -- Declarations of common callback handlers and signal handlers for
+                            black box test cases
+    Copyright (C) 2018  Guus Sliepen <guus@meshlink.io>
+
+    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.
+*/
+
+#ifndef TCPDUMP_H
+#define TCPDUMP_H
+
+#define TCPDUMP_LOG_FILE "tcpdump.log"
+
+extern pid_t tcpdump_start(char *);
+extern void tcpdump_stop(pid_t tcpdump_pid);
+
+#endif // TCPDUMP_H
diff --git a/test/blackbox/common/test_step.c b/test/blackbox/common/test_step.c
new file mode 100644 (file)
index 0000000..4a2bf85
--- /dev/null
@@ -0,0 +1,145 @@
+/*
+    test_step.c -- Handlers for executing test steps during node simulation
+    Copyright (C) 2018  Guus Sliepen <guus@meshlink.io>
+
+    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 <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+#include "../../../src/meshlink.h"
+#include "test_step.h"
+#include "common_handlers.h"
+
+/* Modify this to change the logging level of Meshlink */
+#define TEST_MESHLINK_LOG_LEVEL MESHLINK_DEBUG
+
+meshlink_handle_t *mesh_handle = NULL;
+bool mesh_started = false;
+char *eth_if_name = NULL;
+
+meshlink_handle_t *execute_open(char *node_name, char *dev_class) {
+       /* Set up logging for Meshlink */
+       meshlink_set_log_cb(NULL, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
+
+       /* Create meshlink instance */
+       mesh_handle = meshlink_open("testconf", node_name, "node_sim", atoi(dev_class));
+       fprintf(stderr, "meshlink_open status: %s\n", meshlink_strerror(meshlink_errno));
+       PRINT_TEST_CASE_MSG("meshlink_open status: %s\n", meshlink_strerror(meshlink_errno));
+       assert(mesh_handle);
+
+       /* Set up logging for Meshlink with the newly acquired Mesh Handle */
+       meshlink_set_log_cb(mesh_handle, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
+       /* Set up callback for node status (reachable / unreachable) */
+       meshlink_set_node_status_cb(mesh_handle, meshlink_callback_node_status);
+
+       return mesh_handle;
+}
+
+char *execute_invite(char *invitee) {
+       char *invite_url = meshlink_invite(mesh_handle, invitee);
+
+       PRINT_TEST_CASE_MSG("meshlink_invite status: %s\n", meshlink_strerror(meshlink_errno));
+       assert(invite_url);
+
+       return invite_url;
+}
+
+void execute_join(char *invite_url) {
+       bool join_status;
+
+       /* The inviting node may take a moment to open its listening port
+           This sleep() prevents meshlink_join() from failing when the listening port is not open */
+       /* TO DO: Replace this with code that actually checks for the port being open, if possible */
+       PRINT_TEST_CASE_MSG("Sleeping 1 sec to allow inviting node to start listening...\n");
+       sleep(1);
+
+       PRINT_TEST_CASE_MSG("About to join with mesh_handle = %p, invite_url = %s\n", mesh_handle, invite_url);
+       join_status = meshlink_join(mesh_handle, invite_url);
+       PRINT_TEST_CASE_MSG("meshlink_join status: %s\n", meshlink_strerror(meshlink_errno));
+       assert(join_status);
+}
+
+void execute_start(void) {
+       bool start_init_status = meshlink_start(mesh_handle);
+
+       PRINT_TEST_CASE_MSG("meshlink_start status: %s\n", meshlink_strerror(meshlink_errno));
+       assert(start_init_status);
+       mesh_started = true;
+}
+
+void execute_stop(void) {
+       assert(mesh_handle);
+       meshlink_stop(mesh_handle);
+       mesh_started = false;
+}
+
+void execute_close(void) {
+       assert(mesh_handle);
+       meshlink_close(mesh_handle);
+}
+
+void execute_change_ip(void) {
+       char *eth_if_ip;
+       int last_byte;
+       char new_ip[20], gateway_ip[20];
+       char *last_dot_in_ip;
+       char *eth_if_netmask;
+       char route_chg_command[200];
+       int route_chg_status;
+
+       /* Get existing IP Address of Ethernet Bridge Interface */
+       assert(eth_if_ip = get_ip(eth_if_name));
+
+       /* Set new IP Address by replacing the last byte with last byte + 1 */
+       strncpy(new_ip, eth_if_ip, sizeof(new_ip));
+       assert(last_dot_in_ip = strrchr(new_ip, '.'));
+       last_byte = atoi(last_dot_in_ip + 1);
+       assert(snprintf(last_dot_in_ip + 1, 4, "%d", (last_byte > 253) ? 2 : (last_byte + 1)) >= 0);
+
+       /* TO DO: Check for IP conflicts with other interfaces and existing Containers */
+       /* Bring the network interface down before making changes */
+       stop_nw_intf(eth_if_name);
+       /* Save the netmask first, then restore it after setting the new IP Address */
+       assert(eth_if_netmask = get_netmask(eth_if_name));
+       set_ip(eth_if_name, new_ip);
+       set_netmask(eth_if_name, eth_if_netmask);
+       /* Bring the network interface back up again to apply changes */
+       start_nw_intf(eth_if_name);
+
+       /* Get Gateway's IP Address, by replacing the last byte with 1 in the current IP Address */
+       /* TO DO: Obtain the actual Gateway IP Address */
+       strncpy(gateway_ip, eth_if_ip, sizeof(gateway_ip));
+       assert(last_dot_in_ip = strrchr(gateway_ip, '.'));
+       assert(snprintf(last_dot_in_ip + 1, 4, "%d", 1) >= 0);
+
+       /* Add the default route back again, which would have been deleted when the
+           network interface was brought down */
+       /* TO DO: Perform this action using ioctl with SIOCADDRT */
+       /*assert(snprintf(route_chg_command, sizeof(route_chg_command), "route add default gw %s",
+         gateway_ip) >= 0);
+        route_chg_status = system(route_chg_command);
+        PRINT_TEST_CASE_MSG("Default Route Add status = %d\n", route_chg_status);
+        assert(route_chg_status == 0); */
+       // Not necessary for ubuntu versions of 16.04 and 18.04
+
+       PRINT_TEST_CASE_MSG("Node '%s' IP Address changed to %s\n", NUT_NODE_NAME, new_ip);
+
+       free(eth_if_ip);
+       free(eth_if_netmask);
+}
+
diff --git a/test/blackbox/common/test_step.h b/test/blackbox/common/test_step.h
new file mode 100644 (file)
index 0000000..7a32dff
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+    test_step.h -- Handlers for executing test steps during node simulation
+    Copyright (C) 2018  Guus Sliepen <guus@meshlink.io>
+
+    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.
+*/
+
+#ifndef TEST_STEP_H
+#define TEST_STEP_H
+
+#include "../../../src/meshlink.h"
+
+meshlink_handle_t *execute_open(char *node_name, char *dev_class);
+char *execute_invite(char *invitee);
+void execute_join(char *invite_url);
+void execute_start(void);
+void execute_stop(void);
+void execute_close(void);
+void execute_change_ip(void);
+
+#endif // TEST_STEP_H
diff --git a/test/blackbox/run_blackbox_tests/.gitignore b/test/blackbox/run_blackbox_tests/.gitignore
new file mode 100644 (file)
index 0000000..076f4db
--- /dev/null
@@ -0,0 +1 @@
+/run_blackbox_tests
diff --git a/test/blackbox/run_blackbox_tests/Makefile.am b/test/blackbox/run_blackbox_tests/Makefile.am
new file mode 100644 (file)
index 0000000..defd4b5
--- /dev/null
@@ -0,0 +1,51 @@
+check_PROGRAMS = run_blackbox_tests
+
+run_blackbox_tests_SOURCES = \
+       run_blackbox_tests.c \
+       test_cases.c execute_tests.c \
+       ../common/mesh_event_handler.c \
+       ../common/containers.c \
+       ../common/tcpdump.c \
+       ../common/common_handlers.c \
+       ../common/test_step.c \
+       test_cases_destroy.c \
+       test_cases_export.c \
+       test_cases_get_all_nodes.c \
+       test_cases_get_fingerprint.c \
+       test_cases_invite.c \
+       test_cases_rec_cb.c \
+       test_cases_set_port.c \
+       test_cases_sign.c \
+       test_cases_verify.c \
+       test_cases_channel_ex.c \
+       test_cases_channel_get_flags.c \
+       test_cases_status_cb.c \
+       test_cases_set_log_cb.c \
+       test_cases_join.c \
+       test_cases_import.c \
+       test_cases_channel_set_accept_cb.c \
+       test_cases_channel_set_poll_cb.c \
+       test_cases_hint_address.c \
+       test_cases_channel_set_receive_cb.c \
+       test_cases_open.c \
+       test_cases_start.c \
+       test_cases_stop_close.c \
+       test_cases_pmtu.c \
+       test_cases_get_self.c \
+       test_cases_send.c \
+       test_cases_get_node.c \
+       test_cases_add_addr.c \
+       test_cases_get_ex_addr.c \
+       test_cases_add_ex_addr.c \
+       test_cases_get_port.c \
+       test_cases_blacklist.c \
+       test_cases_whitelist.c \
+       test_cases_default_blacklist.c \
+       test_cases_channel_open.c \
+       test_cases_channel_close.c \
+       test_cases_channel_send.c \
+       test_cases_channel_shutdown.c
+
+run_blackbox_tests_LDADD = ../../../src/libmeshlink.la -llxc -lcmocka
+run_blackbox_tests_CFLAGS = -D_GNU_SOURCE
+
diff --git a/test/blackbox/run_blackbox_tests/execute_tests.c b/test/blackbox/run_blackbox_tests/execute_tests.c
new file mode 100644 (file)
index 0000000..2f9730e
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+    execute_tests.c -- Utility functions for black box test execution
+    Copyright (C) 2018  Guus Sliepen <guus@meshlink.io>
+
+    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 <stdlib.h>
+#include <stdarg.h>
+#include <setjmp.h>
+#include <cmocka.h>
+#include <assert.h>
+#include "execute_tests.h"
+#include "../common/common_handlers.h"
+#include "../common/containers.h"
+#include "../common/test_step.h"
+
+int setup_test(void **state) {
+       int i;
+
+       fprintf(stderr, "Setting up Containers\n");
+       state_ptr = (black_box_state_t *)(*state);
+
+       for(i = 0; i < state_ptr->num_nodes; i++) {
+               meta_conn_status[i] = false;
+       }
+
+       setup_containers(state);
+
+       return EXIT_SUCCESS;
+}
+
+void execute_test(test_step_func_t step_func, void **state) {
+       black_box_state_t *test_state = (black_box_state_t *)(*state);
+
+       fprintf(stderr, "\n\x1b[32mRunning Test\x1b[0m : \x1b[34m%s\x1b[0m\n", test_state->test_case_name);
+       test_state->test_result = step_func();
+
+       if(!test_state->test_result) {
+               fail();
+       }
+}
+
+int teardown_test(void **state) {
+       black_box_state_t *test_state = (black_box_state_t *)(*state);
+       char container_old_name[100], container_new_name[100];
+       int i;
+
+       if(test_state->test_result) {
+               PRINT_TEST_CASE_MSG("Test successful! Shutting down nodes.\n");
+
+               for(i = 0; i < test_state->num_nodes; i++) {
+                       /* Shut down node */
+                       node_step_in_container(test_state->node_names[i], "SIGTERM");
+                       /* Rename Container to run_<node-name> - this allows it to be re-used for the
+                           next test, otherwise it will be ignored assuming that it has been saved
+                           for debugging */
+                       assert(snprintf(container_old_name, sizeof(container_old_name), "%s_%s",
+                                       test_state->test_case_name, test_state->node_names[i]) >= 0);
+                       assert(snprintf(container_new_name, sizeof(container_new_name), "run_%s",
+                                       test_state->node_names[i]) >= 0);
+                       rename_container(container_old_name, container_new_name);
+               }
+       }
+
+       state_ptr = NULL;
+
+       return EXIT_SUCCESS;
+}
diff --git a/test/blackbox/run_blackbox_tests/execute_tests.h b/test/blackbox/run_blackbox_tests/execute_tests.h
new file mode 100644 (file)
index 0000000..03880f5
--- /dev/null
@@ -0,0 +1,31 @@
+#ifndef EXECUTE_TESTS_H
+#define EXECUTE_TESTS_H
+
+/*
+    execute_tests.h -- header file for execute_tests.c
+    Copyright (C) 2018  Guus Sliepen <guus@meshlink.io>
+
+    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 <stdbool.h>
+
+typedef bool (*test_step_func_t)(void);
+
+int setup_test(void **state);
+void execute_test(test_step_func_t step_func, void **state);
+int teardown_test(void **state);
+
+#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
new file mode 100644 (file)
index 0000000..3f6e081
--- /dev/null
@@ -0,0 +1,127 @@
+/*
+    run_blackbox_tests.c -- Implementation of Black Box Test Execution for meshlink
+
+    Copyright (C) 2018  Guus Sliepen <guus@meshlink.io>
+
+    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 <stdlib.h>
+#include <stdarg.h>
+#include <setjmp.h>
+#include <cmocka.h>
+#include <assert.h>
+#include "execute_tests.h"
+#include "test_cases.h"
+#include "test_cases_open.h"
+#include "test_cases_start.h"
+#include "test_cases_stop_close.h"
+#include "test_cases_send.h"
+#include "test_cases_pmtu.h"
+#include "test_cases_get_self.h"
+#include "test_cases_get_node.h"
+#include "test_cases_add_addr.h"
+#include "test_cases_get_ex_addr.h"
+#include "test_cases_add_ex_addr.h"
+#include "test_cases_get_port.h"
+#include "test_cases_blacklist.h"
+#include "test_cases_default_blacklist.h"
+#include "test_cases_whitelist.h"
+#include "test_cases_channel_open.h"
+#include "test_cases_channel_close.h"
+#include "test_cases_channel_send.h"
+#include "test_cases_channel_shutdown.h"
+
+#include "test_cases_destroy.h"
+#include "test_cases_get_all_nodes.h"
+#include "test_cases_get_fingerprint.h"
+#include "test_cases_rec_cb.h"
+#include "test_cases_sign.h"
+#include "test_cases_set_port.h"
+#include "test_cases_verify.h"
+#include "test_cases_invite.h"
+#include "test_cases_export.h"
+#include "test_cases_channel_ex.h"
+#include "test_cases_channel_get_flags.h"
+#include "test_cases_status_cb.h"
+#include "test_cases_set_log_cb.h"
+#include "test_cases_join.h"
+#include "test_cases_import.h"
+#include "test_cases_channel_set_accept_cb.h"
+#include "test_cases_channel_set_poll_cb.h"
+#include "test_cases_channel_set_receive_cb.h"
+#include "test_cases_hint_address.h"
+#include "../common/containers.h"
+#include "../common/common_handlers.h"
+
+char *meshlink_root_path = NULL;
+char *choose_arch = NULL;
+int total_tests;
+
+int main(int argc, char *argv[]) {
+       /* Set configuration */
+       assert(argc > 5);
+       meshlink_root_path = argv[1];
+       lxc_path = argv[2];
+       lxc_bridge = argv[3];
+       eth_if_name = argv[4];
+       choose_arch = argv[5];
+
+       int failed_tests = 0;
+
+       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();
+//  failed_tests += test_meshlink_channel_open_ex();
+       failed_tests += test_meshlink_channel_get_flags();
+       failed_tests += test_meshlink_set_channel_accept_cb();
+       failed_tests += test_meshlink_destroy();
+       failed_tests += test_meshlink_export();
+       failed_tests += test_meshlink_get_fingerprint();
+       failed_tests += test_meshlink_get_all_nodes();
+       failed_tests += test_meshlink_set_port();
+       failed_tests += test_meshlink_sign();
+       failed_tests += test_meshlink_verify();
+       failed_tests += test_meshlink_import();
+       failed_tests += test_meshlink_invite();
+       failed_tests += test_meshlink_set_receive_cb();
+       failed_tests += test_meshlink_set_log_cb();
+       failed_tests += test_meshlink_set_channel_receive_cb();
+       failed_tests += test_meshlink_hint_address();
+
+       failed_tests += test_meshlink_open();
+       failed_tests += test_meshlink_start();
+       failed_tests += test_meshlink_stop_close();
+       failed_tests += test_meshlink_send();
+       failed_tests += test_meshlink_channel_send();
+       failed_tests += test_meshlink_channel_shutdown();
+       failed_tests += test_meshlink_pmtu();
+       failed_tests += test_meshlink_get_self();
+       failed_tests += test_meshlink_get_node();
+       failed_tests += test_meshlink_add_address();
+       failed_tests += test_meshlink_get_external_address();
+       failed_tests += test_meshlink_add_external_address();
+       failed_tests += test_meshlink_get_port();
+       failed_tests += test_meshlink_blacklist();
+       failed_tests += test_meshlink_whitelist();
+       failed_tests += test_meshlink_default_blacklist();
+       failed_tests += test_meshlink_channel_open();
+       failed_tests += test_meshlink_channel_close();
+
+       printf("[ PASSED ] %d test(s).\n", total_tests - failed_tests);
+       printf("[ FAILED ] %d test(s).\n", failed_tests);
+
+       return failed_tests;
+}
diff --git a/test/blackbox/run_blackbox_tests/test_cases.c b/test/blackbox/run_blackbox_tests/test_cases.c
new file mode 100644 (file)
index 0000000..942c72c
--- /dev/null
@@ -0,0 +1,524 @@
+/*
+    test_cases.c -- Execution of specific meshlink black box test cases
+    Copyright (C) 2018  Guus Sliepen <guus@meshlink.io>
+
+    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 <stdlib.h>
+#include <stdarg.h>
+#include <setjmp.h>
+#include <cmocka.h>
+#include <assert.h>
+#include "execute_tests.h"
+#include "test_cases.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 RELAY_ID "0"
+#define PEER_ID  "1"
+#define NUT_ID   "2"
+
+static void test_case_meta_conn_01(void **state);
+static bool test_steps_meta_conn_01(void);
+static void test_case_meta_conn_02(void **state);
+static bool test_steps_meta_conn_02(void);
+static void test_case_meta_conn_03(void **state);
+static bool test_steps_meta_conn_03(void);
+static void test_case_meta_conn_04(void **state);
+static bool test_steps_meta_conn_04(void);
+static void test_case_meta_conn_05(void **state);
+static bool test_steps_meta_conn_05(void);
+
+/* State structure for Meta-connections Test Case #1 */
+static char *test_meta_conn_1_nodes[] = { "relay", "peer", "nut" };
+static black_box_state_t test_meta_conn_1_state = {
+       .test_case_name =  "test_case_meta_conn_01",
+       .node_names =  test_meta_conn_1_nodes,
+       .num_nodes =  3,
+};
+
+/* State structure for Meta-connections Test Case #2 */
+static char *test_meta_conn_2_nodes[] = { "relay", "peer", "nut" };
+static black_box_state_t test_meta_conn_2_state = {
+       .test_case_name = "test_case_meta_conn_02",
+       .node_names = test_meta_conn_2_nodes,
+       .num_nodes = 3,
+};
+
+/* State structure for Meta-connections Test Case #3 */
+static char *test_meta_conn_3_nodes[] = { "relay", "peer", "nut" };
+static black_box_state_t test_meta_conn_3_state = {
+       .test_case_name = "test_case_meta_conn_03",
+       .node_names = test_meta_conn_3_nodes,
+       .num_nodes = 3,
+};
+
+/* State structure for Meta-connections Test Case #4 */
+static char *test_meta_conn_4_nodes[] = { "peer", "nut" };
+static black_box_state_t test_meta_conn_4_state = {
+       .test_case_name = "test_case_meta_conn_04",
+       .node_names = test_meta_conn_4_nodes,
+       .num_nodes = 2,
+};
+
+/* State structure for Meta-connections Test Case #5 */
+static char *test_meta_conn_5_nodes[] = { "peer", "nut" };
+static black_box_state_t test_meta_conn_5_state = {
+       .test_case_name = "test_case_meta_conn_05",
+       .node_names = test_meta_conn_5_nodes,
+       .num_nodes = 2,
+};
+
+int black_box_group0_setup(void **state) {
+       const char *nodes[] = { "peer", "relay", "nut"};
+       int num_nodes = sizeof(nodes) / sizeof(nodes[0]);
+
+       PRINT_TEST_CASE_MSG("Creating Containers\n");
+       destroy_containers();
+       create_containers(nodes, num_nodes);
+
+       return 0;
+}
+
+int black_box_group0_teardown(void **state) {
+       PRINT_TEST_CASE_MSG("Destroying Containers\n");
+       destroy_containers();
+
+       return 0;
+}
+
+int black_box_all_nodes_setup(void **state) {
+       const char *nodes[] = { "peer" };
+       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 meta_conn01_conn;
+static bool meta_conn01_closed;
+static bool meta_conn01_reconn;
+
+static void meta_conn01_cb(mesh_event_payload_t payload) {
+       char event_node_name[][10] = {"RELAY", "PEER", "NUT"};
+       fprintf(stderr, "%s : ", event_node_name[payload.client_id]);
+
+       switch(payload.mesh_event) {
+       case META_CONN_SUCCESSFUL   :
+               meta_conn01_conn = true;
+               break;
+
+       case NODE_STARTED           :
+               fprintf(stderr, "Node started\n");
+               break;
+
+       case META_CONN_CLOSED       :
+               meta_conn01_closed = true;
+               break;
+
+       case META_RECONN_SUCCESSFUL :
+               meta_conn01_reconn = true;
+               break;
+       }
+}
+
+/* Execute Meta-connections Test Case # 1 - re-connection to peer after disconnection when
+    connected via a third node */
+static void test_case_meta_conn_01(void **state) {
+       execute_test(test_steps_meta_conn_01, state);
+}
+
+/* Test Steps for Meta-connections Test Case # 1 - re-connection to peer after disconnection when
+    connected via a third (relay) node
+
+    Test Steps:
+    1. Run NUT, relay and peer nodes with relay inviting the other two nodes
+    2. After connection to peer, terminate the peer node's running instance
+    3. After peer becomes unreachable, wait 60 seconds then re-start the peer node's instance
+
+    Expected Result:
+    NUT is re-connected to peer
+*/
+static bool test_steps_meta_conn_01(void) {
+       char *invite_peer, *invite_nut;
+       bool result = false;
+       int i;
+       char *import;
+
+       import = mesh_event_sock_create(eth_if_name);
+       invite_peer = invite_in_container("relay", "peer");
+       invite_nut = invite_in_container("relay", NUT_NODE_NAME);
+       node_sim_in_container_event("relay", "1", NULL, RELAY_ID, import);
+       wait_for_event(meta_conn01_cb, 5);
+       node_sim_in_container_event("peer", "1", invite_peer, PEER_ID, import);
+       wait_for_event(meta_conn01_cb, 5);
+       node_sim_in_container_event("nut", "1", invite_nut, NUT_ID, import);
+       wait_for_event(meta_conn01_cb, 5);
+
+       PRINT_TEST_CASE_MSG("Waiting for peer to be connected with NUT\n");
+       assert(wait_for_event(meta_conn01_cb, 60));
+       assert(meta_conn01_conn);
+
+       PRINT_TEST_CASE_MSG("Sending SIGTERM to peer\n");
+       node_step_in_container("peer", "SIGTERM");
+       PRINT_TEST_CASE_MSG("Waiting for peer to become unreachable\n");
+       assert(wait_for_event(meta_conn01_cb, 60));
+       assert(meta_conn01_closed);
+
+       node_sim_in_container_event("peer", "1", NULL, PEER_ID, import);
+       wait_for_event(meta_conn01_cb, 5);
+       PRINT_TEST_CASE_MSG("Waiting for peer to be re-connected\n");
+       wait_for_event(meta_conn01_cb, 60);
+
+       assert_int_equal(meta_conn01_reconn, true);
+
+       free(invite_peer);
+       free(invite_nut);
+
+       return true;
+}
+
+
+static bool meta_conn02_conn;
+
+static void meta_conn02_cb(mesh_event_payload_t payload) {
+       char event_node_name[][10] = {"RELAY", "PEER", "NUT"};
+       fprintf(stderr, "%s : ", event_node_name[payload.client_id]);
+
+       switch(payload.mesh_event) {
+       case META_CONN_SUCCESSFUL   :
+               fprintf(stderr, "Meta Connection Successful\n");
+               meta_conn02_conn = true;
+               break;
+
+       case NODE_STARTED           :
+               fprintf(stderr, "Node started\n");
+               break;
+       }
+
+       if(payload.payload_length) {
+               fprintf(stderr, " %s\n", (char *)payload.payload);
+       }
+}
+/* Execute Meta-connections Test Case # 2 - re-connection to peer via third node
+    after changing IP of NUT and peer */
+static void test_case_meta_conn_02(void **state) {
+       execute_test(test_steps_meta_conn_02, state);
+}
+/* Test Steps for Meta-connections Test Case # 2 - re-connection to peer via third node
+    after changing IP of NUT and peer
+
+    Test Steps:
+    1. Run NUT, relay and peer nodes with relay inviting the other two nodes
+    2. After connection to peer, change the NUT's IP Address and the peer node's IP Address
+
+    Expected Result:
+    NUT is first disconnected from peer then automatically re-connected to peer
+*/
+static bool test_steps_meta_conn_02(void) {
+       char *invite_peer, *invite_nut;
+       bool result = false;
+       int i;
+       char *import;
+
+       import = mesh_event_sock_create(eth_if_name);
+       invite_peer = invite_in_container("relay", "peer");
+       invite_nut = invite_in_container("relay", NUT_NODE_NAME);
+       node_sim_in_container_event("relay", "1", NULL, RELAY_ID, import);
+       wait_for_event(meta_conn02_cb, 5);
+       node_sim_in_container_event("peer", "1", invite_peer, PEER_ID, import);
+       wait_for_event(meta_conn02_cb, 5);
+       node_sim_in_container_event("nut", "1", invite_nut, NUT_ID, import);
+       wait_for_event(meta_conn02_cb, 5);
+
+       PRINT_TEST_CASE_MSG("Waiting for peer to be connected with NUT\n");
+       assert(wait_for_event(meta_conn02_cb, 60));
+       assert(meta_conn02_conn);
+
+       meta_conn02_conn = false;
+       node_sim_in_container_event("peer", "1", NULL, PEER_ID, import);
+       wait_for_event(meta_conn02_cb, 5);
+       node_sim_in_container_event("nut", "1", NULL, NUT_ID, import);
+       wait_for_event(meta_conn02_cb, 5);
+
+       PRINT_TEST_CASE_MSG("Waiting for peer to be connected with NUT\n");
+
+       if(!wait_for_event(meta_conn02_cb, 60)) {
+               return false;
+       }
+
+       result = meta_conn02_conn;
+
+       free(invite_peer);
+       free(invite_nut);
+
+       return result;
+}
+
+static bool meta_conn03_result;
+static bool meta_conn03_conn;
+
+static void meta_conn03_cb(mesh_event_payload_t payload) {
+       char event_node_name[][10] = {"RELAY", "PEER", "NUT"};
+       fprintf(stderr, "%s : ", event_node_name[payload.client_id]);
+
+       switch(payload.mesh_event) {
+       case META_CONN_SUCCESSFUL   :
+               fprintf(stderr, "Meta Connection Successful\n");
+               meta_conn03_conn = true;
+               break;
+
+       case NODE_STARTED           :
+               fprintf(stderr, "Node started\n");
+               break;
+
+       case META_RECONN_FAILURE    :
+               fprintf(stderr, "Failed to reconnect with");
+               meta_conn03_result = false;
+               break;
+
+       case META_RECONN_SUCCESSFUL :
+               fprintf(stderr, "Reconnected\n");
+               meta_conn03_result = true;
+               break;
+       }
+}
+/* Execute Meta-connections Test Case # 3 - re-connection to peer via third node
+    after changing IP of peer */
+static void test_case_meta_conn_03(void **state) {
+       execute_test(test_steps_meta_conn_03, state);
+}
+/* Test Steps for Meta-connections Test Case # 3 - re-connection to peer via third node
+    after changing IP of peer
+
+    Test Steps:
+    1. Run NUT, relay and peer nodes with relay inviting the other two nodes
+    2. After connection to peer, change the peer node's IP Address
+
+    Expected Result:
+    NUT is first disconnected from peer then automatically re-connected to peer
+*/
+static bool test_steps_meta_conn_03(void) {
+       char *invite_peer, *invite_nut;
+       bool result = false;
+       int i;
+       char *import;
+
+       import = mesh_event_sock_create(eth_if_name);
+       invite_peer = invite_in_container("relay", "peer");
+       invite_nut = invite_in_container("relay", NUT_NODE_NAME);
+       node_sim_in_container_event("relay", "1", NULL, RELAY_ID, import);
+       wait_for_event(meta_conn03_cb, 5);
+       node_sim_in_container_event("peer", "1", invite_peer, PEER_ID, import);
+       wait_for_event(meta_conn03_cb, 5);
+       node_sim_in_container_event("nut", "1", invite_nut, NUT_ID, import);
+       wait_for_event(meta_conn03_cb, 5);
+
+       PRINT_TEST_CASE_MSG("Waiting for peer to be connected with NUT\n");
+       assert(wait_for_event(meta_conn03_cb, 60));
+       assert(meta_conn03_conn);
+
+       PRINT_TEST_CASE_MSG("Changing IP address of PEER container\n");
+       change_ip(1);
+       node_sim_in_container_event("peer", "1", NULL, PEER_ID, import);
+       wait_for_event(meta_conn03_cb, 5);
+       PRINT_TEST_CASE_MSG("Waiting for peer to be re-connected\n");
+       wait_for_event(meta_conn03_cb, 5);
+       result = meta_conn03_result;
+       free(invite_peer);
+       free(invite_nut);
+
+       return result;
+}
+
+static char *invite_peer = NULL;
+static bool meta_conn04 = false;
+
+static void meta_conn04_cb(mesh_event_payload_t payload) {
+       char event_node_name[][10] = {"PEER", "NUT"};
+       fprintf(stderr, "%s : ", event_node_name[payload.client_id]);
+
+       switch(payload.mesh_event) {
+       case META_CONN_SUCCESSFUL   :
+               fprintf(stderr, "Meta Connection Successful\n");
+               meta_conn04 = true;
+               break;
+
+       case NODE_INVITATION        :
+               fprintf(stderr, "Invitation generated\n");
+               invite_peer = malloc(payload.payload_length);
+               strcpy(invite_peer, (char *)payload.payload);
+               break;
+
+       case NODE_STARTED           :
+               fprintf(stderr, "Node started\n");
+               break;
+       }
+}
+
+/* Execute Meta-connections Test Case # 4 - re-connection to peer after changing IP of
+    NUT and peer */
+static void test_case_meta_conn_04(void **state) {
+       execute_test(test_steps_meta_conn_04, state);
+}
+
+/* Execute Meta-connections Test Case # 4 - re-connection to peer after changing IP of
+    NUT and peer
+
+    Test Steps:
+    1. Run NUT and peer nodes with NUT inviting the peer node
+    2. After connection to peer, change the NUT's IP Address and the peer node's IP Address
+
+    Expected Result:
+    NUT is first disconnected from peer then automatically re-connected to peer
+*/
+static bool test_steps_meta_conn_04(void) {
+       bool result = false;
+       char *import;
+
+       import = mesh_event_sock_create(eth_if_name);
+       node_sim_in_container_event("nut", "1", NULL, "1", import);
+       wait_for_event(meta_conn04_cb, 5);
+
+       PRINT_TEST_CASE_MSG("Waiting for NUT to generate invitation to PEER\n");
+       wait_for_event(meta_conn04_cb, 5);
+
+       if(!invite_peer) {
+               return false;
+       }
+
+       PRINT_TEST_CASE_MSG("Running PEER node in the container\n");
+       node_sim_in_container_event("peer", "1", invite_peer, "0", import);
+       wait_for_event(meta_conn04_cb, 5);
+       PRINT_TEST_CASE_MSG("Waiting for peer to be connected with NUT\n");
+
+       if(!wait_for_event(meta_conn04_cb, 60)) {
+               return false;
+       }
+
+       PRINT_TEST_CASE_MSG("Changing IP address of NUT container\n");
+       change_ip(1);
+
+       node_sim_in_container_event("nut", "1", "restart", "1", import);
+       wait_for_event(meta_conn04_cb, 5);
+       PRINT_TEST_CASE_MSG("Changing IP address of PEER container\n");
+       change_ip(0);
+       node_sim_in_container_event("peer", "1", NULL, "0", import);
+       wait_for_event(meta_conn04_cb, 5);
+
+       PRINT_TEST_CASE_MSG("Waiting for peer to be re-connected\n");
+       wait_for_event(meta_conn04_cb, 5);
+       result = meta_conn04;
+
+       free(invite_peer);
+       free(import);
+       return result;
+}
+
+static char *invitation = NULL;
+
+static bool meta_conn05 = false;
+
+static void meta_conn05_cb(mesh_event_payload_t payload) {
+       char event_node_name[][10] = {"PEER", "NUT"};
+       fprintf(stderr, "%s : ", event_node_name[payload.client_id]);
+
+       switch(payload.mesh_event) {
+       case META_CONN_SUCCESSFUL   :
+               meta_conn05 = true;
+               break;
+
+       case NODE_INVITATION        :
+               invitation = malloc(payload.payload_length);
+               strcpy(invitation, (char *)payload.payload);
+               break;
+
+       case NODE_STARTED           :
+               fprintf(stderr, "Node started\n");
+               break;
+       }
+}
+
+/* Execute Meta-connections Test Case # 5 - re-connection to peer after changing IP of peer */
+static void test_case_meta_conn_05(void **state) {
+       execute_test(test_steps_meta_conn_05, state);
+}
+
+/* Execute Meta-connections Test Case # 5 - re-connection to peer after changing IP of peer
+
+    Test Steps:
+    1. Run NUT and peer nodes with NUT inviting the peer node
+    2. After connection to peer, change the peer node's IP Address
+
+    Expected Result:
+    NUT is first disconnected from peer then automatically re-connected to peer
+*/
+static bool test_steps_meta_conn_05(void) {
+       bool result = false;
+       char *import;
+
+       import = mesh_event_sock_create(eth_if_name);
+       node_sim_in_container_event("nut", "1", NULL, "1", import);
+       wait_for_event(meta_conn05_cb, 5);
+
+       wait_for_event(meta_conn05_cb, 5);
+
+       if(!invitation) {
+               return false;
+       }
+
+       node_sim_in_container_event("peer", "1", invitation, "0", import);
+       wait_for_event(meta_conn05_cb, 5);
+
+       if(!wait_for_event(meta_conn05_cb, 5)) {
+               return false;
+       }
+
+       change_ip(0);
+       meta_conn05 = false;
+       node_sim_in_container_event("peer", "1", NULL, "0", import);
+       wait_for_event(meta_conn05_cb, 5);
+       PRINT_TEST_CASE_MSG("Waiting for peer to be re-connected\n");
+       wait_for_event(meta_conn05_cb, 5);
+       result = meta_conn05;
+
+       free(invitation);
+       free(import);
+       return result;
+}
+
+int test_meta_conn(void) {
+       const struct CMUnitTest blackbox_group0_tests[] = {
+               cmocka_unit_test_prestate_setup_teardown(test_case_meta_conn_01, setup_test, teardown_test,
+                               (void *)&test_meta_conn_1_state),
+               cmocka_unit_test_prestate_setup_teardown(test_case_meta_conn_02, setup_test, teardown_test,
+                               (void *)&test_meta_conn_2_state),
+               cmocka_unit_test_prestate_setup_teardown(test_case_meta_conn_03, setup_test, teardown_test,
+                               (void *)&test_meta_conn_3_state),
+               cmocka_unit_test_prestate_setup_teardown(test_case_meta_conn_04, setup_test, teardown_test,
+                               (void *)&test_meta_conn_4_state),
+               cmocka_unit_test_prestate_setup_teardown(test_case_meta_conn_05, setup_test, teardown_test,
+                               (void *)&test_meta_conn_5_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);
+}
diff --git a/test/blackbox/run_blackbox_tests/test_cases.h b/test/blackbox/run_blackbox_tests/test_cases.h
new file mode 100644 (file)
index 0000000..9260d01
--- /dev/null
@@ -0,0 +1,29 @@
+#ifndef TEST_CASES_H
+#define TEST_CASES_H
+
+/*
+    test_cases.h -- Declarations for Individual Test Case implementation functions
+    Copyright (C) 2018  Guus Sliepen <guus@meshlink.io>
+
+    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 <stdbool.h>
+
+extern int total_tests;
+extern int test_meta_conn(void);
+
+#endif // TEST_STEP_H
diff --git a/test/blackbox/run_blackbox_tests/test_cases_add_addr.c b/test/blackbox/run_blackbox_tests/test_cases_add_addr.c
new file mode 100644 (file)
index 0000000..d9d456f
--- /dev/null
@@ -0,0 +1,168 @@
+/*
+    test_cases_add_addr.c -- Execution of specific meshlink black box test cases
+    Copyright (C) 2018  Guus Sliepen <guus@meshlink.io>
+
+    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 "execute_tests.h"
+#include "test_cases_add_addr.h"
+#include "../common/containers.h"
+#include "../common/test_step.h"
+#include "../common/common_handlers.h"
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <setjmp.h>
+#include <cmocka.h>
+#include <assert.h>
+
+static void test_case_mesh_add_address_01(void **state);
+static bool test_steps_mesh_add_address_01(void);
+static void test_case_mesh_add_address_02(void **state);
+static bool test_steps_mesh_add_address_02(void);
+static void test_case_mesh_add_address_03(void **state);
+static bool test_steps_mesh_add_address_03(void);
+
+/* State structure for meshlink_add_address Test Case #1 */
+static black_box_state_t test_mesh_add_address_01_state = {
+       .test_case_name = "test_case_mesh_add_address_01",
+};
+
+/* State structure for meshlink_add_address Test Case #2 */
+static black_box_state_t test_mesh_add_address_02_state = {
+       .test_case_name = "test_case_mesh_add_address_02",
+};
+
+/* State structure for meshlink_add_address Test Case #3 */
+static black_box_state_t test_mesh_add_address_03_state = {
+       .test_case_name = "test_case_mesh_add_address_03",
+};
+
+/* Execute meshlink_add_address Test Case # 1 */
+static void test_case_mesh_add_address_01(void **state) {
+       execute_test(test_steps_mesh_add_address_01, state);
+}
+
+/* Test Steps for meshlink_add_address Test Case # 1
+
+    Test Steps:
+    1. Create node instance
+    2. Add an address to the host node
+    2. Open host file from confbase & verify address being added
+
+    Expected Result:
+    meshlink_add_address API adds the new address given to it's confbase
+*/
+static bool test_steps_mesh_add_address_01(void) {
+       char *node = "foo";
+       meshlink_destroy("add_conf.1");
+
+       // Create node instance
+       meshlink_handle_t *mesh = meshlink_open("add_conf.1", node, "chat", DEV_CLASS_STATIONARY);
+       assert(mesh != NULL);
+
+       char *hostname = "localhost";
+       bool ret = meshlink_add_address(mesh, hostname);
+       assert_int_equal(ret, true);
+
+       // Open the foo host file from confbase to verify address being added
+       bool found = false;
+       FILE *fp = fopen("./add_conf.1/hosts/foo", "r");
+       assert(fp);
+       char line[100];
+
+       while(fgets(line, 100, fp) != NULL) {
+               if(strcasestr(line, "Address") && strcasestr(line, hostname)) {
+                       found = true;
+               }
+       }
+
+       assert(!fclose(fp));
+
+       assert_int_equal(found, true);
+
+       // Clean up
+       meshlink_close(mesh);
+       meshlink_destroy("add_conf.1");
+       return true;
+}
+
+/* Execute meshlink_add_address Test Case # 2 */
+static void test_case_mesh_add_address_02(void **state) {
+       execute_test(test_steps_mesh_add_address_02, state);
+}
+
+/* Test Steps for meshlink_add_address Test Case # 2
+
+    Test Steps:
+    1. Create node instance
+    2. Call meshlink_add_address API using NULL as mesh handle argument
+
+    Expected Result:
+    meshlink_add_address API returns false by reporting error successfully.
+*/
+static bool test_steps_mesh_add_address_02(void) {
+       // Passing NULL as mesh handle argument to meshlink_add_address API
+       bool result = meshlink_add_address(NULL, "localhost");
+       assert_int_equal(result, false);
+
+       return true;
+}
+
+/* Execute meshlink_add_address Test Case # 3 */
+static void test_case_mesh_add_address_03(void **state) {
+       execute_test(test_steps_mesh_add_address_03, state);
+}
+
+/* Test Steps for meshlink_add_address Test Case # 3
+
+    Test Steps:
+    1. Create node instance
+    2. Call meshlink_add_address API using NULL as address argument
+
+    Expected Result:
+    meshlink_add_address API returns false by reporting error successfully.
+*/
+static bool test_steps_mesh_add_address_03(void) {
+       meshlink_destroy("add_conf.3");
+
+       // Create node instance
+       meshlink_handle_t *mesh = meshlink_open("add_conf.3", "foo", "chat", DEV_CLASS_STATIONARY);
+       assert(mesh != NULL);
+
+       bool result = meshlink_add_address(mesh, NULL);
+       assert_int_equal(result, false);
+
+       meshlink_close(mesh);
+       meshlink_destroy("add_conf.3");
+       return true;
+}
+
+int test_meshlink_add_address(void) {
+       const struct CMUnitTest blackbox_add_addr_tests[] = {
+               cmocka_unit_test_prestate_setup_teardown(test_case_mesh_add_address_01, NULL, NULL,
+                               (void *)&test_mesh_add_address_01_state),
+               cmocka_unit_test_prestate_setup_teardown(test_case_mesh_add_address_02, NULL, NULL,
+                               (void *)&test_mesh_add_address_02_state),
+               cmocka_unit_test_prestate_setup_teardown(test_case_mesh_add_address_03, NULL, NULL,
+                               (void *)&test_mesh_add_address_03_state)
+       };
+
+       total_tests += sizeof(blackbox_add_addr_tests) / sizeof(blackbox_add_addr_tests[0]);
+
+       return cmocka_run_group_tests(blackbox_add_addr_tests, NULL, NULL);
+}
+
diff --git a/test/blackbox/run_blackbox_tests/test_cases_add_addr.h b/test/blackbox/run_blackbox_tests/test_cases_add_addr.h
new file mode 100644 (file)
index 0000000..bfa3c05
--- /dev/null
@@ -0,0 +1,29 @@
+#ifndef TEST_CASES_ADD_ADDR_H
+#define TEST_CASES_ADD_ADDR_H
+
+/*
+    test_cases_add_addr.h -- Declarations for Individual Test Case implementation functions
+    Copyright (C) 2018  Guus Sliepen <guus@meshlink.io>
+
+    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 <stdbool.h>
+
+extern int test_meshlink_add_address(void);
+extern int total_tests;
+
+#endif //TEST_CASES_ADD_ADDR_H_INCLUDED
diff --git a/test/blackbox/run_blackbox_tests/test_cases_add_ex_addr.c b/test/blackbox/run_blackbox_tests/test_cases_add_ex_addr.c
new file mode 100644 (file)
index 0000000..bff9dd8
--- /dev/null
@@ -0,0 +1,130 @@
+/*
+    test_cases_add_ex_addr.c -- Execution of specific meshlink black box test cases
+    Copyright (C) 2018  Guus Sliepen <guus@meshlink.io>
+
+    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 "execute_tests.h"
+#include "test_cases_add_ex_addr.h"
+#include "../common/containers.h"
+#include "../common/test_step.h"
+#include "../common/common_handlers.h"
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <setjmp.h>
+#include <cmocka.h>
+#include <assert.h>
+
+static void test_case_mesh_add_ex_address_01(void **state);
+static bool test_steps_mesh_add_ex_address_01(void);
+static void test_case_mesh_add_ex_address_02(void **state);
+static bool test_steps_mesh_add_ex_address_02(void);
+
+/* State structure for meshlink_add_external_address Test Case #1 */
+static black_box_state_t test_mesh_add_ex_address_01_state = {
+       .test_case_name = "test_case_mesh_add_ex_address_01",
+};
+
+/* State structure for meshlink_add_external_address Test Case #2 */
+static black_box_state_t test_mesh_add_ex_address_02_state = {
+       .test_case_name = "test_case_mesh_add_ex_address_01",
+};
+
+/* Execute meshlink_add_external_address Test Case # 1 */
+void test_case_mesh_add_ex_address_01(void **state) {
+       execute_test(test_steps_mesh_add_ex_address_01, state);
+}
+
+/* Test Steps for meshlink_add_external_address Test Case # 1
+
+    Test Steps:
+    1. Create node instance
+    2. Get mesh's external address
+    3. Add external address using meshlink_add_external_address API
+    4. Open nodes confbase and read the external address from the list if addresses
+
+    Expected Result:
+    meshlink_add_external_address API adds the new address given to it's confbase
+*/
+bool test_steps_mesh_add_ex_address_01(void) {
+       meshlink_destroy("addex_conf.1");
+
+       // Create node instance
+       meshlink_handle_t *mesh = meshlink_open("addex_conf.1", "foo", "test", DEV_CLASS_STATIONARY);
+       assert(mesh != NULL);
+
+       char *external_address = meshlink_get_external_address(mesh);
+       assert(external_address);
+
+       bool ret = meshlink_add_external_address(mesh);
+       assert_int_equal(ret, true);
+
+       // Open the foo host file from confbase to verify address being added
+       bool found = false;
+       FILE *fp = fopen("./addex_conf.1/hosts/foo", "r");
+       assert(fp);
+       char line[100];
+
+       while(fgets(line, 100, fp) != NULL) {
+               if(strcasestr(line, "Address") && strcasestr(line, external_address)) {
+                       found = true;
+               }
+       }
+
+       assert(!fclose(fp));
+
+       assert_int_equal(found, true);
+
+       meshlink_close(mesh);
+       meshlink_destroy("addex_conf.1");
+       return true;
+}
+
+/* Execute meshlink_add_external_address Test Case # 2 */
+void test_case_mesh_add_ex_address_02(void **state) {
+       execute_test(test_steps_mesh_add_ex_address_02, state);
+}
+
+/* Test Steps for meshlink_add_external_address Test Case # 2
+
+    Test Steps:
+    1. Create node instance
+    2. Call meshlink_add_external_address API using NULL as mesh handle argument
+
+    Expected Result:
+    meshlink_add_external_address API returns false by reporting error successfully.
+*/
+bool test_steps_mesh_add_ex_address_02(void) {
+       bool result = meshlink_add_external_address(NULL);
+       assert_int_equal(result, false);
+
+       return true;
+}
+
+int test_meshlink_add_external_address(void) {
+       const struct CMUnitTest blackbox_add_ex_addr_tests[] = {
+               cmocka_unit_test_prestate_setup_teardown(test_case_mesh_add_ex_address_01, NULL, NULL,
+                               (void *)&test_mesh_add_ex_address_01_state),
+               cmocka_unit_test_prestate_setup_teardown(test_case_mesh_add_ex_address_02, NULL, NULL,
+                               (void *)&test_mesh_add_ex_address_02_state)
+       };
+
+       total_tests += sizeof(blackbox_add_ex_addr_tests) / sizeof(blackbox_add_ex_addr_tests[0]);
+
+       return cmocka_run_group_tests(blackbox_add_ex_addr_tests, NULL, NULL);
+}
+
diff --git a/test/blackbox/run_blackbox_tests/test_cases_add_ex_addr.h b/test/blackbox/run_blackbox_tests/test_cases_add_ex_addr.h
new file mode 100644 (file)
index 0000000..c5eca66
--- /dev/null
@@ -0,0 +1,29 @@
+#ifndef TEST_CASES_ADD_EX_ADDR_H
+#define TEST_CASES_ADD_EX_ADDR_H
+
+/*
+    test_cases_add_ex_addr.h -- Declarations for Individual Test Case implementation functions
+    Copyright (C) 2018  Guus Sliepen <guus@meshlink.io>
+
+    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 <stdbool.h>
+
+extern int test_meshlink_add_external_address(void);
+extern int total_tests;
+
+#endif
diff --git a/test/blackbox/run_blackbox_tests/test_cases_blacklist.c b/test/blackbox/run_blackbox_tests/test_cases_blacklist.c
new file mode 100644 (file)
index 0000000..15f1131
--- /dev/null
@@ -0,0 +1,225 @@
+/*
+    test_cases_blacklist.c -- Execution of specific meshlink black box test cases
+    Copyright (C) 2018  Guus Sliepen <guus@meshlink.io>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License along
+    with this program; if not, write to the Free Software Foundation, Inc.,
+    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+/* Modify this to change the logging level of Meshlink */
+#define TEST_MESHLINK_LOG_LEVEL MESHLINK_DEBUG
+
+#include "execute_tests.h"
+#include "test_cases_blacklist.h"
+#include "../common/containers.h"
+#include "../common/test_step.h"
+#include "../common/common_handlers.h"
+#include <stdlib.h>
+#include <stdarg.h>
+#include <setjmp.h>
+#include <cmocka.h>
+#include <assert.h>
+#include <string.h>
+
+static void test_case_mesh_blacklist_01(void **state);
+static bool test_steps_mesh_blacklist_01(void);
+static void test_case_mesh_blacklist_02(void **state);
+static bool test_steps_mesh_blacklist_02(void);
+static void test_case_mesh_blacklist_03(void **state);
+static bool test_steps_mesh_blacklist_03(void);
+
+/* State structure for meshlink_blacklist Test Case #1 */
+static black_box_state_t test_mesh_blacklist_01_state = {
+       .test_case_name = "test_case_mesh_blacklist_01",
+};
+
+/* State structure for meshlink_blacklist Test Case #2 */
+static black_box_state_t test_mesh_blacklist_02_state = {
+       .test_case_name = "test_case_mesh_blacklist_02",
+};
+
+/* State structure for meshlink_blacklist Test Case #3 */
+static black_box_state_t test_mesh_blacklist_03_state = {
+       .test_case_name = "test_case_mesh_blacklist_03",
+};
+
+/* Execute meshlink_blacklist Test Case # 1*/
+void test_case_mesh_blacklist_01(void **state) {
+       execute_test(test_steps_mesh_blacklist_01, state);
+}
+
+static bool received;
+
+static void receive(meshlink_handle_t *mesh, meshlink_node_t *src, const void *data, size_t len) {
+       const char *msg = data;
+       assert(len);
+
+       if(!strcmp(src->name, "bar") && len == 5 && !strcmp(msg, "test")) {
+               received = true;
+       }
+}
+
+static bool bar_reachable;
+
+static void status_cb(meshlink_handle_t *mesh, meshlink_node_t *node, bool reachable) {
+       if(!strcmp(node->name, "bar") && reachable) {
+               bar_reachable = true;
+       }
+}
+
+
+/* Test Steps for meshlink_blacklist Test Case # 1
+
+    Test Steps:
+    1. Open both the node instances
+    2. Join bar node with foo and Send & Receive data
+    3. Blacklist bar and Send & Receive data
+
+    Expected Result:
+    When default blacklist is disabled, foo node should receive data from bar
+    but when enabled foo node should not receive data
+*/
+bool test_steps_mesh_blacklist_01(void) {
+       meshlink_destroy("blacklist_conf.1");
+       meshlink_destroy("blacklist_conf.2");
+
+       // Open two new meshlink instance.
+       meshlink_handle_t *mesh1 = meshlink_open("blacklist_conf.1", "foo", "blacklist", DEV_CLASS_BACKBONE);
+       assert(mesh1 != NULL);
+       meshlink_set_log_cb(mesh1, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
+       meshlink_handle_t *mesh2 = meshlink_open("blacklist_conf.2", "bar", "blacklist", DEV_CLASS_BACKBONE);
+       assert(mesh2 != NULL);
+       meshlink_set_log_cb(mesh2, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
+       meshlink_set_receive_cb(mesh1, receive);
+
+       // Start both instances
+       bar_reachable = false;
+       meshlink_set_node_status_cb(mesh1, status_cb);
+       assert(meshlink_start(mesh1));
+       assert(meshlink_start(mesh2));
+       sleep(1);
+
+       char *foo_export = meshlink_export(mesh1);
+       assert(foo_export != NULL);
+       assert(meshlink_import(mesh2, foo_export));
+       char *bar_export = meshlink_export(mesh2);
+       assert(meshlink_import(mesh1, bar_export));
+       sleep(5);
+       assert_int_equal(bar_reachable, true);
+
+       meshlink_node_t *bar = meshlink_get_node(mesh1, "bar");
+       assert(bar);
+       meshlink_node_t *foo = meshlink_get_node(mesh2, "foo");
+       assert(foo);
+
+       received = false;
+       assert(meshlink_send(mesh2, foo, "test", 5));
+       sleep(1);
+       assert(received);
+
+       meshlink_blacklist(mesh1, bar);
+
+       received = false;
+       assert(meshlink_send(mesh2, foo, "test", 5));
+       sleep(1);
+       assert_int_equal(received, false);
+
+       // Clean up.
+       meshlink_close(mesh2);
+       meshlink_close(mesh1);
+       meshlink_destroy("blacklist_conf.1");
+       meshlink_destroy("blacklist_conf.2");
+       return true;
+}
+
+/* Execute meshlink_blacklist Test Case # 2*/
+void test_case_mesh_blacklist_02(void **state) {
+       execute_test(test_steps_mesh_blacklist_02, state);
+}
+
+
+/* Test Steps for meshlink_blacklist Test Case # 2
+
+    Test Steps:
+    1. Calling meshlink_blacklist with NULL as mesh handle argument.
+
+    Expected Result:
+    meshlink_blacklist API handles the invalid parameter when called by giving proper error number.
+*/
+bool test_steps_mesh_blacklist_02(void) {
+       meshlink_destroy("blacklist_conf.3");
+
+       // Open two new meshlink instance.
+       meshlink_handle_t *mesh = meshlink_open("blacklist_conf.3", "foo", "blacklist", DEV_CLASS_BACKBONE);
+       assert(mesh != NULL);
+
+       meshlink_node_t *node = meshlink_get_self(mesh);
+       assert(node);
+
+       // Passing NULL as mesh handle and node handle being some valid node handle
+       meshlink_blacklist(NULL, node);
+       assert_int_equal(meshlink_errno, MESHLINK_EINVAL);
+
+       // Clean up.
+       meshlink_close(mesh);
+       meshlink_destroy("blacklist_conf.3");
+       return true;
+}
+
+/* Execute meshlink_blacklist Test Case # 3*/
+void test_case_mesh_blacklist_03(void **state) {
+       execute_test(test_steps_mesh_blacklist_03, state);
+}
+
+/* Test Steps for meshlink_blacklist Test Case # 3
+
+    Test Steps:
+    1. Create node instance
+    2. Calling meshlink_blacklist with NULL as node handle argument.
+
+    Expected Result:
+    meshlink_blacklist API handles the invalid parameter when called by giving proper error number.
+*/
+bool test_steps_mesh_blacklist_03(void) {
+       meshlink_destroy("blacklist_conf.4");
+
+       // Open two new meshlink instance.
+       meshlink_handle_t *mesh = meshlink_open("blacklist_conf.4", "foo", "blacklist", DEV_CLASS_BACKBONE);
+       assert(mesh != NULL);
+
+       // Passing NULL as node handle and mesh handle being some valid mesh handle value
+       meshlink_blacklist(mesh, NULL);
+       assert_int_equal(meshlink_errno, MESHLINK_EINVAL);
+
+       // Clean up.
+       meshlink_close(mesh);
+       meshlink_destroy("blacklist_conf.4");
+       return true;
+}
+
+int test_meshlink_blacklist(void) {
+       const struct CMUnitTest blackbox_blacklist_tests[] = {
+               cmocka_unit_test_prestate_setup_teardown(test_case_mesh_blacklist_01, NULL, NULL,
+                               (void *)&test_mesh_blacklist_01_state),
+               cmocka_unit_test_prestate_setup_teardown(test_case_mesh_blacklist_02, NULL, NULL,
+                               (void *)&test_mesh_blacklist_02_state),
+               cmocka_unit_test_prestate_setup_teardown(test_case_mesh_blacklist_03, NULL, NULL,
+                               (void *)&test_mesh_blacklist_03_state)
+       };
+
+       total_tests += sizeof(blackbox_blacklist_tests) / sizeof(blackbox_blacklist_tests[0]);
+
+       return cmocka_run_group_tests(blackbox_blacklist_tests, NULL, NULL);
+}
+
diff --git a/test/blackbox/run_blackbox_tests/test_cases_blacklist.h b/test/blackbox/run_blackbox_tests/test_cases_blacklist.h
new file mode 100644 (file)
index 0000000..b591d02
--- /dev/null
@@ -0,0 +1,28 @@
+#ifndef TEST_CASES_BLACKLIST_H
+#define TEST_CASES_BLACKLIST_H
+
+/*
+    test_cases_blacklist.h -- Declarations for Individual Test Case implementation functions
+    Copyright (C) 2018  Guus Sliepen <guus@meshlink.io>
+
+    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 <stdbool.h>
+
+extern int test_meshlink_blacklist(void);
+extern int total_tests;
+
+#endif
diff --git a/test/blackbox/run_blackbox_tests/test_cases_channel_close.c b/test/blackbox/run_blackbox_tests/test_cases_channel_close.c
new file mode 100644 (file)
index 0000000..bc32256
--- /dev/null
@@ -0,0 +1,148 @@
+/*
+    test_cases_channel_close.c -- Execution of specific meshlink black box test cases
+    Copyright (C) 2018  Guus Sliepen <guus@meshlink.io>
+
+    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 "execute_tests.h"
+#include "test_cases_channel_close.h"
+#include "../common/containers.h"
+#include "../common/test_step.h"
+#include "../common/common_handlers.h"
+#include <stdlib.h>
+#include <stdarg.h>
+#include <setjmp.h>
+#include <cmocka.h>
+#include <assert.h>
+#include <string.h>
+
+static void test_case_mesh_channel_close_01(void **state);
+static bool test_steps_mesh_channel_close_01(void);
+static void test_case_mesh_channel_close_02(void **state);
+static bool test_steps_mesh_channel_close_02(void);
+
+/* State structure for meshlink_channel_close Test Case #1 */
+static black_box_state_t test_mesh_channel_close_01_state = {
+       .test_case_name = "test_case_mesh_channel_close_01",
+};
+
+/* State structure for meshlink_channel_close Test Case #2 */
+static black_box_state_t test_mesh_channel_close_02_state = {
+       .test_case_name = "test_case_mesh_channel_close_02",
+};
+
+/* Execute meshlink_channel_close Test Case # 1*/
+static void test_case_mesh_channel_close_01(void **state) {
+       execute_test(test_steps_mesh_channel_close_01, state);
+       return;
+}
+
+/* Test Steps for meshlink_channel_close Test Case # 1*/
+static bool test_steps_mesh_channel_close_01(void) {
+       bool result = false;
+       char *msg = NULL;
+       char buf[] = "bar";
+       msg = buf;
+       size_t len = sizeof(buf);
+       meshlink_destroy("chan_close_conf.3");
+       meshlink_destroy("chan_close_conf.4");
+
+       // Open two new meshlink instance.
+       meshlink_handle_t *mesh1 = meshlink_open("chan_close_conf.3", "foo", "channels", DEV_CLASS_BACKBONE);
+       assert(mesh1 != NULL);
+
+       meshlink_handle_t *mesh2 = meshlink_open("chan_close_conf.4", "bar", "channels", DEV_CLASS_BACKBONE);
+       assert(mesh2 != NULL);
+
+       if(!mesh2) {
+               fprintf(stderr, "Could not initialize configuration for bar\n");
+               return false;
+       }
+
+       char *exp = meshlink_export(mesh1);
+       assert(exp != NULL);
+       assert(meshlink_import(mesh2, exp));
+       free(exp);
+       exp = meshlink_export(mesh2);
+       assert(exp != NULL);
+       assert(meshlink_import(mesh1, exp));
+       free(exp);
+
+       // Start both instances
+       assert(meshlink_start(mesh1));
+       assert(meshlink_start(mesh2));
+       sleep(2);
+
+       // Open a channel from foo to bar.
+
+       meshlink_node_t *bar = meshlink_get_node(mesh1, "bar");
+       assert(bar != NULL);
+       meshlink_channel_t *channel = meshlink_channel_open(mesh1, bar, 7, NULL, NULL, 0);
+       assert(channel != NULL);
+
+       meshlink_channel_close(NULL, channel);
+       assert_int_equal(meshlink_errno, MESHLINK_EINVAL);
+
+
+       // Clean up.
+
+       meshlink_close(mesh2);
+       meshlink_close(mesh1);
+       meshlink_destroy("chan_close_conf.3");
+       meshlink_destroy("chan_close_conf.4");
+       return true;
+}
+
+/* Execute meshlink_channel_close Test Case # 2*/
+static void test_case_mesh_channel_close_02(void **state) {
+       execute_test(test_steps_mesh_channel_close_02, state);
+       return;
+}
+
+/* Test Steps for meshlink_channel_close Test Case # 2*/
+static bool test_steps_mesh_channel_close_02(void) {
+       meshlink_destroy("chan_close_conf.5");
+       // Open two new meshlink instance.
+
+       meshlink_handle_t *mesh = meshlink_open("chan_close_conf.5", "foo", "channels", DEV_CLASS_BACKBONE);
+       assert(mesh != NULL);
+
+       // Start both instances
+       assert(meshlink_start(mesh));
+
+       // Pass NULL as mesh handle
+       meshlink_channel_close(mesh, NULL);
+       assert_int_equal(meshlink_errno, MESHLINK_EINVAL);
+
+       // Clean up.
+
+       meshlink_close(mesh);
+       meshlink_destroy("chan_close_conf.5");
+       return true;
+}
+
+int test_meshlink_channel_close(void) {
+       const struct CMUnitTest blackbox_channel_close_tests[] = {
+               cmocka_unit_test_prestate_setup_teardown(test_case_mesh_channel_close_01, NULL, NULL,
+                               (void *)&test_mesh_channel_close_01_state),
+               cmocka_unit_test_prestate_setup_teardown(test_case_mesh_channel_close_02, NULL, NULL,
+                               (void *)&test_mesh_channel_close_02_state)
+       };
+
+       total_tests += sizeof(blackbox_channel_close_tests) / sizeof(blackbox_channel_close_tests[0]);
+
+       return cmocka_run_group_tests(blackbox_channel_close_tests, NULL, NULL);
+}
diff --git a/test/blackbox/run_blackbox_tests/test_cases_channel_close.h b/test/blackbox/run_blackbox_tests/test_cases_channel_close.h
new file mode 100644 (file)
index 0000000..7203a19
--- /dev/null
@@ -0,0 +1,28 @@
+#ifndef TEST_CASES_CHANNEL_CLOSE_H
+#define TEST_CASES_CHANNEL_CLOSE_H
+
+/*
+    test_cases_channel_close.h -- Declarations for Individual Test Case implementation functions
+    Copyright (C) 2018  Guus Sliepen <guus@meshlink.io>
+
+    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 <stdbool.h>
+
+extern int test_meshlink_channel_close(void);
+extern int total_tests;
+
+#endif
diff --git a/test/blackbox/run_blackbox_tests/test_cases_channel_conn.h b/test/blackbox/run_blackbox_tests/test_cases_channel_conn.h
new file mode 100644 (file)
index 0000000..9efed2f
--- /dev/null
@@ -0,0 +1,29 @@
+#ifndef TEST_CASES_CHANNEL_CONN_H
+#define TEST_CASES_CHANNEL_CONN_H
+
+/*
+    test_cases_channel_conn.h -- Declarations for Individual Test Case implementation functions
+    Copyright (C) 2018  Guus Sliepen <guus@meshlink.io>
+
+    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 <stdbool.h>
+
+extern int total_tests;
+extern int test_case_channel_conn(void);
+
+#endif // TEST_CASES_CHANNEL_CONN_H
diff --git a/test/blackbox/run_blackbox_tests/test_cases_channel_ex.c b/test/blackbox/run_blackbox_tests/test_cases_channel_ex.c
new file mode 100644 (file)
index 0000000..aa6fa23
--- /dev/null
@@ -0,0 +1,426 @@
+/*
+    test_cases_channel_ex.c -- Execution of specific meshlink black box test cases
+    Copyright (C) 2018  Guus Sliepen <guus@meshlink.io>
+
+    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 "execute_tests.h"
+#include "test_cases_channel_ex.h"
+#include "../common/containers.h"
+#include "../common/test_step.h"
+#include "../common/common_handlers.h"
+#include <assert.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <setjmp.h>
+#include <pthread.h>
+#include <cmocka.h>
+
+/* Modify this to change the logging level of Meshlink */
+#define TEST_MESHLINK_LOG_LEVEL MESHLINK_DEBUG
+/* Modify this to change the port number */
+#define PORT 8000
+
+static void test_case_channel_ex_01(void **state);
+static bool test_steps_channel_ex_01(void);
+static void test_case_channel_ex_02(void **state);
+static bool test_steps_channel_ex_02(void);
+static void test_case_channel_ex_03(void **state);
+static bool test_steps_channel_ex_03(void);
+static void test_case_channel_ex_04(void **state);
+static bool test_steps_channel_ex_04(void);
+static void test_case_channel_ex_05(void **state);
+static bool test_steps_channel_ex_05(void);
+static void test_case_channel_ex_06(void **state);
+static bool test_steps_channel_ex_06(void);
+
+static void 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);
+
+/* channel_acc gives us access to test whether the accept callback has been invoked or not */
+static bool channel_acc;
+/* mutex for the common variable */
+pthread_mutex_t lock;
+
+static black_box_state_t test_case_channel_ex_01_state = {
+       .test_case_name = "test_case_channel_ex_01",
+};
+static black_box_state_t test_case_channel_ex_02_state = {
+       .test_case_name = "test_case_channel_ex_02",
+};
+static black_box_state_t test_case_channel_ex_03_state = {
+       .test_case_name = "test_case_channel_ex_03",
+};
+static black_box_state_t test_case_channel_ex_04_state = {
+       .test_case_name = "test_case_channel_ex_04",
+};
+static black_box_state_t test_case_channel_ex_05_state = {
+       .test_case_name = "test_case_channel_ex_05",
+};
+static black_box_state_t test_case_channel_ex_06_state = {
+       .test_case_name = "test_case_channel_ex_06",
+};
+static black_box_state_t test_case_channel_ex_07_state = {
+       .test_case_name = "test_case_channel_ex_07",
+};
+
+/* mutex for the common variable */
+static pthread_mutex_t accept_lock = PTHREAD_MUTEX_INITIALIZER;
+static pthread_cond_t accept_cond = PTHREAD_COND_INITIALIZER;
+
+static bool channel_acc;
+
+/* channel receive callback */
+static void cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, const void *dat, size_t len) {
+       (void)mesh;
+       (void)channel;
+       (void)dat;
+       (void)len;
+
+       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;
+       char *data = (char *) dat;
+       assert_int_equal(port, PORT);
+
+       pthread_mutex_lock(&accept_lock);
+       channel_acc = true;
+       assert(!pthread_cond_broadcast(&accept_cond));
+       pthread_mutex_unlock(&accept_lock);
+
+       return true;
+}
+
+/* Execute meshlink_channel_open_ex Test Case # 1 - testing meshlink_channel_open_ex API's
+    valid case by passing all valid arguments */
+static void test_case_channel_ex_01(void **state) {
+       execute_test(test_steps_channel_ex_01, state);
+}
+
+/* Test Steps for meshlink_channel_open_ex Test Case # 1 - Valid case
+
+    Test Steps:
+    1. Run NUT(Node Under Test)
+    2. Open channel to ourself
+
+    Expected Result:
+    Opens a channel and echoes the send queue data.
+*/
+/* TODO: When send queue & send queue length are passed with some value other
+          than NULL it throws segmentation fault*/
+static bool test_steps_channel_ex_01(void) {
+       /* Set up logging for Meshlink */
+       meshlink_set_log_cb(NULL, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
+
+       /* Create meshlink instance */
+       meshlink_handle_t *mesh_handle = meshlink_open("channelexconf", "nut", "node_sim", 1);
+       assert(mesh_handle);
+       meshlink_set_log_cb(mesh_handle, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
+       meshlink_set_node_status_cb(mesh_handle, meshlink_callback_node_status);
+       meshlink_set_channel_accept_cb(mesh_handle, channel_accept);
+
+       assert(meshlink_start(mesh_handle));
+
+       /* Getting node handle for itself */
+       meshlink_node_t *node = meshlink_get_self(mesh_handle);
+       assert(node != NULL);
+
+       char string[100] = "Test the 1st case";
+       pthread_mutex_lock(&lock);
+       channel_acc = false;
+       pthread_mutex_unlock(&lock);
+
+       /* Passing all valid arguments for meshlink_channel_open_ex */
+       meshlink_channel_t *channel = NULL;
+       channel = meshlink_channel_open_ex(mesh_handle, node, PORT, cb, string, strlen(string) + 1, MESHLINK_CHANNEL_UDP);
+       assert_int_not_equal(channel, NULL);
+
+       // Delay for establishing a channel
+       sleep(1);
+
+       pthread_mutex_lock(&lock);
+       bool ret = channel_acc;
+       pthread_mutex_unlock(&lock);
+
+       assert_int_equal(ret, true);
+
+       meshlink_close(mesh_handle);
+       meshlink_destroy("channelexconf");
+
+       return true;
+}
+
+/* Execute meshlink_channel_open_ex Test Case # 2 - testing API's valid case by passing NULL and
+    0 for send queue & it's length respectively and others with valid arguments */
+static void test_case_channel_ex_02(void **state) {
+       execute_test(test_steps_channel_ex_02, state);
+}
+/* Test Steps for meshlink_channel_open_ex Test Case # 2 - Valid case (TCP channel)
+
+    Test Steps:
+    1. Run NUT(Node Under Test)
+    2. Open channel to ourself
+
+    Expected Result:
+    Opens a TCP channel successfully by setting channel_acc true*/
+static bool test_steps_channel_ex_02(void) {
+       meshlink_set_log_cb(NULL, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
+
+       /* Create meshlink instance */
+       meshlink_handle_t *mesh_handle = meshlink_open("channelexconf", "nut", "node_sim", 1);
+       assert(mesh_handle);
+       meshlink_set_log_cb(mesh_handle, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
+       meshlink_set_node_status_cb(mesh_handle, meshlink_callback_node_status);
+       meshlink_set_channel_accept_cb(mesh_handle, channel_accept);
+
+       assert(meshlink_start(mesh_handle));
+
+       meshlink_node_t *node = meshlink_get_self(mesh_handle);
+       assert(node != NULL);
+
+       pthread_mutex_lock(&lock);
+       channel_acc = false;
+       pthread_mutex_unlock(&lock);
+       sleep(1);
+
+       PRINT_TEST_CASE_MSG("Opening TCP alike channel ex\n");
+       /* Passing all valid arguments for meshlink_channel_open_ex */
+       meshlink_channel_t *channel;
+       channel = meshlink_channel_open_ex(mesh_handle, node, PORT, cb, NULL, 0, MESHLINK_CHANNEL_TCP);
+       assert_int_not_equal(channel, NULL);
+
+       // Delay for establishing a channel
+       sleep(1);
+       pthread_mutex_lock(&lock);
+       bool ret = channel_acc;
+       pthread_mutex_unlock(&lock);
+
+       assert_int_equal(ret, true);
+
+       meshlink_close(mesh_handle);
+       meshlink_destroy("channelexconf");
+       return true;
+}
+
+/* Execute meshlink_channel_open_ex Test Case # 3 - Open a UDP channel */
+static void test_case_channel_ex_03(void **state) {
+       execute_test(test_steps_channel_ex_03, state);
+}
+/* Test Steps for meshlink_channel_open_ex Test Case # 3 - Valid case (UDP channel)
+
+    Test Steps:
+    1. Run NUT(Node Under Test)
+    2. Open channel to ourself
+
+    Expected Result:
+    Opens a UDP channel successfully by setting channel_acc true */
+static bool test_steps_channel_ex_03(void) {
+       meshlink_set_log_cb(NULL, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
+
+       /* Create meshlink instance */
+       meshlink_handle_t *mesh_handle = meshlink_open("channelexconf", "nut", "node_sim", 1);
+       assert(mesh_handle);
+       meshlink_set_log_cb(mesh_handle, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
+       meshlink_set_node_status_cb(mesh_handle, meshlink_callback_node_status);
+       meshlink_set_channel_accept_cb(mesh_handle, channel_accept);
+
+       assert(meshlink_start(mesh_handle));
+
+       /* Getting node handle for itself */
+       meshlink_node_t *node = meshlink_get_self(mesh_handle);
+       assert(node != NULL);
+
+       pthread_mutex_lock(&lock);
+       channel_acc = false;
+       pthread_mutex_unlock(&lock);
+       sleep(1);
+
+       /* Passing all valid arguments for meshlink_channel_open_ex */
+       meshlink_channel_t *channel;
+       channel = meshlink_channel_open_ex(mesh_handle, node, PORT, cb, NULL, 0, MESHLINK_CHANNEL_UDP);
+       assert_int_not_equal(channel, NULL);
+
+       // Delay for establishing a channel
+       sleep(1);
+
+       pthread_mutex_lock(&lock);
+       bool ret = channel_acc;
+       pthread_mutex_unlock(&lock);
+
+       assert_int_equal(ret, true);
+
+       meshlink_close(mesh_handle);
+       meshlink_destroy("channelexconf");
+       return true;
+}
+
+/* Execute meshlink_channel_open_ex Test Case # 4 - Open a TCP channel with no receive callback
+    and send queue */
+static void test_case_channel_ex_04(void **state) {
+       execute_test(test_steps_channel_ex_04, state);
+}
+/* Test Steps for meshlink_channel_open_ex Test Case # 4 - Valid Case (Disabling receive callback)
+
+    Test Steps:
+    1. Run NUT(Node Under Test)
+    2. Open channel to ourself
+
+    Expected Result:
+    Opens a channel
+*/
+
+static bool test_steps_channel_ex_04(void) {
+       meshlink_set_log_cb(NULL, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
+
+       /* Create meshlink instance */
+       meshlink_handle_t *mesh_handle = meshlink_open("channelexconf", "nut", "node_sim", 1);
+       assert(mesh_handle);
+       meshlink_set_log_cb(mesh_handle, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
+       meshlink_set_node_status_cb(mesh_handle, meshlink_callback_node_status);
+       meshlink_set_channel_accept_cb(mesh_handle, channel_accept);
+
+       assert(meshlink_start(mesh_handle));
+
+       /* Getting node handle for itself */
+       meshlink_node_t *node = meshlink_get_self(mesh_handle);
+       assert(node != NULL);
+
+       pthread_mutex_lock(&lock);
+       channel_acc = false;
+       pthread_mutex_unlock(&lock);
+
+       /* Passing all valid arguments for meshlink_channel_open_ex i.e disabling receive callback and send queue */
+       meshlink_channel_t *channel;
+       channel = meshlink_channel_open_ex(mesh_handle, node, PORT, NULL, NULL, 0, MESHLINK_CHANNEL_UDP);
+       assert(channel != NULL);
+       // Delay for establishing a channel
+
+       pthread_mutex_lock(&lock);
+       bool ret = channel_acc;
+       pthread_mutex_unlock(&lock);
+
+       assert_int_equal(ret, true);
+
+       meshlink_close(mesh_handle);
+       meshlink_destroy("channelexconf");
+       return true;
+}
+
+/* Execute meshlink_channel_open_ex Test Case # 5 - Opening channel using NULL as mesh handle argument
+    for the API */
+static void test_case_channel_ex_05(void **state) {
+       execute_test(test_steps_channel_ex_05, state);
+}
+/* Test Steps for meshlink_channel_open_ex Test Case # 5 - Invalid case (NULL as mesh argument)
+
+    Test Steps:
+    1. Run NUT(Node Under Test)
+    2. Open channel by passing NULL as argument for mesh handle
+
+    Expected Result:
+    meshlink_channel_open_ex returns NULL as channel handle reporting error accordingly
+*/
+static bool test_steps_channel_ex_05(void) {
+       /* Set up logging for Meshlink */
+       meshlink_set_log_cb(NULL, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
+
+       /* Create meshlink instance */
+       meshlink_handle_t *mesh_handle = meshlink_open("channelexconf", "nut", "node_sim", 1);
+       assert(mesh_handle);
+
+       meshlink_set_log_cb(mesh_handle, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
+       meshlink_set_node_status_cb(mesh_handle, meshlink_callback_node_status);
+       meshlink_set_channel_accept_cb(mesh_handle, channel_accept);
+
+       assert(meshlink_start(mesh_handle));
+       /* Getting node handle for itself */
+       meshlink_node_t *node = meshlink_get_self(mesh_handle);
+       assert(node != NULL);
+
+       /* Trying to open channel using mesh handle as NULL argument */
+       meshlink_channel_t *channel = meshlink_channel_open_ex(NULL, node, PORT, cb, NULL, 0, MESHLINK_CHANNEL_TCP);
+       assert(channel == NULL);
+
+       meshlink_close(mesh_handle);
+       meshlink_destroy("channelexconf");
+       return true;
+}
+
+/* Execute meshlink_channel_open_ex Test Case # 6 - Opening channel using NULL as node handle argument
+    for the API*/
+static void test_case_channel_ex_06(void **state) {
+       execute_test(test_steps_channel_ex_06, state);
+}
+
+/* Test Steps for meshlink_channel_open_ex Test Case # 6 - Invalid case (NULL as node argument)
+
+    Test Steps:
+    1. Run NUT(Node Under Test)
+    2. Open channel by passing NULL as argument for node handle
+
+    Expected Result:
+    meshlink_channel_open_ex returns NULL as channel handle reporting error accordingly
+*/
+static bool test_steps_channel_ex_06(void) {
+       meshlink_set_log_cb(NULL, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
+
+       /* Create meshlink instance */
+       meshlink_handle_t *mesh_handle = meshlink_open("channelexconf", "nut", "node_sim", 1);
+       assert(mesh_handle);
+
+       meshlink_set_log_cb(mesh_handle, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
+       meshlink_set_node_status_cb(mesh_handle, meshlink_callback_node_status);
+       meshlink_set_channel_accept_cb(mesh_handle, channel_accept);
+
+       assert(meshlink_start(mesh_handle));
+
+       /* Trying to open channel using node handle as NULL argument */
+       meshlink_channel_t *channel = meshlink_channel_open_ex(mesh_handle, NULL, PORT, cb, NULL, 0, MESHLINK_CHANNEL_TCP);
+
+       assert_int_equal(channel, NULL);
+
+       meshlink_close(mesh_handle);
+       meshlink_destroy("channelexconf");
+       return true;
+}
+
+int test_meshlink_channel_open_ex(void) {
+       const struct CMUnitTest blackbox_channel_ex_tests[] = {
+               cmocka_unit_test_prestate_setup_teardown(test_case_channel_ex_01, NULL, NULL,
+                               (void *)&test_case_channel_ex_01_state),
+               cmocka_unit_test_prestate_setup_teardown(test_case_channel_ex_02, NULL, NULL,
+                               (void *)&test_case_channel_ex_02_state),
+               cmocka_unit_test_prestate_setup_teardown(test_case_channel_ex_03, NULL, NULL,
+                               (void *)&test_case_channel_ex_03_state),
+               cmocka_unit_test_prestate_setup_teardown(test_case_channel_ex_04, NULL, NULL,
+                               (void *)&test_case_channel_ex_04_state),
+               cmocka_unit_test_prestate_setup_teardown(test_case_channel_ex_05, NULL, NULL,
+                               (void *)&test_case_channel_ex_05_state),
+               cmocka_unit_test_prestate_setup_teardown(test_case_channel_ex_06, NULL, NULL,
+                               (void *)&test_case_channel_ex_06_state)
+       };
+
+       total_tests += sizeof(blackbox_channel_ex_tests) / sizeof(blackbox_channel_ex_tests[0]);
+
+       assert(pthread_mutex_init(&lock, NULL) == 0);
+       int failed = cmocka_run_group_tests(blackbox_channel_ex_tests, NULL, NULL);
+       assert(pthread_mutex_destroy(&lock) == 0);
+
+       return failed;
+}
diff --git a/test/blackbox/run_blackbox_tests/test_cases_channel_ex.h b/test/blackbox/run_blackbox_tests/test_cases_channel_ex.h
new file mode 100644 (file)
index 0000000..e15fa28
--- /dev/null
@@ -0,0 +1,28 @@
+#ifndef TEST_CASES_CHANNELS_EX_H
+#define TEST_CASES_CHANNELS_EX_H
+
+/*
+    test_cases_channel_ex.h -- Declarations for Individual Test Case implementation functions
+    Copyright (C) 2018  Guus Sliepen <guus@meshlink.io>
+
+    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 <stdbool.h>
+
+extern int total_tests;
+extern int test_meshlink_channel_open_ex(void);
+
+#endif
diff --git a/test/blackbox/run_blackbox_tests/test_cases_channel_get_flags.c b/test/blackbox/run_blackbox_tests/test_cases_channel_get_flags.c
new file mode 100644 (file)
index 0000000..266b315
--- /dev/null
@@ -0,0 +1,200 @@
+/*
+    test_cases_channel_get_flags.c -- Execution of specific meshlink black box test cases
+    Copyright (C) 2018  Guus Sliepen <guus@meshlink.io>
+
+    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 "execute_tests.h"
+#include "test_cases_channel_get_flags.h"
+#include "../common/containers.h"
+#include "../common/test_step.h"
+#include "../common/common_handlers.h"
+#include <assert.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <setjmp.h>
+#include <cmocka.h>
+
+#define TEST_MESHLINK_LOG_LEVEL MESHLINK_DEBUG
+/* Modify this to change the port number */
+#define PORT 8000
+
+static void test_case_channel_get_flags_01(void **state);
+static bool test_steps_channel_get_flags_01(void);
+static void test_case_channel_get_flags_02(void **state);
+static bool test_steps_channel_get_flags_02(void);
+static void test_case_channel_get_flags_03(void **state);
+static bool test_steps_channel_get_flags_03(void);
+
+static black_box_state_t test_case_channel_get_flags_01_state = {
+       .test_case_name = "test_case_channel_get_flags_01",
+};
+static black_box_state_t test_case_channel_get_flags_02_state = {
+       .test_case_name = "test_case_channel_get_flags_02",
+};
+static black_box_state_t test_case_channel_get_flags_03_state = {
+       .test_case_name = "test_case_channel_get_flags_03",
+};
+static black_box_state_t test_case_channel_get_flags_04_state = {
+       .test_case_name = "test_case_channel_get_flags_04",
+};
+
+
+/* Execute meshlink_channel_get_flags Test Case # 1 - Valid case*/
+static void test_case_channel_get_flags_01(void **state) {
+       execute_test(test_steps_channel_get_flags_01, state);
+}
+/* Test Steps for meshlink_channel_get_flags Test Case # 1
+
+    Test Steps:
+    1. Run NUT(Node Under Test)
+    2. Open channel to ourself (with TCP semantic here)
+    3. Get flag(s) of that channel
+
+    Expected Result:
+    API returning exact flag that has been assigned while opening (here TCP)
+*/
+static bool test_steps_channel_get_flags_01(void) {
+       meshlink_set_log_cb(NULL, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
+
+       /* Create meshlink instance */
+       meshlink_handle_t *mesh_handle = meshlink_open("getflagsconf", "nut", "node_sim", 1);
+       assert(mesh_handle);
+       meshlink_set_log_cb(mesh_handle, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
+       meshlink_set_node_status_cb(mesh_handle, meshlink_callback_node_status);
+       meshlink_set_channel_accept_cb(mesh_handle, NULL);
+
+       assert(meshlink_start(mesh_handle));
+
+       meshlink_node_t *node = meshlink_get_self(mesh_handle);
+       assert(node != NULL);
+       sleep(1);
+
+       /* Passing all valid arguments for meshlink_channel_open_ex */
+       meshlink_channel_t *channel;
+       channel = meshlink_channel_open_ex(mesh_handle, node, PORT, NULL, NULL, 0, MESHLINK_CHANNEL_TCP);
+       assert(channel != NULL);
+
+       // Obtaining channel flags using meshlink_channel_get_flags
+       uint32_t flags = meshlink_channel_get_flags(mesh_handle, channel);
+       assert_int_equal(flags, MESHLINK_CHANNEL_TCP);
+
+       meshlink_close(mesh_handle);
+       meshlink_destroy("getflagsconf");
+
+       return true;
+}
+
+/* Execute meshlink_channel_get_flags Test Case # 2 - Invalid case*/
+static void test_case_channel_get_flags_02(void **state) {
+       execute_test(test_steps_channel_get_flags_02, state);
+}
+/* Test Steps for meshlink_channel_get_flags Test Case # 2
+
+    Test Steps:
+    1. Run NUT(Node Under Test)
+    2. Open channel to ourself (with TCP semantic here)
+    3. Call meshlink_channel_get_flags by passing NULL as mesh handle argument
+
+    Expected Result:
+    API reporting error accordingly.
+*/
+static bool test_steps_channel_get_flags_02(void) {
+       meshlink_set_log_cb(NULL, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
+
+       /* Create meshlink instance */
+       meshlink_handle_t *mesh_handle = meshlink_open("getflagsconf", "nut", "node_sim", 1);
+       assert(mesh_handle);
+
+       meshlink_set_log_cb(mesh_handle, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
+       meshlink_set_node_status_cb(mesh_handle, meshlink_callback_node_status);
+       meshlink_set_channel_accept_cb(mesh_handle, NULL);
+
+       assert(meshlink_start(mesh_handle));
+
+       /* Getting node handle for itself */
+       meshlink_node_t *node = meshlink_get_self(mesh_handle);
+       assert(node != NULL);
+       sleep(1);
+
+       /* Passing all valid arguments for meshlink_channel_open_ex */
+       meshlink_channel_t *channel;
+       channel = meshlink_channel_open_ex(mesh_handle, node, PORT, NULL, NULL, 0, MESHLINK_CHANNEL_TCP);
+       assert(channel != NULL);
+
+       // passing NULL as mesh handle argument for meshlink_channel_get_flags
+       uint32_t flags = meshlink_channel_get_flags(NULL, channel);
+
+       assert_int_equal((int32_t)flags, -1);
+       assert_int_equal(meshlink_errno, MESHLINK_EINVAL);
+
+       meshlink_close(mesh_handle);
+       meshlink_destroy("getflagsconf");
+       return true;
+}
+
+/* Execute meshlink_channel_get flags Test Case # 3 - Invalid case*/
+static void test_case_channel_get_flags_03(void **state) {
+       execute_test(test_steps_channel_get_flags_03, state);
+}
+/* Test Steps for meshlink_channel_get_flags Test Case # 3
+
+    Test Steps:
+    1. Run NUT(Node Under Test)
+    3. Call meshlink_channel_get_flags by passing NULL as channel handle argument
+
+    Expected Result:
+    API reporting error accordingly.
+*/
+static bool test_steps_channel_get_flags_03(void) {
+       meshlink_set_log_cb(NULL, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
+
+       /* Create meshlink instance */
+       meshlink_handle_t *mesh_handle = meshlink_open("getflagsconf", "nut", "node_sim", 1);
+       assert(mesh_handle);
+       meshlink_set_log_cb(mesh_handle, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
+       meshlink_set_node_status_cb(mesh_handle, meshlink_callback_node_status);
+       meshlink_set_channel_accept_cb(mesh_handle, NULL);
+
+       assert(meshlink_start(mesh_handle));
+
+       // passing NULL as channel handle argument for meshlink_channel_get_flags
+       uint32_t flags = meshlink_channel_get_flags(mesh_handle, NULL);
+
+       assert_int_equal((int32_t)flags, -1);
+       assert_int_equal(meshlink_errno, MESHLINK_EINVAL);
+
+       meshlink_close(mesh_handle);
+       meshlink_destroy("getflagsconf");
+       return true;
+}
+
+
+int test_meshlink_channel_get_flags(void) {
+       const struct CMUnitTest blackbox_channel_get_flags_tests[] = {
+               cmocka_unit_test_prestate_setup_teardown(test_case_channel_get_flags_01, NULL, NULL,
+                               (void *)&test_case_channel_get_flags_01_state),
+               cmocka_unit_test_prestate_setup_teardown(test_case_channel_get_flags_02, NULL, NULL,
+                               (void *)&test_case_channel_get_flags_02_state),
+               cmocka_unit_test_prestate_setup_teardown(test_case_channel_get_flags_03, NULL, NULL,
+                               (void *)&test_case_channel_get_flags_03_state)
+       };
+
+       total_tests += sizeof(blackbox_channel_get_flags_tests) / sizeof(blackbox_channel_get_flags_tests[0]);
+
+       return cmocka_run_group_tests(blackbox_channel_get_flags_tests, NULL, NULL);
+}
diff --git a/test/blackbox/run_blackbox_tests/test_cases_channel_get_flags.h b/test/blackbox/run_blackbox_tests/test_cases_channel_get_flags.h
new file mode 100644 (file)
index 0000000..d60ec90
--- /dev/null
@@ -0,0 +1,28 @@
+#ifndef TEST_CASES_CHANNELS_SET_ACCEPT_H
+#define TEST_CASES_CHANNELS_SET_ACCEPT_H
+
+/*
+    test_cases_get_self.h -- Declarations for Individual Test Case implementation functions
+    Copyright (C) 2018  Guus Sliepen <guus@meshlink.io>
+
+    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 <stdbool.h>
+
+extern int total_tests;
+extern int test_meshlink_channel_get_flags(void);
+
+#endif
diff --git a/test/blackbox/run_blackbox_tests/test_cases_channel_open.c b/test/blackbox/run_blackbox_tests/test_cases_channel_open.c
new file mode 100644 (file)
index 0000000..0d5728f
--- /dev/null
@@ -0,0 +1,260 @@
+/*
+    test_cases_channel_open.c -- Execution of specific meshlink black box test cases
+    Copyright (C) 2018  Guus Sliepen <guus@meshlink.io>
+
+    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 "execute_tests.h"
+#include "test_cases_channel_open.h"
+#include "../common/containers.h"
+#include "../common/test_step.h"
+#include "../common/common_handlers.h"
+#include <stdlib.h>
+#include <stdarg.h>
+#include <setjmp.h>
+#include <cmocka.h>
+#include <assert.h>
+#include <string.h>
+
+static void test_case_mesh_channel_open_01(void **state);
+static bool test_steps_mesh_channel_open_01(void);
+static void test_case_mesh_channel_open_02(void **state);
+static bool test_steps_mesh_channel_open_02(void);
+static void test_case_mesh_channel_open_03(void **state);
+static bool test_steps_mesh_channel_open_03(void);
+static void test_case_mesh_channel_open_04(void **state);
+static bool test_steps_mesh_channel_open_04(void);
+
+/* State structure for meshlink_channel_open Test Case #1 */
+static black_box_state_t test_mesh_channel_open_01_state = {
+       .test_case_name = "test_case_mesh_channel_open_01",
+};
+
+/* State structure for meshlink_channel_open Test Case #2 */
+static black_box_state_t test_mesh_channel_open_02_state = {
+       .test_case_name = "test_case_mesh_channel_open_02",
+};
+
+/* State structure for meshlink_channel_open Test Case #3 */
+static black_box_state_t test_mesh_channel_open_03_state = {
+       .test_case_name = "test_case_mesh_channel_open_03",
+};
+
+/* State structure for meshlink_channel_open Test Case #4 */
+static black_box_state_t test_mesh_channel_open_04_state = {
+       .test_case_name = "test_case_mesh_channel_open_04",
+};
+
+/* Execute meshlink_channel_open Test Case # 1*/
+static void test_case_mesh_channel_open_01(void **state) {
+       execute_test(test_steps_mesh_channel_open_01, state);
+}
+
+static void receive_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, const void *data, size_t len) {
+       (void)mesh;
+       (void)channel;
+}
+
+/* Test Steps for meshlink_channel_open Test Case # 1
+
+    Test Steps:
+    1. Open both the node instances
+    2. Join bar node with foo
+    3. Open channel between the nodes
+
+    Expected Result:
+    meshlink_channel_open should open a channel by returning a channel handler
+*/
+static bool test_steps_mesh_channel_open_01(void) {
+       meshlink_destroy("channels_conf.1");
+       meshlink_destroy("channels_conf.2");
+
+       // Open two new meshlink instance.
+       meshlink_handle_t *mesh1 = meshlink_open("channels_conf.1", "foo", "channels", DEV_CLASS_BACKBONE);
+       assert(mesh1 != NULL);
+       meshlink_handle_t *mesh2 = meshlink_open("channels_conf.2", "bar", "channels", DEV_CLASS_BACKBONE);
+       assert(mesh2 != NULL);
+
+       // Import and export both side's data
+       char *exp = meshlink_export(mesh1);
+       assert(exp != NULL);
+       assert(meshlink_import(mesh2, exp));
+       free(exp);
+       exp = meshlink_export(mesh2);
+       assert(exp != NULL);
+       assert(meshlink_import(mesh1, exp));
+       free(exp);
+
+       // Start both instances
+       assert(meshlink_start(mesh1));
+       assert(meshlink_start(mesh2));
+       sleep(2);
+
+       // Open a channel from foo to bar.
+       meshlink_node_t *bar = meshlink_get_node(mesh1, "bar");
+       assert(bar != NULL);
+       meshlink_channel_t *channel = meshlink_channel_open(mesh1, bar, 7000, receive_cb, NULL, 0);
+       assert_int_not_equal(channel, NULL);
+
+       // Clean up.
+       meshlink_close(mesh2);
+       meshlink_close(mesh1);
+       meshlink_destroy("channels_conf.1");
+       meshlink_destroy("channels_conf.2");
+       return true;
+}
+
+/* Execute meshlink_channel_open Test Case # 2
+
+    Test Steps:
+    1. Open both the node instances
+    2. Join bar node with foo
+    3. Open channel between the nodes with NULL as receive callback argument
+
+    Expected Result:
+    meshlink_channel_open should open a channel by returning a channel handler
+*/
+static void test_case_mesh_channel_open_02(void **state) {
+       execute_test(test_steps_mesh_channel_open_02, state);
+}
+
+/* Test Steps for meshlink_channel_open Test Case # 2*/
+static bool test_steps_mesh_channel_open_02(void) {
+       meshlink_destroy("channels_conf.3");
+       meshlink_destroy("channels_conf.4");
+
+       // Open two new meshlink instance.
+       meshlink_handle_t *mesh1 = meshlink_open("channels_conf.3", "foo", "channels", DEV_CLASS_BACKBONE);
+       assert(mesh1 != NULL);
+       meshlink_handle_t *mesh2 = meshlink_open("channels_conf.4", "bar", "channels", DEV_CLASS_BACKBONE);
+       assert(mesh2 != NULL);
+
+       char *exp = meshlink_export(mesh1);
+       assert(exp != NULL);
+       assert(meshlink_import(mesh2, exp));
+       free(exp);
+       exp = meshlink_export(mesh2);
+       assert(exp != NULL);
+       assert(meshlink_import(mesh1, exp));
+       free(exp);
+
+       // Start both instances
+       assert(meshlink_start(mesh1));
+       assert(meshlink_start(mesh2));
+       sleep(1);
+
+       // Open a channel from foo to bar.
+
+       meshlink_node_t *bar = meshlink_get_node(mesh1, "bar");
+       assert(bar != NULL);
+
+       meshlink_channel_t *channel = meshlink_channel_open(mesh1, bar, 7000, NULL, NULL, 0);
+       assert_int_not_equal(channel, NULL);
+
+       // Clean up.
+       meshlink_close(mesh2);
+       meshlink_close(mesh1);
+       meshlink_destroy("channels_conf.3");
+       meshlink_destroy("channels_conf.4");
+       return true;
+}
+
+/* Execute meshlink_channel_open Test Case # 3 */
+static void test_case_mesh_channel_open_03(void **state) {
+       execute_test(test_steps_mesh_channel_open_03, state);
+}
+
+/* Test Steps for meshlink_channel_open Test Case # 3
+
+    Test Steps:
+    1. Create the node instance & obtain node handle
+    2. Open a channel with NULL as mesh handle argument
+        and rest other arguments being valid.
+
+    Expected Result:
+    meshlink_channel_open API handles the invalid parameter
+    when called by giving proper error number.
+*/
+static bool test_steps_mesh_channel_open_03(void) {
+       meshlink_destroy("channels_conf.5");
+
+       // Open two new meshlink instance.
+       meshlink_handle_t *mesh = meshlink_open("channels_conf.5", "foo", "channels", DEV_CLASS_BACKBONE);
+       assert(mesh != NULL);
+
+       meshlink_node_t *node = meshlink_get_self(mesh);
+       assert(node);
+
+       meshlink_channel_t *channel = meshlink_channel_open(NULL, node, 7000, NULL, NULL, 0);
+       assert_int_equal(channel, NULL);
+
+       // Clean up.
+       meshlink_close(mesh);
+       meshlink_destroy("channels_conf.5");
+       return true;
+}
+
+/* Execute meshlink_channel_open Test Case # 4*/
+static void test_case_mesh_channel_open_04(void **state) {
+       execute_test(test_steps_mesh_channel_open_04, state);
+}
+
+/* Test Steps for meshlink_channel_open Test Case # 4
+
+    Test Steps:
+    1. Create the node instance & obtain node handle
+    2. Open a channel with NULL as node handle argument
+        and rest other arguments being valid.
+
+    Expected Result:
+    meshlink_channel_open API handles the invalid parameter
+    when called by giving proper error number.
+*/
+static bool test_steps_mesh_channel_open_04(void) {
+       meshlink_destroy("channels_conf.7");
+
+       // Open two new meshlink instance.
+       meshlink_handle_t *mesh = meshlink_open("channels_conf.7", "foo", "channels", DEV_CLASS_BACKBONE);
+       assert(mesh != NULL);
+
+       // Start both instances
+       assert(meshlink_start(mesh));
+
+       meshlink_channel_t *channel = meshlink_channel_open(mesh, NULL, 7000, NULL, NULL, 0);
+       assert_int_equal(channel, NULL);
+
+       // Clean up.
+       meshlink_close(mesh);
+       meshlink_destroy("channels_conf.7");
+       return true;
+}
+
+int test_meshlink_channel_open(void) {
+       const struct CMUnitTest blackbox_channel_open_tests[] = {
+               cmocka_unit_test_prestate_setup_teardown(test_case_mesh_channel_open_01, NULL, NULL,
+                               (void *)&test_mesh_channel_open_01_state),
+               cmocka_unit_test_prestate_setup_teardown(test_case_mesh_channel_open_02, NULL, NULL,
+                               (void *)&test_mesh_channel_open_02_state),
+               cmocka_unit_test_prestate_setup_teardown(test_case_mesh_channel_open_03, NULL, NULL,
+                               (void *)&test_mesh_channel_open_03_state),
+               cmocka_unit_test_prestate_setup_teardown(test_case_mesh_channel_open_04, NULL, NULL,
+                               (void *)&test_mesh_channel_open_04_state)
+       };
+
+       total_tests += sizeof(blackbox_channel_open_tests) / sizeof(blackbox_channel_open_tests[0]);
+
+       return cmocka_run_group_tests(blackbox_channel_open_tests, NULL, NULL);
+}
diff --git a/test/blackbox/run_blackbox_tests/test_cases_channel_open.h b/test/blackbox/run_blackbox_tests/test_cases_channel_open.h
new file mode 100644 (file)
index 0000000..a1140a0
--- /dev/null
@@ -0,0 +1,28 @@
+#ifndef TEST_CASES_CHANNEL_OPEN_H
+#define TEST_CASES_CHANNEL_OPEN_H
+
+/*
+    test_cases_channel_open.h -- Declarations for Individual Test Case implementation functions
+    Copyright (C) 2018  Guus Sliepen <guus@meshlink.io>
+
+    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 <stdbool.h>
+
+extern int test_meshlink_channel_open(void);
+extern int total_tests;
+
+#endif
diff --git a/test/blackbox/run_blackbox_tests/test_cases_channel_send.c b/test/blackbox/run_blackbox_tests/test_cases_channel_send.c
new file mode 100644 (file)
index 0000000..651e16e
--- /dev/null
@@ -0,0 +1,357 @@
+/*
+    test_cases_channel_send.c -- Execution of specific meshlink black box test cases
+    Copyright (C) 2018  Guus Sliepen <guus@meshlink.io>
+
+    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 "execute_tests.h"
+#include "test_cases_channel_send.h"
+#include "../common/containers.h"
+#include "../common/test_step.h"
+#include "../common/common_handlers.h"
+#include <stdlib.h>
+#include <stdarg.h>
+#include <setjmp.h>
+#include <cmocka.h>
+#include <assert.h>
+#include <string.h>
+#include <pthread.h>
+
+static void test_case_mesh_channel_send_01(void **state);
+static bool test_steps_mesh_channel_send_01(void);
+static void test_case_mesh_channel_send_02(void **state);
+static bool test_steps_mesh_channel_send_02(void);
+static void test_case_mesh_channel_send_03(void **state);
+static bool test_steps_mesh_channel_send_03(void);
+static void test_case_mesh_channel_send_04(void **state);
+static bool test_steps_mesh_channel_send_04(void);
+
+static void receive_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, const void *dat, size_t len);
+static void status_cb(meshlink_handle_t *mesh, meshlink_node_t *node, bool reachable);
+static void poll_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, size_t len);
+
+/* State structure for meshlink_channel_send Test Case #1 */
+static black_box_state_t test_mesh_channel_send_01_state = {
+       .test_case_name = "test_case_mesh_channel_send_01",
+};
+
+/* State structure for meshlink_channel_send Test Case #2 */
+static black_box_state_t test_mesh_channel_send_02_state = {
+       .test_case_name = "test_case_mesh_channel_send_02",
+};
+
+/* State structure for meshlink_channel_send Test Case #3 */
+static black_box_state_t test_mesh_channel_send_03_state = {
+       .test_case_name = "test_case_mesh_channel_send_03",
+};
+
+/* State structure for meshlink_channel_send Test Case #4 */
+static black_box_state_t test_mesh_channel_send_04_state = {
+       .test_case_name = "test_case_mesh_channel_send_04",
+};
+
+/* Execute meshlink_channel_send Test Case # 1*/
+static void test_case_mesh_channel_send_01(void **state) {
+       execute_test(test_steps_mesh_channel_send_01, state);
+}
+
+static pthread_mutex_t poll_lock = PTHREAD_MUTEX_INITIALIZER;
+static pthread_mutex_t bar_reach_lock = PTHREAD_MUTEX_INITIALIZER;
+static pthread_mutex_t bar_responded_lock = PTHREAD_MUTEX_INITIALIZER;
+
+static pthread_cond_t poll_cond = PTHREAD_COND_INITIALIZER;
+static pthread_cond_t status_cond = PTHREAD_COND_INITIALIZER;
+static pthread_cond_t send_cond = PTHREAD_COND_INITIALIZER;
+
+static bool polled;
+static bool bar_reachable;
+static bool bar_responded;
+
+static void status_cb(meshlink_handle_t *mesh, meshlink_node_t *node, bool reachable) {
+       (void)mesh;
+
+       if(!strcmp(node->name, "bar")) {
+               pthread_mutex_lock(& bar_reach_lock);
+               bar_reachable = reachable;
+               assert(!pthread_cond_broadcast(&status_cond));
+               pthread_mutex_unlock(& bar_reach_lock);
+       }
+}
+
+static bool reject_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, uint16_t port, const void *data, size_t len) {
+       (void)mesh;
+       (void)channel;
+       (void)port;
+       (void)data;
+       (void)len;
+       return false;
+}
+
+static bool accept_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, uint16_t port, const void *data, size_t len) {
+       assert(port == 7);
+       assert(!len);
+
+       meshlink_set_channel_receive_cb(mesh, channel, receive_cb);
+
+       return true;
+}
+
+/* channel receive callback */
+static void receive_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, const void *dat, size_t len) {
+       if(len == 5 && !memcmp(dat, "Hello", 5)) {
+               pthread_mutex_lock(& bar_responded_lock);
+               bar_responded = true;
+               assert(!pthread_cond_broadcast(&send_cond));
+               pthread_mutex_unlock(& bar_responded_lock);
+       }
+}
+
+static void poll_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, size_t len) {
+       (void)len;
+
+       meshlink_set_channel_poll_cb(mesh, channel, NULL);
+       pthread_mutex_lock(&poll_lock);
+       polled = true;
+       assert(!pthread_cond_broadcast(&poll_cond));
+       pthread_mutex_unlock(&poll_lock);
+}
+
+
+/* Test Steps for meshlink_channel_send Test Case # 1*/
+static bool test_steps_mesh_channel_send_01(void) {
+       struct timespec timeout = {0};
+       meshlink_destroy("chan_send_conf.1");
+       meshlink_destroy("chan_send_conf.2");
+
+       // Open two new meshlink instance.
+       meshlink_handle_t *mesh1 = meshlink_open("chan_send_conf.1", "foo", "channels", DEV_CLASS_BACKBONE);
+       assert(mesh1 != NULL);
+       meshlink_handle_t *mesh2 = meshlink_open("chan_send_conf.2", "bar", "channels", DEV_CLASS_BACKBONE);
+       assert(mesh2 != NULL);
+       meshlink_set_log_cb(mesh1, MESHLINK_DEBUG, meshlink_callback_logger);
+       meshlink_set_log_cb(mesh2, MESHLINK_DEBUG, meshlink_callback_logger);
+
+       char *data = meshlink_export(mesh1);
+       assert(data);
+       assert(meshlink_import(mesh2, data));
+       free(data);
+       data = meshlink_export(mesh2);
+       assert(data);
+       assert(meshlink_import(mesh1, data));
+       free(data);
+
+       // Set the callbacks.
+
+       meshlink_set_channel_accept_cb(mesh1, reject_cb);
+       meshlink_set_channel_accept_cb(mesh2, accept_cb);
+
+       meshlink_set_node_status_cb(mesh1, status_cb);
+
+       // Start both instances
+       bar_reachable = false;
+       assert(meshlink_start(mesh1));
+       assert(meshlink_start(mesh2));
+
+       timeout.tv_sec = time(NULL) + 10;
+       pthread_mutex_lock(&bar_reach_lock);
+
+       while(bar_reachable == false) {
+               assert(!pthread_cond_timedwait(&status_cond, &bar_reach_lock, &timeout));
+       }
+
+       pthread_mutex_unlock(&bar_reach_lock);
+
+       // Open a channel from foo to bar.
+
+       meshlink_node_t *bar = meshlink_get_node(mesh1, "bar");
+       assert(bar);
+
+       bar_responded = false;
+       meshlink_channel_t *channel = meshlink_channel_open(mesh1, bar, 7, NULL, NULL, 0);
+       meshlink_set_channel_poll_cb(mesh1, channel, poll_cb);
+
+       timeout.tv_sec = time(NULL) + 10;
+       pthread_mutex_lock(&poll_lock);
+
+       while(polled == false) {
+               assert(!pthread_cond_timedwait(&poll_cond, &poll_lock, &timeout));
+       }
+
+       pthread_mutex_unlock(&poll_lock);
+
+       assert(meshlink_channel_send(mesh1, channel, "Hello", 5) >= 0);
+
+       timeout.tv_sec = time(NULL) + 20;
+       pthread_mutex_lock(&bar_responded_lock);
+
+       if(bar_responded == false) {
+               assert(!pthread_cond_timedwait(&send_cond, &bar_responded_lock, &timeout));
+       }
+
+       pthread_mutex_unlock(&bar_responded_lock);
+
+       // Clean up.
+
+       meshlink_close(mesh2);
+       meshlink_close(mesh1);
+       meshlink_destroy("chan_send_conf.1");
+       meshlink_destroy("chan_send_conf.2");
+
+       return true;
+}
+
+/* Execute meshlink_channel_send Test Case # 2*/
+static void test_case_mesh_channel_send_02(void **state) {
+       execute_test(test_steps_mesh_channel_send_02, state);
+}
+
+/* Test Steps for meshlink_channel_send Test Case # 2*/
+static bool test_steps_mesh_channel_send_02(void) {
+       struct timespec timeout = {0};
+       meshlink_destroy("chan_send_conf.5");
+
+       // Open new meshlink instance.
+
+       meshlink_handle_t *mesh1 = meshlink_open("chan_send_conf.5", "foo", "channels", DEV_CLASS_BACKBONE);
+       assert(mesh1 != NULL);
+
+       meshlink_set_channel_accept_cb(mesh1, accept_cb);
+
+       // Start node instance
+
+       assert(meshlink_start(mesh1));
+
+       meshlink_node_t *node = meshlink_get_self(mesh1);
+       assert(node);
+
+       meshlink_channel_t *channel = meshlink_channel_open(mesh1, node, 7, receive_cb, NULL, 0);
+       meshlink_set_channel_poll_cb(mesh1, channel, poll_cb);
+
+       timeout.tv_sec = time(NULL) + 10;
+       pthread_mutex_lock(&poll_lock);
+
+       while(polled == false) {
+               assert(!pthread_cond_timedwait(&poll_cond, &poll_lock, &timeout));
+       }
+
+       pthread_mutex_unlock(&poll_lock);
+
+       ssize_t send_return = meshlink_channel_send(NULL, channel, "Hello", 5);
+
+       assert_int_equal(send_return, -1);
+
+       // Clean up.
+
+       meshlink_close(mesh1);
+       meshlink_destroy("chan_send_conf.5");
+
+       return true;
+}
+
+/* Execute meshlink_channel_send Test Case # 3*/
+static void test_case_mesh_channel_send_03(void **state) {
+       execute_test(test_steps_mesh_channel_send_03, state);
+}
+
+/* Test Steps for meshlink_channel_send Test Case # 3*/
+static bool test_steps_mesh_channel_send_03(void) {
+       struct timespec timeout = {0};
+       meshlink_destroy("chan_send_conf.7");
+       // Open new meshlink instance.
+
+       meshlink_handle_t *mesh1 = meshlink_open("chan_send_conf.7", "foo", "channels", DEV_CLASS_BACKBONE);
+       assert(mesh1 != NULL);
+       meshlink_set_channel_accept_cb(mesh1, accept_cb);
+
+       // Start node instance
+
+       assert(meshlink_start(mesh1));
+
+       ssize_t send_return = meshlink_channel_send(mesh1, NULL, "Hello", 5);
+
+       assert_int_equal(send_return, -1);
+
+       // Clean up.
+
+       meshlink_close(mesh1);
+       meshlink_destroy("chan_send_conf.7");
+
+       return true;
+}
+
+/* Execute meshlink_channel_send Test Case # 4*/
+static void test_case_mesh_channel_send_04(void **state) {
+       execute_test(test_steps_mesh_channel_send_04, state);
+}
+
+/* Test Steps for meshlink_channel_send Test Case # 4*/
+static bool test_steps_mesh_channel_send_04(void) {
+       struct timespec timeout = {0};
+       meshlink_destroy("chan_send_conf.9");
+       // Open two new meshlink instance.
+
+       meshlink_handle_t *mesh1 = meshlink_open("chan_send_conf.9", "foo", "channels", DEV_CLASS_BACKBONE);
+       assert(mesh1 != NULL);
+
+       meshlink_set_channel_accept_cb(mesh1, accept_cb);
+
+       // Start node instance
+
+       assert(meshlink_start(mesh1));
+
+       meshlink_node_t *node = meshlink_get_self(mesh1);
+       assert(node);
+
+       meshlink_channel_t *channel = meshlink_channel_open(mesh1, node, 7, receive_cb, NULL, 0);
+       meshlink_set_channel_poll_cb(mesh1, channel, poll_cb);
+
+       timeout.tv_sec = time(NULL) + 10;
+       pthread_mutex_lock(&poll_lock);
+
+       while(polled == false) {
+               assert(!pthread_cond_timedwait(&poll_cond, &poll_lock, &timeout));
+       }
+
+       pthread_mutex_unlock(&poll_lock);
+
+       ssize_t send_return = meshlink_channel_send(mesh1, channel, NULL, 5);
+
+       assert_int_equal(send_return, -1);
+
+       // Clean up.
+
+       meshlink_close(mesh1);
+       meshlink_destroy("chan_send_conf.9");
+
+       return true;
+}
+
+int test_meshlink_channel_send(void) {
+       const struct CMUnitTest blackbox_channel_send_tests[] = {
+               cmocka_unit_test_prestate_setup_teardown(test_case_mesh_channel_send_01, NULL, NULL,
+                               (void *)&test_mesh_channel_send_01_state),
+               cmocka_unit_test_prestate_setup_teardown(test_case_mesh_channel_send_02, NULL, NULL,
+                               (void *)&test_mesh_channel_send_02_state),
+               cmocka_unit_test_prestate_setup_teardown(test_case_mesh_channel_send_03, NULL, NULL,
+                               (void *)&test_mesh_channel_send_03_state),
+               cmocka_unit_test_prestate_setup_teardown(test_case_mesh_channel_send_04, NULL, NULL,
+                               (void *)&test_mesh_channel_send_04_state)
+       };
+
+       total_tests += sizeof(blackbox_channel_send_tests) / sizeof(blackbox_channel_send_tests[0]);
+
+       return cmocka_run_group_tests(blackbox_channel_send_tests, NULL, NULL);
+}
diff --git a/test/blackbox/run_blackbox_tests/test_cases_channel_send.h b/test/blackbox/run_blackbox_tests/test_cases_channel_send.h
new file mode 100644 (file)
index 0000000..b9e624f
--- /dev/null
@@ -0,0 +1,31 @@
+#ifndef TEST_CASES_CHANNEL_SEND_H
+#define TEST_CASES_CHANNEL_SEND_H
+
+/*
+    test_cases_channel_send.h -- Declarations for Individual Test Case implementation functions
+    Copyright (C) 2018  Guus Sliepen <guus@meshlink.io>
+
+    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 <stdbool.h>
+
+extern int test_meshlink_channel_send(void);
+extern int total_tests;
+
+
+
+
+#endif
diff --git a/test/blackbox/run_blackbox_tests/test_cases_channel_set_accept_cb.c b/test/blackbox/run_blackbox_tests/test_cases_channel_set_accept_cb.c
new file mode 100644 (file)
index 0000000..77d2c9c
--- /dev/null
@@ -0,0 +1,263 @@
+/*
+    test_cases_channel_set_accept_cb.c -- Execution of specific meshlink black box test cases
+    Copyright (C) 2018  Guus Sliepen <guus@meshlink.io>
+
+    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 "execute_tests.h"
+#include "../common/containers.h"
+#include "../common/test_step.h"
+#include "../common/common_handlers.h"
+#include "test_cases_channel_set_accept_cb.h"
+#include <assert.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <setjmp.h>
+#include <cmocka.h>
+#include <pthread.h>
+
+/* Modify this to change the logging level of Meshlink */
+#define TEST_MESHLINK_LOG_LEVEL MESHLINK_DEBUG
+/* Modify this to change the port number */
+#define PORT 8000
+
+static void test_case_set_channel_accept_cb_01(void **state);
+static bool test_steps_set_channel_accept_cb_01(void);
+static void test_case_set_channel_accept_cb_02(void **state);
+static bool test_steps_set_channel_accept_cb_02(void);
+
+static bool channel_accept(meshlink_handle_t *mesh, meshlink_channel_t *channel, uint16_t port, const void *data, size_t len);
+static bool channel_reject(meshlink_handle_t *mesh, meshlink_channel_t *channel, uint16_t port, const void *data, size_t len);
+
+static bool channel_acc;
+static bool channel_rej;
+static bool polled;
+static bool rejected;
+
+/* mutex for the common variable */
+static pthread_mutex_t accept_lock = PTHREAD_MUTEX_INITIALIZER;
+static pthread_mutex_t reject_lock = PTHREAD_MUTEX_INITIALIZER;
+static pthread_mutex_t poll_lock = PTHREAD_MUTEX_INITIALIZER;
+static pthread_mutex_t lock_receive = PTHREAD_MUTEX_INITIALIZER;
+
+static pthread_cond_t accept_cond = PTHREAD_COND_INITIALIZER;
+static pthread_cond_t reject_cond = PTHREAD_COND_INITIALIZER;
+static pthread_cond_t poll_cond = PTHREAD_COND_INITIALIZER;
+static pthread_cond_t receive_cond = PTHREAD_COND_INITIALIZER;
+
+static black_box_state_t test_case_channel_set_accept_cb_01_state = {
+       .test_case_name = "test_case_channel_set_accept_cb_01",
+};
+static black_box_state_t test_case_channel_set_accept_cb_02_state = {
+       .test_case_name = "test_case_channel_set_accept_cb_02",
+};
+
+/* channel receive callback */
+static void channel_receive_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, const void *dat, size_t len) {
+       if(!len) {
+               if(!meshlink_errno) {
+                       pthread_mutex_lock(& lock_receive);
+                       rejected = true;
+                       assert(!pthread_cond_broadcast(&receive_cond));
+                       pthread_mutex_unlock(& lock_receive);
+               }
+       }
+}
+
+/* channel reject callback */
+static bool channel_reject(meshlink_handle_t *mesh, meshlink_channel_t *channel, uint16_t port, const void *data, size_t len) {
+       (void)mesh;
+       (void)channel;
+       (void)port;
+       (void)data;
+       (void)len;
+       return false;
+}
+
+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;
+       char *data = (char *) dat;
+       assert_int_equal(port, PORT);
+
+       pthread_mutex_lock(&accept_lock);
+       channel_acc = true;
+       assert(!pthread_cond_broadcast(&accept_cond));
+       pthread_mutex_unlock(&accept_lock);
+
+       return true;
+}
+
+static void poll_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, size_t len) {
+       (void)len;
+       meshlink_set_channel_poll_cb(mesh, channel, NULL);
+       pthread_mutex_lock(&poll_lock);
+       polled = true;
+       assert(!pthread_cond_broadcast(&poll_cond));
+       pthread_mutex_unlock(&poll_lock);
+}
+
+/* Execute meshlink_channel_set_accept_cb Test Case # 1 - Valid case*/
+static void test_case_set_channel_accept_cb_01(void **state) {
+       execute_test(test_steps_set_channel_accept_cb_01, state);
+}
+/* Test Steps for meshlink_channel_set_accept_cb Test Case # 1 - Valid case
+
+    Test Steps:
+    1. Open NUT(Node Under Test) & bar meshes.
+    2. Set channel_accept callback for NUT's meshlink_set_channel_accept_cb API.
+    3. Export and Import nodes.
+    4. Open a channel with NUT from bar to invoke channel accept callback
+    5. Open a channel with bar from NUT to invoke channel accept callback
+
+    Expected Result:
+    Opens a channel by invoking accept callback, when accept callback rejects the channel
+    it should invoke the other node's receive callback with length = 0 and no error.
+*/
+static bool test_steps_set_channel_accept_cb_01(void) {
+       /* deleting the confbase if already exists */
+       struct timespec timeout = {0};
+       meshlink_destroy("acceptconf1");
+       meshlink_destroy("acceptconf2");
+       meshlink_set_log_cb(NULL, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
+
+       /* Create meshlink instances */
+       meshlink_handle_t *mesh1 = meshlink_open("acceptconf1", "nut", "chat", DEV_CLASS_STATIONARY);
+       assert(mesh1 != NULL);
+       meshlink_handle_t *mesh2 = meshlink_open("acceptconf2", "bar", "chat", DEV_CLASS_STATIONARY);
+       assert(mesh2 != NULL);
+       meshlink_set_log_cb(mesh1, MESHLINK_INFO, meshlink_callback_logger);
+       meshlink_set_log_cb(mesh2, MESHLINK_INFO, meshlink_callback_logger);
+
+       meshlink_set_channel_accept_cb(mesh2, channel_reject);
+       meshlink_set_channel_accept_cb(mesh1, channel_accept);
+
+       /* Export and Import on both sides */
+       char *exp1 = meshlink_export(mesh1);
+       assert(exp1 != NULL);
+       char *exp2 = meshlink_export(mesh2);
+       assert(exp2 != NULL);
+       assert(meshlink_import(mesh1, exp2));
+       assert(meshlink_import(mesh2, exp1));
+
+       assert(meshlink_start(mesh1));
+       assert(meshlink_start(mesh2));
+       sleep(1);
+
+       meshlink_node_t *destination = meshlink_get_node(mesh2, "nut");
+       assert(destination != NULL);
+
+       /* Open channel for nut node from bar node which should be accepted */
+       polled = false;
+       channel_acc = false;
+       meshlink_channel_t *channel2 = meshlink_channel_open(mesh2, destination, PORT, NULL, NULL, 0);
+       assert(channel2);
+       meshlink_set_channel_poll_cb(mesh2, channel2, poll_cb);
+
+       timeout.tv_sec = time(NULL) + 10;
+       pthread_mutex_lock(&poll_lock);
+
+       while(polled == false) {
+               assert(!pthread_cond_timedwait(&poll_cond, &poll_lock, &timeout));
+       }
+
+       pthread_mutex_unlock(&poll_lock);
+
+       timeout.tv_sec = time(NULL) + 10;
+       pthread_mutex_lock(&accept_lock);
+
+       while(channel_acc == false) {
+               assert(!pthread_cond_timedwait(&accept_cond, &accept_lock, &timeout));
+       }
+
+       pthread_mutex_unlock(&accept_lock);
+
+       /* Open channel for bar node from nut node which should be rejected */
+       polled = false;
+       rejected = false;
+       channel_acc = false;
+       destination = meshlink_get_node(mesh1, "bar");
+       assert(destination != NULL);
+
+       meshlink_channel_t *channel1 = meshlink_channel_open(mesh1, destination, PORT, channel_receive_cb, NULL, 0);
+       assert(channel1);
+       meshlink_set_channel_poll_cb(mesh1, channel1, poll_cb);
+
+       timeout.tv_sec = time(NULL) + 10;
+       pthread_mutex_lock(&poll_lock);
+
+       while(polled == false) {
+               assert(!pthread_cond_timedwait(&poll_cond, &poll_lock, &timeout));
+       }
+
+       pthread_mutex_unlock(&poll_lock);
+
+       timeout.tv_sec = time(NULL) + 10;
+       pthread_mutex_lock(&lock_receive);
+
+       while(rejected == false) {
+               assert(!pthread_cond_timedwait(&receive_cond, &lock_receive, &timeout));
+       }
+
+       pthread_mutex_unlock(&lock_receive);
+
+       /* closing channel, meshes and destroying confbase */
+       meshlink_close(mesh1);
+       meshlink_close(mesh2);
+       meshlink_destroy("acceptconf1");
+       meshlink_destroy("acceptconf2");
+
+       return true;
+}
+
+/* Execute meshlink_channel_set_accept_cb Test Case # 2 - Invalid case*/
+static void test_case_set_channel_accept_cb_02(void **state) {
+       execute_test(test_steps_set_channel_accept_cb_02, state);
+}
+/* Test Steps for meshlink_channel_set_accept_cb Test Case # 2 - Invalid case
+
+    Test Steps:
+    1. Passing NULL as mesh handle argument for channel accept callback.
+
+    Expected Result:
+    meshlink_channel_set_accept_cb returning proper meshlink_errno.
+*/
+static bool test_steps_set_channel_accept_cb_02(void) {
+       /* setting channel accept cb with NULL as mesh handle and valid callback */
+       meshlink_set_channel_accept_cb(NULL, channel_accept);
+       assert_int_equal(meshlink_errno, MESHLINK_EINVAL);
+
+       return true;
+}
+
+
+int test_meshlink_set_channel_accept_cb(void) {
+       const struct CMUnitTest blackbox_channel_set_accept_cb_tests[] = {
+               cmocka_unit_test_prestate_setup_teardown(test_case_set_channel_accept_cb_01, NULL, NULL,
+                               (void *)&test_case_channel_set_accept_cb_01_state),
+               cmocka_unit_test_prestate_setup_teardown(test_case_set_channel_accept_cb_02, NULL, NULL,
+                               (void *)&test_case_channel_set_accept_cb_02_state)
+       };
+
+       total_tests += sizeof(blackbox_channel_set_accept_cb_tests) / sizeof(blackbox_channel_set_accept_cb_tests[0]);
+
+       int failed = cmocka_run_group_tests(blackbox_channel_set_accept_cb_tests, NULL, NULL);
+
+       return failed;
+}
+
+
+
diff --git a/test/blackbox/run_blackbox_tests/test_cases_channel_set_accept_cb.h b/test/blackbox/run_blackbox_tests/test_cases_channel_set_accept_cb.h
new file mode 100644 (file)
index 0000000..9d91d59
--- /dev/null
@@ -0,0 +1,28 @@
+#ifndef TEST_CASES_CHANNELS_SET_ACCEPT_CB_H
+#define TEST_CASES_CHANNELS_SET_ACCEPT_CB_H
+
+/*
+    test_cases_channel_set_accept_cb.h -- Declarations for Individual Test Case implementation functions
+    Copyright (C) 2018  Guus Sliepen <guus@meshlink.io>
+
+    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 <stdbool.h>
+
+extern int total_tests;
+extern int test_meshlink_set_channel_accept_cb(void);
+
+#endif
diff --git a/test/blackbox/run_blackbox_tests/test_cases_channel_set_poll_cb.c b/test/blackbox/run_blackbox_tests/test_cases_channel_set_poll_cb.c
new file mode 100644 (file)
index 0000000..2234c39
--- /dev/null
@@ -0,0 +1,253 @@
+/*
+    test_cases_channel_set_poll_cb.c -- Execution of specific meshlink black box test cases
+    Copyright (C) 2018  Guus Sliepen <guus@meshlink.io>
+
+    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 "execute_tests.h"
+#include "test_cases_channel_set_poll_cb.h"
+#include "../common/containers.h"
+#include "../common/test_step.h"
+#include "../common/common_handlers.h"
+#include <assert.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <setjmp.h>
+#include <cmocka.h>
+#include <pthread.h>
+
+/* Modify this to change the logging level of Meshlink */
+#define TEST_MESHLINK_LOG_LEVEL MESHLINK_DEBUG
+/* Modify this to change the port number */
+#define PORT 8000
+
+static void test_case_channel_set_poll_cb_01(void **state);
+static bool test_steps_channel_set_poll_cb_01(void);
+static void test_case_channel_set_poll_cb_02(void **state);
+static bool test_steps_channel_set_poll_cb_02(void);
+static void test_case_channel_set_poll_cb_03(void **state);
+static bool test_steps_channel_set_poll_cb_03(void);
+static void poll_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, size_t len);
+
+static black_box_state_t test_case_channel_set_poll_cb_01_state = {
+       .test_case_name = "test_case_channel_set_poll_cb_01",
+};
+static black_box_state_t test_case_channel_set_poll_cb_02_state = {
+       .test_case_name = "test_case_channel_set_poll_cb_02",
+};
+static black_box_state_t test_case_channel_set_poll_cb_03_state = {
+       .test_case_name = "test_case_channel_set_poll_cb_03",
+};
+
+static bool polled;
+static bool reachable;
+
+static pthread_mutex_t poll_lock = PTHREAD_MUTEX_INITIALIZER;
+static pthread_cond_t poll_cond = PTHREAD_COND_INITIALIZER;
+static pthread_mutex_t reachable_lock = PTHREAD_MUTEX_INITIALIZER;
+static pthread_cond_t reachable_cond = PTHREAD_COND_INITIALIZER;
+
+/* channel accept callback */
+static bool channel_accept_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, uint16_t port, const void *data, size_t len) {
+       (void)mesh;
+       (void)channel;
+       (void)port;
+       (void)data;
+       (void)len;
+       return false;
+}
+
+static void poll_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, size_t len) {
+       (void)len;
+       meshlink_set_channel_poll_cb(mesh, channel, NULL);
+       pthread_mutex_lock(&poll_lock);
+       polled = true;
+       assert(!pthread_cond_broadcast(&poll_cond));
+       pthread_mutex_unlock(&poll_lock);
+}
+
+static void node_status_cb(meshlink_handle_t *mesh, meshlink_node_t *source, bool reach) {
+       pthread_mutex_lock(&reachable_lock);
+       reachable = true;
+       assert(!pthread_cond_broadcast(&reachable_cond));
+       pthread_mutex_unlock(&reachable_lock);
+}
+
+/* Execute meshlink_channel_set_poll_cb Test Case # 1 */
+static void test_case_channel_set_poll_cb_01(void **state) {
+       execute_test(test_steps_channel_set_poll_cb_01, state);
+}
+/* Test Steps for meshlink_channel_set_poll_cb Test Case # 1
+
+    Test Steps:
+    1. Run NUT
+    2. Open channel of the NUT itself
+
+    Expected Result:
+    Opens a channel and also invokes poll callback.
+*/
+static bool test_steps_channel_set_poll_cb_01(void) {
+       /* deleting the confbase if already exists */
+       struct timespec timeout = {0};
+       meshlink_destroy("pollconf1");
+       meshlink_destroy("pollconf2");
+       meshlink_set_log_cb(NULL, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
+
+       /* Create meshlink instances */
+       meshlink_handle_t *mesh1 = meshlink_open("pollconf1", "nut", "chat", DEV_CLASS_STATIONARY);
+       assert(mesh1 != NULL);
+       meshlink_handle_t *mesh2 = meshlink_open("pollconf2", "bar", "chat", DEV_CLASS_STATIONARY);
+       assert(mesh2 != NULL);
+       meshlink_set_log_cb(mesh1, MESHLINK_INFO, meshlink_callback_logger);
+       meshlink_set_log_cb(mesh2, MESHLINK_INFO, meshlink_callback_logger);
+       meshlink_set_node_status_cb(mesh1, node_status_cb);
+       meshlink_set_channel_accept_cb(mesh1, channel_accept_cb);
+
+       /* Export and Import on both sides */
+       reachable = false;
+       char *exp1 = meshlink_export(mesh1);
+       assert(exp1 != NULL);
+       char *exp2 = meshlink_export(mesh2);
+       assert(exp2 != NULL);
+       assert(meshlink_import(mesh1, exp2));
+       assert(meshlink_import(mesh2, exp1));
+
+       assert(meshlink_start(mesh1));
+       assert(meshlink_start(mesh2));
+
+       timeout.tv_sec = time(NULL) + 10;
+       pthread_mutex_lock(&reachable_lock);
+
+       while(reachable == false) {
+               assert(!pthread_cond_timedwait(&reachable_cond, &reachable_lock, &timeout));
+       }
+
+       pthread_mutex_unlock(&reachable_lock);
+
+       meshlink_node_t *destination = meshlink_get_node(mesh2, "nut");
+       assert(destination != NULL);
+
+       /* Open channel for nut node from bar node which should be accepted */
+       polled = false;
+       meshlink_channel_t *channel = meshlink_channel_open(mesh2, destination, PORT, NULL, NULL, 0);
+       assert(channel);
+       meshlink_set_channel_poll_cb(mesh2, channel, poll_cb);
+
+       timeout.tv_sec = time(NULL) + 10;
+       pthread_mutex_lock(&poll_lock);
+
+       while(polled == false) {
+               assert(!pthread_cond_timedwait(&poll_cond, &poll_lock, &timeout));
+       }
+
+       pthread_mutex_unlock(&poll_lock);
+
+       /* closing channel, meshes and destroying confbase */
+       meshlink_close(mesh1);
+       meshlink_close(mesh2);
+       meshlink_destroy("pollconf1");
+       meshlink_destroy("pollconf2");
+
+       return true;
+}
+
+/* Execute meshlink_channel_set_poll_cb Test Case # 2 */
+static void test_case_channel_set_poll_cb_02(void **state) {
+       execute_test(test_steps_channel_set_poll_cb_02, state);
+}
+/* Test Steps for meshlink_channel_set_poll_cb Test Case # 2
+
+    Test Steps:
+    1. Run NUT
+    2. Open channel of the NUT itself
+    3. Pass NULL as mesh handle argument for meshlink_set_channel_poll_cb API
+
+    Expected Result:
+    Reports error accordingly by returning NULL
+*/
+static bool test_steps_channel_set_poll_cb_02(void) {
+       meshlink_set_log_cb(NULL, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
+
+       /* Create meshlink instance */
+       meshlink_handle_t *mesh_handle = meshlink_open("channelpollconf3", "nut", "node_sim", 1);
+       assert(mesh_handle);
+       meshlink_set_log_cb(mesh_handle, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
+
+       assert(meshlink_start(mesh_handle));
+
+       meshlink_node_t *node = meshlink_get_self(mesh_handle);
+       assert(node != NULL);
+
+       /* Opening channel */
+       meshlink_channel_t *channel = meshlink_channel_open(mesh_handle, node, PORT, NULL, NULL, 0);
+       assert(channel != NULL);
+
+       /* Setting poll cb with NULL as mesh handler */
+       meshlink_set_channel_poll_cb(NULL, channel, poll_cb);
+       assert_int_equal(meshlink_errno, MESHLINK_EINVAL);
+
+       meshlink_close(mesh_handle);
+       meshlink_destroy("channelpollconf3");
+       return true;
+}
+
+/* Execute meshlink_channel_set_poll_cb Test Case # 3 */
+static void test_case_channel_set_poll_cb_03(void **state) {
+       execute_test(test_steps_channel_set_poll_cb_03, state);
+}
+/* Test Steps for meshlink_channel_set_poll_cb Test Case # 3
+
+    Test Steps:
+    1. Run NUT
+    2. Open channel of the NUT itself
+    3. Pass NULL as channel handle argument for meshlink_set_channel_poll_cb API
+
+    Expected Result:
+    Reports error accordingly by returning NULL
+*/
+static bool test_steps_channel_set_poll_cb_03(void) {
+       meshlink_set_log_cb(NULL, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
+
+       /* Create meshlink instance */
+       meshlink_handle_t *mesh_handle = meshlink_open("channelpollconf4", "nut", "node_sim", 1);
+       assert(mesh_handle);
+       meshlink_set_log_cb(mesh_handle, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
+
+       assert(meshlink_start(mesh_handle));
+
+       /* Setting poll cb with NULL as channel handler */
+       meshlink_set_channel_poll_cb(mesh_handle, NULL, poll_cb);
+       assert_int_equal(meshlink_errno, MESHLINK_EINVAL);
+
+       meshlink_close(mesh_handle);
+       meshlink_destroy("channelpollconf4");
+       return true;
+}
+
+
+int test_meshlink_set_channel_poll_cb(void) {
+       const struct CMUnitTest blackbox_channel_set_poll_cb_tests[] = {
+               cmocka_unit_test_prestate_setup_teardown(test_case_channel_set_poll_cb_01, NULL, NULL,
+                               (void *)&test_case_channel_set_poll_cb_01_state),
+               cmocka_unit_test_prestate_setup_teardown(test_case_channel_set_poll_cb_02, NULL, NULL,
+                               (void *)&test_case_channel_set_poll_cb_02_state),
+               cmocka_unit_test_prestate_setup_teardown(test_case_channel_set_poll_cb_03, NULL, NULL,
+                               (void *)&test_case_channel_set_poll_cb_03_state)
+       };
+       total_tests += sizeof(blackbox_channel_set_poll_cb_tests) / sizeof(blackbox_channel_set_poll_cb_tests[0]);
+
+       return cmocka_run_group_tests(blackbox_channel_set_poll_cb_tests, NULL, NULL);
+}
diff --git a/test/blackbox/run_blackbox_tests/test_cases_channel_set_poll_cb.h b/test/blackbox/run_blackbox_tests/test_cases_channel_set_poll_cb.h
new file mode 100644 (file)
index 0000000..71796e2
--- /dev/null
@@ -0,0 +1,28 @@
+#ifndef TEST_CASES_SET_POLL_CB_H
+#define TEST_CASES_SET_POLL_CB_H
+
+/*
+    test_cases_set_poll_cb.h -- Declarations for Individual Test Case implementation functions
+    Copyright (C) 2018  Guus Sliepen <guus@meshlink.io>
+
+    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 <stdbool.h>
+
+extern int test_meshlink_set_channel_poll_cb(void);
+extern int total_tests;
+
+#endif
diff --git a/test/blackbox/run_blackbox_tests/test_cases_channel_set_receive_cb.c b/test/blackbox/run_blackbox_tests/test_cases_channel_set_receive_cb.c
new file mode 100644 (file)
index 0000000..d185442
--- /dev/null
@@ -0,0 +1,253 @@
+/*
+    test_cases_channel_set_receive_cb.c -- Execution of specific meshlink black box test cases
+    Copyright (C) 2018  Guus Sliepen <guus@meshlink.io>
+
+    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 "execute_tests.h"
+#include "../common/containers.h"
+#include "../common/test_step.h"
+#include "../common/common_handlers.h"
+#include "test_cases_channel_set_receive_cb.h"
+#include <assert.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <setjmp.h>
+#include <cmocka.h>
+#include <pthread.h>
+#include <errno.h>
+
+/* Modify this to change the logging level of Meshlink */
+#define TEST_MESHLINK_LOG_LEVEL MESHLINK_DEBUG
+
+/* Modify this to change the port number */
+#define PORT 8000
+
+/* Modify this to change the channel receive callback access buffer */
+#define TCP_TEST 8000
+
+static void test_case_set_channel_receive_cb_01(void **state);
+static bool test_steps_set_channel_receive_cb_01(void);
+static void test_case_set_channel_receive_cb_02(void **state);
+static bool test_steps_set_channel_receive_cb_02(void);
+static void test_case_set_channel_receive_cb_03(void **state);
+static bool test_steps_set_channel_receive_cb_03(void);
+static void test_case_set_channel_receive_cb_04(void **state);
+static bool test_steps_set_channel_receive_cb_04(void);
+
+static void channel_poll(meshlink_handle_t *mesh, meshlink_channel_t *channel, size_t len);
+static bool channel_accept(meshlink_handle_t *mesh, meshlink_channel_t *channel, uint16_t port, const void *data, size_t len);
+
+static bool rec_stat = false;
+static bool accept_stat = false;
+
+/* mutex for the receive callback common resources */
+static pthread_mutex_t lock_accept = PTHREAD_MUTEX_INITIALIZER;
+static pthread_mutex_t lock_receive = PTHREAD_MUTEX_INITIALIZER;
+static pthread_cond_t accept_cond = PTHREAD_COND_INITIALIZER;
+static pthread_cond_t receive_cond = PTHREAD_COND_INITIALIZER;
+
+static black_box_state_t test_case_channel_set_receive_cb_01_state = {
+       .test_case_name = "test_case_channel_set_receive_cb_01",
+};
+static black_box_state_t test_case_channel_set_receive_cb_02_state = {
+       .test_case_name = "test_case_channel_set_receive_cb_02",
+};
+static black_box_state_t test_case_channel_set_receive_cb_03_state = {
+       .test_case_name = "test_case_channel_set_receive_cb_03",
+};
+static black_box_state_t test_case_channel_set_receive_cb_04_state = {
+       .test_case_name = "test_case_channel_set_receive_cb_04",
+};
+
+/* channel receive callback */
+static void channel_receive_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, const void *dat, size_t len) {
+       pthread_mutex_lock(& lock_receive);
+       rec_stat = true;
+       assert(!pthread_cond_broadcast(&receive_cond));
+       pthread_mutex_unlock(& lock_receive);
+}
+
+static bool accept_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, uint16_t port, const void *data, size_t len) {
+       meshlink_set_channel_receive_cb(mesh, channel, channel_receive_cb);
+
+       pthread_mutex_lock(& lock_accept);
+       accept_stat = true;
+       assert(!pthread_cond_broadcast(&accept_cond));
+       pthread_mutex_unlock(& lock_accept);
+
+       return true;
+}
+
+static void poll_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, size_t len) {
+       (void)len;
+
+       meshlink_set_channel_poll_cb(mesh, channel, NULL);
+       assert(meshlink_channel_send(mesh, channel, "Hello", 5) >= 0);
+}
+
+/* Execute meshlink_channel_set_receive_cb Test Case # 1 */
+static void test_case_set_channel_receive_cb_01(void **state) {
+       execute_test(test_steps_set_channel_receive_cb_01, state);
+}
+/* Test Steps for meshlink_channel_set_receive_cb Test Case # 1 - Valid case
+
+    Test Steps:
+    1. Run NUT and Open channel for itself.
+    2. Set channel receive callback and send data.
+
+    Expected Result:
+    Opens a channel by invoking channel receive callback when data sent to it.
+*/
+static bool test_steps_set_channel_receive_cb_01(void) {
+       struct timespec timeout = {0};
+       meshlink_destroy("channelreceiveconf");
+       meshlink_set_log_cb(NULL, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
+
+       /* Create meshlink instance */
+       meshlink_handle_t *mesh_handle = meshlink_open("channelreceiveconf", "nut", "node_sim", 1);
+       assert(mesh_handle != NULL);
+       meshlink_set_log_cb(mesh_handle, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
+       meshlink_set_channel_accept_cb(mesh_handle, accept_cb);
+
+       assert(meshlink_start(mesh_handle));
+
+       meshlink_node_t *node = meshlink_get_self(mesh_handle);
+       assert(node != NULL);
+
+       rec_stat = false;
+       accept_stat = false;
+       meshlink_channel_t *channel = meshlink_channel_open(mesh_handle, node, 8000, NULL, NULL, 0);
+       meshlink_set_channel_poll_cb(mesh_handle, channel, poll_cb);
+
+       timeout.tv_sec = time(NULL) + 20;
+       pthread_mutex_lock(& lock_accept);
+
+       while(accept_stat == false) {
+               assert(!pthread_cond_timedwait(&accept_cond, &lock_accept, &timeout));
+       }
+
+       pthread_mutex_unlock(& lock_accept);
+
+       timeout.tv_sec = time(NULL) + 20;
+       pthread_mutex_lock(& lock_receive);
+
+       while(rec_stat == false) {
+               assert(pthread_cond_timedwait(&receive_cond, &lock_receive, &timeout) == 0);
+       }
+
+       pthread_mutex_unlock(& lock_receive);
+
+       meshlink_close(mesh_handle);
+       meshlink_destroy("channelreceiveconf");
+
+       return true;
+}
+
+/* Execute meshlink_channel_set_receive_cb Test Case # 2 */
+static void test_case_set_channel_receive_cb_02(void **state) {
+       execute_test(test_steps_set_channel_receive_cb_02, state);
+}
+/* Test Steps for meshlink_channel_set_receive_cb Test Case # 2 - Invalid case
+
+    Test Steps:
+    1. Run NUT and Open channel for itself.
+    2. Set channel receive callback with NULL as mesh handle.
+
+    Expected Result:
+    meshlink_channel_set_receive_cb returning proper meshlink_errno.
+*/
+static bool test_steps_set_channel_receive_cb_02(void) {
+       meshlink_destroy("channelreceiveconf");
+       meshlink_set_log_cb(NULL, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
+
+       /* Create meshlink instance */
+       meshlink_handle_t *mesh_handle = meshlink_open("channelreceiveconf", "nut", "node_sim", 1);
+       assert(mesh_handle != NULL);
+       meshlink_set_log_cb(mesh_handle, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
+       meshlink_set_channel_accept_cb(mesh_handle, accept_cb);
+
+       /* Starting NUT */
+       assert(meshlink_start(mesh_handle));
+       meshlink_node_t *node = meshlink_get_self(mesh_handle);
+       assert(node != NULL);
+
+       meshlink_channel_t *channel = meshlink_channel_open_ex(mesh_handle, node, 8000, NULL, NULL, 0, MESHLINK_CHANNEL_UDP);
+       assert(channel != NULL);
+       meshlink_set_channel_poll_cb(mesh_handle, channel, poll_cb);
+
+       /* Setting channel for NUT using meshlink_set_channel_receive_cb API with NULL as mesh handle */
+       meshlink_set_channel_receive_cb(NULL, channel, channel_receive_cb);
+       assert_int_equal(meshlink_errno, MESHLINK_EINVAL);
+
+       meshlink_close(mesh_handle);
+       meshlink_destroy("channelreceiveconf");
+
+       return true;
+}
+
+/* Execute meshlink_channel_set_receive_cb Test Case # 3 */
+static void test_case_set_channel_receive_cb_03(void **state) {
+       execute_test(test_steps_set_channel_receive_cb_03, state);
+}
+/* Test Steps for meshlink_channel_set_receive_cb Test Case # 3 - Invalid case
+
+    Test Steps:
+    1. Run NUT and Open channel for itself.
+    2. Set channel receive callback with NULL as channel handle.
+
+    Expected Result:
+    meshlink_channel_set_receive_cb returning proper meshlink_errno.
+*/
+static bool test_steps_set_channel_receive_cb_03(void) {
+       meshlink_destroy("channelreceiveconf");
+       meshlink_set_log_cb(NULL, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
+
+       /* Create meshlink instance */
+       meshlink_handle_t *mesh_handle = meshlink_open("channelreceiveconf", "nut", "node_sim", 1);
+       fprintf(stderr, "meshlink_open status: %s\n", meshlink_strerror(meshlink_errno));
+       assert(mesh_handle != NULL);
+       meshlink_set_log_cb(mesh_handle, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
+       meshlink_set_channel_accept_cb(mesh_handle, accept_cb);
+
+       /* Starting NUT */
+       assert(meshlink_start(mesh_handle));
+
+       /* Setting channel for NUT using meshlink_set_channel_receive_cb API channel handle as NULL */
+       meshlink_set_channel_receive_cb(mesh_handle, NULL, channel_receive_cb);
+
+       assert_int_equal(meshlink_errno, MESHLINK_EINVAL);
+       meshlink_close(mesh_handle);
+       meshlink_destroy("channelreceiveconf");
+       return true;
+}
+
+
+int test_meshlink_set_channel_receive_cb(void) {
+       const struct CMUnitTest blackbox_channel_set_receive_cb_tests[] = {
+               cmocka_unit_test_prestate_setup_teardown(test_case_set_channel_receive_cb_01, NULL, NULL,
+                               (void *)&test_case_channel_set_receive_cb_01_state),
+               cmocka_unit_test_prestate_setup_teardown(test_case_set_channel_receive_cb_02, NULL, NULL,
+                               (void *)&test_case_channel_set_receive_cb_02_state),
+               cmocka_unit_test_prestate_setup_teardown(test_case_set_channel_receive_cb_03, NULL, NULL,
+                               (void *)&test_case_channel_set_receive_cb_03_state)
+       };
+       total_tests += sizeof(blackbox_channel_set_receive_cb_tests) / sizeof(blackbox_channel_set_receive_cb_tests[0]);
+
+       int failed = cmocka_run_group_tests(blackbox_channel_set_receive_cb_tests, NULL, NULL);
+
+       return failed;
+}
diff --git a/test/blackbox/run_blackbox_tests/test_cases_channel_set_receive_cb.h b/test/blackbox/run_blackbox_tests/test_cases_channel_set_receive_cb.h
new file mode 100644 (file)
index 0000000..e781f8c
--- /dev/null
@@ -0,0 +1,28 @@
+#ifndef TEST_CASES_CHANNELS_SET_RECEIVE_H
+#define TEST_CASES_CHANNELS_SET_RECEIVE_H
+
+/*
+    test_cases_channel_set_receive_cb.h -- Declarations for Individual Test Case implementation functions
+    Copyright (C) 2018  Guus Sliepen <guus@meshlink.io>
+
+    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 <stdbool.h>
+
+extern int test_meshlink_set_channel_receive_cb(void);
+extern int total_tests;
+
+#endif
diff --git a/test/blackbox/run_blackbox_tests/test_cases_channel_shutdown.c b/test/blackbox/run_blackbox_tests/test_cases_channel_shutdown.c
new file mode 100644 (file)
index 0000000..f17266f
--- /dev/null
@@ -0,0 +1,356 @@
+/*
+    test_cases_channel_shutdown.c -- Execution of specific meshlink black box test cases
+    Copyright (C) 2018  Guus Sliepen <guus@meshlink.io>
+
+    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 "execute_tests.h"
+#include "test_cases_channel_shutdown.h"
+#include "../common/containers.h"
+#include "../common/test_step.h"
+#include "../common/common_handlers.h"
+#include <assert.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <setjmp.h>
+#include <cmocka.h>
+#include <pthread.h>
+
+/* Modify this to change the logging level of Meshlink */
+#define TEST_MESHLINK_LOG_LEVEL MESHLINK_DEBUG
+
+static void test_case_mesh_channel_shutdown_01(void **state);
+static bool test_steps_mesh_channel_shutdown_01(void);
+static void test_case_mesh_channel_shutdown_02(void **state);
+static bool test_steps_mesh_channel_shutdown_02(void);
+static void test_case_mesh_channel_shutdown_03(void **state);
+static bool test_steps_mesh_channel_shutdown_03(void);
+static void test_case_mesh_channel_shutdown_04(void **state);
+static bool test_steps_mesh_channel_shutdown_04(void);
+static void test_case_mesh_channel_shutdown_05(void **state);
+static bool test_steps_mesh_channel_shutdown_05(void);
+
+static void receive_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, const void *dat, size_t len);
+static void status_cb(meshlink_handle_t *mesh, meshlink_node_t *node, bool reachable);
+static void poll_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, size_t len);
+
+/* State structure for meshlink_channel_shutdown Test Case #1 */
+static black_box_state_t test_mesh_channel_shutdown_01_state = {
+       .test_case_name = "test_case_mesh_channel_shutdown_01",
+};
+
+/* State structure for meshlink_channel_shutdown Test Case #2 */
+static black_box_state_t test_mesh_channel_shutdown_02_state = {
+       .test_case_name = "test_case_mesh_channel_shutdown_02",
+};
+
+/* State structure for meshlink_channel_shutdown Test Case #3 */
+static black_box_state_t test_mesh_channel_shutdown_03_state = {
+       .test_case_name = "test_case_mesh_channel_shutdown_03",
+};
+
+/* State structure for meshlink_channel_shutdown Test Case #4 */
+static black_box_state_t test_mesh_channel_shutdown_04_state = {
+       .test_case_name = "test_case_mesh_channel_shutdown_04",
+};
+
+/* State structure for meshlink_channel_shutdown Test Case #5 */
+static black_box_state_t test_mesh_channel_shutdown_05_state = {
+       .test_case_name = "test_case_mesh_channel_shutdown_05",
+};
+
+static bool channel_acc;
+static bool polled;
+static bool foo_responded;
+static bool bar_responded;
+
+/* mutex for the common variable */
+static pthread_mutex_t accept_lock = PTHREAD_MUTEX_INITIALIZER;
+static pthread_mutex_t poll_lock = PTHREAD_MUTEX_INITIALIZER;
+static pthread_mutex_t bar_responded_lock = PTHREAD_MUTEX_INITIALIZER;
+static pthread_mutex_t foo_responded_lock = PTHREAD_MUTEX_INITIALIZER;
+
+static pthread_cond_t accept_cond = PTHREAD_COND_INITIALIZER;
+static pthread_cond_t poll_cond = PTHREAD_COND_INITIALIZER;
+static pthread_cond_t foo_cond = PTHREAD_COND_INITIALIZER;
+static pthread_cond_t bar_cond = PTHREAD_COND_INITIALIZER;
+
+static bool accept_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, uint16_t port, const void *data, size_t len) {
+       assert(port == 7);
+       assert(!len);
+
+       meshlink_set_channel_receive_cb(mesh, channel, receive_cb);
+       channel->node->priv = channel;
+       pthread_mutex_lock(&accept_lock);
+       channel_acc = true;
+       assert(!pthread_cond_broadcast(&accept_cond));
+       pthread_mutex_unlock(&accept_lock);
+
+       return true;
+}
+
+/* channel receive callback */
+static void receive_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, const void *dat, size_t len) {
+       if(!strcmp(mesh->name, "foo")) {
+               pthread_mutex_lock(& foo_responded_lock);
+               foo_responded = true;
+               assert(!pthread_cond_broadcast(&foo_cond));
+               pthread_mutex_unlock(& foo_responded_lock);
+
+       } else if(!strcmp(mesh->name, "bar")) {
+               pthread_mutex_lock(& bar_responded_lock);
+               bar_responded = true;
+               assert(!pthread_cond_broadcast(&bar_cond));
+               pthread_mutex_unlock(& bar_responded_lock);
+
+               assert(meshlink_channel_send(mesh, channel, "echo", 4) >= 0);
+
+       }
+}
+
+static void poll_cb(meshlink_handle_t *mesh, meshlink_channel_t *channel, size_t len) {
+       (void)len;
+
+       meshlink_set_channel_poll_cb(mesh, channel, NULL);
+       pthread_mutex_lock(&poll_lock);
+       polled = true;
+       assert(!pthread_cond_broadcast(&poll_cond));
+       pthread_mutex_unlock(&poll_lock);
+}
+
+/* Execute meshlink_channel_shutdown Test Case # 1*/
+static void test_case_mesh_channel_shutdown_01(void **state) {
+       execute_test(test_steps_mesh_channel_shutdown_01, state);
+}
+
+/* Test Steps for meshlink_channel_shutdown Test Case # 1 - Valid case
+
+    Test Steps:
+    1. Open foo and bar instances and open a channel between them
+    2. Send data through the channel.
+    3. Shut down channel's read and send data
+    4. Shutdown channel's write and send data
+
+    Expected Result:
+    Data is able to receive through channel before shutting down,
+    On shutting down read its should not able to receive data and when write
+    is shut down its should be able to send data through channel.
+*/
+static bool test_steps_mesh_channel_shutdown_01(void) {
+       struct timespec timeout = {0};
+       meshlink_destroy("chan_shutdown_conf.1");
+       meshlink_destroy("chan_shutdown_conf.2");
+       // Open two new meshlink instance.
+
+       meshlink_handle_t *mesh1 = meshlink_open("chan_shutdown_conf.1", "foo", "channels", DEV_CLASS_BACKBONE);
+       assert(mesh1 != NULL);
+
+       meshlink_handle_t *mesh2 = meshlink_open("chan_shutdown_conf.2", "bar", "channels", DEV_CLASS_BACKBONE);
+       assert(mesh2 != NULL);
+
+       char *data = meshlink_export(mesh1);
+       assert(data);
+       assert(meshlink_import(mesh2, data));
+       free(data);
+       data = meshlink_export(mesh2);
+       assert(data);
+       assert(meshlink_import(mesh1, data));
+       free(data);
+
+       // Set the callbacks.
+
+       meshlink_set_channel_accept_cb(mesh2, accept_cb);
+
+       // Start both instances
+
+       assert(meshlink_start(mesh1));
+       assert(meshlink_start(mesh2));
+       sleep(1);
+
+       // Open a channel from foo to bar.
+
+       meshlink_node_t *bar = meshlink_get_node(mesh1, "bar");
+       assert(bar);
+
+       meshlink_channel_t *channel1 = meshlink_channel_open(mesh1, bar, 7, receive_cb, NULL, 0);
+       meshlink_set_channel_poll_cb(mesh1, channel1, poll_cb);
+
+       timeout.tv_sec = time(NULL) + 10;
+       pthread_mutex_lock(&poll_lock);
+
+       while(polled == false) {
+               assert(!pthread_cond_timedwait(&poll_cond, &poll_lock, &timeout));
+       }
+
+       pthread_mutex_unlock(&poll_lock);
+
+       timeout.tv_sec = time(NULL) + 10;
+       pthread_mutex_lock(&accept_lock);
+
+       while(channel_acc == false) {
+               assert(!pthread_cond_timedwait(&accept_cond, &accept_lock, &timeout));
+       }
+
+       pthread_mutex_unlock(&accept_lock);
+
+       meshlink_channel_t *channel2 = bar->priv;
+
+       // Sending to bar and testing the echo
+
+       assert(meshlink_channel_send(mesh1, channel1, "echo", 4) >= 0);
+
+       timeout.tv_sec = time(NULL) + 10;
+       pthread_mutex_lock(&foo_responded_lock);
+
+       while(foo_responded == false) {
+               assert(!pthread_cond_timedwait(&foo_cond, &foo_responded_lock, &timeout));
+       }
+
+       pthread_mutex_unlock(&foo_responded_lock);
+       assert(foo_responded);
+
+       // Shutting down channel read
+
+       meshlink_channel_shutdown(mesh1, channel1, SHUT_RD);
+       bar_responded = false;
+       foo_responded = false;
+       assert(meshlink_channel_send(mesh1, channel1, "echo", 4) >= 0);
+
+       timeout.tv_sec = time(NULL) + 10;
+       pthread_mutex_lock(&bar_responded_lock);
+
+       while(bar_responded == false) {
+               assert(!pthread_cond_timedwait(&bar_cond, &bar_responded_lock, &timeout));
+       }
+
+       pthread_mutex_unlock(&bar_responded_lock);
+       assert_int_equal(bar_responded, true);
+       sleep(1);
+       assert_int_equal(foo_responded, false);
+
+       // Shutting down channel write
+
+       meshlink_channel_shutdown(mesh1, channel1, SHUT_WR);
+
+       ssize_t send_ret = meshlink_channel_send(mesh1, channel1, "echo", 4);
+       assert_int_equal(send_ret, -1);
+
+       // Clean up.
+
+       meshlink_close(mesh2);
+       meshlink_close(mesh1);
+       meshlink_destroy("chan_shutdown_conf.1");
+       meshlink_destroy("chan_shutdown_conf.2");
+
+       return true;
+}
+
+/* Execute meshlink_channel_shutdown Test Case # 2*/
+static void test_case_mesh_channel_shutdown_02(void **state) {
+       execute_test(test_steps_mesh_channel_shutdown_02, state);
+}
+
+/* Test Steps for meshlink_channel_shutdown Test Case # 2 - Invalid case
+
+    Test Steps:
+    1. Open node instance and create a channel
+    2. Call meshlink_channel_shutdown API by passing NULL as mesh handle
+
+    Expected Result:
+    meshlink_channel_shutdown API should report proper error handling
+*/
+static bool test_steps_mesh_channel_shutdown_02(void) {
+       meshlink_destroy("channelshutdownconf.3");
+       meshlink_set_log_cb(NULL, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
+
+       /* Create meshlink instance */
+       meshlink_handle_t *mesh_handle = meshlink_open("channelshutdownconf.3", "nut", "node_sim", 1);
+       assert(mesh_handle != NULL);
+       meshlink_set_log_cb(mesh_handle, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
+       meshlink_set_channel_accept_cb(mesh_handle, accept_cb);
+
+       assert(meshlink_start(mesh_handle));
+
+       meshlink_node_t *node = meshlink_get_self(mesh_handle);
+       assert(node != NULL);
+
+       meshlink_channel_t *channel = meshlink_channel_open(mesh_handle, node, 8000, NULL, NULL, 0);
+       assert(channel);
+       meshlink_set_channel_poll_cb(mesh_handle, channel, poll_cb);
+
+       // Passing NULL as mesh handle and other arguments being valid
+
+       meshlink_channel_shutdown(NULL, channel, SHUT_WR);
+       assert_int_equal(meshlink_errno, MESHLINK_EINVAL);
+
+       meshlink_close(mesh_handle);
+       meshlink_destroy("channelshutdownconf.3");
+
+       return true;
+}
+
+/* Execute meshlink_channel_shutdown Test Case # 3*/
+static void test_case_mesh_channel_shutdown_03(void **state) {
+       execute_test(test_steps_mesh_channel_shutdown_03, state);
+}
+
+/* Test Steps for meshlink_channel_shutdown Test Case # 3
+
+    Test Steps:
+    1. Open node instance
+    2. Call meshlink_channel_shutdown API by passing NULL as channel handle
+
+    Expected Result:
+    meshlink_channel_shutdown API should report proper error handling
+*/
+static bool test_steps_mesh_channel_shutdown_03(void) {
+       meshlink_destroy("channelshutdownconf.4");
+       meshlink_set_log_cb(NULL, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
+
+       /* Create meshlink instance */
+       meshlink_handle_t *mesh_handle = meshlink_open("channelshutdownconf.4", "nut", "node_sim", 1);
+       assert(mesh_handle != NULL);
+       meshlink_set_log_cb(mesh_handle, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
+       meshlink_set_channel_accept_cb(mesh_handle, accept_cb);
+
+       assert(meshlink_start(mesh_handle));
+
+       // Passing NULL as mesh handle and other arguments being valid
+
+       meshlink_channel_shutdown(mesh_handle, NULL, SHUT_WR);
+       assert_int_equal(meshlink_errno, MESHLINK_EINVAL);
+
+       meshlink_close(mesh_handle);
+       meshlink_destroy("channelshutdownconf.4");
+
+       return true;
+}
+
+
+int test_meshlink_channel_shutdown(void) {
+       const struct CMUnitTest blackbox_channel_shutdown_tests[] = {
+               cmocka_unit_test_prestate_setup_teardown(test_case_mesh_channel_shutdown_01, NULL, NULL,
+                               (void *)&test_mesh_channel_shutdown_01_state),
+               cmocka_unit_test_prestate_setup_teardown(test_case_mesh_channel_shutdown_02, NULL, NULL,
+                               (void *)&test_mesh_channel_shutdown_02_state),
+               cmocka_unit_test_prestate_setup_teardown(test_case_mesh_channel_shutdown_03, NULL, NULL,
+                               (void *)&test_mesh_channel_shutdown_03_state)
+       };
+       total_tests += sizeof(blackbox_channel_shutdown_tests) / sizeof(blackbox_channel_shutdown_tests[0]);
+
+       return cmocka_run_group_tests(blackbox_channel_shutdown_tests, NULL, NULL);
+}
diff --git a/test/blackbox/run_blackbox_tests/test_cases_channel_shutdown.h b/test/blackbox/run_blackbox_tests/test_cases_channel_shutdown.h
new file mode 100644 (file)
index 0000000..13f4690
--- /dev/null
@@ -0,0 +1,28 @@
+#ifndef TEST_CASES_CHANNEL_SHUTDOWN_H
+#define TEST_CASES_CHANNEL_SHUTDOWN_H
+
+/*
+    test_cases_channel_shutdown.h -- Declarations for Individual Test Case implementation functions
+    Copyright (C) 2018  Guus Sliepen <guus@meshlink.io>
+
+    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 <stdbool.h>
+
+extern int test_meshlink_channel_shutdown(void);
+extern int total_tests;
+
+#endif
diff --git a/test/blackbox/run_blackbox_tests/test_cases_default_blacklist.c b/test/blackbox/run_blackbox_tests/test_cases_default_blacklist.c
new file mode 100644 (file)
index 0000000..bf21ed8
--- /dev/null
@@ -0,0 +1,198 @@
+/*
+    test_cases_default_blacklist.c -- Execution of specific meshlink black box test cases
+    Copyright (C) 2018  Guus Sliepen <guus@meshlink.io>
+
+    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 <stdlib.h>
+#include <stdarg.h>
+#include <setjmp.h>
+#include <cmocka.h>
+#include <assert.h>
+#include <string.h>
+#include "execute_tests.h"
+#include "test_cases_default_blacklist.h"
+#include "../common/containers.h"
+#include "../common/test_step.h"
+#include "../common/common_handlers.h"
+#include "../../utils.h"
+
+/* Modify this to change the logging level of Meshlink */
+#define TEST_MESHLINK_LOG_LEVEL MESHLINK_DEBUG
+
+static void test_case_mesh_default_blacklist_01(void **state);
+static bool test_steps_mesh_default_blacklist_01(void);
+static void test_case_mesh_default_blacklist_02(void **state);
+static bool test_steps_mesh_default_blacklist_02(void);
+
+/* State structure for meshlink_default_blacklist Test Case #1 */
+static black_box_state_t test_mesh_default_blacklist_01_state = {
+       .test_case_name = "test_case_mesh_default_blacklist_01",
+};
+
+/* State structure for meshlink_default_blacklist Test Case #2 */
+static black_box_state_t test_mesh_default_blacklist_02_state = {
+       .test_case_name = "test_case_mesh_default_blacklist_02",
+};
+
+/* Execute meshlink_default_blacklist Test Case # 1*/
+static void test_case_mesh_default_blacklist_01(void **state) {
+       execute_test(test_steps_mesh_default_blacklist_01, state);
+       return;
+}
+
+static bool received = false;
+
+static void receive(meshlink_handle_t *mesh, meshlink_node_t *src, const void *data, size_t len) {
+       assert(len);
+
+       if(!strcmp(src->name, "bar") || !strcmp(src->name, "foz")) {
+               received = true;
+       }
+}
+
+static bool bar_reachable = false;
+static bool foz_reachable = false;
+
+void status_cb1(meshlink_handle_t *mesh, meshlink_node_t *node, bool reachable) {
+       if(!strcmp(node->name, "bar")) {
+               bar_reachable = reachable;
+       } else if(!strcmp(node->name, "foz")) {
+               foz_reachable = reachable;
+       }
+}
+
+/* Test Steps for meshlink_default_blacklist Test Case # 1
+
+    Test Steps:
+    1. Open all the node instances & Disable default blacklist
+    2. Join bar node with foo and Send & Receive data
+    3. Enable default blacklist and join foz node with foo node
+        and follow the steps done for bar node
+
+    Expected Result:
+    When default blacklist is disabled, foo node should receive data from bar
+    but when enabled foo node should not receive data from foz
+*/
+static bool test_steps_mesh_default_blacklist_01(void) {
+       meshlink_destroy("def_blacklist_conf.1");
+       meshlink_destroy("def_blacklist_conf.2");
+       meshlink_destroy("def_blacklist_conf.3");
+
+       // Open two new meshlink instance.
+       meshlink_handle_t *mesh1 = meshlink_open("def_blacklist_conf.1", "foo", "blacklist", DEV_CLASS_BACKBONE);
+       assert(mesh1 != NULL);
+       meshlink_set_log_cb(mesh1, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
+       meshlink_handle_t *mesh2 = meshlink_open("def_blacklist_conf.2", "bar", "blacklist", DEV_CLASS_BACKBONE);
+       assert(mesh2 != NULL);
+       meshlink_set_log_cb(mesh2, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
+       meshlink_handle_t *mesh3 = meshlink_open("def_blacklist_conf.3", "foz", "blacklist", DEV_CLASS_BACKBONE);
+       assert(mesh3);
+       meshlink_set_log_cb(mesh3, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
+       meshlink_set_receive_cb(mesh1, receive);
+
+       meshlink_set_default_blacklist(mesh1, false);
+
+       // Start both instances
+       bar_reachable = false;
+       foz_reachable = false;
+       meshlink_set_node_status_cb(mesh1, status_cb1);
+       assert(meshlink_start(mesh1));
+       assert(meshlink_start(mesh2));
+       assert(meshlink_start(mesh3));
+       sleep(1);
+
+       char *foo_export = meshlink_export(mesh1);
+       assert(foo_export != NULL);
+       assert(meshlink_import(mesh2, foo_export));
+       char *bar_export = meshlink_export(mesh2);
+       assert(meshlink_import(mesh1, bar_export));
+       sleep(5);
+       assert(bar_reachable);
+
+       // Nodes should learn about each other
+       meshlink_node_t *foo = NULL;
+       foo = meshlink_get_node(mesh2, "foo");
+       assert(foo);
+
+       received = false;
+       assert(meshlink_send(mesh2, foo, "test", 5));
+       assert_after(received, 2);
+
+       // Enable default blacklist and join another node
+       meshlink_set_default_blacklist(mesh1, true);
+
+       char *foz_export = meshlink_export(mesh3);
+       assert(foz_export);
+       assert(meshlink_import(mesh1, foz_export));
+       assert(meshlink_import(mesh3, foo_export));
+       sleep(5);
+       assert(foz_reachable);
+
+       foo = meshlink_get_node(mesh3, "foo");
+       assert(foo);
+       assert(meshlink_send(mesh3, foo, "test", 5));
+       received = false;
+       assert(meshlink_send(mesh3, foo, "test", 5));
+       assert_after(!received, 2);
+
+       // Clean up.
+       free(foo_export);
+       free(foz_export);
+       free(bar_export);
+       meshlink_close(mesh1);
+       meshlink_close(mesh2);
+       meshlink_close(mesh3);
+       meshlink_destroy("def_blacklist_conf.1");
+       meshlink_destroy("def_blacklist_conf.2");
+       meshlink_destroy("def_blacklist_conf.3");
+
+       return true;
+}
+
+/* Execute meshlink_default_blacklist Test Case # 2*/
+static void test_case_mesh_default_blacklist_02(void **state) {
+       execute_test(test_steps_mesh_default_blacklist_02, state);
+}
+
+/* Test Steps for meshlink_default_blacklist Test Case # 2
+
+    Test Steps:
+    1. Calling meshlink_default_blacklist with NULL as mesh handle argument.
+
+    Expected Result:
+    meshlink_default_blacklist API handles the invalid parameter when called by giving proper error number.
+*/
+static bool test_steps_mesh_default_blacklist_02(void) {
+       // Passing NULL as mesh handle argument to the API
+       meshlink_set_default_blacklist(NULL, true);
+       assert_int_equal(meshlink_errno, MESHLINK_EINVAL);
+
+       return true;
+}
+
+int test_meshlink_default_blacklist(void) {
+       const struct CMUnitTest blackbox_default_blacklist_tests[] = {
+               cmocka_unit_test_prestate_setup_teardown(test_case_mesh_default_blacklist_01, NULL, NULL,
+                               (void *)&test_mesh_default_blacklist_01_state),
+               cmocka_unit_test_prestate_setup_teardown(test_case_mesh_default_blacklist_02, NULL, NULL,
+                               (void *)&test_mesh_default_blacklist_02_state)
+       };
+
+       total_tests += sizeof(blackbox_default_blacklist_tests) / sizeof(blackbox_default_blacklist_tests[0]);
+
+       return cmocka_run_group_tests(blackbox_default_blacklist_tests, NULL, NULL);
+}
diff --git a/test/blackbox/run_blackbox_tests/test_cases_default_blacklist.h b/test/blackbox/run_blackbox_tests/test_cases_default_blacklist.h
new file mode 100644 (file)
index 0000000..c8e7af2
--- /dev/null
@@ -0,0 +1,28 @@
+#ifndef TEST_CASES_DEFAULT_BLACKLIST_H
+#define TEST_CASES_DEFAULT_BLACKLIST_H
+
+/*
+    test_cases_default_blacklist.h -- Declarations for Individual Test Case implementation functions
+    Copyright (C) 2018  Guus Sliepen <guus@meshlink.io>
+
+    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 <stdbool.h>
+
+extern int test_meshlink_default_blacklist(void);
+extern int total_tests;
+
+#endif
diff --git a/test/blackbox/run_blackbox_tests/test_cases_destroy.c b/test/blackbox/run_blackbox_tests/test_cases_destroy.c
new file mode 100644 (file)
index 0000000..30bd376
--- /dev/null
@@ -0,0 +1,149 @@
+/*
+    test_cases_destroy.c -- Execution of specific meshlink black box test cases
+    Copyright (C) 2018  Guus Sliepen <guus@meshlink.io>
+
+    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 "execute_tests.h"
+#include "test_cases_destroy.h"
+#include "../common/containers.h"
+#include "../common/test_step.h"
+#include "../common/common_handlers.h"
+#include <assert.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <setjmp.h>
+#include <cmocka.h>
+#include <sys/types.h>
+#include <dirent.h>
+
+
+/* Modify this to change the logging level of Meshlink */
+#define TEST_MESHLINK_LOG_LEVEL MESHLINK_DEBUG
+
+static void test_case_meshlink_destroy_01(void **state);
+static bool test_meshlink_destroy_01(void);
+static void test_case_meshlink_destroy_02(void **state);
+static bool test_meshlink_destroy_02(void);
+static void test_case_meshlink_destroy_03(void **state);
+static bool test_meshlink_destroy_03(void);
+
+static black_box_state_t test_case_meshlink_destroy_01_state = {
+       .test_case_name = "test_case_meshlink_destroy_01",
+};
+static black_box_state_t test_case_meshlink_destroy_02_state = {
+       .test_case_name = "test_case_meshlink_destroy_02",
+};
+static black_box_state_t test_case_meshlink_destroy_03_state = {
+       .test_case_name = "test_case_meshlink_destroy_03",
+};
+
+
+/* Execute destroy Test Case # 1 - valid case*/
+static void test_case_meshlink_destroy_01(void **state) {
+       execute_test(test_meshlink_destroy_01, state);
+}
+
+/* Test Steps for destroy Test Case # 1 - Valid case
+    Test Steps:
+    1. Open instance for NUT
+    2. Close NUT, and destroy the confbase
+    3. Open the same confbase directory
+
+    Expected Result:
+    confbase should be deleted
+*/
+static bool test_meshlink_destroy_01(void) {
+       meshlink_set_log_cb(NULL, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
+
+       // Create meshlink instance
+       char *confbase = "destroyconf";
+       mesh_handle = meshlink_open(confbase, "nut", "node_sim", 1);
+       assert(mesh_handle);
+
+       meshlink_close(mesh_handle);
+
+       // Destroying NUT's confbase
+       bool result = meshlink_destroy(confbase);
+       assert_int_equal(result, true);
+
+       // Verify whether confbase is removed or not
+       DIR *dir = opendir(confbase);
+       assert_int_equal(dir, NULL);
+
+       return true;
+}
+
+/* Execute destroy Test Case # 2 - passing NULL argument to the API */
+static void test_case_meshlink_destroy_02(void **state) {
+       execute_test(test_meshlink_destroy_02, state);
+}
+
+/* Test Steps for destroy Test Case # 2 - Invalid case
+    Test Steps:
+    1. Just passing NULL as argument to the API
+
+    Expected Result:
+    Return false reporting failure
+*/
+static bool test_meshlink_destroy_02(void) {
+       // Passing NULL as an argument to meshlink_destroy
+       bool result = meshlink_destroy(NULL);
+       assert_int_equal(result, false);
+
+       return true;
+}
+
+/* Execute status Test Case # 3 - destroying non existing file */
+static void test_case_meshlink_destroy_03(void **state) {
+       execute_test(test_meshlink_destroy_03, state);
+}
+/* Test Steps for destroy Test Case # 3 - Invalid case
+    Test Steps:
+    1. unlink if there's any such test file
+    2. Call API with that file name
+
+    Expected Result:
+    Return false reporting failure
+*/
+static bool test_meshlink_destroy_03(void) {
+       bool result = false;
+
+       // Deletes if there is any file named 'non_existing' already
+       unlink("non_existing");
+
+       // Passing non-existing file as an argument to meshlink_destroy
+       result = meshlink_destroy("non_existing");
+       assert_int_equal(result, false);
+
+       return true;
+}
+
+
+int test_meshlink_destroy(void) {
+       const struct CMUnitTest blackbox_destroy_tests[] = {
+               cmocka_unit_test_prestate_setup_teardown(test_case_meshlink_destroy_01, NULL, NULL,
+                               (void *)&test_case_meshlink_destroy_01_state),
+               cmocka_unit_test_prestate_setup_teardown(test_case_meshlink_destroy_02, NULL, NULL,
+                               (void *)&test_case_meshlink_destroy_02_state),
+               cmocka_unit_test_prestate_setup_teardown(test_case_meshlink_destroy_03, NULL, NULL,
+                               (void *)&test_case_meshlink_destroy_03_state)
+       };
+
+       total_tests += sizeof(blackbox_destroy_tests) / sizeof(blackbox_destroy_tests[0]);
+
+       return cmocka_run_group_tests(blackbox_destroy_tests, NULL, NULL);
+}
diff --git a/test/blackbox/run_blackbox_tests/test_cases_destroy.h b/test/blackbox/run_blackbox_tests/test_cases_destroy.h
new file mode 100644 (file)
index 0000000..3d90dcb
--- /dev/null
@@ -0,0 +1,28 @@
+#ifndef TEST_CASES_DESTROY_H
+#define TEST_CASES_DESTROY_H
+
+/*
+    test_cases_destroy.h -- Declarations for Individual Test Case implementation functions
+    Copyright (C) 2018  Guus Sliepen <guus@meshlink.io>
+
+    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 <stdbool.h>
+
+extern int total_tests;
+extern int test_meshlink_destroy(void);
+
+#endif // TEST_CASES_DESTROY_H
diff --git a/test/blackbox/run_blackbox_tests/test_cases_export.c b/test/blackbox/run_blackbox_tests/test_cases_export.c
new file mode 100644 (file)
index 0000000..75e84ec
--- /dev/null
@@ -0,0 +1,113 @@
+/*
+    test_cases_export.c -- Execution of specific meshlink black box test cases
+    Copyright (C) 2018  Guus Sliepen <guus@meshlink.io>
+
+    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 "execute_tests.h"
+#include "test_cases_export.h"
+#include "../common/containers.h"
+#include "../common/test_step.h"
+#include "../common/common_handlers.h"
+#include <assert.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <setjmp.h>
+#include <cmocka.h>
+
+
+/* Modify this to change the logging level of Meshlink */
+#define TEST_MESHLINK_LOG_LEVEL MESHLINK_DEBUG
+
+static void test_case_export_01(void **state);
+static bool test_export_01(void);
+static void test_case_export_02(void **state);
+static bool test_export_02(void);
+
+/* State structure for export API Test Case #1 */
+static black_box_state_t test_case_export_01_state = {
+       .test_case_name = "test_case_export_01",
+};
+/* State structure for export API Test Case #2 */
+static black_box_state_t test_case_export_02_state = {
+       .test_case_name = "test_case_export_02",
+};
+
+
+/* Execute export Test Case # 1 - valid case*/
+static void test_case_export_01(void **state) {
+       execute_test(test_export_01, state);
+}
+/* Test Steps for export Test Case # 1 - Valid case
+    Test Steps:
+    1. Run NUT
+    2. Export mesh
+
+    Expected Result:
+    API returns a NULL terminated string containing meta data of NUT.
+*/
+static bool test_export_01(void) {
+       meshlink_destroy("exportconf");
+       meshlink_set_log_cb(NULL, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
+
+       /* Create meshlink instance */
+       meshlink_handle_t *mesh_handle = meshlink_open("exportconf", "nut", "node_sim", 1);
+       assert(mesh_handle);
+       meshlink_set_log_cb(mesh_handle, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
+
+       char *expo = meshlink_export(mesh_handle);
+       assert_int_not_equal(expo, NULL);
+
+       meshlink_close(mesh_handle);
+       meshlink_destroy("exportconf");
+
+       return true;
+}
+
+/* Execute export Test Case # 2 - Invalid case*/
+static void test_case_export_02(void **state) {
+       execute_test(test_export_02, state);
+}
+/* Test Steps for export Test Case # 2 - Invalid case
+    Test Steps:
+    1. Run NUT
+    2. calling meshlink_export by passing NULL as mesh handle
+
+    Expected Result:
+    API returns NULL reporting error when NULL being passed as mesh handle.
+*/
+static bool test_export_02(void) {
+       // Calling export API with NULL as mesh handle
+       char *expo = meshlink_export(NULL);
+       assert_int_equal(expo, NULL);
+
+       return true;
+}
+
+
+int test_meshlink_export(void) {
+       const struct CMUnitTest blackbox_export_tests[] = {
+               cmocka_unit_test_prestate_setup_teardown(test_case_export_01, NULL, NULL,
+                               (void *)&test_case_export_01_state),
+               cmocka_unit_test_prestate_setup_teardown(test_case_export_02, NULL, NULL,
+                               (void *)&test_case_export_02_state)
+       };
+
+       total_tests += sizeof(blackbox_export_tests) / sizeof(blackbox_export_tests[0]);
+
+       return cmocka_run_group_tests(blackbox_export_tests, NULL, NULL);
+}
+
diff --git a/test/blackbox/run_blackbox_tests/test_cases_export.h b/test/blackbox/run_blackbox_tests/test_cases_export.h
new file mode 100644 (file)
index 0000000..ecea12e
--- /dev/null
@@ -0,0 +1,28 @@
+#ifndef TEST_CASES_EXPORT_H
+#define TEST_CASES_EXPORT_H
+
+/*
+    test_cases_export.h -- Declarations for Individual Test Case implementation functions
+    Copyright (C) 2018  Guus Sliepen <guus@meshlink.io>
+
+    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 <stdbool.h>
+
+extern int total_tests;
+extern int test_meshlink_export(void);
+
+#endif
diff --git a/test/blackbox/run_blackbox_tests/test_cases_get_all_nodes.c b/test/blackbox/run_blackbox_tests/test_cases_get_all_nodes.c
new file mode 100644 (file)
index 0000000..8b885a7
--- /dev/null
@@ -0,0 +1,180 @@
+/*
+    test_cases_get_all_nodes.c -- Execution of specific meshlink black box test cases
+    Copyright (C) 2018  Guus Sliepen <guus@meshlink.io>
+
+    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 "execute_tests.h"
+#include "test_cases.h"
+#include "../common/containers.h"
+#include "../common/test_step.h"
+#include "../common/common_handlers.h"
+#include "test_cases_get_all_nodes.h"
+#include <assert.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <setjmp.h>
+#include <cmocka.h>
+
+
+/* Modify this to change the logging level of Meshlink */
+#define TEST_MESHLINK_LOG_LEVEL MESHLINK_DEBUG
+
+static void test_case_get_all_nodes_01(void **state);
+static bool test_get_all_nodes_01(void);
+static void test_case_get_all_nodes_02(void **state);
+static bool test_get_all_nodes_02(void);
+static void test_case_get_all_nodes_03(void **state);
+static bool test_get_all_nodes_03(void);
+static void test_case_get_all_nodes_04(void **state);
+static bool test_get_all_nodes_04(void);
+
+/* State structure for get_all_nodes Test Case #1 */
+static black_box_state_t test_case_get_all_nodes_01_state = {
+       .test_case_name = "test_case_get_all_nodes_01",
+};
+
+/* State structure for get_all_nodes Test Case #2 */
+static black_box_state_t test_case_get_all_nodes_02_state = {
+       .test_case_name = "test_case_get_all_nodes_02",
+};
+
+/* State structure for get_all_nodes Test Case #3 */
+static black_box_state_t test_case_get_all_nodes_03_state = {
+       .test_case_name = "test_case_get_all_nodes_03",
+};
+
+/* Execute get_all_nodes Test Case # 1 - Valid case - get all nodes in the mesh */
+static void test_case_get_all_nodes_01(void **state) {
+       execute_test(test_get_all_nodes_01, state);
+}
+/* Test Steps for get_all_nodes Test Case # 1 - Valid case
+
+    Test Steps:
+    1. Open NUT and get list of nodes
+    2. Open bar and join with NUT
+    3. get list of nodes together
+
+    Expected Result:
+    Obtaining list of nodes in the mesh at the given instance
+*/
+static bool test_get_all_nodes_01(void) {
+       meshlink_destroy("getnodeconf1");
+       meshlink_destroy("getnodeconf2");
+       meshlink_set_log_cb(NULL, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
+
+       /* Create meshlink instance for NUT */
+       meshlink_handle_t *mesh1 = meshlink_open("getnodeconf1", "nut", "node_sim", DEV_CLASS_STATIONARY);
+       assert(mesh1);
+       meshlink_set_log_cb(mesh1, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
+
+       size_t nnodes = 0;
+       meshlink_node_t **nodes = NULL;
+       nodes = meshlink_get_all_nodes(mesh1, nodes, &nnodes);
+       assert_int_not_equal(nodes, NULL);
+       assert_int_equal(nnodes, 1);
+
+       /* Create meshlink instance for bar */
+       meshlink_handle_t *mesh2 = meshlink_open("getnodeconf2", "bar", "node_sim", DEV_CLASS_STATIONARY);
+       assert(mesh2);
+
+       /* importing and exporting mesh meta data */
+       char *exp1 = meshlink_export(mesh1);
+       assert(exp1 != NULL);
+       char *exp2 = meshlink_export(mesh2);
+       assert(exp2 != NULL);
+       assert(meshlink_import(mesh1, exp2));
+       assert(meshlink_import(mesh2, exp1));
+
+       nodes = meshlink_get_all_nodes(mesh1, nodes, &nnodes);
+       assert_int_not_equal(nodes, NULL);
+       assert_int_equal(nnodes, 2);
+
+       meshlink_close(mesh1);
+       meshlink_close(mesh2);
+       meshlink_destroy("getnodeconf1");
+       meshlink_destroy("getnodeconf2");
+
+       return true;
+}
+
+
+
+/* Execute get_all_nodes Test Case # 2 - Invalid case - get all nodes in the mesh passing NULL */
+static void test_case_get_all_nodes_02(void **state) {
+       execute_test(test_get_all_nodes_02, state);
+}
+
+/* Test Steps for get_all_nodes Test Case # 2 - Invalid case
+
+    Test Steps:
+    1. Passing NULL as mesh handle argument for meshlink_get_all_nodes
+
+    Expected Result:
+    Error reported correctly by returning NULL
+*/
+static bool test_get_all_nodes_02(void) {
+       meshlink_node_t **nodes = NULL;
+       size_t nmemb = 0;
+
+       meshlink_node_t **node = meshlink_get_all_nodes(NULL, nodes, &nmemb);
+       assert_int_equal(nodes, NULL);
+
+       return true;
+}
+
+/* Execute get_all_nodes Test Case # 3 - Invalid case - get all nodes in the mesh passing NULL as nmeb arg */
+static void test_case_get_all_nodes_03(void **state) {
+       execute_test(test_get_all_nodes_03, state);
+}
+/* Test Steps for get_all_nodes Test Case # 3 - Invalid case
+
+    Test Steps:
+    1. Passing NULL as pointer to node members argument for meshlink_get_all_nodes
+
+    Expected Result:
+    Error reported correctly by returning NULL
+*/
+static bool test_get_all_nodes_03(void) {
+       /* Create meshlink instance */
+       meshlink_handle_t *mesh_handle = meshlink_open("getallnodesconf", "nut", "node_sim", 1);
+       assert(mesh_handle);
+       assert(meshlink_start(mesh_handle));
+
+       meshlink_node_t **nodes = NULL;
+       nodes = meshlink_get_all_nodes(mesh_handle, nodes, NULL);
+       assert_int_equal(nodes, NULL);
+
+       meshlink_close(mesh_handle);
+       meshlink_destroy("getallnodesconf");
+
+       return true;
+}
+
+int test_meshlink_get_all_nodes(void) {
+       const struct CMUnitTest blackbox_get_all_nodes[] = {
+               cmocka_unit_test_prestate_setup_teardown(test_case_get_all_nodes_01, NULL, NULL,
+                               (void *)&test_case_get_all_nodes_01_state),
+               cmocka_unit_test_prestate_setup_teardown(test_case_get_all_nodes_02, NULL, NULL,
+                               (void *)&test_case_get_all_nodes_02_state),
+               cmocka_unit_test_prestate_setup_teardown(test_case_get_all_nodes_03, NULL, NULL,
+                               (void *)&test_case_get_all_nodes_03_state)
+       };
+       total_tests += sizeof(blackbox_get_all_nodes) / sizeof(blackbox_get_all_nodes[0]);
+
+       return cmocka_run_group_tests(blackbox_get_all_nodes, NULL, NULL);
+}
diff --git a/test/blackbox/run_blackbox_tests/test_cases_get_all_nodes.h b/test/blackbox/run_blackbox_tests/test_cases_get_all_nodes.h
new file mode 100644 (file)
index 0000000..898114a
--- /dev/null
@@ -0,0 +1,28 @@
+#ifndef TEST_CASES_GET_ALL_NODES_H
+#define TEST_CASES_GET_ALL_NODES_H
+
+/*
+    test_cases_get_all_nodes.h -- Declarations for Individual Test Case implementation functions
+    Copyright (C) 2018  Guus Sliepen <guus@meshlink.io>
+
+    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 <stdbool.h>
+
+extern int total_tests;
+extern int test_meshlink_get_all_nodes(void);
+
+#endif
diff --git a/test/blackbox/run_blackbox_tests/test_cases_get_ex_addr.c b/test/blackbox/run_blackbox_tests/test_cases_get_ex_addr.c
new file mode 100644 (file)
index 0000000..8868c76
--- /dev/null
@@ -0,0 +1,143 @@
+/*
+    test_cases_get_ex_addr.c -- Execution of specific meshlink black box test cases
+    Copyright (C) 2018  Guus Sliepen <guus@meshlink.io>
+
+    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 "execute_tests.h"
+#include "test_cases_get_ex_addr.h"
+#include "../common/containers.h"
+#include "../common/test_step.h"
+#include "../common/common_handlers.h"
+#include <stdlib.h>
+#include <stdarg.h>
+#include <setjmp.h>
+#include <cmocka.h>
+#include <assert.h>
+#include <string.h>
+
+static void test_case_mesh_get_address_01(void **state);
+static bool test_steps_mesh_get_address_01(void);
+static void test_case_mesh_get_address_02(void **state);
+static bool test_steps_mesh_get_address_02(void);
+static void test_case_mesh_get_address_03(void **state);
+static bool test_steps_mesh_get_address_03(void);
+
+/* State structure for meshlink_get_external_address Test Case #1 */
+static black_box_state_t test_mesh_get_address_01_state = {
+       .test_case_name = "test_case_mesh_get_address_01",
+};
+
+/* State structure for meshlink_get_external_address Test Case #2 */
+static black_box_state_t test_mesh_get_address_02_state = {
+       .test_case_name = "test_case_mesh_get_address_02",
+};
+
+/* State structure for meshlink_get_external_address Test Case #3 */
+static black_box_state_t test_mesh_get_address_03_state = {
+       .test_case_name = "test_case_mesh_get_address_03",
+};
+
+/* Execute meshlink_get_external_address Test Case # 1 */
+static void test_case_mesh_get_address_01(void **state) {
+       execute_test(test_steps_mesh_get_address_01, state);
+}
+
+/* Test Steps for meshlink_get_external_address Test Case # 1
+
+    Test Steps:
+    1. Create an instance of the node & start it
+    2. Get node's external address using meshlink_get_external_address
+
+    Expected Result:
+    API returns the external address successfully.
+*/
+static bool test_steps_mesh_get_address_01(void) {
+       meshlink_handle_t *mesh = meshlink_open("getex_conf", "foo", "test", DEV_CLASS_STATIONARY);
+       assert(mesh != NULL);
+       assert(meshlink_start(mesh));
+
+       char *addr = meshlink_get_external_address(mesh);
+       assert_int_not_equal(addr, NULL);
+
+       free(addr);
+       meshlink_close(mesh);
+       meshlink_destroy("getex_conf");
+       return true;
+}
+
+/* Execute meshlink_get_external_address Test Case # 2 */
+static void test_case_mesh_get_address_02(void **state) {
+       execute_test(test_steps_mesh_get_address_02, state);
+}
+
+/* Test Steps for meshlink_get_external_address Test Case # 2
+
+    Test Steps:
+    1. Obtain external address by passing NULL as mesh handle
+        to meshlink_get_external_address API
+
+    Expected Result:
+    Return NULL by reporting error successfully.
+*/
+static bool test_steps_mesh_get_address_02(void) {
+       char *ext = meshlink_get_external_address(NULL);
+       assert_int_equal(ext, NULL);
+
+       return true;
+}
+
+/* Execute meshlink_get_external_address Test Case # 3 */
+static void test_case_mesh_get_address_03(void **state) {
+       execute_test(test_steps_mesh_get_address_03, state);
+}
+
+/* Test Steps for meshlink_get_external_address Test Case # 3 - Functionality test
+
+    Test Steps:
+    1. Create an instance of the node
+    2. Get node's external address using meshlink_get_external_address
+
+    Expected Result:
+    API returns the external address successfully even if the mesh is started.
+*/
+static bool test_steps_mesh_get_address_03(void) {
+       meshlink_handle_t *mesh = meshlink_open("getex_conf", "foo", "test", DEV_CLASS_STATIONARY);
+       assert(mesh != NULL);
+       assert(meshlink_start(mesh));
+
+       char *addr = meshlink_get_external_address(mesh);
+       assert_int_not_equal(addr, NULL);
+
+       free(addr);
+       meshlink_close(mesh);
+       meshlink_destroy("getex_conf");
+       return true;
+}
+
+int test_meshlink_get_external_address(void) {
+       const struct CMUnitTest blackbox_get_ex_addr_tests[] = {
+               cmocka_unit_test_prestate_setup_teardown(test_case_mesh_get_address_01, NULL, NULL,
+                               (void *)&test_mesh_get_address_01_state),
+               cmocka_unit_test_prestate_setup_teardown(test_case_mesh_get_address_02, NULL, NULL,
+                               (void *)&test_mesh_get_address_02_state),
+               cmocka_unit_test_prestate_setup_teardown(test_case_mesh_get_address_03, NULL, NULL,
+                               (void *)&test_mesh_get_address_03_state)
+       };
+       total_tests += sizeof(blackbox_get_ex_addr_tests) / sizeof(blackbox_get_ex_addr_tests[0]);
+
+       return cmocka_run_group_tests(blackbox_get_ex_addr_tests, NULL, NULL);
+}
diff --git a/test/blackbox/run_blackbox_tests/test_cases_get_ex_addr.h b/test/blackbox/run_blackbox_tests/test_cases_get_ex_addr.h
new file mode 100644 (file)
index 0000000..ccd4bb9
--- /dev/null
@@ -0,0 +1,28 @@
+#ifndef TEST_CASES_GET_EX_ADDR_H
+#define TEST_CASES_GET_EX_ADDR_H
+
+/*
+    test_cases_get_ex_addr.h -- Declarations for Individual Test Case implementation functions
+    Copyright (C) 2018  Guus Sliepen <guus@meshlink.io>
+
+    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 <stdbool.h>
+
+extern int test_meshlink_get_external_address(void);
+extern int total_tests;
+
+#endif
diff --git a/test/blackbox/run_blackbox_tests/test_cases_get_fingerprint.c b/test/blackbox/run_blackbox_tests/test_cases_get_fingerprint.c
new file mode 100644 (file)
index 0000000..1315ec5
--- /dev/null
@@ -0,0 +1,176 @@
+/*
+    test_cases_get_fingerprint.c -- Execution of specific meshlink black box test cases
+    Copyright (C) 2018  Guus Sliepen <guus@meshlink.io>
+
+    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 "execute_tests.h"
+#include "test_cases.h"
+#include "../common/containers.h"
+#include "../common/test_step.h"
+#include "../common/common_handlers.h"
+#include "test_cases_get_fingerprint.h"
+#include <assert.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <setjmp.h>
+#include <cmocka.h>
+
+/* Modify this to change the logging level of Meshlink */
+#define TEST_MESHLINK_LOG_LEVEL MESHLINK_DEBUG
+
+static void test_case_get_fingerprint_cb_01(void **state);
+static bool test_get_fingerprint_cb_01(void);
+static void test_case_get_fingerprint_cb_02(void **state);
+static bool test_get_fingerprint_cb_02(void);
+static void test_case_get_fingerprint_cb_03(void **state);
+static bool test_get_fingerprint_cb_03(void);
+
+/* State structure for get_fingerprint Test Case #1 */
+static black_box_state_t test_case_get_fingerprint_cb_01_state = {
+       .test_case_name = "test_case_get_fingerprint_cb_01",
+};
+/* State structure for get_fingerprint Test Case #2 */
+static black_box_state_t test_case_get_fingerprint_cb_02_state = {
+       .test_case_name = "test_case_get_fingerprint_cb_02",
+};
+/* State structure for get_fingerprint Test Case #3 */
+static black_box_state_t test_case_get_fingerprint_cb_03_state = {
+       .test_case_name = "test_case_get_fingerprint_cb_03",
+};
+
+/* Execute get_fingerprint Test Case # 1 - Valid Case of obtaing publickey of NUT */
+static void test_case_get_fingerprint_cb_01(void **state) {
+       execute_test(test_get_fingerprint_cb_01, state);
+}
+/* Test Steps for get_fingerprint Test Case # 1 - Valid case
+
+    Test Steps:
+    1. Run NUT(Node Under Test)
+    2. Get node handle for ourself(for NUT) and obtain fingerprint
+
+    Expected Result:
+    Obtain fingerprint of NUT successfully.
+*/
+static bool test_get_fingerprint_cb_01(void) {
+       meshlink_set_log_cb(NULL, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
+
+       /* Create meshlink instance */
+       meshlink_handle_t *mesh_handle = meshlink_open("getfingerprintconf", "nut", "test", 1);
+       assert(mesh_handle);
+       meshlink_set_log_cb(mesh_handle, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
+
+       meshlink_node_t *node = meshlink_get_self(mesh_handle);
+       assert(node != NULL);
+
+       char *fp = meshlink_get_fingerprint(mesh_handle, node);
+       assert_int_not_equal(fp, NULL);
+
+       meshlink_close(mesh_handle);
+       meshlink_destroy("getfingerprintconf");
+
+       return true;
+}
+
+/* Execute get_fingerprint Test Case # 2 - Invalid Case - trying t0 obtain publickey of a node in a
+   mesh by passing NULL as mesh handle argument*/
+static void test_case_get_fingerprint_cb_02(void **state) {
+       execute_test(test_get_fingerprint_cb_02, state);
+}
+
+/* Test Steps for get_fingerprint Test Case # 2 - Invalid case
+
+    Test Steps:
+    1. Run NUT(Node Under Test)
+    2. Get node handle for ourself(for NUT)
+    3. Obtain fingerprint by passing NULL as mesh handle
+
+    Expected Result:
+    Return NULL by reporting error successfully.
+*/
+static bool test_get_fingerprint_cb_02(void) {
+       /* Set up logging for Meshlink */
+       meshlink_set_log_cb(NULL, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
+
+       /* Create meshlink instance */
+       PRINT_TEST_CASE_MSG("Opening NUT\n");
+       meshlink_handle_t *mesh_handle = meshlink_open("getfingerprintconf", "nut", "test", 1);
+       assert(mesh_handle);
+
+       /* Set up logging for Meshlink with the newly acquired Mesh Handle */
+       meshlink_set_log_cb(mesh_handle, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
+       /* Getting node handle for itself */
+       meshlink_node_t *node = meshlink_get_self(mesh_handle);
+       assert(node != NULL);
+
+       /* passing NULL as mesh handle for meshlink_get_fingerprint API */
+       char *fp = meshlink_get_fingerprint(NULL, node);
+       assert_int_equal(fp, NULL);
+
+       meshlink_close(mesh_handle);
+       meshlink_destroy("getfingerprintconf");
+
+       return true;
+}
+
+/* Execute get_fingerprint Test Case # 3 - Invalid Case - trying t0 obtain publickey of a node in a
+   mesh by passing NULL as node handle argument */
+static void test_case_get_fingerprint_cb_03(void **state) {
+       execute_test(test_get_fingerprint_cb_03, state);
+}
+/* Test Steps for get_fingerprint Test Case # 3 - Invalid case
+
+    Test Steps:
+    1. Run NUT(Node Under Test)
+    2. Get node handle for ourself(for NUT)
+    3. Obtain fingerprint by passing NULL as node handle
+
+    Expected Result:
+    Return NULL by reporting error successfully.
+*/
+static bool test_get_fingerprint_cb_03(void) {
+       meshlink_set_log_cb(NULL, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
+
+       /* Create meshlink instance */
+       meshlink_handle_t *mesh_handle = meshlink_open("getfingerprintconf", "nut", "test", 1);
+       assert(mesh_handle);
+       meshlink_set_log_cb(mesh_handle, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
+
+       char *fp = meshlink_get_fingerprint(mesh_handle, NULL);
+       assert_int_equal(fp, NULL);
+
+       meshlink_close(mesh_handle);
+       meshlink_destroy("getfingerprintconf");
+
+       return true;
+}
+
+int test_meshlink_get_fingerprint(void) {
+       const struct CMUnitTest blackbox_get_fingerprint_tests[] = {
+               cmocka_unit_test_prestate_setup_teardown(test_case_get_fingerprint_cb_01, NULL, NULL,
+                               (void *)&test_case_get_fingerprint_cb_01_state),
+               cmocka_unit_test_prestate_setup_teardown(test_case_get_fingerprint_cb_02, NULL, NULL,
+                               (void *)&test_case_get_fingerprint_cb_02_state),
+               cmocka_unit_test_prestate_setup_teardown(test_case_get_fingerprint_cb_03, NULL, NULL,
+                               (void *)&test_case_get_fingerprint_cb_03_state)
+       };
+
+       total_tests += sizeof(blackbox_get_fingerprint_tests) / sizeof(blackbox_get_fingerprint_tests[0]);
+
+       return cmocka_run_group_tests(blackbox_get_fingerprint_tests, NULL, NULL);
+
+}
diff --git a/test/blackbox/run_blackbox_tests/test_cases_get_fingerprint.h b/test/blackbox/run_blackbox_tests/test_cases_get_fingerprint.h
new file mode 100644 (file)
index 0000000..dafc4bf
--- /dev/null
@@ -0,0 +1,28 @@
+#ifndef TEST_CASES_GET_FINGERPRINT_H
+#define TEST_CASES_GET_FINGERPRINT_H
+
+/*
+    test_cases_get_fingerprint.h -- Declarations for Individual Test Case implementation functions
+    Copyright (C) 2018  Guus Sliepen <guus@meshlink.io>
+
+    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 <stdbool.h>
+
+extern int test_meshlink_get_fingerprint(void);
+extern int total_tests;
+
+#endif // TEST_CASES_GET_FINGERPRINT_H
diff --git a/test/blackbox/run_blackbox_tests/test_cases_get_node.c b/test/blackbox/run_blackbox_tests/test_cases_get_node.c
new file mode 100644 (file)
index 0000000..6ecb146
--- /dev/null
@@ -0,0 +1,205 @@
+/*
+    test_cases_get_node.c -- Execution of specific meshlink black box test cases
+    Copyright (C) 2018  Guus Sliepen <guus@meshlink.io>
+
+    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 "execute_tests.h"
+#include "test_cases_get_node.h"
+#include "../common/containers.h"
+#include "../common/test_step.h"
+#include "../common/common_handlers.h"
+#include <stdlib.h>
+#include <stdarg.h>
+#include <setjmp.h>
+#include <cmocka.h>
+#include <assert.h>
+#include <string.h>
+
+/* Modify this to change the logging level of Meshlink */
+#define TEST_MESHLINK_LOG_LEVEL MESHLINK_DEBUG
+
+static void test_case_mesh_get_node_01(void **state);
+static bool test_steps_mesh_get_node_01(void);
+static void test_case_mesh_get_node_02(void **state);
+static bool test_steps_mesh_get_node_02(void);
+static void test_case_mesh_get_node_03(void **state);
+static bool test_steps_mesh_get_node_03(void);
+static void test_case_mesh_get_node_04(void **state);
+static bool test_steps_mesh_get_node_04(void);
+
+/* State structure for meshlink_get_node Test Case #1 */
+static black_box_state_t test_mesh_get_node_01_state = {
+       .test_case_name = "test_case_mesh_get_node_01",
+};
+
+/* State structure for meshlink_get_node Test Case #2 */
+static black_box_state_t test_mesh_get_node_02_state = {
+       .test_case_name = "test_case_mesh_get_node_02",
+};
+
+/* State structure for meshlink_get_node Test Case #3 */
+static black_box_state_t test_mesh_get_node_03_state = {
+       .test_case_name = "test_case_mesh_get_node_03",
+};
+
+/* State structure for meshlink_get_node Test Case #4 */
+static black_box_state_t test_mesh_get_node_04_state = {
+       .test_case_name = "test_case_mesh_get_node_04",
+};
+
+/* Execute meshlink_get_node Test Case # 1 */
+static void test_case_mesh_get_node_01(void **state) {
+       execute_test(test_steps_mesh_get_node_01, state);
+}
+
+/* Test Steps for meshlink_get_node Test Case # 1
+
+    Test Steps:
+    1. Open nodes instance
+    2. Get node's handle
+
+    Expected Result:
+    node handle of it's own is obtained
+*/
+static bool test_steps_mesh_get_node_01(void) {
+       meshlink_set_log_cb(NULL, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
+       meshlink_destroy("getnode1");
+       meshlink_destroy("getnode2");
+
+       // Opening NUT and bar nodes
+       meshlink_handle_t *mesh1 = meshlink_open("getnode1", "nut", "test", DEV_CLASS_STATIONARY);
+       assert(mesh1 != NULL);
+       meshlink_set_log_cb(mesh1, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
+       meshlink_handle_t *mesh2 = meshlink_open("getnode2", "bar", "test", DEV_CLASS_STATIONARY);
+       assert(mesh2 != NULL);
+       meshlink_set_log_cb(mesh2, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
+
+       // Exporting and Importing mutually
+       char *exp1 = meshlink_export(mesh1);
+       assert(exp1 != NULL);
+       char *exp2 = meshlink_export(mesh2);
+       assert(exp2 != NULL);
+       bool imp1 = meshlink_import(mesh1, exp2);
+       assert(imp1);
+       bool imp2 = meshlink_import(mesh2, exp1);
+       assert(imp2);
+
+       // Get node handles
+       meshlink_node_t *get_node = meshlink_get_node(mesh1, "bar");
+       assert_int_not_equal(get_node, NULL);
+       get_node = meshlink_get_node(mesh1, "nut");
+       assert_int_not_equal(get_node, NULL);
+
+       // Cleanup
+       meshlink_close(mesh1);
+       meshlink_close(mesh2);
+       meshlink_destroy("getnode1");
+       meshlink_destroy("getnode2");
+       return true;
+}
+
+/* Execute meshlink_get_node Test Case # 2 */
+static void test_case_mesh_get_node_02(void **state) {
+       execute_test(test_steps_mesh_get_node_02, state);
+}
+
+/* Test Steps for meshlink_get_node Test Case # 2
+
+    Test Steps:
+    1. Get node handles by passing NULL as mesh handle argument
+
+    Expected Result:
+    Reports error successfully by returning NULL
+*/
+static bool test_steps_mesh_get_node_02(void) {
+       meshlink_node_t *get_node = meshlink_get_node(NULL, "foo");
+       assert_int_equal(get_node, NULL);
+
+       return true;
+}
+
+/* Execute meshlink_get_node Test Case # 3 */
+static void test_case_mesh_get_node_03(void **state) {
+       execute_test(test_steps_mesh_get_node_03, state);
+}
+
+/* Test Steps for meshlink_get_node Test Case # 3
+
+    Test Steps:
+    1. Get node handles by passing NULL as node name argument
+
+    Expected Result:
+    Reports error successfully by returning NULL
+*/
+static bool test_steps_mesh_get_node_03(void) {
+       meshlink_handle_t *mesh = meshlink_open("node_conf.3", "foo", "test", DEV_CLASS_STATIONARY);
+       assert(mesh);
+       assert(meshlink_start(mesh));
+
+       meshlink_node_t *get_node = meshlink_get_node(mesh, NULL);
+       assert_int_equal(get_node, NULL);
+
+       meshlink_close(mesh);
+       meshlink_destroy("node_conf.3");
+       return true;
+}
+
+/* Execute meshlink_get_node Test Case # 4 */
+static void test_case_mesh_get_node_04(void **state) {
+       execute_test(test_steps_mesh_get_node_04, state);
+}
+
+/* Test Steps for meshlink_get_node Test Case # 4
+
+    Test Steps:
+    1. Open node instance
+    2. Get node handle with the name of the node
+        that's not in the mesh
+
+    Expected Result:
+    Reports error successfully by returning NULL
+*/
+static bool test_steps_mesh_get_node_04(void) {
+       meshlink_handle_t *mesh = meshlink_open("node_conf", "foo", "test", DEV_CLASS_STATIONARY);
+       assert(mesh);
+       assert(meshlink_start(mesh));
+
+       const char *nonexisting_node = "bar";
+       meshlink_node_t *get_node = meshlink_get_node(mesh, nonexisting_node);
+       assert_int_equal(get_node, NULL);
+
+       meshlink_close(mesh);
+       meshlink_destroy("node_conf");
+       return true;
+}
+
+int test_meshlink_get_node(void) {
+       const struct CMUnitTest blackbox_get_node_tests[] = {
+               cmocka_unit_test_prestate_setup_teardown(test_case_mesh_get_node_01, NULL, NULL,
+                               (void *)&test_mesh_get_node_01_state),
+               cmocka_unit_test_prestate_setup_teardown(test_case_mesh_get_node_02, NULL, NULL,
+                               (void *)&test_mesh_get_node_02_state),
+               cmocka_unit_test_prestate_setup_teardown(test_case_mesh_get_node_03, NULL, NULL,
+                               (void *)&test_mesh_get_node_03_state),
+               cmocka_unit_test_prestate_setup_teardown(test_case_mesh_get_node_04, NULL, NULL,
+                               (void *)&test_mesh_get_node_04_state)
+       };
+
+       total_tests += sizeof(blackbox_get_node_tests) / sizeof(blackbox_get_node_tests[0]);
+
+       return cmocka_run_group_tests(blackbox_get_node_tests, NULL, NULL);
+}
diff --git a/test/blackbox/run_blackbox_tests/test_cases_get_node.h b/test/blackbox/run_blackbox_tests/test_cases_get_node.h
new file mode 100644 (file)
index 0000000..7d5eb41
--- /dev/null
@@ -0,0 +1,28 @@
+#ifndef TEST_CASES_GET_NODE_H
+#define TEST_CASES_GET_NODE_H
+
+/*
+    test_cases_get_node.h -- Declarations for Individual Test Case implementation functions
+    Copyright (C) 2018  Guus Sliepen <guus@meshlink.io>
+
+    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 <stdbool.h>
+
+extern int test_meshlink_get_node(void);
+extern int total_tests;
+
+#endif
diff --git a/test/blackbox/run_blackbox_tests/test_cases_get_port.c b/test/blackbox/run_blackbox_tests/test_cases_get_port.c
new file mode 100644 (file)
index 0000000..177540b
--- /dev/null
@@ -0,0 +1,106 @@
+/*
+    test_cases_get_port.c -- Execution of specific meshlink black box test cases
+    Copyright (C) 2018  Guus Sliepen <guus@meshlink.io>
+
+    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 "execute_tests.h"
+#include "test_cases_get_port.h"
+#include "../common/containers.h"
+#include "../common/test_step.h"
+#include "../common/common_handlers.h"
+#include <stdlib.h>
+#include <stdarg.h>
+#include <setjmp.h>
+#include <cmocka.h>
+#include <assert.h>
+#include <string.h>
+
+static void test_case_mesh_get_port_01(void **state);
+static bool test_steps_mesh_get_port_01(void);
+static void test_case_mesh_get_port_02(void **state);
+static bool test_steps_mesh_get_port_02(void);
+
+/* State structure for meshlink_get_port Test Case #1 */
+static black_box_state_t test_mesh_get_port_01_state = {
+       .test_case_name = "test_case_mesh_get_port_01",
+};
+
+/* State structure for meshlink_get_port Test Case #2 */
+static black_box_state_t test_mesh_get_port_02_state = {
+       .test_case_name = "test_case_mesh_get_port_02",
+};
+
+/* Execute meshlink_get_port Test Case # 1 */
+static void test_case_mesh_get_port_01(void **state) {
+       execute_test(test_steps_mesh_get_port_01, state);
+}
+
+/* Test Steps for meshlink_get_port Test Case # 1
+
+    Test Steps:
+    1. Open node instance
+    2. Run the node instance
+    3. Obtain port of that mesh using meshlink_get_port API
+
+    Expected Result:
+    API returns valid port number.
+*/
+static bool test_steps_mesh_get_port_01(void) {
+       meshlink_handle_t *mesh = meshlink_open("port_conf", "foo", "chat", DEV_CLASS_STATIONARY);
+       assert(mesh);
+       assert(meshlink_start(mesh));
+
+       int port = meshlink_get_port(mesh);
+       assert_int_not_equal(port, -1);
+
+       meshlink_close(mesh);
+       meshlink_destroy("port_conf");
+       return true;
+}
+
+/* Execute meshlink_get_port Test Case # 2 */
+static void test_case_mesh_get_port_02(void **state) {
+       execute_test(test_steps_mesh_get_port_02, state);
+}
+
+/* Test Steps for meshlink_get_port Test Case # 2 - Invalid case
+
+    Test Steps:
+    1. Pass NULL as mesh handle argument to meshlink_get_port API
+
+    Expected Result:
+    Reports error successfully by returning -1
+*/
+static bool test_steps_mesh_get_port_02(void) {
+       int port = meshlink_get_port(NULL);
+       assert_int_equal(port, -1);
+
+       return true;
+}
+
+int test_meshlink_get_port(void) {
+       const struct CMUnitTest blackbox_get_port_tests[] = {
+               cmocka_unit_test_prestate_setup_teardown(test_case_mesh_get_port_01, NULL, NULL,
+                               (void *)&test_mesh_get_port_01_state),
+               cmocka_unit_test_prestate_setup_teardown(test_case_mesh_get_port_02, NULL, NULL,
+                               (void *)&test_mesh_get_port_02_state)
+       };
+
+       total_tests += sizeof(blackbox_get_port_tests) / sizeof(blackbox_get_port_tests[0]);
+
+       return cmocka_run_group_tests(blackbox_get_port_tests, NULL, NULL);
+}
diff --git a/test/blackbox/run_blackbox_tests/test_cases_get_port.h b/test/blackbox/run_blackbox_tests/test_cases_get_port.h
new file mode 100644 (file)
index 0000000..0386a8a
--- /dev/null
@@ -0,0 +1,28 @@
+#ifndef TEST_CASES_GET_PORT_H
+#define TEST_CASES_GET_PORT_H
+
+/*
+    test_cases_get_port.h -- Declarations for Individual Test Case implementation functions
+    Copyright (C) 2018  Guus Sliepen <guus@meshlink.io>
+
+    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 <stdbool.h>
+
+extern int test_meshlink_get_port(void);
+extern int total_tests;
+
+#endif
diff --git a/test/blackbox/run_blackbox_tests/test_cases_get_self.c b/test/blackbox/run_blackbox_tests/test_cases_get_self.c
new file mode 100644 (file)
index 0000000..53a0833
--- /dev/null
@@ -0,0 +1,111 @@
+/*
+    test_cases_get_port.c -- Execution of specific meshlink black box test cases
+    Copyright (C) 2018  Guus Sliepen <guus@meshlink.io>
+
+    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 "execute_tests.h"
+#include "test_cases_get_self.h"
+#include "../common/containers.h"
+#include "../common/test_step.h"
+#include "../common/common_handlers.h"
+#include <stdlib.h>
+#include <stdarg.h>
+#include <setjmp.h>
+#include <cmocka.h>
+#include <assert.h>
+#include <string.h>
+
+static void test_case_mesh_get_self_01(void **state);
+static bool test_steps_mesh_get_self_01(void);
+static void test_case_mesh_get_self_02(void **state);
+static bool test_steps_mesh_get_self_02(void);
+
+/* State structure for meshlink_get_self Test Case #1 */
+static black_box_state_t test_mesh_get_self_01_state = {
+       .test_case_name = "test_case_mesh_get_self_01",
+};
+
+/* State structure for meshlink_get_self Test Case #2 */
+static black_box_state_t test_mesh_get_self_02_state = {
+       .test_case_name = "test_case_mesh_get_self_02",
+};
+
+/* Execute meshlink_get_self Test Case # 1 */
+static void test_case_mesh_get_self_01(void **state) {
+       execute_test(test_steps_mesh_get_self_01, state);
+}
+
+/* Test Steps for meshlink_get_self Test Case # 1
+
+    Test Steps:
+    1. Open node instance
+    2. Get node's self handle
+
+    Expected Result:
+    node handle of it's own is obtained
+*/
+static bool test_steps_mesh_get_self_01(void) {
+       meshlink_handle_t *mesh = meshlink_open("self_conf", "foo", "test", DEV_CLASS_STATIONARY);
+       assert(mesh);
+
+       assert(meshlink_start(mesh));
+       meshlink_node_t *dest_node = meshlink_get_self(mesh);
+       assert_int_not_equal(dest_node, NULL);
+
+       if(strcmp(dest_node->name, "foo")) {
+               return false;
+       }
+
+       meshlink_close(mesh);
+       meshlink_destroy("self_conf");
+       return true;
+
+}
+
+/* Execute meshlink_get_self Test Case # 2 */
+static void test_case_mesh_get_self_02(void **state) {
+       execute_test(test_steps_mesh_get_self_02, state);
+}
+
+/* Test Steps for meshlink_get_self Test Case # 2
+
+    Test Steps:
+    1. Open NUT(Node Under Test) & bar meshes.
+    2. Export and Import mutually
+
+    Expected Result:
+    Both the nodes imports successfully
+*/
+static bool test_steps_mesh_get_self_02(void) {
+       meshlink_node_t *dest_node = meshlink_get_self(NULL);
+       assert_int_equal(dest_node, NULL);
+
+       return true;
+}
+
+int test_meshlink_get_self(void) {
+       const struct CMUnitTest blackbox_get_self_tests[] = {
+               cmocka_unit_test_prestate_setup_teardown(test_case_mesh_get_self_01, NULL, NULL,
+                               (void *)&test_mesh_get_self_01_state),
+               cmocka_unit_test_prestate_setup_teardown(test_case_mesh_get_self_02, NULL, NULL,
+                               (void *)&test_mesh_get_self_02_state)
+       };
+
+       total_tests += sizeof(blackbox_get_self_tests) / sizeof(blackbox_get_self_tests[0]);
+
+       return cmocka_run_group_tests(blackbox_get_self_tests, NULL, NULL);
+}
diff --git a/test/blackbox/run_blackbox_tests/test_cases_get_self.h b/test/blackbox/run_blackbox_tests/test_cases_get_self.h
new file mode 100644 (file)
index 0000000..24d7fc9
--- /dev/null
@@ -0,0 +1,28 @@
+#ifndef TEST_CASES_GET_SELF_H
+#define TEST_CASES_GET_SELF_H
+
+/*
+    test_cases_get_self.h -- Declarations for Individual Test Case implementation functions
+    Copyright (C) 2018  Guus Sliepen <guus@meshlink.io>
+
+    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 <stdbool.h>
+
+extern int test_meshlink_get_self(void);
+extern int total_tests;
+
+#endif
diff --git a/test/blackbox/run_blackbox_tests/test_cases_hint_address.c b/test/blackbox/run_blackbox_tests/test_cases_hint_address.c
new file mode 100644 (file)
index 0000000..aacbbec
--- /dev/null
@@ -0,0 +1,138 @@
+/*
+    test_cases_hint_address.c -- Execution of specific meshlink black box test cases
+    Copyright (C) 2018  Guus Sliepen <guus@meshlink.io>
+
+    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 "execute_tests.h"
+#include "test_cases_hint_address.h"
+#include "../common/containers.h"
+#include "../common/test_step.h"
+#include "../common/common_handlers.h"
+#include <assert.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <setjmp.h>
+#include <cmocka.h>
+#include <pthread.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <arpa/inet.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+
+/* Modify this to change the logging level of Meshlink */
+#define TEST_MESHLINK_LOG_LEVEL MESHLINK_DEBUG
+
+/* Port number used in the structure */
+#define PORT 8000
+
+/* hint address used in the socket structure */
+#define ADDR "10.1.1.1"
+
+static void test_case_hint_address_01(void **state);
+static bool test_steps_hint_address_01(void);
+
+static black_box_state_t test_case_hint_address_01_state = {
+       .test_case_name = "test_case_hint_address_01",
+};
+
+
+/* Execute meshlink_hint_address Test Case # 1 - Valid Case*/
+void test_case_hint_address_01(void **state) {
+       execute_test(test_steps_hint_address_01, state);
+}
+/* Test Steps for meshlink_hint_address Test Case # 1 - Valid case */
+bool test_steps_hint_address_01(void) {
+       meshlink_destroy("hintconf1");
+       meshlink_destroy("hintconf2");
+       meshlink_set_log_cb(NULL, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
+
+       // Create meshlink instance for the nodes
+       meshlink_handle_t *mesh1 = meshlink_open("hintconf1", "nut", "test", DEV_CLASS_STATIONARY);
+       assert(mesh1);
+       meshlink_handle_t *mesh2 = meshlink_open("hintconf2", "bar", "test", DEV_CLASS_STATIONARY);
+       assert(mesh2);
+       meshlink_set_log_cb(mesh1, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
+       meshlink_set_log_cb(mesh2, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
+
+       // importing and exporting mesh meta data
+       char *exp1 = meshlink_export(mesh1);
+       assert(exp1 != NULL);
+       char *exp2 = meshlink_export(mesh2);
+       assert(exp2 != NULL);
+       assert(meshlink_import(mesh1, exp2));
+       assert(meshlink_import(mesh2, exp1));
+       free(exp1);
+       free(exp2);
+
+       // Nodes should learn about each other
+       sleep(1);
+
+       // Start the nodes
+       assert(meshlink_start(mesh1));
+       assert(meshlink_start(mesh2));
+
+       // socket structure to be hinted
+       struct sockaddr_in hint;
+       hint.sin_family        = AF_INET;
+       hint.sin_port          = htons(PORT);
+       assert(inet_aton(ADDR, &hint.sin_addr));
+
+       // Getting node handle for the NUT itself
+       meshlink_node_t *node = meshlink_get_node(mesh1, "bar");
+       assert(node != NULL);
+
+       meshlink_hint_address(mesh_handle, node, (struct sockaddr *)&hint);
+
+       int fp;
+       fp = open("./hintconf1/hosts/bar", O_RDONLY);
+       assert(fp >= 0);
+       off_t fsize = lseek(fp, 0, SEEK_END);
+       assert(fsize >= 0);
+       char *buff = (char *) calloc(1, fsize + 1);
+       assert(buff != NULL);
+       assert(lseek(fp, 0, SEEK_SET) == 0);
+       assert(read(fp, buff, fsize) >= 0);
+       buff[fsize] = '\0';
+       assert(close(fp) != -1);
+
+       assert_int_not_equal(strstr(buff, ADDR), NULL);
+
+       free(buff);
+       meshlink_close(mesh1);
+       meshlink_close(mesh2);
+       meshlink_destroy("hintconf1");
+       meshlink_destroy("hintconf2");
+
+       return true;
+}
+
+
+int test_meshlink_hint_address(void) {
+       const struct CMUnitTest blackbox_hint_address_tests[] = {
+               cmocka_unit_test_prestate_setup_teardown(test_case_hint_address_01, NULL, NULL,
+                               (void *)&test_case_hint_address_01_state)
+       };
+
+       total_tests += sizeof(blackbox_hint_address_tests) / sizeof(blackbox_hint_address_tests[0]);
+
+       return cmocka_run_group_tests(blackbox_hint_address_tests, NULL, NULL);
+}
diff --git a/test/blackbox/run_blackbox_tests/test_cases_hint_address.h b/test/blackbox/run_blackbox_tests/test_cases_hint_address.h
new file mode 100644 (file)
index 0000000..e64ba5e
--- /dev/null
@@ -0,0 +1,28 @@
+#ifndef TEST_CASES_HINT_H
+#define TEST_CASES_HINT_H
+
+/*
+    test_cases_hint_address.h -- Declarations for Individual Test Case implementation functions
+    Copyright (C) 2018  Guus Sliepen <guus@meshlink.io>
+
+    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 <stdbool.h>
+
+extern int test_meshlink_hint_address(void);
+extern int total_tests;
+
+#endif
diff --git a/test/blackbox/run_blackbox_tests/test_cases_import.c b/test/blackbox/run_blackbox_tests/test_cases_import.c
new file mode 100644 (file)
index 0000000..0ab6c04
--- /dev/null
@@ -0,0 +1,316 @@
+/*
+    test_cases_import.c -- Execution of specific meshlink black box test cases
+    Copyright (C) 2018  Guus Sliepen <guus@meshlink.io>
+
+    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 "execute_tests.h"
+#include "test_cases_import.h"
+#include "../common/containers.h"
+#include "../common/test_step.h"
+#include "../common/common_handlers.h"
+#include <assert.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <setjmp.h>
+#include <cmocka.h>
+
+/* Modify this to change the logging level of Meshlink */
+#define TEST_MESHLINK_LOG_LEVEL MESHLINK_DEBUG
+
+static void test_case_import_01(void **state);
+static bool test_import_01(void);
+static void test_case_import_02(void **state);
+static bool test_import_02(void);
+static void test_case_import_03(void **state);
+static bool test_import_03(void);
+static void test_case_import_04(void **state);
+static bool test_import_04(void);
+static void test_case_import_05(void **state);
+static bool test_import_05(void);
+static void test_case_import_06(void **state);
+static bool test_import_06(void);
+
+/* State structure for import API Test Case #1 */
+static black_box_state_t test_case_import_01_state = {
+       .test_case_name = "test_case_import_01",
+};
+/* State structure for import API Test Case #2 */
+static black_box_state_t test_case_import_02_state = {
+       .test_case_name = "test_case_import_02",
+};
+/* State structure for import API Test Case #3 */
+static black_box_state_t test_case_import_03_state = {
+       .test_case_name = "test_case_import_03",
+};
+/* State structure for import API Test Case #4 */
+static black_box_state_t test_case_import_04_state = {
+       .test_case_name = "test_case_import_04",
+};
+/* State structure for import API Test Case #5 */
+static black_box_state_t test_case_import_05_state = {
+       .test_case_name = "test_case_import_05",
+};
+/* State structure for import API Test Case #6 */
+static black_box_state_t test_case_import_06_state = {
+       .test_case_name = "test_case_import_06",
+};
+
+
+/* Execute import Test Case # 1 - valid case*/
+static void test_case_import_01(void **state) {
+       execute_test(test_import_01, state);
+}
+/* Test Steps for meshlink_import Test Case # 1 - Valid case
+
+    Test Steps:
+    1. Open NUT(Node Under Test) & bar meshes.
+    2. Export and Import mutually
+
+    Expected Result:
+    Both the nodes imports successfully
+*/
+static bool test_import_01(void) {
+       meshlink_set_log_cb(NULL, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
+       meshlink_destroy("importconf1");
+       meshlink_destroy("importconf2");
+
+       // Opening NUT and bar nodes
+       meshlink_handle_t *mesh1 = meshlink_open("importconf1", "nut", "test", DEV_CLASS_STATIONARY);
+       assert(mesh1 != NULL);
+       meshlink_set_log_cb(mesh1, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
+       meshlink_handle_t *mesh2 = meshlink_open("importconf2", "bar", "test", DEV_CLASS_STATIONARY);
+       assert(mesh2 != NULL);
+       meshlink_set_log_cb(mesh2, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
+
+       // Exporting and Importing mutually
+       char *exp1 = meshlink_export(mesh1);
+       assert(exp1 != NULL);
+       char *exp2 = meshlink_export(mesh2);
+       assert(exp2 != NULL);
+       bool imp1 = meshlink_import(mesh1, exp2);
+       bool imp2 = meshlink_import(mesh2, exp1);
+
+       assert_int_equal(imp1 && imp2, true);
+
+       meshlink_close(mesh1);
+       meshlink_close(mesh2);
+       meshlink_destroy("importconf1");
+       meshlink_destroy("importconf2");
+       return imp1 && imp2;
+}
+
+/* Execute import Test Case # 2 - invalid case*/
+static void test_case_import_02(void **state) {
+       execute_test(test_import_02, state);
+}
+/* Test Steps for meshlink_import Test Case # 2 - Invalid case
+
+    Test Steps:
+    1. Open NUT(Node Under Test) & bar meshes.
+    2. Passing NULL as mesh handle argument for meshlink_import API
+
+    Expected Result:
+    Reports error successfully by returning false
+*/
+static bool test_import_02(void) {
+       meshlink_set_log_cb(NULL, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
+       meshlink_destroy("importconf1");
+       meshlink_destroy("importconf2");
+
+       // Opening NUT and bar nodes
+       meshlink_handle_t *mesh1 = meshlink_open("importconf1", "nut", "test", DEV_CLASS_STATIONARY);
+       assert(mesh1 != NULL);
+       meshlink_set_log_cb(mesh1, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
+       meshlink_handle_t *mesh2 = meshlink_open("importconf2", "bar", "test", DEV_CLASS_STATIONARY);
+       assert(mesh2 != NULL);
+       meshlink_set_log_cb(mesh2, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
+
+       // Exporting & Importing nodes
+       char *exp1 = meshlink_export(mesh1);
+       assert(exp1 != NULL);
+       char *exp2 = meshlink_export(mesh2);
+       assert(exp2 != NULL);
+
+       bool imp1 = meshlink_import(NULL, exp2);
+       bool imp2 = meshlink_import(mesh2, exp1);
+       assert_int_equal((!imp1) && imp2, true);
+
+       meshlink_close(mesh1);
+       meshlink_close(mesh2);
+       meshlink_destroy("importconf1");
+       meshlink_destroy("importconf2");
+       return true;
+}
+
+
+/* Execute import Test Case # 3 - invalid case*/
+static void test_case_import_03(void **state) {
+       execute_test(test_import_03, state);
+}
+/* Test Steps for meshlink_import Test Case # 3 - Invalid case
+
+    Test Steps:
+    1. Open NUT(Node Under Test) & bar meshes.
+    2. Passing NULL as exported data argument for meshlink_import API
+
+    Expected Result:
+    Reports error successfully by returning false
+*/
+static bool test_import_03(void) {
+       meshlink_set_log_cb(NULL, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
+
+       meshlink_destroy("importconf1");
+       meshlink_destroy("importconf2");
+
+       /* Opening NUT and bar nodes */
+       meshlink_handle_t *mesh1 = meshlink_open("importconf1", "nut", "chat", DEV_CLASS_STATIONARY);
+       assert(mesh1 != NULL);
+       meshlink_set_log_cb(mesh1, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
+       meshlink_handle_t *mesh2 = meshlink_open("importconf2", "bar", "chat", DEV_CLASS_STATIONARY);
+       assert(mesh2 != NULL);
+       meshlink_set_log_cb(mesh2, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
+
+       /* Exporting & Importing nodes */
+       char *exp1 = meshlink_export(mesh1);
+       assert(exp1 != NULL);
+       char *exp2 = meshlink_export(mesh2);
+       assert(exp2 != NULL);
+
+       bool imp1 = meshlink_import(mesh1, NULL);
+       bool imp2 = meshlink_import(mesh2, exp1);
+
+       assert_int_equal((!imp1) && imp2, true);
+
+       meshlink_close(mesh1);
+       meshlink_close(mesh2);
+       meshlink_destroy("importconf1");
+       meshlink_destroy("importconf2");
+       return true;
+}
+
+/* Execute import Test Case # 4 - invalid case garbage string*/
+static void test_case_import_04(void **state) {
+       execute_test(test_import_04, state);
+}
+/* Test Steps for meshlink_import Test Case # 4 - Invalid case
+
+    Test Steps:
+    1. Open NUT(Node Under Test) & bar meshes.
+    2. Passing some garbage string(NULL terminated)
+        as an argument for meshlink_import API
+
+    Expected Result:
+    Reports error successfully by returning false
+*/
+static bool test_import_04(void) {
+       meshlink_set_log_cb(NULL, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
+       meshlink_destroy("importconf1");
+       meshlink_destroy("importconf2");
+
+       // Opening NUT and bar nodes
+       meshlink_handle_t *mesh1 = meshlink_open("importconf1", "nut", "chat", DEV_CLASS_STATIONARY);
+       assert(mesh1 != NULL);
+       meshlink_set_log_cb(mesh1, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
+       meshlink_handle_t *mesh2 = meshlink_open("importconf2", "bar", "chat", DEV_CLASS_STATIONARY);
+       assert(mesh2 != NULL);
+       meshlink_set_log_cb(mesh2, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
+
+       // Exporting & Importing nodes
+       char *exp1 = meshlink_export(mesh1);
+       assert(exp1 != NULL);
+       char *exp2 = meshlink_export(mesh2);
+       assert(exp2 != NULL);
+
+       // Importing NUT with garbage string as exported data argument
+       bool imp1 = meshlink_import(mesh1, "1/2/3");
+       bool imp2 = meshlink_import(mesh2, exp1);
+       assert_int_equal((!imp1) && imp2, true);
+
+       meshlink_close(mesh1);
+       meshlink_close(mesh2);
+       meshlink_destroy("importconf1");
+       meshlink_destroy("importconf2");
+       return true;
+}
+
+/* Execute import Test Case # 5 - valid case*/
+static void test_case_import_05(void **state) {
+       execute_test(test_import_05, state);
+}
+/* Test Steps for meshlink_import Test Case # 5 - Invalid case
+
+    Test Steps:
+    1. Open NUT(Node Under Test) & bar meshes.
+    2. Export and Import mutually
+    2. Try to import NUT again/twice at 'bar' node
+
+    Expected Result:
+    Reports error successfully by returning false
+*/
+static bool test_import_05(void) {
+       meshlink_set_log_cb(NULL, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
+       meshlink_destroy("importconf1");
+       meshlink_destroy("importconf2");
+
+       /* Opening NUT and bar nodes */
+       meshlink_handle_t *mesh1 = meshlink_open("importconf1", "nut", "chat", DEV_CLASS_STATIONARY);
+       assert(mesh1 != NULL);
+       meshlink_set_log_cb(mesh1, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
+       meshlink_handle_t *mesh2 = meshlink_open("importconf2", "bar", "chat", DEV_CLASS_STATIONARY);
+       assert(mesh2 != NULL);
+       meshlink_set_log_cb(mesh2, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
+
+       /* Exporting  & Importing nodes */
+       char *exp1 = meshlink_export(mesh1);
+       assert(exp1 != NULL);
+       char *exp2 = meshlink_export(mesh2);
+       assert(exp2 != NULL);
+       bool imp1 = meshlink_import(mesh1, exp2);
+       assert(imp1);
+       bool imp2 = meshlink_import(mesh2, exp1);
+       assert(imp2);
+
+       /** Trying to import twice **/
+       bool imp3 = meshlink_import(mesh2, exp1);
+
+       assert_int_equal(imp3, false);
+
+       meshlink_close(mesh1);
+       meshlink_close(mesh2);
+       meshlink_destroy("importconf1");
+       meshlink_destroy("importconf2");
+       return true;
+}
+
+int test_meshlink_import(void) {
+       const struct CMUnitTest blackbox_import_tests[] = {
+               cmocka_unit_test_prestate_setup_teardown(test_case_import_01, NULL, NULL,
+                               (void *)&test_case_import_01_state),
+               cmocka_unit_test_prestate_setup_teardown(test_case_import_02, NULL, NULL,
+                               (void *)&test_case_import_02_state),
+               cmocka_unit_test_prestate_setup_teardown(test_case_import_03, NULL, NULL,
+                               (void *)&test_case_import_03_state),
+               cmocka_unit_test_prestate_setup_teardown(test_case_import_04, NULL, NULL,
+                               (void *)&test_case_import_04_state),
+               cmocka_unit_test_prestate_setup_teardown(test_case_import_05, NULL, NULL,
+                               (void *)&test_case_import_05_state)
+       };
+       total_tests += sizeof(blackbox_import_tests) / sizeof(blackbox_import_tests[0]);
+
+       return cmocka_run_group_tests(blackbox_import_tests, NULL, NULL);
+}
diff --git a/test/blackbox/run_blackbox_tests/test_cases_import.h b/test/blackbox/run_blackbox_tests/test_cases_import.h
new file mode 100644 (file)
index 0000000..4316b93
--- /dev/null
@@ -0,0 +1,28 @@
+#ifndef TEST_CASES_IMPORT_H
+#define TEST_CASES_IMPORT_H
+
+/*
+    test_cases_import.h -- Declarations for Individual Test Case implementation functions
+    Copyright (C) 2018  Guus Sliepen <guus@meshlink.io>
+
+    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 <stdbool.h>
+
+extern int test_meshlink_import(void);
+extern int total_tests;
+
+#endif
diff --git a/test/blackbox/run_blackbox_tests/test_cases_invite.c b/test/blackbox/run_blackbox_tests/test_cases_invite.c
new file mode 100644 (file)
index 0000000..c0f13c5
--- /dev/null
@@ -0,0 +1,200 @@
+/*
+    test_cases_invite.c -- Execution of specific meshlink black box test cases
+    Copyright (C) 2018  Guus Sliepen <guus@meshlink.io>
+
+    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 "execute_tests.h"
+#include "test_cases_invite.h"
+#include "../common/containers.h"
+#include "../common/test_step.h"
+#include "../common/common_handlers.h"
+#include <assert.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <setjmp.h>
+#include <cmocka.h>
+
+/* Modify this to change the logging level of Meshlink */
+#define TEST_MESHLINK_LOG_LEVEL MESHLINK_DEBUG
+
+static void test_case_invite_01(void **state);
+static bool test_invite_01(void);
+static void test_case_invite_02(void **state);
+static bool test_invite_02(void);
+static void test_case_invite_03(void **state);
+static bool test_invite_03(void);
+static void test_case_invite_04(void **state);
+static bool test_invite_04(void);
+
+/* State structure for invite API Test Case #1 */
+static black_box_state_t test_case_invite_01_state = {
+       .test_case_name = "test_case_invite_01",
+};
+
+/* State structure for invite API Test Case #2 */
+static black_box_state_t test_case_invite_02_state = {
+       .test_case_name = "test_case_invite_02",
+};
+
+/* State structure for invite API Test Case #3 */
+static black_box_state_t test_case_invite_03_state = {
+       .test_case_name = "test_case_invite_03",
+};
+
+/* State structure for invite API Test Case #4 */
+static black_box_state_t test_case_invite_04_state = {
+       .test_case_name = "test_case_invite_04",
+};
+
+/* Execute invite Test Case # 1 - valid case*/
+static void test_case_invite_01(void **state) {
+       execute_test(test_invite_01, state);
+}
+/*Test Steps for meshlink_invite Test Case # 1 - Valid case
+    Test Steps:
+    1. Run NUT
+    2. Invite 'new' node
+
+    Expected Result:
+    Generates an invitation
+*/
+static bool test_invite_01(void) {
+       meshlink_destroy("inviteconf");
+       meshlink_set_log_cb(NULL, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
+
+       // Create meshlink instance
+       meshlink_handle_t *mesh_handle = meshlink_open("inviteconf", "nut", "node_sim", 1);
+       assert(mesh_handle);
+       meshlink_set_log_cb(mesh_handle, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
+
+       char *invitation = meshlink_invite(mesh_handle, "new");
+       assert_int_equal(invitation, NULL);
+
+       free(invitation);
+       meshlink_close(mesh_handle);
+       meshlink_destroy("inviteconf");
+       return true;
+}
+
+/* Execute invite Test Case # 2 - Invalid case*/
+static void test_case_invite_02(void **state) {
+       execute_test(test_invite_02, state);
+}
+/*Test Steps for meshlink_invite Test Case # 2 - Invalid case
+    Test Steps:
+    1. Calling meshlink_invite API with NULL as mesh handle argument
+
+    Expected Result:
+    Reports appropriate error by returning NULL
+*/
+static bool test_invite_02(void) {
+       // Trying to generate INVITATION by passing NULL as mesh link handle
+       char *invitation = meshlink_invite(NULL, "nut");
+       assert_int_equal(invitation, NULL);
+
+       return true;
+}
+
+/* Execute invite Test Case # 3 - Invalid case*/
+static void test_case_invite_03(void **state) {
+       execute_test(test_invite_03, state);
+}
+/*Test Steps for meshlink_invite Test Case # 3 - Invalid case
+    Test Steps:
+    1. Run NUT
+    2. Call meshlink_invite with NULL node name argument
+
+    Expected Result:
+    Reports appropriate error by returning NULL
+*/
+static bool test_invite_03(void) {
+       meshlink_destroy("inviteconf");
+       meshlink_set_log_cb(NULL, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
+
+       // Create meshlink instance
+       meshlink_handle_t *mesh_handle = meshlink_open("inviteconf", "nut", "node_sim", 1);
+       assert(mesh_handle);
+       meshlink_set_log_cb(mesh_handle, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
+
+       // Trying to generate INVITATION by passing NULL as mesh link handle
+       char *invitation = meshlink_invite(mesh_handle, NULL);
+       assert_int_equal(invitation, NULL);
+
+       meshlink_close(mesh_handle);
+       meshlink_destroy("inviteconf");
+       return true;
+}
+
+/* Execute invite Test Case # 4 - Functionality test*/
+static void test_case_invite_04(void **state) {
+       execute_test(test_invite_04, state);
+}
+/*Test Steps for meshlink_invite Test Case # 4 - Functionality test
+
+    Test Steps:
+    1. Create node instance
+    2. Add a new address to the mesh and invite a node
+    3. Add another new address and invite a node
+
+    Expected Result:
+    Newly added address should be there in the invitation.
+*/
+static bool test_invite_04(void) {
+       meshlink_destroy("inviteconf");
+       meshlink_set_log_cb(NULL, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
+
+       // Create meshlink instance
+       meshlink_handle_t *mesh_handle = meshlink_open("inviteconf", "nut", "test", 1);
+       assert(mesh_handle);
+       meshlink_set_log_cb(mesh_handle, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
+
+       char *hostname1 = "127.1.1.1";
+       bool ret = meshlink_add_address(mesh_handle, hostname1);
+       char *invitation = meshlink_invite(mesh_handle, "foo");
+       assert_int_not_equal(strstr(invitation, hostname1), NULL);
+
+       char *hostname2 = "127.1.2.3";
+       ret = meshlink_add_address(mesh_handle, hostname2);
+       invitation = meshlink_invite(mesh_handle, "bar");
+
+       // Verify we have both the added addresses
+       assert_int_not_equal(strstr(invitation, hostname1), NULL);
+       assert_int_not_equal(strstr(invitation, hostname2), NULL);
+
+       meshlink_close(mesh_handle);
+       meshlink_destroy("inviteconf");
+
+       return true;
+}
+
+int test_meshlink_invite(void) {
+       const struct CMUnitTest blackbox_invite_tests[] = {
+               cmocka_unit_test_prestate_setup_teardown(test_case_invite_01, NULL, NULL,
+                               (void *)&test_case_invite_01_state),
+               cmocka_unit_test_prestate_setup_teardown(test_case_invite_02, NULL, NULL,
+                               (void *)&test_case_invite_02_state),
+               cmocka_unit_test_prestate_setup_teardown(test_case_invite_03, NULL, NULL,
+                               (void *)&test_case_invite_03_state),
+               cmocka_unit_test_prestate_setup_teardown(test_case_invite_04, NULL, NULL,
+                               (void *)&test_case_invite_04_state)
+       };
+
+       total_tests += sizeof(blackbox_invite_tests) / sizeof(blackbox_invite_tests[0]);
+
+       return cmocka_run_group_tests(blackbox_invite_tests, NULL, NULL);
+}
diff --git a/test/blackbox/run_blackbox_tests/test_cases_invite.h b/test/blackbox/run_blackbox_tests/test_cases_invite.h
new file mode 100644 (file)
index 0000000..e8c06c7
--- /dev/null
@@ -0,0 +1,28 @@
+#ifndef TEST_CASES_INVITE_H
+#define TEST_CASES_INVITE_H
+
+/*
+    test_cases_invite.h -- Declarations for Individual Test Case implementation functions
+    Copyright (C) 2018  Guus Sliepen <guus@meshlink.io>
+
+    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 <stdbool.h>
+
+extern int total_tests;
+extern int test_meshlink_invite(void);
+
+#endif
diff --git a/test/blackbox/run_blackbox_tests/test_cases_join.c b/test/blackbox/run_blackbox_tests/test_cases_join.c
new file mode 100644 (file)
index 0000000..9df001a
--- /dev/null
@@ -0,0 +1,204 @@
+/*
+    test_cases_join.c -- Execution of specific meshlink black box test cases
+    Copyright (C) 2018  Guus Sliepen <guus@meshlink.io>
+
+    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 "execute_tests.h"
+#include "test_cases_join.h"
+#include "../common/containers.h"
+#include "../common/test_step.h"
+#include "../common/common_handlers.h"
+#include <assert.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <setjmp.h>
+#include <cmocka.h>
+#include <pthread.h>
+
+/* Modify this to change the logging level of Meshlink */
+#define TEST_MESHLINK_LOG_LEVEL MESHLINK_DEBUG
+
+static void test_case_meshlink_join_01(void **state);
+static bool test_meshlink_join_01(void);
+static void test_case_meshlink_join_02(void **state);
+static bool test_meshlink_join_02(void);
+static void test_case_meshlink_join_03(void **state);
+static bool test_meshlink_join_03(void);
+static void test_case_meshlink_join_04(void **state);
+static bool test_meshlink_join_04(void);
+
+/* State structure for join Test Case #1 */
+static black_box_state_t test_case_join_01_state = {
+       .test_case_name = "test_case_join_01",
+};
+
+/* State structure for join Test Case #1 */
+static black_box_state_t test_case_join_02_state = {
+       .test_case_name = "test_case_join_02",
+};
+
+/* State structure for join Test Case #1 */
+static black_box_state_t test_case_join_03_state = {
+       .test_case_name = "test_case_join_03",
+};
+
+static bool join_status;
+
+/* status callback */
+static void status_callback(meshlink_handle_t *mesh, meshlink_node_t *source, bool reach) {
+       (void)mesh;
+
+       if(!strcmp(source->name, "relay")) {
+               join_status = reach;
+       }
+}
+
+/* Execute join Test Case # 1 - valid case*/
+static void test_case_meshlink_join_01(void **state) {
+       execute_test(test_meshlink_join_01, state);
+}
+
+/* Test Steps for meshlink_join Test Case # 1 - Valid case
+
+    Test Steps:
+    1. Generate invite in relay container and run 'relay' node
+    2. Run NUT
+    3. Join NUT with relay using invitation generated.
+
+    Expected Result:
+    NUT joins relay using the invitation generated.
+*/
+static bool test_meshlink_join_01(void) {
+       meshlink_destroy("join_conf.1");
+       meshlink_destroy("join_conf.2");
+
+       // Create node instances
+       meshlink_handle_t *mesh1 = meshlink_open("join_conf.1", "nut", "test", DEV_CLASS_STATIONARY);
+       assert(mesh1 != NULL);
+       meshlink_set_log_cb(mesh1, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
+       meshlink_handle_t *mesh2 = meshlink_open("join_conf.2", "relay", "test", DEV_CLASS_STATIONARY);
+       assert(mesh2 != NULL);
+       meshlink_set_log_cb(mesh2, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
+
+       // Setting node status callback
+       meshlink_set_node_status_cb(mesh1, status_callback);
+
+       // Inviting nut
+       meshlink_start(mesh2);
+       char *invitation = meshlink_invite(mesh2, "nut");
+       assert(invitation);
+
+       // Joining Node-Under-Test with relay
+       bool ret = meshlink_join(mesh1, invitation);
+       assert_int_equal(ret, true);
+       assert(meshlink_start(mesh1));
+       sleep(1);
+
+       assert_int_equal(join_status, true);
+
+       free(invitation);
+       meshlink_close(mesh1);
+       meshlink_close(mesh2);
+       meshlink_destroy("join_conf.1");
+       meshlink_destroy("join_conf.2");
+
+       return true;
+}
+
+/* Execute join Test Case # 2 - Invalid case*/
+static void test_case_meshlink_join_02(void **state) {
+       execute_test(test_meshlink_join_02, state);
+}
+
+/* Test Steps for meshlink_join Test Case # 2 - Invalid case
+
+    Test Steps:
+    1. Call meshlink_join with NULL as mesh handler argument.
+
+    Expected Result:
+    report error accordingly when NULL is passed as mesh handle argument
+*/
+static bool test_meshlink_join_02(void) {
+       meshlink_destroy("join_conf.3");
+
+       // Create node instances
+       meshlink_handle_t *mesh1 = meshlink_open("join_conf.3", "nut", "test", DEV_CLASS_STATIONARY);
+       assert(mesh1 != NULL);
+       meshlink_set_log_cb(mesh1, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
+
+       char *invitation = meshlink_invite(mesh1, "nodex");
+
+       /* meshlink_join called with NULL as mesh handle and with valid invitation */
+       bool ret = meshlink_join(NULL, invitation);
+       assert_int_equal(ret, false);
+
+       free(invitation);
+       meshlink_close(mesh1);
+       meshlink_destroy("join_conf.3");
+
+       return true;
+}
+
+/* Execute join Test Case # 3- Invalid case*/
+static void test_case_meshlink_join_03(void **state) {
+       execute_test(test_meshlink_join_03, state);
+}
+
+/* Test Steps for meshlink_join Test Case # 3 - Invalid case
+
+    Test Steps:
+    1. Run NUT
+    1. Call meshlink_join with NULL as invitation argument.
+
+    Expected Result:
+    Report error accordingly when NULL is passed as invite argument
+*/
+static bool test_meshlink_join_03(void) {
+       meshlink_destroy("joinconf.4");
+       meshlink_set_log_cb(NULL, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
+
+       /* Create meshlink instance */
+       mesh_handle = meshlink_open("joinconf.4", "nut", "node_sim", 1);
+       assert(mesh_handle);
+       meshlink_set_log_cb(mesh_handle, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
+
+       /* Passing NULL as invitation to join API*/
+       bool ret  = meshlink_join(mesh_handle, NULL);
+       assert_int_equal(ret, false);
+
+       meshlink_close(mesh_handle);
+       meshlink_destroy("joinconf.4");
+       return true;
+}
+
+int test_meshlink_join(void) {
+       const struct CMUnitTest blackbox_join_tests[] = {
+               cmocka_unit_test_prestate_setup_teardown(test_case_meshlink_join_01, NULL, NULL,
+                               (void *)&test_case_join_01_state),
+               cmocka_unit_test_prestate_setup_teardown(test_case_meshlink_join_02, NULL, NULL,
+                               (void *)&test_case_join_02_state),
+               cmocka_unit_test_prestate_setup_teardown(test_case_meshlink_join_03, NULL, NULL,
+                               (void *)&test_case_join_03_state)
+       };
+       total_tests += sizeof(blackbox_join_tests) / sizeof(blackbox_join_tests[0]);
+
+       int failed = cmocka_run_group_tests(blackbox_join_tests, NULL, NULL);
+
+       return failed;
+}
+
diff --git a/test/blackbox/run_blackbox_tests/test_cases_join.h b/test/blackbox/run_blackbox_tests/test_cases_join.h
new file mode 100644 (file)
index 0000000..c10af0f
--- /dev/null
@@ -0,0 +1,29 @@
+#ifndef TEST_CASES_JOIN_H
+#define TEST_CASES_JOIN_H
+
+/*
+    test_cases_join.h -- Declarations for Individual Test Case implementation functions
+    Copyright (C) 2018  Guus Sliepen <guus@meshlink.io>
+
+    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 <stdbool.h>
+
+extern int test_meshlink_join(void);
+extern int total_tests;
+
+
+#endif
diff --git a/test/blackbox/run_blackbox_tests/test_cases_open.c b/test/blackbox/run_blackbox_tests/test_cases_open.c
new file mode 100644 (file)
index 0000000..2655376
--- /dev/null
@@ -0,0 +1,198 @@
+/*
+    test_cases_open.c -- Execution of specific meshlink black box test cases
+    Copyright (C) 2018  Guus Sliepen <guus@meshlink.io>
+
+    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 "execute_tests.h"
+#include "test_cases_open.h"
+#include "../common/containers.h"
+#include "../common/test_step.h"
+#include "../common/common_handlers.h"
+#include <stdlib.h>
+#include <stdarg.h>
+#include <setjmp.h>
+#include <cmocka.h>
+#include <assert.h>
+#include <string.h>
+
+/* Modify this to change the logging level of Meshlink */
+#define TEST_MESHLINK_LOG_LEVEL MESHLINK_DEBUG
+
+static void test_case_mesh_open_01(void **state);
+static bool test_steps_mesh_open_01(void);
+static void test_case_mesh_open_02(void **state);
+static bool test_steps_mesh_open_02(void);
+static void test_case_mesh_open_03(void **state);
+static bool test_steps_mesh_open_03(void);
+static void test_case_mesh_open_04(void **state);
+static bool test_steps_mesh_open_04(void);
+static void test_case_mesh_open_05(void **state);
+static bool test_steps_mesh_open_05(void);
+
+/* State structure for meshlink_open Test Case #1 */
+static black_box_state_t test_mesh_open_01_state = {
+       .test_case_name = "test_case_mesh_open_01",
+};
+
+/* State structure for meshlink_open Test Case #2 */
+static black_box_state_t test_mesh_open_02_state = {
+       .test_case_name = "test_case_mesh_open_02",
+};
+
+/* State structure for meshlink_open Test Case #3 */
+static black_box_state_t test_mesh_open_03_state = {
+       .test_case_name = "test_case_mesh_open_03",
+};
+
+/* State structure for meshlink_open Test Case #4 */
+static black_box_state_t test_mesh_open_04_state = {
+       .test_case_name = "test_case_mesh_open_04",
+};
+
+/* State structure for meshlink_open Test Case #5 */
+static black_box_state_t test_mesh_open_05_state = {
+       .test_case_name = "test_case_mesh_open_05",
+};
+
+/* Execute meshlink_open Test Case # 1*/
+static void test_case_mesh_open_01(void **state) {
+       execute_test(test_steps_mesh_open_01, state);
+}
+
+/* Test Steps for meshlink_open Test Case # 1
+
+    Test Steps:
+    1. Open the node instance using meshlink_open
+
+    Expected Result:
+    meshlink_open API should successfully return a mesh handle.
+*/
+static bool test_steps_mesh_open_01(void) {
+       meshlink_set_log_cb(NULL, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
+       meshlink_handle_t *mesh = meshlink_open("open_conf", "foo", "test", DEV_CLASS_STATIONARY);
+       assert_int_not_equal(mesh, NULL);
+
+       meshlink_close(mesh);
+       meshlink_destroy("open_conf");
+       return true;
+}
+
+/* Execute meshlink_open Test Case # 2*/
+static void test_case_mesh_open_02(void **state) {
+       execute_test(test_steps_mesh_open_02, state);
+}
+
+/* Test Steps for meshlink_open Test Case # 2
+
+    Test Steps:
+    1. Open the node instance using meshlink_open with NULL as confbase argument
+
+    Expected Result:
+    meshlink_open API should successfully report error by returning NULL pointer
+*/
+static bool test_steps_mesh_open_02(void) {
+       meshlink_set_log_cb(NULL, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
+       meshlink_handle_t *mesh = meshlink_open(NULL, "foo", "test", DEV_CLASS_STATIONARY);
+       assert_int_equal(mesh, NULL);
+
+       return true;
+}
+
+/* Execute meshlink_open Test Case # 3 */
+static void test_case_mesh_open_03(void **state) {
+       execute_test(test_steps_mesh_open_03, state);
+}
+
+/* Test Steps for meshlink_open Test Case # 3
+
+    Test Steps:
+    1. Open the node instance using meshlink_open with NULL as node name argument
+
+    Expected Result:
+    meshlink_open API should successfully report error by returning NULL pointer
+*/
+static bool test_steps_mesh_open_03(void) {
+       meshlink_set_log_cb(NULL, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
+       meshlink_handle_t *mesh = meshlink_open("openconf", NULL, "test", DEV_CLASS_STATIONARY);
+       assert_int_equal(mesh, NULL);
+
+       meshlink_destroy("open_conf");
+       return true;
+}
+
+/* Execute meshlink_open Test Case # 4*/
+static void test_case_mesh_open_04(void **state) {
+       execute_test(test_steps_mesh_open_04, state);
+}
+
+/* Test Steps for meshlink_open Test Case # 4
+
+    Test Steps:
+    1. Open the node instance using meshlink_open with NULL as app name argument
+
+    Expected Result:
+    meshlink_open API should successfully report error by returning NULL pointer
+*/
+static bool test_steps_mesh_open_04(void) {
+       meshlink_set_log_cb(NULL, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
+       meshlink_handle_t *mesh = meshlink_open("openconf", "foo", NULL, DEV_CLASS_STATIONARY);
+       assert_int_equal(mesh, NULL);
+
+       meshlink_destroy("open_conf");
+       return true;
+}
+
+/* Execute meshlink_open Test Case # 5*/
+static void test_case_mesh_open_05(void **state) {
+       execute_test(test_steps_mesh_open_05, state);
+}
+
+/* Test Steps for meshlink_open Test Case # 5
+
+    Test Steps:
+    1. Open the node instance using meshlink_open with invalid device class argument
+
+    Expected Result:
+    meshlink_open API should successfully report error by returning NULL pointer
+*/
+static bool test_steps_mesh_open_05(void) {
+       meshlink_set_log_cb(NULL, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
+       meshlink_handle_t *mesh = meshlink_open("openconf", "foo", "test", -1);
+       assert_int_equal(mesh, NULL);
+
+       meshlink_destroy("open_conf");
+       return true;
+}
+
+int test_meshlink_open(void) {
+       const struct CMUnitTest blackbox_open_tests[] = {
+               cmocka_unit_test_prestate_setup_teardown(test_case_mesh_open_01, NULL, NULL,
+                               (void *)&test_mesh_open_01_state),
+               cmocka_unit_test_prestate_setup_teardown(test_case_mesh_open_02, NULL, NULL,
+                               (void *)&test_mesh_open_02_state),
+               cmocka_unit_test_prestate_setup_teardown(test_case_mesh_open_03, NULL, NULL,
+                               (void *)&test_mesh_open_03_state),
+               cmocka_unit_test_prestate_setup_teardown(test_case_mesh_open_04, NULL, NULL,
+                               (void *)&test_mesh_open_04_state),
+               cmocka_unit_test_prestate_setup_teardown(test_case_mesh_open_05, NULL, NULL,
+                               (void *)&test_mesh_open_05_state)
+
+       };
+       total_tests += sizeof(blackbox_open_tests) / sizeof(blackbox_open_tests[0]);
+
+       return cmocka_run_group_tests(blackbox_open_tests, NULL, NULL);
+}
diff --git a/test/blackbox/run_blackbox_tests/test_cases_open.h b/test/blackbox/run_blackbox_tests/test_cases_open.h
new file mode 100644 (file)
index 0000000..0c3f7d9
--- /dev/null
@@ -0,0 +1,28 @@
+#ifndef TEST_CASES_OPEN_H
+#define TEST_CASES_OPEN_H
+
+/*
+    test_cases_open.h -- Declarations for Individual Test Case implementation functions
+    Copyright (C) 2018  Guus Sliepen <guus@meshlink.io>
+
+    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 <stdbool.h>
+
+extern int test_meshlink_open(void);
+extern int total_tests;
+
+#endif // TEST_STEP_OPEN_H
diff --git a/test/blackbox/run_blackbox_tests/test_cases_pmtu.c b/test/blackbox/run_blackbox_tests/test_cases_pmtu.c
new file mode 100644 (file)
index 0000000..0a037d8
--- /dev/null
@@ -0,0 +1,155 @@
+/*
+    test_cases_pmtu.c -- Execution of specific meshlink black box test cases
+    Copyright (C) 2018  Guus Sliepen <guus@meshlink.io>
+
+    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 "execute_tests.h"
+#include "test_cases_pmtu.h"
+#include "../common/containers.h"
+#include "../common/test_step.h"
+#include "../common/common_handlers.h"
+#include <stdlib.h>
+#include <stdarg.h>
+#include <setjmp.h>
+#include <cmocka.h>
+#include <assert.h>
+#include <string.h>
+
+static void test_case_mesh_pmtu_01(void **state);
+static bool test_steps_mesh_pmtu_01(void);
+static void test_case_mesh_pmtu_02(void **state);
+static bool test_steps_mesh_pmtu_02(void);
+static void test_case_mesh_pmtu_03(void **state);
+static bool test_steps_mesh_pmtu_03(void);
+
+/* State structure for meshlink_get_pmtu Test Case #1 */
+static black_box_state_t test_mesh_pmtu_01_state = {
+       .test_case_name = "test_case_mesh_pmtu_01",
+};
+
+/* State structure for meshlink_get_pmtu Test Case #2 */
+static black_box_state_t test_mesh_pmtu_02_state = {
+       .test_case_name = "test_case_mesh_pmtu_02",
+};
+
+/* State structure for meshlink_get_pmtu Test Case #3 */
+static black_box_state_t test_mesh_pmtu_03_state = {
+       .test_case_name = "test_case_mesh_pmtu_03",
+};
+
+/* Execute meshlink_get_pmtu Test Case # 1 */
+static void test_case_mesh_pmtu_01(void **state) {
+       execute_test(test_steps_mesh_pmtu_01, state);
+}
+
+/* Test Steps for meshlink_get_pmtu Test Case # 1
+
+    Test Steps:
+    1. Create node instance & get self handle
+    2. Obtain MTU size
+
+    Expected Result:
+    meshlink_get_pmtu should return valid MTU size of a node
+*/
+static bool test_steps_mesh_pmtu_01(void) {
+       meshlink_handle_t *mesh = meshlink_open("pmtu_conf", "foo", "test", DEV_CLASS_STATIONARY);
+       assert(mesh != NULL);
+
+       assert(meshlink_start(mesh));
+       meshlink_node_t *dest_node = meshlink_get_self(mesh);
+       assert(dest_node != NULL);
+
+       ssize_t pmtu = meshlink_get_pmtu(mesh, dest_node);
+       assert_int_not_equal(pmtu, -1);
+
+       meshlink_close(mesh);
+       meshlink_destroy("pmtu_conf");
+       return true;
+}
+
+/* Execute meshlink_get_pmtu Test Case # 2
+
+    Test Steps:
+    1. Create node instance & get self handle
+    2. Try to obtain MTU size by passing NULL as mesh handle to API
+
+    Expected Result:
+    meshlink_get_pmtu should return -1 reporting the error
+*/
+static void test_case_mesh_pmtu_02(void **state) {
+       execute_test(test_steps_mesh_pmtu_02, state);
+}
+
+/* Test Steps for meshlink_get_pmtu Test Case # 2*/
+static bool test_steps_mesh_pmtu_02(void) {
+       meshlink_handle_t *mesh = meshlink_open("pmtu_conf", "foo", "test", DEV_CLASS_STATIONARY);
+       assert(mesh != NULL);
+
+       assert(meshlink_start(mesh));
+       meshlink_node_t *dest_node = meshlink_get_self(mesh);
+       assert(dest_node != NULL);
+
+       ssize_t pmtu = meshlink_get_pmtu(NULL, dest_node);
+       assert_int_equal(pmtu, -1);
+
+       meshlink_close(mesh);
+       meshlink_destroy("pmtu_conf");
+       return true;
+}
+
+/* Execute meshlink_get_pmtu Test Case # 3 */
+static void test_case_mesh_pmtu_03(void **state) {
+       execute_test(test_steps_mesh_pmtu_03, state);
+}
+
+/* Test Steps for meshlink_get_pmtu Test Case # 3
+
+    Test Steps:
+    1. Create node instance & get self handle
+    2. Try to obtain MTU size by passing NULL as node handle to API
+
+    Expected Result:
+    meshlink_get_pmtu should return -1 reporting the error
+*/
+static bool test_steps_mesh_pmtu_03(void) {
+       meshlink_handle_t *mesh = meshlink_open("pmtu_conf", "foo", "test", DEV_CLASS_STATIONARY);
+       assert(mesh != NULL);
+
+       assert(meshlink_start(mesh));
+
+       ssize_t pmtu = meshlink_get_pmtu(mesh, NULL);
+       assert_int_equal(pmtu, -1);
+
+       meshlink_close(mesh);
+       meshlink_destroy("pmtu_conf");
+       return true;
+}
+
+int test_meshlink_pmtu(void) {
+       const struct CMUnitTest blackbox_pmtu_tests[] = {
+               cmocka_unit_test_prestate_setup_teardown(test_case_mesh_pmtu_01, NULL, NULL,
+                               (void *)&test_mesh_pmtu_01_state),
+               cmocka_unit_test_prestate_setup_teardown(test_case_mesh_pmtu_02, NULL, NULL,
+                               (void *)&test_mesh_pmtu_02_state),
+               cmocka_unit_test_prestate_setup_teardown(test_case_mesh_pmtu_03, NULL, NULL,
+                               (void *)&test_mesh_pmtu_03_state)
+       };
+
+       total_tests += sizeof(blackbox_pmtu_tests) / sizeof(blackbox_pmtu_tests[0]);
+
+       return cmocka_run_group_tests(blackbox_pmtu_tests, NULL, NULL);
+}
diff --git a/test/blackbox/run_blackbox_tests/test_cases_pmtu.h b/test/blackbox/run_blackbox_tests/test_cases_pmtu.h
new file mode 100644 (file)
index 0000000..db9b5cd
--- /dev/null
@@ -0,0 +1,28 @@
+#ifndef TEST_CASES_PMTU_H
+#define TEST_CASES_PMTU_H
+
+/*
+    test_cases_pmtu.h -- Declarations for Individual Test Case implementation functions
+    Copyright (C) 2018  Guus Sliepen <guus@meshlink.io>
+
+    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 <stdbool.h>
+
+extern int test_meshlink_pmtu(void);
+extern int total_tests;
+
+#endif
diff --git a/test/blackbox/run_blackbox_tests/test_cases_rec_cb.c b/test/blackbox/run_blackbox_tests/test_cases_rec_cb.c
new file mode 100644 (file)
index 0000000..f9ec477
--- /dev/null
@@ -0,0 +1,206 @@
+/*
+    test_cases_rec_cb.c -- Execution of specific meshlink black box test cases
+    Copyright (C) 2018  Guus Sliepen <guus@meshlink.io>
+
+    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 "execute_tests.h"
+#include "test_cases.h"
+#include "../common/containers.h"
+#include "../common/test_step.h"
+#include "../common/common_handlers.h"
+#include "test_cases_rec_cb.h"
+#include <assert.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <setjmp.h>
+#include <cmocka.h>
+#include <pthread.h>
+
+
+/* Modify this to change the logging level of Meshlink */
+#define TEST_MESHLINK_LOG_LEVEL MESHLINK_DEBUG
+
+static void test_case_set_rec_cb_01(void **state);
+static bool test_set_rec_cb_01(void);
+static void test_case_set_rec_cb_02(void **state);
+static bool test_set_rec_cb_02(void);
+static void test_case_set_rec_cb_03(void **state);
+static bool test_set_rec_cb_03(void);
+static void test_case_set_rec_cb_04(void **state);
+static bool test_set_rec_cb_04(void);
+
+/* Test Steps for meshlink_set_receive_cb Test Case #1 */
+static black_box_state_t test_case_set_rec_cb_01_state = {
+       .test_case_name = "test_case_set_rec_cb_01",
+};
+
+/* Test Steps for meshlink_set_receive_cb Test Case #2 */
+static black_box_state_t test_case_set_rec_cb_02_state = {
+       .test_case_name = "test_case_set_rec_cb_02",
+};
+
+/* Test Steps for meshlink_set_receive_cb Test Case #3 */
+static black_box_state_t test_case_set_rec_cb_03_state = {
+       .test_case_name = "test_case_set_rec_cb_03",
+};
+
+static bool received;
+
+/* mutex for the common variable */
+pthread_mutex_t lock;
+
+/* receive callback function */
+static void rec_cb(meshlink_handle_t *mesh, meshlink_node_t *source, const void *data, size_t len) {
+       assert(len);
+
+       pthread_mutex_lock(&lock);
+
+       if(len == 5 && !memcmp(data, "test", 5)) {
+               received = true;
+       }
+
+       pthread_mutex_unlock(&lock);
+}
+
+/* Execute meshlink_set_receive_cb Test Case # 1 - Valid case */
+static void test_case_set_rec_cb_01(void **state) {
+       execute_test(test_set_rec_cb_01, state);
+}
+/* Test Steps for meshlink_set_receive_cb Test Case # 1
+
+    Test Steps:
+    1. Open NUT
+    2. Set receive callback for the NUT
+    3. Echo NUT with some data.
+
+    Expected Result:
+    Receive callback should be invoked when NUT echoes or sends data for itself.
+*/
+static bool test_set_rec_cb_01(void) {
+       meshlink_set_log_cb(NULL, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
+
+       /* Create meshlink instance */
+       meshlink_handle_t *mesh_handle = meshlink_open("set_receive_cb_conf", "nut", "test", 1);
+       assert(mesh_handle);
+       meshlink_set_receive_cb(mesh_handle, rec_cb);
+       meshlink_set_log_cb(mesh_handle, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
+
+       assert(meshlink_start(mesh_handle));
+       sleep(1);
+
+       pthread_mutex_lock(&lock);
+       received = false;
+       pthread_mutex_unlock(&lock);
+       meshlink_node_t *node_handle = meshlink_get_self(mesh_handle);
+       assert(node_handle);
+       assert(meshlink_send(mesh_handle, node_handle, "test", 5));
+       sleep(1);
+
+       pthread_mutex_lock(&lock);
+       assert_int_equal(received, true);
+       pthread_mutex_unlock(&lock);
+
+       meshlink_close(mesh_handle);
+       meshlink_destroy("set_receive_cb_conf");
+       return true;
+}
+
+
+/* Execute meshlink_set_receive_cb Test Case # 2 - Invalid case */
+static void test_case_set_rec_cb_02(void **state) {
+       execute_test(test_set_rec_cb_02, state);
+}
+/* Test Steps for meshlink_set_receive_cb Test Case # 2
+
+    Test Steps:
+    1. Call meshlink_set_receive_cb with NULL as mesh handle argument
+
+    Expected Result:
+    meshlink_set_receive_cb API reports proper error accordingly.
+*/
+static bool test_set_rec_cb_02(void) {
+       meshlink_set_log_cb(NULL, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
+
+       // Setting receive callback with NULL as mesh handle
+       meshlink_set_receive_cb(NULL, rec_cb);
+       assert_int_equal(meshlink_errno, MESHLINK_EINVAL);
+
+       return true;
+}
+
+/* Execute meshlink_set_receive_cb Test Case # 3 - Functionality Test, Trying to set receive call back after
+      starting the mesh */
+static void test_case_set_rec_cb_03(void **state) {
+       execute_test(test_set_rec_cb_03, state);
+}
+/* Test Steps for meshlink_set_receive_cb Test Case # 3
+
+    Test Steps:
+    1. Open NUT
+    2. Starting mesh
+    2. Set receive callback for the NUT
+    3. Echo NUT with some data.
+
+    Expected Result:
+    Receive callback can be invoked when NUT echoes or sends data for itself
+*/
+static bool test_set_rec_cb_03(void) {
+       meshlink_set_log_cb(NULL, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
+
+       /* Create meshlink instance */
+       meshlink_handle_t *mesh_handle = meshlink_open("set_receive_cb_conf", "nut", "test", 1);
+       assert(mesh_handle);
+       meshlink_set_log_cb(mesh_handle, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
+
+       assert(meshlink_start(mesh_handle));
+       sleep(1);
+       meshlink_set_receive_cb(mesh_handle, rec_cb);
+
+       pthread_mutex_lock(&lock);
+       received = false;
+       pthread_mutex_unlock(&lock);
+       meshlink_node_t *node_handle = meshlink_get_self(mesh_handle);
+       assert(node_handle);
+       assert(meshlink_send(mesh_handle, node_handle, "test", 5));
+       sleep(1);
+
+       pthread_mutex_lock(&lock);
+       assert_int_equal(received, true);
+       pthread_mutex_unlock(&lock);
+
+       meshlink_close(mesh_handle);
+       meshlink_destroy("set_receive_cb_conf");
+       return true;
+}
+
+int test_meshlink_set_receive_cb(void) {
+       const struct CMUnitTest blackbox_receive_tests[] = {
+               cmocka_unit_test_prestate_setup_teardown(test_case_set_rec_cb_01, NULL, NULL,
+                               (void *)&test_case_set_rec_cb_01_state),
+               cmocka_unit_test_prestate_setup_teardown(test_case_set_rec_cb_02, NULL, NULL,
+                               (void *)&test_case_set_rec_cb_02_state),
+               cmocka_unit_test_prestate_setup_teardown(test_case_set_rec_cb_03, NULL, NULL,
+                               (void *)&test_case_set_rec_cb_03_state)
+       };
+       total_tests += sizeof(blackbox_receive_tests) / sizeof(blackbox_receive_tests[0]);
+
+       assert(pthread_mutex_init(&lock, NULL) == 0);
+       int failed = cmocka_run_group_tests(blackbox_receive_tests, NULL, NULL);
+       assert(pthread_mutex_destroy(&lock) == 0);
+
+       return failed;
+}
diff --git a/test/blackbox/run_blackbox_tests/test_cases_rec_cb.h b/test/blackbox/run_blackbox_tests/test_cases_rec_cb.h
new file mode 100644 (file)
index 0000000..c4467c8
--- /dev/null
@@ -0,0 +1,28 @@
+#ifndef TEST_CASES_SET_REC_CB_H
+#define TEST_CASES_SET_REC_CB_H
+
+/*
+    test_cases_rec_cb.h -- Declarations for Individual Test Case implementation functions
+    Copyright (C) 2018  Guus Sliepen <guus@meshlink.io>
+
+    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 <stdbool.h>
+
+extern int test_meshlink_set_receive_cb(void);
+extern int total_tests;
+
+#endif // TEST_CASES_SET_REC_CB_H
diff --git a/test/blackbox/run_blackbox_tests/test_cases_send.c b/test/blackbox/run_blackbox_tests/test_cases_send.c
new file mode 100644 (file)
index 0000000..82c494d
--- /dev/null
@@ -0,0 +1,189 @@
+/*
+    test_cases_send.c -- Execution of specific meshlink black box test cases
+    Copyright (C) 2018  Guus Sliepen <guus@meshlink.io>
+
+    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 "execute_tests.h"
+#include "test_cases_send.h"
+#include "../common/containers.h"
+#include "../common/test_step.h"
+#include "../common/common_handlers.h"
+#include <stdlib.h>
+#include <stdarg.h>
+#include <setjmp.h>
+#include <cmocka.h>
+#include <assert.h>
+#include <string.h>
+
+static void test_case_mesh_send_01(void **state);
+static bool test_steps_mesh_send_01(void);
+static void test_case_mesh_send_02(void **state);
+static bool test_steps_mesh_send_02(void);
+static void test_case_mesh_send_03(void **state);
+static bool test_steps_mesh_send_03(void);
+
+/* State structure for meshlink_send Test Case #1 */
+static black_box_state_t test_mesh_send_01_state = {
+       .test_case_name = "test_case_mesh_send_01",
+};
+
+/* State structure for meshlink_send Test Case #2 */
+static black_box_state_t test_mesh_send_02_state = {
+       .test_case_name = "test_case_mesh_send_02",
+};
+
+/* State structure for meshlink_send Test Case #3 */
+static black_box_state_t test_mesh_send_03_state = {
+       .test_case_name = "test_case_mesh_send_03",
+};
+
+/* State structure for meshlink_send Test Case #4 */
+static black_box_state_t test_mesh_send_04_state = {
+       .test_case_name = "test_case_mesh_send_04",
+};
+
+/* State structure for meshlink_send Test Case #5 */
+static black_box_state_t test_mesh_send_05_state = {
+       .test_case_name = "test_case_mesh_send_05",
+};
+
+/* State structure for meshlink_send Test Case #6 */
+static black_box_state_t test_mesh_send_06_state = {
+       .test_case_name = "test_case_mesh_send_06",
+};
+
+/* Execute meshlink_send Test Case # 1 */
+static void test_case_mesh_send_01(void **state) {
+       execute_test(test_steps_mesh_send_01, state);
+}
+
+static bool receive_data = false;
+static void receive(meshlink_handle_t *mesh, meshlink_node_t *dest_node, const void *data, size_t len) {
+       const char *msg = data;
+
+       assert(len);
+
+       if(!memcmp(data, "test", 5)) {
+               receive_data = true;
+       }
+}
+
+/* Test Steps for meshlink_send Test Case # 1
+
+    Test Steps:
+    1. Open instance of foo node
+    2. Run and send data to itself
+
+    Expected Result:
+    Node should receive data sent to itself
+*/
+static bool test_steps_mesh_send_01(void) {
+       bool result = false;
+
+       meshlink_handle_t *mesh = meshlink_open("send_conf", "foo", "test", DEV_CLASS_STATIONARY);
+       assert(mesh != NULL);
+       meshlink_set_receive_cb(mesh, receive);
+       assert(meshlink_start(mesh));
+       sleep(1);
+       meshlink_node_t *dest_node = meshlink_get_self(mesh);
+       assert(dest_node);
+
+       receive_data = false;
+       result = meshlink_send(mesh, dest_node, "test", 5);
+       assert_int_equal(result, true);
+       sleep(1);
+       assert_int_equal(receive_data, true);
+
+       meshlink_close(mesh);
+       meshlink_destroy("send_conf");
+       return result;
+}
+
+/* Execute meshlink_send Test Case # 2
+
+    Test Steps:
+    1. Open instance of foo node
+    2. meshlink_send with NULL as mesh handle
+
+    Expected Result:
+    meshlink_send returns false because of NULL handle
+*/
+static void test_case_mesh_send_02(void **state) {
+       execute_test(test_steps_mesh_send_02, state);
+}
+
+/* Test Steps for meshlink_send Test Case # 2*/
+static bool test_steps_mesh_send_02(void) {
+       meshlink_handle_t *mesh = meshlink_open("send_conf", "foo", "chat", DEV_CLASS_STATIONARY);
+       assert(mesh != NULL);
+       meshlink_set_receive_cb(mesh, receive);
+
+       assert(meshlink_start(mesh));
+       meshlink_node_t *dest_node = meshlink_get_self(mesh);
+       assert(dest_node);
+
+       bool ret = meshlink_send(NULL, dest_node, "test", 5);
+       assert_int_equal(ret, false);
+
+       meshlink_close(mesh);
+       meshlink_destroy("send_conf");
+       return true;
+}
+
+/* Execute meshlink_send Test Case # 3
+
+    Test Steps:
+    1. Open instance of foo node
+    2. meshlink_send with NULL as node handle
+
+    Expected Result:
+    meshlink_send returns false because of NULL handle
+*/
+static void test_case_mesh_send_03(void **state) {
+       execute_test(test_steps_mesh_send_03, state);
+}
+
+/* Test Steps for meshlink_send Test Case # 3*/
+static bool test_steps_mesh_send_03(void) {
+       meshlink_handle_t *mesh = meshlink_open("send_conf", "foo", "chat", DEV_CLASS_STATIONARY);
+       assert(mesh != NULL);
+       meshlink_set_receive_cb(mesh, receive);
+
+       assert(meshlink_start(mesh));
+
+       bool ret = meshlink_send(mesh, NULL, "test", 5);
+       assert_int_equal(ret, false);
+
+       meshlink_close(mesh);
+       meshlink_destroy("send_conf");
+       return true;
+}
+
+int test_meshlink_send(void) {
+       const struct CMUnitTest blackbox_send_tests[] = {
+               cmocka_unit_test_prestate_setup_teardown(test_case_mesh_send_01, NULL, NULL,
+                               (void *)&test_mesh_send_01_state),
+               cmocka_unit_test_prestate_setup_teardown(test_case_mesh_send_02, NULL, NULL,
+                               (void *)&test_mesh_send_02_state),
+               cmocka_unit_test_prestate_setup_teardown(test_case_mesh_send_03, NULL, NULL,
+                               (void *)&test_mesh_send_03_state)
+       };
+
+       total_tests += sizeof(blackbox_send_tests) / sizeof(blackbox_send_tests[0]);
+
+       return cmocka_run_group_tests(blackbox_send_tests, NULL, NULL);
+}
diff --git a/test/blackbox/run_blackbox_tests/test_cases_send.h b/test/blackbox/run_blackbox_tests/test_cases_send.h
new file mode 100644 (file)
index 0000000..6649b8f
--- /dev/null
@@ -0,0 +1,29 @@
+#ifndef TEST_CASES_SEND_H
+#define TEST_CASES_SEND_H
+
+/*
+    test_cases_send.h -- Declarations for Individual Test Case implementation functions
+    Copyright (C) 2018  Guus Sliepen <guus@meshlink.io>
+
+    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 <stdbool.h>
+
+extern int test_meshlink_send(void);
+extern int total_tests;
+
+
+#endif
diff --git a/test/blackbox/run_blackbox_tests/test_cases_set_log_cb.c b/test/blackbox/run_blackbox_tests/test_cases_set_log_cb.c
new file mode 100644 (file)
index 0000000..71019a1
--- /dev/null
@@ -0,0 +1,142 @@
+/*
+    test_cases_set_log_cb.c -- Execution of specific meshlink black box test cases
+    Copyright (C) 2018  Guus Sliepen <guus@meshlink.io>
+
+    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 "execute_tests.h"
+#include "test_cases_set_log_cb.h"
+#include "../common/containers.h"
+#include "../common/test_step.h"
+#include "../common/common_handlers.h"
+#include <assert.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <setjmp.h>
+#include <cmocka.h>
+#include <pthread.h>
+
+
+/* Modify this to change the logging level of Meshlink */
+#define TEST_MESHLINK_LOG_LEVEL MESHLINK_DEBUG
+
+static void test_case_set_log_cb_01(void **state);
+static bool test_set_log_cb_01(void);
+static void test_case_set_log_cb_02(void **state);
+static bool test_set_log_cb_02(void);
+static void test_case_set_log_cb_03(void **state);
+static bool test_set_log_cb_03(void);
+
+/* log variable gives access to the log callback to know whether invoked or not */
+static bool log;
+
+/* State structure for log callback Test Case #1 */
+static black_box_state_t test_case_set_log_cb_01_state = {
+       .test_case_name = "test_case_set_log_cb_01",
+};
+
+/* State structure for log callback Test Case #2 */
+static black_box_state_t test_case_set_log_cb_02_state = {
+       .test_case_name = "test_case_set_log_cb_02",
+};
+
+
+/* log callback */
+static void log_cb(meshlink_handle_t *mesh, meshlink_log_level_t level, const char *text) {
+       fprintf(stderr, "Received log text : %s\n", text);
+       log = true;
+}
+
+/* Execute meshlink_set_log_cb Test Case # 1 - Valid case */
+static void test_case_set_log_cb_01(void **state) {
+       execute_test(test_set_log_cb_01, state);
+}
+/* Test Steps for meshlink_set_receive_cb Test Case # 1
+
+    Test Steps:
+    1. Run relay and Open NUT
+    2. Set log callback for the NUT and Start NUT
+
+    Expected Result:
+    log callback should be invoked when NUT joins with relay.
+*/
+static bool test_set_log_cb_01(void) {
+       meshlink_destroy("logconf");
+
+       // Create meshlink instance for NUT
+
+       meshlink_handle_t *mesh = meshlink_open("logconf", "nut", "test", DEV_CLASS_STATIONARY);
+       assert(mesh != NULL);
+
+       // Set up logging for Meshlink with the newly acquired Mesh Handle
+
+       log = false;
+       meshlink_set_log_cb(mesh, TEST_MESHLINK_LOG_LEVEL, log_cb);
+
+       // Starting node to log
+
+       bool mesh_start = meshlink_start(mesh);
+       assert(mesh_start);
+
+       bool ret = log;
+
+       assert_int_equal(ret, true);
+
+       // closing meshes and destroying confbase
+
+       meshlink_close(mesh);
+       meshlink_destroy("logconf");
+
+       return true;
+}
+
+/* Execute meshlink_set_log_cb Test Case # 2 - Invalid case */
+static void test_case_set_log_cb_02(void **state) {
+       execute_test(test_set_log_cb_02, state);
+}
+/* Test Steps for meshlink_set_poll_cb Test Case # 2
+
+    Test Steps:
+    1. Calling meshlink_set_poll_cb with some invalid integer other than the valid enums.
+
+    Expected Result:
+    set poll callback handles the invalid parameter when called by giving proper error number.
+*/
+static bool test_set_log_cb_02(void) {
+
+       // Setting an invalid level
+
+       meshlink_set_log_cb(NULL, 1000, NULL);
+       assert_int_equal(meshlink_errno, MESHLINK_EINVAL);
+
+       return true;
+}
+
+
+int test_meshlink_set_log_cb(void) {
+       const struct CMUnitTest blackbox_log_tests[] = {
+               cmocka_unit_test_prestate_setup_teardown(test_case_set_log_cb_01, NULL, NULL,
+                               (void *)&test_case_set_log_cb_01_state),
+               cmocka_unit_test_prestate_setup_teardown(test_case_set_log_cb_02, NULL, NULL,
+                               (void *)&test_case_set_log_cb_02_state)
+       };
+       total_tests += sizeof(blackbox_log_tests) / sizeof(blackbox_log_tests[0]);
+
+       int failed = cmocka_run_group_tests(blackbox_log_tests, NULL, NULL);
+
+       return failed;
+}
diff --git a/test/blackbox/run_blackbox_tests/test_cases_set_log_cb.h b/test/blackbox/run_blackbox_tests/test_cases_set_log_cb.h
new file mode 100644 (file)
index 0000000..31b1aa9
--- /dev/null
@@ -0,0 +1,28 @@
+#ifndef TEST_CASES_SET_LOG_CB_H
+#define TEST_CASES_SET_LOG_CB_H
+
+/*
+    test_cases_set_log_cb.h -- Declarations for Individual Test Case implementation functions
+    Copyright (C) 2018  Guus Sliepen <guus@meshlink.io>
+
+    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 <stdbool.h>
+
+extern  int test_meshlink_set_log_cb(void);
+extern  int total_tests;
+
+#endif // TEST_CASES_SET_LOG_H
diff --git a/test/blackbox/run_blackbox_tests/test_cases_set_port.c b/test/blackbox/run_blackbox_tests/test_cases_set_port.c
new file mode 100644 (file)
index 0000000..0bc2c6a
--- /dev/null
@@ -0,0 +1,166 @@
+/*
+    test_cases_set_port.c -- Execution of specific meshlink black box test cases
+    Copyright (C) 2018  Guus Sliepen <guus@meshlink.io>
+
+    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 "execute_tests.h"
+#include "test_cases_destroy.h"
+#include "../common/containers.h"
+#include "../common/test_step.h"
+#include "../common/common_handlers.h"
+#include "test_cases_set_port.h"
+#include <assert.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <setjmp.h>
+#include <cmocka.h>
+
+
+/* Modify this to change the logging level of Meshlink */
+#define TEST_MESHLINK_LOG_LEVEL MESHLINK_DEBUG
+
+static void test_case_set_port_01(void **state);
+static bool test_set_port_01(void);
+static void test_case_set_port_02(void **state);
+static bool test_set_port_02(void);
+static void test_case_set_port_03(void **state);
+static bool test_set_port_03(void);
+
+/* State structure for set port API Test Case #1 */
+static black_box_state_t test_case_set_port_01_state = {
+       .test_case_name = "test_case_set_port_01",
+};
+/* State structure for set port API Test Case #2 */
+static black_box_state_t test_case_set_port_02_state = {
+       .test_case_name = "test_case_set_port_02",
+};
+/* State structure for set port API Test Case #3 */
+static black_box_state_t test_case_set_port_03_state = {
+       .test_case_name = "test_case_set_port_03",
+};
+
+
+/* Execute meshlink_set_port Test Case # 1 - valid case*/
+static void test_case_set_port_01(void **state) {
+       execute_test(test_set_port_01, state);
+}
+/* Test Steps for meshlink_set_port Test Case # 1 - Valid case
+
+    Test Steps:
+    1. Open NUT(Node Under Test)
+    2. Set Port for NUT
+
+    Expected Result:
+    Set the new port to the NUT.
+*/
+static bool test_set_port_01(void) {
+       meshlink_set_log_cb(NULL, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
+
+       // Create meshlink instance
+
+       mesh_handle = meshlink_open("setportconf", "nut", "test", 1);
+       assert(mesh_handle);
+       meshlink_set_log_cb(mesh_handle, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
+
+       // Get old port and set a new port number
+
+       int port;
+       port = meshlink_get_port(mesh_handle);
+       assert(port > 0);
+       bool ret = meshlink_set_port(mesh_handle, 8000);
+       port = meshlink_get_port(mesh_handle);
+
+       assert_int_equal(port, 8000);
+       assert_int_equal(ret, true);
+
+       // Clean up
+
+       meshlink_close(mesh_handle);
+       meshlink_destroy("setportconf");
+       return true;
+}
+
+/* Execute meshlink_set_port Test Case # 2 - Invalid case*/
+static void test_case_set_port_02(void **state) {
+       execute_test(test_set_port_02, state);
+}
+
+/* Test Steps for meshlink_set_port Test Case # 2 - Invalid case
+
+    Test Steps:
+    1. Pass NULL as mesh handle argument for meshlink_set_port
+
+    Expected Result:
+    Report false indicating error.
+*/
+static bool test_set_port_02(void) {
+       // meshlink_set_port called using NULL as mesh handle
+
+       bool ret = meshlink_set_port(NULL, 8000);
+
+       assert_int_equal(ret, false);
+       return false;
+}
+
+
+/* Execute meshlink_set_port Test Case # 3 - Setting port after starting mesh*/
+static void test_case_set_port_03(void **state) {
+       execute_test(test_set_port_03, state);
+}
+
+/* Test Steps for meshlink_set_port Test Case # 2 - functionality test
+
+    Test Steps:
+    1. Open and start NUT and then try to set new port number
+
+    Expected Result:
+    New port number cannot be set while mesh is running.
+*/
+static bool test_set_port_03(void) {
+       meshlink_set_log_cb(NULL, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
+
+       // Create meshlink instance
+
+       mesh_handle = meshlink_open("getportconf", "nut", "test", 1);
+       assert(mesh_handle);
+       meshlink_set_log_cb(mesh_handle, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
+       assert(meshlink_start(mesh_handle));
+
+       // Setting port after starting NUT
+       bool ret = meshlink_set_port(mesh_handle, 50000);
+       assert_int_equal(ret, false);
+
+       // Clean up
+
+       meshlink_close(mesh_handle);
+       meshlink_destroy("getportconf");
+}
+
+
+int test_meshlink_set_port(void) {
+       const struct CMUnitTest blackbox_set_port_tests[] = {
+               cmocka_unit_test_prestate_setup_teardown(test_case_set_port_01, NULL, NULL,
+                               (void *)&test_case_set_port_01_state),
+               cmocka_unit_test_prestate_setup_teardown(test_case_set_port_02, NULL, NULL,
+                               (void *)&test_case_set_port_02_state),
+               cmocka_unit_test_prestate_setup_teardown(test_case_set_port_03, NULL, NULL,
+                               (void *)&test_case_set_port_03_state)
+       };
+       total_tests += sizeof(blackbox_set_port_tests) / sizeof(blackbox_set_port_tests[0]);
+       return cmocka_run_group_tests(blackbox_set_port_tests, NULL, NULL);
+}
diff --git a/test/blackbox/run_blackbox_tests/test_cases_set_port.h b/test/blackbox/run_blackbox_tests/test_cases_set_port.h
new file mode 100644 (file)
index 0000000..fa8a768
--- /dev/null
@@ -0,0 +1,28 @@
+#ifndef TEST_CASES_SET_PORT_H
+#define TEST_CASES_SET_PORT_H
+
+/*
+    test_cases_set_port.h -- Declarations for Individual Test Case implementation functions
+    Copyright (C) 2018  Guus Sliepen <guus@meshlink.io>
+
+    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 <stdbool.h>
+
+extern int total_tests;
+extern int test_meshlink_set_port(void);
+
+#endif // TEST_CASES_SET_PORT
diff --git a/test/blackbox/run_blackbox_tests/test_cases_sign.c b/test/blackbox/run_blackbox_tests/test_cases_sign.c
new file mode 100644 (file)
index 0000000..c120c47
--- /dev/null
@@ -0,0 +1,402 @@
+/*
+    test_cases_sign.c -- Execution of specific meshlink black box test cases
+    Copyright (C) 2018  Guus Sliepen <guus@meshlink.io>
+
+    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 "execute_tests.h"
+#include "test_cases_sign.h"
+#include "../common/containers.h"
+#include "../common/test_step.h"
+#include "../common/common_handlers.h"
+#include <assert.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <setjmp.h>
+#include <cmocka.h>
+
+/* Modify this to change the logging level of Meshlink */
+#define TEST_MESHLINK_LOG_LEVEL MESHLINK_DEBUG
+
+static void test_case_sign_01(void **state);
+static bool test_sign_01(void);
+static void test_case_sign_02(void **state);
+static bool test_sign_02(void);
+static void test_case_sign_03(void **state);
+static bool test_sign_03(void);
+static void test_case_sign_04(void **state);
+static bool test_sign_04(void);
+static void test_case_sign_05(void **state);
+static bool test_sign_05(void);
+static void test_case_sign_06(void **state);
+static bool test_sign_06(void);
+static void test_case_sign_07(void **state);
+static bool test_sign_07(void);
+
+/* State structure for sign API Test Case #1 */
+static black_box_state_t test_case_sign_01_state = {
+       .test_case_name = "test_case_sign_01",
+};
+
+/* State structure for sign API Test Case #2 */
+static black_box_state_t test_case_sign_02_state = {
+       .test_case_name = "test_case_sign_02",
+};
+
+/* State structure for sign API Test Case #3 */
+static black_box_state_t test_case_sign_03_state = {
+       .test_case_name = "test_case_sign_03",
+};
+
+/* State structure for sign API Test Case #4 */
+static black_box_state_t test_case_sign_04_state = {
+       .test_case_name = "test_case_sign_04",
+};
+
+/* State structure for sign API Test Case #5 */
+static black_box_state_t test_case_sign_05_state = {
+       .test_case_name = "test_case_sign_05",
+};
+
+/* State structure for sign API Test Case #6 */
+static black_box_state_t test_case_sign_06_state = {
+       .test_case_name = "test_case_sign_06",
+};
+
+/* State structure for sign API Test Case #7 */
+static black_box_state_t test_case_sign_07_state = {
+       .test_case_name = "test_case_sign_07",
+};
+
+
+/* Execute sign_data Test Case # 1 - Valid case - sign a data successfully*/
+static void test_case_sign_01(void **state) {
+       execute_test(test_sign_01, state);
+}
+
+/* Test Steps for meshlink_sign Test Case # 1 - Valid case
+
+    Test Steps:
+    1. Run NUT(Node Under Test)
+    2. Sign data
+
+    Expected Result:
+    Signs data successfully
+*/
+static bool test_sign_01(void) {
+       meshlink_set_log_cb(NULL, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
+
+       // Create meshlink instance
+       meshlink_handle_t *mesh_handle = meshlink_open("signconf", "nut", "node_sim", 1);
+       assert(mesh_handle);
+       meshlink_set_log_cb(mesh_handle, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
+       assert(meshlink_start(mesh_handle));
+
+       // Signing data
+
+       char *data = "Test";
+       char sig[MESHLINK_SIGLEN];
+       size_t ssize = MESHLINK_SIGLEN;
+       bool ret = meshlink_sign(mesh_handle, data, strlen(data) + 1, sig, &ssize);
+
+       // Clean up
+       meshlink_close(mesh_handle);
+       meshlink_destroy("signconf");
+
+       return ret;
+}
+
+/* Execute sign_data Test Case # 2 - Invalid case - meshlink_sign passing NULL as mesh handle argument*/
+static void test_case_sign_02(void **state) {
+       execute_test(test_sign_02, state);
+       return;
+}
+
+/* Test Steps for meshlink_sign Test Case # 2 - invalid case
+
+    Test Steps:
+    1. meshlink_sign API called by passing NULL as mesh handle argument
+
+    Expected Result:
+    API returns false hinting the error.
+*/
+static bool test_sign_02(void) {
+       char *data = "Test";
+       char sig[MESHLINK_SIGLEN];
+       size_t ssize = MESHLINK_SIGLEN;
+
+       // Calling meshlink_sign API
+       bool ret = meshlink_sign(NULL, data, strlen(data) + 1, sig, &ssize);
+
+       if(!ret) {
+               PRINT_TEST_CASE_MSG("meshlink_sign Successfuly reported error on passing NULL as mesh_handle arg\n");
+               return true;
+       }
+
+       PRINT_TEST_CASE_MSG("meshlink_sign FAILED to report error on passing NULL as mesh_handle arg\n");
+       return false;
+}
+
+/* Execute sign_data Test Case # 3 - Invalid case - meshlink_sign passing data to be signed as NULL */
+static void test_case_sign_03(void **state) {
+       execute_test(test_sign_03, state);
+}
+
+/* Test Steps for meshlink_sign Test Case # 3 - invalid case
+
+    Test Steps:
+    1. Run NUT(Node Under Test)
+    2. meshlink_sign API called by passing NULL as data argument
+        that has to be signed.
+
+    Expected Result:
+    API returns false hinting the error.
+*/
+static bool test_sign_03(void) {
+       meshlink_set_log_cb(NULL, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
+
+       // Create meshlink instance
+       meshlink_handle_t *mesh_handle = meshlink_open("signconf", "nut", "node_sim", 1);
+       assert(mesh_handle);
+       meshlink_set_log_cb(mesh_handle, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
+       assert(meshlink_start(mesh_handle));
+
+       // Signing Data
+       char *data = "Test";
+       char sig[MESHLINK_SIGLEN];
+       size_t ssize = MESHLINK_SIGLEN;
+       bool ret = meshlink_sign(mesh_handle, NULL, strlen(data) + 1, sig, &ssize);
+
+       // Clean up
+
+       meshlink_close(mesh_handle);
+       meshlink_destroy("signconf");
+
+       if(!ret) {
+               PRINT_TEST_CASE_MSG("meshlink_sign Successfuly reported error on passing NULL as data arg\n");
+               return true;
+       } else {
+               PRINT_TEST_CASE_MSG("meshlink_sign FAILED to report error on passing NULL as data arg\n");
+               return false;
+       }
+}
+
+/* Execute sign_data Test Case # 4 - Invalid case - meshlink_sign passing 0 as size of data
+      to be signed */
+static void test_case_sign_04(void **state) {
+       execute_test(test_sign_04, state);
+}
+
+/* Test Steps for meshlink_sign Test Case # 3 - invalid case
+
+    Test Steps:
+    1. Run NUT(Node Under Test)
+    2. meshlink_sign API called by passing 0 as size of data to be signed
+
+    Expected Result:
+    API returns false hinting the error.
+*/
+static bool test_sign_04(void) {
+       meshlink_set_log_cb(NULL, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
+
+       // Create meshlink instance
+
+       meshlink_handle_t *mesh_handle = meshlink_open("signconf", "nut", "node_sim", 1);
+       assert(mesh_handle);
+       meshlink_set_log_cb(mesh_handle, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
+       assert(meshlink_start(mesh_handle));
+
+       // Signing data
+
+       char *data = "Test";
+       char sig[MESHLINK_SIGLEN];
+       size_t ssize = MESHLINK_SIGLEN;
+       bool ret = meshlink_sign(mesh_handle, data, 0, sig, &ssize);
+
+       // Clean up
+
+       meshlink_close(mesh_handle);
+       meshlink_destroy("signconf");
+
+       if(!ret) {
+               PRINT_TEST_CASE_MSG("meshlink_sign Successfuly reported error on passing 0 as size of data arg\n");
+               return true;
+       }
+
+       PRINT_TEST_CASE_MSG("meshlink_sign FAILED to report error on passing 0 as size of data arg\n");
+       return false;
+}
+
+/* Execute sign_data Test Case # 5 - Invalid case - meshlink_sign passing NULL as
+      signature buffer argument*/
+static void test_case_sign_05(void **state) {
+       execute_test(test_sign_05, state);
+}
+
+/* Test Steps for meshlink_sign Test Case # 5 - invalid case
+
+    Test Steps:
+    1. Run NUT(Node Under Test)
+    2. meshlink_sign API called by passing NULL for signature buffer argument
+
+    Expected Result:
+    API returns false hinting the error.
+*/
+static bool test_sign_05(void) {
+       meshlink_set_log_cb(NULL, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
+
+       // Create meshlink instance
+
+       meshlink_handle_t *mesh_handle = meshlink_open("signconf", "nut", "node_sim", 1);
+       assert(mesh_handle);
+       meshlink_set_log_cb(mesh_handle, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
+       assert(meshlink_start(mesh_handle));
+
+       // Signing data
+
+       char *data = "Test";
+       char sig[MESHLINK_SIGLEN];
+       size_t ssize = MESHLINK_SIGLEN;
+       bool ret = meshlink_sign(mesh_handle, data, strlen(data) + 1, NULL, &ssize);
+
+       // Clean up
+
+       meshlink_close(mesh_handle);
+       meshlink_destroy("signconf");
+
+       if(!ret) {
+               PRINT_TEST_CASE_MSG("meshlink_sign Successfuly reported error on passing NULL as sign arg\n");
+               return true;
+       }
+
+       PRINT_TEST_CASE_MSG("meshlink_sign FAILED to report error on passing NULL as sign arg\n");
+       return false;
+}
+
+/* Execute sign_data Test Case # 6 - Invalid case - meshlink_sign passing NULL for size of
+      signature argument */
+static void test_case_sign_06(void **state) {
+       execute_test(test_sign_06, state);
+}
+
+/* Test Steps for meshlink_sign Test Case # 6 - invalid case
+
+    Test Steps:
+    1. Run NUT(Node Under Test)
+    2. meshlink_sign API called by passing NULL for size of signature buffer argument
+
+    Expected Result:
+    API returns false hinting the error.
+*/
+static bool test_sign_06(void) {
+       meshlink_set_log_cb(NULL, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
+
+       // Create meshlink instance
+       meshlink_handle_t *mesh_handle = meshlink_open("signconf", "nut", "node_sim", 1);
+       assert(mesh_handle);
+       meshlink_set_log_cb(mesh_handle, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
+       assert(meshlink_start(mesh_handle));
+
+       // Signing data
+
+       char *data = "Test";
+       char sig[MESHLINK_SIGLEN];
+       size_t ssize = MESHLINK_SIGLEN;
+       bool ret = meshlink_sign(mesh_handle, data, strlen(data) + 1, sig, NULL);
+
+       // Clean up
+
+       meshlink_close(mesh_handle);
+       meshlink_destroy("signconf");
+
+       if(!ret) {
+               PRINT_TEST_CASE_MSG("meshlink_sign Successfuly reported error on passing NULL as signsize arg\n");
+               return true;
+       }
+
+       PRINT_TEST_CASE_MSG("meshlink_sign FAILED to report error on passing NULL as signsize arg\n");
+       return false;
+}
+
+/* Execute sign_data Test Case # 7 - Invalid case - meshlink_sign passing size of signature < MESHLINK_SIGLEN*/
+static void test_case_sign_07(void **state) {
+       execute_test(test_sign_07, state);
+}
+
+/* Test Steps for meshlink_sign Test Case # 6 - invalid case
+
+    Test Steps:
+    1. Run NUT(Node Under Test)
+    2. meshlink_sign API called by passing size of signature < MESHLINK_SIGLEN
+
+    Expected Result:
+    API returns false hinting the error.
+*/
+static bool test_sign_07(void) {
+       meshlink_set_log_cb(NULL, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
+
+       // Create meshlink instance
+
+       meshlink_handle_t *mesh_handle = meshlink_open("signconf", "nut", "node_sim", 1);
+       assert(mesh_handle);
+       meshlink_set_log_cb(mesh_handle, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
+       assert(meshlink_start(mesh_handle));
+
+       // Signing data
+
+       char *data = "Test";
+       char sig[MESHLINK_SIGLEN];
+       size_t ssize = 5;  //5 < MESHLINK_SIGLEN
+       bool ret = meshlink_sign(mesh_handle, data, strlen(data) + 1, sig, &ssize);
+
+       // Cleanup
+
+       meshlink_stop(mesh_handle);
+       meshlink_close(mesh_handle);
+       meshlink_destroy("signconf");
+
+       if(!ret) {
+               PRINT_TEST_CASE_MSG("meshlink_sign Successfuly reported error on passing signsize < MESHLINK_SIGLEN arg\n");
+               return true;
+       }
+
+       PRINT_TEST_CASE_MSG("meshlink_sign FAILED to report error on passing signsize < MESHLINK_SIGLEN arg\n");
+       return false;
+}
+
+
+int test_meshlink_sign(void) {
+       const struct CMUnitTest blackbox_sign_tests[] = {
+               cmocka_unit_test_prestate_setup_teardown(test_case_sign_01, NULL, NULL,
+                               (void *)&test_case_sign_01_state),
+               cmocka_unit_test_prestate_setup_teardown(test_case_sign_02, NULL, NULL,
+                               (void *)&test_case_sign_02_state),
+               cmocka_unit_test_prestate_setup_teardown(test_case_sign_03, NULL, NULL,
+                               (void *)&test_case_sign_03_state),
+               cmocka_unit_test_prestate_setup_teardown(test_case_sign_04, NULL, NULL,
+                               (void *)&test_case_sign_04_state),
+               cmocka_unit_test_prestate_setup_teardown(test_case_sign_05, NULL, NULL,
+                               (void *)&test_case_sign_05_state),
+               cmocka_unit_test_prestate_setup_teardown(test_case_sign_06, NULL, NULL,
+                               (void *)&test_case_sign_06_state),
+               cmocka_unit_test_prestate_setup_teardown(test_case_sign_07, NULL, NULL,
+                               (void *)&test_case_sign_07_state)
+       };
+       total_tests += sizeof(blackbox_sign_tests) / sizeof(blackbox_sign_tests[0]);
+
+       return cmocka_run_group_tests(blackbox_sign_tests, NULL, NULL);
+}
diff --git a/test/blackbox/run_blackbox_tests/test_cases_sign.h b/test/blackbox/run_blackbox_tests/test_cases_sign.h
new file mode 100644 (file)
index 0000000..bbb741b
--- /dev/null
@@ -0,0 +1,28 @@
+#ifndef TEST_CASES_SIGN_H
+#define TEST_CASES_SIGN_H
+
+/*
+    test_cases_sign.h -- Declarations for Individual Test Case implementation functions
+    Copyright (C) 2018  Guus Sliepen <guus@meshlink.io>
+
+    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 <stdbool.h>
+
+extern int total_tests;
+extern int test_meshlink_sign(void);
+
+#endif // TEST_CASES_SIGN_H
diff --git a/test/blackbox/run_blackbox_tests/test_cases_start.c b/test/blackbox/run_blackbox_tests/test_cases_start.c
new file mode 100644 (file)
index 0000000..c01f8f8
--- /dev/null
@@ -0,0 +1,127 @@
+/*
+    test_cases_start.c -- Execution of specific meshlink black box test cases
+    Copyright (C) 2018  Guus Sliepen <guus@meshlink.io>
+
+    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 "execute_tests.h"
+#include "test_cases_start.h"
+#include "../common/containers.h"
+#include "../common/test_step.h"
+#include "../common/common_handlers.h"
+#include <stdlib.h>
+#include <stdarg.h>
+#include <setjmp.h>
+#include <cmocka.h>
+#include <assert.h>
+#include <string.h>
+
+static void test_case_mesh_start_01(void **state);
+static bool test_steps_mesh_start_01(void);
+static void test_case_mesh_start_02(void **state);
+static bool test_steps_mesh_start_02(void);
+
+/* State structure for meshlink_start Test Case #1 */
+static black_box_state_t test_mesh_start_01_state = {
+       .test_case_name = "test_case_mesh_start_01",
+};
+
+/* State structure for meshlink_start Test Case #2 */
+static black_box_state_t test_mesh_start_02_state = {
+       .test_case_name = "test_case_mesh_start_02",
+};
+
+/* Execute meshlink_start Test Case # 1*/
+static void test_case_mesh_start_01(void **state) {
+       execute_test(test_steps_mesh_start_01, state);
+}
+
+/* Test Steps for meshlink_start Test Case # 1
+
+    Test Steps:
+    1. Open Instance & start node
+
+    Expected Result:
+    Successfully node instance should be running
+*/
+static bool test_steps_mesh_start_01(void) {
+
+       // Open instance
+
+       bool result = false;
+       meshlink_handle_t *mesh = meshlink_open("start_conf", "foo", "test", DEV_CLASS_STATIONARY);
+       assert(mesh);
+
+       // Run node instance
+
+       result = meshlink_start(mesh);
+
+       // Clean up
+       meshlink_close(mesh);
+       meshlink_destroy("start_conf");
+
+       if(!result) {
+               fprintf(stderr, "meshlink_start status1: %s\n", meshlink_strerror(meshlink_errno));
+               return false;
+       } else {
+               return true;
+       }
+}
+
+/* Execute meshlink_start Test Case # 2*/
+static void test_case_mesh_start_02(void **state) {
+       execute_test(test_steps_mesh_start_02, state);
+}
+
+/* Test Steps for meshlink_start Test Case # 2
+
+    Test Steps:
+    1. Calling meshlink_start with NULL as mesh handle argument.
+
+    Expected Result:
+    meshlink_start API handles the invalid parameter by returning false.
+*/
+static bool test_steps_mesh_start_02(void) {
+       bool result = false;
+       meshlink_destroy("start_conf");
+       meshlink_handle_t *mesh = meshlink_open("start_conf", "foo", "test", DEV_CLASS_STATIONARY);
+       assert(mesh);
+
+       // Run instance with NULL argument
+
+       result = meshlink_start(NULL);
+       assert_int_equal(result, true);
+
+       // Clean up
+
+       meshlink_close(mesh);
+       meshlink_destroy("start_conf");
+       return true;
+}
+
+int test_meshlink_start(void) {
+       const struct CMUnitTest blackbox_start_tests[] = {
+               cmocka_unit_test_prestate_setup_teardown(test_case_mesh_start_01, NULL, NULL,
+                               (void *)&test_mesh_start_01_state),
+               cmocka_unit_test_prestate_setup_teardown(test_case_mesh_start_02, NULL, NULL,
+                               (void *)&test_mesh_start_02_state)
+
+       };
+
+       total_tests += sizeof(blackbox_start_tests) / sizeof(blackbox_start_tests[0]);
+
+       return cmocka_run_group_tests(blackbox_start_tests, NULL, NULL);
+}
diff --git a/test/blackbox/run_blackbox_tests/test_cases_start.h b/test/blackbox/run_blackbox_tests/test_cases_start.h
new file mode 100644 (file)
index 0000000..835cfac
--- /dev/null
@@ -0,0 +1,30 @@
+#ifndef TEST_CASES_START_H
+#define TEST_CASES_START_H
+
+/*
+    test_cases_start.h -- Declarations for Individual Test Case implementation functions
+    Copyright (C) 2018  Guus Sliepen <guus@meshlink.io>
+
+    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 <stdbool.h>
+
+extern int test_meshlink_start(void);
+extern int total_tests;
+
+
+
+#endif
diff --git a/test/blackbox/run_blackbox_tests/test_cases_status_cb.c b/test/blackbox/run_blackbox_tests/test_cases_status_cb.c
new file mode 100644 (file)
index 0000000..9bfb4c6
--- /dev/null
@@ -0,0 +1,173 @@
+/*
+    test_cases_status_cb.c -- Execution of specific meshlink black box test cases
+    Copyright (C) 2018  Guus Sliepen <guus@meshlink.io>
+
+    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 "execute_tests.h"
+#include "test_cases_status_cb.h"
+#include "../common/containers.h"
+#include "../common/test_step.h"
+#include "../common/common_handlers.h"
+#include <assert.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <setjmp.h>
+#include <cmocka.h>
+#include <pthread.h>
+
+/* Modify this to change the logging level of Meshlink */
+#define TEST_MESHLINK_LOG_LEVEL MESHLINK_DEBUG
+
+static void test_case_set_status_cb_01(void **state);
+static bool test_set_status_cb_01(void);
+static void test_case_set_status_cb_02(void **state);
+static bool test_set_status_cb_02(void);
+
+/* status variable gives access to the status callback to know whether invoked or not */
+static bool status;
+
+/* State structure for status callback Test Case #1 */
+static black_box_state_t test_case_set_status_cb_01_state = {
+       .test_case_name = "test_case_set_status_cb_01",
+};
+
+/* State structure for status callback Test Case #2 */
+static black_box_state_t test_case_set_status_cb_02_state = {
+       .test_case_name = "test_case_set_status_cb_02",
+};
+
+
+static void status_cb(meshlink_handle_t *mesh, meshlink_node_t *source, bool reach) {
+       fprintf(stderr, "In status callback\n");
+
+       if(reach) {
+               fprintf(stderr, "[ %s ] node reachable\n", source->name);
+       } else {
+               fprintf(stderr, "[ %s ] node not reachable\n", source->name) ;
+       }
+
+       status = reach;
+}
+
+/* Execute status callback Test Case # 1 - valid case */
+static void test_case_set_status_cb_01(void **state) {
+       execute_test(test_set_status_cb_01, state);
+}
+
+/* Test Steps for meshlink_set_status_cb Test Case # 1
+
+    Test Steps:
+    1. Run bar and nut node instances
+    2. Set status callback for the NUT and Start NUT
+
+    Expected Result:
+    status callback should be invoked when NUT connects/disconnects with 'relay' node.
+*/
+static bool test_set_status_cb_01(void) {
+       meshlink_destroy("set_status_cb_conf.1");
+       meshlink_destroy("set_status_cb_conf.2");
+
+       // Opening NUT and bar nodes
+       meshlink_handle_t *mesh1 = meshlink_open("set_status_cb_conf.1", "nut", "test", DEV_CLASS_STATIONARY);
+       assert(mesh1 != NULL);
+       meshlink_set_log_cb(mesh1, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
+       meshlink_handle_t *mesh2 = meshlink_open("set_status_cb_conf.2", "bar", "test", DEV_CLASS_STATIONARY);
+       assert(mesh2 != NULL);
+       meshlink_set_log_cb(mesh2, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
+
+       // Set up callback for node status
+       meshlink_set_node_status_cb(mesh1, status_cb);
+
+       // Exporting and Importing mutually
+       char *exp1 = meshlink_export(mesh1);
+       assert(exp1 != NULL);
+       char *exp2 = meshlink_export(mesh2);
+       assert(exp2 != NULL);
+       bool imp1 = meshlink_import(mesh1, exp2);
+       bool imp2 = meshlink_import(mesh2, exp1);
+
+       assert(meshlink_start(mesh1));
+       assert(meshlink_start(mesh2));
+       sleep(1);
+
+       // Test for status from status callback
+       assert_int_equal(status, true);
+
+       meshlink_close(mesh2);
+       sleep(1);
+
+       // Test for status from status callback
+       assert_int_equal(status, false);
+
+       free(exp1);
+       free(exp2);
+       meshlink_close(mesh1);
+       meshlink_destroy("set_status_cb_conf.1");
+       meshlink_destroy("set_status_cb_conf.2");
+
+       return true;
+}
+
+/* Execute status callback Test Case # 2 - Invalid case */
+static void test_case_set_status_cb_02(void **state) {
+       execute_test(test_set_status_cb_02, state);
+}
+
+/* Test Steps for meshlink_set_status_cb Test Case # 2
+
+    Test Steps:
+    1. Calling meshlink_set_status_cb with NULL as mesh handle argument.
+
+    Expected Result:
+    set poll callback handles the invalid parameter when called by giving proper error number.
+*/
+static bool test_set_status_cb_02(void) {
+
+       // Create meshlink instance
+
+       meshlink_destroy("set_status_cb_conf.3");
+       meshlink_handle_t *mesh_handle = meshlink_open("set_status_cb_conf.3", "nut", "node_sim", 1);
+       assert(mesh_handle);
+
+       // Pass NULL as meshlink_set_node_status_cb's argument
+
+       meshlink_set_node_status_cb(NULL, status_cb);
+       meshlink_errno_t meshlink_errno_buff = meshlink_errno;
+       assert_int_equal(meshlink_errno_buff, MESHLINK_EINVAL);
+
+       // Clean up
+
+       meshlink_close(mesh_handle);
+       meshlink_destroy("set_status_cb_conf.3");
+       return true;
+}
+
+
+int test_meshlink_set_status_cb(void) {
+       const struct CMUnitTest blackbox_status_tests[] = {
+               cmocka_unit_test_prestate_setup_teardown(test_case_set_status_cb_01, NULL, NULL,
+                               (void *)&test_case_set_status_cb_01_state),
+               cmocka_unit_test_prestate_setup_teardown(test_case_set_status_cb_02, NULL, NULL,
+                               (void *)&test_case_set_status_cb_02_state)
+       };
+       total_tests += sizeof(blackbox_status_tests) / sizeof(blackbox_status_tests[0]);
+
+       int failed = cmocka_run_group_tests(blackbox_status_tests, NULL, NULL);
+
+       return failed;
+}
diff --git a/test/blackbox/run_blackbox_tests/test_cases_status_cb.h b/test/blackbox/run_blackbox_tests/test_cases_status_cb.h
new file mode 100644 (file)
index 0000000..16e03e3
--- /dev/null
@@ -0,0 +1,28 @@
+#ifndef TEST_CASES_SET_STATUS_CB_H
+#define TEST_CASES_SET_STATUS_CB_H
+
+/*
+    test_cases_status_cb.h -- Declarations for Individual Test Case implementation functions
+    Copyright (C) 2018  Guus Sliepen <guus@meshlink.io>
+
+    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 <stdbool.h>
+
+extern int test_meshlink_set_status_cb(void);
+extern int total_tests;
+
+#endif // TEST_CASES_SET_STATUS_CB_H
diff --git a/test/blackbox/run_blackbox_tests/test_cases_stop_close.c b/test/blackbox/run_blackbox_tests/test_cases_stop_close.c
new file mode 100644 (file)
index 0000000..fc82239
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+    test_cases_stop_close.c -- Execution of specific meshlink black box test cases
+    Copyright (C) 2018  Guus Sliepen <guus@meshlink.io>
+
+    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 "execute_tests.h"
+#include "test_cases_stop_close.h"
+#include "../common/containers.h"
+#include "../common/test_step.h"
+#include "../common/common_handlers.h"
+#include <stdlib.h>
+#include <stdarg.h>
+#include <setjmp.h>
+#include <cmocka.h>
+#include <assert.h>
+#include <string.h>
+#include <sys/wait.h>
+
+#define CLOSE_FILE_PATH "/home/sairoop/meshlink/test/blackbox/test_case_close/mesh_close"
+#define VALGRIND_LOG "valgrind.log"
+
+static void test_case_mesh_close_01(void **state);
+static bool test_steps_mesh_close_01(void);
+static void test_case_mesh_stop_01(void **state);
+static bool test_steps_mesh_stop_01(void);
+
+/* State structure for meshlink_close Test Case #1 */
+static black_box_state_t test_mesh_close_01_state = {
+       .test_case_name = "test_case_mesh_close_01",
+};
+
+/* State structure for meshlink_close Test Case #1 */
+static black_box_state_t test_mesh_stop_01_state = {
+       .test_case_name = "test_case_mesh_stop_01",
+};
+
+/* Execute meshlink_close Test Case # 1*/
+static void test_case_mesh_close_01(void **state) {
+       execute_test(test_steps_mesh_close_01, state);
+}
+
+/* Test Steps for meshlink_close Test Case # 1*/
+
+static bool test_steps_mesh_close_01(void) {
+       meshlink_close(NULL);
+       assert_int_equal(meshlink_errno, MESHLINK_EINVAL);
+
+       return true;
+}
+
+/* Execute meshlink_stop Test Case # 1*/
+static void test_case_mesh_stop_01(void **state) {
+       execute_test(test_steps_mesh_stop_01, state);
+}
+
+/* Test Steps for meshlink_stop Test Case # 1*/
+static bool test_steps_mesh_stop_01(void) {
+       meshlink_stop(NULL);
+       assert_int_equal(meshlink_errno, MESHLINK_EINVAL);
+
+       return true;
+}
+
+int test_meshlink_stop_close(void) {
+       const struct CMUnitTest blackbox_stop_close_tests[] = {
+               cmocka_unit_test_prestate_setup_teardown(test_case_mesh_stop_01, NULL, NULL,
+                               (void *)&test_mesh_stop_01_state),
+               cmocka_unit_test_prestate_setup_teardown(test_case_mesh_close_01, NULL, NULL,
+                               (void *)&test_mesh_close_01_state)
+       };
+
+       total_tests += sizeof(blackbox_stop_close_tests) / sizeof(blackbox_stop_close_tests[0]);
+
+       return cmocka_run_group_tests(blackbox_stop_close_tests, NULL, NULL);
+}
+
diff --git a/test/blackbox/run_blackbox_tests/test_cases_stop_close.h b/test/blackbox/run_blackbox_tests/test_cases_stop_close.h
new file mode 100644 (file)
index 0000000..ede4e5b
--- /dev/null
@@ -0,0 +1,29 @@
+#ifndef TEST_CASES_STOP_CLOSE_H
+#define TEST_CASES_STOP_CLOSE_H
+
+/*
+    test_cases_stop_close.h -- Declarations for Individual Test Case implementation functions
+    Copyright (C) 2018  Guus Sliepen <guus@meshlink.io>
+
+    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 <stdbool.h>
+
+extern int test_meshlink_stop_close(void);
+extern int total_tests;
+
+
+#endif
diff --git a/test/blackbox/run_blackbox_tests/test_cases_verify.c b/test/blackbox/run_blackbox_tests/test_cases_verify.c
new file mode 100644 (file)
index 0000000..e731747
--- /dev/null
@@ -0,0 +1,384 @@
+/*
+    test_cases_verify.c -- Execution of specific meshlink black box test cases
+    Copyright (C) 2018  Guus Sliepen <guus@meshlink.io>
+
+    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 "execute_tests.h"
+#include "test_cases_verify.h"
+#include "../common/containers.h"
+#include "../common/test_step.h"
+#include "../common/common_handlers.h"
+#include <assert.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <setjmp.h>
+#include <cmocka.h>
+
+/* Modify this to change the logging level of Meshlink */
+#define TEST_MESHLINK_LOG_LEVEL MESHLINK_DEBUG
+
+static void test_case_verify_01(void **state);
+static bool test_verify_01(void);
+static void test_case_verify_02(void **state);
+static bool test_verify_02(void);
+static void test_case_verify_03(void **state);
+static bool test_verify_03(void);
+static void test_case_verify_04(void **state);
+static bool test_verify_04(void);
+static void test_case_verify_05(void **state);
+static bool test_verify_05(void);
+static void test_case_verify_06(void **state);
+static bool test_verify_06(void);
+static void test_case_verify_07(void **state);
+static bool test_verify_07(void);
+static void test_case_verify_08(void **state);
+static bool test_verify_08(void);
+
+/* State structure for verify API Test Case #1 */
+static black_box_state_t test_case_verify_01_state = {
+       .test_case_name = "test_case_verify_01",
+};
+
+/* State structure for verify API Test Case #2 */
+static black_box_state_t test_case_verify_02_state = {
+       .test_case_name = "test_case_verify_02",
+};
+
+/* State structure for verify API Test Case #3 */
+static black_box_state_t test_case_verify_03_state = {
+       .test_case_name = "test_case_verify_03",
+};
+
+/* State structure for verify API Test Case #4 */
+static black_box_state_t test_case_verify_04_state = {
+       .test_case_name = "test_case_verify_04",
+};
+
+/* State structure for verify API Test Case #5 */
+static black_box_state_t test_case_verify_05_state = {
+       .test_case_name = "test_case_verify_05",
+};
+
+/* State structure for verify API Test Case #6 */
+static black_box_state_t test_case_verify_06_state = {
+       .test_case_name = "test_case_verify_06",
+};
+
+
+
+/* Execute meshlink_verify Test Case # 1 - Valid case - verify a data successfully*/
+void test_case_verify_01(void **state) {
+       execute_test(test_verify_01, state);
+}
+
+/* Test Steps for meshlink_sign Test Case # 1 - Valid case
+
+    Test Steps:
+    1. Run NUT(Node Under Test)
+    2. Sign data with meshlink_sign
+    3. Verify data with the sign buffer used while signing
+
+    Expected Result:
+    Verifies data successfully with the apt signature
+*/
+bool test_verify_01(void) {
+       meshlink_set_log_cb(NULL, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
+       meshlink_handle_t *mesh_handle = meshlink_open("verifyconf", "nut", "node_sim", DEV_CLASS_BACKBONE);
+       assert(mesh_handle);
+       meshlink_set_log_cb(mesh_handle, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
+       assert(meshlink_start(mesh_handle));
+
+       char *data = "Test";
+       char sig[MESHLINK_SIGLEN];
+       size_t ssize = MESHLINK_SIGLEN;
+       bool ret = meshlink_sign(mesh_handle, data, strlen(data) + 1, sig, &ssize);
+       assert(ret);
+
+       meshlink_node_t *source = meshlink_get_node(mesh_handle, "nut");
+       assert(source);
+       ret = meshlink_verify(mesh_handle, source, data, strlen(data) + 1, sig, ssize);
+       meshlink_close(mesh_handle);
+       meshlink_destroy("verifyconf");
+
+       if(!ret) {
+               PRINT_TEST_CASE_MSG("meshlink_verify FAILED to verify data\n");
+               return false;
+       }
+
+       PRINT_TEST_CASE_MSG("meshlink_verify Successfuly verified data\n");
+       return true;
+}
+
+
+/* Execute verify_data Test Case # 2 - Invalid case - meshlink_verify passing NULL args*/
+void test_case_verify_02(void **state) {
+       execute_test(test_verify_02, state);
+}
+
+/* Test Steps for meshlink_sign Test Case # 2 - Invalid case
+
+    Test Steps:
+    1. Run NUT(Node Under Test)
+    2. Sign data with meshlink_sign
+    3. Trying to pass NULL as mesh handle argument
+        and other arguments being valid
+
+    Expected Result:
+    Reports error accordingly by returning false
+*/
+bool test_verify_02(void) {
+       meshlink_set_log_cb(NULL, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
+       meshlink_handle_t *mesh_handle = meshlink_open("verifyconf", "nut", "node_sim", DEV_CLASS_BACKBONE);
+       assert(mesh_handle);
+       meshlink_set_log_cb(mesh_handle, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
+       assert(meshlink_start(mesh_handle));
+
+       char *data = "Test";
+       char sig[MESHLINK_SIGLEN];
+       size_t ssize = MESHLINK_SIGLEN;
+       bool sret = meshlink_sign(mesh_handle, data, strlen(data) + 1, sig, &ssize);
+       assert(sret);
+
+       meshlink_node_t *source = meshlink_get_node(mesh_handle, "nut");
+       assert(source != NULL);
+       bool ret = meshlink_verify(NULL, source, data, strlen(data) + 1, sig, ssize);
+       meshlink_close(mesh_handle);
+       meshlink_destroy("verifyconf");
+
+       if(!ret) {
+               PRINT_TEST_CASE_MSG("meshlink_sign Successfuly reported error on passing NULL as mesh_handle arg\n");
+               return true;
+       }
+
+       PRINT_TEST_CASE_MSG("meshlink_sign FAILED to report error on passing NULL as mesh_handle arg\n");
+       return false;
+}
+
+
+/* Execute verify_data Test Case # 3 - Invalid case - meshlink_verify passing NULL args*/
+void test_case_verify_03(void **state) {
+       execute_test(test_verify_03, state);
+}
+
+/* Test Steps for meshlink_sign Test Case # 3 - Invalid case
+
+    Test Steps:
+    1. Run NUT(Node Under Test)
+    2. Sign data with meshlink_sign
+    3. Trying to pass NULL as source node handle argument
+        and other arguments being valid
+
+    Expected Result:
+    Reports error accordingly by returning false
+*/
+bool test_verify_03(void) {
+       meshlink_set_log_cb(NULL, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
+       meshlink_handle_t *mesh_handle = meshlink_open("verifyconf", "nut", "node_sim", DEV_CLASS_BACKBONE);
+       assert(mesh_handle);
+       meshlink_set_log_cb(mesh_handle, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
+       assert(meshlink_start(mesh_handle));
+
+       char *data = "Test";
+       char sig[MESHLINK_SIGLEN];
+       size_t ssize = MESHLINK_SIGLEN;
+       bool ret = meshlink_sign(mesh_handle, data, strlen(data) + 1, sig, &ssize);
+       assert(ret);
+       ret = meshlink_verify(mesh_handle, NULL, data, strlen(data) + 1, sig, ssize);
+       meshlink_close(mesh_handle);
+       meshlink_destroy("verifyconf");
+
+       if(!ret) {
+               PRINT_TEST_CASE_MSG("meshlink_verify successfully reported NULL as node_handle arg\n");
+               return true;
+       }
+
+       PRINT_TEST_CASE_MSG("meshlink_verify FAILED to report NULL as node_handle arg\n");
+       return false;
+}
+
+/* Execute verify_data Test Case # 4 - Invalid case - meshlink_verify passing NULL args*/
+void test_case_verify_04(void **state) {
+       execute_test(test_verify_04, state);
+}
+
+/* Test Steps for meshlink_sign Test Case # 4 - Invalid case
+
+    Test Steps:
+    1. Run NUT(Node Under Test)
+    2. Sign data with meshlink_sign
+    3. Trying to pass NULL as signed data argument
+        and other arguments being valid
+
+    Expected Result:
+    Reports error accordingly by returning false
+*/
+bool test_verify_04(void) {
+       meshlink_destroy("verifyconf");
+       meshlink_set_log_cb(NULL, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
+       meshlink_handle_t *mesh_handle = meshlink_open("verifyconf", "nut", "node_sim", DEV_CLASS_BACKBONE);
+       assert(mesh_handle);
+       meshlink_set_log_cb(mesh_handle, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
+       assert(meshlink_start(mesh_handle));
+
+       char *data = "Test";
+       char sig[MESHLINK_SIGLEN];
+       size_t ssize = MESHLINK_SIGLEN;
+       bool ret = meshlink_sign(mesh_handle, data, strlen(data) + 1, sig, &ssize);
+       assert(ret);
+       meshlink_node_t *source = meshlink_get_node(mesh_handle, "nut");
+       assert(source != NULL);
+       ret = meshlink_verify(mesh_handle, source, NULL, strlen(data) + 1, sig, ssize);
+       meshlink_stop(mesh_handle);
+       meshlink_close(mesh_handle);
+       meshlink_destroy("verifyconf");
+
+       if(!ret) {
+               PRINT_TEST_CASE_MSG("meshlink_verify successfully reported NULL as data arg\n");
+               return true;
+       }
+
+       PRINT_TEST_CASE_MSG("meshlink_verify FAILED to report NULL as data arg\n");
+       return false;
+}
+
+
+/* Execute verify_data Test Case # 5 - Invalid case - meshlink_verify passing NULL args*/
+void test_case_verify_05(void **state) {
+       execute_test(test_verify_05, state);
+}
+
+/* Test Steps for meshlink_sign Test Case # 5 - Invalid case
+
+    Test Steps:
+    1. Run NUT(Node Under Test)
+    2. Sign data with meshlink_sign
+    3. Trying to pass NULL as signature buffer argument
+        and other arguments being valid
+
+    Expected Result:
+    Reports error accordingly by returning false
+*/
+bool test_verify_05(void) {
+       meshlink_set_log_cb(NULL, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
+       meshlink_handle_t *mesh_handle = meshlink_open("verifyconf", "nut", "node_sim", 1);
+       assert(mesh_handle);
+       meshlink_set_log_cb(mesh_handle, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
+       assert(meshlink_start(mesh_handle));
+
+       char *data = "Test";
+       char sig[MESHLINK_SIGLEN];
+       size_t ssize = MESHLINK_SIGLEN;
+       bool ret = meshlink_sign(mesh_handle, data, strlen(data) + 1, sig, &ssize);
+       assert(ret);
+       meshlink_node_t *source = meshlink_get_node(mesh_handle, "nut");
+       assert(source != NULL);
+
+       ret = meshlink_verify(mesh_handle, source, data, strlen(data) + 1, NULL, ssize);
+       meshlink_stop(mesh_handle);
+       meshlink_close(mesh_handle);
+       meshlink_destroy("verifyconf");
+
+       if(!ret) {
+               PRINT_TEST_CASE_MSG("meshlink_verify successfully NULL as sign arg\n");
+               return true;
+       }
+
+       PRINT_TEST_CASE_MSG("meshlink_verify FAILED to report NULL as sign arg\n");
+       return false;
+}
+
+/* Execute verify_data Test Case # 6 - Functionality test, when a wrong source node is mentioned to verify
+      the signed data */
+void test_case_verify_06(void **state) {
+       execute_test(test_verify_06, state);
+}
+
+/* Test Steps for meshlink_verify Test Case # 6 - Functionality Test
+
+    Test Steps:
+    1. Run NUT(Node Under Test) and peer
+    2. Sign using peer as source node.
+    3. Verify with NUT but passing NUT as source node rather than
+        'peer' as source node
+
+    Expected Result:
+    API returns false when it detects the wrong source node
+*/
+bool test_verify_06(void) {
+       /* deleting the confbase if already exists */
+       meshlink_destroy("verifyconf1");
+       meshlink_destroy("verifyconf2");
+       /* Set up logging for Meshlink */
+       meshlink_set_log_cb(NULL, TEST_MESHLINK_LOG_LEVEL, meshlink_callback_logger);
+       meshlink_handle_t *mesh1 = meshlink_open("verifyconf1", "nut", "chat", DEV_CLASS_STATIONARY);
+       assert(mesh1);
+       meshlink_handle_t *mesh2 = meshlink_open("verifyconf2", "bar", "chat", DEV_CLASS_STATIONARY);
+       assert(mesh2);
+
+       char *exp1 = meshlink_export(mesh1);
+       assert(exp1 != NULL);
+       char *exp2 = meshlink_export(mesh2);
+       assert(exp2 != NULL);
+       assert(meshlink_import(mesh1, exp2));
+       assert(meshlink_import(mesh2, exp1));
+
+       /* signing done by peer node  */
+       char *data = "Test";
+       char sig[MESHLINK_SIGLEN];
+       size_t ssize = MESHLINK_SIGLEN;
+       bool ret = meshlink_sign(mesh2, data, strlen(data) + 1, sig, &ssize);
+       assert(ret);
+
+       meshlink_node_t *source_nut = meshlink_get_self(mesh1);
+       assert(source_nut);
+       ret = meshlink_verify(mesh_handle, source_nut, data, strlen(data) + 1, sig, ssize);
+       meshlink_close(mesh1);
+       meshlink_close(mesh2);
+       meshlink_destroy("verifyconf1");
+       meshlink_destroy("verifyconf2");
+
+       if(!ret) {
+               PRINT_TEST_CASE_MSG("meshlink_verify successfully returned 'false' when a wrong source node used to verify the data\n");
+               return true;
+       }
+
+       PRINT_TEST_CASE_MSG("meshlink_verify FAILED to report error when a wrong source is mentioned\n");
+       return false;
+}
+
+
+int test_meshlink_verify(void) {
+       const struct CMUnitTest blackbox_verify_tests[] = {
+               cmocka_unit_test_prestate_setup_teardown(test_case_verify_01, NULL, NULL,
+                               (void *)&test_case_verify_01_state),
+               cmocka_unit_test_prestate_setup_teardown(test_case_verify_02, NULL, NULL,
+                               (void *)&test_case_verify_02_state),
+               cmocka_unit_test_prestate_setup_teardown(test_case_verify_03, NULL, NULL,
+                               (void *)&test_case_verify_03_state),
+               cmocka_unit_test_prestate_setup_teardown(test_case_verify_04, NULL, NULL,
+                               (void *)&test_case_verify_04_state),
+               cmocka_unit_test_prestate_setup_teardown(test_case_verify_05, NULL, NULL,
+                               (void *)&test_case_verify_05_state),
+               cmocka_unit_test_prestate_setup_teardown(test_case_verify_06, NULL, NULL,
+                               (void *)&test_case_verify_06_state)
+       };
+
+       total_tests += sizeof(blackbox_verify_tests) / sizeof(blackbox_verify_tests[0]);
+
+       return cmocka_run_group_tests(blackbox_verify_tests, NULL, NULL);
+}
diff --git a/test/blackbox/run_blackbox_tests/test_cases_verify.h b/test/blackbox/run_blackbox_tests/test_cases_verify.h
new file mode 100644 (file)
index 0000000..39661a0
--- /dev/null
@@ -0,0 +1,29 @@
+#ifndef TEST_CASES_VERIFY_H
+#define TEST_CASES_VERIFY_H
+
+/*
+    test_cases_verify.h -- Declarations for Individual Test Case implementation functions
+    Copyright (C) 2018  Guus Sliepen <guus@meshlink.io>
+
+    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 <stdbool.h>
+
+extern int total_tests;
+extern int test_meshlink_verify(void);
+
+#endif // TEST_CASES_VERIFY_H
diff --git a/test/blackbox/run_blackbox_tests/test_cases_whitelist.c b/test/blackbox/run_blackbox_tests/test_cases_whitelist.c
new file mode 100644 (file)
index 0000000..0ee8636
--- /dev/null
@@ -0,0 +1,323 @@
+/*
+    test_cases_whitelist.c -- Execution of specific meshlink black box test cases
+    Copyright (C) 2018  Guus Sliepen <guus@meshlink.io>
+
+    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 "execute_tests.h"
+#include "test_cases_whitelist.h"
+#include "../common/containers.h"
+#include "../common/test_step.h"
+#include "../common/common_handlers.h"
+#include <assert.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <setjmp.h>
+#include <cmocka.h>
+#include <pthread.h>
+#include <errno.h>
+
+#include "../../utils.h"
+
+static void test_case_mesh_whitelist_01(void **state);
+static bool test_steps_mesh_whitelist_01(void);
+static void test_case_mesh_whitelist_02(void **state);
+static bool test_steps_mesh_whitelist_02(void);
+static void test_case_mesh_whitelist_03(void **state);
+static bool test_steps_mesh_whitelist_03(void);
+
+/* State structure for meshlink_whitelist Test Case #1 */
+static black_box_state_t test_mesh_whitelist_01_state = {
+       .test_case_name = "test_case_mesh_whitelist_01",
+};
+
+/* State structure for meshlink_whitelist Test Case #2 */
+static black_box_state_t test_mesh_whitelist_02_state = {
+       .test_case_name = "test_case_mesh_whitelist_02",
+};
+
+/* State structure for meshlink_whitelist Test Case #3 */
+static black_box_state_t test_mesh_whitelist_03_state = {
+       .test_case_name = "test_case_mesh_whitelist_03",
+};
+
+static bool rec_stat;
+static bool reachable;
+static pthread_mutex_t lock_receive = PTHREAD_MUTEX_INITIALIZER;
+static pthread_cond_t receive_cond = PTHREAD_COND_INITIALIZER;
+static pthread_mutex_t reachable_lock = PTHREAD_MUTEX_INITIALIZER;
+static pthread_cond_t reachable_cond = PTHREAD_COND_INITIALIZER;
+
+
+/* Execute meshlink_whitelist Test Case # 1*/
+static void test_case_mesh_whitelist_01(void **state) {
+       execute_test(test_steps_mesh_whitelist_01, state);
+}
+
+
+static void receive(meshlink_handle_t *mesh, meshlink_node_t *src, const void *data, size_t len) {
+       const char *msg = data;
+       assert(len);
+
+       pthread_mutex_lock(& lock_receive);
+       rec_stat = true;
+       assert(!pthread_cond_broadcast(&receive_cond));
+       pthread_mutex_unlock(& lock_receive);
+
+}
+
+static void status_cb(meshlink_handle_t *mesh, meshlink_node_t *node, bool reach) {
+       if(!strcmp(node->name, "bar")) {
+               pthread_mutex_lock(&reachable_lock);
+               reachable = reach;
+               assert(!pthread_cond_broadcast(&reachable_cond));
+               pthread_mutex_unlock(&reachable_lock);
+       }
+}
+
+
+/* Test Steps for meshlink_whitelist Test Case # 1
+
+    Test Steps:
+    1. Run 2 node instances
+    2. Blacklist one node and again whitelist the blacklisted node
+
+    Expected Result:
+    meshlink_whitelist API whitelists the blacklisted node
+*/
+static bool test_steps_mesh_whitelist_01(void) {
+       struct timespec timeout = {0};
+
+       // Open two new meshlink instance.
+
+       meshlink_destroy("whitelist_conf.1");
+       meshlink_destroy("whitelist_conf.2");
+       meshlink_handle_t *mesh1 = meshlink_open("whitelist_conf.1", "foo", "test", DEV_CLASS_BACKBONE);
+       assert(mesh1);
+       meshlink_set_log_cb(mesh1, MESHLINK_DEBUG, meshlink_callback_logger);
+       meshlink_handle_t *mesh2 = meshlink_open("whitelist_conf.2", "bar", "test", DEV_CLASS_BACKBONE);
+       assert(mesh2);
+       meshlink_set_log_cb(mesh2, MESHLINK_DEBUG, meshlink_callback_logger);
+       meshlink_set_receive_cb(mesh2, receive);
+       meshlink_set_receive_cb(mesh1, receive);
+
+       // Export & Import to join the mesh
+
+       reachable = false;
+       char *data = meshlink_export(mesh1);
+       assert(data);
+       assert(meshlink_import(mesh2, data));
+       free(data);
+       data = meshlink_export(mesh2);
+       assert(data);
+       assert(meshlink_import(mesh1, data));
+       free(data);
+
+       // Start both instances
+
+       meshlink_set_node_status_cb(mesh1, status_cb);
+       assert(meshlink_start(mesh1));
+       assert(meshlink_start(mesh2));
+
+       // Nodes should know each other
+       timeout.tv_sec = time(NULL) + 10;
+       pthread_mutex_lock(&reachable_lock);
+
+       while(reachable == false) {
+               assert(!pthread_cond_timedwait(&reachable_cond, &reachable_lock, &timeout));
+       }
+
+       pthread_mutex_unlock(&reachable_lock);
+       sleep(1);
+
+       meshlink_node_t *bar = meshlink_get_node(mesh1, "bar");
+       assert(bar);
+       meshlink_node_t *foo = meshlink_get_node(mesh2, "foo");
+       assert(foo);
+
+       rec_stat = false;
+       assert(meshlink_send(mesh1, bar, "test", 5));
+       timeout.tv_sec = time(NULL) + 10;
+       pthread_mutex_lock(& lock_receive);
+
+       if(rec_stat == false) {
+               assert(pthread_cond_timedwait(&receive_cond, &lock_receive, &timeout) == 0);
+       }
+
+       pthread_mutex_unlock(& lock_receive);
+
+
+       meshlink_blacklist(mesh1, foo);
+
+       rec_stat = false;
+       assert(meshlink_send(mesh1, bar, "test", 5));
+       timeout.tv_sec = time(NULL) + 10;
+       pthread_mutex_lock(& lock_receive);
+
+       if(rec_stat == false) {
+               int err = pthread_cond_timedwait(&receive_cond, &lock_receive, &timeout);
+               assert(err == ETIMEDOUT);
+       }
+
+       pthread_mutex_unlock(& lock_receive);
+       meshlink_whitelist(mesh1, foo);
+
+       rec_stat = false;
+       bool result = meshlink_send(mesh2, foo, "test", 5);
+       timeout.tv_sec = time(NULL) + 10;
+       pthread_mutex_lock(& lock_receive);
+
+       if(rec_stat == false) {
+               assert(pthread_cond_timedwait(&receive_cond, &lock_receive, &timeout) == 0);
+       }
+
+       pthread_mutex_unlock(& lock_receive);
+
+       // Clean up.
+
+       meshlink_close(mesh2);
+       meshlink_close(mesh1);
+       meshlink_destroy("whitelist_conf.1");
+       meshlink_destroy("whitelist_conf.2");
+
+       return result;
+}
+
+/* Test Steps for meshlink_whitelist Test Case # 2
+
+    Test Steps:
+    1. Calling meshlink_whitelist with NULL as mesh handle argument.
+
+    Expected Result:
+    meshlink_whitelist API handles the invalid parameter when called by giving proper error number.
+*/
+static void test_case_mesh_whitelist_02(void **state) {
+       execute_test(test_steps_mesh_whitelist_02, state);
+}
+
+/* Test Steps for meshlink_whitelist Test Case # 2*/
+static bool test_steps_mesh_whitelist_02(void) {
+       struct timespec timeout = {0};
+
+       // Open two new meshlink instance.
+
+       meshlink_destroy("whitelist_conf.3");
+       meshlink_destroy("whitelist_conf.4");
+       meshlink_handle_t *mesh1 = meshlink_open("whitelist_conf.3", "foo", "test", DEV_CLASS_BACKBONE);
+       assert(mesh1);
+       meshlink_handle_t *mesh2 = meshlink_open("whitelist_conf.4", "bar", "test", DEV_CLASS_BACKBONE);
+       assert(mesh2);
+       meshlink_set_receive_cb(mesh2, receive);
+       meshlink_set_receive_cb(mesh1, receive);
+
+       char *data = meshlink_export(mesh1);
+       assert(data);
+       assert(meshlink_import(mesh2, data));
+       free(data);
+       data = meshlink_export(mesh2);
+       assert(data);
+       assert(meshlink_import(mesh1, data));
+       free(data);
+
+       // Start both instances
+
+       reachable = false;
+       meshlink_set_node_status_cb(mesh1, status_cb);
+       assert(meshlink_start(mesh1));
+       assert(meshlink_start(mesh2));
+
+       // Nodes should know each other
+       timeout.tv_sec = time(NULL) + 10;
+       pthread_mutex_lock(&reachable_lock);
+
+       while(reachable == false) {
+               assert(!pthread_cond_timedwait(&reachable_cond, &reachable_lock, &timeout));
+       }
+
+       pthread_mutex_unlock(&reachable_lock);
+
+       meshlink_node_t *bar = meshlink_get_node(mesh1, "bar");
+       assert(bar);
+       meshlink_node_t *foo = meshlink_get_node(mesh2, "foo");
+       assert(foo);
+
+       assert(meshlink_send(mesh1, bar, "test", 5));
+
+       meshlink_blacklist(mesh1, foo);
+
+       // Passing NULL as mesh handle but with valid node handle 'foo'
+
+       meshlink_whitelist(NULL, foo);
+       assert_int_equal(meshlink_errno, MESHLINK_EINVAL);
+
+       // Clean up.
+
+       meshlink_close(mesh2);
+       meshlink_close(mesh1);
+       meshlink_destroy("whitelist_conf.3");
+       meshlink_destroy("whitelist_conf.4");
+
+       return true;
+}
+
+/* Execute meshlink_whitelist Test Case # 3*/
+static void test_case_mesh_whitelist_03(void **state) {
+       execute_test(test_steps_mesh_whitelist_03, state);
+}
+
+/* Test Steps for meshlink_whitelist Test Case # 3
+
+    Test Steps:
+    1. Calling meshlink_whitelist with NULL as node handle argument.
+
+    Expected Result:
+    meshlink_whitelist API handles the invalid parameter when called by giving proper error number.
+*/
+static bool test_steps_mesh_whitelist_03(void) {
+       // Open meshlink instance.
+
+       meshlink_destroy("whitelist_conf");
+       meshlink_handle_t *mesh = meshlink_open("whitelist_conf", "foo", "test", DEV_CLASS_BACKBONE);
+       assert(mesh);
+
+       // Start instance
+       assert(meshlink_start(mesh));
+
+       meshlink_whitelist(mesh, NULL);
+       assert_int_equal(meshlink_errno, MESHLINK_EINVAL);
+
+       // Clean up.
+
+       meshlink_close(mesh);
+       meshlink_destroy("whitelist_conf");
+       return true;
+}
+
+int test_meshlink_whitelist(void) {
+       const struct CMUnitTest blackbox_whitelist_tests[] = {
+               cmocka_unit_test_prestate_setup_teardown(test_case_mesh_whitelist_01, NULL, NULL,
+                               (void *)&test_mesh_whitelist_01_state),
+               cmocka_unit_test_prestate_setup_teardown(test_case_mesh_whitelist_02, NULL, NULL,
+                               (void *)&test_mesh_whitelist_02_state),
+               cmocka_unit_test_prestate_setup_teardown(test_case_mesh_whitelist_03, NULL, NULL,
+                               (void *)&test_mesh_whitelist_03_state)
+       };
+
+       total_tests += sizeof(blackbox_whitelist_tests) / sizeof(blackbox_whitelist_tests[0]);
+
+       return cmocka_run_group_tests(blackbox_whitelist_tests, NULL, NULL);
+}
diff --git a/test/blackbox/run_blackbox_tests/test_cases_whitelist.h b/test/blackbox/run_blackbox_tests/test_cases_whitelist.h
new file mode 100644 (file)
index 0000000..f7f79c4
--- /dev/null
@@ -0,0 +1,28 @@
+#ifndef TEST_CASES_WHITELIST_H
+#define TEST_CASES_WHITELIST_H
+
+/*
+    test_cases_whitelist.h -- Declarations for Individual Test Case implementation functions
+    Copyright (C) 2018  Guus Sliepen <guus@meshlink.io>
+
+    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 <stdbool.h>
+
+extern int test_meshlink_whitelist(void);
+extern int total_tests;
+
+#endif
diff --git a/test/blackbox/test_case_meta_conn_01/Makefile.am b/test/blackbox/test_case_meta_conn_01/Makefile.am
new file mode 100644 (file)
index 0000000..b12e440
--- /dev/null
@@ -0,0 +1,13 @@
+check_PROGRAMS = node_sim_relay node_sim_peer node_sim_nut
+
+node_sim_peer_SOURCES = node_sim_peer.c ../common/common_handlers.c ../common/test_step.c ../common/mesh_event_handler.c
+node_sim_peer_LDADD = ../../../src/libmeshlink.la
+node_sim_peer_CFLAGS = -D_GNU_SOURCE -fsanitize=leak
+
+node_sim_relay_SOURCES = node_sim_relay.c ../common/common_handlers.c ../common/test_step.c ../common/mesh_event_handler.c
+node_sim_relay_LDADD = ../../../src/libmeshlink.la
+node_sim_relay_CFLAGS = -D_GNU_SOURCE -fsanitize=leak
+
+node_sim_nut_SOURCES = node_sim_nut.c ../common/common_handlers.c ../common/test_step.c ../common/mesh_event_handler.c
+node_sim_nut_LDADD = ../../../src/libmeshlink.la
+node_sim_nut_CFLAGS = -D_GNU_SOURCE -fsanitize=leak
diff --git a/test/blackbox/test_case_meta_conn_01/node_sim_nut.c b/test/blackbox/test_case_meta_conn_01/node_sim_nut.c
new file mode 100644 (file)
index 0000000..fc985bd
--- /dev/null
@@ -0,0 +1,131 @@
+/*
+    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 <guus@meshlink.io>
+
+    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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <pthread.h>
+#include "../common/common_handlers.h"
+#include "../common/test_step.h"
+#include "../common/mesh_event_handler.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
+
+static bool conn_status = false;
+
+static void callback_logger(meshlink_handle_t *mesh, meshlink_log_level_t level,
+                            const char *text) {
+       char connection_match_msg[100];
+
+       fprintf(stderr, "meshlink>> %s\n", text);
+
+       if(strstr(text, "Connection") || strstr(text, "connection")) {
+               assert(snprintf(connection_match_msg, sizeof(connection_match_msg),
+                               "Connection with peer") >= 0);
+
+               if(strstr(text, connection_match_msg) && strstr(text, "activated")) {
+                       conn_status = true;
+                       return;
+               }
+
+               assert(snprintf(connection_match_msg, sizeof(connection_match_msg),
+                               "Already connected to peer") >= 0);
+
+               if(strstr(text, connection_match_msg)) {
+                       conn_status = true;
+                       return;
+               }
+
+               assert(snprintf(connection_match_msg, sizeof(connection_match_msg),
+                               "Connection closed by peer") >= 0);
+
+               if(strstr(text, connection_match_msg)) {
+                       conn_status = false;
+                       return;
+               }
+
+               assert(snprintf(connection_match_msg, sizeof(connection_match_msg),
+                               "Closing connection with peer") >= 0);
+
+               if(strstr(text, connection_match_msg)) {
+                       conn_status = false;
+                       return;
+               }
+       }
+
+       return;
+}
+
+int main(int argc, char *argv[]) {
+       int client_id = -1;
+       bool result = false;
+       int i;
+
+       if((argv[3]) && (argv[4])) {
+               client_id = atoi(argv[3]);
+               mesh_event_sock_connect(argv[4]);
+       }
+
+       execute_open(argv[1], argv[2]);
+       meshlink_set_log_cb(mesh_handle, MESHLINK_INFO, callback_logger);
+
+       if(argv[5]) {
+               execute_join(argv[5]);
+       }
+
+       execute_start();
+
+       if(!mesh_event_sock_send(client_id, NODE_STARTED, NULL, 0)) {
+               fprintf(stderr, "Trying to resend mesh event\n");
+               sleep(1);
+       }
+
+       /* Connectivity of peer */
+       while(!conn_status) {
+               sleep(1);
+       }
+
+       fprintf(stderr, "Connected with Peer\n");
+       assert(mesh_event_sock_send(client_id, META_CONN_SUCCESSFUL, "Connected with Peer", 30));
+
+       /* Connectivity of peer */
+       while(conn_status) {
+               sleep(1);
+       }
+
+       fprintf(stderr, "Closed connection with Peer\n");
+       assert(mesh_event_sock_send(client_id, META_CONN_CLOSED, "Connection closed with Peer", 30));
+
+       /* Connectivity of peer */
+       while(!conn_status) {
+               sleep(1);
+       }
+
+       fprintf(stderr, "Connected with Peer\n");
+       assert(mesh_event_sock_send(client_id, META_RECONN_SUCCESSFUL, "Reconnected with Peer", 30));
+
+       execute_close();
+
+       return 0;
+}
diff --git a/test/blackbox/test_case_meta_conn_01/node_sim_peer.c b/test/blackbox/test_case_meta_conn_01/node_sim_peer.c
new file mode 100644 (file)
index 0000000..521a7bb
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+    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 <guus@meshlink.io>
+
+    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 <stdio.h>
+#include <stdlib.h>
+#include "../common/common_handlers.h"
+#include "../common/test_step.h"
+#include "../common/mesh_event_handler.h"
+
+int main(int argc, char *argv[]) {
+       struct timeval main_loop_wait = { 5, 0 };
+       int client_id = -1;
+
+       if((argv[3]) && (argv[4])) {
+               client_id = atoi(argv[3]);
+               mesh_event_sock_connect(argv[4]);
+       }
+
+       /* Setup required signals */
+       setup_signals();
+
+       /* Execute test steps */
+       execute_open(argv[1], argv[2]);
+
+       if(argv[5]) {
+               execute_join(argv[5]);
+       }
+
+       execute_start();
+
+       if(client_id != -1) {
+               if(!mesh_event_sock_send(client_id, NODE_STARTED, NULL, 0)) {
+                       fprintf(stderr, "Trying to resend mesh event\n");
+                       sleep(1);
+               }
+       }
+
+       /* 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);
+       }
+
+       execute_close();
+}
diff --git a/test/blackbox/test_case_meta_conn_01/node_sim_relay.c b/test/blackbox/test_case_meta_conn_01/node_sim_relay.c
new file mode 100644 (file)
index 0000000..3d5ba06
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+    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 <guus@meshlink.io>
+
+    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 <stdio.h>
+#include <stdlib.h>
+#include "../common/common_handlers.h"
+#include "../common/test_step.h"
+#include "../common/mesh_event_handler.h"
+
+int main(int argc, char *argv[]) {
+       struct timeval main_loop_wait = { 5, 0 };
+
+       int client_id = -1;
+
+       if((argv[3]) && (argv[4])) {
+               client_id = atoi(argv[3]);
+               mesh_event_sock_connect(argv[4]);
+       }
+
+       /* Setup required signals */
+       setup_signals();
+
+       /* Execute test steps */
+       execute_open(argv[1], argv[2]);
+       execute_start();
+
+       if(client_id != -1) {
+               if(!mesh_event_sock_send(client_id, NODE_STARTED, NULL, 0)) {
+                       fprintf(stderr, "Trying to resend mesh event\n");
+                       sleep(1);
+               }
+       }
+
+       /* 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);
+       }
+
+       execute_close();
+}
diff --git a/test/blackbox/test_case_meta_conn_02/Makefile.am b/test/blackbox/test_case_meta_conn_02/Makefile.am
new file mode 100644 (file)
index 0000000..6331fb9
--- /dev/null
@@ -0,0 +1,13 @@
+check_PROGRAMS = node_sim_peer node_sim_relay node_sim_nut
+
+node_sim_peer_SOURCES = node_sim_peer.c ../common/common_handlers.c ../common/test_step.c ../common/mesh_event_handler.c
+node_sim_peer_LDADD = ../../../src/libmeshlink.la
+node_sim_peer_CFLAGS = -D_GNU_SOURCE -fsanitize=leak
+
+node_sim_relay_SOURCES = node_sim_relay.c ../common/common_handlers.c ../common/test_step.c ../common/mesh_event_handler.c
+node_sim_relay_LDADD = ../../../src/libmeshlink.la
+node_sim_relay_CFLAGS = -D_GNU_SOURCE -fsanitize=leak
+
+node_sim_nut_SOURCES = node_sim_nut.c ../common/common_handlers.c ../common/test_step.c ../common/mesh_event_handler.c
+node_sim_nut_LDADD = ../../../src/libmeshlink.la
+node_sim_nut_CFLAGS = -D_GNU_SOURCE -fsanitize=leak
diff --git a/test/blackbox/test_case_meta_conn_02/node_sim_nut.c b/test/blackbox/test_case_meta_conn_02/node_sim_nut.c
new file mode 100644 (file)
index 0000000..f447c40
--- /dev/null
@@ -0,0 +1,115 @@
+/*
+    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 <guus@meshlink.io>
+
+    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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <pthread.h>
+#include "../common/common_handlers.h"
+#include "../common/test_step.h"
+#include "../common/mesh_event_handler.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
+
+static bool conn_status = false;
+
+static void callback_logger(meshlink_handle_t *mesh, meshlink_log_level_t level,
+                            const char *text) {
+       char connection_match_msg[100];
+
+       fprintf(stderr, "meshlink>> %s\n", text);
+
+       if(strstr(text, "Connection") || strstr(text, "connection")) {
+               assert(snprintf(connection_match_msg, sizeof(connection_match_msg),
+                               "Connection with peer") >= 0);
+
+               if(strstr(text, connection_match_msg) && strstr(text, "activated")) {
+                       conn_status = true;
+                       return;
+               }
+
+               assert(snprintf(connection_match_msg, sizeof(connection_match_msg),
+                               "Already connected to peer") >= 0);
+
+               if(strstr(text, connection_match_msg)) {
+                       conn_status = true;
+                       return;
+               }
+
+               assert(snprintf(connection_match_msg, sizeof(connection_match_msg),
+                               "Connection closed by peer") >= 0);
+
+               if(strstr(text, connection_match_msg)) {
+                       conn_status = false;
+                       return;
+               }
+
+               assert(snprintf(connection_match_msg, sizeof(connection_match_msg),
+                               "Closing connection with peer") >= 0);
+
+               if(strstr(text, connection_match_msg)) {
+                       conn_status = false;
+                       return;
+               }
+       }
+
+       return;
+}
+
+int main(int argc, char *argv[]) {
+       int client_id = -1;
+       bool result = false;
+       int i;
+
+       if((argv[3]) && (argv[4])) {
+               client_id = atoi(argv[3]);
+               mesh_event_sock_connect(argv[4]);
+       }
+
+       execute_open(argv[1], argv[2]);
+       meshlink_set_log_cb(mesh_handle, MESHLINK_INFO, callback_logger);
+
+       if(argv[5]) {
+               execute_join(argv[5]);
+       }
+
+       execute_start();
+
+       if(!mesh_event_sock_send(client_id, NODE_STARTED, NULL, 0)) {
+               fprintf(stderr, "Trying to resend mesh event\n");
+               sleep(1);
+       }
+
+       /* Connectivity of peer */
+       while(!conn_status) {
+               sleep(1);
+       }
+
+       fprintf(stderr, "Connected with Peer\n");
+       assert(mesh_event_sock_send(client_id, META_CONN_SUCCESSFUL, "Connected with Peer", 30));
+
+       execute_close();
+
+       return 0;
+}
diff --git a/test/blackbox/test_case_meta_conn_02/node_sim_peer.c b/test/blackbox/test_case_meta_conn_02/node_sim_peer.c
new file mode 100644 (file)
index 0000000..a61e89e
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+    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 <guus@meshlink.io>
+
+    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 <stdio.h>
+#include <stdlib.h>
+#include "../common/common_handlers.h"
+#include "../common/test_step.h"
+#include "../common/mesh_event_handler.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
+
+int main(int argc, char *argv[]) {
+       struct timeval main_loop_wait = { 5, 0 };
+       int client_id = -1;
+
+       if((argv[3]) && (argv[4])) {
+               client_id = atoi(argv[3]);
+               mesh_event_sock_connect(argv[4]);
+       }
+
+       /* Setup required signals */
+       setup_signals();
+
+       /* Execute test steps */
+       execute_open(argv[1], argv[2]);
+
+       if(argv[5]) {
+               execute_join(argv[5]);
+       }
+
+       execute_start();
+
+       if(client_id != -1) {
+               if(!mesh_event_sock_send(client_id, NODE_STARTED, NULL, 0)) {
+                       fprintf(stderr, "Trying to resend mesh event\n");
+                       sleep(1);
+               }
+       }
+
+       /* 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);
+       }
+
+       execute_close();
+}
diff --git a/test/blackbox/test_case_meta_conn_02/node_sim_relay.c b/test/blackbox/test_case_meta_conn_02/node_sim_relay.c
new file mode 100644 (file)
index 0000000..6e6caab
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+    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 <guus@meshlink.io>
+
+    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 <stdio.h>
+#include <stdlib.h>
+#include "../common/common_handlers.h"
+#include "../common/test_step.h"
+#include "../common/mesh_event_handler.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
+
+int main(int argc, char *argv[]) {
+       struct timeval main_loop_wait = { 5, 0 };
+
+       int client_id = -1;
+
+       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();
+
+       /* Execute test steps */
+       execute_open(argv[CMD_LINE_ARG_NODENAME], argv[CMD_LINE_ARG_DEVCLASS]);
+       execute_start();
+
+       if(client_id != -1) {
+               if(!mesh_event_sock_send(client_id, NODE_STARTED, NULL, 0)) {
+                       fprintf(stderr, "Trying to resend mesh event\n");
+                       sleep(1);
+               }
+       }
+
+       /* 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);
+       }
+
+       execute_close();
+}
diff --git a/test/blackbox/test_case_meta_conn_03/Makefile.am b/test/blackbox/test_case_meta_conn_03/Makefile.am
new file mode 100644 (file)
index 0000000..6331fb9
--- /dev/null
@@ -0,0 +1,13 @@
+check_PROGRAMS = node_sim_peer node_sim_relay node_sim_nut
+
+node_sim_peer_SOURCES = node_sim_peer.c ../common/common_handlers.c ../common/test_step.c ../common/mesh_event_handler.c
+node_sim_peer_LDADD = ../../../src/libmeshlink.la
+node_sim_peer_CFLAGS = -D_GNU_SOURCE -fsanitize=leak
+
+node_sim_relay_SOURCES = node_sim_relay.c ../common/common_handlers.c ../common/test_step.c ../common/mesh_event_handler.c
+node_sim_relay_LDADD = ../../../src/libmeshlink.la
+node_sim_relay_CFLAGS = -D_GNU_SOURCE -fsanitize=leak
+
+node_sim_nut_SOURCES = node_sim_nut.c ../common/common_handlers.c ../common/test_step.c ../common/mesh_event_handler.c
+node_sim_nut_LDADD = ../../../src/libmeshlink.la
+node_sim_nut_CFLAGS = -D_GNU_SOURCE -fsanitize=leak
diff --git a/test/blackbox/test_case_meta_conn_03/node_sim_nut.c b/test/blackbox/test_case_meta_conn_03/node_sim_nut.c
new file mode 100644 (file)
index 0000000..573e185
--- /dev/null
@@ -0,0 +1,126 @@
+/*
+    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 <guus@meshlink.io>
+
+    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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <pthread.h>
+#include "../common/common_handlers.h"
+#include "../common/test_step.h"
+#include "../common/mesh_event_handler.h"
+
+static bool conn_status = false;
+
+void callback_logger(meshlink_handle_t *mesh, meshlink_log_level_t level,
+                     const char *text) {
+       char connection_match_msg[100];
+
+       fprintf(stderr, "meshlink>> %s\n", text);
+
+       if(strstr(text, "Connection") || strstr(text, "connection")) {
+               assert(snprintf(connection_match_msg, sizeof(connection_match_msg),
+                               "Connection with peer") >= 0);
+
+               if(strstr(text, connection_match_msg) && strstr(text, "activated")) {
+                       conn_status = true;
+                       return;
+               }
+
+               assert(snprintf(connection_match_msg, sizeof(connection_match_msg),
+                               "Already connected to peer") >= 0);
+
+               if(strstr(text, connection_match_msg)) {
+                       conn_status = true;
+                       return;
+               }
+
+               assert(snprintf(connection_match_msg, sizeof(connection_match_msg),
+                               "Connection closed by peer") >= 0);
+
+               if(strstr(text, connection_match_msg)) {
+                       conn_status = false;
+                       return;
+               }
+
+               assert(snprintf(connection_match_msg, sizeof(connection_match_msg),
+                               "Closing connection with peer") >= 0);
+
+               if(strstr(text, connection_match_msg)) {
+                       conn_status = false;
+                       return;
+               }
+       }
+
+       return;
+}
+
+int main(int argc, char *argv[]) {
+       int client_id = -1;
+       bool result = false;
+       int i;
+
+       if((argv[3]) && (argv[4])) {
+               client_id = atoi(argv[3]);
+               mesh_event_sock_connect(argv[4]);
+       }
+
+       execute_open(argv[1], argv[2]);
+       meshlink_set_log_cb(mesh_handle, MESHLINK_DEBUG, callback_logger);
+
+       if(argv[5]) {
+               execute_join(argv[5]);
+       }
+
+       execute_start();
+       mesh_event_sock_send(client_id, NODE_STARTED, NULL, 0);
+
+       /* Connectivity of peer is checked using meshlink_get_node API */
+       while(!conn_status) {
+               sleep(1);
+       }
+
+       sleep(1);
+       fprintf(stderr, "Connected with Peer\n");
+       mesh_event_sock_send(client_id, META_CONN_SUCCESSFUL, "Connected with Peer", 30);
+
+       conn_status = false;
+       fprintf(stderr, "Waiting 120 sec for peer to be re-connected\n");
+
+       for(i = 0; i < 120; i++) {
+               if(conn_status) {
+                       result = true;
+                       break;
+               }
+
+               sleep(1);
+       }
+
+       if(result) {
+               fprintf(stderr, "Re-connected with Peer\n");
+               mesh_event_sock_send(client_id, META_RECONN_SUCCESSFUL, "Peer", 30);
+       } else {
+               fprintf(stderr, "Failed to reconnect with Peer\n");
+               mesh_event_sock_send(client_id, META_RECONN_FAILURE, "Peer", 30);
+       }
+
+       execute_close();
+
+       return 0;
+}
diff --git a/test/blackbox/test_case_meta_conn_03/node_sim_peer.c b/test/blackbox/test_case_meta_conn_03/node_sim_peer.c
new file mode 100644 (file)
index 0000000..a61e89e
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+    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 <guus@meshlink.io>
+
+    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 <stdio.h>
+#include <stdlib.h>
+#include "../common/common_handlers.h"
+#include "../common/test_step.h"
+#include "../common/mesh_event_handler.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
+
+int main(int argc, char *argv[]) {
+       struct timeval main_loop_wait = { 5, 0 };
+       int client_id = -1;
+
+       if((argv[3]) && (argv[4])) {
+               client_id = atoi(argv[3]);
+               mesh_event_sock_connect(argv[4]);
+       }
+
+       /* Setup required signals */
+       setup_signals();
+
+       /* Execute test steps */
+       execute_open(argv[1], argv[2]);
+
+       if(argv[5]) {
+               execute_join(argv[5]);
+       }
+
+       execute_start();
+
+       if(client_id != -1) {
+               if(!mesh_event_sock_send(client_id, NODE_STARTED, NULL, 0)) {
+                       fprintf(stderr, "Trying to resend mesh event\n");
+                       sleep(1);
+               }
+       }
+
+       /* 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);
+       }
+
+       execute_close();
+}
diff --git a/test/blackbox/test_case_meta_conn_03/node_sim_relay.c b/test/blackbox/test_case_meta_conn_03/node_sim_relay.c
new file mode 100644 (file)
index 0000000..e5c7892
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+    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 <guus@meshlink.io>
+
+    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 <stdio.h>
+#include <stdlib.h>
+#include "../common/common_handlers.h"
+#include "../common/test_step.h"
+#include "../common/mesh_event_handler.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
+
+int main(int argc, char *argv[]) {
+       struct timeval main_loop_wait = { 5, 0 };
+
+       int client_id = -1;
+
+       if((argv[3]) && (argv[4])) {
+               client_id = atoi(argv[3]);
+               mesh_event_sock_connect(argv[4]);
+       }
+
+       /* Setup required signals */
+       setup_signals();
+
+       /* Execute test steps */
+       execute_open(argv[1], argv[2]);
+       execute_start();
+
+       if(client_id != -1) {
+               if(!mesh_event_sock_send(client_id, NODE_STARTED, NULL, 0)) {
+                       fprintf(stderr, "Trying to resend mesh event\n");
+                       sleep(1);
+               }
+       }
+
+       /* 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);
+       }
+
+       execute_close();
+}
diff --git a/test/blackbox/test_case_meta_conn_04/Makefile.am b/test/blackbox/test_case_meta_conn_04/Makefile.am
new file mode 100644 (file)
index 0000000..b12e440
--- /dev/null
@@ -0,0 +1,13 @@
+check_PROGRAMS = node_sim_relay node_sim_peer node_sim_nut
+
+node_sim_peer_SOURCES = node_sim_peer.c ../common/common_handlers.c ../common/test_step.c ../common/mesh_event_handler.c
+node_sim_peer_LDADD = ../../../src/libmeshlink.la
+node_sim_peer_CFLAGS = -D_GNU_SOURCE -fsanitize=leak
+
+node_sim_relay_SOURCES = node_sim_relay.c ../common/common_handlers.c ../common/test_step.c ../common/mesh_event_handler.c
+node_sim_relay_LDADD = ../../../src/libmeshlink.la
+node_sim_relay_CFLAGS = -D_GNU_SOURCE -fsanitize=leak
+
+node_sim_nut_SOURCES = node_sim_nut.c ../common/common_handlers.c ../common/test_step.c ../common/mesh_event_handler.c
+node_sim_nut_LDADD = ../../../src/libmeshlink.la
+node_sim_nut_CFLAGS = -D_GNU_SOURCE -fsanitize=leak
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
new file mode 100644 (file)
index 0000000..2c50e0f
--- /dev/null
@@ -0,0 +1,127 @@
+/*
+    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 <guus@meshlink.io>
+
+    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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <pthread.h>
+#include "../common/common_handlers.h"
+#include "../common/test_step.h"
+#include "../common/mesh_event_handler.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
+
+static bool conn_status = false;
+
+void callback_logger(meshlink_handle_t *mesh, meshlink_log_level_t level,
+                     const char *text) {
+       char connection_match_msg[100];
+
+       fprintf(stderr, "meshlink>> %s\n", text);
+
+       if(strstr(text, "Connection") || strstr(text, "connection")) {
+               assert(snprintf(connection_match_msg, sizeof(connection_match_msg),
+                               "Connection with peer") >= 0);
+
+               if(strstr(text, connection_match_msg) && strstr(text, "activated")) {
+                       conn_status = true;
+                       return;
+               }
+
+               assert(snprintf(connection_match_msg, sizeof(connection_match_msg),
+                               "Already connected to peer") >= 0);
+
+               if(strstr(text, connection_match_msg)) {
+                       conn_status = true;
+                       return;
+               }
+
+               assert(snprintf(connection_match_msg, sizeof(connection_match_msg),
+                               "Connection closed by peer") >= 0);
+
+               if(strstr(text, connection_match_msg)) {
+                       conn_status = false;
+                       return;
+               }
+
+               assert(snprintf(connection_match_msg, sizeof(connection_match_msg),
+                               "Closing connection with peer") >= 0);
+
+               if(strstr(text, connection_match_msg)) {
+                       conn_status = false;
+                       return;
+               }
+       }
+
+       return;
+}
+
+int main(int argc, char *argv[]) {
+       struct timeval main_loop_wait = { 5, 0 };
+       int i, clientId = -1;
+       bool result;
+       char *invite_peer;
+
+       if((argv[3]) && (argv[4])) {
+               clientId = atoi(argv[3]);
+               mesh_event_sock_connect(argv[4]);
+       }
+
+       execute_open(argv[1], argv[2]);
+       meshlink_set_log_cb(mesh_handle, MESHLINK_INFO, callback_logger);
+
+       execute_start();
+
+       if(!mesh_event_sock_send(clientId, NODE_STARTED, NULL, 0)) {
+               fprintf(stderr, "Trying to resend mesh event\n");
+               sleep(1);
+       }
+
+       if(!argv[CMD_LINE_ARG_INVITEURL]) {
+               fprintf(stderr, "Generating Inviation to PEER\n");
+               invite_peer = execute_invite("peer");
+               assert(invite_peer != NULL);
+
+               if(!mesh_event_sock_send(clientId, NODE_INVITATION, invite_peer, strlen(invite_peer) + 1)) {
+                       fprintf(stderr, "Trying to resend mesh event\n");
+                       sleep(1);
+               }
+       }
+
+       fprintf(stderr, "Waiting for PEER to be connected\n");
+
+       /* Connectivity of peer is checked */
+       while(!conn_status) {
+               sleep(1);
+       }
+
+       fprintf(stderr, "Connected with Peer\n");
+
+       if(!mesh_event_sock_send(clientId, META_CONN_SUCCESSFUL, "Connected with Peer", 30)) {
+               fprintf(stderr, "Trying to resend mesh event\n");
+               sleep(1);
+       }
+
+       execute_close();
+}
diff --git a/test/blackbox/test_case_meta_conn_04/node_sim_peer.c b/test/blackbox/test_case_meta_conn_04/node_sim_peer.c
new file mode 100644 (file)
index 0000000..a61e89e
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+    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 <guus@meshlink.io>
+
+    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 <stdio.h>
+#include <stdlib.h>
+#include "../common/common_handlers.h"
+#include "../common/test_step.h"
+#include "../common/mesh_event_handler.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
+
+int main(int argc, char *argv[]) {
+       struct timeval main_loop_wait = { 5, 0 };
+       int client_id = -1;
+
+       if((argv[3]) && (argv[4])) {
+               client_id = atoi(argv[3]);
+               mesh_event_sock_connect(argv[4]);
+       }
+
+       /* Setup required signals */
+       setup_signals();
+
+       /* Execute test steps */
+       execute_open(argv[1], argv[2]);
+
+       if(argv[5]) {
+               execute_join(argv[5]);
+       }
+
+       execute_start();
+
+       if(client_id != -1) {
+               if(!mesh_event_sock_send(client_id, NODE_STARTED, NULL, 0)) {
+                       fprintf(stderr, "Trying to resend mesh event\n");
+                       sleep(1);
+               }
+       }
+
+       /* 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);
+       }
+
+       execute_close();
+}
diff --git a/test/blackbox/test_case_meta_conn_04/node_sim_relay.c b/test/blackbox/test_case_meta_conn_04/node_sim_relay.c
new file mode 100644 (file)
index 0000000..683092a
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+    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 <guus@meshlink.io>
+
+    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 <stdio.h>
+#include <stdlib.h>
+#include "../common/common_handlers.h"
+#include "../common/test_step.h"
+#include "../common/mesh_event_handler.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
+
+int main(int argc, char *argv[]) {
+       struct timeval main_loop_wait = { 5, 0 };
+
+       int clientid = -1;
+
+       if((argv[3]) && (argv[4])) {
+               clientid = atoi(argv[3]);
+               mesh_event_sock_connect(argv[4]);
+       }
+
+       /* Setup required signals */
+       setup_signals();
+
+       /* Execute test steps */
+       execute_open(argv[1], argv[2]);
+       execute_start();
+
+       if(clientid != -1) {
+               mesh_event_sock_send(clientid, NODE_STARTED, NULL, 0);
+       }
+
+       /* 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);
+       }
+
+       execute_close();
+}
diff --git a/test/blackbox/test_case_meta_conn_05/Makefile.am b/test/blackbox/test_case_meta_conn_05/Makefile.am
new file mode 100644 (file)
index 0000000..b12e440
--- /dev/null
@@ -0,0 +1,13 @@
+check_PROGRAMS = node_sim_relay node_sim_peer node_sim_nut
+
+node_sim_peer_SOURCES = node_sim_peer.c ../common/common_handlers.c ../common/test_step.c ../common/mesh_event_handler.c
+node_sim_peer_LDADD = ../../../src/libmeshlink.la
+node_sim_peer_CFLAGS = -D_GNU_SOURCE -fsanitize=leak
+
+node_sim_relay_SOURCES = node_sim_relay.c ../common/common_handlers.c ../common/test_step.c ../common/mesh_event_handler.c
+node_sim_relay_LDADD = ../../../src/libmeshlink.la
+node_sim_relay_CFLAGS = -D_GNU_SOURCE -fsanitize=leak
+
+node_sim_nut_SOURCES = node_sim_nut.c ../common/common_handlers.c ../common/test_step.c ../common/mesh_event_handler.c
+node_sim_nut_LDADD = ../../../src/libmeshlink.la
+node_sim_nut_CFLAGS = -D_GNU_SOURCE -fsanitize=leak
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
new file mode 100644 (file)
index 0000000..760ff70
--- /dev/null
@@ -0,0 +1,144 @@
+/*
+    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 <guus@meshlink.io>
+
+    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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <pthread.h>
+#include "../common/common_handlers.h"
+#include "../common/test_step.h"
+#include "../common/mesh_event_handler.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
+
+static bool conn_status = false;
+
+void callback_logger(meshlink_handle_t *mesh, meshlink_log_level_t level,
+                     const char *text) {
+       char connection_match_msg[100];
+
+       fprintf(stderr, "meshlink>> %s\n", text);
+
+       if(strstr(text, "Connection") || strstr(text, "connection")) {
+               assert(snprintf(connection_match_msg, sizeof(connection_match_msg),
+                               "Connection with peer") >= 0);
+
+               if(strstr(text, connection_match_msg) && strstr(text, "activated")) {
+                       conn_status = true;
+                       return;
+               }
+
+               assert(snprintf(connection_match_msg, sizeof(connection_match_msg),
+                               "Already connected to peer") >= 0);
+
+               if(strstr(text, connection_match_msg)) {
+                       conn_status = true;
+                       return;
+               }
+
+               assert(snprintf(connection_match_msg, sizeof(connection_match_msg),
+                               "Connection closed by peer") >= 0);
+
+               if(strstr(text, connection_match_msg)) {
+                       conn_status = false;
+                       return;
+               }
+
+               assert(snprintf(connection_match_msg, sizeof(connection_match_msg),
+                               "Closing connection with peer") >= 0);
+
+               if(strstr(text, connection_match_msg)) {
+                       conn_status = false;
+                       return;
+               }
+       }
+
+       return;
+}
+
+int main(int argc, char *argv[]) {
+       struct timeval main_loop_wait = { 5, 0 };
+       int i, clientId = -1;
+       bool result;
+       char *invite_peer;
+
+       if((argv[3]) && (argv[4])) {
+               clientId = atoi(argv[3]);
+               mesh_event_sock_connect(argv[4]);
+       }
+
+       execute_open(argv[1], argv[2]);
+       meshlink_set_log_cb(mesh_handle, MESHLINK_INFO, callback_logger);
+
+       if(argv[CMD_LINE_ARG_INVITEURL]) {
+               execute_join(argv[CMD_LINE_ARG_INVITEURL]);
+       }
+
+       execute_start();
+
+       if(!mesh_event_sock_send(clientId, NODE_STARTED, NULL, 0)) {
+               fprintf(stderr, "Trying to resend mesh event\n");
+               sleep(1);
+       }
+
+       fprintf(stderr, "Generating Inviation to PEER\n");
+       invite_peer = execute_invite("peer");
+       assert(invite_peer != NULL);
+
+       if(!mesh_event_sock_send(clientId, NODE_INVITATION, invite_peer, strlen(invite_peer) + 1)) {
+               fprintf(stderr, "Trying to resend mesh event\n");
+               sleep(1);
+       }
+
+       fprintf(stderr, "Waiting for PEER to be connected\n");
+
+       /* Connectivity of peer is checked */
+       while(!conn_status) {
+               sleep(1);
+       }
+
+       fprintf(stderr, "Connected with Peer\n");
+
+       if(!mesh_event_sock_send(clientId, META_CONN_SUCCESSFUL, "Connected with Peer", 30)) {
+               fprintf(stderr, "Trying to resend mesh event\n");
+               sleep(1);
+       }
+
+       conn_status = false;
+       fprintf(stderr, "Waiting for PEER to be re-connected\n");
+
+       /* Connectivity of peer */
+       while(!conn_status) {
+               sleep(1);
+       }
+
+       fprintf(stderr, "Re-connected with Peer\n");
+
+       if(!mesh_event_sock_send(clientId, META_CONN_SUCCESSFUL, "Connected with Peer", 30)) {
+               fprintf(stderr, "Trying to resend mesh event\n");
+               sleep(1);
+       }
+
+       execute_close();
+}
diff --git a/test/blackbox/test_case_meta_conn_05/node_sim_peer.c b/test/blackbox/test_case_meta_conn_05/node_sim_peer.c
new file mode 100644 (file)
index 0000000..a61e89e
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+    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 <guus@meshlink.io>
+
+    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 <stdio.h>
+#include <stdlib.h>
+#include "../common/common_handlers.h"
+#include "../common/test_step.h"
+#include "../common/mesh_event_handler.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
+
+int main(int argc, char *argv[]) {
+       struct timeval main_loop_wait = { 5, 0 };
+       int client_id = -1;
+
+       if((argv[3]) && (argv[4])) {
+               client_id = atoi(argv[3]);
+               mesh_event_sock_connect(argv[4]);
+       }
+
+       /* Setup required signals */
+       setup_signals();
+
+       /* Execute test steps */
+       execute_open(argv[1], argv[2]);
+
+       if(argv[5]) {
+               execute_join(argv[5]);
+       }
+
+       execute_start();
+
+       if(client_id != -1) {
+               if(!mesh_event_sock_send(client_id, NODE_STARTED, NULL, 0)) {
+                       fprintf(stderr, "Trying to resend mesh event\n");
+                       sleep(1);
+               }
+       }
+
+       /* 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);
+       }
+
+       execute_close();
+}
diff --git a/test/blackbox/test_case_meta_conn_05/node_sim_relay.c b/test/blackbox/test_case_meta_conn_05/node_sim_relay.c
new file mode 100644 (file)
index 0000000..683092a
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+    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 <guus@meshlink.io>
+
+    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 <stdio.h>
+#include <stdlib.h>
+#include "../common/common_handlers.h"
+#include "../common/test_step.h"
+#include "../common/mesh_event_handler.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
+
+int main(int argc, char *argv[]) {
+       struct timeval main_loop_wait = { 5, 0 };
+
+       int clientid = -1;
+
+       if((argv[3]) && (argv[4])) {
+               clientid = atoi(argv[3]);
+               mesh_event_sock_connect(argv[4]);
+       }
+
+       /* Setup required signals */
+       setup_signals();
+
+       /* Execute test steps */
+       execute_open(argv[1], argv[2]);
+       execute_start();
+
+       if(clientid != -1) {
+               mesh_event_sock_send(clientid, NODE_STARTED, NULL, 0);
+       }
+
+       /* 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);
+       }
+
+       execute_close();
+}
diff --git a/test/blackbox/util/build_container.sh b/test/blackbox/util/build_container.sh
new file mode 100755 (executable)
index 0000000..98fc62e
--- /dev/null
@@ -0,0 +1,99 @@
+#!/bin/sh
+#    build_container.sh -- Script to populate an LXC Container with the files
+#                         required to run a Meshlink Node Simulation.
+#                         Designed to run on unprivileged Containers.
+#    Copyright (C) 2018  Guus Sliepen <guus@meshlink.io>
+#
+#    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.
+
+# Read command-line arguments
+testcase=$1
+nodename=$2
+meshlinkrootpath=$3
+setx=$4
+
+# Set configuration for required folders, programs and scripts
+#   Folder Paths
+ltlibfolder=".libs"
+meshlinksrclibpath="${meshlinkrootpath}/src/${ltlibfolder}"
+cattasrclibpath="${meshlinkrootpath}/catta/src/${ltlibfolder}"
+blackboxpath="${meshlinkrootpath}/test/blackbox"
+blackboxlibpath="${meshlinkrootpath}/test/blackbox/${ltlibfolder}"
+blackboxutilpath="${blackboxpath}/util"
+testcasepath="${blackboxpath}/${testcase}"
+testcaselibpath="${blackboxpath}/${testcase}/${ltlibfolder}"
+mirrorfolder="test"
+mirrorfolderpath="${testcasepath}/${mirrorfolder}"
+mirrorfolderlibpath="${mirrorfolderpath}/${ltlibfolder}"
+containerdstpath="/home/ubuntu/${mirrorfolder}"
+containerconfbase="/testconf"
+containerlogpath=""
+#   Program/Script Names
+ltprefix="lt-"
+nodestepscript="node_step.sh"
+nodesimpgm="node_sim_${nodename}"
+nodesimltscript="${ltprefix}${nodesimpgm}"
+geninvitepgm="gen_invite"
+geninviteltscript="${ltprefix}${geninvitepgm}"
+lxccopydirscript="lxc_copy_dir.sh"
+lxccopyfilescript="lxc_copy_file.sh"
+lxcrunscript="lxc_run.sh"
+#   Container Name
+containername="${testcase}_${nodename}"
+
+# Run Libtool Wrapper Scripts once in their built paths in order to generate lt-<program> script inside .libs directory
+${blackboxpath}/${geninvitepgm} >/dev/null 2>/dev/null
+${testcasepath}/${nodesimpgm} >/dev/null 2>/dev/null
+
+set ${setx}
+
+# Create Meshlink Container Mirror Folder (Delete any existing folder before creating new folder)
+rm -rf ${mirrorfolderpath} >/dev/null 2>/dev/null
+mkdir ${mirrorfolderpath}
+
+# Populate Mirror Folder
+#   Copy Wrapper Scripts for Utility Programs
+cp ${blackboxpath}/${geninvitepgm} ${mirrorfolderpath}
+cp ${testcasepath}/${nodesimpgm} ${mirrorfolderpath}
+#   Copy Utility Scripts
+cp ${blackboxutilpath}/${nodestepscript} ${mirrorfolderpath}
+#    Set Script Permissions
+chmod 755 ${mirrorfolderpath}/*
+#   Copy Binaries, lt- Scripts and Required Libraries
+mkdir ${mirrorfolderlibpath}
+cp ${blackboxlibpath}/* ${mirrorfolderlibpath}
+cp ${testcaselibpath}/*${nodesimpgm}* ${mirrorfolderlibpath}
+cp ${meshlinksrclibpath}/* ${mirrorfolderlibpath}
+cp ${cattasrclibpath}/* ${mirrorfolderlibpath}
+
+# Copy mirror folder into LXC Container
+#   Delete Destination Folder
+${blackboxutilpath}/${lxcrunscript} "rm -rf ${containerdstpath}" ${containername}
+#   Delete Meshlink confbase folder and logs from Container - every new test case starts on a clean slate
+${blackboxutilpath}/${lxcrunscript} "rm -rf ${containerconfbase}" ${containername}
+${blackboxutilpath}/${lxcrunscript} "rm ${containerlogpath}/*.log" ${containername}
+#   Create Destination Folder and Copy Files
+${blackboxutilpath}/${lxccopydirscript} ${mirrorfolderpath} ${containername} ${containerdstpath}
+#   Kill any running instances of the Node Simulation Program
+${blackboxutilpath}/${lxcrunscript} "${containerdstpath}/${nodestepscript} ${ltprefix}${nodesimpgm} SIGTERM 2>/dev/null" ${containername}
+#   Restore the 'interfaces' file in the Container
+echo "auto lo" > interfaces
+echo "iface lo inet loopback" >> interfaces
+echo "" >> interfaces
+echo "auto eth0" >> interfaces
+echo "iface eth0 inet dhcp" >> interfaces
+${blackboxutilpath}/${lxccopyfilescript} interfaces ${containername} /etc/network/interfaces
+
+set +x
diff --git a/test/blackbox/util/gen_invite.c b/test/blackbox/util/gen_invite.c
new file mode 100644 (file)
index 0000000..83c3f4f
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+    gen_invite.c -- Black Box Test Utility to generate a meshlink invite
+    Copyright (C) 2018  Guus Sliepen <guus@meshlink.io>
+
+    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 <stdio.h>
+#include <stdlib.h>
+#include "../../../src/meshlink.h"
+#include "../common/test_step.h"
+
+#define CMD_LINE_ARG_NODENAME   1
+#define CMD_LINE_ARG_INVITEE    2
+
+int main(int argc, char *argv[]) {
+       char *invite = NULL;
+
+       /* Start mesh, generate an invite and print out the invite */
+       execute_open(argv[CMD_LINE_ARG_NODENAME], "1");
+       execute_start();
+       invite = execute_invite(argv[CMD_LINE_ARG_INVITEE]);
+       printf("%s\n", invite);
+       //execute_close();
+
+       return EXIT_SUCCESS;
+}
diff --git a/test/blackbox/util/install_node_sim_copy.sh b/test/blackbox/util/install_node_sim_copy.sh
new file mode 100755 (executable)
index 0000000..af1175d
--- /dev/null
@@ -0,0 +1,3 @@
+cp ../${1}/node_sim_${2} .
+mkdir .libs 2>/dev/null
+cp ../${1}/.libs/*node_sim_${2}* .libs
diff --git a/test/blackbox/util/lxc_copy_dir.sh b/test/blackbox/util/lxc_copy_dir.sh
new file mode 100755 (executable)
index 0000000..d9be5f9
--- /dev/null
@@ -0,0 +1,27 @@
+#    lxc_copy.sh -- Script to transfer multiple files into an LXC Container
+#                  Designed to work on unprivileged Containers
+#    Copyright (C) 2018  Guus Sliepen <guus@meshlink.io>
+#
+#    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.
+
+# Read command-line arguments
+srcdir=$1
+containername=$2
+containerdstdir=$3
+
+# Create destination directory inside container and copy source directory contents into it
+# by 'tar'ing the source directory and un'tar'ing it inside the container
+lxc-attach -n ${containername} -- mkdir ${containerdstdir}
+tar -C ${srcdir} -c . | lxc-attach -n ${containername} -- tar -C ${containerdstdir} -xvp
diff --git a/test/blackbox/util/lxc_copy_file.sh b/test/blackbox/util/lxc_copy_file.sh
new file mode 100755 (executable)
index 0000000..c833681
--- /dev/null
@@ -0,0 +1,25 @@
+#    lxc_copy.sh -- Script to transfer multiple files into an LXC Container
+#                   Designed to work on unprivileged Containers
+#    Copyright (C) 2018  Guus Sliepen <guus@meshlink.io>
+#
+#    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.
+
+# Read Command-line arguments
+srcfilepath=$1
+containername=$2
+dstfilepath=$3
+
+# Copy file into Container
+cat ${srcfilepath} | lxc-attach -n ${containername} -- sh -c "cat > ${dstfilepath}"
diff --git a/test/blackbox/util/lxc_rename.sh b/test/blackbox/util/lxc_rename.sh
new file mode 100755 (executable)
index 0000000..31c0bcf
--- /dev/null
@@ -0,0 +1,29 @@
+#    lxc_rename.sh - Script to rename an LXC Container
+#                Designed to work on unprivileged Containers
+#    Copyright (C) 2018  Guus Sliepen <guus@meshlink.io>
+#
+#    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.
+
+# Read command-line arguments
+lxcpath=$1
+oldname=$2
+newname=$3
+
+# Run command inside Container by attaching to the Container and sending it the command
+mv ${lxcpath}/${oldname} ${lxcpath}/${newname}
+sed {s/${oldname}/${newname}/} ${lxcpath}/${newname}/config > ${lxcpath}/${newname}/config1
+mv ${lxcpath}/${newname}/config1 ${lxcpath}/${newname}/config
+#lxc-copy -n ${oldname} -P lxcpath -N ${newname} -p lxcpath -R
+exit $?
diff --git a/test/blackbox/util/lxc_run.sh b/test/blackbox/util/lxc_run.sh
new file mode 100755 (executable)
index 0000000..4a2456e
--- /dev/null
@@ -0,0 +1,26 @@
+#!/bin/sh
+#    lxc_run.sh - Script to run a command inside an LXC Container
+#                Designed to work on unprivileged Containers
+#    Copyright (C) 2018  Guus Sliepen <guus@meshlink.io>
+#
+#    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.
+
+# Read command-line arguments
+cmd=${1}
+containername=${2}
+
+# Run command inside Container by attaching to the Container and sending it the command
+echo "${cmd}" | lxc-attach -n ${containername} --
+exit $?
diff --git a/test/blackbox/util/node_step.sh b/test/blackbox/util/node_step.sh
new file mode 100755 (executable)
index 0000000..fe28423
--- /dev/null
@@ -0,0 +1,25 @@
+#    node_step.sh -- Script to send signal to control Mesh Node Simulation
+#    Copyright (C) 2018  Guus Sliepen <guus@meshlink.io>
+#
+#    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.
+
+# Read command-line arguments
+prog_name=$1
+signal=$2
+
+# Find instance of running program and send the named signal to it
+pid=`/bin/pidof -s ${prog_name}`
+kill -${signal} ${pid}
+exit $?
diff --git a/test/run_blackbox_tests.sh b/test/run_blackbox_tests.sh
new file mode 100755 (executable)
index 0000000..4bd9dd5
--- /dev/null
@@ -0,0 +1,11 @@
+#!/bin/sh
+meshlinkrootpath=$(realpath ${0%/*}/..)
+host=$(hostname)
+lxcpath=$(lxc-config lxc.lxcpath)
+lxcbridge="lxcbr0"
+ethifname=$(ip route show default | awk '{print $5}' | head -1)
+arch=$(dpkg --print-architecture)
+
+test -f $HOME/.config/meshlink_blackbox.conf && . $HOME/.config/meshlink_blackbox.conf
+
+${0%/*}/blackbox/run_blackbox_tests/run_blackbox_tests ${meshlinkrootpath} ${lxcpath} ${lxcbridge} ${ethifname} ${arch} 2> run_blackbox_test_cases.log