summaryrefslogtreecommitdiff
path: root/buildscripts/tests
diff options
context:
space:
mode:
authorMikhail Shchatko <mikhail.shchatko@mongodb.com>2022-07-29 08:35:33 +0000
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2022-07-29 09:04:37 +0000
commit368542c6aa8a129b461e54582ed0913fc72cdfb8 (patch)
treeca0c5c9b2a8cd9c6f57198bff9a57f818080f40a /buildscripts/tests
parent35978285c4be21c80e4781a827fda307e4b040a0 (diff)
downloadmongo-368542c6aa8a129b461e54582ed0913fc72cdfb8.tar.gz
SERVER-66369 Generate burn_in_tests and burn_in_tags using mongo-task-generator
Diffstat (limited to 'buildscripts/tests')
-rw-r--r--buildscripts/tests/test_burn_in_tags.py261
-rw-r--r--buildscripts/tests/test_burn_in_tags_evergreen.yml138
-rw-r--r--buildscripts/tests/test_evergreen_activate_gen_tasks.py113
-rw-r--r--buildscripts/tests/test_evergreen_burn_in_tests.py408
4 files changed, 98 insertions, 822 deletions
diff --git a/buildscripts/tests/test_burn_in_tags.py b/buildscripts/tests/test_burn_in_tags.py
deleted file mode 100644
index ec53a02d161..00000000000
--- a/buildscripts/tests/test_burn_in_tags.py
+++ /dev/null
@@ -1,261 +0,0 @@
-"""Unit tests for the burn_in_tags.py script."""
-from collections import defaultdict
-import json
-import os
-import sys
-import unittest
-from unittest.mock import MagicMock, patch
-
-from shrub.v2 import ShrubProject
-
-import buildscripts.ciconfig.evergreen as _evergreen
-from buildscripts.burn_in_tests import TaskInfo
-from buildscripts.tests.test_burn_in_tests import ns as burn_in_tests_ns
-from buildscripts.ciconfig.evergreen import EvergreenProjectConfig
-
-import buildscripts.burn_in_tags as under_test
-
-# pylint: disable=missing-docstring,invalid-name,unused-argument,no-self-use,protected-access
-
-EMPTY_PROJECT = {
- "buildvariants": [],
- "tasks": [],
-}
-TEST_FILE_PATH = os.path.join(os.path.dirname(__file__), "test_burn_in_tags_evergreen.yml")
-
-NS = "buildscripts.burn_in_tags"
-
-
-def ns(relative_name): # pylint: disable-invalid-name
- """Return a full name from a name relative to the test module"s name space."""
- return NS + "." + relative_name
-
-
-def get_expansions_data():
- return {
- "branch_name": "fake_branch",
- "build_variant": "enterprise-rhel-80-64-bit-suggested",
- "check_evergreen": 2,
- "distro_id": "rhel80-small",
- "is_patch": "true",
- "max_revisions": 25,
- "repeat_tests_max": 1000,
- "repeat_tests_min": 2,
- "repeat_tests_secs": 600,
- "revision": "fake_sha",
- "project": "fake_project",
- "task_id": "task id",
- } # yapf: disable
-
-
-def get_evergreen_config() -> EvergreenProjectConfig:
- return _evergreen.parse_evergreen_file(TEST_FILE_PATH, evergreen_binary=None)
-
-
-class TestCreateEvgBuildVariantMap(unittest.TestCase):
- def test_create_evg_buildvariant_map(self):
- expansions_file_data = {
- "build_variant": "variant1", "burn_in_tag_buildvariants": "variant2 variant3"
- }
- buildvariant_map = under_test._create_evg_build_variant_map(expansions_file_data)
-
- expected_buildvariant_map = {
- "variant2": "variant2-required", "variant3": "variant3-required"
- }
- self.assertEqual(buildvariant_map, expected_buildvariant_map)
-
-
-class TestGenerateEvgBuildVariants(unittest.TestCase):
- def test_generate_evg_buildvariant_one_base_variant(self):
- evg_conf_mock = get_evergreen_config()
- base_variant = "enterprise-rhel-80-64-bit-inmem"
- generated_variant = "enterprise-rhel-80-64-bit-inmem-required"
- burn_in_tags_gen_variant = "enterprise-rhel-80-64-bit"
- variant = evg_conf_mock.get_variant(base_variant)
-
- build_variant = under_test._generate_evg_build_variant(variant, generated_variant,
- burn_in_tags_gen_variant)
-
- generated_build_variant = build_variant.as_dict()
- self.assertEqual(generated_build_variant["name"], generated_variant)
- self.assertEqual(generated_build_variant["modules"], variant.modules)
- generated_expansions = generated_build_variant["expansions"]
- burn_in_bypass_expansion_value = generated_expansions.pop("burn_in_bypass")
- self.assertEqual(burn_in_bypass_expansion_value, burn_in_tags_gen_variant)
- self.assertEqual(generated_expansions, variant.expansions)
-
-
-class TestGenerateEvgTasks(unittest.TestCase):
- @patch(ns("create_tests_by_task"))
- def test_generate_evg_tasks_no_tests_changed(self, create_tests_by_task_mock):
- evg_conf_mock = get_evergreen_config()
- create_tests_by_task_mock.return_value = {}
- expansions_file_data = get_expansions_data()
- buildvariant_map = {
- "enterprise-rhel-80-64-bit-inmem": "enterprise-rhel-80-64-bit-inmem-required",
- "enterprise-rhel-80-64-bit-majority-read-concern-off":
- "enterprise-rhel-80-64-bit-majority-read-concern-off-required",
- } # yapf: disable
- shrub_config = ShrubProject()
- 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, 'install-dir/bin')
-
- self.assertEqual(shrub_config.as_dict(), EMPTY_PROJECT)
-
- @patch(ns("create_tests_by_task"))
- def test_generate_evg_tasks_one_test_changed(self, create_tests_by_task_mock):
- evg_conf_mock = get_evergreen_config()
- create_tests_by_task_mock.return_value = {
- "aggregation_mongos_passthrough": TaskInfo(
- display_task_name="aggregation_mongos_passthrough",
- suite="aggregation_mongos_passthrough",
- resmoke_args="--suites=aggregation_mongos_passthrough --storageEngine=wiredTiger",
- tests=["jstests/aggregation/ifnull.js"],
- require_multiversion_setup=False,
- distro="",
- build_variant="enterprise-rhel-80-64-bit-inmem"
- )
- } # yapf: disable
- expansions_file_data = get_expansions_data()
- buildvariant_map = {
- "enterprise-rhel-80-64-bit-inmem": "enterprise-rhel-80-64-bit-inmem-required",
- "enterprise-rhel-80-64-bit-majority-read-concern-off":
- "enterprise-rhel-80-64-bit-majority-read-concern-off-required",
- } # yapf: disable
- shrub_config = ShrubProject.empty()
- evergreen_api = MagicMock()
- repo = MagicMock(working_dir=os.getcwd())
- evergreen_api.test_stats_by_project.return_value = [
- 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, 'install-dir/bin')
-
- generated_config = shrub_config.as_dict()
- self.assertEqual(len(generated_config["buildvariants"]), 2)
- first_generated_build_variant = generated_config["buildvariants"][0]
- self.assertIn(first_generated_build_variant["name"], buildvariant_map.values())
- self.assertEqual(first_generated_build_variant["display_tasks"][0]["name"], "burn_in_tests")
- self.assertEqual(
- first_generated_build_variant["display_tasks"][0]["execution_tasks"][0],
- f"burn_in:aggregation_mongos_passthrough_0_{first_generated_build_variant['name']}")
-
-
-EXPANSIONS_FILE_DATA = {
- "build_variant": "enterprise-rhel-80-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", "task_id": "task id"
-}
-
-CREATE_EVG_BUILD_VARIANT_MAP = {
- 'enterprise-rhel-80-64-bit-majority-read-concern-off':
- 'enterprise-rhel-80-64-bit-majority-read-concern-off-required',
- 'enterprise-rhel-80-64-bit-inmem':
- 'enterprise-rhel-80-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",
- "causally_consistent_read_concern_snapshot_passthrough",
- "replica_sets_initsync_jscore_passthrough", "replica_sets_fcbis_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_file_to_dir"))
- @patch(ns("_create_evg_build_variant_map"))
- @patch(ns("EvergreenFileChangeDetector"))
- 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(working_dir=os.getcwd())]
- evg_conf_mock = MagicMock()
- find_changed_tests_mock.return_value.find_changed_tests.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, MagicMock(), repos,
- 'install_dir/bin')
-
- write_to_file_mock.assert_called_once()
- shrub_config = write_to_file_mock.call_args[0][2]
- self.assertEqual(EMPTY_PROJECT, json.loads(shrub_config))
-
- @unittest.skipIf(sys.platform.startswith("win"), "not supported on windows")
- @patch(ns("write_file_to_dir"))
- @patch(ns("_create_evg_build_variant_map"))
- @patch(ns("EvergreenFileChangeDetector"))
- @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(working_dir=os.getcwd())]
- evg_conf = get_evergreen_config()
- create_evg_build_variant_map_mock.return_value = CREATE_EVG_BUILD_VARIANT_MAP
- find_changed_tests_mock.return_value.find_changed_tests.return_value = {
- 'jstests/slow1/large_role_chain.js',
- 'jstests/aggregation/accumulators/accumulator_js.js'
- }
-
- 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]
- written_config_map = json.loads(written_config)
-
- 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
deleted file mode 100644
index 2db458fff05..00000000000
--- a/buildscripts/tests/test_burn_in_tags_evergreen.yml
+++ /dev/null
@@ -1,138 +0,0 @@
-functions:
- "fetch source":
- - command: git.get_project
- params:
- directory: src
- - command: shell.exec
- params:
- working_dir: src
- script: |
- echo "this is a 2nd command in the function!"
- ls
-
-tasks:
-- name: compile
- depends_on: []
- commands:
- - func: "fetch source"
-- name: burn_in_tags_gen
- 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: "generate resmoke tasks"
-- name: aggregation_expression_multiversion_fuzzer_gen
- depends_on: []
- commands:
- - func: "generate resmoke tasks"
-- name: aggregation
- depends_on:
- - name: compile
- commands:
- - func: run tests
- vars:
- resmoke_args: --suites=aggregation --storageEngine=wiredTiger
-
-buildvariants:
-- name: enterprise-rhel-80-64-bit
- display_name: "! Enterprise RHEL 8.0"
- expansions:
- multiversion_platform: rhel80
- burn_in_tag_buildvariants: enterprise-rhel-80-64-bit-majority-read-concern-off enterprise-rhel-80-64-bit-inmem
- tasks:
- - name: compile_all_run_unittests_TG
- distros:
- - rhel80-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"
- expansions:
- multiversion_platform: rhel80
- tasks:
- - name: burn_in_tags_gen
-- name: enterprise-rhel-80-64-bit-majority-read-concern-off
- display_name: "Enterprise RHEL 8.0 (majority read concern off)"
- modules: ["enterprise"]
- run_on:
- - rhel80-small
- expansions: &enterprise-rhel-80-64-bit-majority-read-concern-off-expansions
- multiversion_edition: enterprise
- tasks:
- - name: compile_all_run_unittests_TG
- distros:
- - rhel80-large
- - name: aggregation_multiversion_fuzzer_gen
- - name: aggregation
-- name: enterprise-rhel-80-64-bit-inmem
- display_name: Enterprise RHEL 8.0 (inMemory)
- modules: ["enterprise"]
- run_on:
- - rhel80-small
- expansions: &enterprise-rhel-80-64-bit-inmem-expansions
- test_flags: >-
- --majorityReadConcern=off
- --excludeWithAnyTags=requires_majority_read_concern,uses_prepare_transaction,uses_multi_shard_transaction,uses_atclustertime
- compile_flags: >-
- -j$(grep -c ^processor /proc/cpuinfo)
- --ssl
- --release
- --variables-files=etc/scons/mongodbtoolchain_v3_gcc.vars
- MONGO_DISTMOD=rhel80
- multiversion_platform: rhel80
- multiversion_edition: enterprise
- scons_cache_scope: shared
- tooltags: "ssl sasl gssapi"
- large_distro_name: rhel80-large
- tasks:
- - name: compile
-- name: enterprise-rhel-80-64-bit-inmem
- display_name: Enterprise RHEL 8.0 (inMemory)
- expansions:
- additional_targets: archive-mongocryptd archive-mongocryptd-debug
- compile_flags: --ssl MONGO_DISTMOD=rhel80 -j$(grep -c ^processor /proc/cpuinfo)
- --variables-files=etc/scons/mongodbtoolchain_v3_gcc.vars
- large_distro_name: rhel80-large
- multiversion_edition: enterprise
- multiversion_platform: rhel80
- scons_cache_scope: shared
- test_flags: --storageEngine=inMemory --excludeWithAnyTags=requires_persistence
- modules:
- - enterprise
- run_on:
- - rhel80-small
- tasks:
- - name: compile_all_run_unittests_TG
- distros:
- - rhel80-large
- - name: aggregation_multiversion_fuzzer_gen
- - name: aggregation
diff --git a/buildscripts/tests/test_evergreen_activate_gen_tasks.py b/buildscripts/tests/test_evergreen_activate_gen_tasks.py
index dbb64380838..cc7e85661c0 100644
--- a/buildscripts/tests/test_evergreen_activate_gen_tasks.py
+++ b/buildscripts/tests/test_evergreen_activate_gen_tasks.py
@@ -1,42 +1,125 @@
"""Unit tests for the generate_resmoke_suite script."""
import unittest
-from mock import MagicMock
+from mock import MagicMock, mock
from buildscripts import evergreen_activate_gen_tasks as under_test
+from evergreen import Build, EvergreenApi, Task, Version
# pylint: disable=missing-docstring,invalid-name,unused-argument,no-self-use,protected-access
# pylint: disable=too-many-locals,too-many-lines,too-many-public-methods,no-value-for-parameter
-def build_mock_task(name, task_id):
- mock_task = MagicMock(display_name=name, task_id=task_id)
+def build_mock_task(display_name, task_id):
+ mock_task = MagicMock(spec_set=Task, display_name=display_name, task_id=task_id)
return mock_task
-def build_mock_evg_api(mock_task_list):
- mock_build = MagicMock()
+def build_mock_task_list(num_tasks):
+ return [build_mock_task(f"task_{i}", f"id_{i}") for i in range(num_tasks)]
+
+
+def build_mock_build(mock_task_list):
+ mock_build = MagicMock(spec_set=Build)
mock_build.get_tasks.return_value = mock_task_list
- mock_evg_api = MagicMock()
- mock_evg_api.build_by_id.return_value = mock_build
+ return mock_build
+
+
+def build_mock_evg_api(mock_current_build, mock_other_builds_list):
+ mock_version = MagicMock(spec_set=Version)
+ mock_version.build_by_variant.side_effect = mock_other_builds_list
+ mock_evg_api = MagicMock(spec_set=EvergreenApi)
+ mock_evg_api.version_by_id.return_value = mock_version
+ mock_evg_api.build_by_id.return_value = mock_current_build
return mock_evg_api
class TestActivateTask(unittest.TestCase):
def test_task_with_display_name_is_activated(self):
- n_tasks = 5
- mock_task_list = [build_mock_task(f"task_{i}", f"id_{i}") for i in range(n_tasks)]
- mock_evg_api = build_mock_evg_api(mock_task_list)
+ expansions = under_test.EvgExpansions(**{
+ "build_id": "build_id",
+ "version_id": "version_id",
+ "task_name": "task_3_gen",
+ })
+ mock_task_list = build_mock_task_list(5)
+ mock_evg_api = build_mock_evg_api(build_mock_build(mock_task_list), [])
- under_test.activate_task("build_id", "task_3", mock_evg_api)
+ under_test.activate_task(expansions, mock_evg_api)
mock_evg_api.configure_task.assert_called_with("id_3", activated=True)
def test_task_with_no_matching_name(self):
- n_tasks = 5
- mock_task_list = [build_mock_task(f"task_{i}", f"id_{i}") for i in range(n_tasks)]
- mock_evg_api = build_mock_evg_api(mock_task_list)
+ expansions = under_test.EvgExpansions(**{
+ "build_id": "build_id",
+ "version_id": "version_id",
+ "task_name": "not_an_existing_task",
+ })
+ mock_task_list = build_mock_task_list(5)
+ mock_evg_api = build_mock_evg_api(build_mock_build(mock_task_list), [])
+
+ under_test.activate_task(expansions, mock_evg_api)
+
+ mock_evg_api.configure_task.assert_not_called()
+
+ def test_burn_in_tags_tasks_are_activated(self):
+ expansions = under_test.EvgExpansions(
+ **{
+ "build_id": "build_id",
+ "version_id": "version_id",
+ "task_name": "burn_in_tags_gen",
+ "burn_in_tag_buildvariants": "build_variant_2 build_variant_3",
+ })
+ mock_task_list_1 = build_mock_task_list(5)
+ mock_task_list_1.append(build_mock_task("burn_in_tags_gen", "burn_in_tags_gen_id_1"))
+ mock_task_list_2 = build_mock_task_list(5)
+ mock_task_list_2.append(build_mock_task("burn_in_tests", "burn_in_tests_id_2"))
+ mock_task_list_3 = build_mock_task_list(5)
+ mock_task_list_3.append(build_mock_task("burn_in_tests", "burn_in_tests_id_3"))
+ mock_evg_api = build_mock_evg_api(
+ build_mock_build(mock_task_list_1), [
+ build_mock_build(mock_task_list_2),
+ build_mock_build(mock_task_list_3),
+ ])
+
+ under_test.activate_task(expansions, mock_evg_api)
+
+ mock_evg_api.configure_task.assert_has_calls([
+ mock.call("burn_in_tests_id_2", activated=True),
+ mock.call("burn_in_tests_id_3", activated=True)
+ ])
+
+ def test_burn_in_tags_task_skips_non_existing_build_variant(self):
+ expansions = under_test.EvgExpansions(
+ **{
+ "build_id": "build_id",
+ "version_id": "version_id",
+ "task_name": "burn_in_tags_gen",
+ "burn_in_tag_buildvariants": "not_an_existing_build_variant build_variant_2",
+ })
+ mock_task_list_1 = build_mock_task_list(5)
+ mock_task_list_1.append(build_mock_task("burn_in_tags_gen", "burn_in_tags_gen_id_1"))
+ mock_task_list_2 = build_mock_task_list(5)
+ mock_task_list_2.append(build_mock_task("burn_in_tests", "burn_in_tests_id_2"))
+ mock_evg_api = build_mock_evg_api(
+ build_mock_build(mock_task_list_1), [
+ KeyError,
+ build_mock_build(mock_task_list_2),
+ ])
+
+ under_test.activate_task(expansions, mock_evg_api)
+
+ mock_evg_api.configure_task.assert_called_once_with("burn_in_tests_id_2", activated=True)
+
+ def test_burn_in_tags_task_with_missing_burn_in_tag_buildvariants_expansion(self):
+ expansions = under_test.EvgExpansions(**{
+ "build_id": "build_id",
+ "version_id": "version_id",
+ "task_name": "burn_in_tags_gen",
+ })
+ mock_task_list_1 = build_mock_task_list(5)
+ mock_task_list_1.append(build_mock_task("burn_in_tags_gen", "burn_in_tags_gen_id_1"))
+ mock_evg_api = build_mock_evg_api(build_mock_build(mock_task_list_1), [])
- under_test.activate_task("build_id", "not_an_existing_task", mock_evg_api)
+ under_test.activate_task(expansions, mock_evg_api)
mock_evg_api.configure_task.assert_not_called()
diff --git a/buildscripts/tests/test_evergreen_burn_in_tests.py b/buildscripts/tests/test_evergreen_burn_in_tests.py
deleted file mode 100644
index ee77ced2579..00000000000
--- a/buildscripts/tests/test_evergreen_burn_in_tests.py
+++ /dev/null
@@ -1,408 +0,0 @@
-"""Unit tests for buildscripts/burn_in_tests.py."""
-
-from __future__ import absolute_import
-
-import json
-import os
-import sys
-import unittest
-from datetime import datetime, timedelta
-from math import ceil
-
-import requests
-from mock import patch, MagicMock
-from shrub.v2 import BuildVariant, ShrubProject
-from evergreen.api import EvergreenApi
-
-import buildscripts.evergreen_burn_in_tests as under_test
-from buildscripts.ciconfig.evergreen import parse_evergreen_file
-import buildscripts.resmokelib.parser as _parser
-import buildscripts.resmokelib.config as _config
-import buildscripts.util.teststats as teststats_utils
-_parser.set_run_options()
-
-# pylint: disable=missing-docstring,invalid-name,unused-argument,no-self-use,protected-access
-
-NS = "buildscripts.evergreen_burn_in_tests"
-
-
-def ns(relative_name): # pylint: disable=invalid-name
- """Return a full name from a name relative to the test module"s name space."""
- return NS + "." + relative_name
-
-
-def mock_a_file(filename):
- change = MagicMock(a_path=filename)
- return change
-
-
-def mock_git_diff(change_list):
- diff = MagicMock()
- diff.iter_change_type.return_value = change_list
- return diff
-
-
-def mock_changed_git_files(add_files):
- repo = MagicMock()
- repo.index.diff.return_value = mock_git_diff([mock_a_file(f) for f in add_files])
- repo.working_dir = "."
- return repo
-
-
-def get_evergreen_config(config_file_path):
- evergreen_home = os.path.expanduser(os.path.join("~", "evergreen"))
- if os.path.exists(evergreen_home):
- return parse_evergreen_file(config_file_path, evergreen_home)
- return parse_evergreen_file(config_file_path)
-
-
-class TestAcceptance(unittest.TestCase):
- def tearDown(self):
- _parser.set_run_options()
-
- @patch(ns("write_file"))
- def test_no_tests_run_if_none_changed(self, write_json_mock):
- """
- Given a git repository with no changes,
- When burn_in_tests is run,
- Then no tests are discovered to run.
- """
- variant = "build_variant"
- repos = [mock_changed_git_files([])]
- repeat_config = under_test.RepeatConfig()
- gen_config = under_test.GenerateConfig(
- variant,
- "project",
- ) # yapf: disable
- mock_evg_conf = MagicMock()
- mock_evg_conf.get_task_names_by_tag.return_value = set()
- mock_evg_api = MagicMock()
-
- under_test.burn_in("task_id", variant, gen_config, repeat_config, mock_evg_api,
- 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])
- display_task = written_config["buildvariants"][0]["display_tasks"][0]
- self.assertEqual(1, len(display_task["execution_tasks"]))
- self.assertEqual(under_test.BURN_IN_TESTS_GEN_TASK, display_task["execution_tasks"][0])
-
- @unittest.skipIf(sys.platform.startswith("win"), "not supported on windows")
- @patch(ns("write_file"))
- def test_tests_generated_if_a_file_changed(self, write_json_mock):
- """
- Given a git repository with changes,
- When burn_in_tests is run,
- Then tests are discovered to run.
- """
- # Note: this test is using actual tests and suites. So changes to those suites could
- # introduce failures and require this test to be updated.
- # You can see the test file it is using below. This test is used in the 'auth' and
- # 'auth_audit' test suites. It needs to be in at least one of those for the test to pass.
- variant = "enterprise-rhel-80-64-bit-inmem"
- repos = [mock_changed_git_files(["jstests/auth/auth1.js"])]
- repeat_config = under_test.RepeatConfig()
- gen_config = under_test.GenerateConfig(
- variant,
- "project",
- ) # yapf: disable
- mock_evg_conf = get_evergreen_config("etc/evergreen.yml")
- mock_evg_api = MagicMock()
-
- under_test.burn_in("task_id", variant, gen_config, repeat_config, mock_evg_api,
- 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])
- n_tasks = len(written_config["tasks"])
- # Ensure we are generating at least one task for the test.
- self.assertGreaterEqual(n_tasks, 1)
-
- written_build_variant = written_config["buildvariants"][0]
- self.assertEqual(variant, written_build_variant["name"])
- self.assertEqual(n_tasks, len(written_build_variant["tasks"]))
-
- display_task = written_build_variant["display_tasks"][0]
- # The display task should contain all the generated tasks as well as 1 extra task for
- # the burn_in_test_gen task.
- self.assertEqual(n_tasks + 1, len(display_task["execution_tasks"]))
-
-
-class TestGenerateConfig(unittest.TestCase):
- def test_run_build_variant_with_no_run_build_variant(self):
- gen_config = under_test.GenerateConfig("build_variant", "project")
-
- self.assertEqual(gen_config.build_variant, gen_config.run_build_variant)
-
- def test_run_build_variant_with_run_build_variant(self):
- gen_config = under_test.GenerateConfig("build_variant", "project", "run_build_variant")
-
- self.assertNotEqual(gen_config.build_variant, gen_config.run_build_variant)
- self.assertEqual(gen_config.run_build_variant, "run_build_variant")
-
- def test_validate_non_existing_build_variant(self):
- evg_conf_mock = MagicMock()
- evg_conf_mock.get_variant.return_value = None
-
- gen_config = under_test.GenerateConfig("build_variant", "project", "run_build_variant")
-
- with self.assertRaises(ValueError):
- gen_config.validate(evg_conf_mock)
-
- def test_validate_existing_build_variant(self):
- evg_conf_mock = MagicMock()
-
- gen_config = under_test.GenerateConfig("build_variant", "project", "run_build_variant")
- gen_config.validate(evg_conf_mock)
-
- def test_validate_non_existing_run_build_variant(self):
- evg_conf_mock = MagicMock()
-
- gen_config = under_test.GenerateConfig("build_variant", "project")
- gen_config.validate(evg_conf_mock)
-
-
-class TestParseAvgTestRuntime(unittest.TestCase):
- def test__parse_avg_test_runtime(self):
- task_avg_test_runtime_stats = [
- teststats_utils.TestRuntime(test_name="dir/test1.js", runtime=30.2),
- teststats_utils.TestRuntime(test_name="dir/test2.js", runtime=455.1)
- ]
- result = under_test._parse_avg_test_runtime("dir/test2.js", task_avg_test_runtime_stats)
- self.assertEqual(result, 455.1)
-
-
-class TestCalculateTimeout(unittest.TestCase):
- def test__calculate_timeout(self):
- avg_test_runtime = 455.1
- expected_result = ceil(avg_test_runtime * under_test.AVG_TEST_TIME_MULTIPLIER)
- self.assertEqual(expected_result, under_test._calculate_timeout(avg_test_runtime))
-
- def test__calculate_timeout_avg_is_less_than_min(self):
- avg_test_runtime = 10
- self.assertEqual(under_test.MIN_AVG_TEST_TIME_SEC,
- under_test._calculate_timeout(avg_test_runtime))
-
-
-class TestCalculateExecTimeout(unittest.TestCase):
- def test__calculate_exec_timeout(self):
- repeat_config = under_test.RepeatConfig(repeat_tests_secs=600)
- avg_test_runtime = 455.1
-
- exec_timeout = under_test._calculate_exec_timeout(repeat_config, avg_test_runtime)
-
- self.assertEqual(1771, exec_timeout)
-
- def test_average_timeout_greater_than_execution_time(self):
- repeat_config = under_test.RepeatConfig(repeat_tests_secs=600, repeat_tests_min=2)
- avg_test_runtime = 750
-
- exec_timeout = under_test._calculate_exec_timeout(repeat_config, avg_test_runtime)
-
- # The timeout needs to be greater than the number of the test * the minimum number of runs.
- minimum_expected_timeout = avg_test_runtime * repeat_config.repeat_tests_min
-
- self.assertGreater(exec_timeout, minimum_expected_timeout)
-
-
-class TestGenerateTimeouts(unittest.TestCase):
- def test__generate_timeouts(self):
- repeat_config = under_test.RepeatConfig(repeat_tests_secs=600)
- runtime_stats = [teststats_utils.TestRuntime(test_name="dir/test2.js", runtime=455.1)]
- test_name = "dir/test2.js"
-
- task_generator = under_test.BurnInGenTaskService(MagicMock(), repeat_config, runtime_stats)
- timeout_info = task_generator.generate_timeouts(test_name)
-
- self.assertEqual(timeout_info.exec_timeout, 1771)
- self.assertEqual(timeout_info.timeout, 1366)
-
- def test__generate_timeouts_no_results(self):
- repeat_config = under_test.RepeatConfig(repeat_tests_secs=600)
- runtime_stats = []
- test_name = "dir/new_test.js"
-
- task_generator = under_test.BurnInGenTaskService(MagicMock(), repeat_config, runtime_stats)
- timeout_info = task_generator.generate_timeouts(test_name)
-
- self.assertIsNone(timeout_info.cmd)
-
- def test__generate_timeouts_avg_runtime_is_zero(self):
- repeat_config = under_test.RepeatConfig(repeat_tests_secs=600)
- runtime_stats = [
- teststats_utils.TestRuntime(test_name="dir/test_with_zero_runtime.js", runtime=0)
- ]
- test_name = "dir/test_with_zero_runtime.js"
-
- task_generator = under_test.BurnInGenTaskService(MagicMock(), repeat_config, runtime_stats)
- timeout_info = task_generator.generate_timeouts(test_name)
-
- self.assertIsNone(timeout_info.cmd)
-
-
-class TestGetTaskRuntimeHistory(unittest.TestCase):
- def test_get_task_runtime_history(self):
- mock_evg_api = MagicMock()
- mock_evg_api.test_stats_by_project.return_value = [
- MagicMock(
- test_file="dir/test2.js",
- task_name="task1",
- variant="variant1",
- distro="distro1",
- date=datetime.utcnow().date(),
- num_pass=1,
- num_fail=0,
- avg_duration_pass=10.1,
- )
- ]
- analysis_duration = under_test.AVG_TEST_RUNTIME_ANALYSIS_DAYS
- end_date = datetime.utcnow().replace(microsecond=0)
- start_date = end_date - timedelta(days=analysis_duration)
- mock_gen_config = MagicMock(project="project1", build_variant="variant1")
-
- executor = under_test.GenerateBurnInExecutor(mock_gen_config, MagicMock(), mock_evg_api,
- history_end_date=end_date)
- result = executor.get_task_runtime_history("task1")
-
- self.assertEqual(result, [("dir/test2.js", 10.1)])
- mock_evg_api.test_stats_by_project.assert_called_with(
- "project1", after_date=start_date, before_date=end_date, group_by="test",
- group_num_days=14, tasks=["task1"], variants=["variant1"])
-
- def test_get_task_runtime_history_evg_degraded_mode_error(self):
- mock_response = MagicMock(status_code=requests.codes.SERVICE_UNAVAILABLE)
- mock_evg_api = MagicMock()
- mock_evg_api.test_stats_by_project.side_effect = requests.HTTPError(response=mock_response)
- mock_gen_config = MagicMock(project="project1", build_variant="variant1")
-
- executor = under_test.GenerateBurnInExecutor(mock_gen_config, MagicMock(), mock_evg_api)
- result = executor.get_task_runtime_history("task1")
-
- self.assertEqual(result, [])
-
-
-TESTS_BY_TASK = {
- "task1": {
- "resmoke_args": "--suites=suite1",
- "tests": ["jstests/test1.js", "jstests/test2.js"]},
- "task2": {
- "resmoke_args": "--suites=suite1",
- "tests": ["jstests/test1.js", "jstests/test3.js"]},
- "task3": {
- "resmoke_args": "--suites=suite3",
- "tests": ["jstests/test4.js", "jstests/test5.js"]},
- "task4": {
- "resmoke_args": "--suites=suite4", "tests": []},
-} # yapf: disable
-
-
-def create_tests_by_task_mock(n_tasks, n_tests):
- return {
- f"task_{i}_gen": under_test.TaskInfo(display_task_name=f"task_{i}", resmoke_args="", tests=[
- f"jstests/tests_{j}" for j in range(n_tests)
- ], require_multiversion_setup=False, distro=f"distro_{i}", build_variant="variant",
- suite=f"suite_{i}")
- for i in range(n_tasks)
- }
-
-
-class TestCreateGenerateTasksConfig(unittest.TestCase):
- @unittest.skipIf(sys.platform.startswith("win"), "not supported on windows")
- def test_no_tasks_given(self):
- build_variant = BuildVariant("build variant")
- gen_config = MagicMock(run_build_variant="variant")
- repeat_config = MagicMock()
- mock_evg_api = MagicMock()
-
- executor = under_test.GenerateBurnInExecutor(gen_config, repeat_config, mock_evg_api)
- executor.generate_tasks_for_variant({}, build_variant)
-
- evg_config_dict = build_variant.as_dict()
- self.assertEqual(0, len(evg_config_dict["tasks"]))
-
- @unittest.skipIf(sys.platform.startswith("win"), "not supported on windows")
- def test_one_task_one_test(self):
- n_tasks = 1
- n_tests = 1
- resmoke_options = "options for resmoke"
- build_variant = BuildVariant("build variant")
- gen_config = MagicMock(run_build_variant="variant", distro=None)
- repeat_config = MagicMock()
- repeat_config.generate_resmoke_options.return_value = resmoke_options
- mock_evg_api = MagicMock()
- tests_by_task = create_tests_by_task_mock(n_tasks, n_tests)
-
- executor = under_test.GenerateBurnInExecutor(gen_config, repeat_config, mock_evg_api)
- executor.generate_tasks_for_variant(tests_by_task, build_variant)
-
- shrub_config = ShrubProject.empty().add_build_variant(build_variant)
- evg_config_dict = shrub_config.as_dict()
- tasks = evg_config_dict["tasks"]
- self.assertEqual(n_tasks * n_tests, len(tasks))
- cmd = tasks[0]["commands"]
- self.assertIn(resmoke_options, cmd[2]["vars"]["resmoke_args"])
- self.assertEqual("suite_0", cmd[2]["vars"]["suite"])
- self.assertIn("tests_0", cmd[2]["vars"]["resmoke_args"])
-
- @unittest.skipIf(sys.platform.startswith("win"), "not supported on windows")
- def test_n_task_m_test(self):
- n_tasks = 3
- n_tests = 5
- build_variant = BuildVariant("build variant")
- gen_config = MagicMock(run_build_variant="variant", distro=None)
- repeat_config = MagicMock()
- tests_by_task = create_tests_by_task_mock(n_tasks, n_tests)
- mock_evg_api = MagicMock()
-
- executor = under_test.GenerateBurnInExecutor(gen_config, repeat_config, mock_evg_api)
- executor.generate_tasks_for_variant(tests_by_task, build_variant)
-
- evg_config_dict = build_variant.as_dict()
- self.assertEqual(n_tasks * n_tests, len(evg_config_dict["tasks"]))
-
-
-class TestCreateGenerateTasksFile(unittest.TestCase):
- @unittest.skipIf(sys.platform.startswith("win"), "not supported on windows")
- @patch(ns("sys.exit"))
- @patch(ns("validate_task_generation_limit"))
- def test_cap_on_task_generate(self, validate_mock, exit_mock):
- gen_config = MagicMock(require_multiversion_setup=False)
- repeat_config = MagicMock()
- tests_by_task = MagicMock()
- mock_evg_api = MagicMock()
-
- validate_mock.return_value = False
-
- exit_mock.side_effect = ValueError("exiting")
- with self.assertRaises(ValueError):
- executor = under_test.GenerateBurnInExecutor(gen_config, repeat_config, mock_evg_api,
- "gen_file.json")
- executor.execute(tests_by_task)
-
- exit_mock.assert_called_once()
-
-
-class TestFindChangedTests(unittest.TestCase):
- def test_manual_tests_should_be_specifiable_via_env_vars(self):
- mock_evg_api = MagicMock(spec_set=EvergreenApi)
- mock_repo = MagicMock()
- mock_env = {
- "BURN_IN_TESTS": "jstests/auth/auth1.js,jstests/core/where1.js",
- }
- change_detector = under_test.EvergreenFileChangeDetector("task_id", mock_evg_api, mock_env)
-
- test_set = change_detector.find_changed_tests([mock_repo])
-
- self.assertEqual(2, len(test_set))
- self.assertIn("jstests/auth/auth1.js", test_set)
- self.assertIn("jstests/core/where1.js", test_set)
-
- def test_empty_env_should_not_add_extra_tests(self):
- mock_evg_api = MagicMock(spec_set=EvergreenApi)
- mock_repo = MagicMock()
- mock_env = {}
- change_detector = under_test.EvergreenFileChangeDetector("task_id", mock_evg_api, mock_env)
-
- test_set = change_detector.find_changed_tests([mock_repo])
-
- self.assertEqual(set(), test_set)