net: mqtt-sn: Update MQTT-SN Unit Tests
Fixes: #78010 This commit adds tests for the "Gateway Advertisement and Discovery" process. This includes tests for handling SEARCHGW, GWINFO, and ADVERTISE as well as manually adding a Gateway for use. Gateway pruning when missing ADVERTISE messages is also tested. Signed-off-by: Kenneth Witham <kennywitham4@gmail.com>
This commit is contained in:
parent
aa9c9228d4
commit
cc33fd685f
2 changed files with 252 additions and 32 deletions
|
@ -18,3 +18,8 @@ CONFIG_ZTEST_STACK_SIZE=8192
|
|||
CONFIG_STACK_USAGE=y
|
||||
CONFIG_STACK_SENTINEL=y
|
||||
CONFIG_DEBUG=y
|
||||
|
||||
# Reduce MQTT_SN delay times for testing
|
||||
CONFIG_MQTT_SN_LIB_T_SEARCHGW=0
|
||||
CONFIG_MQTT_SN_LIB_T_GWINFO=0
|
||||
CONFIG_MQTT_SN_LIB_N_ADV=1
|
||||
|
|
|
@ -15,6 +15,9 @@
|
|||
LOG_MODULE_REGISTER(test);
|
||||
|
||||
static const struct mqtt_sn_data client_id = MQTT_SN_DATA_STRING_LITERAL("zephyr");
|
||||
static const struct mqtt_sn_data client2_id = MQTT_SN_DATA_STRING_LITERAL("zephyr2");
|
||||
static const uint8_t gw_id = 12;
|
||||
static const struct mqtt_sn_data gw_addr = MQTT_SN_DATA_STRING_LITERAL("gw1");
|
||||
|
||||
static uint8_t tx[255];
|
||||
static uint8_t rx[255];
|
||||
|
@ -23,24 +26,45 @@ static struct msg_send_data {
|
|||
int called;
|
||||
size_t msg_sz;
|
||||
int ret;
|
||||
const void *dest_addr;
|
||||
size_t addrlen;
|
||||
struct mqtt_sn_client *client;
|
||||
} msg_send_data;
|
||||
|
||||
static int msg_send(struct mqtt_sn_client *client, void *buf, size_t sz)
|
||||
struct k_sem mqtt_sn_tx_sem;
|
||||
struct k_sem mqtt_sn_rx_sem;
|
||||
struct k_sem mqtt_sn_cb_sem;
|
||||
|
||||
int mqtt_sn_data_cmp(struct mqtt_sn_data data1, struct mqtt_sn_data data2)
|
||||
{
|
||||
return data1.size == data2.size && strncmp(data1.data, data2.data, data1.size);
|
||||
}
|
||||
|
||||
static int msg_sendto(struct mqtt_sn_client *client, void *buf, size_t sz, const void *dest_addr,
|
||||
size_t addrlen)
|
||||
{
|
||||
msg_send_data.called++;
|
||||
msg_send_data.msg_sz = sz;
|
||||
msg_send_data.client = client;
|
||||
msg_send_data.dest_addr = dest_addr;
|
||||
msg_send_data.addrlen = addrlen;
|
||||
|
||||
k_sem_give(&mqtt_sn_tx_sem);
|
||||
|
||||
return msg_send_data.ret;
|
||||
}
|
||||
|
||||
static void assert_msg_send(int called, size_t msg_sz)
|
||||
static void assert_msg_send(int called, size_t msg_sz, const struct mqtt_sn_data *dest_addr)
|
||||
{
|
||||
zassert_equal(msg_send_data.called, called, "msg_send called %d times instead of %d",
|
||||
msg_send_data.called, called);
|
||||
zassert_equal(msg_send_data.msg_sz, msg_sz, "msg_sz is %zu instead of %zu",
|
||||
msg_send_data.msg_sz, msg_sz);
|
||||
if (dest_addr != NULL) {
|
||||
zassert_equal(mqtt_sn_data_cmp(*dest_addr,
|
||||
*((struct mqtt_sn_data *)msg_send_data.dest_addr)),
|
||||
0, "Addresses incorrect");
|
||||
}
|
||||
|
||||
memset(&msg_send_data, 0, sizeof(msg_send_data));
|
||||
}
|
||||
|
@ -54,6 +78,8 @@ static void evt_cb(struct mqtt_sn_client *client, const struct mqtt_sn_evt *evt)
|
|||
{
|
||||
memcpy(&evt_cb_data.last_evt, evt, sizeof(*evt));
|
||||
evt_cb_data.called++;
|
||||
|
||||
k_sem_give(&mqtt_sn_cb_sem);
|
||||
}
|
||||
|
||||
static bool tp_initialized;
|
||||
|
@ -68,23 +94,30 @@ static int tp_init(struct mqtt_sn_transport *tp)
|
|||
static struct {
|
||||
void *data;
|
||||
ssize_t sz;
|
||||
} recv_data;
|
||||
const void *src_addr;
|
||||
size_t addrlen;
|
||||
} recvfrom_data;
|
||||
|
||||
static ssize_t tp_recv(struct mqtt_sn_client *client, void *buffer, size_t length)
|
||||
static ssize_t tp_recvfrom(struct mqtt_sn_client *client, void *buffer, size_t length,
|
||||
void *src_addr, size_t *addrlen)
|
||||
{
|
||||
if (recv_data.data && recv_data.sz > 0 && length >= recv_data.sz) {
|
||||
memcpy(buffer, recv_data.data, recv_data.sz);
|
||||
if (recvfrom_data.data && recvfrom_data.sz > 0 && length >= recvfrom_data.sz) {
|
||||
memcpy(buffer, recvfrom_data.data, recvfrom_data.sz);
|
||||
memcpy(src_addr, recvfrom_data.src_addr, recvfrom_data.addrlen);
|
||||
*addrlen = recvfrom_data.addrlen;
|
||||
|
||||
k_sem_give(&mqtt_sn_rx_sem);
|
||||
}
|
||||
|
||||
return recv_data.sz;
|
||||
return recvfrom_data.sz;
|
||||
}
|
||||
|
||||
int tp_poll(struct mqtt_sn_client *client)
|
||||
{
|
||||
return recv_data.sz;
|
||||
return recvfrom_data.sz;
|
||||
}
|
||||
|
||||
static ZTEST_BMEM struct mqtt_sn_client mqtt_clients[3];
|
||||
static ZTEST_BMEM struct mqtt_sn_client mqtt_clients[8];
|
||||
static ZTEST_BMEM struct mqtt_sn_client *mqtt_client;
|
||||
|
||||
static void setup(void *f)
|
||||
|
@ -95,18 +128,24 @@ static void setup(void *f)
|
|||
mqtt_client = &mqtt_clients[i++];
|
||||
|
||||
transport = (struct mqtt_sn_transport){
|
||||
.init = tp_init, .msg_send = msg_send, .recv = tp_recv, .poll = tp_poll};
|
||||
.init = tp_init, .sendto = msg_sendto, .recvfrom = tp_recvfrom, .poll = tp_poll};
|
||||
tp_initialized = false;
|
||||
|
||||
memset(&evt_cb_data, 0, sizeof(evt_cb_data));
|
||||
memset(&msg_send_data, 0, sizeof(msg_send_data));
|
||||
memset(&recv_data, 0, sizeof(recv_data));
|
||||
memset(&recvfrom_data, 0, sizeof(recvfrom_data));
|
||||
k_sem_init(&mqtt_sn_tx_sem, 0, 1);
|
||||
k_sem_init(&mqtt_sn_rx_sem, 0, 1);
|
||||
k_sem_init(&mqtt_sn_cb_sem, 0, 1);
|
||||
}
|
||||
|
||||
static int input(struct mqtt_sn_client *client, void *buf, size_t sz)
|
||||
static int input(struct mqtt_sn_client *client, void *buf, size_t sz,
|
||||
const struct mqtt_sn_data *src_addr)
|
||||
{
|
||||
recv_data.data = buf;
|
||||
recv_data.sz = sz;
|
||||
recvfrom_data.data = buf;
|
||||
recvfrom_data.sz = sz;
|
||||
recvfrom_data.src_addr = src_addr->data;
|
||||
recvfrom_data.addrlen = src_addr->size;
|
||||
|
||||
return mqtt_sn_input(client);
|
||||
}
|
||||
|
@ -122,24 +161,187 @@ static void mqtt_sn_connect_no_will(struct mqtt_sn_client *client)
|
|||
zassert_equal(err, 0, "unexpected error %d");
|
||||
zassert_true(tp_initialized, "Transport not initialized");
|
||||
|
||||
err = mqtt_sn_add_gw(client, gw_id, gw_addr);
|
||||
zassert_equal(err, 0, "unexpected error %d");
|
||||
zassert_equal(evt_cb_data.called, 0, "Unexpected event");
|
||||
zassert_false(sys_slist_is_empty(&client->gateway), "GW not saved.");
|
||||
|
||||
err = mqtt_sn_connect(client, false, false);
|
||||
zassert_equal(err, 0, "unexpected error %d");
|
||||
assert_msg_send(1, 12);
|
||||
assert_msg_send(1, 12, &gw_addr);
|
||||
zassert_equal(client->state, 0, "Wrong state");
|
||||
zassert_equal(evt_cb_data.called, 0, "Unexpected event");
|
||||
|
||||
err = input(client, connack, sizeof(connack));
|
||||
err = input(client, connack, sizeof(connack), &gw_addr);
|
||||
zassert_equal(err, 0, "unexpected error %d");
|
||||
zassert_equal(client->state, 1, "Wrong state");
|
||||
zassert_equal(evt_cb_data.called, 1, "NO event");
|
||||
zassert_equal(evt_cb_data.last_evt.type, MQTT_SN_EVT_CONNECTED, "Wrong event");
|
||||
k_sleep(K_MSEC(10));
|
||||
}
|
||||
|
||||
static ZTEST(mqtt_sn_client, test_mqtt_sn_handle_advertise)
|
||||
{
|
||||
static uint8_t advertise[] = {5, 0x00, 0x0c, 0, 1};
|
||||
static uint8_t connack[] = {3, 0x05, 0x00};
|
||||
int err;
|
||||
|
||||
err = mqtt_sn_client_init(mqtt_client, &client_id, &transport, evt_cb, tx, sizeof(tx), rx,
|
||||
sizeof(rx));
|
||||
zassert_equal(err, 0, "unexpected error %d");
|
||||
|
||||
err = input(mqtt_client, advertise, sizeof(advertise), &gw_addr);
|
||||
zassert_equal(err, 0, "unexpected error %d");
|
||||
zassert_false(sys_slist_is_empty(&mqtt_client->gateway), "GW not saved.");
|
||||
zassert_equal(evt_cb_data.called, 1, "NO event");
|
||||
zassert_equal(evt_cb_data.last_evt.type, MQTT_SN_EVT_ADVERTISE, "Wrong event");
|
||||
|
||||
err = input(mqtt_client, advertise, sizeof(advertise), &gw_addr);
|
||||
zassert_equal(err, 0, "unexpected error %d");
|
||||
zassert_false(sys_slist_is_empty(&mqtt_client->gateway), "GW not saved.");
|
||||
zassert_equal(sys_slist_len(&mqtt_client->gateway), 1, "Too many Gateways stored.");
|
||||
zassert_equal(evt_cb_data.called, 2, "Unexpected event");
|
||||
zassert_equal(evt_cb_data.last_evt.type, MQTT_SN_EVT_ADVERTISE, "Wrong event");
|
||||
|
||||
err = mqtt_sn_connect(mqtt_client, false, false);
|
||||
zassert_equal(err, 0, "unexpected error %d");
|
||||
assert_msg_send(1, 12, &gw_addr);
|
||||
zassert_equal(mqtt_client->state, 0, "Wrong state");
|
||||
zassert_equal(evt_cb_data.called, 2, "Unexpected event");
|
||||
|
||||
err = input(mqtt_client, connack, sizeof(connack), &gw_addr);
|
||||
zassert_equal(err, 0, "unexpected error %d");
|
||||
zassert_equal(mqtt_client->state, 1, "Wrong state");
|
||||
zassert_equal(evt_cb_data.called, 3, "NO event");
|
||||
zassert_equal(evt_cb_data.last_evt.type, MQTT_SN_EVT_CONNECTED, "Wrong event");
|
||||
|
||||
err = k_sem_take(&mqtt_sn_cb_sem, K_NO_WAIT);
|
||||
err = k_sem_take(&mqtt_sn_cb_sem, K_SECONDS(10));
|
||||
zassert_equal(err, 0, "Timed out waiting for callback.");
|
||||
|
||||
zassert_true(sys_slist_is_empty(&mqtt_client->gateway), "GW not cleared on timeout");
|
||||
zassert_equal(evt_cb_data.called, 4, "NO event");
|
||||
zassert_equal(evt_cb_data.last_evt.type, MQTT_SN_EVT_DISCONNECTED, "Wrong event");
|
||||
zassert_equal(mqtt_client->state, 0, "Wrong state");
|
||||
|
||||
mqtt_sn_client_deinit(mqtt_client);
|
||||
}
|
||||
|
||||
static ZTEST(mqtt_sn_client, test_mqtt_sn_add_gw)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = mqtt_sn_client_init(mqtt_client, &client_id, &transport, evt_cb, tx, sizeof(tx), rx,
|
||||
sizeof(rx));
|
||||
zassert_equal(err, 0, "unexpected error %d");
|
||||
|
||||
err = mqtt_sn_add_gw(mqtt_client, gw_id, gw_addr);
|
||||
zassert_equal(err, 0, "unexpected error %d");
|
||||
zassert_false(sys_slist_is_empty(&mqtt_client->gateway), "GW not saved.");
|
||||
zassert_equal(evt_cb_data.called, 0, "Unexpected event");
|
||||
|
||||
mqtt_sn_client_deinit(mqtt_client);
|
||||
}
|
||||
|
||||
/* Test send SEARCHGW and GW response */
|
||||
static ZTEST(mqtt_sn_client, test_mqtt_sn_search_gw)
|
||||
{
|
||||
int err;
|
||||
static uint8_t gwinfo[3];
|
||||
|
||||
gwinfo[0] = 3;
|
||||
gwinfo[1] = 0x02;
|
||||
gwinfo[2] = gw_id;
|
||||
|
||||
err = mqtt_sn_client_init(mqtt_client, &client_id, &transport, evt_cb, tx, sizeof(tx), rx,
|
||||
sizeof(rx));
|
||||
zassert_equal(err, 0, "unexpected error %d");
|
||||
|
||||
err = k_sem_take(&mqtt_sn_tx_sem, K_NO_WAIT);
|
||||
err = mqtt_sn_search(mqtt_client, 1);
|
||||
zassert_equal(err, 0, "unexpected error %d");
|
||||
|
||||
err = k_sem_take(&mqtt_sn_tx_sem, K_SECONDS(10));
|
||||
zassert_equal(err, 0, "Timed out waiting for callback.");
|
||||
|
||||
assert_msg_send(1, 3, NULL);
|
||||
zassert_equal(mqtt_client->state, 0, "Wrong state");
|
||||
zassert_equal(evt_cb_data.called, 0, "Unexpected event");
|
||||
|
||||
err = input(mqtt_client, gwinfo, sizeof(gwinfo), &gw_addr);
|
||||
zassert_equal(err, 0, "unexpected error %d");
|
||||
zassert_false(sys_slist_is_empty(&mqtt_client->gateway), "GW not saved.");
|
||||
zassert_equal(evt_cb_data.last_evt.type, MQTT_SN_EVT_GWINFO, "Wrong event");
|
||||
|
||||
mqtt_sn_client_deinit(mqtt_client);
|
||||
}
|
||||
|
||||
/* Test send SEARCHGW and peer response */
|
||||
static ZTEST(mqtt_sn_client, test_mqtt_sn_search_peer)
|
||||
{
|
||||
int err;
|
||||
static uint8_t gwinfo[3 + 3];
|
||||
|
||||
gwinfo[0] = 3 + gw_addr.size;
|
||||
gwinfo[1] = 0x02;
|
||||
gwinfo[2] = gw_id;
|
||||
memcpy(&gwinfo[3], gw_addr.data, 3);
|
||||
|
||||
err = mqtt_sn_client_init(mqtt_client, &client_id, &transport, evt_cb, tx, sizeof(tx), rx,
|
||||
sizeof(rx));
|
||||
zassert_equal(err, 0, "unexpected error %d");
|
||||
|
||||
err = k_sem_take(&mqtt_sn_tx_sem, K_NO_WAIT);
|
||||
err = mqtt_sn_search(mqtt_client, 1);
|
||||
zassert_equal(err, 0, "unexpected error %d");
|
||||
|
||||
err = k_sem_take(&mqtt_sn_tx_sem, K_SECONDS(10));
|
||||
zassert_equal(err, 0, "Timed out waiting for callback.");
|
||||
|
||||
assert_msg_send(1, 3, NULL);
|
||||
zassert_equal(mqtt_client->state, 0, "Wrong state");
|
||||
zassert_equal(evt_cb_data.called, 0, "Unexpected event");
|
||||
|
||||
err = input(mqtt_client, gwinfo, sizeof(gwinfo), &gw_addr);
|
||||
zassert_equal(err, 0, "unexpected error %d");
|
||||
zassert_false(sys_slist_is_empty(&mqtt_client->gateway), "GW not saved.");
|
||||
zassert_equal(evt_cb_data.called, 1, "NO event");
|
||||
zassert_equal(evt_cb_data.last_evt.type, MQTT_SN_EVT_GWINFO, "Wrong event");
|
||||
|
||||
mqtt_sn_client_deinit(mqtt_client);
|
||||
}
|
||||
|
||||
static ZTEST(mqtt_sn_client, test_mqtt_sn_respond_searchgw)
|
||||
{
|
||||
int err;
|
||||
static uint8_t searchgw[] = {3, 0x01, 1};
|
||||
|
||||
err = mqtt_sn_client_init(mqtt_client, &client_id, &transport, evt_cb, tx, sizeof(tx), rx,
|
||||
sizeof(rx));
|
||||
zassert_equal(err, 0, "unexpected error %d");
|
||||
|
||||
err = mqtt_sn_add_gw(mqtt_client, gw_id, gw_addr);
|
||||
zassert_equal(err, 0, "unexpected error %d");
|
||||
zassert_false(sys_slist_is_empty(&mqtt_client->gateway), "GW not saved.");
|
||||
zassert_equal(evt_cb_data.called, 0, "Unexpected event");
|
||||
|
||||
err = k_sem_take(&mqtt_sn_tx_sem, K_NO_WAIT);
|
||||
err = input(mqtt_client, searchgw, sizeof(searchgw), &client2_id);
|
||||
zassert_equal(err, 0, "unexpected error %d");
|
||||
|
||||
err = k_sem_take(&mqtt_sn_tx_sem, K_SECONDS(10));
|
||||
zassert_equal(err, 0, "Timed out waiting for callback.");
|
||||
|
||||
zassert_equal(evt_cb_data.called, 1, "NO event");
|
||||
zassert_equal(evt_cb_data.last_evt.type, MQTT_SN_EVT_SEARCHGW, "Wrong event");
|
||||
assert_msg_send(1, 3 + gw_addr.size, NULL);
|
||||
|
||||
mqtt_sn_client_deinit(mqtt_client);
|
||||
}
|
||||
|
||||
static ZTEST(mqtt_sn_client, test_mqtt_sn_connect_no_will)
|
||||
{
|
||||
|
||||
mqtt_sn_connect_no_will(mqtt_client);
|
||||
mqtt_sn_client_deinit(mqtt_client);
|
||||
}
|
||||
|
||||
static ZTEST(mqtt_sn_client, test_mqtt_sn_connect_will)
|
||||
|
@ -154,31 +356,37 @@ static ZTEST(mqtt_sn_client, test_mqtt_sn_connect_will)
|
|||
sizeof(rx));
|
||||
zassert_equal(err, 0, "unexpected error %d");
|
||||
|
||||
err = mqtt_sn_add_gw(mqtt_client, gw_id, gw_addr);
|
||||
zassert_equal(err, 0, "unexpected error %d");
|
||||
zassert_false(sys_slist_is_empty(&mqtt_client->gateway), "GW not saved.");
|
||||
zassert_equal(evt_cb_data.called, 0, "Unexpected event");
|
||||
|
||||
mqtt_client->will_topic = MQTT_SN_DATA_STRING_LITERAL("topic");
|
||||
mqtt_client->will_msg = MQTT_SN_DATA_STRING_LITERAL("msg");
|
||||
|
||||
err = mqtt_sn_connect(mqtt_client, true, false);
|
||||
zassert_equal(err, 0, "unexpected error %d");
|
||||
assert_msg_send(1, 12);
|
||||
assert_msg_send(1, 12, &gw_addr);
|
||||
zassert_equal(mqtt_client->state, 0, "Wrong state");
|
||||
|
||||
err = input(mqtt_client, willtopicreq, sizeof(willtopicreq));
|
||||
err = input(mqtt_client, willtopicreq, sizeof(willtopicreq), &gw_addr);
|
||||
zassert_equal(err, 0, "unexpected error %d");
|
||||
zassert_equal(mqtt_client->state, 0, "Wrong state");
|
||||
assert_msg_send(1, 8);
|
||||
assert_msg_send(1, 8, &gw_addr);
|
||||
|
||||
err = input(mqtt_client, willmsgreq, sizeof(willmsgreq));
|
||||
err = input(mqtt_client, willmsgreq, sizeof(willmsgreq), &gw_addr);
|
||||
zassert_equal(err, 0, "unexpected error %d");
|
||||
zassert_equal(mqtt_client->state, 0, "Wrong state");
|
||||
zassert_equal(evt_cb_data.called, 0, "Unexpected event");
|
||||
assert_msg_send(1, 5);
|
||||
assert_msg_send(1, 5, &gw_addr);
|
||||
|
||||
err = input(mqtt_client, connack, sizeof(connack));
|
||||
err = input(mqtt_client, connack, sizeof(connack), &gw_addr);
|
||||
zassert_equal(err, 0, "unexpected error %d");
|
||||
zassert_equal(mqtt_client->state, 1, "Wrong state");
|
||||
zassert_equal(evt_cb_data.called, 1, "NO event");
|
||||
zassert_equal(evt_cb_data.last_evt.type, MQTT_SN_EVT_CONNECTED, "Wrong event");
|
||||
k_sleep(K_MSEC(10));
|
||||
|
||||
mqtt_sn_client_deinit(mqtt_client);
|
||||
}
|
||||
|
||||
static ZTEST(mqtt_sn_client, test_mqtt_sn_publish_qos0)
|
||||
|
@ -190,21 +398,28 @@ static ZTEST(mqtt_sn_client, test_mqtt_sn_publish_qos0)
|
|||
int err;
|
||||
|
||||
mqtt_sn_connect_no_will(mqtt_client);
|
||||
err = k_sem_take(&mqtt_sn_tx_sem, K_NO_WAIT);
|
||||
err = mqtt_sn_publish(mqtt_client, MQTT_SN_QOS_0, &topic, false, &data);
|
||||
zassert_equal(err, 0, "Unexpected error %d", err);
|
||||
|
||||
assert_msg_send(0, 0);
|
||||
k_sleep(K_MSEC(10));
|
||||
assert_msg_send(0, 0, NULL);
|
||||
|
||||
/* Expect a REGISTER to be sent */
|
||||
assert_msg_send(1, 12);
|
||||
err = input(mqtt_client, regack, sizeof(regack));
|
||||
err = k_sem_take(&mqtt_sn_tx_sem, K_SECONDS(10));
|
||||
zassert_equal(err, 0, "Timed out waiting for callback.");
|
||||
assert_msg_send(1, 12, &gw_addr);
|
||||
err = input(mqtt_client, regack, sizeof(regack), &gw_addr);
|
||||
zassert_equal(err, 0, "unexpected error %d");
|
||||
assert_msg_send(0, 0);
|
||||
k_sleep(K_MSEC(10));
|
||||
assert_msg_send(1, 20);
|
||||
err = k_sem_take(&mqtt_sn_tx_sem, K_NO_WAIT);
|
||||
assert_msg_send(0, 0, NULL);
|
||||
err = k_sem_take(&mqtt_sn_tx_sem, K_SECONDS(10));
|
||||
zassert_equal(err, 0, "Timed out waiting for callback.");
|
||||
assert_msg_send(1, 20, &gw_addr);
|
||||
|
||||
zassert_true(sys_slist_is_empty(&mqtt_client->publish), "Publish not empty");
|
||||
zassert_false(sys_slist_is_empty(&mqtt_client->topic), "Topic empty");
|
||||
|
||||
mqtt_sn_client_deinit(mqtt_client);
|
||||
}
|
||||
|
||||
ZTEST_SUITE(mqtt_sn_client, NULL, NULL, setup, NULL, NULL);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue