| Index: content/shell/tools/breakpad_integration_test.py
|
| diff --git a/content/shell/tools/breakpad_integration_test.py b/content/shell/tools/breakpad_integration_test.py
|
| new file mode 100755
|
| index 0000000000000000000000000000000000000000..c9742fe589d99cddf72d49266ba67ca84445d20a
|
| --- /dev/null
|
| +++ b/content/shell/tools/breakpad_integration_test.py
|
| @@ -0,0 +1,147 @@
|
| +#!/usr/bin/env python
|
| +#
|
| +# Copyright 2014 The Chromium Authors. All rights reserved.
|
| +# Use of this source code is governed by a BSD-style license that can be
|
| +# found in the LICENSE file.
|
| +
|
| +"""Integration test for breakpad in content shell.
|
| +
|
| +This test checks that content shell and breakpad are correctly hooked up, as
|
| +well as that the tools can symbolize a stack trace."""
|
| +
|
| +
|
| +import glob
|
| +import optparse
|
| +import os
|
| +import shutil
|
| +import subprocess
|
| +import sys
|
| +import tempfile
|
| +
|
| +
|
| +CONCURRENT_TASKS=4
|
| +
|
| +
|
| +def main():
|
| + parser = optparse.OptionParser()
|
| + parser.add_option('', '--build-dir', default='',
|
| + help='The build output directory.')
|
| + parser.add_option('', '--binary', default='',
|
| + help='The path of the binary to generate symbols for.')
|
| + parser.add_option('', '--no-symbols', default=False, action='store_true',
|
| + help='Symbols are not expected to work.')
|
| + parser.add_option('-j', '--jobs', default=CONCURRENT_TASKS, action='store',
|
| + type='int', help='Number of parallel tasks to run.')
|
| + parser.add_option('-v', '--verbose', action='store_true',
|
| + help='Print verbose status output.')
|
| +
|
| + (options, _) = parser.parse_args()
|
| +
|
| + if not options.build_dir:
|
| + print "Required option --build-dir missing."
|
| + return 1
|
| +
|
| + if not options.binary:
|
| + print "Required option --binary missing."
|
| + return 1
|
| +
|
| + if not os.access(options.binary, os.X_OK):
|
| + print "Cannot find %s." % options.binary
|
| + return 1
|
| +
|
| + failure = ''
|
| +
|
| + # Create a temporary directory to store the crash dumps and symbols in.
|
| + crash_dir = tempfile.mkdtemp()
|
| +
|
| + try:
|
| + print "# Generate symbols."
|
| + breakpad_tools_dir = os.path.join(
|
| + os.path.dirname(__file__), '..', '..', '..',
|
| + 'components', 'breakpad', 'tools')
|
| + generate_symbols = os.path.join(
|
| + breakpad_tools_dir, 'generate_breakpad_symbols.py')
|
| + symbols_dir = os.path.join(crash_dir, 'symbols')
|
| + cmd = [generate_symbols,
|
| + '--build-dir=%s' % options.build_dir,
|
| + '--binary=%s' % options.binary,
|
| + '--symbols-dir=%s' % symbols_dir,
|
| + '--jobs=%d' % options.jobs]
|
| + if options.verbose:
|
| + cmd.append('--verbose')
|
| + print ' '.join(cmd)
|
| + failure = 'Failed to run generate_breakpad_symbols.py.'
|
| + subprocess.check_call(cmd)
|
| +
|
| + print "# Run content_shell and make it crash."
|
| + cmd = [options.binary,
|
| + '--dump-render-tree',
|
| + 'chrome://crash',
|
| + '--enable-crash-reporter',
|
| + '--crash-dumps-dir=%s' % crash_dir]
|
| + if options.verbose:
|
| + print ' '.join(cmd)
|
| + failure = 'Failed to run content_shell.'
|
| + if options.verbose:
|
| + subprocess.check_call(cmd)
|
| + else:
|
| + with open(os.devnull, 'w') as devnull:
|
| + subprocess.check_call(cmd, stdout=devnull, stderr=devnull)
|
| +
|
| + print "# Retrieve crash dump."
|
| + dmp_files = glob.glob(os.path.join(crash_dir, '*.dmp'))
|
| + failure = 'Expected 1 crash dump, found %d.' % len(dmp_files)
|
| + if len(dmp_files) != 1:
|
| + raise Exception(failure)
|
| + dmp_file = dmp_files[0]
|
| + minidump = os.path.join(crash_dir, 'minidump')
|
| +
|
| + dmp_to_minidump = os.path.join(breakpad_tools_dir, 'dmp2minidump.py')
|
| + cmd = [dmp_to_minidump, dmp_file, minidump]
|
| + if options.verbose:
|
| + print ' '.join(cmd)
|
| + failure = 'Failed to run dmp_to_minidump.'
|
| + subprocess.check_call(cmd)
|
| +
|
| + print "# Symbolize crash dump."
|
| + minidump_stackwalk = os.path.join(options.build_dir, 'minidump_stackwalk')
|
| + cmd = [minidump_stackwalk, minidump, symbols_dir]
|
| + if options.verbose:
|
| + print ' '.join(cmd)
|
| + failure = 'Failed to run minidump_stackwalk.'
|
| + proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
| + stack = proc.communicate()[0]
|
| +
|
| + # Check whether the stack contains a CrashIntentionally symbol.
|
| + found_symbol = 'CrashIntentionally' in stack
|
| +
|
| + if options.no_symbols:
|
| + if found_symbol:
|
| + if options.verbose:
|
| + print stack
|
| + failure = 'Found unexpected reference to CrashIntentionally in stack'
|
| + raise Exception(failure)
|
| + else:
|
| + if not found_symbol:
|
| + if options.verbose:
|
| + print stack
|
| + failure = 'Could not find reference to CrashIntentionally in stack.'
|
| + raise Exception(failure)
|
| +
|
| + except:
|
| + print "FAIL: %s" % failure
|
| + return 1
|
| +
|
| + else:
|
| + print "PASS: Breakpad integration test ran successfully."
|
| + return 0
|
| +
|
| + finally:
|
| + try:
|
| + shutil.rmtree(crash_dir)
|
| + except:
|
| + print 'Failed to delete temp directory "%s".' % crash_dir
|
| +
|
| +
|
| +if '__main__' == __name__:
|
| + sys.exit(main())
|
|
|