212 lines
7.9 KiB
Python
Executable File
212 lines
7.9 KiB
Python
Executable File
#!/usr/bin/python
|
|
|
|
# Copyright 2016, The Android Open Source Project
|
|
#
|
|
# Permission is hereby granted, free of charge, to any person
|
|
# obtaining a copy of this software and associated documentation
|
|
# files (the "Software"), to deal in the Software without
|
|
# restriction, including without limitation the rights to use, copy,
|
|
# modify, merge, publish, distribute, sublicense, and/or sell copies
|
|
# of the Software, and to permit persons to whom the Software is
|
|
# furnished to do so, subject to the following conditions:
|
|
#
|
|
# The above copyright notice and this permission notice shall be
|
|
# included in all copies or substantial portions of the Software.
|
|
#
|
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
|
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
|
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
# SOFTWARE.
|
|
|
|
|
|
"""Unit-test for ImageHandler."""
|
|
|
|
|
|
import imp
|
|
import os
|
|
import sys
|
|
import tempfile
|
|
import unittest
|
|
|
|
sys.dont_write_bytecode = True
|
|
avbtool = imp.load_source('avbtool', './avbtool')
|
|
|
|
# The file test_file.bin and test_file.bin.sparse are generated using
|
|
# the following python code:
|
|
#
|
|
# with open('test_file.bin', 'w+b') as f:
|
|
# f.write('Barfoo43'*128*12)
|
|
# os.system('img2simg test_file.bin test_file.bin.sparse')
|
|
# image = avbtool.ImageHandler('test_file.bin.sparse')
|
|
# image.append_dont_care(12*1024)
|
|
# image.append_fill('\x01\x02\x03\x04', 12*1024)
|
|
# image.append_raw('Foobar42'*128*12)
|
|
# image.append_dont_care(12*1024)
|
|
# del image
|
|
# os.system('rm -f test_file.bin')
|
|
# os.system('simg2img test_file.bin.sparse test_file.bin')
|
|
#
|
|
# and manually verified to be correct. The content of the raw and
|
|
# sparse files are as follows (the line with "Fill with 0x04030201" is
|
|
# a simg_dump.py bug):
|
|
#
|
|
# $ hexdump -C test_file.bin
|
|
# 00000000 42 61 72 66 6f 6f 34 33 42 61 72 66 6f 6f 34 33 |Barfoo43Barfoo43|
|
|
# *
|
|
# 00003000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
|
|
# *
|
|
# 00006000 01 02 03 04 01 02 03 04 01 02 03 04 01 02 03 04 |................|
|
|
# *
|
|
# 00009000 46 6f 6f 62 61 72 34 32 46 6f 6f 62 61 72 34 32 |Foobar42Foobar42|
|
|
# *
|
|
# 0000c000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
|
|
# *
|
|
# 0000f000
|
|
#
|
|
# $ system/core/libsparse/simg_dump.py -v test_file.bin.sparse
|
|
# test_file.bin.sparse: Total of 15 4096-byte output blocks in 5 input chunks.
|
|
# input_bytes output_blocks
|
|
# chunk offset number offset number
|
|
# 1 40 12288 0 3 Raw data
|
|
# 2 12340 0 3 3 Don't care
|
|
# 3 12352 4 6 3 Fill with 0x04030201
|
|
# 4 12368 12288 9 3 Raw data
|
|
# 5 24668 0 12 3 Don't care
|
|
# 24668 15 End
|
|
#
|
|
|
|
|
|
class ImageHandler(unittest.TestCase):
|
|
|
|
TEST_FILE_SPARSE_PATH = 'test/data/test_file.bin.sparse'
|
|
TEST_FILE_PATH = 'test/data/test_file.bin'
|
|
TEST_FILE_SIZE = 61440
|
|
TEST_FILE_BLOCK_SIZE = 4096
|
|
|
|
def _file_contents_equal(self, path1, path2, size):
|
|
f1 = open(path1, 'r')
|
|
f2 = open(path2, 'r')
|
|
if f1.read(size) != f2.read(size):
|
|
return False
|
|
return True
|
|
|
|
def _file_size(self, f):
|
|
old_pos = f.tell()
|
|
f.seek(0, os.SEEK_END)
|
|
size = f.tell()
|
|
f.seek(old_pos)
|
|
return size
|
|
|
|
def _clone_sparse_file(self):
|
|
f = tempfile.NamedTemporaryFile()
|
|
f.write(open(self.TEST_FILE_SPARSE_PATH).read())
|
|
f.flush()
|
|
return f
|
|
|
|
def _unsparsify(self, path):
|
|
f = tempfile.NamedTemporaryFile()
|
|
os.system('simg2img {} {}'.format(path, f.name))
|
|
return f
|
|
|
|
def testRead(self):
|
|
"""Checks that reading from a sparse file works as intended."""
|
|
ih = avbtool.ImageHandler(self.TEST_FILE_SPARSE_PATH)
|
|
|
|
# Check that we start at offset 0.
|
|
self.assertEqual(ih.tell(), 0)
|
|
|
|
# Check that reading advances the cursor.
|
|
self.assertEqual(ih.read(14), bytearray('Barfoo43Barfoo'))
|
|
self.assertEqual(ih.tell(), 14)
|
|
self.assertEqual(ih.read(2), bytearray('43'))
|
|
self.assertEqual(ih.tell(), 16)
|
|
|
|
# Check reading in the middle of a fill chunk gets the right data.
|
|
ih.seek(0x6000 + 1)
|
|
self.assertEqual(ih.read(4), bytearray('\x02\x03\x04\x01'))
|
|
|
|
# Check we can cross the chunk boundary correctly.
|
|
ih.seek(0x3000 - 10)
|
|
self.assertEqual(ih.read(12), bytearray('43Barfoo43\x00\x00'))
|
|
ih.seek(0x9000 - 3)
|
|
self.assertEqual(ih.read(5), bytearray('\x02\x03\x04Fo'))
|
|
|
|
# Check reading at end of file is a partial read.
|
|
ih.seek(0xf000 - 2)
|
|
self.assertEqual(ih.read(16), bytearray('\x00\x00'))
|
|
|
|
def testTruncate(self):
|
|
"""Checks that we can truncate a sparse file correctly."""
|
|
# Check truncation at all possible boundaries (including start and end).
|
|
for size in range(0, self.TEST_FILE_SIZE + self.TEST_FILE_BLOCK_SIZE,
|
|
self.TEST_FILE_BLOCK_SIZE):
|
|
sparse_file = self._clone_sparse_file()
|
|
ih = avbtool.ImageHandler(sparse_file.name)
|
|
ih.truncate(size)
|
|
unsparse_file = self._unsparsify(sparse_file.name)
|
|
self.assertEqual(self._file_size(unsparse_file), size)
|
|
self.assertTrue(self._file_contents_equal(unsparse_file.name,
|
|
self.TEST_FILE_PATH,
|
|
size))
|
|
|
|
# Check truncation to grow the file.
|
|
grow_size = 8192
|
|
sparse_file = self._clone_sparse_file()
|
|
ih = avbtool.ImageHandler(sparse_file.name)
|
|
ih.truncate(self.TEST_FILE_SIZE + grow_size)
|
|
unsparse_file = self._unsparsify(sparse_file.name)
|
|
self.assertEqual(self._file_size(unsparse_file),
|
|
self.TEST_FILE_SIZE + grow_size)
|
|
self.assertTrue(self._file_contents_equal(unsparse_file.name,
|
|
self.TEST_FILE_PATH,
|
|
self.TEST_FILE_SIZE))
|
|
unsparse_file.seek(self.TEST_FILE_SIZE)
|
|
self.assertEqual(unsparse_file.read(), '\0'*grow_size)
|
|
|
|
def testAppendRaw(self):
|
|
"""Checks that we can append raw data correctly."""
|
|
sparse_file = self._clone_sparse_file()
|
|
ih = avbtool.ImageHandler(sparse_file.name)
|
|
data = 'SomeData'*4096
|
|
ih.append_raw(data)
|
|
unsparse_file = self._unsparsify(sparse_file.name)
|
|
self.assertTrue(self._file_contents_equal(unsparse_file.name,
|
|
self.TEST_FILE_PATH,
|
|
self.TEST_FILE_SIZE))
|
|
unsparse_file.seek(self.TEST_FILE_SIZE)
|
|
self.assertEqual(unsparse_file.read(), data)
|
|
|
|
def testAppendFill(self):
|
|
"""Checks that we can append fill data correctly."""
|
|
sparse_file = self._clone_sparse_file()
|
|
ih = avbtool.ImageHandler(sparse_file.name)
|
|
data = 'ABCD'*4096
|
|
ih.append_fill('ABCD', len(data))
|
|
unsparse_file = self._unsparsify(sparse_file.name)
|
|
self.assertTrue(self._file_contents_equal(unsparse_file.name,
|
|
self.TEST_FILE_PATH,
|
|
self.TEST_FILE_SIZE))
|
|
unsparse_file.seek(self.TEST_FILE_SIZE)
|
|
self.assertEqual(unsparse_file.read(), data)
|
|
|
|
def testDontCare(self):
|
|
"""Checks that we can append DONT_CARE data correctly."""
|
|
sparse_file = self._clone_sparse_file()
|
|
ih = avbtool.ImageHandler(sparse_file.name)
|
|
data = '\0'*40960
|
|
ih.append_dont_care(len(data))
|
|
unsparse_file = self._unsparsify(sparse_file.name)
|
|
self.assertTrue(self._file_contents_equal(unsparse_file.name,
|
|
self.TEST_FILE_PATH,
|
|
self.TEST_FILE_SIZE))
|
|
unsparse_file.seek(self.TEST_FILE_SIZE)
|
|
self.assertEqual(unsparse_file.read(), data)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
unittest.main()
|