relesetools: Enable releasetools_test in presubmit.
About half of the testcases rely on external tools (i.e. the ones in
`otatools.zip`, which are external to releasetools module, but still
built by Android). It's WAI as releasetools scripts are mostly for
gluing purpose.
However, the current support in Soong doesn't allow packing the helper
modules as part of the built releasetools_test. This CL adds a decorator
that allows declaring external dependencies in testcases, which will be
skipped while running in presubmit. It doesn't affect local invocation
of `atest releasetools_test`.
Fixes: 112080715
Test: `atest releasetools_test`
Test: TreeHugger; check that releasetools_test is invoked (and test
passes).
Change-Id: I8fdeb6549023cf5ddeb79d610c7c37cf9f13d3cc
diff --git a/tools/releasetools/TEST_MAPPING b/tools/releasetools/TEST_MAPPING
new file mode 100644
index 0000000..77cef07
--- /dev/null
+++ b/tools/releasetools/TEST_MAPPING
@@ -0,0 +1,8 @@
+{
+ "presubmit": [
+ {
+ "name": "releasetools_test",
+ "host": true
+ }
+ ]
+}
diff --git a/tools/releasetools/test_add_img_to_target_files.py b/tools/releasetools/test_add_img_to_target_files.py
index 482f86c..013ade6 100644
--- a/tools/releasetools/test_add_img_to_target_files.py
+++ b/tools/releasetools/test_add_img_to_target_files.py
@@ -34,18 +34,6 @@
def setUp(self):
OPTIONS.input_tmp = common.MakeTempDir()
- def _verifyCareMap(self, expected, file_name):
- """Parses the care_map.pb; and checks the content in plain text."""
- text_file = common.MakeTempFile(prefix="caremap-", suffix=".txt")
-
- # Calls an external binary to convert the proto message.
- cmd = ["care_map_generator", "--parse_proto", file_name, text_file]
- common.RunAndCheckOutput(cmd)
-
- with open(text_file, 'r') as verify_fp:
- plain_text = verify_fp.read()
- self.assertEqual('\n'.join(expected), plain_text)
-
@staticmethod
def _create_images(images, prefix):
"""Creates images under OPTIONS.input_tmp/prefix."""
@@ -164,6 +152,19 @@
}
return image_paths
+ def _verifyCareMap(self, expected, file_name):
+ """Parses the care_map.pb; and checks the content in plain text."""
+ text_file = common.MakeTempFile(prefix="caremap-", suffix=".txt")
+
+ # Calls an external binary to convert the proto message.
+ cmd = ["care_map_generator", "--parse_proto", file_name, text_file]
+ common.RunAndCheckOutput(cmd)
+
+ with open(text_file) as verify_fp:
+ plain_text = verify_fp.read()
+ self.assertEqual('\n'.join(expected), plain_text)
+
+ @test_utils.SkipIfExternalToolsUnavailable()
def test_AddCareMapForAbOta(self):
image_paths = self._test_AddCareMapForAbOta()
@@ -179,6 +180,7 @@
self._verifyCareMap(expected, care_map_file)
+ @test_utils.SkipIfExternalToolsUnavailable()
def test_AddCareMapForAbOta_withNonCareMapPartitions(self):
"""Partitions without care_map should be ignored."""
image_paths = self._test_AddCareMapForAbOta()
@@ -196,6 +198,7 @@
self._verifyCareMap(expected, care_map_file)
+ @test_utils.SkipIfExternalToolsUnavailable()
def test_AddCareMapForAbOta_withAvb(self):
"""Tests the case for device using AVB."""
image_paths = self._test_AddCareMapForAbOta()
@@ -223,6 +226,7 @@
self._verifyCareMap(expected, care_map_file)
+ @test_utils.SkipIfExternalToolsUnavailable()
def test_AddCareMapForAbOta_noFingerprint(self):
"""Tests the case for partitions without fingerprint."""
image_paths = self._test_AddCareMapForAbOta()
@@ -240,6 +244,7 @@
self._verifyCareMap(expected, care_map_file)
+ @test_utils.SkipIfExternalToolsUnavailable()
def test_AddCareMapForAbOta_withThumbprint(self):
"""Tests the case for partitions with thumbprint."""
image_paths = self._test_AddCareMapForAbOta()
@@ -282,6 +287,7 @@
self.assertRaises(AssertionError, AddCareMapForAbOta, None,
['system', 'vendor'], image_paths)
+ @test_utils.SkipIfExternalToolsUnavailable()
def test_AddCareMapForAbOta_zipOutput(self):
"""Tests the case with ZIP output."""
image_paths = self._test_AddCareMapForAbOta()
@@ -304,6 +310,7 @@
"google/sailfish/678:user/dev-keys"]
self._verifyCareMap(expected, os.path.join(temp_dir, care_map_name))
+ @test_utils.SkipIfExternalToolsUnavailable()
def test_AddCareMapForAbOta_zipOutput_careMapEntryExists(self):
"""Tests the case with ZIP output which already has care_map entry."""
image_paths = self._test_AddCareMapForAbOta()
@@ -338,6 +345,7 @@
self.assertEqual(
['--include_descriptors_from_image', '/path/to/system.img'], cmd)
+ @test_utils.SkipIfExternalToolsUnavailable()
def test_AppendVBMetaArgsForPartition_vendorAsChainedPartition(self):
testdata_dir = test_utils.get_testdata_dir()
pubkey = os.path.join(testdata_dir, 'testkey.pubkey.pem')
diff --git a/tools/releasetools/test_apex_utils.py b/tools/releasetools/test_apex_utils.py
index 76d4d58..c7d5807 100644
--- a/tools/releasetools/test_apex_utils.py
+++ b/tools/releasetools/test_apex_utils.py
@@ -39,6 +39,7 @@
payload_fp.write(os.urandom(8192))
return payload_file
+ @test_utils.SkipIfExternalToolsUnavailable()
def test_ParseApexPayloadInfo(self):
payload_file = self._GetTestPayload()
apex_utils.SignApexPayload(
@@ -48,12 +49,14 @@
self.assertEqual(self.SALT, payload_info['Salt'])
self.assertEqual('testkey', payload_info['apex.key'])
+ @test_utils.SkipIfExternalToolsUnavailable()
def test_SignApexPayload(self):
payload_file = self._GetTestPayload()
apex_utils.SignApexPayload(
payload_file, self.payload_key, 'testkey', 'SHA256_RSA2048', self.SALT)
apex_utils.VerifyApexPayload(payload_file, self.payload_key)
+ @test_utils.SkipIfExternalToolsUnavailable()
def test_SignApexPayload_withSignerHelper(self):
payload_file = self._GetTestPayload()
signing_helper = os.path.join(self.testdata_dir, 'signing_helper.sh')
@@ -67,6 +70,7 @@
payload_signer_args)
apex_utils.VerifyApexPayload(payload_file, self.payload_key)
+ @test_utils.SkipIfExternalToolsUnavailable()
def test_SignApexPayload_invalidKey(self):
self.assertRaises(
apex_utils.ApexSigningError,
@@ -77,6 +81,7 @@
'SHA256_RSA2048',
self.SALT)
+ @test_utils.SkipIfExternalToolsUnavailable()
def test_VerifyApexPayload_wrongKey(self):
payload_file = self._GetTestPayload()
apex_utils.SignApexPayload(
diff --git a/tools/releasetools/test_build_image.py b/tools/releasetools/test_build_image.py
index 1cebd0c..b24805f 100644
--- a/tools/releasetools/test_build_image.py
+++ b/tools/releasetools/test_build_image.py
@@ -18,12 +18,13 @@
import os.path
import common
+import test_utils
from build_image import (
- BuildImageError, CheckHeadroom, GetFilesystemCharacteristics, SetUpInDirAndFsConfig)
-from test_utils import ReleaseToolsTestCase
+ BuildImageError, CheckHeadroom, GetFilesystemCharacteristics,
+ SetUpInDirAndFsConfig)
-class BuildImageTest(ReleaseToolsTestCase):
+class BuildImageTest(test_utils.ReleaseToolsTestCase):
# Available: 1000 blocks.
EXT4FS_OUTPUT = (
@@ -48,6 +49,7 @@
self.assertRaises(
BuildImageError, CheckHeadroom, self.EXT4FS_OUTPUT, prop_dict)
+ @test_utils.SkipIfExternalToolsUnavailable()
def test_CheckHeadroom_WrongFsType(self):
prop_dict = {
'fs_type' : 'f2fs',
@@ -72,6 +74,7 @@
self.assertRaises(
AssertionError, CheckHeadroom, self.EXT4FS_OUTPUT, prop_dict)
+ @test_utils.SkipIfExternalToolsUnavailable()
def test_CheckHeadroom_WithMke2fsOutput(self):
"""Tests the result parsing from actual call to mke2fs."""
input_dir = common.MakeTempDir()
@@ -177,13 +180,14 @@
self.assertIn('fs-config-root\n', fs_config_data)
self.assertEqual('/', prop_dict['mount_point'])
+ @test_utils.SkipIfExternalToolsUnavailable()
def test_GetFilesystemCharacteristics(self):
input_dir = common.MakeTempDir()
output_image = common.MakeTempFile(suffix='.img')
command = ['mkuserimg_mke2fs', input_dir, output_image, 'ext4',
'/system', '409600', '-j', '0']
proc = common.Run(command)
- ext4fs_output, _ = proc.communicate()
+ proc.communicate()
self.assertEqual(0, proc.returncode)
output_file = common.MakeTempFile(suffix='.img')
diff --git a/tools/releasetools/test_common.py b/tools/releasetools/test_common.py
index 89add40..9b76734 100644
--- a/tools/releasetools/test_common.py
+++ b/tools/releasetools/test_common.py
@@ -315,6 +315,7 @@
finally:
os.remove(zip_file_name)
+ @test_utils.SkipIfExternalToolsUnavailable()
def test_ZipDelete(self):
zip_file = tempfile.NamedTemporaryFile(delete=False, suffix='.zip')
output_zip = zipfile.ZipFile(zip_file.name, 'w',
@@ -376,6 +377,7 @@
common.ZipClose(output_zip)
return zip_file
+ @test_utils.SkipIfExternalToolsUnavailable()
def test_UnzipTemp(self):
zip_file = self._test_UnzipTemp_createZipFile()
unzipped_dir = common.UnzipTemp(zip_file)
@@ -385,6 +387,7 @@
self.assertTrue(os.path.exists(os.path.join(unzipped_dir, 'Bar4')))
self.assertTrue(os.path.exists(os.path.join(unzipped_dir, 'Dir5/Baz5')))
+ @test_utils.SkipIfExternalToolsUnavailable()
def test_UnzipTemp_withPatterns(self):
zip_file = self._test_UnzipTemp_createZipFile()
@@ -425,6 +428,7 @@
self.assertFalse(os.path.exists(os.path.join(unzipped_dir, 'Bar4')))
self.assertFalse(os.path.exists(os.path.join(unzipped_dir, 'Dir5/Baz5')))
+ @test_utils.SkipIfExternalToolsUnavailable()
def test_UnzipTemp_withPartiallyMatchingPatterns(self):
zip_file = self._test_UnzipTemp_createZipFile()
unzipped_dir = common.UnzipTemp(zip_file, ['Test*', 'Nonexistent*'])
@@ -575,6 +579,7 @@
wrong_input = os.path.join(self.testdata_dir, 'testkey.pk8')
self.assertRaises(AssertionError, common.ExtractPublicKey, wrong_input)
+ @test_utils.SkipIfExternalToolsUnavailable()
def test_ExtractAvbPublicKey(self):
privkey = os.path.join(self.testdata_dir, 'testkey.key')
pubkey = os.path.join(self.testdata_dir, 'testkey.pubkey.pem')
@@ -594,18 +599,22 @@
actual = common.ParseCertificate(cert_fp.read())
self.assertEqual(expected, actual)
+ @test_utils.SkipIfExternalToolsUnavailable()
def test_GetMinSdkVersion(self):
test_app = os.path.join(self.testdata_dir, 'TestApp.apk')
self.assertEqual('24', common.GetMinSdkVersion(test_app))
+ @test_utils.SkipIfExternalToolsUnavailable()
def test_GetMinSdkVersion_invalidInput(self):
self.assertRaises(
common.ExternalError, common.GetMinSdkVersion, 'does-not-exist.apk')
+ @test_utils.SkipIfExternalToolsUnavailable()
def test_GetMinSdkVersionInt(self):
test_app = os.path.join(self.testdata_dir, 'TestApp.apk')
self.assertEqual(24, common.GetMinSdkVersionInt(test_app, {}))
+ @test_utils.SkipIfExternalToolsUnavailable()
def test_GetMinSdkVersionInt_invalidInput(self):
self.assertRaises(
common.ExternalError, common.GetMinSdkVersionInt, 'does-not-exist.apk',
@@ -617,6 +626,7 @@
def setUp(self):
self.testdata_dir = test_utils.get_testdata_dir()
+ @test_utils.SkipIfExternalToolsUnavailable()
def test_GetSparseImage_emptyBlockMapFile(self):
target_files = common.MakeTempFile(prefix='target_files-', suffix='.zip')
with zipfile.ZipFile(target_files, 'w') as target_files_zip:
@@ -649,6 +659,7 @@
AssertionError, common.GetSparseImage, 'unknown', self.testdata_dir,
None, False)
+ @test_utils.SkipIfExternalToolsUnavailable()
def test_GetSparseImage_missingBlockMapFile(self):
target_files = common.MakeTempFile(prefix='target_files-', suffix='.zip')
with zipfile.ZipFile(target_files, 'w') as target_files_zip:
@@ -667,6 +678,7 @@
AssertionError, common.GetSparseImage, 'system', tempdir, input_zip,
False)
+ @test_utils.SkipIfExternalToolsUnavailable()
def test_GetSparseImage_sharedBlocks_notAllowed(self):
"""Tests the case of having overlapping blocks but disallowed."""
target_files = common.MakeTempFile(prefix='target_files-', suffix='.zip')
@@ -689,6 +701,7 @@
AssertionError, common.GetSparseImage, 'system', tempdir, input_zip,
False)
+ @test_utils.SkipIfExternalToolsUnavailable()
def test_GetSparseImage_sharedBlocks_allowed(self):
"""Tests the case for target using BOARD_EXT4_SHARE_DUP_BLOCKS := true."""
target_files = common.MakeTempFile(prefix='target_files-', suffix='.zip')
@@ -731,6 +744,7 @@
self.assertFalse(sparse_image.file_map['__NONZERO-0'].extra)
self.assertFalse(sparse_image.file_map['/system/file1'].extra)
+ @test_utils.SkipIfExternalToolsUnavailable()
def test_GetSparseImage_incompleteRanges(self):
"""Tests the case of ext4 images with holes."""
target_files = common.MakeTempFile(prefix='target_files-', suffix='.zip')
@@ -754,6 +768,7 @@
self.assertFalse(sparse_image.file_map['/system/file1'].extra)
self.assertTrue(sparse_image.file_map['/system/file2'].extra['incomplete'])
+ @test_utils.SkipIfExternalToolsUnavailable()
def test_GetSparseImage_systemRootImage_filenameWithExtraLeadingSlash(self):
target_files = common.MakeTempFile(prefix='target_files-', suffix='.zip')
with zipfile.ZipFile(target_files, 'w') as target_files_zip:
@@ -781,6 +796,7 @@
self.assertTrue(
sparse_image.file_map['/system/app/file3'].extra['incomplete'])
+ @test_utils.SkipIfExternalToolsUnavailable()
def test_GetSparseImage_systemRootImage_nonSystemFiles(self):
target_files = common.MakeTempFile(prefix='target_files-', suffix='.zip')
with zipfile.ZipFile(target_files, 'w') as target_files_zip:
@@ -803,6 +819,7 @@
self.assertFalse(sparse_image.file_map['//system/file1'].extra)
self.assertTrue(sparse_image.file_map['//init.rc'].extra['incomplete'])
+ @test_utils.SkipIfExternalToolsUnavailable()
def test_GetSparseImage_fileNotFound(self):
target_files = common.MakeTempFile(prefix='target_files-', suffix='.zip')
with zipfile.ZipFile(target_files, 'w') as target_files_zip:
@@ -822,6 +839,7 @@
AssertionError, common.GetSparseImage, 'system', tempdir, input_zip,
False)
+ @test_utils.SkipIfExternalToolsUnavailable()
def test_GetAvbChainedPartitionArg(self):
pubkey = os.path.join(self.testdata_dir, 'testkey.pubkey.pem')
info_dict = {
@@ -835,6 +853,7 @@
self.assertEqual('2', args[1])
self.assertTrue(os.path.exists(args[2]))
+ @test_utils.SkipIfExternalToolsUnavailable()
def test_GetAvbChainedPartitionArg_withPrivateKey(self):
key = os.path.join(self.testdata_dir, 'testkey.key')
info_dict = {
@@ -848,6 +867,7 @@
self.assertEqual('2', args[1])
self.assertTrue(os.path.exists(args[2]))
+ @test_utils.SkipIfExternalToolsUnavailable()
def test_GetAvbChainedPartitionArg_withSpecifiedKey(self):
info_dict = {
'avb_avbtool': 'avbtool',
@@ -862,6 +882,7 @@
self.assertEqual('2', args[1])
self.assertTrue(os.path.exists(args[2]))
+ @test_utils.SkipIfExternalToolsUnavailable()
def test_GetAvbChainedPartitionArg_invalidKey(self):
pubkey = os.path.join(self.testdata_dir, 'testkey_with_passwd.x509.pem')
info_dict = {
@@ -922,6 +943,7 @@
self.assertIn('/', loaded_dict['fstab'])
self.assertIn('/system', loaded_dict['fstab'])
+ @test_utils.SkipIfExternalToolsUnavailable()
def test_LoadInfoDict_dirInput(self):
target_files = self._test_LoadInfoDict_createTargetFiles(
self.INFO_DICT_DEFAULT,
@@ -933,6 +955,7 @@
self.assertIn('/', loaded_dict['fstab'])
self.assertIn('/system', loaded_dict['fstab'])
+ @test_utils.SkipIfExternalToolsUnavailable()
def test_LoadInfoDict_dirInput_legacyRecoveryFstabPath(self):
target_files = self._test_LoadInfoDict_createTargetFiles(
self.INFO_DICT_DEFAULT,
@@ -990,6 +1013,7 @@
self.assertEqual(2, loaded_dict['fstab_version'])
self.assertIsNone(loaded_dict['fstab'])
+ @test_utils.SkipIfExternalToolsUnavailable()
def test_LoadInfoDict_missingMetaMiscInfoTxt(self):
target_files = self._test_LoadInfoDict_createTargetFiles(
self.INFO_DICT_DEFAULT,
@@ -998,6 +1022,7 @@
with zipfile.ZipFile(target_files, 'r') as target_files_zip:
self.assertRaises(ValueError, common.LoadInfoDict, target_files_zip)
+ @test_utils.SkipIfExternalToolsUnavailable()
def test_LoadInfoDict_repacking(self):
target_files = self._test_LoadInfoDict_createTargetFiles(
self.INFO_DICT_DEFAULT,
@@ -1066,6 +1091,7 @@
validate_target_files.ValidateInstallRecoveryScript(self._tempdir,
self._info)
+ @test_utils.SkipIfExternalToolsUnavailable()
def test_recovery_from_boot(self):
recovery_image = common.File("recovery.img", self.recovery_data)
self._out_tmp_sink("recovery.img", recovery_image.data, "IMAGES")
diff --git a/tools/releasetools/test_merge_target_files.py b/tools/releasetools/test_merge_target_files.py
index bb9ce8e..ec452a8 100644
--- a/tools/releasetools/test_merge_target_files.py
+++ b/tools/releasetools/test_merge_target_files.py
@@ -16,7 +16,6 @@
import os.path
-import common
import test_utils
from merge_target_files import (
read_config_list, validate_config_lists, default_system_item_list,
diff --git a/tools/releasetools/test_ota_from_target_files.py b/tools/releasetools/test_ota_from_target_files.py
index bb0236b..bf94cc2 100644
--- a/tools/releasetools/test_ota_from_target_files.py
+++ b/tools/releasetools/test_ota_from_target_files.py
@@ -427,6 +427,7 @@
common.OPTIONS.search_path = test_utils.get_search_path()
self.assertIsNotNone(common.OPTIONS.search_path)
+ @test_utils.SkipIfExternalToolsUnavailable()
def test_GetPackageMetadata_abOta_full(self):
target_info_dict = copy.deepcopy(self.TEST_TARGET_INFO_DICT)
target_info_dict['ab_update'] = 'true'
@@ -445,6 +446,7 @@
},
metadata)
+ @test_utils.SkipIfExternalToolsUnavailable()
def test_GetPackageMetadata_abOta_incremental(self):
target_info_dict = copy.deepcopy(self.TEST_TARGET_INFO_DICT)
target_info_dict['ab_update'] = 'true'
@@ -467,6 +469,7 @@
},
metadata)
+ @test_utils.SkipIfExternalToolsUnavailable()
def test_GetPackageMetadata_nonAbOta_full(self):
target_info = BuildInfo(self.TEST_TARGET_INFO_DICT, None)
metadata = GetPackageMetadata(target_info)
@@ -482,6 +485,7 @@
},
metadata)
+ @test_utils.SkipIfExternalToolsUnavailable()
def test_GetPackageMetadata_nonAbOta_incremental(self):
target_info = BuildInfo(self.TEST_TARGET_INFO_DICT, None)
source_info = BuildInfo(self.TEST_SOURCE_INFO_DICT, None)
@@ -501,6 +505,7 @@
},
metadata)
+ @test_utils.SkipIfExternalToolsUnavailable()
def test_GetPackageMetadata_wipe(self):
target_info = BuildInfo(self.TEST_TARGET_INFO_DICT, None)
common.OPTIONS.wipe_user_data = True
@@ -518,6 +523,7 @@
},
metadata)
+ @test_utils.SkipIfExternalToolsUnavailable()
def test_GetPackageMetadata_retrofitDynamicPartitions(self):
target_info = BuildInfo(self.TEST_TARGET_INFO_DICT, None)
common.OPTIONS.retrofit_dynamic_partitions = True
@@ -542,6 +548,7 @@
source_info['build.prop']['ro.build.date.utc'],
target_info['build.prop']['ro.build.date.utc'])
+ @test_utils.SkipIfExternalToolsUnavailable()
def test_GetPackageMetadata_unintentionalDowngradeDetected(self):
target_info_dict = copy.deepcopy(self.TEST_TARGET_INFO_DICT)
source_info_dict = copy.deepcopy(self.TEST_SOURCE_INFO_DICT)
@@ -554,6 +561,7 @@
self.assertRaises(RuntimeError, GetPackageMetadata, target_info,
source_info)
+ @test_utils.SkipIfExternalToolsUnavailable()
def test_GetPackageMetadata_downgrade(self):
target_info_dict = copy.deepcopy(self.TEST_TARGET_INFO_DICT)
source_info_dict = copy.deepcopy(self.TEST_SOURCE_INFO_DICT)
@@ -582,6 +590,7 @@
},
metadata)
+ @test_utils.SkipIfExternalToolsUnavailable()
def test_GetTargetFilesZipForSecondaryImages(self):
input_file = construct_target_files(secondary=True)
target_file = GetTargetFilesZipForSecondaryImages(input_file)
@@ -600,6 +609,7 @@
self.assertNotIn('IMAGES/system_other.img', namelist)
self.assertNotIn('IMAGES/system.map', namelist)
+ @test_utils.SkipIfExternalToolsUnavailable()
def test_GetTargetFilesZipForSecondaryImages_skipPostinstall(self):
input_file = construct_target_files(secondary=True)
target_file = GetTargetFilesZipForSecondaryImages(
@@ -619,6 +629,7 @@
self.assertNotIn('IMAGES/system.map', namelist)
self.assertNotIn(POSTINSTALL_CONFIG, namelist)
+ @test_utils.SkipIfExternalToolsUnavailable()
def test_GetTargetFilesZipForSecondaryImages_withoutRadioImages(self):
input_file = construct_target_files(secondary=True)
common.ZipDelete(input_file, 'RADIO/bootloader.img')
@@ -639,12 +650,14 @@
self.assertNotIn('RADIO/bootloader.img', namelist)
self.assertNotIn('RADIO/modem.img', namelist)
+ @test_utils.SkipIfExternalToolsUnavailable()
def test_GetTargetFilesZipWithoutPostinstallConfig(self):
input_file = construct_target_files()
target_file = GetTargetFilesZipWithoutPostinstallConfig(input_file)
with zipfile.ZipFile(target_file) as verify_zip:
self.assertNotIn(POSTINSTALL_CONFIG, verify_zip.namelist())
+ @test_utils.SkipIfExternalToolsUnavailable()
def test_GetTargetFilesZipWithoutPostinstallConfig_missingEntry(self):
input_file = construct_target_files()
common.ZipDelete(input_file, POSTINSTALL_CONFIG)
@@ -675,20 +688,25 @@
FinalizeMetadata(metadata, zip_file, output_file, needed_property_files)
self.assertIn('ota-test-property-files', metadata)
+ @test_utils.SkipIfExternalToolsUnavailable()
def test_FinalizeMetadata(self):
self._test_FinalizeMetadata()
+ @test_utils.SkipIfExternalToolsUnavailable()
def test_FinalizeMetadata_withNoSigning(self):
common.OPTIONS.no_signing = True
self._test_FinalizeMetadata()
+ @test_utils.SkipIfExternalToolsUnavailable()
def test_FinalizeMetadata_largeEntry(self):
self._test_FinalizeMetadata(large_entry=True)
+ @test_utils.SkipIfExternalToolsUnavailable()
def test_FinalizeMetadata_largeEntry_withNoSigning(self):
common.OPTIONS.no_signing = True
self._test_FinalizeMetadata(large_entry=True)
+ @test_utils.SkipIfExternalToolsUnavailable()
def test_FinalizeMetadata_insufficientSpace(self):
entries = [
'required-entry1',
@@ -766,6 +784,7 @@
expected = entry.replace('.', '-').upper().encode()
self.assertEqual(expected, input_fp.read(size))
+ @test_utils.SkipIfExternalToolsUnavailable()
def test_Compute(self):
entries = (
'required-entry1',
@@ -805,6 +824,7 @@
with zipfile.ZipFile(zip_file, 'r') as zip_fp:
self.assertRaises(KeyError, property_files.Compute, zip_fp)
+ @test_utils.SkipIfExternalToolsUnavailable()
def test_Finalize(self):
entries = [
'required-entry1',
@@ -825,6 +845,7 @@
entries[2] = 'metadata'
self._verify_entries(zip_file, tokens, entries)
+ @test_utils.SkipIfExternalToolsUnavailable()
def test_Finalize_assertReservedLength(self):
entries = (
'required-entry1',
@@ -998,6 +1019,7 @@
),
property_files.optional)
+ @test_utils.SkipIfExternalToolsUnavailable()
def test_GetPayloadMetadataOffsetAndSize(self):
target_file = construct_target_files()
payload = Payload()
@@ -1071,6 +1093,7 @@
return zip_file
+ @test_utils.SkipIfExternalToolsUnavailable()
def test_Compute(self):
zip_file = self.construct_zip_package_withValidPayload()
property_files = AbOtaPropertyFiles()
@@ -1084,6 +1107,7 @@
self._verify_entries(
zip_file, tokens, ('care_map.txt', 'compatibility.zip'))
+ @test_utils.SkipIfExternalToolsUnavailable()
def test_Finalize(self):
zip_file = self.construct_zip_package_withValidPayload(with_metadata=True)
property_files = AbOtaPropertyFiles()
@@ -1099,6 +1123,7 @@
self._verify_entries(
zip_file, tokens, ('care_map.txt', 'compatibility.zip'))
+ @test_utils.SkipIfExternalToolsUnavailable()
def test_Verify(self):
zip_file = self.construct_zip_package_withValidPayload(with_metadata=True)
property_files = AbOtaPropertyFiles()
@@ -1204,6 +1229,7 @@
def test_GetKeySizeInBytes_512Bytes(self):
signing_key = os.path.join(self.testdata_dir, 'testkey_RSA4096.key')
+ # pylint: disable=protected-access
key_size = PayloadSigner._GetKeySizeInBytes(signing_key)
self.assertEqual(512, key_size)
@@ -1273,14 +1299,17 @@
payload.Generate(target_file, source_file)
return payload
+ @test_utils.SkipIfExternalToolsUnavailable()
def test_Generate_full(self):
payload = self._create_payload_full()
self.assertTrue(os.path.exists(payload.payload_file))
+ @test_utils.SkipIfExternalToolsUnavailable()
def test_Generate_incremental(self):
payload = self._create_payload_incremental()
self.assertTrue(os.path.exists(payload.payload_file))
+ @test_utils.SkipIfExternalToolsUnavailable()
def test_Generate_additionalArgs(self):
target_file = construct_target_files()
source_file = construct_target_files()
@@ -1291,12 +1320,14 @@
target_file, additional_args=["--source_image", source_file])
self.assertTrue(os.path.exists(payload.payload_file))
+ @test_utils.SkipIfExternalToolsUnavailable()
def test_Generate_invalidInput(self):
target_file = construct_target_files()
common.ZipDelete(target_file, 'IMAGES/vendor.img')
payload = Payload()
self.assertRaises(common.ExternalError, payload.Generate, target_file)
+ @test_utils.SkipIfExternalToolsUnavailable()
def test_Sign_full(self):
payload = self._create_payload_full()
payload.Sign(PayloadSigner())
@@ -1310,6 +1341,7 @@
os.path.join(self.testdata_dir, 'testkey.x509.pem'),
output_file)
+ @test_utils.SkipIfExternalToolsUnavailable()
def test_Sign_incremental(self):
payload = self._create_payload_incremental()
payload.Sign(PayloadSigner())
@@ -1323,6 +1355,7 @@
os.path.join(self.testdata_dir, 'testkey.x509.pem'),
output_file)
+ @test_utils.SkipIfExternalToolsUnavailable()
def test_Sign_withDataWipe(self):
common.OPTIONS.wipe_user_data = True
payload = self._create_payload_full()
@@ -1331,6 +1364,7 @@
with open(payload.payload_properties) as properties_fp:
self.assertIn("POWERWASH=1", properties_fp.read())
+ @test_utils.SkipIfExternalToolsUnavailable()
def test_Sign_secondary(self):
payload = self._create_payload_full(secondary=True)
payload.Sign(PayloadSigner())
@@ -1338,6 +1372,7 @@
with open(payload.payload_properties) as properties_fp:
self.assertIn("SWITCH_SLOT_ON_REBOOT=0", properties_fp.read())
+ @test_utils.SkipIfExternalToolsUnavailable()
def test_Sign_badSigner(self):
"""Tests that signing failure can be captured."""
payload = self._create_payload_full()
@@ -1345,6 +1380,7 @@
payload_signer.signer_args.append('bad-option')
self.assertRaises(common.ExternalError, payload.Sign, payload_signer)
+ @test_utils.SkipIfExternalToolsUnavailable()
def test_WriteToZip(self):
payload = self._create_payload_full()
payload.Sign(PayloadSigner())
@@ -1366,6 +1402,7 @@
continue
self.assertEqual(zipfile.ZIP_STORED, entry_info.compress_type)
+ @test_utils.SkipIfExternalToolsUnavailable()
def test_WriteToZip_unsignedPayload(self):
"""Unsigned payloads should not be allowed to be written to zip."""
payload = self._create_payload_full()
@@ -1381,6 +1418,7 @@
with zipfile.ZipFile(output_file, 'w') as output_zip:
self.assertRaises(AssertionError, payload.WriteToZip, output_zip)
+ @test_utils.SkipIfExternalToolsUnavailable()
def test_WriteToZip_secondary(self):
payload = self._create_payload_full(secondary=True)
payload.Sign(PayloadSigner())
diff --git a/tools/releasetools/test_utils.py b/tools/releasetools/test_utils.py
index ca127b1..1e919f7 100755
--- a/tools/releasetools/test_utils.py
+++ b/tools/releasetools/test_utils.py
@@ -31,6 +31,18 @@
# Some test runner doesn't like outputs from stderr.
logging.basicConfig(stream=sys.stdout)
+# Use ANDROID_BUILD_TOP as an indicator to tell if the needed tools (e.g.
+# avbtool, mke2fs) are available while running the tests. Not having the var or
+# having empty string means we can't run the tests that require external tools.
+EXTERNAL_TOOLS_UNAVAILABLE = not os.environ.get("ANDROID_BUILD_TOP")
+
+
+def SkipIfExternalToolsUnavailable():
+ """Decorator function that allows skipping tests per tools availability."""
+ if EXTERNAL_TOOLS_UNAVAILABLE:
+ return unittest.skip('External tools unavailable')
+ return lambda func: func
+
def get_testdata_dir():
"""Returns the testdata dir, in relative to the script dir."""
diff --git a/tools/releasetools/test_validate_target_files.py b/tools/releasetools/test_validate_target_files.py
index 5f619ec..70e3b49 100644
--- a/tools/releasetools/test_validate_target_files.py
+++ b/tools/releasetools/test_validate_target_files.py
@@ -55,6 +55,7 @@
0, proc.returncode,
"Failed to sign boot image with boot_signer: {}".format(stdoutdata))
+ @test_utils.SkipIfExternalToolsUnavailable()
def test_ValidateVerifiedBootImages_bootImage(self):
input_tmp = common.MakeTempDir()
os.mkdir(os.path.join(input_tmp, 'IMAGES'))
@@ -69,6 +70,7 @@
}
ValidateVerifiedBootImages(input_tmp, info_dict, options)
+ @test_utils.SkipIfExternalToolsUnavailable()
def test_ValidateVerifiedBootImages_bootImage_wrongKey(self):
input_tmp = common.MakeTempDir()
os.mkdir(os.path.join(input_tmp, 'IMAGES'))
@@ -85,6 +87,7 @@
AssertionError, ValidateVerifiedBootImages, input_tmp, info_dict,
options)
+ @test_utils.SkipIfExternalToolsUnavailable()
def test_ValidateVerifiedBootImages_bootImage_corrupted(self):
input_tmp = common.MakeTempDir()
os.mkdir(os.path.join(input_tmp, 'IMAGES'))
@@ -139,6 +142,7 @@
# Append the verity metadata.
verity_image_builder.Build(output_file)
+ @test_utils.SkipIfExternalToolsUnavailable()
def test_ValidateVerifiedBootImages_systemImage(self):
input_tmp = common.MakeTempDir()
os.mkdir(os.path.join(input_tmp, 'IMAGES'))
@@ -162,6 +166,7 @@
}
ValidateVerifiedBootImages(input_tmp, info_dict, options)
+ @test_utils.SkipIfExternalToolsUnavailable()
def test_ValidateFileConsistency_incompleteRange(self):
input_tmp = common.MakeTempDir()
os.mkdir(os.path.join(input_tmp, 'IMAGES'))
diff --git a/tools/releasetools/test_verity_utils.py b/tools/releasetools/test_verity_utils.py
index e0607c8..1cc539f 100644
--- a/tools/releasetools/test_verity_utils.py
+++ b/tools/releasetools/test_verity_utils.py
@@ -24,7 +24,8 @@
import common
import sparse_img
from rangelib import RangeSet
-from test_utils import get_testdata_dir, ReleaseToolsTestCase
+from test_utils import (
+ get_testdata_dir, ReleaseToolsTestCase, SkipIfExternalToolsUnavailable)
from verity_utils import (
CreateHashtreeInfoGenerator, CreateVerityImageBuilder, HashtreeInfo,
VerifiedBootVersion1HashtreeInfoGenerator)
@@ -89,6 +90,7 @@
return output_file
+ @SkipIfExternalToolsUnavailable()
def test_CreateHashtreeInfoGenerator(self):
image_file = sparse_img.SparseImage(self._generate_image())
@@ -99,6 +101,7 @@
self.assertEqual(self.partition_size, generator.partition_size)
self.assertTrue(generator.fec_supported)
+ @SkipIfExternalToolsUnavailable()
def test_DecomposeSparseImage(self):
image_file = sparse_img.SparseImage(self._generate_image())
@@ -109,6 +112,7 @@
self.assertEqual(12288, generator.hashtree_size)
self.assertEqual(32768, generator.metadata_size)
+ @SkipIfExternalToolsUnavailable()
def test_ParseHashtreeMetadata(self):
image_file = sparse_img.SparseImage(self._generate_image())
generator = VerifiedBootVersion1HashtreeInfoGenerator(
@@ -123,6 +127,7 @@
self.assertEqual(self.fixed_salt, generator.hashtree_info.salt)
self.assertEqual(self.expected_root_hash, generator.hashtree_info.root_hash)
+ @SkipIfExternalToolsUnavailable()
def test_ValidateHashtree_smoke(self):
generator = VerifiedBootVersion1HashtreeInfoGenerator(
self.partition_size, 4096, True)
@@ -138,6 +143,7 @@
self.assertTrue(generator.ValidateHashtree())
+ @SkipIfExternalToolsUnavailable()
def test_ValidateHashtree_failure(self):
generator = VerifiedBootVersion1HashtreeInfoGenerator(
self.partition_size, 4096, True)
@@ -153,6 +159,7 @@
self.assertFalse(generator.ValidateHashtree())
+ @SkipIfExternalToolsUnavailable()
def test_Generate(self):
image_file = sparse_img.SparseImage(self._generate_image())
generator = CreateHashtreeInfoGenerator('system', 4096, self.prop_dict)
@@ -193,6 +200,7 @@
del prop_dict['verity_block_device']
self.assertIsNone(CreateVerityImageBuilder(prop_dict))
+ @SkipIfExternalToolsUnavailable()
def test_CalculateMaxImageSize(self):
verity_image_builder = CreateVerityImageBuilder(self.DEFAULT_PROP_DICT)
size = verity_image_builder.CalculateMaxImageSize()
@@ -221,11 +229,13 @@
cmd = ['verity_verifier', image, '-mincrypt', verify_key]
common.RunAndCheckOutput(cmd)
+ @SkipIfExternalToolsUnavailable()
def test_Build(self):
self._BuildAndVerify(
self.DEFAULT_PROP_DICT,
os.path.join(get_testdata_dir(), 'testkey_mincrypt'))
+ @SkipIfExternalToolsUnavailable()
def test_Build_SanityCheck(self):
# A sanity check for the test itself: the image shouldn't be verifiable
# with wrong key.
@@ -235,6 +245,7 @@
self.DEFAULT_PROP_DICT,
os.path.join(get_testdata_dir(), 'verity_mincrypt'))
+ @SkipIfExternalToolsUnavailable()
def test_Build_FecDisabled(self):
prop_dict = copy.deepcopy(self.DEFAULT_PROP_DICT)
del prop_dict['verity_fec']
@@ -242,6 +253,7 @@
prop_dict,
os.path.join(get_testdata_dir(), 'testkey_mincrypt'))
+ @SkipIfExternalToolsUnavailable()
def test_Build_SquashFs(self):
verity_image_builder = CreateVerityImageBuilder(self.DEFAULT_PROP_DICT)
verity_image_builder.CalculateMaxImageSize()
@@ -282,6 +294,7 @@
verity_image_builder = CreateVerityImageBuilder(prop_dict)
self.assertIsNone(verity_image_builder)
+ @SkipIfExternalToolsUnavailable()
def test_Build(self):
prop_dict = copy.deepcopy(self.DEFAULT_PROP_DICT)
verity_image_builder = CreateVerityImageBuilder(prop_dict)