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_size, 4);
256 START_TEST (test_request_pid_standard)
258 uint16_t arb_id = OBD2_MODE_POWERTRAIN_DIAGNOSTIC_REQUEST;
259 DiagnosticRequestHandle handle = diagnostic_request_pid(&SHIMS,
260 DIAGNOSTIC_STANDARD_PID, arb_id, 0x2, response_received_handler);
262 fail_if(last_response_was_received);
263 const uint8_t can_data[] = {0x3, 0x1 + 0x40, 0x2, 0x45};
264 diagnostic_receive_can_frame(&SHIMS, &handle, arb_id + 0x8,
265 can_data, sizeof(can_data));
266 fail_unless(last_response_was_received);
267 ck_assert(last_response_received.success);
268 ck_assert_int_eq(last_response_received.arbitration_id,
270 ck_assert_int_eq(last_response_received.mode, 0x1);
271 fail_unless(last_response_received.has_pid);
272 ck_assert_int_eq(last_response_received.pid, 0x2);
273 ck_assert_int_eq(last_response_received.payload_length, 1);
274 ck_assert_int_eq(last_response_received.payload[0], can_data[3]);
278 START_TEST (test_request_pid_enhanced)
280 uint16_t arb_id = 0x100;
281 DiagnosticRequestHandle handle = diagnostic_request_pid(&SHIMS,
282 DIAGNOSTIC_ENHANCED_PID, arb_id, 0x2, response_received_handler);
284 fail_if(last_response_was_received);
285 const uint8_t can_data[] = {0x4, 0x22 + 0x40, 0x0, 0x2, 0x45};
286 diagnostic_receive_can_frame(&SHIMS, &handle, arb_id + 0x8, can_data,
288 fail_unless(last_response_was_received);
289 ck_assert(last_response_received.success);
290 ck_assert_int_eq(last_response_received.arbitration_id,
292 ck_assert_int_eq(last_response_received.mode, 0x22);
293 fail_unless(last_response_received.has_pid);
294 ck_assert_int_eq(last_response_received.pid, 0x2);
295 ck_assert_int_eq(last_response_received.payload_length, 1);
296 ck_assert_int_eq(last_response_received.payload[0], can_data[4]);
300 START_TEST (test_wrong_mode_response)
302 uint16_t arb_id = 0x100;
303 DiagnosticRequestHandle handle = diagnostic_request_pid(&SHIMS,
304 DIAGNOSTIC_ENHANCED_PID, arb_id, 0x2, response_received_handler);
306 fail_if(last_response_was_received);
307 const uint8_t can_data[] = {0x4, 0x1 + 0x40, 0x0, 0x2, 0x45};
308 diagnostic_receive_can_frame(&SHIMS, &handle, arb_id + 0x8, can_data,
310 fail_if(last_response_was_received);
311 fail_if(handle.completed);
315 START_TEST (test_missing_pid)
317 uint16_t arb_id = 0x100;
318 DiagnosticRequestHandle handle = diagnostic_request_pid(&SHIMS,
319 DIAGNOSTIC_ENHANCED_PID, arb_id, 0x2, response_received_handler);
321 fail_if(last_response_was_received);
322 const uint8_t can_data[] = {0x1, 0x22 + 0x40};
323 diagnostic_receive_can_frame(&SHIMS, &handle, arb_id + 0x8, can_data,
325 fail_if(last_response_was_received);
326 fail_if(handle.completed);
330 START_TEST (test_wrong_pid_response)
332 uint16_t arb_id = 0x100;
333 DiagnosticRequestHandle handle = diagnostic_request_pid(&SHIMS,
334 DIAGNOSTIC_ENHANCED_PID, arb_id, 0x2, response_received_handler);
336 fail_if(last_response_was_received);
337 const uint8_t can_data[] = {0x4, 0x22 + 0x40, 0x0, 0x3, 0x45};
338 diagnostic_receive_can_frame(&SHIMS, &handle, arb_id + 0x8, can_data,
340 fail_if(last_response_was_received);
341 fail_if(handle.completed);
345 START_TEST (test_wrong_pid_then_right_completes)
347 uint16_t arb_id = 0x100;
348 DiagnosticRequestHandle handle = diagnostic_request_pid(&SHIMS,
349 DIAGNOSTIC_ENHANCED_PID, arb_id, 0x2, response_received_handler);
351 fail_if(last_response_was_received);
352 uint8_t can_data[] = {0x4, 0x22 + 0x40, 0x0, 0x3, 0x45};
353 diagnostic_receive_can_frame(&SHIMS, &handle, arb_id + 0x8, can_data,
355 fail_if(last_response_was_received);
356 fail_if(handle.completed);
359 diagnostic_receive_can_frame(&SHIMS, &handle, arb_id + 0x8, can_data,
361 fail_unless(last_response_was_received);
362 fail_unless(handle.completed);
363 fail_unless(handle.success);
364 fail_unless(last_response_received.success);
365 ck_assert_int_eq(last_response_received.pid, 0x2);
369 START_TEST (test_negative_response)
371 DiagnosticRequest request = {
372 arbitration_id: 0x100,
373 mode: OBD2_MODE_POWERTRAIN_DIAGNOSTIC_REQUEST
375 DiagnosticRequestHandle handle = diagnostic_request(&SHIMS, &request,
376 response_received_handler);
377 const uint8_t can_data[] = {0x3, 0x7f, request.mode,
378 NRC_SERVICE_NOT_SUPPORTED};
379 DiagnosticResponse response = diagnostic_receive_can_frame(&SHIMS, &handle,
380 request.arbitration_id + 0x8, can_data, sizeof(can_data));
381 fail_unless(response.completed);
382 fail_if(response.success);
383 fail_unless(handle.completed);
385 fail_if(last_response_received.success);
386 ck_assert_int_eq(last_response_received.arbitration_id,
387 request.arbitration_id + 0x8);
388 ck_assert_int_eq(last_response_received.mode, request.mode);
389 ck_assert_int_eq(last_response_received.pid, 0);
390 ck_assert_int_eq(last_response_received.negative_response_code,
391 NRC_SERVICE_NOT_SUPPORTED);
392 ck_assert_int_eq(last_response_received.payload_length, 0);
396 START_TEST (test_payload_to_integer)
398 uint16_t arb_id = OBD2_MODE_POWERTRAIN_DIAGNOSTIC_REQUEST;
399 DiagnosticRequestHandle handle = diagnostic_request_pid(&SHIMS,
400 DIAGNOSTIC_STANDARD_PID, arb_id, 0x2, response_received_handler);
402 fail_if(last_response_was_received);
403 const uint8_t can_data[] = {0x4, 0x1 + 0x40, 0x2, 0x45, 0x12};
404 DiagnosticResponse response = diagnostic_receive_can_frame(&SHIMS, &handle,
405 arb_id + 0x8, can_data, sizeof(can_data));
406 ck_assert_int_eq(diagnostic_payload_to_integer(&response), 0x4512);
410 Suite* testSuite(void) {
411 Suite* s = suite_create("uds");
412 TCase *tc_core = tcase_create("core");
413 tcase_add_checked_fixture(tc_core, setup, NULL);
414 tcase_add_test(tc_core, test_sent_message_no_padding);
415 tcase_add_test(tc_core, test_sent_message_is_padded);
416 tcase_add_test(tc_core, test_sent_message_is_padded_by_default);
417 tcase_add_test(tc_core, test_generate_diag_request);
418 tcase_add_test(tc_core, test_generate_then_send_request);
419 tcase_add_test(tc_core, test_send_diag_request);
420 tcase_add_test(tc_core, test_send_functional_request);
421 tcase_add_test(tc_core, test_send_diag_request_with_payload);
422 tcase_add_test(tc_core, test_receive_wrong_arb_id);
423 tcase_add_test(tc_core, test_autoset_pid_length);
424 tcase_add_test(tc_core, test_request_pid_standard);
425 tcase_add_test(tc_core, test_request_pid_enhanced);
426 tcase_add_test(tc_core, test_wrong_mode_response);
427 tcase_add_test(tc_core, test_wrong_pid_response);
428 tcase_add_test(tc_core, test_missing_pid);
429 tcase_add_test(tc_core, test_wrong_pid_then_right_completes);
430 tcase_add_test(tc_core, test_negative_response);
431 tcase_add_test(tc_core, test_payload_to_integer);
433 // TODO these are future work:
434 // TODO test request MIL
435 // TODO test request VIN
436 // TODO test request DTC
437 // TODO test clear DTC
438 // TODO test enumerate PIDs
439 suite_add_tcase(s, tc_core);
446 Suite* s = testSuite();
447 SRunner *sr = srunner_create(s);
448 // Don't fork so we can actually use gdb
449 srunner_set_fork_status(sr, CK_NOFORK);
450 srunner_run_all(sr, CK_NORMAL);
451 numberFailed = srunner_ntests_failed(sr);
453 return (numberFailed == 0) ? 0 : 1;