1 /*
2  * Copyright (c) 2022 grandcentrix GmbH
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/logging/log.h>
8 
9 #include <stubs.h>
10 
11 LOG_MODULE_DECLARE(lwm2m_rd_client_test);
12 
13 /* zephyr/net/coap.h */
14 DEFINE_FAKE_VALUE_FUNC(uint8_t, coap_header_get_code, const struct coap_packet *);
coap_header_get_code_fake_created(const struct coap_packet * cpkt)15 uint8_t coap_header_get_code_fake_created(const struct coap_packet *cpkt)
16 {
17 	return COAP_RESPONSE_CODE_CREATED;
18 }
coap_header_get_code_fake_deleted(const struct coap_packet * cpkt)19 uint8_t coap_header_get_code_fake_deleted(const struct coap_packet *cpkt)
20 {
21 	return COAP_RESPONSE_CODE_DELETED;
22 }
coap_header_get_code_fake_changed(const struct coap_packet * cpkt)23 uint8_t coap_header_get_code_fake_changed(const struct coap_packet *cpkt)
24 {
25 	return COAP_RESPONSE_CODE_CHANGED;
26 }
coap_header_get_code_fake_bad_request(const struct coap_packet * cpkt)27 uint8_t coap_header_get_code_fake_bad_request(const struct coap_packet *cpkt)
28 {
29 	return COAP_RESPONSE_CODE_BAD_REQUEST;
30 }
31 
32 DEFINE_FAKE_VALUE_FUNC(int, coap_append_option_int, struct coap_packet *, uint16_t, unsigned int);
33 DEFINE_FAKE_VALUE_FUNC(int, coap_packet_append_option, struct coap_packet *, uint16_t,
34 		       const uint8_t *, uint16_t);
coap_packet_append_option_fake_err(struct coap_packet * cpkt,uint16_t code,const uint8_t * value,uint16_t len)35 int coap_packet_append_option_fake_err(struct coap_packet *cpkt, uint16_t code,
36 				       const uint8_t *value, uint16_t len)
37 {
38 	return -1;
39 }
40 
41 DEFINE_FAKE_VALUE_FUNC(int, coap_packet_append_payload_marker, struct coap_packet *);
42 DEFINE_FAKE_VALUE_FUNC(int, coap_find_options, const struct coap_packet *, uint16_t,
43 		       struct coap_option *, uint16_t);
coap_find_options_do_registration_reply_cb_ok(const struct coap_packet * cpkt,uint16_t code,struct coap_option * options,uint16_t veclen)44 int coap_find_options_do_registration_reply_cb_ok(const struct coap_packet *cpkt, uint16_t code,
45 						  struct coap_option *options, uint16_t veclen)
46 {
47 	char options0[] = "rd";
48 	char options1[] = "jATO2yn9u7";
49 
50 	options[1].len = sizeof(options0);
51 	memcpy(&options[1].value, &options0, sizeof(options0));
52 	options[1].len = sizeof(options1);
53 	memcpy(&options[1].value, &options1, sizeof(options1));
54 	return 3;
55 }
56 
57 DEFINE_FAKE_VALUE_FUNC(uint16_t, coap_next_id);
58 
59 /* zephyr/net/lwm2m.h */
60 DEFINE_FAKE_VALUE_FUNC(int, lwm2m_engine_start, struct lwm2m_ctx *);
61 DEFINE_FAKE_VALUE_FUNC(int, lwm2m_engine_stop, struct lwm2m_ctx *);
62 DEFINE_FAKE_VALUE_FUNC(int, lwm2m_open_socket, struct lwm2m_ctx *);
63 DEFINE_FAKE_VALUE_FUNC(int, lwm2m_get_u32, const struct lwm2m_obj_path *, uint32_t *);
64 DEFINE_FAKE_VALUE_FUNC(int, lwm2m_get_u16, const struct lwm2m_obj_path *, uint16_t *);
65 DEFINE_FAKE_VALUE_FUNC(int, lwm2m_get_bool, const struct lwm2m_obj_path *, bool *);
66 DEFINE_FAKE_VALUE_FUNC(int, lwm2m_set_u32, const struct lwm2m_obj_path *, uint32_t);
lwm2m_get_bool_fake_default(const struct lwm2m_obj_path * path,bool * value)67 int lwm2m_get_bool_fake_default(const struct lwm2m_obj_path *path, bool *value)
68 {
69 	*value = false;
70 	return 0;
71 }
lwm2m_get_bool_fake_true(const struct lwm2m_obj_path * path,bool * value)72 int lwm2m_get_bool_fake_true(const struct lwm2m_obj_path *path, bool *value)
73 {
74 	*value = true;
75 	return 0;
76 }
77 
78 uint32_t get_u32_val;
79 
lwm2m_get_u32_val(const struct lwm2m_obj_path * path,uint32_t * val)80 int lwm2m_get_u32_val(const struct lwm2m_obj_path *path, uint32_t *val)
81 {
82 	*val = get_u32_val;
83 	return 0;
84 }
85 
86 
87 /* subsys/net/lib/lwm2m/lwm2m_engine.h */
88 DEFINE_FAKE_VALUE_FUNC(int, lwm2m_socket_start, struct lwm2m_ctx *);
lwm2m_socket_start_fake_fail(struct lwm2m_ctx * client_ctx)89 int lwm2m_socket_start_fake_fail(struct lwm2m_ctx *client_ctx)
90 {
91 	return -1;
92 }
93 DEFINE_FAKE_VALUE_FUNC(int, lwm2m_socket_close, struct lwm2m_ctx *);
94 DEFINE_FAKE_VALUE_FUNC(int, lwm2m_close_socket, struct lwm2m_ctx *);
95 DEFINE_FAKE_VALUE_FUNC(int, lwm2m_socket_suspend, struct lwm2m_ctx *);
96 DEFINE_FAKE_VALUE_FUNC(int, lwm2m_security_inst_id_to_index, uint16_t);
97 DEFINE_FAKE_VALUE_FUNC(int, lwm2m_engine_connection_resume, struct lwm2m_ctx *);
98 DEFINE_FAKE_VALUE_FUNC(int, lwm2m_push_queued_buffers, struct lwm2m_ctx *);
99 DEFINE_FAKE_VOID_FUNC(lwm2m_engine_context_init, struct lwm2m_ctx *);
100 struct lwm2m_ctx *client_ctx_fake;
lwm2m_engine_context_init_fake1(struct lwm2m_ctx * client_ctx)101 void lwm2m_engine_context_init_fake1(struct lwm2m_ctx *client_ctx)
102 {
103 	client_ctx_fake = client_ctx;
104 }
test_throw_network_error_from_engine(int err)105 void test_throw_network_error_from_engine(int err)
106 {
107 	client_ctx_fake->fault_cb(err);
108 }
109 
110 DEFINE_FAKE_VOID_FUNC(lwm2m_engine_context_close, struct lwm2m_ctx *);
111 DEFINE_FAKE_VALUE_FUNC(char *, lwm2m_sprint_ip_addr, const struct sockaddr *);
lwm2m_sprint_ip_addr_fake_default(const struct sockaddr * addr)112 char *lwm2m_sprint_ip_addr_fake_default(const struct sockaddr *addr)
113 {
114 	return "192.168.1.1:4444";
115 }
116 
117 DEFINE_FAKE_VALUE_FUNC(int, lwm2m_server_short_id_to_inst, uint16_t);
118 DEFINE_FAKE_VALUE_FUNC(int, lwm2m_security_index_to_inst_id, int);
119 DEFINE_FAKE_VALUE_FUNC(int, lwm2m_security_short_id_to_inst, uint16_t);
120 DEFINE_FAKE_VALUE_FUNC(int, lwm2m_server_disable, uint16_t, k_timeout_t);
121 DEFINE_FAKE_VALUE_FUNC(uint8_t, lwm2m_server_get_prio, uint16_t);
122 DEFINE_FAKE_VOID_FUNC(lwm2m_server_reset_timestamps);
123 
124 static bool srv_disabled;
lwm2m_server_select(uint16_t * obj_inst_id)125 bool lwm2m_server_select(uint16_t *obj_inst_id)
126 {
127 	if (obj_inst_id) {
128 		*obj_inst_id = 0;
129 	}
130 	return !srv_disabled;
131 }
132 
stub_lwm2m_server_disable(bool disable)133 void stub_lwm2m_server_disable(bool disable)
134 {
135 	srv_disabled = disable;
136 }
137 
138 k_work_handler_t service;
139 int64_t next;
140 
lwm2m_engine_call_at(k_work_handler_t work,int64_t timestamp)141 int lwm2m_engine_call_at(k_work_handler_t work, int64_t timestamp)
142 {
143 	service = work;
144 	next = timestamp ? timestamp : 1;
145 	return 0;
146 }
147 
148 uint16_t counter = RD_CLIENT_MAX_SERVICE_ITERATIONS;
149 struct lwm2m_message *pending_message;
150 void *(*pending_message_cb)();
151 static bool running;
152 K_SEM_DEFINE(srv_sem, 0, 1);
153 
service_work_fn(struct k_work * work)154 static void service_work_fn(struct k_work *work)
155 {
156 	while (running) {
157 		k_sleep(K_MSEC(10));
158 		if (pending_message != NULL && pending_message_cb != NULL) {
159 			pending_message_cb(pending_message);
160 			pending_message = NULL;
161 		}
162 
163 		if (next && next < k_uptime_get()) {
164 			next = 0;
165 			service(NULL);
166 			k_sem_give(&srv_sem);
167 		}
168 
169 		counter--;
170 
171 		/* avoid endless loop if rd client is stuck somewhere */
172 		if (counter == 0) {
173 			printk("Counter!\n");
174 			break;
175 		}
176 	}
177 }
178 
wait_for_service(uint16_t cycles)179 void wait_for_service(uint16_t cycles)
180 {
181 	while (cycles--) {
182 		k_sem_take(&srv_sem, K_MSEC(100));
183 	}
184 }
185 
186 K_WORK_DEFINE(service_work, service_work_fn);
187 
test_lwm2m_engine_start_service(void)188 void test_lwm2m_engine_start_service(void)
189 {
190 	running = true;
191 	counter = RD_CLIENT_MAX_SERVICE_ITERATIONS;
192 	k_work_submit(&service_work);
193 	k_sem_reset(&srv_sem);
194 }
195 
test_lwm2m_engine_stop_service(void)196 void test_lwm2m_engine_stop_service(void)
197 {
198 	struct k_work_sync sync;
199 
200 	pending_message_cb = NULL;
201 	pending_message = NULL;
202 	running = false;
203 	k_work_cancel(&service_work);
204 	k_work_flush(&service_work, &sync);
205 }
206 
207 /* subsys/net/lib/lwm2m/lwm2m_message_handling.h */
208 DEFINE_FAKE_VALUE_FUNC(int, lwm2m_init_message, struct lwm2m_message *);
209 DEFINE_FAKE_VOID_FUNC(lwm2m_clear_block_contexts);
lwm2m_init_message_fake_default(struct lwm2m_message * msg)210 int lwm2m_init_message_fake_default(struct lwm2m_message *msg)
211 {
212 	pending_message = msg;
213 	return 0;
214 }
215 
test_prepare_pending_message_cb(void * cb)216 void test_prepare_pending_message_cb(void *cb)
217 {
218 	pending_message_cb = cb;
219 }
220 
221 DEFINE_FAKE_VOID_FUNC(lwm2m_reset_message, struct lwm2m_message *, bool);
222 DEFINE_FAKE_VALUE_FUNC(int, lwm2m_send_message_async, struct lwm2m_message *);
223 
224 /* subsys/net/lib/lwm2m/lwm2m_registry.h */
225 DEFINE_FAKE_VOID_FUNC(lwm2m_engine_get_binding, char *);
226 DEFINE_FAKE_VOID_FUNC(lwm2m_engine_get_queue_mode, char *);
227 
228 /* subsys/net/lib/lwm2m/lwm2m_rw_link_format.h */
229 FAKE_VALUE_FUNC(int, put_begin, struct lwm2m_output_context *, struct lwm2m_obj_path *);
230 FAKE_VALUE_FUNC(int, put_end, struct lwm2m_output_context *, struct lwm2m_obj_path *);
231 FAKE_VALUE_FUNC(int, put_begin_oi, struct lwm2m_output_context *, struct lwm2m_obj_path *);
232 FAKE_VALUE_FUNC(int, put_end_oi, struct lwm2m_output_context *, struct lwm2m_obj_path *);
233 FAKE_VALUE_FUNC(int, put_begin_r, struct lwm2m_output_context *, struct lwm2m_obj_path *);
234 FAKE_VALUE_FUNC(int, put_end_r, struct lwm2m_output_context *, struct lwm2m_obj_path *);
235 FAKE_VALUE_FUNC(int, put_begin_ri, struct lwm2m_output_context *, struct lwm2m_obj_path *);
236 FAKE_VALUE_FUNC(int, put_end_ri, struct lwm2m_output_context *, struct lwm2m_obj_path *);
237 FAKE_VALUE_FUNC(int, put_s8, struct lwm2m_output_context *, struct lwm2m_obj_path *, int8_t);
238 FAKE_VALUE_FUNC(int, put_s16, struct lwm2m_output_context *, struct lwm2m_obj_path *, int16_t);
239 FAKE_VALUE_FUNC(int, put_s32, struct lwm2m_output_context *, struct lwm2m_obj_path *, int32_t);
240 FAKE_VALUE_FUNC(int, put_s64, struct lwm2m_output_context *, struct lwm2m_obj_path *, int64_t);
241 FAKE_VALUE_FUNC(int, put_time, struct lwm2m_output_context *, struct lwm2m_obj_path *, time_t);
242 FAKE_VALUE_FUNC(int, put_string, struct lwm2m_output_context *, struct lwm2m_obj_path *, char *,
243 		size_t);
244 FAKE_VALUE_FUNC(int, put_float, struct lwm2m_output_context *, struct lwm2m_obj_path *, double *);
245 FAKE_VALUE_FUNC(int, put_bool, struct lwm2m_output_context *, struct lwm2m_obj_path *, bool);
246 FAKE_VALUE_FUNC(int, put_opaque, struct lwm2m_output_context *, struct lwm2m_obj_path *, char *,
247 		size_t);
248 FAKE_VALUE_FUNC(int, put_objlnk, struct lwm2m_output_context *, struct lwm2m_obj_path *,
249 		struct lwm2m_objlnk *);
250 FAKE_VALUE_FUNC(int, put_corelink, struct lwm2m_output_context *, const struct lwm2m_obj_path *);
251 
252 const struct lwm2m_writer link_format_writer = {
253 	.put_begin = put_begin,
254 	.put_end = put_end,
255 	.put_begin_oi = put_begin_oi,
256 	.put_end_oi = put_end_oi,
257 	.put_begin_r = put_begin_r,
258 	.put_end_r = put_end_r,
259 	.put_begin_ri = put_begin_oi,
260 	.put_end_ri = put_end_oi,
261 	.put_s8 = put_s8,
262 	.put_s16 = put_s16,
263 	.put_s32 = put_s32,
264 	.put_s64 = put_s64,
265 	.put_time = put_time,
266 	.put_string = put_string,
267 	.put_float = put_float,
268 	.put_bool = put_bool,
269 	.put_opaque = put_opaque,
270 	.put_objlnk = put_objlnk,
271 	.put_corelink = put_corelink,
272 };
273 
274 DEFINE_FAKE_VALUE_FUNC(int, do_register_op_link_format, struct lwm2m_message *);
275