BSC_Test_ASCI: Add race condition test, if MSC acknowledges talker

The existing tests (talker fails, talker establishes, talker releases)
delay, so the MSC acknowledges the UPLINK REQUEST first. It is expected
that the events of the talker (failure, establishment, release) are
forwarded to the MSC after the acknowledgement.

New tests are added, so that the MSC acknowledges the UPLINK REQUEST
late. It is expected that the events of the talker are not forwarded
before the MSC acknowledges.

The BSC (under test) must queue the events of the talker before the MSC
has acknowledged the UPLINK REQUEST.

Change-Id: I28081e62287bdc17a3b477d9368f977aedce01c8
diff --git a/bsc/BSC_Tests_ASCI.ttcn b/bsc/BSC_Tests_ASCI.ttcn
index e4a0cca..78b4902 100644
--- a/bsc/BSC_Tests_ASCI.ttcn
+++ b/bsc/BSC_Tests_ASCI.ttcn
@@ -42,6 +42,7 @@
 const charstring COORD_VGCS_UPLINK_BUSY := "VGCS_UPLINK_BUSY";
 const charstring COORD_VGCS_ASSIGN_RES := "VGCS_ASSIGN_RES";
 const charstring COORD_VGCS_ASSIGN_FAIL := "VGCS_ASSIGN_FAIL";
