2 test_cases_get_node_reachability.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.
32 #include <sys/types.h>
39 #include "execute_tests.h"
40 #include "test_cases_get_node_reachability.h"
41 #include "../common/test_step.h"
42 #include "../common/common_handlers.h"
43 #include "../../utils.h"
48 #define GET_NODE_REACHABILITY "test_get_node_reachability"
49 #define create_path(confbase, node_name, test_case_no) assert(snprintf(confbase, sizeof(confbase), GET_NODE_REACHABILITY "_%ld_%s_%02d", (long) getpid(), node_name, test_case_no) > 0)
51 static struct sync_flag peer_reachable_status_cond = {.mutex = PTHREAD_MUTEX_INITIALIZER, .cond = PTHREAD_COND_INITIALIZER};
52 static bool peer_reachable_status;
53 static struct sync_flag nut_reachable_status_cond = {.mutex = PTHREAD_MUTEX_INITIALIZER, .cond = PTHREAD_COND_INITIALIZER};
54 static bool nut_reachable_status;
55 static struct sync_flag nut_started_status_cond = {.mutex = PTHREAD_MUTEX_INITIALIZER, .cond = PTHREAD_COND_INITIALIZER};
56 static bool peer_node_callback_test_status;
58 static void test_case_get_node_reachability_01(void **state);
59 static bool test_get_node_reachability_01(void);
60 static void test_case_get_node_reachability_02(void **state);
61 static bool test_get_node_reachability_02(void);
62 static void test_case_get_node_reachability_03(void **state);
63 static bool test_get_node_reachability_03(void);
64 static void test_case_get_node_reachability_04(void **state);
65 static bool test_get_node_reachability_04(void);
66 static void test_case_get_node_reachability_05(void **state);
67 static bool test_get_node_reachability_05(void);
68 static void test_case_get_node_reachability_06(void **state);
69 static bool test_get_node_reachability_06(void);
70 static void test_case_get_node_reachability_07(void **state);
71 static bool test_get_node_reachability_07(void);
73 /* Node reachable status callback which signals the respective conditional varibale */
74 static void meshlink_node_reachable_status_cb(meshlink_handle_t *mesh, meshlink_node_t *node, bool reachable_status) {
75 if(!strcasecmp(mesh->name, NUT)) {
76 if(!strcasecmp(node->name, PEER)) {
77 peer_reachable_status = reachable_status;
78 set_sync_flag(&peer_reachable_status_cond, true);
80 } else if(!strcasecmp(mesh->name, PEER)) {
81 if(!strcasecmp(node->name, NUT)) {
82 nut_reachable_status = reachable_status;
83 set_sync_flag(&nut_reachable_status_cond, true);
88 static void meshlink_node_reachable_status_cb_2(meshlink_handle_t *mesh, meshlink_node_t *node, bool reachable_status) {
89 meshlink_node_t *peer_handle;
90 char *peer_name = NULL;
91 time_t last_unreachable, last_reachable;
94 if(meshlink_get_self(mesh) == node) {
98 /* Of the 2 node reachable callbacks, the latest callback calls meshlink_get_node_reachability API
99 for the 1st node joined */
100 if(count && reachable_status && !strcasecmp(mesh->name, NUT)) {
104 if(!strcasecmp(node->name, PEER)) {
106 } else if(!strcasecmp(node->name, PEER2)) {
110 peer_handle = meshlink_get_node(mesh, peer_name);
111 assert_non_null(peer_handle);
113 bool status = meshlink_get_node_reachability(mesh, peer_handle, &last_reachable, &last_unreachable);
115 peer_node_callback_test_status = status && last_reachable && !last_unreachable;
116 set_sync_flag(&peer_reachable_status_cond, true);
121 /* SIGUSR2 signal handler that signals the NUT started and PEER node can join */
122 void nut_started_user_signal_handler(int signum) {
123 if(signum == SIGUSR2) {
124 set_sync_flag(&nut_started_status_cond, true);
130 Execute meshlink get last node reachability times feature Test Case # 1 -
133 static void test_case_get_node_reachability_01(void **state) {
134 execute_test(test_get_node_reachability_01, state);
137 /* Test Steps for meshlink_get_node_reachability Test Case # 1
139 Test steps and scenarios:
140 1. Open Node-Under-Test (NUT) instance, Call meshlink_get_node_reachability API
141 with valid mesh handle, self node handle, last_reachable pointer and
142 last_unreachable pointer.
144 API returns self node unreachable, last_reachable and last_unreachable values
147 2. Call meshlink_get_node_reachability API with valid mesh handle, self node handle.
148 But pass NULL pointers for last_reachable and last_unreachable arguments
150 API returns self node unreachable
152 3. Call meshlink_get_node_reachability API with NULL as mesh handle,
153 valid self node handle, last_reachable pointer and last_unreachable pointer.
155 API fails and sets MESHLINK_EINVAL as meshlink errno value
157 4. Call meshlink_get_node_reachability API with NULL as mesh handle,
158 valid self node handle, NULL pointers for last_reachable and last_unreachable
161 API fails and sets MESHLINK_EINVAL as meshlink errno value
163 5. Call meshlink_get_node_reachability API with valid mesh handle,
164 NULL as self node handle, last_reachable pointer and last_unreachable pointer.
166 API fails and sets MESHLINK_EINVAL as meshlink errno value
168 6. Call meshlink_get_node_reachability API with valid mesh handle,
169 NULL as self node handle, NULL pointers for last_reachable and last_unreachable
172 API fails and sets MESHLINK_EINVAL as meshlink errno value
175 static bool test_get_node_reachability_01(void) {
177 time_t last_unreachable, last_reachable;
178 char nut_confbase[PATH_MAX];
179 create_path(nut_confbase, NUT, 1);
181 meshlink_set_log_cb(NULL, MESHLINK_DEBUG, log_cb);
183 // Open Node-Under-Test node instance
185 meshlink_handle_t *mesh = meshlink_open(nut_confbase, NUT, GET_NODE_REACHABILITY, DEV_CLASS_STATIONARY);
186 assert_int_not_equal(mesh, NULL);
188 // Call meshlink_get_node_reachability API with all valid arguments
190 status = meshlink_get_node_reachability(mesh, meshlink_get_self(mesh), &last_reachable, &last_unreachable);
191 assert_int_equal(status, false);
192 assert_int_equal(last_reachable, 0);
193 assert_int_equal(last_unreachable, 0);
195 // Call meshlink_get_node_reachability API with all valid arguments
197 status = meshlink_get_node_reachability(mesh, meshlink_get_self(mesh), NULL, NULL);
198 assert_int_equal(status, false);
200 // Call meshlink_get_node_reachability API with invalid parameters
202 meshlink_errno = MESHLINK_OK;
203 meshlink_get_node_reachability(NULL, meshlink_get_self(mesh), NULL, NULL);
204 assert_int_equal(meshlink_errno, MESHLINK_EINVAL);
205 meshlink_errno = MESHLINK_OK;
206 meshlink_get_node_reachability(NULL, meshlink_get_self(mesh), &last_reachable, &last_unreachable);
207 assert_int_equal(meshlink_errno, MESHLINK_EINVAL);
208 meshlink_errno = MESHLINK_OK;
209 meshlink_get_node_reachability(mesh, NULL, NULL, NULL);
210 assert_int_equal(meshlink_errno, MESHLINK_EINVAL);
211 meshlink_errno = MESHLINK_OK;
212 meshlink_get_node_reachability(mesh, NULL, &last_reachable, &last_unreachable);
213 assert_int_equal(meshlink_errno, MESHLINK_EINVAL);
217 meshlink_close(mesh);
218 assert_true(meshlink_destroy(nut_confbase));
223 Execute meshlink get last node reachability times feature Test Case # 2 -
224 API testing with stand-alone node
226 static void test_case_get_node_reachability_02(void **state) {
227 execute_test(test_get_node_reachability_02, state);
230 /* Test Steps for meshlink_get_node_reachability Test Case # 2
232 Test steps and scenarios:
233 1. Open and start Node-Under-Test (NUT) instance, Call meshlink_get_node_reachability API.
235 API returns self node reachable status, last_reachable as some positive non-zero integer
236 and last_unreachable value as 0 seconds
238 2. Stop the NUT instance, Call meshlink_get_node_reachability API.
240 API returns self node unreachable, both last_reachable and last_unreachable values
241 as some positive non-zero time in seconds
243 3. Close and reopen NUT instance, Call meshlink_get_node_reachability API.
245 API returns self node unreachable, both last_reachable and last_unreachable values
246 as some positive non-zero time in seconds
249 static bool test_get_node_reachability_02(void) {
251 time_t last_unreachable, last_reachable, last_peer_unreachable, last_peer_reachable;
252 char nut_confbase[PATH_MAX];
253 create_path(nut_confbase, NUT, 2);
254 meshlink_set_log_cb(NULL, MESHLINK_DEBUG, log_cb);
256 // Open and start Node-Under-Test node instance
258 meshlink_handle_t *mesh = meshlink_open(nut_confbase, NUT, GET_NODE_REACHABILITY, DEV_CLASS_STATIONARY);
259 assert_non_null(mesh);
260 assert_true(meshlink_start(mesh));
262 // Call meshlink_get_node_reachability API with all valid arguments
264 status = meshlink_get_node_reachability(mesh, meshlink_get_self(mesh), &last_reachable, &last_unreachable);
266 assert_int_not_equal(last_reachable, 0);
267 assert_int_equal(last_unreachable, 0);
268 last_peer_reachable = last_reachable;
270 // Stop NUT node instance
274 // Call meshlink_get_node_reachability API with all valid arguments
276 status = meshlink_get_node_reachability(mesh, meshlink_get_self(mesh), &last_reachable, &last_unreachable);
277 assert_false(status);
278 assert_int_not_equal(last_unreachable, 0);
279 assert_int_equal(last_reachable, last_peer_reachable);
280 last_peer_unreachable = last_unreachable;
282 // Reinitialize NUT node instance
284 meshlink_close(mesh);
285 mesh = meshlink_open(nut_confbase, NUT, GET_NODE_REACHABILITY, DEV_CLASS_STATIONARY);
286 assert_non_null(mesh);
288 // Call meshlink_get_node_reachability API with all valid arguments
290 status = meshlink_get_node_reachability(mesh, meshlink_get_self(mesh), &last_reachable, &last_unreachable);
291 assert_false(status);
292 assert_int_equal(last_reachable, last_peer_reachable);
293 assert_int_equal(last_unreachable, last_peer_unreachable);
297 meshlink_close(mesh);
298 assert_true(meshlink_destroy(nut_confbase));
303 Execute meshlink get last node reachability times feature Test Case # 3 -
304 API testing with host node which already joined with a peer node which later
305 goes offline, test host node with an offline peer node case.
307 static void test_case_get_node_reachability_03(void **state) {
308 execute_test(test_get_node_reachability_03, state);
311 /* Test Steps for meshlink_get_node_reachability Test Case # 3
313 Test steps and scenarios:
314 1. Open Node-Under-Test (NUT) and peer node instance, start peer node instance
315 and invite NUT. NUT joins peer and destroy peer node instance.
316 Call meshlink_get_node_reachability API.
318 API returns peer node unreachable status, last_reachable and last_unreachable
321 2. Start the NUT instance, Call meshlink_get_node_reachability API.
323 API returns peer node unreachable status, last_reachable and last_unreachable
326 3. Stop the NUT instance, Call meshlink_get_node_reachability API.
328 API returns peer node unreachable status, last_reachable and last_unreachable
331 4. Close and reopen NUT instance, Call meshlink_get_node_reachability API.
333 API returns peer node unreachable status, last_reachable and last_unreachable
337 static bool test_get_node_reachability_03(void) {
339 time_t last_unreachable, last_reachable;
340 char nut_confbase[PATH_MAX];
341 char peer_confbase[PATH_MAX];
342 create_path(nut_confbase, NUT, 3);
343 create_path(peer_confbase, PEER, 3);
345 meshlink_set_log_cb(NULL, MESHLINK_DEBUG, log_cb);
347 // Open and start peer node instance, invite NUT.
349 meshlink_handle_t *mesh_peer = meshlink_open(peer_confbase, PEER, GET_NODE_REACHABILITY,
350 DEV_CLASS_STATIONARY);
351 assert_non_null(mesh_peer);
352 assert_true(meshlink_start(mesh_peer));
353 char *invitation = meshlink_invite(mesh_peer, NULL, NUT);
354 assert_non_null(invitation);
356 // Open NUT node instance and join with the peer node
358 meshlink_handle_t *mesh = meshlink_open(nut_confbase, NUT, GET_NODE_REACHABILITY, DEV_CLASS_STATIONARY);
359 assert_non_null(mesh);
360 assert_true(meshlink_join(mesh, invitation));
362 meshlink_node_t *peer_handle = meshlink_get_node(mesh, PEER);
363 assert_non_null(peer_handle);
365 // Cleanup peer node instance
367 meshlink_close(mesh_peer);
368 assert_true(meshlink_destroy(peer_confbase));
370 // Call meshlink_get_node_reachability API with valid arguments
372 status = meshlink_get_node_reachability(mesh, peer_handle, &last_reachable, &last_unreachable);
373 assert_false(status);
374 assert_int_equal(last_reachable, 0);
375 assert_int_equal(last_unreachable, 0);
377 // Start NUT node instance
379 assert_true(meshlink_start(mesh));
381 // Call meshlink_get_node_reachability API with valid arguments
383 status = meshlink_get_node_reachability(mesh, peer_handle, &last_reachable, &last_unreachable);
384 assert_false(status);
385 assert_int_equal(last_reachable, 0);
386 assert_int_equal(last_unreachable, 0);
388 // Stop NUT node instance
392 // Call meshlink_get_node_reachability API with valid arguments
394 status = meshlink_get_node_reachability(mesh, peer_handle, &last_reachable, &last_unreachable);
395 assert_false(status);
396 assert_int_equal(last_reachable, 0);
397 assert_int_equal(last_unreachable, 0);
399 // Reinitialize NUT node instance
401 meshlink_close(mesh);
402 mesh = meshlink_open(nut_confbase, NUT, GET_NODE_REACHABILITY, DEV_CLASS_STATIONARY);
403 assert_non_null(mesh);
404 peer_handle = meshlink_get_node(mesh, PEER);
405 assert_non_null(peer_handle);
407 // Call meshlink_get_node_reachability API with valid arguments
409 status = meshlink_get_node_reachability(mesh, peer_handle, &last_reachable, &last_unreachable);
410 assert_false(status);
411 assert_int_equal(last_reachable, 0);
412 assert_int_equal(last_unreachable, 0);
416 meshlink_close(mesh);
417 assert_true(meshlink_destroy(nut_confbase));
422 Execute meshlink get last node reachability times feature Test Case # 4 -
423 API testing around invited and invitee node.
425 static void test_case_get_node_reachability_04(void **state) {
426 execute_test(test_get_node_reachability_04, state);
429 /* Test Steps for meshlink_get_node_reachability Test Case # 4
431 Test steps and scenarios:
432 1. Open Node-Under-Test (NUT) and peer node instance, join both the node and
433 bring them online. Call meshlink_get_node_reachability API from both the nodes.
435 API for both the nodes returns reachable status, last_reachable should be
436 some non-zero positive seconds and last_unreachable should be 0 seconds.
438 2. Stop both the node instances, Call meshlink_get_node_reachability API from both the nodes.
440 API for both the nodes returns unreachable status. last_reachable should match with
441 the old value and last_unreachable should be non-zero positive value.
443 3. Restart both the node instances, Call meshlink_get_node_reachability APIs.
445 API for both the nodes should return reachable status. last_reachable should not match with
446 the old value, but last_unreachable should remain same
448 4. Close and reopen both the node instances, Call meshlink_get_node_reachability APIs.
450 API returns self node unreachable status, last_reachable should remain same
451 but last_unreachable should vary.
453 4. Start both the node instances, Call meshlink_get_node_reachability APIs.
455 API returns self node reachable status, last_reachable should vary and
456 last_unreachable remains same.
459 static bool test_get_node_reachability_04(void) {
461 time_t last_nut_unreachable, last_nut_reachable;
462 time_t last_peer_unreachable, last_peer_reachable;
463 time_t last_reachable, last_unreachable;
464 char nut_confbase[PATH_MAX];
465 char peer_confbase[PATH_MAX];
466 create_path(nut_confbase, NUT, 4);
467 create_path(peer_confbase, PEER, 4);
468 meshlink_set_log_cb(NULL, MESHLINK_DEBUG, log_cb);
470 // Open both NUT and peer node instance, invite and join NUT with peer node.
472 meshlink_handle_t *mesh_peer = meshlink_open(peer_confbase, PEER, GET_NODE_REACHABILITY,
473 DEV_CLASS_STATIONARY);
474 assert_non_null(mesh_peer);
475 meshlink_set_node_status_cb(mesh_peer, meshlink_node_reachable_status_cb);
476 char *invitation = meshlink_invite(mesh_peer, NULL, NUT);
477 assert_non_null(invitation);
478 assert_true(meshlink_start(mesh_peer));
480 meshlink_handle_t *mesh = meshlink_open(nut_confbase, NUT, GET_NODE_REACHABILITY,
481 DEV_CLASS_STATIONARY);
482 assert_non_null(mesh);
483 meshlink_set_node_status_cb(mesh, meshlink_node_reachable_status_cb);
484 assert_true(meshlink_join(mesh, invitation));
487 meshlink_node_t *peer_handle = meshlink_get_node(mesh, PEER);
488 assert_non_null(peer_handle);
489 meshlink_node_t *nut_handle = meshlink_get_node(mesh_peer, NUT);
490 assert_non_null(nut_handle);
492 // Bring nodes online.
494 set_sync_flag(&peer_reachable_status_cond, false);
495 set_sync_flag(&nut_reachable_status_cond, false);
496 assert_true(meshlink_start(mesh));
497 assert_true(wait_sync_flag(&peer_reachable_status_cond, 60));
498 assert_true(peer_reachable_status);
499 assert_true(wait_sync_flag(&nut_reachable_status_cond, 60));
500 assert_true(nut_reachable_status);
502 // Call meshlink_get_node_reachability API from joined node and also from joining node.
504 status = meshlink_get_node_reachability(mesh, peer_handle, &last_reachable, &last_unreachable);
506 assert_int_not_equal(last_reachable, 0);
507 assert_int_equal(last_unreachable, 0);
508 last_peer_reachable = last_reachable;
510 status = meshlink_get_node_reachability(mesh_peer, nut_handle, &last_reachable, &last_unreachable);
512 assert_int_not_equal(last_reachable, 0);
513 assert_int_equal(last_unreachable, 0);
514 last_nut_reachable = last_reachable;
516 // Stop the node instances of both peer and NUT.
519 meshlink_stop(mesh_peer);
521 // Call meshlink_get_node_reachability API from joined node and also from joining node.
523 status = meshlink_get_node_reachability(mesh, peer_handle, &last_reachable, &last_unreachable);
524 assert_false(status);
525 assert_int_not_equal(last_unreachable, 0);
526 assert_int_equal(last_reachable, last_peer_reachable);
527 last_peer_unreachable = last_unreachable;
529 status = meshlink_get_node_reachability(mesh_peer, nut_handle, &last_reachable, &last_unreachable);
530 assert_false(status);
531 assert_int_not_equal(last_unreachable, 0);
532 assert_int_equal(last_reachable, last_nut_reachable);
533 last_nut_unreachable = last_unreachable;
535 // Restart the node instances of both peer and NUT and wait for nodes to come online
538 set_sync_flag(&peer_reachable_status_cond, false);
539 set_sync_flag(&nut_reachable_status_cond, false);
540 assert_true(meshlink_start(mesh));
541 assert_true(meshlink_start(mesh_peer));
543 assert_true(wait_sync_flag(&peer_reachable_status_cond, 60));
544 assert_true(peer_reachable_status);
545 assert_true(wait_sync_flag(&nut_reachable_status_cond, 60));
546 assert_true(nut_reachable_status);
548 // Call meshlink_get_node_reachability API from joined node and also from joining node.
550 status = meshlink_get_node_reachability(mesh, peer_handle, &last_reachable, &last_unreachable);
552 assert_int_not_equal(last_reachable, last_peer_reachable);
553 assert_int_equal(last_unreachable, last_peer_unreachable);
554 last_peer_reachable = last_reachable;
556 status = meshlink_get_node_reachability(mesh_peer, nut_handle, &last_reachable, &last_unreachable);
558 assert_int_not_equal(last_reachable, last_nut_reachable);
559 assert_int_equal(last_unreachable, last_nut_unreachable);
560 last_nut_reachable = last_reachable;
562 // Reinitialize the node instances of both peer and NUT
564 meshlink_close(mesh);
565 meshlink_close(mesh_peer);
569 mesh = meshlink_open(nut_confbase, NUT, GET_NODE_REACHABILITY, DEV_CLASS_STATIONARY);
570 assert_non_null(mesh);
571 meshlink_set_node_status_cb(mesh, meshlink_node_reachable_status_cb);
572 mesh_peer = meshlink_open(peer_confbase, PEER, GET_NODE_REACHABILITY,
573 DEV_CLASS_STATIONARY);
574 assert_non_null(mesh_peer);
575 meshlink_set_node_status_cb(mesh_peer, meshlink_node_reachable_status_cb);
577 peer_handle = meshlink_get_node(mesh, PEER);
578 assert_non_null(peer_handle);
579 nut_handle = meshlink_get_node(mesh_peer, NUT);
580 assert_non_null(nut_handle);
582 // Call meshlink_get_node_reachability API from joined node and also from joining node.
584 status = meshlink_get_node_reachability(mesh, peer_handle, &last_reachable, &last_unreachable);
585 assert_false(status);
586 assert_int_equal(last_reachable, last_peer_reachable);
587 assert_int_not_equal(last_unreachable, last_peer_unreachable);
588 last_peer_unreachable = last_unreachable;
590 status = meshlink_get_node_reachability(mesh_peer, nut_handle, &last_reachable, &last_unreachable);
591 assert_false(status);
592 assert_int_equal(last_reachable, last_nut_reachable);
593 assert_int_not_equal(last_unreachable, last_nut_unreachable);
594 last_nut_unreachable = last_unreachable;
596 // Restart the node instances of both peer and NUT
598 set_sync_flag(&peer_reachable_status_cond, false);
599 set_sync_flag(&nut_reachable_status_cond, false);
601 assert_true(meshlink_start(mesh));
602 assert_true(meshlink_start(mesh_peer));
604 assert_true(wait_sync_flag(&peer_reachable_status_cond, 60));
605 assert_true(peer_reachable_status);
606 assert_true(wait_sync_flag(&nut_reachable_status_cond, 60));
607 assert_true(nut_reachable_status);
609 // Call meshlink_get_node_reachability API from joined node and also from joining node.
611 status = meshlink_get_node_reachability(mesh, peer_handle, &last_reachable, &last_unreachable);
613 assert_int_not_equal(last_reachable, last_peer_reachable);
614 assert_int_equal(last_unreachable, last_peer_unreachable);
616 status = meshlink_get_node_reachability(mesh_peer, nut_handle, &last_reachable, &last_unreachable);
618 assert_int_not_equal(last_reachable, last_nut_reachable);
619 assert_int_equal(last_unreachable, last_nut_unreachable);
623 meshlink_close(mesh);
624 meshlink_close(mesh_peer);
625 assert_true(meshlink_destroy(nut_confbase));
626 assert_true(meshlink_destroy(peer_confbase));
631 Execute meshlink get last node reachability times feature Test Case # 5 -
632 API testing by calling it in the meshlink callback(s) and also isolation property.
634 static void test_case_get_node_reachability_05(void **state) {
635 execute_test(test_get_node_reachability_05, state);
638 /* Test Steps for meshlink_get_node_reachability Test Case # 5
640 Test steps and scenarios:
641 1. Open Node-Under-Test (NUT), peer and peer2 node instances. Join both the peer nodes
642 with NUT and bring them online.
644 API called from the node reachable callback of the latest peer node from NUT
645 about other peer node which joined 1st should return reachable status,
646 last_reachable status as some positive non-zero value and last unreachable value as 0.
649 static bool test_get_node_reachability_05(void) {
652 time_t last_reachable, last_unreachable;
653 char nut_confbase[PATH_MAX];
654 char peer_confbase[PATH_MAX];
655 char peer2_confbase[PATH_MAX];
656 create_path(nut_confbase, NUT, 5);
657 create_path(peer_confbase, PEER, 5);
658 create_path(peer2_confbase, PEER2, 5);
659 meshlink_set_log_cb(NULL, MESHLINK_DEBUG, log_cb);
661 // Open NUT, peer and peer2 and join peer nodes with NUT.
663 meshlink_handle_t *mesh = meshlink_open(nut_confbase, NUT, GET_NODE_REACHABILITY,
664 DEV_CLASS_STATIONARY);
665 assert_non_null(mesh);
666 meshlink_set_node_status_cb(mesh, meshlink_node_reachable_status_cb_2);
667 meshlink_handle_t *mesh_peer = meshlink_open(peer_confbase, PEER, GET_NODE_REACHABILITY,
668 DEV_CLASS_STATIONARY);
669 assert_non_null(mesh_peer);
670 meshlink_handle_t *mesh_peer2 = meshlink_open(peer2_confbase, PEER2, GET_NODE_REACHABILITY,
671 DEV_CLASS_STATIONARY);
672 assert_non_null(mesh_peer2);
674 assert_true(meshlink_start(mesh));
676 invitation = meshlink_invite(mesh, NULL, PEER);
677 assert_non_null(invitation);
678 assert_true(meshlink_join(mesh_peer, invitation));
679 invitation = meshlink_invite(mesh, NULL, PEER2);
680 assert_non_null(invitation);
681 assert_true(meshlink_join(mesh_peer2, invitation));
683 // Call meshlink_get_node_reachability API from NUT and check they remained 0 and unreachable
685 status = meshlink_get_node_reachability(mesh, meshlink_get_node(mesh, PEER), &last_reachable, &last_unreachable);
686 assert_int_equal(status, false);
687 assert_int_equal(last_reachable, 0);
688 assert_int_equal(last_unreachable, 0);
689 status = meshlink_get_node_reachability(mesh, meshlink_get_node(mesh, PEER2), &last_reachable, &last_unreachable);
690 assert_int_equal(status, false);
691 assert_int_equal(last_reachable, 0);
692 assert_int_equal(last_unreachable, 0);
694 // Start and wait for the signal from the node reachable callback which is raised when
695 // NUT is able to call meshlink_get_node_reachability API from callback of other peer node.
697 set_sync_flag(&peer_reachable_status_cond, false);
698 assert_true(meshlink_start(mesh_peer));
699 assert_true(meshlink_start(mesh_peer2));
700 assert_true(wait_sync_flag(&peer_reachable_status_cond, 60));
701 assert_true(peer_node_callback_test_status);
705 meshlink_close(mesh);
706 meshlink_close(mesh_peer);
707 meshlink_close(mesh_peer2);
708 assert_true(meshlink_destroy(nut_confbase));
709 assert_true(meshlink_destroy(peer_confbase));
710 assert_true(meshlink_destroy(peer2_confbase));
715 Execute meshlink get last node reachability times feature Test Case # 6 -
716 Persistence testing on the joining node.
718 static void test_case_get_node_reachability_06(void **state) {
719 execute_test(test_get_node_reachability_06, state);
722 /* Test Steps for meshlink_get_node_reachability Test Case # 6
724 Test steps and scenarios:
725 1. Open Node-Under-Test (NUT) and invite peer node and close it's instance.
726 Spawn a process which waits for the peer node to join and raises SIGINT if the
727 appropriate callback is received (on the other hand the test suite opens and joins
728 the peer node with NUT in the forked process).
729 Reopen NUT instance in the test suite process and call meshlink_get_node_reachability.
731 API returns peer node unreachable, last_reachable and last_unreachable values
732 as 0 seconds. It is expected that this feature synchronize it at least for the first time
733 when the NUT receives that a new peer node joined.
736 static bool test_get_node_reachability_06(void) {
738 time_t last_reachable, last_unreachable;
741 char nut_confbase[PATH_MAX];
742 char peer_confbase[PATH_MAX];
743 create_path(nut_confbase, NUT, 6);
744 create_path(peer_confbase, PEER, 6);
745 meshlink_set_log_cb(NULL, MESHLINK_DEBUG, log_cb);
747 // Open NUT node instance and invite peer node. Close NUT node instance.
749 meshlink_handle_t *mesh = meshlink_open(nut_confbase, NUT, GET_NODE_REACHABILITY, DEV_CLASS_STATIONARY);
750 assert_non_null(mesh);
751 char *invitation = meshlink_invite(mesh, NULL, PEER);
752 meshlink_close(mesh);
754 // Set the SIGUSR2 signal handler with handler that signal the condition to the test suite
756 sighandler_t usr2sighandler = signal(SIGUSR2, nut_started_user_signal_handler);
757 assert_int_not_equal(usr2sighandler, SIG_ERR);
759 // Fork a new process and run NUT in it which just waits for the peer node reachable status callback
760 // and terminates the process immediately.
763 assert_int_not_equal(pid, -1);
766 assert(signal(SIGUSR2, SIG_DFL) != SIG_ERR);
768 mesh = meshlink_open(nut_confbase, NUT, GET_NODE_REACHABILITY, DEV_CLASS_STATIONARY);
770 meshlink_set_log_cb(mesh, MESHLINK_DEBUG, log_cb);
771 meshlink_set_node_status_cb(mesh, meshlink_node_reachable_status_cb);
773 set_sync_flag(&peer_reachable_status_cond, false);
774 assert(meshlink_start(mesh));
776 assert(kill(getppid(), SIGUSR2) != -1);
778 assert(wait_sync_flag(&peer_reachable_status_cond, 60));
779 assert(peer_reachable_status);
784 // Open peer node instance and join with the invitation obtained.
786 meshlink_handle_t *mesh_peer = meshlink_open(peer_confbase, PEER, GET_NODE_REACHABILITY,
787 DEV_CLASS_STATIONARY);
788 assert_non_null(mesh_peer);
790 // Wait for the started signal from NUT and reset the previous SIGUSR2 signal handler
792 assert_true(wait_sync_flag(&nut_started_status_cond, 60));
793 assert_int_not_equal(signal(SIGUSR2, usr2sighandler), SIG_ERR);
795 assert_true(meshlink_join(mesh_peer, invitation));
796 assert_true(meshlink_start(mesh_peer));
798 // Wait for child exit and verify which signal terminated it
800 assert_int_not_equal(waitpid(pid, &pid_status, 0), -1);
801 assert_int_equal(WIFSIGNALED(pid_status), true);
802 assert_int_equal(WTERMSIG(pid_status), SIGINT);
804 // Reopen the NUT instance in the same test suite
806 mesh = meshlink_open(nut_confbase, NUT, GET_NODE_REACHABILITY, DEV_CLASS_STATIONARY);
807 assert_non_null(mesh);
809 // Call meshlink_get_node_reachability API and verify that the time stamps has persisted.
811 status = meshlink_get_node_reachability(mesh, meshlink_get_node(mesh, PEER), &last_reachable, &last_unreachable);
812 assert_int_equal(status, false);
813 assert_int_not_equal(last_reachable, 0);
814 assert_int_equal(last_unreachable, 0);
818 meshlink_close(mesh);
819 meshlink_close(mesh_peer);
820 assert_true(meshlink_destroy(nut_confbase));
821 assert_true(meshlink_destroy(peer_confbase));
826 Execute meshlink get last node reachability times feature Test Case # 7 -
827 Persistence testing on the invited node.
829 static void test_case_get_node_reachability_07(void **state) {
830 execute_test(test_get_node_reachability_07, state);
833 /* Test Steps for meshlink_get_node_reachability Test Case # 7
835 Test steps and scenarios:
836 1. Open peer node instance, invite NUT and start peer node. Spawn a new process in
837 which it opens and joins the NUT with peer node.
838 Reopen NUT instance in the test suite process and call meshlink_get_node_reachability API.
840 API returns peer node unreachable, last_reachable and last_unreachable values
841 as 0 seconds. It is expected that this feature synchronize it at least for the first time
842 when the Node-Under-Test joined with the peer node.
845 static bool test_get_node_reachability_07(void) {
847 time_t last_reachable, last_unreachable;
850 char nut_confbase[PATH_MAX];
851 char peer_confbase[PATH_MAX];
852 create_path(nut_confbase, NUT, 7);
853 create_path(peer_confbase, PEER, 7);
854 meshlink_set_log_cb(NULL, MESHLINK_DEBUG, log_cb);
856 // Open peer node instance and invite NUT.
858 meshlink_handle_t *mesh_peer = meshlink_open(peer_confbase, PEER, GET_NODE_REACHABILITY,
859 DEV_CLASS_STATIONARY);
860 assert_int_not_equal(mesh_peer, NULL);
861 char *invitation = meshlink_invite(mesh_peer, NULL, NUT);
862 assert_non_null(invitation);
864 assert_true(meshlink_start(mesh_peer));
866 // Fork a new process in which NUT is joins with the peer node and raises SIGINT to terminate.
869 assert_int_not_equal(pid, -1);
872 meshlink_handle_t *mesh = meshlink_open(nut_confbase, NUT, GET_NODE_REACHABILITY, DEV_CLASS_STATIONARY);
874 meshlink_set_log_cb(mesh, MESHLINK_DEBUG, log_cb);
876 assert(meshlink_join(mesh, invitation));
881 // Wait for child exit and verify which signal terminated it
883 assert_int_not_equal(waitpid(pid, &pid_status, 0), -1);
884 assert_int_equal(WIFSIGNALED(pid_status), true);
885 assert_int_equal(WTERMSIG(pid_status), SIGINT);
887 // Reopen the NUT instance in the same test suite
889 meshlink_handle_t *mesh = meshlink_open(nut_confbase, NUT, GET_NODE_REACHABILITY, DEV_CLASS_STATIONARY);
890 assert_non_null(mesh);
892 // Call meshlink_get_node_reachability API and verify that the time stamps has persisted.
894 status = meshlink_get_node_reachability(mesh, meshlink_get_node(mesh, PEER), &last_reachable, &last_unreachable);
895 assert_int_equal(status, false);
896 assert_int_equal(last_reachable, 0);
897 assert_int_equal(last_unreachable, 0);
901 meshlink_close(mesh);
902 meshlink_close(mesh_peer);
903 assert_true(meshlink_destroy(nut_confbase));
904 assert_true(meshlink_destroy(peer_confbase));
908 int test_get_node_reachability(void) {
909 /* State structures for get node reachability Test Cases */
910 black_box_state_t test_case_get_node_reachability_01_state = {
911 .test_case_name = "test_case_get_node_reachability_01",
913 black_box_state_t test_case_get_node_reachability_02_state = {
914 .test_case_name = "test_case_get_node_reachability_02",
916 black_box_state_t test_case_get_node_reachability_03_state = {
917 .test_case_name = "test_case_get_node_reachability_03",
919 black_box_state_t test_case_get_node_reachability_04_state = {
920 .test_case_name = "test_case_get_node_reachability_04",
922 black_box_state_t test_case_get_node_reachability_05_state = {
923 .test_case_name = "test_case_get_node_reachability_05",
925 black_box_state_t test_case_get_node_reachability_06_state = {
926 .test_case_name = "test_case_get_node_reachability_06",
928 black_box_state_t test_case_get_node_reachability_07_state = {
929 .test_case_name = "test_case_get_node_reachability_07",
932 const struct CMUnitTest blackbox_status_tests[] = {
933 cmocka_unit_test_prestate_setup_teardown(test_case_get_node_reachability_01, NULL, NULL,
934 (void *)&test_case_get_node_reachability_01_state),
935 cmocka_unit_test_prestate_setup_teardown(test_case_get_node_reachability_02, NULL, NULL,
936 (void *)&test_case_get_node_reachability_02_state),
937 cmocka_unit_test_prestate_setup_teardown(test_case_get_node_reachability_03, NULL, NULL,
938 (void *)&test_case_get_node_reachability_03_state),
939 cmocka_unit_test_prestate_setup_teardown(test_case_get_node_reachability_04, NULL, NULL,
940 (void *)&test_case_get_node_reachability_04_state),
941 cmocka_unit_test_prestate_setup_teardown(test_case_get_node_reachability_05, NULL, NULL,
942 (void *)&test_case_get_node_reachability_05_state),
943 cmocka_unit_test_prestate_setup_teardown(test_case_get_node_reachability_06, NULL, NULL,
944 (void *)&test_case_get_node_reachability_06_state),
945 cmocka_unit_test_prestate_setup_teardown(test_case_get_node_reachability_07, NULL, NULL,
946 (void *)&test_case_get_node_reachability_07_state),
948 total_tests += sizeof(blackbox_status_tests) / sizeof(blackbox_status_tests[0]);
950 return cmocka_run_group_tests(blackbox_status_tests, NULL, NULL);