From acc824bf085f1c255578e5e48f5e8d337ef84402 Mon Sep 17 00:00:00 2001 From: Jim OLeary Date: Wed, 25 Mar 2020 12:19:41 +0000 Subject: SERVER-46439 Add acceptance tests for burn_in_tags. --- buildscripts/burn_in_tags.py | 40 ++++--- buildscripts/tests/test_burn_in_tags.py | 118 +++++++++++++++++++++ buildscripts/tests/test_burn_in_tags_evergreen.yml | 73 ++++++++++++- 3 files changed, 218 insertions(+), 13 deletions(-) diff --git a/buildscripts/burn_in_tags.py b/buildscripts/burn_in_tags.py index 0a4210c4027..94a6dca6772 100644 --- a/buildscripts/burn_in_tags.py +++ b/buildscripts/burn_in_tags.py @@ -1,11 +1,12 @@ #!/usr/bin/env python3 """Generate burn in tests to run on certain build variants.""" -import argparse import sys import os from collections import namedtuple +from typing import Any, Dict, Iterable +import click from evergreen.api import RetryingEvergreenApi from git import Repo @@ -19,6 +20,7 @@ if __name__ == "__main__" and __package__ is None: # pylint: disable=wrong-import-position import buildscripts.util.read_config as read_config from buildscripts.ciconfig import evergreen +from buildscripts.ciconfig.evergreen import EvergreenProjectConfig from buildscripts.burn_in_tests import create_generate_tasks_config, create_tests_by_task, \ GenerateConfig, RepeatConfig, DEFAULT_REPO_LOCATIONS @@ -163,23 +165,37 @@ def _write_to_file(shrub_config): file_handle.write(shrub_config.to_json()) -def main(evergreen_api, repos): +def burn_in(expansions_file_data: Dict[str, Any], evg_conf: EvergreenProjectConfig, + evergreen_api: RetryingEvergreenApi, repos: Iterable[Repo]): """Execute Main program.""" - parser = argparse.ArgumentParser(description=main.__doc__) - parser.add_argument("--expansion-file", dest="expansion_file", type=str, - help="Location of expansions file generated by evergreen.") - cmd_line_options = parser.parse_args() - expansions_file_data = read_config.read_config_file(cmd_line_options.expansion_file) - shrub_config = Configuration() - evg_conf = evergreen.parse_evergreen_file(EVERGREEN_FILE) build_variant_map = _create_evg_build_variant_map(expansions_file_data, evg_conf) _generate_evg_tasks(evergreen_api, shrub_config, expansions_file_data, build_variant_map, repos, evg_conf) _write_to_file(shrub_config) -if __name__ == '__main__': - REPOSITORIES = [Repo(x) for x in DEFAULT_REPO_LOCATIONS if os.path.isdir(x)] - main(RetryingEvergreenApi.get_api(config_file=EVG_CONFIG_FILE), REPOSITORIES) +@click.command() +@click.option("--expansion-file", "expansion_file", required=True, + help="Location of expansions file generated by evergreen.") +def main(expansion_file: str): + """ + Run new or changed tests in repeated mode to validate their stability. + + burn_in_tags detects jstests that are new or changed since the last git command and then + runs those tests in a loop to validate their reliability. + + \f + :param expansion_file: The expansion file containing the configuration params. + """ + evg_api = RetryingEvergreenApi.get_api(config_file=EVG_CONFIG_FILE) + repos = [Repo(x) for x in DEFAULT_REPO_LOCATIONS if os.path.isdir(x)] + 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) + + +if __name__ == "__main__": + main() # pylint: disable=no-value-for-parameter diff --git a/buildscripts/tests/test_burn_in_tags.py b/buildscripts/tests/test_burn_in_tags.py index e466109a10a..0d166d98dcb 100644 --- a/buildscripts/tests/test_burn_in_tags.py +++ b/buildscripts/tests/test_burn_in_tags.py @@ -1,5 +1,6 @@ """Unit tests for the burn_in_tags.py script.""" +from collections import defaultdict import os import unittest from unittest.mock import MagicMock, patch @@ -10,6 +11,8 @@ import buildscripts.burn_in_tags as under_test import buildscripts.ciconfig.evergreen as _evergreen +from buildscripts.tests.test_burn_in_tests import ns as burn_in_tests_ns + # pylint: disable=missing-docstring,invalid-name,unused-argument,no-self-use,protected-access NS = "buildscripts.burn_in_tags" @@ -144,3 +147,118 @@ class TestGenerateEvgTasks(unittest.TestCase): self.assertEqual( first_generated_build_variant["display_tasks"][0]["execution_tasks"][0], "burn_in:aggregation_mongos_passthrough_0_enterprise-rhel-62-64-bit-inmem-required") + + +EXPANSIONS_FILE_DATA = { + "build_variant": "enterprise-rhel-62-64-bit", + "revision": "badf00d000000000000000000000000000000000", "max_revisions": "1000", + "branch_name": "mongodb-mongo-master", "is_patch": "false", "distro_id": "rhel62-small", + "repeat_tests_min": "2", "repeat_tests_max": "1000", "repeat_tests_secs": "600", "project": + "mongodb-mongo-master" +} + +CREATE_EVG_BUILD_VARIANT_MAP = { + 'enterprise-rhel-62-64-bit-majority-read-concern-off': + 'enterprise-rhel-62-64-bit-majority-read-concern-off-required', + 'enterprise-rhel-62-64-bit-inmem': + 'enterprise-rhel-62-64-bit-inmem-required' +} + +CREATE_TEST_MEMBERSHIP_MAP = { + "jstests/aggregation/accumulators/accumulator_js.js": [ + "aggregation", "aggregation_auth", "aggregation_disabled_optimization", "aggregation_ese", + "aggregation_ese_gcm", "aggregation_facet_unwind_passthrough", + "aggregation_mongos_passthrough", "aggregation_one_shard_sharded_collections", + "aggregation_read_concern_majority_passthrough", "aggregation_secondary_reads", + "aggregation_sharded_collections_passthrough" + ], "jstests/core/create_collection.js": [ + "core", "core_auth", "core_ese", "core_ese_gcm", "core_minimum_batch_size", "core_op_query", + "cwrwc_passthrough", "cwrwc_rc_majority_passthrough", "cwrwc_wc_majority_passthrough", + "logical_session_cache_replication_100ms_refresh_jscore_passthrough", + "logical_session_cache_replication_10sec_refresh_jscore_passthrough", + "logical_session_cache_replication_1sec_refresh_jscore_passthrough", + "logical_session_cache_replication_default_refresh_jscore_passthrough", + "logical_session_cache_standalone_100ms_refresh_jscore_passthrough", + "logical_session_cache_standalone_10sec_refresh_jscore_passthrough", + "logical_session_cache_standalone_1sec_refresh_jscore_passthrough", + "logical_session_cache_standalone_default_refresh_jscore_passthrough", + "read_concern_linearizable_passthrough", "read_concern_majority_passthrough", + "replica_sets_initsync_jscore_passthrough", + "replica_sets_initsync_static_jscore_passthrough", "replica_sets_jscore_passthrough", + "replica_sets_kill_primary_jscore_passthrough", + "replica_sets_kill_secondaries_jscore_passthrough", + "replica_sets_reconfig_jscore_passthrough", + "replica_sets_terminate_primary_jscore_passthrough", "retryable_writes_jscore_passthrough", + "retryable_writes_jscore_stepdown_passthrough", "secondary_reads_passthrough", + "session_jscore_passthrough", "write_concern_majority_passthrough" + ] +} + + +class TestAcceptance(unittest.TestCase): + @patch(ns("_write_to_file")) + @patch(ns("_create_evg_build_variant_map")) + @patch(burn_in_tests_ns("find_changed_tests")) + def test_no_tests_run_if_none_changed(self, find_changed_tests_mock, + create_evg_build_variant_map_mock, write_to_file_mock): + """ + Given a git repository with no changes, + When burn_in_tags is run, + Then no tests are discovered to run. + """ + repos = [MagicMock()] + evg_conf_mock = MagicMock() + find_changed_tests_mock.return_value = {} + + create_evg_build_variant_map_mock.return_value = CREATE_EVG_BUILD_VARIANT_MAP + + under_test.burn_in(EXPANSIONS_FILE_DATA, evg_conf_mock, None, repos) + + write_to_file_mock.assert_called_once() + shrub_config = write_to_file_mock.call_args[0][0] + self.assertEqual('{}', shrub_config.to_json()) + + @patch(ns("_write_to_file")) + @patch(ns("_create_evg_build_variant_map")) + @patch(burn_in_tests_ns("find_changed_tests")) + @patch(burn_in_tests_ns("create_test_membership_map")) + def test_tests_generated_if_a_file_changed( + self, create_test_membership_map_mock, find_changed_tests_mock, + create_evg_build_variant_map_mock, write_to_file_mock): + """ + Given a git repository with changes, + When burn_in_tags is run, + Then some tags are discovered to run. + """ + create_test_membership_map_mock.return_value = defaultdict(list, CREATE_TEST_MEMBERSHIP_MAP) + + repos = [MagicMock()] + evg_conf = get_evergreen_config() + create_evg_build_variant_map_mock.return_value = CREATE_EVG_BUILD_VARIANT_MAP + find_changed_tests_mock.return_value = { + 'jstests/slow1/large_role_chain.js', + 'jstests/aggregation/accumulators/accumulator_js.js' + } + + under_test.burn_in(EXPANSIONS_FILE_DATA, evg_conf, None, repos) + + write_to_file_mock.assert_called_once() + written_config = write_to_file_mock.call_args[0][0] + written_config_map = written_config.to_map() + + n_tasks = len(written_config_map["tasks"]) + # Ensure we are generating at least one task for the test. + self.assertGreaterEqual(n_tasks, 1) + + written_build_variants = written_config_map["buildvariants"] + written_build_variants_name = [variant['name'] for variant in written_build_variants] + self.assertEqual( + set(CREATE_EVG_BUILD_VARIANT_MAP.values()), set(written_build_variants_name)) + + tasks = written_config_map["tasks"] + self.assertGreaterEqual(len(tasks), len(CREATE_EVG_BUILD_VARIANT_MAP)) + + self.assertTrue( + all( + len(display_tasks) == 1 for display_tasks in + [build_variant["display_tasks"] for build_variant in written_build_variants])) diff --git a/buildscripts/tests/test_burn_in_tags_evergreen.yml b/buildscripts/tests/test_burn_in_tags_evergreen.yml index 815906704f9..b013fe271c1 100644 --- a/buildscripts/tests/test_burn_in_tags_evergreen.yml +++ b/buildscripts/tests/test_burn_in_tags_evergreen.yml @@ -19,6 +19,45 @@ tasks: depends_on: [] commands: - func: "fake command" +- name: compile_all_run_unittests_TG + depends_on: [] + commands: + - func: "fake command" +- name: clang_tidy_TG + depends_on: [] + commands: + - func: "fake command" +- name: stitch_support_lib_build_and_archive + depends_on: [] + commands: + - func: "fake command" +- name: lint_pylinters + depends_on: [] + commands: + - func: "fake command" +- name: lint_clang_format + depends_on: [] + commands: + - func: "fake command" +- name: burn_in_tests_gen + depends_on: [] + commands: + - func: "fake command" +- name: aggregation_multiversion_fuzzer_gen + depends_on: [] + commands: + - func: "fake command" +- name: aggregation_expression_multiversion_fuzzer_gen + depends_on: [] + commands: + - func: "fake command" +- name: aggregation + depends_on: + - name: compile + commands: + - func: run tests + vars: + resmoke_args: --suites=aggregation --storageEngine=wiredTiger buildvariants: - name: enterprise-rhel-62-64-bit @@ -27,6 +66,13 @@ buildvariants: multiversion_platform: rhel62 burn_in_tag_buildvariants: enterprise-rhel-62-64-bit-majority-read-concern-off enterprise-rhel-62-64-bit-inmem tasks: + - name: compile_all_run_unittests_TG + distros: + - rhel62-large + - name: lint_pylinters + - name: burn_in_tests_gen + - name: aggregation_multiversion_fuzzer_gen + - name: aggregation - name: burn_in_tags_gen - name: buildvariant-without-burn-in-tag-buildvariants display_name: "Buildvariant without burn in tag buildvariants expansion" @@ -42,7 +88,11 @@ buildvariants: expansions: &enterprise-rhel-62-64-bit-majority-read-concern-off-expansions multiversion_edition: enterprise tasks: - - name: compile + - name: compile_all_run_unittests_TG + distros: + - rhel62-large + - name: aggregation_multiversion_fuzzer_gen + - name: aggregation - name: enterprise-rhel-62-64-bit-inmem display_name: Enterprise RHEL 6.2 (inMemory) modules: ["enterprise"] @@ -65,3 +115,24 @@ buildvariants: large_distro_name: rhel62-large tasks: - name: compile +- name: enterprise-rhel-62-64-bit-inmem + display_name: Enterprise RHEL 6.2 (inMemory) + expansions: + additional_targets: archive-mongocryptd archive-mongocryptd-debug + compile_flags: --ssl MONGO_DISTMOD=rhel62 -j$(grep -c ^processor /proc/cpuinfo) + --variables-files=etc/scons/mongodbtoolchain_v3_gcc.vars + large_distro_name: rhel62-large + multiversion_edition: enterprise + multiversion_platform: rhel62 + scons_cache_scope: shared + test_flags: --storageEngine=inMemory --excludeWithAnyTags=requires_persistence,requires_journaling + modules: + - enterprise + run_on: + - rhel62-small + tasks: + - name: compile_all_run_unittests_TG + distros: + - rhel62-large + - name: aggregation_multiversion_fuzzer_gen + - name: aggregation -- cgit v1.2.1