BSC_Tests: add TC_chan_alloc_algo_{a,de}scending

The aim of these new test cases is to verify both ascending and
descending modes of the BSC's channel allocator.  Both tests are
using BTS2, which has 4 TRX instances.

The common test scenario can be described as follows:

1. Establish an SDCCH channel, send some dummy payload on it.
2. Send a BSSMAP Assignment Request for a TCH/F channel.
3. Expect RSL CHANnel ACTIVation for a TCH/F channel.
4. Respond with RSL CHANnel ACTIVation NACK (*).
5. Expect a BSSMAP Assignment Failure.

These steps are repeated several times.  Note (*) that for the
sake of simplicity, I am aborting the assignment procedure by
sending a NACK, so that the requested logical channel becomes
BORKEN and behaves like an occupied one until the A-bis/OML
link is re-established.  This reduces the overall complexity.

Change-Id: Ic74a9cd264320a9a17648f9331b67fb2c2404122
Related: SYS#5460
diff --git a/bsc/BSC_Tests.ttcn b/bsc/BSC_Tests.ttcn
index ed56fc2..7070c9f 100644
--- a/bsc/BSC_Tests.ttcn
+++ b/bsc/BSC_Tests.ttcn
@@ -11576,6 +11576,68 @@
 	f_shutdown_helper();
 }
 
+private function f_TC_chan_alloc_algo(DchanTuple dt, BtsTrxIdx idx)
+runs on test_CT {
+	/* MSC sends an Assignment Request */
+	var PDU_BSSAP ass_cmd := f_gen_ass_req();
+	ass_cmd.pdu.bssmap.assignmentRequest.channelType := valueof(ts_BSSMAP_IE_ChannelType);
+	ass_cmd.pdu.bssmap.assignmentRequest.codecList := valueof(ts_BSSMAP_IE_CodecList({ts_CodecFR}));
+	BSSAP.send(ts_BSSAP_DATA_req(dt.sccp_conn_id, ass_cmd));
+
+	/* Expect the BSC to allocate a TCH channel on the given BTS/TRX */
+	var RSL_Message rsl_chan_act := f_exp_ipa_rx(tr_RSL_MsgTypeD(RSL_MT_CHAN_ACTIV), idx);
+	/* Send CHAN ACT NACK, so that the requested TCH channel becomes BORKEN */
+	f_ipa_tx(ts_RSL_CHAN_ACT_NACK(rsl_chan_act.ies[0].body.chan_nr, RSL_ERR_EQUIPMENT_FAIL), idx);
+	/* Expect to receive an Assignment Failure */
+	BSSAP.receive(tr_BSSAP_DATA_ind(dt.sccp_conn_id, tr_BSSMAP_AssignmentFail));
+}
+
+testcase TC_chan_alloc_algo_ascending() runs on test_CT {
+	/* We need to access BTS2, which has 4 TRXs */
+	f_init(nr_bts := 3);
+
+	/* HACK: work around "Couldn't find Expect for CRCX" */
+	vc_MGCP.stop;
+
+	f_vty_enter_cfg_bts(BSCVTY, 2);
+	f_vty_transceive(BSCVTY, "channel allocator ascending");
+	f_vty_transceive(BSCVTY, "end");
+
+	/* Expect the BSC to allocate 4 x TCH/F channels on BTS2/TRX0 */
+	for (var integer i := 0; i < 4; i := i + 1) {
+		var DchanTuple dt := f_est_dchan('23'O, 23, '00000000'O, {2, 0});
+		f_TC_chan_alloc_algo(dt, {2, 0});
+		f_perform_clear_test_ct(dt);
+	}
+
+	/* At this point all 4 x TCH/F channels are BORKEN, but they will be
+	 * resurrected upon the A-bis/OML link re-establishment. */
+	f_shutdown_helper();
+}
+
+testcase TC_chan_alloc_algo_descending() runs on test_CT {
+	/* We need to access BTS2, which has 4 TRXs */
+	f_init(nr_bts := 3);
+
+	/* HACK: work around "Couldn't find Expect for CRCX" */
+	vc_MGCP.stop;
+
+	f_vty_enter_cfg_bts(BSCVTY, 2);
+	f_vty_transceive(BSCVTY, "channel allocator descending");
+	f_vty_transceive(BSCVTY, "end");
+
+	/* Expect the BSC to allocate 5 x TCH/F channels on BTS2/TRX3 */
+	for (var integer i := 0; i < 5; i := i + 1) {
+		var DchanTuple dt := f_est_dchan('23'O, 23, '00000000'O, {2, 0});
+		f_TC_chan_alloc_algo(dt, {2, 3});
+		f_perform_clear_test_ct(dt);
+	}
+
+	/* At this point all 5 x TCH/F channels are BORKEN, but they will be
+	 * resurrected upon the A-bis/OML link re-establishment. */
+	f_shutdown_helper();
+}
+
 control {
 	/* CTRL interface testing */
 	execute( TC_ctrl_msc_connection_status() );
@@ -11902,6 +11964,10 @@
 
 	execute( TC_lost_sdcch_during_assignment() );
 
+	/* Channel allocator */
+	execute( TC_chan_alloc_algo_ascending() );
+	execute( TC_chan_alloc_algo_descending() );
+
 	/* Run TC_ho_out_of_this_bsc last, because it may trigger a segfault before osmo-bsc's patch
 	 * with change-id I5a3345ab0005a73597f5c27207480912a2f5aae6 */
 	execute( TC_ho_out_of_this_bsc() );