OLD | NEW |
1 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 # Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
4 | 4 |
5 """Provides an interface to communicate with the device via the adb command. | 5 """Provides an interface to communicate with the device via the adb command. |
6 | 6 |
7 Assumes adb binary is currently on system path. | 7 Assumes adb binary is currently on system path. |
8 """ | 8 """ |
9 | 9 |
10 import collections | 10 import collections |
11 import datetime | 11 import datetime |
12 import logging | 12 import logging |
13 import os | 13 import os |
14 import re | 14 import re |
15 import shlex | 15 import shlex |
16 import subprocess | 16 import subprocess |
17 import sys | 17 import sys |
18 import tempfile | 18 import tempfile |
19 import time | 19 import time |
20 | 20 |
| 21 import cmd_helper |
| 22 import constants |
21 import io_stats_parser | 23 import io_stats_parser |
22 try: | 24 try: |
23 import pexpect | 25 import pexpect |
24 except: | 26 except: |
25 pexpect = None | 27 pexpect = None |
26 | 28 |
27 CHROME_SRC = os.path.join( | 29 sys.path.append(os.path.join( |
28 os.path.abspath(os.path.dirname(__file__)), '..', '..', '..') | 30 constants.CHROME_DIR, 'third_party', 'android_testrunner')) |
29 | |
30 sys.path.append(os.path.join(CHROME_SRC, 'third_party', 'android_testrunner')) | |
31 import adb_interface | 31 import adb_interface |
32 | 32 import am_instrument_parser |
33 import cmd_helper | 33 import errors |
34 import errors # is under ../../../third_party/android_testrunner/errors.py | |
35 | 34 |
36 | 35 |
37 # Pattern to search for the next whole line of pexpect output and capture it | 36 # Pattern to search for the next whole line of pexpect output and capture it |
38 # into a match group. We can't use ^ and $ for line start end with pexpect, | 37 # into a match group. We can't use ^ and $ for line start end with pexpect, |
39 # see http://www.noah.org/python/pexpect/#doc for explanation why. | 38 # see http://www.noah.org/python/pexpect/#doc for explanation why. |
40 PEXPECT_LINE_RE = re.compile('\n([^\r]*)\r') | 39 PEXPECT_LINE_RE = re.compile('\n([^\r]*)\r') |
41 | 40 |
42 # Set the adb shell prompt to be a unique marker that will [hopefully] not | 41 # Set the adb shell prompt to be a unique marker that will [hopefully] not |
43 # appear at the start of any line of a command's output. | 42 # appear at the start of any line of a command's output. |
44 SHELL_PROMPT = '~+~PQ\x17RS~+~' | 43 SHELL_PROMPT = '~+~PQ\x17RS~+~' |
(...skipping 1156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1201 self.RunShellCommand('/system/bin/screencap -p %s' % device_file) | 1200 self.RunShellCommand('/system/bin/screencap -p %s' % device_file) |
1202 assert self._adb.Pull(device_file, host_file) | 1201 assert self._adb.Pull(device_file, host_file) |
1203 assert os.path.exists(host_file) | 1202 assert os.path.exists(host_file) |
1204 | 1203 |
1205 def SetUtilWrapper(self, util_wrapper): | 1204 def SetUtilWrapper(self, util_wrapper): |
1206 """Sets a wrapper prefix to be used when running a locally-built | 1205 """Sets a wrapper prefix to be used when running a locally-built |
1207 binary on the device (ex.: md5sum_bin). | 1206 binary on the device (ex.: md5sum_bin). |
1208 """ | 1207 """ |
1209 self._util_wrapper = util_wrapper | 1208 self._util_wrapper = util_wrapper |
1210 | 1209 |
| 1210 def RunInstrumentationTest(self, test, test_package, instr_args, timeout): |
| 1211 """Runs a single instrumentation test. |
| 1212 |
| 1213 Args: |
| 1214 test: Test class/method. |
| 1215 test_package: Package name of test apk. |
| 1216 instr_args: Extra key/value to pass to am instrument. |
| 1217 timeout: Timeout time in seconds. |
| 1218 |
| 1219 Returns: |
| 1220 An instance of am_instrument_parser.TestResult object. |
| 1221 """ |
| 1222 instrumentation_path = ('%s/android.test.InstrumentationTestRunner' % |
| 1223 test_package) |
| 1224 args_with_filter = dict(instr_args) |
| 1225 args_with_filter['class'] = test |
| 1226 logging.info(args_with_filter) |
| 1227 (raw_results, _) = self._adb.StartInstrumentation( |
| 1228 instrumentation_path=instrumentation_path, |
| 1229 instrumentation_args=args_with_filter, |
| 1230 timeout_time=timeout) |
| 1231 assert len(raw_results) == 1 |
| 1232 return raw_results[0] |
| 1233 |
| 1234 def RunUIAutomatorTest(self, test, test_package, timeout): |
| 1235 """Runs a single uiautomator test. |
| 1236 |
| 1237 Args: |
| 1238 test: Test class/method. |
| 1239 test_package: Name of the test jar. |
| 1240 timeout: Timeout time in seconds. |
| 1241 |
| 1242 Returns: |
| 1243 An instance of am_instrument_parser.TestResult object. |
| 1244 """ |
| 1245 cmd = 'uiautomator runtest %s -e class %s' % (test_package, test) |
| 1246 logging.info('>>> $' + cmd) |
| 1247 output = self._adb.SendShellCommand(cmd, timeout_time=timeout) |
| 1248 # uiautomator doesn't fully conform to the instrumenation test runner |
| 1249 # convention and doesn't terminate with INSTRUMENTATION_CODE. |
| 1250 # Just assume the first result is valid. |
| 1251 (test_results, _) = am_instrument_parser.ParseAmInstrumentOutput(output) |
| 1252 return test_results[0] |
| 1253 |
1211 | 1254 |
1212 class NewLineNormalizer(object): | 1255 class NewLineNormalizer(object): |
1213 """A file-like object to normalize EOLs to '\n'. | 1256 """A file-like object to normalize EOLs to '\n'. |
1214 | 1257 |
1215 Pexpect runs adb within a pseudo-tty device (see | 1258 Pexpect runs adb within a pseudo-tty device (see |
1216 http://www.noah.org/wiki/pexpect), so any '\n' printed by adb is written | 1259 http://www.noah.org/wiki/pexpect), so any '\n' printed by adb is written |
1217 as '\r\n' to the logfile. Since adb already uses '\r\n' to terminate | 1260 as '\r\n' to the logfile. Since adb already uses '\r\n' to terminate |
1218 lines, the log ends up having '\r\r\n' at the end of each line. This | 1261 lines, the log ends up having '\r\r\n' at the end of each line. This |
1219 filter replaces the above with a single '\n' in the data stream. | 1262 filter replaces the above with a single '\n' in the data stream. |
1220 """ | 1263 """ |
1221 def __init__(self, output): | 1264 def __init__(self, output): |
1222 self._output = output | 1265 self._output = output |
1223 | 1266 |
1224 def write(self, data): | 1267 def write(self, data): |
1225 data = data.replace('\r\r\n', '\n') | 1268 data = data.replace('\r\r\n', '\n') |
1226 self._output.write(data) | 1269 self._output.write(data) |
1227 | 1270 |
1228 def flush(self): | 1271 def flush(self): |
1229 self._output.flush() | 1272 self._output.flush() |
OLD | NEW |