This commit is contained in:
Chris AtLee 2015-10-16 16:05:23 -04:00
Родитель 08523ae4f3 d2d11789b4
Коммит e37ab88585
4 изменённых файлов: 169 добавлений и 39 удалений

Просмотреть файл

@ -1,4 +1,5 @@
language: python
sudo: false
python:
- "3.5"

Просмотреть файл

@ -154,16 +154,20 @@ class MarFile:
# TODO: Handle writing the product information block
def __init__(self, name, mode="r", signature_versions=[]):
def __init__(self, name, mode="r", fileobj=None, signature_versions=[]):
if mode not in "rw":
raise ValueError("Mode must be either 'r' or 'w'")
self.name = name
self.mode = mode
if mode == 'w':
self.fileobj = open(name, 'wb')
if fileobj:
self.fileobj = fileobj
if hasattr(self.fileobj, "mode"):
# take the first letter of "rb"/"wb"
self.mode = fileobj.mode[0]
else:
self.fileobj = open(name, 'rb')
if self.mode == 'w':
self.fileobj = open(name, 'wb')
else:
self.fileobj = open(name, 'rb')
self.members = []
self.additional_info = []
@ -180,10 +184,10 @@ class MarFile:
self.signatures = []
self.signature_versions = signature_versions
if mode == "r":
if self.mode == "r":
# Read the file's index
self._read()
elif mode == "w":
elif self.mode == "w":
self._prepare_index()
def _prepare_index(self):
@ -396,8 +400,9 @@ class MarFile:
self.fileobj.flush()
if self.signatures:
fileobj = open(self.name, 'rb')
generate_signature(fileobj, self._update_signatures)
curr_pos = self.fileobj.tell()
generate_signature(self.fileobj, self._update_signatures)
self.fileobj.seek(curr_pos)
for sig in self.signatures:
# print sig._offset
sig.write_signature(self.fileobj)

Просмотреть файл

