From: Elear Solutions Dev Date: Thu, 8 Nov 2018 20:01:10 +0000 (+0100) Subject: Add the blackbox container based test suite. X-Git-Url: https://git.meshlink.io/?a=commitdiff_plain;h=dc68da94af8fca91748579c84ef5ed798db7efab;p=meshlink Add the blackbox container based test suite. 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. --- diff --git a/.gitignore b/.gitignore index 1bc77a14..13a8886d 100644 --- a/.gitignore +++ b/.gitignore @@ -18,6 +18,7 @@ tags /autom4te.cache /aclocal.m4 /aminclude.am +/ar-lib /compile /configure /depcomp diff --git a/Makefile.am b/Makefile.am index 93bc9632..4220d3c8 100644 --- a/Makefile.am +++ b/Makefile.am @@ -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]'` diff --git a/configure.ac b/configure.ac index e02f5c37..363676ee 100644 --- a/configure.ac +++ b/configure.ac @@ -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 diff --git a/test/.gitignore b/test/.gitignore index 62e05a88..cbb1c1ee 100644 --- a/test/.gitignore +++ b/test/.gitignore @@ -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] diff --git a/test/Makefile.am b/test/Makefile.am index 0bc98d0c..77fd5ef1 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -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 index 00000000..4190b424 --- /dev/null +++ b/test/blackbox/.gitignore @@ -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 index 00000000..3afae4b1 --- /dev/null +++ b/test/blackbox/Makefile.am @@ -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 index 00000000..ad32a223 --- /dev/null +++ b/test/blackbox/common/common_handlers.c @@ -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 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#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 index 00000000..7c5fbd23 --- /dev/null +++ b/test/blackbox/common/common_handlers.h @@ -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 + + 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 index 00000000..d0e4d96d --- /dev/null +++ b/test/blackbox/common/common_types.h @@ -0,0 +1,55 @@ +/* + common_types.h -- Declarations of common types used in Black Box Testing + Copyright (C) 2018 Guus Sliepen + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#ifndef COMMON_TYPES_H +#define COMMON_TYPES_H + +#include +#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 index 00000000..263cbf97 --- /dev/null +++ b/test/blackbox/common/containers.c @@ -0,0 +1,455 @@ +/* + containers.h -- Container Management API + Copyright (C) 2018 Guus Sliepen + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include +#include +#include +#include +#include +#include "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_ 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 _ */ +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_ 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_ 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 index 00000000..49cbb7c3 --- /dev/null +++ b/test/blackbox/common/containers.h @@ -0,0 +1,48 @@ +/* + containers.h -- Declarations for Container Management API + Copyright (C) 2018 Guus Sliepen + Manav Kumar Mehta + + 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 + +#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 index 00000000..0f331d67 --- /dev/null +++ b/test/blackbox/common/mesh_event_handler.c @@ -0,0 +1,162 @@ +/* + mesh_event_handler.c -- handling of mesh events API + Copyright (C) 2018 Guus Sliepen + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#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 index 00000000..4300affb --- /dev/null +++ b/test/blackbox/common/mesh_event_handler.h @@ -0,0 +1,141 @@ +/* + mesh_event_handler.h + Copyright (C) 2018 Guus Sliepen + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#ifndef _MESH_EVENT_HANDLER_H_ +#define _MESH_EVENT_HANDLER_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/// 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 index 00000000..a0933f73 --- /dev/null +++ b/test/blackbox/common/tcpdump.c @@ -0,0 +1,60 @@ +/* + tcpdump.c -- Implementation of Black Box Test Execution for meshlink + + Copyright (C) 2018 Guus Sliepen + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ +#include +#include +#include +#include +#include +#include +#include +#include "common_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 index 00000000..37e92b85 --- /dev/null +++ b/test/blackbox/common/tcpdump.h @@ -0,0 +1,29 @@ +/* + tcpdump.h -- Declarations of common callback handlers and signal handlers for + black box test cases + Copyright (C) 2018 Guus Sliepen + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#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 index 00000000..4a2bf853 --- /dev/null +++ b/test/blackbox/common/test_step.c @@ -0,0 +1,145 @@ +/* + test_step.c -- Handlers for executing test steps during node simulation + Copyright (C) 2018 Guus Sliepen + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. +ŝ + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include +#include +#include +#include +#include "../../../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 index 00000000..7a32dff0 --- /dev/null +++ b/test/blackbox/common/test_step.h @@ -0,0 +1,33 @@ +/* + test_step.h -- Handlers for executing test steps during node simulation + Copyright (C) 2018 Guus Sliepen + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#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 index 00000000..076f4db5 --- /dev/null +++ b/test/blackbox/run_blackbox_tests/.gitignore @@ -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 index 00000000..defd4b57 --- /dev/null +++ b/test/blackbox/run_blackbox_tests/Makefile.am @@ -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 index 00000000..2f9730e1 --- /dev/null +++ b/test/blackbox/run_blackbox_tests/execute_tests.c @@ -0,0 +1,81 @@ +/* + execute_tests.c -- Utility functions for black box test execution + Copyright (C) 2018 Guus Sliepen + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include +#include +#include +#include +#include +#include "execute_tests.h" +#include "../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_ - 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 index 00000000..03880f53 --- /dev/null +++ b/test/blackbox/run_blackbox_tests/execute_tests.h @@ -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 + + 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 + +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 index 00000000..3f6e081a --- /dev/null +++ b/test/blackbox/run_blackbox_tests/run_blackbox_tests.c @@ -0,0 +1,127 @@ +/* + run_blackbox_tests.c -- Implementation of Black Box Test Execution for meshlink + + Copyright (C) 2018 Guus Sliepen + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ +#include +#include +#include +#include +#include +#include "execute_tests.h" +#include "test_cases.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 index 00000000..942c72c6 --- /dev/null +++ b/test/blackbox/run_blackbox_tests/test_cases.c @@ -0,0 +1,524 @@ +/* + test_cases.c -- Execution of specific meshlink black box test cases + Copyright (C) 2018 Guus Sliepen + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ +#include +#include +#include +#include +#include +#include "execute_tests.h" +#include "test_cases.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 index 00000000..9260d014 --- /dev/null +++ b/test/blackbox/run_blackbox_tests/test_cases.h @@ -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 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + + +#include + +extern int 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 index 00000000..d9d456f3 --- /dev/null +++ b/test/blackbox/run_blackbox_tests/test_cases_add_addr.c @@ -0,0 +1,168 @@ +/* + test_cases_add_addr.c -- Execution of specific meshlink black box test cases + Copyright (C) 2018 Guus Sliepen + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include "execute_tests.h" +#include "test_cases_add_addr.h" +#include "../common/containers.h" +#include "../common/test_step.h" +#include "../common/common_handlers.h" +#include +#include +#include +#include +#include +#include + +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 index 00000000..bfa3c055 --- /dev/null +++ b/test/blackbox/run_blackbox_tests/test_cases_add_addr.h @@ -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 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + + +#include + +extern int test_meshlink_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 index 00000000..bff9dd83 --- /dev/null +++ b/test/blackbox/run_blackbox_tests/test_cases_add_ex_addr.c @@ -0,0 +1,130 @@ +/* + test_cases_add_ex_addr.c -- Execution of specific meshlink black box test cases + Copyright (C) 2018 Guus Sliepen + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include "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 +#include +#include +#include +#include +#include + +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 index 00000000..c5eca669 --- /dev/null +++ b/test/blackbox/run_blackbox_tests/test_cases_add_ex_addr.h @@ -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 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + + +#include + +extern int test_meshlink_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 index 00000000..15f1131a --- /dev/null +++ b/test/blackbox/run_blackbox_tests/test_cases_blacklist.c @@ -0,0 +1,225 @@ +/* + test_cases_blacklist.c -- Execution of specific meshlink black box test cases + Copyright (C) 2018 Guus Sliepen + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +/* Modify this to change the logging level of Meshlink */ +#define TEST_MESHLINK_LOG_LEVEL MESHLINK_DEBUG + +#include "execute_tests.h" +#include "test_cases_blacklist.h" +#include "../common/containers.h" +#include "../common/test_step.h" +#include "../common/common_handlers.h" +#include +#include +#include +#include +#include +#include + +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 index 00000000..b591d028 --- /dev/null +++ b/test/blackbox/run_blackbox_tests/test_cases_blacklist.h @@ -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 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include + +extern int test_meshlink_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 index 00000000..bc32256d --- /dev/null +++ b/test/blackbox/run_blackbox_tests/test_cases_channel_close.c @@ -0,0 +1,148 @@ +/* + test_cases_channel_close.c -- Execution of specific meshlink black box test cases + Copyright (C) 2018 Guus Sliepen + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include "execute_tests.h" +#include "test_cases_channel_close.h" +#include "../common/containers.h" +#include "../common/test_step.h" +#include "../common/common_handlers.h" +#include +#include +#include +#include +#include +#include + +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 index 00000000..7203a19a --- /dev/null +++ b/test/blackbox/run_blackbox_tests/test_cases_channel_close.h @@ -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 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include + +extern int test_meshlink_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 index 00000000..9efed2f4 --- /dev/null +++ b/test/blackbox/run_blackbox_tests/test_cases_channel_conn.h @@ -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 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + + +#include + +extern int 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 index 00000000..aa6fa23d --- /dev/null +++ b/test/blackbox/run_blackbox_tests/test_cases_channel_ex.c @@ -0,0 +1,426 @@ +/* + test_cases_channel_ex.c -- Execution of specific meshlink black box test cases + Copyright (C) 2018 Guus Sliepen + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ +#include "execute_tests.h" +#include "test_cases_channel_ex.h" +#include "../common/containers.h" +#include "../common/test_step.h" +#include "../common/common_handlers.h" +#include +#include +#include +#include +#include +#include +#include + +/* 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 index 00000000..e15fa28d --- /dev/null +++ b/test/blackbox/run_blackbox_tests/test_cases_channel_ex.h @@ -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 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include + +extern int 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 index 00000000..266b3150 --- /dev/null +++ b/test/blackbox/run_blackbox_tests/test_cases_channel_get_flags.c @@ -0,0 +1,200 @@ +/* + test_cases_channel_get_flags.c -- Execution of specific meshlink black box test cases + Copyright (C) 2018 Guus Sliepen + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include "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 +#include +#include +#include +#include +#include + +#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 index 00000000..d60ec90f --- /dev/null +++ b/test/blackbox/run_blackbox_tests/test_cases_channel_get_flags.h @@ -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 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include + +extern int 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 index 00000000..0d5728f6 --- /dev/null +++ b/test/blackbox/run_blackbox_tests/test_cases_channel_open.c @@ -0,0 +1,260 @@ +/* + test_cases_channel_open.c -- Execution of specific meshlink black box test cases + Copyright (C) 2018 Guus Sliepen + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include "execute_tests.h" +#include "test_cases_channel_open.h" +#include "../common/containers.h" +#include "../common/test_step.h" +#include "../common/common_handlers.h" +#include +#include +#include +#include +#include +#include + +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 index 00000000..a1140a05 --- /dev/null +++ b/test/blackbox/run_blackbox_tests/test_cases_channel_open.h @@ -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 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include + +extern int test_meshlink_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 index 00000000..651e16ed --- /dev/null +++ b/test/blackbox/run_blackbox_tests/test_cases_channel_send.c @@ -0,0 +1,357 @@ +/* + test_cases_channel_send.c -- Execution of specific meshlink black box test cases + Copyright (C) 2018 Guus Sliepen + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include "execute_tests.h" +#include "test_cases_channel_send.h" +#include "../common/containers.h" +#include "../common/test_step.h" +#include "../common/common_handlers.h" +#include +#include +#include +#include +#include +#include +#include + +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 index 00000000..b9e624fe --- /dev/null +++ b/test/blackbox/run_blackbox_tests/test_cases_channel_send.h @@ -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 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include + +extern int test_meshlink_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 index 00000000..77d2c9cf --- /dev/null +++ b/test/blackbox/run_blackbox_tests/test_cases_channel_set_accept_cb.c @@ -0,0 +1,263 @@ +/* + test_cases_channel_set_accept_cb.c -- Execution of specific meshlink black box test cases + Copyright (C) 2018 Guus Sliepen + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ +#include "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 +#include +#include +#include +#include +#include +#include + +/* 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 index 00000000..9d91d593 --- /dev/null +++ b/test/blackbox/run_blackbox_tests/test_cases_channel_set_accept_cb.h @@ -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 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include + +extern int 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 index 00000000..2234c393 --- /dev/null +++ b/test/blackbox/run_blackbox_tests/test_cases_channel_set_poll_cb.c @@ -0,0 +1,253 @@ +/* + test_cases_channel_set_poll_cb.c -- Execution of specific meshlink black box test cases + Copyright (C) 2018 Guus Sliepen + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ +#include "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 +#include +#include +#include +#include +#include +#include + +/* 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 index 00000000..71796e2c --- /dev/null +++ b/test/blackbox/run_blackbox_tests/test_cases_channel_set_poll_cb.h @@ -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 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include + +extern int test_meshlink_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 index 00000000..d1854428 --- /dev/null +++ b/test/blackbox/run_blackbox_tests/test_cases_channel_set_receive_cb.c @@ -0,0 +1,253 @@ +/* + test_cases_channel_set_receive_cb.c -- Execution of specific meshlink black box test cases + Copyright (C) 2018 Guus Sliepen + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ +#include "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 +#include +#include +#include +#include +#include +#include +#include + +/* 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 index 00000000..e781f8cf --- /dev/null +++ b/test/blackbox/run_blackbox_tests/test_cases_channel_set_receive_cb.h @@ -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 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include + +extern int test_meshlink_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 index 00000000..f17266fb --- /dev/null +++ b/test/blackbox/run_blackbox_tests/test_cases_channel_shutdown.c @@ -0,0 +1,356 @@ +/* + test_cases_channel_shutdown.c -- Execution of specific meshlink black box test cases + Copyright (C) 2018 Guus Sliepen + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include "execute_tests.h" +#include "test_cases_channel_shutdown.h" +#include "../common/containers.h" +#include "../common/test_step.h" +#include "../common/common_handlers.h" +#include +#include +#include +#include +#include +#include +#include + +/* 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 index 00000000..13f46906 --- /dev/null +++ b/test/blackbox/run_blackbox_tests/test_cases_channel_shutdown.h @@ -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 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include + +extern int test_meshlink_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 index 00000000..bf21ed84 --- /dev/null +++ b/test/blackbox/run_blackbox_tests/test_cases_default_blacklist.c @@ -0,0 +1,198 @@ +/* + test_cases_default_blacklist.c -- Execution of specific meshlink black box test cases + Copyright (C) 2018 Guus Sliepen + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include +#include +#include +#include +#include +#include +#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 index 00000000..c8e7af22 --- /dev/null +++ b/test/blackbox/run_blackbox_tests/test_cases_default_blacklist.h @@ -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 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include + +extern int test_meshlink_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 index 00000000..30bd3766 --- /dev/null +++ b/test/blackbox/run_blackbox_tests/test_cases_destroy.c @@ -0,0 +1,149 @@ +/* + test_cases_destroy.c -- Execution of specific meshlink black box test cases + Copyright (C) 2018 Guus Sliepen + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ +#include "execute_tests.h" +#include "test_cases_destroy.h" +#include "../common/containers.h" +#include "../common/test_step.h" +#include "../common/common_handlers.h" +#include +#include +#include +#include +#include +#include +#include +#include + + +/* 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 index 00000000..3d90dcb3 --- /dev/null +++ b/test/blackbox/run_blackbox_tests/test_cases_destroy.h @@ -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 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include + +extern int 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 index 00000000..75e84ec5 --- /dev/null +++ b/test/blackbox/run_blackbox_tests/test_cases_export.c @@ -0,0 +1,113 @@ +/* + test_cases_export.c -- Execution of specific meshlink black box test cases + Copyright (C) 2018 Guus Sliepen + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ +#include "execute_tests.h" +#include "test_cases_export.h" +#include "../common/containers.h" +#include "../common/test_step.h" +#include "../common/common_handlers.h" +#include +#include +#include +#include +#include +#include + + +/* 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 index 00000000..ecea12e9 --- /dev/null +++ b/test/blackbox/run_blackbox_tests/test_cases_export.h @@ -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 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include + +extern int 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 index 00000000..8b885a73 --- /dev/null +++ b/test/blackbox/run_blackbox_tests/test_cases_get_all_nodes.c @@ -0,0 +1,180 @@ +/* + test_cases_get_all_nodes.c -- Execution of specific meshlink black box test cases + Copyright (C) 2018 Guus Sliepen + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include "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 +#include +#include +#include +#include +#include + + +/* 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 index 00000000..898114ad --- /dev/null +++ b/test/blackbox/run_blackbox_tests/test_cases_get_all_nodes.h @@ -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 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include + +extern int 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 index 00000000..8868c76d --- /dev/null +++ b/test/blackbox/run_blackbox_tests/test_cases_get_ex_addr.c @@ -0,0 +1,143 @@ +/* + test_cases_get_ex_addr.c -- Execution of specific meshlink black box test cases + Copyright (C) 2018 Guus Sliepen + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include "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 +#include +#include +#include +#include +#include + +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 index 00000000..ccd4bb95 --- /dev/null +++ b/test/blackbox/run_blackbox_tests/test_cases_get_ex_addr.h @@ -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 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include + +extern int test_meshlink_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 index 00000000..1315ec5a --- /dev/null +++ b/test/blackbox/run_blackbox_tests/test_cases_get_fingerprint.c @@ -0,0 +1,176 @@ +/* + test_cases_get_fingerprint.c -- Execution of specific meshlink black box test cases + Copyright (C) 2018 Guus Sliepen + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include "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 +#include +#include +#include +#include +#include + +/* 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 index 00000000..dafc4bfa --- /dev/null +++ b/test/blackbox/run_blackbox_tests/test_cases_get_fingerprint.h @@ -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 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include + +extern int test_meshlink_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 index 00000000..6ecb1467 --- /dev/null +++ b/test/blackbox/run_blackbox_tests/test_cases_get_node.c @@ -0,0 +1,205 @@ +/* + test_cases_get_node.c -- Execution of specific meshlink black box test cases + Copyright (C) 2018 Guus Sliepen + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include "execute_tests.h" +#include "test_cases_get_node.h" +#include "../common/containers.h" +#include "../common/test_step.h" +#include "../common/common_handlers.h" +#include +#include +#include +#include +#include +#include + +/* 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 index 00000000..7d5eb41b --- /dev/null +++ b/test/blackbox/run_blackbox_tests/test_cases_get_node.h @@ -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 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include + +extern int test_meshlink_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 index 00000000..177540b3 --- /dev/null +++ b/test/blackbox/run_blackbox_tests/test_cases_get_port.c @@ -0,0 +1,106 @@ +/* + test_cases_get_port.c -- Execution of specific meshlink black box test cases + Copyright (C) 2018 Guus Sliepen + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include "execute_tests.h" +#include "test_cases_get_port.h" +#include "../common/containers.h" +#include "../common/test_step.h" +#include "../common/common_handlers.h" +#include +#include +#include +#include +#include +#include + +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 index 00000000..0386a8a3 --- /dev/null +++ b/test/blackbox/run_blackbox_tests/test_cases_get_port.h @@ -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 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include + +extern int test_meshlink_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 index 00000000..53a08335 --- /dev/null +++ b/test/blackbox/run_blackbox_tests/test_cases_get_self.c @@ -0,0 +1,111 @@ +/* + test_cases_get_port.c -- Execution of specific meshlink black box test cases + Copyright (C) 2018 Guus Sliepen + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include "execute_tests.h" +#include "test_cases_get_self.h" +#include "../common/containers.h" +#include "../common/test_step.h" +#include "../common/common_handlers.h" +#include +#include +#include +#include +#include +#include + +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 index 00000000..24d7fc95 --- /dev/null +++ b/test/blackbox/run_blackbox_tests/test_cases_get_self.h @@ -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 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include + +extern int test_meshlink_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 index 00000000..aacbbecd --- /dev/null +++ b/test/blackbox/run_blackbox_tests/test_cases_hint_address.c @@ -0,0 +1,138 @@ +/* + test_cases_hint_address.c -- Execution of specific meshlink black box test cases + Copyright (C) 2018 Guus Sliepen + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include "execute_tests.h" +#include "test_cases_hint_address.h" +#include "../common/containers.h" +#include "../common/test_step.h" +#include "../common/common_handlers.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +/* 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 index 00000000..e64ba5e8 --- /dev/null +++ b/test/blackbox/run_blackbox_tests/test_cases_hint_address.h @@ -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 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include + +extern int test_meshlink_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 index 00000000..0ab6c042 --- /dev/null +++ b/test/blackbox/run_blackbox_tests/test_cases_import.c @@ -0,0 +1,316 @@ +/* + test_cases_import.c -- Execution of specific meshlink black box test cases + Copyright (C) 2018 Guus Sliepen + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include "execute_tests.h" +#include "test_cases_import.h" +#include "../common/containers.h" +#include "../common/test_step.h" +#include "../common/common_handlers.h" +#include +#include +#include +#include +#include +#include + +/* 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 index 00000000..4316b93c --- /dev/null +++ b/test/blackbox/run_blackbox_tests/test_cases_import.h @@ -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 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include + +extern int test_meshlink_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 index 00000000..c0f13c58 --- /dev/null +++ b/test/blackbox/run_blackbox_tests/test_cases_invite.c @@ -0,0 +1,200 @@ +/* + test_cases_invite.c -- Execution of specific meshlink black box test cases + Copyright (C) 2018 Guus Sliepen + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include "execute_tests.h" +#include "test_cases_invite.h" +#include "../common/containers.h" +#include "../common/test_step.h" +#include "../common/common_handlers.h" +#include +#include +#include +#include +#include +#include + +/* 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 index 00000000..e8c06c70 --- /dev/null +++ b/test/blackbox/run_blackbox_tests/test_cases_invite.h @@ -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 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include + +extern int 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 index 00000000..9df001af --- /dev/null +++ b/test/blackbox/run_blackbox_tests/test_cases_join.c @@ -0,0 +1,204 @@ +/* + test_cases_join.c -- Execution of specific meshlink black box test cases + Copyright (C) 2018 Guus Sliepen + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include "execute_tests.h" +#include "test_cases_join.h" +#include "../common/containers.h" +#include "../common/test_step.h" +#include "../common/common_handlers.h" +#include +#include +#include +#include +#include +#include +#include + +/* 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 index 00000000..c10af0f8 --- /dev/null +++ b/test/blackbox/run_blackbox_tests/test_cases_join.h @@ -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 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include + +extern int test_meshlink_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 index 00000000..2655376f --- /dev/null +++ b/test/blackbox/run_blackbox_tests/test_cases_open.c @@ -0,0 +1,198 @@ +/* + test_cases_open.c -- Execution of specific meshlink black box test cases + Copyright (C) 2018 Guus Sliepen + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include "execute_tests.h" +#include "test_cases_open.h" +#include "../common/containers.h" +#include "../common/test_step.h" +#include "../common/common_handlers.h" +#include +#include +#include +#include +#include +#include + +/* 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 index 00000000..0c3f7d97 --- /dev/null +++ b/test/blackbox/run_blackbox_tests/test_cases_open.h @@ -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 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include + +extern int test_meshlink_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 index 00000000..0a037d8c --- /dev/null +++ b/test/blackbox/run_blackbox_tests/test_cases_pmtu.c @@ -0,0 +1,155 @@ +/* + test_cases_pmtu.c -- Execution of specific meshlink black box test cases + Copyright (C) 2018 Guus Sliepen + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include "execute_tests.h" +#include "test_cases_pmtu.h" +#include "../common/containers.h" +#include "../common/test_step.h" +#include "../common/common_handlers.h" +#include +#include +#include +#include +#include +#include + +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 index 00000000..db9b5cd3 --- /dev/null +++ b/test/blackbox/run_blackbox_tests/test_cases_pmtu.h @@ -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 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include + +extern int test_meshlink_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 index 00000000..f9ec4770 --- /dev/null +++ b/test/blackbox/run_blackbox_tests/test_cases_rec_cb.c @@ -0,0 +1,206 @@ +/* + test_cases_rec_cb.c -- Execution of specific meshlink black box test cases + Copyright (C) 2018 Guus Sliepen + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ +#include "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 +#include +#include +#include +#include +#include +#include + + +/* 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 index 00000000..c4467c88 --- /dev/null +++ b/test/blackbox/run_blackbox_tests/test_cases_rec_cb.h @@ -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 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include + +extern int test_meshlink_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 index 00000000..82c494d5 --- /dev/null +++ b/test/blackbox/run_blackbox_tests/test_cases_send.c @@ -0,0 +1,189 @@ +/* + test_cases_send.c -- Execution of specific meshlink black box test cases + Copyright (C) 2018 Guus Sliepen + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include "execute_tests.h" +#include "test_cases_send.h" +#include "../common/containers.h" +#include "../common/test_step.h" +#include "../common/common_handlers.h" +#include +#include +#include +#include +#include +#include + +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 index 00000000..6649b8f6 --- /dev/null +++ b/test/blackbox/run_blackbox_tests/test_cases_send.h @@ -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 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include + +extern int test_meshlink_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 index 00000000..71019a13 --- /dev/null +++ b/test/blackbox/run_blackbox_tests/test_cases_set_log_cb.c @@ -0,0 +1,142 @@ +/* + test_cases_set_log_cb.c -- Execution of specific meshlink black box test cases + Copyright (C) 2018 Guus Sliepen + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include "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 +#include +#include +#include +#include +#include +#include + + +/* 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 index 00000000..31b1aa9d --- /dev/null +++ b/test/blackbox/run_blackbox_tests/test_cases_set_log_cb.h @@ -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 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include + +extern int test_meshlink_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 index 00000000..0bc2c6af --- /dev/null +++ b/test/blackbox/run_blackbox_tests/test_cases_set_port.c @@ -0,0 +1,166 @@ +/* + test_cases_set_port.c -- Execution of specific meshlink black box test cases + Copyright (C) 2018 Guus Sliepen + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include "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 +#include +#include +#include +#include +#include + + +/* 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 index 00000000..fa8a768b --- /dev/null +++ b/test/blackbox/run_blackbox_tests/test_cases_set_port.h @@ -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 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include + +extern int 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 index 00000000..c120c475 --- /dev/null +++ b/test/blackbox/run_blackbox_tests/test_cases_sign.c @@ -0,0 +1,402 @@ +/* + test_cases_sign.c -- Execution of specific meshlink black box test cases + Copyright (C) 2018 Guus Sliepen + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include "execute_tests.h" +#include "test_cases_sign.h" +#include "../common/containers.h" +#include "../common/test_step.h" +#include "../common/common_handlers.h" +#include +#include +#include +#include +#include +#include + +/* 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 index 00000000..bbb741b8 --- /dev/null +++ b/test/blackbox/run_blackbox_tests/test_cases_sign.h @@ -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 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include + +extern int 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 index 00000000..c01f8f8b --- /dev/null +++ b/test/blackbox/run_blackbox_tests/test_cases_start.c @@ -0,0 +1,127 @@ +/* + test_cases_start.c -- Execution of specific meshlink black box test cases + Copyright (C) 2018 Guus Sliepen + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include "execute_tests.h" +#include "test_cases_start.h" +#include "../common/containers.h" +#include "../common/test_step.h" +#include "../common/common_handlers.h" +#include +#include +#include +#include +#include +#include + +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 index 00000000..835cface --- /dev/null +++ b/test/blackbox/run_blackbox_tests/test_cases_start.h @@ -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 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include + +extern int test_meshlink_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 index 00000000..9bfb4c63 --- /dev/null +++ b/test/blackbox/run_blackbox_tests/test_cases_status_cb.c @@ -0,0 +1,173 @@ +/* + test_cases_status_cb.c -- Execution of specific meshlink black box test cases + Copyright (C) 2018 Guus Sliepen + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include "execute_tests.h" +#include "test_cases_status_cb.h" +#include "../common/containers.h" +#include "../common/test_step.h" +#include "../common/common_handlers.h" +#include +#include +#include +#include +#include +#include +#include + +/* 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 index 00000000..16e03e3f --- /dev/null +++ b/test/blackbox/run_blackbox_tests/test_cases_status_cb.h @@ -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 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include + +extern int test_meshlink_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 index 00000000..fc822391 --- /dev/null +++ b/test/blackbox/run_blackbox_tests/test_cases_stop_close.c @@ -0,0 +1,90 @@ +/* + test_cases_stop_close.c -- Execution of specific meshlink black box test cases + Copyright (C) 2018 Guus Sliepen + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include "execute_tests.h" +#include "test_cases_stop_close.h" +#include "../common/containers.h" +#include "../common/test_step.h" +#include "../common/common_handlers.h" +#include +#include +#include +#include +#include +#include +#include + +#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 index 00000000..ede4e5bb --- /dev/null +++ b/test/blackbox/run_blackbox_tests/test_cases_stop_close.h @@ -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 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include + +extern int test_meshlink_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 index 00000000..e7317477 --- /dev/null +++ b/test/blackbox/run_blackbox_tests/test_cases_verify.c @@ -0,0 +1,384 @@ +/* + test_cases_verify.c -- Execution of specific meshlink black box test cases + Copyright (C) 2018 Guus Sliepen + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include "execute_tests.h" +#include "test_cases_verify.h" +#include "../common/containers.h" +#include "../common/test_step.h" +#include "../common/common_handlers.h" +#include +#include +#include +#include +#include +#include + +/* 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 index 00000000..39661a0b --- /dev/null +++ b/test/blackbox/run_blackbox_tests/test_cases_verify.h @@ -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 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + + +#include + +extern int 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 index 00000000..0ee8636e --- /dev/null +++ b/test/blackbox/run_blackbox_tests/test_cases_whitelist.c @@ -0,0 +1,323 @@ +/* + test_cases_whitelist.c -- Execution of specific meshlink black box test cases + Copyright (C) 2018 Guus Sliepen + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include "execute_tests.h" +#include "test_cases_whitelist.h" +#include "../common/containers.h" +#include "../common/test_step.h" +#include "../common/common_handlers.h" +#include +#include +#include +#include +#include +#include +#include +#include + +#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 index 00000000..f7f79c45 --- /dev/null +++ b/test/blackbox/run_blackbox_tests/test_cases_whitelist.h @@ -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 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include + +extern int test_meshlink_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 index 00000000..b12e440b --- /dev/null +++ b/test/blackbox/test_case_meta_conn_01/Makefile.am @@ -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 index 00000000..fc985bdf --- /dev/null +++ b/test/blackbox/test_case_meta_conn_01/node_sim_nut.c @@ -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 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ +#include +#include +#include +#include +#include "../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 index 00000000..521a7bbf --- /dev/null +++ b/test/blackbox/test_case_meta_conn_01/node_sim_peer.c @@ -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 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ +#include +#include +#include "../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 index 00000000..3d5ba06d --- /dev/null +++ b/test/blackbox/test_case_meta_conn_01/node_sim_relay.c @@ -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 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ +#include +#include +#include "../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 index 00000000..6331fb9c --- /dev/null +++ b/test/blackbox/test_case_meta_conn_02/Makefile.am @@ -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 index 00000000..f447c400 --- /dev/null +++ b/test/blackbox/test_case_meta_conn_02/node_sim_nut.c @@ -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 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ +#include +#include +#include +#include +#include "../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 index 00000000..a61e89e8 --- /dev/null +++ b/test/blackbox/test_case_meta_conn_02/node_sim_peer.c @@ -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 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ +#include +#include +#include "../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 index 00000000..6e6caabe --- /dev/null +++ b/test/blackbox/test_case_meta_conn_02/node_sim_relay.c @@ -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 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ +#include +#include +#include "../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 index 00000000..6331fb9c --- /dev/null +++ b/test/blackbox/test_case_meta_conn_03/Makefile.am @@ -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 index 00000000..573e185d --- /dev/null +++ b/test/blackbox/test_case_meta_conn_03/node_sim_nut.c @@ -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 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ +#include +#include +#include +#include +#include "../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 index 00000000..a61e89e8 --- /dev/null +++ b/test/blackbox/test_case_meta_conn_03/node_sim_peer.c @@ -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 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ +#include +#include +#include "../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 index 00000000..e5c78926 --- /dev/null +++ b/test/blackbox/test_case_meta_conn_03/node_sim_relay.c @@ -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 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ +#include +#include +#include "../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 index 00000000..b12e440b --- /dev/null +++ b/test/blackbox/test_case_meta_conn_04/Makefile.am @@ -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 index 00000000..2c50e0f1 --- /dev/null +++ b/test/blackbox/test_case_meta_conn_04/node_sim_nut.c @@ -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 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ +#include +#include +#include +#include +#include "../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 index 00000000..a61e89e8 --- /dev/null +++ b/test/blackbox/test_case_meta_conn_04/node_sim_peer.c @@ -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 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ +#include +#include +#include "../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 index 00000000..683092a0 --- /dev/null +++ b/test/blackbox/test_case_meta_conn_04/node_sim_relay.c @@ -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 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ +#include +#include +#include "../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 index 00000000..b12e440b --- /dev/null +++ b/test/blackbox/test_case_meta_conn_05/Makefile.am @@ -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 index 00000000..760ff70e --- /dev/null +++ b/test/blackbox/test_case_meta_conn_05/node_sim_nut.c @@ -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 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ +#include +#include +#include +#include +#include "../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 index 00000000..a61e89e8 --- /dev/null +++ b/test/blackbox/test_case_meta_conn_05/node_sim_peer.c @@ -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 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ +#include +#include +#include "../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 index 00000000..683092a0 --- /dev/null +++ b/test/blackbox/test_case_meta_conn_05/node_sim_relay.c @@ -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 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ +#include +#include +#include "../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 index 00000000..98fc62ed --- /dev/null +++ b/test/blackbox/util/build_container.sh @@ -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 +# +# 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- 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 index 00000000..83c3f4f8 --- /dev/null +++ b/test/blackbox/util/gen_invite.c @@ -0,0 +1,38 @@ +/* + gen_invite.c -- Black Box Test Utility to generate a meshlink invite + Copyright (C) 2018 Guus Sliepen + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ +#include +#include +#include "../../../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 index 00000000..af1175da --- /dev/null +++ b/test/blackbox/util/install_node_sim_copy.sh @@ -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 index 00000000..d9be5f99 --- /dev/null +++ b/test/blackbox/util/lxc_copy_dir.sh @@ -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 +# +# 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 index 00000000..c833681a --- /dev/null +++ b/test/blackbox/util/lxc_copy_file.sh @@ -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 +# +# 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 index 00000000..31c0bcf6 --- /dev/null +++ b/test/blackbox/util/lxc_rename.sh @@ -0,0 +1,29 @@ +# lxc_rename.sh - Script to rename an LXC Container +# Designed to work on unprivileged Containers +# Copyright (C) 2018 Guus Sliepen +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +# 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 index 00000000..4a2456e5 --- /dev/null +++ b/test/blackbox/util/lxc_run.sh @@ -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 +# +# 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 index 00000000..fe28423a --- /dev/null +++ b/test/blackbox/util/node_step.sh @@ -0,0 +1,25 @@ +# node_step.sh -- Script to send signal to control Mesh Node Simulation +# Copyright (C) 2018 Guus Sliepen +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +# 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 index 00000000..4bd9dd5c --- /dev/null +++ b/test/run_blackbox_tests.sh @@ -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