]> git.meshlink.io Git - meshlink/blob - test/blacklist.c
Don't use assert() to check the results of pthread_*() calls.
[meshlink] / test / blacklist.c
1 #define _GNU_SOURCE
2
3 #ifdef NDEBUG
4 #undef NDEBUG
5 #endif
6
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <string.h>
10 #include <unistd.h>
11 #include <errno.h>
12 #include <assert.h>
13 #include <sys/time.h>
14
15 #include "meshlink.h"
16 #include "devtools.h"
17 #include "utils.h"
18
19 static struct sync_flag bar_connected;
20 static struct sync_flag bar_disconnected;
21 static struct sync_flag baz_connected;
22
23 static void foo_status_cb(meshlink_handle_t *mesh, meshlink_node_t *node, bool reachable) {
24         (void)mesh;
25         (void)reachable;
26
27         if(!strcmp(node->name, "bar")) {
28                 if(reachable) {
29                         set_sync_flag(&bar_connected, true);
30                 } else {
31                         set_sync_flag(&bar_disconnected, true);
32                 }
33         }
34 }
35
36 static void baz_status_cb(meshlink_handle_t *mesh, meshlink_node_t *node, bool reachable) {
37         (void)mesh;
38         (void)reachable;
39
40         if(!strcmp(node->name, "bar")) {
41                 if(reachable) {
42                         set_sync_flag(&baz_connected, true);
43                 }
44         }
45 }
46
47 int main(void) {
48         init_sync_flag(&bar_connected);
49         init_sync_flag(&bar_disconnected);
50         init_sync_flag(&baz_connected);
51
52         meshlink_set_log_cb(NULL, MESHLINK_DEBUG, log_cb);
53
54         // Create three instances.
55
56         const char *name[3] = {"foo", "bar", "baz"};
57         meshlink_handle_t *mesh[3];
58         char *data[3];
59
60         for(int i = 0; i < 3; i++) {
61                 char *path = NULL;
62                 assert(asprintf(&path, "blacklist_conf.%d", i) != -1 && path);
63
64                 assert(meshlink_destroy(path));
65                 mesh[i] = meshlink_open(path, name[i], "blacklist", DEV_CLASS_BACKBONE);
66                 assert(mesh[i]);
67                 free(path);
68
69                 assert(meshlink_set_canonical_address(mesh[i], meshlink_get_self(mesh[i]), "localhost", NULL));
70
71                 data[i] = meshlink_export(mesh[i]);
72                 assert(data[i]);
73
74                 // Enable default blacklist on all nodes.
75                 meshlink_set_default_blacklist(mesh[i], true);
76         }
77
78         // The first node knows the two other nodes.
79
80         for(int i = 1; i < 3; i++) {
81                 assert(meshlink_import(mesh[i], data[0]));
82                 assert(meshlink_import(mesh[0], data[i]));
83
84                 assert(meshlink_get_node(mesh[i], name[0]));
85                 assert(meshlink_get_node(mesh[0], name[i]));
86
87         }
88
89         for(int i = 0; i < 3; i++) {
90                 free(data[i]);
91         }
92
93         // Second and third node should not know each other yet.
94
95         assert(!meshlink_get_node(mesh[1], name[2]));
96         assert(!meshlink_get_node(mesh[2], name[1]));
97
98         // Whitelisting and blacklisting by name should work.
99
100         assert(meshlink_whitelist_by_name(mesh[0], "quux"));
101         assert(meshlink_blacklist_by_name(mesh[0], "xyzzy"));
102
103         // Since these nodes now exist we should be able to forget them.
104
105         assert(meshlink_forget_node(mesh[0], meshlink_get_node(mesh[0], "quux")));
106
107         // Start the nodes.
108
109         meshlink_set_node_status_cb(mesh[0], foo_status_cb);
110         meshlink_set_node_status_cb(mesh[2], baz_status_cb);
111
112         for(int i = 0; i < 3; i++) {
113                 assert(meshlink_start(mesh[i]));
114         }
115
116         // Wait for them to connect.
117
118         assert(wait_sync_flag(&bar_connected, 5));
119
120         // Blacklist bar
121
122         set_sync_flag(&bar_disconnected, false);
123         assert(meshlink_blacklist(mesh[0], meshlink_get_node(mesh[0], name[1])));
124         assert(wait_sync_flag(&bar_disconnected, 5));
125
126         // Whitelist bar
127
128         set_sync_flag(&bar_connected, false);
129         assert(meshlink_whitelist(mesh[0], meshlink_get_node(mesh[0], name[1])));
130         assert(wait_sync_flag(&bar_connected, 15));
131
132         // Bar should not connect to baz
133
134         assert(wait_sync_flag(&baz_connected, 5) == false);
135
136         // But it should know about baz by now
137
138         meshlink_node_t *bar = meshlink_get_node(mesh[2], "bar");
139         meshlink_node_t *baz = meshlink_get_node(mesh[1], "baz");
140         assert(bar);
141         assert(baz);
142
143         // Have bar and baz whitelist each other
144
145         assert(meshlink_whitelist(mesh[1], baz));
146         assert(meshlink_whitelist(mesh[2], bar));
147
148         // They should connect to each other
149
150         assert(wait_sync_flag(&baz_connected, 15));
151
152         // Trying to forget an active node should fail.
153
154         assert(!meshlink_forget_node(mesh[1], baz));
155
156         // We need to re-acquire the handle to baz
157
158         baz = meshlink_get_node(mesh[1], "baz");
159         assert(baz);
160
161         // Stop the mesh.
162
163         for(int i = 0; i < 3; i++) {
164                 meshlink_stop(mesh[i]);
165         }
166
167         // Forgetting a node should work now.
168
169         assert(meshlink_forget_node(mesh[1], baz));
170
171         // Clean up.
172
173         for(int i = 0; i < 3; i++) {
174                 meshlink_close(mesh[i]);
175         }
176
177         // Check that foo has a config file for xyzzy but not quux
178         assert(access("blacklist_conf.0/current/hosts/xyzzy", F_OK) == 0);
179         assert(access("blacklist_conf.0/current/hosts/quux", F_OK) != 0 && errno == ENOENT);
180
181         // Check that bar has no config file for baz
182         assert(access("blacklist_conf.2/current/hosts/bar", F_OK) == 0);
183         assert(access("blacklist_conf.1/current/hosts/baz", F_OK) != 0 && errno == ENOENT);
184
185         // Check that we remember xyzzy but not quux after reopening the mesh
186         mesh[0] = meshlink_open("blacklist_conf.0", "foo", "blacklist", DEV_CLASS_BACKBONE);
187         assert(mesh[0]);
188         assert(meshlink_get_node(mesh[0], "xyzzy"));
189         assert(!meshlink_get_node(mesh[0], "quux"));
190
191         meshlink_close(mesh[0]);
192 }