LoRaPHY unittested, small fixed done during tests

pull/8233/head
Antti Kauppila 2018-09-19 16:20:20 +03:00
parent 0f8cfd8631
commit f3d402f70e
14 changed files with 1142 additions and 136 deletions

View File

@ -20,17 +20,17 @@ set(unittest-sources
# Test files
set(unittest-test-sources
features/cellular/framework/AT/at_cellulardevice/at_cellulardevicetest.cpp
stubs/AT_CellularNetwork_stub.cpp
stubs/ATHandler_stub.cpp
stubs/AT_CellularSMS_stub.cpp
stubs/AT_CellularSIM_stub.cpp
stubs/AT_CellularPower_stub.cpp
stubs/AT_CellularInformation_stub.cpp
stubs/CellularUtil_stub.cpp
stubs/AT_CellularBase_stub.cpp
stubs/NetworkInterface_stub.cpp
stubs/EventQueue_stub.cpp
stubs/FileHandle_stub.cpp
stubs/mbed_assert_stub.cpp
stubs/AT_CellularNetwork_stub.cpp
stubs/ATHandler_stub.cpp
stubs/AT_CellularSMS_stub.cpp
stubs/AT_CellularSIM_stub.cpp
stubs/AT_CellularPower_stub.cpp
stubs/AT_CellularInformation_stub.cpp
stubs/CellularUtil_stub.cpp
stubs/AT_CellularBase_stub.cpp
stubs/NetworkInterface_stub.cpp
stubs/EventQueue_stub.cpp
stubs/FileHandle_stub.cpp
stubs/mbed_assert_stub.c
stubs/CellularDevice_stub.cpp
)

View File

@ -18,13 +18,79 @@
#include "gtest/gtest.h"
#include "LoRaPHY.h"
#include "LoRaWANTimer_stub.h"
class my_LoRaPHY : public LoRaPHY
{
public:
my_LoRaPHY(){};
my_LoRaPHY(){phy_params.adr_ack_delay = 1;}
virtual ~my_LoRaPHY(){};
virtual ~my_LoRaPHY(){}
loraphy_params_t &get_phy_params() {
return phy_params;
}
};
class my_radio : public LoRaRadio
{
public:
virtual void init_radio(radio_events_t *events){};
virtual void radio_reset(){};
virtual void sleep(void){};
virtual void standby(void){};
virtual void set_rx_config (radio_modems_t modem, uint32_t bandwidth,
uint32_t datarate, uint8_t coderate,
uint32_t bandwidth_afc, uint16_t preamble_len,
uint16_t symb_timeout, bool fix_len,
uint8_t payload_len,
bool crc_on, bool freq_hop_on, uint8_t hop_period,
bool iq_inverted, bool rx_continuous){};
virtual void set_tx_config(radio_modems_t modem, int8_t power, uint32_t fdev,
uint32_t bandwidth, uint32_t datarate,
uint8_t coderate, uint16_t preamble_len,
bool fix_len, bool crc_on, bool freq_hop_on,
uint8_t hop_period, bool iq_inverted, uint32_t timeout){};
virtual void send(uint8_t *buffer, uint8_t size){};
virtual void receive(void){};
virtual void set_channel(uint32_t freq){};
virtual uint32_t random(void){};
virtual uint8_t get_status(void){return uint8_value;};
virtual void set_max_payload_length(radio_modems_t modem, uint8_t max){};
virtual void set_public_network(bool enable){};
virtual uint32_t time_on_air(radio_modems_t modem, uint8_t pkt_len){};
virtual bool perform_carrier_sense(radio_modems_t modem,
uint32_t freq,
int16_t rssi_threshold,
uint32_t max_carrier_sense_time){ return bool_value;};
virtual void start_cad(void){};
virtual bool check_rf_frequency(uint32_t frequency){ return bool_value; };
virtual void set_tx_continuous_wave(uint32_t freq, int8_t power, uint16_t time){};
virtual void lock(void){};
virtual void unlock(void){};
bool bool_value;
uint8_t uint8_value;
};
class Test_LoRaPHY : public testing::Test {
@ -42,8 +108,706 @@ protected:
}
};
TEST_F(Test_LoRaPHY, constructor)
TEST_F(Test_LoRaPHY, initialize)
{
EXPECT_TRUE(object);
object->initialize(NULL);
}
TEST_F(Test_LoRaPHY, set_radio_instance)
{
my_radio radio;
object->set_radio_instance(radio);
}
TEST_F(Test_LoRaPHY, put_radio_to_sleep)
{
my_radio radio;
object->set_radio_instance(radio);
object->put_radio_to_sleep();
}
TEST_F(Test_LoRaPHY, put_radio_to_standby)
{
my_radio radio;
object->set_radio_instance(radio);
object->put_radio_to_standby();
}
TEST_F(Test_LoRaPHY, handle_receive)
{
my_radio radio;
object->set_radio_instance(radio);
object->handle_receive();
}
TEST_F(Test_LoRaPHY, handle_send)
{
my_radio radio;
object->set_radio_instance(radio);
object->handle_send(NULL, 0);
}
TEST_F(Test_LoRaPHY, setup_public_network_mode)
{
my_radio radio;
channel_params_t p;
object->get_phy_params().channels.channel_list = &p;
object->set_radio_instance(radio);
object->setup_public_network_mode(false);
}
TEST_F(Test_LoRaPHY, get_radio_rng)
{
my_radio radio;
object->set_radio_instance(radio);
EXPECT_TRUE(0 != object->get_radio_rng());
}
TEST_F(Test_LoRaPHY, calculate_backoff)
{
channel_params_t p[1];
p[0].band = 0;
object->get_phy_params().channels.channel_list = p;
band_t b[1];
object->get_phy_params().bands.table = b;
object->calculate_backoff(false, false, false, 0, 10, 12);
object->calculate_backoff(false, true, false, 0, 3600000 + 10, 12);
object->calculate_backoff(false, false, true, 0, 3600000 + 36000000 + 10, 12);
}
TEST_F(Test_LoRaPHY, mask_bit_test)
{
uint16_t buf;
EXPECT_TRUE(!object->mask_bit_test(&buf, 0));
}
TEST_F(Test_LoRaPHY, mask_bit_set)
{
uint16_t buf;
object->mask_bit_set(&buf, 3);
}
TEST_F(Test_LoRaPHY, mask_bit_clear)
{
uint16_t buf;
object->mask_bit_clear(&buf, 0);
}
TEST_F(Test_LoRaPHY, request_new_channel)
{
channel_params_t p;
EXPECT_TRUE(0 == object->request_new_channel(1, &p));
p.frequency = 0;
object->get_phy_params().custom_channelplans_supported = true;
uint16_t list;
object->get_phy_params().channels.default_mask = &list;
channel_params_t pp;
object->get_phy_params().channels.channel_list = &pp;
EXPECT_TRUE(0 == object->request_new_channel(1, &p));
//Default
p.frequency = 2;
EXPECT_TRUE(0 == object->request_new_channel(1, &p));
//Freq & DR invalid
object->get_phy_params().max_channel_cnt = 2;
EXPECT_TRUE(0 == object->request_new_channel(1, &p));
//Freq invalid
pp.frequency = 0;
object->get_phy_params().default_max_datarate = 1;
object->get_phy_params().max_tx_datarate = 8;
p.dr_range.fields.max = 2;
p.dr_range.fields.min = 0;
object->get_phy_params().default_channel_cnt = 3;
EXPECT_TRUE(2 == object->request_new_channel(0, &p));
//DR invalid
pp.frequency = 2;
p.band = 0;
object->get_phy_params().bands.size = 1;
band_t b;
object->get_phy_params().bands.table = &b;
b.higher_band_freq = 5;
b.lower_band_freq = 1;
p.dr_range.fields.max = 12;
p.dr_range.fields.min = 1;
EXPECT_TRUE(1 == object->request_new_channel(0, &p));
//STATUS_OK
p.dr_range.fields.max = 2;
uint16_t list2[16];
p.dr_range.fields.min = 0;
object->get_phy_params().channels.mask = list2;
EXPECT_TRUE(3 == object->request_new_channel(0, &p));
}
TEST_F(Test_LoRaPHY, set_last_tx_done)
{
channel_params_t p[1];
p[0].band = 0;
object->get_phy_params().channels.channel_list = p;
band_t b[1];
object->get_phy_params().bands.table = b;
object->set_last_tx_done(0, false, 0);
object->set_last_tx_done(0, true, 0);
}
TEST_F(Test_LoRaPHY, restore_default_channels)
{
channel_params_t p[1];
p[0].band = 0;
object->get_phy_params().channels.channel_list = p;
uint16_t m, dm;
object->get_phy_params().channels.mask_size = 1;
object->get_phy_params().channels.default_mask = &dm;
object->get_phy_params().channels.mask = &m;
object->restore_default_channels();
}
TEST_F(Test_LoRaPHY, apply_cf_list)
{
uint8_t list[16];
object->apply_cf_list(list, 0);
object->get_phy_params().cflist_supported = true;
object->apply_cf_list(list, 0);
object->get_phy_params().default_channel_cnt = 2;
object->get_phy_params().cflist_channel_cnt = 0;
object->get_phy_params().max_channel_cnt = 3;
uint16_t mask[8];
channel_params_t p[8];
object->get_phy_params().channels.default_mask = mask;
object->get_phy_params().channels.mask = mask;
object->get_phy_params().channels.channel_list = p;
object->apply_cf_list(list, 16);
list[1] = 15;
object->get_phy_params().cflist_channel_cnt = 1;
object->apply_cf_list(list, 16);
}
TEST_F(Test_LoRaPHY, get_next_ADR)
{
int8_t i = 0;
int8_t j = 0;
uint32_t ctr = 0;
object->get_phy_params().min_tx_datarate = 0;
EXPECT_TRUE(!object->get_next_ADR(false, i, j, ctr));
i = 1;
object->get_phy_params().adr_ack_limit = 3;
EXPECT_TRUE(!object->get_next_ADR(false, i, j, ctr));
object->get_phy_params().adr_ack_limit = 3;
ctr = 4;
object->get_phy_params().max_tx_power = 2;
object->get_phy_params().adr_ack_delay = 1;
EXPECT_TRUE(object->get_next_ADR(true, i, j, ctr));
ctr = 5;
object->get_phy_params().adr_ack_delay = 2;
EXPECT_TRUE(!object->get_next_ADR(true, i, j, ctr));
}
TEST_F(Test_LoRaPHY, rx_config)
{
my_radio radio;
object->set_radio_instance(radio);
uint8_t list;
object->get_phy_params().datarates.table = &list;
uint8_t list2;
object->get_phy_params().payloads_with_repeater.table = &list2;
rx_config_params_t p;
p.datarate = 0;
p.rx_slot = RX_SLOT_WIN_1;
channel_params_t pp[1];
object->get_phy_params().channels.channel_list = pp;
pp[0].rx1_frequency = 2;
p.channel = 0;
uint8_t tab[8];
object->get_phy_params().payloads.table = tab;
object->get_phy_params().payloads_with_repeater.table = tab;
EXPECT_TRUE(object->rx_config(&p));
p.datarate = DR_7;
p.is_repeater_supported = true;
object->get_phy_params().fsk_supported = true;
EXPECT_TRUE(object->rx_config(&p));
}
TEST_F(Test_LoRaPHY, compute_rx_win_params)
{
uint32_t list[1];
list[0] = 0;
object->get_phy_params().bandwidths.table = list;
uint8_t list2;
object->get_phy_params().datarates.table = &list2;
rx_config_params_t p;
object->compute_rx_win_params(0, 0, 0, &p);
p.datarate = 0;
list[0] = 125000;
object->compute_rx_win_params(0, 0, 0, &p);
list[0] = 250000;
object->compute_rx_win_params(0, 0, 0, &p);
list[0] = 500000;
object->get_phy_params().fsk_supported = true;
object->get_phy_params().max_rx_datarate = 0;
object->compute_rx_win_params(0, 0, 0, &p);
}
TEST_F(Test_LoRaPHY, tx_config)
{
band_t b;
object->get_phy_params().bands.table = &b;
channel_params_t pp;
pp.band=0;
object->get_phy_params().channels.channel_list = &pp;
uint32_t list = 0;
object->get_phy_params().bandwidths.table = &list;
uint8_t list2;
object->get_phy_params().datarates.table = &list2;
my_radio radio;
object->set_radio_instance(radio);
tx_config_params_t p;
p.channel=0;
int8_t i;
lorawan_time_t t;
object->tx_config(&p, &i, &t);
p.datarate = 8;
object->get_phy_params().max_tx_datarate = 8;
object->tx_config(&p, &i, &t);
}
TEST_F(Test_LoRaPHY, link_ADR_request)
{
adr_req_params_t p;
uint8_t b[100];
p.payload = b;
b[0] = 0x03;
b[1] = 1;
b[2] = 0;
b[3] = 0;
b[4] = 1 << 4;
b[5] = 0x03;
b[6] = 1;
b[7] = 1;
b[8] = 1;
b[9] = 6 << 4;
b[10] = 0x03;
b[11] = 1;
b[12] = 0xff;
b[13] = 0xff;
b[14] = 0;
b[15] = 0;
p.payload_size = 16;
int8_t i, j;
uint8_t k, l;
uint8_t t[5];
t[0] = 0;
object->get_phy_params().datarates.size = 1;
object->get_phy_params().datarates.table = t;
//Test without ADR payload does not make sense here.
object->get_phy_params().max_channel_cnt = 2;
channel_params_t li[4];
object->get_phy_params().channels.channel_list = li;
li[0].frequency = 0;
li[1].frequency = 5;
EXPECT_TRUE(4 == object->link_ADR_request(&p, &i, &j, &k, &l));
t[0] = 3;
//verify adr with p.adr_enabled = false
EXPECT_TRUE(0 == object->link_ADR_request(&p, &i, &j, &k, &l));
p.current_nb_rep = 0;
EXPECT_TRUE(0 == object->link_ADR_request(&p, &i, &j, &k, &l));
p.adr_enabled = true;
li[0].dr_range.value = 0xff;
object->get_phy_params().min_tx_datarate = DR_3;
object->get_phy_params().max_tx_datarate = DR_8;
//verify adr with status != 0
EXPECT_TRUE(0 == object->link_ADR_request(&p, &i, &j, &k, &l));
object->get_phy_params().max_tx_power = 2;
object->get_phy_params().min_tx_power = 6;
//verify adr with status != 0
EXPECT_TRUE(4 == object->link_ADR_request(&p, &i, &j, &k, &l));
object->get_phy_params().min_tx_datarate = DR_0;
li[0].dr_range.value = 0xf0;
EXPECT_TRUE(6 == object->link_ADR_request(&p, &i, &j, &k, &l));
li[1].dr_range.fields.min = DR_0;
li[1].dr_range.fields.max = DR_13;
b[4] = 6 << 4;
p.payload_size = 5;
EXPECT_TRUE(7 == object->link_ADR_request(&p, &i, &j, &k, &l));
uint16_t mask[2];
object->get_phy_params().channels.mask = mask;
object->get_phy_params().channels.mask_size = 2;
EXPECT_TRUE(7 == object->link_ADR_request(&p, &i, &j, &k, &l));
li[0].dr_range.value = 0xff;
object->get_phy_params().max_channel_cnt = 0;
EXPECT_TRUE(5 == object->link_ADR_request(&p, &i, &j, &k, &l));
b[0] = 0x03;
b[1] = 1;
b[2] = 0;
b[3] = 0;
b[4] = 0;
t[0] = 0;
object->get_phy_params().datarates.size = 1;
object->get_phy_params().datarates.table = t;
//Test without ADR payload does not make sense here.
object->get_phy_params().max_channel_cnt = 2;
li[0].frequency = 0;
li[1].frequency = 5;
EXPECT_TRUE(4 == object->link_ADR_request(&p, &i, &j, &k, &l));
}
TEST_F(Test_LoRaPHY, accept_rx_param_setup_req)
{
my_radio radio;
object->set_radio_instance(radio);
rx_param_setup_req_t req;
EXPECT_TRUE(0 == object->accept_rx_param_setup_req(&req));
}
TEST_F(Test_LoRaPHY, accept_tx_param_setup_req)
{
my_radio radio;
object->set_radio_instance(radio);
object->get_phy_params().accept_tx_param_setup_req = true;
EXPECT_TRUE(object->accept_tx_param_setup_req(0, 0));
}
TEST_F(Test_LoRaPHY, dl_channel_request)
{
EXPECT_TRUE(0 == object->dl_channel_request(0, 0));
object->get_phy_params().dl_channel_req_supported = true;
object->get_phy_params().bands.size = 1;
band_t t[1];
object->get_phy_params().bands.table = t;
channel_params_t p[4];
object->get_phy_params().channels.channel_list = p;
p[0].frequency = 0;
EXPECT_TRUE(0 == object->dl_channel_request(0, 1));
t[0].higher_band_freq = 19;
t[0].lower_band_freq = 0;
p[0].frequency = 1;
EXPECT_TRUE(3 == object->dl_channel_request(0, 1));
}
TEST_F(Test_LoRaPHY, get_alternate_DR)
{
EXPECT_TRUE(0 == object->get_alternate_DR(0));
object->get_phy_params().default_max_datarate = 5;
object->get_phy_params().min_tx_datarate = 4;
EXPECT_TRUE(5 == object->get_alternate_DR(1));
object->get_phy_params().default_max_datarate = 6;
object->get_phy_params().min_tx_datarate = 4;
EXPECT_TRUE(5 == object->get_alternate_DR(2));
}
TEST_F(Test_LoRaPHY, set_next_channel)
{
channel_selection_params_t p;
uint8_t ch;
lorawan_time_t t1;
lorawan_time_t t2;
EXPECT_TRUE(LORAWAN_STATUS_DUTYCYCLE_RESTRICTED == object->set_next_channel(&p, &ch, &t1, &t2));
uint16_t list[16];
list[4] = 1;
memcpy(list, "\0", 16);
object->get_phy_params().channels.mask = list;
object->get_phy_params().channels.mask_size = 1;
p.aggregate_timeoff = 10000;
EXPECT_TRUE(LORAWAN_STATUS_DUTYCYCLE_RESTRICTED == object->set_next_channel(&p, &ch, &t1, &t2));
LoRaWANTimer_stub::time_value = 20000;
EXPECT_TRUE(LORAWAN_STATUS_NO_CHANNEL_FOUND == object->set_next_channel(&p, &ch, &t1, &t2));
p.joined = false;
p.dc_enabled = false;
band_t b[4];
object->get_phy_params().bands.size = 2;
object->get_phy_params().bands.table = &b;
b[0].off_time = 0;
b[1].off_time = 9999999;
list[4] = 0;
object->get_phy_params().channels.mask_size = 128;
p.current_datarate = DR_1;
object->get_phy_params().max_channel_cnt = 4;
EXPECT_TRUE(LORAWAN_STATUS_NO_CHANNEL_FOUND == object->set_next_channel(&p, &ch, &t1, &t2));
p.dc_enabled = true;
EXPECT_TRUE(LORAWAN_STATUS_NO_CHANNEL_FOUND == object->set_next_channel(&p, &ch, &t1, &t2));
list[4] = 1;
p.joined = true;
p.dc_enabled = false;
channel_params_t l[4];
l[0].dr_range.value = 0xff;
l[1].dr_range.value = 0xff;
l[2].dr_range.value = 0xf0;
l[3].dr_range.value = 0xf0;
l[2].band = 2;
l[3].band = 3;
object->get_phy_params().channels.channel_list = l;
list[0] = 0xFF;
b[2].off_time = 9999999;
b[3].off_time = 0;
EXPECT_TRUE(LORAWAN_STATUS_OK == object->set_next_channel(&p, &ch, &t1, &t2));
b[0].off_time = 10000;
LoRaWANTimer_stub::time_value = 2000;
p.aggregate_timeoff = 1000;
p.dc_enabled = true;
EXPECT_TRUE(LORAWAN_STATUS_OK == object->set_next_channel(&p, &ch, &t1, &t2));
}
TEST_F(Test_LoRaPHY, add_channel)
{
uint16_t list[16];
object->get_phy_params().channels.mask = list;
object->get_phy_params().channels.default_mask = list;
channel_params_t p;
EXPECT_TRUE(LORAWAN_STATUS_PARAMETER_INVALID == object->add_channel(&p, 0));
object->get_phy_params().custom_channelplans_supported = true;
object->get_phy_params().max_channel_cnt = 2;
object->get_phy_params().min_tx_datarate = 0;
object->get_phy_params().max_tx_datarate = 13;
p.dr_range.fields.min = 6;
p.dr_range.fields.max = 1;
EXPECT_TRUE(LORAWAN_STATUS_FREQ_AND_DR_INVALID == object->add_channel(&p, 0));
}
TEST_F(Test_LoRaPHY, remove_channel)
{
channel_params_t pp;
pp.band=0;
object->get_phy_params().channels.channel_list = &pp;
uint16_t list[16];
list[0] = 1;
object->get_phy_params().channels.mask = list;
object->get_phy_params().channels.default_mask = list;
EXPECT_TRUE(false == object->remove_channel(0));
list[0] = 0;
EXPECT_TRUE(false == object->remove_channel(0));
object->get_phy_params().channels.mask_size = 1;
object->get_phy_params().max_channel_cnt = 0;
EXPECT_TRUE(false == object->remove_channel(0));
object->get_phy_params().max_channel_cnt = 1;
EXPECT_TRUE(true == object->remove_channel(0));
}
TEST_F(Test_LoRaPHY, set_tx_cont_mode)
{
channel_params_t pp;
pp.band=0;
object->get_phy_params().channels.channel_list = &pp;
band_t b;
object->get_phy_params().bands.table = &b;
my_radio radio;
object->set_radio_instance(radio);
cw_mode_params_t p;
p.max_eirp = 0;
p.channel=0;
object->set_tx_cont_mode(&p);
p.max_eirp = 1;
p.antenna_gain = 1;
object->set_tx_cont_mode(&p, 1);
}
TEST_F(Test_LoRaPHY, apply_DR_offset)
{
EXPECT_TRUE(0 == object->apply_DR_offset(0, 0));
object->get_phy_params().min_tx_datarate = 1;
EXPECT_TRUE(1 == object->apply_DR_offset(0, 2));
}
TEST_F(Test_LoRaPHY, reset_to_default_values)
{
loramac_protocol_params p;
object->reset_to_default_values(&p);
object->reset_to_default_values(&p, true);
}
TEST_F(Test_LoRaPHY, get_next_lower_tx_datarate)
{
EXPECT_TRUE(DR_0 == object->get_next_lower_tx_datarate(DR_2));
object->get_phy_params().ul_dwell_time_setting = 1;
object->get_phy_params().dwell_limit_datarate = DR_1;
EXPECT_TRUE(DR_1 == object->get_next_lower_tx_datarate(DR_2));
}
TEST_F(Test_LoRaPHY, get_minimum_rx_datarate)
{
EXPECT_TRUE(DR_0 == object->get_minimum_rx_datarate());
object->get_phy_params().dl_dwell_time_setting = 1;
object->get_phy_params().dwell_limit_datarate = DR_1;
EXPECT_TRUE(DR_1 == object->get_minimum_rx_datarate());
}
TEST_F(Test_LoRaPHY, get_minimum_tx_datarate)
{
EXPECT_TRUE(DR_0 == object->get_minimum_tx_datarate());
object->get_phy_params().ul_dwell_time_setting = 1;
object->get_phy_params().dwell_limit_datarate = DR_1;
EXPECT_TRUE(DR_1 == object->get_minimum_tx_datarate());
}
TEST_F(Test_LoRaPHY, get_default_tx_datarate)
{
EXPECT_TRUE(0 == object->get_default_tx_datarate());
}
TEST_F(Test_LoRaPHY, get_default_max_tx_datarate)
{
EXPECT_TRUE(DR_0 == object->get_default_max_tx_datarate());
}
TEST_F(Test_LoRaPHY, get_default_tx_power)
{
EXPECT_TRUE(0 == object->get_default_tx_power());
}
TEST_F(Test_LoRaPHY, get_max_payload)
{
uint8_t list=8;
object->get_phy_params().payloads.table = &list;
object->get_phy_params().payloads_with_repeater.table = &list;
EXPECT_TRUE(8 == object->get_max_payload(0));
EXPECT_TRUE(8 == object->get_max_payload(0, true));
}
TEST_F(Test_LoRaPHY, get_maximum_frame_counter_gap)
{
EXPECT_TRUE(0 == object->get_maximum_frame_counter_gap());
}
TEST_F(Test_LoRaPHY, get_ack_timeout)
{
EXPECT_TRUE(0 == object->get_ack_timeout());
}
TEST_F(Test_LoRaPHY, get_default_rx2_frequency)
{
EXPECT_TRUE(0 == object->get_default_rx2_frequency());
}
TEST_F(Test_LoRaPHY, get_default_rx2_datarate)
{
EXPECT_TRUE(0 == object->get_default_rx2_datarate());
}
TEST_F(Test_LoRaPHY, get_channel_mask)
{
EXPECT_TRUE(0 == object->get_channel_mask());
EXPECT_TRUE(0 == object->get_channel_mask(true));
}
TEST_F(Test_LoRaPHY, get_max_nb_channels)
{
EXPECT_TRUE(0 == object->get_max_nb_channels());
}
TEST_F(Test_LoRaPHY, get_phy_channels)
{
EXPECT_TRUE(0 == object->get_phy_channels());
}
TEST_F(Test_LoRaPHY, is_custom_channel_plan_supported)
{
EXPECT_TRUE(false == object->is_custom_channel_plan_supported());
}
TEST_F(Test_LoRaPHY, verify_rx_datarate)
{
EXPECT_TRUE(false == object->verify_rx_datarate(0));
object->get_phy_params().datarates.size = 1;
uint8_t t[1];
t[0] = 2;
object->get_phy_params().datarates.table = t;
object->get_phy_params().dl_dwell_time_setting = 0;
EXPECT_TRUE(true == object->verify_rx_datarate(0));
object->get_phy_params().dl_dwell_time_setting = 1;
object->get_phy_params().min_rx_datarate = 0;
EXPECT_TRUE(true == object->verify_rx_datarate(0));
}
TEST_F(Test_LoRaPHY, verify_tx_datarate)
{
EXPECT_TRUE(false == object->verify_tx_datarate(0));
object->get_phy_params().datarates.size = 1;
uint8_t t[1];
t[0] = 2;
object->get_phy_params().datarates.table = t;
object->get_phy_params().ul_dwell_time_setting = 0;
EXPECT_TRUE(true == object->verify_tx_datarate(0));
object->get_phy_params().ul_dwell_time_setting = 1;
EXPECT_TRUE(true == object->verify_tx_datarate(0));
object->get_phy_params().ul_dwell_time_setting = 1;
EXPECT_TRUE(true == object->verify_tx_datarate(0, true));
}
TEST_F(Test_LoRaPHY, verify_tx_power)
{
EXPECT_TRUE(true == object->verify_tx_power(0));
}
TEST_F(Test_LoRaPHY, verify_duty_cycle)
{
EXPECT_TRUE(true == object->verify_duty_cycle(false));
EXPECT_TRUE(false == object->verify_duty_cycle(true));
}
TEST_F(Test_LoRaPHY, verify_nb_join_trials)
{
EXPECT_TRUE(false == object->verify_nb_join_trials(0));
EXPECT_TRUE(true == object->verify_nb_join_trials(100));
}

