michael@0: #!/usr/bin/env python michael@0: # Copyright (c) 2012 The LibYuv Project Authors. All rights reserved. michael@0: # michael@0: # Use of this source code is governed by a BSD-style license michael@0: # that can be found in the LICENSE file in the root of the source michael@0: # tree. An additional intellectual property rights grant can be found michael@0: # in the file PATENTS. All contributing project authors may michael@0: # be found in the AUTHORS file in the root of the source tree. michael@0: michael@0: """Runs various libyuv tests through valgrind_test.py. michael@0: michael@0: This script inherits the chrome_tests.py in Chrome, but allows running any test michael@0: instead of only the hard-coded ones. It uses the -t cmdline flag to do this, and michael@0: only supports specifying a single test for each run. michael@0: michael@0: Suppression files: michael@0: The Chrome valgrind directory we use as a DEPS dependency contains the following michael@0: suppression files: michael@0: valgrind/memcheck/suppressions.txt michael@0: valgrind/memcheck/suppressions_mac.txt michael@0: valgrind/tsan/suppressions.txt michael@0: valgrind/tsan/suppressions_mac.txt michael@0: valgrind/tsan/suppressions_win32.txt michael@0: Since they're referenced from the chrome_tests.py script, we have similar files michael@0: below the directory of this script. When executing, this script will setup both michael@0: Chrome's suppression files and our own, so we can easily maintain libyuv michael@0: specific suppressions in our own files. michael@0: """ michael@0: michael@0: import logging michael@0: import optparse michael@0: import os michael@0: import sys michael@0: michael@0: import logging_utils michael@0: import path_utils michael@0: michael@0: import chrome_tests michael@0: michael@0: michael@0: class LibyuvTest(chrome_tests.ChromeTests): michael@0: """Class that handles setup of suppressions for libyuv. michael@0: michael@0: Everything else is inherited from chrome_tests.ChromeTests. michael@0: """ michael@0: michael@0: def _DefaultCommand(self, tool, exe=None, valgrind_test_args=None): michael@0: """Override command-building method so we can add more suppressions.""" michael@0: cmd = chrome_tests.ChromeTests._DefaultCommand(self, tool, exe, michael@0: valgrind_test_args) michael@0: # When ChromeTests._DefaultCommand has executed, it has setup suppression michael@0: # files based on what's found in the memcheck/ or tsan/ subdirectories of michael@0: # this script's location. If Mac or Windows is executing, additional michael@0: # platform specific files have also been added. michael@0: # Since only the ones located below this directory is added, we must also michael@0: # add the ones maintained by Chrome, located in ../valgrind. michael@0: michael@0: # The idea is to look for --suppression arguments in the cmd list and add a michael@0: # modified copy of each suppression file, for the corresponding file in michael@0: # ../valgrind. If we would simply replace 'valgrind-libyuv' with 'valgrind' michael@0: # we may produce invalid paths if other parts of the path contain that michael@0: # string. That's why the code below only replaces the end of the path. michael@0: script_dir = path_utils.ScriptDir() michael@0: old_base, _ = os.path.split(script_dir) michael@0: new_dir = os.path.join(old_base, 'valgrind') michael@0: add_suppressions = [] michael@0: for token in cmd: michael@0: if '--suppressions' in token: michael@0: add_suppressions.append(token.replace(script_dir, new_dir)) michael@0: return add_suppressions + cmd michael@0: michael@0: michael@0: def main(_): michael@0: parser = optparse.OptionParser('usage: %prog -b -t ') michael@0: parser.disable_interspersed_args() michael@0: parser.add_option('-b', '--build-dir', michael@0: help=('Location of the compiler output. Can only be used ' michael@0: 'when the test argument does not contain this path.')) michael@0: parser.add_option("--target", help="Debug or Release") michael@0: parser.add_option('-t', '--test', help='Test to run.') michael@0: parser.add_option('', '--baseline', action='store_true', default=False, michael@0: help='Generate baseline data instead of validating') michael@0: parser.add_option('', '--gtest_filter', michael@0: help='Additional arguments to --gtest_filter') michael@0: parser.add_option('', '--gtest_repeat', michael@0: help='Argument for --gtest_repeat') michael@0: parser.add_option('-v', '--verbose', action='store_true', default=False, michael@0: help='Verbose output - enable debug log messages') michael@0: parser.add_option('', '--tool', dest='valgrind_tool', default='memcheck', michael@0: help='Specify a valgrind tool to run the tests under') michael@0: parser.add_option('', '--tool_flags', dest='valgrind_tool_flags', default='', michael@0: help='Specify custom flags for the selected valgrind tool') michael@0: parser.add_option('', '--keep_logs', action='store_true', default=False, michael@0: help=('Store memory tool logs in the .logs directory ' michael@0: 'instead of /tmp.\nThis can be useful for tool ' michael@0: 'developers/maintainers.\nPlease note that the ' michael@0: '.logs directory will be clobbered on tool startup.')) michael@0: options, args = parser.parse_args() michael@0: michael@0: if options.verbose: michael@0: logging_utils.config_root(logging.DEBUG) michael@0: else: michael@0: logging_utils.config_root() michael@0: michael@0: if not options.test: michael@0: parser.error('--test not specified') michael@0: michael@0: # Support build dir both with and without the target. michael@0: if (options.target and options.build_dir and michael@0: not options.build_dir.endswith(options.target)): michael@0: options.build_dir = os.path.join(options.build_dir, options.target) michael@0: michael@0: # If --build_dir is provided, prepend it to the test executable if needed. michael@0: test_executable = options.test michael@0: if options.build_dir and not test_executable.startswith(options.build_dir): michael@0: test_executable = os.path.join(options.build_dir, test_executable) michael@0: args = [test_executable] + args michael@0: michael@0: test = LibyuvTest(options, args, 'cmdline') michael@0: return test.Run() michael@0: michael@0: if __name__ == '__main__': michael@0: return_code = main(sys.argv) michael@0: sys.exit(return_code)