@ -16,33 +16,39 @@ def sha1sum(b):
return h.hexdigest()
def test_list():
with MarFile(TEST_MAR) as m:
assert repr(m.members[0]) == "<update.manifest 664 141 bytes starting at 392>", m.members[0]
assert repr(m.members[1]) == "<defaults/pref/channel-prefs.js 664 76 bytes starting at 533>", m.members[1]
assert len(m.additional_info) == 1
assert m.additional_info[0].name == "PRODUCT INFORMATION"
assert m.additional_info[0].info == {'MARChannelName': 'thunderbird-comm-esr', 'ProductVersion': '100.0'}
class TestList(TestCase):
@staticmethod
def check_list(marfile):
with marfile as m:
assert repr(m.members[0]) == "<update.manifest 664 141 bytes starting at 392>", m.members[0]
assert repr(m.members[1]) == "<defaults/pref/channel-prefs.js 664 76 bytes starting at 533>", m.members[1]
assert len(m.additional_info) == 1
assert m.additional_info[0].name == "PRODUCT INFORMATION"
assert m.additional_info[0].info == {'MARChannelName': 'thunderbird-comm-esr', 'ProductVersion': '100.0'}
with BZ2MarFile(TEST_MAR) as m:
assert repr(m.members[0]) == "<update.manifest 664 141 bytes starting at 392>", m.members[0]
assert repr(m.members[1]) == "<defaults/pref/channel-prefs.js 664 76 bytes starting at 533>", m.members[1]
assert len(m.additional_info) == 1
assert m.additional_info[0].name == "PRODUCT INFORMATION"
assert m.additional_info[0].info == {'MARChannelName': 'thunderbird-comm-esr', 'ProductVersion': '100.0'}
def test_list_name(self):
self.check_list(MarFile(TEST_MAR))
def test_list_name_bz(self):
self.check_list(BZ2MarFile(TEST_MAR))
def test_list_fo(self):
self.check_list(MarFile(None, fileobj=open(TEST_MAR, 'rb')))
def test_list_fo_bz(self):
self.check_list(BZ2MarFile(None, fileobj=open(TEST_MAR, 'rb')))
class TestReadingMar(TestCase):
def setUp(self):
self.tmpdir = tempfile.mkdtemp()
self.marfile = MarFile(TEST_MAR)
def tearDown(self):
shutil.rmtree(self.tmpdir)
def test_extract(self):
m = self.marfile.members[0]
self.marfile.extract(m, self.tmpdir)
def check_extract(self, marfile):
m = marfile.members[0]
marfile.extract(m, self.tmpdir)
fn = os.path.join(self.tmpdir, m.name)
# Check that the size matches what's in the manifest
@ -53,29 +59,40 @@ class TestReadingMar(TestCase):
h = sha1sum(data)
self.assertEquals("6a7890e740f1e18a425b51fefbde2f6b86f91a12", h)
def test_extractall(self):
self.marfile.extractall(self.tmpdir)
def check_extractall(self, marfile):
marfile.extractall(self.tmpdir)
all_files = []
for root, dirs, files in os.walk(self.tmpdir):
for f in files:
all_files.append(os.path.join(root, f))
for member in self.marfile.members:
for member in marfile.members:
self.assertTrue(os.path.join(self.tmpdir, member.name) in all_files)
def test_extract_name(self):
self.check_extract(MarFile(TEST_MAR))
def test_extractall_name(self):
self.check_extractall(MarFile(TEST_MAR))
def test_extract_fileobj(self):
self.check_extract(MarFile(None, fileobj=open(TEST_MAR, "rb")))
def test_extractall_fileobj(self):
self.check_extractall(MarFile(None, fileobj=open(TEST_MAR, "rb")))
class TestReadingBZ2Mar(TestCase):
def setUp(self):
self.tmpdir = tempfile.mkdtemp()
self.marfile = BZ2MarFile(TEST_MAR)
def tearDown(self):
shutil.rmtree(self.tmpdir)
def test_extract_bz2(self):
m = self.marfile.members[0]
self.marfile.extract(m, self.tmpdir)
def check_extract_bz2(self, marfile):
m = marfile.members[0]
marfile.extract(m, self.tmpdir)
fn = os.path.join(self.tmpdir, m.name)
# The size in the manifest is of the compressed data, so we need to
@ -88,6 +105,12 @@ class TestReadingBZ2Mar(TestCase):
h = sha1sum(data)
self.assertEquals("5177f5938923e94820d8565a1a0f25d19b4821d1", h)
def test_extract_bz2(self):
self.check_extract_bz2(BZ2MarFile(TEST_MAR))
def test_extract_bz2_fo(self):
self.check_extract_bz2(BZ2MarFile(None, fileobj=open(TEST_MAR, "rb")))
class TestWritingMar(TestCase):
def setUp(self):
@ -98,7 +121,7 @@ class TestWritingMar(TestCase):
def test_add(self):
marfile = os.path.join(self.tmpdir, 'test.mar')
with MarFile(marfile, 'w') as m:
with MarFile(marfile, mode='w') as m:
m.add(__file__)
with MarFile(marfile) as m:
@ -111,9 +134,24 @@ class TestWritingMar(TestCase):
open(__file__, 'rb').read()
)
def test_add_fo(self):
marfile = os.path.join(self.tmpdir, 'test.mar')
with MarFile(None, fileobj=open(marfile, "wb")) as m:
m.add(__file__)
with MarFile(None, fileobj=open(marfile, "rb")) as m:
self.assertEquals(len(m.members), 1)
self.assertEquals(m.members[0].size, os.path.getsize(__file__))
self.assertEquals(m.members[0].flags, os.stat(__file__).st_mode & 0o777)
extracted = m.extract(m.members[0], self.tmpdir)
self.assertEquals(
open(extracted, 'rb').read(),
open(__file__, 'rb').read()
)
def test_additional_info(self):
marfile = os.path.join(self.tmpdir, 'test.mar')
with MarFile(marfile, 'w') as m:
with MarFile(marfile, mode='w') as m:
info = AdditionalInfo.from_info({'MARChannelName': 'test1', 'ProductVersion': '123'})
m.additional_info.append(info)
m.add(__file__)
@ -123,10 +161,22 @@ class TestWritingMar(TestCase):
self.assertEquals(m.additional_info[0].name, 'PRODUCT INFORMATION')
self.assertEquals(m.additional_info[0].info, {'MARChannelName': 'test1', 'ProductVersion': '123'})
def test_additional_info_fo(self):
marfile = os.path.join(self.tmpdir, 'test.mar')
with MarFile(None, fileobj=open(marfile, "wb")) as m:
info = AdditionalInfo.from_info({'MARChannelName': 'test1', 'ProductVersion': '123'})
m.additional_info.append(info)
m.add(__file__)
with MarFile(None, fileobj=open(marfile, "rb")) as m:
self.assertEquals(len(m.additional_info), 1)
self.assertEquals(m.additional_info[0].name, 'PRODUCT INFORMATION')
self.assertEquals(m.additional_info[0].info, {'MARChannelName': 'test1', 'ProductVersion': '123'})
def test_add_dir(self):
marfile = os.path.join(self.tmpdir, 'test.mar')
dirname = os.path.dirname(__file__)
with MarFile(marfile, 'w') as m:
with MarFile(marfile, mode='w') as m:
m.add(dirname)
# List out the files in dirname so we can compare
@ -149,9 +199,35 @@ class TestWritingMar(TestCase):
open(member.name, 'rb').read()
)
def test_add_dir_fo(self):
marfile = os.path.join(self.tmpdir, 'test.mar')
dirname = os.path.dirname(__file__)
with MarFile(None, fileobj=open(marfile, "wb")) as m:
m.add(dirname)
# List out the files in dirname so we can compare
my_files = []
for root, dirs, files in os.walk(dirname):
for f in files:
my_files.append(os.path.join(root, f))
with MarFile(None, fileobj=open(marfile, "rb")) as m:
self.assertEquals(len(m.members), len(my_files))
for member in m.members:
self.assertTrue(member.name in my_files)
self.assertEquals(member.size, os.path.getsize(member.name))
self.assertEquals(member.flags, os.stat(member.name).st_mode & 0o777)
extracted = m.extract(member, self.tmpdir)
self.assertNotEquals(extracted, member.name)
self.assertEquals(
open(extracted, 'rb').read(),
open(member.name, 'rb').read()
)
def test_bz2_add(self):
marfile = os.path.join(self.tmpdir, 'test.mar')
with BZ2MarFile(marfile, 'w') as m:
with BZ2MarFile(marfile, mode='w') as m:
m.add(__file__)
with BZ2MarFile(marfile) as m:
@ -162,10 +238,23 @@ class TestWritingMar(TestCase):
open(__file__, 'rb').read()
)
def test_bz2_add_fo(self):
marfile = os.path.join(self.tmpdir, 'test.mar')
with BZ2MarFile(None, fileobj=open(marfile, "wb")) as m:
m.add(__file__)
with BZ2MarFile(None, fileobj=open(marfile, "rb")) as m:
self.assertEquals(len(m.members), 1)
extracted = m.extract(m.members[0], self.tmpdir)
self.assertEquals(
open(extracted, 'rb').read(),
open(__file__, 'rb').read()
)
def test_bz2_add_dir(self):
marfile = os.path.join(self.tmpdir, 'test.mar')
dirname = os.path.dirname(__file__)
with BZ2MarFile(marfile, 'w') as m:
with BZ2MarFile(marfile, mode='w') as m:
m.add(dirname)
# List out the files in dirname so we can compare
@ -187,11 +276,40 @@ class TestWritingMar(TestCase):
open(member.name, 'rb').read()
)
def test_bz2_add_dir_fo(self):
marfile = os.path.join(self.tmpdir, 'test.mar')
dirname = os.path.dirname(__file__)
with BZ2MarFile(None, fileobj=open(marfile, "wb")) as m:
m.add(dirname)
# List out the files in dirname so we can compare
my_files = []
for root, dirs, files in os.walk(dirname):
for f in files:
my_files.append(os.path.join(root, f))
with BZ2MarFile(None, fileobj=open(marfile, "rb")) as m:
self.assertEquals(len(m.members), len(my_files))
for member in m.members:
self.assertTrue(member.name in my_files)
self.assertEquals(member.flags, os.stat(member.name).st_mode & 0o777)
extracted = m.extract(member, self.tmpdir)
self.assertNotEquals(extracted, member.name)
self.assertEquals(
open(extracted, 'rb').read(),
open(member.name, 'rb').read()
)
class TestExceptions(TestCase):
def test_badmar(self):
self.assertRaises(ValueError, MarFile, __file__)
def test_badmar_fo(self):
self.assertRaises(ValueError, MarFile, name=None,
fileobj=open(__file__, "rb"))
from hypothesis import given, example
from hypothesis import strategies as st

Просмотреть файл

@ -17,3 +17,9 @@ class TestMarSignatures(TestCase):
"""Check that our test mar is signed correctly"""
marfile = MarFile(TEST_MAR, signature_versions=[(1, TEST_KEY)])
marfile.verify_signatures()
def test_verify_fo(self):
"""Check that our test mar fileobject is signed correctly"""
marfile = MarFile(name=TEST_MAR, fileobj=open(TEST_MAR, "rb"),
signature_versions=[(1, TEST_KEY)])
marfile.verify_signatures()