fd1b067941409c6407e9a436dadab1ae0d7c90dc
[metze/samba/wip.git] / ctdb / tests / src / protocol_util_test.c
1 /*
2    protocol utilities tests
3
4    Copyright (C) Martin Schwenke  2016
5
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 3 of the License, or
9    (at your option) any later version.
10
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include "replace.h"
21 #include "system/network.h"
22
23 #include <assert.h>
24
25 #include "protocol/protocol_basic.c"
26 #include "protocol/protocol_types.c"
27 #include "protocol/protocol_util.c"
28
29 /*
30  * Test parsing of IPs, conversion to string
31  */
32
33 static void test_sock_addr_to_string(const char *ip, bool with_port)
34 {
35         ctdb_sock_addr sa;
36         const char *s;
37         int ret;
38
39         ret = ctdb_sock_addr_from_string(ip, &sa, with_port);
40         assert(ret == 0);
41         s = ctdb_sock_addr_to_string(NULL, &sa, with_port);
42         assert(strcmp(ip, s) == 0);
43         talloc_free(discard_const(s));
44 }
45
46 static void test_sock_addr_from_string_bad(const char *ip, bool with_port)
47 {
48         ctdb_sock_addr sa;
49         int ret;
50
51         ret = ctdb_sock_addr_from_string(ip, &sa, with_port);
52         assert(ret != 0);
53 }
54
55 static void test_sock_addr_cmp(const char *ip1, const char *ip2,
56                                bool with_port, int res)
57 {
58         ctdb_sock_addr sa1, sa2;
59         int ret;
60
61         ret = ctdb_sock_addr_from_string(ip1, &sa1, with_port);
62         assert(ret == 0);
63         ret = ctdb_sock_addr_from_string(ip2, &sa2, with_port);
64         assert(ret == 0);
65         ret = ctdb_sock_addr_cmp(&sa1, &sa2);
66         if (ret < 0) {
67                 ret = -1;
68         } else if (ret > 0) {
69                 ret = 1;
70         }
71
72         assert(ret == res);
73 }
74
75 /*
76  * Test parsing of connection, conversion to string
77  */
78
79 static void test_connection_to_string(const char *conn_str)
80 {
81         TALLOC_CTX *tmp_ctx;
82         struct ctdb_connection conn;
83         const char *s, *r;
84         int ret;
85
86         tmp_ctx = talloc_new(NULL);
87         assert(tmp_ctx != NULL);
88
89         /*
90          * Test non-reversed parse and render
91          */
92
93         ret = ctdb_connection_from_string(conn_str, false, &conn);
94         assert(ret == 0);
95
96         s = ctdb_connection_to_string(tmp_ctx, &conn, false);
97         assert(s != NULL);
98         ret = strcmp(conn_str, s);
99         assert(ret == 0);
100
101         talloc_free(discard_const(s));
102
103         /*
104          * Reversed render
105          */
106         r = ctdb_connection_to_string(tmp_ctx, &conn, true);
107         assert(r != NULL);
108         ret = strcmp(conn_str, r);
109         assert(ret != 0);
110
111         /*
112          * Reversed parse with forward render
113          */
114         ret = ctdb_connection_from_string(conn_str, true, &conn);
115         assert(ret == 0);
116
117         s = ctdb_connection_to_string(tmp_ctx, &conn, false);
118         assert(s != NULL);
119         ret = strcmp(r, s);
120         assert(ret == 0);
121
122         talloc_free(discard_const(s));
123
124         /*
125          * Reversed parse and render
126          */
127         ret = ctdb_connection_from_string(conn_str, true, &conn);
128         assert(ret == 0);
129
130         s = ctdb_connection_to_string(tmp_ctx, &conn, true);
131         assert(s != NULL);
132         ret = strcmp(conn_str, s);
133         assert(ret == 0);
134
135         talloc_free(tmp_ctx);
136 }
137
138 static void test_connection_from_string_bad(const char *conn_str)
139 {
140         struct ctdb_connection conn;
141         int ret;
142
143         ret = ctdb_connection_from_string(conn_str, false, &conn);
144         assert(ret != 0);
145 }
146
147 /*
148  * Test connection list utilities
149  */
150
151 static void test_connection_list_read(const char *s1, const char *s2)
152 {
153         TALLOC_CTX *tmp_ctx;
154         int pipefd[2];
155         pid_t pid;
156         struct ctdb_connection_list *conn_list;
157         const char *t;
158         int ret;
159
160         tmp_ctx = talloc_new(NULL);
161         assert(tmp_ctx != NULL);
162
163         ret = pipe(pipefd);
164         assert(ret == 0);
165
166         pid = fork();
167         assert(pid != -1);
168
169         if (pid == 0) {
170                 close(pipefd[0]);
171
172                 ret = dup2(pipefd[1], STDOUT_FILENO);
173                 assert(ret != -1);
174
175                 close(pipefd[1]);
176
177                 printf("%s", s1);
178                 fflush(stdout);
179
180                 exit(0);
181         }
182
183         close(pipefd[1]);
184
185         ret = dup2(pipefd[0], STDIN_FILENO);
186         assert(ret != -1);
187
188         close(pipefd[0]);
189
190         ret = ctdb_connection_list_read(tmp_ctx, false, &conn_list);
191         assert(ret == 0);
192
193         ret = ctdb_connection_list_sort(conn_list);
194         assert(ret == 0);
195
196         t = ctdb_connection_list_to_string(tmp_ctx, conn_list, false);
197         assert(t != NULL);
198         ret = strcmp(t, s2);
199         assert(ret == 0);
200
201         talloc_free(tmp_ctx);
202 }
203
204 static void test_connection_list_read_bad(const char *s1)
205 {
206         TALLOC_CTX *tmp_ctx;
207         int pipefd[2];
208         pid_t pid;
209         struct ctdb_connection_list *conn_list;
210         int ret;
211
212         tmp_ctx = talloc_new(NULL);
213         assert(tmp_ctx != NULL);
214
215         ret = pipe(pipefd);
216         assert(ret == 0);
217
218         pid = fork();
219         assert(pid != -1);
220
221         if (pid == 0) {
222                 close(pipefd[0]);
223
224                 ret = dup2(pipefd[1], STDOUT_FILENO);
225                 assert(ret != -1);
226
227                 close(pipefd[1]);
228
229                 printf("%s", s1);
230                 fflush(stdout);
231
232                 exit(0);
233         }
234
235         close(pipefd[1]);
236
237         ret = dup2(pipefd[0], STDIN_FILENO);
238         assert(ret != -1);
239
240         close(pipefd[0]);
241
242         ret = ctdb_connection_list_read(tmp_ctx, false, &conn_list);
243         assert(ret != 0);
244
245         talloc_free(tmp_ctx);
246 }
247
248 /*
249  * Use macros for these to make them easy to concatenate
250  */
251
252 #define CONN4 \
253 "\
254 127.0.0.1:12345 127.0.0.2:54321\n\
255 127.0.0.2:12345 127.0.0.1:54322\n\
256 127.0.0.1:12346 127.0.0.2:54323\n\
257 127.0.0.2:12345 127.0.0.1:54324\n\
258 127.0.0.1:12345 127.0.0.2:54325\n\
259 "
260
261 #define CONN4_SORT \
262 "\
263 127.0.0.1:12345 127.0.0.2:54321\n\
264 127.0.0.1:12345 127.0.0.2:54325\n\
265 127.0.0.1:12346 127.0.0.2:54323\n\
266 127.0.0.2:12345 127.0.0.1:54322\n\
267 127.0.0.2:12345 127.0.0.1:54324\n\
268 "
269
270 #define CONN6 \
271 "\
272 fe80::6af7:28ff:fefa:d136:12345 fe80::6af7:28ff:fefa:d137:54321\n\
273 fe80::6af7:28ff:fefa:d138:12345 fe80::6af7:28ff:fefa:d137:54322\n\
274 fe80::6af7:28ff:fefa:d136:12346 fe80::6af7:28ff:fefa:d137:54323\n\
275 fe80::6af7:28ff:fefa:d132:12345 fe80::6af7:28ff:fefa:d137:54324\n\
276 fe80::6af7:28ff:fefa:d136:12345 fe80::6af7:28ff:fefa:d137:54325\n\
277 "
278
279 #define CONN6_SORT \
280 "\
281 fe80::6af7:28ff:fefa:d132:12345 fe80::6af7:28ff:fefa:d137:54324\n\
282 fe80::6af7:28ff:fefa:d136:12345 fe80::6af7:28ff:fefa:d137:54321\n\
283 fe80::6af7:28ff:fefa:d136:12345 fe80::6af7:28ff:fefa:d137:54325\n\
284 fe80::6af7:28ff:fefa:d136:12346 fe80::6af7:28ff:fefa:d137:54323\n\
285 fe80::6af7:28ff:fefa:d138:12345 fe80::6af7:28ff:fefa:d137:54322\n\
286 "
287
288 int main(int argc, char *argv[])
289 {
290         test_sock_addr_to_string("0.0.0.0", false);
291         test_sock_addr_to_string("127.0.0.1", false);
292         test_sock_addr_to_string("::1", false);
293         test_sock_addr_to_string("192.168.2.1", false);
294         test_sock_addr_to_string("fe80::6af7:28ff:fefa:d136", false);
295
296         test_sock_addr_to_string("0.0.0.0:0", true);
297         test_sock_addr_to_string("127.0.0.1:123", true);
298         test_sock_addr_to_string("::1:234", true);
299         test_sock_addr_to_string("192.168.2.1:123", true);
300         test_sock_addr_to_string("fe80::6af7:28ff:fefa:d136:234", true);
301
302         test_sock_addr_from_string_bad("0.0.0", false);
303         test_sock_addr_from_string_bad("0.0.0:0", true);
304         test_sock_addr_from_string_bad("fe80::6af7:28ff:fefa:d136", true);
305         test_sock_addr_from_string_bad("junk", false);
306         test_sock_addr_from_string_bad("0.0.0.0:0 trailing junk", true);
307
308         test_sock_addr_cmp("127.0.0.1", "127.0.0.1" , false, 0);
309         test_sock_addr_cmp("127.0.0.1", "127.0.0.2" , false, -1);
310         test_sock_addr_cmp("127.0.0.2", "127.0.0.1" , false, 1);
311         test_sock_addr_cmp("127.0.1.2", "127.0.2.1" , false, -1);
312         test_sock_addr_cmp("127.0.2.1", "127.0.1.2" , false, 1);
313         test_sock_addr_cmp("fe80::6af7:28ff:fefa:d136", "127.0.1.2" , false, 1);
314         test_sock_addr_cmp("fe80::6af7:28ff:fefa:d136",
315                            "fe80::6af7:28ff:fefa:d136" , false, 0);
316         test_sock_addr_cmp("fe80::6af7:28ff:fefa:d136",
317                            "fe80::6af7:28ff:fefa:d137" , false, -1);
318         test_sock_addr_cmp("fe80::6af7:28ff:fefa:d136",
319                            "fe80:0000:0000:0000:6af7:28ff:fefa:d136" ,
320                            false, 0);
321         test_sock_addr_cmp("::ffff:192.0.2.128", "192.0.2.128", false, 0);
322
323         test_sock_addr_cmp("127.0.0.1:123", "127.0.0.1:124" , true, -1);
324         test_sock_addr_cmp("fe80::6af7:28ff:fefa:d136:123",
325                            "fe80::6af7:28ff:fefa:d136:122" , true, 1);
326
327         test_connection_to_string("127.0.0.1:12345 127.0.0.2:54321");
328         test_connection_to_string("fe80::6af7:28ff:fefa:d137:12345 "
329                                   "fe80::6af7:28ff:fefa:d138:54321");
330
331         test_connection_from_string_bad("127.0.0.1:12345 127.0.0.2:");
332         test_connection_from_string_bad("127.0.0.1:12345");
333         test_connection_from_string_bad("127.0.0.1:12345 "
334                                         "fe80::6af7:28ff:fefa:d136:122");
335         test_connection_from_string_bad("Junk!");
336         test_connection_from_string_bad("More junk");
337
338         test_connection_list_read(CONN4, CONN4_SORT);
339         test_connection_list_read(CONN6, CONN6_SORT);
340         test_connection_list_read(CONN4 CONN6, CONN4_SORT CONN6_SORT);
341         test_connection_list_read(CONN4 "# Comment\n\n# Comment\n" CONN6,
342                                   CONN4_SORT CONN6_SORT);
343
344         test_connection_list_read_bad(CONN4 "# Comment\n\nJunk!!!\n" CONN6);
345         test_connection_list_read_bad(CONN4
346                                       "# Comment\n\n127.0.0.1: 127.0.0.1:124\n"
347                                       CONN6);
348
349         return 0;
350 }