Tests: add SIB2/SIB3/SIB4 ASN.1 round-trip coverage

Add encode/decode helpers and basic round-trip tests for NR SIB2, SIB3
and SIB4 in test_asn1_msg.cpp to ensure we produce decodable messages
with expected fields. Extend SIB4 coverage with an
inter_freq_carrier_freq_info_ranges test that exercises boundary and
out-of-range values for carrier reselection parameters and checks
encoder failures for invalid configurations.

Changes:
- Introduce encode_and_decode_sib2, encode_and_decode_sib3 and
  encode_and_decode_sib4 helpers that call do_SIB2_NR, do_SIB3_NR,
  do_SIB4_NR and uper_decode and assert non-empty, non-null byte
  arrays and successful decoding.
- Add sib2_basic_encode_decode, sib3_basic_encode_decode and
  sib4_basic_encode_decode tests that populate minimal but
  representative NR_SIB2_t, NR_SIB3_t and NR_SIB4_t instances and
  verify selected decoded fields match the originals.
- Add inter_freq_carrier_freq_info_ranges test that builds an NR_SIB4_t
  with NR_InterFreqCarrierFreqInfo_t and varies different offsets and
  thresholds to confirm valid combinations encode and invalid ones
  are rejected.
This commit is contained in:
Guido Casati
2026-04-10 10:22:50 +02:00
parent da7054092a
commit 3e515d9c9c
@@ -14,12 +14,61 @@ extern "C" {
#include "NR_DRB-ToAddMod.h"
#include "NR_DRB-ToAddModList.h"
#include "NR_SRB-ToAddModList.h"
#include "NR_InterFreqCarrierFreqInfo.h"
#include "ds/byte_array.h"
#include "NR_SIB2.h"
#include "NR_SIB3.h"
#include "NR_SIB4.h"
#include "NR_IntraFreqNeighCellInfo.h"
#include "NR_IntraFreqNeighCellList.h"
#include "NR_InterFreqCarrierFreqInfo.h"
#include "NR_InterFreqNeighCellInfo.h"
#include "NR_InterFreqNeighCellList.h"
#include "asn_application.h"
RAN_CONTEXT_t RC;
#ifdef __cplusplus
}
#endif
static NR_SIB2_t *encode_and_decode_sib2(const NR_SIB2_t *sib2, byte_array_t *ba_out)
{
*ba_out = do_SIB2_NR(sib2);
EXPECT_GT(ba_out->len, 0);
EXPECT_NE(ba_out->buf, nullptr);
NR_SIB2_t *decoded = nullptr;
asn_dec_rval_t dec = uper_decode(nullptr, &asn_DEF_NR_SIB2, (void **)&decoded, ba_out->buf, ba_out->len, 0, 0);
EXPECT_EQ(dec.code, RC_OK);
EXPECT_NE(decoded, nullptr);
return decoded;
}
static NR_SIB3_t *encode_and_decode_sib3(const NR_SIB3_t *sib3, byte_array_t *ba_out)
{
*ba_out = do_SIB3_NR(sib3);
EXPECT_GT(ba_out->len, 0);
EXPECT_NE(ba_out->buf, nullptr);
NR_SIB3_t *decoded = nullptr;
asn_dec_rval_t dec = uper_decode(nullptr, &asn_DEF_NR_SIB3, (void **)&decoded, ba_out->buf, ba_out->len, 0, 0);
EXPECT_EQ(dec.code, RC_OK);
EXPECT_NE(decoded, nullptr);
return decoded;
}
static NR_SIB4_t *encode_and_decode_sib4(NR_SIB4_t *sib4, byte_array_t *ba_out)
{
*ba_out = do_SIB4_NR(sib4);
EXPECT_GT(ba_out->len, 0);
EXPECT_NE(ba_out->buf, nullptr);
NR_SIB4_t *decoded = nullptr;
asn_dec_rval_t dec = uper_decode(nullptr, &asn_DEF_NR_SIB4, (void **)&decoded, ba_out->buf, ba_out->len, 0, 0);
EXPECT_EQ(dec.code, RC_OK);
EXPECT_NE(decoded, nullptr);
return decoded;
}
TEST(nr_asn1, rrc_reject)
{
unsigned char buf[1000];
@@ -138,6 +187,167 @@ TEST(nr_asn1, rrc_reconfiguration)
free_RRCReconfiguration_params(params);
}
TEST(nr_asn1, sib2_basic_encode_decode)
{
NR_SIB2_t *sib2 = (NR_SIB2_t *)calloc_or_fail(1, sizeof(*sib2));
sib2->cellReselectionInfoCommon.q_Hyst = NR_SIB2__cellReselectionInfoCommon__q_Hyst_dB0;
sib2->cellReselectionServingFreqInfo.cellReselectionPriority = 3;
sib2->cellReselectionServingFreqInfo.threshServingLowP = 10;
sib2->intraFreqCellReselectionInfo.q_RxLevMin = -56;
sib2->intraFreqCellReselectionInfo.s_IntraSearchP = 22;
sib2->intraFreqCellReselectionInfo.t_ReselectionNR = 1;
sib2->intraFreqCellReselectionInfo.deriveSSB_IndexFromCell = true;
byte_array_t ba = {};
NR_SIB2_t *decoded = encode_and_decode_sib2(sib2, &ba);
EXPECT_EQ(decoded->cellReselectionServingFreqInfo.cellReselectionPriority,
sib2->cellReselectionServingFreqInfo.cellReselectionPriority);
EXPECT_EQ(decoded->cellReselectionServingFreqInfo.threshServingLowP, sib2->cellReselectionServingFreqInfo.threshServingLowP);
ASN_STRUCT_FREE(asn_DEF_NR_SIB2, sib2);
ASN_STRUCT_FREE(asn_DEF_NR_SIB2, decoded);
free_byte_array(ba);
}
TEST(nr_asn1, sib3_basic_encode_decode)
{
NR_SIB3_t *sib3 = (NR_SIB3_t *)calloc_or_fail(1, sizeof(*sib3));
sib3->intraFreqNeighCellList = (struct NR_IntraFreqNeighCellList *)calloc_or_fail(1, sizeof(*sib3->intraFreqNeighCellList));
NR_IntraFreqNeighCellInfo_t *cell = (NR_IntraFreqNeighCellInfo_t *)calloc_or_fail(1, sizeof(*cell));
cell->physCellId = 100;
cell->q_OffsetCell = NR_Q_OffsetRange_dB0;
ASN_SEQUENCE_ADD(&sib3->intraFreqNeighCellList->list, cell);
byte_array_t ba = {};
NR_SIB3_t *decoded = encode_and_decode_sib3(sib3, &ba);
ASSERT_NE(decoded->intraFreqNeighCellList, nullptr);
EXPECT_EQ(decoded->intraFreqNeighCellList->list.count, 1);
EXPECT_EQ(decoded->intraFreqNeighCellList->list.array[0]->physCellId, cell->physCellId);
ASN_STRUCT_FREE(asn_DEF_NR_SIB3, sib3);
ASN_STRUCT_FREE(asn_DEF_NR_SIB3, decoded);
free_byte_array(ba);
}
TEST(nr_asn1, sib4_basic_encode_decode)
{
NR_SIB4_t *sib4 = (NR_SIB4_t *)calloc_or_fail(1, sizeof(*sib4));
NR_InterFreqCarrierFreqInfo_t *carrier = (NR_InterFreqCarrierFreqInfo_t *)calloc_or_fail(1, sizeof(*carrier));
carrier->dl_CarrierFreq = 2000;
carrier->ssbSubcarrierSpacing = NR_SubcarrierSpacing_kHz15;
carrier->deriveSSB_IndexFromCell = true;
carrier->q_RxLevMin = -56;
carrier->t_ReselectionNR = 1;
carrier->threshX_HighP = 5;
carrier->threshX_LowP = 3;
carrier->interFreqNeighCellList = (struct NR_InterFreqNeighCellList *)calloc_or_fail(1, sizeof(*carrier->interFreqNeighCellList));
NR_InterFreqNeighCellInfo_t *ncell = (NR_InterFreqNeighCellInfo_t *)calloc_or_fail(1, sizeof(*ncell));
ncell->physCellId = 200;
ncell->q_OffsetCell = NR_Q_OffsetRange_dB0;
ASN_SEQUENCE_ADD(&carrier->interFreqNeighCellList->list, ncell);
ASN_SEQUENCE_ADD(&sib4->interFreqCarrierFreqList.list, carrier);
byte_array_t ba = {};
NR_SIB4_t *decoded = encode_and_decode_sib4(sib4, &ba);
ASSERT_GT(decoded->interFreqCarrierFreqList.list.count, 0);
EXPECT_EQ(decoded->interFreqCarrierFreqList.list.array[0]->dl_CarrierFreq, carrier->dl_CarrierFreq);
ASN_STRUCT_FREE(asn_DEF_NR_SIB4, sib4);
ASN_STRUCT_FREE(asn_DEF_NR_SIB4, decoded);
free_byte_array(ba);
}
TEST(nr_asn1, inter_freq_carrier_freq_info_ranges)
{
NR_SIB4_t *sib4 = (NR_SIB4_t *)calloc_or_fail(1, sizeof(*sib4));
ASN_SEQUENCE_ADD(&sib4->interFreqCarrierFreqList.list,
(NR_InterFreqCarrierFreqInfo_t *)calloc_or_fail(1, sizeof(NR_InterFreqCarrierFreqInfo_t)));
NR_InterFreqCarrierFreqInfo_t *carrier = sib4->interFreqCarrierFreqList.list.array[0];
carrier->dl_CarrierFreq = 640000;
carrier->ssbSubcarrierSpacing = NR_SubcarrierSpacing_kHz30;
carrier->deriveSSB_IndexFromCell = 1;
carrier->threshX_HighP = 0;
carrier->threshX_LowP = 0;
NR_Q_OffsetRange_t *qoff = (NR_Q_OffsetRange_t *)calloc_or_fail(1, sizeof(*qoff));
*qoff = 15; // arbitrary valid Q-OffsetRange enum
carrier->q_OffsetFreq = qoff;
// Optional threshX_Q struct
carrier->threshX_Q = (decltype(carrier->threshX_Q))calloc_or_fail(1, sizeof(*carrier->threshX_Q));
carrier->threshX_Q->threshX_HighQ = 0;
carrier->threshX_Q->threshX_LowQ = 0;
auto try_encode = [](NR_SIB4_t *s, bool expect_success) {
byte_array_t ba = do_SIB4_NR(s);
int len = (int)ba.len;
if (expect_success) {
EXPECT_GT(len, 0);
EXPECT_NE(ba.buf, nullptr);
} else {
EXPECT_LE(len, 0);
}
free_byte_array(ba);
};
// Valid lower bounds for all constrained scalars
carrier->q_RxLevMin = -70;
carrier->t_ReselectionNR = 0;
carrier->threshX_HighP = 0;
carrier->threshX_LowP = 0;
carrier->threshX_Q->threshX_HighQ = 0;
carrier->threshX_Q->threshX_LowQ = 0;
*qoff = 15;
try_encode(sib4, true);
// Invalid q_RxLevMin (below ASN.1 range)
carrier->q_RxLevMin = -80;
carrier->t_ReselectionNR = 0;
try_encode(sib4, false);
// Invalid t_ReselectionNR (above ASN.1 range)
carrier->q_RxLevMin = -70;
carrier->t_ReselectionNR = 8;
try_encode(sib4, false);
// Restore valid q_RxLevMin / t_ReselectionNR
carrier->q_RxLevMin = -70;
carrier->t_ReselectionNR = 0;
// Invalid threshX_HighP (below 0)
carrier->threshX_HighP = -1;
try_encode(sib4, false);
carrier->threshX_HighP = 0;
// Invalid threshX_LowP (below 0)
carrier->threshX_LowP = -1;
try_encode(sib4, false);
carrier->threshX_LowP = 0;
// Invalid threshX_HighQ (below 0)
carrier->threshX_Q->threshX_HighQ = -1;
try_encode(sib4, false);
carrier->threshX_Q->threshX_HighQ = 0;
// Invalid threshX_LowQ (below 0)
carrier->threshX_Q->threshX_LowQ = -1;
try_encode(sib4, false);
carrier->threshX_Q->threshX_LowQ = 0;
// Invalid q_OffsetFreq (outside [-24,24] enum range)
*qoff = 99;
try_encode(sib4, false);
ASN_STRUCT_FREE(asn_DEF_NR_SIB4, sib4);
}
int main(int argc, char **argv)
{
logInit();