View File

@ -229,4 +229,3 @@ TEST_F(Test_LoRaPHYAU915, apply_DR_offset)
}
}
}

View File

@ -233,4 +233,3 @@ TEST_F(Test_LoRaPHYUS915, set_tx_cont_mode)
p.datarate = 4;
object->set_tx_cont_mode(&p, 0);
}

View File

@ -17,6 +17,87 @@
#include "gtest/gtest.h"
#include "LoRaWANStack.h"
#include "EventQueue.h"
#include "LoRaPHY_stub.h"
using namespace events;
class my_LoRaPHY : public LoRaPHY
{
public:
my_LoRaPHY(){};
virtual ~my_LoRaPHY(){};
};
uint8_t my_cb()
{
return 1;
}
class my_radio : public LoRaRadio
{
public:
virtual void init_radio(radio_events_t *events){};
virtual void radio_reset(){};
virtual void sleep(void){};
virtual void standby(void){};
virtual void set_rx_config (radio_modems_t modem, uint32_t bandwidth,
uint32_t datarate, uint8_t coderate,
uint32_t bandwidth_afc, uint16_t preamble_len,
uint16_t symb_timeout, bool fix_len,
uint8_t payload_len,
bool crc_on, bool freq_hop_on, uint8_t hop_period,
bool iq_inverted, bool rx_continuous){};
virtual void set_tx_config(radio_modems_t modem, int8_t power, uint32_t fdev,
uint32_t bandwidth, uint32_t datarate,
uint8_t coderate, uint16_t preamble_len,
bool fix_len, bool crc_on, bool freq_hop_on,
uint8_t hop_period, bool iq_inverted, uint32_t timeout){};
virtual void send(uint8_t *buffer, uint8_t size){};
virtual void receive(void){};
virtual void set_channel(uint32_t freq){};
virtual uint32_t random(void){};
virtual uint8_t get_status(void){return uint8_value;};
virtual void set_max_payload_length(radio_modems_t modem, uint8_t max){};
virtual void set_public_network(bool enable){};
virtual uint32_t time_on_air(radio_modems_t modem, uint8_t pkt_len){};
virtual bool perform_carrier_sense(radio_modems_t modem,
uint32_t freq,
int16_t rssi_threshold,
uint32_t max_carrier_sense_time){ return bool_value;};
virtual void start_cad(void){};
virtual bool check_rf_frequency(uint32_t frequency){ return bool_value; };
virtual void set_tx_continuous_wave(uint32_t freq, int8_t power, uint16_t time){};
virtual void lock(void){};
virtual void unlock(void){};
bool bool_value;
uint8_t uint8_value;
};
class Test_LoRaWANStack : public testing::Test {
protected:
@ -38,3 +119,134 @@ TEST_F(Test_LoRaWANStack, constructor)
EXPECT_TRUE(object);
}
TEST_F(Test_LoRaWANStack, bind_phy_and_radio_driver)
{
my_radio radio;
my_LoRaPHY phy;
object->bind_phy_and_radio_driver(radio, phy);
}
TEST_F(Test_LoRaWANStack, initialize_mac_layer)
{
EXPECT_TRUE(LORAWAN_STATUS_PARAMETER_INVALID == object->initialize_mac_layer(NULL));
EventQueue queue;
EXPECT_TRUE(LORAWAN_STATUS_OK == object->initialize_mac_layer(&queue));
}
TEST_F(Test_LoRaWANStack, set_lora_callbacks)
{
lorawan_app_callbacks_t cb;
EXPECT_TRUE(LORAWAN_STATUS_NOT_INITIALIZED == object->set_lora_callbacks(&cb));
}
TEST_F(Test_LoRaWANStack, connect)
{
EXPECT_TRUE(LORAWAN_STATUS_NOT_INITIALIZED == object->connect());
lorawan_connect_t conn;
EXPECT_TRUE(LORAWAN_STATUS_NOT_INITIALIZED == object->connect(conn));
}
TEST_F(Test_LoRaWANStack, add_channels)
{
lorawan_channelplan_t plan;
EXPECT_TRUE(LORAWAN_STATUS_NOT_INITIALIZED == object->add_channels(plan));
}
TEST_F(Test_LoRaWANStack, remove_a_channel)
{
EXPECT_TRUE(LORAWAN_STATUS_NOT_INITIALIZED == object->remove_a_channel(1));
}
TEST_F(Test_LoRaWANStack, drop_channel_list)
{
EXPECT_TRUE(LORAWAN_STATUS_NOT_INITIALIZED == object->drop_channel_list());
}
TEST_F(Test_LoRaWANStack, get_enabled_channels)
{
lorawan_channelplan_t plan;
EXPECT_TRUE(LORAWAN_STATUS_NOT_INITIALIZED == object->get_enabled_channels(plan));
}
TEST_F(Test_LoRaWANStack, set_confirmed_msg_retry)
{
EXPECT_TRUE(LORAWAN_STATUS_NOT_INITIALIZED == object->set_confirmed_msg_retry(1));
}
TEST_F(Test_LoRaWANStack, set_channel_data_rate)
{
EXPECT_TRUE(LORAWAN_STATUS_NOT_INITIALIZED == object->set_channel_data_rate(4));
}
TEST_F(Test_LoRaWANStack, enable_adaptive_datarate)
{
EXPECT_TRUE(LORAWAN_STATUS_NOT_INITIALIZED == object->enable_adaptive_datarate(false));
}
TEST_F(Test_LoRaWANStack, handle_tx)
{
EXPECT_TRUE(LORAWAN_STATUS_NOT_INITIALIZED == object->handle_tx(0, NULL, 0, 0, true, false));
}
TEST_F(Test_LoRaWANStack, handle_rx)
{
uint8_t port;
int flags;
EXPECT_TRUE(LORAWAN_STATUS_NOT_INITIALIZED == object->handle_rx(NULL, 0, port, flags, false));
}
TEST_F(Test_LoRaWANStack, set_link_check_request)
{
EXPECT_TRUE(LORAWAN_STATUS_NOT_INITIALIZED == object->set_link_check_request());
}
TEST_F(Test_LoRaWANStack, remove_link_check_request)
{
object->remove_link_check_request();
}
TEST_F(Test_LoRaWANStack, shutdown)
{
EXPECT_TRUE(LORAWAN_STATUS_NOT_INITIALIZED == object->shutdown());
}
TEST_F(Test_LoRaWANStack, set_device_class)
{
EXPECT_TRUE(LORAWAN_STATUS_NOT_INITIALIZED == object->set_device_class(CLASS_A));
}
TEST_F(Test_LoRaWANStack, acquire_tx_metadata)
{
lorawan_tx_metadata data;
EXPECT_TRUE(LORAWAN_STATUS_NOT_INITIALIZED == object->acquire_tx_metadata(data));
}
TEST_F(Test_LoRaWANStack, acquire_rx_metadata)
{
lorawan_rx_metadata data;
EXPECT_TRUE(LORAWAN_STATUS_NOT_INITIALIZED == object->acquire_rx_metadata(data));
}
TEST_F(Test_LoRaWANStack, acquire_backoff_metadata)
{
int b;
EXPECT_TRUE(LORAWAN_STATUS_NOT_INITIALIZED == object->acquire_backoff_metadata(b));
}
TEST_F(Test_LoRaWANStack, stop_sending)
{
EXPECT_TRUE(LORAWAN_STATUS_NOT_INITIALIZED == object->stop_sending());
}
TEST_F(Test_LoRaWANStack, lock)
{
object->lock();
}
TEST_F(Test_LoRaWANStack, unlock)
{
object->unlock();
}

