Skip to content

Commit cb54b39

Browse files
Damian-Nordicrlubos
authored andcommitted
net: openthread: rpc: add unit tests for otNetDataXXX
1. Add unit tests for APIs implemented in ot_rpc_netdata.c 2. Fix the implementation of otNetDataGet() not to use the output length if the function returns an error. Signed-off-by: Damian Krolik <[email protected]>
1 parent 8cea4b0 commit cb54b39

File tree

7 files changed

+363
-61
lines changed

7 files changed

+363
-61
lines changed

subsys/net/openthread/rpc/client/ot_rpc_netdata.c

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,26 +15,34 @@
1515
otError otNetDataGet(otInstance *aInstance, bool aStable, uint8_t *aData, uint8_t *aDataLength)
1616
{
1717
struct nrf_rpc_cbor_ctx ctx;
18-
otError error = OT_ERROR_NONE;
19-
size_t size = 0;
20-
const void *buf = NULL;
18+
otError error;
19+
const uint8_t *netdata = NULL;
20+
size_t netdata_len;
2121

22-
NRF_RPC_CBOR_ALLOC(&ot_group, ctx, 5);
22+
NRF_RPC_CBOR_ALLOC(&ot_group, ctx, 1 + 1 + sizeof(*aDataLength));
2323
nrf_rpc_encode_bool(&ctx, aStable);
2424
nrf_rpc_encode_uint(&ctx, *aDataLength);
25+
2526
nrf_rpc_cbor_cmd_rsp_no_err(&ot_group, OT_RPC_CMD_NETDATA_GET, &ctx);
2627

27-
buf = nrf_rpc_decode_buffer_ptr_and_size(&ctx, &size);
28+
error = nrf_rpc_decode_uint(&ctx);
2829

29-
if (buf && size) {
30-
memcpy(aData, buf, MIN(size, *aDataLength));
30+
/* Only expect the network data buffer if the error indicates success. */
31+
if (nrf_rpc_decode_valid(&ctx) && error == OT_ERROR_NONE) {
32+
netdata = nrf_rpc_decode_buffer_ptr_and_size(&ctx, &netdata_len);
3133
}
3234

33-
error = nrf_rpc_decode_uint(&ctx);
35+
if (netdata) {
36+
if (netdata_len <= *aDataLength) {
37+
memcpy(aData, netdata, netdata_len);
38+
*aDataLength = netdata_len;
39+
} else {
40+
nrf_rpc_decoder_invalid(&ctx, ZCBOR_ERR_UNKNOWN);
41+
}
42+
}
3443

3544
if (!nrf_rpc_decoding_done_and_check(&ot_group, &ctx)) {
3645
ot_rpc_report_rsp_decoding_error(OT_RPC_CMD_NETDATA_GET);
37-
return OT_ERROR_FAILED;
3846
}
3947

4048
return error;

subsys/net/openthread/rpc/common/ot_rpc_common.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -276,17 +276,17 @@ void ot_rpc_decode_service_config(struct nrf_rpc_cbor_ctx *ctx, otServiceConfig
276276

277277
buf = nrf_rpc_decode_buffer_ptr_and_size(ctx, &size);
278278
if (buf && size) {
279-
size = MIN(size, sizeof(config->mServerConfig.mServerData));
280-
memcpy(config->mServerConfig.mServerData, buf, size);
279+
size = MIN(size, sizeof(config->mServiceData));
280+
memcpy(config->mServiceData, buf, size);
281281
config->mServiceDataLength = size;
282282
}
283283

284284
config->mServerConfig.mStable = nrf_rpc_decode_bool(ctx);
285285

286286
buf = nrf_rpc_decode_buffer_ptr_and_size(ctx, &size);
287287
if (buf && size) {
288-
size = MIN(size, sizeof(config->mServiceData));
289-
memcpy(config->mServiceData, buf, size);
288+
size = MIN(size, sizeof(config->mServerConfig.mServerData));
289+
memcpy(config->mServerConfig.mServerData, buf, size);
290290
config->mServerConfig.mServerDataLength = size;
291291
}
292292

@@ -314,7 +314,7 @@ bool ot_rpc_encode_border_router_config(struct nrf_rpc_cbor_ctx *ctx,
314314

315315
tmp = config->mPreference;
316316

317-
if (!zcbor_uint_encode(ctx->zs, &tmp, sizeof(tmp))) {
317+
if (!zcbor_int_encode(ctx->zs, &tmp, sizeof(tmp))) {
318318
return false;
319319
}
320320

subsys/net/openthread/rpc/server/ot_rpc_netdata.c

Lines changed: 23 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -18,58 +18,44 @@
1818
static void ot_rpc_cmd_netdata_get(const struct nrf_rpc_group *group, struct nrf_rpc_cbor_ctx *ctx,
1919
void *handler_data)
2020
{
21-
struct nrf_rpc_cbor_ctx rsp_ctx;
22-
otError error = OT_ERROR_NONE;
2321
bool stable;
24-
bool decoded_ok;
25-
bool buff_allocated = false;
26-
uint8_t length = 0;
22+
uint8_t length;
23+
otError error;
24+
uint8_t *netdata;
25+
struct nrf_rpc_cbor_ctx rsp_ctx;
26+
size_t cbor_buffer_size = 0;
2727

28-
decoded_ok = zcbor_bool_decode(ctx->zs, &stable);
28+
stable = nrf_rpc_decode_bool(ctx);
29+
length = nrf_rpc_decode_uint(ctx);
2930

30-
if (!decoded_ok) {
31-
error = OT_ERROR_INVALID_ARGS;
32-
goto exit;
31+
if (!nrf_rpc_decoding_done_and_check(group, ctx)) {
32+
ot_rpc_report_cmd_decoding_error(OT_RPC_CMD_NETDATA_GET);
33+
return;
3334
}
3435

35-
decoded_ok = zcbor_uint_decode(ctx->zs, &length, sizeof(length));
36-
if (!decoded_ok) {
37-
error = OT_ERROR_INVALID_ARGS;
38-
goto exit;
39-
}
40-
41-
nrf_rpc_cbor_decoding_done(group, ctx);
42-
43-
NRF_RPC_CBOR_ALLOC(group, rsp_ctx, sizeof(error) + length + 3);
44-
buff_allocated = true;
36+
netdata = malloc(UINT8_MAX);
4537

46-
if (!zcbor_bstr_start_encode(rsp_ctx.zs)) {
47-
error = OT_ERROR_FAILED;
48-
goto exit;
38+
if (!netdata) {
39+
nrf_rpc_err(-ENOMEM, NRF_RPC_ERR_SRC_RECV, group, OT_RPC_CMD_NETDATA_GET,
40+
NRF_RPC_PACKET_TYPE_RSP);
41+
return;
4942
}
5043

5144
openthread_api_mutex_lock(openthread_get_default_context());
52-
53-
error = otNetDataGet(openthread_get_default_instance(), stable, rsp_ctx.zs[0].payload_mut,
54-
&length);
55-
rsp_ctx.zs[0].payload_mut += length;
56-
45+
error = otNetDataGet(openthread_get_default_instance(), stable, netdata, &length);
5746
openthread_api_mutex_unlock(openthread_get_default_context());
5847

59-
if (!zcbor_bstr_end_encode(rsp_ctx.zs, NULL)) {
60-
goto exit;
61-
}
48+
cbor_buffer_size += 1 + sizeof(error);
49+
cbor_buffer_size += (error == OT_ERROR_NONE) ? 2 + length : 0;
6250

63-
exit:
64-
if (!decoded_ok) {
65-
nrf_rpc_cbor_decoding_done(group, ctx);
66-
}
51+
NRF_RPC_CBOR_ALLOC(group, rsp_ctx, cbor_buffer_size);
52+
nrf_rpc_encode_uint(&rsp_ctx, error);
6753

68-
if (!buff_allocated) {
69-
NRF_RPC_CBOR_ALLOC(group, rsp_ctx, sizeof(error) + 1);
54+
if (error == OT_ERROR_NONE) {
55+
nrf_rpc_encode_buffer(&rsp_ctx, netdata, length);
7056
}
7157

72-
zcbor_uint_encode(rsp_ctx.zs, &error, sizeof(error));
58+
free(netdata);
7359
nrf_rpc_cbor_rsp_no_err(group, &rsp_ctx);
7460
}
7561

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
/*
2+
* Copyright (c) 2024 Nordic Semiconductor ASA
3+
*
4+
* SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
5+
*/
6+
7+
#include <mock_nrf_rpc_transport.h>
8+
#include <ot_rpc_ids.h>
9+
#include <ot_rpc_types.h>
10+
#include <test_rpc_env.h>
11+
12+
#include <zephyr/kernel.h>
13+
#include <zephyr/ztest.h>
14+
15+
#include <openthread/netdata.h>
16+
17+
/* Fake functions */
18+
19+
static void nrf_rpc_err_handler(const struct nrf_rpc_err_report *report)
20+
{
21+
zassert_ok(report->code);
22+
}
23+
24+
static void tc_setup(void *f)
25+
{
26+
mock_nrf_rpc_tr_expect_add(RPC_INIT_REQ, RPC_INIT_RSP);
27+
zassert_ok(nrf_rpc_init(nrf_rpc_err_handler));
28+
mock_nrf_rpc_tr_expect_reset();
29+
}
30+
31+
/* Test serialization of otNetDataGet() */
32+
ZTEST(ot_rpc_netdata, test_otNetDataGet)
33+
{
34+
const uint8_t exp_netdata[] = {NETDATA};
35+
otError error;
36+
/* Make the buffer slightly bigger than the actual data */
37+
uint8_t netdata[NETDATA_LENGTH + 1];
38+
uint8_t netdata_len = sizeof(netdata);
39+
40+
mock_nrf_rpc_tr_expect_add(
41+
RPC_CMD(OT_RPC_CMD_NETDATA_GET, CBOR_TRUE, CBOR_UINT8(NETDATA_LENGTH + 1)),
42+
RPC_RSP(OT_ERROR_NONE, CBOR_NETDATA));
43+
error = otNetDataGet(NULL, true, netdata, &netdata_len);
44+
mock_nrf_rpc_tr_expect_done();
45+
46+
zassert_equal(error, OT_ERROR_NONE);
47+
zassert_equal(netdata_len, NETDATA_LENGTH);
48+
zassert_mem_equal(netdata, exp_netdata, NETDATA_LENGTH);
49+
}
50+
51+
/* Test serialization of otNetDataGet() returning OT_ERROR_NO_BUFS */
52+
ZTEST(ot_rpc_netdata, test_otNetDataGet_nobufs)
53+
{
54+
otError error;
55+
/* Make the buffer slightly smaller than the actual data */
56+
uint8_t netdata[NETDATA_LENGTH - 1];
57+
uint8_t netdata_len = sizeof(netdata);
58+
59+
mock_nrf_rpc_tr_expect_add(
60+
RPC_CMD(OT_RPC_CMD_NETDATA_GET, CBOR_FALSE, CBOR_UINT8(NETDATA_LENGTH - 1)),
61+
RPC_RSP(OT_ERROR_NO_BUFS));
62+
error = otNetDataGet(NULL, false, netdata, &netdata_len);
63+
mock_nrf_rpc_tr_expect_done();
64+
65+
zassert_equal(error, OT_ERROR_NO_BUFS);
66+
}
67+
68+
/* Test serialization of otNetDataGetNextService() returning OT_ERROR_NONE */
69+
ZTEST(ot_rpc_netdata, test_otNetDataGetNextService)
70+
{
71+
const uint8_t exp_svc_data[] = {NETDATA_SVC_DATA};
72+
const uint8_t exp_svr_data[] = {NETDATA_SVR_DATA};
73+
otError error;
74+
otNetworkDataIterator iter = UINT32_MAX - 1;
75+
otServiceConfig service;
76+
77+
mock_nrf_rpc_tr_expect_add(
78+
RPC_CMD(OT_RPC_CMD_NETDATA_GET_NEXT_SERVICE, CBOR_UINT32(UINT32_MAX - 1)),
79+
RPC_RSP(CBOR_UINT32(UINT32_MAX), CBOR_NETDATA_SVC, OT_ERROR_NONE));
80+
error = otNetDataGetNextService(NULL, &iter, &service);
81+
mock_nrf_rpc_tr_expect_done();
82+
83+
zassert_equal(error, OT_ERROR_NONE);
84+
zassert_equal(iter, UINT32_MAX);
85+
zassert_equal(service.mServiceId, NETDATA_SVC_ID);
86+
zassert_equal(service.mEnterpriseNumber, NETDATA_SVC_ENTERPRISE);
87+
zassert_equal(service.mServiceDataLength, sizeof(exp_svc_data));
88+
zassert_mem_equal(service.mServiceData, exp_svc_data, service.mServiceDataLength);
89+
zassert_true(service.mServerConfig.mStable);
90+
zassert_equal(service.mServerConfig.mServerDataLength, sizeof(exp_svr_data));
91+
zassert_mem_equal(service.mServerConfig.mServerData, exp_svr_data,
92+
service.mServerConfig.mServerDataLength);
93+
zassert_equal(service.mServerConfig.mRloc16, NETDATA_SVR_RLOC);
94+
}
95+
96+
/* Test serialization of otNetDataGetNextOnMeshPrefix() returning OT_ERROR_NONE */
97+
ZTEST(ot_rpc_netdata, test_otNetDataGetNextOnMeshPrefix)
98+
{
99+
const uint8_t exp_prefix[] = {ADDR_1};
100+
otError error;
101+
otNetworkDataIterator iter = UINT32_MAX - 1;
102+
otBorderRouterConfig br;
103+
104+
mock_nrf_rpc_tr_expect_add(
105+
RPC_CMD(OT_RPC_CMD_NETDATA_GET_NEXT_ON_MESH_PREFIX, CBOR_UINT32(UINT32_MAX - 1)),
106+
RPC_RSP(CBOR_UINT32(UINT32_MAX), CBOR_NETDATA_BR, OT_ERROR_NONE));
107+
error = otNetDataGetNextOnMeshPrefix(NULL, &iter, &br);
108+
mock_nrf_rpc_tr_expect_done();
109+
110+
zassert_equal(error, OT_ERROR_NONE);
111+
zassert_equal(iter, UINT32_MAX);
112+
zassert_equal(br.mPrefix.mLength, 64);
113+
zassert_mem_equal(br.mPrefix.mPrefix.mFields.m8, exp_prefix, 64 / 8);
114+
zassert_equal(br.mPreference, -1);
115+
zassert_true(br.mPreferred);
116+
zassert_false(br.mSlaac);
117+
zassert_true(br.mDhcp);
118+
zassert_false(br.mConfigure);
119+
zassert_true(br.mDefaultRoute);
120+
zassert_false(br.mOnMesh);
121+
zassert_true(br.mStable);
122+
zassert_false(br.mNdDns);
123+
zassert_true(br.mDp);
124+
}
125+
126+
ZTEST_SUITE(ot_rpc_netdata, NULL, NULL, tc_setup, NULL, NULL);

tests/subsys/net/openthread/rpc/common/test_rpc_env.h

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,6 @@
5353
#define HOP_LIMIT 64
5454
#define DNS_NAME \
5555
STR_SEQUENCE(63), '.', STR_SEQUENCE(63), '.', STR_SEQUENCE(63), '.', STR_SEQUENCE(63)
56-
5756
#define MADDR_FF02_1 0xff, 0x02, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x01
5857
#define EXT_ADDR 0x48, INT_SEQUENCE(OT_EXT_ADDRESS_SIZE)
5958
#define NWK_NAME 0x70, INT_SEQUENCE(OT_NETWORK_NAME_MAX_SIZE)
@@ -81,3 +80,20 @@
8180
#define CBOR_ADDR1 0x50, ADDR_1
8281

8382
#define CBOR_SOC_ADDR CBOR_ADDR1, CBOR_UINT16(1024)
83+
84+
#define NETDATA_LENGTH 254
85+
#define NETDATA INT_SEQUENCE(NETDATA_LENGTH)
86+
#define NETDATA_SVC_ID 0x51
87+
#define NETDATA_SVC_ENTERPRISE 0x51012345
88+
#define NETDATA_SVC_DATA INT_SEQUENCE(OT_SERVICE_DATA_MAX_SIZE)
89+
#define NETDATA_SVR_DATA INT_SEQUENCE(OT_SERVER_DATA_MAX_SIZE)
90+
#define NETDATA_SVR_RLOC 0x1234
91+
#define NETDATA_BR_RLOC 0x2345
92+
#define CBOR_NETDATA 0x58, NETDATA_LENGTH, NETDATA
93+
#define CBOR_NETDATA_SVC \
94+
CBOR_UINT8(NETDATA_SVC_ID), CBOR_UINT32(NETDATA_SVC_ENTERPRISE), 0x58, \
95+
OT_SERVICE_DATA_MAX_SIZE, NETDATA_SVC_DATA, CBOR_TRUE, 0x58, \
96+
OT_SERVER_DATA_MAX_SIZE, NETDATA_SVR_DATA, CBOR_UINT16(NETDATA_SVR_RLOC)
97+
#define CBOR_NETDATA_BR \
98+
CBOR_ADDR1, CBOR_UINT8(64), 0x20, CBOR_TRUE, CBOR_FALSE, CBOR_TRUE, CBOR_FALSE, CBOR_TRUE, \
99+
CBOR_FALSE, CBOR_TRUE, CBOR_FALSE, CBOR_TRUE, CBOR_UINT16(NETDATA_BR_RLOC)

tests/subsys/net/openthread/rpc/server/src/ip6_suite.c

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -27,11 +27,6 @@ FAKE_VALUE_FUNC(otError, otIp6SubscribeMulticastAddress, otInstance *, const otI
2727
FAKE_VALUE_FUNC(otError, otIp6UnsubscribeMulticastAddress, otInstance *, const otIp6Address *);
2828
FAKE_VALUE_FUNC(otError, otIp6SetEnabled, otInstance *, bool);
2929
FAKE_VALUE_FUNC(bool, otIp6IsEnabled, otInstance *);
30-
FAKE_VALUE_FUNC(otError, otNetDataGet, otInstance *, bool, uint8_t *, uint8_t *);
31-
FAKE_VALUE_FUNC(otError, otNetDataGetNextService, otInstance *, otNetworkDataIterator *,
32-
otServiceConfig *);
33-
FAKE_VALUE_FUNC(otError, otNetDataGetNextOnMeshPrefix, otInstance *, otNetworkDataIterator *,
34-
otBorderRouterConfig *);
3530

3631
#define FOREACH_FAKE(f) \
3732
f(otCliInit); \
@@ -41,10 +36,7 @@ FAKE_VALUE_FUNC(otError, otNetDataGetNextOnMeshPrefix, otInstance *, otNetworkDa
4136
f(otIp6SubscribeMulticastAddress); \
4237
f(otIp6UnsubscribeMulticastAddress); \
4338
f(otIp6SetEnabled); \
44-
f(otIp6IsEnabled); \
45-
f(otNetDataGet); \
46-
f(otNetDataGetNextService); \
47-
f(otNetDataGetNextOnMeshPrefix);
39+
f(otIp6IsEnabled);
4840

4941
static void nrf_rpc_err_handler(const struct nrf_rpc_err_report *report)
5042
{

0 commit comments

Comments
 (0)