]> git.meshlink.io Git - meshlink/blob - test/blackbox/run_blackbox_tests/test_cases_random_port_bindings02.c
Add test cases for random port bindings
[meshlink] / test / blackbox / run_blackbox_tests / test_cases_random_port_bindings02.c
1 /*
2     test_optimal_pmtu.c -- Execution of specific meshlink black box test cases
3     Copyright (C) 2019  Guus Sliepen <guus@meshlink.io>
4
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.
9
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.
14
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.
18 */
19 #include <stdlib.h>
20 #include <stdarg.h>
21 #include <setjmp.h>
22 #include <cmocka.h>
23 #include <assert.h>
24 #include <pthread.h>
25 #include "../../../src/meshlink.h"
26 #include "../common/containers.h"
27 #include "../common/test_step.h"
28 #include "../common/common_handlers.h"
29 #include "../common/network_namespace_framework.h"
30 #include "../../utils.h"
31 #include "test_cases_random_port_bindings02.h"
32
33 static void test_case_mesh_random_port_bindings_04(void **state);
34 static bool test_steps_mesh_random_port_bindings_04(void);
35 static void test_case_mesh_random_port_bindings_05(void **state);
36 static bool test_steps_mesh_random_port_bindings_05(void);
37
38 typedef bool (*test_step_func_t)(void);
39 static int setup_test(void **state);
40
41 static meshlink_handle_t *peer, *nut_instance, *relay;
42 static char *peer_invite, *nut_invite;
43 struct sync_flag test_random_port_binding_node_connected = {.mutex  = PTHREAD_MUTEX_INITIALIZER, .cond = PTHREAD_COND_INITIALIZER};
44 struct sync_flag test_random_port_binding_node_started = {.mutex  = PTHREAD_MUTEX_INITIALIZER, .cond = PTHREAD_COND_INITIALIZER};
45 struct sync_flag test_random_port_binding_peer_reachable = {.mutex  = PTHREAD_MUTEX_INITIALIZER, .cond = PTHREAD_COND_INITIALIZER};
46 struct sync_flag test_random_port_binding_make_switch = {.mutex  = PTHREAD_MUTEX_INITIALIZER, .cond = PTHREAD_COND_INITIALIZER};
47 struct sync_flag test_random_port_binding_relay_closed = {.mutex  = PTHREAD_MUTEX_INITIALIZER, .cond = PTHREAD_COND_INITIALIZER};
48 struct sync_flag test_random_port_binding_peer_closed = {.mutex  = PTHREAD_MUTEX_INITIALIZER, .cond = PTHREAD_COND_INITIALIZER};
49 struct sync_flag test_random_port_binding_nut_closed = {.mutex  = PTHREAD_MUTEX_INITIALIZER, .cond = PTHREAD_COND_INITIALIZER};
50 static netns_state_t *test_random_port_bindings_state;
51 static bool localnode = false;
52
53 static int setup_test(void **state) {
54         netns_create_topology(test_random_port_bindings_state);
55         fprintf(stderr, "\nCreated topology\n");
56
57         set_sync_flag(&test_random_port_binding_node_connected, false);
58         set_sync_flag(&test_random_port_binding_node_started, false);
59         set_sync_flag(&test_random_port_binding_peer_reachable, false);
60         set_sync_flag(&test_random_port_binding_make_switch, false);
61         set_sync_flag(&test_random_port_binding_relay_closed, false);
62         set_sync_flag(&test_random_port_binding_peer_closed, false);
63         set_sync_flag(&test_random_port_binding_nut_closed, false);
64
65         meshlink_destroy("nut");
66         meshlink_destroy("peer");
67         meshlink_destroy("relay");
68
69         return EXIT_SUCCESS;
70 }
71
72 static int teardown_test(void **state) {
73         meshlink_destroy("nut");
74         meshlink_destroy("peer");
75         meshlink_destroy("relay");
76         netns_destroy_topology(test_random_port_bindings_state);
77
78         return EXIT_SUCCESS;
79 }
80
81 static void execute_test(test_step_func_t step_func, void **state) {
82
83         fprintf(stderr, "\n\x1b[32mRunning Test\x1b[0m\n");
84         bool test_result = step_func();
85
86         if(!test_result) {
87                 fail();
88         }
89 }
90
91 static void message_log(meshlink_handle_t *mesh, meshlink_log_level_t level, const char *text) {
92         char *levelstr = "\x1b[32mRELAY";
93
94         if(strcmp(mesh->name, "peer") == 0) {
95                 if(strcmp("Connection with nut activated", text) == 0) {
96                         set_sync_flag(&test_random_port_binding_node_connected, true);
97                 }
98
99                 levelstr = "\x1b[34mPEER";
100         } else if(strcmp(mesh->name, "nut") == 0) {
101                 if(strcmp("Connection with peer activated", text) == 0) {
102                         set_sync_flag(&test_random_port_binding_node_connected, true);
103                 }
104
105                 levelstr = "\x1b[33mNUT";
106         }
107
108         fprintf(stderr, "%s:\x1b[0m %s\n", levelstr, text);
109 }
110
111 static void node_status(meshlink_handle_t *mesh, meshlink_node_t *node, bool reachable) {
112         (void)mesh;
113
114         if(reachable) {
115                 if((strcmp(mesh->name, "nut") == 0) && (strcmp(node->name, "peer") == 0)) {
116                         set_sync_flag(&test_random_port_binding_peer_reachable, true);
117                 }
118
119                 fprintf(stderr, "%s: %s joined.\n", mesh->name, node->name);
120         }
121 }
122
123 static void *relay_node(void *arg) {
124         mesh_arg_t *mesh_arg = (mesh_arg_t *)arg;
125
126         //system("ifconfig");
127
128         meshlink_destroy("relay");
129
130         relay = meshlink_open(mesh_arg->node_name, mesh_arg->confbase, mesh_arg->app_name, mesh_arg->dev_class);
131         assert(relay);
132
133         assert_true(meshlink_start(relay));
134         fprintf(stderr, "\n\x1b[32mRelay Started\x1b[0m\n");
135
136         assert((peer_invite = meshlink_invite(relay, NULL, "peer")));
137         assert((nut_invite = meshlink_invite(relay, NULL, "nut")));
138
139         set_sync_flag(&test_random_port_binding_node_started, true);
140
141         meshlink_set_log_cb(relay, MESHLINK_DEBUG, message_log);
142
143         if(localnode == true) {
144                 assert(wait_sync_flag(&test_random_port_binding_make_switch, 300));
145                 meshlink_close(relay);
146                 meshlink_destroy("relay");
147
148
149                 set_sync_flag(&test_random_port_binding_relay_closed, true);
150
151                 return NULL;
152         }
153
154         assert(wait_sync_flag(&test_random_port_binding_node_connected, 300));
155
156         meshlink_close(relay);
157         meshlink_destroy("relay");
158
159
160         set_sync_flag(&test_random_port_binding_relay_closed, true);
161
162         return NULL;
163 }
164
165 static void *peer_node(void *arg) {
166         mesh_arg_t *mesh_arg = (mesh_arg_t *)arg;
167
168         fprintf(stderr, "\n\x1b[32mPeer Thread Started\x1b[0m\n");
169
170         meshlink_destroy("peer");
171
172         peer = meshlink_open(mesh_arg->node_name, mesh_arg->confbase, mesh_arg->app_name, mesh_arg->dev_class);
173         assert(peer);
174         meshlink_set_log_cb(peer, MESHLINK_DEBUG, message_log);
175
176         fprintf(stderr, "\n\x1b[32mPeer joining relay\x1b[0m\n");
177
178         assert_true(meshlink_join(peer, (const char *)mesh_arg->join_invitation));
179
180         assert_true(meshlink_start(peer));
181
182         fprintf(stderr, "\n\x1b[32mPeer Started\x1b[0m\n");
183
184         set_sync_flag(&test_random_port_binding_node_started, true);
185
186         assert(wait_sync_flag(&test_random_port_binding_make_switch, 300));
187
188         meshlink_stop(peer);
189
190         //meshlink_set_log_cb(peer, MESHLINK_DEBUG, message_log);
191
192         assert(meshlink_set_port(peer, 20000));
193
194         assert_true(meshlink_start(peer));
195
196         assert(wait_sync_flag(&test_random_port_binding_node_connected, 300));
197
198         meshlink_close(peer);
199         meshlink_destroy("peer");
200
201         set_sync_flag(&test_random_port_binding_peer_closed, true);
202
203         return NULL;
204 }
205
206 static void *nut_node(void *arg) {
207         mesh_arg_t *mesh_arg = (mesh_arg_t *)arg;
208
209         fprintf(stderr, "\n\x1b[32mNut Thread Started\x1b[0m\n");
210
211         meshlink_destroy("nut");
212
213         nut_instance = meshlink_open(mesh_arg->node_name, mesh_arg->confbase, mesh_arg->app_name, mesh_arg->dev_class);
214         assert(nut_instance);
215
216         meshlink_set_log_cb(nut_instance, MESHLINK_DEBUG, message_log);
217
218         fprintf(stderr, "\n\x1b[32mNut joining relay\x1b[0m\n");
219
220         assert_true(meshlink_join(nut_instance, (const char *)mesh_arg->join_invitation));
221
222         meshlink_set_node_status_cb(nut_instance, node_status);
223
224         assert_true(meshlink_start(nut_instance));
225
226         fprintf(stderr, "\n\x1b[32mNut Started\x1b[0m\n");
227         sleep(5);
228
229         set_sync_flag(&test_random_port_binding_node_started, true);
230
231         assert(wait_sync_flag(&test_random_port_binding_make_switch, 300));
232
233         meshlink_stop(nut_instance);
234
235         //meshlink_set_log_cb(nut_instance, MESHLINK_DEBUG, message_log);
236
237         assert(meshlink_set_port(nut_instance, 30000));
238
239         assert_true(meshlink_start(nut_instance));
240
241         assert(wait_sync_flag(&test_random_port_binding_node_connected, 300));
242
243         meshlink_close(nut_instance);
244         meshlink_destroy("nut");
245
246         set_sync_flag(&test_random_port_binding_nut_closed, true);
247
248         return NULL;
249 }
250
251 /* Test Steps for Random port bindings Test Case # 4 */
252 static void test_case_mesh_random_port_bindings_04(void **state) {
253         execute_test(test_steps_mesh_random_port_bindings_04, state);
254         return;
255 }
256
257 /* Test Steps for Random port bindings Test Case # 4
258
259     Test Steps:
260     1. Create three node nut, peer and relay in three different name spaces.
261     2. Join nut and peer to relay with invitation.
262     3. Stop the three nodes and change the ports of nut and peer.
263     4. Start all the nodes again.
264     Expected Result:
265       NUT and Peer should be able to discover each others port with the help
266       of RELAY and form the direct meta connection.
267 */
268 static bool test_steps_mesh_random_port_bindings_04(void) {
269         mesh_arg_t relay_arg = {.node_name = "relay", .confbase = "relay", .app_name = "chat", .dev_class = 0 };
270         mesh_arg_t peer_arg = {.node_name = "peer", .confbase = "peer", .app_name = "chat", .dev_class = 1 };
271         mesh_arg_t nut_arg = {.node_name = "nut", .confbase = "nut", .app_name = "chat", .dev_class = 1 };
272
273         netns_thread_t netns_relay_handle = {.namespace_name = "relay", .netns_thread = relay_node, .arg = &relay_arg};
274         run_node_in_namespace_thread(&netns_relay_handle);
275
276         assert(wait_sync_flag(&test_random_port_binding_node_started, 5));
277         fprintf(stderr, "\n\x1b[32mTest-04 : Relay Started\x1b[0m\n");
278
279         set_sync_flag(&test_random_port_binding_node_started, false);
280         peer_arg.join_invitation = peer_invite;
281         fprintf(stderr, "\n\x1b[32mTest-04: Got Invite {%s} for peer\x1b[0m\n", peer_arg.join_invitation);
282         netns_thread_t netns_peer_handle = {.namespace_name = "peer", .netns_thread = peer_node, .arg = &peer_arg};
283         run_node_in_namespace_thread(&netns_peer_handle);
284
285         assert(wait_sync_flag(&test_random_port_binding_node_started, 20));
286         fprintf(stderr, "\n\x1b[32mTest-04 : Peer Started\x1b[0m\n");
287
288         set_sync_flag(&test_random_port_binding_node_started, false);
289         nut_arg.join_invitation = nut_invite;
290         fprintf(stderr, "\n\x1b[32mTest-04: Got Invite {%s} for nut\x1b[0m\n", nut_arg.join_invitation);
291         netns_thread_t netns_nut_handle = {.namespace_name = "nut", .netns_thread = nut_node, .arg = &nut_arg};
292         run_node_in_namespace_thread(&netns_nut_handle);
293
294         assert(wait_sync_flag(&test_random_port_binding_node_started, 20));
295         fprintf(stderr, "\n\x1b[32mTest-04 : Nut Started\x1b[0m\n");
296
297         set_sync_flag(&test_random_port_binding_make_switch, true);
298         fprintf(stderr, "\n\x1b[32mTest-04 : Making Switch\x1b[0m\n");
299
300         assert(wait_sync_flag(&test_random_port_binding_node_connected, 300));
301
302         fprintf(stderr, "\n\x1b[32mDone Test-04\x1b[0m\n");
303
304         assert(wait_sync_flag(&test_random_port_binding_relay_closed, 10));
305         assert(wait_sync_flag(&test_random_port_binding_peer_closed, 10));
306         assert(wait_sync_flag(&test_random_port_binding_nut_closed, 10));
307
308         return true;
309 }
310
311 /* Test Steps for Random port bindings Test Case # 5 */
312 static void test_case_mesh_random_port_bindings_05(void **state) {
313         execute_test(test_steps_mesh_random_port_bindings_05, state);
314         return;
315 }
316
317 /* Test Steps for Random port bindings Test Case # 5
318
319     Test Steps:
320     1. Create three node nut, peer and relay in same name spaces.
321     2. Join nut and peer to relay with invitation.
322     3. Stop the three nodes and change the ports of nut and peer.
323     4. Close the relay node and start nut and peer nodes again.
324     Expected Result:
325       NUT and Peer should be able to discover each others port with the help
326       of CATTA and form the direct meta connection.
327 */
328 static bool test_steps_mesh_random_port_bindings_05(void) {
329         localnode = true;
330
331         mesh_arg_t relay_arg = {.node_name = "relay", .confbase = "relay", .app_name = "chat", .dev_class = 1 };
332         mesh_arg_t peer_arg = {.node_name = "peer", .confbase = "peer", .app_name = "chat", .dev_class = 1 };
333         mesh_arg_t nut_arg = {.node_name = "nut", .confbase = "nut", .app_name = "chat", .dev_class = 1 };
334
335         netns_thread_t netns_relay_handle = {.namespace_name = "relay", .netns_thread = relay_node, .arg = &relay_arg};
336         run_node_in_namespace_thread(&netns_relay_handle);
337
338         assert(wait_sync_flag(&test_random_port_binding_node_started, 20));
339
340         set_sync_flag(&test_random_port_binding_node_started, false);
341         peer_arg.join_invitation = peer_invite;
342         netns_thread_t netns_peer_handle = {.namespace_name = "peer", .netns_thread = peer_node, .arg = &peer_arg};
343         run_node_in_namespace_thread(&netns_peer_handle);
344
345         assert(wait_sync_flag(&test_random_port_binding_node_started, 20));
346
347         set_sync_flag(&test_random_port_binding_node_started, false);
348         nut_arg.join_invitation = nut_invite;
349         netns_thread_t netns_nut_handle = {.namespace_name = "nut", .netns_thread = nut_node, .arg = &nut_arg};
350         run_node_in_namespace_thread(&netns_nut_handle);
351
352         assert(wait_sync_flag(&test_random_port_binding_node_started, 20));
353
354         assert(wait_sync_flag(&test_random_port_binding_peer_reachable, 300));
355
356         set_sync_flag(&test_random_port_binding_make_switch, true);
357
358         assert(wait_sync_flag(&test_random_port_binding_node_connected, 300));
359
360         fprintf(stderr, "\n\x1b[32mDone Test-05\x1b[0m\n");
361
362         assert(wait_sync_flag(&test_random_port_binding_relay_closed, 10));
363         assert(wait_sync_flag(&test_random_port_binding_peer_closed, 10));
364         assert(wait_sync_flag(&test_random_port_binding_nut_closed, 10));
365
366         return true;
367 }
368
369 // Optimal PMTU test case driver
370
371 int test_meshlink_random_port_bindings02(void) {
372         interface_t nut_ifs[] = {{.if_peer = "wan_bridge"}};
373         namespace_t nut = {
374                 .name = "nut",
375                 .type = HOST,
376                 .interfaces = nut_ifs,
377                 .interfaces_no = 1,
378         };
379
380         interface_t peer_ifs[] = {{.if_peer = "wan_bridge"}};
381         namespace_t peer = {
382                 .name = "peer",
383                 .type = HOST,
384                 .interfaces = peer_ifs,
385                 .interfaces_no = 1,
386         };
387
388         interface_t relay_ifs[] = {{.if_peer = "wan_bridge"}};
389         namespace_t relay = {
390                 .name = "relay",
391                 .type = HOST,
392                 .interfaces = relay_ifs,
393                 .interfaces_no = 1,
394         };
395
396         interface_t wan_ifs[] = { { .if_peer = "nut" }, { .if_peer = "peer" }, { .if_peer = "relay" } };
397         namespace_t wan_bridge = {
398                 .name = "wan_bridge",
399                 .type = BRIDGE,
400                 .interfaces = wan_ifs,
401                 .interfaces_no = 3,
402         };
403
404         namespace_t test_random_port_bindings_02_nodes[] = {wan_bridge, nut, peer, relay };
405
406         netns_state_t test_port_bindings_nodes = {
407                 .test_case_name =  "test_case_random_port_bindings_02",
408                 .namespaces =  test_random_port_bindings_02_nodes,
409                 .num_namespaces = 4,
410         };
411         test_random_port_bindings_state = &test_port_bindings_nodes;
412
413         const struct CMUnitTest blackbox_group0_tests[] = {
414                 cmocka_unit_test_prestate_setup_teardown(test_case_mesh_random_port_bindings_04, setup_test, teardown_test,
415                                 (void *)&test_random_port_bindings_state),
416                 cmocka_unit_test_prestate_setup_teardown(test_case_mesh_random_port_bindings_05, setup_test, teardown_test,
417                                 (void *)&test_random_port_bindings_state)
418         };
419         total_tests += sizeof(blackbox_group0_tests) / sizeof(blackbox_group0_tests[0]);
420
421         return cmocka_run_group_tests(blackbox_group0_tests, NULL, NULL);
422 }