Rename from simply obd2 to more general UDS (unified diagnostics).
[apps/low-level-can-service.git] / tests / test_core.c
1 #include <uds/uds.h>
2 #include <check.h>
3 #include <stdint.h>
4 #include <stdio.h>
5 #include <stdbool.h>
6
7 extern void setup();
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;
14
15 void response_received_handler(const DiagnosticResponse* response) {
16     last_response_was_received = true;
17     last_response_received = *response;
18 }
19
20 START_TEST (test_receive_wrong_arb_id)
21 {
22     DiagnosticRequest request = {
23         arbitration_id: 0x100,
24         mode: OBD2_MODE_POWERTRAIN_DIAGNOSTIC_REQUEST
25     };
26     DiagnosticRequestHandle handle = diagnostic_request(&SHIMS, &request,
27             response_received_handler);
28
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);
34 }
35 END_TEST
36
37 START_TEST (test_send_diag_request_with_payload)
38 {
39     DiagnosticRequest request = {
40         arbitration_id: 0x100,
41         mode: OBD2_MODE_POWERTRAIN_DIAGNOSTIC_REQUEST,
42         payload: {0x12, 0x34},
43         payload_length: 2
44     };
45     DiagnosticRequestHandle handle = diagnostic_request(&SHIMS, &request,
46             response_received_handler);
47
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]);
56 }
57 END_TEST
58
59 START_TEST (test_send_functional_request)
60 {
61     DiagnosticRequest request = {
62         arbitration_id: OBD2_FUNCTIONAL_BROADCAST_ID,
63         mode: OBD2_MODE_EMISSIONS_DTC_REQUEST
64     };
65     DiagnosticRequestHandle handle = diagnostic_request(&SHIMS, &request,
66             response_received_handler);
67
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);
72
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;
77             filter++) {
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,
85                 filter);
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]);
90     }
91 }
92 END_TEST
93
94 START_TEST (test_send_diag_request)
95 {
96     DiagnosticRequest request = {
97         arbitration_id: 0x100,
98         mode: OBD2_MODE_EMISSIONS_DTC_REQUEST
99     };
100     DiagnosticRequestHandle handle = diagnostic_request(&SHIMS, &request,
101             response_received_handler);
102
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);
107
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]);
122 }
123 END_TEST
124
125 START_TEST (test_request_pid_standard)
126 {
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);
130
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,
138             arb_id + 0x8);
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]);
144 }
145 END_TEST
146
147 START_TEST (test_request_pid_enhanced)
148 {
149     uint16_t arb_id = 0x100;
150     DiagnosticRequestHandle handle = diagnostic_request_pid(&SHIMS,
151             DIAGNOSTIC_ENHANCED_PID, arb_id, 0x2, response_received_handler);
152
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,
156             sizeof(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,
160             arb_id + 0x8);
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]);
166 }
167 END_TEST
168
169 START_TEST (test_wrong_mode_response)
170 {
171     uint16_t arb_id = 0x100;
172     DiagnosticRequestHandle handle = diagnostic_request_pid(&SHIMS,
173             DIAGNOSTIC_ENHANCED_PID, arb_id, 0x2, response_received_handler);
174
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,
178             sizeof(can_data));
179     fail_if(last_response_was_received);
180     fail_if(handle.completed);
181 }
182 END_TEST
183
184 START_TEST (test_missing_pid)
185 {
186     uint16_t arb_id = 0x100;
187     DiagnosticRequestHandle handle = diagnostic_request_pid(&SHIMS,
188             DIAGNOSTIC_ENHANCED_PID, arb_id, 0x2, response_received_handler);
189
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,
193             sizeof(can_data));
194     fail_if(last_response_was_received);
195     fail_if(handle.completed);
196 }
197 END_TEST
198
199 START_TEST (test_wrong_pid_response)
200 {
201     uint16_t arb_id = 0x100;
202     DiagnosticRequestHandle handle = diagnostic_request_pid(&SHIMS,
203             DIAGNOSTIC_ENHANCED_PID, arb_id, 0x2, response_received_handler);
204
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,
208             sizeof(can_data));
209     fail_if(last_response_was_received);
210     fail_if(handle.completed);
211 }
212 END_TEST
213
214 START_TEST (test_wrong_pid_then_right_completes)
215 {
216     uint16_t arb_id = 0x100;
217     DiagnosticRequestHandle handle = diagnostic_request_pid(&SHIMS,
218             DIAGNOSTIC_ENHANCED_PID, arb_id, 0x2, response_received_handler);
219
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,
223             sizeof(can_data));
224     fail_if(last_response_was_received);
225     fail_if(handle.completed);
226
227     can_data[3] = 0x2;
228     diagnostic_receive_can_frame(&SHIMS, &handle, arb_id + 0x8, can_data,
229             sizeof(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);
235 }
236 END_TEST
237
238 START_TEST (test_negative_response)
239 {
240     DiagnosticRequest request = {
241         arbitration_id: 0x100,
242         mode: OBD2_MODE_POWERTRAIN_DIAGNOSTIC_REQUEST
243     };
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);
252
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);
260 }
261 END_TEST
262
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);
278
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);
286
287     return s;
288 }
289
290 int main(void) {
291     int numberFailed;
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);
298     srunner_free(sr);
299     return (numberFailed == 0) ? 0 : 1;
300 }