Test receiving a CAN frame to an already completed message.
[apps/low-level-can-service.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     // TODO not sure if we can copy the struct like this
18     last_response_received = *response;
19 }
20
21 START_TEST (test_receive_wrong_arb_id)
22 {
23     DiagnosticRequest request = {
24         arbitration_id: 0x7df,
25         mode: OBD2_MODE_POWERTRAIN_DIAGNOSTIC_REQUEST
26     };
27     DiagnosticRequestHandle handle = diagnostic_request(&SHIMS, &request,
28             response_received_handler);
29
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);
35 }
36 END_TEST
37
38 START_TEST (test_send_diag_request_with_payload)
39 {
40     DiagnosticRequest request = {
41         arbitration_id: 0x7df,
42         mode: OBD2_MODE_POWERTRAIN_DIAGNOSTIC_REQUEST,
43         payload: {0x12, 0x34},
44         payload_length: 2
45     };
46     DiagnosticRequestHandle handle = diagnostic_request(&SHIMS, &request,
47             response_received_handler);
48
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]);
57 }
58 END_TEST
59
60 START_TEST (test_send_diag_request)
61 {
62     DiagnosticRequest request = {
63         arbitration_id: 0x7df,
64         mode: OBD2_MODE_POWERTRAIN_DIAGNOSTIC_REQUEST
65     };
66     DiagnosticRequestHandle handle = diagnostic_request(&SHIMS, &request,
67             response_received_handler);
68
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);
73
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]);
88 }
89 END_TEST
90
91 START_TEST (test_request_pid_standard)
92 {
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);
97
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,
105             arb_id + 0x8);
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]);
110 }
111 END_TEST
112
113 START_TEST (test_request_pid_enhanced)
114 {
115     uint16_t arb_id = 0x7df;
116     DiagnosticRequestHandle handle = diagnostic_request_pid(&SHIMS,
117             DIAGNOSTIC_ENHANCED_PID, arb_id, 0x2, response_received_handler);
118
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,
122             sizeof(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,
126             arb_id + 0x8);
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]);
131 }
132 END_TEST
133
134 START_TEST (test_wrong_mode_response)
135 {
136     uint16_t arb_id = 0x7df;
137     DiagnosticRequestHandle handle = diagnostic_request_pid(&SHIMS,
138             DIAGNOSTIC_ENHANCED_PID, arb_id, 0x2, response_received_handler);
139
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,
143             sizeof(can_data));
144     fail_unless(last_response_was_received);
145     fail_if(last_response_received.success);
146 }
147 END_TEST
148
149 START_TEST (test_handle_completed)
150 {
151     DiagnosticRequest request = {
152         arbitration_id: 0x7df,
153         mode: OBD2_MODE_POWERTRAIN_DIAGNOSTIC_REQUEST
154     };
155     DiagnosticRequestHandle handle = diagnostic_request(&SHIMS, &request,
156             response_received_handler);
157
158     fail_if(handle.completed);
159
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);
166
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);
172
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]);
180 }
181 END_TEST
182
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);
194
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);
202
203     return s;
204 }
205
206 int main(void) {
207     int numberFailed;
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);
214     srunner_free(sr);
215     return (numberFailed == 0) ? 0 : 1;
216 }