8 extern bool last_response_was_received;
9 extern DiagnosticResponse last_response_received;
10 extern DiagnosticShims SHIMS;
11 extern uint16_t last_can_frame_sent_arb_id;
12 extern uint8_t last_can_payload_sent[8];
13 extern uint8_t last_can_payload_size;
15 void response_received_handler(const DiagnosticResponse* response) {
16 last_response_was_received = true;
17 last_response_received = *response;
20 START_TEST (test_receive_wrong_arb_id)
22 DiagnosticRequest request = {
23 arbitration_id: 0x100,
24 mode: OBD2_MODE_POWERTRAIN_DIAGNOSTIC_REQUEST
26 DiagnosticRequestHandle handle = diagnostic_request(&SHIMS, &request,
27 response_received_handler);
29 fail_if(last_response_was_received);
30 const uint8_t can_data[] = {0x2, request.mode + 0x40, 0x23};
31 diagnostic_receive_can_frame(&SHIMS, &handle, request.arbitration_id,
32 can_data, sizeof(can_data));
33 fail_if(last_response_was_received);
37 START_TEST (test_send_diag_request_with_payload)
39 DiagnosticRequest request = {
40 arbitration_id: 0x100,
41 mode: OBD2_MODE_POWERTRAIN_DIAGNOSTIC_REQUEST,
42 payload: {0x12, 0x34},
45 DiagnosticRequestHandle handle = diagnostic_request(&SHIMS, &request,
46 response_received_handler);
48 fail_if(handle.completed);
49 // TODO it'd be better to check the ISO-TP message instead of the CAN frame,
50 // but we don't have a good way to do that
51 ck_assert_int_eq(last_can_frame_sent_arb_id, request.arbitration_id);
52 ck_assert_int_eq(last_can_payload_sent[1], request.mode);
53 ck_assert_int_eq(last_can_payload_size, 4);
54 ck_assert_int_eq(last_can_payload_sent[2], request.payload[0]);
55 ck_assert_int_eq(last_can_payload_sent[3], request.payload[1]);
59 START_TEST (test_send_functional_request)
61 DiagnosticRequest request = {
62 arbitration_id: OBD2_FUNCTIONAL_BROADCAST_ID,
63 mode: OBD2_MODE_EMISSIONS_DTC_REQUEST
65 DiagnosticRequestHandle handle = diagnostic_request(&SHIMS, &request,
66 response_received_handler);
68 fail_if(handle.completed);
69 ck_assert_int_eq(last_can_frame_sent_arb_id, request.arbitration_id);
70 ck_assert_int_eq(last_can_payload_sent[1], request.mode);
71 ck_assert_int_eq(last_can_payload_size, 2);
73 fail_if(last_response_was_received);
74 const uint8_t can_data[] = {0x2, request.mode + 0x40, 0x23};
75 for(uint16_t filter = OBD2_FUNCTIONAL_RESPONSE_START; filter <
76 OBD2_FUNCTIONAL_RESPONSE_START + OBD2_FUNCTIONAL_RESPONSE_COUNT;
78 DiagnosticResponse response = diagnostic_receive_can_frame(&SHIMS, &handle,
79 filter, can_data, sizeof(can_data));
80 fail_unless(response.success);
81 fail_unless(response.completed);
82 fail_unless(handle.completed);
83 ck_assert(last_response_received.success);
84 ck_assert_int_eq(last_response_received.arbitration_id,
86 ck_assert_int_eq(last_response_received.mode, request.mode);
87 fail_if(last_response_received.has_pid);
88 ck_assert_int_eq(last_response_received.payload_length, 1);
89 ck_assert_int_eq(last_response_received.payload[0], can_data[2]);
94 START_TEST (test_send_diag_request)
96 DiagnosticRequest request = {
97 arbitration_id: 0x100,
98 mode: OBD2_MODE_EMISSIONS_DTC_REQUEST
100 DiagnosticRequestHandle handle = diagnostic_request(&SHIMS, &request,
101 response_received_handler);
103 fail_if(handle.completed);
104 ck_assert_int_eq(last_can_frame_sent_arb_id, request.arbitration_id);
105 ck_assert_int_eq(last_can_payload_sent[1], request.mode);
106 ck_assert_int_eq(last_can_payload_size, 2);
108 fail_if(last_response_was_received);
109 const uint8_t can_data[] = {0x2, request.mode + 0x40, 0x23};
110 DiagnosticResponse response = diagnostic_receive_can_frame(&SHIMS, &handle,
111 request.arbitration_id + 0x8, can_data, sizeof(can_data));
112 fail_unless(response.success);
113 fail_unless(response.completed);
114 fail_unless(handle.completed);
115 ck_assert(last_response_received.success);
116 ck_assert_int_eq(last_response_received.arbitration_id,
117 request.arbitration_id + 0x8);
118 ck_assert_int_eq(last_response_received.mode, request.mode);
119 fail_if(last_response_received.has_pid);
120 ck_assert_int_eq(last_response_received.payload_length, 1);
121 ck_assert_int_eq(last_response_received.payload[0], can_data[2]);
125 START_TEST (test_request_pid_standard)
127 uint16_t arb_id = OBD2_MODE_POWERTRAIN_DIAGNOSTIC_REQUEST;
128 DiagnosticRequestHandle handle = diagnostic_request_pid(&SHIMS,
129 DIAGNOSTIC_STANDARD_PID, arb_id, 0x2, response_received_handler);
131 fail_if(last_response_was_received);
132 const uint8_t can_data[] = {0x3, 0x1 + 0x40, 0x2, 0x45};
133 diagnostic_receive_can_frame(&SHIMS, &handle, arb_id + 0x8,
134 can_data, sizeof(can_data));
135 fail_unless(last_response_was_received);
136 ck_assert(last_response_received.success);
137 ck_assert_int_eq(last_response_received.arbitration_id,
139 ck_assert_int_eq(last_response_received.mode, 0x1);
140 fail_unless(last_response_received.has_pid);
141 ck_assert_int_eq(last_response_received.pid, 0x2);
142 ck_assert_int_eq(last_response_received.payload_length, 1);
143 ck_assert_int_eq(last_response_received.payload[0], can_data[3]);
147 START_TEST (test_request_pid_enhanced)
149 uint16_t arb_id = 0x100;
150 DiagnosticRequestHandle handle = diagnostic_request_pid(&SHIMS,
151 DIAGNOSTIC_ENHANCED_PID, arb_id, 0x2, response_received_handler);
153 fail_if(last_response_was_received);
154 const uint8_t can_data[] = {0x4, 0x22 + 0x40, 0x0, 0x2, 0x45};
155 diagnostic_receive_can_frame(&SHIMS, &handle, arb_id + 0x8, can_data,
157 fail_unless(last_response_was_received);
158 ck_assert(last_response_received.success);
159 ck_assert_int_eq(last_response_received.arbitration_id,
161 ck_assert_int_eq(last_response_received.mode, 0x22);
162 fail_unless(last_response_received.has_pid);
163 ck_assert_int_eq(last_response_received.pid, 0x2);
164 ck_assert_int_eq(last_response_received.payload_length, 1);
165 ck_assert_int_eq(last_response_received.payload[0], can_data[4]);
169 START_TEST (test_wrong_mode_response)
171 uint16_t arb_id = 0x100;
172 DiagnosticRequestHandle handle = diagnostic_request_pid(&SHIMS,
173 DIAGNOSTIC_ENHANCED_PID, arb_id, 0x2, response_received_handler);
175 fail_if(last_response_was_received);
176 const uint8_t can_data[] = {0x4, 0x1 + 0x40, 0x0, 0x2, 0x45};
177 diagnostic_receive_can_frame(&SHIMS, &handle, arb_id + 0x8, can_data,
179 fail_if(last_response_was_received);
180 fail_if(handle.completed);
184 START_TEST (test_missing_pid)
186 uint16_t arb_id = 0x100;
187 DiagnosticRequestHandle handle = diagnostic_request_pid(&SHIMS,
188 DIAGNOSTIC_ENHANCED_PID, arb_id, 0x2, response_received_handler);
190 fail_if(last_response_was_received);
191 const uint8_t can_data[] = {0x1, 0x22 + 0x40};
192 diagnostic_receive_can_frame(&SHIMS, &handle, arb_id + 0x8, can_data,
194 fail_if(last_response_was_received);
195 fail_if(handle.completed);
199 START_TEST (test_wrong_pid_response)
201 uint16_t arb_id = 0x100;
202 DiagnosticRequestHandle handle = diagnostic_request_pid(&SHIMS,
203 DIAGNOSTIC_ENHANCED_PID, arb_id, 0x2, response_received_handler);
205 fail_if(last_response_was_received);
206 const uint8_t can_data[] = {0x4, 0x22 + 0x40, 0x0, 0x3, 0x45};
207 diagnostic_receive_can_frame(&SHIMS, &handle, arb_id + 0x8, can_data,
209 fail_if(last_response_was_received);
210 fail_if(handle.completed);
214 START_TEST (test_wrong_pid_then_right_completes)
216 uint16_t arb_id = 0x100;
217 DiagnosticRequestHandle handle = diagnostic_request_pid(&SHIMS,
218 DIAGNOSTIC_ENHANCED_PID, arb_id, 0x2, response_received_handler);
220 fail_if(last_response_was_received);
221 uint8_t can_data[] = {0x4, 0x22 + 0x40, 0x0, 0x3, 0x45};
222 diagnostic_receive_can_frame(&SHIMS, &handle, arb_id + 0x8, can_data,
224 fail_if(last_response_was_received);
225 fail_if(handle.completed);
228 diagnostic_receive_can_frame(&SHIMS, &handle, arb_id + 0x8, can_data,
230 fail_unless(last_response_was_received);
231 fail_unless(handle.completed);
232 fail_unless(handle.success);
233 fail_unless(last_response_received.success);
234 ck_assert_int_eq(last_response_received.pid, 0x2);
238 START_TEST (test_negative_response)
240 DiagnosticRequest request = {
241 arbitration_id: 0x100,
242 mode: OBD2_MODE_POWERTRAIN_DIAGNOSTIC_REQUEST
244 DiagnosticRequestHandle handle = diagnostic_request(&SHIMS, &request,
245 response_received_handler);
246 const uint8_t can_data[] = {0x3, 0x7f, request.mode, NRC_SERVICE_NOT_SUPPORTED};
247 DiagnosticResponse response = diagnostic_receive_can_frame(&SHIMS, &handle,
248 request.arbitration_id + 0x8, can_data, sizeof(can_data));
249 fail_unless(response.completed);
250 fail_if(response.success);
251 fail_unless(handle.completed);
253 fail_if(last_response_received.success);
254 ck_assert_int_eq(last_response_received.arbitration_id,
255 request.arbitration_id + 0x8);
256 ck_assert_int_eq(last_response_received.mode, request.mode);
257 ck_assert_int_eq(last_response_received.pid, 0);
258 ck_assert_int_eq(last_response_received.negative_response_code, NRC_SERVICE_NOT_SUPPORTED);
259 ck_assert_int_eq(last_response_received.payload_length, 0);
263 Suite* testSuite(void) {
264 Suite* s = suite_create("uds");
265 TCase *tc_core = tcase_create("core");
266 tcase_add_checked_fixture(tc_core, setup, NULL);
267 tcase_add_test(tc_core, test_send_diag_request);
268 tcase_add_test(tc_core, test_send_functional_request);
269 tcase_add_test(tc_core, test_send_diag_request_with_payload);
270 tcase_add_test(tc_core, test_receive_wrong_arb_id);
271 tcase_add_test(tc_core, test_request_pid_standard);
272 tcase_add_test(tc_core, test_request_pid_enhanced);
273 tcase_add_test(tc_core, test_wrong_mode_response);
274 tcase_add_test(tc_core, test_wrong_pid_response);
275 tcase_add_test(tc_core, test_missing_pid);
276 tcase_add_test(tc_core, test_wrong_pid_then_right_completes);
277 tcase_add_test(tc_core, test_negative_response);
279 // TODO these are future work:
280 // TODO test request MIL
281 // TODO test request VIN
282 // TODO test request DTC
283 // TODO test clear DTC
284 // TODO test enumerate PIDs
285 suite_add_tcase(s, tc_core);
292 Suite* s = testSuite();
293 SRunner *sr = srunner_create(s);
294 // Don't fork so we can actually use gdb
295 srunner_set_fork_status(sr, CK_NOFORK);
296 srunner_run_all(sr, CK_NORMAL);
297 numberFailed = srunner_ntests_failed(sr);
299 return (numberFailed == 0) ? 0 : 1;