summaryrefslogtreecommitdiff
path: root/modules
diff options
context:
space:
mode:
authorAlfred E. Heggestad <aeh@db.org>2014-04-12 16:04:48 +0200
committerAlfred E. Heggestad <aeh@db.org>2014-04-12 16:04:48 +0200
commitc789e9a72c9f65f8f598823da0adb82cde2b3bce (patch)
treedd91fb42f686894613436744d5cfb4e464a4d369 /modules
parentcfa7d320a82be9c85ec31235de4c7b79336bcbe2 (diff)
selftest: new module for testing baresip core
the selftest module is using the public API of the Baresip core (in baresip.h) to verify the expected behaviour and to test various protocol scenarios. the module can be loaded with the 'module' directive or 'module_tmp' directive: module_tmp selftest.so OR: module selftest.so
Diffstat (limited to 'modules')
-rw-r--r--modules/selftest/cmd.c77
-rw-r--r--modules/selftest/module.mk11
-rw-r--r--modules/selftest/selftest.c75
-rw-r--r--modules/selftest/selftest.h58
-rw-r--r--modules/selftest/sip_server.c97
-rw-r--r--modules/selftest/ua.c154
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;
+}