7 extern bool can_frame_was_sent;
9 extern bool last_response_was_received;
10 extern DiagnosticResponse last_response_received;
11 extern DiagnosticShims SHIMS;
12 extern uint16_t last_can_frame_sent_arb_id;
13 extern uint8_t last_can_payload_sent[8];
14 extern uint8_t last_can_payload_size;
16 void response_received_handler(const DiagnosticResponse* response) {
17 last_response_was_received = true;
18 last_response_received = *response;
21 START_TEST (test_receive_wrong_arb_id)
23 DiagnosticRequest request = {
24 arbitration_id: 0x100,
25 mode: OBD2_MODE_POWERTRAIN_DIAGNOSTIC_REQUEST
27 DiagnosticRequestHandle handle = diagnostic_request(&SHIMS, &request,
28 response_received_handler);
30 fail_if(last_response_was_received);
31 const uint8_t can_data[] = {0x2, request.mode + 0x40, 0x23};
32 diagnostic_receive_can_frame(&SHIMS, &handle, request.arbitration_id,
33 can_data, sizeof(can_data));
34 fail_if(last_response_was_received);
38 START_TEST (test_send_diag_request_with_payload)
40 DiagnosticRequest request = {
41 arbitration_id: 0x100,
42 mode: OBD2_MODE_POWERTRAIN_DIAGNOSTIC_REQUEST,
43 payload: {0x12, 0x34},
45 no_frame_padding: true
47 DiagnosticRequestHandle handle = diagnostic_request(&SHIMS, &request,
48 response_received_handler);
50 fail_if(handle.completed);
51 // TODO it'd be better to check the ISO-TP message instead of the CAN frame,
52 // but we don't have a good way to do that
53 ck_assert_int_eq(last_can_frame_sent_arb_id, request.arbitration_id);
54 ck_assert_int_eq(last_can_payload_sent[1], request.mode);
55 ck_assert_int_eq(last_can_payload_size, 4);
56 ck_assert_int_eq(last_can_payload_sent[2], request.payload[0]);
57 ck_assert_int_eq(last_can_payload_sent[3], request.payload[1]);
61 START_TEST (test_send_functional_request)
63 DiagnosticRequest request = {
64 arbitration_id: OBD2_FUNCTIONAL_BROADCAST_ID,
65 mode: OBD2_MODE_EMISSIONS_DTC_REQUEST,
66 no_frame_padding: true
68 DiagnosticRequestHandle handle = diagnostic_request(&SHIMS, &request,
69 response_received_handler);
71 fail_if(handle.completed);
72 ck_assert_int_eq(last_can_frame_sent_arb_id, request.arbitration_id);
73 ck_assert_int_eq(last_can_payload_sent[1], request.mode);
74 ck_assert_int_eq(last_can_payload_size, 2);
76 fail_if(last_response_was_received);
77 const uint8_t can_data[] = {0x2, request.mode + 0x40, 0x23};
78 for(uint16_t filter = OBD2_FUNCTIONAL_RESPONSE_START; filter <
79 OBD2_FUNCTIONAL_RESPONSE_START + OBD2_FUNCTIONAL_RESPONSE_COUNT;
81 DiagnosticResponse response = diagnostic_receive_can_frame(&SHIMS,
82 &handle, filter, can_data, sizeof(can_data));
83 fail_unless(response.success);
84 fail_unless(response.completed);
85 fail_unless(handle.completed);
86 ck_assert(last_response_received.success);
87 ck_assert_int_eq(last_response_received.arbitration_id,
89 ck_assert_int_eq(last_response_received.mode, request.mode);
90 fail_if(last_response_received.has_pid);
91 ck_assert_int_eq(last_response_received.payload_length, 1);
92 ck_assert_int_eq(last_response_received.payload[0], can_data[2]);
97 START_TEST (test_sent_message_no_padding)
99 DiagnosticRequest request = {
100 arbitration_id: 0x100,
101 mode: OBD2_MODE_EMISSIONS_DTC_REQUEST,
102 no_frame_padding: true
104 DiagnosticRequestHandle handle = diagnostic_request(&SHIMS, &request,
105 response_received_handler);
107 fail_if(handle.completed);
108 ck_assert_int_eq(last_can_frame_sent_arb_id, request.arbitration_id);
109 ck_assert_int_eq(last_can_payload_size, 2);
113 START_TEST (test_sent_message_is_padded_by_default)
115 DiagnosticRequest request = {
116 arbitration_id: 0x100,
117 mode: OBD2_MODE_EMISSIONS_DTC_REQUEST
119 DiagnosticRequestHandle handle = diagnostic_request(&SHIMS, &request,
120 response_received_handler);
122 fail_if(handle.completed);
123 ck_assert_int_eq(last_can_frame_sent_arb_id, request.arbitration_id);
124 ck_assert_int_eq(last_can_payload_size, 8);
128 START_TEST (test_sent_message_is_padded)
130 DiagnosticRequest request = {
131 arbitration_id: 0x100,
132 mode: OBD2_MODE_EMISSIONS_DTC_REQUEST,
133 no_frame_padding: false
135 DiagnosticRequestHandle handle = diagnostic_request(&SHIMS, &request,
136 response_received_handler);
138 fail_if(handle.completed);
139 ck_assert_int_eq(last_can_frame_sent_arb_id, request.arbitration_id);
140 ck_assert_int_eq(last_can_payload_size, 8);
144 START_TEST (test_send_diag_request)
146 DiagnosticRequest request = {
147 arbitration_id: 0x100,
148 mode: OBD2_MODE_EMISSIONS_DTC_REQUEST,
149 no_frame_padding: true
151 DiagnosticRequestHandle handle = diagnostic_request(&SHIMS, &request,
152 response_received_handler);
154 fail_if(handle.completed);
155 fail_unless(can_frame_was_sent);
156 ck_assert_int_eq(last_can_frame_sent_arb_id, request.arbitration_id);
157 ck_assert_int_eq(last_can_payload_sent[1], request.mode);
158 ck_assert_int_eq(last_can_payload_size, 2);
160 fail_if(last_response_was_received);
161 const uint8_t can_data[] = {0x2, request.mode + 0x40, 0x23};
162 DiagnosticResponse response = diagnostic_receive_can_frame(&SHIMS, &handle,
163 request.arbitration_id + 0x8, can_data, sizeof(can_data));
164 fail_unless(response.success);
165 fail_unless(response.completed);
166 fail_unless(handle.completed);
167 ck_assert(last_response_received.success);
168 ck_assert_int_eq(last_response_received.arbitration_id,
169 request.arbitration_id + 0x8);
170 ck_assert_int_eq(last_response_received.mode, request.mode);
171 fail_if(last_response_received.has_pid);
172 ck_assert_int_eq(last_response_received.payload_length, 1);
173 ck_assert_int_eq(last_response_received.payload[0], can_data[2]);
177 START_TEST (test_generate_then_send_request)
179 DiagnosticRequest request = {
180 arbitration_id: 0x100,
181 mode: OBD2_MODE_EMISSIONS_DTC_REQUEST,
182 no_frame_padding: true
184 DiagnosticRequestHandle handle = generate_diagnostic_request(&SHIMS,
185 &request, response_received_handler);
187 fail_if(handle.completed);
188 fail_if(can_frame_was_sent);
190 start_diagnostic_request(&SHIMS, &handle);
191 fail_unless(can_frame_was_sent);
192 ck_assert_int_eq(last_can_frame_sent_arb_id, request.arbitration_id);
193 ck_assert_int_eq(last_can_payload_sent[1], request.mode);
194 ck_assert_int_eq(last_can_payload_size, 2);
196 fail_if(last_response_was_received);
197 const uint8_t can_data[] = {0x2, request.mode + 0x40, 0x23};
198 DiagnosticResponse response = diagnostic_receive_can_frame(&SHIMS, &handle,
199 request.arbitration_id + 0x8, can_data, sizeof(can_data));
200 fail_unless(response.success);
201 fail_unless(response.completed);
202 fail_unless(handle.completed);
203 ck_assert(last_response_received.success);
204 ck_assert_int_eq(last_response_received.arbitration_id,
205 request.arbitration_id + 0x8);
206 ck_assert_int_eq(last_response_received.mode, request.mode);
207 fail_if(last_response_received.has_pid);
208 ck_assert_int_eq(last_response_received.payload_length, 1);
209 ck_assert_int_eq(last_response_received.payload[0], can_data[2]);
213 START_TEST (test_generate_diag_request)
215 DiagnosticRequest request = {
216 arbitration_id: 0x100,
217 mode: OBD2_MODE_EMISSIONS_DTC_REQUEST,
218 no_frame_padding: true
220 DiagnosticRequestHandle handle = generate_diagnostic_request(&SHIMS,
221 &request, response_received_handler);
223 fail_if(handle.completed);
224 fail_if(can_frame_was_sent);
228 START_TEST (test_autoset_pid_length)
230 uint16_t arb_id = OBD2_MODE_POWERTRAIN_DIAGNOSTIC_REQUEST;
231 diagnostic_request_pid(&SHIMS, DIAGNOSTIC_STANDARD_PID, arb_id, 0x2,
232 response_received_handler);
234 ck_assert_int_eq(last_can_frame_sent_arb_id, arb_id);
235 ck_assert_int_eq(last_can_payload_sent[1], 0x1);
236 ck_assert_int_eq(last_can_payload_sent[2], 0x2);
237 // padding is on for the diagnostic_request_pid helper function - if you
238 // need to turn it off, use the more manual diagnostic_request(...)
239 ck_assert_int_eq(last_can_payload_size, 8);
241 DiagnosticRequest request = {
242 arbitration_id: 0x100,
246 no_frame_padding: true
248 diagnostic_request(&SHIMS, &request, response_received_handler);
250 ck_assert_int_eq(last_can_frame_sent_arb_id, request.arbitration_id);
251 ck_assert_int_eq(last_can_payload_sent[1], request.mode);
252 ck_assert_int_eq(last_can_payload_sent[2], (request.pid & 0xFF00) >> 8);
253 ck_assert_int_eq(last_can_payload_sent[3], request.pid & 0xFF);
254 ck_assert_int_eq(last_can_payload_size, 4);
256 request.arbitration_id = 0x101;
259 diagnostic_request(&SHIMS, &request, response_received_handler);
261 ck_assert_int_eq(last_can_frame_sent_arb_id, request.arbitration_id);
262 ck_assert_int_eq(last_can_payload_sent[1], request.mode);
263 ck_assert_int_eq(last_can_payload_sent[2], request.pid);
264 ck_assert_int_eq(last_can_payload_size, 3);
268 START_TEST (test_request_pid_standard)
270 uint16_t arb_id = OBD2_MODE_POWERTRAIN_DIAGNOSTIC_REQUEST;
271 DiagnosticRequestHandle handle = diagnostic_request_pid(&SHIMS,
272 DIAGNOSTIC_STANDARD_PID, arb_id, 0x2, response_received_handler);
274 fail_if(last_response_was_received);
275 const uint8_t can_data[] = {0x3, 0x1 + 0x40, 0x2, 0x45};
276 diagnostic_receive_can_frame(&SHIMS, &handle, arb_id + 0x8,
277 can_data, sizeof(can_data));
278 fail_unless(last_response_was_received);
279 ck_assert(last_response_received.success);
280 ck_assert_int_eq(last_response_received.arbitration_id,
282 ck_assert_int_eq(last_response_received.mode, 0x1);
283 fail_unless(last_response_received.has_pid);
284 ck_assert_int_eq(last_response_received.pid, 0x2);
285 ck_assert_int_eq(last_response_received.payload_length, 1);
286 ck_assert_int_eq(last_response_received.payload[0], can_data[3]);
290 START_TEST (test_request_pid_enhanced)
292 uint16_t arb_id = 0x100;
293 DiagnosticRequestHandle handle = diagnostic_request_pid(&SHIMS,
294 DIAGNOSTIC_ENHANCED_PID, arb_id, 0x1234, response_received_handler);
296 fail_if(last_response_was_received);
297 const uint8_t can_data[] = {0x4, 0x22 + 0x40, 0x12, 0x34, 0x45};
298 diagnostic_receive_can_frame(&SHIMS, &handle, arb_id + 0x8, can_data,
300 fail_unless(last_response_was_received);
301 ck_assert(last_response_received.success);
302 ck_assert_int_eq(last_response_received.arbitration_id,
304 ck_assert_int_eq(last_response_received.mode, 0x22);
305 fail_unless(last_response_received.has_pid);
306 ck_assert_int_eq(last_response_received.pid, 0x1234);
307 ck_assert_int_eq(last_response_received.payload_length, 1);
308 ck_assert_int_eq(last_response_received.payload[0], can_data[4]);
312 START_TEST (test_wrong_mode_response)
314 uint16_t arb_id = 0x100;
315 DiagnosticRequestHandle handle = diagnostic_request_pid(&SHIMS,
316 DIAGNOSTIC_ENHANCED_PID, arb_id, 0x1234, response_received_handler);
318 fail_if(last_response_was_received);
319 const uint8_t can_data[] = {0x4, 0x1 + 0x40, 0x12, 0x34, 0x45};
320 diagnostic_receive_can_frame(&SHIMS, &handle, arb_id + 0x8, can_data,
322 fail_if(last_response_was_received);
323 fail_if(handle.completed);
327 START_TEST (test_missing_pid)
329 uint16_t arb_id = 0x100;
330 DiagnosticRequestHandle handle = diagnostic_request_pid(&SHIMS,
331 DIAGNOSTIC_ENHANCED_PID, arb_id, 0x1234, response_received_handler);
333 fail_if(last_response_was_received);
334 const uint8_t can_data[] = {0x1, 0x22 + 0x40};
335 diagnostic_receive_can_frame(&SHIMS, &handle, arb_id + 0x8, can_data,
337 fail_if(last_response_was_received);
338 fail_if(handle.completed);
342 START_TEST (test_wrong_pid_response)
344 uint16_t arb_id = 0x100;
345 DiagnosticRequestHandle handle = diagnostic_request_pid(&SHIMS,
346 DIAGNOSTIC_ENHANCED_PID, arb_id, 0x1234, response_received_handler);
348 fail_if(last_response_was_received);
349 const uint8_t can_data[] = {0x4, 0x22 + 0x40, 0x12, 0x33, 0x45};
350 diagnostic_receive_can_frame(&SHIMS, &handle, arb_id + 0x8, can_data,
352 fail_if(last_response_was_received);
353 fail_if(handle.completed);
357 START_TEST (test_wrong_pid_then_right_completes)
359 uint16_t arb_id = 0x100;
360 DiagnosticRequestHandle handle = diagnostic_request_pid(&SHIMS,
361 DIAGNOSTIC_ENHANCED_PID, arb_id, 0x1234, response_received_handler);
363 fail_if(last_response_was_received);
364 uint8_t can_data[] = {0x4, 0x22 + 0x40, 0x12, 0x33, 0x45};
365 diagnostic_receive_can_frame(&SHIMS, &handle, arb_id + 0x8, can_data,
367 fail_if(last_response_was_received);
368 fail_if(handle.completed);
371 diagnostic_receive_can_frame(&SHIMS, &handle, arb_id + 0x8, can_data,
373 fail_unless(last_response_was_received);
374 fail_unless(handle.completed);
375 fail_unless(handle.success);
376 fail_unless(last_response_received.success);
377 ck_assert_int_eq(last_response_received.pid, 0x1234);
381 START_TEST (test_negative_response)
383 DiagnosticRequest request = {
384 arbitration_id: 0x100,
385 mode: OBD2_MODE_POWERTRAIN_DIAGNOSTIC_REQUEST
387 DiagnosticRequestHandle handle = diagnostic_request(&SHIMS, &request,
388 response_received_handler);
389 const uint8_t can_data[] = {0x3, 0x7f, request.mode,
390 NRC_SERVICE_NOT_SUPPORTED};
391 DiagnosticResponse response = diagnostic_receive_can_frame(&SHIMS, &handle,
392 request.arbitration_id + 0x8, can_data, sizeof(can_data));
393 fail_unless(response.completed);
394 fail_if(response.success);
395 fail_unless(handle.completed);
397 fail_if(last_response_received.success);
398 ck_assert_int_eq(last_response_received.arbitration_id,
399 request.arbitration_id + 0x8);
400 ck_assert_int_eq(last_response_received.mode, request.mode);
401 ck_assert_int_eq(last_response_received.pid, 0);
402 ck_assert_int_eq(last_response_received.negative_response_code,
403 NRC_SERVICE_NOT_SUPPORTED);
404 ck_assert_int_eq(last_response_received.payload_length, 0);
408 START_TEST (test_payload_to_integer)
410 uint16_t arb_id = OBD2_MODE_POWERTRAIN_DIAGNOSTIC_REQUEST;
411 DiagnosticRequestHandle handle = diagnostic_request_pid(&SHIMS,
412 DIAGNOSTIC_STANDARD_PID, arb_id, 0x2, response_received_handler);
414 fail_if(last_response_was_received);
415 const uint8_t can_data[] = {0x4, 0x1 + 0x40, 0x2, 0x45, 0x12};
416 DiagnosticResponse response = diagnostic_receive_can_frame(&SHIMS, &handle,
417 arb_id + 0x8, can_data, sizeof(can_data));
418 ck_assert_int_eq(diagnostic_payload_to_integer(&response), 0x4512);
422 START_TEST (test_response_multi_frame)
424 DiagnosticRequest request = {
425 arbitration_id: 0x100,
426 mode: OBD2_MODE_VEHICLE_INFORMATION,
430 DiagnosticRequestHandle handle = diagnostic_request(&SHIMS, &request,
431 response_received_handler);
433 const uint8_t can_data[] = {0x10, 0x14, 0x9 + 0x40, 0x2, 0x1, 0x31, 0x46, 0x4d};
434 DiagnosticResponse response = diagnostic_receive_can_frame(&SHIMS, &handle,
435 request.arbitration_id + 0x8, can_data, sizeof(can_data));
437 fail_unless(can_frame_was_sent);
438 fail_unless(!response.success);
439 fail_unless(!response.completed);
440 fail_unless(response.multi_frame);
441 ck_assert_int_eq(last_can_frame_sent_arb_id, request.arbitration_id);
442 ck_assert_int_eq(last_can_payload_sent[0], 0x30);
444 const uint8_t can_data_1[] = {0x21, 0x43, 0x55, 0x39, 0x4a, 0x39, 0x34, 0x48};
445 response = diagnostic_receive_can_frame(&SHIMS, &handle,
446 request.arbitration_id + 0x8, can_data_1, sizeof(can_data_1));
447 fail_unless(!response.success);
448 fail_unless(!response.completed);
449 fail_unless(response.multi_frame);
451 const uint8_t can_data_2[] = {0x22, 0x55, 0x41, 0x30, 0x34, 0x35, 0x32, 0x34};
452 response = diagnostic_receive_can_frame(&SHIMS, &handle,
453 request.arbitration_id + 0x8, can_data_2, sizeof(can_data_2));
454 fail_unless(response.success);
455 fail_unless(response.completed);
456 fail_unless(response.multi_frame);
457 ck_assert_int_eq(response.mode, OBD2_MODE_VEHICLE_INFORMATION);
458 ck_assert_int_eq(response.pid, 0x2);
459 ck_assert_int_eq(response.payload_length, 18);
460 ck_assert_int_eq(response.payload[0], 0x01);
461 ck_assert_int_eq(response.payload[1], 0x31);
462 ck_assert_int_eq(response.payload[2], 0x46);
463 ck_assert_int_eq(response.payload[3], 0x4d);
464 ck_assert_int_eq(response.payload[4], 0x43);
465 ck_assert_int_eq(response.payload[5], 0x55);
466 ck_assert_int_eq(response.payload[6], 0x39);
467 ck_assert_int_eq(response.payload[7], 0x4a);
468 ck_assert_int_eq(response.payload[8], 0x39);
469 ck_assert_int_eq(response.payload[9], 0x34);
470 ck_assert_int_eq(response.payload[10], 0x48);
471 ck_assert_int_eq(response.payload[11], 0x55);
472 ck_assert_int_eq(response.payload[12], 0x41);
473 ck_assert_int_eq(response.payload[13], 0x30);
474 ck_assert_int_eq(response.payload[14], 0x34);
475 ck_assert_int_eq(response.payload[15], 0x35);
476 ck_assert_int_eq(response.payload[16], 0x32);
477 ck_assert_int_eq(response.payload[17], 0x34);
481 Suite* testSuite(void) {
482 Suite* s = suite_create("uds");
483 TCase *tc_core = tcase_create("core");
484 tcase_add_checked_fixture(tc_core, setup, NULL);
485 tcase_add_test(tc_core, test_sent_message_no_padding);
486 tcase_add_test(tc_core, test_sent_message_is_padded);
487 tcase_add_test(tc_core, test_sent_message_is_padded_by_default);
488 tcase_add_test(tc_core, test_generate_diag_request);
489 tcase_add_test(tc_core, test_generate_then_send_request);
490 tcase_add_test(tc_core, test_send_diag_request);
491 tcase_add_test(tc_core, test_send_functional_request);
492 tcase_add_test(tc_core, test_send_diag_request_with_payload);
493 tcase_add_test(tc_core, test_receive_wrong_arb_id);
494 tcase_add_test(tc_core, test_autoset_pid_length);
495 tcase_add_test(tc_core, test_request_pid_standard);
496 tcase_add_test(tc_core, test_request_pid_enhanced);
497 tcase_add_test(tc_core, test_wrong_mode_response);
498 tcase_add_test(tc_core, test_wrong_pid_response);
499 tcase_add_test(tc_core, test_missing_pid);
500 tcase_add_test(tc_core, test_wrong_pid_then_right_completes);
501 tcase_add_test(tc_core, test_negative_response);
502 tcase_add_test(tc_core, test_payload_to_integer);
503 tcase_add_test(tc_core, test_response_multi_frame);
505 // TODO these are future work:
506 // TODO test request MIL
507 // TODO test request VIN
508 // TODO test request DTC
509 // TODO test clear DTC
510 // TODO test enumerate PIDs
511 suite_add_tcase(s, tc_core);
518 Suite* s = testSuite();
519 SRunner *sr = srunner_create(s);
520 // Don't fork so we can actually use gdb
521 srunner_set_fork_status(sr, CK_NOFORK);
522 srunner_run_all(sr, CK_NORMAL);
523 numberFailed = srunner_ntests_failed(sr);
525 return (numberFailed == 0) ? 0 : 1;