bts: Refactor code to support mixed DEFAULT + NORMAL and EXTENDED CBCH

The existing code structure could only test for normal messages with a
NULL default, but didn't handle situations where normal and/or schedule
messages were superimposed on top of DEFAULT messages.

Also, prepare the infrastructure for testing both CBCH BASIC and CBCH
EXTENDED.

No new tests are introduced, the code should behave identical before
and after this patch.

Change-Id: I144c7d833b79c648b1ac69a6155f3603025ede5c
Related: OS#4011
This commit is contained in:
Harald Welte 2019-05-20 20:03:50 +02:00
parent df4d0f0b8c
commit a3ff670c5f
2 changed files with 220 additions and 62 deletions

View File

@ -30,9 +30,28 @@ import from BTS_Tests all;
* Cell Broadcast related tests
***********************************************************************/
/* Test parameters for one channel (e.g. Basic, Extended) */
type record CbchTestParsChan {
/* list of "normal" (sent-once) SMSCB messages */
CbchTestMsgs msgs,
/* default message, if any */
CbchTestMsg default_msg optional
}
private template (value) CbchTestParsChan
t_CbchPC(template (value) CbchTestMsgs msgs, template (omit) CbchTestMsg def := omit) := {
msgs := msgs,
default_msg := def
}
/* CBCH test parameters for most of our tests */
type record CbchTestPars {
/* should we execute on SDCCH4 (true) or SDCCH8 (false) ? */
boolean use_sdcch4,
CbchTestMsgs msgs
/* Parameters for BASIC CBCH */
CbchTestParsChan basic,
/* Parameters for EXTENDED CBCH */
CbchTestParsChan extended optional
};
type record CbchTestMsg {
@ -56,10 +75,18 @@ type record of CbchBlock CbchBlocks;
/* compute the expected blocks for given test parameters */
private function f_cbch_compute_exp_blocks(inout CbchTestPars pars) {
f_cbch_compute_exp_blocks_chan(pars.basic);
if (ispresent(pars.extended)) {
f_cbch_compute_exp_blocks_chan(pars.extended);
}
}
private function f_cbch_compute_exp_blocks_chan(inout CbchTestParsChan pars_chan) {
var integer i;
for (i := 0; i < lengthof(pars.msgs); i := i+1) {
pars.msgs[i].blocks := f_comp_blocks(pars.msgs[i]);
for (i := 0; i < lengthof(pars_chan.msgs); i := i+1) {
pars_chan.msgs[i].blocks := f_comp_blocks(pars_chan.msgs[i]);
}
if (ispresent(pars_chan.default_msg)) {
pars_chan.default_msg.blocks := f_comp_blocks(pars_chan.default_msg);
}
}
private function f_comp_blocks(in CbchTestMsg msg) return CbchBlocks {
@ -127,8 +154,39 @@ private function f_rsl_smscb_default_null() runs on test_CT
RSL_CCHAN.send(ts_RSL_UD(ts_RSL_SMSCB_CMD(cmd_type, ''O)));
}
private function f_smscb_setup(inout CbchTestPars pars) runs on test_CT {
template RSL_IE t_RSL_IE_SMSCB_EXT := t_RSL_IE(RSL_IE_SMSCB_CHAN_INDICATOR, {smscb_chan_ind := 1});
private function f_smscb_setup_rsl_chan(inout CbchTestParsChan pars_chan, boolean extd := false)
runs on test_CT {
var integer i;
var CbchTestMsg msg;
var uint2_t rsl_last_block;
var RSL_IE_CbCommandType cmd_type;
var RSL_Message rsl;
/* send SMSCB[s] via RSL */
for (i := 0; i < lengthof(pars_chan.msgs); i := i+1) {
msg := pars_chan.msgs[i];
rsl_last_block := f_cbch_block_nr2rsl(msg.last_block);
cmd_type := valueof(ts_RSL_IE_CbCmdType(msg.rsl_cb_cmd, rsl_last_block));
rsl := valueof(ts_RSL_SMSCB_CMD(cmd_type, msg.payload));
if (extd) {
rsl.ies := rsl.ies & { valueof(t_RSL_IE_SMSCB_EXT) };
}
RSL_CCHAN.send(ts_RSL_UD(rsl));
}
if (ispresent(pars_chan.default_msg)) {
msg := pars_chan.default_msg;
rsl_last_block := f_cbch_block_nr2rsl(msg.last_block);
cmd_type := valueof(ts_RSL_IE_CbCmdType(msg.rsl_cb_cmd, rsl_last_block, false));
rsl := valueof(ts_RSL_SMSCB_CMD(cmd_type, msg.payload));
if (extd) {
rsl.ies := rsl.ies & { valueof(t_RSL_IE_SMSCB_EXT) };
}
RSL_CCHAN.send(ts_RSL_UD(rsl));
}
}
private function f_smscb_setup(inout CbchTestPars pars) runs on test_CT {
f_cbch_compute_exp_blocks(pars);
@ -154,12 +212,9 @@ private function f_smscb_setup(inout CbchTestPars pars) runs on test_CT {
/* FIXME: switch to dedicated mode for SDCCH/8 */
/* send SMSCB[s] via RSL */
for (i := 0; i < lengthof(pars.msgs); i := i+1) {
var CbchTestMsg msg := pars.msgs[i];
var uint2_t rsl_last_block := f_cbch_block_nr2rsl(msg.last_block);
var RSL_IE_CbCommandType cmd_type :=
valueof(ts_RSL_IE_CbCmdType(msg.rsl_cb_cmd, rsl_last_block));
RSL_CCHAN.send(ts_RSL_UD(ts_RSL_SMSCB_CMD(cmd_type, msg.payload)));
f_smscb_setup_rsl_chan(pars.basic, false);
if (ispresent(pars.extended)) {
f_smscb_setup_rsl_chan(pars.extended, true);
}
}
@ -171,59 +226,141 @@ private function f_smscb_cleanup() runs on test_CT {
"phys_chan_config SDCCH8");
}
/* construct a receive/match template for given block_nr in given msg */
private function f_get_block_template(CbchTestMsg msg, integer block_nr) return template CBCH_Block {
var template CBCH_Block tr;
if (block_nr < lengthof(msg.blocks)) {
var CbchBlock b := msg.blocks[block_nr];
tr := tr_CBCH_Block(b.seq_nr, b.is_last, b.payload);
} else {
tr := tr_CBCH_Block(15, ?, ?);
}
return tr;
}
/* the heart of the CBCH test case matching engine for one channel (basic, extended) */
private function f_cbch_match(inout CbchTestParsChan pars_chan, CBCH_Block cb, integer tb)
{
var integer block_nr := tb mod 4;
var integer i;
if (not match(cb, tr_CBCH_Block)) {
setverdict(fail, "Illegal CBCH Block received: ", cb);
} else {
var boolean matched := false;
/* check if it's any of our expected blocks */
for (i := 0; i < lengthof(pars_chan.msgs); i := i+1) {
if (block_nr < lengthof(pars_chan.msgs[i].blocks)) {
if (match(cb, f_get_block_template(pars_chan.msgs[i], block_nr))) {
log("Found block_nr ", block_nr, " of msg ", i);
if (not pars_chan.msgs[i].blocks[block_nr].seen_once) {
pars_chan.msgs[i].blocks[block_nr].seen_once := true;
setverdict(pass);
} else {
setverdict(fail, "Received SMSCB twice! ", cb);
}
matched := true;
break;
}
}
}
if (not matched) {
var template CBCH_Block tr;
if (ispresent(pars_chan.default_msg)) {
/* it must be a block of the default message */
tr := f_get_block_template(pars_chan.default_msg, block_nr);
} else {
/* it must be a NULL block */
tr := tr_CBCH_Block(15, ?, ?);
}
if (not match(cb, tr)) {
setverdict(fail, "Received unexpected CBCH block: ", cb);
} else {
log("Found block_nr ", block_nr, " of DEFAULT/NULL");
if (ispresent(pars_chan.default_msg) and
block_nr < lengthof(pars_chan.default_msg.blocks)) {
pars_chan.default_msg.blocks[block_nr].seen_once := true;
}
}
}
}
}
/* Report/Evaluate the per-channel CBCH test results */
private function f_cbch_report(CbchTestParsChan pars_chan, charstring id)
{
var integer i, j;
/* verify that each block of each message has been seen once */
for (i := 0; i < lengthof(pars_chan.msgs); i := i+1) {
for (j := 0; j < lengthof(pars_chan.msgs[i].blocks); j := j+1) {
var CbchBlock b := pars_chan.msgs[i].blocks[j];
if (not b.seen_once) {
setverdict(fail, "Timeout waiting for ", id, " CBCH block ",
j, " of msg ", i);
}
}
}
if (ispresent(pars_chan.default_msg)) {
/* verify that each block of default message has been seen at least once */
for (j := 0; j < lengthof(pars_chan.default_msg.blocks); j := j+1) {
var CbchBlock b := pars_chan.default_msg.blocks[j];
if (not b.seen_once) {
setverdict(fail, "Timeout waiting for at leaset one instance of ",
"CBCH block ", j, " of DEFAULT msg");
}
}
}
}
/* shared function doing the heavy lifting for most CBCH tests */
private function f_TC_smscb(CbchTestPars pars) runs on test_CT {
var L1ctlDlMessage dl;
var integer i, j;
timer T := 5.0 * int2float(lengthof(pars.msgs));
var integer msg_count;
timer T;
msg_count := lengthof(pars.basic.msgs);
if (ispresent(pars.basic.default_msg)) {
msg_count := msg_count + 1;
}
if (ispresent(pars.extended)) {
msg_count := msg_count + lengthof(pars.extended.msgs);
if (ispresent(pars.extended.default_msg)) {
msg_count := msg_count + 1;
}
}
f_smscb_setup(pars);
T.start;
/* dynamically adjust timeout based on number of messages */
T.start(5.0 + 3.0 * int2float(msg_count));
/* Expect this to show up exactly once on the basic CBCH (four blocks) */
alt {
/* FIXME: Channel Nr for SDCCH/8 */
[] L1CTL.receive(tr_L1CTL_DATA_IND(t_RslChanNr_CBCH(0))) -> value dl {
log("CBCH: ", dl);
var integer tb := f_cbch_fn2tb(dl.dl_info.frame_nr);
var CBCH_Block cb := dec_CBCH_Block(dl.payload.data_ind.payload);
log("Tb=", tb, ", CBCH: ", dl, ", block: ", cb);
/* detect the proper CBCH messages; check frame number */
f_cbch_fn_verify(dl.dl_info.frame_nr, cb);
if (not match(cb, tr_CBCH_Block)) {
setverdict(fail, "Illegal CBCH Block received: ", cb);
if (tb < 4) {
f_cbch_match(pars.basic, cb, tb);
} else {
var boolean matched := false;
/* ignore NULL messages */
if (match(cb, tr_CBCH_Block(15, ?, ?))) { repeat; }
for (i := 0; i < lengthof(pars.msgs); i := i+1) {
for (j := 0; j < lengthof(pars.msgs[i].blocks); j := j+1) {
var CbchBlock b := pars.msgs[i].blocks[j];
if (match(cb, tr_CBCH_Block(b.seq_nr, b.is_last, b.payload))) {
if (not pars.msgs[i].blocks[j].seen_once) {
pars.msgs[i].blocks[j].seen_once := true;
setverdict(pass);
} else {
setverdict(fail, "Received SMSCB twice! ", cb);
}
matched := true;
continue;
}
}
if (not ispresent(pars.extended)) {
/* no parameters for ext. BCCH given: ignore */
repeat;
}
if (not matched) {
setverdict(fail, "Received unexpected CBCH block: ", cb);
}
repeat;
f_cbch_match(pars.extended, cb, tb);
}
repeat;
}
[] L1CTL.receive { repeat; }
[] T.timeout {
for (i := 0; i < lengthof(pars.msgs); i := i+1) {
for (j := 0; j < lengthof(pars.msgs[i].blocks); j := j+1) {
var CbchBlock b := pars.msgs[i].blocks[j];
if (not b.seen_once) {
setverdict(fail, "Timeout waiting for CBCH");
}
}
f_cbch_report(pars.basic, "Basic");
if (ispresent(pars.extended)) {
f_cbch_report(pars.extended, "Extended");
}
}
}
@ -259,8 +396,8 @@ private function f_TC_smscb_default_only(CbchTestPars pars) runs on test_CT {
} else {
var uint4_t rx_seq_nr := cb.block_type.seq_nr;
var template CBCH_Block tr;
if (rx_seq_nr < lengthof(pars.msgs[0].blocks)) {
var CbchBlock b := pars.msgs[0].blocks[rx_seq_nr];
if (rx_seq_nr < lengthof(pars.basic.msgs[0].blocks)) {
var CbchBlock b := pars.basic.msgs[0].blocks[rx_seq_nr];
tr := tr_CBCH_Block(b.seq_nr, b.is_last, b.payload);
} else {
tr := tr_CBCH_Block(15, ?, ?);
@ -338,19 +475,25 @@ private const CbchTestMsgs msgs_1m_3b_default := {
'101112131415161718191a1b1c1d1e1f202223242526'O,
omit }
}
private const CbchTestMsg msg_default := {
RSL_CB_CMD_DEFAULT, 0, '010203040506070708090a0b0c0d0e0f101112131415'O,
omit
}
/* transmit single-block SMSCB COMMAND */
testcase TC_sms_cb_cmd_sdcch4_1block() runs on test_CT {
var CbchTestPars pars := {
use_sdcch4 := true,
msgs := msgs_1m_1b_norm
basic := valueof(t_CbchPC(msgs_1m_1b_norm)),
extended := omit
};
f_TC_smscb(pars);
}
testcase TC_sms_cb_cmd_sdcch8_1block() runs on test_CT {
var CbchTestPars pars := {
use_sdcch4 := false,
msgs := msgs_1m_1b_norm
basic := valueof(t_CbchPC(msgs_1m_1b_norm)),
extended := omit
};
f_TC_smscb(pars);
}
@ -359,14 +502,16 @@ testcase TC_sms_cb_cmd_sdcch8_1block() runs on test_CT {
testcase TC_sms_cb_cmd_sdcch4_2block() runs on test_CT {
var CbchTestPars pars := {
use_sdcch4 := true,
msgs := msgs_1m_2b_norm
basic := valueof(t_CbchPC(msgs_1m_2b_norm)),
extended := omit
};
f_TC_smscb(pars);
}
testcase TC_sms_cb_cmd_sdcch8_2block() runs on test_CT {
var CbchTestPars pars := {
use_sdcch4 := false,
msgs := msgs_1m_2b_norm
basic := valueof(t_CbchPC(msgs_1m_2b_norm)),
extended := omit
};
f_TC_smscb(pars);
}
@ -375,14 +520,16 @@ testcase TC_sms_cb_cmd_sdcch8_2block() runs on test_CT {
testcase TC_sms_cb_cmd_sdcch4_3block() runs on test_CT {
var CbchTestPars pars := {
use_sdcch4 := true,
msgs := msgs_1m_3b_norm
basic := valueof(t_CbchPC(msgs_1m_3b_norm)),
extended := omit
};
f_TC_smscb(pars);
}
testcase TC_sms_cb_cmd_sdcch8_3block() runs on test_CT {
var CbchTestPars pars := {
use_sdcch4 := false,
msgs := msgs_1m_3b_norm
basic := valueof(t_CbchPC(msgs_1m_3b_norm)),
extended := omit
};
f_TC_smscb(pars);
}
@ -391,14 +538,16 @@ testcase TC_sms_cb_cmd_sdcch8_3block() runs on test_CT {
testcase TC_sms_cb_cmd_sdcch4_4block() runs on test_CT {
var CbchTestPars pars := {
use_sdcch4 := true,
msgs := msgs_1m_4b_norm
basic := valueof(t_CbchPC(msgs_1m_4b_norm)),
extended := omit
};
f_TC_smscb(pars);
}
testcase TC_sms_cb_cmd_sdcch8_4block() runs on test_CT {
var CbchTestPars pars := {
use_sdcch4 := false,
msgs := msgs_1m_4b_norm
basic := valueof(t_CbchPC(msgs_1m_4b_norm)),
extended := omit
};
f_TC_smscb(pars);
}
@ -407,14 +556,16 @@ testcase TC_sms_cb_cmd_sdcch8_4block() runs on test_CT {
testcase TC_sms_cb_cmd_sdcch4_multi() runs on test_CT {
var CbchTestPars pars := {
use_sdcch4 := true,
msgs := msgs_3m_4b_norm
basic := valueof(t_CbchPC(msgs_3m_4b_norm)),
extended := omit
};
f_TC_smscb(pars);
}
testcase TC_sms_cb_cmd_sdcch8_multi() runs on test_CT {
var CbchTestPars pars := {
use_sdcch4 := false,
msgs := msgs_3m_4b_norm
basic := valueof(t_CbchPC(msgs_3m_4b_norm)),
extended := omit
};
f_TC_smscb(pars);
}
@ -423,14 +574,16 @@ testcase TC_sms_cb_cmd_sdcch8_multi() runs on test_CT {
testcase TC_sms_cb_cmd_sdcch4_schedule() runs on test_CT {
var CbchTestPars pars := {
use_sdcch4 := true,
msgs := msgs_1m_4b_sched
basic := valueof(t_CbchPC(msgs_1m_4b_sched)),
extended := omit
};
f_TC_smscb(pars);
}
testcase TC_sms_cb_cmd_sdcch8_schedule() runs on test_CT {
var CbchTestPars pars := {
use_sdcch4 := false,
msgs := msgs_1m_4b_sched
basic := valueof(t_CbchPC(msgs_1m_4b_sched)),
extended := omit
};
f_TC_smscb(pars);
}
@ -439,7 +592,8 @@ testcase TC_sms_cb_cmd_sdcch8_schedule() runs on test_CT {
testcase TC_sms_cb_cmd_sdcch4_default_only() runs on test_CT {
var CbchTestPars pars := {
use_sdcch4 := true,
msgs := msgs_1m_3b_default
basic := valueof(t_CbchPC(msgs_1m_3b_default)),
extended := omit
};
f_TC_smscb_default_only(pars);
Misc_Helpers.f_shutdown(__BFILE__, __LINE__, pass);
@ -447,7 +601,8 @@ testcase TC_sms_cb_cmd_sdcch4_default_only() runs on test_CT {
testcase TC_sms_cb_cmd_sdcch8_default_only() runs on test_CT {
var CbchTestPars pars := {
use_sdcch4 := true,
msgs := msgs_1m_3b_default
basic := valueof(t_CbchPC(msgs_1m_3b_default)),
extended := omit
};
f_TC_smscb_default_only(pars);
Misc_Helpers.f_shutdown(__BFILE__, __LINE__, pass);
@ -457,7 +612,8 @@ testcase TC_sms_cb_cmd_sdcch8_default_only() runs on test_CT {
testcase TC_sms_cb_cmd_sdcch4_default_then_null() runs on test_CT {
var CbchTestPars pars := {
use_sdcch4 := true,
msgs := msgs_1m_3b_default
basic := valueof(t_CbchPC(msgs_1m_3b_default)),
extended := omit
};
var L1ctlDlMessage dl;
timer T := 5.0;

View File

@ -766,6 +766,7 @@ module RSL_Types {
RSL_IE_StartingTime starting_time,
RSL_IE_EncryptionInfo encr_info,
uint8_t smscb_chan_ind,
RSL_IE_RequestRef req_ref,
RSL_LV full_imm_ass_info,
RSL_LV ms_identity,
@ -818,6 +819,7 @@ module RSL_Types {
sacch_info, iei = RSL_IE_SACCH_INFO;
starting_time, iei = RSL_IE_STARTNG_TIME;
encr_info, iei = RSL_IE_ENCR_INFO;
smscb_chan_ind, iei = RSL_IE_SMSCB_CHAN_INDICATOR;
req_ref, iei = RSL_IE_REQ_REFERENCE;
full_imm_ass_info, iei = RSL_IE_FULL_IMM_ASS_INFO;