diff options
author | Alfred E. Heggestad <alfred.heggestad@gmail.com> | 2017-02-23 19:21:50 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-02-23 19:21:50 +0100 |
commit | fb6bf93a7816516247523bd004737b2d1f3bba86 (patch) | |
tree | 334abf16f49890e6825c815a5b889f675c2033fb /test/message.c | |
parent | 39ff942fa874ff0d698d3ac938a6c8c741afb107 (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.c | 232 |
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; +} |