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 |