summaryrefslogtreecommitdiff
path: root/source4/lib/messaging/tests
diff options
context:
space:
mode:
Diffstat (limited to 'source4/lib/messaging/tests')
-rw-r--r--source4/lib/messaging/tests/bindings.py57
-rw-r--r--source4/lib/messaging/tests/irpc.c271
-rw-r--r--source4/lib/messaging/tests/messaging.c145
3 files changed, 473 insertions, 0 deletions
diff --git a/source4/lib/messaging/tests/bindings.py b/source4/lib/messaging/tests/bindings.py
new file mode 100644
index 0000000000..c89538ddfa
--- /dev/null
+++ b/source4/lib/messaging/tests/bindings.py
@@ -0,0 +1,57 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# Unix SMB/CIFS implementation.
+# Copyright © Jelmer Vernooij <jelmer@samba.org> 2008
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+
+from samba.messaging import Messaging
+from unittest import TestCase
+
+class MessagingTests(TestCase):
+ def get_context(self, *args, **kwargs):
+ kwargs["messaging_path"] = "."
+ return Messaging(*args, **kwargs)
+
+ def test_register(self):
+ x = self.get_context()
+ def callback():
+ pass
+ msg_type = x.register(callback)
+ x.deregister(callback, msg_type)
+
+ def test_assign_server_id(self):
+ x = self.get_context()
+ self.assertTrue(isinstance(x.server_id, tuple))
+ self.assertEquals(3, len(x.server_id))
+
+ def test_ping_speed(self):
+ server_ctx = self.get_context((0, 1))
+ def ping_callback(src, data):
+ server_ctx.send(src, data)
+ def exit_callback():
+ print "received exit"
+ msg_ping = server_ctx.register(ping_callback)
+ msg_exit = server_ctx.register(exit_callback)
+
+ def pong_callback():
+ print "received pong"
+ client_ctx = self.get_context((0, 2))
+ msg_pong = client_ctx.register(pong_callback)
+
+ client_ctx.send((0,1), msg_ping, "testing")
+ client_ctx.send((0,1), msg_ping, "")
+
diff --git a/source4/lib/messaging/tests/irpc.c b/source4/lib/messaging/tests/irpc.c
new file mode 100644
index 0000000000..d9b0548643
--- /dev/null
+++ b/source4/lib/messaging/tests/irpc.c
@@ -0,0 +1,271 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ local test for irpc code
+
+ Copyright (C) Andrew Tridgell 2004
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
+#include "lib/events/events.h"
+#include "lib/messaging/irpc.h"
+#include "librpc/gen_ndr/ndr_echo.h"
+#include "torture/torture.h"
+#include "cluster/cluster.h"
+#include "param/param.h"
+
+const uint32_t MSG_ID1 = 1, MSG_ID2 = 2;
+
+static bool test_debug;
+
+struct irpc_test_data
+{
+ struct messaging_context *msg_ctx1, *msg_ctx2;
+ struct event_context *ev;
+};
+
+/*
+ serve up AddOne over the irpc system
+*/
+static NTSTATUS irpc_AddOne(struct irpc_message *irpc, struct echo_AddOne *r)
+{
+ *r->out.out_data = r->in.in_data + 1;
+ if (test_debug) {
+ printf("irpc_AddOne: in=%u in+1=%u out=%u\n",
+ r->in.in_data, r->in.in_data+1, *r->out.out_data);
+ }
+ return NT_STATUS_OK;
+}
+
+/*
+ a deferred reply to echodata
+*/
+static void deferred_echodata(struct event_context *ev, struct timed_event *te,
+ struct timeval t, void *private)
+{
+ struct irpc_message *irpc = talloc_get_type(private, struct irpc_message);
+ struct echo_EchoData *r = irpc->data;
+ r->out.out_data = talloc_memdup(r, r->in.in_data, r->in.len);
+ if (r->out.out_data == NULL) {
+ irpc_send_reply(irpc, NT_STATUS_NO_MEMORY);
+ }
+ printf("sending deferred reply\n");
+ irpc_send_reply(irpc, NT_STATUS_OK);
+}
+
+
+/*
+ serve up EchoData over the irpc system
+*/
+static NTSTATUS irpc_EchoData(struct irpc_message *irpc, struct echo_EchoData *r)
+{
+ irpc->defer_reply = true;
+ event_add_timed(irpc->ev, irpc, timeval_zero(), deferred_echodata, irpc);
+ return NT_STATUS_OK;
+}
+
+
+/*
+ test a addone call over the internal messaging system
+*/
+static bool test_addone(struct torture_context *test, const void *_data,
+ const void *_value)
+{
+ struct echo_AddOne r;
+ NTSTATUS status;
+ const struct irpc_test_data *data = (const struct irpc_test_data *)_data;
+ uint32_t value = (uint32_t)_value;
+
+ /* make the call */
+ r.in.in_data = value;
+
+ test_debug = true;
+ status = IRPC_CALL(data->msg_ctx1, cluster_id(0, MSG_ID2),
+ rpcecho, ECHO_ADDONE, &r, test);
+ test_debug = false;
+ torture_assert_ntstatus_ok(test, status, "AddOne failed");
+
+ /* check the answer */
+ torture_assert(test, *r.out.out_data == r.in.in_data + 1,
+ "AddOne wrong answer");
+
+ torture_comment(test, "%u + 1 = %u\n", r.in.in_data, *r.out.out_data);
+ return true;
+}
+
+/*
+ test a echodata call over the internal messaging system
+*/
+static bool test_echodata(struct torture_context *tctx,
+ const void *tcase_data,
+ const void *test_data)
+{
+ struct echo_EchoData r;
+ NTSTATUS status;
+ const struct irpc_test_data *data = (const struct irpc_test_data *)tcase_data;
+ TALLOC_CTX *mem_ctx = tctx;
+
+ /* make the call */
+ r.in.in_data = (unsigned char *)talloc_strdup(mem_ctx, "0123456789");
+ r.in.len = strlen((char *)r.in.in_data);
+
+ status = IRPC_CALL(data->msg_ctx1, cluster_id(0, MSG_ID2),
+ rpcecho, ECHO_ECHODATA, &r,
+ mem_ctx);
+ torture_assert_ntstatus_ok(tctx, status, "EchoData failed");
+
+ /* check the answer */
+ if (memcmp(r.out.out_data, r.in.in_data, r.in.len) != 0) {
+ NDR_PRINT_OUT_DEBUG(echo_EchoData, &r);
+ torture_fail(tctx, "EchoData wrong answer");
+ }
+
+ torture_comment(tctx, "Echo '%*.*s' -> '%*.*s'\n",
+ r.in.len, r.in.len,
+ r.in.in_data,
+ r.in.len, r.in.len,
+ r.out.out_data);
+ return true;
+}
+
+
+static void irpc_callback(struct irpc_request *irpc)
+{
+ struct echo_AddOne *r = (struct echo_AddOne *)irpc->r;
+ int *pong_count = (int *)irpc->async.private;
+ NTSTATUS status = irpc_call_recv(irpc);
+ if (!NT_STATUS_IS_OK(status)) {
+ printf("irpc call failed - %s\n", nt_errstr(status));
+ }
+ if (*r->out.out_data != r->in.in_data + 1) {
+ printf("AddOne wrong answer - %u + 1 = %u should be %u\n",
+ r->in.in_data, *r->out.out_data, r->in.in_data+1);
+ }
+ (*pong_count)++;
+}
+
+/*
+ test echo speed
+*/
+static bool test_speed(struct torture_context *tctx,
+ const void *tcase_data,
+ const void *test_data)
+{
+ int ping_count = 0;
+ int pong_count = 0;
+ const struct irpc_test_data *data = (const struct irpc_test_data *)tcase_data;
+ struct timeval tv;
+ struct echo_AddOne r;
+ TALLOC_CTX *mem_ctx = tctx;
+ int timelimit = torture_setting_int(tctx, "timelimit", 10);
+
+ tv = timeval_current();
+
+ r.in.in_data = 0;
+
+ torture_comment(tctx, "Sending echo for %d seconds\n", timelimit);
+ while (timeval_elapsed(&tv) < timelimit) {
+ struct irpc_request *irpc;
+
+ irpc = IRPC_CALL_SEND(data->msg_ctx1, cluster_id(0, MSG_ID2),
+ rpcecho, ECHO_ADDONE,
+ &r, mem_ctx);
+ torture_assert(tctx, irpc != NULL, "AddOne send failed");
+
+ irpc->async.fn = irpc_callback;
+ irpc->async.private = &pong_count;
+
+ ping_count++;
+
+ while (ping_count > pong_count + 20) {
+ event_loop_once(data->ev);
+ }
+ }
+
+ torture_comment(tctx, "waiting for %d remaining replies (done %d)\n",
+ ping_count - pong_count, pong_count);
+ while (timeval_elapsed(&tv) < 30 && pong_count < ping_count) {
+ event_loop_once(data->ev);
+ }
+
+ torture_assert_int_equal(tctx, ping_count, pong_count, "ping test failed");
+
+ torture_comment(tctx, "echo rate of %.0f messages/sec\n",
+ (ping_count+pong_count)/timeval_elapsed(&tv));
+ return true;
+}
+
+
+static bool irpc_setup(struct torture_context *tctx, void **_data)
+{
+ struct irpc_test_data *data;
+
+ *_data = data = talloc(tctx, struct irpc_test_data);
+
+ lp_set_cmdline(tctx->lp_ctx, "pid directory", "piddir.tmp");
+
+ data->ev = tctx->ev;
+ torture_assert(tctx, data->msg_ctx1 =
+ messaging_init(tctx,
+ lp_messaging_path(tctx, tctx->lp_ctx),
+ cluster_id(0, MSG_ID1),
+ lp_iconv_convenience(tctx->lp_ctx),
+ data->ev),
+ "Failed to init first messaging context");
+
+ torture_assert(tctx, data->msg_ctx2 =
+ messaging_init(tctx,
+ lp_messaging_path(tctx, tctx->lp_ctx),
+ cluster_id(0, MSG_ID2),
+ lp_iconv_convenience(tctx->lp_ctx),
+ data->ev),
+ "Failed to init second messaging context");
+
+ /* register the server side function */
+ IRPC_REGISTER(data->msg_ctx1, rpcecho, ECHO_ADDONE, irpc_AddOne, NULL);
+ IRPC_REGISTER(data->msg_ctx2, rpcecho, ECHO_ADDONE, irpc_AddOne, NULL);
+
+ IRPC_REGISTER(data->msg_ctx1, rpcecho, ECHO_ECHODATA, irpc_EchoData, NULL);
+ IRPC_REGISTER(data->msg_ctx2, rpcecho, ECHO_ECHODATA, irpc_EchoData, NULL);
+
+ return true;
+}
+
+struct torture_suite *torture_local_irpc(TALLOC_CTX *mem_ctx)
+{
+ struct torture_suite *suite = torture_suite_create(mem_ctx, "IRPC");
+ struct torture_tcase *tcase = torture_suite_add_tcase(suite, "irpc");
+ int i;
+ uint32_t *values = talloc_array(tcase, uint32_t, 5);
+
+ values[0] = 0;
+ values[1] = 0x7FFFFFFE;
+ values[2] = 0xFFFFFFFE;
+ values[3] = 0xFFFFFFFF;
+ values[4] = random() & 0xFFFFFFFF;
+
+ tcase->setup = irpc_setup;
+
+ for (i = 0; i < 5; i++) {
+ torture_tcase_add_test_const(tcase, "addone", test_addone,
+ (void *)values[i]);
+ }
+
+ torture_tcase_add_test_const(tcase, "echodata", test_echodata, NULL);
+ torture_tcase_add_test_const(tcase, "speed", test_speed, NULL);
+
+ return suite;
+}
diff --git a/source4/lib/messaging/tests/messaging.c b/source4/lib/messaging/tests/messaging.c
new file mode 100644
index 0000000000..f66b3a5b43
--- /dev/null
+++ b/source4/lib/messaging/tests/messaging.c
@@ -0,0 +1,145 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ local test for messaging code
+
+ Copyright (C) Andrew Tridgell 2004
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
+#include "lib/events/events.h"
+#include "lib/messaging/irpc.h"
+#include "torture/torture.h"
+#include "cluster/cluster.h"
+#include "param/param.h"
+
+
+static uint32_t msg_pong;
+
+static void ping_message(struct messaging_context *msg, void *private,
+ uint32_t msg_type, struct server_id src, DATA_BLOB *data)
+{
+ NTSTATUS status;
+ status = messaging_send(msg, src, msg_pong, data);
+ if (!NT_STATUS_IS_OK(status)) {
+ printf("pong failed - %s\n", nt_errstr(status));
+ }
+}
+
+static void pong_message(struct messaging_context *msg, void *private,
+ uint32_t msg_type, struct server_id src, DATA_BLOB *data)
+{
+ int *count = private;
+ (*count)++;
+}
+
+static void exit_message(struct messaging_context *msg, void *private,
+ uint32_t msg_type, struct server_id src, DATA_BLOB *data)
+{
+ talloc_free(private);
+ exit(0);
+}
+
+/*
+ test ping speed
+*/
+static bool test_ping_speed(struct torture_context *tctx)
+{
+ struct event_context *ev;
+ struct messaging_context *msg_client_ctx;
+ struct messaging_context *msg_server_ctx;
+ int ping_count = 0;
+ int pong_count = 0;
+ struct timeval tv;
+ int timelimit = torture_setting_int(tctx, "timelimit", 10);
+ uint32_t msg_ping, msg_exit;
+
+ lp_set_cmdline(tctx->lp_ctx, "pid directory", "piddir.tmp");
+
+ ev = tctx->ev;
+
+ msg_server_ctx = messaging_init(tctx,
+ lp_messaging_path(tctx, tctx->lp_ctx),
+ cluster_id(0, 1),
+ lp_iconv_convenience(tctx->lp_ctx),
+ ev);
+
+ torture_assert(tctx, msg_server_ctx != NULL, "Failed to init ping messaging context");
+
+ messaging_register_tmp(msg_server_ctx, NULL, ping_message, &msg_ping);
+ messaging_register_tmp(msg_server_ctx, tctx, exit_message, &msg_exit);
+
+ msg_client_ctx = messaging_init(tctx,
+ lp_messaging_path(tctx, tctx->lp_ctx),
+ cluster_id(0, 2),
+ lp_iconv_convenience(tctx->lp_ctx),
+ ev);
+
+ torture_assert(tctx, msg_client_ctx != NULL,
+ "msg_client_ctx messaging_init() failed");
+
+ messaging_register_tmp(msg_client_ctx, &pong_count, pong_message, &msg_pong);
+
+ tv = timeval_current();
+
+ torture_comment(tctx, "Sending pings for %d seconds\n", timelimit);
+ while (timeval_elapsed(&tv) < timelimit) {
+ DATA_BLOB data;
+ NTSTATUS status1, status2;
+
+ data.data = discard_const_p(uint8_t, "testing");
+ data.length = strlen((const char *)data.data);
+
+ status1 = messaging_send(msg_client_ctx, cluster_id(0, 1), msg_ping, &data);
+ status2 = messaging_send(msg_client_ctx, cluster_id(0, 1), msg_ping, NULL);
+
+ torture_assert_ntstatus_ok(tctx, status1, "msg1 failed");
+ ping_count++;
+
+ torture_assert_ntstatus_ok(tctx, status2, "msg2 failed");
+ ping_count++;
+
+ while (ping_count > pong_count + 20) {
+ event_loop_once(ev);
+ }
+ }
+
+ torture_comment(tctx, "waiting for %d remaining replies (done %d)\n",
+ ping_count - pong_count, pong_count);
+ while (timeval_elapsed(&tv) < 30 && pong_count < ping_count) {
+ event_loop_once(ev);
+ }
+
+ torture_comment(tctx, "sending exit\n");
+ messaging_send(msg_client_ctx, cluster_id(0, 1), msg_exit, NULL);
+
+ torture_assert_int_equal(tctx, ping_count, pong_count, "ping test failed");
+
+ torture_comment(tctx, "ping rate of %.0f messages/sec\n",
+ (ping_count+pong_count)/timeval_elapsed(&tv));
+
+ talloc_free(msg_client_ctx);
+ talloc_free(msg_server_ctx);
+
+ return true;
+}
+
+struct torture_suite *torture_local_messaging(TALLOC_CTX *mem_ctx)
+{
+ struct torture_suite *s = torture_suite_create(mem_ctx, "MESSAGING");
+ torture_suite_add_simple_test(s, "ping_speed", test_ping_speed);
+ return s;
+}