Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(393)

Side by Side Diff: build/android/pylib/android_commands.py

Issue 13799010: [Android] Reduce test logging verbosity. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « build/android/buildbot/bb_device_steps.py ('k') | build/android/pylib/base/shard.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
102 emulator-5554 offline 102 emulator-5554 offline
103 """ 103 """
104 re_device = re.compile('^([a-zA-Z0-9_:.-]+)\tdevice$', re.MULTILINE) 104 re_device = re.compile('^([a-zA-Z0-9_:.-]+)\tdevice$', re.MULTILINE)
105 devices = re_device.findall(cmd_helper.GetCmdOutput(['adb', 'devices'])) 105 devices = re_device.findall(cmd_helper.GetCmdOutput(['adb', 'devices']))
106 preferred_device = os.environ.get('ANDROID_SERIAL') 106 preferred_device = os.environ.get('ANDROID_SERIAL')
107 if preferred_device in devices: 107 if preferred_device in devices:
108 devices.remove(preferred_device) 108 devices.remove(preferred_device)
109 devices.insert(0, preferred_device) 109 devices.insert(0, preferred_device)
110 return devices 110 return devices
111 111
112
112 def IsDeviceAttached(device): 113 def IsDeviceAttached(device):
113 return device in GetAttachedDevices() 114 return device in GetAttachedDevices()
114 115
116
115 def _GetFilesFromRecursiveLsOutput(path, ls_output, re_file, utc_offset=None): 117 def _GetFilesFromRecursiveLsOutput(path, ls_output, re_file, utc_offset=None):
116 """Gets a list of files from `ls` command output. 118 """Gets a list of files from `ls` command output.
117 119
118 Python's os.walk isn't used because it doesn't work over adb shell. 120 Python's os.walk isn't used because it doesn't work over adb shell.
119 121
120 Args: 122 Args:
121 path: The path to list. 123 path: The path to list.
122 ls_output: A list of lines returned by an `ls -lR` command. 124 ls_output: A list of lines returned by an `ls -lR` command.
123 re_file: A compiled regular expression which parses a line into named groups 125 re_file: A compiled regular expression which parses a line into named groups
124 consisting of at minimum "filename", "date", "time", "size" and 126 consisting of at minimum "filename", "date", "time", "size" and
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
157 utc_offset = file_match.group('timezone') 159 utc_offset = file_match.group('timezone')
158 if isinstance(utc_offset, str) and len(utc_offset) == 5: 160 if isinstance(utc_offset, str) and len(utc_offset) == 5:
159 utc_delta = datetime.timedelta(hours=int(utc_offset[1:3]), 161 utc_delta = datetime.timedelta(hours=int(utc_offset[1:3]),
160 minutes=int(utc_offset[3:5])) 162 minutes=int(utc_offset[3:5]))
161 if utc_offset[0:1] == '-': 163 if utc_offset[0:1] == '-':
162 utc_delta = -utc_delta 164 utc_delta = -utc_delta
163 lastmod -= utc_delta 165 lastmod -= utc_delta
164 files[filename] = (int(file_match.group('size')), lastmod) 166 files[filename] = (int(file_match.group('size')), lastmod)
165 return files 167 return files
166 168
169
167 def _ComputeFileListHash(md5sum_output): 170 def _ComputeFileListHash(md5sum_output):
168 """Returns a list of MD5 strings from the provided md5sum output.""" 171 """Returns a list of MD5 strings from the provided md5sum output."""
169 return [line.split(' ')[0] for line in md5sum_output] 172 return [line.split(' ')[0] for line in md5sum_output]
170 173
174
171 def _HasAdbPushSucceeded(command_output): 175 def _HasAdbPushSucceeded(command_output):
172 """Returns whether adb push has succeeded from the provided output.""" 176 """Returns whether adb push has succeeded from the provided output."""
173 if not command_output: 177 if not command_output:
174 return False 178 return False
175 # Success looks like this: "3035 KB/s (12512056 bytes in 4.025s)" 179 # Success looks like this: "3035 KB/s (12512056 bytes in 4.025s)"
176 # Errors look like this: "failed to copy ... " 180 # Errors look like this: "failed to copy ... "
177 if not re.search('^[0-9]', command_output.splitlines()[-1]): 181 if not re.search('^[0-9]', command_output.splitlines()[-1]):
178 logging.critical('PUSH FAILED: ' + command_output) 182 logging.critical('PUSH FAILED: ' + command_output)
179 return False 183 return False
180 return True 184 return True
181 185
186
182 def GetLogTimestamp(log_line, year): 187 def GetLogTimestamp(log_line, year):
183 """Returns the timestamp of the given |log_line| in the given year.""" 188 """Returns the timestamp of the given |log_line| in the given year."""
184 try: 189 try:
185 return datetime.datetime.strptime('%s-%s' % (year, log_line[:18]), 190 return datetime.datetime.strptime('%s-%s' % (year, log_line[:18]),
186 '%Y-%m-%d %H:%M:%S.%f') 191 '%Y-%m-%d %H:%M:%S.%f')
187 except (ValueError, IndexError): 192 except (ValueError, IndexError):
188 logging.critical('Error reading timestamp from ' + log_line) 193 logging.critical('Error reading timestamp from ' + log_line)
189 return None 194 return None
190 195
191 196
(...skipping 12 matching lines...) Expand all
204 self._device = device 209 self._device = device
205 self._logcat = None 210 self._logcat = None
206 self.logcat_process = None 211 self.logcat_process = None
207 self._logcat_tmpoutfile = None 212 self._logcat_tmpoutfile = None
208 self._pushed_files = [] 213 self._pushed_files = []
209 self._device_utc_offset = self.RunShellCommand('date +%z')[0] 214 self._device_utc_offset = self.RunShellCommand('date +%z')[0]
210 self._md5sum_path = '' 215 self._md5sum_path = ''
211 self._external_storage = '' 216 self._external_storage = ''
212 self._util_wrapper = '' 217 self._util_wrapper = ''
213 218
219 def _LogShell(self, cmd):
220 """Logs the adb shell command."""
221 if self._device:
222 device_repr = self._device[-4:]
223 else:
224 device_repr = '????'
225 logging.info('[%s]> %s', device_repr, cmd)
226
214 def Adb(self): 227 def Adb(self):
215 """Returns our AdbInterface to avoid us wrapping all its methods.""" 228 """Returns our AdbInterface to avoid us wrapping all its methods."""
216 return self._adb 229 return self._adb
217 230
218 def IsOnline(self): 231 def IsOnline(self):
219 """Checks whether the device is online. 232 """Checks whether the device is online.
220 233
221 Returns: 234 Returns:
222 True if device is in 'device' mode, False otherwise. 235 True if device is in 'device' mode, False otherwise.
223 """ 236 """
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
310 """Uninstalls the specified package from the device. 323 """Uninstalls the specified package from the device.
311 324
312 Args: 325 Args:
313 package: Name of the package to remove. 326 package: Name of the package to remove.
314 327
315 Returns: 328 Returns:
316 A status string returned by adb uninstall 329 A status string returned by adb uninstall
317 """ 330 """
318 uninstall_command = 'uninstall %s' % package 331 uninstall_command = 'uninstall %s' % package
319 332
320 logging.info('>>> $' + uninstall_command) 333 self._LogShell(uninstall_command)
321 return self._adb.SendCommand(uninstall_command, timeout_time=60) 334 return self._adb.SendCommand(uninstall_command, timeout_time=60)
322 335
323 def Install(self, package_file_path, reinstall=False): 336 def Install(self, package_file_path, reinstall=False):
324 """Installs the specified package to the device. 337 """Installs the specified package to the device.
325 338
326 Args: 339 Args:
327 package_file_path: Path to .apk file to install. 340 package_file_path: Path to .apk file to install.
328 reinstall: Reinstall an existing apk, keeping the data. 341 reinstall: Reinstall an existing apk, keeping the data.
329 342
330 Returns: 343 Returns:
331 A status string returned by adb install 344 A status string returned by adb install
332 """ 345 """
333 assert os.path.isfile(package_file_path), ('<%s> is not file' % 346 assert os.path.isfile(package_file_path), ('<%s> is not file' %
334 package_file_path) 347 package_file_path)
335 348
336 install_cmd = ['install'] 349 install_cmd = ['install']
337 350
338 if reinstall: 351 if reinstall:
339 install_cmd.append('-r') 352 install_cmd.append('-r')
340 353
341 install_cmd.append(package_file_path) 354 install_cmd.append(package_file_path)
342 install_cmd = ' '.join(install_cmd) 355 install_cmd = ' '.join(install_cmd)
343 356
344 logging.info('>>> $' + install_cmd) 357 self._LogShell(install_cmd)
345 return self._adb.SendCommand(install_cmd, 358 return self._adb.SendCommand(install_cmd,
346 timeout_time=2 * 60, 359 timeout_time=2 * 60,
347 retry_count=0) 360 retry_count=0)
348 361
349 def ManagedInstall(self, apk_path, keep_data=False, package_name=None, 362 def ManagedInstall(self, apk_path, keep_data=False, package_name=None,
350 reboots_on_failure=2): 363 reboots_on_failure=2):
351 """Installs specified package and reboots device on timeouts. 364 """Installs specified package and reboots device on timeouts.
352 365
353 Args: 366 Args:
354 apk_path: Path to .apk file to install. 367 apk_path: Path to .apk file to install.
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
465 command: String containing the shell command to send. Must not include 478 command: String containing the shell command to send. Must not include
466 the single quotes as we use them to escape the whole command. 479 the single quotes as we use them to escape the whole command.
467 timeout_time: Number of seconds to wait for command to respond before 480 timeout_time: Number of seconds to wait for command to respond before
468 retrying, used by AdbInterface.SendShellCommand. 481 retrying, used by AdbInterface.SendShellCommand.
469 log_result: Boolean to indicate whether we should log the result of the 482 log_result: Boolean to indicate whether we should log the result of the
470 shell command. 483 shell command.
471 484
472 Returns: 485 Returns:
473 list containing the lines of output received from running the command 486 list containing the lines of output received from running the command
474 """ 487 """
475 logging.info('>>> $' + command) 488 self._LogShell(command)
476 if "'" in command: logging.warning(command + " contains ' quotes") 489 if "'" in command: logging.warning(command + " contains ' quotes")
477 result = self._adb.SendShellCommand( 490 result = self._adb.SendShellCommand(
478 "'%s'" % command, timeout_time).splitlines() 491 "'%s'" % command, timeout_time).splitlines()
479 if ['error: device not found'] == result: 492 if ['error: device not found'] == result:
480 raise errors.DeviceUnresponsiveError('device not found') 493 raise errors.DeviceUnresponsiveError('device not found')
481 if log_result: 494 if log_result:
482 logging.info('\n>>> '.join(result)) 495 self._LogShell('\n'.join(result))
483 return result 496 return result
484 497
485 def GetShellCommandStatusAndOutput(self, command, timeout_time=20, 498 def GetShellCommandStatusAndOutput(self, command, timeout_time=20,
486 log_result=False): 499 log_result=False):
487 """See RunShellCommand() above. 500 """See RunShellCommand() above.
488 501
489 Returns: 502 Returns:
490 The tuple (exit code, list of output lines). 503 The tuple (exit code, list of output lines).
491 """ 504 """
492 lines = self.RunShellCommand( 505 lines = self.RunShellCommand(
(...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after
690 return 703 return
691 704
692 # They don't match, so remove everything first and then create it. 705 # They don't match, so remove everything first and then create it.
693 if os.path.isdir(local_path): 706 if os.path.isdir(local_path):
694 self.RunShellCommand('rm -r %s' % device_path, timeout_time=2 * 60) 707 self.RunShellCommand('rm -r %s' % device_path, timeout_time=2 * 60)
695 self.RunShellCommand('mkdir -p %s' % device_path) 708 self.RunShellCommand('mkdir -p %s' % device_path)
696 709
697 # NOTE: We can't use adb_interface.Push() because it hardcodes a timeout of 710 # NOTE: We can't use adb_interface.Push() because it hardcodes a timeout of
698 # 60 seconds which isn't sufficient for a lot of users of this method. 711 # 60 seconds which isn't sufficient for a lot of users of this method.
699 push_command = 'push %s %s' % (local_path, device_path) 712 push_command = 'push %s %s' % (local_path, device_path)
700 logging.info('>>> $' + push_command) 713 self._LogShell(push_command)
701 output = self._adb.SendCommand(push_command, timeout_time=30 * 60) 714 output = self._adb.SendCommand(push_command, timeout_time=30 * 60)
702 assert _HasAdbPushSucceeded(output) 715 assert _HasAdbPushSucceeded(output)
703 716
704 717
705 def GetFileContents(self, filename, log_result=False): 718 def GetFileContents(self, filename, log_result=False):
706 """Gets contents from the file specified by |filename|.""" 719 """Gets contents from the file specified by |filename|."""
707 return self.RunShellCommand('cat "%s" 2>/dev/null' % filename, 720 return self.RunShellCommand('cat "%s" 2>/dev/null' % filename,
708 log_result=log_result) 721 log_result=log_result)
709 722
710 def SetFileContents(self, filename, contents): 723 def SetFileContents(self, filename, contents):
(...skipping 535 matching lines...) Expand 10 before | Expand all | Expand 10 after
1246 1259
1247 Args: 1260 Args:
1248 test: Test class/method. 1261 test: Test class/method.
1249 test_package: Name of the test jar. 1262 test_package: Name of the test jar.
1250 timeout: Timeout time in seconds. 1263 timeout: Timeout time in seconds.
1251 1264
1252 Returns: 1265 Returns:
1253 An instance of am_instrument_parser.TestResult object. 1266 An instance of am_instrument_parser.TestResult object.
1254 """ 1267 """
1255 cmd = 'uiautomator runtest %s -e class %s' % (test_package, test) 1268 cmd = 'uiautomator runtest %s -e class %s' % (test_package, test)
1256 logging.info('>>> $' + cmd) 1269 self._LogShell(cmd)
1257 output = self._adb.SendShellCommand(cmd, timeout_time=timeout) 1270 output = self._adb.SendShellCommand(cmd, timeout_time=timeout)
1258 # uiautomator doesn't fully conform to the instrumenation test runner 1271 # uiautomator doesn't fully conform to the instrumenation test runner
1259 # convention and doesn't terminate with INSTRUMENTATION_CODE. 1272 # convention and doesn't terminate with INSTRUMENTATION_CODE.
1260 # Just assume the first result is valid. 1273 # Just assume the first result is valid.
1261 (test_results, _) = am_instrument_parser.ParseAmInstrumentOutput(output) 1274 (test_results, _) = am_instrument_parser.ParseAmInstrumentOutput(output)
1262 return test_results[0] 1275 return test_results[0]
1263 1276
1264 1277
1265 class NewLineNormalizer(object): 1278 class NewLineNormalizer(object):
1266 """A file-like object to normalize EOLs to '\n'. 1279 """A file-like object to normalize EOLs to '\n'.
1267 1280
1268 Pexpect runs adb within a pseudo-tty device (see 1281 Pexpect runs adb within a pseudo-tty device (see
1269 http://www.noah.org/wiki/pexpect), so any '\n' printed by adb is written 1282 http://www.noah.org/wiki/pexpect), so any '\n' printed by adb is written
1270 as '\r\n' to the logfile. Since adb already uses '\r\n' to terminate 1283 as '\r\n' to the logfile. Since adb already uses '\r\n' to terminate
1271 lines, the log ends up having '\r\r\n' at the end of each line. This 1284 lines, the log ends up having '\r\r\n' at the end of each line. This
1272 filter replaces the above with a single '\n' in the data stream. 1285 filter replaces the above with a single '\n' in the data stream.
1273 """ 1286 """
1274 def __init__(self, output): 1287 def __init__(self, output):
1275 self._output = output 1288 self._output = output
1276 1289
1277 def write(self, data): 1290 def write(self, data):
1278 data = data.replace('\r\r\n', '\n') 1291 data = data.replace('\r\r\n', '\n')
1279 self._output.write(data) 1292 self._output.write(data)
1280 1293
1281 def flush(self): 1294 def flush(self):
1282 self._output.flush() 1295 self._output.flush()
OLDNEW
« no previous file with comments | « build/android/buildbot/bb_device_steps.py ('k') | build/android/pylib/base/shard.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698