Add a constant for the functional broadcast address 0x7df.
[apps/agl-service-can-low-level.git] / tests / test_core.c
1 #include <obd2/obd2.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: OBD2_FUNCTIONAL_BROADCAST_ID,
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: OBD2_FUNCTIONAL_BROADCAST_ID,
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_diag_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     DiagnosticResponse response = diagnostic_receive_can_frame(&SHIMS, &handle,
76             request.arbitration_id + 0x8, can_data, sizeof(can_data));
77     fail_unless(response.success);
78     fail_unless(response.completed);
79     fail_unless(handle.completed);
80     ck_assert(last_response_received.success);
81     ck_assert_int_eq(last_response_received.arbitration_id,
82             request.arbitration_id + 0x8);
83     ck_assert_int_eq(last_response_received.mode, request.mode);
84     ck_assert_int_eq(last_response_received.pid, 0);
85     ck_assert_int_eq(last_response_received.payload_length, 1);
86     ck_assert_int_eq(last_response_received.payload[0], can_data[2]);
87 }
88 END_TEST
89
90 START_TEST (test_request_pid_standard)
91 {
92     uint16_t arb_id = OBD2_MODE_POWERTRAIN_DIAGNOSTIC_REQUEST;
93     DiagnosticRequestHandle handle = diagnostic_request_pid(&SHIMS,
94             DIAGNOSTIC_STANDARD_PID, arb_id, 0x2, response_received_handler);
95
96     fail_if(last_response_was_received);
97     const uint8_t can_data[] = {0x3, 0x1 + 0x40, 0x2, 0x45};
98     diagnostic_receive_can_frame(&SHIMS, &handle, arb_id + 0x8,
99             can_data, sizeof(can_data));
100     fail_unless(last_response_was_received);
101     ck_assert(last_response_received.success);
102     ck_assert_int_eq(last_response_received.arbitration_id,
103             arb_id + 0x8);
104     ck_assert_int_eq(last_response_received.mode, 0x1);
105     ck_assert_int_eq(last_response_received.pid, 0x2);
106     ck_assert_int_eq(last_response_received.payload_length, 1);
107     ck_assert_int_eq(last_response_received.payload[0], can_data[3]);
108 }
109 END_TEST
110
111 START_TEST (test_request_pid_enhanced)
112 {
113     uint16_t arb_id = OBD2_FUNCTIONAL_BROADCAST_ID;
114     DiagnosticRequestHandle handle = diagnostic_request_pid(&SHIMS,
115             DIAGNOSTIC_ENHANCED_PID, arb_id, 0x2, response_received_handler);
116
117     fail_if(last_response_was_received);
118     const uint8_t can_data[] = {0x4, 0x22 + 0x40, 0x0, 0x2, 0x45};
119     diagnostic_receive_can_frame(&SHIMS, &handle, arb_id + 0x8, can_data,
120             sizeof(can_data));
121     fail_unless(last_response_was_received);
122     ck_assert(last_response_received.success);
123     ck_assert_int_eq(last_response_received.arbitration_id,
124             arb_id + 0x8);
125     ck_assert_int_eq(last_response_received.mode, 0x22);
126     ck_assert_int_eq(last_response_received.pid, 0x2);
127     ck_assert_int_eq(last_response_received.payload_length, 1);
128     ck_assert_int_eq(last_response_received.payload[0], can_data[4]);
129 }
130 END_TEST
131
132 START_TEST (test_wrong_mode_response)
133 {
134     uint16_t arb_id = OBD2_FUNCTIONAL_BROADCAST_ID;
135     DiagnosticRequestHandle handle = diagnostic_request_pid(&SHIMS,
136             DIAGNOSTIC_ENHANCED_PID, arb_id, 0x2, response_received_handler);
137
138     fail_if(last_response_was_received);
139     const uint8_t can_data[] = {0x4, 0x1 + 0x40, 0x0, 0x2, 0x45};
140     diagnostic_receive_can_frame(&SHIMS, &handle, arb_id + 0x8, can_data,
141             sizeof(can_data));
142     // TODO change this if we even re-request a message receipt on a mode or PID
143     // mismatch
144     fail_unless(last_response_was_received);
145     fail_unless(handle.completed);
146     fail_if(last_response_received.success);
147 }
148 END_TEST
149
150 START_TEST (test_handle_completed)
151 {
152     DiagnosticRequest request = {
153         arbitration_id: OBD2_FUNCTIONAL_BROADCAST_ID,
154         mode: OBD2_MODE_POWERTRAIN_DIAGNOSTIC_REQUEST
155     };
156     DiagnosticRequestHandle handle = diagnostic_request(&SHIMS, &request,
157             response_received_handler);
158
159     fail_if(handle.completed);
160
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
168     response = diagnostic_receive_can_frame(&SHIMS, &handle,
169             request.arbitration_id + 0x8, can_data, sizeof(can_data));
170     fail_if(response.success);
171     fail_if(response.completed);
172     fail_unless(handle.completed);
173
174     ck_assert(last_response_received.success);
175     ck_assert_int_eq(last_response_received.arbitration_id,
176             request.arbitration_id + 0x8);
177     ck_assert_int_eq(last_response_received.mode, request.mode);
178     ck_assert_int_eq(last_response_received.pid, 0);
179     ck_assert_int_eq(last_response_received.payload_length, 1);
180     ck_assert_int_eq(last_response_received.payload[0], can_data[2]);
181 }
182 END_TEST
183
184 START_TEST (test_negative_response)
185 {
186     DiagnosticRequest request = {
187         arbitration_id: OBD2_FUNCTIONAL_BROADCAST_ID,
188         mode: OBD2_MODE_POWERTRAIN_DIAGNOSTIC_REQUEST
189     };
190     DiagnosticRequestHandle handle = diagnostic_request(&SHIMS, &request,
191             response_received_handler);
192     const uint8_t can_data[] = {0x3, 0x7f, request.mode, NRC_SERVICE_NOT_SUPPORTED};
193     DiagnosticResponse response = diagnostic_receive_can_frame(&SHIMS, &handle,
194             request.arbitration_id + 0x8, can_data, sizeof(can_data));
195     fail_unless(response.completed);
196     fail_if(response.success);
197     fail_unless(handle.completed);
198
199     fail_if(last_response_received.success);
200     ck_assert_int_eq(last_response_received.arbitration_id,
201             request.arbitration_id + 0x8);
202     ck_assert_int_eq(last_response_received.mode, request.mode);
203     ck_assert_int_eq(last_response_received.pid, 0);
204     ck_assert_int_eq(last_response_received.negative_response_code, NRC_SERVICE_NOT_SUPPORTED);
205     ck_assert_int_eq(last_response_received.payload_length, 0);
206 }
207 END_TEST
208
209 Suite* testSuite(void) {
210     Suite* s = suite_create("obd2");
211     TCase *tc_core = tcase_create("core");
212     tcase_add_checked_fixture(tc_core, setup, NULL);
213     tcase_add_test(tc_core, test_send_diag_request);
214     tcase_add_test(tc_core, test_send_diag_request_with_payload);
215     tcase_add_test(tc_core, test_receive_wrong_arb_id);
216     tcase_add_test(tc_core, test_request_pid_standard);
217     tcase_add_test(tc_core, test_request_pid_enhanced);
218     tcase_add_test(tc_core, test_wrong_mode_response);
219     tcase_add_test(tc_core, test_handle_completed);
220     tcase_add_test(tc_core, test_negative_response);
221
222     // TODO these are future work:
223     // TODO test request MIL
224     // TODO test request VIN
225     // TODO test request DTC
226     // TODO test clear DTC
227     // TODO test enumerate PIDs
228     suite_add_tcase(s, tc_core);
229
230     return s;
231 }
232
233 int main(void) {
234     int numberFailed;
235     Suite* s = testSuite();
236     SRunner *sr = srunner_create(s);
237     // Don't fork so we can actually use gdb
238     srunner_set_fork_status(sr, CK_NOFORK);
239     srunner_run_all(sr, CK_NORMAL);
240     numberFailed = srunner_ntests_failed(sr);
241     srunner_free(sr);
242     return (numberFailed == 0) ? 0 : 1;
243 }