summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/cmd.c77
-rw-r--r--test/main.c86
-rw-r--r--test/sip_server.c113
-rw-r--r--test/srcs.mk13
-rw-r--r--test/test.c30
-rw-r--r--test/test.h58
-rw-r--r--test/ua.c156
7 files changed, 533 insertions, 0 deletions
diff --git a/test/cmd.c b/test/cmd.c
new file mode 100644
index 0000000..dfd42fa
--- /dev/null
+++ b/test/cmd.c
@@ -0,0 +1,77 @@
+/**
+ * @file test/cmd.c Baresip selftest -- cmd
+ *
+ * Copyright (C) 2010 Creytiv.com
+ */
+#include <re.h>
+#include <baresip.h>
+#include "test.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/test/main.c b/test/main.c
new file mode 100644
index 0000000..c32cd4b
--- /dev/null
+++ b/test/main.c
@@ -0,0 +1,86 @@
+/**
+ * @file test/main.c Selftest for Baresip core
+ *
+ * Copyright (C) 2010 Creytiv.com
+ */
+#include <re.h>
+#include <baresip.h>
+#include "test.h"
+
+
+static int run_tests(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;
+
+ return 0;
+}
+
+
+int main(void)
+{
+ struct config *config;
+ int err;
+
+ err = libre_init();
+ if (err)
+ return err;
+
+ re_printf("running test..\n");
+
+ /* note: run SIP-traffic on localhost */
+ config = conf_config();
+ if (!config) {
+ err = ENOENT;
+ goto out;
+ }
+ str_ncpy(config->sip.local, "127.0.0.1:0", sizeof(config->sip.local));
+
+ /* XXX: needed for ua tests */
+ err = ua_init("test", true, true, false, false);
+ if (err)
+ goto out;
+
+ err = run_tests();
+ if (err)
+ goto out;
+
+#if 1
+ ua_stop_all(false);
+ err = re_main_timeout(5);
+ if (err)
+ goto out;
+#endif
+
+ re_printf("\x1b[32mOK. selftest passed successfully\x1b[;m\n");
+
+ out:
+ if (err) {
+ warning("test failed (%m)\n", err);
+ re_printf("%H\n", re_debug, 0);
+ }
+ ua_stop_all(true);
+ ua_close();
+
+ libre_close();
+
+ tmr_debug();
+ mem_debug();
+
+ return err;
+}
diff --git a/test/sip_server.c b/test/sip_server.c
new file mode 100644
index 0000000..0e637de
--- /dev/null
+++ b/test/sip_server.c
@@ -0,0 +1,113 @@
+/**
+ * @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 "test.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("sip: %zu bytes from %J\n", mbuf_get_left(mb), src);
+ 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;
+ struct sa laddr_tp;
+ int err;
+
+ srv = mem_zalloc(sizeof *srv, destructor);
+ if (!srv)
+ return ENOMEM;
+
+ err = sa_set_str(&laddr_tp, "127.0.0.1", 0);
+ err |= sa_set_str(&srv->laddr, "127.0.0.1", 0);
+ if (err)
+ goto out;
+
+ 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, &laddr_tp);
+ if (err) {
+ warning("failed to add sip transport (%m)\n", err);
+ goto out;
+ }
+
+ err = udp_listen(&srv->us, &srv->laddr, udp_recv, srv);
+ if (err) {
+ warning("sip: udp_listen on '%J' failed (%d/%m)\n",
+ &srv->laddr, err, err);
+ goto out;
+ }
+
+ err = udp_local_get(srv->us, &srv->laddr);
+ if (err) {
+ warning("sip: udp_local_get\n");
+ goto out;
+ }
+
+#if 0
+ re_printf("sip: listen on %J\n", &srv->laddr);
+#endif
+
+ out:
+ if (err)
+ mem_deref(srv);
+ else
+ *srvp = srv;
+
+ return err;
+}
diff --git a/test/srcs.mk b/test/srcs.mk
new file mode 100644
index 0000000..df16f8b
--- /dev/null
+++ b/test/srcs.mk
@@ -0,0 +1,13 @@
+#
+# srcs.mk All application source files.
+#
+# Copyright (C) 2010 Creytiv.com
+#
+
+TEST_SRCS += cmd.c
+TEST_SRCS += ua.c
+
+TEST_SRCS += sip_server.c
+TEST_SRCS += test.c
+
+TEST_SRCS += main.c
diff --git a/test/test.c b/test/test.c
new file mode 100644
index 0000000..ec6f6fb
--- /dev/null
+++ b/test/test.c
@@ -0,0 +1,30 @@
+#include <re.h>
+#include <baresip.h>
+#include "test.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;
+}
diff --git a/test/test.h b/test/test.h
new file mode 100644
index 0000000..20807b6
--- /dev/null
+++ b/test/test.h
@@ -0,0 +1,58 @@
+/**
+ * @file test.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/test/ua.c b/test/ua.c
new file mode 100644
index 0000000..ddfa76e
--- /dev/null
+++ b/test/ua.c
@@ -0,0 +1,156 @@
+/**
+ * @file test/ua.c Baresip selftest -- User-Agent (UA)
+ *
+ * Copyright (C) 2010 Creytiv.com
+ */
+#include <string.h>
+#include <re.h>
+#include <baresip.h>
+#include "test.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) {
+ warning("failed to create sip server (%d/%m)\n", err, 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;
+}