diff options
Diffstat (limited to 'modules')
-rw-r--r-- | modules/selftest/cmd.c | 77 | ||||
-rw-r--r-- | modules/selftest/module.mk | 11 | ||||
-rw-r--r-- | modules/selftest/selftest.c | 75 | ||||
-rw-r--r-- | modules/selftest/selftest.h | 58 | ||||
-rw-r--r-- | modules/selftest/sip_server.c | 97 | ||||
-rw-r--r-- | modules/selftest/ua.c | 154 |
6 files changed, 472 insertions, 0 deletions
diff --git a/modules/selftest/cmd.c b/modules/selftest/cmd.c new file mode 100644 index 0000000..a0e5e2c --- /dev/null +++ b/modules/selftest/cmd.c @@ -0,0 +1,77 @@ +/** + * @file selftest/cmd.c Baresip selftest -- cmd + * + * Copyright (C) 2010 Creytiv.com + */ +#include <re.h> +#include <baresip.h> +#include "selftest.h" + + +static bool cmd_called; + + +static int cmd_test(struct re_printf *pf, void *arg) +{ + struct cmd_arg *carg = arg; + int err = 0; + (void)pf; + + ASSERT_EQ(false, cmd_called); + + ASSERT_EQ('@', carg->key); + ASSERT_TRUE(NULL == carg->prm); + ASSERT_EQ(true, carg->complete); + + cmd_called = true; + + out: + return err; +} + + +static const struct cmd cmdv[] = { + {'@', 0, "Test command", cmd_test}, +}; + + +static int vprintf_null(const char *p, size_t size, void *arg) +{ + (void)p; + (void)size; + (void)arg; + return 0; +} + + +static struct re_printf pf_null = {vprintf_null, 0}; + + +int test_cmd(void) +{ + struct cmd_ctx *ctx = 0; + int err = 0; + + cmd_called = false; + + err = cmd_register(cmdv, ARRAY_SIZE(cmdv)); + ASSERT_EQ(0, err); + + /* issue a different command */ + err = cmd_process(&ctx, 'h', &pf_null); + ASSERT_EQ(0, err); + ASSERT_EQ(false, cmd_called); + + /* issue our command, expect handler to be called */ + err = cmd_process(&ctx, '@', &pf_null); + ASSERT_EQ(0, err); + ASSERT_EQ(true, cmd_called); + + cmd_unregister(cmdv); + + /* verify that context was not created */ + ASSERT_TRUE(NULL == ctx); + + out: + return err; +} diff --git a/modules/selftest/module.mk b/modules/selftest/module.mk new file mode 100644 index 0000000..d47f2fe --- /dev/null +++ b/modules/selftest/module.mk @@ -0,0 +1,11 @@ +# +# module.mk +# +# Copyright (C) 2010 Creytiv.com +# + +MOD := selftest +$(MOD)_SRCS += selftest.c cmd.c ua.c +$(MOD)_SRCS += sip_server.c + +include mk/mod.mk diff --git a/modules/selftest/selftest.c b/modules/selftest/selftest.c new file mode 100644 index 0000000..87e89d3 --- /dev/null +++ b/modules/selftest/selftest.c @@ -0,0 +1,75 @@ +/** + * @file selftest.c Selftest for Baresip core + * + * Copyright (C) 2010 Creytiv.com + */ +#include <re.h> +#include <baresip.h> +#include "selftest.h" + + +static void timeout_handler(void *arg) +{ + int *err = arg; + + warning("selftest: re_main() loop timed out -- test hung..\n"); + + *err = ETIMEDOUT; + + re_cancel(); +} + + +int re_main_timeout(uint32_t timeout) +{ + struct tmr tmr; + int err = 0; + + tmr_init(&tmr); + + tmr_start(&tmr, timeout * 1000, timeout_handler, &err); + re_main(NULL); + + tmr_cancel(&tmr); + return err; +} + + +static int module_init(void) +{ + int err; + + err = test_cmd(); + if (err) + return err; + + err = test_ua_alloc(); + if (err) + return err; + + err = test_uag_find_param(); + if (err) + return err; + + err = test_ua_register(); + if (err) + return err; + + re_printf("\x1b[32mselftest passed successfully\x1b[;m\n"); + + return 0; +} + + +static int module_close(void) +{ + return 0; +} + + +const struct mod_export DECL_EXPORTS(selftest) = { + "selftest", + "application", + module_init, + module_close +}; diff --git a/modules/selftest/selftest.h b/modules/selftest/selftest.h new file mode 100644 index 0000000..f460b3f --- /dev/null +++ b/modules/selftest/selftest.h @@ -0,0 +1,58 @@ +/** + * @file selftest.h Selftest for Baresip core -- internal API + * + * Copyright (C) 2010 Creytiv.com + */ + + +#define ASSERT_TRUE(cond) \ + if (!(cond)) { \ + warning("selftest: ASSERT_TRUE: %s:%u:\n", \ + __FILE__, __LINE__); \ + err = EINVAL; \ + goto out; \ + } + +#define ASSERT_EQ(expected, actual) \ + if ((expected) != (actual)) { \ + warning("selftest: ASSERT_EQ: %s:%u:" \ + " expected=%d, actual=%d\n", \ + __FILE__, __LINE__, \ + (int)(expected), (int)(actual)); \ + err = EINVAL; \ + goto out; \ + } + +#define ASSERT_STREQ(expected, actual) \ + if (0 != str_cmp((expected), (actual))) { \ + warning("selftest: ASSERT_STREQ: %s:%u:" \ + " expected = '%s', actual = '%s'\n", \ + __FILE__, __LINE__, \ + (expected), (actual)); \ + err = EBADMSG; \ + goto out; \ + } + + +/* helpers */ + +int re_main_timeout(uint32_t timeout); + +struct sip_server { + struct sa laddr; + struct udp_sock *us; + struct sip *sip; + + bool got_register_req; + bool terminate; +}; + +int sip_server_create(struct sip_server **srvp); + + +/* test cases */ + +int test_cmd(void); +int test_ua_alloc(void); +int test_uag_find_param(void); +int test_ua_register(void); diff --git a/modules/selftest/sip_server.c b/modules/selftest/sip_server.c new file mode 100644 index 0000000..1962c3c --- /dev/null +++ b/modules/selftest/sip_server.c @@ -0,0 +1,97 @@ +/** + * @file sip_server.c Selftest for Baresip core -- SIP Server + * + * Copyright (C) 2010 Creytiv.com + */ +#include <string.h> +#include <re.h> +#include <baresip.h> +#include "selftest.h" + + +static void udp_recv(const struct sa *src, struct mbuf *mb, void *arg) +{ + struct sip_server *srv = arg; + struct sip_msg *msg; + int err; + +#if 0 + re_printf("%b\n", mb->buf, mb->end); +#endif + + err = sip_msg_decode(&msg, mb); + if (err) { + warning("selftest: sip_msg_decode: %m\n", err); + return; + } + + if (0 == pl_strcmp(&msg->met, "REGISTER")) + srv->got_register_req = true; + + msg->sock = mem_ref(srv->us); + msg->src = *src; + msg->dst = srv->laddr; + msg->tp = SIP_TRANSP_UDP; + + if (srv->terminate) + err = sip_reply(srv->sip, msg, 503, "Server Error"); + else + err = sip_reply(srv->sip, msg, 200, "OK"); + if (err) { + warning("selftest: could not reply: %m\n", err); + } + + mem_deref(msg); + + if (srv->terminate) + re_cancel(); +} + + +static void destructor(void *arg) +{ + struct sip_server *srv = arg; + + sip_close(srv->sip, false); + mem_deref(srv->sip); + + mem_deref(srv->us); +} + + +int sip_server_create(struct sip_server **srvp) +{ + struct sip_server *srv; + int err; + + srv = mem_zalloc(sizeof *srv, destructor); + if (!srv) + return ENOMEM; + + sa_set_str(&srv->laddr, "127.0.0.1", 0); + + err = sip_alloc(&srv->sip, NULL, 16, 16, 16, + "dummy SIP registrar", NULL, NULL); + if (err) + goto out; + + err = sip_transp_add(srv->sip, SIP_TRANSP_UDP, &srv->laddr); + if (err) + goto out; + + err = udp_listen(&srv->us, &srv->laddr, udp_recv, srv); + if (err) + goto out; + + err = udp_local_get(srv->us, &srv->laddr); + if (err) + goto out; + + out: + if (err) + mem_deref(srv); + else + *srvp = srv; + + return err; +} diff --git a/modules/selftest/ua.c b/modules/selftest/ua.c new file mode 100644 index 0000000..0117867 --- /dev/null +++ b/modules/selftest/ua.c @@ -0,0 +1,154 @@ +/** + * @file selftest/ua.c Baresip selftest -- User-Agent (UA) + * + * Copyright (C) 2010 Creytiv.com + */ +#include <string.h> +#include <re.h> +#include <baresip.h> +#include "selftest.h" + + +struct test { + struct sip_server *srv; + struct ua *ua; + int err; + bool got_register_ok; +}; + + +static void ua_event_handler(struct ua *ua, enum ua_event ev, + struct call *call, const char *prm, void *arg) +{ + struct test *t = arg; + int err = 0; + (void)call; + (void)prm; + + ASSERT_TRUE(t != NULL); + + if (ua != t->ua) + return; + + if (ev == UA_EVENT_REGISTER_OK) { + + t->got_register_ok = true; + + /* verify register success */ + ASSERT_TRUE(ua_isregistered(t->ua)); + + /* Terminate SIP Server, then De-REGISTER */ + t->srv->terminate = true; + t->ua = mem_deref(t->ua); + } + + out: + if (err) { + warning("selftest: event handler error: %m\n", err); + t->err = err; + } +} + + +int test_ua_register(void) +{ + struct test t; + char aor[256]; + int err; + + memset(&t, 0, sizeof t); + + err = sip_server_create(&t.srv); + if (err) + goto out; + + re_snprintf(aor, sizeof(aor), "sip:x:x@%J", &t.srv->laddr); + + err = ua_alloc(&t.ua, aor); + if (err) + goto out; + + err = uag_event_register(ua_event_handler, &t); + if (err) + goto out; + + /* run main-loop with timeout, wait for events */ + err = re_main_timeout(5); + if (err) + goto out; + + if (t.err) + err = t.err; + + ASSERT_TRUE(t.srv->got_register_req); + ASSERT_TRUE(t.got_register_ok); + + out: + if (err) { + warning("selftest: ua_register test failed (%m)\n", err); + } + uag_event_unregister(ua_event_handler); + mem_deref(t.srv); + mem_deref(t.ua); + + return err; +} + + +int test_ua_alloc(void) +{ + struct ua *ua; + uint32_t n_uas = list_count(uag_list()); + int err = 0; + + /* make sure we dont have that UA already */ + ASSERT_TRUE(NULL == uag_find_aor("sip:user@127.0.0.1")); + + err = ua_alloc(&ua, "Foo <sip:user:pass@127.0.0.1>;regint=0"); + if (err) + return err; + + /* verify this UA-instance */ + ASSERT_EQ(-1, ua_sipfd(ua)); + ASSERT_TRUE(!ua_isregistered(ua)); + ASSERT_STREQ("sip:user@127.0.0.1", ua_aor(ua)); + ASSERT_TRUE(NULL == ua_call(ua)); + + /* verify global UA keeper */ + ASSERT_EQ((n_uas + 1), list_count(uag_list())); + ASSERT_TRUE(ua == uag_find_aor("sip:user@127.0.0.1")); + + mem_deref(ua); + + ASSERT_EQ((n_uas), list_count(uag_list())); + + out: + return err; +} + + +int test_uag_find_param(void) +{ + struct ua *ua1 = NULL, *ua2 = NULL; + int err = 0; + + ASSERT_TRUE(NULL == uag_find_param("not", "found")); + + err = ua_alloc(&ua1, "<sip:x:x@127.0.0.1>;regint=0;abc"); + err |= ua_alloc(&ua2, "<sip:x:x@127.0.0.1>;regint=0;def=123"); + if (err) + goto out; + + ASSERT_TRUE(ua1 == uag_find_param("abc", NULL)); + ASSERT_TRUE(NULL == uag_find_param("abc", "123")); + ASSERT_TRUE(ua2 == uag_find_param("def", NULL)); + ASSERT_TRUE(ua2 == uag_find_param("def", "123")); + + ASSERT_TRUE(NULL == uag_find_param("not", "found")); + + out: + mem_deref(ua2); + mem_deref(ua1); + + return err; +} |