Пример #1
0
class TarTest(unittest.TestCase):
    def setUp(self):
        self.out = io.BytesIO()
        self.tarfixer = TarFixer(None, self.out, EXPECTED_TIMESTAMP, EXPECTED_REF)
        self.utf8_containing_file = os.path.join(os.path.dirname(__file__), 'resources', 'les_misérables.tar')
        self.utf8_file = os.path.join(os.path.dirname(__file__), 'resources', 'archivé.tar')
        self.test_file = os.path.join(os.path.dirname(__file__), 'resources', 'archive.tar')
        self.reference_file = os.path.join(os.path.dirname(__file__), 'resources', 'archive-fixed.tar')
        self.reference_hash = self.hash_file(self.reference_file)

    def tearDown(self):
        self.out = None

    def hash_file(self, filename):
        file_bytes = open(filename, 'rb').read()
        return self.hash_buffer(file_bytes)

    def hash_buffer(self, buf):
        hasher = hashlib.sha256()
        hasher.update(buf)
        return hasher.hexdigest()

    def _irregular_reader(self, items):
        def item_read(read_length):
            try:
                item = items.pop(0)
            except IndexError:
                # If no more items, the buffer is empty and would return empty string
                return ''

            return item.read(read_length)

        mock_fh = Mock()
        mock_fh.read = Mock()
        mock_fh.read.side_effect = item_read

        return mock_fh

    def test_full_read(self):
        items = [StringIO("1" * 5), StringIO("1" * 2), StringIO("1" * 6)]
        self.tarfixer.fh = self._irregular_reader(items)
        self.assertEqual("1" * 10, self.tarfixer.full_read(10))

    def test_full_read_buffer_underflow(self):
        input = StringIO("1" * 9)
        self.tarfixer.fh = input
        self.assertRaises(IOError, self.tarfixer.full_read, 10)

    def test_full_read_eventual_buffer_underflow(self):
        items = [StringIO("1" * 5), StringIO("1" * 2), StringIO("1" * 2)]
        self.tarfixer.fh = self._irregular_reader(items)
        self.assertRaises(IOError, self.tarfixer.full_read, 10)

    def test_fix(self):
        self.fh = open(self.test_file, 'rb')
        self.tarfixer.fh = self.fh
        self.tarfixer.fix()
        self.assertEqual(self.reference_hash, self.hash_buffer(self.out.getvalue()))

    def test_fix_fails_unless_file_in_binary_mode(self):
        self.fh = open(self.test_file, 'r')
        self.tarfixer.fh = self.fh
        self.assertRaises(IOError, self.tarfixer.fix)

    def test_padded_size_length_small(self):
        length = 10
        block_size = 512
        self.assertEqual(512, self.tarfixer.padded_size(length, block_size))

    def test_padded_size_length_spot_on(self):
        length = 512
        block_size = 512
        self.assertEqual(512, self.tarfixer.padded_size(length, block_size))

    def test_padded_size_length_over(self):
        length = 513
        block_size = 512
        self.assertEqual(1024, self.tarfixer.padded_size(length, block_size))

    def test_padded_size_length_long(self):
        length = 82607
        block_size = 512
        self.assertEqual(82944, self.tarfixer.padded_size(length, block_size))

    def test_create_extended_header(self):
        self.tarfixer.create_extended_header()
        header = self.out.getvalue()
        self.assertEqual(512, len(header))
        self.assertEqual(ensure_binary("52 comment=%s\n" % EXPECTED_REF), header[:52])
        self.assertEqual(ensure_binary("\x00" * (512 - 53)), header[53:])

    def test_calculate_checksum(self):
        fields = {
            'a': '\x01',
            'b': '\x02',
            'c': '\x03',
            'd': '\x04',
        }
        self.tarfixer.struct_members = list(fields.keys()) + ['checksum']
        result = self.tarfixer.calculate_checksum(fields)
        expected_result = 10 + ord(" ") * 8
        self.assertEqual("%07o\x00" % expected_result, result)

    def test_encode_header(self):
        mode = 123
        chunk = {
            'mode': mode,
            'name': 'hello',
        }
        result = self.tarfixer.encode_header(chunk, ['mode', 'name'])
        expected_result = ["%07o\x00" % mode, "hello"]
        expected_result = list(map(lambda x: ensure_binary(x), expected_result))
        self.assertEqual(expected_result, result)

    def test_utf8_file(self):
        # The goal of this test is to *not* throw a UnicodeDecodeError
        self.fh = open(self.utf8_file, 'rb')
        self.tarfixer.fh = self.fh
        self.tarfixer.fix()

        self.assertEqual(self.reference_hash, self.hash_buffer(self.out.getvalue()))

        # rewind the buffer
        self.out.seek(0)
        try:
            tarball = tarfile.open(fileobj=self.out, mode="r")
        except tarfile.TarError:
            self.fail("Unable to open generated tarball")

    def test_utf8_containing_file(self):
        # # The goal of this test is to *not* blow up due to a corrupted tarball
        self.fh = open(self.utf8_containing_file, 'rb')
        self.tarfixer.fh = self.fh
        self.tarfixer.fix()

        # rewind the buffer
        self.out.seek(0)
        try:
            tarball = tarfile.open(fileobj=self.out, mode="r")
        except tarfile.TarError as e:
            self.fail("Unable to open generated tarball: %s" % e)
