#undef NDEBUG
#endif
-#include "execute_tests.h"
-#include "test_cases_join.h"
-#include "../common/containers.h"
-#include "../common/test_step.h"
-#include "../common/common_handlers.h"
#include <assert.h>
#include <string.h>
#include <stdlib.h>
#include <setjmp.h>
#include <cmocka.h>
#include <pthread.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <dirent.h>
+#include <sys/wait.h>
+#include <signal.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <utime.h>
+#include "execute_tests.h"
+#include "test_cases_get_node_reachability.h"
+#include "../common/test_step.h"
+#include "../common/common_handlers.h"
+#include "../../utils.h"
+#include "../../../src/devtools.h"
+
+#define NUT "nut"
+#define PEER "peer"
+#define PEER2 "peer2"
+#define TEST_MESHLINK_JOIN "test_meshlink_join"
+#define create_path(confbase, node_name, test_case_no) assert(snprintf(confbase, sizeof(confbase), TEST_MESHLINK_JOIN "_%ld_%s_%02d", (long) getpid(), node_name, test_case_no) > 0)
+
+static struct sync_flag peer_reachable_status_cond = {.mutex = PTHREAD_MUTEX_INITIALIZER, .cond = PTHREAD_COND_INITIALIZER};
+static bool peer_reachable_status;
+static struct sync_flag nut_reachable_status_cond = {.mutex = PTHREAD_MUTEX_INITIALIZER, .cond = PTHREAD_COND_INITIALIZER};
+static bool nut_reachable_status;
+static struct sync_flag nut_started_status_cond = {.mutex = PTHREAD_MUTEX_INITIALIZER, .cond = PTHREAD_COND_INITIALIZER};
+
+/* Node reachable status callback which signals the respective conditional varibale */
+static void meshlink_node_reachable_status_cb(meshlink_handle_t *mesh, meshlink_node_t *node, bool reachable_status) {
+ if(!strcasecmp(mesh->name, NUT)) {
+ if(!strcasecmp(node->name, PEER)) {
+ peer_reachable_status = reachable_status;
+ set_sync_flag(&peer_reachable_status_cond, true);
+ }
+ } else if(!strcasecmp(mesh->name, PEER)) {
+ if(!strcasecmp(node->name, NUT)) {
+ nut_reachable_status = reachable_status;
+ set_sync_flag(&nut_reachable_status_cond, true);
+ }
+ }
+}
-/* Modify this to change the logging level of Meshlink */
-#define TEST_MESHLINK_LOG_LEVEL MESHLINK_DEBUG
+/* SIGUSR2 signal handler that signals the NUT started and PEER node can join */
+static void nut_started_user_signal_handler(int signum) {
+ if(signum == SIGUSR2) {
+ set_sync_flag(&nut_started_status_cond, true);
+ }
+
+}
-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);
+/* Test Steps for meshlink_join Test Case # 1 - Valid case
-/* State structure for join Test Case #1 */
-static black_box_state_t test_case_join_01_state = {
- .test_case_name = "test_case_join_01",
-};
+ Test Steps:
+ 1. Open instances for NUT and peer, peer invites NUT and starts instance.
+ 2. NUT consumes the invitation generated by peer
-/* State structure for join Test Case #1 */
-static black_box_state_t test_case_join_02_state = {
- .test_case_name = "test_case_join_02",
-};
+ Expected Result:
+ NUT joins peer using the invitation generated.
+*/
+static void test_case_meshlink_join_01(void **state) {
+ (void) state;
+ char nut_confbase[PATH_MAX];
+ char peer_confbase[PATH_MAX];
+ create_path(nut_confbase, NUT, 1);
+ create_path(peer_confbase, PEER, 1);
+ meshlink_set_log_cb(NULL, MESHLINK_DEBUG, log_cb);
+
+ // Open both NUT and peer node instance, invite and join NUT with peer node.
+
+ meshlink_handle_t *mesh_peer = meshlink_open(peer_confbase, PEER, TEST_MESHLINK_JOIN,
+ DEV_CLASS_STATIONARY);
+ assert_non_null(mesh_peer);
+ meshlink_set_inviter_commits_first(mesh_peer, true);
+ meshlink_set_node_status_cb(mesh_peer, meshlink_node_reachable_status_cb);
+ char *invitation = meshlink_invite(mesh_peer, NULL, NUT);
+ assert_non_null(invitation);
+ assert_true(meshlink_start(mesh_peer));
+
+ meshlink_handle_t *mesh = meshlink_open(nut_confbase, NUT, TEST_MESHLINK_JOIN,
+ DEV_CLASS_STATIONARY);
+ assert_non_null(mesh);
+ meshlink_set_inviter_commits_first(mesh, true);
+ meshlink_set_node_status_cb(mesh, meshlink_node_reachable_status_cb);
+ assert_true(meshlink_join(mesh, invitation));
+ free(invitation);
-/* State structure for join Test Case #1 */
-static black_box_state_t test_case_join_03_state = {
- .test_case_name = "test_case_join_03",
-};
+ meshlink_node_t *peer_handle = meshlink_get_node(mesh, PEER);
+ assert_non_null(peer_handle);
+ meshlink_node_t *nut_handle = meshlink_get_node(mesh_peer, NUT);
+ assert_non_null(nut_handle);
-static bool join_status;
+ // Bring nodes online.
-/* status callback */
-static void status_callback(meshlink_handle_t *mesh, meshlink_node_t *source, bool reach) {
- (void)mesh;
+ set_sync_flag(&peer_reachable_status_cond, false);
+ set_sync_flag(&nut_reachable_status_cond, false);
+ assert_true(meshlink_start(mesh));
+ assert_true(wait_sync_flag(&peer_reachable_status_cond, 60));
+ assert_true(peer_reachable_status);
+ assert_true(wait_sync_flag(&nut_reachable_status_cond, 60));
+ assert_true(nut_reachable_status);
- if(!strcmp(source->name, "relay")) {
- join_status = reach;
- }
-}
+ // Cleanup
-/* Execute join Test Case # 1 - valid case*/
-static void test_case_meshlink_join_01(void **state) {
- execute_test(test_meshlink_join_01, state);
+ meshlink_close(mesh);
+ meshlink_close(mesh_peer);
+ assert_true(meshlink_destroy(nut_confbase));
+ assert_true(meshlink_destroy(peer_confbase));
+ return;
}
-/* Test Steps for meshlink_join Test Case # 1 - Valid case
+/* Test Steps for meshlink_join Test Case # 2 - Invalid case
Test Steps:
- 1. Generate invite in relay container and run 'relay' node
- 2. Run NUT
- 3. Join NUT with relay using invitation generated.
+ 1. Call meshlink_join with NULL as mesh handler or node name argument.
Expected Result:
- NUT joins relay using the invitation generated.
+ NUT joining fails when NULL is passed as mesh handle or node name argument
*/
-static bool test_meshlink_join_01(void) {
- assert(meshlink_destroy("join_conf.1"));
- assert(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
- assert(meshlink_start(mesh2));
- char *invitation = meshlink_invite(mesh2, NULL, "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);
+static void test_case_meshlink_join_02(void **state) {
+ (void) state;
+ char nut_confbase[PATH_MAX];
+ char peer_confbase[PATH_MAX];
+ create_path(nut_confbase, NUT, 2);
+ create_path(peer_confbase, PEER, 2);
+ meshlink_set_log_cb(NULL, MESHLINK_DEBUG, log_cb);
+
+ // Open both NUT and peer node instance, invite and join NUT with peer node.
+
+ meshlink_handle_t *mesh_peer = meshlink_open(peer_confbase, PEER, TEST_MESHLINK_JOIN,
+ DEV_CLASS_STATIONARY);
+ assert_non_null(mesh_peer);
+ meshlink_set_node_status_cb(mesh_peer, meshlink_node_reachable_status_cb);
+ char *invitation = meshlink_invite(mesh_peer, NULL, NUT);
+ assert_non_null(invitation);
+ assert_true(meshlink_start(mesh_peer));
+
+ meshlink_handle_t *mesh = meshlink_open(nut_confbase, NUT, TEST_MESHLINK_JOIN,
+ DEV_CLASS_STATIONARY);
+ assert_non_null(mesh);
+ meshlink_set_node_status_cb(mesh, meshlink_node_reachable_status_cb);
+
+ // meshlink_join called with NULL as mesh handle and with valid invitation
+
+ assert_int_equal(meshlink_join(NULL, invitation), false);
+ assert_int_equal(meshlink_join(mesh, NULL), false);
+
+ // Cleanup
free(invitation);
- meshlink_close(mesh1);
- meshlink_close(mesh2);
- assert(meshlink_destroy("join_conf.1"));
- assert(meshlink_destroy("join_conf.2"));
+ meshlink_close(mesh);
+ meshlink_close(mesh_peer);
+ assert_true(meshlink_destroy(nut_confbase));
+ assert_true(meshlink_destroy(peer_confbase));
+ return;
+}
+
+/* Test Steps for meshlink_join Test Case # 3 - Persistence testing around inviter
+
+ Test steps and scenarios:
+ 1. Open Node-Under-Test (NUT) and invite peer node and close it's instance.
+ Spawn a process which waits for the peer node to join and raises SIGINT if the
+ appropriate callback is received (on the other hand the test suite opens and joins
+ the peer node with NUT in the forked process).
+ Expected Result:
+ NUT joins peer successfully
+
+
+*/
+static void test_case_meshlink_join_03(void **state) {
+ (void) state;
+ pid_t pid;
+ int pid_status;
+ char nut_confbase[PATH_MAX];
+ char peer_confbase[PATH_MAX];
+ create_path(nut_confbase, NUT, 3);
+ create_path(peer_confbase, PEER, 3);
+ meshlink_set_log_cb(NULL, MESHLINK_DEBUG, log_cb);
+
+ // Open NUT node instance and invite peer node. Close NUT node instance.
+
+ meshlink_handle_t *mesh = meshlink_open(nut_confbase, NUT, TEST_MESHLINK_JOIN, DEV_CLASS_STATIONARY);
+ assert_non_null(mesh);
+ char *invitation = meshlink_invite(mesh, NULL, PEER);
+ meshlink_close(mesh);
+
+ // Set the SIGUSR2 signal handler with handler that signal the condition to the test suite
+
+ sighandler_t usr2sighandler = signal(SIGUSR2, nut_started_user_signal_handler);
+ assert_int_not_equal(usr2sighandler, SIG_ERR);
+
+ // Fork a new process and run NUT in it which just waits for the peer node reachable status callback
+ // and terminates the process immediately.
+
+ pid = fork();
+ assert_int_not_equal(pid, -1);
+
+ if(!pid) {
+ assert(signal(SIGUSR2, SIG_DFL) != SIG_ERR);
- return true;
+ mesh = meshlink_open(nut_confbase, NUT, TEST_MESHLINK_JOIN, DEV_CLASS_STATIONARY);
+ assert(mesh);
+ meshlink_set_log_cb(mesh, MESHLINK_DEBUG, log_cb);
+ meshlink_set_node_status_cb(mesh, meshlink_node_reachable_status_cb);
+
+ set_sync_flag(&peer_reachable_status_cond, false);
+ assert(meshlink_start(mesh));
+
+ assert(kill(getppid(), SIGUSR2) != -1);
+
+ assert(wait_sync_flag(&peer_reachable_status_cond, 60));
+ assert(peer_reachable_status);
+
+ raise(SIGINT);
+ }
+
+ // Open peer node instance and join with the invitation obtained.
+
+ meshlink_handle_t *mesh_peer = meshlink_open(peer_confbase, PEER, TEST_MESHLINK_JOIN,
+ DEV_CLASS_STATIONARY);
+ assert_non_null(mesh_peer);
+
+ // Wait for the started signal from NUT and reset the previous SIGUSR2 signal handler
+
+ assert_true(wait_sync_flag(&nut_started_status_cond, 60));
+ assert_int_not_equal(signal(SIGUSR2, usr2sighandler), SIG_ERR);
+
+ assert_true(meshlink_join(mesh_peer, invitation));
+ assert_true(meshlink_start(mesh_peer));
+
+ // Wait for child exit and verify which signal terminated it
+
+ assert_int_not_equal(waitpid(pid, &pid_status, 0), -1);
+ assert_int_equal(WIFSIGNALED(pid_status), true);
+ assert_int_equal(WTERMSIG(pid_status), SIGINT);
+
+ // Reopen the NUT instance in the same test suite
+
+ mesh = meshlink_open(nut_confbase, NUT, TEST_MESHLINK_JOIN, DEV_CLASS_STATIONARY);
+ assert_non_null(mesh);
+
+ assert_non_null(meshlink_get_node(mesh, PEER));
+
+ // Cleanup
+
+ meshlink_close(mesh);
+ meshlink_close(mesh_peer);
+ assert_true(meshlink_destroy(nut_confbase));
+ assert_true(meshlink_destroy(peer_confbase));
+ return;
}
-/* 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_get_node_reachability Test Case # 4 - Persistence testing around invitee
+
+ Test steps and scenarios:
+ 1. Open peer node instance, invite NUT and start peer node. Spawn a new process in
+ which it opens and joins the NUT with peer node.
+ Reopen NUT instance in the test suite process and verify peer is joined.
+ Expected Result:
+ NUT joins peer successfully
+
+*/
+static void test_case_meshlink_join_04(void **state) {
+ (void) state;
+ pid_t pid;
+ int pid_status;
+ char nut_confbase[PATH_MAX];
+ char peer_confbase[PATH_MAX];
+ create_path(nut_confbase, NUT, 4);
+ create_path(peer_confbase, PEER, 4);
+ meshlink_set_log_cb(NULL, MESHLINK_DEBUG, log_cb);
+
+ // Open peer node instance and invite NUT.
+
+ meshlink_handle_t *mesh_peer = meshlink_open(peer_confbase, PEER, TEST_MESHLINK_JOIN,
+ DEV_CLASS_STATIONARY);
+ assert_int_not_equal(mesh_peer, NULL);
+ char *invitation = meshlink_invite(mesh_peer, NULL, NUT);
+ assert_non_null(invitation);
+
+ assert_true(meshlink_start(mesh_peer));
+
+ // Fork a new process in which NUT is joins with the peer node and raises SIGINT to terminate.
+
+ pid = fork();
+ assert_int_not_equal(pid, -1);
+
+ if(!pid) {
+ meshlink_handle_t *mesh = meshlink_open(nut_confbase, NUT, TEST_MESHLINK_JOIN, DEV_CLASS_STATIONARY);
+ assert(mesh);
+ meshlink_set_log_cb(mesh, MESHLINK_DEBUG, log_cb);
+
+ assert(meshlink_join(mesh, invitation));
+
+ raise(SIGINT);
+ }
+
+ // Wait for child exit and verify which signal terminated it
+
+ assert_int_not_equal(waitpid(pid, &pid_status, 0), -1);
+ assert_int_equal(WIFSIGNALED(pid_status), true);
+ assert_int_equal(WTERMSIG(pid_status), SIGINT);
+
+ // Reopen the NUT instance in the same test suite
+
+ meshlink_handle_t *mesh = meshlink_open(nut_confbase, NUT, TEST_MESHLINK_JOIN, DEV_CLASS_STATIONARY);
+ assert_non_null(mesh);
+
+ assert_non_null(meshlink_get_node(mesh, PEER));
+
+ // Cleanup
+
+ meshlink_close(mesh);
+ meshlink_close(mesh_peer);
+ assert_true(meshlink_destroy(nut_confbase));
+ assert_true(meshlink_destroy(peer_confbase));
+ return;
}
-/* Test Steps for meshlink_join Test Case # 2 - Invalid case
+static void nop_stage(bool stage) {
+ (void)stage;
+ return;
+}
+
+static void debug_probe(bool stage) {
+ (void)stage;
+ raise(SIGINT);
+ return;
+}
+
+/* Test Steps for meshlink_get_node_reachability Test Case # 5 - Test the invitee committing first scenario
+
+ Test steps and scenarios:
+ 1. Open peer node instance, invite NUT and start peer node. Enable the debug probe, Spawn a new process in
+ which it opens and joins the NUT with peer node which terminates the NUT while joining.
+ Reopen NUT instance in the test suite process and verify peer is joined.
+ Expected Result:
+ NUT(invitee) commits the config file(s) first but peer is unaware of NUT.
+
+*/
+static void test_case_meshlink_join_05(void **state) {
+ (void) state;
+ pid_t pid;
+ int pid_status;
+ char nut_confbase[PATH_MAX];
+ char peer_confbase[PATH_MAX];
+ create_path(nut_confbase, NUT, 5);
+ create_path(peer_confbase, PEER, 5);
+ meshlink_set_log_cb(NULL, MESHLINK_DEBUG, log_cb);
+
+ assert(signal(SIGINT, SIG_DFL) != SIG_ERR);
+ assert(signal(SIGABRT, SIG_DFL) != SIG_ERR);
+
+ // Set debug_probe callback
+
+ devtool_set_inviter_commits_first = debug_probe;
+
+ // Open peer node instance and invite NUT.
+
+ meshlink_handle_t *mesh_peer = meshlink_open(peer_confbase, PEER, TEST_MESHLINK_JOIN,
+ DEV_CLASS_STATIONARY);
+ assert_int_not_equal(mesh_peer, NULL);
+ meshlink_set_inviter_commits_first(mesh_peer, false);
+ char *invitation = meshlink_invite(mesh_peer, NULL, NUT);
+ assert_non_null(invitation);
+
+ assert_true(meshlink_start(mesh_peer));
+
+ // Fork a new process in which NUT is joins with the peer node and raises SIGINT to terminate.
+
+ pid = fork();
+ assert_int_not_equal(pid, -1);
+
+ if(!pid) {
+ meshlink_handle_t *mesh = meshlink_open(nut_confbase, NUT, TEST_MESHLINK_JOIN, DEV_CLASS_STATIONARY);
+ assert(mesh);
+ meshlink_set_inviter_commits_first(mesh_peer, false);
+ meshlink_set_log_cb(mesh, MESHLINK_DEBUG, log_cb);
+
+ assert_true(meshlink_join(mesh, invitation));
+
+ raise(SIGABRT);
+ }
+
+ // Wait for child exit and verify which signal terminated it
+ printf("\n");
+ assert_int_not_equal(waitpid(pid, &pid_status, 0), -1);
+ assert_int_equal(WIFSIGNALED(pid_status), true);
+ assert_int_equal(WTERMSIG(pid_status), SIGINT);
+
+ // Reopen the NUT instance in the same test suite
+
+ meshlink_handle_t *mesh = meshlink_open(nut_confbase, NUT, TEST_MESHLINK_JOIN, DEV_CLASS_STATIONARY);
+ assert_non_null(mesh);
+
+ // Invitee committed host config file but invitee should not
+
+ assert_non_null(meshlink_get_node(mesh, PEER));
+ assert_null(meshlink_get_node(mesh_peer, NUT));
+
+ // Cleanup
+
+ free(invitation);
+ meshlink_close(mesh);
+ meshlink_close(mesh_peer);
+ assert_true(meshlink_destroy(nut_confbase));
+ assert_true(meshlink_destroy(peer_confbase));
+
+ devtool_set_inviter_commits_first = nop_stage;
+ return;
+}
+
+/* Test Steps for meshlink_get_node_reachability Test Case # 6 - Test the inviter committing first scenario
+
+ Test steps and scenarios:
+ 1. Open NUT node instance, invite peer and close the instance. Enable the debug probe, Spawn a new process in
+ which it starts the NUT instance. At the parents/test vector thread wait for the signal that NUT raises after starting
+ and join peer with NUT. NUT terminates in debug probe after committing into the disk
+ Reopen NUT instance in the test suite process and verify peer is joined.
+ Expected Result:
+ NUT(inviter) commits the config file(s) first but peer is unaware of NUT.
+
+*/
+static void test_case_meshlink_join_06(void **state) {
+ (void) state;
+ pid_t pid;
+ int pid_status;
+ char nut_confbase[PATH_MAX];
+ char peer_confbase[PATH_MAX];
+ create_path(nut_confbase, NUT, 6);
+ create_path(peer_confbase, PEER, 6);
+ meshlink_set_log_cb(NULL, MESHLINK_DEBUG, log_cb);
+
+ assert(signal(SIGINT, SIG_DFL) != SIG_ERR);
+ assert(signal(SIGABRT, SIG_DFL) != SIG_ERR);
+
+ // Set debug_probe callback
+
+ devtool_set_inviter_commits_first = debug_probe;
+
+ // Open NUT node instance and invite peer node. Close NUT node instance.
+
+ meshlink_handle_t *mesh = meshlink_open(nut_confbase, NUT, TEST_MESHLINK_JOIN, DEV_CLASS_STATIONARY);
+ assert_non_null(mesh);
+ meshlink_set_inviter_commits_first(mesh, true);
+ char *invitation = meshlink_invite(mesh, NULL, PEER);
+ meshlink_close(mesh);
+
+ // Set the SIGUSR2 signal handler with handler that signal the condition to the test suite
+
+ sighandler_t usr2sighandler = signal(SIGUSR2, nut_started_user_signal_handler);
+ assert_int_not_equal(usr2sighandler, SIG_ERR);
+ set_sync_flag(&peer_reachable_status_cond, false);
+
+ // Fork a new process and run NUT in it which just waits for the peer node reachable status callback
+ // and terminates the process immediately.
+
+ pid = fork();
+ assert_int_not_equal(pid, -1);
+
+ if(!pid) {
+ assert(signal(SIGUSR2, SIG_DFL) != SIG_ERR);
+
+ mesh = meshlink_open(nut_confbase, NUT, TEST_MESHLINK_JOIN, DEV_CLASS_STATIONARY);
+ assert(mesh);
+ meshlink_set_inviter_commits_first(mesh, true);
+ meshlink_set_log_cb(mesh, MESHLINK_DEBUG, log_cb);
+ meshlink_set_node_status_cb(mesh, meshlink_node_reachable_status_cb);
+
+ assert(meshlink_start(mesh));
+
+ assert(kill(getppid(), SIGUSR2) != -1);
+
+ sleep(10);
+
+ raise(SIGABRT);
+ }
+
+ // Open peer node instance and join with the invitation obtained.
+
+ meshlink_handle_t *mesh_peer = meshlink_open(peer_confbase, PEER, TEST_MESHLINK_JOIN,
+ DEV_CLASS_STATIONARY);
+ assert_non_null(mesh_peer);
+ meshlink_set_inviter_commits_first(mesh_peer, true);
+
+ // Wait for the started signal from NUT and reset the previous SIGUSR2 signal handler
+
+ assert_true(wait_sync_flag(&nut_started_status_cond, 60));
+ assert_int_not_equal(signal(SIGUSR2, usr2sighandler), SIG_ERR);
+
+ assert_false(meshlink_join(mesh_peer, invitation));
+
+ // Wait for child exit and verify which signal terminated it
+
+ assert_int_not_equal(waitpid(pid, &pid_status, 0), -1);
+ assert_int_equal(WIFSIGNALED(pid_status), true);
+ assert_int_equal(WTERMSIG(pid_status), SIGINT);
+
+ // Reopen the NUT instance in the same test suite
+
+ mesh = meshlink_open(nut_confbase, NUT, TEST_MESHLINK_JOIN, DEV_CLASS_STATIONARY);
+ assert_non_null(mesh);
+
+ // Inviter should first commit config file(s) into the disk
+
+ assert_null(meshlink_get_node(mesh_peer, NUT));
+ assert_non_null(meshlink_get_node(mesh, PEER));
+
+ // Cleanup
+
+ free(invitation);
+ meshlink_close(mesh);
+ meshlink_close(mesh_peer);
+ assert_true(meshlink_destroy(nut_confbase));
+ assert_true(meshlink_destroy(peer_confbase));
+ devtool_set_inviter_commits_first = nop_stage;
+ return;
+}
+
+/* Test Steps for meshlink_join Test Case # 7 - Inviter sets that invitee should commit first,
+ even invitee sets that inviter should commit first.
Test Steps:
- 1. Call meshlink_join with NULL as mesh handler argument.
+ 1. Open instances for NUT and peer, peer invites NUT and starts instance.
+ Both the instances sets meshlink_set_inviter_commits_first API mutually exclusively
+ NUT tries to consume the invitation generated by peer
Expected Result:
- report error accordingly when NULL is passed as mesh handle argument
+ NUT fails to join peer using the invitation generated.
*/
-static bool test_meshlink_join_02(void) {
- assert(meshlink_destroy("join_conf.3"));
+static void test_case_meshlink_join_07(void **state) {
+ (void) state;
+ char nut_confbase[PATH_MAX];
+ char peer_confbase[PATH_MAX];
+ create_path(nut_confbase, NUT, 7);
+ create_path(peer_confbase, PEER, 7);
+ meshlink_set_log_cb(NULL, MESHLINK_DEBUG, log_cb);
+
+ // Open both NUT and peer node instance, invite and join NUT with peer node.
+
+ meshlink_handle_t *mesh_peer = meshlink_open(peer_confbase, PEER, TEST_MESHLINK_JOIN,
+ DEV_CLASS_STATIONARY);
+ assert_non_null(mesh_peer);
+ meshlink_set_inviter_commits_first(mesh_peer, false);
+ meshlink_set_node_status_cb(mesh_peer, meshlink_node_reachable_status_cb);
+ char *invitation = meshlink_invite(mesh_peer, NULL, NUT);
+ assert_non_null(invitation);
+ assert_true(meshlink_start(mesh_peer));
+
+ meshlink_handle_t *mesh = meshlink_open(nut_confbase, NUT, TEST_MESHLINK_JOIN,
+ DEV_CLASS_STATIONARY);
+ assert_non_null(mesh);
+ meshlink_set_inviter_commits_first(mesh, true);
+ meshlink_set_node_status_cb(mesh, meshlink_node_reachable_status_cb);
+ assert_false(meshlink_join(mesh, invitation));
+ free(invitation);
+
+ meshlink_node_t *peer_handle = meshlink_get_node(mesh, PEER);
+ assert_null(peer_handle);
+ meshlink_node_t *nut_handle = meshlink_get_node(mesh_peer, NUT);
+ assert_null(nut_handle);
+
+ // Cleanup
- // 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);
+ meshlink_close(mesh);
+ meshlink_close(mesh_peer);
+ assert_true(meshlink_destroy(nut_confbase));
+ assert_true(meshlink_destroy(peer_confbase));
+ return;
+}
- char *invitation = meshlink_invite(mesh1, NULL, "nodex");
+/* Test Steps for meshlink_join Test Case # 8 - Inviter sets that it should commit first,
+ even invitee sets that it should commit first
- /* meshlink_join called with NULL as mesh handle and with valid invitation */
- bool ret = meshlink_join(NULL, invitation);
- assert_int_equal(ret, false);
+ Test Steps:
+ 1. Open instances for NUT and peer, peer invites NUT and starts instance.
+ Both the instances sets meshlink_set_inviter_commits_first API mutually exclusively
+ NUT tries to consume the invitation generated by peer
+ Expected Result:
+ NUT fails to join peer using the invitation generated.
+*/
+static void test_case_meshlink_join_08(void **state) {
+ (void) state;
+ char nut_confbase[PATH_MAX];
+ char peer_confbase[PATH_MAX];
+ create_path(nut_confbase, NUT, 8);
+ create_path(peer_confbase, PEER, 8);
+ meshlink_set_log_cb(NULL, MESHLINK_DEBUG, log_cb);
+
+ // Open both NUT and peer node instance, invite and join NUT with peer node.
+
+ meshlink_handle_t *mesh_peer = meshlink_open(peer_confbase, PEER, TEST_MESHLINK_JOIN,
+ DEV_CLASS_STATIONARY);
+ assert_non_null(mesh_peer);
+ meshlink_set_inviter_commits_first(mesh_peer, true);
+ meshlink_set_node_status_cb(mesh_peer, meshlink_node_reachable_status_cb);
+ char *invitation = meshlink_invite(mesh_peer, NULL, NUT);
+ assert_non_null(invitation);
+ assert_true(meshlink_start(mesh_peer));
+
+ meshlink_handle_t *mesh = meshlink_open(nut_confbase, NUT, TEST_MESHLINK_JOIN,
+ DEV_CLASS_STATIONARY);
+ assert_non_null(mesh);
+ meshlink_set_inviter_commits_first(mesh, false);
+ meshlink_set_node_status_cb(mesh, meshlink_node_reachable_status_cb);
+ assert_false(meshlink_join(mesh, invitation));
free(invitation);
- meshlink_close(mesh1);
- assert(meshlink_destroy("join_conf.3"));
- return true;
+ meshlink_node_t *peer_handle = meshlink_get_node(mesh, PEER);
+ assert_null(peer_handle);
+ meshlink_node_t *nut_handle = meshlink_get_node(mesh_peer, NUT);
+ assert_null(nut_handle);
+
+ // Cleanup
+
+ meshlink_close(mesh);
+ meshlink_close(mesh_peer);
+ assert_true(meshlink_destroy(nut_confbase));
+ assert_true(meshlink_destroy(peer_confbase));
+ return;
}
-/* 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 # 9 - Invitee already started its instance
+
+ Test Steps:
+ 1. Open instances for NUT and peer, peer invites NUT and both the instances starts their instances.
+ NUT tries to join the peer with the generated invitation.
+
+ Expected Result:
+ NUT fails to join peer using the invitation generated.
+*/
+static void test_case_meshlink_join_09(void **state) {
+ (void) state;
+ char nut_confbase[PATH_MAX];
+ char peer_confbase[PATH_MAX];
+ create_path(nut_confbase, NUT, 9);
+ create_path(peer_confbase, PEER, 9);
+ meshlink_set_log_cb(NULL, MESHLINK_DEBUG, log_cb);
+
+ // Open both NUT and peer node instance, invite and join NUT with peer node.
+
+ meshlink_handle_t *mesh_peer = meshlink_open(peer_confbase, PEER, TEST_MESHLINK_JOIN,
+ DEV_CLASS_STATIONARY);
+ assert_non_null(mesh_peer);
+ meshlink_set_node_status_cb(mesh_peer, meshlink_node_reachable_status_cb);
+ char *invitation = meshlink_invite(mesh_peer, NULL, NUT);
+ assert_non_null(invitation);
+ assert_true(meshlink_start(mesh_peer));
+
+ meshlink_handle_t *mesh = meshlink_open(nut_confbase, NUT, TEST_MESHLINK_JOIN,
+ DEV_CLASS_STATIONARY);
+ assert_non_null(mesh);
+ meshlink_set_node_status_cb(mesh, meshlink_node_reachable_status_cb);
+
+ assert_true(meshlink_start(mesh));
+
+ assert_false(meshlink_join(mesh, invitation));
+ free(invitation);
+
+ meshlink_node_t *peer_handle = meshlink_get_node(mesh, PEER);
+ assert_null(peer_handle);
+ meshlink_node_t *nut_handle = meshlink_get_node(mesh_peer, NUT);
+ assert_null(nut_handle);
+
+ // Cleanup
+
+ meshlink_close(mesh);
+ meshlink_close(mesh_peer);
+ assert_true(meshlink_destroy(nut_confbase));
+ assert_true(meshlink_destroy(peer_confbase));
+ return;
}
-/* Test Steps for meshlink_join Test Case # 3 - Invalid case
+/* Test Steps for meshlink_join Test Case # 10 - Invitee already joined in a mesh
Test Steps:
- 1. Run NUT
- 1. Call meshlink_join with NULL as invitation argument.
+ 1. Open instances for NUT, peer2 and peer, peer invites NUT. Peer2 and NUT both mutually imports data
+ i.e, both formed or joined the mesh.
+ NUT tries to join the peer with the generated invitation.
Expected Result:
- Report error accordingly when NULL is passed as invite argument
+ NUT fails to join peer using the invitation generated.
*/
-static bool test_meshlink_join_03(void) {
- assert(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);
- assert(meshlink_destroy("joinconf.4"));
- return true;
+static void test_case_meshlink_join_10(void **state) {
+ (void) state;
+ char nut_confbase[PATH_MAX];
+ char peer_confbase[PATH_MAX];
+ char peer_confbase2[PATH_MAX];
+ create_path(nut_confbase, NUT, 10);
+ create_path(peer_confbase, PEER, 10);
+ create_path(peer_confbase2, PEER2, 10);
+ meshlink_set_log_cb(NULL, MESHLINK_DEBUG, log_cb);
+
+ // Open both NUT and peer node instance, invite and join NUT with peer node.
+
+ meshlink_handle_t *mesh_peer = meshlink_open(peer_confbase, PEER, TEST_MESHLINK_JOIN,
+ DEV_CLASS_STATIONARY);
+ assert_non_null(mesh_peer);
+ meshlink_set_node_status_cb(mesh_peer, meshlink_node_reachable_status_cb);
+ char *invitation = meshlink_invite(mesh_peer, NULL, NUT);
+ assert_non_null(invitation);
+ assert_true(meshlink_start(mesh_peer));
+
+ meshlink_handle_t *mesh_peer2 = meshlink_open(peer_confbase2, PEER2, TEST_MESHLINK_JOIN,
+ DEV_CLASS_STATIONARY);
+ assert_non_null(mesh_peer2);
+ meshlink_handle_t *mesh = meshlink_open(nut_confbase, NUT, TEST_MESHLINK_JOIN,
+ DEV_CLASS_STATIONARY);
+ assert_non_null(mesh);
+ meshlink_set_node_status_cb(mesh, meshlink_node_reachable_status_cb);
+
+ char *data = meshlink_export(mesh);
+ assert_non_null(data);
+ assert_true(meshlink_import(mesh_peer2, data));
+ free(data);
+ data = meshlink_export(mesh_peer2);
+ assert_non_null(data);
+ assert_true(meshlink_import(mesh, data));
+ free(data);
+
+ assert_true(meshlink_start(mesh));
+
+ assert_false(meshlink_join(mesh, invitation));
+ free(invitation);
+
+ meshlink_node_t *peer_handle = meshlink_get_node(mesh, PEER);
+ assert_null(peer_handle);
+ meshlink_node_t *nut_handle = meshlink_get_node(mesh_peer, NUT);
+ assert_null(nut_handle);
+
+ // Cleanup
+
+ meshlink_close(mesh);
+ meshlink_close(mesh_peer);
+ assert_true(meshlink_destroy(nut_confbase));
+ assert_true(meshlink_destroy(peer_confbase));
+ return;
}
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)
+ cmocka_unit_test(test_case_meshlink_join_01),
+ cmocka_unit_test(test_case_meshlink_join_02),
+ cmocka_unit_test(test_case_meshlink_join_03),
+ cmocka_unit_test(test_case_meshlink_join_04),
+ cmocka_unit_test(test_case_meshlink_join_05),
+ cmocka_unit_test(test_case_meshlink_join_06),
+ cmocka_unit_test(test_case_meshlink_join_07),
+ cmocka_unit_test(test_case_meshlink_join_08),
+ cmocka_unit_test(test_case_meshlink_join_09),
+ cmocka_unit_test(test_case_meshlink_join_10)
};
total_tests += sizeof(blackbox_join_tests) / sizeof(blackbox_join_tests[0]);
return failed;
}
-