Chromium Code Reviews| 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..a38989be3a5d1f350211ebe9e10a9bbba7ea0f7f |
| --- /dev/null |
| +++ b/content/shell/tools/breakpad_integration_test.py |
| @@ -0,0 +1,150 @@ |
| +#!/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." |
| + generate_symbols = os.path.join( |
| + os.path.dirname(os.path.dirname(options.build_dir)), |
| + 'components', 'breakpad', 'tools', 'generate_breakpad_symbols.py') |
|
Lei Zhang
2014/05/23 03:13:53
this should be relative to breakpad_integration_te
jochen (gone - plz use gerrit)
2014/05/23 07:22:22
Done.
|
| + 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', |
|
Lei Zhang
2014/05/23 05:22:51
Oh, please use --enable-crash-reporter-for-testing
jochen (gone - plz use gerrit)
2014/05/23 07:22:22
--enable-crash-reporter-for-testing is a linux onl
|
| + '--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 = 'Could not find a single crash dump.' |
|
Lei Zhang
2014/05/23 03:13:53
This is slightly confusing, maybe change it to: 'E
jochen (gone - plz use gerrit)
2014/05/23 07:22:22
Done.
|
| + 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( |
| + os.path.dirname(os.path.dirname(options.build_dir)), |
| + 'components', 'breakpad', 'tools', 'dmp2minidump.py') |
|
Lei Zhang
2014/05/23 03:13:53
same comment as line 61
jochen (gone - plz use gerrit)
2014/05/23 07:22:22
Done.
|
| + 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 = stack.find('CrashIntentionally') != -1 |
| + |
| + 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: |
| + try: |
| + shutil.rmtree(crash_dir) |
| + except: |
| + print 'Failed to delete temp directory.' |
| + |
| + print "FAIL: %s" % failure |
| + return 1 |
| + |
| + try: |
|
Lei Zhang
2014/05/23 03:13:53
put the above rmtree() attempt inside finally: and
jochen (gone - plz use gerrit)
2014/05/23 07:22:22
Done.
|
| + shutil.rmtree(crash_dir) |
| + except: |
| + print 'Failed to delete temp directory.' |
| + |
| + print "PASS: Breakpad integration test ran successfully." |
| + return 0 |
| + |
| + |
| +if '__main__' == __name__: |
| + sys.exit(main()) |