+const charstring COORD_UPLINK_REQUEST_CONFIRM := "UPLINK_REQUEST_CONFIRM";
 
 template (value) DescriptiveGroupOrBroadcastCallReference_V
 			ts_BSSMAP_IE_GroupCallRef(integer cr,
@@ -82,6 +83,18 @@
  * VGCS/VBS call controling connection
  */
 
+private function f_delay_msc() runs on MSC_ConnHdlr {
+	var PDU_BSSAP rx_bssap;
+	timer T := 2.0;
+	T.start;
+	alt {
+	[] BSSAP.receive(tr_BSSAP_BSSMAP) -> value rx_bssap {
+		setverdict(fail, "Got BSSAP message from BSC. This is unexpected:", rx_bssap);
+		}
+	[] T.timeout { }
+	}
+}
+
 private function f_tc_vgcs_vbs_setup(charstring id) runs on MSC_ConnHdlr {
 	var PDU_BSSAP rx_bssap;
 	var template (value) DescriptiveGroupOrBroadcastCallReference_V callref :=
@@ -129,6 +142,11 @@
 	[] BSSAP.receive(tr_BSSMAP_UplinkReq) -> value rx_bssap {
 		log("VGCS: received uplink req");
 		uplink_req := true;
+		if (g_pars.asci_test.delay_msc) {
+			log("VGCS: delay uplink req ack");
+			f_delay_msc();
+		}
+		log("VGCS: sending uplink req ack");
 		BSSAP.send(ts_BSSMAP_UplinkReqAck(omit));
 		if (g_pars.asci_test.vgcs_talker_req) {
 			T.start;
@@ -138,6 +156,7 @@
 	[] BSSAP.receive(tr_BSSMAP_UplinkReqConf(?, omit, '1234'O)) -> value rx_bssap {
 		log("VGCS: received uplink req confirm");
 		uplink_req_conf := true;
+		COORD.send(COORD_UPLINK_REQUEST_CONFIRM);
 		if (g_pars.asci_test.vgcs_talker_est) {
 			T.start;
 		}
@@ -159,6 +178,9 @@
 		}
 		repeat;
 		}
+	[] BSSAP.receive(tr_BSSMAP_UplinkRelInd(?, omit)) -> value rx_bssap {
+		setverdict(fail, "VGCS: received uplink rel ind, caused by failure with invalid cause: ", rx_bssap);
+		}
 	[] COORD.receive(COORD_VGCS_ASSIGN_RES) {
 		log("VGCS: got assignment result at call control");
 		assign_res := true;
@@ -322,6 +344,17 @@
 	}
 }
 
+private function f_delay_bts() runs on MSC_ConnHdlr {
+	timer T := 2.0;
+	T.start;
+	alt {
+	[] COORD.receive(COORD_UPLINK_REQUEST_CONFIRM) {
+		setverdict(fail, "Got UPLINK REQUEST CONFIRM from BSC. This is unexpected.");
+		}
+	[] T.timeout { }
+	}
+}
+
 private function f_tc_asci_assignment(charstring id) runs on MSC_ConnHdlr {
 	var PDU_BSSAP rx_bssap;
 	/* Hack: the proper way would be to wait for the BSSMAP VGCS Assignment Result and extract the
@@ -374,11 +407,19 @@
 			RSL.send(ts_RSL_TALKER_DET(g_chan_nr));
 		}
 		if (g_pars.asci_test.vgcs_talker_fail) {
+			if (g_pars.asci_test.delay_bts) {
+				log("VGCS: delay sending RSL failure ind");
+				f_delay_bts();
+			}
 			log("VGCS: sending RSL failure ind");
 			RSL.send(ts_RSL_CONN_FAIL_IND(g_chan_nr, RSL_ERR_TALKER_ACC_FAIL));
 		}
 		if (g_pars.asci_test.vgcs_talker_est or
 		    g_pars.asci_test.vgcs_talker_rel) {
+			if (g_pars.asci_test.delay_bts) {
+				log("VGCS: delay sending RSL estblish ind");
+				f_delay_bts();
+			}
 			log("VGCS: sending RSL etabish ind");
 			RSL.send(ts_RSL_EST_IND(g_chan_nr, ts_RslLinkID_DCCH(0), '1234'O));
 		}
@@ -415,6 +456,7 @@
 		COORD.send(COORD_VGCS_UPLINK_BUSY);
 		repeat;
 		}
+	[] COORD.receive(COORD_UPLINK_REQUEST_CONFIRM) { repeat; }
 	}
 
 	/* The RSL Emulation magically accepts the Chan Activ behind the scenes. */
@@ -531,7 +573,33 @@
 	pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
 	pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
 
+	/* MSC sends acknowledge before link on BTS fail. */
 	pars.asci_test.vgcs_talker_fail := true;
+	pars.asci_test.delay_bts := true;
+
+	call_conn := f_start_handler(refers(f_tc_vgcs_vbs_setup), pars);
+	chan_conn := f_start_handler(refers(f_tc_asci_assignment), pars);
+	/* Connect COORD ports of both functions. The functions will delay before using them. */
+	connect(call_conn:COORD, chan_conn:COORD);
+
+	call_conn.done;
+	chan_conn.done;
+
+	f_shutdown_helper();
+}
+
+testcase TC_vgcs_vbs_talker_fail_late_msc() runs on test_CT {
+	var MSC_ConnHdlr call_conn, chan_conn;
+	var TestHdlrParams pars := f_gen_test_hdlr_pars();
+
+	f_init(1, true);
+
+	pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
+	pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
+
+	/* MSC sends acknowledge after link on BTS fail. */
+	pars.asci_test.vgcs_talker_fail := true;
+	pars.asci_test.delay_msc := true;
 
 	call_conn := f_start_handler(refers(f_tc_vgcs_vbs_setup), pars);
 	chan_conn := f_start_handler(refers(f_tc_asci_assignment), pars);
@@ -553,7 +621,33 @@
 	pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
 	pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
 
+	/* MSC sends acknowledge before BTS establishes the uplink. */
 	pars.asci_test.vgcs_talker_est := true;
+	pars.asci_test.delay_bts := true;
+
+	call_conn := f_start_handler(refers(f_tc_vgcs_vbs_setup), pars);
+	chan_conn := f_start_handler(refers(f_tc_asci_assignment), pars);
+	/* Connect COORD ports of both functions. The functions will delay before using them. */
+	connect(call_conn:COORD, chan_conn:COORD);
+
+	call_conn.done;
+	chan_conn.done;
+
+	f_shutdown_helper();
+}
+
+testcase TC_vgcs_vbs_talker_est_late_msc() runs on test_CT {
+	var MSC_ConnHdlr call_conn, chan_conn;
+	var TestHdlrParams pars := f_gen_test_hdlr_pars();
+
+	f_init(1, true);
+
+	pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
+	pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
+
+	/* MSC sends acknowledge after BTS established the uplink. */
+	pars.asci_test.vgcs_talker_est := true;
+	pars.asci_test.delay_msc := true;
 
 	call_conn := f_start_handler(refers(f_tc_vgcs_vbs_setup), pars);
 	chan_conn := f_start_handler(refers(f_tc_asci_assignment), pars);
@@ -576,6 +670,30 @@
 	pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
 
 	pars.asci_test.vgcs_talker_rel := true;
+	pars.asci_test.delay_bts := true;
+
+	call_conn := f_start_handler(refers(f_tc_vgcs_vbs_setup), pars);
+	chan_conn := f_start_handler(refers(f_tc_asci_assignment), pars);
+	/* Connect COORD ports of both functions. The functions will delay before using them. */
+	connect(call_conn:COORD, chan_conn:COORD);
+
+	call_conn.done;
+	chan_conn.done;
+
+	f_shutdown_helper();
+}
+
+testcase TC_vgcs_vbs_talker_rel_late_msc() runs on test_CT {
+	var MSC_ConnHdlr call_conn, chan_conn;
+	var TestHdlrParams pars := f_gen_test_hdlr_pars();
+
+	f_init(1, true);
+
+	pars.sccp_addr_msc := g_bssap[0].sccp_addr_own;
+	pars.sccp_addr_bsc := g_bssap[0].sccp_addr_peer;
+
+	pars.asci_test.vgcs_talker_rel := true;
+	pars.asci_test.delay_msc := true;
 
 	call_conn := f_start_handler(refers(f_tc_vgcs_vbs_setup), pars);
 	chan_conn := f_start_handler(refers(f_tc_asci_assignment), pars);
@@ -638,8 +756,11 @@
 	execute( TC_vgcs_vbs_assignment_fail() );
 	execute( TC_vgcs_vbs_talker_req() );
 	execute( TC_vgcs_vbs_talker_fail() );
+	execute( TC_vgcs_vbs_talker_fail_late_msc() );
 	execute( TC_vgcs_vbs_talker_est() );
+	execute( TC_vgcs_vbs_talker_est_late_msc() );
 	execute( TC_vgcs_vbs_talker_rel() );
+	execute( TC_vgcs_vbs_talker_rel_late_msc() );
 	execute( TC_vgcs_vbs_uplink_seized() );
 	execute( TC_vgcs_vbs_uplink_release() );
 }
diff --git a/bsc/MSC_ConnectionHandler.ttcn b/bsc/MSC_ConnectionHandler.ttcn
index 0c62003..b7760d0 100644
--- a/bsc/MSC_ConnectionHandler.ttcn
+++ b/bsc/MSC_ConnectionHandler.ttcn
@@ -761,7 +761,9 @@
 	boolean vgcs_talker_est,
 	boolean vgcs_talker_rel,
 	boolean vgcs_uplink_seized,
-	boolean vgcs_uplink_release
+	boolean vgcs_uplink_release,
+	boolean delay_bts,
+	boolean delay_msc
 };
 
 type record TestHdlrParams {
@@ -853,10 +855,13 @@
 		vgcs_assign_ok := false,
 		vgcs_assign_fail := false,
 		vgcs_talker_req := false,
+		vgcs_talker_fail := false,
 		vgcs_talker_est := false,
 		vgcs_talker_rel := false,
 		vgcs_uplink_seized := false,
-		vgcs_uplink_release := false
+		vgcs_uplink_release := false,
+		delay_bts := false,
+		delay_msc := false
 	}
 }