1#!/usr/bin/python 2# Copyright 2015 The Chromium OS Authors. All rights reserved. 3# Use of this source code is governed by a BSD-style license that can be 4# found in the LICENSE file. 5 6import argparse 7import os 8import sys 9 10import logging 11# Turn the logging level to INFO before importing other autotest 12# code, to avoid having failed import logging messages confuse the 13# test_droid user. 14logging.basicConfig(level=logging.INFO) 15 16 17import common 18# Unfortunately, autotest depends on external packages for assorted 19# functionality regardless of whether or not it is needed in a particular 20# context. 21# Since we can't depend on people to import these utilities in any principled 22# way, we dynamically download code before any autotest imports. 23try: 24 import chromite.lib.terminal # pylint: disable=unused-import 25 import django.http # pylint: disable=unused-import 26except ImportError: 27 # Ensure the chromite site-package is installed. 28 import subprocess 29 build_externals_path = os.path.join( 30 os.path.dirname(os.path.dirname(os.path.realpath(__file__))), 31 'utils', 'build_externals.py') 32 subprocess.check_call([build_externals_path, 'chromiterepo', 'django']) 33 # Restart the script so python now finds the autotest site-packages. 34 sys.exit(os.execv(__file__, sys.argv)) 35 36from autotest_lib.client.common_lib import utils 37from autotest_lib.server.hosts import adb_host 38from autotest_lib.site_utils import test_runner_utils 39from autotest_lib.site_utils import tester_feedback 40 41 42def parse_arguments(argv): 43 """ 44 Parse command line arguments 45 46 @param argv: argument list to parse 47 48 @returns: parsed arguments 49 50 @raises SystemExit if arguments are malformed, or required arguments 51 are not present. 52 """ 53 return _parse_arguments_internal(argv)[0] 54 55 56def _parse_arguments_internal(argv): 57 """ 58 Parse command line arguments 59 60 @param argv: argument list to parse 61 62 @returns: tuple of parsed arguments and argv suitable for remote runs 63 64 @raises SystemExit if arguments are malformed, or required arguments 65 are not present. 66 """ 67 68 parser = argparse.ArgumentParser(description='Run remote tests.') 69 70 parser.add_argument('-s', '--serials', metavar='SERIALS', 71 help='Comma separate list of device serials under ' 72 'test.') 73 parser.add_argument('-f', '--fastboot_serial', metavar='FB_SERIALS', 74 help='Comma separate list of fastboot serials under ' 75 'test.', default=None) 76 parser.add_argument('-r', '--remote', metavar='REMOTE', 77 default='localhost', 78 help='hostname[:port] if the ADB device is connected ' 79 'to a remote machine. Ensure this workstation ' 80 'is configured for passwordless ssh access as ' 81 'users "root" or "adb"') 82 parser.add_argument('-i', '--interactive', action='store_true', 83 help='Enable interactive feedback requests from tests.') 84 test_runner_utils.add_common_args(parser) 85 return parser.parse_args(argv) 86 87 88def main(argv): 89 """ 90 Entry point for test_droid script. 91 92 @param argv: arguments list 93 """ 94 arguments = _parse_arguments_internal(argv) 95 96 serials = arguments.serials 97 if serials is None: 98 result = utils.run(['adb', 'devices']) 99 devices = adb_host.ADBHost.parse_device_serials(result.stdout) 100 if len(devices) != 1: 101 logging.error('could not detect exactly one device; please select ' 102 'one with -s: %s', devices) 103 return 1 104 serials = devices[0] 105 106 results_directory = test_runner_utils.create_results_directory( 107 arguments.results_dir) 108 arguments.results_dir = results_directory 109 110 autotest_path = os.path.dirname(os.path.dirname( 111 os.path.realpath(__file__))) 112 site_utils_path = os.path.join(autotest_path, 'site_utils') 113 realpath = os.path.realpath(__file__) 114 site_utils_path = os.path.realpath(site_utils_path) 115 host_attributes = {'serials' : serials, 116 'os_type' : 'android'} 117 if arguments.fastboot_serial: 118 host_attributes['fastboot_serial'] = arguments.fastboot_serial 119 120 fb_service = None 121 try: 122 # Start the feedback service if needed. 123 if arguments.interactive: 124 fb_service = tester_feedback.FeedbackService() 125 fb_service.start() 126 127 if arguments.args: 128 arguments.args += ' ' 129 else: 130 arguments.args = '' 131 arguments.args += ( 132 'feedback=interactive feedback_args=localhost:%d' % 133 fb_service.server_port) 134 135 return test_runner_utils.perform_run_from_autotest_root( 136 autotest_path, argv, arguments.tests, arguments.remote, 137 args=arguments.args, ignore_deps=not arguments.enforce_deps, 138 results_directory=results_directory, 139 iterations=arguments.iterations, 140 fast_mode=arguments.fast_mode, debug=arguments.debug, 141 host_attributes=host_attributes, pretend=arguments.pretend) 142 finally: 143 if fb_service is not None: 144 fb_service.stop() 145 146 147if __name__ == '__main__': 148 sys.exit(main(sys.argv[1:])) 149