1 /*
2  * Copyright (c) 2019 Alexander Wachter
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 #include <zephyr/canbus/isotp.h>
7 #include <zephyr/ztest.h>
8 #include <strings.h>
9 #include "random_data.h"
10 #include <zephyr/net_buf.h>
11 
12 #define NUMBER_OF_REPETITIONS 5
13 #define DATA_SIZE_SF          7
14 
15 /*
16  * @addtogroup t_can
17  * @{
18  * @defgroup t_can_isotp test_can_isotp
19  * @brief TestPurpose: struggle the implementation and see if it breaks apart.
20  * @details
21  * - Test Steps
22  *   -#
23  * - Expected Results
24  *   -#
25  * @}
26  */
27 
28 const struct device *const can_dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_canbus));
29 
30 const struct isotp_fc_opts fc_opts = {
31 	.bs = 8,
32 	.stmin = 0
33 };
34 const struct isotp_fc_opts fc_opts_single = {
35 	.bs = 0,
36 	.stmin = 1
37 };
38 
39 const struct isotp_msg_id rx_addr = {
40 	.std_id = 0x10,
41 };
42 const struct isotp_msg_id tx_addr = {
43 	.std_id = 0x11,
44 };
45 
46 struct isotp_recv_ctx recv_ctx;
47 struct isotp_send_ctx send_ctx;
48 uint8_t data_buf[128];
49 
send_complete_cb(int error_nr,void * arg)50 void send_complete_cb(int error_nr, void *arg)
51 {
52 	zassert_equal(error_nr, ISOTP_N_OK, "Sending failed (%d)", error_nr);
53 }
54 
send_sf(const struct device * can_dev)55 static void send_sf(const struct device *can_dev)
56 {
57 	int ret;
58 
59 	ret = isotp_send(&send_ctx, can_dev, random_data, DATA_SIZE_SF,
60 			 &rx_addr, &tx_addr, send_complete_cb, NULL);
61 	zassert_equal(ret, 0, "Send returned %d", ret);
62 }
63 
get_sf_net(struct isotp_recv_ctx * recv_ctx)64 static void get_sf_net(struct isotp_recv_ctx *recv_ctx)
65 {
66 	struct net_buf *buf;
67 	int remaining_len, ret;
68 
69 	remaining_len = isotp_recv_net(recv_ctx, &buf, K_MSEC(1000));
70 	zassert_true(remaining_len >= 0, "recv returned %d", remaining_len);
71 	zassert_equal(remaining_len, 0, "SF should fit in one frame");
72 	zassert_equal(buf->len, DATA_SIZE_SF, "Data length (%d) should be %d.",
73 		      buf->len, DATA_SIZE_SF);
74 
75 	ret = memcmp(random_data, buf->data, buf->len);
76 	zassert_equal(ret, 0, "received data differ");
77 	memset(buf->data, 0, buf->len);
78 	net_buf_unref(buf);
79 }
80 
get_sf(struct isotp_recv_ctx * recv_ctx)81 static void get_sf(struct isotp_recv_ctx *recv_ctx)
82 {
83 	int ret;
84 	uint8_t *data_buf_ptr = data_buf;
85 
86 	memset(data_buf, 0, sizeof(data_buf));
87 	ret = isotp_recv(recv_ctx, data_buf_ptr++, 1, K_MSEC(1000));
88 	zassert_equal(ret, 1, "recv returned %d", ret);
89 	ret = isotp_recv(recv_ctx, data_buf_ptr++, sizeof(data_buf) - 1,
90 			  K_MSEC(1000));
91 	zassert_equal(ret, DATA_SIZE_SF - 1, "recv returned %d", ret);
92 
93 	ret = memcmp(random_data, data_buf, DATA_SIZE_SF);
94 	zassert_equal(ret, 0, "received data differ");
95 }
96 
print_hex(const uint8_t * ptr,size_t len)97 void print_hex(const uint8_t *ptr, size_t len)
98 {
99 	while (len--) {
100 		printk("%02x", *ptr++);
101 	}
102 }
103 
send_test_data(const struct device * can_dev,const uint8_t * data,size_t len)104 static void send_test_data(const struct device *can_dev, const uint8_t *data,
105 			   size_t len)
106 {
107 	int ret;
108 
109 	ret = isotp_send(&send_ctx, can_dev, data, len, &rx_addr, &tx_addr,
110 			  send_complete_cb, NULL);
111 	zassert_equal(ret, 0, "Send returned %d", ret);
112 }
113 
check_frag(struct net_buf * frag,const uint8_t * data)114 static const uint8_t *check_frag(struct net_buf *frag, const uint8_t *data)
115 {
116 	int ret;
117 
118 	ret = memcmp(data, frag->data, frag->len);
119 	if (ret) {
120 		printk("expected bytes:\n");
121 		print_hex(data, frag->len);
122 		printk("\nreceived (%d bytes):\n", frag->len);
123 		print_hex(frag->data, frag->len);
124 		printk("\n");
125 	}
126 	zassert_equal(ret, 0, "Received data differ");
127 	return data + frag->len;
128 }
129 
receive_test_data_net(struct isotp_recv_ctx * recv_ctx,const uint8_t * data,size_t len,int32_t delay)130 static void receive_test_data_net(struct isotp_recv_ctx *recv_ctx,
131 				 const uint8_t *data, size_t len, int32_t delay)
132 {
133 	int remaining_len;
134 	size_t received_len = 0;
135 	const uint8_t *data_ptr = data;
136 	struct net_buf *buf;
137 
138 	do {
139 		remaining_len = isotp_recv_net(recv_ctx, &buf, K_MSEC(1000));
140 		zassert_true(remaining_len >= 0, "recv error: %d",
141 			     remaining_len);
142 		received_len += buf->len;
143 		zassert_equal(received_len + remaining_len, len,
144 			      "Length mismatch");
145 
146 		data_ptr = check_frag(buf, data_ptr);
147 
148 		if (delay) {
149 			k_msleep(delay);
150 		}
151 		memset(buf->data, 0, buf->len);
152 		net_buf_unref(buf);
153 	} while (remaining_len);
154 
155 	remaining_len = isotp_recv_net(recv_ctx, &buf, K_MSEC(50));
156 	zassert_equal(remaining_len, ISOTP_RECV_TIMEOUT,
157 		      "Expected timeout but got %d", remaining_len);
158 }
159 
check_data(const uint8_t * recv_data,const uint8_t * send_data,size_t len)160 static void check_data(const uint8_t *recv_data, const uint8_t *send_data, size_t len)
161 {
162 	int ret;
163 
164 	ret = memcmp(send_data, recv_data, len);
165 	if (ret) {
166 		printk("expected bytes:\n");
167 		print_hex(send_data, len);
168 		printk("\nreceived (%zu bytes):\n", len);
169 		print_hex(recv_data, len);
170 		printk("\n");
171 	}
172 	zassert_equal(ret, 0, "Received data differ");
173 }
174 
receive_test_data(struct isotp_recv_ctx * recv_ctx,const uint8_t * data,size_t len,int32_t delay)175 static void receive_test_data(struct isotp_recv_ctx *recv_ctx,
176 			      const uint8_t *data, size_t len, int32_t delay)
177 {
178 	size_t remaining_len = len;
179 	int ret;
180 	const uint8_t *data_ptr = data;
181 
182 	do {
183 		memset(data_buf, 0, sizeof(data_buf));
184 		ret = isotp_recv(recv_ctx, data_buf, sizeof(data_buf),
185 				 K_MSEC(1000));
186 		zassert_true(ret >= 0, "recv error: %d", ret);
187 
188 		zassert_true(remaining_len >= ret, "More data then expected");
189 		check_data(data_buf, data_ptr, ret);
190 		data_ptr += ret;
191 		remaining_len -= ret;
192 
193 		if (delay) {
194 			k_msleep(delay);
195 		}
196 	} while (remaining_len);
197 
198 	ret = isotp_recv(recv_ctx, data_buf, sizeof(data_buf), K_MSEC(50));
199 	zassert_equal(ret, ISOTP_RECV_TIMEOUT,
200 		      "Expected timeout but got %d", ret);
201 }
202 
ZTEST(isotp_implementation,test_send_receive_net_sf)203 ZTEST(isotp_implementation, test_send_receive_net_sf)
204 {
205 	int ret, i;
206 
207 	ret = isotp_bind(&recv_ctx, can_dev, &rx_addr, &tx_addr, &fc_opts,
208 			 K_NO_WAIT);
209 	zassert_equal(ret, 0, "Bind returned %d", ret);
210 
211 	for (i = 0; i < NUMBER_OF_REPETITIONS; i++) {
212 		send_sf(can_dev);
213 		get_sf_net(&recv_ctx);
214 	}
215 
216 	isotp_unbind(&recv_ctx);
217 }
218 
ZTEST(isotp_implementation,test_send_receive_sf)219 ZTEST(isotp_implementation, test_send_receive_sf)
220 {
221 	int ret, i;
222 
223 	ret = isotp_bind(&recv_ctx, can_dev, &rx_addr, &tx_addr, &fc_opts,
224 			 K_NO_WAIT);
225 	zassert_equal(ret, 0, "Bind returned %d", ret);
226 
227 	for (i = 0; i < NUMBER_OF_REPETITIONS; i++) {
228 		send_sf(can_dev);
229 		get_sf(&recv_ctx);
230 	}
231 
232 	isotp_unbind(&recv_ctx);
233 }
234 
ZTEST(isotp_implementation,test_send_receive_net_blocks)235 ZTEST(isotp_implementation, test_send_receive_net_blocks)
236 {
237 	int ret, i;
238 
239 	ret = isotp_bind(&recv_ctx, can_dev, &rx_addr, &tx_addr, &fc_opts,
240 			 K_NO_WAIT);
241 	zassert_equal(ret, 0, "Binding failed (%d)", ret);
242 
243 	for (i = 0; i < NUMBER_OF_REPETITIONS; i++) {
244 		send_test_data(can_dev, random_data, sizeof(random_data));
245 		receive_test_data_net(&recv_ctx, random_data, sizeof(random_data), 0);
246 	}
247 
248 	isotp_unbind(&recv_ctx);
249 }
250 
ZTEST(isotp_implementation,test_send_receive_blocks)251 ZTEST(isotp_implementation, test_send_receive_blocks)
252 {
253 	const size_t data_size = sizeof(data_buf) * 2 + 10;
254 	int ret, i;
255 
256 	ret = isotp_bind(&recv_ctx, can_dev, &rx_addr, &tx_addr, &fc_opts,
257 			 K_NO_WAIT);
258 	zassert_equal(ret, 0, "Binding failed (%d)", ret);
259 
260 	for (i = 0; i < NUMBER_OF_REPETITIONS; i++) {
261 		send_test_data(can_dev, random_data, data_size);
262 		receive_test_data(&recv_ctx, random_data, data_size, 0);
263 	}
264 
265 	isotp_unbind(&recv_ctx);
266 }
267 
ZTEST(isotp_implementation,test_send_receive_net_single_blocks)268 ZTEST(isotp_implementation, test_send_receive_net_single_blocks)
269 {
270 	const size_t send_len = CONFIG_ISOTP_RX_BUF_COUNT *
271 				CONFIG_ISOTP_RX_BUF_SIZE + 6;
272 	int ret, i;
273 	size_t buf_len;
274 	struct net_buf *buf, *frag;
275 	const uint8_t *data_ptr;
276 
277 	ret = isotp_bind(&recv_ctx, can_dev, &rx_addr, &tx_addr,
278 			 &fc_opts_single, K_NO_WAIT);
279 	zassert_equal(ret, 0, "Binding failed (%d)", ret);
280 
281 	for (i = 0; i < NUMBER_OF_REPETITIONS; i++) {
282 		send_test_data(can_dev, random_data, send_len);
283 		data_ptr = random_data;
284 
285 		ret = isotp_recv_net(&recv_ctx, &buf, K_MSEC(1000));
286 		zassert_equal(ret, 0, "recv returned %d", ret);
287 		buf_len = net_buf_frags_len(buf);
288 		zassert_equal(buf_len, send_len, "Data length differ");
289 		frag = buf;
290 
291 		do {
292 			data_ptr = check_frag(frag, data_ptr);
293 			memset(frag->data, 0, frag->len);
294 		} while ((frag = frag->frags));
295 
296 		net_buf_unref(buf);
297 	}
298 
299 	isotp_unbind(&recv_ctx);
300 }
301 
ZTEST(isotp_implementation,test_send_receive_single_block)302 ZTEST(isotp_implementation, test_send_receive_single_block)
303 {
304 	const size_t send_len = CONFIG_ISOTP_RX_BUF_COUNT *
305 				CONFIG_ISOTP_RX_BUF_SIZE + 6;
306 	int ret, i;
307 
308 	ret = isotp_bind(&recv_ctx, can_dev, &rx_addr, &tx_addr,
309 			 &fc_opts_single, K_NO_WAIT);
310 	zassert_equal(ret, 0, "Binding failed (%d)", ret);
311 
312 	for (i = 0; i < NUMBER_OF_REPETITIONS; i++) {
313 		send_test_data(can_dev, random_data, send_len);
314 
315 		memset(data_buf, 0, sizeof(data_buf));
316 		ret = isotp_recv(&recv_ctx, data_buf, sizeof(data_buf),
317 				 K_MSEC(1000));
318 		zassert_equal(ret, send_len,
319 			      "data should be received at once (ret: %d)", ret);
320 		ret = memcmp(random_data, data_buf, send_len);
321 		zassert_equal(ret, 0, "Data differ");
322 	}
323 
324 	isotp_unbind(&recv_ctx);
325 }
326 
ZTEST(isotp_implementation,test_bind_unbind)327 ZTEST(isotp_implementation, test_bind_unbind)
328 {
329 	int ret, i;
330 
331 	for (i = 0; i < 100; i++) {
332 		ret = isotp_bind(&recv_ctx, can_dev, &rx_addr, &tx_addr,
333 				 &fc_opts, K_NO_WAIT);
334 		zassert_equal(ret, 0, "Binding failed (%d)", ret);
335 		isotp_unbind(&recv_ctx);
336 	}
337 
338 	for (i = 0; i < NUMBER_OF_REPETITIONS; i++) {
339 		ret = isotp_bind(&recv_ctx, can_dev, &rx_addr, &tx_addr,
340 				 &fc_opts, K_NO_WAIT);
341 		zassert_equal(ret, 0, "Binding failed (%d)", ret);
342 		send_sf(can_dev);
343 		k_sleep(K_MSEC(100));
344 		get_sf_net(&recv_ctx);
345 		isotp_unbind(&recv_ctx);
346 	}
347 
348 	for (i = 0; i < NUMBER_OF_REPETITIONS; i++) {
349 		ret = isotp_bind(&recv_ctx, can_dev, &rx_addr, &tx_addr,
350 				 &fc_opts, K_NO_WAIT);
351 		zassert_equal(ret, 0, "Binding failed (%d)", ret);
352 		send_sf(can_dev);
353 		k_sleep(K_MSEC(100));
354 		get_sf(&recv_ctx);
355 		isotp_unbind(&recv_ctx);
356 	}
357 
358 	for (i = 0; i < NUMBER_OF_REPETITIONS; i++) {
359 		ret = isotp_bind(&recv_ctx, can_dev, &rx_addr, &tx_addr,
360 				 &fc_opts, K_NO_WAIT);
361 		zassert_equal(ret, 0, "Binding failed (%d)", ret);
362 		send_test_data(can_dev, random_data, 60);
363 		k_sleep(K_MSEC(100));
364 		receive_test_data_net(&recv_ctx, random_data, 60, 0);
365 		isotp_unbind(&recv_ctx);
366 	}
367 
368 	for (i = 0; i < NUMBER_OF_REPETITIONS; i++) {
369 		ret = isotp_bind(&recv_ctx, can_dev, &rx_addr, &tx_addr,
370 				 &fc_opts, K_NO_WAIT);
371 		zassert_equal(ret, 0, "Binding failed (%d)", ret);
372 		send_test_data(can_dev, random_data, 60);
373 		k_sleep(K_MSEC(100));
374 		receive_test_data(&recv_ctx, random_data, 60, 0);
375 		isotp_unbind(&recv_ctx);
376 	}
377 }
378 
ZTEST(isotp_implementation,test_buffer_allocation)379 ZTEST(isotp_implementation, test_buffer_allocation)
380 {
381 	int ret;
382 	size_t send_data_length = CONFIG_ISOTP_RX_BUF_COUNT *
383 				  CONFIG_ISOTP_RX_BUF_SIZE * 3 + 6;
384 
385 	ret = isotp_bind(&recv_ctx, can_dev, &rx_addr, &tx_addr, &fc_opts,
386 			 K_NO_WAIT);
387 	zassert_equal(ret, 0, "Binding failed (%d)", ret);
388 
389 	send_test_data(can_dev, random_data, send_data_length);
390 	k_msleep(100);
391 	receive_test_data_net(&recv_ctx, random_data, send_data_length, 200);
392 	isotp_unbind(&recv_ctx);
393 }
394 
ZTEST(isotp_implementation,test_buffer_allocation_wait)395 ZTEST(isotp_implementation, test_buffer_allocation_wait)
396 {
397 	int ret;
398 	size_t send_data_length = CONFIG_ISOTP_RX_BUF_COUNT *
399 				  CONFIG_ISOTP_RX_BUF_SIZE * 2 + 6;
400 
401 	ret = isotp_bind(&recv_ctx, can_dev, &rx_addr, &tx_addr, &fc_opts,
402 			 K_NO_WAIT);
403 	zassert_equal(ret, 0, "Binding failed (%d)", ret);
404 
405 	send_test_data(can_dev, random_data, send_data_length);
406 	k_sleep(K_MSEC(100));
407 	receive_test_data_net(&recv_ctx, random_data, send_data_length, 2000);
408 	isotp_unbind(&recv_ctx);
409 }
410 
isotp_implementation_setup(void)411 void *isotp_implementation_setup(void)
412 {
413 	int ret;
414 
415 	zassert_true(sizeof(random_data) >= sizeof(data_buf) * 2 + 10,
416 		     "Test data size to small");
417 
418 	zassert_true(device_is_ready(can_dev), "CAN device not ready");
419 
420 	ret = can_set_mode(can_dev, CAN_MODE_LOOPBACK);
421 	zassert_equal(ret, 0, "Configuring loopback mode failed (%d)", ret);
422 
423 	ret = can_start(can_dev);
424 	zassert_equal(ret, 0, "Failed to start CAN controller [%d]", ret);
425 
426 	return NULL;
427 }
428 
429 ZTEST_SUITE(isotp_implementation, NULL, isotp_implementation_setup, NULL, NULL, NULL);
430