finished the function to compute diffs between cells/measObjs of two var_meas_cfg objects. Added tests for this. Now the update of a UE's var_meas_cfg is made via a shared pointer.

This commit is contained in:
Francisco Paisana 2019-10-31 12:52:28 +00:00
parent b7559171b7
commit 1524e28c3a
5 changed files with 300 additions and 130 deletions

View File

@ -196,7 +196,7 @@ public:
const T* begin() const { return &data_[0]; }
const T* end() const { return &data_[size()]; }
using iterator = T*;
using const_iterator = T*;
using const_iterator = const T*;
private:
T* data_ = nullptr;

View File

@ -43,11 +43,11 @@ public:
std::tuple<bool, meas_obj_t*, meas_cell_t*> add_cell_cfg(const meas_cell_cfg_t& cellcfg);
uint32_t get_new_obj_id();
void compute_diff_meas_cfg(const var_meas_cfg_t& target_cfg, asn1::rrc::meas_cfg_s* meas_cfg);
void compute_diff_meas_objs(const var_meas_cfg_t& target_cfg, asn1::rrc::meas_cfg_s* meas_cfg);
void compute_diff_meas_cfg(const var_meas_cfg_t& target_cfg, asn1::rrc::meas_cfg_s* meas_cfg) const;
void compute_diff_meas_objs(const var_meas_cfg_t& target_cfg, asn1::rrc::meas_cfg_s* meas_cfg) const;
void compute_diff_cells(const asn1::rrc::meas_obj_eutra_s& target_it,
asn1::rrc::meas_obj_eutra_s& src_it,
asn1::rrc::meas_obj_to_add_mod_s* added_obj);
const asn1::rrc::meas_obj_eutra_s& src_it,
asn1::rrc::meas_obj_to_add_mod_s* added_obj) const;
// getters
const asn1::rrc::meas_obj_to_add_mod_list_l& meas_objs() const { return var_meas.meas_obj_list; }
@ -62,7 +62,7 @@ class rrc::mobility_cfg
public:
explicit mobility_cfg(rrc* outer_rrc);
var_meas_cfg_t current_meas_cfg;
std::shared_ptr<const var_meas_cfg_t> current_meas_cfg; ///< const to enable ptr comparison as identity comparison
private:
rrc* rrc_enb = nullptr;
@ -82,7 +82,7 @@ private:
srslte::log* rrc_log = nullptr;
// vars
var_meas_cfg_t ue_var_meas;
std::shared_ptr<const var_meas_cfg_t> ue_var_meas;
class mobility_proc_t
{

View File

@ -1908,6 +1908,10 @@ void rrc::ue::send_connection_reconf(srslte::unique_byte_buffer_t pdu)
conn_reconf->ded_info_nas_list.resize(0);
}
if (mobility_handler != nullptr) {
mobility_handler->fill_conn_recfg_msg(conn_reconf);
}
// Reuse same PDU
pdu->clear();

View File

