Skip to content

Commit

Permalink
Additional test cases and error checks.
Browse files Browse the repository at this point in the history
  • Loading branch information
eerimoq committed Aug 31, 2016
1 parent d8fc2c4 commit 1bc5a37
Show file tree
Hide file tree
Showing 2 changed files with 104 additions and 40 deletions.
53 changes: 28 additions & 25 deletions bincopy.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
from io import StringIO

__author__ = 'Erik Moqvist'
__version__ = '7.1.1'
__version__ = '7.1.2'

DEFAULT_WORD_SIZE_BITS = 8

Expand Down Expand Up @@ -63,7 +63,7 @@ def pack_srec(type_, address, size, data):
elif type_ in '37':
line = '%02X%08X' % (size + 4 + 1, address)
else:
raise Error('Bad Motorola S-Record type %s.' % type_)
raise Error("bad type '{}'".format(type_))

if data:
line += binascii.hexlify(data).decode('utf-8').upper()
Expand All @@ -76,8 +76,11 @@ def unpack_srec(record):
"""

if len(record) < 6:
raise Error("bad record '{}'".format(record))

if record[0] != 'S':
raise Error('bad srecord "%s"' % record)
raise Error("bad record '{}'".format(record))

size = int(record[2:4], 16)
type_ = record[1:2]
Expand All @@ -89,17 +92,15 @@ def unpack_srec(record):
elif type_ in '37':
width = 8
else:
raise Error('Bad Motorola S-Record type %s.' % type_)
raise Error("bad record type '{}'".format(type_))

address = int(record[4:4+width], 16)
data = binascii.unhexlify(record[4 + width:4 + 2 * size - 2])
real_crc = int(record[4 + 2 * size - 2:], 16)
calc_crc = crc_srec(record[2:4 + 2 * size - 2])

if real_crc != calc_crc:
raise Error('Bad Motorola S-Record CRC for record '
'"{}" ({:02x} != {:02x})'.format(
record, real_crc, calc_crc))
raise Error("bad crc in record '{}'".format(record))

return (type_, address, size - 1 - width // 2, data)

Expand All @@ -122,8 +123,11 @@ def unpack_ihex(record):
"""

if len(record) < 11:
raise Error("bad record '{}'".format(record))

if record[0] != ':':
raise Error('bad intel hex record "%s"' % record)
raise Error("bad record '{}'".format(record))

size = int(record[1:3], 16)
address = int(record[3:7], 16)
Expand All @@ -138,9 +142,7 @@ def unpack_ihex(record):
calc_crc = crc_ihex(record[1:9 + 2 * size])

if real_crc != calc_crc:
print('warning: bad Intel HEX crc for record '
'"{}" ({:02x} != {:02x})'.format(
record, real_crc, calc_crc))
raise Error("bad crc in record '{}'".format(record))

return (type_, address, size, data)

Expand Down Expand Up @@ -194,17 +196,18 @@ def add_data(self, minimum_address, maximum_address, data, overwrite):
self.data += data
self.maximum_address = maximum_address
else:
raise Error('Data added to a segment must be adjacent to or '
'overlapping with the original segment data.')
raise Error('data added to a segment must be adjacent to or '
'overlapping with the original segment data')

def remove_data(self, minimum_address, maximum_address):
"""Remove given data range from this segment. Returns the second
segment if the removed data splits this segment in two.
"""

if (minimum_address >= self.maximum_address) and (maximum_address <= self.minimum_address):
raise Error('Cannot remove data that is not part of the segment.')
if ((minimum_address >= self.maximum_address)
and (maximum_address <= self.minimum_address)):
raise Error('cannot remove data that is not part of the segment')

if minimum_address < self.minimum_address:
minimum_address = self.minimum_address
Expand Down Expand Up @@ -371,7 +374,7 @@ def get_minimum_address(self):
"""

if not self.list:
return None
raise Error('cannot get minimum address from an empty file')

return self.list[0].minimum_address

Expand All @@ -381,7 +384,7 @@ def get_maximum_address(self):
"""

if not self.list:
return None
raise Error('cannot get maximum address from an empty file')

return self.list[-1].maximum_address

Expand All @@ -403,7 +406,7 @@ class BinFile(object):

def __init__(self, word_size_bits=DEFAULT_WORD_SIZE_BITS):
if (word_size_bits % 8) != 0:
raise Error('Word size must be a multiple of 8 bits.')
raise Error('word size must be a multiple of 8 bits')
self.word_size_bits = word_size_bits
self.word_size_bytes = (word_size_bits // 8)
self.header = None
Expand All @@ -417,7 +420,7 @@ def add_srec(self, records, overwrite=False):
"""

for record in StringIO(records):
type_, address, size, data = unpack_srec(record)
type_, address, size, data = unpack_srec(record.strip())

if type_ == '0':
self.header = data
Expand All @@ -439,7 +442,7 @@ def add_ihex(self, records, overwrite=False):
extmaximum_addressed_linear_address = 0

for record in StringIO(records):
type_, address, size, data = unpack_ihex(record)
type_, address, size, data = unpack_ihex(record.strip())

if type_ == 0:
address = (address
Expand All @@ -462,7 +465,7 @@ def add_ihex(self, records, overwrite=False):
elif type_ == 5:
self.execution_start_address = int(binascii.hexlify(data), 16)
else:
raise Error('Bad ihex type %d.' % type_)
raise Error('bad type {}'.format(type_))

def add_binary(self, data, address=0, overwrite=False):
"""Add given data at given address. Set `overwrite` to True to allow
Expand Down Expand Up @@ -583,8 +586,8 @@ def as_ihex(self, number_of_data_bytes=32, address_length_bits=32):
% extended_linear_address))
data_address.append(packed)
else:
raise Error('unsupported address length %d'
% address_length_bits)
raise Error('unsupported address length {}'.format(
address_length_bits))

