1 /*
2  * Copyright (c) 2023 Basalte bv
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <string.h>
8 
9 #include <zephyr/ztest.h>
10 #include <zephyr/net/coap_service.h>
11 
coap_method1(struct coap_resource * resource,struct coap_packet * request,struct sockaddr * addr,socklen_t addr_len)12 static int coap_method1(struct coap_resource *resource, struct coap_packet *request,
13 			struct sockaddr *addr, socklen_t addr_len)
14 {
15 	ARG_UNUSED(resource);
16 	ARG_UNUSED(request);
17 	ARG_UNUSED(addr);
18 	ARG_UNUSED(addr_len);
19 
20 	return -ENOSYS;
21 }
22 
coap_method2(struct coap_resource * resource,struct coap_packet * request,struct sockaddr * addr,socklen_t addr_len)23 static int coap_method2(struct coap_resource *resource, struct coap_packet *request,
24 			struct sockaddr *addr, socklen_t addr_len)
25 {
26 	ARG_UNUSED(resource);
27 	ARG_UNUSED(request);
28 	ARG_UNUSED(addr);
29 	ARG_UNUSED(addr_len);
30 
31 	return -ENOSYS;
32 }
33 
34 static const uint16_t service_A_port = 4242;
35 COAP_SERVICE_DEFINE(service_A, "a.service.com", &service_A_port, COAP_SERVICE_AUTOSTART);
36 
37 static const char * const resource_0_path[] = { "res0", NULL };
38 COAP_RESOURCE_DEFINE(resource_0, service_A, {
39 	.path = resource_0_path,
40 	.get = coap_method1,
41 	.put = coap_method2,
42 });
43 
44 static const char * const resource_1_path[] = { "res1", NULL };
45 COAP_RESOURCE_DEFINE(resource_1, service_A, {
46 	.path = resource_1_path,
47 	.post = coap_method1,
48 });
49 
50 static uint16_t service_B_port;
51 COAP_SERVICE_DEFINE(service_B, "b.service.com", &service_B_port, 0);
52 
53 static const char * const resource_2_path[] = { "res2", "sub", NULL };
54 COAP_RESOURCE_DEFINE(resource_2, service_B, {
55 	.path = resource_2_path,
56 	.get = coap_method2,
57 	.put = coap_method1,
58 });
59 
60 static const char * const resource_3_path[] = { "res3", "+", NULL };
61 COAP_RESOURCE_DEFINE(resource_3, service_B, {
62 	.path = resource_3_path,
63 	.post = coap_method2,
64 });
65 
66 static const uint16_t service_C_port = 5959;
67 COAP_SERVICE_DEFINE(service_C, "192.168.1.1", &service_C_port, 0);
68 
69 static const char * const resource_4_path[] = { "res4", "*", NULL };
70 COAP_RESOURCE_DEFINE(resource_4, service_C, {
71 	.path = resource_4_path,
72 	.get = coap_method1,
73 });
74 
ZTEST(coap_service,test_COAP_SERVICE_DEFINE)75 ZTEST(coap_service, test_COAP_SERVICE_DEFINE)
76 {
77 	zassert_ok(strcmp(service_A.host, "a.service.com"));
78 	zassert_equal(service_A.port, &service_A_port);
79 	zassert_equal(*service_A.port, 4242);
80 
81 	zassert_ok(strcmp(service_B.host, "b.service.com"));
82 	zassert_equal(service_B.port, &service_B_port);
83 	zassert_equal(*service_B.port, 0);
84 
85 	zassert_ok(strcmp(service_C.host, "192.168.1.1"));
86 	zassert_equal(service_C.port, &service_C_port);
87 	zassert_equal(*service_C.port, 5959);
88 }
89 
ZTEST(coap_service,test_COAP_SERVICE_COUNT)90 ZTEST(coap_service, test_COAP_SERVICE_COUNT)
91 {
92 	size_t n_svc;
93 
94 	n_svc = 4273;
95 	COAP_SERVICE_COUNT(&n_svc);
96 	zassert_equal(n_svc, 3);
97 }
98 
ZTEST(coap_service,test_COAP_SERVICE_RESOURCE_COUNT)99 ZTEST(coap_service, test_COAP_SERVICE_RESOURCE_COUNT)
100 {
101 	zassert_equal(COAP_SERVICE_RESOURCE_COUNT(&service_A), 2);
102 	zassert_equal(COAP_SERVICE_RESOURCE_COUNT(&service_B), 2);
103 	zassert_equal(COAP_SERVICE_RESOURCE_COUNT(&service_C), 1);
104 }
105 
ZTEST(coap_service,test_COAP_SERVICE_HAS_RESOURCE)106 ZTEST(coap_service, test_COAP_SERVICE_HAS_RESOURCE)
107 {
108 	zassert_true(COAP_SERVICE_HAS_RESOURCE(&service_A, &resource_0));
109 	zassert_true(COAP_SERVICE_HAS_RESOURCE(&service_A, &resource_1));
110 	zassert_false(COAP_SERVICE_HAS_RESOURCE(&service_A, &resource_2));
111 	zassert_false(COAP_SERVICE_HAS_RESOURCE(&service_A, &resource_3));
112 
113 	zassert_false(COAP_SERVICE_HAS_RESOURCE(&service_B, &resource_0));
114 	zassert_false(COAP_SERVICE_HAS_RESOURCE(&service_B, &resource_1));
115 	zassert_true(COAP_SERVICE_HAS_RESOURCE(&service_B, &resource_2));
116 	zassert_true(COAP_SERVICE_HAS_RESOURCE(&service_B, &resource_3));
117 
118 	zassert_false(COAP_SERVICE_HAS_RESOURCE(&service_C, &resource_0));
119 	zassert_true(COAP_SERVICE_HAS_RESOURCE(&service_C, &resource_4));
120 }
121 
ZTEST(coap_service,test_COAP_SERVICE_FOREACH)122 ZTEST(coap_service, test_COAP_SERVICE_FOREACH)
123 {
124 	size_t n_svc = 0;
125 	size_t have_service_A = 0;
126 	size_t have_service_B = 0;
127 	size_t have_service_C = 0;
128 
129 	COAP_SERVICE_FOREACH(svc) {
130 		if (svc == &service_A) {
131 			have_service_A = 1;
132 			zassert_equal(svc->flags & COAP_SERVICE_AUTOSTART, COAP_SERVICE_AUTOSTART);
133 		} else if (svc == &service_B) {
134 			have_service_B = 1;
135 			zassert_equal(svc->flags & COAP_SERVICE_AUTOSTART, 0);
136 		} else if (svc == &service_C) {
137 			have_service_C = 1;
138 			zassert_equal(svc->flags & COAP_SERVICE_AUTOSTART, 0);
139 		} else {
140 			zassert_unreachable("svc (%p) not equal to &service_A (%p), &service_B "
141 					    "(%p), or &service_C (%p)",
142 					    svc, &service_A, &service_B, &service_C);
143 		}
144 
145 		n_svc++;
146 	}
147 
148 	zassert_equal(n_svc, 3);
149 	zassert_equal(have_service_A + have_service_B + have_service_C, n_svc);
150 }
151 
ZTEST(coap_service,test_COAP_RESOURCE_FOREACH)152 ZTEST(coap_service, test_COAP_RESOURCE_FOREACH)
153 {
154 	size_t first_res, second_res, n_res;
155 
156 	n_res = 0;
157 	first_res = 0;
158 	second_res = 0;
159 	COAP_RESOURCE_FOREACH(service_A, res) {
160 		if (res == &resource_0) {
161 			first_res = 1;
162 		} else if (res == &resource_1) {
163 			second_res = 1;
164 		} else {
165 			zassert_unreachable(
166 				"res (%p) not equal to &resource_0 (%p) or &resource_1 (%p)", res,
167 				&resource_0, &resource_1);
168 		}
169 
170 		n_res++;
171 	}
172 
173 	zassert_equal(n_res, 2);
174 	zassert_equal(first_res + second_res, n_res);
175 
176 	n_res = 0;
177 	first_res = 0;
178 	second_res = 0;
179 	COAP_RESOURCE_FOREACH(service_B, res) {
180 		if (res == &resource_2) {
181 			first_res = 1;
182 		} else if (res == &resource_3) {
183 			second_res = 1;
184 		} else {
185 			zassert_unreachable(
186 				"res (%p) not equal to &resource_2 (%p) or &resource_3 (%p)", res,
187 				&resource_2, &resource_3);
188 		}
189 
190 		n_res++;
191 	}
192 
193 	zassert_equal(n_res, 2);
194 	zassert_equal(first_res + second_res, n_res);
195 
196 	n_res = 0;
197 	first_res = 0;
198 	second_res = 0;
199 	COAP_RESOURCE_FOREACH(service_C, res) {
200 		if (res == &resource_4) {
201 			first_res = 1;
202 		} else {
203 			zassert_unreachable(
204 				"res (%p) not equal to &resource_4 (%p)", res, &resource_4);
205 		}
206 		n_res++;
207 	}
208 
209 	zassert_equal(n_res, 1);
210 	zassert_equal(first_res + second_res, n_res);
211 }
212 
ZTEST(coap_service,test_COAP_SERVICE_FOREACH_RESOURCE)213 ZTEST(coap_service, test_COAP_SERVICE_FOREACH_RESOURCE)
214 {
215 	size_t first_res, second_res, n_res;
216 
217 	n_res = 0;
218 	first_res = 0;
219 	second_res = 0;
220 	COAP_SERVICE_FOREACH_RESOURCE(&service_A, res) {
221 		if (res == &resource_0) {
222 			first_res = 1;
223 		} else if (res == &resource_1) {
224 			second_res = 1;
225 		} else {
226 			zassert_unreachable(
227 				"res (%p) not equal to &resource_0 (%p) or &resource_1 (%p)", res,
228 				&resource_0, &resource_1);
229 		}
230 
231 		n_res++;
232 	}
233 
234 	zassert_equal(n_res, 2);
235 	zassert_equal(first_res + second_res, n_res);
236 
237 	n_res = 0;
238 	first_res = 0;
239 	second_res = 0;
240 	COAP_SERVICE_FOREACH_RESOURCE(&service_B, res) {
241 		if (res == &resource_2) {
242 			first_res = 1;
243 		} else if (res == &resource_3) {
244 			second_res = 1;
245 		} else {
246 			zassert_unreachable(
247 				"res (%p) not equal to &resource_2 (%p) or &resource_3 (%p)", res,
248 				&resource_2, &resource_3);
249 		}
250 
251 		n_res++;
252 	}
253 
254 	zassert_equal(n_res, 2);
255 	zassert_equal(first_res + second_res, n_res);
256 
257 	n_res = 0;
258 	first_res = 0;
259 	second_res = 0;
260 	COAP_SERVICE_FOREACH_RESOURCE(&service_C, res) {
261 		if (res == &resource_4) {
262 			first_res = 1;
263 		} else {
264 			zassert_unreachable(
265 				"res (%p) not equal to &resource_4 (%p)", res, &resource_4);
266 		}
267 		n_res++;
268 	}
269 
270 	zassert_equal(n_res, 1);
271 	zassert_equal(first_res + second_res, n_res);
272 }
273 
ZTEST(coap_service,test_COAP_RESOURCE_DEFINE)274 ZTEST(coap_service, test_COAP_RESOURCE_DEFINE)
275 {
276 	COAP_SERVICE_FOREACH_RESOURCE(&service_A, res) {
277 		if (res == &resource_0) {
278 			zassert_ok(strcmp(res->path[0], "res0"));
279 			zassert_equal(res->get, coap_method1);
280 			zassert_equal(res->put, coap_method2);
281 		} else if (res == &resource_1) {
282 			zassert_ok(strcmp(res->path[0], "res1"));
283 			zassert_equal(res->post, coap_method1);
284 		} else {
285 			zassert_unreachable(
286 				"res (%p) not equal to &resource_0 (%p) or &resource_1 (%p)", res,
287 				&resource_0, &resource_1);
288 		}
289 	}
290 
291 	COAP_SERVICE_FOREACH_RESOURCE(&service_B, res) {
292 		if (res == &resource_2) {
293 			zassert_ok(strcmp(res->path[0], "res2"));
294 			zassert_ok(strcmp(res->path[1], "sub"));
295 			zassert_equal(res->get, coap_method2);
296 			zassert_equal(res->put, coap_method1);
297 		} else if (res == &resource_3) {
298 			zassert_ok(strcmp(res->path[0], "res3"));
299 			zassert_ok(strcmp(res->path[1], "+"));
300 			zassert_equal(res->post, coap_method2);
301 		} else {
302 			zassert_unreachable(
303 				"res (%p) not equal to &resource_2 (%p) or &resource_3 (%p)", res,
304 				&resource_2, &resource_3);
305 		}
306 	}
307 
308 	COAP_SERVICE_FOREACH_RESOURCE(&service_C, res) {
309 		if (res == &resource_4) {
310 			zassert_ok(strcmp(res->path[0], "res4"));
311 			zassert_ok(strcmp(res->path[1], "*"));
312 			zassert_equal(res->get, coap_method1);
313 			zassert_equal(res->put, NULL);
314 		} else {
315 			zassert_unreachable(
316 				"res (%p) not equal to &resource_4 (%p)", res, &resource_4);
317 		}
318 	}
319 }
320 
321 ZTEST_SUITE(coap_service, NULL, NULL, NULL, NULL, NULL);
322