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]);
176 nread
= read(down_pipe
[0], &c
, 1);
177 } while ((nread
== -1) && (errno
== EINTR
));
183 nread
= read(up_pipe
[0], &c
, 1);
184 } while ((nread
== -1) && (errno
== EINTR
));
186 msg_ctx
= imessaging_init(tctx
, tctx
->lp_ctx
, cluster_id(getpid(), 0),
188 torture_assert(tctx
, msg_ctx
!= NULL
, "imessaging_init failed");
190 for (i
=0; i
<1000; i
++) {
192 status
= imessaging_send(msg_ctx
, cluster_id(child
, 0),
194 torture_assert_ntstatus_ok(tctx
, status
,
195 "imessaging_send failed");
198 tevent_loop_once(tctx
->ev
);
200 talloc_free(msg_ctx
);
202 ret
= close(down_pipe
[1]);
203 torture_assert(tctx
, ret
== 0, "close failed");
205 ret
= waitpid(child
, &child_status
, 0);
206 torture_assert(tctx
, ret
== child
, "wrong child exited");
207 torture_assert(tctx
, child_status
== 0, "child failed");
214 struct overflow_parent_child
{
219 static void overflow_md5_child_handler(struct imessaging_context
*msg
,
222 struct server_id server_id
,
225 struct overflow_parent_child
*state
= private_data
;
227 if (data
->length
== 0) {
232 MD5Update(&state
->md5ctx
, data
->data
, data
->length
);
235 struct overflow_child_parent
{
240 static void overflow_md5_parent_handler(struct imessaging_context
*msg_ctx
,
243 struct server_id server_id
,
246 struct overflow_child_parent
*state
= private_data
;
248 if (data
->length
!= sizeof(state
->final
)) {
249 memset(state
->final
, 0, sizeof(state
->final
));
253 memcpy(state
->final
, data
->data
, 16);
257 static bool test_messaging_overflow_check(struct torture_context
*tctx
)
259 struct imessaging_context
*msg_ctx
;
260 ssize_t nwritten
, nread
;
263 int up_pipe
[2], down_pipe
[2];
264 int i
, ret
, child_status
;
267 struct overflow_child_parent child_msg
= { .done
= false };
271 torture_assert(tctx
, ret
== 0, "pipe failed");
272 ret
= pipe(down_pipe
);
273 torture_assert(tctx
, ret
== 0, "pipe failed");
277 torture_fail(tctx
, "fork failed");
281 struct overflow_parent_child child_state
= { .done
= false };
282 DATA_BLOB retblob
= { .data
= final
, .length
= sizeof(final
) };
284 ret
= tevent_re_initialise(tctx
->ev
);
285 torture_assert(tctx
, ret
== 0, "tevent_re_initialise failed");
287 MD5Init(&child_state
.md5ctx
);
289 msg_ctx
= imessaging_init(tctx
, tctx
->lp_ctx
,
290 cluster_id(getpid(), 0),
292 torture_assert(tctx
, msg_ctx
!= NULL
,
293 "imessaging_init failed");
295 status
= imessaging_register(msg_ctx
, &child_state
,
297 overflow_md5_child_handler
);
298 torture_assert(tctx
, NT_STATUS_IS_OK(status
),
299 "imessaging_register failed");
302 nwritten
= write(up_pipe
[1], &c
, 1);
303 } while ((nwritten
== -1) && (errno
== EINTR
));
305 ret
= close(down_pipe
[1]);
306 torture_assert(tctx
, ret
== 0, "close failed");
309 nread
= read(down_pipe
[0], &c
, 1);
310 } while ((nread
== -1) && (errno
== EINTR
));
312 while (!child_state
.done
) {
313 tevent_loop_once(tctx
->ev
);
316 MD5Final(final
, &child_state
.md5ctx
);
318 status
= imessaging_send(msg_ctx
,
319 cluster_id(getppid(), 0),
322 torture_assert(tctx
, NT_STATUS_IS_OK(status
),
323 "imessaging_send failed");
329 nread
= read(up_pipe
[0], &c
, 1);
330 } while ((nread
== -1) && (errno
== EINTR
));
332 msg_ctx
= imessaging_init(tctx
, tctx
->lp_ctx
, cluster_id(getpid(), 0),
334 torture_assert(tctx
, msg_ctx
!= NULL
, "imessaging_init failed");
336 status
= imessaging_register(msg_ctx
,
339 overflow_md5_parent_handler
);
341 NT_STATUS_IS_OK(status
),
342 "imessaging_register failed");
346 for (i
=0; i
<1000; i
++) {
347 size_t len
= ((random() % 100) + 1);
349 DATA_BLOB blob
= { .data
= buf
, .length
= len
};
351 generate_random_buffer(buf
, len
);
353 MD5Update(&md5ctx
, buf
, len
);
355 status
= imessaging_send(msg_ctx
, cluster_id(child
, 0),
356 MSG_TMP_BASE
-1, &blob
);
357 torture_assert_ntstatus_ok(tctx
, status
,
358 "imessaging_send failed");
361 status
= imessaging_send(msg_ctx
, cluster_id(child
, 0),
362 MSG_TMP_BASE
-1, NULL
);
363 torture_assert_ntstatus_ok(tctx
, status
,
364 "imessaging_send failed");
366 MD5Final(final
, &md5ctx
);
369 nwritten
= write(down_pipe
[1], &c
, 1);
370 } while ((nwritten
== -1) && (errno
== EINTR
));
372 while (!child_msg
.done
) {
373 tevent_loop_once(tctx
->ev
);
376 ret
= close(down_pipe
[1]);
377 torture_assert(tctx
, ret
== 0, "close failed");
379 talloc_free(msg_ctx
);
381 ret
= waitpid(child
, &child_status
, 0);
382 torture_assert(tctx
, ret
== child
, "wrong child exited");
383 torture_assert(tctx
, child_status
== 0, "child failed");
385 if (memcmp(final
, child_msg
.final
, 16) != 0) {
386 dump_data_file(final
, 16, false, stderr
);
387 dump_data_file(child_msg
.final
, 16, false, stderr
);
389 torture_fail(tctx
, "checksum comparison failed");
395 struct torture_suite
*torture_local_messaging(TALLOC_CTX
*mem_ctx
)
397 struct torture_suite
*s
= torture_suite_create(mem_ctx
, "messaging");
398 torture_suite_add_simple_test(s
, "overflow", test_messaging_overflow
);
399 torture_suite_add_simple_test(s
, "overflow_check",
400 test_messaging_overflow_check
);
401 torture_suite_add_simple_test(s
, "ping_speed", test_ping_speed
);