summaryrefslogtreecommitdiff
path: root/test/message.c
diff options
context:
space:
mode:
authorAlfred E. Heggestad <alfred.heggestad@gmail.com>2017-02-23 19:21:50 +0100
committerGitHub <noreply@github.com>2017-02-23 19:21:50 +0100
commitfb6bf93a7816516247523bd004737b2d1f3bba86 (patch)
tree334abf16f49890e6825c815a5b889f675c2033fb /test/message.c
parent39ff942fa874ff0d698d3ac938a6c8c741afb107 (diff)
Message reentrant (#214)
* message: make it re-entrant * clean up message test-code
Diffstat (limited to 'test/message.c')
-rw-r--r--test/message.c232
1 files changed, 232 insertions, 0 deletions
diff --git a/test/message.c b/test/message.c
new file mode 100644
index 0000000..467fd8a
--- /dev/null
+++ b/test/message.c
@@ -0,0 +1,232 @@
+/**
+ * @file test/message.c Baresip selftest -- message sending
+ *
+ * Copyright (C) 2010 Creytiv.com
+ */
+#include <string.h>
+#include <re.h>
+#include <baresip.h>
+#include "test.h"
+
+
+struct test {
+ enum sip_transp transp;
+ int err;
+};
+
+struct endpoint {
+ struct test *test;
+ struct endpoint *other;
+ struct message *message;
+ struct ua *ua;
+ char uri[256];
+ unsigned n_msg;
+ unsigned n_resp;
+};
+
+
+static const char dummy_msg[] = "hei paa deg";
+static const char text_plain[] = "text/plain";
+
+
+static bool endpoint_is_complete(const struct endpoint *ep)
+{
+ return ep->n_msg >= 1 || ep->n_resp >= 1;
+}
+
+
+static bool test_is_complete(struct endpoint *ep)
+{
+ return endpoint_is_complete(ep) &&
+ endpoint_is_complete(ep->other);
+}
+
+
+static void message_recv_handler(const struct pl *peer, const struct pl *ctype,
+ struct mbuf *body, void *arg)
+{
+ struct endpoint *ep = arg;
+ int err = 0;
+
+ info("[ %s ] recv msg from %r: \"%b\"\n", ep->uri, peer,
+ mbuf_buf(body), mbuf_get_left(body));
+
+ TEST_STRCMP(text_plain, strlen(text_plain),
+ ctype->p, ctype->l);
+
+ TEST_STRCMP(dummy_msg, str_len(dummy_msg),
+ mbuf_buf(body), mbuf_get_left(body));
+
+ ++ep->n_msg;
+
+ if (test_is_complete(ep)) {
+ re_cancel();
+ return;
+ }
+
+ out:
+ if (err) {
+ ep->test->err = err;
+ re_cancel();
+ }
+}
+
+
+static void send_resp_handler(int err, const struct sip_msg *msg, void *arg)
+{
+ struct endpoint *ep = arg;
+
+ ++ep->n_resp;
+
+ if (err) {
+ warning("sending failed: %m\n", err);
+ goto out;
+ }
+
+ if (msg->scode >= 300) {
+ warning("sending failed: %u %r\n", msg->scode, &msg->reason);
+ err = EPROTO;
+ goto out;
+ }
+
+ info("[ %s ] message sent OK\n", ep->uri);
+
+ ASSERT_EQ(ep->test->transp, msg->tp);
+ ASSERT_EQ(200, msg->scode);
+
+ if (test_is_complete(ep)) {
+ re_cancel();
+ return;
+ }
+
+ out:
+ if (err) {
+ ep->test->err = err;
+ re_cancel();
+ }
+}
+
+
+static void endpoint_destructor(void *data)
+{
+ struct endpoint *ep = data;
+
+ mem_deref(ep->message);
+ mem_deref(ep->ua);
+}
+
+
+static int endpoint_alloc(struct endpoint **epp, struct test *test,
+ const char *name, enum sip_transp transp)
+{
+ struct endpoint *ep;
+ struct sa laddr;
+ char aor[256];
+ int err = 0;
+
+ err = sip_transp_laddr(uag_sip(), &laddr, transp, NULL);
+ TEST_ERR(err);
+
+ ep = mem_zalloc(sizeof(*ep), endpoint_destructor);
+ if (!ep)
+ return ENOMEM;
+
+ ep->test = test;
+
+ if (re_snprintf(aor, sizeof(aor),
+ "%s <sip:%s:xxx@127.0.0.1;transport=%s>;regint=0",
+ name, name,
+ sip_transp_name(transp)) < 0) {
+ err = ENOMEM;
+ goto out;
+ }
+
+ if (re_snprintf(ep->uri, sizeof(ep->uri), "sip:%s@%J;transport=%s",
+ name,
+ &laddr, sip_transp_name(transp)) < 0) {
+ err = ENOMEM;
+ goto out;
+ }
+
+ err = ua_alloc(&ep->ua, aor);
+ if (err)
+ goto out;
+
+ err = message_init(&ep->message);
+ TEST_ERR(err);
+
+ out:
+ if (err)
+ mem_deref(ep);
+ else
+ *epp = ep;
+
+ return err;
+}
+
+
+static int test_message_transp(enum sip_transp transp)
+{
+ struct test test;
+ struct endpoint *a, *b;
+ bool enable_udp, enable_tcp;
+ int err = 0;
+
+ enable_udp = transp == SIP_TRANSP_UDP;
+ enable_tcp = transp == SIP_TRANSP_TCP;
+
+ memset(&test, 0, sizeof(test));
+
+ test.transp = transp;
+
+ err = ua_init("test", enable_udp, enable_tcp, false, false);
+ TEST_ERR(err);
+
+ err = endpoint_alloc(&a, &test, "a", transp);
+ TEST_ERR(err);
+
+ err = endpoint_alloc(&b, &test, "b", transp);
+ TEST_ERR(err);
+
+ a->other = b;
+ b->other = a;
+
+ /* NOTE: can only listen to one global instance for now */
+ err = message_listen(NULL, b->message, message_recv_handler, b);
+ TEST_ERR(err);
+
+ /* Send a message from A to B */
+ err = message_send(a->ua, b->uri, dummy_msg, send_resp_handler, a);
+ TEST_ERR(err);
+
+ err = re_main_timeout(1000);
+ TEST_ERR(err);
+
+ TEST_ERR(test.err);
+ ASSERT_EQ(0, a->n_msg);
+ ASSERT_EQ(1, a->n_resp);
+ ASSERT_EQ(1, b->n_msg);
+ ASSERT_EQ(0, b->n_resp);
+
+ out:
+ mem_deref(b);
+ mem_deref(a);
+ ua_close();
+
+ return err;
+}
+
+
+int test_message(void)
+{
+ int err = 0;
+
+ err = test_message_transp(SIP_TRANSP_UDP);
+ TEST_ERR(err);
+
+ err |= test_message_transp(SIP_TRANSP_TCP);
+ TEST_ERR(err);
+
+ out:
+ return err;
+}