diff options
-rw-r--r-- | test/call.c | 236 | ||||
-rw-r--r-- | test/main.c | 2 | ||||
-rw-r--r-- | test/srcs.mk | 1 | ||||
-rw-r--r-- | test/test.h | 3 |
4 files changed, 242 insertions, 0 deletions
diff --git a/test/call.c b/test/call.c new file mode 100644 index 0000000..cad90a6 --- /dev/null +++ b/test/call.c @@ -0,0 +1,236 @@ +/** + * @file test/call.c Baresip selftest -- call + * + * Copyright (C) 2010 - 2015 Creytiv.com + */ +#include <string.h> +#include <re.h> +#include <baresip.h> +#include "test.h" + + +#define MAGIC 0x7004ca11 + + +enum behaviour { + BEHAVIOUR_ANSWER = 0, + BEHAVIOUR_REJECT +}; + +struct agent { + struct agent *peer; + struct ua *ua; + uint16_t close_scode; + bool failed; + + unsigned n_incoming; + unsigned n_established; + unsigned n_closed; +}; + +struct fixture { + uint32_t magic; + struct agent a, b; + struct sa laddr_sip; + enum behaviour behaviour; + char buri[256]; + int err; +}; + + +#define fixture_init(f) \ + memset(f, 0, sizeof(*f)); \ + \ + f->magic = MAGIC; \ + aucodec_register(&dummy_pcma); \ + \ + err = ua_alloc(&f->a.ua, "A <sip:a:xxx@127.0.0.1>;regint=0"); \ + TEST_ERR(err); \ + err = ua_alloc(&f->b.ua, "B <sip:b:xxx@127.0.0.1>;regint=0"); \ + TEST_ERR(err); \ + \ + f->a.peer = &f->b; \ + f->b.peer = &f->a; \ + \ + err = uag_event_register(event_handler, f); \ + TEST_ERR(err); \ + \ + err = sip_transp_laddr(uag_sip(), &f->laddr_sip, \ + SIP_TRANSP_UDP, NULL); \ + TEST_ERR(err); \ + \ + re_snprintf(f->buri, sizeof(f->buri), "sip:b@%J", &f->laddr_sip); + + +#define fixture_close(f) \ + mem_deref(f->b.ua); \ + mem_deref(f->a.ua); \ + \ + aucodec_unregister(&dummy_pcma); \ + \ + uag_event_unregister(event_handler) + + +static struct aucodec dummy_pcma = { + .pt = "8", + .name = "PCMA", + .srate = 8000, + .ch = 1, +}; + + +static void event_handler(struct ua *ua, enum ua_event ev, + struct call *call, const char *prm, void *arg) +{ + struct fixture *f = arg; + struct agent *ag; + int err = 0; + + ASSERT_TRUE(ua != NULL); + ASSERT_TRUE(call != NULL); + ASSERT_TRUE(f != NULL); + ASSERT_EQ(MAGIC, f->magic); + + if (ua == f->a.ua) + ag = &f->a; + else if (ua == f->b.ua) + ag = &f->b; + else { + warning("ua not found\n"); + return; + } + +#if 0 + re_printf("[ %s ] event: %s (%s)\n", + ua_aor(ua), uag_event_str(ev), prm); +#endif + + switch (ev) { + + case UA_EVENT_CALL_INCOMING: + ++ag->n_incoming; + + switch (f->behaviour) { + + case BEHAVIOUR_ANSWER: + err = ua_answer(ua, call); + if (err) { + warning("ua_answer failed (%m)\n", err); + goto out; + } + break; + + case BEHAVIOUR_REJECT: + ua_hangup(ua, call, 0, 0); + call = NULL; + ag->failed = true; + break; + + default: + break; + } + break; + + case UA_EVENT_CALL_ESTABLISHED: + ++ag->n_established; + + if (ag->peer->n_established) { + re_printf("@@@ test complete\n"); + re_cancel(); + } + break; + + case UA_EVENT_CALL_CLOSED: + ag->failed = true; + ++ag->n_closed; + + ag->close_scode = call_scode(call); + + if (ag->peer->n_closed) { + re_printf("@@@ test complete\n"); + re_cancel(); + } + break; + + default: + break; + } + + if (ag->failed && ag->peer->failed) { + re_cancel(); + return; + } + + out: + if (err) { + warning("error in event-handler (%m)\n", err); + f->err = err; + re_cancel(); + } +} + + +int test_call_answer(void) +{ + struct fixture fix, *f = &fix; + int err = 0; + + fixture_init(f); + + f->behaviour = BEHAVIOUR_ANSWER; + + /* Make a call from A to B */ + err = ua_connect(f->a.ua, 0, NULL, f->buri, NULL, VIDMODE_OFF); + TEST_ERR(err); + + /* run main-loop with timeout, wait for events */ + err = re_main_timeout(5); + TEST_ERR(err); + TEST_ERR(fix.err); + + ASSERT_EQ(0, fix.a.n_incoming); + ASSERT_EQ(1, fix.a.n_established); + ASSERT_EQ(0, fix.a.n_closed); + ASSERT_EQ(0, fix.a.close_scode); + + ASSERT_EQ(1, fix.b.n_incoming); + ASSERT_EQ(1, fix.b.n_established); + ASSERT_EQ(0, fix.b.n_closed); + + out: + fixture_close(f); + + return err; +} + + +int test_call_reject(void) +{ + struct fixture fix, *f = &fix; + int err = 0; + + fixture_init(f); + + f->behaviour = BEHAVIOUR_REJECT; + + /* Make a call from A to B */ + err = ua_connect(f->a.ua, 0, NULL, f->buri, NULL, VIDMODE_OFF); + TEST_ERR(err); + + /* run main-loop with timeout, wait for events */ + err = re_main_timeout(5); + TEST_ERR(err); + TEST_ERR(fix.err); + + ASSERT_EQ(0, fix.a.n_incoming); + ASSERT_EQ(0, fix.a.n_established); + ASSERT_EQ(1, fix.a.n_closed); + + ASSERT_EQ(1, fix.b.n_incoming); + ASSERT_EQ(0, fix.b.n_established); + + out: + fixture_close(f); + + return err; +} diff --git a/test/main.c b/test/main.c index f10293a..a959a5e 100644 --- a/test/main.c +++ b/test/main.c @@ -23,6 +23,8 @@ static const struct test tests[] = { TEST(test_uag_find_param), TEST(test_ua_register), TEST(test_cplusplus), + TEST(test_call_answer), + TEST(test_call_reject), }; diff --git a/test/srcs.mk b/test/srcs.mk index 1caafbb..6195d10 100644 --- a/test/srcs.mk +++ b/test/srcs.mk @@ -11,6 +11,7 @@ TEST_SRCS += cmd.c TEST_SRCS += ua.c TEST_SRCS += cplusplus.c +TEST_SRCS += call.c # diff --git a/test/test.h b/test/test.h index 61ddd27..2600bd6 100644 --- a/test/test.h +++ b/test/test.h @@ -79,6 +79,9 @@ int test_ua_alloc(void); int test_uag_find_param(void); int test_ua_register(void); +int test_call_answer(void); +int test_call_reject(void); + #ifdef __cplusplus extern "C" { |