diff options
author | Mike Grundy <michael.grundy@10gen.com> | 2016-04-28 14:11:49 -0400 |
---|---|---|
committer | Mike Grundy <michael.grundy@10gen.com> | 2016-05-10 09:51:17 -0400 |
commit | 686bd5e0aba3716f093ee9b6f9d8c67f2faef3d9 (patch) | |
tree | 92434d0615dec7bebbb264cb56221aa4b416d72a | |
parent | 6218a59683bf97c6cb7f198f9d9eccc0371f8bb7 (diff) | |
download | mongo-686bd5e0aba3716f093ee9b6f9d8c67f2faef3d9.tar.gz |
SERVER-21841 Add mode to resmoke.py to list under what suites a test runs
-rwxr-xr-x | buildscripts/resmoke.py | 23 | ||||
-rw-r--r-- | buildscripts/resmokelib/config.py | 10 | ||||
-rw-r--r-- | buildscripts/resmokelib/parser.py | 33 | ||||
-rw-r--r-- | buildscripts/resmokelib/selector.py | 10 |
4 files changed, 74 insertions, 2 deletions
diff --git a/buildscripts/resmoke.py b/buildscripts/resmoke.py index a6cb03cb620..8afa1d5e77c 100755 --- a/buildscripts/resmoke.py +++ b/buildscripts/resmoke.py @@ -115,6 +115,20 @@ def _dump_suite_config(suite, logging_config): return "\n".join(sb) +def find_suites_by_test(suites): + """ + Looks up what other resmoke suites run the tests specified in the suites + parameter. Returns a dict keyed by test name, value is array of suite names. + """ + + memberships = {} + test_membership = resmokelib.parser.create_test_membership_map() + for suite in suites: + for group in suite.test_groups: + for test in group.tests: + memberships[test] = test_membership[test] + return memberships + def _write_report_file(suites, pathname): """ Writes the report.json file if requested. @@ -151,6 +165,15 @@ def main(): interrupted = False suites = resmokelib.parser.get_suites(values, args) + + # Run the suite finder after the test suite parsing is complete. + if values.find_suites: + suites_by_test = find_suites_by_test(suites) + for test in sorted(suites_by_test): + suite_names = suites_by_test[test] + resmoke_logger.info("%s will be run by the following suite(s): %s", test, suite_names) + sys.exit(0) + try: for suite in suites: resmoke_logger.info(_dump_suite_config(suite, logging_config)) diff --git a/buildscripts/resmokelib/config.py b/buildscripts/resmokelib/config.py index d19ca0181df..950a0f8ffa2 100644 --- a/buildscripts/resmokelib/config.py +++ b/buildscripts/resmokelib/config.py @@ -170,3 +170,13 @@ WT_INDEX_CONFIG = None # Default sort order for test execution. Will only be changed if --suites wasn't specified. ORDER_TESTS_BY_NAME = True + +# Default file names for externally generated lists of tests created during the build. +DEFAULT_UNIT_TEST_LIST = "build/unittests.txt" +DEFAULT_INTEGRATION_TEST_LIST = "build/integration_tests.txt" + +# External files or executables, used as suite selectors, that are created during the build and +# therefore might not be available when creating a test membership map. +EXTERNAL_SUITE_SELECTORS = [DEFAULT_UNIT_TEST_LIST, + DEFAULT_INTEGRATION_TEST_LIST, + DEFAULT_DBTEST_EXECUTABLE] diff --git a/buildscripts/resmokelib/parser.py b/buildscripts/resmokelib/parser.py index c170e4c218d..9966fff46c6 100644 --- a/buildscripts/resmokelib/parser.py +++ b/buildscripts/resmokelib/parser.py @@ -4,6 +4,7 @@ Parser for command line arguments. from __future__ import absolute_import +import collections import os import os.path import optparse @@ -102,6 +103,9 @@ def parse_command_line(): help=("Comma separated list of tags. Any jstest that contains any of the" " specified tags will be excluded from any suites that are run.")) + parser.add_option("-f", "--findSuites", action="store_true", dest="find_suites", + help="List the names of the suites that will execute the specified tests.") + parser.add_option("--includeWithAllTags", dest="include_with_all_tags", metavar="TAG1,TAG2", help=("Comma separated list of tags. For the jstest portion of the suite(s)," " only tests which have all of the specified tags will be run.")) @@ -195,6 +199,7 @@ def parse_command_line(): parser.set_defaults(executor_file="with_server", logger_file="console", dry_run="off", + find_suites=False, list_suites=False, prealloc_journal="off") @@ -252,6 +257,34 @@ def update_config_vars(values): raise optparse.OptionValueError("Unknown option(s): %s" % (config.keys())) +def create_test_membership_map(fail_on_missing_selector=False): + """ + Returns a dict keyed by test name containing all of the suites that will run that test. + Since this iterates through every available suite, it should only be run once. + """ + + test_membership = collections.defaultdict(list) + suite_names = get_named_suites() + for suite_name in suite_names: + try: + suite_config = _get_suite_config(suite_name) + suite = testing.suite.Suite(suite_name, suite_config) + except IOError as err: + # If unittests.txt or integration_tests.txt aren't there we'll ignore the error because + # unittests haven't been built yet (this is highly likely using find interactively). + if err.filename in _config.EXTERNAL_SUITE_SELECTORS: + if not fail_on_missing_selector: + continue + raise + + for group in suite.test_groups: + for testfile in group.tests: + if isinstance(testfile, dict): + continue + test_membership[testfile].append(suite_name) + return test_membership + + def get_suites(values, args): if (values.suite_files is None and not args) or (values.suite_files is not None and args): raise optparse.OptionValueError("Must specify either --suites or a list of tests") diff --git a/buildscripts/resmokelib/selector.py b/buildscripts/resmokelib/selector.py index c2dc0fca41b..be9359b5d28 100644 --- a/buildscripts/resmokelib/selector.py +++ b/buildscripts/resmokelib/selector.py @@ -7,6 +7,7 @@ on whether they apply to C++ unit tests, dbtests, or JS tests. from __future__ import absolute_import +import errno import fnmatch import os.path import subprocess @@ -43,14 +44,16 @@ def _filter_cpp_tests(kind, root, include_files, exclude_files): return list(remaining) return tests -def filter_cpp_unit_tests(root="build/unittests.txt", include_files=None, exclude_files=None): +def filter_cpp_unit_tests(root=config.DEFAULT_UNIT_TEST_LIST, + include_files=None, + exclude_files=None): """ Filters out what C++ unit tests to run. """ return _filter_cpp_tests("C++ unit test", root, include_files, exclude_files) -def filter_cpp_integration_tests(root="build/integration_tests.txt", +def filter_cpp_integration_tests(root=config.DEFAULT_INTEGRATION_TEST_LIST, include_files=None, exclude_files=None): """ @@ -78,6 +81,9 @@ def filter_dbtests(binary=None, include_suites=None): if sys.platform == "win32" and os.path.splitext(binary)[1] != ".exe": binary += ".exe" + if not os.path.isfile(binary): + raise IOError(errno.ENOENT, "File not found", binary) + program = subprocess.Popen([binary, "--list"], stdout=subprocess.PIPE) stdout = program.communicate()[0] |