summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/audio.c2
-rw-r--r--test/call.c99
-rw-r--r--test/main.c1
-rw-r--r--test/mock/mock_ausrc.c88
-rw-r--r--test/srcs.mk2
-rw-r--r--test/test.h9
6 files changed, 197 insertions, 4 deletions
diff --git a/src/audio.c b/src/audio.c
index c98e35c..2b5be6e 100644
--- a/src/audio.c
+++ b/src/audio.c
@@ -325,7 +325,7 @@ static void encode_rtp_send(struct audio *a, struct autx *tx,
size_t len;
int err;
- if (!tx->ac)
+ if (!tx->ac || !tx->ac->ench)
return;
tx->mb->pos = tx->mb->end = STREAM_PRESZ;
diff --git a/test/call.c b/test/call.c
index b752228..8495761 100644
--- a/test/call.c
+++ b/test/call.c
@@ -25,6 +25,7 @@ enum action {
};
struct agent {
+ struct fixture *fix; /* pointer to parent */
struct agent *peer;
struct ua *ua;
uint16_t close_scode;
@@ -33,6 +34,7 @@ struct agent {
unsigned n_incoming;
unsigned n_established;
unsigned n_closed;
+ unsigned n_dtmf_recv;
};
struct fixture {
@@ -48,9 +50,12 @@ struct fixture {
};
-#define fixture_init(f) \
+#define fixture_init_prm(f, prm) \
memset(f, 0, sizeof(*f)); \
\
+ f->a.fix = f; \
+ f->b.fix = f; \
+ \
err = ua_init("test", true, true, true, false); \
TEST_ERR(err); \
\
@@ -59,9 +64,11 @@ struct fixture {
f->exp_closed = 1; \
aucodec_register(&dummy_pcma); \
\
- err = ua_alloc(&f->a.ua, "A <sip:a:xxx@127.0.0.1>;regint=0"); \
+ err = ua_alloc(&f->a.ua, \
+ "A <sip:a:xxx@127.0.0.1>;regint=0" prm); \
TEST_ERR(err); \
- err = ua_alloc(&f->b.ua, "B <sip:b:xxx@127.0.0.1>;regint=0"); \
+ err = ua_alloc(&f->b.ua, \
+ "B <sip:b:xxx@127.0.0.1>;regint=0" prm); \
TEST_ERR(err); \
\
f->a.peer = &f->b; \
@@ -77,6 +84,10 @@ struct fixture {
re_snprintf(f->buri, sizeof(f->buri), "sip:b@%J", &f->laddr_sip);
+#define fixture_init(f) \
+ fixture_init_prm((f), "");
+
+
#define fixture_close(f) \
mem_deref(f->b.ua); \
mem_deref(f->a.ua); \
@@ -88,6 +99,12 @@ struct fixture {
ua_stop_all(true); \
ua_close();
+#define fixture_abort(f, error) \
+ do { \
+ (f)->err = (error); \
+ re_cancel(); \
+ } while (0)
+
static struct aucodec dummy_pcma = {
.pt = "8",
@@ -569,3 +586,79 @@ int test_call_max(void)
return err;
}
+
+
+static const char dtmf_digits[] = "123";
+
+
+static void dtmf_handler(struct call *call, char key, void *arg)
+{
+ struct agent *ag = arg;
+ int err = 0;
+
+ /* ignore key-release */
+ if (key == 0)
+ return;
+
+ ASSERT_EQ(dtmf_digits[ag->n_dtmf_recv], key);
+ ++ag->n_dtmf_recv;
+
+ if (ag->n_dtmf_recv >= str_len(dtmf_digits)) {
+ re_cancel();
+ }
+
+ out:
+ if (err) {
+ fixture_abort(ag->fix, err);
+ }
+}
+
+
+int test_call_dtmf(void)
+{
+ struct fixture fix, *f = &fix;
+ struct ausrc *ausrc = NULL;
+ size_t i, n = str_len(dtmf_digits);
+ int err = 0;
+
+ /* Use a low packet time, so the test completes quickly */
+ fixture_init_prm(f, ";ptime=1");
+
+ /* audio-source is needed for dtmf/telev to work */
+ err = mock_ausrc_register(&ausrc);
+ TEST_ERR(err);
+
+ 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(5000);
+ TEST_ERR(err);
+ TEST_ERR(fix.err);
+
+ call_set_handlers(ua_call(f->a.ua), NULL, dtmf_handler, &f->a);
+ call_set_handlers(ua_call(f->b.ua), NULL, dtmf_handler, &f->b);
+
+ /* send some DTMF digits from A to B .. */
+ for (i=0; i<n; i++) {
+ err = call_send_digit(ua_call(f->a.ua), dtmf_digits[i]);
+ TEST_ERR(err);
+ }
+
+ /* run main-loop with timeout, wait for events */
+ err = re_main_timeout(5000);
+ TEST_ERR(err);
+ TEST_ERR(fix.err);
+
+ ASSERT_EQ(0, fix.a.n_dtmf_recv);
+ ASSERT_EQ(n, fix.b.n_dtmf_recv);
+
+ out:
+ fixture_close(f);
+ mem_deref(ausrc);
+
+ return err;
+}
diff --git a/test/main.c b/test/main.c
index c0bc1c1..6991671 100644
--- a/test/main.c
+++ b/test/main.c
@@ -27,6 +27,7 @@ static const struct test tests[] = {
TEST(test_call_rtp_timeout),
TEST(test_call_multiple),
TEST(test_call_max),
+ TEST(test_call_dtmf),
TEST(test_cmd),
TEST(test_contact),
TEST(test_cplusplus),
diff --git a/test/mock/mock_ausrc.c b/test/mock/mock_ausrc.c
new file mode 100644
index 0000000..8e29dbf
--- /dev/null
+++ b/test/mock/mock_ausrc.c
@@ -0,0 +1,88 @@
+/**
+ * @file mock/mock_ausrc.c Mock audio source
+ *
+ * Copyright (C) 2010 - 2016 Creytiv.com
+ */
+#include <re.h>
+#include <baresip.h>
+#include "../test.h"
+
+
+struct ausrc_st {
+ const struct ausrc *as; /* inheritance */
+
+ struct tmr tmr;
+ struct ausrc_prm prm;
+ int16_t *sampv;
+ size_t sampc;
+ ausrc_read_h *rh;
+ void *arg;
+};
+
+
+static void tmr_handler(void *arg)
+{
+ struct ausrc_st *st = arg;
+
+ tmr_start(&st->tmr, st->prm.ptime, tmr_handler, st);
+
+ if (st->rh)
+ st->rh(st->sampv, st->sampc, st->arg);
+}
+
+
+static void ausrc_destructor(void *arg)
+{
+ struct ausrc_st *st = arg;
+
+ tmr_cancel(&st->tmr);
+ mem_deref(st->sampv);
+}
+
+
+static int mock_ausrc_alloc(struct ausrc_st **stp, const struct ausrc *as,
+ struct media_ctx **ctx,
+ struct ausrc_prm *prm, const char *device,
+ ausrc_read_h *rh, ausrc_error_h *errh, void *arg)
+{
+ struct ausrc_st *st;
+ int err = 0;
+ (void)ctx;
+ (void)errh;
+
+ if (!stp || !as || !prm)
+ return EINVAL;
+
+ st = mem_zalloc(sizeof(*st), ausrc_destructor);
+ if (!st)
+ return ENOMEM;
+
+ st->as = as;
+ st->prm = *prm;
+ st->rh = rh;
+ st->arg = arg;
+
+ st->sampc = prm->srate * prm->ch * prm->ptime / 1000;
+
+ st->sampv = mem_zalloc(2 * st->sampc, NULL);
+ if (!st->sampv) {
+ err = ENOMEM;
+ goto out;
+ }
+
+ tmr_start(&st->tmr, 0, tmr_handler, st);
+
+ out:
+ if (err)
+ mem_deref(st);
+ else
+ *stp = st;
+
+ return err;
+}
+
+
+int mock_ausrc_register(struct ausrc **ausrcp)
+{
+ return ausrc_register(ausrcp, "mock-ausrc", mock_ausrc_alloc);
+}
diff --git a/test/srcs.mk b/test/srcs.mk
index 2158ca8..b992822 100644
--- a/test/srcs.mk
+++ b/test/srcs.mk
@@ -33,6 +33,8 @@ ifneq ($(USE_TLS),)
TEST_SRCS += mock/cert.c
endif
+TEST_SRCS += mock/mock_ausrc.c
+
TEST_SRCS += test.c
diff --git a/test/test.h b/test/test.h
index 489f8e0..4c6c11b 100644
--- a/test/test.h
+++ b/test/test.h
@@ -83,6 +83,14 @@ int dns_server_add_srv(struct dns_server *srv, const char *name,
uint16_t pri, uint16_t weight, uint16_t port,
const char *target);
+/*
+ * Mock Audio-source
+ */
+
+struct ausrc;
+
+int mock_ausrc_register(struct ausrc **ausrcp);
+
/* test cases */
@@ -106,6 +114,7 @@ int test_call_answer_hangup_b(void);
int test_call_rtp_timeout(void);
int test_call_multiple(void);
int test_call_max(void);
+int test_call_dtmf(void);
#ifdef __cplusplus