2 test_optimal_pmtu.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.
30 #include "../../../src/meshlink.h"
31 #include "../common/containers.h"
32 #include "../common/test_step.h"
33 #include "../common/common_handlers.h"
34 #include "../common/network_namespace_framework.h"
35 #include "../../utils.h"
36 #include "test_cases_random_port_bindings02.h"
38 static void test_case_mesh_random_port_bindings_04(void **state);
39 static bool test_steps_mesh_random_port_bindings_04(void);
40 static void test_case_mesh_random_port_bindings_05(void **state);
41 static bool test_steps_mesh_random_port_bindings_05(void);
43 typedef bool (*test_step_func_t)(void);
44 static int setup_test(void **state);
46 static meshlink_handle_t *peer, *nut_instance, *relay;
47 static char *peer_invite, *nut_invite;
48 struct sync_flag test_random_port_binding_node_connected = {.mutex = PTHREAD_MUTEX_INITIALIZER, .cond = PTHREAD_COND_INITIALIZER};
49 struct sync_flag test_random_port_binding_node_started = {.mutex = PTHREAD_MUTEX_INITIALIZER, .cond = PTHREAD_COND_INITIALIZER};
50 struct sync_flag test_random_port_binding_peer_reachable = {.mutex = PTHREAD_MUTEX_INITIALIZER, .cond = PTHREAD_COND_INITIALIZER};
51 struct sync_flag test_random_port_binding_make_switch = {.mutex = PTHREAD_MUTEX_INITIALIZER, .cond = PTHREAD_COND_INITIALIZER};
52 struct sync_flag test_random_port_binding_relay_closed = {.mutex = PTHREAD_MUTEX_INITIALIZER, .cond = PTHREAD_COND_INITIALIZER};
53 struct sync_flag test_random_port_binding_peer_closed = {.mutex = PTHREAD_MUTEX_INITIALIZER, .cond = PTHREAD_COND_INITIALIZER};
54 struct sync_flag test_random_port_binding_nut_closed = {.mutex = PTHREAD_MUTEX_INITIALIZER, .cond = PTHREAD_COND_INITIALIZER};
55 static netns_state_t *test_random_port_bindings_state;
56 static bool localnode = false;
58 static int setup_test(void **state) {
61 netns_create_topology(test_random_port_bindings_state);
62 fprintf(stderr, "\nCreated topology\n");
64 set_sync_flag(&test_random_port_binding_node_connected, false);
65 set_sync_flag(&test_random_port_binding_node_started, false);
66 set_sync_flag(&test_random_port_binding_peer_reachable, false);
67 set_sync_flag(&test_random_port_binding_make_switch, false);
68 set_sync_flag(&test_random_port_binding_relay_closed, false);
69 set_sync_flag(&test_random_port_binding_peer_closed, false);
70 set_sync_flag(&test_random_port_binding_nut_closed, false);
72 assert(meshlink_destroy("nut"));
73 assert(meshlink_destroy("peer"));
74 assert(meshlink_destroy("relay"));
79 static int teardown_test(void **state) {
82 assert(meshlink_destroy("nut"));
83 assert(meshlink_destroy("peer"));
84 assert(meshlink_destroy("relay"));
85 netns_destroy_topology(test_random_port_bindings_state);
90 static void execute_test(test_step_func_t step_func, void **state) {
94 fprintf(stderr, "\n\x1b[32mRunning Test\x1b[0m\n");
95 bool test_result = step_func();
102 static void message_log(meshlink_handle_t *mesh, meshlink_log_level_t level, const char *text) {
105 char *levelstr = "\x1b[32mRELAY";
107 if(strcmp(mesh->name, "peer") == 0) {
108 if(strcmp("Connection with nut activated", text) == 0) {
109 set_sync_flag(&test_random_port_binding_node_connected, true);
112 levelstr = "\x1b[34mPEER";
113 } else if(strcmp(mesh->name, "nut") == 0) {
114 if(strcmp("Connection with peer activated", text) == 0) {
115 set_sync_flag(&test_random_port_binding_node_connected, true);
118 levelstr = "\x1b[33mNUT";
121 fprintf(stderr, "%s:\x1b[0m %s\n", levelstr, text);
124 static void node_status(meshlink_handle_t *mesh, meshlink_node_t *node, bool reachable) {
128 if((strcmp(mesh->name, "nut") == 0) && (strcmp(node->name, "peer") == 0)) {
129 set_sync_flag(&test_random_port_binding_peer_reachable, true);
132 fprintf(stderr, "%s: %s joined.\n", mesh->name, node->name);
136 static void *relay_node(void *arg) {
137 mesh_arg_t *mesh_arg = (mesh_arg_t *)arg;
139 //system("ifconfig");
141 assert(meshlink_destroy("relay"));
143 relay = meshlink_open(mesh_arg->node_name, mesh_arg->confbase, mesh_arg->app_name, mesh_arg->dev_class);
146 assert_true(meshlink_start(relay));
147 fprintf(stderr, "\n\x1b[32mRelay Started\x1b[0m\n");
149 assert((peer_invite = meshlink_invite(relay, NULL, "peer")));
150 assert((nut_invite = meshlink_invite(relay, NULL, "nut")));
152 set_sync_flag(&test_random_port_binding_node_started, true);
154 meshlink_set_log_cb(relay, MESHLINK_DEBUG, message_log);
156 if(localnode == true) {
157 assert(wait_sync_flag(&test_random_port_binding_make_switch, 300));
158 meshlink_close(relay);
159 assert(meshlink_destroy("relay"));
162 set_sync_flag(&test_random_port_binding_relay_closed, true);
167 assert(wait_sync_flag(&test_random_port_binding_node_connected, 300));
169 meshlink_close(relay);
170 assert(meshlink_destroy("relay"));
173 set_sync_flag(&test_random_port_binding_relay_closed, true);
178 static void *peer_node(void *arg) {
179 mesh_arg_t *mesh_arg = (mesh_arg_t *)arg;
181 fprintf(stderr, "\n\x1b[32mPeer Thread Started\x1b[0m\n");
183 assert(meshlink_destroy("peer"));
185 peer = meshlink_open(mesh_arg->node_name, mesh_arg->confbase, mesh_arg->app_name, mesh_arg->dev_class);
187 meshlink_set_log_cb(peer, MESHLINK_DEBUG, message_log);
189 fprintf(stderr, "\n\x1b[32mPeer joining relay\x1b[0m\n");
191 assert_true(meshlink_join(peer, (const char *)mesh_arg->join_invitation));
193 assert_true(meshlink_start(peer));
195 fprintf(stderr, "\n\x1b[32mPeer Started\x1b[0m\n");
197 set_sync_flag(&test_random_port_binding_node_started, true);
199 assert(wait_sync_flag(&test_random_port_binding_make_switch, 300));
203 //meshlink_set_log_cb(peer, MESHLINK_DEBUG, message_log);
205 assert(meshlink_set_port(peer, 20000));
207 assert_true(meshlink_start(peer));
209 assert(wait_sync_flag(&test_random_port_binding_node_connected, 300));
211 meshlink_close(peer);
212 assert(meshlink_destroy("peer"));
214 set_sync_flag(&test_random_port_binding_peer_closed, true);
219 static void *nut_node(void *arg) {
220 mesh_arg_t *mesh_arg = (mesh_arg_t *)arg;
222 fprintf(stderr, "\n\x1b[32mNut Thread Started\x1b[0m\n");
224 assert(meshlink_destroy("nut"));
226 nut_instance = meshlink_open(mesh_arg->node_name, mesh_arg->confbase, mesh_arg->app_name, mesh_arg->dev_class);
227 assert(nut_instance);
229 meshlink_set_log_cb(nut_instance, MESHLINK_DEBUG, message_log);
231 fprintf(stderr, "\n\x1b[32mNut joining relay\x1b[0m\n");
233 assert_true(meshlink_join(nut_instance, (const char *)mesh_arg->join_invitation));
235 meshlink_set_node_status_cb(nut_instance, node_status);
237 assert_true(meshlink_start(nut_instance));
239 fprintf(stderr, "\n\x1b[32mNut Started\x1b[0m\n");
242 set_sync_flag(&test_random_port_binding_node_started, true);
244 assert(wait_sync_flag(&test_random_port_binding_make_switch, 300));
246 meshlink_stop(nut_instance);
248 //meshlink_set_log_cb(nut_instance, MESHLINK_DEBUG, message_log);
250 assert(meshlink_set_port(nut_instance, 30000));
252 assert_true(meshlink_start(nut_instance));
254 assert(wait_sync_flag(&test_random_port_binding_node_connected, 300));
256 meshlink_close(nut_instance);
257 assert(meshlink_destroy("nut"));
259 set_sync_flag(&test_random_port_binding_nut_closed, true);
264 /* Test Steps for Random port bindings Test Case # 4 */
265 static void test_case_mesh_random_port_bindings_04(void **state) {
266 execute_test(test_steps_mesh_random_port_bindings_04, state);
270 /* Test Steps for Random port bindings Test Case # 4
273 1. Create three node nut, peer and relay in three different name spaces.
274 2. Join nut and peer to relay with invitation.
275 3. Stop the three nodes and change the ports of nut and peer.
276 4. Start all the nodes again.
278 NUT and Peer should be able to discover each others port with the help
279 of RELAY and form the direct meta connection.
281 static bool test_steps_mesh_random_port_bindings_04(void) {
282 mesh_arg_t relay_arg = {.node_name = "relay", .confbase = "relay", .app_name = "chat", .dev_class = 0 };
283 mesh_arg_t peer_arg = {.node_name = "peer", .confbase = "peer", .app_name = "chat", .dev_class = 1 };
284 mesh_arg_t nut_arg = {.node_name = "nut", .confbase = "nut", .app_name = "chat", .dev_class = 1 };
286 netns_thread_t netns_relay_handle = {.namespace_name = "relay", .netns_thread = relay_node, .arg = &relay_arg};
287 run_node_in_namespace_thread(&netns_relay_handle);
289 assert(wait_sync_flag(&test_random_port_binding_node_started, 5));
290 fprintf(stderr, "\n\x1b[32mTest-04 : Relay Started\x1b[0m\n");
292 set_sync_flag(&test_random_port_binding_node_started, false);
293 peer_arg.join_invitation = peer_invite;
294 fprintf(stderr, "\n\x1b[32mTest-04: Got Invite {%s} for peer\x1b[0m\n", peer_arg.join_invitation);
295 netns_thread_t netns_peer_handle = {.namespace_name = "peer", .netns_thread = peer_node, .arg = &peer_arg};
296 run_node_in_namespace_thread(&netns_peer_handle);
298 assert(wait_sync_flag(&test_random_port_binding_node_started, 20));
299 fprintf(stderr, "\n\x1b[32mTest-04 : Peer Started\x1b[0m\n");
301 set_sync_flag(&test_random_port_binding_node_started, false);
302 nut_arg.join_invitation = nut_invite;
303 fprintf(stderr, "\n\x1b[32mTest-04: Got Invite {%s} for nut\x1b[0m\n", nut_arg.join_invitation);
304 netns_thread_t netns_nut_handle = {.namespace_name = "nut", .netns_thread = nut_node, .arg = &nut_arg};
305 run_node_in_namespace_thread(&netns_nut_handle);
307 assert(wait_sync_flag(&test_random_port_binding_node_started, 20));
308 fprintf(stderr, "\n\x1b[32mTest-04 : Nut Started\x1b[0m\n");
310 set_sync_flag(&test_random_port_binding_make_switch, true);
311 fprintf(stderr, "\n\x1b[32mTest-04 : Making Switch\x1b[0m\n");
313 assert(wait_sync_flag(&test_random_port_binding_node_connected, 300));
315 fprintf(stderr, "\n\x1b[32mDone Test-04\x1b[0m\n");
317 assert(wait_sync_flag(&test_random_port_binding_relay_closed, 10));
318 assert(wait_sync_flag(&test_random_port_binding_peer_closed, 10));
319 assert(wait_sync_flag(&test_random_port_binding_nut_closed, 10));
324 /* Test Steps for Random port bindings Test Case # 5 */
325 static void test_case_mesh_random_port_bindings_05(void **state) {
326 execute_test(test_steps_mesh_random_port_bindings_05, state);
330 /* Test Steps for Random port bindings Test Case # 5
333 1. Create three node nut, peer and relay in same name spaces.
334 2. Join nut and peer to relay with invitation.
335 3. Stop the three nodes and change the ports of nut and peer.
336 4. Close the relay node and start nut and peer nodes again.
338 NUT and Peer should be able to discover each others port with the help
339 of CATTA and form the direct meta connection.
341 static bool test_steps_mesh_random_port_bindings_05(void) {
344 mesh_arg_t relay_arg = {.node_name = "relay", .confbase = "relay", .app_name = "chat", .dev_class = 1 };
345 mesh_arg_t peer_arg = {.node_name = "peer", .confbase = "peer", .app_name = "chat", .dev_class = 1 };
346 mesh_arg_t nut_arg = {.node_name = "nut", .confbase = "nut", .app_name = "chat", .dev_class = 1 };
348 netns_thread_t netns_relay_handle = {.namespace_name = "relay", .netns_thread = relay_node, .arg = &relay_arg};
349 run_node_in_namespace_thread(&netns_relay_handle);
351 assert(wait_sync_flag(&test_random_port_binding_node_started, 20));
353 set_sync_flag(&test_random_port_binding_node_started, false);
354 peer_arg.join_invitation = peer_invite;
355 netns_thread_t netns_peer_handle = {.namespace_name = "peer", .netns_thread = peer_node, .arg = &peer_arg};
356 run_node_in_namespace_thread(&netns_peer_handle);
358 assert(wait_sync_flag(&test_random_port_binding_node_started, 20));
360 set_sync_flag(&test_random_port_binding_node_started, false);
361 nut_arg.join_invitation = nut_invite;
362 netns_thread_t netns_nut_handle = {.namespace_name = "nut", .netns_thread = nut_node, .arg = &nut_arg};
363 run_node_in_namespace_thread(&netns_nut_handle);
365 assert(wait_sync_flag(&test_random_port_binding_node_started, 20));
367 assert(wait_sync_flag(&test_random_port_binding_peer_reachable, 300));
369 set_sync_flag(&test_random_port_binding_make_switch, true);
371 assert(wait_sync_flag(&test_random_port_binding_node_connected, 300));
373 fprintf(stderr, "\n\x1b[32mDone Test-05\x1b[0m\n");
375 assert(wait_sync_flag(&test_random_port_binding_relay_closed, 10));
376 assert(wait_sync_flag(&test_random_port_binding_peer_closed, 10));
377 assert(wait_sync_flag(&test_random_port_binding_nut_closed, 10));
382 // Optimal PMTU test case driver
384 int test_meshlink_random_port_bindings02(void) {
385 interface_t nut_ifs[] = {{.if_peer = "wan_bridge"}};
389 .interfaces = nut_ifs,
393 interface_t peer_ifs[] = {{.if_peer = "wan_bridge"}};
397 .interfaces = peer_ifs,
401 interface_t relay_ifs[] = {{.if_peer = "wan_bridge"}};
402 namespace_t relay = {
405 .interfaces = relay_ifs,
409 interface_t wan_ifs[] = { { .if_peer = "nut" }, { .if_peer = "peer" }, { .if_peer = "relay" } };
410 namespace_t wan_bridge = {
411 .name = "wan_bridge",
413 .interfaces = wan_ifs,
417 namespace_t test_random_port_bindings_02_nodes[] = {wan_bridge, nut, peer, relay };
419 netns_state_t test_port_bindings_nodes = {
420 .test_case_name = "test_case_random_port_bindings_02",
421 .namespaces = test_random_port_bindings_02_nodes,
424 test_random_port_bindings_state = &test_port_bindings_nodes;
426 const struct CMUnitTest blackbox_group0_tests[] = {
427 cmocka_unit_test_prestate_setup_teardown(test_case_mesh_random_port_bindings_04, setup_test, teardown_test,
428 (void *)&test_random_port_bindings_state),
429 cmocka_unit_test_prestate_setup_teardown(test_case_mesh_random_port_bindings_05, setup_test, teardown_test,
430 (void *)&test_random_port_bindings_state)
432 total_tests += sizeof(blackbox_group0_tests) / sizeof(blackbox_group0_tests[0]);
434 return cmocka_run_group_tests(blackbox_group0_tests, NULL, NULL);