module HNB_Tests { /* Integration Tests for OsmoHNodeB * (C) 2021 by sysmocom - s.f.m.c. GmbH * All rights reserved. * * Released under the terms of GNU General Public License, Version 2 or * (at your option) any later version. * * SPDX-License-Identifier: GPL-2.0-or-later * * This test suite tests OsmoHNodB while emulating both multiple UE as * well as the HNBGW. See README for more details. * * There are test cases that run in so-called 'handler mode' and test cases * that run directly on top of the BSSAP and RSL CodecPorts. The "handler mode" * tests abstract the multiplexing/demultiplexing of multiple SCCP connections * and/or RSL channels and are hence suitable for higher-level test cases, while * the "raw" tests directly on top of the CodecPorts are more suitable for lower- * level testing. */ import from Misc_Helpers all; import from General_Types all; import from Osmocom_Types all; import from IPL4asp_Types all; import from Osmocom_CTRL_Functions all; import from Osmocom_CTRL_Types all; import from Osmocom_CTRL_Adapter all; import from StatsD_Types all; import from StatsD_CodecPort all; import from StatsD_CodecPort_CtrlFunct all; import from StatsD_Checker all; import from Osmocom_VTY_Functions all; import from TELNETasp_PortType all; import from HNBAP_Templates all; import from HNBGW_ConnectionHandler all; import from Iuh_Emulation all; modulepar { /* IP address at which the HNodeB can be reached */ charstring mp_hnodeb_ip := "127.0.0.1"; /* IP address at which the test binds */ charstring mp_hnbgw_iuh_ip := "127.0.0.1"; integer mp_hnbgw_iuh_port := 29169; } type component test_CT extends CTRL_Adapter_CT { port TELNETasp_PT HNBVTY; /* global test case guard timer (actual timeout value is set in f_init()) */ timer T_guard := 30.0; } /* global altstep for global guard timer; */ altstep as_Tguard() runs on test_CT { [] T_guard.timeout { setverdict(fail, "Timeout of T_guard"); mtc.stop; } } friend function f_logp(TELNETasp_PT pt, charstring log_msg) { // log on TTCN3 log output log(log_msg); // log in stderr log f_vty_transceive(pt, "logp lglobal notice TTCN3 f_logp(): " & log_msg); } function f_init_vty(charstring id := "foo") runs on test_CT { if (HNBVTY.checkstate("Mapped")) { /* skip initialization if already executed once */ return; } map(self:HNBVTY, system:HNBVTY); f_vty_set_prompts(HNBVTY); f_vty_transceive(HNBVTY, "enable"); } /* global initialization function */ function f_init(float guard_timeout := 30.0) runs on test_CT { var integer bssap_idx; T_guard.start(guard_timeout); activate(as_Tguard()); f_init_vty("VirtHNBGW"); /* TODO: Wait for Iuh connection to be established */ } friend function f_shutdown_helper() runs on test_CT { all component.stop; setverdict(pass); mtc.stop; } friend function f_gen_test_hdlr_pars() return TestHdlrParams { var TestHdlrParams pars := valueof(t_def_TestHdlrPars); pars.hnodeb_addr := mp_hnodeb_ip; pars.hnbgw_addr := mp_hnbgw_iuh_ip; pars.hnbgw_port := mp_hnbgw_iuh_port; return pars; } type function void_fn(charstring id) runs on HNBGW_ConnHdlr; /* helper function to create and connect a HNBGW_ConnHdlr component */ private function f_connect_handler(inout HNBGW_ConnHdlr vc_conn, integer bssap_idx := 0) runs on test_CT { /*connect(vc_conn:RAN, g_bssap[bssap_idx].vc_RAN:PROC); connect(vc_conn:MGCP_PROC, vc_MGCP:MGCP_PROC); connect(vc_conn:RSL, bts[0].rsl.vc_RSL:CLIENT_PT); connect(vc_conn:RSL_PROC, bts[0].rsl.vc_RSL:RSL_PROC); if (isvalue(bts[1])) { connect(vc_conn:RSL1, bts[1].rsl.vc_RSL:CLIENT_PT); connect(vc_conn:RSL1_PROC, bts[1].rsl.vc_RSL:RSL_PROC); } if (isvalue(bts[2])) { connect(vc_conn:RSL2, bts[2].rsl.vc_RSL:CLIENT_PT); connect(vc_conn:RSL2_PROC, bts[2].rsl.vc_RSL:RSL_PROC); } connect(vc_conn:BSSAP, g_bssap[bssap_idx].vc_RAN:CLIENT); if (mp_enable_lcs_tests) { connect(vc_conn:BSSAP_LE, g_bssap_le.vc_BSSAP_LE:CLIENT); connect(vc_conn:BSSAP_LE_PROC, g_bssap_le.vc_BSSAP_LE:PROC); } connect(vc_conn:MGCP, vc_MGCP:MGCP_CLIENT); connect(vc_conn:MGCP_MULTI, vc_MGCP:MGCP_CLIENT_MULTI); connect(vc_conn:STATSD_PROC, vc_STATSD:STATSD_PROC);*/ } function f_start_handler_create(TestHdlrParams pars) runs on test_CT return HNBGW_ConnHdlr { var charstring id := testcasename(); var HNBGW_ConnHdlr vc_conn; vc_conn := HNBGW_ConnHdlr.create(id); f_connect_handler(vc_conn); return vc_conn; } function f_start_handler_run(HNBGW_ConnHdlr vc_conn, void_fn fn, TestHdlrParams pars) runs on test_CT return HNBGW_ConnHdlr { var charstring id := testcasename(); /* Emit a marker to appear in the SUT's own logging output */ f_logp(HNBVTY, id & "() start"); vc_conn.start(f_handler_init(fn, id, pars)); return vc_conn; } function f_start_handler(void_fn fn, template (omit) TestHdlrParams pars_tmpl := omit) runs on test_CT return HNBGW_ConnHdlr { var TestHdlrParams pars; if (isvalue(pars)) { pars := valueof(pars_tmpl); } else { pars := valueof(f_gen_test_hdlr_pars()); } return f_start_handler_run(f_start_handler_create(pars), fn, pars); } /* first function inside ConnHdlr component; sets g_pars + starts function */ private function f_handler_init(void_fn fn, charstring id, TestHdlrParams pars) runs on HNBGW_ConnHdlr { f_HNBGW_ConnHdlr_init(pars); HNBAP.receive(IUHEM_Event:{up_down:=IUHEM_EVENT_UP}); /* Wait for HNB to connect to us */ fn.apply(id); } private function f_tc_hnb_register_request(charstring id) runs on HNBGW_ConnHdlr { f_handle_hnbap_hnb_register_req(); f_sleep(1.0); } testcase TC_hnb_register_request_accept() runs on test_CT { var HNBGW_ConnHdlr vc_conn; f_init(); vc_conn := f_start_handler(refers(f_tc_hnb_register_request)); vc_conn.done; f_shutdown_helper(); } private function f_tc_hnb_register_reject(charstring id) runs on HNBGW_ConnHdlr { HNBAP.receive(tr_HNBAP_HNBRegisterRequest(char2oct(g_pars.hNB_Identity_Info), g_pars.plmnid, int2bit(g_pars.cell_identity, 28), int2oct(g_pars.lac, 2), int2oct(g_pars.rac, 1), int2oct(g_pars.sac, 2) )); HNBAP.send(ts_HNBAP_HNBRegisterReject(ts_HnbapCause(overload))); f_sleep(1.0); } testcase TC_hnb_register_request_reject() runs on test_CT { var HNBGW_ConnHdlr vc_conn; f_init(); vc_conn := f_start_handler(refers(f_tc_hnb_register_reject)); vc_conn.done; f_shutdown_helper(); } control { execute( TC_hnb_register_request_accept() ); execute( TC_hnb_register_request_reject() ); } }