]> git.meshlink.io Git - meshlink/blob - test/get-all-nodes.c
Fix potential NULL pointer dereference.
[meshlink] / test / get-all-nodes.c
1 #ifdef NDEBUG
2 #undef NDEBUG
3 #endif
4
5 #include <stdio.h>
6 #include <unistd.h>
7 #include <stdlib.h>
8 #include <string.h>
9 #include <sys/time.h>
10 #include <time.h>
11 #include <assert.h>
12
13 #include "meshlink.h"
14 #include "utils.h"
15
16 static struct sync_flag bar_reachable;
17
18 static void status_cb(meshlink_handle_t *mesh, meshlink_node_t *node, bool reachable) {
19         (void)mesh;
20
21         if(reachable && !strcmp(node->name, "bar")) {
22                 set_sync_flag(&bar_reachable, true);
23         }
24 }
25
26 int main(void) {
27         init_sync_flag(&bar_reachable);
28
29         struct meshlink_node **nodes = NULL;
30         size_t nnodes = 0;
31
32         meshlink_set_log_cb(NULL, MESHLINK_DEBUG, log_cb);
33
34         // Open new meshlink instances.
35
36         assert(meshlink_destroy("get_all_nodes_conf.1"));
37         assert(meshlink_destroy("get_all_nodes_conf.2"));
38         assert(meshlink_destroy("get_all_nodes_conf.3"));
39
40         meshlink_handle_t *mesh[3];
41         mesh[0] = meshlink_open("get_all_nodes_conf.1", "foo", "get-all-nodes", DEV_CLASS_BACKBONE);
42         assert(mesh[0]);
43
44         mesh[1] = meshlink_open("get_all_nodes_conf.2", "bar", "get-all-nodes", DEV_CLASS_STATIONARY);
45         assert(mesh[1]);
46
47         mesh[2] = meshlink_open("get_all_nodes_conf.3", "baz", "get-all-nodes", DEV_CLASS_STATIONARY);
48         assert(mesh[2]);
49
50         // Check that we only know about ourself.
51
52         nodes = meshlink_get_all_nodes(mesh[0], nodes, &nnodes);
53         assert(nnodes == 1);
54         assert(nodes[0] == meshlink_get_self(mesh[0]));
55
56         // We should never have been online.
57
58         nodes = meshlink_get_all_nodes_by_last_reachable(mesh[0], 0, -1, nodes, &nnodes);
59         assert(nnodes == 0);
60
61         nodes = meshlink_get_all_nodes_by_last_reachable(mesh[0], 0, 0, nodes, &nnodes);
62         assert(nnodes == 1);
63         assert(nodes[0] == meshlink_get_self(mesh[0]));
64
65         // Let nodes know about each other.
66
67         for(int i = 0; i < 3; i++) {
68                 meshlink_enable_discovery(mesh[i], false);
69                 assert(meshlink_set_canonical_address(mesh[i], meshlink_get_self(mesh[i]), "localhost", NULL));
70                 char *data = meshlink_export(mesh[i]);
71                 assert(data);
72
73                 for(int j = 0; j < 3; j++) {
74                         if(i == j) {
75                                 continue;
76                         }
77
78                         assert(meshlink_import(mesh[j], data));
79                 }
80         }
81
82         // We should know about all nodes now, and their device class.
83
84         nodes = meshlink_get_all_nodes(mesh[0], nodes, &nnodes);
85         assert(nnodes == 3);
86
87         nodes = meshlink_get_all_nodes_by_dev_class(mesh[0], DEV_CLASS_BACKBONE, nodes, &nnodes);
88         assert(nnodes == 1);
89         assert(nodes[0] == meshlink_get_self(mesh[0]));
90
91         nodes = meshlink_get_all_nodes_by_dev_class(mesh[0], DEV_CLASS_STATIONARY, nodes, &nnodes);
92         assert(nnodes == 2);
93
94         // But no node should have been online.
95
96         nodes = meshlink_get_all_nodes_by_last_reachable(mesh[0], 0, -1, nodes, &nnodes);
97         assert(nnodes == 0);
98
99         nodes = meshlink_get_all_nodes_by_last_reachable(mesh[0], 0, 0, nodes, &nnodes);
100         assert(nnodes == 3);
101
102         // Start foo.
103
104         time_t foo_started = time(NULL);
105         assert(meshlink_start(mesh[0]));
106
107         nodes = meshlink_get_all_nodes_by_last_reachable(mesh[0], 0, -1, nodes, &nnodes);
108         assert(nnodes == 1);
109         assert(nodes[0] == meshlink_get_self(mesh[0]));
110
111         nodes = meshlink_get_all_nodes_by_last_reachable(mesh[0], 0, 0, nodes, &nnodes);
112         assert(nnodes == 2);
113
114         nodes = meshlink_get_all_nodes_by_last_reachable(mesh[0], foo_started - 1, -1, nodes, &nnodes);
115         assert(nnodes == 1);
116         assert(nodes[0] == meshlink_get_self(mesh[0]));
117
118         nodes = meshlink_get_all_nodes_by_last_reachable(mesh[0], 1, foo_started - 1, nodes, &nnodes);
119         assert(nnodes == 0);
120
121         nodes = meshlink_get_all_nodes_by_last_reachable(mesh[0], 1, foo_started + 1, nodes, &nnodes);
122         assert(nnodes == 1);
123         assert(nodes[0] == meshlink_get_self(mesh[0]));
124
125         // Start bar and wait for it to connect.
126
127         meshlink_set_node_status_cb(mesh[0], status_cb);
128
129         sleep(2);
130         assert(meshlink_start(mesh[1]));
131         assert(wait_sync_flag(&bar_reachable, 20));
132         time_t bar_started = time(NULL);
133
134         // Validate time ranges.
135
136         nodes = meshlink_get_all_nodes_by_last_reachable(mesh[0], 0, -1, nodes, &nnodes);
137         assert(nnodes == 2);
138
139         nodes = meshlink_get_all_nodes_by_last_reachable(mesh[0], 0, 0, nodes, &nnodes);
140         assert(nnodes == 1);
141         assert(nodes[0] == meshlink_get_node(mesh[0], "baz"));
142
143         nodes = meshlink_get_all_nodes_by_last_reachable(mesh[0], 1, foo_started + 1, nodes, &nnodes);
144         assert(nnodes == 1);
145         assert(nodes[0] == meshlink_get_self(mesh[0]));
146
147         nodes = meshlink_get_all_nodes_by_last_reachable(mesh[0], bar_started, bar_started, nodes, &nnodes);
148         assert(nnodes == 2);
149         assert(nodes[0] == meshlink_get_node(mesh[0], "bar"));
150         assert(nodes[1] == meshlink_get_self(mesh[0]));
151
152         // Stop bar.
153
154         meshlink_stop(mesh[1]);
155         sleep(2);
156         time_t bar_stopped = time(NULL);
157
158         // Validate we can see when bar was reachable.
159
160         nodes = meshlink_get_all_nodes_by_last_reachable(mesh[0], bar_stopped, bar_stopped, nodes, &nnodes);
161         assert(nnodes == 1);
162         assert(nodes[0] == meshlink_get_self(mesh[0]));
163
164         nodes = meshlink_get_all_nodes_by_last_reachable(mesh[0], bar_started, bar_started, nodes, &nnodes);
165         assert(nnodes == 2);
166         assert(nodes[0] == meshlink_get_node(mesh[0], "bar"));
167         assert(nodes[1] == meshlink_get_self(mesh[0]));
168
169         // Close and restart foo, check that it remembers correctly.
170
171         meshlink_close(mesh[0]);
172         sleep(2);
173         time_t foo_stopped = time(NULL);
174         mesh[0] = meshlink_open("get_all_nodes_conf.1", "foo", "get-all_nodes", DEV_CLASS_BACKBONE);
175         assert(mesh[0]);
176
177         nodes = meshlink_get_all_nodes(mesh[0], nodes, &nnodes);
178         assert(nnodes == 3);
179
180         nodes = meshlink_get_all_nodes_by_dev_class(mesh[0], DEV_CLASS_BACKBONE, nodes, &nnodes);
181         assert(nnodes == 1);
182         assert(nodes[0] == meshlink_get_self(mesh[0]));
183
184         nodes = meshlink_get_all_nodes_by_dev_class(mesh[0], DEV_CLASS_STATIONARY, nodes, &nnodes);
185         assert(nnodes == 2);
186
187         nodes = meshlink_get_all_nodes_by_last_reachable(mesh[0], 0, 0, nodes, &nnodes);
188         assert(nnodes == 1);
189         assert(nodes[0] == meshlink_get_node(mesh[0], "baz"));
190
191         nodes = meshlink_get_all_nodes_by_last_reachable(mesh[0], 0, -1, nodes, &nnodes);
192         assert(nnodes == 2);
193
194         nodes = meshlink_get_all_nodes_by_last_reachable(mesh[0], 1, foo_started - 1, nodes, &nnodes);
195         assert(nnodes == 0);
196
197         nodes = meshlink_get_all_nodes_by_last_reachable(mesh[0], 1, foo_started + 1, nodes, &nnodes);
198         assert(nnodes == 1);
199         assert(nodes[0] == meshlink_get_self(mesh[0]));
200
201         nodes = meshlink_get_all_nodes_by_last_reachable(mesh[0], bar_started, bar_started, nodes, &nnodes);
202         assert(nnodes == 2);
203         assert(nodes[0] == meshlink_get_node(mesh[0], "bar"));
204         assert(nodes[1] == meshlink_get_self(mesh[0]));
205
206         nodes = meshlink_get_all_nodes_by_last_reachable(mesh[0], bar_stopped, bar_stopped, nodes, &nnodes);
207         assert(nnodes == 1);
208         assert(nodes[0] == meshlink_get_self(mesh[0]));
209
210         nodes = meshlink_get_all_nodes_by_last_reachable(mesh[0], foo_stopped, -1, nodes, &nnodes);
211         assert(nnodes == 0);
212
213         // Clean up.
214
215         for(int i = 0; i < 3; i++) {
216                 meshlink_close(mesh[i]);
217         }
218 }