1 /*
2 * Copyright (c) 2023 Nordic Semiconductor ASA
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/fff.h>
8 #include <zephyr/logging/log.h>
9 #include <zephyr/misc/lorem_ipsum.h>
10 #include <zephyr/ztest.h>
11 #if defined(CONFIG_NATIVE_SIM_SLOWDOWN_TO_REAL_TIME)
12 #include "timer_model.h"
13 #endif
14 #include "stubs.h"
15
16 LOG_MODULE_REGISTER(coap_client_test, LOG_LEVEL_DBG);
17
18 DEFINE_FFF_GLOBALS;
19 #define FFF_FAKES_LIST(FAKE)
20
21 #define LONG_ACK_TIMEOUT_MS (2 * CONFIG_COAP_INIT_ACK_TIMEOUT_MS)
22 #define MORE_THAN_EXCHANGE_LIFETIME_MS 4 * CONFIG_COAP_INIT_ACK_TIMEOUT_MS
23 #define MORE_THAN_LONG_EXCHANGE_LIFETIME_MS 4 * LONG_ACK_TIMEOUT_MS
24 #define MORE_THAN_ACK_TIMEOUT_MS \
25 (CONFIG_COAP_INIT_ACK_TIMEOUT_MS + CONFIG_COAP_INIT_ACK_TIMEOUT_MS / 2)
26 #define COAP_SEPARATE_TIMEOUT (6000 * 2) /* Needs a safety marging, tests run faster than -rt */
27 #define VALID_MESSAGE_ID BIT(31)
28 #define TOKEN_OFFSET 4
29
30 void coap_callback(int16_t code, size_t offset, const uint8_t *payload, size_t len, bool last_block,
31 void *user_data);
32
33 static int16_t last_response_code;
34 static const char test_path[] = "test";
35
36 static uint32_t messages_needing_response[2];
37 static uint8_t last_token[2][COAP_TOKEN_MAX_LEN];
38 static const uint8_t empty_token[COAP_TOKEN_MAX_LEN] = {0};
39 K_SEM_DEFINE(sem1, 0, 1);
40 K_SEM_DEFINE(sem2, 0, 1);
41
42 static struct coap_client client;
43 static struct coap_client client2 = {
44 .fd = 1,
45 };
46
47 static const char short_payload[] = "testing";
48 static const char long_payload[] = LOREM_IPSUM_SHORT;
49 static struct coap_client_request short_request = {
50 .method = COAP_METHOD_GET,
51 .confirmable = true,
52 .path = test_path,
53 .fmt = COAP_CONTENT_FORMAT_TEXT_PLAIN,
54 .cb = coap_callback,
55 .payload = short_payload,
56 .len = sizeof(short_payload) - 1,
57 .user_data = &sem1,
58 };
59 static struct coap_client_request long_request = {
60 .method = COAP_METHOD_GET,
61 .confirmable = true,
62 .path = test_path,
63 .fmt = COAP_CONTENT_FORMAT_TEXT_PLAIN,
64 .cb = coap_callback,
65 .payload = long_payload,
66 .len = sizeof(long_payload) - 1,
67 .user_data = &sem2,
68 };
69 static struct sockaddr dst_address;
70
71
72
get_next_pending_message_id(void)73 static uint16_t get_next_pending_message_id(void)
74 {
75 int i;
76
77 for (i = 0; i < ARRAY_SIZE(messages_needing_response); i++) {
78 if (messages_needing_response[i] & VALID_MESSAGE_ID) {
79 messages_needing_response[i] &= ~VALID_MESSAGE_ID;
80 return messages_needing_response[i];
81 }
82 }
83
84 return UINT16_MAX;
85 }
86
set_next_pending_message_id(uint16_t id)87 static void set_next_pending_message_id(uint16_t id)
88 {
89 int i;
90
91 for (i = 0; i < ARRAY_SIZE(messages_needing_response); i++) {
92 if (!(messages_needing_response[i] & VALID_MESSAGE_ID)) {
93 messages_needing_response[i] = id;
94 messages_needing_response[i] |= VALID_MESSAGE_ID;
95 return;
96 }
97 }
98 }
99
store_token(uint8_t * buf)100 static void store_token(uint8_t *buf)
101 {
102 for (int i = 0; i < ARRAY_SIZE(last_token); i++) {
103 if (memcmp(last_token[i], empty_token, 8) == 0) {
104 memcpy(last_token[i], buf + TOKEN_OFFSET, COAP_TOKEN_MAX_LEN);
105 return;
106 }
107 }
108 }
109
restore_token(uint8_t * buf)110 static void restore_token(uint8_t *buf)
111 {
112 for (int i = 0; i < ARRAY_SIZE(last_token); i++) {
113 if (memcmp(last_token[i], empty_token, 8) != 0) {
114 memcpy(buf + TOKEN_OFFSET, last_token[i], COAP_TOKEN_MAX_LEN);
115 memset(last_token[i], 0, COAP_TOKEN_MAX_LEN);
116 return;
117 }
118 }
119 }
120
z_impl_zsock_recvfrom_custom_fake(int sock,void * buf,size_t max_len,int flags,struct sockaddr * src_addr,socklen_t * addrlen)121 static ssize_t z_impl_zsock_recvfrom_custom_fake(int sock, void *buf, size_t max_len, int flags,
122 struct sockaddr *src_addr, socklen_t *addrlen)
123 {
124 uint16_t last_message_id = 0;
125
126 LOG_INF("Recvfrom");
127 uint8_t ack_data[] = {0x68, 0x40, 0x00, 0x00, 0x00, 0x00,
128 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
129
130 last_message_id = get_next_pending_message_id();
131
132 ack_data[2] = (uint8_t)(last_message_id >> 8);
133 ack_data[3] = (uint8_t)last_message_id;
134 restore_token(ack_data);
135
136 memcpy(buf, ack_data, sizeof(ack_data));
137
138 clear_socket_events(sock, ZSOCK_POLLIN);
139
140 return sizeof(ack_data);
141 }
142
z_impl_zsock_sendto_custom_fake(int sock,void * buf,size_t len,int flags,const struct sockaddr * dest_addr,socklen_t addrlen)143 static ssize_t z_impl_zsock_sendto_custom_fake(int sock, void *buf, size_t len, int flags,
144 const struct sockaddr *dest_addr, socklen_t addrlen)
145 {
146 uint16_t last_message_id = 0;
147 uint8_t type;
148
149 last_message_id |= ((uint8_t *)buf)[2] << 8;
150 last_message_id |= ((uint8_t *)buf)[3];
151 type = (((uint8_t *)buf)[0] & 0x30) >> 4;
152 store_token(buf);
153
154 set_next_pending_message_id(last_message_id);
155 LOG_INF("Latest message ID: %d", last_message_id);
156
157 if (type == 0) {
158 set_socket_events(sock, ZSOCK_POLLIN);
159 }
160
161 return 1;
162 }
163
z_impl_zsock_sendto_custom_fake_no_reply(int sock,void * buf,size_t len,int flags,const struct sockaddr * dest_addr,socklen_t addrlen)164 static ssize_t z_impl_zsock_sendto_custom_fake_no_reply(int sock, void *buf, size_t len, int flags,
165 const struct sockaddr *dest_addr,
166 socklen_t addrlen)
167 {
168 uint16_t last_message_id = 0;
169
170 last_message_id |= ((uint8_t *)buf)[2] << 8;
171 last_message_id |= ((uint8_t *)buf)[3];
172 store_token(buf);
173
174 set_next_pending_message_id(last_message_id);
175 LOG_INF("Latest message ID: %d", last_message_id);
176
177 return 1;
178 }
179
z_impl_zsock_sendto_custom_fake_echo(int sock,void * buf,size_t len,int flags,const struct sockaddr * dest_addr,socklen_t addrlen)180 static ssize_t z_impl_zsock_sendto_custom_fake_echo(int sock, void *buf, size_t len, int flags,
181 const struct sockaddr *dest_addr,
182 socklen_t addrlen)
183 {
184 uint16_t last_message_id = 0;
185 struct coap_packet response = {0};
186 struct coap_option option = {0};
187
188 last_message_id |= ((uint8_t *)buf)[2] << 8;
189 last_message_id |= ((uint8_t *)buf)[3];
190 store_token(buf);
191
192 set_next_pending_message_id(last_message_id);
193 LOG_INF("Latest message ID: %d", last_message_id);
194
195 int ret = coap_packet_parse(&response, buf, len, NULL, 0);
196 if (ret < 0) {
197 LOG_ERR("Invalid data received");
198 }
199
200 ret = coap_find_options(&response, COAP_OPTION_ECHO, &option, 1);
201
202 zassert_equal(ret, 1, "Coap echo option not found, %d", ret);
203 zassert_mem_equal(option.value, "echo_value", option.len, "Incorrect echo data");
204
205 z_impl_zsock_sendto_fake.custom_fake = z_impl_zsock_sendto_custom_fake;
206
207 set_socket_events(sock, ZSOCK_POLLIN);
208
209 return 1;
210 }
211
z_impl_zsock_sendto_custom_fake_echo_next_req(int sock,void * buf,size_t len,int flags,const struct sockaddr * dest_addr,socklen_t addrlen)212 static ssize_t z_impl_zsock_sendto_custom_fake_echo_next_req(int sock, void *buf, size_t len,
213 int flags,
214 const struct sockaddr *dest_addr,
215 socklen_t addrlen)
216 {
217 uint16_t last_message_id = 0;
218 struct coap_packet response = {0};
219 struct coap_option option = {0};
220
221 last_message_id |= ((uint8_t *)buf)[2] << 8;
222 last_message_id |= ((uint8_t *)buf)[3];
223 store_token(buf);
224
225 set_next_pending_message_id(last_message_id);
226 LOG_INF("Latest message ID: %d", last_message_id);
227
228 int ret = coap_packet_parse(&response, buf, len, NULL, 0);
229 if (ret < 0) {
230 LOG_ERR("Invalid data received");
231 }
232
233 ret = coap_header_get_code(&response);
234 zassert_equal(ret, COAP_METHOD_POST, "Incorrect method, %d", ret);
235
236 uint16_t payload_len;
237
238 const uint8_t *payload = coap_packet_get_payload(&response, &payload_len);
239
240 zassert_mem_equal(payload, "echo testing", payload_len, "Incorrect payload");
241
242 ret = coap_find_options(&response, COAP_OPTION_ECHO, &option, 1);
243 zassert_equal(ret, 1, "Coap echo option not found, %d", ret);
244 zassert_mem_equal(option.value, "echo_value", option.len, "Incorrect echo data");
245
246 z_impl_zsock_sendto_fake.custom_fake = z_impl_zsock_sendto_custom_fake;
247
248 set_socket_events(sock, ZSOCK_POLLIN);
249
250 return 1;
251 }
252
z_impl_zsock_sendto_custom_fake_block(int sock,void * buf,size_t len,int flags,const struct sockaddr * dest_addr,socklen_t addrlen)253 static ssize_t z_impl_zsock_sendto_custom_fake_block(int sock, void *buf, size_t len, int flags,
254 const struct sockaddr *dest_addr,
255 socklen_t addrlen)
256 {
257 errno = EAGAIN;
258 return -1;
259 }
260
z_impl_zsock_sendto_custom_fake_err(int sock,void * buf,size_t len,int flags,const struct sockaddr * dest_addr,socklen_t addrlen)261 static ssize_t z_impl_zsock_sendto_custom_fake_err(int sock, void *buf, size_t len, int flags,
262 const struct sockaddr *dest_addr,
263 socklen_t addrlen)
264 {
265 errno = ENETDOWN;
266 return -1;
267 }
268
z_impl_zsock_recvfrom_custom_fake_response(int sock,void * buf,size_t max_len,int flags,struct sockaddr * src_addr,socklen_t * addrlen)269 static ssize_t z_impl_zsock_recvfrom_custom_fake_response(int sock, void *buf, size_t max_len,
270 int flags, struct sockaddr *src_addr,
271 socklen_t *addrlen)
272 {
273 uint16_t last_message_id = 0;
274
275 static uint8_t ack_data[] = {0x48, 0x40, 0x00, 0x00, 0x00, 0x00,
276 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
277
278 last_message_id = get_next_pending_message_id();
279
280 ack_data[2] = (uint8_t)(last_message_id >> 8);
281 ack_data[3] = (uint8_t)last_message_id;
282 restore_token(ack_data);
283
284 memcpy(buf, ack_data, sizeof(ack_data));
285
286 clear_socket_events(sock, ZSOCK_POLLIN);
287
288 return sizeof(ack_data);
289 }
290
z_impl_zsock_recvfrom_custom_fake_empty_ack(int sock,void * buf,size_t max_len,int flags,struct sockaddr * src_addr,socklen_t * addrlen)291 static ssize_t z_impl_zsock_recvfrom_custom_fake_empty_ack(int sock, void *buf, size_t max_len,
292 int flags, struct sockaddr *src_addr,
293 socklen_t *addrlen)
294 {
295 uint16_t last_message_id = 0;
296
297 static uint8_t ack_data[] = {0x60, 0x00, 0x00, 0x00, 0x00, 0x00,
298 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
299
300 last_message_id = get_next_pending_message_id();
301
302 ack_data[2] = (uint8_t)(last_message_id >> 8);
303 ack_data[3] = (uint8_t)last_message_id;
304
305 memcpy(buf, ack_data, sizeof(ack_data));
306
307 z_impl_zsock_recvfrom_fake.custom_fake = z_impl_zsock_recvfrom_custom_fake_response;
308
309 return sizeof(ack_data);
310 }
311
z_impl_zsock_recvfrom_custom_fake_rst(int sock,void * buf,size_t max_len,int flags,struct sockaddr * src_addr,socklen_t * addrlen)312 static ssize_t z_impl_zsock_recvfrom_custom_fake_rst(int sock, void *buf, size_t max_len, int flags,
313 struct sockaddr *src_addr, socklen_t *addrlen)
314 {
315 uint16_t last_message_id = 0;
316
317 static uint8_t rst_data[] = {0x70, 0x00, 0x00, 0x00, 0x00, 0x00,
318 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
319
320 last_message_id = get_next_pending_message_id();
321
322 rst_data[2] = (uint8_t)(last_message_id >> 8);
323 rst_data[3] = (uint8_t)last_message_id;
324
325 memcpy(buf, rst_data, sizeof(rst_data));
326 clear_socket_events(sock, ZSOCK_POLLIN);
327
328 return sizeof(rst_data);
329 }
330
z_impl_zsock_recvfrom_custom_fake_only_ack(int sock,void * buf,size_t max_len,int flags,struct sockaddr * src_addr,socklen_t * addrlen)331 static ssize_t z_impl_zsock_recvfrom_custom_fake_only_ack(int sock, void *buf, size_t max_len,
332 int flags, struct sockaddr *src_addr,
333 socklen_t *addrlen)
334 {
335 int ret;
336
337 ret = z_impl_zsock_recvfrom_custom_fake_empty_ack(sock, buf, max_len, flags, src_addr,
338 addrlen);
339 clear_socket_events(sock, ZSOCK_POLLIN);
340 return ret;
341 }
342
z_impl_zsock_recvfrom_custom_fake_unmatching(int sock,void * buf,size_t max_len,int flags,struct sockaddr * src_addr,socklen_t * addrlen)343 static ssize_t z_impl_zsock_recvfrom_custom_fake_unmatching(int sock, void *buf, size_t max_len,
344 int flags, struct sockaddr *src_addr,
345 socklen_t *addrlen)
346 {
347 uint16_t last_message_id = 0;
348
349 static uint8_t ack_data[] = {0x68, 0x40, 0x00, 0x00, 0x00, 0x00,
350 0x00, 0x00, 0x00, 0x00, 0x00, 0x01};
351
352 last_message_id = get_next_pending_message_id();
353
354 ack_data[2] = (uint8_t)(last_message_id >> 8);
355 ack_data[3] = (uint8_t)last_message_id;
356
357 memcpy(buf, ack_data, sizeof(ack_data));
358
359 clear_socket_events(sock, ZSOCK_POLLIN);
360
361 return sizeof(ack_data);
362 }
363
z_impl_zsock_recvfrom_custom_fake_echo(int sock,void * buf,size_t max_len,int flags,struct sockaddr * src_addr,socklen_t * addrlen)364 static ssize_t z_impl_zsock_recvfrom_custom_fake_echo(int sock, void *buf, size_t max_len,
365 int flags, struct sockaddr *src_addr,
366 socklen_t *addrlen)
367 {
368 uint16_t last_message_id = 0;
369
370 LOG_INF("Recvfrom");
371 uint8_t ack_data[] = {0x68, 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
372 0x00, 0x00, 0x00, 0x00, 0xda, 0xef, 'e', 'c',
373 'h', 'o', '_', 'v', 'a', 'l', 'u', 'e'};
374
375 last_message_id = get_next_pending_message_id();
376
377 ack_data[2] = (uint8_t)(last_message_id >> 8);
378 ack_data[3] = (uint8_t)last_message_id;
379 restore_token(ack_data);
380
381 memcpy(buf, ack_data, sizeof(ack_data));
382
383 z_impl_zsock_recvfrom_fake.custom_fake = z_impl_zsock_recvfrom_custom_fake_response;
384 z_impl_zsock_sendto_fake.custom_fake = z_impl_zsock_sendto_custom_fake_echo;
385
386 clear_socket_events(sock, ZSOCK_POLLIN);
387
388 return sizeof(ack_data);
389 }
390
z_impl_zsock_recvfrom_custom_fake_echo_next_req(int sock,void * buf,size_t max_len,int flags,struct sockaddr * src_addr,socklen_t * addrlen)391 static ssize_t z_impl_zsock_recvfrom_custom_fake_echo_next_req(int sock, void *buf, size_t max_len,
392 int flags, struct sockaddr *src_addr,
393 socklen_t *addrlen)
394 {
395 uint16_t last_message_id = 0;
396
397 LOG_INF("Recvfrom");
398 uint8_t ack_data[] = {0x68, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
399 0x00, 0x00, 0x00, 0x00, 0xda, 0xef, 'e', 'c',
400 'h', 'o', '_', 'v', 'a', 'l', 'u', 'e'};
401
402 last_message_id = get_next_pending_message_id();
403
404 ack_data[2] = (uint8_t)(last_message_id >> 8);
405 ack_data[3] = (uint8_t)last_message_id;
406 restore_token(ack_data);
407
408 memcpy(buf, ack_data, sizeof(ack_data));
409
410 z_impl_zsock_recvfrom_fake.custom_fake = z_impl_zsock_recvfrom_custom_fake_response;
411 z_impl_zsock_sendto_fake.custom_fake = z_impl_zsock_sendto_custom_fake_echo_next_req;
412
413 clear_socket_events(sock, ZSOCK_POLLIN);
414
415 return sizeof(ack_data);
416 }
417
z_impl_zsock_recvfrom_custom_fake_duplicate_response(int sock,void * buf,size_t max_len,int flags,struct sockaddr * src_addr,socklen_t * addrlen)418 static ssize_t z_impl_zsock_recvfrom_custom_fake_duplicate_response(int sock, void *buf,
419 size_t max_len, int flags,
420 struct sockaddr *src_addr,
421 socklen_t *addrlen)
422 {
423 uint8_t token[TOKEN_OFFSET + COAP_TOKEN_MAX_LEN];
424
425 uint16_t last_message_id = get_next_pending_message_id();
426
427 restore_token(token);
428
429 set_next_pending_message_id(last_message_id);
430 set_next_pending_message_id(last_message_id);
431 store_token(token);
432 store_token(token);
433
434 int ret = z_impl_zsock_recvfrom_custom_fake(sock, buf, max_len, flags, src_addr, addrlen);
435
436 set_socket_events(sock, ZSOCK_POLLIN);
437 z_impl_zsock_recvfrom_fake.custom_fake = z_impl_zsock_recvfrom_custom_fake;
438
439 return ret;
440 }
441
z_impl_zsock_recvfrom_custom_fake_observe(int sock,void * buf,size_t max_len,int flags,struct sockaddr * src_addr,socklen_t * addrlen)442 static ssize_t z_impl_zsock_recvfrom_custom_fake_observe(int sock, void *buf, size_t max_len,
443 int flags, struct sockaddr *src_addr,
444 socklen_t *addrlen)
445 {
446 int ret = z_impl_zsock_recvfrom_custom_fake_duplicate_response(sock, buf, max_len, flags,
447 src_addr, addrlen);
448
449 set_next_pending_message_id(get_next_pending_message_id() + 1);
450 z_impl_zsock_recvfrom_fake.custom_fake = z_impl_zsock_recvfrom_custom_fake_observe;
451 return ret;
452 }
453
coap_callback(int16_t code,size_t offset,const uint8_t * payload,size_t len,bool last_block,void * user_data)454 void coap_callback(int16_t code, size_t offset, const uint8_t *payload, size_t len, bool last_block,
455 void *user_data)
456 {
457 LOG_INF("CoAP response callback, %d", code);
458 last_response_code = code;
459 if (user_data) {
460 k_sem_give((struct k_sem *) user_data);
461 }
462 }
463
464 extern void net_coap_init(void);
465
suite_setup(void)466 static void *suite_setup(void)
467 {
468 #if defined(CONFIG_NATIVE_SIM_SLOWDOWN_TO_REAL_TIME)
469 /* It is enough that some slow-down is happening on sleeps, it does not have to be
470 * real time
471 */
472 hwtimer_set_rt_ratio(100.0);
473 k_sleep(K_MSEC(1));
474 #endif
475 net_coap_init();
476 zassert_ok(coap_client_init(&client, NULL));
477 zassert_ok(coap_client_init(&client2, NULL));
478
479 return NULL;
480 }
481
test_setup(void * data)482 static void test_setup(void *data)
483 {
484 int i;
485
486 k_mutex_lock(&client.lock, K_FOREVER);
487
488 /* Register resets */
489 DO_FOREACH_FAKE(RESET_FAKE);
490 /* reset common FFF internal structures */
491 FFF_RESET_HISTORY();
492
493 z_impl_zsock_recvfrom_fake.custom_fake = z_impl_zsock_recvfrom_custom_fake;
494 z_impl_zsock_sendto_fake.custom_fake = z_impl_zsock_sendto_custom_fake;
495 clear_socket_events(0, ZSOCK_POLLIN | ZSOCK_POLLOUT | ZSOCK_POLLERR);
496 clear_socket_events(1, ZSOCK_POLLIN | ZSOCK_POLLOUT | ZSOCK_POLLERR);
497
498 for (i = 0; i < ARRAY_SIZE(messages_needing_response); i++) {
499 messages_needing_response[i] = 0;
500 }
501
502 memset(&client.requests, 0, sizeof(client.requests));
503 memset(last_token, 0, sizeof(last_token));
504 last_response_code = 0;
505 k_sem_reset(&sem1);
506 k_sem_reset(&sem2);
507
508 k_mutex_unlock(&client.lock);
509 }
510
test_after(void * data)511 static void test_after(void *data)
512 {
513 coap_client_cancel_requests(&client);
514 coap_client_cancel_requests(&client2);
515 }
516
517 ZTEST_SUITE(coap_client, NULL, suite_setup, test_setup, test_after, NULL);
518
ZTEST(coap_client,test_get_request)519 ZTEST(coap_client, test_get_request)
520 {
521 zassert_ok(coap_client_req(&client, 0, &dst_address, &short_request, NULL));
522
523 k_sleep(K_MSEC(MORE_THAN_EXCHANGE_LIFETIME_MS));
524 zassert_equal(last_response_code, COAP_RESPONSE_CODE_OK, "Unexpected response");
525 }
526
ZTEST(coap_client,test_request_block)527 ZTEST(coap_client, test_request_block)
528 {
529 z_impl_zsock_sendto_fake.custom_fake = z_impl_zsock_sendto_custom_fake_block;
530
531 zassert_equal(coap_client_req(&client, 0, &dst_address, &short_request, NULL), -EAGAIN, "");
532 }
533
ZTEST(coap_client,test_resend_request)534 ZTEST(coap_client, test_resend_request)
535 {
536 int (*sendto_fakes[])(int, void *, size_t, int, const struct sockaddr *, socklen_t) = {
537 z_impl_zsock_sendto_custom_fake_no_reply,
538 z_impl_zsock_sendto_custom_fake_block,
539 z_impl_zsock_sendto_custom_fake,
540 };
541
542 SET_CUSTOM_FAKE_SEQ(z_impl_zsock_sendto, sendto_fakes, ARRAY_SIZE(sendto_fakes));
543 set_socket_events(client.fd, ZSOCK_POLLOUT);
544
545 zassert_ok(coap_client_req(&client, 0, &dst_address, &short_request, NULL));
546 k_sleep(K_MSEC(MORE_THAN_ACK_TIMEOUT_MS));
547
548 k_sleep(K_MSEC(MORE_THAN_EXCHANGE_LIFETIME_MS));
549 zassert_equal(last_response_code, COAP_RESPONSE_CODE_OK, "Unexpected response");
550 zassert_equal(z_impl_zsock_sendto_fake.call_count, 3);
551 }
552
ZTEST(coap_client,test_echo_option)553 ZTEST(coap_client, test_echo_option)
554 {
555 z_impl_zsock_recvfrom_fake.custom_fake = z_impl_zsock_recvfrom_custom_fake_echo;
556
557 zassert_ok(coap_client_req(&client, 0, &dst_address, &short_request, NULL));
558
559 k_sleep(K_MSEC(MORE_THAN_EXCHANGE_LIFETIME_MS));
560 zassert_equal(last_response_code, COAP_RESPONSE_CODE_OK, "Unexpected response");
561 }
562
ZTEST(coap_client,test_echo_option_next_req)563 ZTEST(coap_client, test_echo_option_next_req)
564 {
565 struct coap_client_request req = short_request;
566
567 z_impl_zsock_recvfrom_fake.custom_fake = z_impl_zsock_recvfrom_custom_fake_echo_next_req;
568
569 zassert_ok(coap_client_req(&client, 0, &dst_address, &short_request, NULL));
570
571 k_sleep(K_MSEC(MORE_THAN_EXCHANGE_LIFETIME_MS));
572 zassert_equal(last_response_code, COAP_RESPONSE_CODE_OK, "Unexpected response");
573
574 char *payload = "echo testing";
575
576 req.method = COAP_METHOD_POST;
577 req.payload = payload;
578 req.len = strlen(payload);
579
580 LOG_INF("Send next request");
581 zassert_ok(coap_client_req(&client, 0, &dst_address, &req, NULL));
582
583 k_sleep(K_MSEC(MORE_THAN_EXCHANGE_LIFETIME_MS));
584 zassert_equal(last_response_code, COAP_RESPONSE_CODE_OK, "Unexpected response");
585 }
586
ZTEST(coap_client,test_get_no_path)587 ZTEST(coap_client, test_get_no_path)
588 {
589 struct coap_client_request req = short_request;
590
591 req.path = NULL;
592 zassert_equal(coap_client_req(&client, 0, &dst_address, &req, NULL), -EINVAL, "");
593 }
594
ZTEST(coap_client,test_send_large_data)595 ZTEST(coap_client, test_send_large_data)
596 {
597 zassert_ok(coap_client_req(&client, 0, &dst_address, &long_request, NULL));
598
599 k_sleep(K_MSEC(MORE_THAN_EXCHANGE_LIFETIME_MS));
600 zassert_equal(last_response_code, COAP_RESPONSE_CODE_OK, "Unexpected response");
601 }
602
ZTEST(coap_client,test_no_response)603 ZTEST(coap_client, test_no_response)
604 {
605 struct coap_transmission_parameters params = {
606 .ack_timeout = LONG_ACK_TIMEOUT_MS,
607 .coap_backoff_percent = 200,
608 .max_retransmission = 0
609 };
610
611 z_impl_zsock_sendto_fake.custom_fake = z_impl_zsock_sendto_custom_fake_no_reply;
612 set_socket_events(client.fd, ZSOCK_POLLOUT);
613
614 zassert_ok(coap_client_req(&client, 0, &dst_address, &short_request, ¶ms));
615
616 k_sleep(K_MSEC(MORE_THAN_LONG_EXCHANGE_LIFETIME_MS));
617 zassert_equal(last_response_code, -ETIMEDOUT, "Unexpected response");
618 }
619
ZTEST(coap_client,test_separate_response)620 ZTEST(coap_client, test_separate_response)
621 {
622 z_impl_zsock_recvfrom_fake.custom_fake = z_impl_zsock_recvfrom_custom_fake_empty_ack;
623
624 zassert_ok(coap_client_req(&client, 0, &dst_address, &short_request, NULL));
625
626 k_sleep(K_MSEC(MORE_THAN_EXCHANGE_LIFETIME_MS));
627 zassert_equal(last_response_code, COAP_RESPONSE_CODE_OK, "Unexpected response");
628 }
629
ZTEST(coap_client,test_separate_response_lost)630 ZTEST(coap_client, test_separate_response_lost)
631 {
632 struct coap_client_request req = short_request;
633
634 req.user_data = &sem1;
635
636 z_impl_zsock_recvfrom_fake.custom_fake = z_impl_zsock_recvfrom_custom_fake_only_ack;
637 set_socket_events(client.fd, ZSOCK_POLLOUT);
638
639 zassert_ok(coap_client_req(&client, 0, &dst_address, &req, NULL));
640
641 zassert_ok(k_sem_take(&sem1, K_MSEC(COAP_SEPARATE_TIMEOUT)));
642 zassert_equal(last_response_code, -ETIMEDOUT, "");
643 }
644
ZTEST(coap_client,test_separate_response_ack_fail)645 ZTEST(coap_client, test_separate_response_ack_fail)
646 {
647 struct coap_client_request req = short_request;
648
649 req.user_data = &sem1;
650
651 int (*sendto_fakes[])(int, void *, size_t, int, const struct sockaddr *, socklen_t) = {
652 z_impl_zsock_sendto_custom_fake,
653 z_impl_zsock_sendto_custom_fake_err,
654 };
655
656 SET_CUSTOM_FAKE_SEQ(z_impl_zsock_sendto, sendto_fakes, ARRAY_SIZE(sendto_fakes));
657 z_impl_zsock_recvfrom_fake.custom_fake = z_impl_zsock_recvfrom_custom_fake_empty_ack;
658
659 zassert_ok(coap_client_req(&client, 0, &dst_address, &req, NULL));
660
661 zassert_ok(k_sem_take(&sem1, K_MSEC(COAP_SEPARATE_TIMEOUT)));
662 zassert_equal(last_response_code, -ENETDOWN, "");
663 }
664
ZTEST(coap_client,test_multiple_requests)665 ZTEST(coap_client, test_multiple_requests)
666 {
667 struct coap_client_request req1 = short_request;
668 struct coap_client_request req2 = short_request;
669
670 req1.user_data = &sem1;
671 req2.user_data = &sem2;
672
673 z_impl_zsock_sendto_fake.custom_fake = z_impl_zsock_sendto_custom_fake_no_reply;
674
675 zassert_ok(coap_client_req(&client, 0, &dst_address, &req1, NULL));
676 zassert_ok(coap_client_req(&client, 0, &dst_address, &req2, NULL));
677
678 set_socket_events(client.fd, ZSOCK_POLLIN);
679 zassert_ok(k_sem_take(&sem1, K_MSEC(MORE_THAN_EXCHANGE_LIFETIME_MS)));
680 zassert_equal(last_response_code, COAP_RESPONSE_CODE_OK, "Unexpected response");
681
682 last_response_code = 0;
683 set_socket_events(client.fd, ZSOCK_POLLIN);
684 zassert_ok(k_sem_take(&sem2, K_MSEC(MORE_THAN_EXCHANGE_LIFETIME_MS)));
685 zassert_equal(last_response_code, COAP_RESPONSE_CODE_OK, "Unexpected response");
686 }
687
ZTEST(coap_client,test_unmatching_tokens)688 ZTEST(coap_client, test_unmatching_tokens)
689 {
690 struct coap_transmission_parameters params = {
691 .ack_timeout = LONG_ACK_TIMEOUT_MS,
692 .coap_backoff_percent = 200,
693 .max_retransmission = 0
694 };
695
696 z_impl_zsock_recvfrom_fake.custom_fake = z_impl_zsock_recvfrom_custom_fake_unmatching;
697 set_socket_events(client.fd, ZSOCK_POLLIN | ZSOCK_POLLOUT);
698
699 zassert_ok(coap_client_req(&client, 0, &dst_address, &short_request, ¶ms));
700
701 k_sleep(K_MSEC(MORE_THAN_LONG_EXCHANGE_LIFETIME_MS));
702 zassert_equal(last_response_code, -ETIMEDOUT, "Unexpected response");
703 }
704
ZTEST(coap_client,test_multiple_clients)705 ZTEST(coap_client, test_multiple_clients)
706 {
707 struct coap_client_request req1 = short_request;
708 struct coap_client_request req2 = long_request;
709
710 req1.user_data = &sem1;
711 req2.user_data = &sem2;
712
713 zassert_ok(coap_client_req(&client, client.fd, &dst_address, &req1, NULL));
714 zassert_ok(coap_client_req(&client2, client2.fd, &dst_address, &req2, NULL));
715
716 /* ensure we got both responses */
717 zassert_ok(k_sem_take(&sem1, K_MSEC(MORE_THAN_EXCHANGE_LIFETIME_MS)));
718 zassert_ok(k_sem_take(&sem2, K_MSEC(MORE_THAN_EXCHANGE_LIFETIME_MS)));
719 zassert_equal(last_response_code, COAP_RESPONSE_CODE_OK, "Unexpected response");
720 }
721
722
ZTEST(coap_client,test_poll_err)723 ZTEST(coap_client, test_poll_err)
724 {
725 z_impl_zsock_sendto_fake.custom_fake = z_impl_zsock_sendto_custom_fake_no_reply;
726 set_socket_events(client.fd, ZSOCK_POLLERR);
727
728 zassert_ok(coap_client_req(&client, 0, &dst_address, &short_request, NULL));
729
730 k_sleep(K_MSEC(MORE_THAN_EXCHANGE_LIFETIME_MS));
731 zassert_equal(last_response_code, -EIO, "Unexpected response");
732 }
733
ZTEST(coap_client,test_poll_err_after_response)734 ZTEST(coap_client, test_poll_err_after_response)
735 {
736 z_impl_zsock_sendto_fake.custom_fake = z_impl_zsock_sendto_custom_fake_no_reply;
737 set_socket_events(client.fd, ZSOCK_POLLIN);
738
739 zassert_ok(coap_client_req(&client, 0, &dst_address, &short_request, NULL));
740
741 zassert_ok(k_sem_take(&sem1, K_MSEC(MORE_THAN_EXCHANGE_LIFETIME_MS)));
742 zassert_equal(last_response_code, COAP_RESPONSE_CODE_OK, "Unexpected response");
743
744 set_socket_events(client.fd, ZSOCK_POLLERR);
745 zassert_not_ok(k_sem_take(&sem1, K_MSEC(MORE_THAN_EXCHANGE_LIFETIME_MS)));
746 }
747
ZTEST(coap_client,test_poll_err_on_another_sock)748 ZTEST(coap_client, test_poll_err_on_another_sock)
749 {
750 struct coap_client_request req1 = short_request;
751 struct coap_client_request req2 = short_request;
752
753 req1.user_data = &sem1;
754 req2.user_data = &sem2;
755
756 z_impl_zsock_sendto_fake.custom_fake = z_impl_zsock_sendto_custom_fake_no_reply;
757 set_socket_events(client.fd, ZSOCK_POLLERR);
758
759 zassert_ok(coap_client_req(&client2, client2.fd, &dst_address, &req2, NULL));
760 zassert_ok(coap_client_req(&client, client.fd, &dst_address, &req1, NULL));
761
762 set_socket_events(client2.fd, ZSOCK_POLLIN);
763
764 zassert_ok(k_sem_take(&sem1, K_MSEC(MORE_THAN_EXCHANGE_LIFETIME_MS)));
765 zassert_equal(last_response_code, -EIO, "");
766 zassert_ok(k_sem_take(&sem2, K_MSEC(MORE_THAN_EXCHANGE_LIFETIME_MS)));
767 zassert_equal(last_response_code, COAP_RESPONSE_CODE_OK, "");
768 }
769
ZTEST(coap_client,test_duplicate_response)770 ZTEST(coap_client, test_duplicate_response)
771 {
772 z_impl_zsock_recvfrom_fake.custom_fake =
773 z_impl_zsock_recvfrom_custom_fake_duplicate_response;
774
775 zassert_ok(coap_client_req(&client, 0, &dst_address, &short_request, NULL));
776
777 zassert_ok(k_sem_take(&sem1, K_MSEC(MORE_THAN_EXCHANGE_LIFETIME_MS)));
778 zassert_equal(last_response_code, COAP_RESPONSE_CODE_OK, "Unexpected response");
779
780 zassert_equal(k_sem_take(&sem1, K_MSEC(MORE_THAN_EXCHANGE_LIFETIME_MS)), -EAGAIN, "");
781 }
782
ZTEST(coap_client,test_observe)783 ZTEST(coap_client, test_observe)
784 {
785 struct coap_client_option options = {
786 .code = COAP_OPTION_OBSERVE,
787 .value[0] = 0,
788 .len = 1,
789 };
790 struct coap_client_request req = {
791 .method = COAP_METHOD_GET,
792 .confirmable = true,
793 .path = test_path,
794 .fmt = COAP_CONTENT_FORMAT_TEXT_PLAIN,
795 .cb = coap_callback,
796 .payload = short_payload,
797 .len = strlen(short_payload),
798 .options = &options,
799 .num_options = 1,
800 .user_data = &sem1,
801 };
802
803 z_impl_zsock_recvfrom_fake.custom_fake = z_impl_zsock_recvfrom_custom_fake_observe;
804
805
806 zassert_ok(coap_client_req(&client, 0, &dst_address, &req, NULL));
807
808 zassert_ok(k_sem_take(&sem1, K_MSEC(MORE_THAN_EXCHANGE_LIFETIME_MS)));
809 zassert_ok(k_sem_take(&sem1, K_MSEC(MORE_THAN_EXCHANGE_LIFETIME_MS)));
810 zassert_ok(k_sem_take(&sem1, K_MSEC(MORE_THAN_EXCHANGE_LIFETIME_MS)));
811
812 coap_client_cancel_requests(&client);
813 zassert_ok(k_sem_take(&sem1, K_MSEC(MORE_THAN_EXCHANGE_LIFETIME_MS)));
814 zassert_equal(last_response_code, -ECANCELED, "");
815
816 zassert_not_ok(k_sem_take(&sem1, K_MSEC(MORE_THAN_EXCHANGE_LIFETIME_MS)));
817 }
818
ZTEST(coap_client,test_request_rst)819 ZTEST(coap_client, test_request_rst)
820 {
821 z_impl_zsock_recvfrom_fake.custom_fake = z_impl_zsock_recvfrom_custom_fake_rst;
822
823 zassert_ok(coap_client_req(&client, 0, &dst_address, &short_request, NULL));
824
825 zassert_ok(k_sem_take(&sem1, K_MSEC(MORE_THAN_EXCHANGE_LIFETIME_MS)));
826 zassert_equal(last_response_code, -ECONNRESET, "");
827 }
828
ZTEST(coap_client,test_cancel)829 ZTEST(coap_client, test_cancel)
830 {
831 struct coap_client_request req1 = short_request;
832 struct coap_client_request req2 = short_request;
833
834 req1.user_data = &sem1;
835 req2.user_data = &sem2;
836
837 z_impl_zsock_sendto_fake.custom_fake = z_impl_zsock_sendto_custom_fake_no_reply;
838
839 zassert_ok(coap_client_req(&client, 0, &dst_address, &req1, NULL));
840 zassert_ok(coap_client_req(&client, 0, &dst_address, &req2, NULL));
841
842 k_sleep(K_SECONDS(1));
843
844 coap_client_cancel_request(&client, &req1);
845 zassert_ok(k_sem_take(&sem1, K_MSEC(MORE_THAN_EXCHANGE_LIFETIME_MS)));
846 zassert_not_ok(k_sem_take(&sem2, K_MSEC(MORE_THAN_EXCHANGE_LIFETIME_MS)));
847 zassert_equal(last_response_code, -ECANCELED, "");
848
849 set_socket_events(client.fd, ZSOCK_POLLIN); /* First response is the cancelled one */
850 zassert_not_ok(k_sem_take(&sem1, K_MSEC(MORE_THAN_EXCHANGE_LIFETIME_MS)));
851 set_socket_events(client.fd, ZSOCK_POLLIN);
852 zassert_ok(k_sem_take(&sem2, K_MSEC(MORE_THAN_EXCHANGE_LIFETIME_MS)));
853 zassert_equal(last_response_code, COAP_RESPONSE_CODE_OK, "");
854 }
855
ZTEST(coap_client,test_cancel_match)856 ZTEST(coap_client, test_cancel_match)
857 {
858 struct coap_client_request req1 = short_request;
859 struct coap_client_request req2 = short_request;
860
861 req1.user_data = &sem1;
862 req2.user_data = &sem2;
863 req2.path = "another";
864
865 z_impl_zsock_sendto_fake.custom_fake = z_impl_zsock_sendto_custom_fake_no_reply;
866
867 zassert_ok(coap_client_req(&client, 0, &dst_address, &req1, NULL));
868 zassert_ok(coap_client_req(&client, 0, &dst_address, &req2, NULL));
869
870 k_sleep(K_SECONDS(1));
871
872 /* match only one */
873 coap_client_cancel_request(&client, &(struct coap_client_request) {
874 .path = test_path
875 });
876 zassert_ok(k_sem_take(&sem1, K_MSEC(MORE_THAN_EXCHANGE_LIFETIME_MS)));
877 zassert_not_ok(k_sem_take(&sem2, K_MSEC(MORE_THAN_EXCHANGE_LIFETIME_MS)));
878 zassert_equal(last_response_code, -ECANCELED, "");
879
880 zassert_ok(coap_client_req(&client, 0, &dst_address, &req1, NULL));
881
882 /* should not match */
883 coap_client_cancel_request(&client, &(struct coap_client_request) {
884 .path = test_path,
885 .user_data = &sem2,
886 });
887 zassert_not_ok(k_sem_take(&sem1, K_MSEC(MORE_THAN_EXCHANGE_LIFETIME_MS)));
888 zassert_not_ok(k_sem_take(&sem2, K_MSEC(MORE_THAN_EXCHANGE_LIFETIME_MS)));
889
890 /* match both (all GET queries) */
891 coap_client_cancel_request(&client, &(struct coap_client_request) {
892 .method = COAP_METHOD_GET,
893 });
894 zassert_ok(k_sem_take(&sem1, K_MSEC(MORE_THAN_EXCHANGE_LIFETIME_MS)));
895 zassert_ok(k_sem_take(&sem2, K_MSEC(MORE_THAN_EXCHANGE_LIFETIME_MS)));
896
897 zassert_ok(coap_client_req(&client, 0, &dst_address, &req1, NULL));
898 zassert_ok(coap_client_req(&client, 0, &dst_address, &req2, NULL));
899
900 /* match both (wildcard)*/
901 coap_client_cancel_request(&client, &(struct coap_client_request) {0});
902 zassert_ok(k_sem_take(&sem1, K_MSEC(MORE_THAN_EXCHANGE_LIFETIME_MS)));
903 zassert_ok(k_sem_take(&sem2, K_MSEC(MORE_THAN_EXCHANGE_LIFETIME_MS)));
904
905 }
906
ZTEST(coap_client,test_non_confirmable)907 ZTEST(coap_client, test_non_confirmable)
908 {
909 struct coap_client_request req = {
910 .method = COAP_METHOD_GET,
911 .confirmable = false,
912 .path = test_path,
913 .fmt = COAP_CONTENT_FORMAT_TEXT_PLAIN,
914 .cb = coap_callback,
915 .payload = short_payload,
916 .len = strlen(short_payload),
917 .user_data = &sem1
918 };
919
920 z_impl_zsock_sendto_fake.custom_fake = z_impl_zsock_sendto_custom_fake_no_reply;
921 set_socket_events(client.fd, ZSOCK_POLLOUT);
922
923 for (int i = 0; i < CONFIG_COAP_CLIENT_MAX_REQUESTS; i++) {
924 zassert_ok(coap_client_req(&client, 0, &dst_address, &req, NULL));
925 }
926 zassert_equal(coap_client_req(&client, 0, &dst_address, &req, NULL), -EAGAIN, "");
927
928 k_sleep(K_MSEC(MORE_THAN_LONG_EXCHANGE_LIFETIME_MS));
929
930 for (int i = 0; i < CONFIG_COAP_CLIENT_MAX_REQUESTS; i++) {
931 zassert_ok(coap_client_req(&client, 0, &dst_address, &req, NULL));
932 }
933 zassert_equal(coap_client_req(&client, 0, &dst_address, &req, NULL), -EAGAIN, "");
934
935 /* No callbacks from non-confirmable */
936 zassert_not_ok(k_sem_take(&sem1, K_MSEC(MORE_THAN_EXCHANGE_LIFETIME_MS)));
937 }
938