diff options
Diffstat (limited to 'third_party/libwebrtc/build/android/list_class_verification_failures_test.py')
-rwxr-xr-x | third_party/libwebrtc/build/android/list_class_verification_failures_test.py | 237 |
1 files changed, 237 insertions, 0 deletions
diff --git a/third_party/libwebrtc/build/android/list_class_verification_failures_test.py b/third_party/libwebrtc/build/android/list_class_verification_failures_test.py new file mode 100755 index 0000000000..c3522d651d --- /dev/null +++ b/third_party/libwebrtc/build/android/list_class_verification_failures_test.py @@ -0,0 +1,237 @@ +#!/usr/bin/env vpython3 +# Copyright 2018 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import unittest + +import list_class_verification_failures as list_verification + +import devil_chromium # pylint: disable=unused-import +from devil.android import device_errors +from devil.android import device_utils +from devil.android.ndk import abis +from devil.android.sdk import version_codes + +import mock # pylint: disable=import-error + + +def _CreateOdexLine(java_class_name, type_idx, verification_status): + """Create a rough approximation of a line of oatdump output.""" + return ('{type_idx}: L{java_class}; (offset=0xac) (type_idx={type_idx}) ' + '({verification}) ' + '(OatClassNoneCompiled)'.format(type_idx=type_idx, + java_class=java_class_name, + verification=verification_status)) + + +def _ClassForName(name, classes): + return next(c for c in classes if c.name == name) + + +class _DetermineDeviceToUseTest(unittest.TestCase): + + def testDetermineDeviceToUse_emptyListWithOneAttachedDevice(self): + fake_attached_devices = ['123'] + user_specified_devices = [] + device_utils.DeviceUtils.HealthyDevices = mock.MagicMock( + return_value=fake_attached_devices) + result = list_verification.DetermineDeviceToUse(user_specified_devices) + self.assertEqual(result, fake_attached_devices[0]) + # pylint: disable=no-member + device_utils.DeviceUtils.HealthyDevices.assert_called_with(device_arg=None) + # pylint: enable=no-member + + def testDetermineDeviceToUse_emptyListWithNoAttachedDevices(self): + user_specified_devices = [] + device_utils.DeviceUtils.HealthyDevices = mock.MagicMock( + side_effect=device_errors.NoDevicesError()) + with self.assertRaises(device_errors.NoDevicesError) as _: + list_verification.DetermineDeviceToUse(user_specified_devices) + # pylint: disable=no-member + device_utils.DeviceUtils.HealthyDevices.assert_called_with(device_arg=None) + # pylint: enable=no-member + + def testDetermineDeviceToUse_oneElementListWithOneAttachedDevice(self): + user_specified_devices = ['123'] + fake_attached_devices = ['123'] + device_utils.DeviceUtils.HealthyDevices = mock.MagicMock( + return_value=fake_attached_devices) + result = list_verification.DetermineDeviceToUse(user_specified_devices) + self.assertEqual(result, fake_attached_devices[0]) + # pylint: disable=no-member + device_utils.DeviceUtils.HealthyDevices.assert_called_with( + device_arg=user_specified_devices) + # pylint: enable=no-member + + +class _ListClassVerificationFailuresTest(unittest.TestCase): + + def testPathToDexForPlatformVersion_noPaths(self): + sdk_int = version_codes.LOLLIPOP + paths_to_apk = [] + package_name = 'package.name' + arch = abis.ARM_64 + + device = mock.Mock(build_version_sdk=sdk_int, product_cpu_abi=arch) + device.GetApplicationPaths = mock.MagicMock(return_value=paths_to_apk) + + with self.assertRaises(list_verification.DeviceOSError) as cm: + list_verification.PathToDexForPlatformVersion(device, package_name) + message = str(cm.exception) + self.assertIn('Could not find data directory', message) + + def testPathToDexForPlatformVersion_multiplePaths(self): + sdk_int = version_codes.LOLLIPOP + paths_to_apk = ['/first/path', '/second/path'] + package_name = 'package.name' + arch = abis.ARM_64 + + device = mock.Mock(build_version_sdk=sdk_int, product_cpu_abi=arch) + device.GetApplicationPaths = mock.MagicMock(return_value=paths_to_apk) + + with self.assertRaises(list_verification.DeviceOSError) as cm: + list_verification.PathToDexForPlatformVersion(device, package_name) + message = str(cm.exception) + self.assertIn('Expected exactly one path for', message) + + def testPathToDexForPlatformVersion_dalvikApiLevel(self): + sdk_int = version_codes.KITKAT + paths_to_apk = ['/some/path'] + package_name = 'package.name' + arch = abis.ARM_64 + + device = mock.Mock(build_version_sdk=sdk_int, product_cpu_abi=arch) + device.GetApplicationPaths = mock.MagicMock(return_value=paths_to_apk) + + with self.assertRaises(list_verification.UnsupportedDeviceError) as _: + list_verification.PathToDexForPlatformVersion(device, package_name) + + def testPathToDexForPlatformVersion_lollipopArm(self): + sdk_int = version_codes.LOLLIPOP + package_name = 'package.name' + paths_to_apk = ['/some/path/{}-1/base.apk'.format(package_name)] + arch = 'arm' + + device = mock.Mock(build_version_sdk=sdk_int, product_cpu_abi=arch) + device.GetApplicationPaths = mock.MagicMock(return_value=paths_to_apk) + device.FileExists = mock.MagicMock(return_value=True) + + odex_file = list_verification.PathToDexForPlatformVersion(device, + package_name) + self.assertEqual(odex_file, + ('/data/dalvik-cache/arm/data@app' + '@package.name-1@base.apk@classes.dex')) + + def testPathToDexForPlatformVersion_mashmallowArm(self): + sdk_int = version_codes.MARSHMALLOW + package_name = 'package.name' + paths_to_apk = ['/some/path/{}-1/base.apk'.format(package_name)] + arch = 'arm' + + device = mock.Mock(build_version_sdk=sdk_int, product_cpu_abi=arch) + device.GetApplicationPaths = mock.MagicMock(return_value=paths_to_apk) + device.FileExists = mock.MagicMock(return_value=True) + + odex_file = list_verification.PathToDexForPlatformVersion(device, + package_name) + self.assertEqual(odex_file, + '/some/path/package.name-1/oat/arm/base.odex') + + def testPathToDexForPlatformVersion_mashmallowArm64(self): + sdk_int = version_codes.MARSHMALLOW + package_name = 'package.name' + paths_to_apk = ['/some/path/{}-1/base.apk'.format(package_name)] + arch = abis.ARM_64 + + device = mock.Mock(build_version_sdk=sdk_int, product_cpu_abi=arch) + device.GetApplicationPaths = mock.MagicMock(return_value=paths_to_apk) + device.FileExists = mock.MagicMock(return_value=True) + + odex_file = list_verification.PathToDexForPlatformVersion(device, + package_name) + self.assertEqual(odex_file, + '/some/path/package.name-1/oat/arm64/base.odex') + + def testPathToDexForPlatformVersion_pieNoOdexFile(self): + sdk_int = version_codes.PIE + package_name = 'package.name' + paths_to_apk = ['/some/path/{}-1/base.apk'.format(package_name)] + arch = abis.ARM_64 + + device = mock.Mock(build_version_sdk=sdk_int, product_cpu_abi=arch) + device.GetApplicationPaths = mock.MagicMock(return_value=paths_to_apk) + device.FileExists = mock.MagicMock(return_value=False) + + with self.assertRaises(list_verification.DeviceOSError) as cm: + list_verification.PathToDexForPlatformVersion(device, package_name) + message = str(cm.exception) + self.assertIn('you must run dex2oat on debuggable apps on >= P', message) + + def testPathToDexForPlatformVersion_lowerApiLevelNoOdexFile(self): + sdk_int = version_codes.MARSHMALLOW + package_name = 'package.name' + paths_to_apk = ['/some/path/{}-1/base.apk'.format(package_name)] + arch = abis.ARM_64 + + device = mock.Mock(build_version_sdk=sdk_int, product_cpu_abi=arch) + device.GetApplicationPaths = mock.MagicMock(return_value=paths_to_apk) + device.FileExists = mock.MagicMock(return_value=False) + + with self.assertRaises(list_verification.DeviceOSError) as _: + list_verification.PathToDexForPlatformVersion(device, package_name) + + def testListClasses_noProguardMap(self): + oatdump_output = [ + _CreateOdexLine('a.b.JavaClass1', 6, 'StatusVerified'), + _CreateOdexLine('a.b.JavaClass2', 7, + 'StatusRetryVerificationAtRuntime'), + ] + + classes = list_verification.ListClassesAndVerificationStatus(oatdump_output, + None) + self.assertEqual(2, len(classes)) + java_class_1 = _ClassForName('a.b.JavaClass1', classes) + java_class_2 = _ClassForName('a.b.JavaClass2', classes) + self.assertEqual(java_class_1.verification_status, 'Verified') + self.assertEqual(java_class_2.verification_status, + 'RetryVerificationAtRuntime') + + def testListClasses_proguardMap(self): + oatdump_output = [ + _CreateOdexLine('a.b.ObfuscatedJavaClass1', 6, 'StatusVerified'), + _CreateOdexLine('a.b.ObfuscatedJavaClass2', 7, + 'StatusRetryVerificationAtRuntime'), + ] + + mapping = { + 'a.b.ObfuscatedJavaClass1': 'a.b.JavaClass1', + 'a.b.ObfuscatedJavaClass2': 'a.b.JavaClass2', + } + classes = list_verification.ListClassesAndVerificationStatus(oatdump_output, + mapping) + self.assertEqual(2, len(classes)) + java_class_1 = _ClassForName('a.b.JavaClass1', classes) + java_class_2 = _ClassForName('a.b.JavaClass2', classes) + self.assertEqual(java_class_1.verification_status, 'Verified') + self.assertEqual(java_class_2.verification_status, + 'RetryVerificationAtRuntime') + + def testListClasses_noStatusPrefix(self): + oatdump_output = [ + _CreateOdexLine('a.b.JavaClass1', 6, 'Verified'), + _CreateOdexLine('a.b.JavaClass2', 7, 'RetryVerificationAtRuntime'), + ] + + classes = list_verification.ListClassesAndVerificationStatus(oatdump_output, + None) + self.assertEqual(2, len(classes)) + java_class_1 = _ClassForName('a.b.JavaClass1', classes) + java_class_2 = _ClassForName('a.b.JavaClass2', classes) + self.assertEqual(java_class_1.verification_status, 'Verified') + self.assertEqual(java_class_2.verification_status, + 'RetryVerificationAtRuntime') + +if __name__ == '__main__': + # Suppress logging messages. + unittest.main(buffer=True) |