| OLD | NEW |
| 1 # Copyright 2015 The Chromium Authors. All rights reserved. | 1 # Copyright 2015 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 # pylint: disable=unused-argument | 5 # pylint: disable=unused-argument |
| 6 | 6 |
| 7 import collections | 7 import collections |
| 8 import itertools | 8 import itertools |
| 9 import logging | 9 import logging |
| 10 import subprocess | 10 import subprocess |
| 11 import tempfile | 11 import tempfile |
| 12 import time | 12 import time |
| 13 import re | 13 import re |
| 14 | 14 |
| 15 from pylib.device import adb_wrapper | 15 from pylib.device import adb_wrapper |
| 16 from pylib.device import decorators | 16 from pylib.device import decorators |
| 17 from pylib.device import device_errors | 17 from pylib.device import device_errors |
| 18 | 18 |
| 19 | 19 |
| 20 class LogcatMonitor(object): | 20 class LogcatMonitor(object): |
| 21 | 21 |
| 22 # Format: <DATE> <TIME> <PID> <TID> <LEVEL> <COMPONENT>: <MESSAGE> | 22 # Format: <DATE> <TIME> <PID> <TID> <LEVEL> <COMPONENT>: <MESSAGE> |
| 23 _THREADTIME_RE_FORMAT = r'\S* +\S* +(%s) +(%s) +(%s) +(%s): +(%s)$' | 23 _THREADTIME_RE_FORMAT = r'\S* +\S* +(%s) +(%s) +(%s) +(%s): +(%s)$' |
| 24 | 24 |
| 25 def __init__(self, adb, clear=True): | 25 def __init__(self, adb, clear=True, filter_specs=None): |
| 26 """Create a LogcatMonitor instance. | 26 """Create a LogcatMonitor instance. |
| 27 | 27 |
| 28 Args: | 28 Args: |
| 29 adb: An instance of adb_wrapper.AdbWrapper. | 29 adb: An instance of adb_wrapper.AdbWrapper. |
| 30 clear: If True, clear the logcat when monitoring starts. | 30 clear: If True, clear the logcat when monitoring starts. |
| 31 filter_specs: An optional list of '<tag>[:priority]' strings. |
| 31 """ | 32 """ |
| 32 if isinstance(adb, adb_wrapper.AdbWrapper): | 33 if isinstance(adb, adb_wrapper.AdbWrapper): |
| 33 self._adb = adb | 34 self._adb = adb |
| 34 else: | 35 else: |
| 35 raise ValueError('Unsupported type passed for argument "device"') | 36 raise ValueError('Unsupported type passed for argument "device"') |
| 36 self._clear = clear | 37 self._clear = clear |
| 38 self._filter_specs = filter_specs |
| 37 self._logcat_out = None | 39 self._logcat_out = None |
| 38 self._logcat_out_file = None | 40 self._logcat_out_file = None |
| 39 self._logcat_proc = None | 41 self._logcat_proc = None |
| 40 | 42 |
| 41 @decorators.WithTimeoutAndRetriesDefaults(10, 0) | 43 @decorators.WithTimeoutAndRetriesDefaults(10, 0) |
| 42 def WaitFor(self, success_regex, failure_regex=None, timeout=None, | 44 def WaitFor(self, success_regex, failure_regex=None, timeout=None, |
| 43 retries=None): | 45 retries=None): |
| 44 """Wait for a matching logcat line or until a timeout occurs. | 46 """Wait for a matching logcat line or until a timeout occurs. |
| 45 | 47 |
| 46 This will attempt to match lines in the logcat against both |success_regex| | 48 This will attempt to match lines in the logcat against both |success_regex| |
| (...skipping 22 matching lines...) Expand all Loading... |
| 69 if isinstance(failure_regex, basestring): | 71 if isinstance(failure_regex, basestring): |
| 70 failure_regex = re.compile(failure_regex) | 72 failure_regex = re.compile(failure_regex) |
| 71 | 73 |
| 72 logging.debug('Waiting %d seconds for "%s"', timeout, success_regex.pattern) | 74 logging.debug('Waiting %d seconds for "%s"', timeout, success_regex.pattern) |
| 73 | 75 |
| 74 # NOTE This will continue looping until: | 76 # NOTE This will continue looping until: |
| 75 # - success_regex matches a line, in which case the match object is | 77 # - success_regex matches a line, in which case the match object is |
| 76 # returned. | 78 # returned. |
| 77 # - failure_regex matches a line, in which case None is returned | 79 # - failure_regex matches a line, in which case None is returned |
| 78 # - the timeout is hit, in which case a CommandTimeoutError is raised. | 80 # - the timeout is hit, in which case a CommandTimeoutError is raised. |
| 79 for l in self._adb.Logcat(): | 81 for l in self._adb.Logcat(filter_specs=self._filter_specs): |
| 80 m = success_regex.search(l) | 82 m = success_regex.search(l) |
| 81 if m: | 83 if m: |
| 82 return m | 84 return m |
| 83 if failure_regex and failure_regex.search(l): | 85 if failure_regex and failure_regex.search(l): |
| 84 return None | 86 return None |
| 85 | 87 |
| 86 def FindAll(self, message_regex, proc_id=None, thread_id=None, log_level=None, | 88 def FindAll(self, message_regex, proc_id=None, thread_id=None, log_level=None, |
| 87 component=None): | 89 component=None): |
| 88 """Finds all lines in the logcat that match the provided constraints. | 90 """Finds all lines in the logcat that match the provided constraints. |
| 89 | 91 |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 134 self._adb.Logcat(clear=True) | 136 self._adb.Logcat(clear=True) |
| 135 | 137 |
| 136 def __enter__(self): | 138 def __enter__(self): |
| 137 """Starts the logcat monitor.""" | 139 """Starts the logcat monitor.""" |
| 138 self.Start() | 140 self.Start() |
| 139 return self | 141 return self |
| 140 | 142 |
| 141 def __exit__(self, exc_type, exc_val, exc_tb): | 143 def __exit__(self, exc_type, exc_val, exc_tb): |
| 142 """Stops the logcat monitor.""" | 144 """Stops the logcat monitor.""" |
| 143 pass | 145 pass |
| OLD | NEW |