ctdb: add ctdb_canonicalize_ip_inplace() helper
[Samba.git] / ctdb / tests / src / comm_test.c
blob4595928e91924adbd9020e8869a1a6c39c6a1bdd
1 /*
2 comm tests
4 Copyright (C) Amitay Isaacs 2015
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.
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.
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/>.
20 #include "replace.h"
21 #include "system/filesys.h"
23 #include <assert.h>
25 #include "common/pkt_read.c"
26 #include "common/pkt_write.c"
27 #include "common/comm.c"
30 * Test read_handler and dead_handler
33 static void test1_read_handler(uint8_t *buf, size_t buflen,
34 void *private_data)
36 int *result = (int *)private_data;
38 *result = -1;
41 static void test1_dead_handler(void *private_data)
43 int *result = (int *)private_data;
45 *result = 1;
48 static void test1(void)
50 TALLOC_CTX *mem_ctx;
51 struct tevent_context *ev;
52 struct comm_context *comm;
53 int fd[2];
54 int result = 0;
55 uint32_t data[2];
56 int ret;
57 ssize_t n;
59 mem_ctx = talloc_new(NULL);
60 assert(mem_ctx != NULL);
62 ev = tevent_context_init(mem_ctx);
63 assert(ev != NULL);
65 ret = pipe(fd);
66 assert(ret == 0);
68 ret = comm_setup(ev, ev, fd[0], test1_read_handler, &result,
69 test1_dead_handler, &result, &comm);
70 assert(ret == 0);
72 data[0] = 2 * sizeof(uint32_t);
73 data[1] = 0;
75 n = write(fd[1], (void *)&data, data[0]);
76 assert(n == data[0]);
78 while (result == 0) {
79 tevent_loop_once(ev);
82 assert(result == -1);
84 result = 0;
85 close(fd[1]);
87 while (result == 0) {
88 tevent_loop_once(ev);
91 assert(result == 1);
93 talloc_free(mem_ctx);
97 * Test that the tevent_req returned by comm_write_send() can be free'd.
100 struct test2_state {
101 TALLOC_CTX *mem_ctx;
102 bool done;
105 static void test2_read_handler(uint8_t *buf, size_t buflen,
106 void *private_data)
108 struct test2_state *state = (struct test2_state *)private_data;
110 TALLOC_FREE(state->mem_ctx);
113 static void test2_dead_handler(void *private_data)
115 abort();
118 struct test2_write_state {
119 int count;
122 static void test2_write_done(struct tevent_req *subreq);
124 static struct tevent_req *test2_write_send(TALLOC_CTX *mem_ctx,
125 struct tevent_context *ev,
126 struct comm_context *comm,
127 uint8_t *buf, size_t buflen)
129 struct tevent_req *req, *subreq;
130 struct test2_write_state *state;
131 int i;
133 req = tevent_req_create(mem_ctx, &state, struct test2_write_state);
134 if (req == NULL) {
135 return NULL;
138 state->count = 0;
140 for (i=0; i<10; i++) {
141 subreq = comm_write_send(state, ev, comm, buf, buflen);
142 if (tevent_req_nomem(subreq, req)) {
143 return tevent_req_post(req, ev);
145 tevent_req_set_callback(subreq, test2_write_done, req);
148 return req;
151 static void test2_write_done(struct tevent_req *subreq)
153 struct tevent_req *req = tevent_req_callback_data(
154 subreq, struct tevent_req);
155 struct test2_write_state *state = tevent_req_data(
156 req, struct test2_write_state);
157 bool status;
158 int ret;
160 status = comm_write_recv(subreq, &ret);
161 TALLOC_FREE(subreq);
162 if (! status) {
163 tevent_req_error(req, ret);
164 return;
167 state->count += 1;
169 if (state->count == 10) {
170 tevent_req_done(req);
174 static void test2_timer_handler(struct tevent_context *ev,
175 struct tevent_timer *te,
176 struct timeval cur_time,
177 void *private_data)
179 struct test2_state *state = (struct test2_state *)private_data;
181 state->done = true;
184 static void test2(void)
186 TALLOC_CTX *mem_ctx;
187 struct tevent_context *ev;
188 struct comm_context *comm_reader, *comm_writer;
189 struct test2_state test2_state;
190 struct tevent_req *req;
191 struct tevent_timer *te;
192 int fd[2];
193 uint32_t data[2];
194 int ret;
196 mem_ctx = talloc_new(NULL);
197 assert(mem_ctx != NULL);
199 test2_state.mem_ctx = talloc_new(mem_ctx);
200 assert(test2_state.mem_ctx != NULL);
202 test2_state.done = false;
204 ev = tevent_context_init(mem_ctx);
205 assert(ev != NULL);
207 ret = pipe(fd);
208 assert(ret == 0);
210 ret = comm_setup(ev, ev, fd[0], test2_read_handler, &test2_state,
211 test2_dead_handler, NULL, &comm_reader);
212 assert(ret == 0);
214 ret = comm_setup(ev, ev, fd[1], NULL, NULL, test2_dead_handler, NULL,
215 &comm_writer);
216 assert(ret == 0);
218 data[0] = 2 * sizeof(uint32_t);
219 data[1] = 0;
221 req = test2_write_send(test2_state.mem_ctx, ev, comm_writer,
222 (uint8_t *)data, data[0]);
223 assert(req != NULL);
225 te = tevent_add_timer(ev, ev, tevent_timeval_current_ofs(5,0),
226 test2_timer_handler, &test2_state);
227 assert(te != NULL);
229 while (! test2_state.done) {
230 tevent_loop_once(ev);
233 talloc_free(mem_ctx);
237 * Test that data is written and read correctly.
240 static void test3_dead_handler(void *private_data)
242 int dead_data = *(int *)private_data;
244 assert(dead_data == 1 || dead_data == 2);
246 if (dead_data == 1) {
247 /* reader */
248 fprintf(stderr, "writer closed pipe\n");
249 } else {
250 /* writer */
251 fprintf(stderr, "reader closed pipe\n");
255 struct test3_writer_state {
256 struct tevent_context *ev;
257 struct comm_context *comm;
258 uint8_t *buf;
259 size_t *pkt_size;
260 int count, id;
263 static void test3_writer_next(struct tevent_req *subreq);
265 static struct tevent_req *test3_writer_send(TALLOC_CTX *mem_ctx,
266 struct tevent_context *ev,
267 struct comm_context *comm,
268 size_t *pkt_size, size_t count)
270 struct tevent_req *req, *subreq;
271 struct test3_writer_state *state;
272 size_t max_size = 0, buflen;
273 size_t i;
275 for (i=0; i<count; i++) {
276 if (pkt_size[i] > max_size) {
277 max_size = pkt_size[i];
281 req = tevent_req_create(mem_ctx, &state, struct test3_writer_state);
282 if (req == NULL) {
283 return NULL;
286 state->ev = ev;
287 state->comm = comm;
288 state->pkt_size = pkt_size;
289 state->count = count;
290 state->id = 0;
292 state->buf = talloc_array(state, uint8_t, max_size);
293 if (state->buf == NULL) {
294 talloc_free(req);
295 return NULL;
297 for (i=0; i<max_size; i++) {
298 state->buf[i] = i%256;
301 buflen = state->pkt_size[state->id];
302 *(uint32_t *)state->buf = buflen;
303 subreq = comm_write_send(state, state->ev, state->comm,
304 state->buf, buflen);
305 if (tevent_req_nomem(subreq, req)) {
306 return tevent_req_post(req, ev);
309 tevent_req_set_callback(subreq, test3_writer_next, req);
310 return req;
313 static void test3_writer_next(struct tevent_req *subreq)
315 struct tevent_req *req = tevent_req_callback_data(
316 subreq, struct tevent_req);
317 struct test3_writer_state *state = tevent_req_data(
318 req, struct test3_writer_state);
319 bool ret;
320 int err;
321 size_t buflen;
323 ret = comm_write_recv(subreq, &err);
324 TALLOC_FREE(subreq);
325 if (!ret) {
326 tevent_req_error(req, err);
327 return;
330 state->id++;
331 if (state->id >= state->count) {
332 tevent_req_done(req);
333 return;
336 buflen = state->pkt_size[state->id];
337 *(uint32_t *)state->buf = buflen;
338 subreq = comm_write_send(state, state->ev, state->comm,
339 state->buf, buflen);
340 if (tevent_req_nomem(subreq, req)) {
341 return;
344 tevent_req_set_callback(subreq, test3_writer_next, req);
347 static void test3_writer_recv(struct tevent_req *req, int *perr)
349 if (tevent_req_is_unix_error(req, perr)) {
350 return;
352 *perr = 0;
355 static void test3_writer(int fd, size_t *pkt_size, size_t count)
357 TALLOC_CTX *mem_ctx;
358 struct tevent_context *ev;
359 struct comm_context *comm;
360 struct tevent_req *req;
361 int dead_data = 2;
362 int err;
364 mem_ctx = talloc_new(NULL);
365 assert(mem_ctx != NULL);
367 ev = tevent_context_init(mem_ctx);
368 assert(ev != NULL);
370 err = comm_setup(mem_ctx, ev, fd, NULL, NULL,
371 test3_dead_handler, &dead_data, &comm);
372 assert(err == 0);
373 assert(comm != NULL);
375 req = test3_writer_send(mem_ctx, ev, comm, pkt_size, count);
376 assert(req != NULL);
378 tevent_req_poll(req, ev);
380 test3_writer_recv(req, &err);
381 assert(err == 0);
383 talloc_free(mem_ctx);
386 struct test3_reader_state {
387 size_t *pkt_size;
388 int count, received;
389 bool done;
392 static void test3_reader_handler(uint8_t *buf, size_t buflen,
393 void *private_data)
395 struct test3_reader_state *state = talloc_get_type_abort(
396 private_data, struct test3_reader_state);
398 assert(buflen == state->pkt_size[state->received]);
399 printf("%zi ", buflen);
400 state->received++;
402 if (state->received == state->count) {
403 printf("\n");
404 state->done = true;
408 static void test3_reader(int fd, size_t *pkt_size, int count)
410 TALLOC_CTX *mem_ctx;
411 struct tevent_context *ev;
412 struct comm_context *comm;
413 struct test3_reader_state *state;
414 int dead_data = 1;
415 int err;
417 mem_ctx = talloc_new(NULL);
418 assert(mem_ctx != NULL);
420 ev = tevent_context_init(mem_ctx);
421 assert(ev != NULL);
423 state = talloc_zero(mem_ctx, struct test3_reader_state);
424 assert(state != NULL);
426 state->pkt_size = pkt_size;
427 state->count = count;
428 state->received = 0;
429 state->done = false;
431 err = comm_setup(mem_ctx, ev, fd, test3_reader_handler, state,
432 test3_dead_handler, &dead_data, &comm);
433 assert(err == 0);
434 assert(comm != NULL);
436 while (!state->done) {
437 tevent_loop_once(ev);
440 talloc_free(mem_ctx);
443 static void test3(void)
445 int fd[2];
446 int ret;
447 pid_t pid;
448 size_t pkt_size[13] = { 100, 2048, 500, 4096, 1024, 8192,
449 200, 16384, 300, 32768, 400, 65536,
450 1024*1024 };
452 ret = pipe(fd);
453 assert(ret == 0);
455 pid = fork();
456 assert(pid != -1);
458 if (pid == 0) {
459 /* Child process */
460 close(fd[0]);
461 test3_writer(fd[1], pkt_size, 13);
462 close(fd[1]);
463 exit(0);
466 close(fd[1]);
467 test3_reader(fd[0], pkt_size, 13);
468 close(fd[0]);
472 int main(int argc, const char **argv)
474 int num;
476 if (argc != 2) {
477 fprintf(stderr, "%s <testnum>\n", argv[0]);
478 exit(1);
481 num = atoi(argv[1]);
483 switch (num) {
484 case 1:
485 test1();
486 break;
488 case 2:
489 test2();
490 break;
492 case 3:
493 test3();
494 break;
496 default:
497 fprintf(stderr, "Unknown test number %s\n", argv[1]);
500 return 0;