Skip to content

Commit fcbae0b

Browse files
committed
Added reportUserDefMemoryDTCExtDataRecordByDTCNumber
1 parent 8173727 commit fcbae0b

File tree

4 files changed

+394
-7
lines changed

4 files changed

+394
-7
lines changed

doc/source/udsoncan/client.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -400,6 +400,7 @@ Methods by services
400400
.. automethod:: udsoncan.client.Client.get_user_defined_dtc_snapshot_by_dtc_number
401401
.. automethod:: udsoncan.client.Client.get_dtc_snapshot_by_record_number
402402
.. automethod:: udsoncan.client.Client.get_dtc_extended_data_by_dtc_number
403+
.. automethod:: udsoncan.client.Client.get_user_defined_dtc_extended_data_by_dtc_number
403404
.. automethod:: udsoncan.client.Client.get_mirrormemory_dtc_extended_data_by_dtc_number
404405

405406

test/client/test_read_dtc_information.py

Lines changed: 339 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3299,3 +3299,342 @@ def _test_oob_values(self):
32993299
self.udsclient.set_config('standard_version', 2013)
33003300
self.udsclient.get_user_defined_dtc_snapshot_by_dtc_number(dtc=0x123456, record_number=0x02, memory_selection = 0x99)
33013301
self.udsclient.set_config('standard_version', latest_standard)
3302+
3303+
3304+
3305+
3306+
class TestTeportUserDefMemoryDTCExtDataRecordByDTCNumber(ClientServerTest): # Subfn = 0x19
3307+
sb = struct.pack('B', 0x19)
3308+
badsb = struct.pack('B', 0x19+1)
3309+
3310+
def assert_single_data_response(self, response):
3311+
self.assertEqual(response.service_data.memory_selection_echo, 0x88)
3312+
self.assertEqual(len(response.service_data.dtcs), 1)
3313+
self.assertEqual(response.service_data.dtc_count, 1)
3314+
3315+
dtc = response.service_data.dtcs[0]
3316+
3317+
self.assertEqual(dtc.id, 0x123456)
3318+
self.assertEqual(dtc.status.get_byte_as_int(), 0x20)
3319+
3320+
self.assertEqual(len(dtc.extended_data), 1)
3321+
extended_data = dtc.extended_data[0]
3322+
3323+
self.assertTrue(isinstance(extended_data, Dtc.ExtendedData))
3324+
self.assertEqual(extended_data.record_number, 0x99)
3325+
3326+
self.assertEqual(extended_data.raw_data, b'\x01\x02\x03\x04\x05')
3327+
3328+
def test_single_data(self):
3329+
request = self.conn.touserqueue.get(timeout=0.2)
3330+
self.assertEqual(request, b'\x19' + self.sb + b'\x12\x34\x56\x99\x88')
3331+
self.conn.fromuserqueue.put(b'\x59' + self.sb + b'\x88\x12\x34\x56\x20\x99\x01\x02\x03\x04\x05')
3332+
3333+
def _test_single_data(self):
3334+
3335+
response = self.udsclient.get_user_defined_dtc_extended_data_by_dtc_number(dtc=0x123456, record_number=0x99, data_size=5, memory_selection=0x88)
3336+
self.assert_single_data_response(response)
3337+
3338+
def test_single_data_instance_param(self):
3339+
request = self.conn.touserqueue.get(timeout=0.2)
3340+
self.assertEqual(request, b'\x19' + self.sb + b'\x12\x34\x56\x99\x88')
3341+
self.conn.fromuserqueue.put(b'\x59' + self.sb + b'\x88\x12\x34\x56\x20\x99\x01\x02\x03\x04\x05')
3342+
3343+
def _test_single_data_instance_param(self):
3344+
response = self.udsclient.get_user_defined_dtc_extended_data_by_dtc_number(dtc=Dtc(0x123456), record_number=0x99, data_size=5, memory_selection=0x88)
3345+
self.assert_single_data_response(response)
3346+
3347+
def test_single_data_config_size(self):
3348+
self.wait_request_and_respond(b'\x59' + self.sb + b'\x88\x12\x34\x56\x20\x99\x01\x02\x03\x04\x05')
3349+
3350+
def _test_single_data_config_size(self):
3351+
self.udsclient.config['extended_data_size'] = {0x123456 : 5}
3352+
response = self.udsclient.get_user_defined_dtc_extended_data_by_dtc_number(dtc=0x123456, record_number=0x99, memory_selection=0x88)
3353+
self.assert_single_data_response(response)
3354+
3355+
def test_single_data_zeropadding_ok(self):
3356+
data = b'\x59' + self.sb + b'\x88\x12\x34\x56\x20\x99\x01\x02\x03\x04\x05'
3357+
for i in range(8):
3358+
self.wait_request_and_respond(data + b'\x00' * (i+1))
3359+
3360+
def _test_single_data_zeropadding_ok(self):
3361+
self.udsclient.config['tolerate_zero_padding'] = True
3362+
for i in range(8):
3363+
response = self.udsclient.get_user_defined_dtc_extended_data_by_dtc_number(dtc=0x123456, record_number=0x99, data_size=5, memory_selection=0x88)
3364+
self.assert_single_data_response(response)
3365+
3366+
def test_single_data_zeropadding_notok_exception(self):
3367+
data = b'\x59' + self.sb + b'\x88\x12\x34\x56\x20\x99\x01\x02\x03\x04\x05'
3368+
for i in range(8):
3369+
self.wait_request_and_respond(data + b'\x00' * (i+1))
3370+
3371+
def _test_single_data_zeropadding_notok_exception(self):
3372+
self.udsclient.config['tolerate_zero_padding'] = False
3373+
for i in range(8):
3374+
with self.assertRaises(InvalidResponseException):
3375+
self.udsclient.get_user_defined_dtc_extended_data_by_dtc_number(dtc=0x123456, record_number=0x99, data_size=5, memory_selection=0x88)
3376+
3377+
def test_single_data_zeropadding_notok_no_exception(self):
3378+
data = b'\x59' + self.sb + b'\x88\x12\x34\x56\x20\x99\x01\x02\x03\x04\x05'
3379+
for i in range(8):
3380+
self.wait_request_and_respond(data + b'\x00' * (i+1))
3381+
3382+
def _test_single_data_zeropadding_notok_no_exception(self):
3383+
self.udsclient.config['tolerate_zero_padding'] = False
3384+
self.udsclient.config['exception_on_invalid_response'] = False
3385+
for i in range(8):
3386+
response = self.udsclient.get_user_defined_dtc_extended_data_by_dtc_number(dtc=0x123456, record_number=0x99, data_size=5, memory_selection=0x88)
3387+
self.assertFalse(response.valid)
3388+
3389+
def test_double_data(self):
3390+
self.wait_request_and_respond(b'\x59' + self.sb + b'\x88\x12\x34\x56\x20\x10\x01\x02\x03\x11\x04\x05\x06')
3391+
3392+
def _test_double_data(self):
3393+
response = self.udsclient.get_user_defined_dtc_extended_data_by_dtc_number(dtc=0x123456, data_size=3, memory_selection=0x88)
3394+
3395+
self.assertEqual(response.service_data.memory_selection_echo, 0x88)
3396+
self.assertEqual(len(response.service_data.dtcs), 1)
3397+
self.assertEqual(response.service_data.dtc_count, 1)
3398+
3399+
dtc = response.service_data.dtcs[0]
3400+
3401+
self.assertEqual(dtc.id, 0x123456)
3402+
self.assertEqual(dtc.status.get_byte_as_int(), 0x20)
3403+
3404+
self.assertEqual(len(dtc.extended_data), 2)
3405+
3406+
self.assertTrue(isinstance(dtc.extended_data[0], Dtc.ExtendedData))
3407+
self.assertEqual(dtc.extended_data[0].record_number, 0x10)
3408+
self.assertEqual(dtc.extended_data[0].raw_data, b'\x01\x02\x03')
3409+
3410+
self.assertTrue(isinstance(dtc.extended_data[1], Dtc.ExtendedData))
3411+
self.assertEqual(dtc.extended_data[1].record_number, 0x11)
3412+
self.assertEqual(dtc.extended_data[1].raw_data, b'\x04\x05\x06')
3413+
3414+
3415+
def test_no_data(self):
3416+
self.wait_request_and_respond(b'\x59' + self.sb + b'\x88\x12\x34\x56\x20')
3417+
3418+
def _test_no_data(self):
3419+
response = self.udsclient.get_user_defined_dtc_extended_data_by_dtc_number(dtc=0x123456, data_size=3, memory_selection=0x88)
3420+
3421+
self.assertEqual(len(response.service_data.dtcs), 1)
3422+
self.assertEqual(response.service_data.dtc_count, 1)
3423+
dtc = response.service_data.dtcs[0]
3424+
3425+
self.assertEqual(dtc.id, 0x123456)
3426+
self.assertEqual(dtc.status.get_byte_as_int(), 0x20)
3427+
self.assertEqual(len(dtc.extended_data), 0)
3428+
3429+
def test_no_data_zeropadding_ok(self):
3430+
data = b'\x59' + self.sb + b'\x88\x12\x34\x56\x20'
3431+
for i in range(8):
3432+
self.wait_request_and_respond(data + b'\x00' * (i+1) )
3433+
3434+
def _test_no_data_zeropadding_ok(self):
3435+
self.udsclient.config['tolerate_zero_padding'] = True
3436+
for i in range(8):
3437+
response = self.udsclient.get_user_defined_dtc_extended_data_by_dtc_number(dtc=0x123456, data_size=3, memory_selection=0x88)
3438+
3439+
self.assertEqual(response.service_data.memory_selection_echo, 0x88)
3440+
self.assertEqual(len(response.service_data.dtcs), 1)
3441+
self.assertEqual(response.service_data.dtc_count, 1)
3442+
dtc = response.service_data.dtcs[0]
3443+
3444+
self.assertEqual(dtc.id, 0x123456)
3445+
self.assertEqual(dtc.status.get_byte_as_int(), 0x20)
3446+
self.assertEqual(len(dtc.extended_data), 0)
3447+
3448+
def test_no_data_zeropadding_not_ok_exception(self):
3449+
data = b'\x59' + self.sb + b'\x88\x12\x34\x56\x20'
3450+
for i in range(8):
3451+
self.wait_request_and_respond(data + b'\x00' * (i+1) )
3452+
3453+
def _test_no_data_zeropadding_not_ok_exception(self):
3454+
self.udsclient.config['tolerate_zero_padding'] = False
3455+
for i in range(8):
3456+
with self.assertRaises(InvalidResponseException):
3457+
self.udsclient.get_user_defined_dtc_extended_data_by_dtc_number(dtc=0x123456, data_size=3, memory_selection=0x88)
3458+
3459+
def test_no_data_zeropadding_not_ok_no_exception(self):
3460+
data = b'\x59' + self.sb + b'\x88\x12\x34\x56\x20'
3461+
for i in range(8):
3462+
self.wait_request_and_respond(data + b'\x00' * (i+1) )
3463+
3464+
def _test_no_data_zeropadding_not_ok_no_exception(self):
3465+
self.udsclient.config['tolerate_zero_padding'] = False
3466+
self.udsclient.config['exception_on_invalid_response'] = False
3467+
for i in range(8):
3468+
response = self.udsclient.get_user_defined_dtc_extended_data_by_dtc_number(dtc=0x123456, data_size=3, memory_selection=0x88)
3469+
self.assertFalse(response.valid)
3470+
3471+
def invalid_length_no_response_server_task(self):
3472+
self.wait_request_and_respond(b'')
3473+
self.wait_request_and_respond(b'\x59')
3474+
3475+
def test_invalid_length_no_response_exception(self):
3476+
self.invalid_length_no_response_server_task()
3477+
3478+
def _test_invalid_length_no_response_exception(self):
3479+
for i in range(2):
3480+
with self.assertRaises(InvalidResponseException):
3481+
self.udsclient.get_user_defined_dtc_extended_data_by_dtc_number(dtc=0x123456, data_size=3, record_number=0x99, memory_selection=0x88)
3482+
3483+
def test_invalid_length_no_response_no_exception(self):
3484+
self.invalid_length_no_response_server_task()
3485+
3486+
def _test_invalid_length_no_response_no_exception(self):
3487+
self.udsclient.config['exception_on_invalid_response'] = False
3488+
for i in range(2):
3489+
response = self.udsclient.get_user_defined_dtc_extended_data_by_dtc_number(dtc=0x123456, data_size=3, record_number=0x99, memory_selection=0x88)
3490+
self.assertFalse(response.valid)
3491+
3492+
def invalid_length_incomplete_dtc_server_task(self):
3493+
self.wait_request_and_respond(b'\x59' + self.sb)
3494+
self.wait_request_and_respond(b'\x59' + self.sb + b'\x88')
3495+
self.wait_request_and_respond(b'\x59' + self.sb + b'\x88\x12')
3496+
self.wait_request_and_respond(b'\x59' + self.sb + b'\x88\x12\x34')
3497+
self.wait_request_and_respond(b'\x59' + self.sb + b'\x88\x12\x34\x56')
3498+
3499+
def test_invalid_length_incomplete_dtc_exception(self):
3500+
self.invalid_length_incomplete_dtc_server_task()
3501+
3502+
def _test_invalid_length_incomplete_dtc_exception(self):
3503+
for i in range(5):
3504+
with self.assertRaises(InvalidResponseException):
3505+
self.udsclient.get_user_defined_dtc_extended_data_by_dtc_number(dtc=0x123456, data_size=3, record_number=0x99, memory_selection=0x88)
3506+
3507+
def test_invalid_length_incomplete_dtc_no_exception(self):
3508+
self.invalid_length_incomplete_dtc_server_task()
3509+
3510+
def _test_invalid_length_incomplete_dtc_no_exception(self):
3511+
self.udsclient.config['exception_on_invalid_response'] = False
3512+
for i in range(5):
3513+
response = self.udsclient.get_user_defined_dtc_extended_data_by_dtc_number(dtc=0x123456, data_size=3, record_number=0x99, memory_selection=0x88)
3514+
self.assertFalse(response.valid)
3515+
3516+
def invalid_length_missing_data_server_task(self):
3517+
self.wait_request_and_respond(b'\x59' + self.sb + b'\x88\x12\x34\x56\x20\x99')
3518+
self.wait_request_and_respond(b'\x59' + self.sb + b'\x88\x12\x34\x56\x20\x99\x01')
3519+
self.wait_request_and_respond(b'\x59' + self.sb + b'\x88\x12\x34\x56\x20\x99\x01\x02')
3520+
3521+
def test_invalid_length_missing_data_exception(self):
3522+
self.invalid_length_missing_data_server_task()
3523+
3524+
def _test_invalid_length_missing_data_exception(self):
3525+
for i in range(3):
3526+
with self.assertRaises(InvalidResponseException):
3527+
self.udsclient.get_user_defined_dtc_extended_data_by_dtc_number(dtc=0x123456, data_size=3, record_number=0x99, memory_selection=0x88)
3528+
3529+
def test_invalid_length_missing_data_no_exception(self):
3530+
self.invalid_length_missing_data_server_task()
3531+
3532+
def _test_invalid_length_missing_data_no_exception(self):
3533+
self.udsclient.config['exception_on_invalid_response'] = False
3534+
for i in range(3):
3535+
response = self.udsclient.get_user_defined_dtc_extended_data_by_dtc_number(dtc=0x123456, data_size=3, record_number=0x99, memory_selection=0x88)
3536+
self.assertFalse(response.valid)
3537+
3538+
def test_wrong_subfn_response_exception(self):
3539+
self.wait_request_and_respond(b'\x59' + self.badsb + b'\x88\x12\x34\x56\x20\x99\x01\x02\x03')
3540+
3541+
def _test_wrong_subfn_response_exception(self):
3542+
with self.assertRaises(UnexpectedResponseException):
3543+
self.udsclient.get_user_defined_dtc_extended_data_by_dtc_number(dtc=0x123456, data_size=3, record_number=0x99, memory_selection=0x88)
3544+
3545+
def test_wrong_subfn_response_no_exception(self):
3546+
self.wait_request_and_respond(b'\x59' + self.badsb + b'\x88\x12\x34\x56\x20\x99\x01\x02\x03')
3547+
3548+
def _test_wrong_subfn_response_no_exception(self):
3549+
self.udsclient.config['exception_on_unexpected_response'] = False
3550+
response = self.udsclient.get_user_defined_dtc_extended_data_by_dtc_number(dtc=0x123456, data_size=3, record_number=0x99, memory_selection=0x88)
3551+
self.assertTrue(response.valid)
3552+
self.assertTrue(response.unexpected)
3553+
3554+
def test_wrong_memory_selection_response_exception(self):
3555+
self.wait_request_and_respond(b'\x59' + self.sb + b'\x89\x12\x34\x56\x20\x99\x01\x02\x03')
3556+
3557+
def _test_wrong_memory_selection_response_exception(self):
3558+
with self.assertRaises(UnexpectedResponseException):
3559+
self.udsclient.get_user_defined_dtc_extended_data_by_dtc_number(dtc=0x123456, data_size=3, record_number=0x99, memory_selection=0x88)
3560+
3561+
def test_wrong_memory_selection_response_no_exception(self):
3562+
self.wait_request_and_respond(b'\x59' + self.sb + b'\x89\x12\x34\x56\x20\x99\x01\x02\x03')
3563+
3564+
def _test_wrong_memory_selection_response_no_exception(self):
3565+
self.udsclient.config['exception_on_unexpected_response'] = False
3566+
response = self.udsclient.get_user_defined_dtc_extended_data_by_dtc_number(dtc=0x123456, data_size=3, record_number=0x99, memory_selection=0x88)
3567+
self.assertTrue(response.valid)
3568+
self.assertTrue(response.unexpected)
3569+
3570+
def test_wrong_record_number_response_exception(self):
3571+
self.wait_request_and_respond(b'\x59' + self.sb + b'\x88\x12\x34\x56\x20\x98\x01\x02\x03')
3572+
3573+
def _test_wrong_record_number_response_exception(self):
3574+
with self.assertRaises(UnexpectedResponseException):
3575+
self.udsclient.get_user_defined_dtc_extended_data_by_dtc_number(dtc=0x123456, data_size=3, record_number=0x99, memory_selection=0x88)
3576+
3577+
def test_wrong_record_number_response_no_exception(self):
3578+
self.wait_request_and_respond(b'\x59' + self.sb + b'\x88\x12\x34\x56\x20\x98\x01\x02\x03')
3579+
3580+
def _test_wrong_record_number_response_no_exception(self):
3581+
self.udsclient.config['exception_on_unexpected_response'] = False
3582+
response = self.udsclient.get_user_defined_dtc_extended_data_by_dtc_number(dtc=0x123456, data_size=3, record_number=0x99, memory_selection=0x88)
3583+
self.assertTrue(response.valid)
3584+
self.assertTrue(response.unexpected)
3585+
3586+
def test_wrong_service_response_exception(self):
3587+
self.wait_request_and_respond(b'\x6F' + self.sb + b'\x88\x12\x34\x56\x20\x98\x01\x02\x03')
3588+
3589+
def _test_wrong_service_response_exception(self):
3590+
with self.assertRaises(UnexpectedResponseException):
3591+
self.udsclient.get_user_defined_dtc_extended_data_by_dtc_number(dtc=0x123456, data_size=3, record_number=0x99, memory_selection=0x88)
3592+
3593+
def test_wrong_service_response_no_exception(self):
3594+
self.wait_request_and_respond(b'\x6F' + self.sb + b'\x88\x12\x34\x56\x20\x98\x01\x02\x03')
3595+
3596+
def _test_wrong_service_response_no_exception(self):
3597+
self.udsclient.config['exception_on_unexpected_response'] = False
3598+
response = self.udsclient.get_user_defined_dtc_extended_data_by_dtc_number(dtc=0x123456, data_size=3, record_number=0x99, memory_selection=0x88)
3599+
self.assertTrue(response.valid)
3600+
self.assertTrue(response.unexpected)
3601+
3602+
def test_oob_values(self):
3603+
pass
3604+
3605+
def _test_oob_values(self):
3606+
with self.assertRaises(ValueError):
3607+
self.udsclient.get_user_defined_dtc_extended_data_by_dtc_number(dtc=-1, data_size=3, record_number=0x99, memory_selection=0x88)
3608+
3609+
with self.assertRaises(ValueError):
3610+
self.udsclient.get_user_defined_dtc_extended_data_by_dtc_number(dtc=0x1000000, data_size=3, record_number=0x99, memory_selection=0x88)
3611+
3612+
with self.assertRaises(ValueError):
3613+
self.udsclient.get_user_defined_dtc_extended_data_by_dtc_number(dtc=0x123456, data_size=3, record_number=-1, memory_selection=0x88)
3614+
3615+
with self.assertRaises(ValueError):
3616+
self.udsclient.get_user_defined_dtc_extended_data_by_dtc_number(dtc=0x123456, data_size=3, record_number=0x100, memory_selection=0x88)
3617+
3618+
with self.assertRaises(ValueError):
3619+
self.udsclient.get_user_defined_dtc_extended_data_by_dtc_number(dtc=0x123456, data_size=3, record_number=0x99, memory_selection=-1)
3620+
3621+
with self.assertRaises(ValueError):
3622+
self.udsclient.get_user_defined_dtc_extended_data_by_dtc_number(dtc=0x123456, data_size=3, record_number=0x99, memory_selection=0x100)
3623+
3624+
3625+
with self.assertRaises(NotImplementedError):
3626+
self.udsclient.set_config('standard_version', 2013)
3627+
self.udsclient.get_user_defined_dtc_extended_data_by_dtc_number(dtc=0x123456, data_size=3, record_number=0x99, memory_selection=0x88)
3628+
self.udsclient.set_config('standard_version', latest_standard)
3629+
3630+
def test_oob_values_data_size(self): # validation is made at interpret_response
3631+
self.wait_request_and_respond(b'\x59' + self.sb + b'\x88\x12\x34\x56\x20\x99\x01\x02\x03')
3632+
self.wait_request_and_respond(b'\x59' + self.sb + b'\x88\x12\x34\x56\x20\x99\x01\x02\x03')
3633+
3634+
def _test_oob_values_data_size(self):
3635+
with self.assertRaises(ValueError):
3636+
self.udsclient.get_user_defined_dtc_extended_data_by_dtc_number(dtc=0x123456, data_size=-1, record_number=0x99, memory_selection=0x88)
3637+
3638+
with self.assertRaises(ValueError):
3639+
self.udsclient.config['extended_data_size'] = {0x123456 : -1}
3640+
self.udsclient.get_user_defined_dtc_extended_data_by_dtc_number(dtc=0x123456, record_number=0x99, memory_selection=0x88)

0 commit comments

Comments
 (0)