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