def _test_read_file_extra_bytes_response_zero_padding_not_ok(self): self.udsclient.config['tolerate_zero_padding'] = False with self.assertRaises(InvalidResponseException): self.udsclient.read_file("my_file.txt", dfi= DataFormatIdentifier(compression=5, encryption=2))
def _test_read_file_invalid_length(self): for i in range(11): with self.assertRaises(InvalidResponseException): self.udsclient.read_file("my_file.txt", dfi= DataFormatIdentifier(compression=5, encryption=2))
def _test_read_file_extra_bytes_response(self): with self.assertRaises(InvalidResponseException): self.udsclient.read_file("my_file.txt", dfi= DataFormatIdentifier(compression=5, encryption=2))
def _test_read_file_bad_moop_echo_no_exception(self): self.udsclient.config['exception_on_unexpected_response'] = False response = self.udsclient.read_file("my_file.txt", dfi= DataFormatIdentifier(compression=5, encryption=2)) self.assertTrue(response.valid) self.assertTrue(response.positive) self.assertTrue(response.unexpected)
def _test_read_file_zerolen_length_fsodipl(self): with self.assertRaises(InvalidResponseException): self.udsclient.read_file("my_file.txt", dfi= DataFormatIdentifier(compression=5, encryption=2))
def interpret_response(cls, response, tolerate_zero_padding=True): """ Populates the response ``service_data`` property with an instance of :class:`RequestFileTransfer.ResponseData<udsoncan.services.RequestFileTransfer.ResponseData>` :param response: The received response to interpret :type response: :ref:`Response<Response>` :raises InvalidResponseException: If length of ``response.data`` is too short or payload does not respect ISO-14229 specifications :raises NotImplementedError: If the MaxNumberOfBlock or fileSizeUncompressedOrDirInfoLength value is encoded over more than 8 bytes. """ from udsoncan import Filesize, DataFormatIdentifier response.service_data = cls.ResponseData() if len(response.data) < 1: raise InvalidResponseException( response, 'Response payload must be at least 1 byte long') response.service_data.moop_echo = int(response.data[0]) has_lfid = response.service_data.moop_echo in [ cls.ModeOfOperation.AddFile, cls.ModeOfOperation.ReplaceFile, cls.ModeOfOperation.ReadFile, cls.ModeOfOperation.ReadDir ] has_dfi = response.service_data.moop_echo in [ cls.ModeOfOperation.AddFile, cls.ModeOfOperation.ReplaceFile, cls.ModeOfOperation.ReadFile, cls.ModeOfOperation.ReadDir ] has_filesize_length = response.service_data.moop_echo in [ cls.ModeOfOperation.ReadFile, cls.ModeOfOperation.ReadDir ] has_uncompressed_filesize = response.service_data.moop_echo in [ cls.ModeOfOperation.ReadFile, cls.ModeOfOperation.ReadDir ] has_compressed_filesize = response.service_data.moop_echo in [ cls.ModeOfOperation.ReadFile ] cursor = 1 if has_lfid: if len(response.data) < 2: raise InvalidResponseException( response, 'Response payload must be at least 2 byte long for Mode of operation %d' % response.service_data.moop_echo) lfid = int(response.data[1]) cursor = 2 if lfid > 8: raise NotImplementedError( 'This client does not support number bigger than %d bits, but MaxNumberOfBlock is encoded on %d bits' % ((8 * 8), (lfid * 8))) if lfid == 0: raise InvalidResponseException( response, 'Received a MaxNumberOfBlockLength of 0 which is impossible' ) if len(response.data) < 2 + lfid: raise InvalidResponseException( response, 'Response payload says that MaxNumberOfBlock is encoded on %d bytes, but only %d bytes are present' % (lfid, (len(response.data) - 2))) todecode = bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') for i in range(1, lfid + 1): todecode[-i] = response.data[cursor + lfid - i] response.service_data.max_length = struct.unpack('>q', todecode)[0] cursor += lfid if has_dfi: if len(response.data) < cursor + 1: raise InvalidResponseException( response, 'Missing DataFormatIdentifier in received response') response.service_data.dfi = DataFormatIdentifier.from_byte( response.data[cursor]) cursor += 1 dfi = response.service_data.dfi.get_byte_as_int() if response.service_data.moop_echo == cls.ModeOfOperation.ReadDir and dfi != 0: raise InvalidResponseException( response, 'DataFormatIdentifier for ReadDir can only be 0x00 as per ISO-14229, but its value was set to 0x%02x' % (dfi)) if has_filesize_length: if len(response.data) < cursor + 2: raise InvalidResponseException( response, 'Missing or incomplete FileSizeOrDirInfoParameterLength in received response' ) fsodipl = struct.unpack('>H', response.data[cursor:cursor + 2])[0] cursor += 2 if fsodipl > 8: raise NotImplementedError( response, 'This client does not support number bigger than %d bits, but FileSizeOrDirInfoLength is encoded on %d bits' % ((8 * 8), (fsodipl * 8))) if fsodipl == 0: raise InvalidResponseException( response, 'Received a FileSizeOrDirInfoParameterLength of 0 which is impossible' ) if has_uncompressed_filesize: if len(response.data) < cursor + fsodipl: raise InvalidResponseException( response, 'Missing or incomplete fileSizeUncompressedOrDirInfoLength in received response' ) todecode = bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') for i in range(1, lfid + 1): todecode[-i] = response.data[cursor + fsodipl - i] uncompressed_size = struct.unpack('>q', todecode)[0] cursor += fsodipl else: uncompressed_size = None if has_compressed_filesize: if len(response.data) < cursor + fsodipl: raise InvalidResponseException( response, 'Missing or incomplete fileSizeCompressed in received response' ) todecode = bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00') for i in range(1, lfid + 1): todecode[-i] = response.data[cursor + fsodipl - i] compressed_size = struct.unpack('>q', todecode)[0] cursor += fsodipl else: compressed_size = None if has_uncompressed_filesize and response.service_data.moop_echo == cls.ModeOfOperation.ReadDir: response.service_data.dirinfo_length = uncompressed_size else: if has_uncompressed_filesize or has_compressed_filesize: response.service_data.filesize = Filesize( uncompressed=uncompressed_size, compressed=compressed_size) if len(response.data) > cursor: if response.data[cursor:] == b'\x00' * ( len(response.data) - cursor) and tolerate_zero_padding: pass else: raise InvalidResponseException( response, 'Response payload has extra data that has no meaning') response.service_data = response.service_data
def _test_read_file_bad_moop_echo(self): with self.assertRaises(UnexpectedResponseException): self.udsclient.read_file("my_file.txt", dfi= DataFormatIdentifier(compression=5, encryption=2))
def _test_replace_file_extra_bytes_response_zero_padding_not_ok(self): self.udsclient.config['tolerate_zero_padding'] = False with self.assertRaises(InvalidResponseException): self.udsclient.replace_file("my_file.txt", dfi= DataFormatIdentifier(compression=5, encryption=2), filesize = Filesize(uncompressed=0x222, compressed=0x111, width=4))
def _test_read_file_negative_response(self): with self.assertRaises(NegativeResponseException): self.udsclient.read_file("my_file.txt", dfi= DataFormatIdentifier(compression=5, encryption=2))
def _test_replace_file_negative_response_no_exception(self): self.udsclient.config['exception_on_negative_response'] = False response = self.udsclient.replace_file("my_file.txt", dfi= DataFormatIdentifier(compression=5, encryption=2), filesize = Filesize(uncompressed=0x222, compressed=0x111, width=4)) self.assertTrue(response.valid) self.assertFalse(response.positive)
def _test_replace_file_extra_bytes_response(self): with self.assertRaises(InvalidResponseException): self.udsclient.replace_file("my_file.txt", dfi= DataFormatIdentifier(compression=5, encryption=2), filesize = Filesize(uncompressed=0x222, compressed=0x111, width=4))
def test_str_repr(self): dfi = DataFormatIdentifier(compression=1, encryption=2) str(dfi) dfi.__repr__()
def test_dfi2(self): dfi = DataFormatIdentifier(compression=15, encryption=15) self.assertEqual(dfi.get_byte(), b'\xFF')
def test_dfi(self): dfi = DataFormatIdentifier(compression=1, encryption=2) self.assertEqual(dfi.get_byte(), b'\x12')
def _test_add_file_bad_dfi(self): with self.assertRaises(UnexpectedResponseException): self.udsclient.add_file("my_file.txt", dfi= DataFormatIdentifier(compression=5, encryption=2), filesize = 0x100)
def _test_read_file_negative_response_no_exception(self): self.udsclient.config['exception_on_negative_response'] = False response = self.udsclient.read_file("my_file.txt", dfi= DataFormatIdentifier(compression=5, encryption=2)) self.assertTrue(response.valid) self.assertFalse(response.positive)
def _test_request_download_success_dfi(self): memloc = MemoryLocation(address=0x1234, memorysize=0xFF, address_format=16, memorysize_format=8) dfi =DataFormatIdentifier(compression=5, encryption=2) response = self.udsclient.request_download(memory_location=memloc, dfi=dfi) self.assertEqual(response.service_data.max_length,0xabcd)
def test_from_byte(self): dfi = DataFormatIdentifier.from_byte(0xAB) self.assertEqual(dfi.compression, 0xA) self.assertEqual(dfi.encryption, 0xB)