View File

@ -104,9 +104,7 @@ int32_t LoRaPHY::get_random(int32_t min, int32_t max)
return LoRaPHY_stub::uint32_value;
}
bool LoRaPHY::verify_channel_DR(uint8_t nb_channels, uint16_t *channel_mask,
int8_t dr, int8_t min_dr, int8_t max_dr,
channel_params_t *channels)
bool LoRaPHY::verify_channel_DR(uint16_t *channel_mask, int8_t dr)
{
return LoRaPHY_stub::bool_table[LoRaPHY_stub::bool_counter++];
}
@ -142,24 +140,6 @@ void LoRaPHY::copy_channel_mask(uint16_t *dest_mask, uint16_t *src_mask, uint8_t
}
}
void LoRaPHY::intersect_channel_mask(const uint16_t *source,
uint16_t *destination, uint8_t size)
{
}
void LoRaPHY::fill_channel_mask_with_fsb(const uint16_t *expectation,
const uint16_t *fsb_mask,
uint16_t *destination,
uint8_t size)
{
}
void LoRaPHY::fill_channel_mask_with_value(uint16_t *channel_mask,
uint16_t value, uint8_t size)
{
}
void LoRaPHY::set_last_tx_done(uint8_t channel, bool joined, lorawan_time_t last_tx_done_time)
{
}
@ -188,16 +168,6 @@ uint8_t LoRaPHY::verify_link_ADR_req(verify_adr_params_t *verify_params,
return LoRaPHY_stub::uint8_value;
}
double LoRaPHY::compute_symb_timeout_lora(uint8_t phy_dr, uint32_t bandwidth)
{
return LoRaPHY_stub::double_value;
}
double LoRaPHY::compute_symb_timeout_fsk(uint8_t phy_dr)
{
return LoRaPHY_stub::double_value;
}
void LoRaPHY::get_rx_window_params(double t_symb, uint8_t min_rx_symb,
uint32_t rx_error, uint32_t wakeup_time,
uint32_t *window_timeout, int32_t *window_offset)

