2 Unix SMB/CIFS implementation.
4 local test for messaging code
6 Copyright (C) Andrew Tridgell 2004
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 #include "lib/events/events.h"
24 #include "lib/messaging/irpc.h"
25 #include "torture/torture.h"
26 #include "cluster/cluster.h"
27 #include "param/param.h"
28 #include "torture/local/proto.h"
29 #include "system/select.h"
30 #include "system/filesys.h"
31 #include "lib/crypto/md5.h"
33 static uint32_t msg_pong;
35 static void ping_message(struct imessaging_context *msg, void *private_data,
36 uint32_t msg_type, struct server_id src, DATA_BLOB *data)
39 status = imessaging_send(msg, src, msg_pong, data);
40 if (!NT_STATUS_IS_OK(status)) {
41 printf("pong failed - %s\n", nt_errstr(status));
45 static void pong_message(struct imessaging_context *msg, void *private_data,
46 uint32_t msg_type, struct server_id src, DATA_BLOB *data)
48 int *count = (int *)private_data;
52 static void exit_message(struct imessaging_context *msg, void *private_data,
53 uint32_t msg_type, struct server_id src, DATA_BLOB *data)
55 talloc_free(private_data);
62 static bool test_ping_speed(struct torture_context *tctx)
64 struct tevent_context *ev;
65 struct imessaging_context *msg_client_ctx;
66 struct imessaging_context *msg_server_ctx;
70 int timelimit = torture_setting_int(tctx, "timelimit", 10);
71 uint32_t msg_ping, msg_exit;
73 lpcfg_set_cmdline(tctx->lp_ctx, "pid directory", "piddir.tmp");
77 msg_server_ctx = imessaging_init(tctx,
78 tctx->lp_ctx, cluster_id(0, 1),
81 torture_assert(tctx, msg_server_ctx != NULL, "Failed to init ping messaging context");
83 imessaging_register_tmp(msg_server_ctx, NULL, ping_message, &msg_ping);
84 imessaging_register_tmp(msg_server_ctx, tctx, exit_message, &msg_exit);
86 msg_client_ctx = imessaging_init(tctx,
91 torture_assert(tctx, msg_client_ctx != NULL,
92 "msg_client_ctx imessaging_init() failed");
94 imessaging_register_tmp(msg_client_ctx, &pong_count, pong_message, &msg_pong);
96 tv = timeval_current();
98 torture_comment(tctx, "Sending pings for %d seconds\n", timelimit);
99 while (timeval_elapsed(&tv) < timelimit) {
101 NTSTATUS status1, status2;
103 data.data = discard_const_p(uint8_t, "testing");
104 data.length = strlen((const char *)data.data);
106 status1 = imessaging_send(msg_client_ctx, cluster_id(0, 1), msg_ping, &data);
107 status2 = imessaging_send(msg_client_ctx, cluster_id(0, 1), msg_ping, NULL);
109 torture_assert_ntstatus_ok(tctx, status1, "msg1 failed");
112 torture_assert_ntstatus_ok(tctx, status2, "msg2 failed");
115 while (ping_count > pong_count + 20) {
116 tevent_loop_once(ev);
120 torture_comment(tctx, "waiting for %d remaining replies (done %d)\n",
121 ping_count - pong_count, pong_count);
122 while (timeval_elapsed(&tv) < 30 && pong_count < ping_count) {
123 tevent_loop_once(ev);
126 torture_comment(tctx, "sending exit\n");
127 imessaging_send(msg_client_ctx, cluster_id(0, 1), msg_exit, NULL);
129 torture_assert_int_equal(tctx, ping_count, pong_count, "ping test failed");
131 torture_comment(tctx, "ping rate of %.0f messages/sec\n",
132 (ping_count+pong_count)/timeval_elapsed(&tv));
134 talloc_free(msg_client_ctx);
135 talloc_free(msg_server_ctx);
140 static bool test_messaging_overflow(struct torture_context *tctx)
142 struct imessaging_context *msg_ctx;
143 ssize_t nwritten, nread;
146 int up_pipe[2], down_pipe[2];
147 int i, ret, child_status;
150 torture_assert(tctx, ret == 0, "pipe failed");
151 ret = pipe(down_pipe);
152 torture_assert(tctx, ret == 0, "pipe failed");
156 torture_fail(tctx, "fork failed");
160 ret = tevent_re_initialise(tctx->ev);
161 torture_assert(tctx, ret == 0, "tevent_re_initialise failed");
163 msg_ctx = imessaging_init(tctx, tctx->lp_ctx,
164 cluster_id(getpid(), 0),
166 torture_assert(tctx, msg_ctx != NULL,
167 "imessaging_init failed");
170 nwritten = write(up_pipe[1], &c, 1);
171 } while ((nwritten == -1) && (errno == EINTR));
173 ret = close(down_pipe[1]);
174 torture_assert(tctx, ret == 0, "close failed");
177 nread = read(down_pipe[0], &c, 1);
178 } while ((nread == -1) && (errno == EINTR));
184 nread = read(up_pipe[0], &c, 1);
185 } while ((nread == -1) && (errno == EINTR));
187 msg_ctx = imessaging_init(tctx, tctx->lp_ctx, cluster_id(getpid(), 0),
189 torture_assert(tctx, msg_ctx != NULL, "imessaging_init failed");
191 for (i=0; i<1000; i++) {
193 status = imessaging_send(msg_ctx, cluster_id(child, 0),
195 torture_assert_ntstatus_ok(tctx, status,
196 "imessaging_send failed");
199 tevent_loop_once(tctx->ev);
201 talloc_free(msg_ctx);
203 ret = close(down_pipe[1]);
204 torture_assert(tctx, ret == 0, "close failed");
206 ret = waitpid(child, &child_status, 0);
207 torture_assert(tctx, ret == child, "wrong child exited");
208 torture_assert(tctx, child_status == 0, "child failed");
215 struct overflow_parent_child {
220 static void overflow_md5_child_handler(struct imessaging_context *msg,
223 struct server_id server_id,
226 struct overflow_parent_child *state = private_data;
228 if (data->length == 0) {
233 MD5Update(&state->md5ctx, data->data, data->length);
236 struct overflow_child_parent {
241 static void overflow_md5_parent_handler(struct imessaging_context *msg_ctx,
244 struct server_id server_id,
247 struct overflow_child_parent *state = private_data;
249 if (data->length != sizeof(state->final)) {
250 memset(state->final, 0, sizeof(state->final));
254 memcpy(state->final, data->data, 16);
258 static bool test_messaging_overflow_check(struct torture_context *tctx)
260 struct imessaging_context *msg_ctx;
261 ssize_t nwritten, nread;
264 int up_pipe[2], down_pipe[2];
265 int i, ret, child_status;
268 struct overflow_child_parent child_msg = { .done = false };
272 torture_assert(tctx, ret == 0, "pipe failed");
273 ret = pipe(down_pipe);
274 torture_assert(tctx, ret == 0, "pipe failed");
278 torture_fail(tctx, "fork failed");
282 struct overflow_parent_child child_state = { .done = false };
283 DATA_BLOB retblob = { .data = final, .length = sizeof(final) };
285 ret = tevent_re_initialise(tctx->ev);
286 torture_assert(tctx, ret == 0, "tevent_re_initialise failed");
288 MD5Init(&child_state.md5ctx);
290 msg_ctx = imessaging_init(tctx, tctx->lp_ctx,
291 cluster_id(getpid(), 0),
293 torture_assert(tctx, msg_ctx != NULL,
294 "imessaging_init failed");
296 status = imessaging_register(msg_ctx, &child_state,
298 overflow_md5_child_handler);
299 torture_assert(tctx, NT_STATUS_IS_OK(status),
300 "imessaging_register failed");
303 nwritten = write(up_pipe[1], &c, 1);
304 } while ((nwritten == -1) && (errno == EINTR));
306 ret = close(down_pipe[1]);
307 torture_assert(tctx, ret == 0, "close failed");
310 nread = read(down_pipe[0], &c, 1);
311 } while ((nread == -1) && (errno == EINTR));
313 while (!child_state.done) {
314 tevent_loop_once(tctx->ev);
317 MD5Final(final, &child_state.md5ctx);
319 status = imessaging_send(msg_ctx,
320 cluster_id(getppid(), 0),
323 torture_assert(tctx, NT_STATUS_IS_OK(status),
324 "imessaging_send failed");
330 nread = read(up_pipe[0], &c, 1);
331 } while ((nread == -1) && (errno == EINTR));
333 msg_ctx = imessaging_init(tctx, tctx->lp_ctx, cluster_id(getpid(), 0),
335 torture_assert(tctx, msg_ctx != NULL, "imessaging_init failed");
337 status = imessaging_register(msg_ctx,
340 overflow_md5_parent_handler);
342 NT_STATUS_IS_OK(status),
343 "imessaging_register failed");
347 for (i=0; i<1000; i++) {
348 size_t len = ((random() % 100) + 1);
350 DATA_BLOB blob = { .data = buf, .length = len };
352 generate_random_buffer(buf, len);
354 MD5Update(&md5ctx, buf, len);
356 status = imessaging_send(msg_ctx, cluster_id(child, 0),
357 MSG_TMP_BASE-1, &blob);
358 torture_assert_ntstatus_ok(tctx, status,
359 "imessaging_send failed");
362 status = imessaging_send(msg_ctx, cluster_id(child, 0),
363 MSG_TMP_BASE-1, NULL);
364 torture_assert_ntstatus_ok(tctx, status,
365 "imessaging_send failed");
367 MD5Final(final, &md5ctx);
370 nwritten = write(down_pipe[1], &c, 1);
371 } while ((nwritten == -1) && (errno == EINTR));
373 while (!child_msg.done) {
374 tevent_loop_once(tctx->ev);
377 ret = close(down_pipe[1]);
378 torture_assert(tctx, ret == 0, "close failed");
380 talloc_free(msg_ctx);
382 ret = waitpid(child, &child_status, 0);
383 torture_assert(tctx, ret == child, "wrong child exited");
384 torture_assert(tctx, child_status == 0, "child failed");
386 if (memcmp(final, child_msg.final, 16) != 0) {
387 dump_data_file(final, 16, false, stderr);
388 dump_data_file(child_msg.final, 16, false, stderr);
390 torture_fail(tctx, "checksum comparison failed");
396 struct test_multi_ctx {
397 struct torture_context *tctx;
398 struct imessaging_context *server_ctx;
399 struct imessaging_context *client_ctx[4];
407 static void multi_ctx_server_handler(struct imessaging_context *msg,
410 struct server_id server_id,
413 struct test_multi_ctx *state = private_data;
416 torture_assert_goto(state->tctx, state->num_missing >= 1,
418 "num_missing should be at least 1.");
419 state->num_missing -= 1;
421 torture_assert_goto(state->tctx, !state->got_server,
423 "already got server.");
424 state->got_server = true;
427 * We free the context itself and most likely reuse
428 * the memory immediately.
430 TALLOC_FREE(state->server_ctx);
431 str = generate_random_str(state->tctx, 128);
432 torture_assert_goto(state->tctx, str != NULL,
434 "generate_random_str()");
440 static void multi_ctx_client_0_1_handler(struct imessaging_context *msg,
443 struct server_id server_id,
446 struct test_multi_ctx *state = private_data;
449 torture_assert_goto(state->tctx, state->num_missing >= 2,
451 "num_missing should be at least 2.");
452 state->num_missing -= 2;
454 torture_assert_goto(state->tctx, !state->got_client_0_1,
456 "already got client_0_1.");
457 state->got_client_0_1 = true;
460 * We free two contexts and most likely reuse
461 * the memory immediately.
463 TALLOC_FREE(state->client_ctx[0]);
464 str = generate_random_str(state->tctx, 128);
465 torture_assert_goto(state->tctx, str != NULL,
467 "generate_random_str()");
468 TALLOC_FREE(state->client_ctx[1]);
469 str = generate_random_str(state->tctx, 128);
470 torture_assert_goto(state->tctx, str != NULL,
472 "generate_random_str()");
478 static void multi_ctx_client_2_3_handler(struct imessaging_context *msg,
481 struct server_id server_id,
484 struct test_multi_ctx *state = private_data;
487 torture_assert_goto(state->tctx, state->num_missing >= 2,
489 "num_missing should be at least 2.");
490 state->num_missing -= 2;
492 torture_assert_goto(state->tctx, !state->got_client_2_3,
494 "already got client_2_3.");
495 state->got_client_2_3 = true;
498 * We free two contexts and most likely reuse
499 * the memory immediately.
501 TALLOC_FREE(state->client_ctx[2]);
502 str = generate_random_str(state->tctx, 128);
503 torture_assert_goto(state->tctx, str != NULL,
505 "generate_random_str()");
506 TALLOC_FREE(state->client_ctx[3]);
507 str = generate_random_str(state->tctx, 128);
508 torture_assert_goto(state->tctx, str != NULL,
510 "generate_random_str()");
516 static bool test_multi_ctx(struct torture_context *tctx)
518 struct test_multi_ctx state = {
525 lpcfg_set_cmdline(tctx->lp_ctx, "pid directory", "piddir.tmp");
528 * We use cluster_id(0, 0) as that gets for
531 state.server_ctx = imessaging_init(tctx,
535 torture_assert(tctx, state.server_ctx != NULL,
536 "Failed to init messaging context");
538 status = imessaging_register(state.server_ctx, &state,
540 multi_ctx_server_handler);
541 torture_assert(tctx, NT_STATUS_IS_OK(status), "imessaging_register failed");
543 state.client_ctx[0] = imessaging_init(tctx,
547 torture_assert(tctx, state.client_ctx[0] != NULL,
548 "msg_client_ctx imessaging_init() failed");
549 status = imessaging_register(state.client_ctx[0], &state,
551 multi_ctx_client_0_1_handler);
552 torture_assert(tctx, NT_STATUS_IS_OK(status), "imessaging_register failed");
553 state.client_ctx[1] = imessaging_init(tctx,
557 torture_assert(tctx, state.client_ctx[1] != NULL,
558 "msg_client_ctx imessaging_init() failed");
559 status = imessaging_register(state.client_ctx[1], &state,
561 multi_ctx_client_0_1_handler);
562 torture_assert(tctx, NT_STATUS_IS_OK(status), "imessaging_register failed");
563 state.client_ctx[2] = imessaging_init(tctx,
567 torture_assert(tctx, state.client_ctx[2] != NULL,
568 "msg_client_ctx imessaging_init() failed");
569 status = imessaging_register(state.client_ctx[2], &state,
571 multi_ctx_client_2_3_handler);
572 torture_assert(tctx, NT_STATUS_IS_OK(status), "imessaging_register failed");
573 state.client_ctx[3] = imessaging_init(tctx,
577 torture_assert(tctx, state.client_ctx[3] != NULL,
578 "msg_client_ctx imessaging_init() failed");
579 status = imessaging_register(state.client_ctx[3], &state,
581 multi_ctx_client_2_3_handler);
582 torture_assert(tctx, NT_STATUS_IS_OK(status), "imessaging_register failed");
585 * Send one message that need to arrive on 3 ( 5 - 2 ) handlers.
587 state.num_missing = 5;
589 status = imessaging_send(state.server_ctx,
591 MSG_TMP_BASE-1, NULL);
592 torture_assert_ntstatus_ok(tctx, status, "msg failed");
594 tv = timeval_current();
595 while (timeval_elapsed(&tv) < 30 && state.num_missing > 0 && state.ok) {
598 ret = tevent_loop_once(tctx->ev);
599 torture_assert_int_equal(tctx, ret, 0, "tevent_loop_once()");
606 torture_assert_int_equal(tctx, state.num_missing, 0,
607 "wrong message count");
609 torture_assert(tctx, state.got_client_0_1, "got_client_0_1");
610 torture_assert(tctx, state.got_client_2_3, "got_client_2_3");
611 torture_assert(tctx, state.got_server, "got_server");
616 struct torture_suite *torture_local_messaging(TALLOC_CTX *mem_ctx)
618 struct torture_suite *s = torture_suite_create(mem_ctx, "messaging");
619 torture_suite_add_simple_test(s, "overflow", test_messaging_overflow);
620 torture_suite_add_simple_test(s, "overflow_check",
621 test_messaging_overflow_check);
622 torture_suite_add_simple_test(s, "ping_speed", test_ping_speed);
623 torture_suite_add_simple_test(s, "multi_ctx", test_multi_ctx);