data_address.append(pack_ihex(0,
address_lower_16_bits,
Expand Down Expand Up @@ -625,8 +628,8 @@ def as_binary(self, minimum_address=None, padding=b'\xff'):

if minimum_address is not None:
if minimum_address > self.get_minimum_address():
raise Error(('The selected start address must be lower of equal to '
'the start address of the binary.'))
raise Error('the selected start address must be lower or '
'equal to the start address of the binary')

current_maximum_address = minimum_address

Expand Down
91 changes: 76 additions & 15 deletions tests/test_bincopy.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,44 @@ def test_srec(self):
with open('tests/files/empty_main.bin', 'rb') as fin:
self.assertEqual(binfile.as_binary(padding=b'\x00'), fin.read())

try:
with self.assertRaises(bincopy.Error) as cm:
binfile.add_srec_file('tests/files/bad_crc.s19')
self.fail()
except bincopy.Error as e:
print(e)
self.assertEqual(str(cm.exception),
"bad crc in record "
"'S2144002640000000002000000060000001800000022'")

def test_bad_srec(self):
# pack
with self.assertRaises(bincopy.Error) as cm:
bincopy.pack_srec('q', 0, 0, '')
self.assertEqual(str(cm.exception), "bad type 'q'")

# unpack
with self.assertRaises(bincopy.Error) as cm:
bincopy.unpack_srec('')
self.assertEqual(str(cm.exception), "bad record ''")

with self.assertRaises(bincopy.Error) as cm:
bincopy.unpack_srec('S.000011')
self.assertEqual(str(cm.exception), "bad record type '.'")

with self.assertRaises(bincopy.Error) as cm:
bincopy.unpack_srec('S1000011')
self.assertEqual(str(cm.exception), "bad crc in record 'S1000011'")

def test_bad_ihex(self):
# unpack
with self.assertRaises(bincopy.Error) as cm:
bincopy.unpack_ihex('')
self.assertEqual(str(cm.exception), "bad record ''")

with self.assertRaises(bincopy.Error) as cm:
bincopy.unpack_ihex('.0011110022')
self.assertEqual(str(cm.exception), "bad record '.0011110022'")

with self.assertRaises(bincopy.Error) as cm:
bincopy.unpack_ihex(':0011110022')
self.assertEqual(str(cm.exception), "bad crc in record ':0011110022'")

def test_ihex(self):
binfile = bincopy.BinFile()
Expand Down Expand Up @@ -58,20 +91,25 @@ def test_binary(self):
binfile = bincopy.BinFile()
binfile.add_binary_file('tests/files/binary2.bin', 15)
binfile.add_binary_file('tests/files/binary2.bin', 15, overwrite=True)
try:
with self.assertRaises(bincopy.Error) as cm:
# cannot add overlapping segments
with open('tests/files/binary2.bin', 'rb') as fin:
binfile.add_binary(fin.read(), 20)
self.fail()
except bincopy.Error as err:
print(err)
# exclude the overlapping part and add
binfile.exclude(20, 1024)
with open('tests/files/binary2.bin', 'rb') as fin:
binfile.add_binary(fin.read(), 20)
with open('tests/files/binary3.bin', 'rb') as fin:
self.assertEqual(binfile.as_binary(minimum_address=0,
padding=b'\x00'), fin.read())

# Exclude the overlapping part and add.
binfile.exclude(20, 1024)
with open('tests/files/binary2.bin', 'rb') as fin:
binfile.add_binary(fin.read(), 20)
with open('tests/files/binary3.bin', 'rb') as fin:
self.assertEqual(binfile.as_binary(minimum_address=0,
padding=b'\x00'), fin.read())

# Dump with too high start address
with self.assertRaises(bincopy.Error) as cm:
binfile.as_binary(minimum_address=512)
self.assertEqual(str(cm.exception),
'the selected start address must be lower or equal '
'to the start address of the binary')

def test_array(self):
binfile = bincopy.BinFile()
Expand Down Expand Up @@ -152,6 +190,20 @@ def test_exclude_crop(self):

def test_minimum_maximum(self):
binfile = bincopy.BinFile()

# Get the minimum address from an empty file.
with self.assertRaises(bincopy.Error) as cm:
binfile.get_minimum_address()
self.assertEqual(str(cm.exception),
'cannot get minimum address from an empty file')

# Get the maximum address from an empty file.
with self.assertRaises(bincopy.Error) as cm:
binfile.get_maximum_address()
self.assertEqual(str(cm.exception),
'cannot get maximum address from an empty file')

# Get from a small file.
with open('tests/files/in.s19', 'r') as fin:
binfile.add_srec(fin.read())
self.assertEqual(binfile.get_minimum_address(), 0)
Expand Down Expand Up @@ -191,6 +243,15 @@ def test_info(self):
0x00600e10 - 0x00601038
""")

def test_execution_start_address(self):
binfile = bincopy.BinFile()
with open('tests/files/empty_main.s19', 'r') as fin:
binfile.add_srec(fin.read())
self.assertEqual(binfile.get_execution_start_address(), 0x00400400)

binfile.set_execution_start_address(0x00400401)
self.assertEqual(binfile.get_execution_start_address(), 0x00400401)

def test_ihex_crc(self):
self.assertEqual(bincopy.crc_ihex('0300300002337a'), 0x1e)
self.assertEqual(bincopy.crc_ihex('00000000'), 0)
Expand Down

0 comments on commit 1bc5a37

Please sign in to comment.