tests: coap_client: Improve socket stubs

* Use sys_rand_get() and seed the CoAP library, so our MIDs are
  random.
* Set socket events per socket, so we don't accidentally receive
  on wrong socket
* Reply with correct tokens

Signed-off-by: Seppo Takalo <seppo.takalo@nordicsemi.no>
This commit is contained in:
Seppo Takalo 2024-11-11 14:35:30 +02:00 committed by Anas Nashif
commit ca67f51170
4 changed files with 77 additions and 42 deletions

View file

@ -1,3 +1,4 @@
#Testing
CONFIG_ZTEST=y
CONFIG_ZTEST_STACK_SIZE=4096
CONFIG_TEST_RANDOM_GENERATOR=y

View file

@ -11,7 +11,7 @@
#include "stubs.h"
LOG_MODULE_REGISTER(coap_client_test);
LOG_MODULE_REGISTER(coap_client_test, LOG_LEVEL_DBG);
DEFINE_FFF_GLOBALS;
#define FFF_FAKES_LIST(FAKE)
@ -23,11 +23,14 @@ DEFINE_FFF_GLOBALS;
(CONFIG_COAP_INIT_ACK_TIMEOUT_MS + CONFIG_COAP_INIT_ACK_TIMEOUT_MS / 2)
#define VALID_MESSAGE_ID BIT(31)
#define TOKEN_OFFSET 4
static int16_t last_response_code;
static const char *test_path = "test";
static uint32_t messages_needing_response[2];
static uint8_t last_token[2][COAP_TOKEN_MAX_LEN];
static const uint8_t empty_token[COAP_TOKEN_MAX_LEN] = {0};
static struct coap_client client;
@ -61,6 +64,27 @@ static void set_next_pending_message_id(uint16_t id)
}
}
static void store_token(uint8_t *buf)
{
for (int i = 0; i < ARRAY_SIZE(last_token); i++) {
if (memcmp(last_token[i], empty_token, 8) == 0) {
memcpy(last_token[i], buf + TOKEN_OFFSET, COAP_TOKEN_MAX_LEN);
return;
}
}
}
static void restore_token(uint8_t *buf)
{
for (int i = 0; i < ARRAY_SIZE(last_token); i++) {
if (memcmp(last_token[i], empty_token, 8) != 0) {
memcpy(buf + TOKEN_OFFSET, last_token[i], COAP_TOKEN_MAX_LEN);
memset(last_token[i], 0, COAP_TOKEN_MAX_LEN);
return;
}
}
}
static ssize_t z_impl_zsock_recvfrom_custom_fake(int sock, void *buf, size_t max_len, int flags,
struct sockaddr *src_addr, socklen_t *addrlen)
{
@ -74,10 +98,11 @@ static ssize_t z_impl_zsock_recvfrom_custom_fake(int sock, void *buf, size_t max
ack_data[2] = (uint8_t)(last_message_id >> 8);
ack_data[3] = (uint8_t)last_message_id;
restore_token(ack_data);
memcpy(buf, ack_data, sizeof(ack_data));
clear_socket_events(ZSOCK_POLLIN);
clear_socket_events(sock, ZSOCK_POLLIN);
return sizeof(ack_data);
}
@ -90,14 +115,14 @@ static ssize_t z_impl_zsock_sendto_custom_fake(int sock, void *buf, size_t len,
last_message_id |= ((uint8_t *)buf)[2] << 8;
last_message_id |= ((uint8_t *)buf)[3];
type = (((uint8_t *)buf)[0] & 0x30) >> 4;
store_token(buf);
set_next_pending_message_id(last_message_id);
LOG_INF("Latest message ID: %d", last_message_id);
if (type == 0) {
set_socket_events(ZSOCK_POLLIN);
set_socket_events(sock, ZSOCK_POLLIN);
}
return 1;
@ -111,6 +136,7 @@ static ssize_t z_impl_zsock_sendto_custom_fake_no_reply(int sock, void *buf, siz
last_message_id |= ((uint8_t *)buf)[2] << 8;
last_message_id |= ((uint8_t *)buf)[3];
store_token(buf);
set_next_pending_message_id(last_message_id);
LOG_INF("Latest message ID: %d", last_message_id);
@ -128,6 +154,7 @@ static ssize_t z_impl_zsock_sendto_custom_fake_echo(int sock, void *buf, size_t
last_message_id |= ((uint8_t *)buf)[2] << 8;
last_message_id |= ((uint8_t *)buf)[3];
store_token(buf);
set_next_pending_message_id(last_message_id);
LOG_INF("Latest message ID: %d", last_message_id);
@ -144,7 +171,7 @@ static ssize_t z_impl_zsock_sendto_custom_fake_echo(int sock, void *buf, size_t
z_impl_zsock_sendto_fake.custom_fake = z_impl_zsock_sendto_custom_fake;
set_socket_events(ZSOCK_POLLIN);
set_socket_events(sock, ZSOCK_POLLIN);
return 1;
}
@ -160,6 +187,7 @@ static ssize_t z_impl_zsock_sendto_custom_fake_echo_next_req(int sock, void *buf
last_message_id |= ((uint8_t *)buf)[2] << 8;
last_message_id |= ((uint8_t *)buf)[3];
store_token(buf);
set_next_pending_message_id(last_message_id);
LOG_INF("Latest message ID: %d", last_message_id);
@ -184,7 +212,7 @@ static ssize_t z_impl_zsock_sendto_custom_fake_echo_next_req(int sock, void *buf
z_impl_zsock_sendto_fake.custom_fake = z_impl_zsock_sendto_custom_fake;
set_socket_events(ZSOCK_POLLIN);
set_socket_events(sock, ZSOCK_POLLIN);
return 1;
}
@ -202,10 +230,11 @@ static ssize_t z_impl_zsock_recvfrom_custom_fake_response(int sock, void *buf, s
ack_data[2] = (uint8_t)(last_message_id >> 8);
ack_data[3] = (uint8_t)last_message_id;
restore_token(ack_data);
memcpy(buf, ack_data, sizeof(ack_data));
clear_socket_events(ZSOCK_POLLIN);
clear_socket_events(sock, ZSOCK_POLLIN);
return sizeof(ack_data);
}
@ -216,7 +245,7 @@ static ssize_t z_impl_zsock_recvfrom_custom_fake_empty_ack(int sock, void *buf,
{
uint16_t last_message_id = 0;
static uint8_t ack_data[] = {0x68, 0x00, 0x00, 0x00, 0x00, 0x00,
static uint8_t ack_data[] = {0x60, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
last_message_id = get_next_pending_message_id();
@ -247,7 +276,7 @@ static ssize_t z_impl_zsock_recvfrom_custom_fake_unmatching(int sock, void *buf,
memcpy(buf, ack_data, sizeof(ack_data));
clear_socket_events(ZSOCK_POLLIN);
clear_socket_events(sock, ZSOCK_POLLIN);
return sizeof(ack_data);
}
@ -267,13 +296,14 @@ static ssize_t z_impl_zsock_recvfrom_custom_fake_echo(int sock, void *buf, size_
ack_data[2] = (uint8_t)(last_message_id >> 8);
ack_data[3] = (uint8_t)last_message_id;
restore_token(ack_data);
memcpy(buf, ack_data, sizeof(ack_data));
z_impl_zsock_recvfrom_fake.custom_fake = z_impl_zsock_recvfrom_custom_fake_response;
z_impl_zsock_sendto_fake.custom_fake = z_impl_zsock_sendto_custom_fake_echo;
clear_socket_events(ZSOCK_POLLIN);
clear_socket_events(sock, ZSOCK_POLLIN);
return sizeof(ack_data);
}
@ -293,19 +323,23 @@ static ssize_t z_impl_zsock_recvfrom_custom_fake_echo_next_req(int sock, void *b
ack_data[2] = (uint8_t)(last_message_id >> 8);
ack_data[3] = (uint8_t)last_message_id;
restore_token(ack_data);
memcpy(buf, ack_data, sizeof(ack_data));
z_impl_zsock_recvfrom_fake.custom_fake = z_impl_zsock_recvfrom_custom_fake_response;
z_impl_zsock_sendto_fake.custom_fake = z_impl_zsock_sendto_custom_fake_echo_next_req;
clear_socket_events(ZSOCK_POLLIN);
clear_socket_events(sock, ZSOCK_POLLIN);
return sizeof(ack_data);
}
extern void net_coap_init(void);
static void *suite_setup(void)
{
net_coap_init();
coap_client_init(&client, NULL);
return NULL;
@ -315,6 +349,8 @@ static void test_setup(void *data)
{
int i;
k_mutex_lock(&client.lock, K_FOREVER);
/* Register resets */
DO_FOREACH_FAKE(RESET_FAKE);
/* reset common FFF internal structures */
@ -322,13 +358,19 @@ static void test_setup(void *data)
z_impl_zsock_recvfrom_fake.custom_fake = z_impl_zsock_recvfrom_custom_fake;
z_impl_zsock_sendto_fake.custom_fake = z_impl_zsock_sendto_custom_fake;
clear_socket_events(ZSOCK_POLLIN | ZSOCK_POLLOUT | ZSOCK_POLLERR);
clear_socket_events(0, ZSOCK_POLLIN | ZSOCK_POLLOUT | ZSOCK_POLLERR);
clear_socket_events(1, ZSOCK_POLLIN | ZSOCK_POLLOUT | ZSOCK_POLLERR);
for (i = 0; i < ARRAY_SIZE(messages_needing_response); i++) {
messages_needing_response[i] = 0;
}
memset(&client.requests, 0, sizeof(client.requests));
memset(last_token, 0, sizeof(last_token));
last_response_code = 0;
k_mutex_unlock(&client.lock);
}
void coap_callback(int16_t code, size_t offset, const uint8_t *payload, size_t len, bool last_block,
@ -396,7 +438,7 @@ ZTEST(coap_client, test_resend_request)
ret = coap_client_req(&client, 0, &address, &client_request, NULL);
zassert_true(ret >= 0, "Sending request failed, %d", ret);
k_sleep(K_MSEC(MORE_THAN_ACK_TIMEOUT_MS));
set_socket_events(ZSOCK_POLLIN | ZSOCK_POLLOUT);
set_socket_events(client.fd, ZSOCK_POLLIN | ZSOCK_POLLOUT);
k_sleep(K_MSEC(MORE_THAN_EXCHANGE_LIFETIME_MS));
zassert_equal(last_response_code, COAP_RESPONSE_CODE_OK, "Unexpected response");
@ -551,7 +593,7 @@ ZTEST(coap_client, test_no_response)
client_request.len = strlen(short_payload);
z_impl_zsock_sendto_fake.custom_fake = z_impl_zsock_sendto_custom_fake_no_reply;
set_socket_events(ZSOCK_POLLOUT);
set_socket_events(client.fd, ZSOCK_POLLOUT);
k_sleep(K_MSEC(1));
@ -628,7 +670,7 @@ ZTEST(coap_client, test_multiple_requests)
ret = coap_client_req(&client, 0, &address, &req2, NULL);
zassert_true(ret >= 0, "Sending request failed, %d", ret);
set_socket_events(ZSOCK_POLLIN);
set_socket_events(client.fd, ZSOCK_POLLIN);
while (last_response_code == 0 && retry > 0) {
retry--;
k_sleep(K_MSEC(1));
@ -636,7 +678,7 @@ ZTEST(coap_client, test_multiple_requests)
zassert_equal(last_response_code, COAP_RESPONSE_CODE_OK, "Unexpected response");
last_response_code = 0;
set_socket_events(ZSOCK_POLLIN);
set_socket_events(client.fd, ZSOCK_POLLIN);
zassert_ok(k_sem_take(&sem1, K_MSEC(MORE_THAN_EXCHANGE_LIFETIME_MS)));
zassert_ok(k_sem_take(&sem2, K_MSEC(MORE_THAN_EXCHANGE_LIFETIME_MS)));
zassert_equal(last_response_code, COAP_RESPONSE_CODE_OK, "Unexpected response");
@ -665,7 +707,7 @@ ZTEST(coap_client, test_unmatching_tokens)
client_request.len = strlen(short_payload);
z_impl_zsock_recvfrom_fake.custom_fake = z_impl_zsock_recvfrom_custom_fake_unmatching;
set_socket_events(ZSOCK_POLLIN | ZSOCK_POLLOUT);
set_socket_events(client.fd, ZSOCK_POLLIN | ZSOCK_POLLOUT);
k_sleep(K_MSEC(1));
@ -681,9 +723,6 @@ ZTEST(coap_client, test_multiple_clients)
{
int ret;
int retry = MORE_THAN_EXCHANGE_LIFETIME_MS;
static struct coap_client client2 = {
.fd = 2,
};
struct k_sem sem1, sem2;
struct sockaddr address = {0};
struct coap_client_request req1 = {
@ -710,17 +749,17 @@ ZTEST(coap_client, test_multiple_clients)
k_sleep(K_MSEC(1));
LOG_INF("Sending requests");
ret = coap_client_req(&client, 1, &address, &req1, NULL);
ret = coap_client_req(&client, client.fd, &address, &req1, NULL);
zassert_true(ret >= 0, "Sending request failed, %d", ret);
ret = coap_client_req(&client2, 2, &address, &req2, NULL);
ret = coap_client_req(&client2, client2.fd, &address, &req2, NULL);
zassert_true(ret >= 0, "Sending request failed, %d", ret);
while (last_response_code == 0 && retry > 0) {
retry--;
k_sleep(K_MSEC(1));
}
set_socket_events(ZSOCK_POLLIN);
set_socket_events(client2.fd, ZSOCK_POLLIN);
k_sleep(K_SECONDS(1));
@ -746,7 +785,7 @@ ZTEST(coap_client, test_poll_err)
};
z_impl_zsock_sendto_fake.custom_fake = z_impl_zsock_sendto_custom_fake_no_reply;
set_socket_events(ZSOCK_POLLERR);
set_socket_events(client.fd, ZSOCK_POLLERR);
k_sleep(K_MSEC(1));
@ -776,7 +815,7 @@ ZTEST(coap_client, test_poll_err_after_response)
zassert_ok(k_sem_init(&sem1, 0, 1));
z_impl_zsock_sendto_fake.custom_fake = z_impl_zsock_sendto_custom_fake_no_reply;
set_socket_events(ZSOCK_POLLIN);
set_socket_events(client.fd, ZSOCK_POLLIN);
k_sleep(K_MSEC(1));
@ -787,6 +826,6 @@ ZTEST(coap_client, test_poll_err_after_response)
zassert_ok(k_sem_take(&sem1, K_MSEC(MORE_THAN_EXCHANGE_LIFETIME_MS)));
zassert_equal(last_response_code, COAP_RESPONSE_CODE_OK, "Unexpected response");
set_socket_events(ZSOCK_POLLERR);
set_socket_events(client.fd, ZSOCK_POLLERR);
zassert_not_ok(k_sem_take(&sem1, K_MSEC(MORE_THAN_EXCHANGE_LIFETIME_MS)));
}

View file

@ -10,7 +10,6 @@
LOG_MODULE_DECLARE(coap_client_test);
DEFINE_FAKE_VALUE_FUNC(uint32_t, z_impl_sys_rand32_get);
DEFINE_FAKE_VOID_FUNC(z_impl_sys_rand_get, void *, size_t);
DEFINE_FAKE_VALUE_FUNC(ssize_t, z_impl_zsock_recvfrom, int, void *, size_t, int, struct sockaddr *,
socklen_t *);
DEFINE_FAKE_VALUE_FUNC(ssize_t, z_impl_zsock_sendto, int, void *, size_t, int,
@ -22,21 +21,17 @@ struct zvfs_pollfd {
short revents;
};
static short my_events;
static short my_events[NUM_FD];
void set_socket_events(short events)
void set_socket_events(int fd, short events)
{
my_events |= events;
__ASSERT_NO_MSG(fd < NUM_FD);
my_events[fd] |= events;
}
void clear_socket_events(short events)
void clear_socket_events(int fd, short events)
{
my_events &= ~events;
}
int z_impl_zsock_socket(int family, int type, int proto)
{
return 0;
my_events[fd] &= ~events;
}
int z_impl_zvfs_poll(struct zvfs_pollfd *fds, int nfds, int poll_timeout)
@ -44,7 +39,8 @@ int z_impl_zvfs_poll(struct zvfs_pollfd *fds, int nfds, int poll_timeout)
int events = 0;
k_sleep(K_MSEC(1));
for (int i = 0; i < nfds; i++) {
fds[i].revents = my_events & (fds[i].events | ZSOCK_POLLERR | ZSOCK_POLLHUP);
fds[i].revents =
my_events[fds[i].fd] & (fds[i].events | ZSOCK_POLLERR | ZSOCK_POLLHUP);
if (fds[i].revents) {
events++;
}

View file

@ -36,12 +36,12 @@
#define ZSOCK_POLLNVAL 0x20
/** @} */
#define NUM_FD 2
void set_socket_events(short events);
void clear_socket_events(short events);
void set_socket_events(int fd, short events);
void clear_socket_events(int fd, short events);
DECLARE_FAKE_VALUE_FUNC(uint32_t, z_impl_sys_rand32_get);
DECLARE_FAKE_VOID_FUNC(z_impl_sys_rand_get, void *, size_t);
DECLARE_FAKE_VALUE_FUNC(ssize_t, z_impl_zsock_recvfrom, int, void *, size_t, int, struct sockaddr *,
socklen_t *);
DECLARE_FAKE_VALUE_FUNC(ssize_t, z_impl_zsock_sendto, int, void*, size_t, int,
@ -50,7 +50,6 @@ DECLARE_FAKE_VALUE_FUNC(ssize_t, z_impl_zsock_sendto, int, void*, size_t, int,
#define DO_FOREACH_FAKE(FUNC) \
do { \
FUNC(z_impl_sys_rand32_get) \
FUNC(z_impl_sys_rand_get) \
FUNC(z_impl_zsock_recvfrom) \
FUNC(z_impl_zsock_sendto) \
} while (0)