pespin has uploaded this change for review. (
https://gerrit.osmocom.org/c/libosmo-netif/+/29513 )
Change subject: tests/osmux: Add new osmux_input_test to validate AMR FT changes
......................................................................
tests/osmux: Add new osmux_input_test to validate AMR FT changes
Related: SYS#5987
Change-Id: I105466fc8a4d92341f34886ee81ef0ca04014514
---
M tests/Makefile.am
A tests/osmux/osmux_input_test.c
A tests/osmux/osmux_input_test.ok
M tests/testsuite.at
4 files changed, 305 insertions(+), 1 deletion(-)
git pull ssh://gerrit.osmocom.org:29418/libosmo-netif refs/changes/13/29513/1
diff --git a/tests/Makefile.am b/tests/Makefile.am
index ab2bf59..cb31baa 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -1,7 +1,14 @@
AM_CFLAGS = -Wall -I$(top_srcdir)/include $(LIBOSMOCORE_CFLAGS) -g
AM_LDFLAGS = $(LIBOSMOCORE_LDFLAGS) -no-install
-check_PROGRAMS = osmux/osmux_test osmux/osmux_output_test stream/stream_test
jibuf/jibuf_test amr/amr_test
+check_PROGRAMS = \
+ osmux/osmux_test \
+ osmux/osmux_output_test \
+ osmux/osmux_input_test \
+ stream/stream_test \
+ jibuf/jibuf_test \
+ amr/amr_test \
+ $(NULL)
check_HEADERS =
osmux_osmux_test_SOURCES = osmux/osmux_test.c
@@ -10,6 +17,9 @@
osmux_osmux_output_test_SOURCES = osmux/osmux_output_test.c
osmux_osmux_output_test_LDADD = $(LIBOSMOCORE_LIBS) $(LIBOSMOGSM_LIBS)
$(top_builddir)/src/libosmonetif.la
+osmux_osmux_input_test_SOURCES = osmux/osmux_input_test.c
+osmux_osmux_input_test_LDADD = $(LIBOSMOCORE_LIBS) $(LIBOSMOGSM_LIBS)
$(top_builddir)/src/libosmonetif.la
+
stream_stream_test_SOURCES = stream/stream_test.c
stream_stream_test_LDADD = $(LIBOSMOCORE_LIBS) $(LIBOSMOGSM_LIBS)
$(top_builddir)/src/libosmonetif.la
diff --git a/tests/osmux/osmux_input_test.c b/tests/osmux/osmux_input_test.c
new file mode 100644
index 0000000..dcec949
--- /dev/null
+++ b/tests/osmux/osmux_input_test.c
@@ -0,0 +1,275 @@
+/* (C) 2022 by sysmocom - s.f.m.c. GmbH <info(a)sysmocom.de>
+ *
+ * Author: Pau Espin Pedrol <pespin(a)sysmocom.de>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <unistd.h>
+#include <stdint.h>
+#include <inttypes.h>
+#include <string.h>
+#include <signal.h>
+#include <arpa/inet.h>
+#include <sys/time.h>
+#include <getopt.h>
+
+#include <osmocom/core/select.h>
+#include <osmocom/core/application.h>
+#include <osmocom/core/logging.h>
+#include <osmocom/core/msgb.h>
+#include <osmocom/netif/rtp.h>
+#include <osmocom/netif/osmux.h>
+#include <osmocom/netif/amr.h>
+
+static uint16_t rtp_next_seq;
+static uint16_t rtp_next_ts;
+
+#define TIME_RTP_PKT_MS 20
+#define BATCH_FACTOR 6
+/* ----------------------------- */
+
+/* Logging related stuff */
+#define INT2IDX(x) (-1*(x)-1)
+struct log_info_cat jibuf_test_cat[] = {
+ [INT2IDX(DLMUX)] = {
+ .name = "DLMUX",
+ .description = "Osmocom Osmux",
+ .enabled = 1, .loglevel = LOGL_DEBUG,
+ },
+};
+const struct log_info log_info = {
+ .filter_fn = NULL,
+ .cat = jibuf_test_cat,
+ .num_cat = ARRAY_SIZE(jibuf_test_cat),
+};
+/* ----------------------------- */
+
+static void rtp_init(uint16_t seq, uint16_t ts)
+{
+ rtp_next_seq = seq;
+ rtp_next_ts = ts;
+}
+
+static struct msgb *rtp_new(uint16_t seq, uint8_t timestamp, uint8_t marker)
+{
+ struct msgb *msg;
+ struct rtp_hdr *rtph;
+
+ msg = msgb_alloc(1500, "rtp");
+ if (!msg)
+ exit(EXIT_FAILURE);
+ msgb_put(msg, sizeof(struct rtp_hdr));
+
+ rtph = (struct rtp_hdr *)msg->data;
+ rtph->version = RTP_VERSION;
+ rtph->marker = marker;
+ rtph->sequence = htons(seq);
+ rtph->timestamp = htons(timestamp);
+ rtph->ssrc = 0x6789;
+ return msg;
+}
+
+static struct msgb *rtp_next(void)
+{
+ rtp_next_seq++;
+ rtp_next_ts += TIME_RTP_PKT_MS;
+ return rtp_new(rtp_next_seq, rtp_next_ts, 0);
+}
+
+static void rtp_append_amr(struct msgb *msg, uint8_t ft)
+{
+ struct amr_hdr *amrh;
+ struct rtp_hdr *rtph = (struct rtp_hdr *)msg->data;
+
+ msgb_put(msg, sizeof(struct amr_hdr));
+ amrh = (struct amr_hdr *)rtph->data;
+
+ amrh->cmr = 0;
+ amrh->q = 1;
+ amrh->f = 0;
+ amrh->ft = ft;
+ msgb_put(msg, osmo_amr_bytes(amrh->ft));
+}
+
+static void sigalarm_handler(int foo)
+{
+ printf("FAIL: test did not run successfully\n");
+ exit(EXIT_FAILURE);
+}
+
+#define clock_debug(fmt, args...) \
+ do { \
+ struct timespec ts; \
+ struct timeval tv; \
+ osmo_clock_gettime(CLOCK_MONOTONIC, &ts); \
+ osmo_gettimeofday(&tv, NULL); \
+ fprintf(stdout, "sys={%lu.%06lu}, mono={%lu.%06lu}: " fmt "\n", \
+ tv.tv_sec, tv.tv_usec, ts.tv_sec, ts.tv_nsec/1000, ##args); \
+ } while(0)
+
+static void clock_override_enable(bool enable)
+{
+ osmo_gettimeofday_override = enable;
+ osmo_clock_override_enable(CLOCK_MONOTONIC, enable);
+}
+
+static void clock_override_set(long sec, long usec)
+{
+ struct timespec *mono;
+ osmo_gettimeofday_override_time.tv_sec = sec;
+ osmo_gettimeofday_override_time.tv_usec = usec;
+ mono = osmo_clock_override_gettimespec(CLOCK_MONOTONIC);
+ mono->tv_sec = sec;
+ mono->tv_nsec = usec*1000;
+
+ clock_debug("clock_override_set");
+}
+
+static void clock_override_add_debug(long sec, long usec, bool dbg)
+{
+ osmo_gettimeofday_override_add(sec, usec);
+ osmo_clock_override_add(CLOCK_MONOTONIC, sec, usec*1000);
+ if (dbg)
+ clock_debug("clock_override_add");
+}
+#define clock_override_add(sec, usec) clock_override_add_debug(sec, usec, true)
+
+static void test_amr_ft_change_middle_batch_osmux_deliver_cb(struct msgb *batch_msg, void
*data)
+{
+ struct osmux_hdr *osmuxh;
+ char buf[2048];
+ int n = 0;
+ bool *osmux_transmitted = (bool *)data;
+
+ osmux_snprintf(buf, sizeof(buf), batch_msg);
+ clock_debug("OSMUX message (len=%d): %s\n", batch_msg->len, buf);
+
+ /* We expect 3 batches: */
+ while ((osmuxh = osmux_xfrm_output_pull(batch_msg))) {
+ n++;
+ OSMO_ASSERT(osmuxh->ft == OSMUX_FT_VOICE_AMR);
+ OSMO_ASSERT(osmuxh->rtp_m == 0);
+ OSMO_ASSERT(osmuxh->amr_cmr == 0);
+ OSMO_ASSERT(osmuxh->amr_q == 1);
+ switch (n) {
+ case 1:
+ OSMO_ASSERT(osmuxh->seq == 0);
+ OSMO_ASSERT(osmuxh->ctr == 1);
+ OSMO_ASSERT(osmuxh->amr_ft == AMR_FT_2);
+ break;
+ case 2:
+ OSMO_ASSERT(osmuxh->seq == 1);
+ OSMO_ASSERT(osmuxh->ctr == 0);
+ OSMO_ASSERT(osmuxh->amr_ft == AMR_FT_6);
+ break;
+ case 3:
+ OSMO_ASSERT(osmuxh->seq == 2);
+ OSMO_ASSERT(osmuxh->ctr == 0);
+ OSMO_ASSERT(osmuxh->amr_ft == AMR_FT_1);
+ break;
+ }
+ }
+ OSMO_ASSERT(n == 3);
+
+ msgb_free(batch_msg);
+
+ *osmux_transmitted = true;
+}
+/* Test if an RTP pkt with changed AMR FT passed to osmux_input is properly
+ * processed: The current batch ends and a new batch with a new osmux header is
+ * appeneded to the generated packet. */
+static void test_amr_ft_change_middle_batch(void)
+{
+ struct msgb *msg;
+ int rc;
+ const uint8_t cid = 30;
+ bool osmux_transmitted = false;
+
+ printf("===%s===\n", __FUNCTION__);
+
+
+ clock_override_enable(true);
+ clock_override_set(0, 0);
+ rtp_init(0, 0);
+
+ struct osmux_in_handle h_input = {
+ .osmux_seq = 0, /* sequence number to start OSmux message from */
+ .batch_factor = 4, /* batch up to 4 RTP messages */
+ .deliver = test_amr_ft_change_middle_batch_osmux_deliver_cb,
+ .data = &osmux_transmitted,
+ };
+
+ osmux_xfrm_input_init(&h_input);
+ osmux_xfrm_input_open_circuit(&h_input, cid, false);
+
+ /* First RTP frame at t=0 */
+ msg = rtp_next();
+ rtp_append_amr(msg, AMR_FT_2);
+ rc = osmux_xfrm_input(&h_input, msg, cid);
+ OSMO_ASSERT(rc == 0);
+
+ /* Second RTP frame at t=20 */
+ clock_override_add(0, TIME_RTP_PKT_MS*1000);
+ msg = rtp_next();
+ rtp_append_amr(msg, AMR_FT_2);
+ rc = osmux_xfrm_input(&h_input, msg, cid);
+ OSMO_ASSERT(rc == 0);
+
+ /* Third RTP frame at t=40, AMR FT changes: */
+ clock_debug("Submit RTP with 1st AMR FT change");
+ clock_override_add(0, TIME_RTP_PKT_MS*1000);
+ msg = rtp_next();
+ rtp_append_amr(msg, AMR_FT_6);
+ rc = osmux_xfrm_input(&h_input, msg, cid);
+ OSMO_ASSERT(rc == 0);
+
+ /* Forth RTP frame at t=60, AMR FT changes again: */
+ clock_debug("Submit RTP with 2nd AMR FT change");
+ clock_override_add(0, TIME_RTP_PKT_MS*1000);
+ msg = rtp_next();
+ rtp_append_amr(msg, AMR_FT_1);
+ rc = osmux_xfrm_input(&h_input, msg, cid);
+ OSMO_ASSERT(rc == 0);
+
+ /* t=80, osmux batch is scheduled to be transmitted: */
+ clock_override_add(0, TIME_RTP_PKT_MS*1000);
+ clock_debug("Osmux frame should now be transmitted");
+ osmo_select_main(0);
+ OSMO_ASSERT(osmux_transmitted == true);
+
+ clock_debug("Closing circuit");
+ osmux_xfrm_input_close_circuit(&h_input, cid);
+ osmux_xfrm_input_fini(&h_input);
+}
+
+int main(int argc, char **argv)
+{
+
+ if (signal(SIGALRM, sigalarm_handler) == SIG_ERR) {
+ perror("signal");
+ exit(EXIT_FAILURE);
+ }
+
+ void *tall_ctx = talloc_named_const(NULL, 1, "Root context");
+ msgb_talloc_ctx_init(tall_ctx, 0);
+ osmo_init_logging2(tall_ctx, &log_info);
+ log_set_print_filename2(osmo_stderr_target, LOG_FILENAME_NONE);
+ log_set_log_level(osmo_stderr_target, LOGL_DEBUG);
+ log_set_category_filter(osmo_stderr_target, DLMUX, 1, LOGL_DEBUG);
+
+ alarm(10);
+
+ test_amr_ft_change_middle_batch();
+
+ fprintf(stdout, "OK: Test passed\n");
+ return EXIT_SUCCESS;
+}
diff --git a/tests/osmux/osmux_input_test.ok b/tests/osmux/osmux_input_test.ok
new file mode 100644
index 0000000..9aca52e
--- /dev/null
+++ b/tests/osmux/osmux_input_test.ok
@@ -0,0 +1,13 @@
+===test_amr_ft_change_middle_batch===
+sys={0.000000}, mono={0.000000}: clock_override_set
+sys={0.020000}, mono={0.020000}: clock_override_add
+sys={0.020000}, mono={0.020000}: Submit RTP with 1st AMR FT change
+sys={0.040000}, mono={0.040000}: clock_override_add
+sys={0.040000}, mono={0.040000}: Submit RTP with 2nd AMR FT change
+sys={0.060000}, mono={0.060000}: clock_override_add
+sys={0.080000}, mono={0.080000}: clock_override_add
+sys={0.080000}, mono={0.080000}: Osmux frame should now be transmitted
+sys={0.080000}, mono={0.080000}: OSMUX message (len=81): OSMUX seq=000 ccid=030 ft=1
rtp_m=0 ctr=1 amr_f=0 amr_q=1 amr_ft=02 amr_cmr=00 [ 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ], OSMUX seq=001 ccid=030 ft=1
rtp_m=0 ctr=0 amr_f=0 amr_q=1 amr_ft=06 amr_cmr=00 [ 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 ], OSMUX seq=002 ccid=030 ft=1 rtp_m=0 ctr=0
amr_f=0 amr_q=1 amr_ft=01 amr_cmr=00 [ 00 00 00 00 00 00 00 00 00 00 00 00 00 ]
+
+sys={0.080000}, mono={0.080000}: Closing circuit
+OK: Test passed
diff --git a/tests/testsuite.at b/tests/testsuite.at
index 17883cc..b84c4ee 100644
--- a/tests/testsuite.at
+++ b/tests/testsuite.at
@@ -20,6 +20,12 @@
AT_CHECK([$abs_top_builddir/tests/osmux/osmux_output_test], [0], [expout], [ignore])
AT_CLEANUP
+AT_SETUP([osmux_input_test])
+AT_KEYWORDS([osmux_input_test])
+cat $abs_srcdir/osmux/osmux_input_test.ok > expout
+AT_CHECK([$abs_top_builddir/tests/osmux/osmux_input_test], [0], [expout], [ignore])
+AT_CLEANUP
+
AT_SETUP([jibuf_test])
AT_KEYWORDS([jibuf_test])
cat $abs_srcdir/jibuf/jibuf_test.ok > expout
--
To view, visit
https://gerrit.osmocom.org/c/libosmo-netif/+/29513
To unsubscribe, or for help writing mail filters, visit
https://gerrit.osmocom.org/settings
Gerrit-Project: libosmo-netif
Gerrit-Branch: master
Gerrit-Change-Id: I105466fc8a4d92341f34886ee81ef0ca04014514
Gerrit-Change-Number: 29513
Gerrit-PatchSet: 1
Gerrit-Owner: pespin <pespin(a)sysmocom.de>
Gerrit-MessageType: newchange