2 test_cases_set_connection_try_cb.c -- Execution of specific meshlink black box test cases
3 Copyright (C) 2019 Guus Sliepen <guus@meshlink.io>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24 #include "execute_tests.h"
25 #include "test_cases_set_connection_try_cb.h"
26 #include "../common/test_step.h"
27 #include "../common/common_handlers.h"
28 #include "../../utils.h"
34 static void test_case_set_connection_try_cb_01(void **state);
35 static bool test_set_connection_try_cb_01(void);
37 static bool bar_reachable;
38 static int connection_attempts;
39 static struct sync_flag status_changed_cond = {.mutex = PTHREAD_MUTEX_INITIALIZER, .cond = PTHREAD_COND_INITIALIZER};
40 static struct sync_flag connection_attempt_cond = {.mutex = PTHREAD_MUTEX_INITIALIZER, .cond = PTHREAD_COND_INITIALIZER};
42 static void node_status_cb(meshlink_handle_t *mesh, meshlink_node_t *source, bool reachable) {
43 if(!strcmp(mesh->name, "foo") && !strcmp(source->name, "bar")) {
44 bar_reachable = reachable;
45 set_sync_flag(&status_changed_cond, true);
49 /* Meta-connection try callback handler */
50 static void connection_try_cb(meshlink_handle_t *mesh, meshlink_node_t *source) {
53 if(!strcmp(mesh->name, "foo")) {
54 ++connection_attempts;
56 if(connection_attempts > 3) {
57 set_sync_flag(&connection_attempt_cond, true);
62 /* Execute set meta connection try callback Test Case # 1 */
63 static void test_case_set_connection_try_cb_01(void **state) {
64 execute_test(test_set_connection_try_cb_01, state);
67 /* Test Steps for meshlink_set_connection_try_cb Test Case # 1
70 1. Run foo and bar nodes after exporting and importing node's keys and addresses mutually.
71 2. Close bar node. Wait for connection attempts and cleanup.
74 Connection try callback should be invoked initially when foo and bar forms a meta-connection.
75 After closing bar node it should invoke 3 connection try callbacks in span of about 30 seconds.
77 static bool test_set_connection_try_cb_01(void) {
78 assert(meshlink_destroy("meshlink_conf.1"));
79 assert(meshlink_destroy("meshlink_conf.2"));
81 // Opening foo and bar nodes
82 meshlink_handle_t *mesh1 = meshlink_open("meshlink_conf.1", "foo", "test", DEV_CLASS_STATIONARY);
83 assert(mesh1 != NULL);
84 meshlink_set_log_cb(mesh1, MESHLINK_DEBUG, meshlink_callback_logger);
85 meshlink_enable_discovery(mesh1, false);
86 meshlink_handle_t *mesh2 = meshlink_open("meshlink_conf.2", "bar", "test", DEV_CLASS_STATIONARY);
87 assert(mesh2 != NULL);
89 // Set up callback for node status
90 meshlink_set_node_status_cb(mesh1, node_status_cb);
91 meshlink_set_connection_try_cb(mesh1, connection_try_cb);
93 // Exporting and Importing mutually
94 char *exp1 = meshlink_export(mesh1);
96 char *exp2 = meshlink_export(mesh2);
98 assert(meshlink_import(mesh1, exp2));
99 assert(meshlink_import(mesh2, exp1));
103 assert(meshlink_start(mesh1));
104 assert(meshlink_start(mesh2));
106 // Wait for foo and bar nodes to join
107 assert(wait_sync_flag(&status_changed_cond, 5));
108 assert(bar_reachable);
110 // Joining should in this case raise one connection try callback
111 assert_int_equal(connection_attempts, 1);
113 // Close the bar node
114 set_sync_flag(&status_changed_cond, false);
115 meshlink_close(mesh2);
116 assert(wait_sync_flag(&status_changed_cond, 5));
117 assert(!bar_reachable);
119 // Wait for additional 3 connection try callbacks
120 time_t attempt_time_start = time(NULL);
121 assert(attempt_time_start != -1);
122 assert_int_equal(wait_sync_flag(&connection_attempt_cond, 60), true);
124 // Close bar node and assert on number of callbacks invoked and the time taken.
125 meshlink_close(mesh1);
126 time_t attempt_time_stop = time(NULL);
127 assert(attempt_time_stop != -1);
128 assert_int_equal(connection_attempts, 4);
129 assert_in_range(attempt_time_stop - attempt_time_start, 25, 45);
132 assert(meshlink_destroy("meshlink_conf.1"));
133 assert(meshlink_destroy("meshlink_conf.2"));
138 int test_cases_connection_try(void) {
139 black_box_state_t test_case_set_connection_try_cb_01_state = {
140 .test_case_name = "test_case_set_connection_try_cb_01",
143 const struct CMUnitTest blackbox_connection_try_tests[] = {
144 cmocka_unit_test_prestate_setup_teardown(test_case_set_connection_try_cb_01, NULL, NULL,
145 (void *)&test_case_set_connection_try_cb_01_state),
147 total_tests += sizeof(blackbox_connection_try_tests) / sizeof(blackbox_connection_try_tests[0]);
149 int failed = cmocka_run_group_tests(blackbox_connection_try_tests, NULL, NULL);