mirror of
https://github.com/mongodb/mongo.git
synced 2024-11-30 00:56:44 +01:00
132 lines
5.4 KiB
Python
132 lines
5.4 KiB
Python
"""Module for retrieving the configuration of resmoke.py test suites."""
|
|
|
|
import collections
|
|
import optparse
|
|
import os
|
|
|
|
from . import config as _config
|
|
from . import errors
|
|
from . import utils
|
|
from .testing import suite as _suite
|
|
|
|
|
|
def get_named_suites():
|
|
"""Return a sorted list of the suites names."""
|
|
# Skip "with_*server" and "no_server" because they do not define any test files to run.
|
|
executor_only = {"with_server", "with_external_server", "no_server"}
|
|
names = [name for name in _config.NAMED_SUITES.keys() if name not in executor_only]
|
|
names.sort()
|
|
return names
|
|
|
|
|
|
def get_named_suites_with_root_level_key(root_level_key):
|
|
"""Return the suites that contain the given root_level_key and their values."""
|
|
all_suite_names = get_named_suites()
|
|
suites_to_return = []
|
|
|
|
for suite in all_suite_names:
|
|
suite_config = _get_suite_config(suite)
|
|
if root_level_key in suite_config.keys() and suite_config[root_level_key]:
|
|
suites_to_return.append(
|
|
{"origin": suite, "multiversion_name": suite_config[root_level_key]})
|
|
return suites_to_return
|
|
|
|
|
|
def create_test_membership_map(fail_on_missing_selector=False, test_kind=None):
|
|
"""Return a dict keyed by test name containing all of the suites that will run that test.
|
|
|
|
If 'test_kind' is specified, then only the mappings for that kind of test are returned. Multiple
|
|
kinds of tests can be specified as an iterable (e.g. a tuple or list). This function parses the
|
|
definition of every available test suite, which is an expensive operation. It is therefore
|
|
desirable for it to only ever be called once.
|
|
"""
|
|
if test_kind is not None:
|
|
if isinstance(test_kind, str):
|
|
test_kind = [test_kind]
|
|
|
|
test_kind = frozenset(test_kind)
|
|
|
|
test_membership = collections.defaultdict(list)
|
|
suite_names = get_named_suites()
|
|
for suite_name in suite_names:
|
|
try:
|
|
suite_config = _get_suite_config(suite_name)
|
|
if test_kind and suite_config.get("test_kind") not in test_kind:
|
|
continue
|
|
suite = _suite.Suite(suite_name, suite_config)
|
|
except IOError as err:
|
|
# We ignore errors from missing files referenced in the test suite's "selector"
|
|
# section. Certain test suites (e.g. unittests.yml) have a dedicated text file to
|
|
# capture the list of tests they run; the text file may not be available if the
|
|
# associated SCons target hasn't been built yet.
|
|
if err.filename in _config.EXTERNAL_SUITE_SELECTORS:
|
|
if not fail_on_missing_selector:
|
|
continue
|
|
raise
|
|
|
|
for testfile in suite.tests:
|
|
if isinstance(testfile, (dict, list)):
|
|
continue
|
|
test_membership[testfile].append(suite_name)
|
|
return test_membership
|
|
|
|
|
|
def get_suites(suite_files, test_files):
|
|
"""Retrieve the Suite instances based on suite configuration files and override parameters.
|
|
|
|
Args:
|
|
suite_files: A list of file paths pointing to suite YAML configuration files. For the suites
|
|
defined in 'buildscripts/resmokeconfig/suites/', a shorthand name consisting of the
|
|
filename without the extension can be used.
|
|
test_files: A list of file paths pointing to test files overriding the roots for the suites.
|
|
"""
|
|
suite_roots = None
|
|
if test_files:
|
|
# Do not change the execution order of the tests passed as args, unless a tag option is
|
|
# specified. If an option is specified, then sort the tests for consistent execution order.
|
|
_config.ORDER_TESTS_BY_NAME = any(
|
|
tag_filter is not None
|
|
for tag_filter in (_config.EXCLUDE_WITH_ANY_TAGS, _config.INCLUDE_WITH_ANY_TAGS))
|
|
# Build configuration for list of files to run.
|
|
suite_roots = _make_suite_roots(test_files)
|
|
|
|
suites = []
|
|
for suite_filename in suite_files:
|
|
suite_config = _get_suite_config(suite_filename)
|
|
if suite_roots:
|
|
# Override the suite's default test files with those passed in from the command line.
|
|
suite_config.update(suite_roots)
|
|
suite = _suite.Suite(suite_filename, suite_config)
|
|
suites.append(suite)
|
|
return suites
|
|
|
|
|
|
def get_suite(suite_file):
|
|
"""Retrieve the Suite instance corresponding to a suite configuration file."""
|
|
suite_config = _get_suite_config(suite_file)
|
|
return _suite.Suite(suite_file, suite_config)
|
|
|
|
|
|
def _make_suite_roots(files):
|
|
return {"selector": {"roots": files}}
|
|
|
|
|
|
def _get_suite_config(pathname):
|
|
"""Attempt to read YAML configuration from 'pathname' for the suite."""
|
|
return _get_yaml_config("suite", pathname)
|
|
|
|
|
|
def _get_yaml_config(kind, pathname):
|
|
# Named executors or suites are specified as the basename of the file, without the .yml
|
|
# extension.
|
|
if not utils.is_yaml_file(pathname) and not os.path.dirname(pathname):
|
|
if pathname not in _config.NAMED_SUITES: # pylint: disable=unsupported-membership-test
|
|
raise errors.SuiteNotFound("Unknown %s '%s'" % (kind, pathname))
|
|
# Expand 'pathname' to full path.
|
|
pathname = _config.NAMED_SUITES[pathname] # pylint: disable=unsubscriptable-object
|
|
|
|
if not utils.is_yaml_file(pathname) or not os.path.isfile(pathname):
|
|
raise optparse.OptionValueError(
|
|
"Expected a %s YAML config, but got '%s'" % (kind, pathname))
|
|
return utils.load_yaml_file(pathname)
|