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 // TODO not sure if we can copy the struct like this
18 last_response_received = *response;
21 START_TEST (test_receive_wrong_arb_id)
23 DiagnosticRequest request = {
24 arbitration_id: 0x7df,
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: 0x7df,
42 mode: OBD2_MODE_POWERTRAIN_DIAGNOSTIC_REQUEST,
43 payload: {0x12, 0x34},
46 DiagnosticRequestHandle handle = diagnostic_request(&SHIMS, &request,
47 response_received_handler);
49 fail_if(handle.completed);
50 // TODO it'd be better to check the ISO-TP message instead of the CAN frame,
51 // but we don't have a good way to do that
52 ck_assert_int_eq(last_can_frame_sent_arb_id, request.arbitration_id);
53 ck_assert_int_eq(last_can_payload_sent[1], request.mode);
54 ck_assert_int_eq(last_can_payload_size, 4);
55 ck_assert_int_eq(last_can_payload_sent[2], request.payload[0]);
56 ck_assert_int_eq(last_can_payload_sent[3], request.payload[1]);
60 START_TEST (test_send_diag_request)
62 DiagnosticRequest request = {
63 arbitration_id: 0x7df,
64 mode: OBD2_MODE_POWERTRAIN_DIAGNOSTIC_REQUEST
66 DiagnosticRequestHandle handle = diagnostic_request(&SHIMS, &request,
67 response_received_handler);
69 fail_if(handle.completed);
70 ck_assert_int_eq(last_can_frame_sent_arb_id, request.arbitration_id);
71 ck_assert_int_eq(last_can_payload_sent[1], request.mode);
72 ck_assert_int_eq(last_can_payload_size, 2);
74 fail_if(last_response_was_received);
75 const uint8_t can_data[] = {0x2, request.mode + 0x40, 0x23};
76 DiagnosticResponse response = diagnostic_receive_can_frame(&SHIMS, &handle,
77 request.arbitration_id + 0x8, can_data, sizeof(can_data));
78 fail_unless(response.success);
79 fail_unless(response.completed);
80 fail_unless(handle.completed);
81 ck_assert(last_response_received.success);
82 ck_assert_int_eq(last_response_received.arbitration_id,
83 request.arbitration_id + 0x8);
84 ck_assert_int_eq(last_response_received.mode, request.mode);
85 ck_assert_int_eq(last_response_received.pid, 0);
86 ck_assert_int_eq(last_response_received.payload_length, 1);
87 ck_assert_int_eq(last_response_received.payload[0], can_data[2]);
91 START_TEST (test_request_pid_standard)
93 // TODO need a constant for the 7df broadcast functional request
94 uint16_t arb_id = 0x7df;
95 DiagnosticRequestHandle handle = diagnostic_request_pid(&SHIMS,
96 DIAGNOSTIC_STANDARD_PID, arb_id, 0x2, response_received_handler);
98 fail_if(last_response_was_received);
99 const uint8_t can_data[] = {0x3, 0x1 + 0x40, 0x2, 0x45};
100 diagnostic_receive_can_frame(&SHIMS, &handle, arb_id + 0x8,
101 can_data, sizeof(can_data));
102 fail_unless(last_response_was_received);
103 ck_assert(last_response_received.success);
104 ck_assert_int_eq(last_response_received.arbitration_id,
106 ck_assert_int_eq(last_response_received.mode, 0x1);
107 ck_assert_int_eq(last_response_received.pid, 0x2);
108 ck_assert_int_eq(last_response_received.payload_length, 1);
109 ck_assert_int_eq(last_response_received.payload[0], can_data[3]);
113 START_TEST (test_request_pid_enhanced)
115 uint16_t arb_id = 0x7df;
116 DiagnosticRequestHandle handle = diagnostic_request_pid(&SHIMS,
117 DIAGNOSTIC_ENHANCED_PID, arb_id, 0x2, response_received_handler);
119 fail_if(last_response_was_received);
120 const uint8_t can_data[] = {0x4, 0x22 + 0x40, 0x0, 0x2, 0x45};
121 diagnostic_receive_can_frame(&SHIMS, &handle, arb_id + 0x8, can_data,
123 fail_unless(last_response_was_received);
124 ck_assert(last_response_received.success);
125 ck_assert_int_eq(last_response_received.arbitration_id,
127 ck_assert_int_eq(last_response_received.mode, 0x22);
128 ck_assert_int_eq(last_response_received.pid, 0x2);
129 ck_assert_int_eq(last_response_received.payload_length, 1);
130 ck_assert_int_eq(last_response_received.payload[0], can_data[4]);
134 START_TEST (test_wrong_mode_response)
136 uint16_t arb_id = 0x7df;
137 DiagnosticRequestHandle handle = diagnostic_request_pid(&SHIMS,
138 DIAGNOSTIC_ENHANCED_PID, arb_id, 0x2, response_received_handler);
140 fail_if(last_response_was_received);
141 const uint8_t can_data[] = {0x4, 0x1 + 0x40, 0x0, 0x2, 0x45};
142 diagnostic_receive_can_frame(&SHIMS, &handle, arb_id + 0x8, can_data,
144 fail_unless(last_response_was_received);
145 fail_if(last_response_received.success);
149 START_TEST (test_handle_completed)
151 DiagnosticRequest request = {
152 arbitration_id: 0x7df,
153 mode: OBD2_MODE_POWERTRAIN_DIAGNOSTIC_REQUEST
155 DiagnosticRequestHandle handle = diagnostic_request(&SHIMS, &request,
156 response_received_handler);
158 fail_if(handle.completed);
160 const uint8_t can_data[] = {0x2, request.mode + 0x40, 0x23};
161 DiagnosticResponse response = diagnostic_receive_can_frame(&SHIMS, &handle,
162 request.arbitration_id + 0x8, can_data, sizeof(can_data));
163 fail_unless(response.success);
164 fail_unless(response.completed);
165 fail_unless(handle.completed);
167 response = diagnostic_receive_can_frame(&SHIMS, &handle,
168 request.arbitration_id + 0x8, can_data, sizeof(can_data));
169 fail_if(response.success);
170 fail_if(response.completed);
171 fail_unless(handle.completed);
173 ck_assert(last_response_received.success);
174 ck_assert_int_eq(last_response_received.arbitration_id,
175 request.arbitration_id + 0x8);
176 ck_assert_int_eq(last_response_received.mode, request.mode);
177 ck_assert_int_eq(last_response_received.pid, 0);
178 ck_assert_int_eq(last_response_received.payload_length, 1);
179 ck_assert_int_eq(last_response_received.payload[0], can_data[2]);
183 Suite* testSuite(void) {
184 Suite* s = suite_create("obd2");
185 TCase *tc_core = tcase_create("core");
186 tcase_add_checked_fixture(tc_core, setup, NULL);
187 tcase_add_test(tc_core, test_send_diag_request);
188 tcase_add_test(tc_core, test_send_diag_request_with_payload);
189 tcase_add_test(tc_core, test_receive_wrong_arb_id);
190 tcase_add_test(tc_core, test_request_pid_standard);
191 tcase_add_test(tc_core, test_request_pid_enhanced);
192 tcase_add_test(tc_core, test_wrong_mode_response);
193 tcase_add_test(tc_core, test_handle_completed);
195 // TODO these are future work:
196 // TODO test request MIL
197 // TODO test request VIN
198 // TODO test request DTC
199 // TODO test clear DTC
200 // TODO test enumerate PIDs
201 suite_add_tcase(s, tc_core);
208 Suite* s = testSuite();
209 SRunner *sr = srunner_create(s);
210 // Don't fork so we can actually use gdb
211 srunner_set_fork_status(sr, CK_NOFORK);
212 srunner_run_all(sr, CK_NORMAL);
213 numberFailed = srunner_ntests_failed(sr);
215 return (numberFailed == 0) ? 0 : 1;