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.
20 #include "execute_tests.h"
21 #include "test_cases_set_connection_try_cb.h"
22 #include "../common/test_step.h"
23 #include "../common/common_handlers.h"
24 #include "../../utils.h"
30 static void test_case_set_connection_try_cb_01(void **state);
31 static bool test_set_connection_try_cb_01(void);
33 static bool bar_reachable;
34 static int connection_attempts;
35 static struct sync_flag status_changed_cond = {.mutex = PTHREAD_MUTEX_INITIALIZER, .cond = PTHREAD_COND_INITIALIZER};
36 static struct sync_flag connection_attempt_cond = {.mutex = PTHREAD_MUTEX_INITIALIZER, .cond = PTHREAD_COND_INITIALIZER};
38 static void node_status_cb(meshlink_handle_t *mesh, meshlink_node_t *source, bool reachable) {
39 if(!strcmp(mesh->name, "foo") && !strcmp(source->name, "bar")) {
40 bar_reachable = reachable;
41 set_sync_flag(&status_changed_cond, true);
45 /* Meta-connection try callback handler */
46 static void connection_try_cb(meshlink_handle_t *mesh, meshlink_node_t *source) {
49 if(!strcmp(mesh->name, "foo")) {
50 ++connection_attempts;
52 if(connection_attempts > 3) {
53 set_sync_flag(&connection_attempt_cond, true);
58 /* Execute set meta connection try callback Test Case # 1 */
59 static void test_case_set_connection_try_cb_01(void **state) {
60 execute_test(test_set_connection_try_cb_01, state);
63 /* Test Steps for meshlink_set_connection_try_cb Test Case # 1
66 1. Run foo and bar nodes after exporting and importing node's keys and addresses mutually.
67 2. Close bar node. Wait for connection attempts and cleanup.
70 Connection try callback should be invoked initially when foo and bar forms a meta-connection.
71 After closing bar node it should invoke 3 connection try callbacks in span of about 30 seconds.
73 static bool test_set_connection_try_cb_01(void) {
74 meshlink_destroy("meshlink_conf.1");
75 meshlink_destroy("meshlink_conf.2");
77 // Opening foo and bar nodes
78 meshlink_handle_t *mesh1 = meshlink_open("meshlink_conf.1", "foo", "test", DEV_CLASS_STATIONARY);
79 assert(mesh1 != NULL);
80 meshlink_set_log_cb(mesh1, MESHLINK_DEBUG, meshlink_callback_logger);
81 meshlink_enable_discovery(mesh1, false);
82 meshlink_handle_t *mesh2 = meshlink_open("meshlink_conf.2", "bar", "test", DEV_CLASS_STATIONARY);
83 assert(mesh2 != NULL);
85 // Set up callback for node status
86 meshlink_set_node_status_cb(mesh1, node_status_cb);
87 meshlink_set_connection_try_cb(mesh1, connection_try_cb);
89 // Exporting and Importing mutually
90 char *exp1 = meshlink_export(mesh1);
92 char *exp2 = meshlink_export(mesh2);
94 meshlink_import(mesh1, exp2);
95 meshlink_import(mesh2, exp1);
99 assert(meshlink_start(mesh1));
100 assert(meshlink_start(mesh2));
102 // Wait for foo and bar nodes to join
103 assert(wait_sync_flag(&status_changed_cond, 5));
104 assert(bar_reachable);
106 // Joining should in this case raise one connection try callback
107 assert_int_equal(connection_attempts, 1);
109 // Close the bar node
110 set_sync_flag(&status_changed_cond, false);
111 meshlink_close(mesh2);
112 assert(wait_sync_flag(&status_changed_cond, 5));
113 assert(!bar_reachable);
115 // Wait for additional 3 connection try callbacks
116 time_t attempt_time_start = time(NULL);
117 assert(attempt_time_start != -1);
118 assert_int_equal(wait_sync_flag(&connection_attempt_cond, 60), true);
120 // Close bar node and assert on number of callbacks invoked and the time taken.
121 meshlink_close(mesh1);
122 time_t attempt_time_stop = time(NULL);
123 assert(attempt_time_stop != -1);
124 assert_int_equal(connection_attempts, 4);
125 assert_in_range(attempt_time_stop - attempt_time_start, 25, 45);
128 meshlink_destroy("meshlink_conf.1");
129 meshlink_destroy("meshlink_conf.2");
134 int test_cases_connection_try(void) {
135 black_box_state_t test_case_set_connection_try_cb_01_state = {
136 .test_case_name = "test_case_set_connection_try_cb_01",
139 const struct CMUnitTest blackbox_connection_try_tests[] = {
140 cmocka_unit_test_prestate_setup_teardown(test_case_set_connection_try_cb_01, NULL, NULL,
141 (void *)&test_case_set_connection_try_cb_01_state),
143 total_tests += sizeof(blackbox_connection_try_tests) / sizeof(blackbox_connection_try_tests[0]);
145 int failed = cmocka_run_group_tests(blackbox_connection_try_tests, NULL, NULL);