0
0
mirror of https://github.com/mongodb/mongo.git synced 2024-11-30 00:56:44 +01:00
mongodb/buildscripts/resmokelib/suitesconfig.py

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)