Home | History | Annotate | Download | only in valgrind-webrtc
      1 #!/usr/bin/env python
      2 # Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
      3 #
      4 # Use of this source code is governed by a BSD-style license
      5 # that can be found in the LICENSE file in the root of the source
      6 # tree. An additional intellectual property rights grant can be found
      7 # in the file PATENTS.  All contributing project authors may
      8 # be found in the AUTHORS file in the root of the source tree.
      9 
     10 """Runs various WebRTC tests through valgrind_test.py.
     11 
     12 This script inherits the chrome_tests.py in Chrome, but allows running any test
     13 instead of only the hard-coded ones. It uses the -t cmdline flag to do this, and
     14 only supports specifying a single test for each run.
     15 
     16 Suppression files:
     17 The Chrome valgrind directory we use as a DEPS dependency contains the following
     18 suppression files:
     19   valgrind/memcheck/suppressions.txt
     20   valgrind/memcheck/suppressions_mac.txt
     21 Since they're referenced from the chrome_tests.py script, we have similar files
     22 below the directory of this script. When executing, this script will setup both
     23 Chrome's suppression files and our own, so we can easily maintain WebRTC
     24 specific suppressions in our own files.
     25 """
     26 
     27 import logging
     28 import optparse
     29 import os
     30 import sys
     31 
     32 import logging_utils
     33 import path_utils
     34 
     35 import chrome_tests
     36 
     37 
     38 class WebRTCTest(chrome_tests.ChromeTests):
     39   """Class that handles setup of suppressions for WebRTC.
     40 
     41   Everything else is inherited from chrome_tests.ChromeTests.
     42   """
     43 
     44   def __init__(self, test_name, options, args, test_in_chrome_tests):
     45     """Create a WebRTC test.
     46     Args:
     47       test_name: Short name for the test executable (no path).
     48       options: options to pass to ChromeTests.
     49       args: args to pass to ChromeTests.
     50       test_in_chrome_tests: The name of the test configuration in ChromeTests.
     51     """
     52     self._test_name = test_name
     53     chrome_tests.ChromeTests.__init__(self, options, args, test_in_chrome_tests)
     54 
     55   def _DefaultCommand(self, tool, exe=None, valgrind_test_args=None):
     56     """Override command-building method so we can add more suppressions."""
     57     cmd = chrome_tests.ChromeTests._DefaultCommand(self, tool, exe,
     58                                                    valgrind_test_args)
     59 
     60     # Add gtest filters, if found.
     61     chrome_tests.ChromeTests._AppendGtestFilter(self, tool, self._test_name,
     62                                                 cmd)
     63 
     64     # When ChromeTests._DefaultCommand has executed, it has setup suppression
     65     # files based on what's found in the memcheck/ subdirectory of
     66     # this script's location. If Mac or Windows is executing, additional
     67     # platform specific files have also been added.
     68     # Since only the ones located below this directory are added, we must also
     69     # add the ones maintained by Chrome, located in ../valgrind.
     70 
     71     # The idea is to look for --suppression arguments in the cmd list and add a
     72     # modified copy of each suppression file, for the corresponding file in
     73     # ../valgrind. If we would simply replace 'valgrind-webrtc' with 'valgrind'
     74     # we may produce invalid paths if other parts of the path contain that
     75     # string. That's why the code below only replaces the end of the path.
     76     script_dir = path_utils.ScriptDir()
     77     old_base, _ = os.path.split(script_dir)
     78     new_dir = os.path.join(old_base, 'valgrind')
     79     add_suppressions = []
     80     for token in cmd:
     81       if '--suppressions' in token:
     82         add_suppressions.append(token.replace(script_dir, new_dir))
     83     return add_suppressions + cmd
     84 
     85 
     86 def main(_):
     87   parser = optparse.OptionParser(
     88       'usage: %prog -b <dir> -t <test> -- <test args>')
     89   parser.disable_interspersed_args()
     90   parser.add_option('-b', '--build-dir',
     91                     help=('Location of the compiler output. Can only be used '
     92                           'when the test argument does not contain this path.'))
     93   parser.add_option("--target", help="Debug or Release")
     94   parser.add_option('-t', '--test', help='Test to run.')
     95   parser.add_option('', '--baseline', action='store_true', default=False,
     96                     help='Generate baseline data instead of validating')
     97   parser.add_option('', '--gtest_filter',
     98                     help='Additional arguments to --gtest_filter')
     99   parser.add_option('', '--gtest_repeat',
    100                     help='Argument for --gtest_repeat')
    101   parser.add_option("--gtest_shuffle", action="store_true", default=False,
    102                     help="Randomize tests' orders on every iteration.")
    103   parser.add_option("--gtest_break_on_failure", action="store_true",
    104                     default=False,
    105                     help="Drop in to debugger on assertion failure. Also "
    106                          "useful for forcing tests to exit with a stack dump "
    107                          "on the first assertion failure when running with "
    108                          "--gtest_repeat=-1")
    109   parser.add_option('-v', '--verbose', action='store_true', default=False,
    110                     help='Verbose output - enable debug log messages')
    111   parser.add_option('', '--tool', dest='valgrind_tool', default='memcheck',
    112                     help='Specify a valgrind tool to run the tests under')
    113   parser.add_option('', '--tool_flags', dest='valgrind_tool_flags', default='',
    114                     help='Specify custom flags for the selected valgrind tool')
    115   parser.add_option('', '--keep_logs', action='store_true', default=False,
    116                     help=('Store memory tool logs in the <tool>.logs directory '
    117                           'instead of /tmp.\nThis can be useful for tool '
    118                           'developers/maintainers.\nPlease note that the <tool>'
    119                           '.logs directory will be clobbered on tool startup.'))
    120   parser.add_option("--test-launcher-bot-mode", action="store_true",
    121                     help="run the tests with --test-launcher-bot-mode")
    122   parser.add_option("--test-launcher-total-shards", type=int,
    123                     help="run the tests with --test-launcher-total-shards")
    124   parser.add_option("--test-launcher-shard-index", type=int,
    125                     help="run the tests with --test-launcher-shard-index")
    126   options, args = parser.parse_args()
    127 
    128   if options.verbose:
    129     logging_utils.config_root(logging.DEBUG)
    130   else:
    131     logging_utils.config_root()
    132 
    133   if not options.test:
    134     parser.error('--test not specified')
    135 
    136   # Support build dir both with and without the target.
    137   if (options.target and options.build_dir and
    138       not options.build_dir.endswith(options.target)):
    139     options.build_dir = os.path.join(options.build_dir, options.target)
    140 
    141   # If --build_dir is provided, prepend it to the test executable if needed.
    142   test_executable = options.test
    143   if options.build_dir and not test_executable.startswith(options.build_dir):
    144     test_executable = os.path.join(options.build_dir, test_executable)
    145   args = [test_executable] + args
    146 
    147   test = WebRTCTest(options.test, options, args, 'cmdline')
    148   return test.Run()
    149 
    150 if __name__ == '__main__':
    151   return_code = main(sys.argv)
    152   sys.exit(return_code)
    153