pespin has submitted this change. ( 
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, 306 insertions(+), 1 deletion(-)

Approvals:
  Jenkins Builder: Verified
  laforge: Looks good to me, but someone else must approve
  fixeria: Looks good to me, approved



diff --git a/tests/Makefile.am b/tests/Makefile.am
index ab2bf59..a21f0b1 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

@@ -63,6 +73,7 @@
 EXTRA_DIST = testsuite.at $(srcdir)/package.m4 $(TESTSUITE)            \
             osmux/osmux_test.ok \
             osmux/osmux_output_test.ok \
+            osmux/osmux_input_test.ok \
             stream/stream_test.ok \
             stream/stream_test.err \
             jibuf/jibuf_test.ok \
diff --git a/tests/osmux/osmux_input_test.c b/tests/osmux/osmux_input_test.c
new file mode 100644
index 0000000..3b7774c
--- /dev/null
+++ b/tests/osmux/osmux_input_test.c
@@ -0,0 +1,275 @@
+/* (C) 2022 by sysmocom - s.f.m.c. GmbH <[email protected]>
+ *
+ * Author: Pau Espin Pedrol <[email protected]>
+ *
+ * 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", __func__);
+
+
+       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: 2
Gerrit-Owner: pespin <[email protected]>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: fixeria <[email protected]>
Gerrit-Reviewer: laforge <[email protected]>
Gerrit-Reviewer: pespin <[email protected]>
Gerrit-MessageType: merged

Reply via email to