fccfe5524a8c5d9ca381f3410c4ef249270d2dc5
[sfrench/samba-autobuild/.git] / ctdb / tests / src / protocol_ctdb_test.c
1 /*
2    protocol tests
3
4    Copyright (C) Amitay Isaacs  2015
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 <assert.h>
21
22 #include "protocol/protocol_basic.c"
23 #include "protocol/protocol_types.c"
24 #include "protocol/protocol_header.c"
25 #include "protocol/protocol_call.c"
26 #include "protocol/protocol_control.c"
27 #include "protocol/protocol_message.c"
28 #include "protocol/protocol_packet.c"
29
30 #include "tests/src/protocol_common.h"
31 #include "tests/src/protocol_common_ctdb.h"
32
33
34 #define GENERATION      0xabcdef12
35 #define OPERATION       CTDB_REQ_KEEPALIVE
36 #define REQID           0x34567890
37 #define SRCNODE         7
38 #define DESTNODE        13
39
40 /*
41  * Functions to test marshalling
42  */
43
44 /* for ctdb_req_header */
45 #define PROTOCOL_CTDB1_TEST(TYPE, NAME) \
46 static void TEST_FUNC(NAME)(void) \
47 { \
48         TALLOC_CTX *mem_ctx; \
49         TYPE c1, c2; \
50         uint8_t *pkt; \
51         size_t pkt_len, buflen, np; \
52         int ret; \
53 \
54         printf("%s\n", #NAME); \
55         fflush(stdout); \
56         mem_ctx = talloc_new(NULL); \
57         assert(mem_ctx != NULL); \
58         FILL_FUNC(NAME)(&c1); \
59         buflen = LEN_FUNC(NAME)(&c1); \
60         ret = ctdb_allocate_pkt(mem_ctx, buflen, &pkt, &pkt_len); \
61         assert(ret == 0); \
62         assert(pkt != NULL); \
63         assert(pkt_len >= buflen); \
64         np = 0; \
65         PUSH_FUNC(NAME)(&c1, pkt, &np); \
66         assert(np == buflen); \
67         np = 0; \
68         ret = PULL_FUNC(NAME)(pkt, pkt_len, &c2, &np); \
69         assert(ret == 0); \
70         assert(np == buflen); \
71         VERIFY_FUNC(NAME)(&c1, &c2); \
72         talloc_free(mem_ctx); \
73 }
74
75 /* for ctdb_req_control_data, ctdb_reply_control_data */
76 #define PROTOCOL_CTDB2_TEST(TYPE, NAME) \
77 static void TEST_FUNC(NAME)(uint32_t opcode) \
78 { \
79         TALLOC_CTX *mem_ctx; \
80         TYPE c1, c2; \
81         uint8_t *pkt; \
82         size_t pkt_len, buflen, np; \
83         int ret; \
84 \
85         printf("%s %u\n", #NAME, opcode); \
86         fflush(stdout); \
87         mem_ctx = talloc_new(NULL); \
88         assert(mem_ctx != NULL); \
89         FILL_FUNC(NAME)(mem_ctx, &c1, opcode); \
90         buflen = LEN_FUNC(NAME)(&c1); \
91         ret = ctdb_allocate_pkt(mem_ctx, buflen, &pkt, &pkt_len); \
92         assert(ret == 0); \
93         assert(pkt != NULL); \
94         assert(pkt_len >= buflen); \
95         np = 0; \
96         PUSH_FUNC(NAME)(&c1, pkt, &np); \
97         assert(np == buflen); \
98         np = 0; \
99         ret = PULL_FUNC(NAME)(pkt, pkt_len, opcode, mem_ctx, &c2, &np); \
100         assert(ret == 0); \
101         assert(np == buflen); \
102         VERIFY_FUNC(NAME)(&c1, &c2); \
103         talloc_free(mem_ctx); \
104 }
105
106 /* for ctdb_message_data */
107 #define PROTOCOL_CTDB3_TEST(TYPE, NAME) \
108 static void TEST_FUNC(NAME)(uint64_t srvid) \
109 { \
110         TALLOC_CTX *mem_ctx; \
111         TYPE c1, c2; \
112         uint8_t *pkt; \
113         size_t pkt_len, buflen, np; \
114         int ret; \
115 \
116         printf("%s %"PRIx64"\n", #NAME, srvid); \
117         fflush(stdout); \
118         mem_ctx = talloc_new(NULL); \
119         assert(mem_ctx != NULL); \
120         FILL_FUNC(NAME)(mem_ctx, &c1, srvid); \
121         buflen = LEN_FUNC(NAME)(&c1, srvid); \
122         ret = ctdb_allocate_pkt(mem_ctx, buflen, &pkt, &pkt_len); \
123         assert(ret == 0); \
124         assert(pkt != NULL); \
125         assert(pkt_len >= buflen); \
126         np = 0; \
127         PUSH_FUNC(NAME)(&c1, srvid, pkt, &np); \
128         assert(np == buflen); \
129         np = 0; \
130         ret = PULL_FUNC(NAME)(pkt, pkt_len, srvid, mem_ctx, &c2, &np); \
131         assert(ret == 0); \
132         assert(np == buflen); \
133         VERIFY_FUNC(NAME)(&c1, &c2, srvid); \
134         talloc_free(mem_ctx); \
135 }
136
137 /* for ctdb_req_call, ctdb_reply_call, etc. */
138 #define PROTOCOL_CTDB4_TEST(TYPE, NAME, OPER) \
139 static void TEST_FUNC(NAME)(void) \
140 { \
141         TALLOC_CTX *mem_ctx; \
142         struct ctdb_req_header h1, h2; \
143         TYPE c1, c2; \
144         uint8_t *pkt; \
145         size_t pkt_len, buflen, len; \
146         int ret; \
147 \
148         printf("%s\n", #NAME); \
149         fflush(stdout); \
150         mem_ctx = talloc_new(NULL); \
151         assert(mem_ctx != NULL); \
152         fill_ctdb_req_header(&h1); \
153         FILL_FUNC(NAME)(mem_ctx, &c1); \
154         buflen = LEN_FUNC(NAME)(&h1, &c1); \
155         ret = ctdb_allocate_pkt(mem_ctx, buflen, &pkt, &pkt_len); \
156         assert(ret == 0); \
157         assert(pkt != NULL); \
158         assert(pkt_len >= buflen); \
159         len = 0; \
160         ret = PUSH_FUNC(NAME)(&h1, &c1, pkt, &len); \
161         assert(ret == EMSGSIZE); \
162         assert(len == buflen); \
163         ret = PUSH_FUNC(NAME)(&h1, &c1, pkt, &pkt_len); \
164         assert(ret == 0); \
165         ret = PULL_FUNC(NAME)(pkt, pkt_len, &h2, mem_ctx, &c2); \
166         assert(ret == 0); \
167         verify_ctdb_req_header(&h1, &h2); \
168         assert(h2.length == pkt_len); \
169         VERIFY_FUNC(NAME)(&c1, &c2); \
170         talloc_free(mem_ctx); \
171 }
172
173 /* for ctdb_req_control */
174 #define PROTOCOL_CTDB5_TEST(TYPE, NAME, OPER) \
175 static void TEST_FUNC(NAME)(uint32_t opcode) \
176 { \
177         TALLOC_CTX *mem_ctx; \
178         struct ctdb_req_header h1, h2; \
179         TYPE c1, c2; \
180         uint8_t *pkt; \
181         size_t pkt_len, buflen, len; \
182         int ret; \
183 \
184         printf("%s %u\n", #NAME, opcode); \
185         fflush(stdout); \
186         mem_ctx = talloc_new(NULL); \
187         assert(mem_ctx != NULL); \
188         fill_ctdb_req_header(&h1); \
189         FILL_FUNC(NAME)(mem_ctx, &c1, opcode); \
190         buflen = LEN_FUNC(NAME)(&h1, &c1); \
191         ret = ctdb_allocate_pkt(mem_ctx, buflen, &pkt, &pkt_len); \
192         assert(ret == 0); \
193         assert(pkt != NULL); \
194         assert(pkt_len >= buflen); \
195         len = 0; \
196         ret = PUSH_FUNC(NAME)(&h1, &c1, pkt, &len); \
197         assert(ret == EMSGSIZE); \
198         assert(len == buflen); \
199         ret = PUSH_FUNC(NAME)(&h1, &c1, pkt, &pkt_len); \
200         assert(ret == 0); \
201         ret = PULL_FUNC(NAME)(pkt, pkt_len, &h2, mem_ctx, &c2); \
202         assert(ret == 0); \
203         verify_ctdb_req_header(&h1, &h2); \
204         assert(h2.length == pkt_len); \
205         VERIFY_FUNC(NAME)(&c1, &c2); \
206         talloc_free(mem_ctx); \
207 }
208
209 /* for ctdb_reply_control */
210 #define PROTOCOL_CTDB6_TEST(TYPE, NAME, OPER) \
211 static void TEST_FUNC(NAME)(uint32_t opcode) \
212 { \
213         TALLOC_CTX *mem_ctx; \
214         struct ctdb_req_header h1, h2; \
215         TYPE c1, c2; \
216         uint8_t *pkt; \
217         size_t pkt_len, buflen, len; \
218         int ret; \
219 \
220         printf("%s %u\n", #NAME, opcode); \
221         fflush(stdout); \
222         mem_ctx = talloc_new(NULL); \
223         assert(mem_ctx != NULL); \
224         fill_ctdb_req_header(&h1); \
225         FILL_FUNC(NAME)(mem_ctx, &c1, opcode); \
226         buflen = LEN_FUNC(NAME)(&h1, &c1); \
227         ret = ctdb_allocate_pkt(mem_ctx, buflen, &pkt, &pkt_len); \
228         assert(ret == 0); \
229         assert(pkt != NULL); \
230         assert(pkt_len >= buflen); \
231         len = 0; \
232         ret = PUSH_FUNC(NAME)(&h1, &c1, pkt, &len); \
233         assert(ret == EMSGSIZE); \
234         assert(len == buflen); \
235         ret = PUSH_FUNC(NAME)(&h1, &c1, pkt, &pkt_len); \
236         assert(ret == 0); \
237         ret = PULL_FUNC(NAME)(pkt, pkt_len, opcode, &h2, mem_ctx, &c2); \
238         assert(ret == 0); \
239         verify_ctdb_req_header(&h1, &h2); \
240         assert(h2.length == pkt_len); \
241         VERIFY_FUNC(NAME)(&c1, &c2); \
242         talloc_free(mem_ctx); \
243 }
244
245 /* for ctdb_req_message */
246 #define PROTOCOL_CTDB7_TEST(TYPE, NAME, OPER) \
247 static void TEST_FUNC(NAME)(uint64_t srvid) \
248 { \
249         TALLOC_CTX *mem_ctx; \
250         struct ctdb_req_header h1, h2; \
251         TYPE c1, c2; \
252         uint8_t *pkt; \
253         size_t pkt_len, buflen, len; \
254         int ret; \
255 \
256         printf("%s %"PRIx64"\n", #NAME, srvid); \
257         fflush(stdout); \
258         mem_ctx = talloc_new(NULL); \
259         assert(mem_ctx != NULL); \
260         fill_ctdb_req_header(&h1); \
261         FILL_FUNC(NAME)(mem_ctx, &c1, srvid); \
262         buflen = LEN_FUNC(NAME)(&h1, &c1); \
263         ret = ctdb_allocate_pkt(mem_ctx, buflen, &pkt, &pkt_len); \
264         assert(ret == 0); \
265         assert(pkt != NULL); \
266         assert(pkt_len >= buflen); \
267         len = 0; \
268         ret = PUSH_FUNC(NAME)(&h1, &c1, pkt, &len); \
269         assert(ret == EMSGSIZE); \
270         assert(len == buflen); \
271         ret = PUSH_FUNC(NAME)(&h1, &c1, pkt, &pkt_len); \
272         assert(ret == 0); \
273         ret = PULL_FUNC(NAME)(pkt, pkt_len, &h2, mem_ctx, &c2); \
274         assert(ret == 0); \
275         verify_ctdb_req_header(&h1, &h2); \
276         assert(h2.length == pkt_len); \
277         VERIFY_FUNC(NAME)(&c1, &c2); \
278         talloc_free(mem_ctx); \
279 }
280
281 static void test_ctdb_req_header(void)
282 {
283         TALLOC_CTX *mem_ctx;
284         uint8_t *pkt;
285         size_t pkt_len;
286         struct ctdb_req_header h, h2;
287         int ret;
288
289         printf("ctdb_req_header\n");
290         fflush(stdout);
291
292         mem_ctx = talloc_new(NULL);
293         assert(mem_ctx != NULL);
294
295         ctdb_req_header_fill(&h, GENERATION, OPERATION, DESTNODE, SRCNODE,
296                              REQID);
297
298         ret = ctdb_allocate_pkt(mem_ctx, ctdb_req_header_len(&h),
299                                 &pkt, &pkt_len);
300         assert(ret == 0);
301         assert(pkt != NULL);
302         assert(pkt_len >= ctdb_req_header_len(&h));
303
304         ctdb_req_header_push(&h, pkt);
305
306         ret = ctdb_req_header_pull(pkt, pkt_len, &h2);
307         assert(ret == 0);
308
309         verify_ctdb_req_header(&h, &h2);
310
311         talloc_free(mem_ctx);
312 }
313
314 static void test_ctdb_req_call(void)
315 {
316         TALLOC_CTX *mem_ctx;
317         uint8_t *pkt;
318         size_t datalen, pkt_len, len;
319         int ret;
320         struct ctdb_req_header h, h2;
321         struct ctdb_req_call c, c2;
322
323         printf("ctdb_req_call\n");
324         fflush(stdout);
325
326         mem_ctx = talloc_new(NULL);
327         assert(mem_ctx != NULL);
328
329         ctdb_req_header_fill(&h, GENERATION, CTDB_REQ_CALL,
330                              DESTNODE, SRCNODE, REQID);
331
332         fill_ctdb_req_call(mem_ctx, &c);
333         datalen = ctdb_req_call_len(&h, &c);
334         ret = ctdb_allocate_pkt(mem_ctx, datalen, &pkt, &pkt_len);
335         assert(ret == 0);
336         assert(pkt != NULL);
337         assert(pkt_len >= datalen);
338         len = 0;
339         ret = ctdb_req_call_push(&h, &c, pkt, &len);
340         assert(ret == EMSGSIZE);
341         assert(len == datalen);
342         ret = ctdb_req_call_push(&h, &c, pkt, &pkt_len);
343         assert(ret == 0);
344         ret = ctdb_req_call_pull(pkt, pkt_len, &h2, mem_ctx, &c2);
345         assert(ret == 0);
346         verify_ctdb_req_header(&h, &h2);
347         assert(h2.length == pkt_len);
348         verify_ctdb_req_call(&c, &c2);
349
350         talloc_free(mem_ctx);
351 }
352
353 static void test_ctdb_reply_call(void)
354 {
355         TALLOC_CTX *mem_ctx;
356         uint8_t *pkt;
357         size_t datalen, pkt_len, len;
358         int ret;
359         struct ctdb_req_header h, h2;
360         struct ctdb_reply_call c, c2;
361
362         printf("ctdb_reply_call\n");
363         fflush(stdout);
364
365         mem_ctx = talloc_new(NULL);
366         assert(mem_ctx != NULL);
367
368         ctdb_req_header_fill(&h, GENERATION, CTDB_REPLY_CALL,
369                              DESTNODE, SRCNODE, REQID);
370
371         fill_ctdb_reply_call(mem_ctx, &c);
372         datalen = ctdb_reply_call_len(&h, &c);
373         ret = ctdb_allocate_pkt(mem_ctx, datalen, &pkt, &pkt_len);
374         assert(ret == 0);
375         assert(pkt != NULL);
376         assert(pkt_len >= datalen);
377         len = 0;
378         ret = ctdb_reply_call_push(&h, &c, pkt, &len);
379         assert(ret == EMSGSIZE);
380         assert(len == datalen);
381         ret = ctdb_reply_call_push(&h, &c, pkt, &pkt_len);
382         assert(ret == 0);
383         ret = ctdb_reply_call_pull(pkt, pkt_len, &h2, mem_ctx, &c2);
384         assert(ret == 0);
385         verify_ctdb_req_header(&h, &h2);
386         assert(h2.length == pkt_len);
387         verify_ctdb_reply_call(&c, &c2);
388
389         talloc_free(mem_ctx);
390 }
391
392 static void test_ctdb_reply_error(void)
393 {
394         TALLOC_CTX *mem_ctx;
395         uint8_t *pkt;
396         size_t datalen, pkt_len, len;
397         int ret;
398         struct ctdb_req_header h, h2;
399         struct ctdb_reply_error c, c2;
400
401         printf("ctdb_reply_error\n");
402         fflush(stdout);
403
404         mem_ctx = talloc_new(NULL);
405         assert(mem_ctx != NULL);
406
407         ctdb_req_header_fill(&h, GENERATION, CTDB_REPLY_ERROR,
408                              DESTNODE, SRCNODE, REQID);
409
410         fill_ctdb_reply_error(mem_ctx, &c);
411         datalen = ctdb_reply_error_len(&h, &c);
412         ret = ctdb_allocate_pkt(mem_ctx, datalen, &pkt, &pkt_len);
413         assert(ret == 0);
414         assert(pkt != NULL);
415         assert(pkt_len >= datalen);
416         len = 0;
417         ret = ctdb_reply_error_push(&h, &c, pkt, &len);
418         assert(ret == EMSGSIZE);
419         assert(len == datalen);
420         ret = ctdb_reply_error_push(&h, &c, pkt, &pkt_len);
421         assert(ret == 0);
422         ret = ctdb_reply_error_pull(pkt, pkt_len, &h2, mem_ctx, &c2);
423         assert(ret == 0);
424         verify_ctdb_req_header(&h, &h2);
425         assert(h2.length == pkt_len);
426         verify_ctdb_reply_error(&c, &c2);
427
428         talloc_free(mem_ctx);
429 }
430
431 static void test_ctdb_req_dmaster(void)
432 {
433         TALLOC_CTX *mem_ctx;
434         uint8_t *pkt;
435         size_t datalen, pkt_len, len;
436         int ret;
437         struct ctdb_req_header h, h2;
438         struct ctdb_req_dmaster c, c2;
439
440         printf("ctdb_req_dmaster\n");
441         fflush(stdout);
442
443         mem_ctx = talloc_new(NULL);
444         assert(mem_ctx != NULL);
445
446         ctdb_req_header_fill(&h, GENERATION, CTDB_REQ_DMASTER,
447                              DESTNODE, SRCNODE, REQID);
448
449         fill_ctdb_req_dmaster(mem_ctx, &c);
450         datalen = ctdb_req_dmaster_len(&h, &c);
451         ret = ctdb_allocate_pkt(mem_ctx, datalen, &pkt, &pkt_len);
452         assert(ret == 0);
453         assert(pkt != NULL);
454         assert(pkt_len >= datalen);
455         len = 0;
456         ret = ctdb_req_dmaster_push(&h, &c, pkt, &len);
457         assert(ret == EMSGSIZE);
458         assert(len == datalen);
459         ret = ctdb_req_dmaster_push(&h, &c, pkt, &pkt_len);
460         assert(ret == 0);
461         ret = ctdb_req_dmaster_pull(pkt, pkt_len, &h2, mem_ctx, &c2);
462         assert(ret == 0);
463         verify_ctdb_req_header(&h, &h2);
464         assert(h2.length == pkt_len);
465         verify_ctdb_req_dmaster(&c, &c2);
466
467         talloc_free(mem_ctx);
468 }
469
470 static void test_ctdb_reply_dmaster(void)
471 {
472         TALLOC_CTX *mem_ctx;
473         uint8_t *pkt;
474         size_t datalen, pkt_len, len;
475         int ret;
476         struct ctdb_req_header h, h2;
477         struct ctdb_reply_dmaster c, c2;
478
479         printf("ctdb_reply_dmaster\n");
480         fflush(stdout);
481
482         mem_ctx = talloc_new(NULL);
483         assert(mem_ctx != NULL);
484
485         ctdb_req_header_fill(&h, GENERATION, CTDB_REPLY_DMASTER,
486                              DESTNODE, SRCNODE, REQID);
487
488         fill_ctdb_reply_dmaster(mem_ctx, &c);
489         datalen = ctdb_reply_dmaster_len(&h, &c);
490         ret = ctdb_allocate_pkt(mem_ctx, datalen, &pkt, &pkt_len);
491         assert(ret == 0);
492         assert(pkt != NULL);
493         assert(pkt_len >= datalen);
494         len = 0;
495         ret = ctdb_reply_dmaster_push(&h, &c, pkt, &len);
496         assert(ret == EMSGSIZE);
497         assert(len == datalen);
498         ret = ctdb_reply_dmaster_push(&h, &c, pkt, &pkt_len);
499         assert(ret == 0);
500         ret = ctdb_reply_dmaster_pull(pkt, pkt_len, &h2, mem_ctx, &c2);
501         assert(ret == 0);
502         verify_ctdb_req_header(&h, &h2);
503         assert(h2.length == pkt_len);
504         verify_ctdb_reply_dmaster(&c, &c2);
505
506         talloc_free(mem_ctx);
507 }
508
509 #define NUM_CONTROLS    151
510
511 static void test_ctdb_req_control_data(void)
512 {
513         TALLOC_CTX *mem_ctx;
514         size_t buflen;
515         int ret;
516         struct ctdb_req_control_data cd, cd2;
517         uint32_t opcode;
518
519         printf("ctdb_req_control_data\n");
520         fflush(stdout);
521
522         for (opcode=0; opcode<NUM_CONTROLS; opcode++) {
523                 mem_ctx = talloc_new(NULL);
524                 assert(mem_ctx != NULL);
525
526                 printf("%u.. ", opcode);
527                 fflush(stdout);
528                 fill_ctdb_req_control_data(mem_ctx, &cd, opcode);
529                 buflen = ctdb_req_control_data_len(&cd);
530                 ctdb_req_control_data_push(&cd, BUFFER);
531                 ret = ctdb_req_control_data_pull(BUFFER, buflen, opcode, mem_ctx, &cd2);
532                 assert(ret == 0);
533                 verify_ctdb_req_control_data(&cd, &cd2);
534                 talloc_free(mem_ctx);
535         }
536
537         printf("\n");
538         fflush(stdout);
539 }
540
541 static void test_ctdb_reply_control_data(void)
542 {
543         TALLOC_CTX *mem_ctx;
544         size_t buflen;
545         int ret;
546         struct ctdb_reply_control_data cd, cd2;
547         uint32_t opcode;
548
549         printf("ctdb_reply_control_data\n");
550         fflush(stdout);
551
552         for (opcode=0; opcode<NUM_CONTROLS; opcode++) {
553                 mem_ctx = talloc_new(NULL);
554                 assert(mem_ctx != NULL);
555
556                 printf("%u.. ", opcode);
557                 fflush(stdout);
558                 fill_ctdb_reply_control_data(mem_ctx, &cd, opcode);
559                 buflen = ctdb_reply_control_data_len(&cd);
560                 ctdb_reply_control_data_push(&cd, BUFFER);
561                 ret = ctdb_reply_control_data_pull(BUFFER, buflen, opcode, mem_ctx, &cd2);
562                 assert(ret == 0);
563                 verify_ctdb_reply_control_data(&cd, &cd2);
564                 talloc_free(mem_ctx);
565         }
566
567         printf("\n");
568         fflush(stdout);
569 }
570
571 static void test_ctdb_req_control(void)
572 {
573         TALLOC_CTX *mem_ctx;
574         uint8_t *pkt;
575         size_t datalen, pkt_len, len;
576         int ret;
577         struct ctdb_req_header h, h2;
578         struct ctdb_req_control c, c2;
579         uint32_t opcode;
580
581         printf("ctdb_req_control\n");
582         fflush(stdout);
583
584         ctdb_req_header_fill(&h, GENERATION, CTDB_REQ_CONTROL,
585                              DESTNODE, SRCNODE, REQID);
586
587         for (opcode=0; opcode<NUM_CONTROLS; opcode++) {
588                 mem_ctx = talloc_new(NULL);
589                 assert(mem_ctx != NULL);
590
591                 printf("%u.. ", opcode);
592                 fflush(stdout);
593                 fill_ctdb_req_control(mem_ctx, &c, opcode);
594                 datalen = ctdb_req_control_len(&h, &c);
595                 ret = ctdb_allocate_pkt(mem_ctx, datalen, &pkt, &pkt_len);
596                 assert(ret == 0);
597                 assert(pkt != NULL);
598                 assert(pkt_len >= datalen);
599                 len = 0;
600                 ret = ctdb_req_control_push(&h, &c, pkt, &len);
601                 assert(ret == EMSGSIZE);
602                 assert(len == datalen);
603                 ret = ctdb_req_control_push(&h, &c, pkt, &pkt_len);
604                 assert(ret == 0);
605                 ret = ctdb_req_control_pull(pkt, pkt_len, &h2, mem_ctx, &c2);
606                 assert(ret == 0);
607                 verify_ctdb_req_header(&h, &h2);
608                 assert(h2.length == pkt_len);
609                 verify_ctdb_req_control(&c, &c2);
610
611                 talloc_free(mem_ctx);
612         }
613
614         printf("\n");
615         fflush(stdout);
616 }
617
618 static void test_ctdb_reply_control(void)
619 {
620         TALLOC_CTX *mem_ctx;
621         uint8_t *pkt;
622         size_t datalen, pkt_len, len;
623         int ret;
624         struct ctdb_req_header h, h2;
625         struct ctdb_reply_control c, c2;
626         uint32_t opcode;
627
628         printf("ctdb_reply_control\n");
629         fflush(stdout);
630
631         ctdb_req_header_fill(&h, GENERATION, CTDB_REPLY_CONTROL,
632                              DESTNODE, SRCNODE, REQID);
633
634         for (opcode=0; opcode<NUM_CONTROLS; opcode++) {
635                 mem_ctx = talloc_new(NULL);
636                 assert(mem_ctx != NULL);
637
638                 printf("%u.. ", opcode);
639                 fflush(stdout);
640                 fill_ctdb_reply_control(mem_ctx, &c, opcode);
641                 datalen = ctdb_reply_control_len(&h, &c);
642                 ret = ctdb_allocate_pkt(mem_ctx, datalen, &pkt, &pkt_len);
643                 assert(ret == 0);
644                 assert(pkt != NULL);
645                 assert(pkt_len >= datalen);
646                 len = 0;
647                 ret = ctdb_reply_control_push(&h, &c, pkt, &len);
648                 assert(ret == EMSGSIZE);
649                 assert(len == datalen);
650                 ret = ctdb_reply_control_push(&h, &c, pkt, &pkt_len);
651                 assert(ret == 0);
652                 ret = ctdb_reply_control_pull(pkt, pkt_len, opcode, &h2, mem_ctx, &c2);
653                 assert(ret == 0);
654                 verify_ctdb_req_header(&h, &h2);
655                 assert(h2.length == pkt_len);
656                 verify_ctdb_reply_control(&c, &c2);
657
658                 talloc_free(mem_ctx);
659         }
660
661         printf("\n");
662         fflush(stdout);
663 }
664
665 static void test_ctdb_req_message_data(void)
666 {
667         TALLOC_CTX *mem_ctx;
668         uint8_t *pkt;
669         size_t datalen, pkt_len, len;
670         int ret;
671         struct ctdb_req_header h, h2;
672         struct ctdb_req_message_data c, c2;
673
674         printf("ctdb_req_message\n");
675         fflush(stdout);
676
677         mem_ctx = talloc_new(NULL);
678         assert(mem_ctx != NULL);
679
680         ctdb_req_header_fill(&h, GENERATION, CTDB_REQ_MESSAGE,
681                              DESTNODE, SRCNODE, REQID);
682
683         fill_ctdb_req_message_data(mem_ctx, &c);
684         datalen = ctdb_req_message_data_len(&h, &c);
685         ret = ctdb_allocate_pkt(mem_ctx, datalen, &pkt, &pkt_len);
686         assert(ret == 0);
687         assert(pkt != NULL);
688         assert(pkt_len >= datalen);
689         len = 0;
690         ret = ctdb_req_message_data_push(&h, &c, pkt, &len);
691         assert(ret == EMSGSIZE);
692         assert(len == datalen);
693         ret = ctdb_req_message_data_push(&h, &c, pkt, &pkt_len);
694         assert(ret == 0);
695         ret = ctdb_req_message_data_pull(pkt, pkt_len, &h2, mem_ctx, &c2);
696         assert(ret == 0);
697         verify_ctdb_req_header(&h, &h2);
698         assert(h2.length == pkt_len);
699         verify_ctdb_req_message_data(&c, &c2);
700
701         talloc_free(mem_ctx);
702 }
703
704 int main(int argc, char *argv[])
705 {
706         if (argc == 2) {
707                 int seed = atoi(argv[1]);
708                 srandom(seed);
709         }
710
711         test_ctdb_req_header();
712
713         test_ctdb_req_call();
714         test_ctdb_reply_call();
715         test_ctdb_reply_error();
716         test_ctdb_req_dmaster();
717         test_ctdb_reply_dmaster();
718
719         test_ctdb_req_control_data();
720         test_ctdb_reply_control_data();
721
722         test_ctdb_req_control();
723         test_ctdb_reply_control();
724
725         test_ctdb_req_message_data();
726
727         return 0;
728 }