tests: subsys: openthread: OpenThread radio interface tests
Currently there are no test for openthread on zephyr. Created tests for OpenThread platform radio interface. Signed-off-by: Marek Porwisz <marek.porwisz@nordicsemi.no>
This commit is contained in:
parent
d9f8a6f8e9
commit
673b1da46d
5 changed files with 892 additions and 0 deletions
16
tests/subsys/openthread/CMakeLists.txt
Normal file
16
tests/subsys/openthread/CMakeLists.txt
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
# Boilerplate code, which pulls in the Zephyr build system.
|
||||||
|
cmake_minimum_required(VERSION 3.13.1)
|
||||||
|
include($ENV{ZEPHYR_BASE}/cmake/app/boilerplate.cmake NO_POLICY_SCOPE)
|
||||||
|
|
||||||
|
project(openthread_tests)
|
||||||
|
|
||||||
|
zephyr_library_include_directories(
|
||||||
|
${ZEPHYR_BASE}/../modules/lib/openthread/include/
|
||||||
|
${ZEPHYR_BASE}/../modules/lib/openthread/src/posix/platform/
|
||||||
|
${ZEPHYR_BASE}/subsys/net/lib/openthread/platform/
|
||||||
|
${ZEPHYR_BASE}/../modules/lib/openthread/examples/platforms/
|
||||||
|
)
|
||||||
|
|
||||||
|
# Add your source file to the "app" target. This must come after
|
||||||
|
# the boilerplate code, which defines the target.
|
||||||
|
target_sources(app PRIVATE radio_test.c radio_stub.c)
|
21
tests/subsys/openthread/prj.conf
Normal file
21
tests/subsys/openthread/prj.conf
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
CONFIG_SHELL=y
|
||||||
|
CONFIG_ZTEST=y
|
||||||
|
CONFIG_ZTEST_MOCKING=y
|
||||||
|
CONFIG_ZTEST_PARAMETER_COUNT=50
|
||||||
|
CONFIG_IEEE802154=y
|
||||||
|
CONFIG_NETWORKING=y
|
||||||
|
|
||||||
|
# Network buffers
|
||||||
|
CONFIG_NET_PKT_RX_COUNT=5
|
||||||
|
CONFIG_NET_PKT_TX_COUNT=5
|
||||||
|
CONFIG_NET_BUF_RX_COUNT=5
|
||||||
|
CONFIG_NET_BUF_TX_COUNT=5
|
||||||
|
CONFIG_NET_CONTEXT_NET_PKT_POOL=y
|
||||||
|
|
||||||
|
CONFIG_NET_DEBUG_NET_PKT_ALLOC=y
|
||||||
|
|
||||||
|
# Logging
|
||||||
|
CONFIG_NET_LOG=y
|
||||||
|
CONFIG_LOG=y
|
||||||
|
CONFIG_NET_STATISTICS=y
|
||||||
|
CONFIG_PRINTK=y
|
26
tests/subsys/openthread/radio_stub.c
Normal file
26
tests/subsys/openthread/radio_stub.c
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2020 Nordic Semiconductor ASA
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* needed here so the static device_get_binding does not get renamed */
|
||||||
|
#include <device.h>
|
||||||
|
|
||||||
|
/* OpenThread not enabled here */
|
||||||
|
#define CONFIG_OPENTHREAD_L2_LOG_LEVEL LOG_LEVEL_DBG
|
||||||
|
|
||||||
|
#ifndef CONFIG_NET_CONFIG_IEEE802154_DEV_NAME
|
||||||
|
#define CONFIG_NET_CONFIG_IEEE802154_DEV_NAME ""
|
||||||
|
#endif /* CONFIG_NET_CONFIG_IEEE802154_DEV_NAME */
|
||||||
|
|
||||||
|
#define CONFIG_OPENTHREAD_THREAD_PRIORITY 5
|
||||||
|
#define OT_WORKER_PRIORITY K_PRIO_COOP(CONFIG_OPENTHREAD_THREAD_PRIORITY)
|
||||||
|
#define CONFIG_NET_L2_OPENTHREAD 1
|
||||||
|
|
||||||
|
/* needed for stubbing device driver */
|
||||||
|
struct device *device_get_binding_stub(const char *name);
|
||||||
|
#define device_get_binding device_get_binding_stub
|
||||||
|
|
||||||
|
/* file itself */
|
||||||
|
#include "radio.c"
|
825
tests/subsys/openthread/radio_test.c
Normal file
825
tests/subsys/openthread/radio_test.c
Normal file
|
@ -0,0 +1,825 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2020 Nordic Semiconductor ASA
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <ztest.h>
|
||||||
|
|
||||||
|
#include <zephyr.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include <net/ieee802154_radio.h>
|
||||||
|
#include <net/net_pkt.h>
|
||||||
|
|
||||||
|
#include <openthread/platform/radio.h>
|
||||||
|
#include <platform-zephyr.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Tests for the radio.c - OpenThread radio api
|
||||||
|
* @defgroup openthread_tests radio
|
||||||
|
* @ingroup all_tests
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define ACK_PKT_LENGTH 3
|
||||||
|
#define FRAME_TYPE_MASK 0x07
|
||||||
|
#define FRAME_TYPE_ACK 0x02
|
||||||
|
|
||||||
|
K_SEM_DEFINE(ot_sem, 0, 1);
|
||||||
|
|
||||||
|
energy_scan_done_cb_t scan_done_cb;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fake pointer as it should not be accessed by the code.
|
||||||
|
* Should not be null to be sure it was properly passed.
|
||||||
|
*/
|
||||||
|
otInstance *ot = (otInstance *)0xAAAA;
|
||||||
|
|
||||||
|
/* forward declarations */
|
||||||
|
static int scan_mock(struct device *dev, u16_t duration,
|
||||||
|
energy_scan_done_cb_t done_cb);
|
||||||
|
static enum ieee802154_hw_caps get_capabilities(struct device *dev);
|
||||||
|
static int cca_mock(struct device *dev);
|
||||||
|
static int set_channel_mock(struct device *dev, u16_t channel);
|
||||||
|
static int filter_mock(struct device *dev, bool set,
|
||||||
|
enum ieee802154_filter_type type,
|
||||||
|
const struct ieee802154_filter *filter);
|
||||||
|
static int set_txpower_mock(struct device *dev, s16_t dbm);
|
||||||
|
static int tx_mock(struct device *dev, enum ieee802154_tx_mode mode,
|
||||||
|
struct net_pkt *pkt, struct net_buf *frag);
|
||||||
|
static int start_mock(struct device *dev);
|
||||||
|
static int stop_mock(struct device *dev);
|
||||||
|
static int configure_mock(struct device *dev, enum ieee802154_config_type type,
|
||||||
|
const struct ieee802154_config *config);
|
||||||
|
|
||||||
|
/* mocks */
|
||||||
|
static struct ieee802154_radio_api rapi = {
|
||||||
|
.get_capabilities = get_capabilities,
|
||||||
|
.cca = cca_mock,
|
||||||
|
.set_channel = set_channel_mock,
|
||||||
|
.filter = filter_mock,
|
||||||
|
.set_txpower = set_txpower_mock,
|
||||||
|
.tx = tx_mock,
|
||||||
|
.start = start_mock,
|
||||||
|
.stop = stop_mock,
|
||||||
|
.configure = configure_mock,
|
||||||
|
#ifdef CONFIG_NET_L2_IEEE802154_SUB_GHZ
|
||||||
|
.get_subg_channel_count = NULL,
|
||||||
|
#endif /* CONFIG_NET_L2_IEEE802154_SUB_GHZ */
|
||||||
|
.ed_scan = scan_mock
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct device radio = { .driver_api = &rapi };
|
||||||
|
|
||||||
|
static int scan_mock(struct device *dev, u16_t duration,
|
||||||
|
energy_scan_done_cb_t done_cb)
|
||||||
|
{
|
||||||
|
zassert_equal(dev, &radio, "Device handle incorrect.");
|
||||||
|
ztest_check_expected_value(duration);
|
||||||
|
scan_done_cb = done_cb;
|
||||||
|
return ztest_get_return_value();
|
||||||
|
}
|
||||||
|
|
||||||
|
static int rssi_scan_mock(struct device *dev, u16_t duration,
|
||||||
|
energy_scan_done_cb_t done_cb)
|
||||||
|
{
|
||||||
|
zassert_equal(dev, &radio, "Device handle incorrect.");
|
||||||
|
zassert_equal(duration, 1,
|
||||||
|
"otPlatRadioGetRssi shall pass minimal allowed value.");
|
||||||
|
|
||||||
|
/* use return value as callback param */
|
||||||
|
done_cb(&radio, ztest_get_return_value());
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int set_channel_mock(struct device *dev, u16_t channel)
|
||||||
|
{
|
||||||
|
zassert_equal(dev, &radio, "Device handle incorrect.");
|
||||||
|
ztest_check_expected_value(channel);
|
||||||
|
return ztest_get_return_value();
|
||||||
|
}
|
||||||
|
|
||||||
|
void otPlatRadioEnergyScanDone(otInstance *aInstance, int8_t aEnergyScanMaxRssi)
|
||||||
|
{
|
||||||
|
zassert_equal(aInstance, ot, "Incorrect instance.");
|
||||||
|
ztest_check_expected_value(aEnergyScanMaxRssi);
|
||||||
|
}
|
||||||
|
|
||||||
|
void otSysEventSignalPending(void)
|
||||||
|
{
|
||||||
|
k_sem_give(&ot_sem);
|
||||||
|
}
|
||||||
|
|
||||||
|
void otTaskletsSignalPending(otInstance *aInstance)
|
||||||
|
{
|
||||||
|
zassert_equal(aInstance, ot, "Incorrect instance.");
|
||||||
|
k_sem_give(&ot_sem);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void make_sure_sem_set(k_timeout_t timeout)
|
||||||
|
{
|
||||||
|
zassert_equal(k_sem_take(&ot_sem, timeout), 0, "Sem not released.");
|
||||||
|
}
|
||||||
|
|
||||||
|
void otPlatRadioReceiveDone(otInstance *aInstance, otRadioFrame *aFrame,
|
||||||
|
otError aError)
|
||||||
|
{
|
||||||
|
zassert_equal(aInstance, ot, "Incorrect instance.");
|
||||||
|
ztest_check_expected_value(aFrame->mChannel);
|
||||||
|
ztest_check_expected_value(aFrame->mLength);
|
||||||
|
ztest_check_expected_data(aFrame->mPsdu, aFrame->mLength);
|
||||||
|
ztest_check_expected_value(aError);
|
||||||
|
}
|
||||||
|
|
||||||
|
void otPlatRadioTxDone(otInstance *aInstance, otRadioFrame *aFrame,
|
||||||
|
otRadioFrame *aAckFrame, otError aError)
|
||||||
|
{
|
||||||
|
zassert_equal(aInstance, ot, "Incorrect instance.");
|
||||||
|
ztest_check_expected_value(aError);
|
||||||
|
}
|
||||||
|
|
||||||
|
static enum ieee802154_hw_caps get_capabilities(struct device *dev)
|
||||||
|
{
|
||||||
|
zassert_equal(dev, &radio, "Device handle incorrect.");
|
||||||
|
|
||||||
|
return IEEE802154_HW_FCS | IEEE802154_HW_2_4_GHZ |
|
||||||
|
IEEE802154_HW_TX_RX_ACK | IEEE802154_HW_FILTER |
|
||||||
|
IEEE802154_HW_ENERGY_SCAN;
|
||||||
|
}
|
||||||
|
|
||||||
|
static enum ieee802154_hw_caps get_capabilities_caps_mock(struct device *dev)
|
||||||
|
{
|
||||||
|
zassert_equal(dev, &radio, "Device handle incorrect.");
|
||||||
|
|
||||||
|
return ztest_get_return_value();
|
||||||
|
}
|
||||||
|
|
||||||
|
static int configure_mock(struct device *dev, enum ieee802154_config_type type,
|
||||||
|
const struct ieee802154_config *config)
|
||||||
|
{
|
||||||
|
zassert_equal(dev, &radio, "Device handle incorrect.");
|
||||||
|
|
||||||
|
zassert_equal(type, IEEE802154_CONFIG_EVENT_HANDLER,
|
||||||
|
"Only event handler configuration was expected.");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int configure_match_mock(struct device *dev,
|
||||||
|
enum ieee802154_config_type type,
|
||||||
|
const struct ieee802154_config *config)
|
||||||
|
{
|
||||||
|
zassert_equal(dev, &radio, "Device handle incorrect.");
|
||||||
|
ztest_check_expected_value(type);
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case IEEE802154_CONFIG_AUTO_ACK_FPB:
|
||||||
|
ztest_check_expected_value(config->auto_ack_fpb.mode);
|
||||||
|
ztest_check_expected_value(config->auto_ack_fpb.enabled);
|
||||||
|
break;
|
||||||
|
case IEEE802154_CONFIG_ACK_FPB:
|
||||||
|
ztest_check_expected_value(config->ack_fpb.extended);
|
||||||
|
ztest_check_expected_value(config->ack_fpb.enabled);
|
||||||
|
ztest_check_expected_data(
|
||||||
|
config->ack_fpb.addr,
|
||||||
|
(config->ack_fpb.extended) ? sizeof(otExtAddress) : 2);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
zassert_unreachable("Unexpected config type %d.", type);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int configure_promiscuous_mock(struct device *dev,
|
||||||
|
enum ieee802154_config_type type,
|
||||||
|
const struct ieee802154_config *config)
|
||||||
|
{
|
||||||
|
zassert_equal(dev, &radio, "Device handle incorrect.");
|
||||||
|
zassert_equal(type, IEEE802154_CONFIG_PROMISCUOUS,
|
||||||
|
"Config type incorrect.");
|
||||||
|
ztest_check_expected_value(config->promiscuous);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cca_mock(struct device *dev)
|
||||||
|
{
|
||||||
|
/* not using assert to verify function called */
|
||||||
|
ztest_check_expected_value(dev);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int filter_mock(struct device *dev, bool set,
|
||||||
|
enum ieee802154_filter_type type,
|
||||||
|
const struct ieee802154_filter *filter)
|
||||||
|
{
|
||||||
|
zassert_equal(dev, &radio, "Device handle incorrect.");
|
||||||
|
ztest_check_expected_value(set);
|
||||||
|
ztest_check_expected_value(type);
|
||||||
|
switch (type) {
|
||||||
|
case IEEE802154_FILTER_TYPE_IEEE_ADDR:
|
||||||
|
ztest_check_expected_data(filter->ieee_addr,
|
||||||
|
OT_EXT_ADDRESS_SIZE);
|
||||||
|
break;
|
||||||
|
case IEEE802154_FILTER_TYPE_SHORT_ADDR:
|
||||||
|
ztest_check_expected_value(filter->short_addr);
|
||||||
|
break;
|
||||||
|
case IEEE802154_FILTER_TYPE_PAN_ID:
|
||||||
|
ztest_check_expected_value(filter->pan_id);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
zassert_false(true, "Type not supported in mock: %d.", type);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int set_txpower_mock(struct device *dev, s16_t dbm)
|
||||||
|
{
|
||||||
|
zassert_equal(dev, &radio, "Device handle incorrect.");
|
||||||
|
ztest_check_expected_value(dbm);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int tx_mock(struct device *dev, enum ieee802154_tx_mode mode,
|
||||||
|
struct net_pkt *pkt, struct net_buf *frag)
|
||||||
|
{
|
||||||
|
zassert_equal(dev, &radio, "Device handle incorrect.");
|
||||||
|
ztest_check_expected_value(frag->data);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int start_mock(struct device *dev)
|
||||||
|
{
|
||||||
|
ztest_check_expected_value(dev);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int stop_mock(struct device *dev)
|
||||||
|
{
|
||||||
|
ztest_check_expected_value(dev);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct device *device_get_binding_stub(const char *name)
|
||||||
|
{
|
||||||
|
return &radio;
|
||||||
|
}
|
||||||
|
|
||||||
|
void otPlatRadioTxStarted(otInstance *aInstance, otRadioFrame *aFrame)
|
||||||
|
{
|
||||||
|
zassert_equal(aInstance, ot, "Incorrect instance.");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Test for immediate energy scan
|
||||||
|
* Tests for case when radio energy scan returns success at the first call.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static void energy_scan_immediate_test(void)
|
||||||
|
{
|
||||||
|
const u8_t chan = 10;
|
||||||
|
const u8_t dur = 100;
|
||||||
|
const s16_t energy = -94;
|
||||||
|
|
||||||
|
scan_done_cb = NULL;
|
||||||
|
|
||||||
|
ztest_returns_value(set_channel_mock, 0);
|
||||||
|
ztest_expect_value(set_channel_mock, channel, chan);
|
||||||
|
|
||||||
|
ztest_returns_value(scan_mock, 0);
|
||||||
|
ztest_expect_value(scan_mock, duration, dur);
|
||||||
|
|
||||||
|
zassert_equal(otPlatRadioEnergyScan(ot, chan, dur), OT_ERROR_NONE,
|
||||||
|
"Energy scan returned error.");
|
||||||
|
zassert_not_null(scan_done_cb, "Scan callback not specified.");
|
||||||
|
|
||||||
|
scan_done_cb(&radio, energy);
|
||||||
|
make_sure_sem_set(K_NO_WAIT);
|
||||||
|
|
||||||
|
ztest_expect_value(otPlatRadioEnergyScanDone, aEnergyScanMaxRssi,
|
||||||
|
energy);
|
||||||
|
platformRadioProcess(ot);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Test for delayed energy scan
|
||||||
|
* Tests for case when radio returns not being able to start energy scan and
|
||||||
|
* the scan should be sheduled for later.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static void energy_scan_delayed_test(void)
|
||||||
|
{
|
||||||
|
const u8_t chan = 10;
|
||||||
|
const u8_t dur = 100;
|
||||||
|
const s16_t energy = -94;
|
||||||
|
|
||||||
|
scan_done_cb = NULL;
|
||||||
|
|
||||||
|
/* request scan */
|
||||||
|
ztest_returns_value(set_channel_mock, 0);
|
||||||
|
ztest_expect_value(set_channel_mock, channel, chan);
|
||||||
|
|
||||||
|
ztest_returns_value(scan_mock, -EBUSY);
|
||||||
|
ztest_expect_value(scan_mock, duration, dur);
|
||||||
|
|
||||||
|
zassert_equal(otPlatRadioEnergyScan(ot, chan, dur), OT_ERROR_NONE,
|
||||||
|
"Energy scan returned error.");
|
||||||
|
zassert_not_null(scan_done_cb, "Scan callback not specified.");
|
||||||
|
make_sure_sem_set(K_NO_WAIT);
|
||||||
|
|
||||||
|
/* process reported event */
|
||||||
|
ztest_returns_value(scan_mock, 0);
|
||||||
|
ztest_expect_value(scan_mock, duration, dur);
|
||||||
|
|
||||||
|
ztest_returns_value(set_channel_mock, 0);
|
||||||
|
ztest_expect_value(set_channel_mock, channel, chan);
|
||||||
|
platformRadioProcess(ot);
|
||||||
|
zassert_not_null(scan_done_cb, "Scan callback not specified.");
|
||||||
|
|
||||||
|
/* invoke scan done */
|
||||||
|
scan_done_cb(&radio, energy);
|
||||||
|
make_sure_sem_set(K_NO_WAIT);
|
||||||
|
|
||||||
|
ztest_expect_value(otPlatRadioEnergyScanDone, aEnergyScanMaxRssi,
|
||||||
|
energy);
|
||||||
|
platformRadioProcess(ot);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void create_ack_frame(void)
|
||||||
|
{
|
||||||
|
struct net_pkt *packet;
|
||||||
|
struct net_buf *buf;
|
||||||
|
const u8_t lqi = 230;
|
||||||
|
const s8_t rssi = -80;
|
||||||
|
|
||||||
|
packet = net_pkt_alloc(K_NO_WAIT);
|
||||||
|
buf = net_pkt_get_reserve_tx_data(K_NO_WAIT);
|
||||||
|
net_pkt_append_buffer(packet, buf);
|
||||||
|
|
||||||
|
buf->len = ACK_PKT_LENGTH;
|
||||||
|
buf->data[0] = FRAME_TYPE_ACK;
|
||||||
|
|
||||||
|
net_pkt_set_ieee802154_rssi(packet, rssi);
|
||||||
|
net_pkt_set_ieee802154_lqi(packet, lqi);
|
||||||
|
zassert_equal(ieee802154_radio_handle_ack(NULL, packet), NET_OK,
|
||||||
|
"Handling ack failed.");
|
||||||
|
net_pkt_unref(packet);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Test for tx data handling
|
||||||
|
* Tests if OT frame is correctly passed to the radio driver.
|
||||||
|
* Additionally verifies ACK frame passing back to the OT.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static void tx_test(void)
|
||||||
|
{
|
||||||
|
const u8_t chan = 20;
|
||||||
|
u8_t chan2 = chan - 1;
|
||||||
|
const s8_t power = -3;
|
||||||
|
|
||||||
|
otRadioFrame *frm = otPlatRadioGetTransmitBuffer(ot);
|
||||||
|
|
||||||
|
zassert_not_null(frm, "Transmit buffer is null.");
|
||||||
|
|
||||||
|
otPlatRadioSetTransmitPower(ot, power);
|
||||||
|
|
||||||
|
ztest_returns_value(set_channel_mock, 0);
|
||||||
|
ztest_expect_value(set_channel_mock, channel, chan);
|
||||||
|
ztest_expect_value(set_txpower_mock, dbm, power);
|
||||||
|
ztest_expect_value(start_mock, dev, &radio);
|
||||||
|
otPlatRadioReceive(ot, chan);
|
||||||
|
|
||||||
|
/* ACKed frame */
|
||||||
|
frm->mChannel = chan2;
|
||||||
|
frm->mInfo.mTxInfo.mCsmaCaEnabled = true;
|
||||||
|
frm->mPsdu[0] = IEEE802154_AR_FLAG_SET;
|
||||||
|
ztest_returns_value(set_channel_mock, 0);
|
||||||
|
ztest_expect_value(set_channel_mock, channel, chan2);
|
||||||
|
ztest_expect_value(cca_mock, dev, &radio);
|
||||||
|
ztest_expect_value(tx_mock, frag->data, frm->mPsdu);
|
||||||
|
ztest_expect_value(set_txpower_mock, dbm, power);
|
||||||
|
zassert_equal(otPlatRadioTransmit(ot, frm), OT_ERROR_NONE,
|
||||||
|
"Transmit failed.");
|
||||||
|
|
||||||
|
create_ack_frame();
|
||||||
|
make_sure_sem_set(Z_TIMEOUT_MS(100));
|
||||||
|
|
||||||
|
ztest_expect_value(otPlatRadioTxDone, aError, OT_ERROR_NONE);
|
||||||
|
platformRadioProcess(ot);
|
||||||
|
|
||||||
|
/* Non-ACKed frame */
|
||||||
|
frm->mChannel = --chan2;
|
||||||
|
frm->mInfo.mTxInfo.mCsmaCaEnabled = false;
|
||||||
|
frm->mPsdu[0] = 0;
|
||||||
|
|
||||||
|
ztest_returns_value(set_channel_mock, 0);
|
||||||
|
ztest_expect_value(set_channel_mock, channel, chan2);
|
||||||
|
ztest_expect_value(tx_mock, frag->data, frm->mPsdu);
|
||||||
|
ztest_expect_value(set_txpower_mock, dbm, power);
|
||||||
|
zassert_equal(otPlatRadioTransmit(ot, frm), OT_ERROR_NONE,
|
||||||
|
"Transmit failed.");
|
||||||
|
make_sure_sem_set(Z_TIMEOUT_MS(100));
|
||||||
|
ztest_expect_value(otPlatRadioTxDone, aError, OT_ERROR_NONE);
|
||||||
|
platformRadioProcess(ot);
|
||||||
|
|
||||||
|
/* ACKed frame, no ACK */
|
||||||
|
frm->mChannel = --chan2;
|
||||||
|
frm->mInfo.mTxInfo.mCsmaCaEnabled = false;
|
||||||
|
frm->mPsdu[0] = IEEE802154_AR_FLAG_SET;
|
||||||
|
|
||||||
|
ztest_returns_value(set_channel_mock, 0);
|
||||||
|
ztest_expect_value(set_channel_mock, channel, chan2);
|
||||||
|
ztest_expect_value(tx_mock, frag->data, frm->mPsdu);
|
||||||
|
ztest_expect_value(set_txpower_mock, dbm, power);
|
||||||
|
zassert_equal(otPlatRadioTransmit(ot, frm), OT_ERROR_NONE,
|
||||||
|
"Transmit failed.");
|
||||||
|
make_sure_sem_set(Z_TIMEOUT_MS(100));
|
||||||
|
|
||||||
|
ztest_expect_value(otPlatRadioTxDone, aError, OT_ERROR_NO_ACK);
|
||||||
|
platformRadioProcess(ot);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Test for tx power setting
|
||||||
|
* Tests if tx power requested by the OT is correctly passed to the radio.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static void tx_power_test(void)
|
||||||
|
{
|
||||||
|
s8_t out_power = 0;
|
||||||
|
|
||||||
|
otPlatRadioSetTransmitPower(ot, -3);
|
||||||
|
otPlatRadioGetTransmitPower(ot, &out_power);
|
||||||
|
zassert_equal(out_power, -3, "Got different power than set.");
|
||||||
|
otPlatRadioSetTransmitPower(ot, -6);
|
||||||
|
otPlatRadioGetTransmitPower(ot, &out_power);
|
||||||
|
zassert_equal(out_power, -6,
|
||||||
|
"Second call to otPlatRadioSetTransmitPower failed.");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Test for getting radio sensitivity
|
||||||
|
* There is no api to get radio sensitivity from the radio so the value is
|
||||||
|
* hardcoded in radio.c. Test only verifies if the value returned makes any
|
||||||
|
* sense.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static void sensitivity_test(void)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Nothing to test actually as this is constant 100.
|
||||||
|
* When radio interface will be extended to get sensitivity this test
|
||||||
|
* can be extended with the radio api call. For now just verify if the
|
||||||
|
* value is reasonable.
|
||||||
|
*/
|
||||||
|
zassert_true(-80 > otPlatRadioGetReceiveSensitivity(ot),
|
||||||
|
"Radio sensitivity not in range.");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void set_expected_match_values(enum ieee802154_config_type type,
|
||||||
|
u8_t *addr, bool extended, bool enabled)
|
||||||
|
{
|
||||||
|
ztest_expect_value(configure_match_mock, type, type);
|
||||||
|
switch (type) {
|
||||||
|
case IEEE802154_CONFIG_AUTO_ACK_FPB:
|
||||||
|
ztest_expect_value(configure_match_mock,
|
||||||
|
config->auto_ack_fpb.enabled, enabled);
|
||||||
|
ztest_expect_value(configure_match_mock,
|
||||||
|
config->auto_ack_fpb.mode,
|
||||||
|
IEEE802154_FPB_ADDR_MATCH_THREAD);
|
||||||
|
break;
|
||||||
|
case IEEE802154_CONFIG_ACK_FPB:
|
||||||
|
ztest_expect_value(configure_match_mock,
|
||||||
|
config->ack_fpb.extended, extended);
|
||||||
|
ztest_expect_value(configure_match_mock,
|
||||||
|
config->ack_fpb.enabled, enabled);
|
||||||
|
ztest_expect_data(configure_match_mock, config->ack_fpb.addr,
|
||||||
|
addr);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Test different types of OT source match.
|
||||||
|
* Tests if Enable, Disable, Add and Clear Source Match calls are passed to the
|
||||||
|
* radio driver correctly.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static void source_match_test(void)
|
||||||
|
{
|
||||||
|
otExtAddress ext_addr;
|
||||||
|
|
||||||
|
rapi.configure = configure_match_mock;
|
||||||
|
/* Enable/Disable */
|
||||||
|
set_expected_match_values(IEEE802154_CONFIG_AUTO_ACK_FPB, NULL, false,
|
||||||
|
true);
|
||||||
|
otPlatRadioEnableSrcMatch(ot, true);
|
||||||
|
set_expected_match_values(IEEE802154_CONFIG_AUTO_ACK_FPB, NULL, false,
|
||||||
|
false);
|
||||||
|
otPlatRadioEnableSrcMatch(ot, false);
|
||||||
|
|
||||||
|
set_expected_match_values(IEEE802154_CONFIG_AUTO_ACK_FPB, NULL, false,
|
||||||
|
true);
|
||||||
|
otPlatRadioEnableSrcMatch(ot, true);
|
||||||
|
|
||||||
|
/* Add */
|
||||||
|
sys_put_le16(12345, ext_addr.m8);
|
||||||
|
set_expected_match_values(IEEE802154_CONFIG_ACK_FPB, ext_addr.m8, false,
|
||||||
|
true);
|
||||||
|
otPlatRadioAddSrcMatchShortEntry(ot, 12345);
|
||||||
|
|
||||||
|
for (int i = 0; i < sizeof(ext_addr.m8); i++) {
|
||||||
|
ext_addr.m8[i] = i;
|
||||||
|
}
|
||||||
|
set_expected_match_values(IEEE802154_CONFIG_ACK_FPB, ext_addr.m8, true,
|
||||||
|
true);
|
||||||
|
otPlatRadioAddSrcMatchExtEntry(ot, &ext_addr);
|
||||||
|
|
||||||
|
/* Clear */
|
||||||
|
sys_put_le16(12345, ext_addr.m8);
|
||||||
|
set_expected_match_values(IEEE802154_CONFIG_ACK_FPB, ext_addr.m8, false,
|
||||||
|
false);
|
||||||
|
otPlatRadioClearSrcMatchShortEntry(ot, 12345);
|
||||||
|
|
||||||
|
set_expected_match_values(IEEE802154_CONFIG_ACK_FPB, ext_addr.m8, true,
|
||||||
|
false);
|
||||||
|
otPlatRadioClearSrcMatchExtEntry(ot, &ext_addr);
|
||||||
|
|
||||||
|
set_expected_match_values(IEEE802154_CONFIG_ACK_FPB, NULL, false,
|
||||||
|
false);
|
||||||
|
otPlatRadioClearSrcMatchShortEntries(ot);
|
||||||
|
|
||||||
|
set_expected_match_values(IEEE802154_CONFIG_ACK_FPB, NULL, true, false);
|
||||||
|
otPlatRadioClearSrcMatchExtEntries(ot);
|
||||||
|
|
||||||
|
rapi.configure = configure_mock;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Test for enabling or disabling promiscuous mode
|
||||||
|
* Tests if OT can successfully enable or disable promiscuous mode.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static void promiscuous_mode_set_test(void)
|
||||||
|
{
|
||||||
|
rapi.configure = configure_promiscuous_mock;
|
||||||
|
|
||||||
|
zassert_false(otPlatRadioGetPromiscuous(ot),
|
||||||
|
"By default promiscuous mode shall be disabled.");
|
||||||
|
|
||||||
|
ztest_expect_value(configure_promiscuous_mock, config->promiscuous,
|
||||||
|
true);
|
||||||
|
otPlatRadioSetPromiscuous(ot, true);
|
||||||
|
zassert_true(otPlatRadioGetPromiscuous(ot), "Mode not enabled.");
|
||||||
|
|
||||||
|
ztest_expect_value(configure_promiscuous_mock, config->promiscuous,
|
||||||
|
false);
|
||||||
|
otPlatRadioSetPromiscuous(ot, false);
|
||||||
|
zassert_false(otPlatRadioGetPromiscuous(ot), "Mode still enabled.");
|
||||||
|
|
||||||
|
rapi.configure = configure_mock;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Test of proper radio to OT capabilities mapping
|
||||||
|
* Tests if different radio capabilities map for their corresponding OpenThread
|
||||||
|
* capability
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static void get_caps_test(void)
|
||||||
|
{
|
||||||
|
rapi.get_capabilities = get_capabilities_caps_mock;
|
||||||
|
|
||||||
|
/* no caps */
|
||||||
|
ztest_returns_value(get_capabilities_caps_mock, 0);
|
||||||
|
zassert_equal(otPlatRadioGetCaps(ot), OT_RADIO_CAPS_NONE,
|
||||||
|
"Incorrect capabilities returned.");
|
||||||
|
|
||||||
|
/* not used by OT */
|
||||||
|
ztest_returns_value(get_capabilities_caps_mock, IEEE802154_HW_FCS);
|
||||||
|
zassert_equal(otPlatRadioGetCaps(ot), OT_RADIO_CAPS_NONE,
|
||||||
|
"Incorrect capabilities returned.");
|
||||||
|
ztest_returns_value(get_capabilities_caps_mock, IEEE802154_HW_2_4_GHZ);
|
||||||
|
zassert_equal(otPlatRadioGetCaps(ot), OT_RADIO_CAPS_NONE,
|
||||||
|
"Incorrect capabilities returned.");
|
||||||
|
ztest_returns_value(get_capabilities_caps_mock, IEEE802154_HW_SUB_GHZ);
|
||||||
|
zassert_equal(otPlatRadioGetCaps(ot), OT_RADIO_CAPS_NONE,
|
||||||
|
"Incorrect capabilities returned.");
|
||||||
|
|
||||||
|
/* not implemented or not fully supported */
|
||||||
|
ztest_returns_value(get_capabilities_caps_mock, IEEE802154_HW_TXTIME);
|
||||||
|
zassert_equal(otPlatRadioGetCaps(ot), OT_RADIO_CAPS_NONE,
|
||||||
|
"Incorrect capabilities returned.");
|
||||||
|
|
||||||
|
ztest_returns_value(get_capabilities_caps_mock, IEEE802154_HW_PROMISC);
|
||||||
|
zassert_equal(otPlatRadioGetCaps(ot), OT_RADIO_CAPS_NONE,
|
||||||
|
"Incorrect capabilities returned.");
|
||||||
|
|
||||||
|
/* proper mapping */
|
||||||
|
ztest_returns_value(get_capabilities_caps_mock, IEEE802154_HW_CSMA);
|
||||||
|
zassert_equal(otPlatRadioGetCaps(ot),
|
||||||
|
OT_RADIO_CAPS_TRANSMIT_RETRIES |
|
||||||
|
OT_RADIO_CAPS_CSMA_BACKOFF,
|
||||||
|
"Incorrect capabilities returned.");
|
||||||
|
|
||||||
|
ztest_returns_value(get_capabilities_caps_mock,
|
||||||
|
IEEE802154_HW_ENERGY_SCAN);
|
||||||
|
zassert_equal(otPlatRadioGetCaps(ot), OT_RADIO_CAPS_ENERGY_SCAN,
|
||||||
|
"Incorrect capabilities returned.");
|
||||||
|
|
||||||
|
ztest_returns_value(get_capabilities_caps_mock,
|
||||||
|
IEEE802154_HW_TX_RX_ACK);
|
||||||
|
zassert_equal(otPlatRadioGetCaps(ot), OT_RADIO_CAPS_ACK_TIMEOUT,
|
||||||
|
"Incorrect capabilities returned.");
|
||||||
|
|
||||||
|
/* all at once */
|
||||||
|
ztest_returns_value(
|
||||||
|
get_capabilities_caps_mock,
|
||||||
|
IEEE802154_HW_FCS | IEEE802154_HW_PROMISC |
|
||||||
|
IEEE802154_HW_FILTER | IEEE802154_HW_CSMA |
|
||||||
|
IEEE802154_HW_2_4_GHZ | IEEE802154_HW_TX_RX_ACK |
|
||||||
|
IEEE802154_HW_SUB_GHZ | IEEE802154_HW_ENERGY_SCAN |
|
||||||
|
IEEE802154_HW_TXTIME);
|
||||||
|
zassert_equal(
|
||||||
|
otPlatRadioGetCaps(ot),
|
||||||
|
OT_RADIO_CAPS_TRANSMIT_RETRIES | OT_RADIO_CAPS_CSMA_BACKOFF |
|
||||||
|
OT_RADIO_CAPS_ENERGY_SCAN | OT_RADIO_CAPS_ACK_TIMEOUT,
|
||||||
|
"Incorrect capabilities returned.");
|
||||||
|
|
||||||
|
rapi.get_capabilities = get_capabilities;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Test for getting the rssi value from the radio
|
||||||
|
* Tests if correct value is returned from the otPlatRadioGetRssi function.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static void get_rssi_test(void)
|
||||||
|
{
|
||||||
|
const s8_t rssi = -103;
|
||||||
|
|
||||||
|
rapi.ed_scan = rssi_scan_mock;
|
||||||
|
|
||||||
|
ztest_returns_value(rssi_scan_mock, rssi);
|
||||||
|
zassert_equal(otPlatRadioGetRssi(ot), rssi,
|
||||||
|
"Invalid RSSI value reveiced.");
|
||||||
|
|
||||||
|
rapi.ed_scan = scan_mock;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Test switching between radio states
|
||||||
|
* Tests if radio is correctly switched between states.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static void radio_state_test(void)
|
||||||
|
{
|
||||||
|
const u8_t channel = 12;
|
||||||
|
const u8_t power = 10;
|
||||||
|
|
||||||
|
otPlatRadioSetTransmitPower(ot, power);
|
||||||
|
zassert_equal(otPlatRadioDisable(ot), OT_ERROR_NONE,
|
||||||
|
"Failed to disable radio.");
|
||||||
|
|
||||||
|
zassert_false(otPlatRadioIsEnabled(ot), "Radio reports as enabled.");
|
||||||
|
|
||||||
|
zassert_equal(otPlatRadioSleep(ot), OT_ERROR_INVALID_STATE,
|
||||||
|
"Changed to sleep regardles being disabled.");
|
||||||
|
|
||||||
|
zassert_equal(otPlatRadioEnable(ot), OT_ERROR_NONE,
|
||||||
|
"Enabling radio failed.");
|
||||||
|
|
||||||
|
zassert_true(otPlatRadioIsEnabled(ot), "Radio reports disabled.");
|
||||||
|
|
||||||
|
ztest_expect_value(stop_mock, dev, &radio);
|
||||||
|
zassert_equal(otPlatRadioSleep(ot), OT_ERROR_NONE,
|
||||||
|
"Failed to switch to sleep mode.");
|
||||||
|
|
||||||
|
zassert_true(otPlatRadioIsEnabled(ot), "Radio reports as disabled.");
|
||||||
|
|
||||||
|
ztest_returns_value(set_channel_mock, 0);
|
||||||
|
ztest_expect_value(set_channel_mock, channel, channel);
|
||||||
|
ztest_expect_value(set_txpower_mock, dbm, power);
|
||||||
|
ztest_expect_value(start_mock, dev, &radio);
|
||||||
|
otPlatRadioReceive(ot, channel);
|
||||||
|
zassert_equal(platformRadioChannelGet(ot), channel,
|
||||||
|
"Channel number not remembered.");
|
||||||
|
|
||||||
|
zassert_true(otPlatRadioIsEnabled(ot), "Radio reports as disabled.");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Test address filtering
|
||||||
|
* Tests if short, extended address and PanID are correctly passed to the radio
|
||||||
|
* driver.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static void address_test(void)
|
||||||
|
{
|
||||||
|
const u16_t pan_id = 0xDEAD;
|
||||||
|
const u16_t short_add = 0xCAFE;
|
||||||
|
otExtAddress ieee_addr;
|
||||||
|
|
||||||
|
for (int i = 0; i < sizeof(ieee_addr.m8); i++) {
|
||||||
|
ieee_addr.m8[i] = 'a' + i;
|
||||||
|
}
|
||||||
|
|
||||||
|
ztest_expect_value(filter_mock, set, true);
|
||||||
|
ztest_expect_value(filter_mock, type, IEEE802154_FILTER_TYPE_PAN_ID);
|
||||||
|
ztest_expect_value(filter_mock, filter->pan_id, pan_id);
|
||||||
|
otPlatRadioSetPanId(ot, pan_id);
|
||||||
|
|
||||||
|
ztest_expect_value(filter_mock, set, true);
|
||||||
|
ztest_expect_value(filter_mock, type,
|
||||||
|
IEEE802154_FILTER_TYPE_SHORT_ADDR);
|
||||||
|
ztest_expect_value(filter_mock, filter->short_addr, short_add);
|
||||||
|
otPlatRadioSetShortAddress(ot, short_add);
|
||||||
|
|
||||||
|
ztest_expect_value(filter_mock, set, true);
|
||||||
|
ztest_expect_value(filter_mock, type, IEEE802154_FILTER_TYPE_IEEE_ADDR);
|
||||||
|
ztest_expect_data(filter_mock, filter->ieee_addr, ieee_addr.m8);
|
||||||
|
otPlatRadioSetExtendedAddress(ot, &ieee_addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Test received messages handling.
|
||||||
|
* Tests if received frames are properly passed to the OpenThread
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
static void receive_test(void)
|
||||||
|
{
|
||||||
|
struct net_pkt *packet;
|
||||||
|
struct net_buf *buf;
|
||||||
|
const u8_t channel = 21;
|
||||||
|
const s8_t power = -5;
|
||||||
|
const u8_t lqi = 240;
|
||||||
|
const s8_t rssi = -90;
|
||||||
|
u8_t len;
|
||||||
|
|
||||||
|
packet = net_pkt_alloc(K_NO_WAIT);
|
||||||
|
buf = net_pkt_get_reserve_tx_data(K_NO_WAIT);
|
||||||
|
net_pkt_append_buffer(packet, buf);
|
||||||
|
|
||||||
|
for (int i = 0; i < buf->size; i++) {
|
||||||
|
buf->data[i] = ('a' + i) & 0xFF;
|
||||||
|
}
|
||||||
|
len = buf->size - 3;
|
||||||
|
buf->len = len;
|
||||||
|
|
||||||
|
net_pkt_set_ieee802154_lqi(packet, lqi);
|
||||||
|
net_pkt_set_ieee802154_rssi(packet, rssi);
|
||||||
|
|
||||||
|
otPlatRadioSetTransmitPower(ot, power);
|
||||||
|
|
||||||
|
ztest_returns_value(set_channel_mock, 0);
|
||||||
|
ztest_expect_value(set_channel_mock, channel, channel);
|
||||||
|
ztest_expect_value(set_txpower_mock, dbm, power);
|
||||||
|
ztest_expect_value(start_mock, dev, &radio);
|
||||||
|
otPlatRadioReceive(ot, channel);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Not setting any expect values as nothing shall be called from
|
||||||
|
* notify_new_rx_frame calling thread. OT functions can be called only
|
||||||
|
* after semaphore for main thread is released.
|
||||||
|
*/
|
||||||
|
notify_new_rx_frame(packet);
|
||||||
|
|
||||||
|
make_sure_sem_set(Z_TIMEOUT_MS(100));
|
||||||
|
ztest_expect_value(otPlatRadioReceiveDone, aError, OT_ERROR_NONE);
|
||||||
|
ztest_expect_value(otPlatRadioReceiveDone, aFrame->mChannel, channel);
|
||||||
|
ztest_expect_value(otPlatRadioReceiveDone, aFrame->mLength, len);
|
||||||
|
ztest_expect_data(otPlatRadioReceiveDone, aFrame->mPsdu, buf->data);
|
||||||
|
platformRadioProcess(ot);
|
||||||
|
}
|
||||||
|
|
||||||
|
void test_main(void)
|
||||||
|
{
|
||||||
|
platformRadioInit();
|
||||||
|
|
||||||
|
ztest_test_suite(openthread_radio,
|
||||||
|
ztest_unit_test(energy_scan_immediate_test),
|
||||||
|
ztest_unit_test(energy_scan_delayed_test),
|
||||||
|
ztest_unit_test(tx_test),
|
||||||
|
ztest_unit_test(tx_power_test),
|
||||||
|
ztest_unit_test(sensitivity_test),
|
||||||
|
ztest_unit_test(source_match_test),
|
||||||
|
ztest_unit_test(promiscuous_mode_set_test),
|
||||||
|
ztest_unit_test(get_caps_test),
|
||||||
|
ztest_unit_test(get_rssi_test),
|
||||||
|
ztest_unit_test(radio_state_test),
|
||||||
|
ztest_unit_test(address_test),
|
||||||
|
ztest_unit_test(receive_test));
|
||||||
|
|
||||||
|
ztest_run_test_suite(openthread_radio);
|
||||||
|
}
|
4
tests/subsys/openthread/testcase.yaml
Normal file
4
tests/subsys/openthread/testcase.yaml
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
tests:
|
||||||
|
openthread.radio:
|
||||||
|
platform_whitelist: native_posix native_posix_64
|
||||||
|
tags: ot_radio
|
Loading…
Add table
Add a link
Reference in a new issue