Merge pull request #8 from claneys/master
[apps/agl-service-can-low-level.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 bool can_frame_was_sent;
8 extern void setup();
9 extern bool last_response_was_received;
10 extern DiagnosticResponse last_response_received;
11 extern DiagnosticShims SHIMS;
12 extern uint16_t last_can_frame_sent_arb_id;
13 extern uint8_t last_can_payload_sent[8];
14 extern uint8_t last_can_payload_size;
15
16 void response_received_handler(const DiagnosticResponse* response) {
17     last_response_was_received = true;
18     last_response_received = *response;
19 }
20
21 START_TEST (test_receive_wrong_arb_id)
22 {
23     DiagnosticRequest request = {
24         arbitration_id: 0x100,
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: 0x100,
42         mode: OBD2_MODE_POWERTRAIN_DIAGNOSTIC_REQUEST,
43         payload: {0x12, 0x34},
44         payload_length: 2,
45         no_frame_padding: true
46     };
47     DiagnosticRequestHandle handle = diagnostic_request(&SHIMS, &request,
48             response_received_handler);
49
50     fail_if(handle.completed);
51     // TODO it'd be better to check the ISO-TP message instead of the CAN frame,
52     // but we don't have a good way to do that
53     ck_assert_int_eq(last_can_frame_sent_arb_id, request.arbitration_id);
54     ck_assert_int_eq(last_can_payload_sent[1], request.mode);
55     ck_assert_int_eq(last_can_payload_size, 4);
56     ck_assert_int_eq(last_can_payload_sent[2], request.payload[0]);
57     ck_assert_int_eq(last_can_payload_sent[3], request.payload[1]);
58 }
59 END_TEST
60
61 START_TEST (test_send_functional_request)
62 {
63     DiagnosticRequest request = {
64         arbitration_id: OBD2_FUNCTIONAL_BROADCAST_ID,
65         mode: OBD2_MODE_EMISSIONS_DTC_REQUEST,
66         no_frame_padding: true
67     };
68     DiagnosticRequestHandle handle = diagnostic_request(&SHIMS, &request,
69             response_received_handler);
70
71     fail_if(handle.completed);
72     ck_assert_int_eq(last_can_frame_sent_arb_id, request.arbitration_id);
73     ck_assert_int_eq(last_can_payload_sent[1], request.mode);
74     ck_assert_int_eq(last_can_payload_size, 2);
75
76     fail_if(last_response_was_received);
77     const uint8_t can_data[] = {0x2, request.mode + 0x40, 0x23};
78     for(uint16_t filter = OBD2_FUNCTIONAL_RESPONSE_START; filter <
79             OBD2_FUNCTIONAL_RESPONSE_START + OBD2_FUNCTIONAL_RESPONSE_COUNT;
80             filter++) {
81         DiagnosticResponse response = diagnostic_receive_can_frame(&SHIMS,
82                 &handle, filter, can_data, sizeof(can_data));
83         fail_unless(response.success);
84         fail_unless(response.completed);
85         fail_unless(handle.completed);
86         ck_assert(last_response_received.success);
87         ck_assert_int_eq(last_response_received.arbitration_id,
88                 filter);
89         ck_assert_int_eq(last_response_received.mode, request.mode);
90         fail_if(last_response_received.has_pid);
91         ck_assert_int_eq(last_response_received.payload_length, 1);
92         ck_assert_int_eq(last_response_received.payload[0], can_data[2]);
93     }
94 }
95 END_TEST
96
97 START_TEST (test_sent_message_no_padding)
98 {
99     DiagnosticRequest request = {
100         arbitration_id: 0x100,
101         mode: OBD2_MODE_EMISSIONS_DTC_REQUEST,
102         no_frame_padding: true
103     };
104     DiagnosticRequestHandle handle = diagnostic_request(&SHIMS, &request,
105             response_received_handler);
106
107     fail_if(handle.completed);
108     ck_assert_int_eq(last_can_frame_sent_arb_id, request.arbitration_id);
109     ck_assert_int_eq(last_can_payload_size, 2);
110 }
111 END_TEST
112
113 START_TEST (test_sent_message_is_padded_by_default)
114 {
115     DiagnosticRequest request = {
116         arbitration_id: 0x100,
117         mode: OBD2_MODE_EMISSIONS_DTC_REQUEST
118     };
119     DiagnosticRequestHandle handle = diagnostic_request(&SHIMS, &request,
120             response_received_handler);
121
122     fail_if(handle.completed);
123     ck_assert_int_eq(last_can_frame_sent_arb_id, request.arbitration_id);
124     ck_assert_int_eq(last_can_payload_size, 8);
125 }
126 END_TEST
127
128 START_TEST (test_sent_message_is_padded)
129 {
130     DiagnosticRequest request = {
131         arbitration_id: 0x100,
132         mode: OBD2_MODE_EMISSIONS_DTC_REQUEST,
133         no_frame_padding: false
134     };
135     DiagnosticRequestHandle handle = diagnostic_request(&SHIMS, &request,
136             response_received_handler);
137
138     fail_if(handle.completed);
139     ck_assert_int_eq(last_can_frame_sent_arb_id, request.arbitration_id);
140     ck_assert_int_eq(last_can_payload_size, 8);
141 }
142 END_TEST
143
144 START_TEST (test_send_diag_request)
145 {
146     DiagnosticRequest request = {
147         arbitration_id: 0x100,
148         mode: OBD2_MODE_EMISSIONS_DTC_REQUEST,
149         no_frame_padding: true
150     };
151     DiagnosticRequestHandle handle = diagnostic_request(&SHIMS, &request,
152             response_received_handler);
153
154     fail_if(handle.completed);
155     fail_unless(can_frame_was_sent);
156     ck_assert_int_eq(last_can_frame_sent_arb_id, request.arbitration_id);
157     ck_assert_int_eq(last_can_payload_sent[1], request.mode);
158     ck_assert_int_eq(last_can_payload_size, 2);
159
160     fail_if(last_response_was_received);
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     ck_assert(last_response_received.success);
168     ck_assert_int_eq(last_response_received.arbitration_id,
169             request.arbitration_id + 0x8);
170     ck_assert_int_eq(last_response_received.mode, request.mode);
171         fail_if(last_response_received.has_pid);
172     ck_assert_int_eq(last_response_received.payload_length, 1);
173     ck_assert_int_eq(last_response_received.payload[0], can_data[2]);
174 }
175 END_TEST
176
177 START_TEST (test_generate_then_send_request)
178 {
179     DiagnosticRequest request = {
180         arbitration_id: 0x100,
181         mode: OBD2_MODE_EMISSIONS_DTC_REQUEST,
182         no_frame_padding: true
183     };
184     DiagnosticRequestHandle handle = generate_diagnostic_request(&SHIMS,
185             &request, response_received_handler);
186
187     fail_if(handle.completed);
188     fail_if(can_frame_was_sent);
189
190     start_diagnostic_request(&SHIMS, &handle);
191     fail_unless(can_frame_was_sent);
192     ck_assert_int_eq(last_can_frame_sent_arb_id, request.arbitration_id);
193     ck_assert_int_eq(last_can_payload_sent[1], request.mode);
194     ck_assert_int_eq(last_can_payload_size, 2);
195
196     fail_if(last_response_was_received);
197     const uint8_t can_data[] = {0x2, request.mode + 0x40, 0x23};
198     DiagnosticResponse response = diagnostic_receive_can_frame(&SHIMS, &handle,
199             request.arbitration_id + 0x8, can_data, sizeof(can_data));
200     fail_unless(response.success);
201     fail_unless(response.completed);
202     fail_unless(handle.completed);
203     ck_assert(last_response_received.success);
204     ck_assert_int_eq(last_response_received.arbitration_id,
205             request.arbitration_id + 0x8);
206     ck_assert_int_eq(last_response_received.mode, request.mode);
207         fail_if(last_response_received.has_pid);
208     ck_assert_int_eq(last_response_received.payload_length, 1);
209     ck_assert_int_eq(last_response_received.payload[0], can_data[2]);
210 }
211 END_TEST
212
213 START_TEST (test_generate_diag_request)
214 {
215     DiagnosticRequest request = {
216         arbitration_id: 0x100,
217         mode: OBD2_MODE_EMISSIONS_DTC_REQUEST,
218         no_frame_padding: true
219     };
220     DiagnosticRequestHandle handle = generate_diagnostic_request(&SHIMS,
221             &request, response_received_handler);
222
223     fail_if(handle.completed);
224     fail_if(can_frame_was_sent);
225 }
226 END_TEST
227
228 START_TEST (test_autoset_pid_length)
229 {
230     uint16_t arb_id = OBD2_MODE_POWERTRAIN_DIAGNOSTIC_REQUEST;
231     diagnostic_request_pid(&SHIMS, DIAGNOSTIC_STANDARD_PID, arb_id, 0x2,
232             response_received_handler);
233
234     ck_assert_int_eq(last_can_frame_sent_arb_id, arb_id);
235     ck_assert_int_eq(last_can_payload_sent[1], 0x1);
236     ck_assert_int_eq(last_can_payload_sent[2], 0x2);
237     // padding is on for the diagnostic_request_pid helper function - if you
238     // need to turn it off, use the more manual diagnostic_request(...)
239     ck_assert_int_eq(last_can_payload_size, 8);
240
241     DiagnosticRequest request = {
242         arbitration_id: 0x100,
243         mode: 0x22,
244         has_pid: true,
245         pid: 0x1234,
246         no_frame_padding: true
247     };
248     diagnostic_request(&SHIMS, &request, response_received_handler);
249
250     ck_assert_int_eq(last_can_frame_sent_arb_id, request.arbitration_id);
251     ck_assert_int_eq(last_can_payload_sent[1], request.mode);
252     ck_assert_int_eq(last_can_payload_sent[2], (request.pid & 0xFF00) >> 8);
253     ck_assert_int_eq(last_can_payload_sent[3], request.pid & 0xFF);
254     ck_assert_int_eq(last_can_payload_size, 4);
255
256     request.arbitration_id = 0x101;
257     request.pid = 0x12;
258
259     diagnostic_request(&SHIMS, &request, response_received_handler);
260
261     ck_assert_int_eq(last_can_frame_sent_arb_id, request.arbitration_id);
262     ck_assert_int_eq(last_can_payload_sent[1], request.mode);
263     ck_assert_int_eq(last_can_payload_sent[2], request.pid);
264     ck_assert_int_eq(last_can_payload_size, 3);
265 }
266 END_TEST
267
268 START_TEST (test_request_pid_standard)
269 {
270     uint16_t arb_id = OBD2_MODE_POWERTRAIN_DIAGNOSTIC_REQUEST;
271     DiagnosticRequestHandle handle = diagnostic_request_pid(&SHIMS,
272             DIAGNOSTIC_STANDARD_PID, arb_id, 0x2, response_received_handler);
273
274     fail_if(last_response_was_received);
275     const uint8_t can_data[] = {0x3, 0x1 + 0x40, 0x2, 0x45};
276     diagnostic_receive_can_frame(&SHIMS, &handle, arb_id + 0x8,
277             can_data, sizeof(can_data));
278     fail_unless(last_response_was_received);
279     ck_assert(last_response_received.success);
280     ck_assert_int_eq(last_response_received.arbitration_id,
281             arb_id + 0x8);
282     ck_assert_int_eq(last_response_received.mode, 0x1);
283     fail_unless(last_response_received.has_pid);
284     ck_assert_int_eq(last_response_received.pid, 0x2);
285     ck_assert_int_eq(last_response_received.payload_length, 1);
286     ck_assert_int_eq(last_response_received.payload[0], can_data[3]);
287 }
288 END_TEST
289
290 START_TEST (test_request_pid_enhanced)
291 {
292     uint16_t arb_id = 0x100;
293     DiagnosticRequestHandle handle = diagnostic_request_pid(&SHIMS,
294             DIAGNOSTIC_ENHANCED_PID, arb_id, 0x1234, response_received_handler);
295
296     fail_if(last_response_was_received);
297     const uint8_t can_data[] = {0x4, 0x22 + 0x40, 0x12, 0x34, 0x45};
298     diagnostic_receive_can_frame(&SHIMS, &handle, arb_id + 0x8, can_data,
299             sizeof(can_data));
300     fail_unless(last_response_was_received);
301     ck_assert(last_response_received.success);
302     ck_assert_int_eq(last_response_received.arbitration_id,
303             arb_id + 0x8);
304     ck_assert_int_eq(last_response_received.mode, 0x22);
305     fail_unless(last_response_received.has_pid);
306     ck_assert_int_eq(last_response_received.pid, 0x1234);
307     ck_assert_int_eq(last_response_received.payload_length, 1);
308     ck_assert_int_eq(last_response_received.payload[0], can_data[4]);
309 }
310 END_TEST
311
312 START_TEST (test_wrong_mode_response)
313 {
314     uint16_t arb_id = 0x100;
315     DiagnosticRequestHandle handle = diagnostic_request_pid(&SHIMS,
316             DIAGNOSTIC_ENHANCED_PID, arb_id, 0x1234, response_received_handler);
317
318     fail_if(last_response_was_received);
319     const uint8_t can_data[] = {0x4, 0x1 + 0x40, 0x12, 0x34, 0x45};
320     diagnostic_receive_can_frame(&SHIMS, &handle, arb_id + 0x8, can_data,
321             sizeof(can_data));
322     fail_if(last_response_was_received);
323     fail_if(handle.completed);
324 }
325 END_TEST
326
327 START_TEST (test_missing_pid)
328 {
329     uint16_t arb_id = 0x100;
330     DiagnosticRequestHandle handle = diagnostic_request_pid(&SHIMS,
331             DIAGNOSTIC_ENHANCED_PID, arb_id, 0x1234, response_received_handler);
332
333     fail_if(last_response_was_received);
334     const uint8_t can_data[] = {0x1, 0x22 + 0x40};
335     diagnostic_receive_can_frame(&SHIMS, &handle, arb_id + 0x8, can_data,
336             sizeof(can_data));
337     fail_if(last_response_was_received);
338     fail_if(handle.completed);
339 }
340 END_TEST
341
342 START_TEST (test_wrong_pid_response)
343 {
344     uint16_t arb_id = 0x100;
345     DiagnosticRequestHandle handle = diagnostic_request_pid(&SHIMS,
346             DIAGNOSTIC_ENHANCED_PID, arb_id, 0x1234, response_received_handler);
347
348     fail_if(last_response_was_received);
349     const uint8_t can_data[] = {0x4, 0x22 + 0x40, 0x12, 0x33, 0x45};
350     diagnostic_receive_can_frame(&SHIMS, &handle, arb_id + 0x8, can_data,
351             sizeof(can_data));
352     fail_if(last_response_was_received);
353     fail_if(handle.completed);
354 }
355 END_TEST
356
357 START_TEST (test_wrong_pid_then_right_completes)
358 {
359     uint16_t arb_id = 0x100;
360     DiagnosticRequestHandle handle = diagnostic_request_pid(&SHIMS,
361             DIAGNOSTIC_ENHANCED_PID, arb_id, 0x1234, response_received_handler);
362
363     fail_if(last_response_was_received);
364     uint8_t can_data[] = {0x4, 0x22 + 0x40, 0x12, 0x33, 0x45};
365     diagnostic_receive_can_frame(&SHIMS, &handle, arb_id + 0x8, can_data,
366             sizeof(can_data));
367     fail_if(last_response_was_received);
368     fail_if(handle.completed);
369
370     can_data[3] = 0x34;
371     diagnostic_receive_can_frame(&SHIMS, &handle, arb_id + 0x8, can_data,
372             sizeof(can_data));
373     fail_unless(last_response_was_received);
374     fail_unless(handle.completed);
375     fail_unless(handle.success);
376     fail_unless(last_response_received.success);
377     ck_assert_int_eq(last_response_received.pid, 0x1234);
378 }
379 END_TEST
380
381 START_TEST (test_negative_response)
382 {
383     DiagnosticRequest request = {
384         arbitration_id: 0x100,
385         mode: OBD2_MODE_POWERTRAIN_DIAGNOSTIC_REQUEST
386     };
387     DiagnosticRequestHandle handle = diagnostic_request(&SHIMS, &request,
388             response_received_handler);
389     const uint8_t can_data[] = {0x3, 0x7f, request.mode,
390         NRC_SERVICE_NOT_SUPPORTED};
391     DiagnosticResponse response = diagnostic_receive_can_frame(&SHIMS, &handle,
392             request.arbitration_id + 0x8, can_data, sizeof(can_data));
393     fail_unless(response.completed);
394     fail_if(response.success);
395     fail_unless(handle.completed);
396
397     fail_if(last_response_received.success);
398     ck_assert_int_eq(last_response_received.arbitration_id,
399             request.arbitration_id + 0x8);
400     ck_assert_int_eq(last_response_received.mode, request.mode);
401     ck_assert_int_eq(last_response_received.pid, 0);
402     ck_assert_int_eq(last_response_received.negative_response_code,
403             NRC_SERVICE_NOT_SUPPORTED);
404     ck_assert_int_eq(last_response_received.payload_length, 0);
405 }
406 END_TEST
407
408 START_TEST (test_payload_to_integer)
409 {
410     uint16_t arb_id = OBD2_MODE_POWERTRAIN_DIAGNOSTIC_REQUEST;
411     DiagnosticRequestHandle handle = diagnostic_request_pid(&SHIMS,
412             DIAGNOSTIC_STANDARD_PID, arb_id, 0x2, response_received_handler);
413
414     fail_if(last_response_was_received);
415     const uint8_t can_data[] = {0x4, 0x1 + 0x40, 0x2, 0x45, 0x12};
416     DiagnosticResponse response = diagnostic_receive_can_frame(&SHIMS, &handle,
417             arb_id + 0x8, can_data, sizeof(can_data));
418     ck_assert_int_eq(diagnostic_payload_to_integer(&response), 0x4512);
419 }
420 END_TEST
421
422 START_TEST (test_response_multi_frame)
423 {
424     DiagnosticRequest request = {
425         arbitration_id: 0x100,
426         mode: OBD2_MODE_VEHICLE_INFORMATION,
427         has_pid: true,
428         pid: 0x2
429     };
430     DiagnosticRequestHandle handle = diagnostic_request(&SHIMS, &request,
431             response_received_handler);
432
433     const uint8_t can_data[] = {0x10, 0x14, 0x9 + 0x40, 0x2, 0x1, 0x31, 0x46, 0x4d};
434     DiagnosticResponse response = diagnostic_receive_can_frame(&SHIMS, &handle,
435             request.arbitration_id + 0x8, can_data, sizeof(can_data));
436
437     fail_unless(can_frame_was_sent);
438     fail_unless(!response.success);
439     fail_unless(!response.completed);
440     fail_unless(response.multi_frame);
441     ck_assert_int_eq(last_can_frame_sent_arb_id, request.arbitration_id);
442     ck_assert_int_eq(last_can_payload_sent[0], 0x30);
443
444     const uint8_t can_data_1[] = {0x21, 0x43, 0x55, 0x39, 0x4a, 0x39, 0x34, 0x48};
445     response = diagnostic_receive_can_frame(&SHIMS, &handle,
446             request.arbitration_id + 0x8, can_data_1, sizeof(can_data_1));
447     fail_unless(!response.success);
448     fail_unless(!response.completed);
449     fail_unless(response.multi_frame);
450
451     const uint8_t can_data_2[] = {0x22, 0x55, 0x41, 0x30, 0x34, 0x35, 0x32, 0x34};
452     response = diagnostic_receive_can_frame(&SHIMS, &handle,
453             request.arbitration_id + 0x8, can_data_2, sizeof(can_data_2));
454     fail_unless(response.success);
455     fail_unless(response.completed);
456     fail_unless(response.multi_frame);
457     ck_assert_int_eq(response.mode, OBD2_MODE_VEHICLE_INFORMATION);
458     ck_assert_int_eq(response.pid, 0x2);
459     ck_assert_int_eq(response.payload_length, 18);
460     ck_assert_int_eq(response.payload[0], 0x01);
461     ck_assert_int_eq(response.payload[1], 0x31);
462     ck_assert_int_eq(response.payload[2], 0x46);
463     ck_assert_int_eq(response.payload[3], 0x4d);
464     ck_assert_int_eq(response.payload[4], 0x43);
465     ck_assert_int_eq(response.payload[5], 0x55);
466     ck_assert_int_eq(response.payload[6], 0x39);
467     ck_assert_int_eq(response.payload[7], 0x4a);
468     ck_assert_int_eq(response.payload[8], 0x39);
469     ck_assert_int_eq(response.payload[9], 0x34);
470     ck_assert_int_eq(response.payload[10], 0x48);
471     ck_assert_int_eq(response.payload[11], 0x55);
472     ck_assert_int_eq(response.payload[12], 0x41);
473     ck_assert_int_eq(response.payload[13], 0x30);
474     ck_assert_int_eq(response.payload[14], 0x34);
475     ck_assert_int_eq(response.payload[15], 0x35);
476     ck_assert_int_eq(response.payload[16], 0x32);
477     ck_assert_int_eq(response.payload[17], 0x34);
478 }
479 END_TEST
480
481 Suite* testSuite(void) {
482     Suite* s = suite_create("uds");
483     TCase *tc_core = tcase_create("core");
484     tcase_add_checked_fixture(tc_core, setup, NULL);
485     tcase_add_test(tc_core, test_sent_message_no_padding);
486     tcase_add_test(tc_core, test_sent_message_is_padded);
487     tcase_add_test(tc_core, test_sent_message_is_padded_by_default);
488     tcase_add_test(tc_core, test_generate_diag_request);
489     tcase_add_test(tc_core, test_generate_then_send_request);
490     tcase_add_test(tc_core, test_send_diag_request);
491     tcase_add_test(tc_core, test_send_functional_request);
492     tcase_add_test(tc_core, test_send_diag_request_with_payload);
493     tcase_add_test(tc_core, test_receive_wrong_arb_id);
494     tcase_add_test(tc_core, test_autoset_pid_length);
495     tcase_add_test(tc_core, test_request_pid_standard);
496     tcase_add_test(tc_core, test_request_pid_enhanced);
497     tcase_add_test(tc_core, test_wrong_mode_response);
498     tcase_add_test(tc_core, test_wrong_pid_response);
499     tcase_add_test(tc_core, test_missing_pid);
500     tcase_add_test(tc_core, test_wrong_pid_then_right_completes);
501     tcase_add_test(tc_core, test_negative_response);
502     tcase_add_test(tc_core, test_payload_to_integer);
503     tcase_add_test(tc_core, test_response_multi_frame);
504
505     // TODO these are future work:
506     // TODO test request MIL
507     // TODO test request VIN
508     // TODO test request DTC
509     // TODO test clear DTC
510     // TODO test enumerate PIDs
511     suite_add_tcase(s, tc_core);
512
513     return s;
514 }
515
516 int main(void) {
517     int numberFailed;
518     Suite* s = testSuite();
519     SRunner *sr = srunner_create(s);
520     // Don't fork so we can actually use gdb
521     srunner_set_fork_status(sr, CK_NOFORK);
522     srunner_run_all(sr, CK_NORMAL);
523     numberFailed = srunner_ntests_failed(sr);
524     srunner_free(sr);
525     return (numberFailed == 0) ? 0 : 1;
526 }