Merge "Use seek() instead of writing 0s" into main am: dfa0c85705
Original change: https://android-review.googlesource.com/c/platform/build/+/2734171 Change-Id: Iccf7a483cc5202e913293e8692d8af244df3b7c6 Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
@@ -15,14 +15,13 @@
|
|||||||
#
|
#
|
||||||
|
|
||||||
import copy
|
import copy
|
||||||
import json
|
|
||||||
import os
|
import os
|
||||||
import subprocess
|
import subprocess
|
||||||
import tempfile
|
import tempfile
|
||||||
import time
|
|
||||||
import unittest
|
import unittest
|
||||||
import zipfile
|
import zipfile
|
||||||
from hashlib import sha1
|
from hashlib import sha1
|
||||||
|
from typing import BinaryIO
|
||||||
|
|
||||||
import common
|
import common
|
||||||
import test_utils
|
import test_utils
|
||||||
@@ -36,14 +35,24 @@ MiB = 1024 * KiB
|
|||||||
GiB = 1024 * MiB
|
GiB = 1024 * MiB
|
||||||
|
|
||||||
|
|
||||||
def get_2gb_string():
|
def get_2gb_file():
|
||||||
size = int(2 * GiB + 1)
|
size = int(2 * GiB + 1)
|
||||||
block_size = 4 * KiB
|
block_size = 4 * KiB
|
||||||
step_size = 4 * MiB
|
step_size = 4 * MiB
|
||||||
# Generate a long string with holes, e.g. 'xyz\x00abc\x00...'.
|
tmpfile = tempfile.NamedTemporaryFile()
|
||||||
|
tmpfile.truncate(size)
|
||||||
for _ in range(0, size, step_size):
|
for _ in range(0, size, step_size):
|
||||||
yield os.urandom(block_size)
|
tmpfile.write(os.urandom(block_size))
|
||||||
yield b'\0' * (step_size - block_size)
|
tmpfile.seek(step_size - block_size, os.SEEK_CUR)
|
||||||
|
return tmpfile
|
||||||
|
|
||||||
|
|
||||||
|
def hash_file(filename):
|
||||||
|
sha1_hash = sha1()
|
||||||
|
with open(filename, "rb") as fp:
|
||||||
|
for data in iter(lambda: fp.read(4*MiB), b''):
|
||||||
|
sha1_hash.update(data)
|
||||||
|
return sha1_hash
|
||||||
|
|
||||||
|
|
||||||
class BuildInfoTest(test_utils.ReleaseToolsTestCase):
|
class BuildInfoTest(test_utils.ReleaseToolsTestCase):
|
||||||
@@ -222,17 +231,17 @@ class BuildInfoTest(test_utils.ReleaseToolsTestCase):
|
|||||||
info_dict = copy.deepcopy(self.TEST_INFO_FINGERPRINT_DICT)
|
info_dict = copy.deepcopy(self.TEST_INFO_FINGERPRINT_DICT)
|
||||||
build_info = common.BuildInfo(info_dict)
|
build_info = common.BuildInfo(info_dict)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
'product-brand/product-name/product-device:version-release/build-id/'
|
'product-brand/product-name/product-device:version-release/build-id/'
|
||||||
'version-incremental:build-type/build-tags', build_info.fingerprint)
|
'version-incremental:build-type/build-tags', build_info.fingerprint)
|
||||||
|
|
||||||
build_props = info_dict['build.prop'].build_props
|
build_props = info_dict['build.prop'].build_props
|
||||||
del build_props['ro.build.id']
|
del build_props['ro.build.id']
|
||||||
build_props['ro.build.legacy.id'] = 'legacy-build-id'
|
build_props['ro.build.legacy.id'] = 'legacy-build-id'
|
||||||
build_info = common.BuildInfo(info_dict, use_legacy_id=True)
|
build_info = common.BuildInfo(info_dict, use_legacy_id=True)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
'product-brand/product-name/product-device:version-release/'
|
'product-brand/product-name/product-device:version-release/'
|
||||||
'legacy-build-id/version-incremental:build-type/build-tags',
|
'legacy-build-id/version-incremental:build-type/build-tags',
|
||||||
build_info.fingerprint)
|
build_info.fingerprint)
|
||||||
|
|
||||||
self.assertRaises(common.ExternalError, common.BuildInfo, info_dict, None,
|
self.assertRaises(common.ExternalError, common.BuildInfo, info_dict, None,
|
||||||
False)
|
False)
|
||||||
@@ -241,9 +250,9 @@ class BuildInfoTest(test_utils.ReleaseToolsTestCase):
|
|||||||
info_dict['vbmeta_digest'] = 'abcde12345'
|
info_dict['vbmeta_digest'] = 'abcde12345'
|
||||||
build_info = common.BuildInfo(info_dict, use_legacy_id=False)
|
build_info = common.BuildInfo(info_dict, use_legacy_id=False)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
'product-brand/product-name/product-device:version-release/'
|
'product-brand/product-name/product-device:version-release/'
|
||||||
'legacy-build-id.abcde123/version-incremental:build-type/build-tags',
|
'legacy-build-id.abcde123/version-incremental:build-type/build-tags',
|
||||||
build_info.fingerprint)
|
build_info.fingerprint)
|
||||||
|
|
||||||
def test___getitem__(self):
|
def test___getitem__(self):
|
||||||
target_info = common.BuildInfo(self.TEST_INFO_DICT, None)
|
target_info = common.BuildInfo(self.TEST_INFO_DICT, None)
|
||||||
@@ -376,7 +385,7 @@ class BuildInfoTest(test_utils.ReleaseToolsTestCase):
|
|||||||
info_dict['build.prop'].build_props[
|
info_dict['build.prop'].build_props[
|
||||||
'ro.product.property_source_order'] = 'bad-source'
|
'ro.product.property_source_order'] = 'bad-source'
|
||||||
with self.assertRaisesRegexp(common.ExternalError,
|
with self.assertRaisesRegexp(common.ExternalError,
|
||||||
'Invalid ro.product.property_source_order'):
|
'Invalid ro.product.property_source_order'):
|
||||||
info = common.BuildInfo(info_dict, None)
|
info = common.BuildInfo(info_dict, None)
|
||||||
info.GetBuildProp('ro.product.device')
|
info.GetBuildProp('ro.product.device')
|
||||||
|
|
||||||
@@ -429,6 +438,13 @@ class CommonZipTest(test_utils.ReleaseToolsTestCase):
|
|||||||
self.assertIsNone(zip_file.testzip())
|
self.assertIsNone(zip_file.testzip())
|
||||||
|
|
||||||
def _test_ZipWrite(self, contents, extra_zipwrite_args=None):
|
def _test_ZipWrite(self, contents, extra_zipwrite_args=None):
|
||||||
|
with tempfile.NamedTemporaryFile() as test_file:
|
||||||
|
test_file_name = test_file.name
|
||||||
|
for data in contents:
|
||||||
|
test_file.write(bytes(data))
|
||||||
|
return self._test_ZipWriteFile(test_file_name, extra_zipwrite_args)
|
||||||
|
|
||||||
|
def _test_ZipWriteFile(self, test_file_name, extra_zipwrite_args=None):
|
||||||
extra_zipwrite_args = dict(extra_zipwrite_args or {})
|
extra_zipwrite_args = dict(extra_zipwrite_args or {})
|
||||||
|
|
||||||
test_file = tempfile.NamedTemporaryFile(delete=False)
|
test_file = tempfile.NamedTemporaryFile(delete=False)
|
||||||
@@ -441,17 +457,12 @@ class CommonZipTest(test_utils.ReleaseToolsTestCase):
|
|||||||
arcname = extra_zipwrite_args.get("arcname", test_file_name)
|
arcname = extra_zipwrite_args.get("arcname", test_file_name)
|
||||||
if arcname[0] == "/":
|
if arcname[0] == "/":
|
||||||
arcname = arcname[1:]
|
arcname = arcname[1:]
|
||||||
|
sha1_hash = hash_file(test_file_name)
|
||||||
|
|
||||||
zip_file.close()
|
zip_file.close()
|
||||||
zip_file = zipfile.ZipFile(zip_file_name, "w", allowZip64=True)
|
zip_file = zipfile.ZipFile(zip_file_name, "w", allowZip64=True)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
sha1_hash = sha1()
|
|
||||||
for data in contents:
|
|
||||||
sha1_hash.update(bytes(data))
|
|
||||||
test_file.write(bytes(data))
|
|
||||||
test_file.close()
|
|
||||||
|
|
||||||
expected_mode = extra_zipwrite_args.get("perms", 0o644)
|
expected_mode = extra_zipwrite_args.get("perms", 0o644)
|
||||||
expected_compress_type = extra_zipwrite_args.get("compress_type",
|
expected_compress_type = extra_zipwrite_args.get("compress_type",
|
||||||
zipfile.ZIP_STORED)
|
zipfile.ZIP_STORED)
|
||||||
@@ -467,7 +478,6 @@ class CommonZipTest(test_utils.ReleaseToolsTestCase):
|
|||||||
test_file_name, expected_stat, expected_mode,
|
test_file_name, expected_stat, expected_mode,
|
||||||
expected_compress_type)
|
expected_compress_type)
|
||||||
finally:
|
finally:
|
||||||
os.remove(test_file_name)
|
|
||||||
os.remove(zip_file_name)
|
os.remove(zip_file_name)
|
||||||
|
|
||||||
def _test_ZipWriteStr(self, zinfo_or_arcname, contents, extra_args=None):
|
def _test_ZipWriteStr(self, zinfo_or_arcname, contents, extra_args=None):
|
||||||
@@ -502,14 +512,13 @@ class CommonZipTest(test_utils.ReleaseToolsTestCase):
|
|||||||
finally:
|
finally:
|
||||||
os.remove(zip_file_name)
|
os.remove(zip_file_name)
|
||||||
|
|
||||||
def _test_ZipWriteStr_large_file(self, large, small, extra_args=None):
|
def _test_ZipWriteStr_large_file(self, large_file: BinaryIO, small, extra_args=None):
|
||||||
extra_args = dict(extra_args or {})
|
extra_args = dict(extra_args or {})
|
||||||
|
|
||||||
zip_file = tempfile.NamedTemporaryFile(delete=False)
|
zip_file = tempfile.NamedTemporaryFile(delete=False)
|
||||||
zip_file_name = zip_file.name
|
zip_file_name = zip_file.name
|
||||||
|
|
||||||
test_file = tempfile.NamedTemporaryFile(delete=False)
|
test_file_name = large_file.name
|
||||||
test_file_name = test_file.name
|
|
||||||
|
|
||||||
arcname_large = test_file_name
|
arcname_large = test_file_name
|
||||||
arcname_small = "bar"
|
arcname_small = "bar"
|
||||||
@@ -522,11 +531,7 @@ class CommonZipTest(test_utils.ReleaseToolsTestCase):
|
|||||||
zip_file = zipfile.ZipFile(zip_file_name, "w", allowZip64=True)
|
zip_file = zipfile.ZipFile(zip_file_name, "w", allowZip64=True)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
sha1_hash = sha1()
|
sha1_hash = hash_file(test_file_name)
|
||||||
for data in large:
|
|
||||||
sha1_hash.update(data)
|
|
||||||
test_file.write(data)
|
|
||||||
test_file.close()
|
|
||||||
|
|
||||||
# Arbitrary timestamp, just to make sure common.ZipWrite() restores
|
# Arbitrary timestamp, just to make sure common.ZipWrite() restores
|
||||||
# the timestamp after writing.
|
# the timestamp after writing.
|
||||||
@@ -551,7 +556,6 @@ class CommonZipTest(test_utils.ReleaseToolsTestCase):
|
|||||||
expected_compress_type=expected_compress_type)
|
expected_compress_type=expected_compress_type)
|
||||||
finally:
|
finally:
|
||||||
os.remove(zip_file_name)
|
os.remove(zip_file_name)
|
||||||
os.remove(test_file_name)
|
|
||||||
|
|
||||||
def _test_reset_ZIP64_LIMIT(self, func, *args):
|
def _test_reset_ZIP64_LIMIT(self, func, *args):
|
||||||
default_limit = (1 << 31) - 1
|
default_limit = (1 << 31) - 1
|
||||||
@@ -577,10 +581,10 @@ class CommonZipTest(test_utils.ReleaseToolsTestCase):
|
|||||||
})
|
})
|
||||||
|
|
||||||
def test_ZipWrite_large_file(self):
|
def test_ZipWrite_large_file(self):
|
||||||
file_contents = get_2gb_string()
|
with get_2gb_file() as tmpfile:
|
||||||
self._test_ZipWrite(file_contents, {
|
self._test_ZipWriteFile(tmpfile.name, {
|
||||||
"compress_type": zipfile.ZIP_DEFLATED,
|
"compress_type": zipfile.ZIP_DEFLATED,
|
||||||
})
|
})
|
||||||
|
|
||||||
def test_ZipWrite_resets_ZIP64_LIMIT(self):
|
def test_ZipWrite_resets_ZIP64_LIMIT(self):
|
||||||
self._test_reset_ZIP64_LIMIT(self._test_ZipWrite, "")
|
self._test_reset_ZIP64_LIMIT(self._test_ZipWrite, "")
|
||||||
@@ -627,11 +631,11 @@ class CommonZipTest(test_utils.ReleaseToolsTestCase):
|
|||||||
# zipfile.writestr() doesn't work when the str size is over 2GiB even with
|
# zipfile.writestr() doesn't work when the str size is over 2GiB even with
|
||||||
# the workaround. We will only test the case of writing a string into a
|
# the workaround. We will only test the case of writing a string into a
|
||||||
# large archive.
|
# large archive.
|
||||||
long_string = get_2gb_string()
|
|
||||||
short_string = os.urandom(1024)
|
short_string = os.urandom(1024)
|
||||||
self._test_ZipWriteStr_large_file(long_string, short_string, {
|
with get_2gb_file() as large_file:
|
||||||
"compress_type": zipfile.ZIP_DEFLATED,
|
self._test_ZipWriteStr_large_file(large_file, short_string, {
|
||||||
})
|
"compress_type": zipfile.ZIP_DEFLATED,
|
||||||
|
})
|
||||||
|
|
||||||
def test_ZipWriteStr_resets_ZIP64_LIMIT(self):
|
def test_ZipWriteStr_resets_ZIP64_LIMIT(self):
|
||||||
self._test_reset_ZIP64_LIMIT(self._test_ZipWriteStr, 'foo', b'')
|
self._test_reset_ZIP64_LIMIT(self._test_ZipWriteStr, 'foo', b'')
|
||||||
@@ -821,9 +825,9 @@ class CommonApkUtilsTest(test_utils.ReleaseToolsTestCase):
|
|||||||
)
|
)
|
||||||
|
|
||||||
APKCERTS_CERTMAP1 = {
|
APKCERTS_CERTMAP1 = {
|
||||||
'RecoveryLocalizer.apk' : 'certs/devkey',
|
'RecoveryLocalizer.apk': 'certs/devkey',
|
||||||
'Settings.apk' : 'build/make/target/product/security/platform',
|
'Settings.apk': 'build/make/target/product/security/platform',
|
||||||
'TV.apk' : 'PRESIGNED',
|
'TV.apk': 'PRESIGNED',
|
||||||
}
|
}
|
||||||
|
|
||||||
APKCERTS_TXT2 = (
|
APKCERTS_TXT2 = (
|
||||||
@@ -838,10 +842,10 @@ class CommonApkUtilsTest(test_utils.ReleaseToolsTestCase):
|
|||||||
)
|
)
|
||||||
|
|
||||||
APKCERTS_CERTMAP2 = {
|
APKCERTS_CERTMAP2 = {
|
||||||
'Compressed1.apk' : 'certs/compressed1',
|
'Compressed1.apk': 'certs/compressed1',
|
||||||
'Compressed2a.apk' : 'certs/compressed2',
|
'Compressed2a.apk': 'certs/compressed2',
|
||||||
'Compressed2b.apk' : 'certs/compressed2',
|
'Compressed2b.apk': 'certs/compressed2',
|
||||||
'Compressed3.apk' : 'certs/compressed3',
|
'Compressed3.apk': 'certs/compressed3',
|
||||||
}
|
}
|
||||||
|
|
||||||
APKCERTS_TXT3 = (
|
APKCERTS_TXT3 = (
|
||||||
@@ -850,7 +854,7 @@ class CommonApkUtilsTest(test_utils.ReleaseToolsTestCase):
|
|||||||
)
|
)
|
||||||
|
|
||||||
APKCERTS_CERTMAP3 = {
|
APKCERTS_CERTMAP3 = {
|
||||||
'Compressed4.apk' : 'certs/compressed4',
|
'Compressed4.apk': 'certs/compressed4',
|
||||||
}
|
}
|
||||||
|
|
||||||
# Test parsing with no optional fields, both optional fields, and only the
|
# Test parsing with no optional fields, both optional fields, and only the
|
||||||
@@ -867,9 +871,9 @@ class CommonApkUtilsTest(test_utils.ReleaseToolsTestCase):
|
|||||||
)
|
)
|
||||||
|
|
||||||
APKCERTS_CERTMAP4 = {
|
APKCERTS_CERTMAP4 = {
|
||||||
'RecoveryLocalizer.apk' : 'certs/devkey',
|
'RecoveryLocalizer.apk': 'certs/devkey',
|
||||||
'Settings.apk' : 'build/make/target/product/security/platform',
|
'Settings.apk': 'build/make/target/product/security/platform',
|
||||||
'TV.apk' : 'PRESIGNED',
|
'TV.apk': 'PRESIGNED',
|
||||||
}
|
}
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
@@ -973,7 +977,7 @@ class CommonApkUtilsTest(test_utils.ReleaseToolsTestCase):
|
|||||||
extracted_from_privkey = common.ExtractAvbPublicKey('avbtool', privkey)
|
extracted_from_privkey = common.ExtractAvbPublicKey('avbtool', privkey)
|
||||||
extracted_from_pubkey = common.ExtractAvbPublicKey('avbtool', pubkey)
|
extracted_from_pubkey = common.ExtractAvbPublicKey('avbtool', pubkey)
|
||||||
with open(extracted_from_privkey, 'rb') as privkey_fp, \
|
with open(extracted_from_privkey, 'rb') as privkey_fp, \
|
||||||
open(extracted_from_pubkey, 'rb') as pubkey_fp:
|
open(extracted_from_pubkey, 'rb') as pubkey_fp:
|
||||||
self.assertEqual(privkey_fp.read(), pubkey_fp.read())
|
self.assertEqual(privkey_fp.read(), pubkey_fp.read())
|
||||||
|
|
||||||
def test_ParseCertificate(self):
|
def test_ParseCertificate(self):
|
||||||
@@ -1237,7 +1241,8 @@ class CommonUtilsTest(test_utils.ReleaseToolsTestCase):
|
|||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
'1-5 9-10',
|
'1-5 9-10',
|
||||||
sparse_image.file_map['//system/file1'].extra['text_str'])
|
sparse_image.file_map['//system/file1'].extra['text_str'])
|
||||||
self.assertTrue(sparse_image.file_map['//system/file2'].extra['incomplete'])
|
self.assertTrue(
|
||||||
|
sparse_image.file_map['//system/file2'].extra['incomplete'])
|
||||||
self.assertTrue(
|
self.assertTrue(
|
||||||
sparse_image.file_map['/system/app/file3'].extra['incomplete'])
|
sparse_image.file_map['/system/app/file3'].extra['incomplete'])
|
||||||
|
|
||||||
@@ -1345,7 +1350,7 @@ class CommonUtilsTest(test_utils.ReleaseToolsTestCase):
|
|||||||
'recovery_api_version': 3,
|
'recovery_api_version': 3,
|
||||||
'fstab_version': 2,
|
'fstab_version': 2,
|
||||||
'system_root_image': 'true',
|
'system_root_image': 'true',
|
||||||
'no_recovery' : 'true',
|
'no_recovery': 'true',
|
||||||
'recovery_as_boot': 'true',
|
'recovery_as_boot': 'true',
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1667,6 +1672,7 @@ class CommonUtilsTest(test_utils.ReleaseToolsTestCase):
|
|||||||
self.assertRaises(common.ExternalError, common._GenerateGkiCertificate,
|
self.assertRaises(common.ExternalError, common._GenerateGkiCertificate,
|
||||||
test_file.name, 'generic_kernel')
|
test_file.name, 'generic_kernel')
|
||||||
|
|
||||||
|
|
||||||
class InstallRecoveryScriptFormatTest(test_utils.ReleaseToolsTestCase):
|
class InstallRecoveryScriptFormatTest(test_utils.ReleaseToolsTestCase):
|
||||||
"""Checks the format of install-recovery.sh.
|
"""Checks the format of install-recovery.sh.
|
||||||
|
|
||||||
@@ -1676,7 +1682,7 @@ class InstallRecoveryScriptFormatTest(test_utils.ReleaseToolsTestCase):
|
|||||||
def setUp(self):
|
def setUp(self):
|
||||||
self._tempdir = common.MakeTempDir()
|
self._tempdir = common.MakeTempDir()
|
||||||
# Create a fake dict that contains the fstab info for boot&recovery.
|
# Create a fake dict that contains the fstab info for boot&recovery.
|
||||||
self._info = {"fstab" : {}}
|
self._info = {"fstab": {}}
|
||||||
fake_fstab = [
|
fake_fstab = [
|
||||||
"/dev/soc.0/by-name/boot /boot emmc defaults defaults",
|
"/dev/soc.0/by-name/boot /boot emmc defaults defaults",
|
||||||
"/dev/soc.0/by-name/recovery /recovery emmc defaults defaults"]
|
"/dev/soc.0/by-name/recovery /recovery emmc defaults defaults"]
|
||||||
@@ -2023,11 +2029,11 @@ class PartitionBuildPropsTest(test_utils.ReleaseToolsTestCase):
|
|||||||
input_zip, 'odm', placeholder_values)
|
input_zip, 'odm', placeholder_values)
|
||||||
|
|
||||||
self.assertEqual({
|
self.assertEqual({
|
||||||
'ro.odm.build.date.utc': '1578430045',
|
'ro.odm.build.date.utc': '1578430045',
|
||||||
'ro.odm.build.fingerprint':
|
'ro.odm.build.fingerprint':
|
||||||
'google/coral/coral:10/RP1A.200325.001/6337676:user/dev-keys',
|
'google/coral/coral:10/RP1A.200325.001/6337676:user/dev-keys',
|
||||||
'ro.product.odm.device': 'coral',
|
'ro.product.odm.device': 'coral',
|
||||||
'ro.product.odm.name': 'product1',
|
'ro.product.odm.name': 'product1',
|
||||||
}, partition_props.build_props)
|
}, partition_props.build_props)
|
||||||
|
|
||||||
with zipfile.ZipFile(input_file, 'r', allowZip64=True) as input_zip:
|
with zipfile.ZipFile(input_file, 'r', allowZip64=True) as input_zip:
|
||||||
@@ -2210,8 +2216,8 @@ class PartitionBuildPropsTest(test_utils.ReleaseToolsTestCase):
|
|||||||
|
|
||||||
copied_props = copy.deepcopy(partition_props)
|
copied_props = copy.deepcopy(partition_props)
|
||||||
self.assertEqual({
|
self.assertEqual({
|
||||||
'ro.odm.build.date.utc': '1578430045',
|
'ro.odm.build.date.utc': '1578430045',
|
||||||
'ro.odm.build.fingerprint':
|
'ro.odm.build.fingerprint':
|
||||||
'google/coral/coral:10/RP1A.200325.001/6337676:user/dev-keys',
|
'google/coral/coral:10/RP1A.200325.001/6337676:user/dev-keys',
|
||||||
'ro.product.odm.device': 'coral',
|
'ro.product.odm.device': 'coral',
|
||||||
}, copied_props.build_props)
|
}, copied_props.build_props)
|
||||||
|
Reference in New Issue
Block a user