View File

@ -17,6 +17,10 @@
#include "LoRaWANTimer.h"
#include "LoRaWANTimer_stub.h"
lorawan_time_t LoRaWANTimer_stub::time_value = 0;
LoRaWANTimeHandler::LoRaWANTimeHandler()
: _queue(NULL)
{
@ -32,12 +36,12 @@ void LoRaWANTimeHandler::activate_timer_subsystem(events::EventQueue *queue)
lorawan_time_t LoRaWANTimeHandler::get_current_time( void )
{
return (lorawan_time_t)0;
return LoRaWANTimer_stub::time_value;
}
lorawan_time_t LoRaWANTimeHandler::get_elapsed_time(lorawan_time_t saved_time)
{
return (lorawan_time_t)0;
return LoRaWANTimer_stub::time_value;
}
void LoRaWANTimeHandler::init(timer_event_t &obj, mbed::Callback<void()> callback)

View File

@ -0,0 +1,23 @@
/*
* Copyright (c) , Arm Limited and affiliates.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "LoRaWANTimer.h"
namespace LoRaWANTimer_stub
{
extern lorawan_time_t time_value;
}

View File

@ -164,19 +164,18 @@ int32_t LoRaPHY::get_random(int32_t min, int32_t max)
return (int32_t) rand() % (max - min + 1) + min;
}
bool LoRaPHY::verify_channel_DR(uint8_t nb_channels, uint16_t *channel_mask,
int8_t dr, int8_t min_dr, int8_t max_dr,
channel_params_t *channels)
bool LoRaPHY::verify_channel_DR(uint16_t *channel_mask, int8_t dr)
{
if (val_in_range(dr, min_dr, max_dr) == 0) {
if (val_in_range(dr, phy_params.min_tx_datarate,
phy_params.max_tx_datarate) == 0) {
return false;
}
for (uint8_t i = 0; i < phy_params.max_channel_cnt; i++) {
if (mask_bit_test(channel_mask, i)) {
// Check datarate validity for enabled channels
if (val_in_range(dr, (channels[i].dr_range.fields.min & 0x0F),
(channels[i].dr_range.fields.max & 0x0F))) {
if (val_in_range(dr, (phy_params.channels.channel_list[i].dr_range.fields.min & 0x0F),
(phy_params.channels.channel_list[i].dr_range.fields.max & 0x0F))) {
// At least 1 channel has been found we can return OK.
return true;
}
@ -248,45 +247,6 @@ void LoRaPHY::copy_channel_mask(uint16_t *dest_mask, uint16_t *src_mask, uint8_t
}
}
void LoRaPHY::intersect_channel_mask(const uint16_t *source,
uint16_t *destination, uint8_t size)
{
if (!source || !destination || size == 0) {
return;
}
for (uint8_t i = 0; i < size; i++) {
destination[i] &= source[i];
}
}
void LoRaPHY::fill_channel_mask_with_fsb(const uint16_t *expectation,
const uint16_t *fsb_mask,
uint16_t *destination,
uint8_t size)
{
if (!expectation || !fsb_mask || !destination || size == 0) {
return;
}
for (uint8_t i = 0; i < size; i++) {
destination[i] = expectation[i] & fsb_mask[i];
}
}
void LoRaPHY::fill_channel_mask_with_value(uint16_t *channel_mask,
uint16_t value, uint8_t size)
{
if (!channel_mask || size == 0) {
return;
}
for (uint8_t i = 0; i < size; i++) {
channel_mask[i] = value;
}
}
void LoRaPHY::set_last_tx_done(uint8_t channel, bool joined, lorawan_time_t last_tx_done_time)
{
band_t *band_table = (band_t *) phy_params.bands.table;
@ -396,16 +356,13 @@ uint8_t LoRaPHY::verify_link_ADR_req(verify_adr_params_t *verify_params,
if (status != 0) {
// Verify channel datarate
if (verify_channel_DR(phy_params.max_channel_cnt, verify_params->channel_mask,
datarate, phy_params.min_tx_datarate,
phy_params.max_tx_datarate, phy_params.channels.channel_list)
== false) {
if (verify_channel_DR(verify_params->channel_mask, datarate) == false) {
status &= 0xFD; // Datarate KO
}
// Verify tx power
if (val_in_range(tx_power, phy_params.max_tx_power,
phy_params.min_tx_power) == 0) {
phy_params.min_tx_power) == false) {
// Verify if the maximum TX power is exceeded
if (phy_params.max_tx_power > tx_power) {
// Apply maximum TX power. Accept TX power.
@ -1140,8 +1097,8 @@ uint8_t LoRaPHY::dl_channel_request(uint8_t channel_id, uint32_t rx1_frequency)
uint8_t status = 0x03;
// Verify if the frequency is supported
uint8_t band = lookup_band_for_frequency(rx1_frequency);
if (verify_frequency_for_band(rx1_frequency, band) == false) {
int band = lookup_band_for_frequency(rx1_frequency);
if (band < 0) {
status &= 0xFE;
}
@ -1343,7 +1300,7 @@ lorawan_status_t LoRaPHY::add_channel(const channel_params_t *new_channel,
// Default channels don't accept all values
if (id < phy_params.default_channel_cnt) {
// Validate the datarate range for min: must be DR_0
if (new_channel->dr_range.fields.min > phy_params.min_tx_datarate) {
if (new_channel->dr_range.fields.min != DR_0) {
dr_invalid = true;
}

View File

@ -535,26 +535,6 @@ public: //Verifiers
protected:
LoRaPHY();
/**
* Sets the intersection of source and destination channel masks
* into the destination.
*/
void intersect_channel_mask(const uint16_t *source, uint16_t *destination,
uint8_t size);
/**
* Fills channel mask array based upon the provided FSB mask
*/
void fill_channel_mask_with_fsb(const uint16_t *expectation,
const uint16_t *fsb_mask,
uint16_t *channel_mask, uint8_t size);
/**
* Fills channel mask array with a given value
*/
void fill_channel_mask_with_value(uint16_t *channel_mask,
uint16_t value, uint8_t size);
/**
* Looks up corresponding band for a frequency. Returns -1 if not in any band.
*/
@ -573,8 +553,7 @@ protected:
/**
* Verifies, if a datarate is available on an active channel.
*/
bool verify_channel_DR(uint8_t nbChannels, uint16_t* channelsMask, int8_t dr,
int8_t minDr, int8_t maxDr, channel_params_t* channels);
bool verify_channel_DR(uint16_t* channelsMask, int8_t dr);
/**
* Disables a channel in a given channels mask.
@ -615,16 +594,6 @@ protected:
uint8_t verify_link_ADR_req(verify_adr_params_t* verify_params, int8_t* dr,
int8_t* tx_pow, uint8_t* nb_rep);
/**
* Computes the symbol time for LoRa modulation.
*/
double compute_symb_timeout_lora(uint8_t phy_dr, uint32_t bandwidth );
/**
* Computes the symbol time for FSK modulation.
*/
double compute_symb_timeout_fsk(uint8_t phy_dr);
/**
* Computes the RX window timeout and the RX window offset.
*/
@ -658,6 +627,18 @@ protected:
bool is_datarate_supported(const int8_t datarate) const;
private:
/**
* Computes the symbol time for LoRa modulation.
*/
double compute_symb_timeout_lora(uint8_t phy_dr, uint32_t bandwidth );
/**
* Computes the symbol time for FSK modulation.
*/
double compute_symb_timeout_fsk(uint8_t phy_dr);
protected:
LoRaRadio *_radio;
LoRaWANTimeHandler *_lora_time;

View File

@ -617,3 +617,30 @@ uint8_t LoRaPHYAU915::apply_DR_offset(int8_t dr, int8_t dr_offset)
{
return datarate_offsets_AU915[dr][dr_offset];
}
void LoRaPHYAU915::intersect_channel_mask(const uint16_t *source,
uint16_t *destination, uint8_t size)
{
for (uint8_t i = 0; i < size; i++) {
destination[i] &= source[i];
}
}
void LoRaPHYAU915::fill_channel_mask_with_fsb(const uint16_t *expectation,
const uint16_t *fsb_mask,
uint16_t *destination,
uint8_t size)
{
for (uint8_t i = 0; i < size; i++) {
destination[i] = expectation[i] & fsb_mask[i];
}
}
void LoRaPHYAU915::fill_channel_mask_with_value(uint16_t *channel_mask,
uint16_t value, uint8_t size)
{
for (uint8_t i = 0; i < size; i++) {
channel_mask[i] = value;
}
}

View File

@ -76,6 +76,28 @@ public:
virtual uint8_t apply_DR_offset(int8_t dr, int8_t dr_offset);
private:
/**
* Sets the intersection of source and destination channel masks
* into the destination.
*/
void intersect_channel_mask(const uint16_t *source, uint16_t *destination,
uint8_t size);
/**
* Fills channel mask array based upon the provided FSB mask
*/
void fill_channel_mask_with_fsb(const uint16_t *expectation,
const uint16_t *fsb_mask,
uint16_t *channel_mask, uint8_t size);
/**
* Fills channel mask array with a given value
*/
void fill_channel_mask_with_value(uint16_t *channel_mask,
uint16_t value, uint8_t size);
private:
/*!

View File

@ -678,3 +678,31 @@ uint8_t LoRaPHYUS915::apply_DR_offset(int8_t dr, int8_t dr_offset)
{
return datarate_offsets_US915[dr][dr_offset];
}
void LoRaPHYUS915::intersect_channel_mask(const uint16_t *source,
uint16_t *destination, uint8_t size)
{
for (uint8_t i = 0; i < size; i++) {
destination[i] &= source[i];
}
}
void LoRaPHYUS915::fill_channel_mask_with_fsb(const uint16_t *expectation,
const uint16_t *fsb_mask,
uint16_t *destination,
uint8_t size)
{
for (uint8_t i = 0; i < size; i++) {
destination[i] = expectation[i] & fsb_mask[i];
}
}
void LoRaPHYUS915::fill_channel_mask_with_value(uint16_t *channel_mask,
uint16_t value, uint8_t size)
{
for (uint8_t i = 0; i < size; i++) {
channel_mask[i] = value;
}
}

View File

@ -80,6 +80,26 @@ public:
private:
/**
* Sets the intersection of source and destination channel masks
* into the destination.
*/
void intersect_channel_mask(const uint16_t *source, uint16_t *destination,
uint8_t size);
/**
* Fills channel mask array based upon the provided FSB mask
*/
void fill_channel_mask_with_fsb(const uint16_t *expectation,
const uint16_t *fsb_mask,
uint16_t *channel_mask, uint8_t size);
/**
* Fills channel mask array with a given value
*/
void fill_channel_mask_with_value(uint16_t *channel_mask,
uint16_t value, uint8_t size);
int8_t limit_tx_power(int8_t tx_power, int8_t max_band_tx_power,
int8_t datarate);