@@ -2584,6 +2584,319 @@ def __init__(self, *args, **kwargs):
25842584
25852585
25862586
2587+ class TestreportDTCExtDataRecordByRecordNumber(ClientServerTest): # Subfn = 0x16
2588+ sb = struct.pack('B', 0x16)
2589+ badsb = struct.pack('B', 0x16+1)
2590+
2591+ def assert_single_data_response(self, response):
2592+ self.assertEqual(len(response.service_data.dtcs), 1)
2593+ self.assertEqual(response.service_data.dtc_count, 1)
2594+
2595+ dtc = response.service_data.dtcs[0]
2596+
2597+ self.assertEqual(dtc.id, 0x123456)
2598+ self.assertEqual(dtc.status.get_byte_as_int(), 0x20)
2599+
2600+ self.assertEqual(len(dtc.extended_data), 1)
2601+ extended_data = dtc.extended_data[0]
2602+
2603+ self.assertTrue(isinstance(extended_data, Dtc.ExtendedData))
2604+ self.assertEqual(extended_data.record_number, 0x33)
2605+
2606+ self.assertEqual(extended_data.raw_data, b'\x01\x02\x03\x04\x05')
2607+
2608+ def test_single_data(self):
2609+ for i in range(3):
2610+ request = self.conn.touserqueue.get(timeout=0.2)
2611+ self.assertEqual(request, b'\x19' + self.sb + b'\x33')
2612+ self.conn.fromuserqueue.put(b'\x59' + self.sb + b'\x33\x12\x34\x56\x20\x01\x02\x03\x04\x05')
2613+
2614+ def _test_single_data(self):
2615+ response = self.udsclient.get_dtc_extended_data_by_record_number(record_number = 0x33, data_size = 5)
2616+ self.assert_single_data_response(response)
2617+
2618+ response = self.udsclient.get_dtc_extended_data_by_record_number(record_number = 0x33, data_size = {0x123456 : 5})
2619+ self.assert_single_data_response(response)
2620+
2621+ self.udsclient.config['extended_data_size'] = {0x123456 : 5}
2622+ response = self.udsclient.get_dtc_extended_data_by_record_number(record_number = 0x33)
2623+ self.assert_single_data_response(response)
2624+
2625+ def test_single_data_missing_size(self):
2626+ for i in range(2):
2627+ self.wait_request_and_respond(b'\x59' + self.sb + b'\x33\x12\x34\x56\x20\x01\x02\x03\x04\x05')
2628+
2629+ def _test_single_data_missing_size(self):
2630+ with self.assertRaises(ConfigError):
2631+ self.udsclient.get_dtc_extended_data_by_record_number(record_number = 0x33, data_size = {0x111111 : 5}) # 123456 is not there!
2632+
2633+ with self.assertRaises(ConfigError):
2634+ self.udsclient.config['extended_data_size'] = {0x111111 : 5} # 123456 is not there!
2635+ self.udsclient.get_dtc_extended_data_by_record_number(record_number = 0x33)
2636+
2637+ def test_single_data_zeropadding_ok(self):
2638+ data = b'\x59' + self.sb + b'\x33\x12\x34\x56\x20\x01\x02\x03\x04\x05'
2639+ for i in range(8):
2640+ self.wait_request_and_respond(data + b'\x00' * (i+1))
2641+
2642+ def _test_single_data_zeropadding_ok(self):
2643+ self.udsclient.config['tolerate_zero_padding'] = True
2644+ for i in range(8):
2645+ response = self.udsclient.get_dtc_extended_data_by_record_number(record_number = 0x33, data_size = {0x123456 : 5})
2646+ self.assert_single_data_response(response)
2647+
2648+ def test_single_data_zeropadding_notok_exception(self):
2649+ data = b'\x59' + self.sb + b'\x33\x12\x34\x56\x20\x01\x02\x03\x04\x05'
2650+ for i in range(8):
2651+ self.wait_request_and_respond(data + b'\x00' * (i+1))
2652+
2653+ def _test_single_data_zeropadding_notok_exception(self):
2654+ self.udsclient.config['tolerate_zero_padding'] = False
2655+ for i in range(8):
2656+ with self.assertRaises(InvalidResponseException):
2657+ self.udsclient.get_dtc_extended_data_by_record_number(record_number = 0x33, data_size = {0x123456 : 5})
2658+
2659+
2660+ def test_single_data_zeropadding_notok_no_exception(self):
2661+ data = b'\x59' + self.sb + b'\x33\x12\x34\x56\x20\x01\x02\x03\x04\x05'
2662+ for i in range(8):
2663+ self.wait_request_and_respond(data + b'\x00' * (i+1))
2664+
2665+ def _test_single_data_zeropadding_notok_no_exception(self):
2666+ self.udsclient.config['tolerate_zero_padding'] = False
2667+ self.udsclient.config['exception_on_invalid_response'] = False
2668+ for i in range(8):
2669+ response = self.udsclient.get_dtc_extended_data_by_record_number(record_number = 0x33, data_size = {0x123456 : 5})
2670+ self.assertFalse(response.valid)
2671+
2672+
2673+ def test_double_data(self):
2674+ self.wait_request_and_respond(b'\x59' + self.sb + b'\x33\x12\x34\x56\x20\x01\x02\x03\x04\x05\x78\x9a\xbc\x30\xaa\xbb\xcc')
2675+
2676+ def _test_double_data(self):
2677+ response = self.udsclient.get_dtc_extended_data_by_record_number(record_number = 0x33, data_size = {0x123456 : 5, 0x789abc : 3})
2678+
2679+ self.assertEqual(len(response.service_data.dtcs), 2)
2680+ self.assertEqual(response.service_data.dtc_count, 2)
2681+
2682+ dtc = response.service_data.dtcs[0]
2683+
2684+ self.assertEqual(dtc.id, 0x123456)
2685+ self.assertEqual(dtc.status.get_byte_as_int(), 0x20)
2686+
2687+ self.assertEqual(len(dtc.extended_data), 1)
2688+
2689+ self.assertTrue(isinstance(dtc.extended_data[0], Dtc.ExtendedData))
2690+ self.assertEqual(dtc.extended_data[0].record_number, 0x33)
2691+ self.assertEqual(dtc.extended_data[0].raw_data, b'\x01\x02\x03\x04\x05')
2692+
2693+
2694+ dtc = response.service_data.dtcs[1]
2695+
2696+ self.assertEqual(dtc.id, 0x789abc)
2697+ self.assertEqual(dtc.status.get_byte_as_int(), 0x30)
2698+
2699+ self.assertEqual(len(dtc.extended_data), 1)
2700+
2701+ self.assertTrue(isinstance(dtc.extended_data[0], Dtc.ExtendedData))
2702+ self.assertEqual(dtc.extended_data[0].record_number, 0x33)
2703+ self.assertEqual(dtc.extended_data[0].raw_data, b'\xaa\xbb\xcc')
2704+
2705+
2706+ def test_no_data(self):
2707+ self.wait_request_and_respond(b'\x59' + self.sb + b'\x33\x12\x34\x56\x20')
2708+
2709+ def _test_no_data(self):
2710+ with self.assertRaises(InvalidResponseException):
2711+ self.udsclient.get_dtc_extended_data_by_record_number(record_number = 0x33, data_size = {0x123456 : 5})
2712+
2713+ def test_zero_sized_data(self):
2714+ self.wait_request_and_respond(b'\x59' + self.sb + b'\x33\x12\x34\x56\x20')
2715+
2716+ def _test_zero_sized_data(self):
2717+ response = self.udsclient.get_dtc_extended_data_by_record_number(record_number = 0x33, data_size = {0x123456 : 0})
2718+
2719+ self.assertEqual(len(response.service_data.dtcs), 1)
2720+ self.assertEqual(response.service_data.dtc_count, 1)
2721+ dtc = response.service_data.dtcs[0]
2722+
2723+ self.assertEqual(dtc.id, 0x123456)
2724+ self.assertEqual(dtc.status.get_byte_as_int(), 0x20)
2725+ self.assertEqual(len(dtc.extended_data), 1)
2726+
2727+ self.assertEqual(len(dtc.extended_data[0].raw_data), 0)
2728+
2729+ def test_zero_sized_data_zeropadding_ok(self):
2730+ data = b'\x59' + self.sb + b'\x33\x12\x34\x56\x20'
2731+ for i in range(8):
2732+ self.wait_request_and_respond(data + b'\x00' * (i+1) )
2733+
2734+ def _test_zero_sized_data_zeropadding_ok(self):
2735+ self.udsclient.config['tolerate_zero_padding'] = True
2736+ for i in range(8):
2737+ response = self.udsclient.get_dtc_extended_data_by_record_number(record_number = 0x33, data_size = {0x123456 : 0})
2738+
2739+ self.assertEqual(len(response.service_data.dtcs), 1)
2740+ self.assertEqual(response.service_data.dtc_count, 1)
2741+ dtc = response.service_data.dtcs[0]
2742+
2743+ self.assertEqual(dtc.id, 0x123456)
2744+ self.assertEqual(dtc.status.get_byte_as_int(), 0x20)
2745+ self.assertEqual(len(dtc.extended_data), 1)
2746+
2747+ self.assertEqual(len(dtc.extended_data[0].raw_data), 0)
2748+
2749+ def test_zero_sized_data_zeropadding_not_ok_exception(self):
2750+ data = b'\x59' + self.sb + b'\x33\x12\x34\x56\x20'
2751+ for i in range(8):
2752+ self.wait_request_and_respond(data + b'\x00' * (i+1) )
2753+
2754+ def _test_zero_sized_data_zeropadding_not_ok_exception(self):
2755+ self.udsclient.config['tolerate_zero_padding'] = False
2756+ for i in range(8):
2757+ with self.assertRaises(InvalidResponseException):
2758+ self.udsclient.get_dtc_extended_data_by_record_number(record_number = 0x33, data_size = {0x123456 : 0})
2759+
2760+ def invalid_length_no_response_server_task(self):
2761+ self.wait_request_and_respond(b'')
2762+ self.wait_request_and_respond(b'\x59')
2763+ self.wait_request_and_respond(b'\x59'+ self.sb)
2764+
2765+ def test_invalid_length_no_response_exception(self):
2766+ self.invalid_length_no_response_server_task()
2767+
2768+ def _test_invalid_length_no_response_exception(self):
2769+ for i in range(3):
2770+ with self.assertRaises(InvalidResponseException):
2771+ self.udsclient.get_dtc_extended_data_by_record_number(record_number = 0x33, data_size = {0x123456 : 5, 0x789abc : 3})
2772+
2773+ def test_invalid_length_no_response_no_exception(self):
2774+ self.invalid_length_no_response_server_task()
2775+
2776+ def _test_invalid_length_no_response_no_exception(self):
2777+ self.udsclient.config['exception_on_invalid_response'] = False
2778+ for i in range(3):
2779+ response = self.udsclient.get_dtc_extended_data_by_record_number(record_number = 0x33, data_size = {0x123456 : 5, 0x789abc : 3})
2780+ self.assertFalse(response.valid)
2781+
2782+
2783+ def invalid_length_incomplete_dtc_server_task(self):
2784+ self.wait_request_and_respond(b'\x59' + self.sb + b'\x33\x12')
2785+ self.wait_request_and_respond(b'\x59' + self.sb + b'\x33\x12\x34')
2786+ self.wait_request_and_respond(b'\x59' + self.sb + b'\x33\x12\x34\x56')
2787+
2788+ def test_invalid_length_incomplete_dtc_exception(self):
2789+ self.invalid_length_incomplete_dtc_server_task()
2790+
2791+ def _test_invalid_length_incomplete_dtc_exception(self):
2792+ for i in range(3):
2793+ with self.assertRaises(InvalidResponseException):
2794+ self.udsclient.get_dtc_extended_data_by_record_number(record_number = 0x33, data_size = {0x123456 : 5, 0x789abc : 3})
2795+
2796+ def test_invalid_length_incomplete_dtc_no_exception(self):
2797+ self.invalid_length_incomplete_dtc_server_task()
2798+
2799+ def _test_invalid_length_incomplete_dtc_no_exception(self):
2800+ self.udsclient.config['exception_on_invalid_response'] = False
2801+ for i in range(3):
2802+ response = self.udsclient.get_dtc_extended_data_by_record_number(record_number = 0x33, data_size = {0x123456 : 5, 0x789abc : 3})
2803+ self.assertFalse(response.valid)
2804+
2805+ def invalid_length_missing_data_server_task(self):
2806+ self.wait_request_and_respond(b'\x59' + self.sb + b'\x33\x12\x34\x56\x20')
2807+ self.wait_request_and_respond(b'\x59' + self.sb + b'\x33\x12\x34\x56\x20\x01')
2808+ self.wait_request_and_respond(b'\x59' + self.sb + b'\x33\x12\x34\x56\x20\x01\x02')
2809+ self.wait_request_and_respond(b'\x59' + self.sb + b'\x33\x12\x34\x56\x20\x01\x02\x03')
2810+ self.wait_request_and_respond(b'\x59' + self.sb + b'\x33\x12\x34\x56\x20\x01\x02\x03\x04')
2811+
2812+ def test_invalid_length_missing_data_exception(self):
2813+ self.invalid_length_missing_data_server_task()
2814+
2815+ def _test_invalid_length_missing_data_exception(self):
2816+ for i in range(5):
2817+ with self.assertRaises(InvalidResponseException):
2818+ self.udsclient.get_dtc_extended_data_by_record_number(record_number = 0x33, data_size = {0x123456 : 5, 0x789abc : 3})
2819+
2820+ def test_invalid_length_missing_data_no_exception(self):
2821+ self.invalid_length_missing_data_server_task()
2822+
2823+ def _test_invalid_length_missing_data_no_exception(self):
2824+ self.udsclient.config['exception_on_invalid_response'] = False
2825+ for i in range(5):
2826+ response = self.udsclient.get_dtc_extended_data_by_record_number(record_number = 0x33, data_size = {0x123456 : 5, 0x789abc : 3})
2827+ self.assertFalse(response.valid)
2828+
2829+ def test_wrong_subfn_response_exception(self):
2830+ self.wait_request_and_respond(b'\x59' + self.badsb + b'\x33\x12\x34\x56\x20\x01\x02\x03\x04\x05')
2831+
2832+ def _test_wrong_subfn_response_exception(self):
2833+ with self.assertRaises(UnexpectedResponseException):
2834+ self.udsclient.get_dtc_extended_data_by_record_number(record_number = 0x33)
2835+
2836+ def test_wrong_subfn_response_no_exception(self):
2837+ self.wait_request_and_respond(b'\x59' + self.badsb + b'\x33\x12\x34\x56\x20\x01\x02\x03\x04\x05')
2838+
2839+ def _test_wrong_subfn_response_no_exception(self):
2840+ self.udsclient.config['exception_on_unexpected_response'] = False
2841+ response = self.udsclient.get_dtc_extended_data_by_record_number(record_number = 0x33, data_size = {0x123456 : 5, 0x789abc : 3})
2842+ self.assertTrue(response.valid)
2843+ self.assertTrue(response.unexpected)
2844+
2845+ def test_wrong_record_number_response_exception(self):
2846+ self.wait_request_and_respond(b'\x59' + self.sb + b'\x34\x12\x34\x56\x20\x01\x02\x03\x04\x05')
2847+
2848+ def _test_wrong_record_number_response_exception(self):
2849+ with self.assertRaises(UnexpectedResponseException):
2850+ self.udsclient.get_dtc_extended_data_by_record_number(record_number = 0x33, data_size = {0x123456 : 5, 0x789abc : 3})
2851+
2852+ def test_duplicate_dtc(self):
2853+ self.wait_request_and_respond(b'\x59' + self.sb + b'\x33\x12\x34\x56\x20\x01\x02\x03\x04\x05\x12\x34\x56\x20\x01\x02\x03\x04\x05')
2854+
2855+ def _test_duplicate_dtc(self):
2856+ with self.assertRaises(InvalidResponseException):
2857+ self.udsclient.get_dtc_extended_data_by_record_number(record_number = 0x33, data_size = {0x123456 : 5, 0x789abc : 3})
2858+
2859+ def test_wrong_service_response_exception(self):
2860+ self.wait_request_and_respond(b'\x6F' + self.sb + b'\x33\x12\x34\x56\x20\x01\x02\x03\x04\x05')
2861+
2862+ def _test_wrong_service_response_exception(self):
2863+ with self.assertRaises(UnexpectedResponseException):
2864+ self.udsclient.get_dtc_extended_data_by_record_number(record_number = 0x33, data_size = {0x123456 : 5, 0x789abc : 3})
2865+
2866+ def test_oob_values(self):
2867+ pass
2868+
2869+ def _test_oob_values(self):
2870+ with self.assertRaises(ValueError):
2871+ self.udsclient.get_dtc_extended_data_by_record_number(record_number = -1, data_size=5)
2872+
2873+ with self.assertRaises(ValueError):
2874+ self.udsclient.get_dtc_extended_data_by_record_number(record_number = 0xF0, data_size=5) # Limited to 0xEF
2875+
2876+ with self.assertRaises(ValueError):
2877+ self.udsclient.get_dtc_extended_data_by_record_number(record_number = 'asd', data_size=5)
2878+
2879+ with self.assertRaises(NotImplementedError):
2880+ self.udsclient.set_config('standard_version', 2013)
2881+ self.udsclient.get_dtc_extended_data_by_record_number(record_number = 0x33, data_size=5)
2882+ self.udsclient.set_config('standard_version', latest_standard)
2883+
2884+ def test_oob_values_data_size(self): # validation is made at interpret_response
2885+ self.wait_request_and_respond(b'\x59' + self.sb + b'\x12\x34\x56\x20\x99\x01\x02\x03')
2886+ self.wait_request_and_respond(b'\x59' + self.sb + b'\x12\x34\x56\x20\x99\x01\x02\x03')
2887+ self.wait_request_and_respond(b'\x59' + self.sb + b'\x12\x34\x56\x20\x99\x01\x02\x03')
2888+
2889+ def _test_oob_values_data_size(self):
2890+ with self.assertRaises(ValueError):
2891+ self.udsclient.get_dtc_extended_data_by_record_number(record_number = 0x33, data_size = -1)
2892+
2893+ with self.assertRaises(ValueError):
2894+ self.udsclient.get_dtc_extended_data_by_record_number(record_number = 0x33, data_size = {0x123456 : -1})
2895+
2896+ with self.assertRaises(ValueError):
2897+ self.udsclient.config['extended_data_size'] = {0x123456 : -1}
2898+ self.udsclient.get_dtc_extended_data_by_record_number(record_number = 0x33)
2899+
25872900
25882901class TestReportUserDefMemoryDTCByStatusMask(ClientServerTest): # Subfn = 0x17
25892902 # Almost identical copy of duplicate of GenericTestStatusMaskRequest_DtcAndStatusMaskResponse
@@ -2860,7 +3173,6 @@ def _test_oob_value(self):
28603173 self.udsclient.set_config('standard_version', latest_standard)
28613174
28623175
2863-
28643176class TestReportUserDefMemoryDTCSnapshotRecordByDTCNumber(ClientServerTest): # Subfn = 0x18
28653177
28663178 class Codec4711(DidCodec):
@@ -3301,8 +3613,6 @@ def _test_oob_values(self):
33013613 self.udsclient.set_config('standard_version', latest_standard)
33023614
33033615
3304-
3305-
33063616class TestTeportUserDefMemoryDTCExtDataRecordByDTCNumber(ClientServerTest): # Subfn = 0x19
33073617 sb = struct.pack('B', 0x19)
33083618 badsb = struct.pack('B', 0x19+1)
0 commit comments