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