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

Unified Diff: build/android/pylib/debug_info.py

Issue 10777017: Android: further simplication for test runners. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Nit on comment Created 8 years, 5 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | build/android/pylib/single_test_runner.py » ('j') | build/android/run_tests.py » ('J')
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: build/android/pylib/debug_info.py
diff --git a/build/android/pylib/debug_info.py b/build/android/pylib/debug_info.py
index 4678c20d9e767070dbb9b8289cc5761d2bbb2d28..6f0f55a33f2eafa74dd38d4b5f9625aaf5ce2cc3 100644
--- a/build/android/pylib/debug_info.py
+++ b/build/android/pylib/debug_info.py
@@ -20,7 +20,13 @@ TOMBSTONE_DIR = '/data/tombstones/'
class GTestDebugInfo(object):
- """A helper class to get relate debug information for a gtest.
+ """A helper class to collect related debug information for a gtest.
+
+ Debug info is collected in two steps:
+ - first, object(s) of this class (one per device), accumulate logs
+ and screenshots in tempdir.
+ - once the test has finished, call ZipAndCleanResults to create
+ a zip containing the logs from all devices, and clean them up.
Args:
adb: ADB interface the tests are using.
@@ -29,8 +35,7 @@ class GTestDebugInfo(object):
gtest_filter: Test filter used by the specified gtest.
"""
- def __init__(self, adb, device, testsuite_name, gtest_filter,
- collect_new_crashes=True):
+ def __init__(self, adb, device, testsuite_name, gtest_filter):
"""Initializes the DebugInfo class for a specified gtest."""
self.adb = adb
self.device = device
@@ -38,34 +43,15 @@ class GTestDebugInfo(object):
self.gtest_filter = gtest_filter
self.logcat_process = None
self.has_storage = False
- self.log_dir = None
- self.log_file_name = None
- self.collect_new_crashes = collect_new_crashes
- self.old_crash_files = self.ListCrashFiles()
-
- def InitStorage(self):
- """Initializes the storage in where we put the debug information."""
- if self.has_storage:
- return
- self.has_storage = True
- self.log_dir = tempfile.mkdtemp()
+ self.log_dir = os.path.join(tempfile.gettempdir(),
+ 'gtest_debug_info',
+ self.testsuite_name,
+ self.device)
+ if not os.path.exists(self.log_dir):
+ os.makedirs(self.log_dir)
self.log_file_name = os.path.join(self.log_dir,
self._GeneratePrefixName() + '_log.txt')
-
- def CleanupStorage(self):
- """Cleans up the storage in where we put the debug information."""
- if not self.has_storage:
- return
- self.has_storage = False
- assert os.path.exists(self.log_dir)
- shutil.rmtree(self.log_dir)
- self.log_dir = None
- self.log_file_name = None
-
- def GetStoragePath(self):
- """Returns the path in where we store the debug information."""
- self.InitStorage()
- return self.log_dir
+ self.old_crash_files = self._ListCrashFiles()
def _GetSignatureFromGTestFilter(self):
"""Gets a signature from gtest_filter.
@@ -79,7 +65,11 @@ class GTestDebugInfo(object):
if not self.gtest_filter:
return 'all'
filename_chars = "-_()%s%s" % (string.ascii_letters, string.digits)
- return ''.join(c for c in self.gtest_filter if c in filename_chars)
+ signature = ''.join(c for c in self.gtest_filter if c in filename_chars)
+ if len(signature) > 64:
+ # The signature can't be too long, as it'll be part of a file name.
+ signature = signature[:64]
+ return signature
def _GeneratePrefixName(self):
"""Generates a prefix name for debug information of the test.
@@ -87,7 +77,7 @@ class GTestDebugInfo(object):
The prefix name consists of the following:
(1) root name of test_suite_base.
(2) device serial number.
- (3) filter signature generate from gtest_filter.
+ (3) prefix of filter signature generate from gtest_filter.
(4) date & time when calling this method.
Returns:
@@ -107,13 +97,13 @@ class GTestDebugInfo(object):
clear: True if existing log output should be cleared.
filters: A list of logcat filters to be used.
"""
- self.InitStorage()
self.StopRecordingLog()
if clear:
- cmd_helper.RunCmd(['adb', 'logcat', '-c'])
- logging.info('Start dumping log to %s ...' % self.log_file_name)
- command = 'adb logcat -v threadtime %s > %s' % (' '.join(filters),
- self.log_file_name)
+ cmd_helper.RunCmd(['adb', '-s', self.device, 'logcat', '-c'])
+ logging.info('Start dumping log to %s ...', self.log_file_name)
+ command = 'adb -s %s logcat -v threadtime %s > %s' % (self.device,
+ ' '.join(filters),
+ self.log_file_name)
self.logcat_process = subprocess.Popen(command, shell=True)
def StopRecordingLog(self):
@@ -137,74 +127,70 @@ class GTestDebugInfo(object):
Returns the file name on the host of the screenshot if successful,
None otherwise.
"""
- self.InitStorage()
assert isinstance(identifier_mark, str)
+ screenshot_path = os.path.join(os.getenv('ANDROID_HOST_OUT', ''),
+ 'bin',
+ 'screenshot2')
+ if not os.path.exists(screenshot_path):
+ logging.error('Failed to take screen shot from device %s', self.device)
+ return None
shot_path = os.path.join(self.log_dir, ''.join([self._GeneratePrefixName(),
identifier_mark,
'_screenshot.png']))
- screenshot_path = os.path.join(os.getenv('ANDROID_HOST_OUT'), 'bin',
- 'screenshot2')
re_success = re.compile(re.escape('Success.'), re.MULTILINE)
if re_success.findall(cmd_helper.GetCmdOutput([screenshot_path, '-s',
self.device, shot_path])):
- logging.info("Successfully took a screen shot to %s" % shot_path)
+ logging.info('Successfully took a screen shot to %s', shot_path)
return shot_path
- logging.error('Failed to take screen shot from device %s' % self.device)
+ logging.error('Failed to take screen shot from device %s', self.device)
return None
- def ListCrashFiles(self):
+ def _ListCrashFiles(self):
"""Collects crash files from current specified device.
Returns:
A dict of crash files in format {"name": (size, lastmod), ...}.
"""
- if not self.collect_new_crashes:
- return {}
return self.adb.ListPathContents(TOMBSTONE_DIR)
def ArchiveNewCrashFiles(self):
"""Archives the crash files newly generated until calling this method."""
- if not self.collect_new_crashes:
- return
- current_crash_files = self.ListCrashFiles()
+ current_crash_files = self._ListCrashFiles()
files = []
for f in current_crash_files:
if f not in self.old_crash_files:
files += [f]
elif current_crash_files[f] != self.old_crash_files[f]:
- # Tomestones dir can only have maximum 10 files, so we need to compare
+ # Tombstones dir can only have maximum 10 files, so we need to compare
# size and timestamp information of file if the file exists.
files += [f]
if files:
logging.info('New crash file(s):%s' % ' '.join(files))
for f in files:
self.adb.Adb().Pull(TOMBSTONE_DIR + f,
- os.path.join(self.GetStoragePath(), f))
+ os.path.join(self.log_dir, f))
@staticmethod
- def ZipAndCleanResults(dest_dir, dump_file_name, debug_info_list):
+ def ZipAndCleanResults(dest_dir, dump_file_name):
"""A helper method to zip all debug information results into a dump file.
Args:
- dest-dir: Dir path in where we put the dump file.
+ dest_dir: Dir path in where we put the dump file.
dump_file_name: Desired name of the dump file. This method makes sure
'.zip' will be added as ext name.
- debug_info_list: List of all debug info objects.
"""
- if not dest_dir or not dump_file_name or not debug_info_list:
+ if not dest_dir or not dump_file_name:
return
cmd_helper.RunCmd(['mkdir', '-p', dest_dir])
log_basename = os.path.basename(dump_file_name)
- log_file = os.path.join(dest_dir,
- os.path.splitext(log_basename)[0] + '.zip')
- logging.info('Zipping debug dumps into %s ...' % log_file)
- for d in debug_info_list:
- d.ArchiveNewCrashFiles()
+ log_zip_file = os.path.join(dest_dir,
+ os.path.splitext(log_basename)[0] + '.zip')
+ logging.info('Zipping debug dumps into %s ...', log_zip_file)
# Add new dumps into the zip file. The zip may exist already if previous
# gtest also dumps the debug information. It's OK since we clean up the old
# dumps in each build step.
- cmd_helper.RunCmd(['zip', '-q', '-r', log_file,
- ' '.join([d.GetStoragePath() for d in debug_info_list])])
- assert os.path.exists(log_file)
- for debug_info in debug_info_list:
- debug_info.CleanupStorage()
+ log_src_dir = os.path.join(tempfile.gettempdir(), 'gtest_debug_info')
+ cmd_helper.RunCmd(['zip', '-q', '-r', log_zip_file, log_src_dir])
+ assert os.path.exists(log_zip_file)
+ assert os.path.exists(log_src_dir)
+ shutil.rmtree(log_src_dir)
« no previous file with comments | « no previous file | build/android/pylib/single_test_runner.py » ('j') | build/android/run_tests.py » ('J')

Powered by Google App Engine
This is Rietveld 408576698