# Copyright 2016 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # This module has common mock objects and functions used in unit tests for # mobly.controllers.android_device module. import logging import os from unittest import mock DEFAULT_MOCK_PROPERTIES = { 'ro.build.id': 'AB42', 'ro.build.type': 'userdebug', 'ro.build.fingerprint': 'FakeModel:Dessert/AB42/1234567:userdebug/dev-keys', 'ro.build.product': 'FakeModel', 'ro.build.version.codename': 'Z', 'ro.build.version.incremental': '1234567', 'ro.build.version.sdk': '28', 'ro.product.name': 'FakeModel', 'ro.debuggable': '1', 'sys.boot_completed': "1", 'ro.build.characteristics': 'emulator,phone', 'ro.hardware': 'marlin', } class Error(Exception): pass def get_mock_ads(num): """Generates a list of mock AndroidDevice objects. The serial number of each device will be integer 0 through num - 1. Args: num: An integer that is the number of mock AndroidDevice objects to create. """ ads = [] for i in range(num): ad = mock.MagicMock(name="AndroidDevice", serial=str(i), h_port=None) ad.skip_logcat = False ads.append(ad) return ads def get_all_instances(): return get_mock_ads(5) def get_instances(serials): ads = [] for serial in serials: ad = mock.MagicMock(name="AndroidDevice", serial=serial, h_port=None) ads.append(ad) return ads def get_instances_with_configs(dicts): return get_instances([d['serial'] for d in dicts]) def list_adb_devices(): return [ad.serial for ad in get_mock_ads(5)] class MockAdbProxy: """Mock class that swaps out calls to adb with mock calls.""" def __init__(self, serial='', fail_br=False, fail_br_before_N=False, mock_properties=None, installed_packages=None, instrumented_packages=None): self.serial = serial self.fail_br = fail_br self.fail_br_before_N = fail_br_before_N self.getprops_call_count = 0 if mock_properties is None: self.mock_properties = DEFAULT_MOCK_PROPERTIES.copy() else: self.mock_properties = mock_properties if installed_packages is None: installed_packages = [] self.installed_packages = installed_packages if instrumented_packages is None: instrumented_packages = [] self.installed_packages = installed_packages self.instrumented_packages = instrumented_packages def shell(self, params, timeout=None): if params == "id -u": return b"root" elif params == "bugreportz": if self.fail_br: return b"OMG I died!\n" return b'OK:/path/bugreport.zip\n' elif params == "bugreportz -v": if self.fail_br_before_N: return b"/system/bin/sh: bugreportz: not found" return b'1.1' elif 'pm list package' in params: packages = self.installed_packages + [ package for package, _, _ in self.instrumented_packages ] return bytes('\n'.join(['package:%s' % package for package in packages]), 'utf-8') elif 'pm list instrumentation' in params: return bytes( '\n'.join([ 'instrumentation:%s/%s (target=%s)' % (package, runner, target) for package, runner, target in self.instrumented_packages ]), 'utf-8') elif 'which' in params: return b'' def getprop(self, params): if params in self.mock_properties: return self.mock_properties[params] def getprops(self, params): self.getprops_call_count = self.getprops_call_count + 1 return self.mock_properties def bugreport(self, args, shell=False, timeout=None): expected = os.path.join( logging.log_path, 'AndroidDevice%s' % self.serial, 'BugReports', 'bugreport,test_something,%s,fakemodel,sometime' % self.serial) if expected not in args: raise Error('"Expected "%s", got "%s"' % (expected, args)) def __getattr__(self, name): """All calls to the none-existent functions in adb proxy would simply return the adb command string. """ def adb_call(*args, **kwargs): arg_str = ' '.join(str(elem) for elem in args) return arg_str return adb_call class MockFastbootProxy: """Mock class that swaps out calls to adb with mock calls.""" def __init__(self, serial): self.serial = serial def devices(self): return b"xxxx device\nyyyy device" def __getattr__(self, name): def fastboot_call(*args): arg_str = ' '.join(str(elem) for elem in args) return arg_str return fastboot_call