| #!/usr/bin/env python |
| # Copyright (c) 2020, the R8 project authors. Please see the AUTHORS file |
| # for details. All rights reserved. Use of this source code is governed by a |
| # BSD-style license that can be found in the LICENSE file. |
| |
| import subprocess |
| import time |
| import utils |
| |
| def install_apk_on_emulator(apk, emulator_id, quiet=False): |
| cmd = ['adb', '-s', emulator_id, 'install', '-r', '-d', apk] |
| if quiet: |
| subprocess.check_output(cmd) |
| else: |
| subprocess.check_call(cmd) |
| |
| |
| def uninstall_apk_on_emulator(app_id, emulator_id): |
| process = subprocess.Popen( |
| ['adb', '-s', emulator_id, 'uninstall', app_id], |
| stdout=subprocess.PIPE, stderr=subprocess.PIPE) |
| stdout, stderr = process.communicate() |
| stdout = stdout.decode('UTF-8') |
| stderr = stderr.decode('UTF-8') |
| |
| if stdout.strip() == 'Success': |
| # Successfully uninstalled |
| return |
| |
| if 'Unknown package: {}'.format(app_id) in stderr: |
| # Application not installed |
| return |
| |
| # Check if the app is listed in packages |
| packages = subprocess.check_output(['adb', 'shell', 'pm', 'list', 'packages']) |
| if not 'package:' + app_id in packages: |
| return |
| |
| raise Exception( |
| 'Unexpected result from `adb uninstall {}\nStdout: {}\nStderr: {}'.format( |
| app_id, stdout, stderr)) |
| |
| |
| def wait_for_emulator(emulator_id): |
| stdout = subprocess.check_output(['adb', 'devices']).decode('UTF-8') |
| if '{}\tdevice'.format(emulator_id) in stdout: |
| return True |
| |
| print('Emulator \'{}\' not connected; waiting for connection'.format( |
| emulator_id)) |
| |
| time_waited = 0 |
| while True: |
| time.sleep(10) |
| time_waited += 10 |
| stdout = subprocess.check_output(['adb', 'devices']).decode('UTF-8') |
| if '{}\tdevice'.format(emulator_id) not in stdout: |
| print('... still waiting for connection') |
| if time_waited >= 5 * 60: |
| return False |
| else: |
| return True |
| |
| |
| def run_monkey(app_id, emulator_id, apk, monkey_events, quiet, enable_logging): |
| if not wait_for_emulator(emulator_id): |
| return False |
| |
| install_apk_on_emulator(apk, emulator_id, quiet) |
| |
| # Intentionally using a constant seed such that the monkey generates the same |
| # event sequence for each shrinker. |
| random_seed = 42 |
| |
| cmd = ['adb', '-s', emulator_id, 'shell', 'monkey', '-p', app_id, |
| '-s', str(random_seed), str(monkey_events)] |
| |
| try: |
| stdout = utils.RunCmd(cmd, quiet=quiet, logging=enable_logging) |
| succeeded = ('Events injected: {}'.format(monkey_events) in stdout) |
| except subprocess.CalledProcessError as e: |
| succeeded = False |
| |
| uninstall_apk_on_emulator(app_id, emulator_id) |
| |
| return succeeded |
| |
| |
| def run_instrumented(app_id, test_id, emulator_id, apk, test_apk, quiet, |
| enable_logging, |
| test_runner='androidx.test.runner.AndroidJUnitRunner'): |
| if not wait_for_emulator(emulator_id): |
| return None |
| |
| install_apk_on_emulator(apk, emulator_id, quiet) |
| install_apk_on_emulator(test_apk, emulator_id, quiet) |
| |
| cmd = ['adb', '-s', emulator_id, 'shell', 'am', 'instrument', '-w', |
| '{}/{}'.format(test_id, test_runner)] |
| |
| try: |
| stdout = utils.RunCmd(cmd, quiet=quiet, logging=enable_logging) |
| # The runner will print OK (X tests) if completed succesfully |
| succeeded = any("OK (" in s for s in stdout) |
| except subprocess.CalledProcessError as e: |
| succeeded = False |
| |
| uninstall_apk_on_emulator(test_id, emulator_id) |
| uninstall_apk_on_emulator(app_id, emulator_id) |
| |
| return succeeded |