blob: a3da0fd6d7e320542cf4cbdbe1070e2966575430 [file] [log] [blame]
# 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
from pylib.constants import host_paths
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
with host_paths.SysPath(host_paths.PYMOCK_PATH):
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])
device_utils.DeviceUtils.HealthyDevices.assert_called_with(device_arg=None)
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)
device_utils.DeviceUtils.HealthyDevices.assert_called_with(device_arg=None)
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])
device_utils.DeviceUtils.HealthyDevices.assert_called_with(
device_arg=user_specified_devices)
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)