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, &params));
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, &params));
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