diff options
author | Thorsten Alteholz <debian@alteholz.de> | 2017-12-14 20:07:28 +0100 |
---|---|---|
committer | Thorsten Alteholz <debian@alteholz.de> | 2017-12-14 20:07:28 +0100 |
commit | 1737d3d0e59c7ffbca33c6b79123d7633185c12a (patch) | |
tree | c72aec0dfa2f3c953e999af196ab595e53c084cd /tests |
Import Upstream version 1.2.0
Diffstat (limited to 'tests')
-rw-r--r-- | tests/Makefile.am | 64 | ||||
-rw-r--r-- | tests/atlocal.in | 7 | ||||
-rw-r--r-- | tests/legacy_mgcp/Makefile.am | 61 | ||||
-rw-r--r-- | tests/legacy_mgcp/mgcp_test.c | 1236 | ||||
-rw-r--r-- | tests/legacy_mgcp/mgcp_test.ok | 480 | ||||
-rw-r--r-- | tests/legacy_mgcp/mgcp_transcoding_test.c | 661 | ||||
-rw-r--r-- | tests/legacy_mgcp/mgcp_transcoding_test.ok | 539 | ||||
-rw-r--r-- | tests/mgcp/Makefile.am | 38 | ||||
-rw-r--r-- | tests/mgcp/mgcp_test.c | 1353 | ||||
-rw-r--r-- | tests/mgcp/mgcp_test.ok | 471 | ||||
-rw-r--r-- | tests/mgcp_client/Makefile.am | 39 | ||||
-rw-r--r-- | tests/mgcp_client/mgcp_client_test.c | 255 | ||||
-rw-r--r-- | tests/mgcp_client/mgcp_client_test.err | 2 | ||||
-rw-r--r-- | tests/mgcp_client/mgcp_client_test.ok | 62 | ||||
-rw-r--r-- | tests/testsuite.at | 28 | ||||
-rw-r--r-- | tests/vty_test_runner.py | 171 |
16 files changed, 5467 insertions, 0 deletions
diff --git a/tests/Makefile.am b/tests/Makefile.am new file mode 100644 index 0000000..2eed271 --- /dev/null +++ b/tests/Makefile.am @@ -0,0 +1,64 @@ +SUBDIRS = \ + legacy_mgcp \ + mgcp_client \ + mgcp \ + $(NULL) + +# The `:;' works around a Bash 3.2 bug when the output is not writeable. +$(srcdir)/package.m4: $(top_srcdir)/configure.ac + :;{ \ + echo '# Signature of the current package.' && \ + echo 'm4_define([AT_PACKAGE_NAME],' && \ + echo ' [$(PACKAGE_NAME)])' && \ + echo 'm4_define([AT_PACKAGE_TARNAME],' && \ + echo ' [$(PACKAGE_TARNAME)])' && \ + echo 'm4_define([AT_PACKAGE_VERSION],' && \ + echo ' [$(PACKAGE_VERSION)])' && \ + echo 'm4_define([AT_PACKAGE_STRING],' && \ + echo ' [$(PACKAGE_STRING)])' && \ + echo 'm4_define([AT_PACKAGE_BUGREPORT],' && \ + echo ' [$(PACKAGE_BUGREPORT)])'; \ + echo 'm4_define([AT_PACKAGE_URL],' && \ + echo ' [$(PACKAGE_URL)])'; \ + } >'$(srcdir)/package.m4' + +EXTRA_DIST = \ + testsuite.at \ + $(srcdir)/package.m4 \ + $(TESTSUITE) \ + vty_test_runner.py \ + $(NULL) + +TESTSUITE = $(srcdir)/testsuite + +DISTCLEANFILES = \ + atconfig \ + $(NULL) + +if ENABLE_EXT_TESTS +python-tests: $(BUILT_SOURCES) + osmotestvty.py -p $(abs_top_srcdir) -w $(abs_top_builddir) -v + osmotestconfig.py -p $(abs_top_srcdir) -w $(abs_top_builddir) -v + $(PYTHON) $(srcdir)/vty_test_runner.py -w $(abs_top_builddir) -v +else +python-tests: $(BUILT_SOURCES) + echo "Not running python-based tests (determined at configure-time)" +endif + +check-local: atconfig $(TESTSUITE) + $(SHELL) '$(TESTSUITE)' $(TESTSUITEFLAGS) + $(MAKE) $(AM_MAKEFLAGS) python-tests + +installcheck-local: atconfig $(TESTSUITE) + $(SHELL) '$(TESTSUITE)' AUTOTEST_PATH='$(bindir)' \ + $(TESTSUITEFLAGS) + +clean-local: + test ! -f '$(TESTSUITE)' || \ + $(SHELL) '$(TESTSUITE)' --clean + +AUTOM4TE = $(SHELL) $(top_srcdir)/missing --run autom4te +AUTOTEST = $(AUTOM4TE) --language=autotest +$(TESTSUITE): $(srcdir)/testsuite.at $(srcdir)/package.m4 + $(AUTOTEST) -I '$(srcdir)' -o $@.tmp $@.at + mv $@.tmp $@ diff --git a/tests/atlocal.in b/tests/atlocal.in new file mode 100644 index 0000000..362bfa9 --- /dev/null +++ b/tests/atlocal.in @@ -0,0 +1,7 @@ +enable_nat_test='@osmo_ac_build_nat@' +enable_smpp_test='@osmo_ac_build_smpp@' +enable_bsc_test='@osmo_ac_build_bsc@' +enable_mgcp_transcoding_test='@osmo_ac_mgcp_transcoding@' +enable_sgsn_test='@found_libgtp_and_libcares@' +enable_oap_test='@found_libgtp_and_libcares@' +enable_gtphub_test='@found_libgtp_and_libcares@' diff --git a/tests/legacy_mgcp/Makefile.am b/tests/legacy_mgcp/Makefile.am new file mode 100644 index 0000000..f043124 --- /dev/null +++ b/tests/legacy_mgcp/Makefile.am @@ -0,0 +1,61 @@ +AM_CPPFLAGS = \ + $(all_includes) \ + -I$(top_srcdir)/include \ + -I$(top_srcdir) \ + $(NULL) + +AM_CFLAGS = \ + -Wall \ + -ggdb3 \ + $(LIBOSMOCORE_CFLAGS) \ + $(LIBOSMONETIF_CFLAGS) \ + $(LIBBCG729_CFLAGS) \ + $(COVERAGE_CFLAGS) \ + $(NULL) + +AM_LDFLAGS = \ + $(COVERAGE_LDFLAGS) \ + $(NULL) + +EXTRA_DIST = \ + mgcp_test.ok \ + mgcp_transcoding_test.ok \ + $(NULL) + +noinst_PROGRAMS = \ + mgcp_test \ + $(NULL) +if BUILD_MGCP_TRANSCODING +noinst_PROGRAMS += \ + mgcp_transcoding_test \ + $(NULL) +endif + +mgcp_test_SOURCES = \ + mgcp_test.c \ + $(NULL) + +mgcp_test_LDADD = \ + $(top_builddir)/src/libosmo-legacy-mgcp/libosmo-legacy-mgcp.la \ + $(LIBOSMOCORE_LIBS) \ + $(LIBOSMOVTY_LIBS) \ + $(LIBRARY_DL) \ + $(LIBOSMONETIF_LIBS) \ + $(LIBRARY_GSM) \ + -lm \ + $(NULL) + +mgcp_transcoding_test_SOURCES = \ + mgcp_transcoding_test.c \ + $(NULL) + +mgcp_transcoding_test_LDADD = \ + $(top_builddir)/src/libosmo-legacy-mgcp/libosmo-legacy-mgcp.la \ + $(LIBOSMOCORE_LIBS) \ + $(LIBOSMOVTY_LIBS) \ + $(LIBBCG729_LIBS) \ + $(LIBRARY_DL) \ + $(LIBOSMONETIF_LIBS) \ + $(LIBRARY_GSM) \ + -lm \ + $(NULL) diff --git a/tests/legacy_mgcp/mgcp_test.c b/tests/legacy_mgcp/mgcp_test.c new file mode 100644 index 0000000..1400893 --- /dev/null +++ b/tests/legacy_mgcp/mgcp_test.c @@ -0,0 +1,1236 @@ +/* + * (C) 2011-2012,2014 by Holger Hans Peter Freyther <zecke@selfish.org> + * (C) 2011-2012,2014 by On-Waves + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +#undef _GNU_SOURCE +#define _GNU_SOURCE + +#include <osmocom/legacy_mgcp/mgcp.h> +#include <osmocom/legacy_mgcp/vty.h> +#include <osmocom/legacy_mgcp/mgcp_internal.h> + +#include <osmocom/core/application.h> +#include <osmocom/core/talloc.h> +#include <osmocom/core/utils.h> +#include <string.h> +#include <limits.h> +#include <dlfcn.h> +#include <time.h> +#include <math.h> + +char *strline_r(char *str, char **saveptr); + +const char *strline_test_data = + "one CR\r" + "two CR\r" + "\r" + "one CRLF\r\n" + "two CRLF\r\n" + "\r\n" + "one LF\n" + "two LF\n" + "\n" + "mixed (4 lines)\r\r\n\n\r\n"; + +#define EXPECTED_NUMBER_OF_LINES 13 + +static void test_strline(void) +{ + char *save = NULL; + char *line; + char buf[2048]; + int counter = 0; + + osmo_strlcpy(buf, strline_test_data, sizeof(buf)); + + for (line = strline_r(buf, &save); line; + line = strline_r(NULL, &save)) { + printf("line: '%s'\n", line); + counter++; + } + + OSMO_ASSERT(counter == EXPECTED_NUMBER_OF_LINES); +} + +#define AUEP1 "AUEP 158663169 ds/e1-1/2@172.16.6.66 MGCP 1.0\r\n" +#define AUEP1_RET "200 158663169 OK\r\n" +#define AUEP2 "AUEP 18983213 ds/e1-2/1@172.16.6.66 MGCP 1.0\r\n" +#define AUEP2_RET "500 18983213 FAIL\r\n" +#define EMPTY "\r\n" +#define EMPTY_RET NULL +#define SHORT "CRCX \r\n" +#define SHORT_RET "510 000000 FAIL\r\n" + +#define MDCX_WRONG_EP "MDCX 18983213 ds/e1-3/1@172.16.6.66 MGCP 1.0\r\n" +#define MDCX_ERR_RET "510 18983213 FAIL\r\n" +#define MDCX_UNALLOCATED "MDCX 18983214 ds/e1-1/2@172.16.6.66 MGCP 1.0\r\n" +#define MDCX_RET "400 18983214 FAIL\r\n" +#define MDCX3 "MDCX 18983215 1@mgw MGCP 1.0\r\n" +#define MDCX3_RET "200 18983215 OK\r\n" \ + "I: 1\n" \ + "\n" \ + "v=0\r\n" \ + "o=- 1 23 IN IP4 0.0.0.0\r\n" \ + "s=-\r\n" \ + "c=IN IP4 0.0.0.0\r\n" \ + "t=0 0\r\n" \ + "m=audio 0 RTP/AVP 126\r\n" \ + "a=rtpmap:126 AMR/8000\r\n" \ + "a=ptime:20\r\n" +#define MDCX3_FMTP_RET "200 18983215 OK\r\n" \ + "I: 3\n" \ + "\n" \ + "v=0\r\n" \ + "o=- 3 23 IN IP4 0.0.0.0\r\n" \ + "s=-\r\n" \ + "c=IN IP4 0.0.0.0\r\n" \ + "t=0 0\r\n" \ + "m=audio 0 RTP/AVP 126\r\n" \ + "a=rtpmap:126 AMR/8000\r\n" \ + "a=fmtp:126 0/1/2\r\n" \ + "a=ptime:20\r\n" +#define MDCX4 "MDCX 18983216 1@mgw MGCP 1.0\r\n" \ + "M: sendrecv\r" \ + "C: 2\r\n" \ + "I: 1\r\n" \ + "L: p:20, a:AMR, nt:IN\r\n" \ + "\n" \ + "v=0\r\n" \ + "o=- 1 23 IN IP4 0.0.0.0\r\n" \ + "c=IN IP4 0.0.0.0\r\n" \ + "t=0 0\r\n" \ + "m=audio 4441 RTP/AVP 99\r\n" \ + "a=rtpmap:99 AMR/8000\r\n" \ + "a=ptime:40\r\n" +#define MDCX4_RET(Ident) "200 " Ident " OK\r\n" \ + "I: 1\n" \ + "\n" \ + "v=0\r\n" \ + "o=- 1 23 IN IP4 0.0.0.0\r\n" \ + "s=-\r\n" \ + "c=IN IP4 0.0.0.0\r\n" \ + "t=0 0\r\n" \ + "m=audio 0 RTP/AVP 126\r\n" \ + "a=rtpmap:126 AMR/8000\r\n" \ + "a=ptime:20\r\n" + +#define MDCX4_PT1 "MDCX 18983217 1@mgw MGCP 1.0\r\n" \ + "M: sendrecv\r" \ + "C: 2\r\n" \ + "I: 1\r\n" \ + "L: p:20-40, a:AMR, nt:IN\r\n" \ + "\n" \ + "v=0\r\n" \ + "o=- 1 23 IN IP4 0.0.0.0\r\n" \ + "c=IN IP4 0.0.0.0\r\n" \ + "t=0 0\r\n" \ + "m=audio 4441 RTP/AVP 99\r\n" \ + "a=rtpmap:99 AMR/8000\r\n" \ + "a=ptime:40\r\n" + +#define MDCX4_PT2 "MDCX 18983218 1@mgw MGCP 1.0\r\n" \ + "M: sendrecv\r" \ + "C: 2\r\n" \ + "I: 1\r\n" \ + "L: p:20-20, a:AMR, nt:IN\r\n" \ + "\n" \ + "v=0\r\n" \ + "o=- 1 23 IN IP4 0.0.0.0\r\n" \ + "c=IN IP4 0.0.0.0\r\n" \ + "t=0 0\r\n" \ + "m=audio 4441 RTP/AVP 99\r\n" \ + "a=rtpmap:99 AMR/8000\r\n" \ + "a=ptime:40\r\n" + +#define MDCX4_PT3 "MDCX 18983219 1@mgw MGCP 1.0\r\n" \ + "M: sendrecv\r" \ + "C: 2\r\n" \ + "I: 1\r\n" \ + "L: a:AMR, nt:IN\r\n" \ + "\n" \ + "v=0\r\n" \ + "o=- 1 23 IN IP4 0.0.0.0\r\n" \ + "c=IN IP4 0.0.0.0\r\n" \ + "t=0 0\r\n" \ + "m=audio 4441 RTP/AVP 99\r\n" \ + "a=rtpmap:99 AMR/8000\r\n" \ + "a=ptime:40\r\n" + +#define MDCX4_SO "MDCX 18983220 1@mgw MGCP 1.0\r\n" \ + "M: sendonly\r" \ + "C: 2\r\n" \ + "I: 1\r\n" \ + "L: p:20, a:AMR, nt:IN\r\n" \ + "\n" \ + "v=0\r\n" \ + "o=- 1 23 IN IP4 0.0.0.0\r\n" \ + "c=IN IP4 0.0.0.0\r\n" \ + "t=0 0\r\n" \ + "m=audio 4441 RTP/AVP 99\r\n" \ + "a=rtpmap:99 AMR/8000\r\n" \ + "a=ptime:40\r\n" + +#define MDCX4_RO "MDCX 18983221 1@mgw MGCP 1.0\r\n" \ + "M: recvonly\r" \ + "C: 2\r\n" \ + "I: 1\r\n" \ + "L: p:20, a:AMR, nt:IN\r\n" + +#define SHORT2 "CRCX 1" +#define SHORT2_RET "510 000000 FAIL\r\n" +#define SHORT3 "CRCX 1 1@mgw" +#define SHORT4 "CRCX 1 1@mgw MGCP" +#define SHORT5 "CRCX 1 1@mgw MGCP 1.0" + +#define CRCX "CRCX 2 1@mgw MGCP 1.0\r\n" \ + "M: recvonly\r\n" \ + "C: 2\r\n" \ + "X\r\n" \ + "L: p:20\r\n" \ + "\r\n" \ + "v=0\r\n" \ + "c=IN IP4 123.12.12.123\r\n" \ + "m=audio 5904 RTP/AVP 97\r\n" \ + "a=rtpmap:97 GSM-EFR/8000\r\n" \ + "a=ptime:40\r\n" + +#define CRCX_RET "200 2 OK\r\n" \ + "I: 1\n" \ + "\n" \ + "v=0\r\n" \ + "o=- 1 23 IN IP4 0.0.0.0\r\n" \ + "s=-\r\n" \ + "c=IN IP4 0.0.0.0\r\n" \ + "t=0 0\r\n" \ + "m=audio 0 RTP/AVP 126\r\n" \ + "a=rtpmap:126 AMR/8000\r\n" \ + "a=ptime:20\r\n" + +#define CRCX_RET_NO_RTPMAP "200 2 OK\r\n" \ + "I: 1\n" \ + "\n" \ + "v=0\r\n" \ + "o=- 1 23 IN IP4 0.0.0.0\r\n" \ + "s=-\r\n" \ + "c=IN IP4 0.0.0.0\r\n" \ + "t=0 0\r\n" \ + "m=audio 0 RTP/AVP 126\r\n" \ + "a=ptime:20\r\n" + +#define CRCX_FMTP_RET "200 2 OK\r\n" \ + "I: 3\n" \ + "\n" \ + "v=0\r\n" \ + "o=- 3 23 IN IP4 0.0.0.0\r\n" \ + "s=-\r\n" \ + "c=IN IP4 0.0.0.0\r\n" \ + "t=0 0\r\n" \ + "m=audio 0 RTP/AVP 126\r\n" \ + "a=rtpmap:126 AMR/8000\r\n" \ + "a=fmtp:126 0/1/2\r\n" \ + "a=ptime:20\r\n" + +#define CRCX_ZYN "CRCX 2 1@mgw MGCP 1.0\r" \ + "M: recvonly\r" \ + "C: 2\r\r" \ + "v=0\r" \ + "c=IN IP4 123.12.12.123\r" \ + "m=audio 5904 RTP/AVP 97\r" \ + "a=rtpmap:97 GSM-EFR/8000\r" + +#define CRCX_ZYN_RET "200 2 OK\r\n" \ + "I: 2\n" \ + "\n" \ + "v=0\r\n" \ + "o=- 2 23 IN IP4 0.0.0.0\r\n" \ + "s=-\r\n" \ + "c=IN IP4 0.0.0.0\r\n" \ + "t=0 0\r\n" \ + "m=audio 0 RTP/AVP 126\r\n" \ + "a=rtpmap:126 AMR/8000\r\n" \ + "a=ptime:20\r\n" + +#define DLCX "DLCX 7 1@mgw MGCP 1.0\r\n" \ + "C: 2\r\n" + +#define DLCX_RET "250 7 OK\r\n" \ + "P: PS=0, OS=0, PR=0, OR=0, PL=0, JI=0\r\n" \ + "X-Osmo-CP: EC TIS=0, TOS=0, TIR=0, TOR=0\r\n" + +#define RQNT "RQNT 186908780 1@mgw MGCP 1.0\r\n" \ + "X: B244F267488\r\n" \ + "S: D/9\r\n" + +#define RQNT2 "RQNT 186908781 1@mgw MGCP 1.0\r\n" \ + "X: ADD4F26746F\r\n" \ + "R: D/[0-9#*](N), G/ft, fxr/t38\r\n" + +#define RQNT1_RET "200 186908780 OK\r\n" +#define RQNT2_RET "200 186908781 OK\r\n" + +#define PTYPE_IGNORE 0 /* == default initializer */ +#define PTYPE_NONE 128 +#define PTYPE_NYI PTYPE_NONE + +#define CRCX_MULT_1 "CRCX 2 1@mgw MGCP 1.0\r\n" \ + "M: recvonly\r\n" \ + "C: 2\r\n" \ + "X\r\n" \ + "L: p:20\r\n" \ + "\r\n" \ + "v=0\r\n" \ + "c=IN IP4 123.12.12.123\r\n" \ + "m=audio 5904 RTP/AVP 18 97\r\n"\ + "a=rtpmap:18 G729/8000\r\n" \ + "a=rtpmap:97 GSM-EFR/8000\r\n" \ + "a=ptime:40\r\n" + +#define CRCX_MULT_2 "CRCX 2 2@mgw MGCP 1.0\r\n" \ + "M: recvonly\r\n" \ + "C: 2\r\n" \ + "X\r\n" \ + "L: p:20\r\n" \ + "\r\n" \ + "v=0\r\n" \ + "c=IN IP4 123.12.12.123\r\n" \ + "m=audio 5904 RTP/AVP 18 97 101\r\n"\ + "a=rtpmap:18 G729/8000\r\n" \ + "a=rtpmap:97 GSM-EFR/8000\r\n" \ + "a=rtpmap:101 FOO/8000\r\n" \ + "a=ptime:40\r\n" + +#define CRCX_MULT_3 "CRCX 2 3@mgw MGCP 1.0\r\n" \ + "M: recvonly\r\n" \ + "C: 2\r\n" \ + "X\r\n" \ + "L: p:20\r\n" \ + "\r\n" \ + "v=0\r\n" \ + "c=IN IP4 123.12.12.123\r\n" \ + "m=audio 5904 RTP/AVP\r\n" \ + "a=rtpmap:18 G729/8000\r\n" \ + "a=rtpmap:97 GSM-EFR/8000\r\n" \ + "a=rtpmap:101 FOO/8000\r\n" \ + "a=ptime:40\r\n" + +#define CRCX_MULT_4 "CRCX 2 4@mgw MGCP 1.0\r\n" \ + "M: recvonly\r\n" \ + "C: 2\r\n" \ + "X\r\n" \ + "L: p:20\r\n" \ + "\r\n" \ + "v=0\r\n" \ + "c=IN IP4 123.12.12.123\r\n" \ + "m=audio 5904 RTP/AVP 18\r\n" \ + "a=rtpmap:18 G729/8000\r\n" \ + "a=rtpmap:97 GSM-EFR/8000\r\n" \ + "a=rtpmap:101 FOO/8000\r\n" \ + "a=ptime:40\r\n" + +#define CRCX_MULT_GSM_EXACT \ + "CRCX 259260421 5@mgw MGCP 1.0\r\n" \ + "C: 1355c6041e\r\n" \ + "I: 3\r\n" \ + "L: p:20, a:GSM, nt:IN\r\n" \ + "M: recvonly\r\n" \ + "\r\n" \ + "v=0\r\n" \ + "o=- 1439038275 1439038275 IN IP4 192.168.181.247\r\n" \ + "s=-\r\nc=IN IP4 192.168.181.247\r\n" \ + "t=0 0\r\nm=audio 29084 RTP/AVP 255 0 8 3 18 4 96 97 101\r\n" \ + "a=rtpmap:0 PCMU/8000\r\n" \ + "a=rtpmap:8 PCMA/8000\r\n" \ + "a=rtpmap:3 gsm/8000\r\n" \ + "a=rtpmap:18 G729/8000\r\n" \ + "a=fmtp:18 annexb=no\r\n" \ + "a=rtpmap:4 G723/8000\r\n" \ + "a=rtpmap:96 iLBC/8000\r\n" \ + "a=fmtp:96 mode=20\r\n" \ + "a=rtpmap:97 iLBC/8000\r\n" \ + "a=fmtp:97 mode=30\r\n" \ + "a=rtpmap:101 telephone-event/8000\r\n" \ + "a=fmtp:101 0-15\r\n" \ + "a=recvonly\r\n" +#define MDCX_NAT_DUMMY \ + "MDCX 23 5@mgw MGCP 1.0\r\n" \ + "C: 1355c6041e\r\n" \ + "\r\n" \ + "c=IN IP4 8.8.8.8\r\n" \ + "m=audio 16434 RTP/AVP 255\r\n" + + +struct mgcp_test { + const char *name; + const char *req; + const char *exp_resp; + int exp_net_ptype; + int exp_bts_ptype; + + const char *extra_fmtp; +}; + +static const struct mgcp_test tests[] = { + { "AUEP1", AUEP1, AUEP1_RET }, + { "AUEP2", AUEP2, AUEP2_RET }, + { "MDCX1", MDCX_WRONG_EP, MDCX_ERR_RET }, + { "MDCX2", MDCX_UNALLOCATED, MDCX_RET }, + { "CRCX", CRCX, CRCX_RET, 97, 126 }, + { "MDCX3", MDCX3, MDCX3_RET, PTYPE_NONE, 126 }, + { "MDCX4", MDCX4, MDCX4_RET("18983216"), 99, 126 }, + { "MDCX4_PT1", MDCX4_PT1, MDCX4_RET("18983217"), 99, 126 }, + { "MDCX4_PT2", MDCX4_PT2, MDCX4_RET("18983218"), 99, 126 }, + { "MDCX4_PT3", MDCX4_PT3, MDCX4_RET("18983219"), 99, 126 }, + { "MDCX4_SO", MDCX4_SO, MDCX4_RET("18983220"), 99, 126 }, + { "MDCX4_RO", MDCX4_RO, MDCX4_RET("18983221"), PTYPE_IGNORE, 126 }, + { "DLCX", DLCX, DLCX_RET, -1, -1 }, + { "CRCX_ZYN", CRCX_ZYN, CRCX_ZYN_RET, 97, 126 }, + { "EMPTY", EMPTY, EMPTY_RET }, + { "SHORT1", SHORT, SHORT_RET }, + { "SHORT2", SHORT2, SHORT2_RET }, + { "SHORT3", SHORT3, SHORT2_RET }, + { "SHORT4", SHORT4, SHORT2_RET }, + { "RQNT1", RQNT, RQNT1_RET }, + { "RQNT2", RQNT2, RQNT2_RET }, + { "DLCX", DLCX, DLCX_RET, -1, -1 }, + { "CRCX", CRCX, CRCX_FMTP_RET, 97, 126, .extra_fmtp = "a=fmtp:126 0/1/2" }, + { "MDCX3", MDCX3, MDCX3_FMTP_RET, PTYPE_NONE, 126 , .extra_fmtp = "a=fmtp:126 0/1/2" }, + { "DLCX", DLCX, DLCX_RET, -1, -1 , .extra_fmtp = "a=fmtp:126 0/1/2" }, +}; + +static const struct mgcp_test retransmit[] = { + { "CRCX", CRCX, CRCX_RET }, + { "RQNT1", RQNT, RQNT1_RET }, + { "RQNT2", RQNT2, RQNT2_RET }, + { "MDCX3", MDCX3, MDCX3_RET }, + { "DLCX", DLCX, DLCX_RET }, +}; + +static struct msgb *create_msg(const char *str) +{ + struct msgb *msg; + + msg = msgb_alloc_headroom(4096, 128, "MGCP msg"); + int len = sprintf((char *)msg->data, "%s", str); + msg->l2h = msgb_put(msg, len); + return msg; +} + +static int last_endpoint = -1; + +static int mgcp_test_policy_cb(struct mgcp_trunk_config *cfg, int endpoint, + int state, const char *transactio_id) +{ + fprintf(stderr, "Policy CB got state %d on endpoint %d\n", + state, endpoint); + last_endpoint = endpoint; + return MGCP_POLICY_CONT; +} + +#define MGCP_DUMMY_LOAD 0x23 +static int dummy_packets = 0; +/* override and forward */ +ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, + const struct sockaddr *dest_addr, socklen_t addrlen) +{ + typedef ssize_t (*sendto_t)(int, const void *, size_t, int, + const struct sockaddr *, socklen_t); + static sendto_t real_sendto = NULL; + uint32_t dest_host = htonl(((struct sockaddr_in *)dest_addr)->sin_addr.s_addr); + int dest_port = htons(((struct sockaddr_in *)dest_addr)->sin_port); + + if (!real_sendto) + real_sendto = dlsym(RTLD_NEXT, "sendto"); + + if (len == 1 && ((const char *)buf)[0] == MGCP_DUMMY_LOAD ) { + fprintf(stderr, "Dummy packet to 0x%08x:%d, msg length %zu\n%s\n\n", + dest_host, dest_port, + len, osmo_hexdump(buf, len)); + dummy_packets += 1; + } + + return real_sendto(sockfd, buf, len, flags, dest_addr, addrlen); +} + +static int64_t force_monotonic_time_us = -1; +/* override and forward */ +int clock_gettime(clockid_t clk_id, struct timespec *tp) +{ + typedef int (*clock_gettime_t)(clockid_t clk_id, struct timespec *tp); + static clock_gettime_t real_clock_gettime = NULL; + + if (!real_clock_gettime) + real_clock_gettime = dlsym(RTLD_NEXT, "clock_gettime"); + + if (clk_id == CLOCK_MONOTONIC && force_monotonic_time_us >= 0) { + tp->tv_sec = force_monotonic_time_us / 1000000; + tp->tv_nsec = (force_monotonic_time_us % 1000000) * 1000; + return 0; + } + + return real_clock_gettime(clk_id, tp); +} + +#define CONN_UNMODIFIED (0x1000) + +static void test_values(void) +{ + /* Check that NONE disables all output */ + OSMO_ASSERT((MGCP_CONN_NONE & MGCP_CONN_RECV_SEND) == 0); + + /* Check that LOOPBACK enables all output */ + OSMO_ASSERT((MGCP_CONN_LOOPBACK & MGCP_CONN_RECV_SEND) == + MGCP_CONN_RECV_SEND); +} + + +static void test_messages(void) +{ + struct mgcp_config *cfg; + struct mgcp_endpoint *endp; + int i; + + cfg = mgcp_config_alloc(); + + cfg->trunk.number_endpoints = 64; + mgcp_endpoints_allocate(&cfg->trunk); + + cfg->policy_cb = mgcp_test_policy_cb; + + mgcp_endpoints_allocate(mgcp_trunk_alloc(cfg, 1)); + + /* reset endpoints */ + for (i = 0; i < cfg->trunk.number_endpoints; i++) { + endp = &cfg->trunk.endpoints[i]; + endp->net_end.codec.payload_type = PTYPE_NONE; + endp->net_end.packet_duration_ms = -1; + + OSMO_ASSERT(endp->conn_mode == MGCP_CONN_NONE); + endp->conn_mode |= CONN_UNMODIFIED; + } + + for (i = 0; i < ARRAY_SIZE(tests); i++) { + const struct mgcp_test *t = &tests[i]; + struct msgb *inp; + struct msgb *msg; + + printf("Testing %s\n", t->name); + + last_endpoint = -1; + dummy_packets = 0; + + osmo_talloc_replace_string(cfg, &cfg->trunk.audio_fmtp_extra, t->extra_fmtp); + + inp = create_msg(t->req); + msg = mgcp_handle_message(cfg, inp); + msgb_free(inp); + if (!t->exp_resp) { + if (msg) + printf("%s failed '%s'\n", t->name, (char *) msg->data); + } else if (strcmp((char *) msg->data, t->exp_resp) != 0) + printf("%s failed.\nExpected:\n%s\nGot:\n%s\n", + t->name, t->exp_resp, (char *) msg->data); + msgb_free(msg); + + if (dummy_packets) + printf("Dummy packets: %d\n", dummy_packets); + + if (last_endpoint != -1) { + endp = &cfg->trunk.endpoints[last_endpoint]; + + if (endp->net_end.packet_duration_ms != -1) + printf("Detected packet duration: %d\n", + endp->net_end.packet_duration_ms); + else + printf("Packet duration not set\n"); + if (endp->local_options.pkt_period_min || + endp->local_options.pkt_period_max) + printf("Requested packetetization period: " + "%d-%d\n", + endp->local_options.pkt_period_min, + endp->local_options.pkt_period_max); + else + printf("Requested packetization period not set\n"); + + if ((endp->conn_mode & CONN_UNMODIFIED) == 0) { + printf("Connection mode: %d:%s%s%s%s\n", + endp->conn_mode, + !endp->conn_mode ? " NONE" : "", + endp->conn_mode & MGCP_CONN_SEND_ONLY ? + " SEND" : "", + endp->conn_mode & MGCP_CONN_RECV_ONLY ? + " RECV" : "", + endp->conn_mode & MGCP_CONN_LOOPBACK & + ~MGCP_CONN_RECV_SEND ? + " LOOP" : ""); + fprintf(stderr, + "BTS output %sabled, NET output %sabled\n", + endp->bts_end.output_enabled ? "en" : "dis", + endp->net_end.output_enabled ? "en" : "dis"); + } else + printf("Connection mode not set\n"); + + OSMO_ASSERT(endp->net_end.output_enabled == + (endp->conn_mode & MGCP_CONN_SEND_ONLY ? 1 : 0)); + OSMO_ASSERT(endp->bts_end.output_enabled == + (endp->conn_mode & MGCP_CONN_RECV_ONLY ? 1 : 0)); + + endp->net_end.packet_duration_ms = -1; + endp->local_options.pkt_period_min = 0; + endp->local_options.pkt_period_max = 0; + endp->conn_mode |= CONN_UNMODIFIED; + } + + + /* Check detected payload type */ + if (t->exp_net_ptype != PTYPE_IGNORE || + t->exp_bts_ptype != PTYPE_IGNORE) { + OSMO_ASSERT(last_endpoint != -1); + endp = &cfg->trunk.endpoints[last_endpoint]; + + fprintf(stderr, "endpoint %d: " + "payload type BTS %d (exp %d), NET %d (exp %d)\n", + last_endpoint, + endp->bts_end.codec.payload_type, t->exp_bts_ptype, + endp->net_end.codec.payload_type, t->exp_net_ptype); + + if (t->exp_bts_ptype != PTYPE_IGNORE) + OSMO_ASSERT(endp->bts_end.codec.payload_type == + t->exp_bts_ptype); + if (t->exp_net_ptype != PTYPE_IGNORE) + OSMO_ASSERT(endp->net_end.codec.payload_type == + t->exp_net_ptype); + + /* Reset them again for next test */ + endp->net_end.codec.payload_type = PTYPE_NONE; + } + } + + talloc_free(cfg); +} + +static void test_retransmission(void) +{ + struct mgcp_config *cfg; + int i; + + cfg = mgcp_config_alloc(); + + cfg->trunk.number_endpoints = 64; + mgcp_endpoints_allocate(&cfg->trunk); + + mgcp_endpoints_allocate(mgcp_trunk_alloc(cfg, 1)); + + /* reset endpoints */ + for (i = 0; i < cfg->trunk.number_endpoints; i++) { + struct mgcp_endpoint *endp; + endp = &cfg->trunk.endpoints[i]; + endp->bts_end.packet_duration_ms = 20; + } + + for (i = 0; i < ARRAY_SIZE(retransmit); i++) { + const struct mgcp_test *t = &retransmit[i]; + struct msgb *inp; + struct msgb *msg; + + printf("Testing %s\n", t->name); + + inp = create_msg(t->req); + msg = mgcp_handle_message(cfg, inp); + msgb_free(inp); + if (strcmp((char *) msg->data, t->exp_resp) != 0) + printf("%s failed '%s'\n", t->name, (char *) msg->data); + msgb_free(msg); + + /* Retransmit... */ + printf("Re-transmitting %s\n", t->name); + inp = create_msg(t->req); + msg = mgcp_handle_message(cfg, inp); + msgb_free(inp); + if (strcmp((char *) msg->data, t->exp_resp) != 0) + printf("%s failed '%s'\n", t->name, (char *) msg->data); + msgb_free(msg); + } + + talloc_free(cfg); +} + +static int rqnt_cb(struct mgcp_endpoint *endp, char _tone) +{ + ptrdiff_t tone = _tone; + endp->cfg->data = (void *) tone; + return 0; +} + +static void test_rqnt_cb(void) +{ + struct mgcp_config *cfg; + struct msgb *inp, *msg; + + cfg = mgcp_config_alloc(); + cfg->rqnt_cb = rqnt_cb; + + cfg->trunk.number_endpoints = 64; + mgcp_endpoints_allocate(&cfg->trunk); + + mgcp_endpoints_allocate(mgcp_trunk_alloc(cfg, 1)); + + inp = create_msg(CRCX); + msgb_free(mgcp_handle_message(cfg, inp)); + msgb_free(inp); + + /* send the RQNT and check for the CB */ + inp = create_msg(RQNT); + msg = mgcp_handle_message(cfg, inp); + if (strncmp((const char *) msg->l2h, "200", 3) != 0) { + printf("FAILED: message is not 200. '%s'\n", msg->l2h); + abort(); + } + + if (cfg->data != (void *) '9') { + printf("FAILED: callback not called: %p\n", cfg->data); + abort(); + } + + msgb_free(msg); + msgb_free(inp); + + inp = create_msg(DLCX); + msgb_free(mgcp_handle_message(cfg, inp)); + msgb_free(inp); + talloc_free(cfg); +} + +struct pl_test { + int cycles; + uint16_t base_seq; + uint16_t max_seq; + uint32_t packets; + + uint32_t expected; + int loss; +}; + +static const struct pl_test pl_test_dat[] = { + /* basic.. just one package */ + { .cycles = 0, .base_seq = 0, .max_seq = 0, .packets = 1, .expected = 1, .loss = 0}, + /* some packages and a bit of loss */ + { .cycles = 0, .base_seq = 0, .max_seq = 100, .packets = 100, .expected = 101, .loss = 1}, + /* wrap around */ + { .cycles = 1<<16, .base_seq = 0xffff, .max_seq = 2, .packets = 4, .expected = 4, .loss = 0}, + /* min loss */ + { .cycles = 0, .base_seq = 0, .max_seq = 0, .packets = UINT_MAX, .expected = 1, .loss = INT_MIN }, + /* max loss, with wrap around on expected max */ + { .cycles = INT_MAX, .base_seq = 0, .max_seq = UINT16_MAX, .packets = 0, .expected = ((uint32_t)(INT_MAX) + UINT16_MAX + 1), .loss = INT_MAX }, +}; + +static void test_packet_loss_calc(void) +{ + int i; + printf("Testing packet loss calculation.\n"); + + for (i = 0; i < ARRAY_SIZE(pl_test_dat); ++i) { + uint32_t expected; + int loss; + struct mgcp_rtp_state state; + struct mgcp_rtp_end rtp; + memset(&state, 0, sizeof(state)); + memset(&rtp, 0, sizeof(rtp)); + + state.stats_initialized = 1; + state.stats_base_seq = pl_test_dat[i].base_seq; + state.stats_max_seq = pl_test_dat[i].max_seq; + state.stats_cycles = pl_test_dat[i].cycles; + + rtp.packets = pl_test_dat[i].packets; + mgcp_state_calc_loss(&state, &rtp, &expected, &loss); + + if (loss != pl_test_dat[i].loss || expected != pl_test_dat[i].expected) { + printf("FAIL: Wrong exp/loss at idx(%d) Loss(%d vs. %d) Exp(%u vs. %u)\n", + i, loss, pl_test_dat[i].loss, + expected, pl_test_dat[i].expected); + } + } +} + +static void test_mgcp_stats(void) +{ + printf("Testing stat parsing\n"); + + uint32_t bps, bos, pr, _or, jitter; + struct msgb *msg; + int loss; + int rc; + + msg = create_msg(DLCX_RET); + rc = mgcp_parse_stats(msg, &bps, &bos, &pr, &_or, &loss, &jitter); + printf("Parsing result: %d\n", rc); + if (bps != 0 || bos != 0 || pr != 0 || _or != 0 || loss != 0 || jitter != 0) + printf("FAIL: Parsing failed1.\n"); + msgb_free(msg); + + msg = create_msg("250 7 OK\r\nP: PS=10, OS=20, PR=30, OR=40, PL=-3, JI=40\r\n"); + rc = mgcp_parse_stats(msg, &bps, &bos, &pr, &_or, &loss, &jitter); + printf("Parsing result: %d\n", rc); + if (bps != 10 || bos != 20 || pr != 30 || _or != 40 || loss != -3 || jitter != 40) + printf("FAIL: Parsing failed2.\n"); + msgb_free(msg); +} + +struct rtp_packet_info { + float txtime; + int len; + char *data; +}; + +struct rtp_packet_info test_rtp_packets1[] = { + /* RTP: SeqNo=0, TS=0 */ + {0.000000, 20, "\x80\x62\x00\x00\x00\x00\x00\x00\x11\x22\x33\x44" + "\x01\x23\x45\x67\x89\xAB\xCD\xEF"}, + /* RTP: SeqNo=1, TS=160 */ + {0.020000, 20, "\x80\x62\x00\x01\x00\x00\x00\xA0\x11\x22\x33\x44" + "\x01\x23\x45\x67\x89\xAB\xCD\xEF"}, + /* RTP: SeqNo=2, TS=320 */ + {0.040000, 20, "\x80\x62\x00\x02\x00\x00\x01\x40\x11\x22\x33\x44" + "\x01\x23\x45\x67\x89\xAB\xCD\xEF"}, + /* Repeat RTP timestamp: */ + /* RTP: SeqNo=3, TS=320 */ + {0.060000, 20, "\x80\x62\x00\x03\x00\x00\x01\x40\x11\x22\x33\x44" + "\x01\x23\x45\x67\x89\xAB\xCD\xEF"}, + /* RTP: SeqNo=4, TS=480 */ + {0.080000, 20, "\x80\x62\x00\x04\x00\x00\x01\xE0\x11\x22\x33\x44" + "\x01\x23\x45\x67\x89\xAB\xCD\xEF"}, + /* RTP: SeqNo=5, TS=640 */ + {0.100000, 20, "\x80\x62\x00\x05\x00\x00\x02\x80\x11\x22\x33\x44" + "\x01\x23\x45\x67\x89\xAB\xCD\xEF"}, + /* Double skip RTP timestamp (delta = 2*160): */ + /* RTP: SeqNo=6, TS=960 */ + {0.120000, 20, "\x80\x62\x00\x06\x00\x00\x03\xC0\x11\x22\x33\x44" + "\x01\x23\x45\x67\x89\xAB\xCD\xEF"}, + /* RTP: SeqNo=7, TS=1120 */ + {0.140000, 20, "\x80\x62\x00\x07\x00\x00\x04\x60\x11\x22\x33\x44" + "\x01\x23\x45\x67\x89\xAB\xCD\xEF"}, + /* RTP: SeqNo=8, TS=1280 */ + {0.160000, 20, "\x80\x62\x00\x08\x00\x00\x05\x00\x11\x22\x33\x44" + "\x01\x23\x45\x67\x89\xAB\xCD\xEF"}, + /* Non 20ms RTP timestamp (delta = 120): */ + /* RTP: SeqNo=9, TS=1400 */ + {0.180000, 20, "\x80\x62\x00\x09\x00\x00\x05\x78\x11\x22\x33\x44" + "\x01\x23\x45\x67\x89\xAB\xCD\xEF"}, + /* RTP: SeqNo=10, TS=1560 */ + {0.200000, 20, "\x80\x62\x00\x0A\x00\x00\x06\x18\x11\x22\x33\x44" + "\x01\x23\x45\x67\x89\xAB\xCD\xEF"}, + /* RTP: SeqNo=11, TS=1720 */ + {0.220000, 20, "\x80\x62\x00\x0B\x00\x00\x06\xB8\x11\x22\x33\x44" + "\x01\x23\x45\x67\x89\xAB\xCD\xEF"}, + /* SSRC changed to 0x10203040, RTP timestamp jump */ + /* RTP: SeqNo=12, TS=34688 */ + {0.240000, 20, "\x80\x62\x00\x0C\x00\x00\x87\x80\x10\x20\x30\x40" + "\x01\x23\x45\x67\x89\xAB\xCD\xEF"}, + /* RTP: SeqNo=13, TS=34848 */ + {0.260000, 20, "\x80\x62\x00\x0D\x00\x00\x88\x20\x10\x20\x30\x40" + "\x01\x23\x45\x67\x89\xAB\xCD\xEF"}, + /* RTP: SeqNo=14, TS=35008 */ + {0.280000, 20, "\x80\x62\x00\x0E\x00\x00\x88\xC0\x10\x20\x30\x40" + "\x01\x23\x45\x67\x89\xAB\xCD\xEF"}, + /* Non 20ms RTP timestamp (delta = 120): */ + /* RTP: SeqNo=15, TS=35128 */ + {0.300000, 20, "\x80\x62\x00\x0F\x00\x00\x89\x38\x10\x20\x30\x40" + "\x01\x23\x45\x67\x89\xAB\xCD\xEF"}, + /* RTP: SeqNo=16, TS=35288 */ + {0.320000, 20, "\x80\x62\x00\x10\x00\x00\x89\xD8\x10\x20\x30\x40" + "\x01\x23\x45\x67\x89\xAB\xCD\xEF"}, + /* RTP: SeqNo=17, TS=35448 */ + {0.340000, 20, "\x80\x62\x00\x11\x00\x00\x8A\x78\x10\x20\x30\x40" + "\x01\x23\x45\x67\x8A\xAB\xCD\xEF"}, + /* SeqNo increment by 2, RTP timestamp delta = 320: */ + /* RTP: SeqNo=19, TS=35768 */ + {0.360000, 20, "\x80\x62\x00\x13\x00\x00\x8B\xB8\x10\x20\x30\x40" + "\x01\x23\x45\x67\x89\xAB\xCD\xEF"}, + /* RTP: SeqNo=20, TS=35928 */ + {0.380000, 20, "\x80\x62\x00\x14\x00\x00\x8C\x58\x10\x20\x30\x40" + "\x01\x23\x45\x67\x89\xAB\xCD\xEF"}, + /* RTP: SeqNo=21, TS=36088 */ + {0.380000, 20, "\x80\x62\x00\x15\x00\x00\x8C\xF8\x10\x20\x30\x40" + "\x01\x23\x45\x67\x89\xAB\xCD\xEF"}, + /* Repeat last packet */ + /* RTP: SeqNo=21, TS=36088 */ + {0.400000, 20, "\x80\x62\x00\x15\x00\x00\x8C\xF8\x10\x20\x30\x40" + "\x01\x23\x45\x67\x89\xAB\xCD\xEF"}, + /* RTP: SeqNo=22, TS=36248 */ + {0.420000, 20, "\x80\x62\x00\x16\x00\x00\x8D\x98\x10\x20\x30\x40" + "\x01\x23\x45\x67\x89\xAB\xCD\xEF"}, + /* RTP: SeqNo=23, TS=36408 */ + {0.440000, 20, "\x80\x62\x00\x17\x00\x00\x8E\x38\x10\x20\x30\x40" + "\x01\x23\x45\x67\x89\xAB\xCD\xEF"}, + /* Don't increment SeqNo but increment timestamp by 160 */ + /* RTP: SeqNo=23, TS=36568 */ + {0.460000, 20, "\x80\x62\x00\x17\x00\x00\x8E\xD8\x10\x20\x30\x40" + "\x01\x23\x45\x67\x89\xAB\xCD\xEF"}, + /* RTP: SeqNo=24, TS=36728 */ + {0.480000, 20, "\x80\x62\x00\x18\x00\x00\x8F\x78\x10\x20\x30\x40" + "\x01\x23\x45\x67\x89\xAB\xCD\xEF"}, + /* RTP: SeqNo=25, TS=36888 */ + {0.500000, 20, "\x80\x62\x00\x19\x00\x00\x90\x18\x10\x20\x30\x40" + "\x01\x23\x45\x67\x89\xAB\xCD\xEF"}, + /* SSRC changed to 0x50607080, RTP timestamp jump, Delay of 1.5s, + * SeqNo jump */ + /* RTP: SeqNo=1000, TS=160000 */ + {2.000000, 20, "\x80\x62\x03\xE8\x00\x02\x71\x00\x50\x60\x70\x80" + "\x01\x23\x45\x67\x89\xAB\xCD\xEF"}, + /* RTP: SeqNo=1001, TS=160160 */ + {2.020000, 20, "\x80\x62\x03\xE9\x00\x02\x71\xA0\x50\x60\x70\x80" + "\x01\x23\x45\x67\x89\xAB\xCD\xEF"}, + /* RTP: SeqNo=1002, TS=160320 */ + {2.040000, 20, "\x80\x62\x03\xEA\x00\x02\x72\x40\x50\x60\x70\x80" + "\x01\x23\x45\x67\x89\xAB\xCD\xEF"}, +}; + +void mgcp_patch_and_count(struct mgcp_endpoint *endp, struct mgcp_rtp_state *state, + struct mgcp_rtp_end *rtp_end, struct sockaddr_in *addr, + char *data, int len); + +static void test_packet_error_detection(int patch_ssrc, int patch_ts) +{ + int i; + + struct mgcp_trunk_config trunk; + struct mgcp_endpoint endp; + struct mgcp_rtp_state state; + struct mgcp_rtp_end *rtp = &endp.net_end; + struct sockaddr_in addr = {0}; + char buffer[4096]; + uint32_t last_ssrc = 0; + uint32_t last_timestamp = 0; + uint32_t last_seqno = 0; + int last_in_ts_err_cnt = 0; + int last_out_ts_err_cnt = 0; + + printf("Testing packet error detection%s%s.\n", + patch_ssrc ? ", patch SSRC" : "", + patch_ts ? ", patch timestamps" : ""); + + memset(&trunk, 0, sizeof(trunk)); + memset(&endp, 0, sizeof(endp)); + memset(&state, 0, sizeof(state)); + + trunk.number_endpoints = 1; + trunk.endpoints = &endp; + trunk.force_constant_ssrc = patch_ssrc; + trunk.force_aligned_timing = patch_ts; + + endp.tcfg = &trunk; + + mgcp_initialize_endp(&endp); + + rtp->codec.payload_type = 98; + + for (i = 0; i < ARRAY_SIZE(test_rtp_packets1); ++i) { + struct rtp_packet_info *info = test_rtp_packets1 + i; + + force_monotonic_time_us = round(1000000.0 * info->txtime); + + OSMO_ASSERT(info->len <= sizeof(buffer)); + OSMO_ASSERT(info->len >= 0); + memmove(buffer, info->data, info->len); + + mgcp_rtp_end_config(&endp, 1, rtp); + + mgcp_patch_and_count(&endp, &state, rtp, &addr, + buffer, info->len); + + if (state.out_stream.ssrc != last_ssrc) { + printf("Output SSRC changed to %08x\n", + state.out_stream.ssrc); + last_ssrc = state.out_stream.ssrc; + } + + printf("In TS: %d, dTS: %d, Seq: %d\n", + state.in_stream.last_timestamp, + state.in_stream.last_tsdelta, + state.in_stream.last_seq); + + printf("Out TS change: %d, dTS: %d, Seq change: %d, " + "TS Err change: in %+d, out %+d\n", + state.out_stream.last_timestamp - last_timestamp, + state.out_stream.last_tsdelta, + state.out_stream.last_seq - last_seqno, + state.in_stream.err_ts_counter - last_in_ts_err_cnt, + state.out_stream.err_ts_counter - last_out_ts_err_cnt); + + printf("Stats: Jitter = %u, Transit = %d\n", + mgcp_state_calc_jitter(&state), state.stats_transit); + + last_in_ts_err_cnt = state.in_stream.err_ts_counter; + last_out_ts_err_cnt = state.out_stream.err_ts_counter; + last_timestamp = state.out_stream.last_timestamp; + last_seqno = state.out_stream.last_seq; + } + + force_monotonic_time_us = -1; +} + +static void test_multilple_codec(void) +{ + struct mgcp_config *cfg; + struct mgcp_endpoint *endp; + struct msgb *inp, *resp; + struct in_addr addr; + + printf("Testing multiple payload types\n"); + + cfg = mgcp_config_alloc(); + cfg->trunk.number_endpoints = 64; + mgcp_endpoints_allocate(&cfg->trunk); + cfg->policy_cb = mgcp_test_policy_cb; + mgcp_endpoints_allocate(mgcp_trunk_alloc(cfg, 1)); + + /* Allocate endpoint 1@mgw with two codecs */ + last_endpoint = -1; + inp = create_msg(CRCX_MULT_1); + resp = mgcp_handle_message(cfg, inp); + msgb_free(inp); + msgb_free(resp); + + OSMO_ASSERT(last_endpoint == 1); + endp = &cfg->trunk.endpoints[last_endpoint]; + OSMO_ASSERT(endp->net_end.codec.payload_type == 18); + OSMO_ASSERT(endp->net_end.alt_codec.payload_type == 97); + + /* Allocate 2@mgw with three codecs, last one ignored */ + last_endpoint = -1; + inp = create_msg(CRCX_MULT_2); + resp = mgcp_handle_message(cfg, inp); + msgb_free(inp); + msgb_free(resp); + + OSMO_ASSERT(last_endpoint == 2); + endp = &cfg->trunk.endpoints[last_endpoint]; + OSMO_ASSERT(endp->net_end.codec.payload_type == 18); + OSMO_ASSERT(endp->net_end.alt_codec.payload_type == 97); + + /* Allocate 3@mgw with no codecs, check for PT == -1 */ + last_endpoint = -1; + inp = create_msg(CRCX_MULT_3); + resp = mgcp_handle_message(cfg, inp); + msgb_free(inp); + msgb_free(resp); + + OSMO_ASSERT(last_endpoint == 3); + endp = &cfg->trunk.endpoints[last_endpoint]; + OSMO_ASSERT(endp->net_end.codec.payload_type == -1); + OSMO_ASSERT(endp->net_end.alt_codec.payload_type == -1); + + /* Allocate 4@mgw with a single codec */ + last_endpoint = -1; + inp = create_msg(CRCX_MULT_4); + resp = mgcp_handle_message(cfg, inp); + msgb_free(inp); + msgb_free(resp); + + OSMO_ASSERT(last_endpoint == 4); + endp = &cfg->trunk.endpoints[last_endpoint]; + OSMO_ASSERT(endp->net_end.codec.payload_type == 18); + OSMO_ASSERT(endp->net_end.alt_codec.payload_type == -1); + + /* Allocate 5@mgw at select GSM.. */ + last_endpoint = -1; + inp = create_msg(CRCX_MULT_GSM_EXACT); + talloc_free(cfg->trunk.audio_name); + cfg->trunk.audio_name = "GSM/8000"; + cfg->trunk.no_audio_transcoding = 1; + resp = mgcp_handle_message(cfg, inp); + msgb_free(inp); + msgb_free(resp); + + OSMO_ASSERT(last_endpoint == 5); + endp = &cfg->trunk.endpoints[last_endpoint]; + OSMO_ASSERT(endp->net_end.codec.payload_type == 3); + OSMO_ASSERT(endp->net_end.alt_codec.payload_type == -1); + + inp = create_msg(MDCX_NAT_DUMMY); + last_endpoint = -1; + resp = mgcp_handle_message(cfg, inp); + msgb_free(inp); + msgb_free(resp); + OSMO_ASSERT(last_endpoint == 5); + endp = &cfg->trunk.endpoints[last_endpoint]; + OSMO_ASSERT(endp->net_end.codec.payload_type == 3); + OSMO_ASSERT(endp->net_end.alt_codec.payload_type == -1); + OSMO_ASSERT(endp->net_end.rtp_port == htons(16434)); + memset(&addr, 0, sizeof(addr)); + inet_aton("8.8.8.8", &addr); + OSMO_ASSERT(endp->net_end.addr.s_addr == addr.s_addr); + + /* Check what happens without that flag */ + + /* Free the previous endpoint and the data ... */ + mgcp_release_endp(endp); + talloc_free(endp->last_response); + talloc_free(endp->last_trans); + endp->last_response = endp->last_trans = NULL; + + last_endpoint = -1; + inp = create_msg(CRCX_MULT_GSM_EXACT); + cfg->trunk.no_audio_transcoding = 0; + resp = mgcp_handle_message(cfg, inp); + msgb_free(inp); + msgb_free(resp); + + OSMO_ASSERT(last_endpoint == 5); + endp = &cfg->trunk.endpoints[last_endpoint]; + OSMO_ASSERT(endp->net_end.codec.payload_type == 255); + OSMO_ASSERT(endp->net_end.alt_codec.payload_type == 0); + + talloc_free(cfg); +} + +static void test_no_cycle(void) +{ + struct mgcp_config *cfg; + struct mgcp_endpoint *endp; + + printf("Testing no sequence flow on initial packet\n"); + + cfg = mgcp_config_alloc(); + cfg->trunk.number_endpoints = 64; + mgcp_endpoints_allocate(&cfg->trunk); + + endp = &cfg->trunk.endpoints[1]; + OSMO_ASSERT(endp->net_state.stats_initialized == 0); + + mgcp_rtp_annex_count(endp, &endp->net_state, 0, 0, 2342); + OSMO_ASSERT(endp->net_state.stats_initialized == 1); + OSMO_ASSERT(endp->net_state.stats_cycles == 0); + OSMO_ASSERT(endp->net_state.stats_max_seq == 0); + + mgcp_rtp_annex_count(endp, &endp->net_state, 1, 0, 2342); + OSMO_ASSERT(endp->net_state.stats_initialized == 1); + OSMO_ASSERT(endp->net_state.stats_cycles == 0); + OSMO_ASSERT(endp->net_state.stats_max_seq == 1); + + /* now jump.. */ + mgcp_rtp_annex_count(endp, &endp->net_state, UINT16_MAX, 0, 2342); + OSMO_ASSERT(endp->net_state.stats_initialized == 1); + OSMO_ASSERT(endp->net_state.stats_cycles == 0); + OSMO_ASSERT(endp->net_state.stats_max_seq == UINT16_MAX); + + /* and wrap */ + mgcp_rtp_annex_count(endp, &endp->net_state, 0, 0, 2342); + OSMO_ASSERT(endp->net_state.stats_initialized == 1); + OSMO_ASSERT(endp->net_state.stats_cycles == UINT16_MAX + 1); + OSMO_ASSERT(endp->net_state.stats_max_seq == 0); + + talloc_free(cfg); +} + +static void test_no_name(void) +{ + struct mgcp_config *cfg; + struct mgcp_endpoint *endp; + struct msgb *inp, *msg; + int i; + + printf("Testing no rtpmap name\n"); + cfg = mgcp_config_alloc(); + + cfg->trunk.number_endpoints = 64; + cfg->trunk.audio_send_name = 0; + mgcp_endpoints_allocate(&cfg->trunk); + + cfg->policy_cb = mgcp_test_policy_cb; + + mgcp_endpoints_allocate(mgcp_trunk_alloc(cfg, 1)); + + /* reset endpoints */ + for (i = 0; i < cfg->trunk.number_endpoints; i++) { + endp = &cfg->trunk.endpoints[i]; + endp->net_end.codec.payload_type = PTYPE_NONE; + endp->net_end.packet_duration_ms = -1; + + OSMO_ASSERT(endp->conn_mode == MGCP_CONN_NONE); + endp->conn_mode |= CONN_UNMODIFIED; + } + + inp = create_msg(CRCX); + msg = mgcp_handle_message(cfg, inp); + if (strcmp((char *) msg->data, CRCX_RET_NO_RTPMAP) != 0) + printf("FAILED: there should not be a RTPMAP: %s\n", + (char *) msg->data); + msgb_free(inp); + msgb_free(msg); + + mgcp_release_endp(&cfg->trunk.endpoints[1]); + talloc_free(cfg); +} + +static void test_osmux_cid(void) +{ + int id, i; + + OSMO_ASSERT(osmux_used_cid() == 0); + id = osmux_get_cid(); + OSMO_ASSERT(id == 0); + OSMO_ASSERT(osmux_used_cid() == 1); + osmux_put_cid(id); + OSMO_ASSERT(osmux_used_cid() == 0); + + for (i = 0; i < 256; ++i) { + id = osmux_get_cid(); + OSMO_ASSERT(id == i); + OSMO_ASSERT(osmux_used_cid() == i + 1); + } + + id = osmux_get_cid(); + OSMO_ASSERT(id == -1); + + for (i = 0; i < 256; ++i) + osmux_put_cid(i); + OSMO_ASSERT(osmux_used_cid() == 0); +} + +static const struct log_info_cat log_categories[] = { +}; + +const struct log_info log_info = { + .cat = log_categories, + .num_cat = ARRAY_SIZE(log_categories), +}; + +int main(int argc, char **argv) +{ + msgb_talloc_ctx_init(NULL, 0); + osmo_init_logging(&log_info); + + test_strline(); + test_values(); + test_messages(); + test_retransmission(); + test_packet_loss_calc(); + test_rqnt_cb(); + test_mgcp_stats(); + test_packet_error_detection(1, 0); + test_packet_error_detection(0, 0); + test_packet_error_detection(0, 1); + test_packet_error_detection(1, 1); + test_multilple_codec(); + test_no_cycle(); + test_no_name(); + test_osmux_cid(); + + printf("Done\n"); + return EXIT_SUCCESS; +} diff --git a/tests/legacy_mgcp/mgcp_test.ok b/tests/legacy_mgcp/mgcp_test.ok new file mode 100644 index 0000000..4e27282 --- /dev/null +++ b/tests/legacy_mgcp/mgcp_test.ok @@ -0,0 +1,480 @@ +line: 'one CR' +line: 'two CR' +line: '' +line: 'one CRLF' +line: 'two CRLF' +line: '' +line: 'one LF' +line: 'two LF' +line: '' +line: 'mixed (4 lines)' +line: '' +line: '' +line: '' +Testing AUEP1 +Testing AUEP2 +Testing MDCX1 +Testing MDCX2 +Testing CRCX +Dummy packets: 1 +Detected packet duration: 40 +Requested packetetization period: 20-20 +Connection mode: 1: RECV +Testing MDCX3 +Dummy packets: 1 +Packet duration not set +Requested packetization period not set +Connection mode not set +Testing MDCX4 +Dummy packets: 1 +Detected packet duration: 40 +Requested packetetization period: 20-20 +Connection mode: 3: SEND RECV +Testing MDCX4_PT1 +Dummy packets: 1 +Detected packet duration: 40 +Requested packetetization period: 20-40 +Connection mode: 3: SEND RECV +Testing MDCX4_PT2 +Dummy packets: 1 +Detected packet duration: 40 +Requested packetetization period: 20-20 +Connection mode: 3: SEND RECV +Testing MDCX4_PT3 +Dummy packets: 1 +Detected packet duration: 40 +Requested packetization period not set +Connection mode: 3: SEND RECV +Testing MDCX4_SO +Detected packet duration: 40 +Requested packetetization period: 20-20 +Connection mode: 2: SEND +Testing MDCX4_RO +Dummy packets: 1 +Packet duration not set +Requested packetetization period: 20-20 +Connection mode: 1: RECV +Testing DLCX +Detected packet duration: 20 +Requested packetization period not set +Connection mode: 0: NONE +Testing CRCX_ZYN +Dummy packets: 1 +Packet duration not set +Requested packetization period not set +Connection mode: 1: RECV +Testing EMPTY +Testing SHORT1 +Testing SHORT2 +Testing SHORT3 +Testing SHORT4 +Testing RQNT1 +Testing RQNT2 +Testing DLCX +Detected packet duration: 20 +Requested packetization period not set +Connection mode: 0: NONE +Testing CRCX +Dummy packets: 1 +Detected packet duration: 40 +Requested packetetization period: 20-20 +Connection mode: 1: RECV +Testing MDCX3 +Dummy packets: 1 +Packet duration not set +Requested packetization period not set +Connection mode not set +Testing DLCX +Detected packet duration: 20 +Requested packetization period not set +Connection mode: 0: NONE +Testing CRCX +Re-transmitting CRCX +Testing RQNT1 +Re-transmitting RQNT1 +Testing RQNT2 +Re-transmitting RQNT2 +Testing MDCX3 +Re-transmitting MDCX3 +Testing DLCX +Re-transmitting DLCX +Testing packet loss calculation. +Testing stat parsing +Parsing result: 0 +Parsing result: 0 +Testing packet error detection, patch SSRC. +Output SSRC changed to 11223344 +In TS: 0, dTS: 0, Seq: 0 +Out TS change: 0, dTS: 0, Seq change: 0, TS Err change: in +0, out +0 +Stats: Jitter = 0, Transit = 0 +In TS: 160, dTS: 160, Seq: 1 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 0, Transit = 0 +In TS: 320, dTS: 160, Seq: 2 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 0, Transit = 0 +In TS: 320, dTS: 160, Seq: 3 +Out TS change: 0, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 10, Transit = 160 +In TS: 480, dTS: 160, Seq: 4 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 9, Transit = 160 +In TS: 640, dTS: 160, Seq: 5 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 8, Transit = 160 +In TS: 960, dTS: 320, Seq: 6 +Out TS change: 320, dTS: 320, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 18, Transit = 0 +In TS: 1120, dTS: 160, Seq: 7 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 17, Transit = 0 +In TS: 1280, dTS: 160, Seq: 8 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 16, Transit = 0 +In TS: 1400, dTS: 120, Seq: 9 +Out TS change: 120, dTS: 120, Seq change: 1, TS Err change: in +1, out +1 +Stats: Jitter = 17, Transit = 40 +In TS: 1560, dTS: 160, Seq: 10 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 16, Transit = 40 +In TS: 1720, dTS: 160, Seq: 11 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 15, Transit = 40 +In TS: 34688, dTS: 0, Seq: 12 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 0, Transit = -32768 +In TS: 34848, dTS: 160, Seq: 13 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 0, Transit = -32768 +In TS: 35008, dTS: 160, Seq: 14 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 0, Transit = -32768 +In TS: 35128, dTS: 120, Seq: 15 +Out TS change: 120, dTS: 120, Seq change: 1, TS Err change: in +1, out +1 +Stats: Jitter = 2, Transit = -32728 +In TS: 35288, dTS: 160, Seq: 16 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 2, Transit = -32728 +In TS: 35448, dTS: 160, Seq: 17 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 2, Transit = -32728 +In TS: 35768, dTS: 160, Seq: 19 +Out TS change: 320, dTS: 160, Seq change: 2, TS Err change: in +0, out +0 +Stats: Jitter = 12, Transit = -32888 +In TS: 35928, dTS: 160, Seq: 20 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 11, Transit = -32888 +In TS: 36088, dTS: 160, Seq: 21 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 20, Transit = -33048 +In TS: 36088, dTS: 160, Seq: 21 +Out TS change: 0, dTS: 160, Seq change: 0, TS Err change: in +0, out +0 +Stats: Jitter = 29, Transit = -32888 +In TS: 36248, dTS: 160, Seq: 22 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 27, Transit = -32888 +In TS: 36408, dTS: 160, Seq: 23 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 25, Transit = -32888 +In TS: 36568, dTS: 160, Seq: 23 +Out TS change: 160, dTS: 160, Seq change: 0, TS Err change: in +1, out +1 +Stats: Jitter = 24, Transit = -32888 +In TS: 36728, dTS: 160, Seq: 24 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 22, Transit = -32888 +In TS: 36888, dTS: 160, Seq: 25 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 21, Transit = -32888 +In TS: 160000, dTS: 0, Seq: 1000 +Out TS change: 12000, dTS: 12000, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 0, Transit = -144000 +In TS: 160160, dTS: 160, Seq: 1001 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 0, Transit = -144000 +In TS: 160320, dTS: 160, Seq: 1002 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 0, Transit = -144000 +Testing packet error detection. +Output SSRC changed to 11223344 +In TS: 0, dTS: 0, Seq: 0 +Out TS change: 0, dTS: 0, Seq change: 0, TS Err change: in +0, out +0 +Stats: Jitter = 0, Transit = 0 +In TS: 160, dTS: 160, Seq: 1 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 0, Transit = 0 +In TS: 320, dTS: 160, Seq: 2 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 0, Transit = 0 +In TS: 320, dTS: 160, Seq: 3 +Out TS change: 0, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 10, Transit = 160 +In TS: 480, dTS: 160, Seq: 4 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 9, Transit = 160 +In TS: 640, dTS: 160, Seq: 5 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 8, Transit = 160 +In TS: 960, dTS: 320, Seq: 6 +Out TS change: 320, dTS: 320, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 18, Transit = 0 +In TS: 1120, dTS: 160, Seq: 7 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 17, Transit = 0 +In TS: 1280, dTS: 160, Seq: 8 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 16, Transit = 0 +In TS: 1400, dTS: 120, Seq: 9 +Out TS change: 120, dTS: 120, Seq change: 1, TS Err change: in +1, out +1 +Stats: Jitter = 17, Transit = 40 +In TS: 1560, dTS: 160, Seq: 10 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 16, Transit = 40 +In TS: 1720, dTS: 160, Seq: 11 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 15, Transit = 40 +Output SSRC changed to 10203040 +In TS: 34688, dTS: 0, Seq: 12 +Out TS change: 32968, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 0, Transit = -32768 +In TS: 34848, dTS: 160, Seq: 13 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 0, Transit = -32768 +In TS: 35008, dTS: 160, Seq: 14 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 0, Transit = -32768 +In TS: 35128, dTS: 120, Seq: 15 +Out TS change: 120, dTS: 120, Seq change: 1, TS Err change: in +1, out +1 +Stats: Jitter = 2, Transit = -32728 +In TS: 35288, dTS: 160, Seq: 16 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 2, Transit = -32728 +In TS: 35448, dTS: 160, Seq: 17 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 2, Transit = -32728 +In TS: 35768, dTS: 160, Seq: 19 +Out TS change: 320, dTS: 160, Seq change: 2, TS Err change: in +0, out +0 +Stats: Jitter = 12, Transit = -32888 +In TS: 35928, dTS: 160, Seq: 20 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 11, Transit = -32888 +In TS: 36088, dTS: 160, Seq: 21 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 20, Transit = -33048 +In TS: 36088, dTS: 160, Seq: 21 +Out TS change: 0, dTS: 160, Seq change: 0, TS Err change: in +0, out +0 +Stats: Jitter = 29, Transit = -32888 +In TS: 36248, dTS: 160, Seq: 22 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 27, Transit = -32888 +In TS: 36408, dTS: 160, Seq: 23 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 25, Transit = -32888 +In TS: 36568, dTS: 160, Seq: 23 +Out TS change: 160, dTS: 160, Seq change: 0, TS Err change: in +1, out +1 +Stats: Jitter = 24, Transit = -32888 +In TS: 36728, dTS: 160, Seq: 24 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 22, Transit = -32888 +In TS: 36888, dTS: 160, Seq: 25 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 21, Transit = -32888 +Output SSRC changed to 50607080 +In TS: 160000, dTS: 0, Seq: 1000 +Out TS change: 123112, dTS: 160, Seq change: 975, TS Err change: in +0, out +0 +Stats: Jitter = 0, Transit = -144000 +In TS: 160160, dTS: 160, Seq: 1001 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 0, Transit = -144000 +In TS: 160320, dTS: 160, Seq: 1002 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 0, Transit = -144000 +Testing packet error detection, patch timestamps. +Output SSRC changed to 11223344 +In TS: 0, dTS: 0, Seq: 0 +Out TS change: 0, dTS: 0, Seq change: 0, TS Err change: in +0, out +0 +Stats: Jitter = 0, Transit = 0 +In TS: 160, dTS: 160, Seq: 1 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 0, Transit = 0 +In TS: 320, dTS: 160, Seq: 2 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 0, Transit = 0 +In TS: 320, dTS: 160, Seq: 3 +Out TS change: 0, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 10, Transit = 160 +In TS: 480, dTS: 160, Seq: 4 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 9, Transit = 160 +In TS: 640, dTS: 160, Seq: 5 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 8, Transit = 160 +In TS: 960, dTS: 320, Seq: 6 +Out TS change: 320, dTS: 320, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 18, Transit = 0 +In TS: 1120, dTS: 160, Seq: 7 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 17, Transit = 0 +In TS: 1280, dTS: 160, Seq: 8 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 16, Transit = 0 +In TS: 1400, dTS: 120, Seq: 9 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +1, out +0 +Stats: Jitter = 17, Transit = 40 +In TS: 1560, dTS: 160, Seq: 10 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 16, Transit = 40 +In TS: 1720, dTS: 160, Seq: 11 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 15, Transit = 40 +Output SSRC changed to 10203040 +In TS: 34688, dTS: 0, Seq: 12 +Out TS change: 32968, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 0, Transit = -32768 +In TS: 34848, dTS: 160, Seq: 13 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 0, Transit = -32768 +In TS: 35008, dTS: 160, Seq: 14 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 0, Transit = -32768 +In TS: 35128, dTS: 120, Seq: 15 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +1, out +0 +Stats: Jitter = 2, Transit = -32728 +In TS: 35288, dTS: 160, Seq: 16 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 2, Transit = -32728 +In TS: 35448, dTS: 160, Seq: 17 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 2, Transit = -32728 +In TS: 35768, dTS: 160, Seq: 19 +Out TS change: 320, dTS: 160, Seq change: 2, TS Err change: in +0, out +0 +Stats: Jitter = 12, Transit = -32888 +In TS: 35928, dTS: 160, Seq: 20 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 11, Transit = -32888 +In TS: 36088, dTS: 160, Seq: 21 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 20, Transit = -33048 +In TS: 36088, dTS: 160, Seq: 21 +Out TS change: 0, dTS: 160, Seq change: 0, TS Err change: in +0, out +0 +Stats: Jitter = 29, Transit = -32888 +In TS: 36248, dTS: 160, Seq: 22 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 27, Transit = -32888 +In TS: 36408, dTS: 160, Seq: 23 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 25, Transit = -32888 +In TS: 36568, dTS: 160, Seq: 23 +Out TS change: 160, dTS: 160, Seq change: 0, TS Err change: in +1, out +1 +Stats: Jitter = 24, Transit = -32888 +In TS: 36728, dTS: 160, Seq: 24 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 22, Transit = -32888 +In TS: 36888, dTS: 160, Seq: 25 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 21, Transit = -32888 +Output SSRC changed to 50607080 +In TS: 160000, dTS: 0, Seq: 1000 +Out TS change: 123112, dTS: 160, Seq change: 975, TS Err change: in +0, out +0 +Stats: Jitter = 0, Transit = -144000 +In TS: 160160, dTS: 160, Seq: 1001 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 0, Transit = -144000 +In TS: 160320, dTS: 160, Seq: 1002 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 0, Transit = -144000 +Testing packet error detection, patch SSRC, patch timestamps. +Output SSRC changed to 11223344 +In TS: 0, dTS: 0, Seq: 0 +Out TS change: 0, dTS: 0, Seq change: 0, TS Err change: in +0, out +0 +Stats: Jitter = 0, Transit = 0 +In TS: 160, dTS: 160, Seq: 1 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 0, Transit = 0 +In TS: 320, dTS: 160, Seq: 2 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 0, Transit = 0 +In TS: 320, dTS: 160, Seq: 3 +Out TS change: 0, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 10, Transit = 160 +In TS: 480, dTS: 160, Seq: 4 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 9, Transit = 160 +In TS: 640, dTS: 160, Seq: 5 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 8, Transit = 160 +In TS: 960, dTS: 320, Seq: 6 +Out TS change: 320, dTS: 320, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 18, Transit = 0 +In TS: 1120, dTS: 160, Seq: 7 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 17, Transit = 0 +In TS: 1280, dTS: 160, Seq: 8 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 16, Transit = 0 +In TS: 1400, dTS: 120, Seq: 9 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +1, out +0 +Stats: Jitter = 17, Transit = 40 +In TS: 1560, dTS: 160, Seq: 10 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 16, Transit = 40 +In TS: 1720, dTS: 160, Seq: 11 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 15, Transit = 40 +In TS: 34688, dTS: 0, Seq: 12 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 0, Transit = -32768 +In TS: 34848, dTS: 160, Seq: 13 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 0, Transit = -32768 +In TS: 35008, dTS: 160, Seq: 14 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 0, Transit = -32768 +In TS: 35128, dTS: 120, Seq: 15 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +1, out +0 +Stats: Jitter = 2, Transit = -32728 +In TS: 35288, dTS: 160, Seq: 16 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 2, Transit = -32728 +In TS: 35448, dTS: 160, Seq: 17 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 2, Transit = -32728 +In TS: 35768, dTS: 160, Seq: 19 +Out TS change: 320, dTS: 160, Seq change: 2, TS Err change: in +0, out +0 +Stats: Jitter = 12, Transit = -32888 +In TS: 35928, dTS: 160, Seq: 20 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 11, Transit = -32888 +In TS: 36088, dTS: 160, Seq: 21 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 20, Transit = -33048 +In TS: 36088, dTS: 160, Seq: 21 +Out TS change: 0, dTS: 160, Seq change: 0, TS Err change: in +0, out +0 +Stats: Jitter = 29, Transit = -32888 +In TS: 36248, dTS: 160, Seq: 22 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 27, Transit = -32888 +In TS: 36408, dTS: 160, Seq: 23 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 25, Transit = -32888 +In TS: 36568, dTS: 160, Seq: 23 +Out TS change: 160, dTS: 160, Seq change: 0, TS Err change: in +1, out +1 +Stats: Jitter = 24, Transit = -32888 +In TS: 36728, dTS: 160, Seq: 24 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 22, Transit = -32888 +In TS: 36888, dTS: 160, Seq: 25 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 21, Transit = -32888 +In TS: 160000, dTS: 0, Seq: 1000 +Out TS change: 12000, dTS: 12000, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 0, Transit = -144000 +In TS: 160160, dTS: 160, Seq: 1001 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 0, Transit = -144000 +In TS: 160320, dTS: 160, Seq: 1002 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 0, Transit = -144000 +Testing multiple payload types +Testing no sequence flow on initial packet +Testing no rtpmap name +Done diff --git a/tests/legacy_mgcp/mgcp_transcoding_test.c b/tests/legacy_mgcp/mgcp_transcoding_test.c new file mode 100644 index 0000000..61de25f --- /dev/null +++ b/tests/legacy_mgcp/mgcp_transcoding_test.c @@ -0,0 +1,661 @@ +#include <stdlib.h> +#include <unistd.h> +#include <stdio.h> +#include <string.h> +#include <err.h> +#include <stdint.h> +#include <errno.h> + +#include <osmocom/core/talloc.h> +#include <osmocom/core/application.h> + +#include <osmocom/netif/rtp.h> + +#include <osmocom/legacy_mgcp/mgcp.h> +#include <osmocom/legacy_mgcp/mgcp_internal.h> + +#include "bscconfig.h" +#ifndef BUILD_MGCP_TRANSCODING +#error "Requires MGCP transcoding enabled (see --enable-mgcp-transcoding)" +#endif + +#include <osmocom/legacy_mgcp/mgcp_transcode.h> + +uint8_t *audio_frame_l16[] = { +}; + +struct rtp_packets { + float t; + int len; + char *data; +}; + +struct rtp_packets audio_packets_l16[] = { + /* RTP: SeqNo=1, TS=160 */ + {0.020000, 332, + "\x80\x0B\x00\x01\x00\x00\x00\xA0\x11\x22\x33\x44" + "\x00\x00\x40\x13\x5A\x9E\x40\x13\x00\x00\xBF\xED\xA5\x62\xBF\xED" + "\x00\x00\x40\x13\x5A\x9E\x40\x13\x00\x00\xBF\xED\xA5\x62\xBF\xED" + "\x00\x00\x40\x13\x5A\x9E\x40\x13\x00\x00\xBF\xED\xA5\x62\xBF\xED" + "\x00\x00\x40\x13\x5A\x9E\x40\x13\x00\x00\xBF\xED\xA5\x62\xBF\xED" + "\x00\x00\x40\x13\x5A\x9E\x40\x13\x00\x00\xBF\xED\xA5\x62\xBF\xED" + "\x00\x00\x40\x13\x5A\x9E\x40\x13\x00\x00\xBF\xED\xA5\x62\xBF\xED" + "\x00\x00\x40\x13\x5A\x9E\x40\x13\x00\x00\xBF\xED\xA5\x62\xBF\xED" + "\x00\x00\x40\x13\x5A\x9E\x40\x13\x00\x00\xBF\xED\xA5\x62\xBF\xED" + "\x00\x00\x40\x13\x5A\x9E\x40\x13\x00\x00\xBF\xED\xA5\x62\xBF\xED" + "\x00\x00\x40\x13\x5A\x9E\x40\x13\x00\x00\xBF\xED\xA5\x62\xBF\xED" + "\x00\x00\x40\x13\x5A\x9E\x40\x13\x00\x00\xBF\xED\xA5\x62\xBF\xED" + "\x00\x00\x40\x13\x5A\x9E\x40\x13\x00\x00\xBF\xED\xA5\x62\xBF\xED" + "\x00\x00\x40\x13\x5A\x9E\x40\x13\x00\x00\xBF\xED\xA5\x62\xBF\xED" + "\x00\x00\x40\x13\x5A\x9E\x40\x13\x00\x00\xBF\xED\xA5\x62\xBF\xED" + "\x00\x00\x40\x13\x5A\x9E\x40\x13\x00\x00\xBF\xED\xA5\x62\xBF\xED" + "\x00\x00\x40\x13\x5A\x9E\x40\x13\x00\x00\xBF\xED\xA5\x62\xBF\xED" + "\x00\x00\x40\x13\x5A\x9E\x40\x13\x00\x00\xBF\xED\xA5\x62\xBF\xED" + "\x00\x00\x40\x13\x5A\x9E\x40\x13\x00\x00\xBF\xED\xA5\x62\xBF\xED" + "\x00\x00\x40\x13\x5A\x9E\x40\x13\x00\x00\xBF\xED\xA5\x62\xBF\xED" + "\x00\x00\x40\x13\x5A\x9E\x40\x13\x00\x00\xBF\xED\xA5\x62\xBF\xED" + }, +}; + +struct rtp_packets audio_packets_gsm[] = { + /* RTP: SeqNo=1, TS=160 */ + {0.020000, 45, + "\x80\x03\x00\x01\x00\x00\x00\xA0\x11\x22\x33\x44" + "\xD4\x7C\xE3\xE9\x62\x50\x39\xF0\xF8\xB4\x68\xEA\x6C\x0E\x81\x1B" + "\x56\x2A\xD5\xBC\x69\x9C\xD1\xF0\x66\x7A\xEC\x49\x7A\x33\x3D\x0A" + "\xDE" + }, +}; + +struct rtp_packets audio_packets_gsm_invalid_size[] = { + /* RTP: SeqNo=1, TS=160 */ + {0.020000, 41, + "\x80\x03\x00\x01\x00\x00\x00\xA0\x11\x22\x33\x44" + "\xD4\x7C\xE3\xE9\x62\x50\x39\xF0\xF8\xB4\x68\xEA\x6C\x0E\x81\x1B" + "\x56\x2A\xD5\xBC\x69\x9C\xD1\xF0\x66\x7A\xEC\x49\x7A\x33\x3D\x0A" + "\xDE" + }, +}; + +struct rtp_packets audio_packets_gsm_invalid_data[] = { + /* RTP: SeqNo=1, TS=160 */ + {0.020000, 45, + "\x80\x03\x00\x01\x00\x00\x00\xA0\x11\x22\x33\x44" + "\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE" + "\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE" + "\xEE" + }, +}; + +struct rtp_packets audio_packets_gsm_invalid_ptype[] = { + /* RTP: SeqNo=1, TS=160 */ + {0.020000, 45, + "\x80\x08\x00\x01\x00\x00\x00\xA0\x11\x22\x33\x44" + "\xD4\x7C\xE3\xE9\x62\x50\x39\xF0\xF8\xB4\x68\xEA\x6C\x0E\x81\x1B" + "\x56\x2A\xD5\xBC\x69\x9C\xD1\xF0\x66\x7A\xEC\x49\x7A\x33\x3D\x0A" + "\xDE" + }, +}; + +struct rtp_packets audio_packets_g729[] = { + /* RTP: SeqNo=1, TS=160 */ + {0.020000, 32, + "\x80\x12\x00\x01\x00\x00\x00\xA0\x11\x22\x33\x44" + "\xAF\xC2\x81\x40\x00\xFA\xCE\xA4\x21\x7C\xC5\xC3\x4F\xA5\x98\xF5" + "\xB2\x95\xC4\xAD" + }, +}; + +struct rtp_packets audio_packets_pcma[] = { + /* RTP: SeqNo=1, TS=160 */ + {0.020000, 172, + "\x80\x08\x00\x01\x00\x00\x00\xA0\x11\x22\x33\x44" + "\xD5\xA5\xA3\xA5\xD5\x25\x23\x25\xD5\xA5\xA3\xA5\xD5\x25\x23\x25" + "\xD5\xA5\xA3\xA5\xD5\x25\x23\x25\xD5\xA5\xA3\xA5\xD5\x25\x23\x25" + "\xD5\xA5\xA3\xA5\xD5\x25\x23\x25\xD5\xA5\xA3\xA5\xD5\x25\x23\x25" + "\xD5\xA5\xA3\xA5\xD5\x25\x23\x25\xD5\xA5\xA3\xA5\xD5\x25\x23\x25" + "\xD5\xA5\xA3\xA5\xD5\x25\x23\x25\xD5\xA5\xA3\xA5\xD5\x25\x23\x25" + "\xD5\xA5\xA3\xA5\xD5\x25\x23\x25\xD5\xA5\xA3\xA5\xD5\x25\x23\x25" + "\xD5\xA5\xA3\xA5\xD5\x25\x23\x25\xD5\xA5\xA3\xA5\xD5\x25\x23\x25" + "\xD5\xA5\xA3\xA5\xD5\x25\x23\x25\xD5\xA5\xA3\xA5\xD5\x25\x23\x25" + "\xD5\xA5\xA3\xA5\xD5\x25\x23\x25\xD5\xA5\xA3\xA5\xD5\x25\x23\x25" + "\xD5\xA5\xA3\xA5\xD5\x25\x23\x25\xD5\xA5\xA3\xA5\xD5\x25\x23\x25" + }, + /* RTP: SeqNo=26527, TS=232640 */ + {0.020000, 92, + "\x80\x08\x67\x9f\x00\x03\x8c\xc0\x04\xaa\x67\x9f\xd5\xd5\xd5\xd5" + "\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5" + "\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5" + "\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5" + "\xd5\xd5\xd5\xd5\xd5\xd5\x55\x55\xd5\xd5\x55\x55\xd5\xd5\x55\x55" + "\xd5\xd5\xd5\x55\x55\xd5\xd5\xd5\x55\x55\xd5\xd5" + }, + /* RTP: SeqNo=26528, TS=232720 */ + {0.020000, 92, + "\x80\x08\x67\xa0\x00\x03\x8d\x10\x04\xaa\x67\x9f\x55\xd5\xd5\x55" + "\xd5\x55\xd5\xd5\xd5\x55\xd5\x55\xd5\xd5\x55\xd5\x55\xd5\x55\xd5" + "\x55\x55\xd5\x55\xd5\xd5\x55\x55\x55\x55\x55\xd5\xd5\x55\xd5\xd5" + "\xd5\x55\xd5\xd5\xd5\x55\x54\x55\xd5\xd5\x55\xd5\xd5\xd5\xd5\x55" + "\x54\x55\xd5\x55\xd5\x55\x55\x55\x55\x55\xd5\xd5\xd5\xd5\xd5\xd4" + "\xd5\x54\x55\xd5\xd4\xd5\x54\xd5\x55\xd5\xd5\xd5" + }, +}; + + + +static int audio_name_to_type(const char *name) +{ + if (!strcasecmp(name, "gsm")) + return 3; +#ifdef HAVE_BCG729 + else if (!strcasecmp(name, "g729")) + return 18; +#endif + else if (!strcasecmp(name, "pcma")) + return 8; + else if (!strcasecmp(name, "l16")) + return 11; + return -1; +} + +int mgcp_get_trans_frame_size(void *state_, int nsamples, int dst); + +static int given_configured_endpoint(int in_samples, int out_samples, + const char *srcfmt, const char *dstfmt, + void **out_ctx, struct mgcp_endpoint **out_endp) +{ + int rc; + struct mgcp_rtp_end *dst_end; + struct mgcp_rtp_end *src_end; + struct mgcp_config *cfg; + struct mgcp_trunk_config *tcfg; + struct mgcp_endpoint *endp; + + cfg = mgcp_config_alloc(); + tcfg = talloc_zero(cfg, struct mgcp_trunk_config); + endp = talloc_zero(tcfg, struct mgcp_endpoint); + + cfg->setup_rtp_processing_cb = mgcp_transcoding_setup; + cfg->rtp_processing_cb = mgcp_transcoding_process_rtp; + cfg->get_net_downlink_format_cb = mgcp_transcoding_net_downlink_format; + + tcfg->endpoints = endp; + tcfg->number_endpoints = 1; + tcfg->cfg = cfg; + endp->tcfg = tcfg; + endp->cfg = cfg; + mgcp_initialize_endp(endp); + + dst_end = &endp->bts_end; + dst_end->codec.payload_type = audio_name_to_type(dstfmt); + + src_end = &endp->net_end; + src_end->codec.payload_type = audio_name_to_type(srcfmt); + + if (out_samples) { + dst_end->codec.frame_duration_den = dst_end->codec.rate; + dst_end->codec.frame_duration_num = out_samples; + dst_end->frames_per_packet = 1; + dst_end->force_output_ptime = 1; + } + + rc = mgcp_transcoding_setup(endp, dst_end, src_end); + if (rc < 0) { + printf("setup failed: %s", strerror(-rc)); + abort(); + } + + *out_ctx = cfg; + *out_endp = endp; + return 0; +} + + +static int transcode_test(const char *srcfmt, const char *dstfmt, + uint8_t *src_pkts, size_t src_pkt_size) +{ + char buf[4096] = {0x80, 0}; + void *ctx; + + struct mgcp_rtp_end *dst_end; + struct mgcp_process_rtp_state *state; + struct mgcp_endpoint *endp; + int in_size; + const int in_samples = 160; + int len, cont; + + printf("== Transcoding test ==\n"); + printf("converting %s -> %s\n", srcfmt, dstfmt); + + given_configured_endpoint(in_samples, 0, srcfmt, dstfmt, &ctx, &endp); + + dst_end = &endp->bts_end; + state = dst_end->rtp_process_data; + OSMO_ASSERT(state != NULL); + + in_size = mgcp_transcoding_get_frame_size(state, in_samples, 0); + OSMO_ASSERT(sizeof(buf) >= in_size + 12); + + memcpy(buf, src_pkts, src_pkt_size); + + len = src_pkt_size; + + cont = mgcp_transcoding_process_rtp(endp, dst_end, + buf, &len, sizeof(buf)); + if (cont < 0) { + printf("Nothing encoded due: %s\n", strerror(-cont)); + talloc_free(ctx); + return -1; + } + + if (len < 24) { + printf("encoded: %s\n", osmo_hexdump((unsigned char *)buf, len)); + } else { + const char *str = osmo_hexdump((unsigned char *)buf, len); + int i = 0; + const int prefix = 4; + const int cutlen = 48; + int nchars = 0; + + printf("encoded:\n"); + do { + nchars = printf("%*s%-.*s", prefix, "", cutlen, str + i); + i += nchars - prefix; + printf("\n"); + } while (nchars - prefix >= cutlen); + } + printf("counted: %d\n", cont); + talloc_free(ctx); + return 0; +} + +static void test_rtp_seq_state(void) +{ + char buf[4096]; + int len; + int cont; + void *ctx; + struct mgcp_endpoint *endp; + struct mgcp_process_rtp_state *state; + struct rtp_hdr *hdr; + uint32_t ts_no; + uint16_t seq_no; + + given_configured_endpoint(160, 0, "pcma", "l16", &ctx, &endp); + state = endp->bts_end.rtp_process_data; + OSMO_ASSERT(!state->is_running); + OSMO_ASSERT(state->next_seq == 0); + OSMO_ASSERT(state->next_time == 0); + + /* initialize packet */ + len = audio_packets_pcma[0].len; + memcpy(buf, audio_packets_pcma[0].data, len); + cont = mgcp_transcoding_process_rtp(endp, &endp->bts_end, buf, &len, len); + OSMO_ASSERT(cont >= 0); + OSMO_ASSERT(state->is_running); + OSMO_ASSERT(state->next_seq == 2); + OSMO_ASSERT(state->next_time == 240); + + /* verify that the right timestamp was written */ + OSMO_ASSERT(len == audio_packets_pcma[0].len); + hdr = (struct rtp_hdr *) &buf[0]; + + memcpy(&ts_no, &hdr->timestamp, sizeof(ts_no)); + OSMO_ASSERT(htonl(ts_no) == 160); + memcpy(&seq_no, &hdr->sequence, sizeof(seq_no)); + OSMO_ASSERT(htons(seq_no) == 1); + /* Check the right sequence number is written */ + state->next_seq = 1234; + len = audio_packets_pcma[0].len; + memcpy(buf, audio_packets_pcma[0].data, len); + cont = mgcp_transcoding_process_rtp(endp, &endp->bts_end, buf, &len, len); + OSMO_ASSERT(cont >= 0); + OSMO_ASSERT(len == audio_packets_pcma[0].len); + hdr = (struct rtp_hdr *) &buf[0]; + + memcpy(&seq_no, &hdr->sequence, sizeof(seq_no)); + OSMO_ASSERT(htons(seq_no) == 1234); + + talloc_free(ctx); +} + +static void test_transcode_result(void) +{ + char buf[4096]; + int len, res; + void *ctx; + struct mgcp_endpoint *endp; + struct mgcp_process_rtp_state *state; + + { + /* from GSM to PCMA and same ptime */ + given_configured_endpoint(160, 0, "gsm", "pcma", &ctx, &endp); + state = endp->bts_end.rtp_process_data; + + /* result */ + len = audio_packets_gsm[0].len; + memcpy(buf, audio_packets_gsm[0].data, len); + res = mgcp_transcoding_process_rtp(endp, &endp->bts_end, buf, &len, ARRAY_SIZE(buf)); + OSMO_ASSERT(res == sizeof(struct rtp_hdr)); + OSMO_ASSERT(state->sample_cnt == 0); + + len = res; + res = mgcp_transcoding_process_rtp(endp, &endp->bts_end, buf, &len, ARRAY_SIZE(buf)); + OSMO_ASSERT(res == -ENOMSG); + + talloc_free(ctx); + } + + { + /* from GSM to PCMA and same ptime */ + given_configured_endpoint(160, 160, "gsm", "pcma", &ctx, &endp); + state = endp->bts_end.rtp_process_data; + + /* result */ + len = audio_packets_gsm[0].len; + memcpy(buf, audio_packets_gsm[0].data, len); + res = mgcp_transcoding_process_rtp(endp, &endp->bts_end, buf, &len, ARRAY_SIZE(buf)); + OSMO_ASSERT(res == sizeof(struct rtp_hdr)); + OSMO_ASSERT(state->sample_cnt == 0); + + len = res; + res = mgcp_transcoding_process_rtp(endp, &endp->bts_end, buf, &len, ARRAY_SIZE(buf)); + OSMO_ASSERT(res == -EAGAIN); + + talloc_free(ctx); + } + + { + /* from PCMA to GSM and wrong different ptime */ + given_configured_endpoint(80, 160, "pcma", "gsm", &ctx, &endp); + state = endp->bts_end.rtp_process_data; + + /* Add the first sample */ + len = audio_packets_pcma[1].len; + memcpy(buf, audio_packets_pcma[1].data, len); + res = mgcp_transcoding_process_rtp(endp, &endp->bts_end, buf, &len, ARRAY_SIZE(buf)); + OSMO_ASSERT(state->sample_cnt == 80); + OSMO_ASSERT(state->next_time == 232640); + OSMO_ASSERT(res < 0); + + /* Add the second sample and it should be consumable */ + len = audio_packets_pcma[2].len; + memcpy(buf, audio_packets_pcma[2].data, len); + res = mgcp_transcoding_process_rtp(endp, &endp->bts_end, buf, &len, ARRAY_SIZE(buf)); + OSMO_ASSERT(state->sample_cnt == 0); + OSMO_ASSERT(state->next_time == 232640 + 80 + 160); + OSMO_ASSERT(res == sizeof(struct rtp_hdr)); + + talloc_free(ctx); + } + + { + /* from PCMA to GSM with a big time jump */ + struct rtp_hdr *hdr; + uint32_t ts; + + given_configured_endpoint(80, 160, "pcma", "gsm", &ctx, &endp); + state = endp->bts_end.rtp_process_data; + + /* Add the first sample */ + len = audio_packets_pcma[1].len; + memcpy(buf, audio_packets_pcma[1].data, len); + res = mgcp_transcoding_process_rtp(endp, &endp->bts_end, buf, &len, ARRAY_SIZE(buf)); + OSMO_ASSERT(state->sample_cnt == 80); + OSMO_ASSERT(state->next_time == 232640); + OSMO_ASSERT(state->next_seq == 26527); + OSMO_ASSERT(res < 0); + + /* Add a skip to the packet to force a 'resync' */ + len = audio_packets_pcma[2].len; + memcpy(buf, audio_packets_pcma[2].data, len); + hdr = (struct rtp_hdr *) &buf[0]; + /* jump the time and add alignment error */ + ts = ntohl(hdr->timestamp) + 123 * 80 + 2; + hdr->timestamp = htonl(ts); + res = mgcp_transcoding_process_rtp(endp, &endp->bts_end, buf, &len, ARRAY_SIZE(buf)); + OSMO_ASSERT(res < 0); + OSMO_ASSERT(state->sample_cnt == 80); + OSMO_ASSERT(state->next_time == ts); + OSMO_ASSERT(state->next_seq == 26527); + /* TODO: this can create alignment errors */ + + + /* Now attempt to consume 160 samples */ + len = audio_packets_pcma[2].len; + memcpy(buf, audio_packets_pcma[2].data, len); + hdr = (struct rtp_hdr *) &buf[0]; + ts += 80; + hdr->timestamp = htonl(ts); + res = mgcp_transcoding_process_rtp(endp, &endp->bts_end, buf, &len, ARRAY_SIZE(buf)); + OSMO_ASSERT(res == 12); + OSMO_ASSERT(state->sample_cnt == 0); + OSMO_ASSERT(state->next_time == ts + 160); + OSMO_ASSERT(state->next_seq == 26528); + + talloc_free(ctx); + } +} + +static void test_transcode_change(void) +{ + char buf[4096] = {0x80, 0}; + void *ctx; + + struct mgcp_endpoint *endp; + struct mgcp_process_rtp_state *state; + struct rtp_hdr *hdr; + + int len, res; + + { + /* from GSM to PCMA and same ptime */ + printf("Testing Initial L16->GSM, PCMA->GSM\n"); + given_configured_endpoint(160, 0, "l16", "gsm", &ctx, &endp); + endp->net_end.alt_codec = endp->net_end.codec; + endp->net_end.alt_codec.payload_type = audio_name_to_type("pcma"); + state = endp->bts_end.rtp_process_data; + + /* initial transcoding work */ + OSMO_ASSERT(state->src_fmt == AF_L16); + OSMO_ASSERT(state->dst_fmt == AF_GSM); + OSMO_ASSERT(endp->net_end.alt_codec.payload_type == 8); + OSMO_ASSERT(endp->net_end.codec.payload_type == 11); + + /* result */ + len = audio_packets_pcma[0].len; + memcpy(buf, audio_packets_pcma[0].data, len); + res = mgcp_transcoding_process_rtp(endp, &endp->bts_end, buf, &len, ARRAY_SIZE(buf)); + state = endp->bts_end.rtp_process_data; + OSMO_ASSERT(res == sizeof(struct rtp_hdr)); + OSMO_ASSERT(state->sample_cnt == 0); + OSMO_ASSERT(state->src_fmt == AF_PCMA); + OSMO_ASSERT(state->dst_fmt == AF_GSM); + OSMO_ASSERT(endp->net_end.alt_codec.payload_type == 11); + OSMO_ASSERT(endp->net_end.codec.payload_type == 8); + + len = res; + res = mgcp_transcoding_process_rtp(endp, &endp->bts_end, buf, &len, ARRAY_SIZE(buf)); + OSMO_ASSERT(res == -ENOMSG); + OSMO_ASSERT(state == endp->bts_end.rtp_process_data); + + + /* now check that comfort noise doesn't change anything */ + len = audio_packets_pcma[1].len; + memcpy(buf, audio_packets_pcma[1].data, len); + hdr = (struct rtp_hdr *) buf; + hdr->payload_type = 12; + res = mgcp_transcoding_process_rtp(endp, &endp->bts_end, buf, &len, ARRAY_SIZE(buf)); + OSMO_ASSERT(state == endp->bts_end.rtp_process_data); + OSMO_ASSERT(state->sample_cnt == 80); + OSMO_ASSERT(state->src_fmt == AF_PCMA); + OSMO_ASSERT(state->dst_fmt == AF_GSM); + OSMO_ASSERT(endp->net_end.alt_codec.payload_type == 11); + OSMO_ASSERT(endp->net_end.codec.payload_type == 8); + + talloc_free(ctx); + } +} + +static int test_repacking(int in_samples, int out_samples, int no_transcode) +{ + char buf[4096] = {0x80, 0}; + int cc; + struct mgcp_endpoint *endp; + void *ctx; + + struct mgcp_process_rtp_state *state; + int in_cnt; + int out_size; + int in_size; + uint32_t ts = 0; + uint16_t seq = 0; + const char *srcfmt = "pcma"; + const char *dstfmt = no_transcode ? "pcma" : "l16"; + + printf("== Transcoding test ==\n"); + printf("converting %s -> %s\n", srcfmt, dstfmt); + + given_configured_endpoint(in_samples, out_samples, srcfmt, dstfmt, &ctx, &endp); + + state = endp->bts_end.rtp_process_data; + OSMO_ASSERT(state != NULL); + + in_size = mgcp_transcoding_get_frame_size(state, in_samples, 0); + OSMO_ASSERT(sizeof(buf) >= in_size + 12); + + out_size = mgcp_transcoding_get_frame_size(state, -1, 1); + OSMO_ASSERT(sizeof(buf) >= out_size + 12); + + buf[1] = endp->net_end.codec.payload_type; + *(uint16_t*)(buf+2) = htons(1); + *(uint32_t*)(buf+4) = htonl(0); + *(uint32_t*)(buf+8) = htonl(0xaabbccdd); + + for (in_cnt = 0; in_cnt < 16; in_cnt++) { + int cont; + int len; + + /* fake PCMA data */ + printf("generating %d %s input samples\n", in_samples, srcfmt); + for (cc = 0; cc < in_samples; cc++) + buf[12+cc] = cc; + + *(uint16_t*)(buf+2) = htonl(seq); + *(uint32_t*)(buf+4) = htonl(ts); + + seq += 1; + ts += in_samples; + + cc += 12; /* include RTP header */ + + len = cc; + + do { + cont = mgcp_transcoding_process_rtp(endp, &endp->bts_end, + buf, &len, sizeof(buf)); + if (cont == -EAGAIN) { + fprintf(stderr, "Got EAGAIN\n"); + break; + } + + if (cont < 0) { + printf("processing failed: %s", strerror(-cont)); + abort(); + } + + len -= 12; /* ignore RTP header */ + + printf("got %d %s output frames (%d octets) count=%d\n", + len / out_size, dstfmt, len, cont); + + len = cont; + } while (len > 0); + } + + talloc_free(ctx); + return 0; +} + +static const struct log_info_cat log_categories[] = { +}; + +const struct log_info log_info = { + .cat = log_categories, + .num_cat = ARRAY_SIZE(log_categories), +}; + +int main(int argc, char **argv) +{ + int rc; + osmo_init_logging(&log_info); + + printf("=== Transcoding Good Cases ===\n"); + + transcode_test("l16", "l16", + (uint8_t *)audio_packets_l16[0].data, + audio_packets_l16[0].len); + transcode_test("l16", "gsm", + (uint8_t *)audio_packets_l16[0].data, + audio_packets_l16[0].len); + transcode_test("l16", "pcma", + (uint8_t *)audio_packets_l16[0].data, + audio_packets_l16[0].len); + transcode_test("gsm", "l16", + (uint8_t *)audio_packets_gsm[0].data, + audio_packets_gsm[0].len); + transcode_test("gsm", "gsm", + (uint8_t *)audio_packets_gsm[0].data, + audio_packets_gsm[0].len); + transcode_test("gsm", "pcma", + (uint8_t *)audio_packets_gsm[0].data, + audio_packets_gsm[0].len); + transcode_test("pcma", "l16", + (uint8_t *)audio_packets_pcma[0].data, + audio_packets_pcma[0].len); + transcode_test("pcma", "gsm", + (uint8_t *)audio_packets_pcma[0].data, + audio_packets_pcma[0].len); + transcode_test("pcma", "pcma", + (uint8_t *)audio_packets_pcma[0].data, + audio_packets_pcma[0].len); + + printf("=== Transcoding Bad Cases ===\n"); + + printf("Invalid size:\n"); + rc = transcode_test("gsm", "pcma", + (uint8_t *)audio_packets_gsm_invalid_size[0].data, + audio_packets_gsm_invalid_size[0].len); + OSMO_ASSERT(rc < 0); + + printf("Invalid data:\n"); + rc = transcode_test("gsm", "pcma", + (uint8_t *)audio_packets_gsm_invalid_data[0].data, + audio_packets_gsm_invalid_data[0].len); + OSMO_ASSERT(rc < 0); + + printf("Invalid payload type:\n"); + rc = transcode_test("gsm", "pcma", + (uint8_t *)audio_packets_gsm_invalid_ptype[0].data, + audio_packets_gsm_invalid_ptype[0].len); + OSMO_ASSERT(rc == 0); + + printf("=== Repacking ===\n"); + + test_repacking(160, 160, 0); + test_repacking(160, 160, 1); + test_repacking(160, 80, 0); + test_repacking(160, 80, 1); + test_repacking(160, 320, 0); + test_repacking(160, 320, 1); + test_repacking(160, 240, 0); + test_repacking(160, 240, 1); + test_repacking(160, 100, 0); + test_repacking(160, 100, 1); + test_rtp_seq_state(); + test_transcode_result(); + test_transcode_change(); + + return 0; +} + diff --git a/tests/legacy_mgcp/mgcp_transcoding_test.ok b/tests/legacy_mgcp/mgcp_transcoding_test.ok new file mode 100644 index 0000000..387cfd2 --- /dev/null +++ b/tests/legacy_mgcp/mgcp_transcoding_test.ok @@ -0,0 +1,539 @@ +=== Transcoding Good Cases === +== Transcoding test == +converting l16 -> l16 +encoded: + 80 0b 00 01 00 00 00 a0 11 22 33 44 00 00 40 13 + 5a 9e 40 13 00 00 bf ed a5 62 bf ed 00 00 40 13 + 5a 9e 40 13 00 00 bf ed a5 62 bf ed 00 00 40 13 + 5a 9e 40 13 00 00 bf ed a5 62 bf ed 00 00 40 13 + 5a 9e 40 13 00 00 bf ed a5 62 bf ed 00 00 40 13 + 5a 9e 40 13 00 00 bf ed a5 62 bf ed 00 00 40 13 + 5a 9e 40 13 00 00 bf ed a5 62 bf ed 00 00 40 13 + 5a 9e 40 13 00 00 bf ed a5 62 bf ed 00 00 40 13 + 5a 9e 40 13 00 00 bf ed a5 62 bf ed 00 00 40 13 + 5a 9e 40 13 00 00 bf ed a5 62 bf ed 00 00 40 13 + 5a 9e 40 13 00 00 bf ed a5 62 bf ed 00 00 40 13 + 5a 9e 40 13 00 00 bf ed a5 62 bf ed 00 00 40 13 + 5a 9e 40 13 00 00 bf ed a5 62 bf ed 00 00 40 13 + 5a 9e 40 13 00 00 bf ed a5 62 bf ed 00 00 40 13 + 5a 9e 40 13 00 00 bf ed a5 62 bf ed 00 00 40 13 + 5a 9e 40 13 00 00 bf ed a5 62 bf ed 00 00 40 13 + 5a 9e 40 13 00 00 bf ed a5 62 bf ed 00 00 40 13 + 5a 9e 40 13 00 00 bf ed a5 62 bf ed 00 00 40 13 + 5a 9e 40 13 00 00 bf ed a5 62 bf ed 00 00 40 13 + 5a 9e 40 13 00 00 bf ed a5 62 bf ed 00 00 40 13 + 5a 9e 40 13 00 00 bf ed a5 62 bf ed +counted: 0 +== Transcoding test == +converting l16 -> gsm +encoded: + 80 0b 00 01 00 00 00 a0 11 22 33 44 d4 7c e3 e9 + 62 50 39 f0 f8 b4 68 ea 6c 0e 81 1b 56 2a d5 bc + 69 9c d1 f0 66 7a ec 49 7a 33 3d 0a de +counted: 12 +== Transcoding test == +converting l16 -> pcma +encoded: + 80 0b 00 01 00 00 00 a0 11 22 33 44 d5 a5 a3 a5 + d5 25 23 25 d5 a5 a3 a5 d5 25 23 25 d5 a5 a3 a5 + d5 25 23 25 d5 a5 a3 a5 d5 25 23 25 d5 a5 a3 a5 + d5 25 23 25 d5 a5 a3 a5 d5 25 23 25 d5 a5 a3 a5 + d5 25 23 25 d5 a5 a3 a5 d5 25 23 25 d5 a5 a3 a5 + d5 25 23 25 d5 a5 a3 a5 d5 25 23 25 d5 a5 a3 a5 + d5 25 23 25 d5 a5 a3 a5 d5 25 23 25 d5 a5 a3 a5 + d5 25 23 25 d5 a5 a3 a5 d5 25 23 25 d5 a5 a3 a5 + d5 25 23 25 d5 a5 a3 a5 d5 25 23 25 d5 a5 a3 a5 + d5 25 23 25 d5 a5 a3 a5 d5 25 23 25 d5 a5 a3 a5 + d5 25 23 25 d5 a5 a3 a5 d5 25 23 25 +counted: 12 +== Transcoding test == +converting gsm -> l16 +encoded: + 80 03 00 01 00 00 00 a0 11 22 33 44 00 00 54 00 + 59 f0 34 20 c4 c8 b9 f8 e2 18 f1 e8 f2 28 f0 e0 + 46 08 4f 80 2c a0 a9 c8 80 00 c0 58 3f 80 63 c0 + 24 b8 fa b8 f6 88 0b a0 c8 70 a8 b0 c8 c0 3b a8 + 66 a0 2e 38 d1 f8 98 98 aa 18 e8 30 26 a0 37 40 + 37 e8 17 00 ee 50 b7 80 b1 88 de 28 18 40 45 b0 + 4f 48 21 d8 df 78 ae 68 ab 98 d6 b8 18 18 48 90 + 4e 70 27 40 e8 10 b5 b0 ac 80 d4 60 14 50 48 48 + 50 10 2a 00 ec 08 ba 00 af 58 d1 c0 10 60 45 c8 + 54 10 30 78 f1 a8 bb 18 ad 48 ce 30 0a e8 3f 30 + 4f 10 32 18 f6 18 bf 20 ac 30 cd 80 0b d0 43 d8 + 55 e0 34 a0 f5 78 bc 98 ad 98 cd c8 0a 80 40 58 + 51 c0 35 40 f9 60 c1 68 ac c8 cb 38 08 00 40 98 + 51 e0 34 d8 fa 28 c2 f0 ae 40 c7 70 02 d0 3c a8 + 54 78 38 a0 fc 68 c2 08 ad 50 c7 78 01 60 39 c0 + 51 38 3a e8 00 e8 c6 38 ab d8 c4 00 fe 08 39 18 + 50 30 39 50 01 d8 ca 70 b1 80 c4 c8 fc 58 36 40 + 51 d8 3b 08 02 80 c8 58 b0 60 c5 a8 fb d0 33 e8 + 4e 80 3c e0 06 10 cb 90 ae 48 c2 60 f9 58 34 08 + 4d a0 3a a8 06 48 cf 80 b4 60 c3 e8 f7 90 30 18 + 4d a0 3b 98 07 90 cf 18 b4 68 c4 88 +counted: 12 +== Transcoding test == +converting gsm -> gsm +encoded: + 80 03 00 01 00 00 00 a0 11 22 33 44 d4 7c e3 e9 + 62 50 39 f0 f8 b4 68 ea 6c 0e 81 1b 56 2a d5 bc + 69 9c d1 f0 66 7a ec 49 7a 33 3d 0a de +counted: 0 +== Transcoding test == +converting gsm -> pcma +encoded: + 80 03 00 01 00 00 00 a0 11 22 33 44 d5 a0 a3 bf + 38 24 08 19 1e 1b a4 a6 b3 20 2a 3a ba ad b7 60 + 17 92 3e 20 3e b8 ac b2 32 2c 20 02 b6 be be 82 + 04 27 26 35 8d a4 a6 b5 35 21 20 31 8d a7 a6 b6 + 02 27 21 30 81 a7 a1 b0 06 24 21 32 85 a4 a0 bd + 19 24 21 3d 90 ba a6 bc 16 25 21 3c 92 a5 a0 bf + 10 25 21 3c 90 a5 a1 bf 6f 3a 21 3f 95 a5 a1 bf + 62 3b 21 39 f3 bb a0 b9 79 3b 21 39 c3 b9 a1 b8 + db 39 20 3b 4a b9 a1 b9 c8 3f 26 38 78 be a1 b8 + f1 3e 26 38 65 bc a6 bb ed 3f 21 3b 6f bf a6 b8 + ec 3d 27 3b 15 bd a6 b8 eb 3d 27 38 +counted: 12 +== Transcoding test == +converting pcma -> l16 +encoded: + 80 08 00 01 00 00 00 a0 11 22 33 44 00 08 42 00 + 5a 00 42 00 00 08 be 00 a6 00 be 00 00 08 42 00 + 5a 00 42 00 00 08 be 00 a6 00 be 00 00 08 42 00 + 5a 00 42 00 00 08 be 00 a6 00 be 00 00 08 42 00 + 5a 00 42 00 00 08 be 00 a6 00 be 00 00 08 42 00 + 5a 00 42 00 00 08 be 00 a6 00 be 00 00 08 42 00 + 5a 00 42 00 00 08 be 00 a6 00 be 00 00 08 42 00 + 5a 00 42 00 00 08 be 00 a6 00 be 00 00 08 42 00 + 5a 00 42 00 00 08 be 00 a6 00 be 00 00 08 42 00 + 5a 00 42 00 00 08 be 00 a6 00 be 00 00 08 42 00 + 5a 00 42 00 00 08 be 00 a6 00 be 00 00 08 42 00 + 5a 00 42 00 00 08 be 00 a6 00 be 00 00 08 42 00 + 5a 00 42 00 00 08 be 00 a6 00 be 00 00 08 42 00 + 5a 00 42 00 00 08 be 00 a6 00 be 00 00 08 42 00 + 5a 00 42 00 00 08 be 00 a6 00 be 00 00 08 42 00 + 5a 00 42 00 00 08 be 00 a6 00 be 00 00 08 42 00 + 5a 00 42 00 00 08 be 00 a6 00 be 00 00 08 42 00 + 5a 00 42 00 00 08 be 00 a6 00 be 00 00 08 42 00 + 5a 00 42 00 00 08 be 00 a6 00 be 00 00 08 42 00 + 5a 00 42 00 00 08 be 00 a6 00 be 00 00 08 42 00 + 5a 00 42 00 00 08 be 00 a6 00 be 00 +counted: 12 +== Transcoding test == +converting pcma -> gsm +encoded: + 80 08 00 01 00 00 00 a0 11 22 33 44 d4 b9 f4 5d + d9 50 5a e1 a0 cd 76 ea 52 0e 87 53 ad d4 ea a2 + 0a 63 ca e9 60 79 e2 2a 25 d2 c0 f3 39 +counted: 12 +== Transcoding test == +converting pcma -> pcma +encoded: + 80 08 00 01 00 00 00 a0 11 22 33 44 d5 a5 a3 a5 + d5 25 23 25 d5 a5 a3 a5 d5 25 23 25 d5 a5 a3 a5 + d5 25 23 25 d5 a5 a3 a5 d5 25 23 25 d5 a5 a3 a5 + d5 25 23 25 d5 a5 a3 a5 d5 25 23 25 d5 a5 a3 a5 + d5 25 23 25 d5 a5 a3 a5 d5 25 23 25 d5 a5 a3 a5 + d5 25 23 25 d5 a5 a3 a5 d5 25 23 25 d5 a5 a3 a5 + d5 25 23 25 d5 a5 a3 a5 d5 25 23 25 d5 a5 a3 a5 + d5 25 23 25 d5 a5 a3 a5 d5 25 23 25 d5 a5 a3 a5 + d5 25 23 25 d5 a5 a3 a5 d5 25 23 25 d5 a5 a3 a5 + d5 25 23 25 d5 a5 a3 a5 d5 25 23 25 d5 a5 a3 a5 + d5 25 23 25 d5 a5 a3 a5 d5 25 23 25 +counted: 0 +=== Transcoding Bad Cases === +Invalid size: +== Transcoding test == +converting gsm -> pcma +Nothing encoded due: No message of desired type +Invalid data: +== Transcoding test == +converting gsm -> pcma +Nothing encoded due: No message of desired type +Invalid payload type: +== Transcoding test == +converting gsm -> pcma +encoded: + 80 08 00 01 00 00 00 a0 11 22 33 44 d5 a0 a3 bf + 38 24 08 19 1e 1b a4 a6 b3 20 2a 3a ba ad b7 60 + 17 92 3e 20 3e b8 ac b2 32 2c 20 02 b6 be be 82 + 04 27 26 35 8d a4 a6 b5 35 21 20 31 8d a7 a6 b6 + 02 27 21 30 81 a7 a1 b0 06 24 21 32 85 a4 a0 bd + 19 24 21 3d 90 ba a6 bc 16 25 21 3c 92 a5 a0 bf + 10 25 21 3c 90 a5 a1 bf 6f 3a 21 3f 95 a5 a1 bf + 62 3b 21 39 f3 bb a0 b9 79 3b 21 39 c3 b9 a1 b8 + db 39 20 3b 4a b9 a1 b9 c8 3f 26 38 78 be a1 b8 + f1 3e 26 38 65 bc a6 bb ed 3f 21 3b 6f bf a6 b8 + ec 3d 27 3b 15 bd a6 b8 eb 3d 27 38 +counted: 12 +=== Repacking === +== Transcoding test == +converting pcma -> l16 +generating 160 pcma input samples +got 2 l16 output frames (320 octets) count=12 +generating 160 pcma input samples +got 2 l16 output frames (320 octets) count=12 +generating 160 pcma input samples +got 2 l16 output frames (320 octets) count=12 +generating 160 pcma input samples +got 2 l16 output frames (320 octets) count=12 +generating 160 pcma input samples +got 2 l16 output frames (320 octets) count=12 +generating 160 pcma input samples +got 2 l16 output frames (320 octets) count=12 +generating 160 pcma input samples +got 2 l16 output frames (320 octets) count=12 +generating 160 pcma input samples +got 2 l16 output frames (320 octets) count=12 +generating 160 pcma input samples +got 2 l16 output frames (320 octets) count=12 +generating 160 pcma input samples +got 2 l16 output frames (320 octets) count=12 +generating 160 pcma input samples +got 2 l16 output frames (320 octets) count=12 +generating 160 pcma input samples +got 2 l16 output frames (320 octets) count=12 +generating 160 pcma input samples +got 2 l16 output frames (320 octets) count=12 +generating 160 pcma input samples +got 2 l16 output frames (320 octets) count=12 +generating 160 pcma input samples +got 2 l16 output frames (320 octets) count=12 +generating 160 pcma input samples +got 2 l16 output frames (320 octets) count=12 +== Transcoding test == +converting pcma -> pcma +generating 160 pcma input samples +got 2 pcma output frames (160 octets) count=12 +generating 160 pcma input samples +got 2 pcma output frames (160 octets) count=12 +generating 160 pcma input samples +got 2 pcma output frames (160 octets) count=12 +generating 160 pcma input samples +got 2 pcma output frames (160 octets) count=12 +generating 160 pcma input samples +got 2 pcma output frames (160 octets) count=12 +generating 160 pcma input samples +got 2 pcma output frames (160 octets) count=12 +generating 160 pcma input samples +got 2 pcma output frames (160 octets) count=12 +generating 160 pcma input samples +got 2 pcma output frames (160 octets) count=12 +generating 160 pcma input samples +got 2 pcma output frames (160 octets) count=12 +generating 160 pcma input samples +got 2 pcma output frames (160 octets) count=12 +generating 160 pcma input samples +got 2 pcma output frames (160 octets) count=12 +generating 160 pcma input samples +got 2 pcma output frames (160 octets) count=12 +generating 160 pcma input samples +got 2 pcma output frames (160 octets) count=12 +generating 160 pcma input samples +got 2 pcma output frames (160 octets) count=12 +generating 160 pcma input samples +got 2 pcma output frames (160 octets) count=12 +generating 160 pcma input samples +got 2 pcma output frames (160 octets) count=12 +== Transcoding test == +converting pcma -> l16 +generating 160 pcma input samples +got 1 l16 output frames (160 octets) count=12 +got 1 l16 output frames (160 octets) count=12 +generating 160 pcma input samples +got 1 l16 output frames (160 octets) count=12 +got 1 l16 output frames (160 octets) count=12 +generating 160 pcma input samples +got 1 l16 output frames (160 octets) count=12 +got 1 l16 output frames (160 octets) count=12 +generating 160 pcma input samples +got 1 l16 output frames (160 octets) count=12 +got 1 l16 output frames (160 octets) count=12 +generating 160 pcma input samples +got 1 l16 output frames (160 octets) count=12 +got 1 l16 output frames (160 octets) count=12 +generating 160 pcma input samples +got 1 l16 output frames (160 octets) count=12 +got 1 l16 output frames (160 octets) count=12 +generating 160 pcma input samples +got 1 l16 output frames (160 octets) count=12 +got 1 l16 output frames (160 octets) count=12 +generating 160 pcma input samples +got 1 l16 output frames (160 octets) count=12 +got 1 l16 output frames (160 octets) count=12 +generating 160 pcma input samples +got 1 l16 output frames (160 octets) count=12 +got 1 l16 output frames (160 octets) count=12 +generating 160 pcma input samples +got 1 l16 output frames (160 octets) count=12 +got 1 l16 output frames (160 octets) count=12 +generating 160 pcma input samples +got 1 l16 output frames (160 octets) count=12 +got 1 l16 output frames (160 octets) count=12 +generating 160 pcma input samples +got 1 l16 output frames (160 octets) count=12 +got 1 l16 output frames (160 octets) count=12 +generating 160 pcma input samples +got 1 l16 output frames (160 octets) count=12 +got 1 l16 output frames (160 octets) count=12 +generating 160 pcma input samples +got 1 l16 output frames (160 octets) count=12 +got 1 l16 output frames (160 octets) count=12 +generating 160 pcma input samples +got 1 l16 output frames (160 octets) count=12 +got 1 l16 output frames (160 octets) count=12 +generating 160 pcma input samples +got 1 l16 output frames (160 octets) count=12 +got 1 l16 output frames (160 octets) count=12 +== Transcoding test == +converting pcma -> pcma +generating 160 pcma input samples +got 1 pcma output frames (80 octets) count=12 +got 1 pcma output frames (80 octets) count=12 +generating 160 pcma input samples +got 1 pcma output frames (80 octets) count=12 +got 1 pcma output frames (80 octets) count=12 +generating 160 pcma input samples +got 1 pcma output frames (80 octets) count=12 +got 1 pcma output frames (80 octets) count=12 +generating 160 pcma input samples +got 1 pcma output frames (80 octets) count=12 +got 1 pcma output frames (80 octets) count=12 +generating 160 pcma input samples +got 1 pcma output frames (80 octets) count=12 +got 1 pcma output frames (80 octets) count=12 +generating 160 pcma input samples +got 1 pcma output frames (80 octets) count=12 +got 1 pcma output frames (80 octets) count=12 +generating 160 pcma input samples +got 1 pcma output frames (80 octets) count=12 +got 1 pcma output frames (80 octets) count=12 +generating 160 pcma input samples +got 1 pcma output frames (80 octets) count=12 +got 1 pcma output frames (80 octets) count=12 +generating 160 pcma input samples +got 1 pcma output frames (80 octets) count=12 +got 1 pcma output frames (80 octets) count=12 +generating 160 pcma input samples +got 1 pcma output frames (80 octets) count=12 +got 1 pcma output frames (80 octets) count=12 +generating 160 pcma input samples +got 1 pcma output frames (80 octets) count=12 +got 1 pcma output frames (80 octets) count=12 +generating 160 pcma input samples +got 1 pcma output frames (80 octets) count=12 +got 1 pcma output frames (80 octets) count=12 +generating 160 pcma input samples +got 1 pcma output frames (80 octets) count=12 +got 1 pcma output frames (80 octets) count=12 +generating 160 pcma input samples +got 1 pcma output frames (80 octets) count=12 +got 1 pcma output frames (80 octets) count=12 +generating 160 pcma input samples +got 1 pcma output frames (80 octets) count=12 +got 1 pcma output frames (80 octets) count=12 +generating 160 pcma input samples +got 1 pcma output frames (80 octets) count=12 +got 1 pcma output frames (80 octets) count=12 +== Transcoding test == +converting pcma -> l16 +generating 160 pcma input samples +generating 160 pcma input samples +got 4 l16 output frames (640 octets) count=12 +generating 160 pcma input samples +generating 160 pcma input samples +got 4 l16 output frames (640 octets) count=12 +generating 160 pcma input samples +generating 160 pcma input samples +got 4 l16 output frames (640 octets) count=12 +generating 160 pcma input samples +generating 160 pcma input samples +got 4 l16 output frames (640 octets) count=12 +generating 160 pcma input samples +generating 160 pcma input samples +got 4 l16 output frames (640 octets) count=12 +generating 160 pcma input samples +generating 160 pcma input samples +got 4 l16 output frames (640 octets) count=12 +generating 160 pcma input samples +generating 160 pcma input samples +got 4 l16 output frames (640 octets) count=12 +generating 160 pcma input samples +generating 160 pcma input samples +got 4 l16 output frames (640 octets) count=12 +== Transcoding test == +converting pcma -> pcma +generating 160 pcma input samples +generating 160 pcma input samples +got 4 pcma output frames (320 octets) count=12 +generating 160 pcma input samples +generating 160 pcma input samples +got 4 pcma output frames (320 octets) count=12 +generating 160 pcma input samples +generating 160 pcma input samples +got 4 pcma output frames (320 octets) count=12 +generating 160 pcma input samples +generating 160 pcma input samples +got 4 pcma output frames (320 octets) count=12 +generating 160 pcma input samples +generating 160 pcma input samples +got 4 pcma output frames (320 octets) count=12 +generating 160 pcma input samples +generating 160 pcma input samples +got 4 pcma output frames (320 octets) count=12 +generating 160 pcma input samples +generating 160 pcma input samples +got 4 pcma output frames (320 octets) count=12 +generating 160 pcma input samples +generating 160 pcma input samples +got 4 pcma output frames (320 octets) count=12 +== Transcoding test == +converting pcma -> l16 +generating 160 pcma input samples +generating 160 pcma input samples +got 3 l16 output frames (480 octets) count=12 +generating 160 pcma input samples +generating 160 pcma input samples +got 3 l16 output frames (480 octets) count=12 +generating 160 pcma input samples +generating 160 pcma input samples +got 3 l16 output frames (480 octets) count=12 +generating 160 pcma input samples +generating 160 pcma input samples +got 3 l16 output frames (480 octets) count=12 +generating 160 pcma input samples +generating 160 pcma input samples +got 3 l16 output frames (480 octets) count=12 +generating 160 pcma input samples +generating 160 pcma input samples +got 3 l16 output frames (480 octets) count=12 +generating 160 pcma input samples +generating 160 pcma input samples +got 3 l16 output frames (480 octets) count=12 +generating 160 pcma input samples +generating 160 pcma input samples +got 3 l16 output frames (480 octets) count=12 +== Transcoding test == +converting pcma -> pcma +generating 160 pcma input samples +generating 160 pcma input samples +got 3 pcma output frames (240 octets) count=12 +generating 160 pcma input samples +generating 160 pcma input samples +got 3 pcma output frames (240 octets) count=12 +generating 160 pcma input samples +generating 160 pcma input samples +got 3 pcma output frames (240 octets) count=12 +generating 160 pcma input samples +generating 160 pcma input samples +got 3 pcma output frames (240 octets) count=12 +generating 160 pcma input samples +generating 160 pcma input samples +got 3 pcma output frames (240 octets) count=12 +generating 160 pcma input samples +generating 160 pcma input samples +got 3 pcma output frames (240 octets) count=12 +generating 160 pcma input samples +generating 160 pcma input samples +got 3 pcma output frames (240 octets) count=12 +generating 160 pcma input samples +generating 160 pcma input samples +got 3 pcma output frames (240 octets) count=12 +== Transcoding test == +converting pcma -> l16 +generating 160 pcma input samples +got 1 l16 output frames (160 octets) count=12 +generating 160 pcma input samples +got 1 l16 output frames (160 octets) count=12 +got 1 l16 output frames (160 octets) count=12 +generating 160 pcma input samples +got 1 l16 output frames (160 octets) count=12 +got 1 l16 output frames (160 octets) count=12 +generating 160 pcma input samples +got 1 l16 output frames (160 octets) count=12 +got 1 l16 output frames (160 octets) count=12 +generating 160 pcma input samples +got 1 l16 output frames (160 octets) count=12 +got 1 l16 output frames (160 octets) count=12 +generating 160 pcma input samples +got 1 l16 output frames (160 octets) count=12 +got 1 l16 output frames (160 octets) count=12 +generating 160 pcma input samples +got 1 l16 output frames (160 octets) count=12 +got 1 l16 output frames (160 octets) count=12 +generating 160 pcma input samples +got 1 l16 output frames (160 octets) count=12 +got 1 l16 output frames (160 octets) count=12 +generating 160 pcma input samples +got 1 l16 output frames (160 octets) count=12 +got 1 l16 output frames (160 octets) count=12 +generating 160 pcma input samples +got 1 l16 output frames (160 octets) count=12 +got 1 l16 output frames (160 octets) count=12 +generating 160 pcma input samples +got 1 l16 output frames (160 octets) count=12 +got 1 l16 output frames (160 octets) count=12 +generating 160 pcma input samples +got 1 l16 output frames (160 octets) count=12 +got 1 l16 output frames (160 octets) count=12 +generating 160 pcma input samples +got 1 l16 output frames (160 octets) count=12 +got 1 l16 output frames (160 octets) count=12 +generating 160 pcma input samples +got 1 l16 output frames (160 octets) count=12 +got 1 l16 output frames (160 octets) count=12 +generating 160 pcma input samples +got 1 l16 output frames (160 octets) count=12 +got 1 l16 output frames (160 octets) count=12 +generating 160 pcma input samples +got 1 l16 output frames (160 octets) count=12 +got 1 l16 output frames (160 octets) count=12 +== Transcoding test == +converting pcma -> pcma +generating 160 pcma input samples +got 1 pcma output frames (80 octets) count=12 +generating 160 pcma input samples +got 1 pcma output frames (80 octets) count=12 +got 1 pcma output frames (80 octets) count=12 +generating 160 pcma input samples +got 1 pcma output frames (80 octets) count=12 +got 1 pcma output frames (80 octets) count=12 +generating 160 pcma input samples +got 1 pcma output frames (80 octets) count=12 +got 1 pcma output frames (80 octets) count=12 +generating 160 pcma input samples +got 1 pcma output frames (80 octets) count=12 +got 1 pcma output frames (80 octets) count=12 +generating 160 pcma input samples +got 1 pcma output frames (80 octets) count=12 +got 1 pcma output frames (80 octets) count=12 +generating 160 pcma input samples +got 1 pcma output frames (80 octets) count=12 +got 1 pcma output frames (80 octets) count=12 +generating 160 pcma input samples +got 1 pcma output frames (80 octets) count=12 +got 1 pcma output frames (80 octets) count=12 +generating 160 pcma input samples +got 1 pcma output frames (80 octets) count=12 +got 1 pcma output frames (80 octets) count=12 +generating 160 pcma input samples +got 1 pcma output frames (80 octets) count=12 +got 1 pcma output frames (80 octets) count=12 +generating 160 pcma input samples +got 1 pcma output frames (80 octets) count=12 +got 1 pcma output frames (80 octets) count=12 +generating 160 pcma input samples +got 1 pcma output frames (80 octets) count=12 +got 1 pcma output frames (80 octets) count=12 +generating 160 pcma input samples +got 1 pcma output frames (80 octets) count=12 +got 1 pcma output frames (80 octets) count=12 +generating 160 pcma input samples +got 1 pcma output frames (80 octets) count=12 +got 1 pcma output frames (80 octets) count=12 +generating 160 pcma input samples +got 1 pcma output frames (80 octets) count=12 +got 1 pcma output frames (80 octets) count=12 +generating 160 pcma input samples +got 1 pcma output frames (80 octets) count=12 +got 1 pcma output frames (80 octets) count=12 +Testing Initial L16->GSM, PCMA->GSM diff --git a/tests/mgcp/Makefile.am b/tests/mgcp/Makefile.am new file mode 100644 index 0000000..caccb9f --- /dev/null +++ b/tests/mgcp/Makefile.am @@ -0,0 +1,38 @@ +AM_CPPFLAGS = \ + $(all_includes) \ + -I$(top_srcdir)/include \ + -I$(top_srcdir) \ + $(NULL) + +AM_CFLAGS = \ + -Wall \ + -ggdb3 \ + $(LIBOSMOCORE_CFLAGS) \ + $(LIBOSMONETIF_CFLAGS) \ + $(COVERAGE_CFLAGS) \ + $(NULL) + +AM_LDFLAGS = \ + $(COVERAGE_LDFLAGS) \ + $(NULL) + +EXTRA_DIST = \ + mgcp_test.ok \ + $(NULL) + +noinst_PROGRAMS = \ + mgcp_test \ + $(NULL) + +mgcp_test_SOURCES = \ + mgcp_test.c \ + $(NULL) + +mgcp_test_LDADD = \ + $(top_builddir)/src/libosmo-mgcp/libosmo-mgcp.la \ + $(LIBOSMOCORE_LIBS) \ + $(LIBOSMOVTY_LIBS) \ + $(LIBRARY_DL) \ + $(LIBOSMONETIF_LIBS) \ + -lm \ + $(NULL) diff --git a/tests/mgcp/mgcp_test.c b/tests/mgcp/mgcp_test.c new file mode 100644 index 0000000..e14b7ee --- /dev/null +++ b/tests/mgcp/mgcp_test.c @@ -0,0 +1,1353 @@ +/* + * (C) 2011-2012,2014 by Holger Hans Peter Freyther <zecke@selfish.org> + * (C) 2011-2012,2014 by On-Waves + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +#undef _GNU_SOURCE +#define _GNU_SOURCE + +#include <osmocom/mgcp/mgcp.h> +#include <osmocom/mgcp/vty.h> +#include <osmocom/mgcp/mgcp_common.h> +#include <osmocom/mgcp/mgcp_internal.h> +#include <osmocom/mgcp/mgcp_stat.h> +#include <osmocom/mgcp/mgcp_msg.h> +#include <osmocom/mgcp/mgcp_ep.h> + +#include <osmocom/core/application.h> +#include <osmocom/core/talloc.h> +#include <osmocom/core/utils.h> +#include <string.h> +#include <limits.h> +#include <dlfcn.h> +#include <time.h> +#include <math.h> + +char *strline_r(char *str, char **saveptr); + +const char *strline_test_data = + "one CR\r" + "two CR\r" + "\r" + "one CRLF\r\n" + "two CRLF\r\n" + "\r\n" "one LF\n" "two LF\n" "\n" "mixed (4 lines)\r\r\n\n\r\n"; + +#define EXPECTED_NUMBER_OF_LINES 13 + +static void test_strline(void) +{ + char *save = NULL; + char *line; + char buf[2048]; + int counter = 0; + + osmo_strlcpy(buf, strline_test_data, sizeof(buf)); + + for (line = mgcp_strline(buf, &save); line; + line = mgcp_strline(NULL, &save)) { + printf("line: '%s'\n", line); + counter++; + } + + OSMO_ASSERT(counter == EXPECTED_NUMBER_OF_LINES); +} + +#define AUEP1 "AUEP 158663169 ds/e1-1/2@172.16.6.66 MGCP 1.0\r\n" +#define AUEP1_RET "200 158663169 OK\r\n" +#define AUEP2 "AUEP 18983213 ds/e1-2/1@172.16.6.66 MGCP 1.0\r\n" +#define AUEP2_RET "500 18983213 FAIL\r\n" +#define EMPTY "\r\n" +#define EMPTY_RET NULL +#define SHORT "CRCX \r\n" +#define SHORT_RET "510 000000 FAIL\r\n" + +#define MDCX_WRONG_EP "MDCX 18983213 ds/e1-3/1@172.16.6.66 MGCP 1.0\r\n" +#define MDCX_ERR_RET "510 18983213 FAIL\r\n" +#define MDCX_UNALLOCATED "MDCX 18983214 ds/e1-1/2@172.16.6.66 MGCP 1.0\r\n" +#define MDCX_RET "400 18983214 FAIL\r\n" + +#define MDCX3 \ + "MDCX 18983215 1@mgw MGCP 1.0\r\n" \ + "I: 1\n" + +#define MDCX3_RET \ + "200 18983215 OK\r\n" \ + "I: 1\n" \ + "\n" \ + "v=0\r\n" \ + "o=- 1 23 IN IP4 0.0.0.0\r\n" \ + "s=-\r\n" \ + "c=IN IP4 0.0.0.0\r\n" \ + "t=0 0\r\n" \ + "m=audio 16002 RTP/AVP 128\r\n" \ + "a=rtpmap:128 GSM-EFR/8000\r\n" \ + "a=ptime:40\r\n" + +#define MDCX3A_RET \ + "200 18983215 OK\r\n" \ + "I: 1\n" \ + "\n" \ + "v=0\r\n" \ + "o=- 1 23 IN IP4 0.0.0.0\r\n" \ + "s=-\r\n" \ + "c=IN IP4 0.0.0.0\r\n" \ + "t=0 0\r\n" \ + "m=audio 16002 RTP/AVP 97\r\n" \ + "a=rtpmap:97 GSM-EFR/8000\r\n" \ + "a=ptime:40\r\n" + +#define MDCX3_FMTP_RET \ + "200 18983215 OK\r\n" \ + "I: 1\n" \ + "\n" \ + "v=0\r\n" \ + "o=- 1 23 IN IP4 0.0.0.0\r\n" \ + "s=-\r\n" \ + "c=IN IP4 0.0.0.0\r\n" \ + "t=0 0\r\n" \ + "m=audio 16006 RTP/AVP 128\r\n" \ + "a=rtpmap:128 GSM-EFR/8000\r\n" \ + "a=fmtp:126 0/1/2\r\n" \ + "a=ptime:40\r\n" + +#define MDCX4 \ + "MDCX 18983216 1@mgw MGCP 1.0\r\n" \ + "M: sendrecv\r" \ + "C: 2\r\n" \ + "I: 1\r\n" \ + "L: p:20, a:AMR, nt:IN\r\n" \ + "\n" \ + "v=0\r\n" \ + "o=- 1 23 IN IP4 0.0.0.0\r\n" \ + "c=IN IP4 0.0.0.0\r\n" \ + "t=0 0\r\n" \ + "m=audio 4441 RTP/AVP 99\r\n" \ + "a=rtpmap:99 AMR/8000\r\n" \ + "a=ptime:40\r\n" + +#define MDCX4_RET(Ident) \ + "200 " Ident " OK\r\n" \ + "I: 1\n" \ + "\n" \ + "v=0\r\n" \ + "o=- 1 23 IN IP4 0.0.0.0\r\n" \ + "s=-\r\n" \ + "c=IN IP4 0.0.0.0\r\n" \ + "t=0 0\r\n" \ + "m=audio 16002 RTP/AVP 99\r\n" \ + "a=rtpmap:99 AMR/8000\r\n" \ + "a=ptime:40\r\n" + +#define MDCX4_RO_RET(Ident) \ + "200 " Ident " OK\r\n" \ + "I: 1\n" \ + "\n" \ + "v=0\r\n" \ + "o=- 1 23 IN IP4 0.0.0.0\r\n" \ + "s=-\r\n" \ + "c=IN IP4 0.0.0.0\r\n" \ + "t=0 0\r\n" \ + "m=audio 16002 RTP/AVP 96\r\n" \ + "a=rtpmap:96 AMR\r\n" \ + "a=ptime:40\r\n" + +#define MDCX4_PT1 \ + "MDCX 18983217 1@mgw MGCP 1.0\r\n" \ + "M: sendrecv\r" \ + "C: 2\r\n" \ + "I: 1\r\n" \ + "L: p:20-40, a:AMR, nt:IN\r\n" \ + "\n" \ + "v=0\r\n" \ + "o=- 1 23 IN IP4 0.0.0.0\r\n" \ + "c=IN IP4 0.0.0.0\r\n" \ + "t=0 0\r\n" \ + "m=audio 4441 RTP/AVP 99\r\n" \ + "a=rtpmap:99 AMR/8000\r\n" \ + "a=ptime:40\r\n" + +#define MDCX4_PT2 \ + "MDCX 18983218 1@mgw MGCP 1.0\r\n" \ + "M: sendrecv\r" \ + "C: 2\r\n" \ + "I: 1\r\n" \ + "L: p:20-20, a:AMR, nt:IN\r\n" \ + "\n" \ + "v=0\r\n" \ + "o=- 1 23 IN IP4 0.0.0.0\r\n" \ + "c=IN IP4 0.0.0.0\r\n" \ + "t=0 0\r\n" \ + "m=audio 4441 RTP/AVP 99\r\n" \ + "a=rtpmap:99 AMR/8000\r\n" \ + "a=ptime:40\r\n" + +#define MDCX4_PT3 \ + "MDCX 18983219 1@mgw MGCP 1.0\r\n" \ + "M: sendrecv\r" \ + "C: 2\r\n" \ + "I: 1\r\n" \ + "L: a:AMR, nt:IN\r\n" \ + "\n" \ + "v=0\r\n" \ + "o=- 1 23 IN IP4 0.0.0.0\r\n" \ + "c=IN IP4 0.0.0.0\r\n" \ + "t=0 0\r\n" \ + "m=audio 4441 RTP/AVP 99\r\n" \ + "a=rtpmap:99 AMR/8000\r\n" \ + "a=ptime:40\r\n" + +#define MDCX4_SO \ + "MDCX 18983220 1@mgw MGCP 1.0\r\n" \ + "M: sendonly\r" \ + "C: 2\r\n" \ + "I: 1\r\n" \ + "L: p:20, a:AMR, nt:IN\r\n" \ + "\n" \ + "v=0\r\n" \ + "o=- 1 23 IN IP4 0.0.0.0\r\n" \ + "c=IN IP4 0.0.0.0\r\n" \ + "t=0 0\r\n" \ + "m=audio 4441 RTP/AVP 99\r\n" \ + "a=rtpmap:99 AMR/8000\r\n" \ + "a=ptime:40\r\n" + +#define MDCX4_RO \ + "MDCX 18983221 1@mgw MGCP 1.0\r\n" \ + "M: recvonly\r" \ + "C: 2\r\n" \ + "I: 1\r\n" \ + "L: p:20, a:AMR, nt:IN\r\n" + +#define SHORT2 "CRCX 1" +#define SHORT2_RET "510 000000 FAIL\r\n" +#define SHORT3 "CRCX 1 1@mgw" +#define SHORT4 "CRCX 1 1@mgw MGCP" +#define SHORT5 "CRCX 1 1@mgw MGCP 1.0" + +#define CRCX \ + "CRCX 2 1@mgw MGCP 1.0\r\n" \ + "M: recvonly\r\n" \ + "C: 2\r\n" \ + "I: 1\r\n" \ + "L: p:20\r\n" \ + "\r\n" \ + "v=0\r\n" \ + "c=IN IP4 123.12.12.123\r\n" \ + "m=audio 5904 RTP/AVP 97\r\n" \ + "a=rtpmap:97 GSM-EFR/8000\r\n" \ + "a=ptime:40\r\n" + +#define CRCX_RET \ + "200 2 OK\r\n" \ + "I: 1\n" \ + "\n" \ + "v=0\r\n" \ + "o=- 1 23 IN IP4 0.0.0.0\r\n" \ + "s=-\r\n" \ + "c=IN IP4 0.0.0.0\r\n" \ + "t=0 0\r\n" \ + "m=audio 16002 RTP/AVP 97\r\n" \ + "a=rtpmap:97 GSM-EFR/8000\r\n" \ + "a=ptime:40\r\n" + +#define CRCX_RET_NO_RTPMAP \ + "200 2 OK\r\n" \ + "I: 1\n" \ + "\n" \ + "v=0\r\n" \ + "o=- 1 23 IN IP4 0.0.0.0\r\n" \ + "s=-\r\n" \ + "c=IN IP4 0.0.0.0\r\n" \ + "t=0 0\r\n" \ + "m=audio 16002 RTP/AVP 97\r\n" \ + "a=ptime:40\r\n" + +#define CRCX_FMTP_RET \ + "200 2 OK\r\n" \ + "I: 1\n" \ + "\n" \ + "v=0\r\n" \ + "o=- 1 23 IN IP4 0.0.0.0\r\n" \ + "s=-\r\n" \ + "c=IN IP4 0.0.0.0\r\n" \ + "t=0 0\r\n" \ + "m=audio 16006 RTP/AVP 97\r\n" \ + "a=rtpmap:97 GSM-EFR/8000\r\n" \ + "a=fmtp:126 0/1/2\r\n" \ + "a=ptime:40\r\n" + +#define CRCX_ZYN \ + "CRCX 2 1@mgw MGCP 1.0\r" \ + "M: recvonly\r" \ + "C: 2\r\n" \ + "I: 1\n" \ + "\n" \ + "v=0\r" \ + "c=IN IP4 123.12.12.123\r" \ + "m=audio 5904 RTP/AVP 97\r" \ + "a=rtpmap:97 GSM-EFR/8000\r" + +#define CRCX_ZYN_RET \ + "200 2 OK\r\n" \ + "I: 1\n" \ + "\n" \ + "v=0\r\n" \ + "o=- 1 23 IN IP4 0.0.0.0\r\n" \ + "s=-\r\n" \ + "c=IN IP4 0.0.0.0\r\n" \ + "t=0 0\r\n" \ + "m=audio 16004 RTP/AVP 97\r\n" \ + "a=rtpmap:97 GSM-EFR/8000\r\n" \ + "a=ptime:20\r\n" + +#define DLCX \ + "DLCX 7 1@mgw MGCP 1.0\r\n" \ + "I: 1\r\n" \ + "C: 2\r\n" + +#define DLCX_RET \ + "250 7 OK\r\n" \ + "P: PS=0, OS=0, PR=0, OR=0, PL=0, JI=0\r\n" \ + "X-Osmo-CP: EC TI=0, TO=0\r\n" + +#define RQNT \ + "RQNT 186908780 1@mgw MGCP 1.0\r\n" \ + "X: B244F267488\r\n" \ + "S: D/9\r\n" + +#define RQNT2 \ + "RQNT 186908781 1@mgw MGCP 1.0\r\n" \ + "X: ADD4F26746F\r\n" \ + "R: D/[0-9#*](N), G/ft, fxr/t38\r\n" + +#define RQNT1_RET "200 186908780 OK\r\n" +#define RQNT2_RET "200 186908781 OK\r\n" + +#define PTYPE_IGNORE 0 /* == default initializer */ +#define PTYPE_NONE 128 +#define PTYPE_NYI PTYPE_NONE + +#define CRCX_MULT_1 \ + "CRCX 2 1@mgw MGCP 1.0\r\n" \ + "I: 4711\r\n" \ + "M: recvonly\r\n" \ + "C: 2\r\n" \ + "X\r\n" \ + "L: p:20\r\n" \ + "\r\n" \ + "v=0\r\n" \ + "c=IN IP4 123.12.12.123\r\n" \ + "m=audio 5904 RTP/AVP 18 97\r\n" \ + "a=rtpmap:18 G729/8000\r\n" \ + "a=rtpmap:97 GSM-EFR/8000\r\n" \ + "a=ptime:40\r\n" + +#define CRCX_MULT_2 \ + "CRCX 2 2@mgw MGCP 1.0\r\n" \ + "I: 90210\r\n" \ + "M: recvonly\r\n" \ + "C: 2\r\n" \ + "X\r\n" \ + "L: p:20\r\n" \ + "\r\n" \ + "v=0\r\n" \ + "c=IN IP4 123.12.12.123\r\n" \ + "m=audio 5904 RTP/AVP 18 97 101\r\n" \ + "a=rtpmap:18 G729/8000\r\n" \ + "a=rtpmap:97 GSM-EFR/8000\r\n" \ + "a=rtpmap:101 FOO/8000\r\n" \ + "a=ptime:40\r\n" + +#define CRCX_MULT_3 \ + "CRCX 2 3@mgw MGCP 1.0\r\n" \ + "I: 0815\r\n" \ + "M: recvonly\r\n" \ + "C: 2\r\n" \ + "X\r\n" \ + "L: p:20\r\n" \ + "\r\n" \ + "v=0\r\n" \ + "c=IN IP4 123.12.12.123\r\n" \ + "m=audio 5904 RTP/AVP\r\n" \ + "a=rtpmap:18 G729/8000\r\n" \ + "a=rtpmap:97 GSM-EFR/8000\r\n" \ + "a=rtpmap:101 FOO/8000\r\n" \ + "a=ptime:40\r\n" + +#define CRCX_MULT_4 \ + "CRCX 2 4@mgw MGCP 1.0\r\n" \ + "I: 32168\r\n" \ + "M: recvonly\r\n" \ + "C: 2\r\n" \ + "X\r\n" \ + "L: p:20\r\n" \ + "\r\n" \ + "v=0\r\n" \ + "c=IN IP4 123.12.12.123\r\n" \ + "m=audio 5904 RTP/AVP 18\r\n" \ + "a=rtpmap:18 G729/8000\r\n" \ + "a=rtpmap:97 GSM-EFR/8000\r\n" \ + "a=rtpmap:101 FOO/8000\r\n" \ + "a=ptime:40\r\n" + +#define CRCX_MULT_GSM_EXACT \ + "CRCX 259260421 5@mgw MGCP 1.0\r\n" \ + "C: 1355c6041e\r\n" \ + "I: 3\r\n" \ + "L: p:20, a:GSM, nt:IN\r\n" \ + "M: recvonly\r\n" \ + "\r\n" \ + "v=0\r\n" \ + "o=- 1439038275 1439038275 IN IP4 192.168.181.247\r\n" \ + "s=-\r\nc=IN IP4 192.168.181.247\r\n" \ + "t=0 0\r\nm=audio 29084 RTP/AVP 255 0 8 3 18 4 96 97 101\r\n" \ + "a=rtpmap:0 PCMU/8000\r\n" \ + "a=rtpmap:8 PCMA/8000\r\n" \ + "a=rtpmap:3 gsm/8000\r\n" \ + "a=rtpmap:18 G729/8000\r\n" \ + "a=fmtp:18 annexb=no\r\n" \ + "a=rtpmap:4 G723/8000\r\n" \ + "a=rtpmap:96 iLBC/8000\r\n" \ + "a=fmtp:96 mode=20\r\n" \ + "a=rtpmap:97 iLBC/8000\r\n" \ + "a=fmtp:97 mode=30\r\n" \ + "a=rtpmap:101 telephone-event/8000\r\n" \ + "a=fmtp:101 0-15\r\n" \ + "a=recvonly\r\n" + +#define MDCX_NAT_DUMMY \ + "MDCX 23 5@mgw MGCP 1.0\r\n" \ + "C: 1355c6041e\r\n" \ + "I: 3\r\n" \ + "\r\n" \ + "c=IN IP4 8.8.8.8\r\n" \ + "m=audio 16434 RTP/AVP 255\r\n" + +struct mgcp_test { + const char *name; + const char *req; + const char *exp_resp; + int ptype; + const char *extra_fmtp; +}; + +static const struct mgcp_test tests[] = { + {"AUEP1", AUEP1, AUEP1_RET}, + {"AUEP2", AUEP2, AUEP2_RET}, + {"MDCX1", MDCX_WRONG_EP, MDCX_ERR_RET}, + {"MDCX2", MDCX_UNALLOCATED, MDCX_RET}, + {"CRCX", CRCX, CRCX_RET, 97}, + {"MDCX3", MDCX3, MDCX3_RET, PTYPE_IGNORE}, + {"MDCX4", MDCX4, MDCX4_RET("18983216"), 99}, + {"MDCX4_PT1", MDCX4_PT1, MDCX4_RET("18983217"), 99}, + {"MDCX4_PT2", MDCX4_PT2, MDCX4_RET("18983218"), 99}, + {"MDCX4_PT3", MDCX4_PT3, MDCX4_RET("18983219"), 99}, + {"MDCX4_SO", MDCX4_SO, MDCX4_RET("18983220"), 99}, + {"MDCX4_RO", MDCX4_RO, MDCX4_RO_RET("18983221"), PTYPE_IGNORE}, + {"DLCX", DLCX, DLCX_RET, PTYPE_IGNORE}, + {"CRCX_ZYN", CRCX_ZYN, CRCX_ZYN_RET, 97}, + {"EMPTY", EMPTY, EMPTY_RET}, + {"SHORT1", SHORT, SHORT_RET}, + {"SHORT2", SHORT2, SHORT2_RET}, + {"SHORT3", SHORT3, SHORT2_RET}, + {"SHORT4", SHORT4, SHORT2_RET}, + {"RQNT1", RQNT, RQNT1_RET}, + {"RQNT2", RQNT2, RQNT2_RET}, + {"DLCX", DLCX, DLCX_RET, PTYPE_IGNORE}, + {"CRCX", CRCX, CRCX_FMTP_RET, 97,.extra_fmtp = "a=fmtp:126 0/1/2"}, + {"MDCX3", MDCX3, MDCX3_FMTP_RET, PTYPE_NONE,.extra_fmtp = + "a=fmtp:126 0/1/2"}, + {"DLCX", DLCX, DLCX_RET, PTYPE_IGNORE,.extra_fmtp = "a=fmtp:126 0/1/2"}, +}; + +static const struct mgcp_test retransmit[] = { + {"CRCX", CRCX, CRCX_RET}, + {"RQNT1", RQNT, RQNT1_RET}, + {"RQNT2", RQNT2, RQNT2_RET}, + {"MDCX3", MDCX3, MDCX3A_RET}, + {"DLCX", DLCX, DLCX_RET}, +}; + +static struct msgb *create_msg(const char *str) +{ + struct msgb *msg; + + msg = msgb_alloc_headroom(4096, 128, "MGCP msg"); + int len = sprintf((char *)msg->data, "%s", str); + msg->l2h = msgb_put(msg, len); + return msg; +} + +static int last_endpoint = -1; + +static int mgcp_test_policy_cb(struct mgcp_trunk_config *cfg, int endpoint, + int state, const char *transactio_id) +{ + fprintf(stderr, "Policy CB got state %d on endpoint %d\n", + state, endpoint); + last_endpoint = endpoint; + return MGCP_POLICY_CONT; +} + +#define MGCP_DUMMY_LOAD 0x23 +static int dummy_packets = 0; +/* override and forward */ +ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, + const struct sockaddr *dest_addr, socklen_t addrlen) +{ + uint32_t dest_host = + htonl(((struct sockaddr_in *)dest_addr)->sin_addr.s_addr); + int dest_port = htons(((struct sockaddr_in *)dest_addr)->sin_port); + + if (len == 1 && ((const char *)buf)[0] == MGCP_DUMMY_LOAD) { + fprintf(stderr, + "Dummy packet to 0x%08x:%d, msg length %zu\n%s\n\n", + dest_host, dest_port, len, osmo_hexdump(buf, len)); + dummy_packets += 1; + } + + return len; +} + +static int64_t force_monotonic_time_us = -1; +/* override and forward */ +int clock_gettime(clockid_t clk_id, struct timespec *tp) +{ + typedef int (*clock_gettime_t)(clockid_t clk_id, struct timespec *tp); + static clock_gettime_t real_clock_gettime = NULL; + + if (!real_clock_gettime) + real_clock_gettime = dlsym(RTLD_NEXT, "clock_gettime"); + + if (clk_id == CLOCK_MONOTONIC && force_monotonic_time_us >= 0) { + tp->tv_sec = force_monotonic_time_us / 1000000; + tp->tv_nsec = (force_monotonic_time_us % 1000000) * 1000; + return 0; + } + + return real_clock_gettime(clk_id, tp); +} + +#define CONN_UNMODIFIED (0x1000) + +static void test_values(void) +{ + /* Check that NONE disables all output */ + OSMO_ASSERT((MGCP_CONN_NONE & MGCP_CONN_RECV_SEND) == 0); + + /* Check that LOOPBACK enables all output */ + OSMO_ASSERT((MGCP_CONN_LOOPBACK & MGCP_CONN_RECV_SEND) == + MGCP_CONN_RECV_SEND); +} + +static void test_messages(void) +{ + struct mgcp_config *cfg; + struct mgcp_endpoint *endp; + int i; + struct mgcp_conn_rtp *conn = NULL; + + cfg = mgcp_config_alloc(); + + cfg->trunk.number_endpoints = 64; + mgcp_endpoints_allocate(&cfg->trunk); + + cfg->policy_cb = mgcp_test_policy_cb; + + mgcp_endpoints_allocate(mgcp_trunk_alloc(cfg, 1)); + + for (i = 0; i < ARRAY_SIZE(tests); i++) { + const struct mgcp_test *t = &tests[i]; + struct msgb *inp; + struct msgb *msg; + + printf("Testing %s\n", t->name); + + last_endpoint = -1; + dummy_packets = 0; + + osmo_talloc_replace_string(cfg, &cfg->trunk.audio_fmtp_extra, + t->extra_fmtp); + + inp = create_msg(t->req); + msg = mgcp_handle_message(cfg, inp); + msgb_free(inp); + if (!t->exp_resp) { + if (msg) { + printf("%s failed '%s'\n", t->name, + (char *)msg->data); + OSMO_ASSERT(false); + } + } else if (strcmp((char *)msg->data, t->exp_resp) != 0) { + printf("%s failed.\nExpected:\n%s\nGot:\n%s\n", + t->name, t->exp_resp, (char *) msg->data); + OSMO_ASSERT(false); + } + msgb_free(msg); + + if (dummy_packets) + printf("Dummy packets: %d\n", dummy_packets); + + if (last_endpoint != -1) { + endp = &cfg->trunk.endpoints[last_endpoint]; + + conn = mgcp_conn_get_rtp(endp, 1); + if (conn) { + OSMO_ASSERT(conn); + + if (conn->end.packet_duration_ms != -1) + printf("Detected packet duration: %d\n", + conn->end.packet_duration_ms); + else + printf("Packet duration not set\n"); + if (endp->local_options.pkt_period_min || + endp->local_options.pkt_period_max) + printf + ("Requested packetetization period: " + "%d-%d\n", + endp->local_options.pkt_period_min, + endp-> + local_options.pkt_period_max); + else + printf + ("Requested packetization period not set\n"); + + if ((conn->conn->mode & CONN_UNMODIFIED) == 0) { + printf("Connection mode: %d:%s%s%s%s\n", + conn->conn->mode, + !conn->conn->mode ? " NONE" : "", + conn->conn->mode & MGCP_CONN_SEND_ONLY + ? " SEND" : "", + conn->conn->mode & MGCP_CONN_RECV_ONLY + ? " RECV" : "", + conn->conn->mode & MGCP_CONN_LOOPBACK + & ~MGCP_CONN_RECV_SEND + ? " LOOP" : ""); + fprintf(stderr, + "RTP output %sabled, NET output %sabled\n", + conn->end.output_enabled + ? "en" : "dis", + conn->end.output_enabled + ? "en" : "dis"); + } else + printf("Connection mode not set\n"); + + OSMO_ASSERT(conn->end.output_enabled + == (conn->conn->mode & MGCP_CONN_SEND_ONLY ? 1 : 0)); + + conn->conn->mode |= CONN_UNMODIFIED; + + } + endp->local_options.pkt_period_min = 0; + endp->local_options.pkt_period_max = 0; + } + + /* Check detected payload type */ + if (t->ptype != PTYPE_IGNORE) { + OSMO_ASSERT(last_endpoint != -1); + endp = &cfg->trunk.endpoints[last_endpoint]; + + fprintf(stderr, "endpoint %d: " + "payload type %d (expected %d)\n", + last_endpoint, + conn->end.codec.payload_type, t->ptype); + + if (t->ptype != PTYPE_IGNORE) + OSMO_ASSERT(conn->end.codec.payload_type == + t->ptype); + + /* Reset them again for next test */ + conn->end.codec.payload_type = PTYPE_NONE; + } + } + + talloc_free(cfg); +} + +static void test_retransmission(void) +{ + struct mgcp_config *cfg; + int i; + + cfg = mgcp_config_alloc(); + + cfg->trunk.number_endpoints = 64; + mgcp_endpoints_allocate(&cfg->trunk); + + mgcp_endpoints_allocate(mgcp_trunk_alloc(cfg, 1)); + + for (i = 0; i < ARRAY_SIZE(retransmit); i++) { + const struct mgcp_test *t = &retransmit[i]; + struct msgb *inp; + struct msgb *msg; + + printf("Testing %s\n", t->name); + + inp = create_msg(t->req); + msg = mgcp_handle_message(cfg, inp); + + msgb_free(inp); + if (strcmp((char *)msg->data, t->exp_resp) != 0) { + printf("%s failed '%s'\n", t->name, (char *)msg->data); + OSMO_ASSERT(false); + } + msgb_free(msg); + + /* Retransmit... */ + printf("Re-transmitting %s\n", t->name); + inp = create_msg(t->req); + msg = mgcp_handle_message(cfg, inp); + msgb_free(inp); + if (strcmp((char *)msg->data, t->exp_resp) != 0) { + printf("%s failed '%s'\n", t->name, (char *)msg->data); + OSMO_ASSERT(false); + } + msgb_free(msg); + } + + talloc_free(cfg); +} + +static int rqnt_cb(struct mgcp_endpoint *endp, char _tone) +{ + ptrdiff_t tone = _tone; + endp->cfg->data = (void *)tone; + return 0; +} + +static void test_rqnt_cb(void) +{ + struct mgcp_config *cfg; + struct msgb *inp, *msg; + + cfg = mgcp_config_alloc(); + cfg->rqnt_cb = rqnt_cb; + + cfg->trunk.number_endpoints = 64; + mgcp_endpoints_allocate(&cfg->trunk); + + mgcp_endpoints_allocate(mgcp_trunk_alloc(cfg, 1)); + + inp = create_msg(CRCX); + msgb_free(mgcp_handle_message(cfg, inp)); + msgb_free(inp); + + /* send the RQNT and check for the CB */ + inp = create_msg(RQNT); + msg = mgcp_handle_message(cfg, inp); + if (strncmp((const char *)msg->l2h, "200", 3) != 0) { + printf("FAILED: message is not 200. '%s'\n", msg->l2h); + abort(); + } + + if (cfg->data != (void *)'9') { + printf("FAILED: callback not called: %p\n", cfg->data); + abort(); + } + + msgb_free(msg); + msgb_free(inp); + + inp = create_msg(DLCX); + msgb_free(mgcp_handle_message(cfg, inp)); + msgb_free(inp); + talloc_free(cfg); +} + +struct pl_test { + int cycles; + uint16_t base_seq; + uint16_t max_seq; + uint32_t packets; + + uint32_t expected; + int loss; +}; + +static const struct pl_test pl_test_dat[] = { + /* basic.. just one package */ + {.cycles = 0,.base_seq = 0,.max_seq = 0,.packets = 1,.expected = + 1,.loss = 0}, + /* some packages and a bit of loss */ + {.cycles = 0,.base_seq = 0,.max_seq = 100,.packets = 100,.expected = + 101,.loss = 1}, + /* wrap around */ + {.cycles = 1 << 16,.base_seq = 0xffff,.max_seq = 2,.packets = + 4,.expected = 4,.loss = 0}, + /* min loss */ + {.cycles = 0,.base_seq = 0,.max_seq = 0,.packets = UINT_MAX,.expected = + 1,.loss = INT_MIN}, + /* max loss, with wrap around on expected max */ + {.cycles = INT_MAX,.base_seq = 0,.max_seq = UINT16_MAX,.packets = + 0,.expected = ((uint32_t) (INT_MAX) + UINT16_MAX + 1),.loss = INT_MAX}, +}; + +static void test_packet_loss_calc(void) +{ + int i; + printf("Testing packet loss calculation.\n"); + + for (i = 0; i < ARRAY_SIZE(pl_test_dat); ++i) { + uint32_t expected; + int loss; + struct mgcp_rtp_state state; + struct mgcp_rtp_end rtp; + memset(&state, 0, sizeof(state)); + memset(&rtp, 0, sizeof(rtp)); + + state.stats_initialized = 1; + state.stats_base_seq = pl_test_dat[i].base_seq; + state.stats_max_seq = pl_test_dat[i].max_seq; + state.stats_cycles = pl_test_dat[i].cycles; + + rtp.packets_rx = pl_test_dat[i].packets; + calc_loss(&state, &rtp, &expected, &loss); + + if (loss != pl_test_dat[i].loss + || expected != pl_test_dat[i].expected) { + printf + ("FAIL: Wrong exp/loss at idx(%d) Loss(%d vs. %d) Exp(%u vs. %u)\n", + i, loss, pl_test_dat[i].loss, expected, + pl_test_dat[i].expected); + } + } +} + +int mgcp_parse_stats(struct msgb *msg, uint32_t *ps, uint32_t *os, + uint32_t *pr, uint32_t *_or, int *loss, + uint32_t *jitter) +{ + char *line, *save; + int rc; + + /* initialize with bad values */ + *ps = *os = *pr = *_or = *jitter = UINT_MAX; + *loss = INT_MAX; + + line = strtok_r((char *)msg->l2h, "\r\n", &save); + if (!line) + return -1; + + /* this can only parse the message that is created above... */ + for_each_non_empty_line(line, save) { + switch (line[0]) { + case 'P': + rc = sscanf(line, + "P: PS=%u, OS=%u, PR=%u, OR=%u, PL=%d, JI=%u", + ps, os, pr, _or, loss, jitter); + return rc == 6 ? 0 : -1; + } + } + + return -1; +} + +static void test_mgcp_stats(void) +{ + printf("Testing stat parsing\n"); + + uint32_t bps, bos, pr, _or, jitter; + struct msgb *msg; + int loss; + int rc; + + msg = create_msg(DLCX_RET); + rc = mgcp_parse_stats(msg, &bps, &bos, &pr, &_or, &loss, &jitter); + printf("Parsing result: %d\n", rc); + if (bps != 0 || bos != 0 || pr != 0 || _or != 0 || loss != 0 + || jitter != 0) + printf("FAIL: Parsing failed1.\n"); + msgb_free(msg); + + msg = + create_msg + ("250 7 OK\r\nP: PS=10, OS=20, PR=30, OR=40, PL=-3, JI=40\r\n"); + rc = mgcp_parse_stats(msg, &bps, &bos, &pr, &_or, &loss, &jitter); + printf("Parsing result: %d\n", rc); + if (bps != 10 || bos != 20 || pr != 30 || _or != 40 || loss != -3 + || jitter != 40) + printf("FAIL: Parsing failed2.\n"); + msgb_free(msg); +} + +struct rtp_packet_info { + float txtime; + int len; + char *data; +}; + +struct rtp_packet_info test_rtp_packets1[] = { + /* RTP: SeqNo=0, TS=0 */ + {0.000000, 20, "\x80\x62\x00\x00\x00\x00\x00\x00\x11\x22\x33\x44" + "\x01\x23\x45\x67\x89\xAB\xCD\xEF"}, + /* RTP: SeqNo=1, TS=160 */ + {0.020000, 20, "\x80\x62\x00\x01\x00\x00\x00\xA0\x11\x22\x33\x44" + "\x01\x23\x45\x67\x89\xAB\xCD\xEF"}, + /* RTP: SeqNo=2, TS=320 */ + {0.040000, 20, "\x80\x62\x00\x02\x00\x00\x01\x40\x11\x22\x33\x44" + "\x01\x23\x45\x67\x89\xAB\xCD\xEF"}, + /* Repeat RTP timestamp: */ + /* RTP: SeqNo=3, TS=320 */ + {0.060000, 20, "\x80\x62\x00\x03\x00\x00\x01\x40\x11\x22\x33\x44" + "\x01\x23\x45\x67\x89\xAB\xCD\xEF"}, + /* RTP: SeqNo=4, TS=480 */ + {0.080000, 20, "\x80\x62\x00\x04\x00\x00\x01\xE0\x11\x22\x33\x44" + "\x01\x23\x45\x67\x89\xAB\xCD\xEF"}, + /* RTP: SeqNo=5, TS=640 */ + {0.100000, 20, "\x80\x62\x00\x05\x00\x00\x02\x80\x11\x22\x33\x44" + "\x01\x23\x45\x67\x89\xAB\xCD\xEF"}, + /* Double skip RTP timestamp (delta = 2*160): */ + /* RTP: SeqNo=6, TS=960 */ + {0.120000, 20, "\x80\x62\x00\x06\x00\x00\x03\xC0\x11\x22\x33\x44" + "\x01\x23\x45\x67\x89\xAB\xCD\xEF"}, + /* RTP: SeqNo=7, TS=1120 */ + {0.140000, 20, "\x80\x62\x00\x07\x00\x00\x04\x60\x11\x22\x33\x44" + "\x01\x23\x45\x67\x89\xAB\xCD\xEF"}, + /* RTP: SeqNo=8, TS=1280 */ + {0.160000, 20, "\x80\x62\x00\x08\x00\x00\x05\x00\x11\x22\x33\x44" + "\x01\x23\x45\x67\x89\xAB\xCD\xEF"}, + /* Non 20ms RTP timestamp (delta = 120): */ + /* RTP: SeqNo=9, TS=1400 */ + {0.180000, 20, "\x80\x62\x00\x09\x00\x00\x05\x78\x11\x22\x33\x44" + "\x01\x23\x45\x67\x89\xAB\xCD\xEF"}, + /* RTP: SeqNo=10, TS=1560 */ + {0.200000, 20, "\x80\x62\x00\x0A\x00\x00\x06\x18\x11\x22\x33\x44" + "\x01\x23\x45\x67\x89\xAB\xCD\xEF"}, + /* RTP: SeqNo=11, TS=1720 */ + {0.220000, 20, "\x80\x62\x00\x0B\x00\x00\x06\xB8\x11\x22\x33\x44" + "\x01\x23\x45\x67\x89\xAB\xCD\xEF"}, + /* SSRC changed to 0x10203040, RTP timestamp jump */ + /* RTP: SeqNo=12, TS=34688 */ + {0.240000, 20, "\x80\x62\x00\x0C\x00\x00\x87\x80\x10\x20\x30\x40" + "\x01\x23\x45\x67\x89\xAB\xCD\xEF"}, + /* RTP: SeqNo=13, TS=34848 */ + {0.260000, 20, "\x80\x62\x00\x0D\x00\x00\x88\x20\x10\x20\x30\x40" + "\x01\x23\x45\x67\x89\xAB\xCD\xEF"}, + /* RTP: SeqNo=14, TS=35008 */ + {0.280000, 20, "\x80\x62\x00\x0E\x00\x00\x88\xC0\x10\x20\x30\x40" + "\x01\x23\x45\x67\x89\xAB\xCD\xEF"}, + /* Non 20ms RTP timestamp (delta = 120): */ + /* RTP: SeqNo=15, TS=35128 */ + {0.300000, 20, "\x80\x62\x00\x0F\x00\x00\x89\x38\x10\x20\x30\x40" + "\x01\x23\x45\x67\x89\xAB\xCD\xEF"}, + /* RTP: SeqNo=16, TS=35288 */ + {0.320000, 20, "\x80\x62\x00\x10\x00\x00\x89\xD8\x10\x20\x30\x40" + "\x01\x23\x45\x67\x89\xAB\xCD\xEF"}, + /* RTP: SeqNo=17, TS=35448 */ + {0.340000, 20, "\x80\x62\x00\x11\x00\x00\x8A\x78\x10\x20\x30\x40" + "\x01\x23\x45\x67\x8A\xAB\xCD\xEF"}, + /* SeqNo increment by 2, RTP timestamp delta = 320: */ + /* RTP: SeqNo=19, TS=35768 */ + {0.360000, 20, "\x80\x62\x00\x13\x00\x00\x8B\xB8\x10\x20\x30\x40" + "\x01\x23\x45\x67\x89\xAB\xCD\xEF"}, + /* RTP: SeqNo=20, TS=35928 */ + {0.380000, 20, "\x80\x62\x00\x14\x00\x00\x8C\x58\x10\x20\x30\x40" + "\x01\x23\x45\x67\x89\xAB\xCD\xEF"}, + /* RTP: SeqNo=21, TS=36088 */ + {0.380000, 20, "\x80\x62\x00\x15\x00\x00\x8C\xF8\x10\x20\x30\x40" + "\x01\x23\x45\x67\x89\xAB\xCD\xEF"}, + /* Repeat last packet */ + /* RTP: SeqNo=21, TS=36088 */ + {0.400000, 20, "\x80\x62\x00\x15\x00\x00\x8C\xF8\x10\x20\x30\x40" + "\x01\x23\x45\x67\x89\xAB\xCD\xEF"}, + /* RTP: SeqNo=22, TS=36248 */ + {0.420000, 20, "\x80\x62\x00\x16\x00\x00\x8D\x98\x10\x20\x30\x40" + "\x01\x23\x45\x67\x89\xAB\xCD\xEF"}, + /* RTP: SeqNo=23, TS=36408 */ + {0.440000, 20, "\x80\x62\x00\x17\x00\x00\x8E\x38\x10\x20\x30\x40" + "\x01\x23\x45\x67\x89\xAB\xCD\xEF"}, + /* Don't increment SeqNo but increment timestamp by 160 */ + /* RTP: SeqNo=23, TS=36568 */ + {0.460000, 20, "\x80\x62\x00\x17\x00\x00\x8E\xD8\x10\x20\x30\x40" + "\x01\x23\x45\x67\x89\xAB\xCD\xEF"}, + /* RTP: SeqNo=24, TS=36728 */ + {0.480000, 20, "\x80\x62\x00\x18\x00\x00\x8F\x78\x10\x20\x30\x40" + "\x01\x23\x45\x67\x89\xAB\xCD\xEF"}, + /* RTP: SeqNo=25, TS=36888 */ + {0.500000, 20, "\x80\x62\x00\x19\x00\x00\x90\x18\x10\x20\x30\x40" + "\x01\x23\x45\x67\x89\xAB\xCD\xEF"}, + /* SSRC changed to 0x50607080, RTP timestamp jump, Delay of 1.5s, + * SeqNo jump */ + /* RTP: SeqNo=1000, TS=160000 */ + {2.000000, 20, "\x80\x62\x03\xE8\x00\x02\x71\x00\x50\x60\x70\x80" + "\x01\x23\x45\x67\x89\xAB\xCD\xEF"}, + /* RTP: SeqNo=1001, TS=160160 */ + {2.020000, 20, "\x80\x62\x03\xE9\x00\x02\x71\xA0\x50\x60\x70\x80" + "\x01\x23\x45\x67\x89\xAB\xCD\xEF"}, + /* RTP: SeqNo=1002, TS=160320 */ + {2.040000, 20, "\x80\x62\x03\xEA\x00\x02\x72\x40\x50\x60\x70\x80" + "\x01\x23\x45\x67\x89\xAB\xCD\xEF"}, +}; + +void mgcp_patch_and_count(struct mgcp_endpoint *endp, + struct mgcp_rtp_state *state, + struct mgcp_rtp_end *rtp_end, + struct sockaddr_in *addr, char *data, int len); + +static void test_packet_error_detection(int patch_ssrc, int patch_ts) +{ + int i; + + struct mgcp_trunk_config trunk; + struct mgcp_endpoint endp; + struct mgcp_rtp_state state; + struct mgcp_rtp_end *rtp; + struct sockaddr_in addr = { 0 }; + char buffer[4096]; + uint32_t last_ssrc = 0; + uint32_t last_timestamp = 0; + uint32_t last_seqno = 0; + int last_in_ts_err_cnt = 0; + int last_out_ts_err_cnt = 0; + struct mgcp_conn_rtp *conn = NULL; + + printf("Testing packet error detection%s%s.\n", + patch_ssrc ? ", patch SSRC" : "", + patch_ts ? ", patch timestamps" : ""); + + memset(&trunk, 0, sizeof(trunk)); + memset(&endp, 0, sizeof(endp)); + memset(&state, 0, sizeof(state)); + + endp.type = &ep_typeset.rtp; + + trunk.number_endpoints = 1; + trunk.endpoints = &endp; + trunk.force_constant_ssrc = patch_ssrc; + trunk.force_aligned_timing = patch_ts; + + endp.tcfg = &trunk; + + INIT_LLIST_HEAD(&endp.conns); + mgcp_conn_alloc(NULL, &endp, 4711, MGCP_CONN_TYPE_RTP, + "test-connection"); + conn = mgcp_conn_get_rtp(&endp, 4711); + OSMO_ASSERT(conn); + + rtp = &conn->end; + + rtp->codec.payload_type = 98; + + for (i = 0; i < ARRAY_SIZE(test_rtp_packets1); ++i) { + struct rtp_packet_info *info = test_rtp_packets1 + i; + + force_monotonic_time_us = round(1000000.0 * info->txtime); + + OSMO_ASSERT(info->len <= sizeof(buffer)); + OSMO_ASSERT(info->len >= 0); + memmove(buffer, info->data, info->len); + mgcp_rtp_end_config(&endp, 1, rtp); + + mgcp_patch_and_count(&endp, &state, rtp, &addr, + buffer, info->len); + + if (state.out_stream.ssrc != last_ssrc) { + printf("Output SSRC changed to %08x\n", + state.out_stream.ssrc); + last_ssrc = state.out_stream.ssrc; + } + + printf("In TS: %d, dTS: %d, Seq: %d\n", + state.in_stream.last_timestamp, + state.in_stream.last_tsdelta, state.in_stream.last_seq); + + printf("Out TS change: %d, dTS: %d, Seq change: %d, " + "TS Err change: in %+d, out %+d\n", + state.out_stream.last_timestamp - last_timestamp, + state.out_stream.last_tsdelta, + state.out_stream.last_seq - last_seqno, + state.in_stream.err_ts_counter - last_in_ts_err_cnt, + state.out_stream.err_ts_counter - last_out_ts_err_cnt); + + printf("Stats: Jitter = %u, Transit = %d\n", + calc_jitter(&state), state.stats_transit); + + last_in_ts_err_cnt = state.in_stream.err_ts_counter; + last_out_ts_err_cnt = state.out_stream.err_ts_counter; + last_timestamp = state.out_stream.last_timestamp; + last_seqno = state.out_stream.last_seq; + } + + force_monotonic_time_us = -1; +} + +static void test_multilple_codec(void) +{ + struct mgcp_config *cfg; + struct mgcp_endpoint *endp; + struct msgb *inp, *resp; + struct in_addr addr; + struct mgcp_conn_rtp *conn = NULL; + + printf("Testing multiple payload types\n"); + + cfg = mgcp_config_alloc(); + cfg->trunk.number_endpoints = 64; + mgcp_endpoints_allocate(&cfg->trunk); + cfg->policy_cb = mgcp_test_policy_cb; + mgcp_endpoints_allocate(mgcp_trunk_alloc(cfg, 1)); + + /* Allocate endpoint 1@mgw with two codecs */ + last_endpoint = -1; + inp = create_msg(CRCX_MULT_1); + resp = mgcp_handle_message(cfg, inp); + msgb_free(inp); + msgb_free(resp); + + OSMO_ASSERT(last_endpoint == 1); + endp = &cfg->trunk.endpoints[last_endpoint]; + conn = mgcp_conn_get_rtp(endp, 4711); + OSMO_ASSERT(conn); + OSMO_ASSERT(conn->end.codec.payload_type == 18); + OSMO_ASSERT(conn->end.alt_codec.payload_type == 97); + + /* Allocate 2@mgw with three codecs, last one ignored */ + last_endpoint = -1; + inp = create_msg(CRCX_MULT_2); + resp = mgcp_handle_message(cfg, inp); + msgb_free(inp); + msgb_free(resp); + + OSMO_ASSERT(last_endpoint == 2); + endp = &cfg->trunk.endpoints[last_endpoint]; + conn = mgcp_conn_get_rtp(endp, 90210); + OSMO_ASSERT(conn); + OSMO_ASSERT(conn->end.codec.payload_type == 18); + OSMO_ASSERT(conn->end.alt_codec.payload_type == 97); + + /* Allocate 3@mgw with no codecs, check for PT == -1 */ + last_endpoint = -1; + inp = create_msg(CRCX_MULT_3); + resp = mgcp_handle_message(cfg, inp); + msgb_free(inp); + msgb_free(resp); + + OSMO_ASSERT(last_endpoint == 3); + endp = &cfg->trunk.endpoints[last_endpoint]; + conn = mgcp_conn_get_rtp(endp, 815); + OSMO_ASSERT(conn); + OSMO_ASSERT(conn->end.codec.payload_type == -1); + OSMO_ASSERT(conn->end.alt_codec.payload_type == -1); + + /* Allocate 4@mgw with a single codec */ + last_endpoint = -1; + inp = create_msg(CRCX_MULT_4); + resp = mgcp_handle_message(cfg, inp); + msgb_free(inp); + msgb_free(resp); + + OSMO_ASSERT(last_endpoint == 4); + endp = &cfg->trunk.endpoints[last_endpoint]; + conn = mgcp_conn_get_rtp(endp, 32168); + OSMO_ASSERT(conn); + OSMO_ASSERT(conn->end.codec.payload_type == 18); + OSMO_ASSERT(conn->end.alt_codec.payload_type == -1); + + /* Allocate 5@mgw at select GSM.. */ + last_endpoint = -1; + inp = create_msg(CRCX_MULT_GSM_EXACT); + talloc_free(cfg->trunk.audio_name); + cfg->trunk.audio_name = "GSM/8000"; + cfg->trunk.no_audio_transcoding = 1; + resp = mgcp_handle_message(cfg, inp); + msgb_free(inp); + msgb_free(resp); + + OSMO_ASSERT(last_endpoint == 5); + endp = &cfg->trunk.endpoints[last_endpoint]; + conn = mgcp_conn_get_rtp(endp, 3); + OSMO_ASSERT(conn); + OSMO_ASSERT(conn->end.codec.payload_type == 3); + OSMO_ASSERT(conn->end.alt_codec.payload_type == -1); + + inp = create_msg(MDCX_NAT_DUMMY); + last_endpoint = -1; + resp = mgcp_handle_message(cfg, inp); + msgb_free(inp); + msgb_free(resp); + OSMO_ASSERT(last_endpoint == 5); + endp = &cfg->trunk.endpoints[last_endpoint]; + conn = mgcp_conn_get_rtp(endp, 3); + OSMO_ASSERT(conn); + OSMO_ASSERT(conn->end.codec.payload_type == 3); + OSMO_ASSERT(conn->end.alt_codec.payload_type == -1); + OSMO_ASSERT(conn->end.rtp_port == htons(16434)); + memset(&addr, 0, sizeof(addr)); + inet_aton("8.8.8.8", &addr); + OSMO_ASSERT(conn->end.addr.s_addr == addr.s_addr); + + /* Check what happens without that flag */ + + /* Free the previous endpoint and the data and + * check if the connection really vanished... */ + mgcp_release_endp(endp); + talloc_free(endp->last_response); + talloc_free(endp->last_trans); + endp->last_response = endp->last_trans = NULL; + conn = mgcp_conn_get_rtp(endp, 3); + OSMO_ASSERT(!conn); + + last_endpoint = -1; + inp = create_msg(CRCX_MULT_GSM_EXACT); + cfg->trunk.no_audio_transcoding = 0; + resp = mgcp_handle_message(cfg, inp); + msgb_free(inp); + msgb_free(resp); + + OSMO_ASSERT(last_endpoint == 5); + endp = &cfg->trunk.endpoints[last_endpoint]; + conn = mgcp_conn_get_rtp(endp, 3); + OSMO_ASSERT(conn); + OSMO_ASSERT(conn->end.codec.payload_type == 255); + OSMO_ASSERT(conn->end.alt_codec.payload_type == 0); + + talloc_free(cfg); +} + +static void test_no_cycle(void) +{ + struct mgcp_config *cfg; + struct mgcp_endpoint *endp; + struct mgcp_conn_rtp *conn = NULL; + + printf("Testing no sequence flow on initial packet\n"); + + cfg = mgcp_config_alloc(); + cfg->trunk.number_endpoints = 64; + mgcp_endpoints_allocate(&cfg->trunk); + + endp = &cfg->trunk.endpoints[1]; + + mgcp_conn_alloc(NULL, endp, 4711, MGCP_CONN_TYPE_RTP, + "test-connection"); + conn = mgcp_conn_get_rtp(endp, 4711); + OSMO_ASSERT(conn); + + OSMO_ASSERT(conn->state.stats_initialized == 0); + + mgcp_rtp_annex_count(endp, &conn->state, 0, 0, 2342); + OSMO_ASSERT(conn->state.stats_initialized == 1); + OSMO_ASSERT(conn->state.stats_cycles == 0); + OSMO_ASSERT(conn->state.stats_max_seq == 0); + + mgcp_rtp_annex_count(endp, &conn->state, 1, 0, 2342); + OSMO_ASSERT(conn->state.stats_initialized == 1); + OSMO_ASSERT(conn->state.stats_cycles == 0); + OSMO_ASSERT(conn->state.stats_max_seq == 1); + + /* now jump.. */ + mgcp_rtp_annex_count(endp, &conn->state, UINT16_MAX, 0, 2342); + OSMO_ASSERT(conn->state.stats_initialized == 1); + OSMO_ASSERT(conn->state.stats_cycles == 0); + OSMO_ASSERT(conn->state.stats_max_seq == UINT16_MAX); + + /* and wrap */ + mgcp_rtp_annex_count(endp, &conn->state, 0, 0, 2342); + OSMO_ASSERT(conn->state.stats_initialized == 1); + OSMO_ASSERT(conn->state.stats_cycles == UINT16_MAX + 1); + OSMO_ASSERT(conn->state.stats_max_seq == 0); + + talloc_free(cfg); +} + +static void test_no_name(void) +{ + struct mgcp_config *cfg; + struct msgb *inp, *msg; + + printf("Testing no rtpmap name\n"); + cfg = mgcp_config_alloc(); + + cfg->trunk.number_endpoints = 64; + cfg->trunk.audio_send_name = 0; + mgcp_endpoints_allocate(&cfg->trunk); + + cfg->policy_cb = mgcp_test_policy_cb; + + mgcp_endpoints_allocate(mgcp_trunk_alloc(cfg, 1)); + + inp = create_msg(CRCX); + msg = mgcp_handle_message(cfg, inp); + if (strcmp((char *)msg->data, CRCX_RET_NO_RTPMAP) != 0) { + printf("FAILED: there should not be a RTPMAP: %s\n", + (char *)msg->data); + OSMO_ASSERT(false); + } + msgb_free(inp); + msgb_free(msg); + + mgcp_release_endp(&cfg->trunk.endpoints[1]); + talloc_free(cfg); +} + +static void test_osmux_cid(void) +{ + int id, i; + + OSMO_ASSERT(osmux_used_cid() == 0); + id = osmux_get_cid(); + OSMO_ASSERT(id == 0); + OSMO_ASSERT(osmux_used_cid() == 1); + osmux_put_cid(id); + OSMO_ASSERT(osmux_used_cid() == 0); + + for (i = 0; i < 256; ++i) { + id = osmux_get_cid(); + OSMO_ASSERT(id == i); + OSMO_ASSERT(osmux_used_cid() == i + 1); + } + + id = osmux_get_cid(); + OSMO_ASSERT(id == -1); + + for (i = 0; i < 256; ++i) + osmux_put_cid(i); + OSMO_ASSERT(osmux_used_cid() == 0); +} + +static const struct log_info_cat log_categories[] = { +}; + +const struct log_info log_info = { + .cat = log_categories, + .num_cat = ARRAY_SIZE(log_categories), +}; + +int main(int argc, char **argv) +{ + msgb_talloc_ctx_init(NULL, 0); + osmo_init_logging(&log_info); + + test_strline(); + test_values(); + test_messages(); + test_retransmission(); + test_packet_loss_calc(); + test_rqnt_cb(); + test_mgcp_stats(); + test_packet_error_detection(1, 0); + test_packet_error_detection(0, 0); + test_packet_error_detection(0, 1); + test_packet_error_detection(1, 1); + test_multilple_codec(); + test_no_cycle(); + test_no_name(); + test_osmux_cid(); + + printf("Done\n"); + return EXIT_SUCCESS; +} diff --git a/tests/mgcp/mgcp_test.ok b/tests/mgcp/mgcp_test.ok new file mode 100644 index 0000000..7376930 --- /dev/null +++ b/tests/mgcp/mgcp_test.ok @@ -0,0 +1,471 @@ +line: 'one CR' +line: 'two CR' +line: '' +line: 'one CRLF' +line: 'two CRLF' +line: '' +line: 'one LF' +line: 'two LF' +line: '' +line: 'mixed (4 lines)' +line: '' +line: '' +line: '' +Testing AUEP1 +Testing AUEP2 +Testing MDCX1 +Testing MDCX2 +Testing CRCX +Dummy packets: 2 +Detected packet duration: 40 +Requested packetetization period: 20-20 +Connection mode: 1: RECV +Testing MDCX3 +Dummy packets: 2 +Detected packet duration: 40 +Requested packetization period not set +Connection mode: 1: RECV +Testing MDCX4 +Dummy packets: 2 +Detected packet duration: 40 +Requested packetetization period: 20-20 +Connection mode: 3: SEND RECV +Testing MDCX4_PT1 +Dummy packets: 2 +Detected packet duration: 40 +Requested packetetization period: 20-40 +Connection mode: 3: SEND RECV +Testing MDCX4_PT2 +Dummy packets: 2 +Detected packet duration: 40 +Requested packetetization period: 20-20 +Connection mode: 3: SEND RECV +Testing MDCX4_PT3 +Dummy packets: 2 +Detected packet duration: 40 +Requested packetization period not set +Connection mode: 3: SEND RECV +Testing MDCX4_SO +Detected packet duration: 40 +Requested packetetization period: 20-20 +Connection mode: 2: SEND +Testing MDCX4_RO +Dummy packets: 2 +Detected packet duration: 40 +Requested packetetization period: 20-20 +Connection mode: 1: RECV +Testing DLCX +Testing CRCX_ZYN +Dummy packets: 2 +Detected packet duration: 20 +Requested packetization period not set +Connection mode: 1: RECV +Testing EMPTY +Testing SHORT1 +Testing SHORT2 +Testing SHORT3 +Testing SHORT4 +Testing RQNT1 +Testing RQNT2 +Testing DLCX +Testing CRCX +Dummy packets: 2 +Detected packet duration: 40 +Requested packetetization period: 20-20 +Connection mode: 1: RECV +Testing MDCX3 +Dummy packets: 2 +Detected packet duration: 40 +Requested packetization period not set +Connection mode: 1: RECV +Testing DLCX +Testing CRCX +Re-transmitting CRCX +Testing RQNT1 +Re-transmitting RQNT1 +Testing RQNT2 +Re-transmitting RQNT2 +Testing MDCX3 +Re-transmitting MDCX3 +Testing DLCX +Re-transmitting DLCX +Testing packet loss calculation. +Testing stat parsing +Parsing result: 0 +Parsing result: 0 +Testing packet error detection, patch SSRC. +Output SSRC changed to 11223344 +In TS: 0, dTS: 0, Seq: 0 +Out TS change: 0, dTS: 0, Seq change: 0, TS Err change: in +0, out +0 +Stats: Jitter = 0, Transit = 0 +In TS: 160, dTS: 160, Seq: 1 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 0, Transit = 0 +In TS: 320, dTS: 160, Seq: 2 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 0, Transit = 0 +In TS: 320, dTS: 160, Seq: 3 +Out TS change: 0, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 10, Transit = 160 +In TS: 480, dTS: 160, Seq: 4 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 9, Transit = 160 +In TS: 640, dTS: 160, Seq: 5 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 8, Transit = 160 +In TS: 960, dTS: 320, Seq: 6 +Out TS change: 320, dTS: 320, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 18, Transit = 0 +In TS: 1120, dTS: 160, Seq: 7 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 17, Transit = 0 +In TS: 1280, dTS: 160, Seq: 8 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 16, Transit = 0 +In TS: 1400, dTS: 120, Seq: 9 +Out TS change: 120, dTS: 120, Seq change: 1, TS Err change: in +1, out +1 +Stats: Jitter = 17, Transit = 40 +In TS: 1560, dTS: 160, Seq: 10 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 16, Transit = 40 +In TS: 1720, dTS: 160, Seq: 11 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 15, Transit = 40 +In TS: 34688, dTS: 0, Seq: 12 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 0, Transit = -32768 +In TS: 34848, dTS: 160, Seq: 13 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 0, Transit = -32768 +In TS: 35008, dTS: 160, Seq: 14 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 0, Transit = -32768 +In TS: 35128, dTS: 120, Seq: 15 +Out TS change: 120, dTS: 120, Seq change: 1, TS Err change: in +1, out +1 +Stats: Jitter = 2, Transit = -32728 +In TS: 35288, dTS: 160, Seq: 16 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 2, Transit = -32728 +In TS: 35448, dTS: 160, Seq: 17 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 2, Transit = -32728 +In TS: 35768, dTS: 160, Seq: 19 +Out TS change: 320, dTS: 160, Seq change: 2, TS Err change: in +0, out +0 +Stats: Jitter = 12, Transit = -32888 +In TS: 35928, dTS: 160, Seq: 20 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 11, Transit = -32888 +In TS: 36088, dTS: 160, Seq: 21 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 20, Transit = -33048 +In TS: 36088, dTS: 160, Seq: 21 +Out TS change: 0, dTS: 160, Seq change: 0, TS Err change: in +0, out +0 +Stats: Jitter = 29, Transit = -32888 +In TS: 36248, dTS: 160, Seq: 22 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 27, Transit = -32888 +In TS: 36408, dTS: 160, Seq: 23 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 25, Transit = -32888 +In TS: 36568, dTS: 160, Seq: 23 +Out TS change: 160, dTS: 160, Seq change: 0, TS Err change: in +1, out +1 +Stats: Jitter = 24, Transit = -32888 +In TS: 36728, dTS: 160, Seq: 24 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 22, Transit = -32888 +In TS: 36888, dTS: 160, Seq: 25 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 21, Transit = -32888 +In TS: 160000, dTS: 0, Seq: 1000 +Out TS change: 12000, dTS: 12000, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 0, Transit = -144000 +In TS: 160160, dTS: 160, Seq: 1001 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 0, Transit = -144000 +In TS: 160320, dTS: 160, Seq: 1002 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 0, Transit = -144000 +Testing packet error detection. +Output SSRC changed to 11223344 +In TS: 0, dTS: 0, Seq: 0 +Out TS change: 0, dTS: 0, Seq change: 0, TS Err change: in +0, out +0 +Stats: Jitter = 0, Transit = 0 +In TS: 160, dTS: 160, Seq: 1 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 0, Transit = 0 +In TS: 320, dTS: 160, Seq: 2 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 0, Transit = 0 +In TS: 320, dTS: 160, Seq: 3 +Out TS change: 0, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 10, Transit = 160 +In TS: 480, dTS: 160, Seq: 4 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 9, Transit = 160 +In TS: 640, dTS: 160, Seq: 5 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 8, Transit = 160 +In TS: 960, dTS: 320, Seq: 6 +Out TS change: 320, dTS: 320, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 18, Transit = 0 +In TS: 1120, dTS: 160, Seq: 7 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 17, Transit = 0 +In TS: 1280, dTS: 160, Seq: 8 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 16, Transit = 0 +In TS: 1400, dTS: 120, Seq: 9 +Out TS change: 120, dTS: 120, Seq change: 1, TS Err change: in +1, out +1 +Stats: Jitter = 17, Transit = 40 +In TS: 1560, dTS: 160, Seq: 10 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 16, Transit = 40 +In TS: 1720, dTS: 160, Seq: 11 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 15, Transit = 40 +Output SSRC changed to 10203040 +In TS: 34688, dTS: 0, Seq: 12 +Out TS change: 32968, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 0, Transit = -32768 +In TS: 34848, dTS: 160, Seq: 13 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 0, Transit = -32768 +In TS: 35008, dTS: 160, Seq: 14 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 0, Transit = -32768 +In TS: 35128, dTS: 120, Seq: 15 +Out TS change: 120, dTS: 120, Seq change: 1, TS Err change: in +1, out +1 +Stats: Jitter = 2, Transit = -32728 +In TS: 35288, dTS: 160, Seq: 16 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 2, Transit = -32728 +In TS: 35448, dTS: 160, Seq: 17 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 2, Transit = -32728 +In TS: 35768, dTS: 160, Seq: 19 +Out TS change: 320, dTS: 160, Seq change: 2, TS Err change: in +0, out +0 +Stats: Jitter = 12, Transit = -32888 +In TS: 35928, dTS: 160, Seq: 20 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 11, Transit = -32888 +In TS: 36088, dTS: 160, Seq: 21 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 20, Transit = -33048 +In TS: 36088, dTS: 160, Seq: 21 +Out TS change: 0, dTS: 160, Seq change: 0, TS Err change: in +0, out +0 +Stats: Jitter = 29, Transit = -32888 +In TS: 36248, dTS: 160, Seq: 22 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 27, Transit = -32888 +In TS: 36408, dTS: 160, Seq: 23 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 25, Transit = -32888 +In TS: 36568, dTS: 160, Seq: 23 +Out TS change: 160, dTS: 160, Seq change: 0, TS Err change: in +1, out +1 +Stats: Jitter = 24, Transit = -32888 +In TS: 36728, dTS: 160, Seq: 24 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 22, Transit = -32888 +In TS: 36888, dTS: 160, Seq: 25 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 21, Transit = -32888 +Output SSRC changed to 50607080 +In TS: 160000, dTS: 0, Seq: 1000 +Out TS change: 123112, dTS: 160, Seq change: 975, TS Err change: in +0, out +0 +Stats: Jitter = 0, Transit = -144000 +In TS: 160160, dTS: 160, Seq: 1001 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 0, Transit = -144000 +In TS: 160320, dTS: 160, Seq: 1002 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 0, Transit = -144000 +Testing packet error detection, patch timestamps. +Output SSRC changed to 11223344 +In TS: 0, dTS: 0, Seq: 0 +Out TS change: 0, dTS: 0, Seq change: 0, TS Err change: in +0, out +0 +Stats: Jitter = 0, Transit = 0 +In TS: 160, dTS: 160, Seq: 1 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 0, Transit = 0 +In TS: 320, dTS: 160, Seq: 2 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 0, Transit = 0 +In TS: 320, dTS: 160, Seq: 3 +Out TS change: 0, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 10, Transit = 160 +In TS: 480, dTS: 160, Seq: 4 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 9, Transit = 160 +In TS: 640, dTS: 160, Seq: 5 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 8, Transit = 160 +In TS: 960, dTS: 320, Seq: 6 +Out TS change: 320, dTS: 320, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 18, Transit = 0 +In TS: 1120, dTS: 160, Seq: 7 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 17, Transit = 0 +In TS: 1280, dTS: 160, Seq: 8 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 16, Transit = 0 +In TS: 1400, dTS: 120, Seq: 9 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +1, out +0 +Stats: Jitter = 17, Transit = 40 +In TS: 1560, dTS: 160, Seq: 10 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 16, Transit = 40 +In TS: 1720, dTS: 160, Seq: 11 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 15, Transit = 40 +Output SSRC changed to 10203040 +In TS: 34688, dTS: 0, Seq: 12 +Out TS change: 32968, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 0, Transit = -32768 +In TS: 34848, dTS: 160, Seq: 13 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 0, Transit = -32768 +In TS: 35008, dTS: 160, Seq: 14 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 0, Transit = -32768 +In TS: 35128, dTS: 120, Seq: 15 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +1, out +0 +Stats: Jitter = 2, Transit = -32728 +In TS: 35288, dTS: 160, Seq: 16 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 2, Transit = -32728 +In TS: 35448, dTS: 160, Seq: 17 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 2, Transit = -32728 +In TS: 35768, dTS: 160, Seq: 19 +Out TS change: 320, dTS: 160, Seq change: 2, TS Err change: in +0, out +0 +Stats: Jitter = 12, Transit = -32888 +In TS: 35928, dTS: 160, Seq: 20 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 11, Transit = -32888 +In TS: 36088, dTS: 160, Seq: 21 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 20, Transit = -33048 +In TS: 36088, dTS: 160, Seq: 21 +Out TS change: 0, dTS: 160, Seq change: 0, TS Err change: in +0, out +0 +Stats: Jitter = 29, Transit = -32888 +In TS: 36248, dTS: 160, Seq: 22 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 27, Transit = -32888 +In TS: 36408, dTS: 160, Seq: 23 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 25, Transit = -32888 +In TS: 36568, dTS: 160, Seq: 23 +Out TS change: 160, dTS: 160, Seq change: 0, TS Err change: in +1, out +1 +Stats: Jitter = 24, Transit = -32888 +In TS: 36728, dTS: 160, Seq: 24 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 22, Transit = -32888 +In TS: 36888, dTS: 160, Seq: 25 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 21, Transit = -32888 +Output SSRC changed to 50607080 +In TS: 160000, dTS: 0, Seq: 1000 +Out TS change: 123112, dTS: 160, Seq change: 975, TS Err change: in +0, out +0 +Stats: Jitter = 0, Transit = -144000 +In TS: 160160, dTS: 160, Seq: 1001 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 0, Transit = -144000 +In TS: 160320, dTS: 160, Seq: 1002 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 0, Transit = -144000 +Testing packet error detection, patch SSRC, patch timestamps. +Output SSRC changed to 11223344 +In TS: 0, dTS: 0, Seq: 0 +Out TS change: 0, dTS: 0, Seq change: 0, TS Err change: in +0, out +0 +Stats: Jitter = 0, Transit = 0 +In TS: 160, dTS: 160, Seq: 1 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 0, Transit = 0 +In TS: 320, dTS: 160, Seq: 2 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 0, Transit = 0 +In TS: 320, dTS: 160, Seq: 3 +Out TS change: 0, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 10, Transit = 160 +In TS: 480, dTS: 160, Seq: 4 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 9, Transit = 160 +In TS: 640, dTS: 160, Seq: 5 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 8, Transit = 160 +In TS: 960, dTS: 320, Seq: 6 +Out TS change: 320, dTS: 320, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 18, Transit = 0 +In TS: 1120, dTS: 160, Seq: 7 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 17, Transit = 0 +In TS: 1280, dTS: 160, Seq: 8 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 16, Transit = 0 +In TS: 1400, dTS: 120, Seq: 9 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +1, out +0 +Stats: Jitter = 17, Transit = 40 +In TS: 1560, dTS: 160, Seq: 10 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 16, Transit = 40 +In TS: 1720, dTS: 160, Seq: 11 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 15, Transit = 40 +In TS: 34688, dTS: 0, Seq: 12 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 0, Transit = -32768 +In TS: 34848, dTS: 160, Seq: 13 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 0, Transit = -32768 +In TS: 35008, dTS: 160, Seq: 14 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 0, Transit = -32768 +In TS: 35128, dTS: 120, Seq: 15 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +1, out +0 +Stats: Jitter = 2, Transit = -32728 +In TS: 35288, dTS: 160, Seq: 16 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 2, Transit = -32728 +In TS: 35448, dTS: 160, Seq: 17 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 2, Transit = -32728 +In TS: 35768, dTS: 160, Seq: 19 +Out TS change: 320, dTS: 160, Seq change: 2, TS Err change: in +0, out +0 +Stats: Jitter = 12, Transit = -32888 +In TS: 35928, dTS: 160, Seq: 20 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 11, Transit = -32888 +In TS: 36088, dTS: 160, Seq: 21 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 20, Transit = -33048 +In TS: 36088, dTS: 160, Seq: 21 +Out TS change: 0, dTS: 160, Seq change: 0, TS Err change: in +0, out +0 +Stats: Jitter = 29, Transit = -32888 +In TS: 36248, dTS: 160, Seq: 22 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 27, Transit = -32888 +In TS: 36408, dTS: 160, Seq: 23 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 25, Transit = -32888 +In TS: 36568, dTS: 160, Seq: 23 +Out TS change: 160, dTS: 160, Seq change: 0, TS Err change: in +1, out +1 +Stats: Jitter = 24, Transit = -32888 +In TS: 36728, dTS: 160, Seq: 24 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 22, Transit = -32888 +In TS: 36888, dTS: 160, Seq: 25 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 21, Transit = -32888 +In TS: 160000, dTS: 0, Seq: 1000 +Out TS change: 12000, dTS: 12000, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 0, Transit = -144000 +In TS: 160160, dTS: 160, Seq: 1001 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 0, Transit = -144000 +In TS: 160320, dTS: 160, Seq: 1002 +Out TS change: 160, dTS: 160, Seq change: 1, TS Err change: in +0, out +0 +Stats: Jitter = 0, Transit = -144000 +Testing multiple payload types +Testing no sequence flow on initial packet +Testing no rtpmap name +Done diff --git a/tests/mgcp_client/Makefile.am b/tests/mgcp_client/Makefile.am new file mode 100644 index 0000000..5cd0d8a --- /dev/null +++ b/tests/mgcp_client/Makefile.am @@ -0,0 +1,39 @@ +AM_CPPFLAGS = \ + $(all_includes) \ + -I$(top_srcdir)/include \ + -I$(top_builddir)/include \ + -I$(top_srcdir) \ + $(NULL) + +AM_CFLAGS = \ + -Wall \ + -ggdb3 \ + $(LIBOSMOCORE_CFLAGS) \ + $(LIBOSMONETIF_CFLAGS) \ + $(COVERAGE_CFLAGS) \ + $(NULL) + +AM_LDFLAGS = \ + $(COVERAGE_LDFLAGS) \ + $(NULL) + +EXTRA_DIST = \ + mgcp_client_test.ok \ + mgcp_client_test.err \ + $(NULL) + +noinst_PROGRAMS = \ + mgcp_client_test \ + $(NULL) + +mgcp_client_test_SOURCES = \ + mgcp_client_test.c \ + $(NULL) + +mgcp_client_test_LDADD = \ + $(top_builddir)/src/libosmo-mgcp-client/libosmo-mgcp-client.la \ + $(LIBOSMOCORE_LIBS) \ + $(LIBOSMOVTY_LIBS) \ + $(LIBRARY_DL) \ + $(LIBOSMONETIF_LIBS) \ + $(NULL) diff --git a/tests/mgcp_client/mgcp_client_test.c b/tests/mgcp_client/mgcp_client_test.c new file mode 100644 index 0000000..513f345 --- /dev/null +++ b/tests/mgcp_client/mgcp_client_test.c @@ -0,0 +1,255 @@ +/* + * (C) 2016 by sysmocom s.f.m.c. GmbH <info@sysmocom.de> + * All Rights Reserved + * + * Author: Neels Hofmeyr + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <string.h> + +#include <osmocom/core/msgb.h> +#include <osmocom/core/application.h> +#include <osmocom/mgcp_client/mgcp_client.h> +#include <osmocom/mgcp_client/mgcp_client_internal.h> + +void *ctx; + +#define buf_len 4096 + +#if 0 +static struct msgb *from_hex(const char *hex) +{ + struct msgb *msg = msgb_alloc(buf_len, "mgcpgw_test_from_hex"); + unsigned int l = osmo_hexparse(hex, msg->data, buf_len); + msg->l2h = msgb_put(msg, l); + return msg; +} + +static struct msgb *mgcp_from_str(const char *head, const char *params) +{ + struct msgb *msg = msgb_alloc(buf_len, "mgcp_from_str"); + unsigned int l; + char *data; + l = strlen(head); + msg->l2h = msgb_put(msg, l); + data = (char*)msgb_l2(msg); + strncpy(data, head, l); + + data = (char*)msgb_put(msg, 1); + *data = '\n'; + + l = strlen(params); + data = (char*)msgb_put(msg, l); + strncpy(data, params, l); + + return msg; +} +#endif + +static struct msgb *from_str(const char *str) +{ + struct msgb *msg = msgb_alloc(buf_len, "from_str"); + unsigned int l = strlen(str); + char *data; + msg->l2h = msgb_put(msg, l); + data = (char*)msgb_l2(msg); + strncpy(data, str, l); + return msg; +} + +static struct mgcp_client_conf conf; +struct mgcp_client *mgcp = NULL; + +static void reply_to(mgcp_trans_id_t trans_id, int code, const char *comment, + int conn_id, const char *params) +{ + static char compose[4096 - 128]; + int len; + + len = snprintf(compose, sizeof(compose), + "%d %u %s\r\nI: %d\n\n%s", + code, trans_id, comment, conn_id, params); + OSMO_ASSERT(len < sizeof(compose)); + OSMO_ASSERT(len > 0); + + printf("composed response:\n-----\n%s\n-----\n", + compose); + mgcp_client_rx(mgcp, from_str(compose)); +} + +void test_response_cb(struct mgcp_response *response, void *priv) +{ + OSMO_ASSERT(priv == mgcp); + mgcp_response_parse_params(response); + + printf("response cb received:\n" + " head.response_code = %d\n" + " head.trans_id = %u\n" + " head.comment = %s\n" + " audio_port = %u\n" + " audio_ip = %s\n", + response->head.response_code, + response->head.trans_id, + response->head.comment, + response->audio_port, + response->audio_ip + ); +} + +mgcp_trans_id_t dummy_mgcp_send(struct msgb *msg) +{ + mgcp_trans_id_t trans_id; + trans_id = msg->cb[MSGB_CB_MGCP_TRANS_ID]; + char *end; + + OSMO_ASSERT(mgcp_client_pending_add(mgcp, trans_id, test_response_cb, mgcp)); + + end = (char*)msgb_put(msg, 1); + *end = '\0'; + printf("composed:\n-----\n%s\n-----\n", + (char*)msgb_l2(msg)); + + talloc_free(msg); + return trans_id; +} + +void test_crcx(void) +{ + struct msgb *msg; + mgcp_trans_id_t trans_id; + + printf("\n===== %s =====\n", __func__); + + if (mgcp) + talloc_free(mgcp); + mgcp = mgcp_client_init(ctx, &conf); + + msg = mgcp_msg_crcx(mgcp, 23, 42, MGCP_CONN_LOOPBACK); + trans_id = dummy_mgcp_send(msg); + + reply_to(trans_id, 200, "OK", 1, + "v=0\r\n" + "o=- 1 23 IN IP4 10.9.1.120\r\n" + "s=-\r\n" + "c=IN IP4 10.9.1.120\r\n" + "t=0 0\r\n" + "m=audio 16002 RTP/AVP 98\r\n" + "a=rtpmap:98 AMR/8000\r\n" + "a=ptime:20\r\n"); +} + +void test_mgcp_msg(void) +{ + struct msgb *msg; + char audio_ip_overflow[5000]; + + /* A message struct prefilled with some arbitary values */ + struct mgcp_msg mgcp_msg = { + .audio_ip = "192.168.100.23", + .endpoint = "23@mgw", + .audio_port = 1234, + .call_id = 47, + .conn_id = 11, + .conn_mode = MGCP_CONN_RECV_SEND + }; + + if (mgcp) + talloc_free(mgcp); + mgcp = mgcp_client_init(ctx, &conf); + + printf("\n"); + + printf("Generated CRCX message:\n"); + mgcp_msg.verb = MGCP_VERB_CRCX; + mgcp_msg.presence = + (MGCP_MSG_PRESENCE_ENDPOINT | MGCP_MSG_PRESENCE_CALL_ID | + MGCP_MSG_PRESENCE_CONN_ID | MGCP_MSG_PRESENCE_CONN_MODE); + msg = mgcp_msg_gen(mgcp, &mgcp_msg); + printf("%s\n", (char *)msg->data); + + printf("Generated MDCX message:\n"); + mgcp_msg.verb = MGCP_VERB_MDCX; + mgcp_msg.presence = + (MGCP_MSG_PRESENCE_ENDPOINT | MGCP_MSG_PRESENCE_CALL_ID | + MGCP_MSG_PRESENCE_CONN_ID | MGCP_MSG_PRESENCE_CONN_MODE | + MGCP_MSG_PRESENCE_AUDIO_IP | MGCP_MSG_PRESENCE_AUDIO_PORT); + msg = mgcp_msg_gen(mgcp, &mgcp_msg); + printf("%s\n", (char *)msg->data); + + printf("Generated DLCX message:\n"); + mgcp_msg.verb = MGCP_VERB_DLCX; + mgcp_msg.presence = + (MGCP_MSG_PRESENCE_ENDPOINT | MGCP_MSG_PRESENCE_CALL_ID | + MGCP_MSG_PRESENCE_CONN_ID); + msg = mgcp_msg_gen(mgcp, &mgcp_msg); + printf("%s\n", (char *)msg->data); + + printf("Generated AUEP message:\n"); + mgcp_msg.verb = MGCP_VERB_AUEP; + mgcp_msg.presence = (MGCP_MSG_PRESENCE_ENDPOINT); + msg = mgcp_msg_gen(mgcp, &mgcp_msg); + printf("%s\n", msg->data); + + printf("Generated RSIP message:\n"); + mgcp_msg.verb = MGCP_VERB_RSIP; + mgcp_msg.presence = (MGCP_MSG_PRESENCE_ENDPOINT); + msg = mgcp_msg_gen(mgcp, &mgcp_msg); + printf("%s\n", (char *)msg->data); + + printf("Overfolow test:\n"); + mgcp_msg.verb = MGCP_VERB_MDCX; + mgcp_msg.presence = + (MGCP_MSG_PRESENCE_ENDPOINT | MGCP_MSG_PRESENCE_CALL_ID | + MGCP_MSG_PRESENCE_CONN_ID | MGCP_MSG_PRESENCE_CONN_MODE | + MGCP_MSG_PRESENCE_AUDIO_IP | MGCP_MSG_PRESENCE_AUDIO_PORT); + memset(audio_ip_overflow, 'X', sizeof(audio_ip_overflow)); + audio_ip_overflow[sizeof(audio_ip_overflow) - 1] = '\0'; + mgcp_msg.audio_ip = audio_ip_overflow; + msg = mgcp_msg_gen(mgcp, &mgcp_msg); + OSMO_ASSERT(msg == NULL); + + printf("\n"); + msgb_free(msg); +} + +static const struct log_info_cat log_categories[] = { +}; + +const struct log_info log_info = { + .cat = log_categories, + .num_cat = ARRAY_SIZE(log_categories), +}; + + +int main(int argc, char **argv) +{ + ctx = talloc_named_const(NULL, 1, "mgcp_client_test"); + msgb_talloc_ctx_init(ctx, 0); + osmo_init_logging(&log_info); + log_set_print_filename(osmo_stderr_target, 0); + log_set_print_timestamp(osmo_stderr_target, 0); + log_set_use_color(osmo_stderr_target, 0); + log_set_print_category(osmo_stderr_target, 1); + + mgcp_client_conf_init(&conf); + + test_crcx(); + test_mgcp_msg(); + + printf("Done\n"); + fprintf(stderr, "Done\n"); + return EXIT_SUCCESS; +} diff --git a/tests/mgcp_client/mgcp_client_test.err b/tests/mgcp_client/mgcp_client_test.err new file mode 100644 index 0000000..24151ee --- /dev/null +++ b/tests/mgcp_client/mgcp_client_test.err @@ -0,0 +1,2 @@ +DLMGCP message buffer to small, can not generate MGCP message +Done diff --git a/tests/mgcp_client/mgcp_client_test.ok b/tests/mgcp_client/mgcp_client_test.ok new file mode 100644 index 0000000..d4efee4 --- /dev/null +++ b/tests/mgcp_client/mgcp_client_test.ok @@ -0,0 +1,62 @@ + +===== test_crcx ===== +composed: +----- +CRCX 1 17@mgw MGCP 1.0
+C: 2a
+L: p:20, a:AMR, nt:IN
+M: loopback
+ +----- +composed response: +----- +200 1 OK
+I: 1 + +v=0
+o=- 1 23 IN IP4 10.9.1.120
+s=-
+c=IN IP4 10.9.1.120
+t=0 0
+m=audio 16002 RTP/AVP 98
+a=rtpmap:98 AMR/8000
+a=ptime:20
+ +----- +response cb received: + head.response_code = 200 + head.trans_id = 1 + head.comment = OK + audio_port = 16002 + audio_ip = 10.9.1.120 + +Generated CRCX message: +CRCX 1 23@mgw MGCP 1.0
+C: 2f
+I: 11
+L: p:20, a:AMR, nt:IN
+M: sendrecv
+ +Generated MDCX message: +MDCX 2 23@mgw MGCP 1.0
+C: 2f
+I: 11
+M: sendrecv
+
+c=IN IP4 192.168.100.23
+m=audio 1234 RTP/AVP 255
+ +Generated DLCX message: +DLCX 3 23@mgw MGCP 1.0
+C: 2f
+I: 11
+ +Generated AUEP message: +AUEP 4 23@mgw MGCP 1.0
+ +Generated RSIP message: +RSIP 5 23@mgw MGCP 1.0
+ +Overfolow test: + +Done diff --git a/tests/testsuite.at b/tests/testsuite.at new file mode 100644 index 0000000..03ec4b9 --- /dev/null +++ b/tests/testsuite.at @@ -0,0 +1,28 @@ +AT_INIT +AT_BANNER([Regression tests.]) + +AT_SETUP([legacy_mgcp]) +AT_KEYWORDS([legacy_mgcp]) +cat $abs_srcdir/legacy_mgcp/mgcp_test.ok > expout +AT_CHECK([$abs_top_builddir/tests/legacy_mgcp/mgcp_test], [], [expout], [ignore]) +AT_CLEANUP + +AT_SETUP([legacy_mgcp-trans]) +AT_KEYWORDS([legacy_mgcp-trans]) +AT_CHECK([test "$enable_mgcp_transcoding_test" == yes || exit 77]) +cat $abs_srcdir/legacy_mgcp/mgcp_transcoding_test.ok > expout +AT_CHECK([$abs_top_builddir/tests/legacy_mgcp/mgcp_transcoding_test], [], [expout], [ignore]) +AT_CLEANUP + +AT_SETUP([mgcp_client]) +AT_KEYWORDS([mgcp_client]) +cat $abs_srcdir/mgcp_client/mgcp_client_test.ok > expout +cat $abs_srcdir/mgcp_client/mgcp_client_test.err > experr +AT_CHECK([$abs_top_builddir/tests/mgcp_client/mgcp_client_test], [], [expout], [experr]) +AT_CLEANUP + +AT_SETUP([mgcp]) +AT_KEYWORDS([mgcp]) +cat $abs_srcdir/mgcp/mgcp_test.ok > expout +AT_CHECK([$abs_top_builddir/tests/mgcp/mgcp_test], [], [expout], [ignore]) +AT_CLEANUP diff --git a/tests/vty_test_runner.py b/tests/vty_test_runner.py new file mode 100644 index 0000000..05bc3bf --- /dev/null +++ b/tests/vty_test_runner.py @@ -0,0 +1,171 @@ +#!/usr/bin/env python + +# (C) 2013 by Katerina Barone-Adesi <kat.obsc@gmail.com> +# (C) 2013 by Holger Hans Peter Freyther +# 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 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +import os, sys +import time +import unittest +import socket +import subprocess + +import osmopy.obscvty as obscvty +import osmopy.osmoutil as osmoutil + +# add $top_srcdir/contrib to find ipa.py +sys.path.append(os.path.join(sys.path[0], '..', 'contrib')) + +from ipa import IPA + +# to be able to find $top_srcdir/doc/... +confpath = os.path.join(sys.path[0], '..') + +class TestVTYBase(unittest.TestCase): + + def checkForEndAndExit(self): + res = self.vty.command("list") + #print ('looking for "exit"\n') + self.assert_(res.find(' exit\r') > 0) + #print 'found "exit"\nlooking for "end"\n' + self.assert_(res.find(' end\r') > 0) + #print 'found "end"\n' + + def vty_command(self): + raise Exception("Needs to be implemented by a subclass") + + def vty_app(self): + raise Exception("Needs to be implemented by a subclass") + + def setUp(self): + osmo_vty_cmd = self.vty_command()[:] + config_index = osmo_vty_cmd.index('-c') + if config_index: + cfi = config_index + 1 + osmo_vty_cmd[cfi] = os.path.join(confpath, osmo_vty_cmd[cfi]) + + try: + self.proc = osmoutil.popen_devnull(osmo_vty_cmd) + except OSError: + print >> sys.stderr, "Current directory: %s" % os.getcwd() + print >> sys.stderr, "Consider setting -b" + + appstring = self.vty_app()[2] + appport = self.vty_app()[0] + self.vty = obscvty.VTYInteract(appstring, "127.0.0.1", appport) + + def tearDown(self): + if self.vty: + self.vty._close_socket() + self.vty = None + osmoutil.end_proc(self.proc) + +class TestVTYMGCP(TestVTYBase): + def vty_command(self): + return ["./src/osmo-bsc_mgcp/osmo-bsc_mgcp", "-c", + "doc/examples/osmo-bsc_mgcp/mgcp.cfg"] + + def vty_app(self): + return (4243, "./src/osmo-bsc_mgcp/osmo-bsc_mgcp", "OpenBSC MGCP", "mgcp") + + def testForcePtime(self): + self.vty.enable() + res = self.vty.command("show running-config") + self.assert_(res.find(' rtp force-ptime 20\r') > 0) + self.assertEquals(res.find(' no rtp force-ptime\r'), -1) + + self.vty.command("configure terminal") + self.vty.command("mgcp") + self.vty.command("no rtp force-ptime") + res = self.vty.command("show running-config") + self.assertEquals(res.find(' rtp force-ptime 20\r'), -1) + self.assertEquals(res.find(' no rtp force-ptime\r'), -1) + + def testOmitAudio(self): + self.vty.enable() + res = self.vty.command("show running-config") + self.assert_(res.find(' sdp audio-payload send-name\r') > 0) + self.assertEquals(res.find(' no sdp audio-payload send-name\r'), -1) + + self.vty.command("configure terminal") + self.vty.command("mgcp") + self.vty.command("no sdp audio-payload send-name") + res = self.vty.command("show running-config") + self.assertEquals(res.find(' rtp sdp audio-payload send-name\r'), -1) + self.assert_(res.find(' no sdp audio-payload send-name\r') > 0) + + # TODO: test it for the trunk! + + def testBindAddr(self): + self.vty.enable() + + self.vty.command("configure terminal") + self.vty.command("mgcp") + + # enable.. disable bts-bind-ip + self.vty.command("rtp bts-bind-ip 254.253.252.250") + res = self.vty.command("show running-config") + self.assert_(res.find('rtp bts-bind-ip 254.253.252.250') > 0) + self.vty.command("no rtp bts-bind-ip") + res = self.vty.command("show running-config") + self.assertEquals(res.find(' rtp bts-bind-ip'), -1) + + # enable.. disable net-bind-ip + self.vty.command("rtp net-bind-ip 254.253.252.250") + res = self.vty.command("show running-config") + self.assert_(res.find('rtp net-bind-ip 254.253.252.250') > 0) + self.vty.command("no rtp net-bind-ip") + res = self.vty.command("show running-config") + self.assertEquals(res.find(' rtp net-bind-ip'), -1) + + +if __name__ == '__main__': + import argparse + import sys + + workdir = '.' + + parser = argparse.ArgumentParser() + parser.add_argument("-v", "--verbose", dest="verbose", + action="store_true", help="verbose mode") + parser.add_argument("-p", "--pythonconfpath", dest="p", + help="searchpath for config") + parser.add_argument("-w", "--workdir", dest="w", + help="Working directory") + parser.add_argument("test_name", nargs="*", help="(parts of) test names to run, case-insensitive") + args = parser.parse_args() + + verbose_level = 1 + if args.verbose: + verbose_level = 2 + + if args.w: + workdir = args.w + + if args.p: + confpath = args.p + + print "confpath %s, workdir %s" % (confpath, workdir) + os.chdir(workdir) + print "Running tests for specific VTY commands" + suite = unittest.TestSuite() + suite.addTest(unittest.TestLoader().loadTestsFromTestCase(TestVTYMGCP)) + + if args.test_name: + osmoutil.pick_tests(suite, *args.test_name) + + res = unittest.TextTestRunner(verbosity=verbose_level, stream=sys.stdout).run(suite) + sys.exit(len(res.errors) + len(res.failures)) + +# vim: shiftwidth=4 expandtab nocin ai |