]> git.meshlink.io Git - meshlink/blob - test/blackbox/run_blackbox_tests/test_cases_random_port_bindings02.c
Fix __warn_unused_result__, add more of it and fix the resulting warnings.
[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
20 #ifdef NDEBUG
21 #undef NDEBUG
22 #endif
23
24 #include <stdlib.h>
25 #include <stdarg.h>
26 #include <setjmp.h>
27 #include <cmocka.h>
28 #include <assert.h>
29 #include <pthread.h>
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"
37
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);
42
43 typedef bool (*test_step_func_t)(void);
44 static int setup_test(void **state);
45
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;
57
58 static int setup_test(void **state) {
59         (void)state;
60
61         netns_create_topology(test_random_port_bindings_state);
62         fprintf(stderr, "\nCreated topology\n");
63
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);
71
72         assert(meshlink_destroy("nut"));
73         assert(meshlink_destroy("peer"));
74         assert(meshlink_destroy("relay"));
75
76         return EXIT_SUCCESS;
77 }
78
79 static int teardown_test(void **state) {
80         (void)state;
81
82         assert(meshlink_destroy("nut"));
83         assert(meshlink_destroy("peer"));
84         assert(meshlink_destroy("relay"));
85         netns_destroy_topology(test_random_port_bindings_state);
86
87         return EXIT_SUCCESS;
88 }
89
90 static void execute_test(test_step_func_t step_func, void **state) {
91         (void)state;
92
93
94         fprintf(stderr, "\n\x1b[32mRunning Test\x1b[0m\n");
95         bool test_result = step_func();
96
97         if(!test_result) {
98                 fail();
99         }
100 }
101
102 static void message_log(meshlink_handle_t *mesh, meshlink_log_level_t level, const char *text) {
103         (void)level;
104
105         char *levelstr = "\x1b[32mRELAY";
106
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);
110                 }
111
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);
116                 }
117
118                 levelstr = "\x1b[33mNUT";
119         }
120
121         fprintf(stderr, "%s:\x1b[0m %s\n", levelstr, text);
122 }
123
124 static void node_status(meshlink_handle_t *mesh, meshlink_node_t *node, bool reachable) {
125         (void)mesh;
126
127         if(reachable) {
128                 if((strcmp(mesh->name, "nut") == 0) && (strcmp(node->name, "peer") == 0)) {
129                         set_sync_flag(&test_random_port_binding_peer_reachable, true);
130                 }
131
132                 fprintf(stderr, "%s: %s joined.\n", mesh->name, node->name);
133         }
134 }
135
136 static void *relay_node(void *arg) {
137         mesh_arg_t *mesh_arg = (mesh_arg_t *)arg;
138
139         //system("ifconfig");
140
141         assert(meshlink_destroy("relay"));
142
143         relay = meshlink_open(mesh_arg->node_name, mesh_arg->confbase, mesh_arg->app_name, mesh_arg->dev_class);
144         assert(relay);
145
146         assert_true(meshlink_start(relay));
147         fprintf(stderr, "\n\x1b[32mRelay Started\x1b[0m\n");
148
149         assert((peer_invite = meshlink_invite(relay, NULL, "peer")));
150         assert((nut_invite = meshlink_invite(relay, NULL, "nut")));
151
152         set_sync_flag(&test_random_port_binding_node_started, true);
153
154         meshlink_set_log_cb(relay, MESHLINK_DEBUG, message_log);
155
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"));
160
161
162                 set_sync_flag(&test_random_port_binding_relay_closed, true);
163
164                 return NULL;
165         }
166
167         assert(wait_sync_flag(&test_random_port_binding_node_connected, 300));
168
169         meshlink_close(relay);
170         assert(meshlink_destroy("relay"));
171
172
173         set_sync_flag(&test_random_port_binding_relay_closed, true);
174
175         return NULL;
176 }
177
178 static void *peer_node(void *arg) {
179         mesh_arg_t *mesh_arg = (mesh_arg_t *)arg;
180
181         fprintf(stderr, "\n\x1b[32mPeer Thread Started\x1b[0m\n");
182
183         assert(meshlink_destroy("peer"));
184
185         peer = meshlink_open(mesh_arg->node_name, mesh_arg->confbase, mesh_arg->app_name, mesh_arg->dev_class);
186         assert(peer);
187         meshlink_set_log_cb(peer, MESHLINK_DEBUG, message_log);
188
189         fprintf(stderr, "\n\x1b[32mPeer joining relay\x1b[0m\n");
190
191         assert_true(meshlink_join(peer, (const char *)mesh_arg->join_invitation));
192
193         assert_true(meshlink_start(peer));
194
195         fprintf(stderr, "\n\x1b[32mPeer Started\x1b[0m\n");
196
197         set_sync_flag(&test_random_port_binding_node_started, true);
198
199         assert(wait_sync_flag(&test_random_port_binding_make_switch, 300));
200
201         meshlink_stop(peer);
202
203         //meshlink_set_log_cb(peer, MESHLINK_DEBUG, message_log);
204
205         assert(meshlink_set_port(peer, 20000));
206
207         assert_true(meshlink_start(peer));
208
209         assert(wait_sync_flag(&test_random_port_binding_node_connected, 300));
210
211         meshlink_close(peer);
212         assert(meshlink_destroy("peer"));
213
214         set_sync_flag(&test_random_port_binding_peer_closed, true);
215
216         return NULL;
217 }
218
219 static void *nut_node(void *arg) {
220         mesh_arg_t *mesh_arg = (mesh_arg_t *)arg;
221
222         fprintf(stderr, "\n\x1b[32mNut Thread Started\x1b[0m\n");
223
224         assert(meshlink_destroy("nut"));
225
226         nut_instance = meshlink_open(mesh_arg->node_name, mesh_arg->confbase, mesh_arg->app_name, mesh_arg->dev_class);
227         assert(nut_instance);
228
229         meshlink_set_log_cb(nut_instance, MESHLINK_DEBUG, message_log);
230
231         fprintf(stderr, "\n\x1b[32mNut joining relay\x1b[0m\n");
232
233         assert_true(meshlink_join(nut_instance, (const char *)mesh_arg->join_invitation));
234
235         meshlink_set_node_status_cb(nut_instance, node_status);
236
237         assert_true(meshlink_start(nut_instance));
238
239         fprintf(stderr, "\n\x1b[32mNut Started\x1b[0m\n");
240         sleep(5);
241
242         set_sync_flag(&test_random_port_binding_node_started, true);
243
244         assert(wait_sync_flag(&test_random_port_binding_make_switch, 300));
245
246         meshlink_stop(nut_instance);
247
248         //meshlink_set_log_cb(nut_instance, MESHLINK_DEBUG, message_log);
249
250         assert(meshlink_set_port(nut_instance, 30000));
251
252         assert_true(meshlink_start(nut_instance));
253
254         assert(wait_sync_flag(&test_random_port_binding_node_connected, 300));
255
256         meshlink_close(nut_instance);
257         assert(meshlink_destroy("nut"));
258
259         set_sync_flag(&test_random_port_binding_nut_closed, true);
260
261         return NULL;
262 }
263
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);
267         return;
268 }
269
270 /* Test Steps for Random port bindings Test Case # 4
271
272     Test Steps:
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.
277     Expected Result:
278       NUT and Peer should be able to discover each others port with the help
279       of RELAY and form the direct meta connection.
280 */
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 };
285
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);
288
289         assert(wait_sync_flag(&test_random_port_binding_node_started, 5));
290         fprintf(stderr, "\n\x1b[32mTest-04 : Relay Started\x1b[0m\n");
291
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);
297
298         assert(wait_sync_flag(&test_random_port_binding_node_started, 20));
299         fprintf(stderr, "\n\x1b[32mTest-04 : Peer Started\x1b[0m\n");
300
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);
306
307         assert(wait_sync_flag(&test_random_port_binding_node_started, 20));
308         fprintf(stderr, "\n\x1b[32mTest-04 : Nut Started\x1b[0m\n");
309
310         set_sync_flag(&test_random_port_binding_make_switch, true);
311         fprintf(stderr, "\n\x1b[32mTest-04 : Making Switch\x1b[0m\n");
312
313         assert(wait_sync_flag(&test_random_port_binding_node_connected, 300));
314
315         fprintf(stderr, "\n\x1b[32mDone Test-04\x1b[0m\n");
316
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));
320
321         return true;
322 }
323
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);
327         return;
328 }
329
330 /* Test Steps for Random port bindings Test Case # 5
331
332     Test Steps:
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.
337     Expected Result:
338       NUT and Peer should be able to discover each others port with the help
339       of CATTA and form the direct meta connection.
340 */
341 static bool test_steps_mesh_random_port_bindings_05(void) {
342         localnode = true;
343
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 };
347
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);
350
351         assert(wait_sync_flag(&test_random_port_binding_node_started, 20));
352
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);
357
358         assert(wait_sync_flag(&test_random_port_binding_node_started, 20));
359
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);
364
365         assert(wait_sync_flag(&test_random_port_binding_node_started, 20));
366
367         assert(wait_sync_flag(&test_random_port_binding_peer_reachable, 300));
368
369         set_sync_flag(&test_random_port_binding_make_switch, true);
370
371         assert(wait_sync_flag(&test_random_port_binding_node_connected, 300));
372
373         fprintf(stderr, "\n\x1b[32mDone Test-05\x1b[0m\n");
374
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));
378
379         return true;
380 }
381
382 // Optimal PMTU test case driver
383
384 int test_meshlink_random_port_bindings02(void) {
385         interface_t nut_ifs[] = {{.if_peer = "wan_bridge"}};
386         namespace_t nut = {
387                 .name = "nut",
388                 .type = HOST,
389                 .interfaces = nut_ifs,
390                 .interfaces_no = 1,
391         };
392
393         interface_t peer_ifs[] = {{.if_peer = "wan_bridge"}};
394         namespace_t peer = {
395                 .name = "peer",
396                 .type = HOST,
397                 .interfaces = peer_ifs,
398                 .interfaces_no = 1,
399         };
400
401         interface_t relay_ifs[] = {{.if_peer = "wan_bridge"}};
402         namespace_t relay = {
403                 .name = "relay",
404                 .type = HOST,
405                 .interfaces = relay_ifs,
406                 .interfaces_no = 1,
407         };
408
409         interface_t wan_ifs[] = { { .if_peer = "nut" }, { .if_peer = "peer" }, { .if_peer = "relay" } };
410         namespace_t wan_bridge = {
411                 .name = "wan_bridge",
412                 .type = BRIDGE,
413                 .interfaces = wan_ifs,
414                 .interfaces_no = 3,
415         };
416
417         namespace_t test_random_port_bindings_02_nodes[] = {wan_bridge, nut, peer, relay };
418
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,
422                 .num_namespaces = 4,
423         };
424         test_random_port_bindings_state = &test_port_bindings_nodes;
425
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)
431         };
432         total_tests += sizeof(blackbox_group0_tests) / sizeof(blackbox_group0_tests[0]);
433
434         return cmocka_run_group_tests(blackbox_group0_tests, NULL, NULL);
435 }