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
3 # found in the LICENSE file.
5 # pylint: disable=unused-argument
15 from pylib
.device
import adb_wrapper
16 from pylib
.device
import decorators
17 from pylib
.device
import device_errors
20 class LogcatMonitor(object):
22 _THREADTIME_RE_FORMAT
= (
23 r
'(?P<date>\S*) +(?P<time>\S*) +(?P<proc_id>%s) +(?P<thread_id>%s) +'
24 r
'(?P<log_level>%s) +(?P<component>%s) *: +(?P<message>%s)$')
26 def __init__(self
, adb
, clear
=True, filter_specs
=None):
27 """Create a LogcatMonitor instance.
30 adb: An instance of adb_wrapper.AdbWrapper.
31 clear: If True, clear the logcat when monitoring starts.
32 filter_specs: An optional list of '<tag>[:priority]' strings.
34 if isinstance(adb
, adb_wrapper
.AdbWrapper
):
37 raise ValueError('Unsupported type passed for argument "device"')
39 self
._filter
_specs
= filter_specs
40 self
._logcat
_out
= None
41 self
._logcat
_out
_file
= None
42 self
._logcat
_proc
= None
44 @decorators.WithTimeoutAndRetriesDefaults(10, 0)
45 def WaitFor(self
, success_regex
, failure_regex
=None, timeout
=None,
47 """Wait for a matching logcat line or until a timeout occurs.
49 This will attempt to match lines in the logcat against both |success_regex|
50 and |failure_regex| (if provided). Note that this calls re.search on each
51 logcat line, not re.match, so the provided regular expressions don't have
52 to match an entire line.
55 success_regex: The regular expression to search for.
56 failure_regex: An optional regular expression that, if hit, causes this
57 to stop looking for a match. Can be None.
58 timeout: timeout in seconds
59 retries: number of retries
62 A match object if |success_regex| matches a part of a logcat line, or
63 None if |failure_regex| matches a part of a logcat line.
65 CommandFailedError on logcat failure (NOT on a |failure_regex| match).
66 CommandTimeoutError if no logcat line matching either |success_regex| or
67 |failure_regex| is found in |timeout| seconds.
68 DeviceUnreachableError if the device becomes unreachable.
70 if isinstance(success_regex
, basestring
):
71 success_regex
= re
.compile(success_regex
)
72 if isinstance(failure_regex
, basestring
):
73 failure_regex
= re
.compile(failure_regex
)
75 logging
.debug('Waiting %d seconds for "%s"', timeout
, success_regex
.pattern
)
77 # NOTE This will continue looping until:
78 # - success_regex matches a line, in which case the match object is
80 # - failure_regex matches a line, in which case None is returned
81 # - the timeout is hit, in which case a CommandTimeoutError is raised.
82 for l
in self
._adb
.Logcat(filter_specs
=self
._filter
_specs
):
83 m
= success_regex
.search(l
)
86 if failure_regex
and failure_regex
.search(l
):
89 def FindAll(self
, message_regex
, proc_id
=None, thread_id
=None, log_level
=None,
91 """Finds all lines in the logcat that match the provided constraints.
94 message_regex: The regular expression that the <message> section must
96 proc_id: The process ID to match. If None, matches any process ID.
97 thread_id: The thread ID to match. If None, matches any thread ID.
98 log_level: The log level to match. If None, matches any log level.
99 component: The component to match. If None, matches any component.
102 A match object for each matching line in the logcat. The match object
103 will always contain, in addition to groups defined in |message_regex|,
104 the following named groups: 'date', 'time', 'proc_id', 'thread_id',
105 'log_level', 'component', and 'message'.
109 if thread_id
is None:
111 if log_level
is None:
112 log_level
= r
'[VDIWEF]'
113 if component
is None:
114 component
= r
'[^\s:]+'
115 threadtime_re
= re
.compile(
116 type(self
)._THREADTIME
_RE
_FORMAT
% (
117 proc_id
, thread_id
, log_level
, component
, message_regex
))
119 for line
in self
._adb
.Logcat(dump
=True, logcat_format
='threadtime'):
120 m
= re
.match(threadtime_re
, line
)
125 """Starts the logcat monitor.
127 Clears the logcat if |clear| was set in |__init__|.
130 self
._adb
.Logcat(clear
=True)
133 """Starts the logcat monitor."""
137 def __exit__(self
, exc_type
, exc_val
, exc_tb
):
138 """Stops the logcat monitor."""