Пример #2
0
class TarTest(unittest.TestCase):
    def setUp(self):
        self.out = io.BytesIO()
        self.tarfixer = TarFixer(None, self.out, EXPECTED_TIMESTAMP,
                                 EXPECTED_REF)
        self.utf8_containing_file = os.path.join(os.path.dirname(__file__),
                                                 'resources',
                                                 'les_misérables.tar')
        self.utf8_file = os.path.join(os.path.dirname(__file__), 'resources',
                                      'archivé.tar')
        self.test_file = os.path.join(os.path.dirname(__file__), 'resources',
                                      'archive.tar')
        self.reference_file = os.path.join(os.path.dirname(__file__),
                                           'resources', 'archive-fixed.tar')
        self.reference_hash = self.hash_file(self.reference_file)

    def tearDown(self):
        self.out = None

    def hash_file(self, filename):
        file_bytes = open(filename, 'rb').read()
        return self.hash_buffer(file_bytes)

    def hash_buffer(self, buf):
        hasher = hashlib.sha256()
        hasher.update(buf)
        return hasher.hexdigest()

    def _irregular_reader(self, items):
        def item_read(read_length):
            try:
                item = items.pop(0)
            except IndexError:
                # If no more items, the buffer is empty and would return empty string
                return ''

            return item.read(read_length)

        mock_fh = Mock()
        mock_fh.read = Mock()
        mock_fh.read.side_effect = item_read

        return mock_fh

    def test_full_read(self):
        items = [StringIO("1" * 5), StringIO("1" * 2), StringIO("1" * 6)]
        self.tarfixer.fh = self._irregular_reader(items)
        self.assertEqual("1" * 10, self.tarfixer.full_read(10))

    def test_full_read_buffer_underflow(self):
        input = StringIO("1" * 9)
        self.tarfixer.fh = input
        self.assertRaises(IOError, self.tarfixer.full_read, 10)

    def test_full_read_eventual_buffer_underflow(self):
        items = [StringIO("1" * 5), StringIO("1" * 2), StringIO("1" * 2)]
        self.tarfixer.fh = self._irregular_reader(items)
        self.assertRaises(IOError, self.tarfixer.full_read, 10)

    def test_fix(self):
        self.fh = open(self.test_file, 'rb')
        self.tarfixer.fh = self.fh
        self.tarfixer.fix()
        self.assertEqual(self.reference_hash,
                         self.hash_buffer(self.out.getvalue()))

    def test_fix_fails_unless_file_in_binary_mode(self):
        self.fh = open(self.test_file, 'r')
        self.tarfixer.fh = self.fh
        self.assertRaises(IOError, self.tarfixer.fix)

    def test_padded_size_length_small(self):
        length = 10
        block_size = 512
        self.assertEqual(512, self.tarfixer.padded_size(length, block_size))

    def test_padded_size_length_spot_on(self):
        length = 512
        block_size = 512
        self.assertEqual(512, self.tarfixer.padded_size(length, block_size))

    def test_padded_size_length_over(self):
        length = 513
        block_size = 512
        self.assertEqual(1024, self.tarfixer.padded_size(length, block_size))

    def test_padded_size_length_long(self):
        length = 82607
        block_size = 512
        self.assertEqual(82944, self.tarfixer.padded_size(length, block_size))

    def test_create_extended_header(self):
        self.tarfixer.create_extended_header()
        header = self.out.getvalue()
        self.assertEqual(512, len(header))
        self.assertEqual(ensure_binary("52 comment=%s\n" % EXPECTED_REF),
                         header[:52])
        self.assertEqual(ensure_binary("\x00" * (512 - 53)), header[53:])

    def test_calculate_checksum(self):
        fields = {
            'a': '\x01',
            'b': '\x02',
            'c': '\x03',
            'd': '\x04',
        }
        self.tarfixer.struct_members = list(fields.keys()) + ['checksum']
        result = self.tarfixer.calculate_checksum(fields)
        expected_result = 10 + ord(" ") * 8
        self.assertEqual("%07o\x00" % expected_result, result)

    def test_encode_header(self):
        mode = 123
        chunk = {
            'mode': mode,
            'name': 'hello',
        }
        result = self.tarfixer.encode_header(chunk, ['mode', 'name'])
        expected_result = ["%07o\x00" % mode, "hello"]
        expected_result = list(map(lambda x: ensure_binary(x),
                                   expected_result))
        self.assertEqual(expected_result, result)

    def test_utf8_file(self):
        # The goal of this test is to *not* throw a UnicodeDecodeError
        self.fh = open(self.utf8_file, 'rb')
        self.tarfixer.fh = self.fh
        self.tarfixer.fix()

        self.assertEqual(self.reference_hash,
                         self.hash_buffer(self.out.getvalue()))

        # rewind the buffer
        self.out.seek(0)
        try:
            tarball = tarfile.open(fileobj=self.out, mode="r")
        except tarfile.TarError:
            self.fail("Unable to open generated tarball")

    def test_utf8_containing_file(self):
        # # The goal of this test is to *not* blow up due to a corrupted tarball
        self.fh = open(self.utf8_containing_file, 'rb')
        self.tarfixer.fh = self.fh
        self.tarfixer.fix()

        # rewind the buffer
        self.out.seek(0)
        try:
            tarball = tarfile.open(fileobj=self.out, mode="r")
        except tarfile.TarError as e:
            self.fail("Unable to open generated tarball: %s" % e)