You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
105 lines
3.6 KiB
105 lines
3.6 KiB
#!/usr/bin/env python3
|
|
#
|
|
# Copyright 2019, The Android Open Source Project
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
# you may not use this file except in compliance with the License.
|
|
# You may obtain a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
# See the License for the specific language governing permissions and
|
|
# limitations under the License.
|
|
|
|
"""Helper util libraries for parsing logcat logs."""
|
|
|
|
import asyncio
|
|
import re
|
|
from datetime import datetime
|
|
from typing import Optional, Pattern
|
|
|
|
# local import
|
|
import lib.print_utils as print_utils
|
|
|
|
def parse_logcat_datetime(timestamp: str) -> Optional[datetime]:
|
|
"""Parses the timestamp of logcat.
|
|
|
|
Params:
|
|
timestamp: for example "2019-07-01 16:13:55.221".
|
|
|
|
Returns:
|
|
a datetime of timestamp with the year now.
|
|
"""
|
|
try:
|
|
# Match the format of logcat. For example: "2019-07-01 16:13:55.221",
|
|
# because it doesn't have year, set current year to it.
|
|
timestamp = datetime.strptime(timestamp,
|
|
'%Y-%m-%d %H:%M:%S.%f')
|
|
return timestamp
|
|
except ValueError as ve:
|
|
print_utils.debug_print('Invalid line: ' + timestamp)
|
|
return None
|
|
|
|
def _is_time_out(timeout: datetime, line: str) -> bool:
|
|
"""Checks if the timestamp of this line exceeds the timeout.
|
|
|
|
Returns:
|
|
true if the timestamp exceeds the timeout.
|
|
"""
|
|
# Get the timestampe string.
|
|
cur_timestamp_str = ' '.join(re.split(r'\s+', line)[0:2])
|
|
timestamp = parse_logcat_datetime(cur_timestamp_str)
|
|
if not timestamp:
|
|
return False
|
|
|
|
return timestamp > timeout
|
|
|
|
async def _blocking_wait_for_logcat_pattern(timestamp: datetime,
|
|
pattern: Pattern,
|
|
timeout: datetime) -> Optional[str]:
|
|
# Show the year in the timestampe.
|
|
logcat_cmd = 'adb logcat -v UTC -v year -v threadtime -T'.split()
|
|
logcat_cmd.append(str(timestamp))
|
|
print_utils.debug_print('[LOGCAT]:' + ' '.join(logcat_cmd))
|
|
|
|
# Create subprocess
|
|
process = await asyncio.create_subprocess_exec(
|
|
*logcat_cmd,
|
|
# stdout must a pipe to be accessible as process.stdout
|
|
stdout=asyncio.subprocess.PIPE)
|
|
|
|
while (True):
|
|
# Read one line of output.
|
|
data = await process.stdout.readline()
|
|
line = data.decode('utf-8').rstrip()
|
|
|
|
# 2019-07-01 14:54:21.946 27365 27392 I ActivityTaskManager: Displayed
|
|
# com.android.settings/.Settings: +927ms
|
|
# TODO: Detect timeouts even when there is no logcat output.
|
|
if _is_time_out(timeout, line):
|
|
print_utils.debug_print('DID TIMEOUT BEFORE SEEING ANYTHING ('
|
|
'timeout={timeout} seconds << {pattern} '
|
|
'>>'.format(timeout=timeout, pattern=pattern))
|
|
return None
|
|
|
|
if pattern.match(line):
|
|
print_utils.debug_print(
|
|
'WE DID SEE PATTERN << "{}" >>.'.format(pattern))
|
|
return line
|
|
|
|
def blocking_wait_for_logcat_pattern(timestamp: datetime,
|
|
pattern: Pattern,
|
|
timeout: datetime) -> Optional[str]:
|
|
"""Selects the line that matches the pattern and within the timeout.
|
|
|
|
Returns:
|
|
the line that matches the pattern and within the timeout.
|
|
"""
|
|
loop = asyncio.get_event_loop()
|
|
result = loop.run_until_complete(
|
|
_blocking_wait_for_logcat_pattern(timestamp, pattern, timeout))
|
|
return result
|