@ -33,6 +33,49 @@ namespace srsenb {
using namespace asn1::rrc;
/*************************************************************************************************
* Convenience Functions to handle ASN1 MeasObjs/MeasId/ReportCfg/Cells/etc.
************************************************************************************************/
//! Convenience operator== overload to compare Fields of MeasObj/MeasId/ReportCfg/Cells/etc.
bool operator==(const cells_to_add_mod_s& lhs, const cells_to_add_mod_s& rhs)
{
return lhs.cell_idx == rhs.cell_idx and lhs.pci == rhs.pci and
lhs.cell_individual_offset == rhs.cell_individual_offset;
}
bool operator==(const meas_obj_to_add_mod_s& lhs, const meas_obj_to_add_mod_s& rhs)
{
if (lhs.meas_obj_id != rhs.meas_obj_id or lhs.meas_obj.type() != lhs.meas_obj.type()) {
return false;
}
auto &lhs_eutra = lhs.meas_obj.meas_obj_eutra(), &rhs_eutra = rhs.meas_obj.meas_obj_eutra();
if (lhs_eutra.ext or rhs_eutra.ext) {
printf("[%d] extension of measObjToAddMod not supported\n", __LINE__);
return false;
}
if (lhs_eutra.offset_freq_present != rhs_eutra.offset_freq_present or
(lhs_eutra.offset_freq_present and lhs_eutra.offset_freq != rhs_eutra.offset_freq)) {
return false;
}
if (lhs_eutra.carrier_freq != rhs_eutra.carrier_freq or not(lhs_eutra.neigh_cell_cfg == rhs_eutra.neigh_cell_cfg) or
lhs_eutra.presence_ant_port1 != rhs_eutra.presence_ant_port1 or
lhs_eutra.allowed_meas_bw != rhs_eutra.allowed_meas_bw) {
return false;
}
if (lhs_eutra.cells_to_add_mod_list.size() != rhs_eutra.cells_to_add_mod_list.size()) {
return false;
}
auto cells_are_equal = [](const cells_to_add_mod_s& lhs, const cells_to_add_mod_s& rhs) { return lhs == rhs; };
return std::equal(lhs_eutra.cells_to_add_mod_list.begin(),
lhs_eutra.cells_to_add_mod_list.end(),
rhs_eutra.cells_to_add_mod_list.begin(),
cells_are_equal);
}
namespace rrc_details {
//! extract cell id from ECI
@ -41,21 +84,34 @@ uint32_t eci_to_cellid(uint32_t eci)
return eci & 0xFFu;
}
//! cell comparison based on content
bool cells_are_equal(const cells_to_add_mod_s& lhs, const cells_to_add_mod_s& rhs)
//! convenience function overload to extract Id from MeasObj/MeasId/ReportCfg/Cells
uint8_t get_id(const cells_to_add_mod_s& obj)
{
return lhs.cell_idx == rhs.cell_idx and lhs.pci == rhs.pci and
lhs.cell_individual_offset == rhs.cell_individual_offset;
return obj.cell_idx;
}
uint8_t get_id(const meas_obj_to_add_mod_s& obj)
{
return obj.meas_obj_id;
}
//! convenience function overload to print MeasObj/MeasId/etc. fields
std::string to_string(const cells_to_add_mod_s& obj)
{
char buf[128];
std::snprintf(
buf, 128, "{cell_idx: %d, pci: %d, offset: %d}", obj.cell_idx, obj.pci, obj.cell_individual_offset.to_number());
return {buf};
}
//! meas field comparison based on ID solely
template <typename T, typename IdType, IdType T::*field>
template <typename T>
struct field_id_cmp {
bool operator()(const T& lhs, const T& rhs) const { return lhs.*field < rhs.*field; }
bool operator()(const T& lhs, IdType id) const { return lhs.*field < id; }
using IdType = decltype(get_id(T{}));
bool operator()(const T& lhs, const T& rhs) const { return get_id(lhs) < get_id(rhs); }
bool operator()(const T& lhs, IdType id) const { return get_id(lhs) < id; }
};
using cell_id_cmp = field_id_cmp<cells_to_add_mod_s, uint8_t, &cells_to_add_mod_s::cell_idx>;
using meas_obj_id_cmp = field_id_cmp<meas_obj_to_add_mod_s, uint8_t, &meas_obj_to_add_mod_s::meas_obj_id>;
using cell_id_cmp = field_id_cmp<cells_to_add_mod_s>;
using meas_obj_id_cmp = field_id_cmp<meas_obj_to_add_mod_s>;
//! Find MeasObj with same earfcn
meas_obj_to_add_mod_s* find_meas_obj(meas_obj_to_add_mod_list_l& l, uint32_t earfcn)
@ -96,8 +152,9 @@ cells_to_add_mod_s* meascfg_add_cell(meas_obj_eutra_s& eutra_obj, const cells_to
{
// create new cell_id in the provided eutra_obj.
// if the cell_id already exists, just update the fields.
eutra_obj.cells_to_add_mod_list_present = true;
// find the cell.
// find the cell. Assumes sorted list
auto& l = eutra_obj.cells_to_add_mod_list;
auto found_it = std::lower_bound(l.begin(), l.end(), celltoadd.cell_idx, rrc_details::cell_id_cmp{});
if (found_it == l.end()) {
@ -115,8 +172,7 @@ cells_to_add_mod_s* meascfg_add_cell(meas_obj_eutra_s& eutra_obj, const cells_to
/**
* Adds MeasObjtoAddMod to MeasCfg object
*/
meas_obj_to_add_mod_s*
meascfg_add_meas_obj(meas_cfg_s* meas_cfg, const meas_obj_to_add_mod_s& meas_obj, bool add_cells_flag)
meas_obj_to_add_mod_s* meascfg_add_meas_obj(meas_cfg_s* meas_cfg, const meas_obj_to_add_mod_s& meas_obj)
{
meas_cfg->meas_obj_to_add_mod_list_present = true;
meas_obj_to_add_mod_list_l& l = meas_cfg->meas_obj_to_add_mod_list;
@ -139,47 +195,55 @@ meascfg_add_meas_obj(meas_cfg_s* meas_cfg, const meas_obj_to_add_mod_s& meas_obj
target_eutra.presence_ant_port1 = src_eutra.presence_ant_port1;
target_eutra.neigh_cell_cfg = src_eutra.neigh_cell_cfg;
if (add_cells_flag) {
for (const cells_to_add_mod_s& cell_it : src_eutra.cells_to_add_mod_list) {
rrc_details::meascfg_add_cell(target_eutra, cell_it);
}
}
return found_it;
}
//! Find difference between MeasObjs
bool meas_objs_are_equal(const meas_obj_to_add_mod_s& lhs, const meas_obj_to_add_mod_s& rhs)
{
if (lhs.meas_obj_id != rhs.meas_obj_id or lhs.meas_obj.type() != lhs.meas_obj.type()) {
return false;
}
auto &lhs_eutra = lhs.meas_obj.meas_obj_eutra(), &rhs_eutra = rhs.meas_obj.meas_obj_eutra();
if (lhs_eutra.ext or rhs_eutra.ext) {
printf("[%d] extension of measObjToAddMod not supported\n", __LINE__);
return false;
/*
* Algorithm to compare differences between Meas Fields. This is used for MeasObjs, Cells, ReportConfig, MeasId (and
* more in the future)
* Returns outcome==same_id, if two fields were spotted with same id, "id_removed" if an id was removed from the target
* "id_added" if an id was added to the target, and complete when the iteration is over
*/
enum class diff_outcome_t { same_id, id_removed, id_added, complete };
template <typename Container>
struct compute_diff_generator {
using const_iterator = typename Container::const_iterator;
struct result_t {
diff_outcome_t outcome;
const_iterator src_it;
const_iterator target_it;
};
compute_diff_generator(const Container& src, const Container& target) :
src_it(src.begin()),
src_end(src.end()),
target_it(target.begin()),
target_end(target.end())
{
}
if (lhs_eutra.offset_freq_present != rhs_eutra.offset_freq_present or
(lhs_eutra.offset_freq_present and lhs_eutra.offset_freq != rhs_eutra.offset_freq)) {
return false;
result_t next()
{
bool src_left = src_it != src_end;
bool target_left = target_it != target_end;
if (not src_left and not target_left) {
return {diff_outcome_t::complete, nullptr, nullptr};
}
if (not target_left or (src_left and get_id(*src_it) < get_id(*target_it))) {
// an object has been removed from the target
return {diff_outcome_t::id_removed, src_it++, target_it};
}
if (not src_left or (target_left and get_id(*src_it) > get_id(*target_it))) {
// a new object has been added to target
return {diff_outcome_t::id_added, src_it, target_it++};
}
// Same ID
return {diff_outcome_t::same_id, src_it++, target_it++};
}
if (lhs_eutra.carrier_freq != rhs_eutra.carrier_freq or not(lhs_eutra.neigh_cell_cfg == rhs_eutra.neigh_cell_cfg) or
lhs_eutra.presence_ant_port1 != rhs_eutra.presence_ant_port1 or
lhs_eutra.allowed_meas_bw != rhs_eutra.allowed_meas_bw) {
return false;
}
if (lhs_eutra.cells_to_add_mod_list.size() != rhs_eutra.cells_to_add_mod_list.size()) {
return false;
}
return std::equal(lhs_eutra.cells_to_add_mod_list.begin(),
lhs_eutra.cells_to_add_mod_list.end(),
rhs_eutra.cells_to_add_mod_list.begin(),
cells_are_equal);
}
private:
const_iterator src_it, src_end, target_it, target_end;
};
} // namespace rrc_details
@ -264,8 +328,9 @@ uint32_t var_meas_cfg_t::get_new_obj_id()
return (prev_it == var_meas.meas_obj_list.end()) ? 1 : prev_it->meas_obj_id + 1; // starts at 1.
}
void var_meas_cfg_t::compute_diff_meas_cfg(const var_meas_cfg_t& target_cfg, asn1::rrc::meas_cfg_s* meas_cfg)
void var_meas_cfg_t::compute_diff_meas_cfg(const var_meas_cfg_t& target_cfg, asn1::rrc::meas_cfg_s* meas_cfg) const
{
*meas_cfg = {};
// TODO: Create a flag to disable changing the "this" members (useful for transparent container)
// Set a MeasConfig in the RRC Connection Reconfiguration for HO.
compute_diff_meas_objs(target_cfg, meas_cfg);
@ -280,75 +345,78 @@ void var_meas_cfg_t::compute_diff_meas_cfg(const var_meas_cfg_t& target_cfg, asn
//! adds all the cells that got updated to MeasCfg.
void var_meas_cfg_t::compute_diff_cells(const meas_obj_eutra_s& target_it,
meas_obj_eutra_s& src_it,
meas_obj_to_add_mod_s* added_obj)
const meas_obj_eutra_s& src_it,
meas_obj_to_add_mod_s* added_obj) const
{
cells_to_add_mod_s* src_cell = src_it.cells_to_add_mod_list.begin();
const cells_to_add_mod_s* target_cell = target_it.cells_to_add_mod_list.begin();
bool src_left = src_cell != src_it.cells_to_add_mod_list.end();
bool target_left = target_cell != target_it.cells_to_add_mod_list.end();
while (src_left or target_left) {
if (not target_left or (src_left and src_cell->cell_idx < target_cell->cell_idx)) {
// a cell was removed from the eNB
// TODO: add cell to remove list
++src_cell;
} else if (not src_left or (target_left and src_cell->cell_idx > target_cell->cell_idx)) {
// a cell was added to the eNB
Info("UE has now to measure activity of (earfcn,cell_id)=(%d,%d).\n", target_cell->cell_idx, target_cell->pci);
rrc_details::meascfg_add_cell(added_obj->meas_obj.meas_obj_eutra(), *target_cell);
} else {
// check if cells are the same. if not, update.
if (not rrc_details::cells_are_equal(*src_cell, *target_cell)) {
Info("UE has now to measure activity of (earfcn,cell_id)=(%d,%d) with updated params.\n",
target_cell->cell_idx,
target_cell->pci);
rrc_details::meascfg_add_cell(added_obj->meas_obj.meas_obj_eutra(), *target_cell);
*src_cell = *target_cell;
}
++src_cell;
++target_cell;
rrc_details::compute_diff_generator<cells_to_add_mod_list_l> diffs{src_it.cells_to_add_mod_list,
target_it.cells_to_add_mod_list};
meas_obj_eutra_s* eutra_obj = &added_obj->meas_obj.meas_obj_eutra();
while (true) {
auto result = diffs.next();
switch (result.outcome) {
case rrc_details::diff_outcome_t::complete:
return;
case rrc_details::diff_outcome_t::id_removed:
Info("UE can now cease to measure activity of cell %s.\n", rrc_details::to_string(*result.target_it).c_str());
eutra_obj->cells_to_rem_list_present = true;
eutra_obj->cells_to_rem_list.push_back(result.src_it->cell_idx);
break;
case rrc_details::diff_outcome_t::id_added:
Info("UE has now to measure activity of %s.\n", rrc_details::to_string(*result.target_it).c_str());
rrc_details::meascfg_add_cell(*eutra_obj, *result.target_it);
break;
case rrc_details::diff_outcome_t::same_id:
// check if cells are the same. if not, update.
if (not(*result.src_it == *result.target_it)) {
Info("UE has now to measure activity of %s with updated params.\n",
rrc_details::to_string(*result.target_it).c_str());
rrc_details::meascfg_add_cell(*eutra_obj, *result.target_it);
}
break;
}
src_left = src_cell != src_it.cells_to_add_mod_list.end();
target_left = target_cell != target_it.cells_to_add_mod_list.end();
}
}
//! compute diff between target_cfg and var_meas -> depending on diff, add/remove/update meas_obj in meas_cfg
void var_meas_cfg_t::compute_diff_meas_objs(const var_meas_cfg_t& target_cfg, meas_cfg_s* meas_cfg)
void var_meas_cfg_t::compute_diff_meas_objs(const var_meas_cfg_t& target_cfg, meas_cfg_s* meas_cfg) const
{
// TODO: black cells and white cells
rrc_details::compute_diff_generator<meas_obj_to_add_mod_list_l> diffs{var_meas.meas_obj_list,
target_cfg.var_meas.meas_obj_list};
meas_obj_t * ue_it = var_meas.meas_obj_list.begin(), *ue_end = var_meas.meas_obj_list.end();
const meas_obj_t *target_it = target_cfg.var_meas.meas_obj_list.begin(),
*target_end = target_cfg.var_meas.meas_obj_list.end();
bool ues_left = ue_it != ue_end;
bool enbs_left = target_it != target_end;
while (ues_left or enbs_left) {
if (not enbs_left or (ues_left and ue_it->meas_obj_id < target_it->meas_obj_id)) {
// an object has been removed from the target_var_meas
Info("UE can cease to measure activity in frequency earfcn=%d.\n", ue_it->meas_obj.meas_obj_eutra().carrier_freq);
// TODO: add to remove list
++ue_it;
} else if (!ues_left or (enbs_left and ue_it->meas_obj_id > target_it->meas_obj_id)) {
// a new object has been added to enb_var_meas
Info("HO: UE has now to measure activity of new frequency earfcn=%d.\n",
target_it->meas_obj.meas_obj_eutra().carrier_freq);
rrc_details::meascfg_add_meas_obj(meas_cfg, *target_it, true);
++target_it;
} else {
bool are_equal = rrc_details::meas_objs_are_equal(*ue_it, *target_it);
if (not are_equal) {
// if we found a difference in obj IDs
meas_obj_to_add_mod_s* added_obj = rrc_details::meascfg_add_meas_obj(meas_cfg, *target_it, false);
// Add cells/meas_obj if there were changes.
compute_diff_cells(target_it->meas_obj.meas_obj_eutra(), ue_it->meas_obj.meas_obj_eutra(), added_obj);
}
++ue_it;
++target_it;
while (true) {
auto result = diffs.next();
switch (result.outcome) {
case rrc_details::diff_outcome_t::complete:
return;
case rrc_details::diff_outcome_t::id_removed:
Info("UE can cease to measure activity in frequency earfcn=%d.\n",
result.src_it->meas_obj.meas_obj_eutra().carrier_freq);
meas_cfg->meas_obj_to_rem_list_present = true;
meas_cfg->meas_obj_to_rem_list.push_back(result.src_it->meas_obj_id);
break;
case rrc_details::diff_outcome_t::id_added: {
Info("HO: UE has now to measure activity of new frequency earfcn=%d.\n",
result.target_it->meas_obj.meas_obj_eutra().carrier_freq);
auto& target_eutra = result.target_it->meas_obj.meas_obj_eutra();
auto& added_eutra = rrc_details::meascfg_add_meas_obj(meas_cfg, *result.target_it)->meas_obj.meas_obj_eutra();
// add all cells in measCfg
for (const cells_to_add_mod_s& cell_it : target_eutra.cells_to_add_mod_list) {
rrc_details::meascfg_add_cell(added_eutra, cell_it);
}
} break;
case rrc_details::diff_outcome_t::same_id:
bool are_equal = *result.src_it == *result.target_it;
if (not are_equal) {
// if we found a difference in obj IDs
meas_obj_to_add_mod_s* added_obj = rrc_details::meascfg_add_meas_obj(meas_cfg, *result.target_it);
// Add cells if there were changes.
compute_diff_cells(
result.target_it->meas_obj.meas_obj_eutra(), result.src_it->meas_obj.meas_obj_eutra(), added_obj);
}
break;
}
ues_left = ue_it != ue_end;
enbs_left = target_it != target_end;
}
}
@ -356,14 +424,18 @@ void var_meas_cfg_t::compute_diff_meas_objs(const var_meas_cfg_t& target_cfg, me
* mobility_cfg class
************************************************************************************************/
rrc::mobility_cfg::mobility_cfg(rrc* outer_rrc) : rrc_enb(outer_rrc), current_meas_cfg(outer_rrc->rrc_log)
rrc::mobility_cfg::mobility_cfg(rrc* outer_rrc) : rrc_enb(outer_rrc)
{
var_meas_cfg_t var_meas{outer_rrc->rrc_log};
// inserts all neighbor cells
if (rrc_enb->cfg.meas_cfg_present) {
for (meas_cell_cfg_t& meascell : rrc_enb->cfg.meas_cfg.meas_cells) {
current_meas_cfg.add_cell_cfg(meascell);
var_meas.add_cell_cfg(meascell);
}
}
current_meas_cfg = std::make_shared<var_meas_cfg_t>(var_meas);
}
/*************************************************************************************************
@ -375,9 +447,9 @@ rrc::ue::rrc_mobility::rrc_mobility(rrc::ue* outer_ue) :
rrc_enb(outer_ue->parent),
cfg(outer_ue->parent->enb_mobility_cfg.get()),
pool(outer_ue->pool),
rrc_log(outer_ue->parent->rrc_log),
ue_var_meas(outer_ue->parent->rrc_log)
rrc_log(outer_ue->parent->rrc_log)
{
ue_var_meas = std::make_shared<var_meas_cfg_t>(outer_ue->parent->rrc_log);
}
bool rrc::ue::rrc_mobility::fill_conn_recfg_msg(asn1::rrc::rrc_conn_recfg_r8_ies_s* conn_recfg)
@ -387,8 +459,14 @@ bool rrc::ue::rrc_mobility::fill_conn_recfg_msg(asn1::rrc::rrc_conn_recfg_r8_ies
return false;
}
// Check if there has been any update
if (ue_var_meas.get() == cfg->current_meas_cfg.get()) {
return false;
}
asn1::rrc::meas_cfg_s* meas_cfg = &conn_recfg->meas_cfg;
ue_var_meas.compute_diff_meas_cfg(cfg->current_meas_cfg, meas_cfg);
ue_var_meas->compute_diff_meas_cfg(*cfg->current_meas_cfg, meas_cfg);
ue_var_meas = cfg->current_meas_cfg;
// if there is at least one difference, we tag a new measurement report in conn_reconf.
bool diff = meas_cfg->meas_obj_to_add_mod_list_present;

View File

@ -36,20 +36,32 @@ using namespace asn1::rrc;
srslte::log_filter log_h("ALL");
int test_correct_insertion()
meas_cell_cfg_t generate_cell1()
{
meas_cell_cfg_t cell1{}, cell2{}, cell3{}, cell4{};
meas_cell_cfg_t cell1{};
cell1.earfcn = 3400;
cell1.pci = 1;
cell1.q_offset = 0;
cell1.cell_id = 0x19C01;
cell2 = cell1;
cell2.pci = 2;
cell2.cell_id = 0x19C02;
cell3 = cell1;
cell3.earfcn = 2850;
cell4 = cell1;
cell4.q_offset = 1;
return cell1;
}
bool is_cell_cfg_equal(const meas_cell_cfg_t& cfg, const cells_to_add_mod_s& cell)
{
return cfg.pci == cell.pci and cell.cell_individual_offset.to_number() == (int8_t)round(cfg.q_offset) and
cell.cell_idx == (cfg.cell_id & 0xFFu);
}
int test_correct_insertion()
{
meas_cell_cfg_t cell1 = generate_cell1(), cell2{}, cell3{}, cell4{};
cell2 = cell1;
cell2.pci = 2;
cell2.cell_id = 0x19C02;
cell3 = cell1;
cell3.earfcn = 2850;
cell4 = cell1;
cell4.q_offset = 1;
// TEST 1: cell insertion in empty varMeasCfg
{
@ -63,9 +75,7 @@ int test_correct_insertion()
auto& eutra = objs[0].meas_obj.meas_obj_eutra();
TESTASSERT(eutra.carrier_freq == cell1.earfcn);
TESTASSERT(eutra.cells_to_add_mod_list.size() == 1);
TESTASSERT(eutra.cells_to_add_mod_list[0].pci == cell1.pci);
TESTASSERT(eutra.cells_to_add_mod_list[0].cell_idx == (cell1.cell_id & 0xFFu));
TESTASSERT(eutra.cells_to_add_mod_list[0].cell_individual_offset.to_number() == (int8_t)round(cell1.q_offset));
TESTASSERT(is_cell_cfg_equal(cell1, eutra.cells_to_add_mod_list[0]));
}
{
@ -106,9 +116,87 @@ int test_correct_insertion()
return 0;
}
int test_correct_meascfg_calculation()
{
var_meas_cfg_t src_var(&log_h), target_var(&log_h);
meas_cell_cfg_t cell1{}, cell2{};
cell1.earfcn = 3400;
cell1.pci = 1;
cell1.q_offset = 0;
cell1.cell_id = 0x19C01;
cell2 = cell1;
cell2.pci = 2;
cell2.cell_id = 0x19C02;
{
meas_cfg_s result_meascfg;
// TEST: Insertion of two cells in var_meas propagates to the resulting meas_cfg_s cellsToAddMod list
target_var.add_cell_cfg(cell1);
target_var.add_cell_cfg(cell2);
src_var.compute_diff_meas_cfg(target_var, &result_meascfg);
TESTASSERT(result_meascfg.meas_obj_to_add_mod_list_present);
TESTASSERT(not result_meascfg.meas_obj_to_rem_list_present);
TESTASSERT(result_meascfg.meas_obj_to_add_mod_list.size() == 1);
auto* item = &result_meascfg.meas_obj_to_add_mod_list[0];
TESTASSERT(item->meas_obj_id == 1 and
item->meas_obj.type().value == meas_obj_to_add_mod_s::meas_obj_c_::types_opts::meas_obj_eutra);
auto& eutra = item->meas_obj.meas_obj_eutra();
TESTASSERT(eutra.cells_to_add_mod_list_present and not eutra.cells_to_rem_list_present);
TESTASSERT(eutra.cells_to_add_mod_list.size() == 2);
auto* cell_item = &eutra.cells_to_add_mod_list[0];
TESTASSERT(is_cell_cfg_equal(cell1, *cell_item));
cell_item++;
TESTASSERT(is_cell_cfg_equal(cell2, *cell_item));
// TEST: if measCfg is empty if nothing was updated
src_var = target_var;
src_var.compute_diff_meas_cfg(target_var, &result_meascfg);
TESTASSERT(not result_meascfg.meas_obj_to_add_mod_list_present);
TESTASSERT(result_meascfg.meas_obj_to_add_mod_list.size() == 0);
// TEST: Cell is added to cellsToAddModList if just a field was updated
cell1.pci = 3;
src_var = target_var;
target_var.add_cell_cfg(cell1);
src_var.compute_diff_meas_cfg(target_var, &result_meascfg);
TESTASSERT(result_meascfg.meas_obj_to_add_mod_list_present);
TESTASSERT(result_meascfg.meas_obj_to_add_mod_list.size() == 1);
item = &result_meascfg.meas_obj_to_add_mod_list[0];
TESTASSERT(item->meas_obj_id == 1 and
item->meas_obj.type().value == meas_obj_to_add_mod_s::meas_obj_c_::types_opts::meas_obj_eutra);
eutra = item->meas_obj.meas_obj_eutra();
TESTASSERT(eutra.cells_to_add_mod_list_present and not eutra.cells_to_rem_list_present);
TESTASSERT(eutra.cells_to_add_mod_list.size() == 1);
cell_item = &eutra.cells_to_add_mod_list[0];
TESTASSERT(is_cell_cfg_equal(cell1, *cell_item));
// TEST: Removal of cell from target propagates to the resulting meas_cfg_s cellsToRemoveList
src_var = target_var;
target_var = var_meas_cfg_t{&log_h};
target_var.add_cell_cfg(cell2);
src_var.compute_diff_meas_cfg(target_var, &result_meascfg);
TESTASSERT(result_meascfg.meas_obj_to_add_mod_list_present);
TESTASSERT(result_meascfg.meas_obj_to_add_mod_list.size() == 1);
item = &result_meascfg.meas_obj_to_add_mod_list[0];
TESTASSERT(item->meas_obj_id == 1 and
item->meas_obj.type().value == meas_obj_to_add_mod_s::meas_obj_c_::types_opts::meas_obj_eutra);
eutra = item->meas_obj.meas_obj_eutra();
TESTASSERT(not eutra.cells_to_add_mod_list_present and eutra.cells_to_rem_list_present);
TESTASSERT(eutra.cells_to_rem_list.size() == 1);
TESTASSERT(eutra.cells_to_rem_list[0] == (cell1.cell_id & 0xFFu));
}
return SRSLTE_SUCCESS;
}
int main()
{
TESTASSERT(test_correct_insertion() == 0);
TESTASSERT(test_correct_meascfg_calculation() == 0);
printf("Success\n");
return 0;
}