summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--SConstruct18
-rw-r--r--buildscripts/burn_in_tags.py16
-rwxr-xr-xbuildscripts/burn_in_tests.py16
-rw-r--r--buildscripts/evergreen_burn_in_tests.py12
-rwxr-xr-xbuildscripts/evergreen_task_timeout.py7
-rw-r--r--buildscripts/idl/check_stable_api_commands_have_idl_definitions.py10
-rw-r--r--buildscripts/resmoke.ini.in2
-rw-r--r--buildscripts/resmokelib/configure_resmoke.py44
-rw-r--r--buildscripts/resmokelib/testing/testcases/sdam_json_test.py25
-rw-r--r--buildscripts/resmokelib/testing/testcases/server_selection_json_test.py22
-rw-r--r--buildscripts/tests/test_burn_in_tags.py9
-rw-r--r--buildscripts/tests/test_burn_in_tests.py2
-rw-r--r--buildscripts/tests/test_evergreen_burn_in_tests.py4
-rw-r--r--docs/testing/README.md36
-rw-r--r--etc/evergreen_yml_components/definitions.yml4
-rwxr-xr-xevergreen/burn_in_tests.sh2
-rw-r--r--evergreen/burn_in_tests_generate.sh2
-rwxr-xr-xevergreen/check_idl_compat.sh2
-rw-r--r--evergreen/functions/task_timeout_determine.sh1
-rw-r--r--site_scons/site_tools/auto_archive.py9
-rw-r--r--site_scons/site_tools/ninja.py1
-rw-r--r--src/mongo/SConscript1
-rw-r--r--src/mongo/resmoke/SConscript28
-rw-r--r--src/mongo/resmoke/resmoke.py.in55
24 files changed, 246 insertions, 82 deletions
diff --git a/SConstruct b/SConstruct
index 1d93db8371d..ffbf1280250 100644
--- a/SConstruct
+++ b/SConstruct
@@ -5381,24 +5381,6 @@ if has_option("cache"):
addNoCacheEmitter(env['BUILDERS']['SharedLibrary'])
addNoCacheEmitter(env['BUILDERS']['LoadableModule'])
-
-# We need to be explicit about including $DESTDIR here, unlike most
-# other places. Normally, auto_install_binaries will take care of
-# injecting DESTDIR for us, but we aren't using that now.
-resmoke_install_dir = env.subst("$DESTDIR/$PREFIX_BINDIR")
-resmoke_install_dir = os.path.normpath(resmoke_install_dir).replace("\\", r"\\")
-
-# Much blood sweat and tears were shed getting to this point. Any version of
-# this that uses SCons builders and a scanner will either not regenerate when it
-# should, cause everything to rebuild, or conflict with ninja. Sometimes all
-# three. So we've decided it's best to just write this file here every time
-# because it's the only solution that always works.
-with open("resmoke.ini", "w") as resmoke_config:
- resmoke_config.write("""
-[resmoke]
-install_dir = {install_dir}
-""".format(install_dir=resmoke_install_dir))
-
env.SConscript(
dirs=[
'src',
diff --git a/buildscripts/burn_in_tags.py b/buildscripts/burn_in_tags.py
index 1aba5eab457..5acb2e75861 100644
--- a/buildscripts/burn_in_tags.py
+++ b/buildscripts/burn_in_tags.py
@@ -132,7 +132,8 @@ def _generate_evg_build_variant(
# pylint: disable=too-many-arguments,too-many-locals
def _generate_evg_tasks(evergreen_api: EvergreenApi, shrub_project: ShrubProject,
task_expansions: Dict[str, Any], build_variant_map: Dict[str, str],
- repos: List[Repo], evg_conf: EvergreenProjectConfig) -> None:
+ repos: List[Repo], evg_conf: EvergreenProjectConfig,
+ install_dir: str) -> None:
"""
Generate burn in tests tasks for a given shrub config and group of build variants.
@@ -147,7 +148,7 @@ def _generate_evg_tasks(evergreen_api: EvergreenApi, shrub_project: ShrubProject
task_id = task_expansions[TASK_ID_EXPANSION]
change_detector = EvergreenFileChangeDetector(task_id, evergreen_api, os.environ)
changed_tests = change_detector.find_changed_tests(repos)
- tests_by_task = create_tests_by_task(build_variant, evg_conf, changed_tests)
+ tests_by_task = create_tests_by_task(build_variant, evg_conf, changed_tests, install_dir)
if tests_by_task:
shrub_build_variant = _generate_evg_build_variant(
evg_conf.get_variant(build_variant), run_build_variant,
@@ -165,7 +166,7 @@ def _generate_evg_tasks(evergreen_api: EvergreenApi, shrub_project: ShrubProject
def burn_in(task_expansions: Dict[str, Any], evg_conf: EvergreenProjectConfig,
- evergreen_api: RetryingEvergreenApi, repos: List[Repo]):
+ evergreen_api: RetryingEvergreenApi, repos: List[Repo], install_dir: str):
"""
Execute main program.
@@ -173,11 +174,12 @@ def burn_in(task_expansions: Dict[str, Any], evg_conf: EvergreenProjectConfig,
:param evg_conf: Evergreen configuration.
:param evergreen_api: Evergreen.py object.
:param repos: Git repositories.
+ :param install_dir: path to bin directory of a testable installation
"""
shrub_project = ShrubProject.empty()
build_variant_map = _create_evg_build_variant_map(task_expansions)
_generate_evg_tasks(evergreen_api, shrub_project, task_expansions, build_variant_map, repos,
- evg_conf)
+ evg_conf, install_dir)
if not validate_task_generation_limit(shrub_project):
sys.exit(1)
@@ -204,7 +206,9 @@ def _configure_logging(verbose: bool):
@click.option("--expansion-file", "expansion_file", required=True,
help="Location of expansions file generated by evergreen.")
@click.option("--verbose", is_flag=True)
-def main(expansion_file: str, verbose: bool):
+@click.option("--install-dir", "install_dir", required=True,
+ help="Path to bin directory of a testable installation")
+def main(expansion_file: str, verbose: bool, install_dir: str):
"""
Run new or changed tests in repeated mode to validate their stability.
@@ -220,7 +224,7 @@ def main(expansion_file: str, verbose: bool):
expansions_file_data = read_config.read_config_file(expansion_file)
evg_conf = evergreen.parse_evergreen_file(EVERGREEN_FILE)
- burn_in(expansions_file_data, evg_conf, evg_api, repos)
+ burn_in(expansions_file_data, evg_conf, evg_api, repos, install_dir)
if __name__ == "__main__":
diff --git a/buildscripts/burn_in_tests.py b/buildscripts/burn_in_tests.py
index dbd5f29f92c..27da0996b63 100755
--- a/buildscripts/burn_in_tests.py
+++ b/buildscripts/burn_in_tests.py
@@ -352,7 +352,7 @@ def create_task_list_for_tests(changed_tests: Set[str], build_variant: str,
def create_tests_by_task(build_variant: str, evg_conf: EvergreenProjectConfig,
- changed_tests: Set[str]) -> Dict[str, TaskInfo]:
+ changed_tests: Set[str], install_dir: str) -> Dict[str, TaskInfo]:
"""
Create a list of tests by task.
@@ -367,7 +367,7 @@ def create_tests_by_task(build_variant: str, evg_conf: EvergreenProjectConfig,
exclude_tests.append(f"{ENTERPRISE_MODULE_PATH}/**/*")
changed_tests = filter_tests(changed_tests, exclude_tests)
- buildscripts.resmokelib.parser.set_run_options()
+ buildscripts.resmokelib.parser.set_run_options(f"--installDir={shlex.quote(install_dir)}")
if changed_tests:
return create_task_list_for_tests(changed_tests, build_variant, evg_conf, exclude_suites,
exclude_tasks)
@@ -553,7 +553,7 @@ class BurnInOrchestrator:
self.burn_in_executor = burn_in_executor
self.evg_conf = evg_conf
- def burn_in(self, repos: List[Repo], build_variant: str) -> None:
+ def burn_in(self, repos: List[Repo], build_variant: str, install_dir: str) -> None:
"""
Execute burn in tests for the given git repositories.
@@ -563,12 +563,14 @@ class BurnInOrchestrator:
changed_tests = self.change_detector.find_changed_tests(repos)
LOGGER.info("Found changed tests", files=changed_tests)
- tests_by_task = create_tests_by_task(build_variant, self.evg_conf, changed_tests)
+ tests_by_task = create_tests_by_task(build_variant, self.evg_conf, changed_tests,
+ install_dir)
LOGGER.debug("tests and tasks found", tests_by_task=tests_by_task)
self.burn_in_executor.execute(tests_by_task)
+# pylint: disable=too-many-function-args
@click.command(context_settings=dict(ignore_unknown_options=True))
@click.option("--no-exec", "no_exec", default=False, is_flag=True,
help="Do not execute the found tests.")
@@ -586,12 +588,14 @@ class BurnInOrchestrator:
@click.option(
"--origin-rev", "origin_rev", default=None,
help="The revision in the mongo repo that changes will be compared against if specified.")
+@click.option("--install-dir", "install_dir", required=True, type=str,
+ help="Path to bin directory of a testable installation")
@click.argument("resmoke_args", nargs=-1, type=click.UNPROCESSED)
# pylint: disable=too-many-arguments,too-many-locals
def main(build_variant: str, no_exec: bool, repeat_tests_num: Optional[int],
repeat_tests_min: Optional[int], repeat_tests_max: Optional[int],
repeat_tests_secs: Optional[int], resmoke_args: str, verbose: bool,
- origin_rev: Optional[str]) -> None:
+ origin_rev: Optional[str], install_dir: str) -> None:
"""
Run new or changed tests in repeated mode to validate their stability.
@@ -639,7 +643,7 @@ def main(build_variant: str, no_exec: bool, repeat_tests_num: Optional[int],
executor = NopBurnInExecutor()
burn_in_orchestrator = BurnInOrchestrator(change_detector, executor, evg_conf)
- burn_in_orchestrator.burn_in(repos, build_variant)
+ burn_in_orchestrator.burn_in(repos, build_variant, install_dir)
if __name__ == "__main__":
diff --git a/buildscripts/evergreen_burn_in_tests.py b/buildscripts/evergreen_burn_in_tests.py
index 7ac28e4063c..37a0d2874ff 100644
--- a/buildscripts/evergreen_burn_in_tests.py
+++ b/buildscripts/evergreen_burn_in_tests.py
@@ -419,7 +419,7 @@ class GenerateBurnInExecutor(BurnInExecutor):
# pylint: disable=too-many-arguments
def burn_in(task_id: str, build_variant: str, generate_config: GenerateConfig,
repeat_config: RepeatConfig, evg_api: EvergreenApi, evg_conf: EvergreenProjectConfig,
- repos: List[Repo], generate_tasks_file: str) -> None:
+ repos: List[Repo], generate_tasks_file: str, install_dir: str) -> None:
"""
Run burn_in_tests.
@@ -431,12 +431,13 @@ def burn_in(task_id: str, build_variant: str, generate_config: GenerateConfig,
:param evg_conf: Evergreen project configuration.
:param repos: Git repos containing changes.
:param generate_tasks_file: File to write generate tasks configuration to.
+ :param install_dir: Path to bin directory of a testable installation
"""
change_detector = EvergreenFileChangeDetector(task_id, evg_api, os.environ)
executor = GenerateBurnInExecutor(generate_config, repeat_config, evg_api, generate_tasks_file)
burn_in_orchestrator = BurnInOrchestrator(change_detector, executor, evg_conf)
- burn_in_orchestrator.burn_in(repos, build_variant)
+ burn_in_orchestrator.burn_in(repos, build_variant, install_dir)
@click.command()
@@ -463,11 +464,13 @@ def burn_in(task_id: str, build_variant: str, generate_config: GenerateConfig,
@click.option("--verbose", "verbose", default=False, is_flag=True, help="Enable extra logging.")
@click.option("--task_id", "task_id", required=True, metavar='TASK_ID',
help="The evergreen task id.")
+@click.option("--install-dir", "install_dir", required=True,
+ help="Path to bin directory of a testable installation.")
# pylint: disable=too-many-arguments,too-many-locals
def main(build_variant: str, run_build_variant: str, distro: str, project: str,
generate_tasks_file: str, repeat_tests_num: Optional[int], repeat_tests_min: Optional[int],
repeat_tests_max: Optional[int], repeat_tests_secs: Optional[int], evg_api_config: str,
- verbose: bool, task_id: str):
+ verbose: bool, task_id: str, install_dir: str):
"""
Run new or changed tests in repeated mode to validate their stability.
@@ -500,6 +503,7 @@ def main(build_variant: str, run_build_variant: str, distro: str, project: str,
:param evg_api_config: Location of configuration file to connect to evergreen.
:param verbose: Log extra debug information.
:param task_id: Id of evergreen task being run in.
+ :param install_dir: path to bin directory of a testable installation
"""
_configure_logging(verbose)
@@ -520,7 +524,7 @@ def main(build_variant: str, run_build_variant: str, distro: str, project: str,
generate_config.validate(evg_conf)
burn_in(task_id, build_variant, generate_config, repeat_config, evg_api, evg_conf, repos,
- generate_tasks_file)
+ generate_tasks_file, install_dir)
if __name__ == "__main__":
diff --git a/buildscripts/evergreen_task_timeout.py b/buildscripts/evergreen_task_timeout.py
index f2177b35a16..bd5d48275d9 100755
--- a/buildscripts/evergreen_task_timeout.py
+++ b/buildscripts/evergreen_task_timeout.py
@@ -8,6 +8,7 @@ import sys
from datetime import datetime, timedelta
from pathlib import Path
from typing import Dict, List, Optional
+import shlex
import inject
import structlog
@@ -15,6 +16,7 @@ import yaml
from pydantic import BaseModel
from evergreen import EvergreenApi, RetryingEvergreenApi
+from buildscripts.task_generation.resmoke_proxy import ResmokeProxyService
from buildscripts.ciconfig.evergreen import (EvergreenProjectConfig, parse_evergreen_file)
from buildscripts.timeouts.timeout_service import (TimeoutParams, TimeoutService, TimeoutSettings)
from buildscripts.util.cmdutils import enable_logging
@@ -319,6 +321,8 @@ def main():
"""Determine the timeout value a task should use in evergreen."""
parser = argparse.ArgumentParser(description=main.__doc__)
+ parser.add_argument("--install-dir", dest="install_dir", required=True,
+ help="Path to bin directory of testable installation")
parser.add_argument("--task-name", dest="task", required=True, help="Task being executed.")
parser.add_argument("--suite-name", dest="suite_name", required=True,
help="Resmoke suite being run against.")
@@ -363,6 +367,9 @@ def main():
binder.bind(TimeoutOverrides, timeout_overrides)
binder.bind(EvergreenProjectConfig,
parse_evergreen_file(os.path.expanduser(options.evg_project_config)))
+ binder.bind(
+ ResmokeProxyService,
+ ResmokeProxyService(run_options=f"--installDir={shlex.quote(options.install_dir)}"))
inject.configure(dependencies)
diff --git a/buildscripts/idl/check_stable_api_commands_have_idl_definitions.py b/buildscripts/idl/check_stable_api_commands_have_idl_definitions.py
index b8b0c0ccae7..af3fe729ab7 100644
--- a/buildscripts/idl/check_stable_api_commands_have_idl_definitions.py
+++ b/buildscripts/idl/check_stable_api_commands_have_idl_definitions.py
@@ -167,14 +167,20 @@ def main():
arg_parser = argparse.ArgumentParser(description=__doc__)
arg_parser.add_argument("--include", type=str, action="append",
help="Directory to search for IDL import files")
- arg_parser.add_argument("--installDir", dest="install_dir", metavar="INSTALL_DIR",
+ arg_parser.add_argument("--install-dir", dest="install_dir", required=True,
help="Directory to search for MongoDB binaries")
arg_parser.add_argument("-v", "--verbose", action="count", help="Enable verbose logging")
arg_parser.add_argument("api_version", metavar="API_VERSION", help="API Version to check")
args = arg_parser.parse_args()
+ class FakeArgs:
+ """Fake argparse.Namespace-like class to pass arguments to _update_config_vars."""
+
+ def __init__(self):
+ self.INSTALL_DIR = args.install_dir # pylint: disable=invalid-name
+
# pylint: disable=protected-access
- configure_resmoke._update_config_vars(object)
+ configure_resmoke._update_config_vars(FakeArgs())
configure_resmoke._set_logging_config()
# Configure Fixture logging.
diff --git a/buildscripts/resmoke.ini.in b/buildscripts/resmoke.ini.in
deleted file mode 100644
index 5ee714b6dd2..00000000000
--- a/buildscripts/resmoke.ini.in
+++ /dev/null
@@ -1,2 +0,0 @@
-[resmoke]
-install_dir = @install_dir@ \ No newline at end of file
diff --git a/buildscripts/resmokelib/configure_resmoke.py b/buildscripts/resmokelib/configure_resmoke.py
index cc474d4dc59..ae3e05df25d 100644
--- a/buildscripts/resmokelib/configure_resmoke.py
+++ b/buildscripts/resmokelib/configure_resmoke.py
@@ -9,6 +9,9 @@ import distutils.spawn
import sys
import platform
import random
+import glob
+import textwrap
+import shlex
import pymongo.uri_parser
@@ -133,6 +136,19 @@ def _validate_config(parser): # pylint: disable=too-many-branches
parser.error(f"Found '{resolved_path}', but it is not an executable file")
+def _find_resmoke_wrappers():
+ # This is technically incorrect. PREFIX_BINDIR defaults to $PREFIX/bin, so
+ # if the user changes it to any some other value, this glob will fail to
+ # detect the resmoke wrapper.
+ # Additionally, the resmoke wrapper will not be found if a user performs
+ # their builds outside of the git repository root, (ex checkout at
+ # /data/mongo, build-dir at /data/build)
+ # We assume that users who fall under either case will explicitly pass the
+ # --installDir argument.
+ candidate_installs = glob.glob("**/bin/resmoke.py", recursive=True)
+ return list(map(os.path.dirname, candidate_installs))
+
+
def _update_config_vars(values): # pylint: disable=too-many-statements,too-many-locals,too-many-branches
"""Update the variables of the config module."""
@@ -148,11 +164,25 @@ def _update_config_vars(values): # pylint: disable=too-many-statements,too-many
config[cmdline_key] = cmdline_vars[cmdline_key]
if os.path.isfile("resmoke.ini"):
+ err = textwrap.dedent("""\
+Support for resmoke.ini has been removed. You must delete
+resmoke.ini and rerun your build to run resmoke. If only one testable
+installation is present, resmoke will automatically locate that installation.
+If you have multiple installations, you must either pass an explicit
+--installDir argument to the run subcommand to identify the installation you
+would like to test, or invoke the customized resmoke.py wrapper script staged
+into the bin directory of each installation.""")
config_parser = configparser.ConfigParser()
config_parser.read("resmoke.ini")
if "resmoke" in config_parser.sections():
user_config = dict(config_parser["resmoke"])
- config.update(user_config)
+ err += textwrap.dedent(f"""
+
+Based on the current value of resmoke.ini, after rebuilding, resmoke.py should
+be invoked as either:
+- {shlex.quote(f"{user_config['install_dir']}/resmoke.py")}
+- buildscripts/resmoke.py --installDir {shlex.quote(user_config['install_dir'])}""")
+ raise RuntimeError(err)
def setup_feature_flags():
_config.RUN_ALL_FEATURE_FLAG_TESTS = config.pop("run_all_feature_flag_tests")
@@ -224,6 +254,18 @@ def _update_config_vars(values): # pylint: disable=too-many-statements,too-many
_config.MULTIVERSION_BIN_VERSION = config.pop("old_bin_version")
_config.INSTALL_DIR = config.pop("install_dir")
+ if _config.INSTALL_DIR is None:
+ resmoke_wrappers = _find_resmoke_wrappers()
+ if len(resmoke_wrappers) == 1:
+ _config.INSTALL_DIR = resmoke_wrappers[0]
+ elif len(resmoke_wrappers) > 1:
+ err = textwrap.dedent(f"""\
+Multiple testable installations were found, but installDir was not specified.
+You must either call resmoke via one of the following scripts:
+{os.linesep.join(shlex.quote(resmoke_wrappers))}
+
+or explicitly pass --installDir to the run subcommand of buildscripts/resmoke.py.""")
+ raise RuntimeError(err)
if _config.INSTALL_DIR is not None:
# Normalize the path so that on Windows dist-test/bin
# translates to .\dist-test\bin then absolutify it since the
diff --git a/buildscripts/resmokelib/testing/testcases/sdam_json_test.py b/buildscripts/resmokelib/testing/testcases/sdam_json_test.py
index 3318e8c6ccc..0c952a84490 100644
--- a/buildscripts/resmokelib/testing/testcases/sdam_json_test.py
+++ b/buildscripts/resmokelib/testing/testcases/sdam_json_test.py
@@ -14,7 +14,6 @@ class SDAMJsonTestCase(interface.ProcessTestCase):
"""Server Discovery and Monitoring JSON test case."""
REGISTERED_NAME = "sdam_json_test"
- EXECUTABLE_BUILD_PATH = "build/**/mongo/client/sdam/sdam_json_test"
TEST_DIR = os.path.normpath("src/mongo/client/sdam/json_tests/sdam_tests")
def __init__(self, logger, json_test_file, program_options=None):
@@ -25,22 +24,14 @@ class SDAMJsonTestCase(interface.ProcessTestCase):
self.json_test_file = os.path.normpath(json_test_file)
self.program_options = utils.default_if_none(program_options, {}).copy()
- def _find_executable(self):
- if config.INSTALL_DIR is not None:
- binary = os.path.join(config.INSTALL_DIR, "sdam_json_test")
- if os.name == "nt":
- binary += ".exe"
-
- if os.path.isfile(binary):
- return binary
-
- execs = globstar.glob(self.EXECUTABLE_BUILD_PATH + '.exe')
- if not execs:
- execs = globstar.glob(self.EXECUTABLE_BUILD_PATH)
- if len(execs) != 1:
- raise errors.StopExecution(
- "There must be a single sdam_json_test binary in {}".format(execs))
- return execs[0]
+ def _find_executable(self): # pylint: disable=no-self-use
+ binary = os.path.join(config.INSTALL_DIR, "sdam_json_test")
+ if os.name == "nt":
+ binary += ".exe"
+
+ if not os.path.isfile(binary):
+ raise errors.StopExecution(f"Failed to locate sdam_json_test binary at {binary}")
+ return binary
def _make_process(self):
command_line = [self.program_executable]
diff --git a/buildscripts/resmokelib/testing/testcases/server_selection_json_test.py b/buildscripts/resmokelib/testing/testcases/server_selection_json_test.py
index b32c9dede9f..65dc5a49e39 100644
--- a/buildscripts/resmokelib/testing/testcases/server_selection_json_test.py
+++ b/buildscripts/resmokelib/testing/testcases/server_selection_json_test.py
@@ -14,7 +14,6 @@ class ServerSelectionJsonTestCase(interface.ProcessTestCase):
"""Server Selection JSON test case."""
REGISTERED_NAME = "server_selection_json_test"
- EXECUTABLE_BUILD_PATH = "build/**/mongo/client/sdam/server_selection_json_test"
TEST_DIR = os.path.normpath("src/mongo/client/sdam/json_tests/server_selection_tests")
def __init__(self, logger, json_test_file, program_options=None):
@@ -26,22 +25,15 @@ class ServerSelectionJsonTestCase(interface.ProcessTestCase):
self.json_test_file = os.path.normpath(json_test_file)
self.program_options = utils.default_if_none(program_options, {}).copy()
- def _find_executable(self):
- if config.INSTALL_DIR is not None:
- binary = os.path.join(config.INSTALL_DIR, "server_selection_json_test")
- if os.name == "nt":
- binary += ".exe"
+ def _find_executable(self): # pylint: disable=no-self-use
+ binary = os.path.join(config.INSTALL_DIR, "server_selection_json_test")
+ if os.name == "nt":
+ binary += ".exe"
- if os.path.isfile(binary):
- return binary
-
- execs = globstar.glob(self.EXECUTABLE_BUILD_PATH + '.exe')
- if not execs:
- execs = globstar.glob(self.EXECUTABLE_BUILD_PATH)
- if len(execs) != 1:
+ if not os.path.isfile(binary):
raise errors.StopExecution(
- "There must be a single server_selection_json_test binary in {}".format(execs))
- return execs[0]
+ f"Failed to locate server_selection_json_test binary at {binary}")
+ return binary
def _make_process(self):
command_line = [self.program_executable]
diff --git a/buildscripts/tests/test_burn_in_tags.py b/buildscripts/tests/test_burn_in_tags.py
index 023a47c3eb1..ec53a02d161 100644
--- a/buildscripts/tests/test_burn_in_tags.py
+++ b/buildscripts/tests/test_burn_in_tags.py
@@ -100,7 +100,7 @@ class TestGenerateEvgTasks(unittest.TestCase):
evergreen_api = MagicMock()
repo = MagicMock(working_dir=os.getcwd())
under_test._generate_evg_tasks(evergreen_api, shrub_config, expansions_file_data,
- buildvariant_map, [repo], evg_conf_mock)
+ buildvariant_map, [repo], evg_conf_mock, 'install-dir/bin')
self.assertEqual(shrub_config.as_dict(), EMPTY_PROJECT)
@@ -131,7 +131,7 @@ class TestGenerateEvgTasks(unittest.TestCase):
MagicMock(test_file="dir/test2.js", avg_duration_pass=10)
]
under_test._generate_evg_tasks(evergreen_api, shrub_config, expansions_file_data,
- buildvariant_map, [repo], evg_conf_mock)
+ buildvariant_map, [repo], evg_conf_mock, 'install-dir/bin')
generated_config = shrub_config.as_dict()
self.assertEqual(len(generated_config["buildvariants"]), 2)
@@ -207,7 +207,8 @@ class TestAcceptance(unittest.TestCase):
create_evg_build_variant_map_mock.return_value = CREATE_EVG_BUILD_VARIANT_MAP
- under_test.burn_in(EXPANSIONS_FILE_DATA, evg_conf_mock, MagicMock(), repos)
+ under_test.burn_in(EXPANSIONS_FILE_DATA, evg_conf_mock, MagicMock(), repos,
+ 'install_dir/bin')
write_to_file_mock.assert_called_once()
shrub_config = write_to_file_mock.call_args[0][2]
@@ -236,7 +237,7 @@ class TestAcceptance(unittest.TestCase):
'jstests/aggregation/accumulators/accumulator_js.js'
}
- under_test.burn_in(EXPANSIONS_FILE_DATA, evg_conf, MagicMock(), repos)
+ under_test.burn_in(EXPANSIONS_FILE_DATA, evg_conf, MagicMock(), repos, 'install_dir/bin')
write_to_file_mock.assert_called_once()
written_config = write_to_file_mock.call_args[0][2]
diff --git a/buildscripts/tests/test_burn_in_tests.py b/buildscripts/tests/test_burn_in_tests.py
index 4610332dfe6..c51f8c60ecf 100644
--- a/buildscripts/tests/test_burn_in_tests.py
+++ b/buildscripts/tests/test_burn_in_tests.py
@@ -497,7 +497,7 @@ class TestCreateTestsByTask(unittest.TestCase):
evg_conf_mock.get_variant.return_value = None
with self.assertRaises(ValueError):
- under_test.create_tests_by_task(variant, evg_conf_mock, set())
+ under_test.create_tests_by_task(variant, evg_conf_mock, set(), "install-dir/bin")
class TestLocalFileChangeDetector(unittest.TestCase):
diff --git a/buildscripts/tests/test_evergreen_burn_in_tests.py b/buildscripts/tests/test_evergreen_burn_in_tests.py
index 8b13189fe81..ee77ced2579 100644
--- a/buildscripts/tests/test_evergreen_burn_in_tests.py
+++ b/buildscripts/tests/test_evergreen_burn_in_tests.py
@@ -79,7 +79,7 @@ class TestAcceptance(unittest.TestCase):
mock_evg_api = MagicMock()
under_test.burn_in("task_id", variant, gen_config, repeat_config, mock_evg_api,
- mock_evg_conf, repos, "testfile.json")
+ mock_evg_conf, repos, "testfile.json", "install-dir/bin")
write_json_mock.assert_called_once()
written_config = json.loads(write_json_mock.call_args[0][1])
@@ -110,7 +110,7 @@ class TestAcceptance(unittest.TestCase):
mock_evg_api = MagicMock()
under_test.burn_in("task_id", variant, gen_config, repeat_config, mock_evg_api,
- mock_evg_conf, repos, "testfile.json")
+ mock_evg_conf, repos, "testfile.json", 'install-dir/bin')
write_json_mock.assert_called_once()
written_config = json.loads(write_json_mock.call_args[0][1])
diff --git a/docs/testing/README.md b/docs/testing/README.md
new file mode 100644
index 00000000000..8c76472c334
--- /dev/null
+++ b/docs/testing/README.md
@@ -0,0 +1,36 @@
+# Testing
+
+Most tests for MongoDB are run through resmoke, our test runner and orchestration tool.
+The entry point for resmoke can be found at `buildscripts/resmoke.py`
+
+## run
+
+The run subcommand can run suites (list of tests and the MongoDB topology and
+configuration to run them against), and explicitly named test files.
+
+A single suite can be specified using the `--suite` flag, and multiple suites
+can be specified by providing a comma separated list to the `--suites` flag.
+
+Additional parameters for the run subcommand can be found on the help page,
+accessible by running `buildscripts/resmoke.py run --help`
+
+Additional documentation on our suite configuration can be found on the
+[Suites configuration file page](../suites.md)
+
+### Testable Installations (`--installDir`)
+
+resmoke can run tests against any testable installation of MongoDB (such
+as ASAN, Debug, Release). When possible, resmoke will automatically locate and
+run with a locally built copy of MongoDB Server, so long as that build was
+installed to a subdirectory of the root of the git repository, and there is
+exactly one build. In other situations, the `--installDir` flag, passed to run
+subcommand, can be used to indicate the location of the mongod/mongos binaries.
+
+As an alternative, you may instead prefer to use the resmoke.py wrapper script
+located in the same directory as the mongod binary, which will automatically
+set `installDir` for you.
+
+Note that this wrapper is unavailable in packaged installations of MongoDB
+Server, such as those provided by Homebrew, and other package managers. If you
+would like to run tests against a packaged installation, you must explicitly
+pass `--installDir` to resmoke.py
diff --git a/etc/evergreen_yml_components/definitions.yml b/etc/evergreen_yml_components/definitions.yml
index a0ab51f47ea..79927a7c975 100644
--- a/etc/evergreen_yml_components/definitions.yml
+++ b/etc/evergreen_yml_components/definitions.yml
@@ -2425,6 +2425,7 @@ tasks:
- func: "run tests"
vars:
suite: unittests
+ install_dir: build/install/bin
## run_unittests with UndoDB live-record ##
#- name: run_unittests_with_recording
@@ -2452,6 +2453,7 @@ tasks:
# # Start fewer jobs since there's a constant amount of overhead of starting
# # live-record for each job.
# resmoke_jobs_factor: 0.3
+# install_dir: build/install/bin
##compile_and_archive_libfuzzertests - build libfuzzertests ##
@@ -2492,6 +2494,7 @@ tasks:
vars:
targets: install-sdam-json-test
compiling_for_test: true
+ install_dir: build/install/bin
- func: "run tests"
vars:
suite: sdam_json_test
@@ -2503,6 +2506,7 @@ tasks:
vars:
targets: install-server-selection-json-test
compiling_for_test: true
+ install_dir: build/install/bin
- func: "run tests"
## compile_dbtest ##
diff --git a/evergreen/burn_in_tests.sh b/evergreen/burn_in_tests.sh
index 23ac58851d4..5f6124a5f47 100755
--- a/evergreen/burn_in_tests.sh
+++ b/evergreen/burn_in_tests.sh
@@ -17,4 +17,4 @@ if [ -n "${burn_in_tests_build_variant}" ]; then
fi
burn_in_args="$burn_in_args --repeat-tests-min=2 --repeat-tests-max=1000 --repeat-tests-secs=600"
# Evergreen executable is in $HOME.
-PATH="$PATH:$HOME" eval $python buildscripts/evergreen_burn_in_tests.py --project=${project} $build_variant_opts --distro=${distro_id} --generate-tasks-file=burn_in_tests_gen.json --task_id ${task_id} $burn_in_args --verbose
+PATH="$PATH:$HOME" eval $python buildscripts/evergreen_burn_in_tests.py --project=${project} $build_variant_opts --distro=${distro_id} --generate-tasks-file=burn_in_tests_gen.json --task_id ${task_id} $burn_in_args --verbose --install-dir "${install_dir}"
diff --git a/evergreen/burn_in_tests_generate.sh b/evergreen/burn_in_tests_generate.sh
index 639a18e0045..6e2499d5e39 100644
--- a/evergreen/burn_in_tests_generate.sh
+++ b/evergreen/burn_in_tests_generate.sh
@@ -9,4 +9,4 @@ set -o verbose
activate_venv
# Evergreen executable is in $HOME.
-PATH=$PATH:$HOME $python buildscripts/burn_in_tags.py --expansion-file ../expansions.yml
+PATH=$PATH:$HOME $python buildscripts/burn_in_tags.py --expansion-file ../expansions.yml --install-dir "${install_dir}"
diff --git a/evergreen/check_idl_compat.sh b/evergreen/check_idl_compat.sh
index 0fb71452e9c..afa9c3f3239 100755
--- a/evergreen/check_idl_compat.sh
+++ b/evergreen/check_idl_compat.sh
@@ -7,7 +7,7 @@ set -o errexit
set -o verbose
activate_venv
-$python buildscripts/idl/check_stable_api_commands_have_idl_definitions.py -v --include src --include src/mongo/db/modules/enterprise/src --installDir dist-test/bin 1
+$python buildscripts/idl/check_stable_api_commands_have_idl_definitions.py -v --install-dir dist-test/bin --include src --include src/mongo/db/modules/enterprise/src 1
$python buildscripts/idl/checkout_idl_files_from_past_releases.py -v idls
find idls -maxdepth 1 -mindepth 1 -type d | while read dir; do
echo "Performing idl check compatibility with release: $dir:"
diff --git a/evergreen/functions/task_timeout_determine.sh b/evergreen/functions/task_timeout_determine.sh
index 93c7d2baa36..79d393bb964 100644
--- a/evergreen/functions/task_timeout_determine.sh
+++ b/evergreen/functions/task_timeout_determine.sh
@@ -27,6 +27,7 @@ fi
activate_venv
PATH=$PATH:$HOME:/ $python buildscripts/evergreen_task_timeout.py $timeout_factor \
+ --install-dir "${install_dir}" \
--task-name ${task_name} \
--suite-name ${suite_name} \
--build-variant $build_variant_for_timeout \
diff --git a/site_scons/site_tools/auto_archive.py b/site_scons/site_tools/auto_archive.py
index f4c7201b33e..b3c9ddd99a4 100644
--- a/site_scons/site_tools/auto_archive.py
+++ b/site_scons/site_tools/auto_archive.py
@@ -133,7 +133,14 @@ def collect_transitive_files(env, entry):
# anyway.
stack.extend(env.GetTransitivelyInstalledFiles(s))
- return sorted(files)
+ # Setting the AIB_NO_ARCHIVE attribute to True prevents outputs from an
+ # AutoInstall builder from being included into archives produced by this
+ # tool
+ # Usage:
+ # node = env.AutoInstall(...)
+ # setattr(node[0].attributes, 'AIB_NO_ARCHIVE', True)
+ # TODO SERVER-61013 Update documentation once AutoInstall is a real builder
+ return sorted(f for f in files if not getattr(f.attributes, 'AIB_NO_ARCHIVE', False))
def auto_archive_gen(first_env, make_archive_script, pkg_fmt):
diff --git a/site_scons/site_tools/ninja.py b/site_scons/site_tools/ninja.py
index 5826be827f4..c755e12b469 100644
--- a/site_scons/site_tools/ninja.py
+++ b/site_scons/site_tools/ninja.py
@@ -660,6 +660,7 @@ class NinjaState:
kwargs['pool'] = 'local_pool'
ninja.rule(rule, **kwargs)
+ # TODO SERVER-64664
generated_source_files = sorted({
output
# First find builds which have header files in their outputs.
diff --git a/src/mongo/SConscript b/src/mongo/SConscript
index 82e6e06b67c..8696da79339 100644
--- a/src/mongo/SConscript
+++ b/src/mongo/SConscript
@@ -35,6 +35,7 @@ env.SConscript(
'installer',
'logv2',
'platform',
+ 'resmoke',
'rpc',
's',
'scripting',
diff --git a/src/mongo/resmoke/SConscript b/src/mongo/resmoke/SConscript
new file mode 100644
index 00000000000..fb80ab1a713
--- /dev/null
+++ b/src/mongo/resmoke/SConscript
@@ -0,0 +1,28 @@
+# -*- mode: python -*-
+import os
+import SCons
+Import('env')
+
+env = env.Clone()
+
+install_dir = env.Dir('$DESTDIR/$PREFIX_BINDIR').path.replace("\\", r"\\")
+resmoke_py = env.Substfile(
+ target="resmoke.py",
+ source='resmoke.py.in',
+ SUBST_DICT = {
+ '@install_dir@': install_dir,
+ }
+)
+resmoke_py_install = env.AutoInstall(
+ '$PREFIX_BINDIR',
+ source=resmoke_py,
+ AIB_COMPONENT='common',
+ AIB_ROLE='runtime',
+)
+# TODO SERVER-61013: We shouldn't have to setattr this once AutoInstall is a
+# real builder
+setattr(resmoke_py_install[0].attributes, 'AIB_NO_ARCHIVE', True)
+env.AddPostAction(
+ resmoke_py_install,
+ action=SCons.Defaults.Chmod('$TARGET', "u+x"),
+)
diff --git a/src/mongo/resmoke/resmoke.py.in b/src/mongo/resmoke/resmoke.py.in
new file mode 100644
index 00000000000..8b5d4106480
--- /dev/null
+++ b/src/mongo/resmoke/resmoke.py.in
@@ -0,0 +1,55 @@
+#!/usr/bin/env python3
+import importlib.util
+import os
+import os.path
+import argparse
+import sys
+import shlex
+import textwrap
+
+BUILD_BIN_DIR=r"@install_dir@"
+
+class _SilentArgumentParser(argparse.ArgumentParser):
+ """ArgumentParser variant that silently swallows errors."""
+ def error(self, message):
+ pass
+
+# We do not want people to use this wrapper and provide --installDir,
+# especially if the user tries to supply the wrong installDir. Prevent that
+# by parsing the command line flags and make sure that --installDir is not
+# passed in. (only the run command supports this flag)
+try:
+ parser = _SilentArgumentParser(add_help=False)
+
+ subparsers = parser.add_subparsers(dest="cmd")
+ run = subparsers.add_parser("run")
+ run.add_argument("--installDir")
+ args, _ = parser.parse_known_args()
+ if "installDir" in args and args.installDir is not None:
+ err = textwrap.dedent(f"""\
+Argument '--installDir' passed to resmoke wrapper script, but this action can
+have unforeseen consequences. Either remove --installDir, or call resmoke as
+`buildscripts/resmoke.py run --installDir={shlex.quote(args.installDir)}`""")
+ raise RuntimeError(err)
+
+ run_cmd_called = args.cmd == "run"
+except RuntimeError:
+ raise
+except:
+ run_cmd_called = False
+
+# If the run subcommand is being used, inject installDir
+if run_cmd_called:
+ i = sys.argv.index("run")
+ sys.argv.insert(i+1, "--installDir")
+ sys.argv.insert(i+2, BUILD_BIN_DIR)
+
+path_to_resmoke_py = os.path.join("buildscripts", "resmoke.py")
+
+# import and run the cli
+spec = importlib.util.spec_from_file_location("__main__", path_to_resmoke_py)
+resmoke = importlib.util.module_from_spec(spec)
+resmoke.__package__ = None
+spec.loader.exec_module(resmoke)
+
+# -*- mode: python -*-