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 (test_results, _) = am_instrument_parser.ParseAmInstrumentOutput(output) | |
craigdh
2013/03/19 20:37:46
assert len(test_results) == 1?
frankf
2013/03/19 23:28:08
There's an extra garbage result.
On 2013/03/19 20
| |
1249 return test_results[0] | |
craigdh
2013/03/19 20:37:46
add comment explaining hackery.
frankf
2013/03/19 23:28:08
Done.
| |
1250 | |
1211 | 1251 |
1212 class NewLineNormalizer(object): | 1252 class NewLineNormalizer(object): |
1213 """A file-like object to normalize EOLs to '\n'. | 1253 """A file-like object to normalize EOLs to '\n'. |
1214 | 1254 |
1215 Pexpect runs adb within a pseudo-tty device (see | 1255 Pexpect runs adb within a pseudo-tty device (see |
1216 http://www.noah.org/wiki/pexpect), so any '\n' printed by adb is written | 1256 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 | 1257 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 | 1258 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. | 1259 filter replaces the above with a single '\n' in the data stream. |
1220 """ | 1260 """ |
1221 def __init__(self, output): | 1261 def __init__(self, output): |
1222 self._output = output | 1262 self._output = output |
1223 | 1263 |
1224 def write(self, data): | 1264 def write(self, data): |
1225 data = data.replace('\r\r\n', '\n') | 1265 data = data.replace('\r\r\n', '\n') |
1226 self._output.write(data) | 1266 self._output.write(data) |
1227 | 1267 |
1228 def flush(self): | 1268 def flush(self): |
1229 self._output.flush() | 1269 self._output.flush() |
OLD | NEW |