mirror of https://github.com/mongodb/mongo
273 lines
10 KiB
Python
273 lines
10 KiB
Python
''' Tests for the multiversion generators '''
|
|
|
|
import os
|
|
import unittest
|
|
from tempfile import TemporaryDirectory, NamedTemporaryFile
|
|
|
|
from mock import patch, MagicMock
|
|
from click.testing import CliRunner
|
|
|
|
from buildscripts import evergreen_gen_multiversion_tests as under_test
|
|
import buildscripts.evergreen_generate_resmoke_tasks as generate_resmoke
|
|
from buildscripts.util.fileops import read_yaml_file
|
|
|
|
# pylint: disable=missing-docstring, no-self-use
|
|
|
|
|
|
class TestRun(unittest.TestCase):
|
|
def setUp(self):
|
|
self._tmpdir = TemporaryDirectory()
|
|
|
|
def tearDown(self):
|
|
self._tmpdir.cleanup()
|
|
under_test.CONFIG_DIR = generate_resmoke.DEFAULT_CONFIG_VALUES
|
|
|
|
@patch.object(under_test.EvergreenMultiversionConfigGenerator, 'generate_evg_tasks')
|
|
@patch('buildscripts.evergreen_generate_resmoke_tasks.should_tasks_be_generated')
|
|
@patch('buildscripts.evergreen_gen_multiversion_tests.write_file_to_dir')
|
|
def test_empty_result_config_fails(self, generate_evg_tasks, should_tasks_be_generated,
|
|
write_file_to_dir):
|
|
# pylint: disable=unused-argument
|
|
''' Hijacks the write_file_to_dir function to prevent the configuration
|
|
from being written to disk, and ensure the command fails '''
|
|
under_test.CONFIG_DIR = self._tmpdir.name
|
|
|
|
# NamedTemporaryFile doesn't work too well on Windows. We need to
|
|
# close the fd's so that run_generate_tasks can open the files,
|
|
# so we override the delete-on-close behaviour on Windows, and manually
|
|
# handle cleanup later
|
|
is_windows = os.name == 'nt'
|
|
with NamedTemporaryFile(mode='w',
|
|
delete=not is_windows) as expansions_file, NamedTemporaryFile(
|
|
mode='w', delete=not is_windows) as evg_conf:
|
|
expansions_file.write(EXPANSIONS)
|
|
expansions_file.flush()
|
|
should_tasks_be_generated.return_value = True
|
|
if is_windows:
|
|
# on windows we need to close the fd's so that
|
|
# run_generate_tasks can open the file handle
|
|
expansions_file.close()
|
|
evg_conf.close()
|
|
|
|
runner = CliRunner()
|
|
result = runner.invoke(
|
|
under_test.run_generate_tasks,
|
|
['--expansion-file', expansions_file.name, '--evergreen-config', evg_conf.name])
|
|
self.assertEqual(result.exit_code, 1, result)
|
|
self.assertTrue(isinstance(result.exception, RuntimeError))
|
|
self.assertEqual(
|
|
str(result.exception),
|
|
f"Multiversion suite generator unexpectedly yielded no configuration in '{self._tmpdir.name}'"
|
|
)
|
|
self.assertEqual(write_file_to_dir.call_count, 1)
|
|
if is_windows:
|
|
# on windows we need to manually delete these files, since
|
|
# we've disabled the delete-on-close mechanics
|
|
os.remove(expansions_file.name)
|
|
os.remove(evg_conf.name)
|
|
|
|
|
|
class TestGenerateExcludeYaml(unittest.TestCase):
|
|
def setUp(self):
|
|
self._tmpdir = TemporaryDirectory()
|
|
|
|
def tearDown(self):
|
|
if self._tmpdir is not None:
|
|
self._tmpdir.cleanup()
|
|
|
|
def assert_contents(self, expected):
|
|
actual = read_yaml_file(os.path.join(self._tmpdir.name, under_test.EXCLUDE_TAGS_FILE))
|
|
self.assertEqual(actual, expected)
|
|
|
|
def patch_and_run(self, latest, last_stable):
|
|
"""
|
|
Helper to patch and run the test.
|
|
"""
|
|
mock_multiversion_methods = {
|
|
'get_backports_required_last_stable_hash': MagicMock(),
|
|
'get_last_stable_yaml': MagicMock(return_value=last_stable)
|
|
}
|
|
|
|
with patch.multiple('buildscripts.evergreen_gen_multiversion_tests',
|
|
**mock_multiversion_methods):
|
|
with patch('buildscripts.evergreen_gen_multiversion_tests.read_yaml_file',
|
|
return_value=latest) as mock_read_yaml:
|
|
|
|
output = os.path.join(self._tmpdir.name, under_test.EXCLUDE_TAGS_FILE)
|
|
runner = CliRunner()
|
|
result = runner.invoke(
|
|
under_test.generate_exclude_yaml,
|
|
[f"--output={output}", '--task-path-suffix=/data/multiversion'])
|
|
|
|
self.assertEqual(result.exit_code, 0, result)
|
|
mock_read_yaml.assert_called_once()
|
|
mock_multiversion_methods[
|
|
'get_backports_required_last_stable_hash'].assert_called_once()
|
|
mock_multiversion_methods['get_last_stable_yaml'].assert_called_once()
|
|
|
|
def test_create_yaml_suite1(self):
|
|
latest_yaml = {
|
|
'all': [{'ticket': 'fake_ticket0', 'test_file': 'jstests/fake_file0.js'}], 'suites': {
|
|
'suite1': [{'ticket': 'fake_ticket1', 'test_file': 'jstests/fake_file1.js'},
|
|
{'ticket': 'fake_ticket2', 'test_file': 'jstests/fake_file2.js'}]
|
|
}
|
|
}
|
|
|
|
last_stable_yaml = {
|
|
'all': [{'ticket': 'fake_ticket0', 'test_file': 'jstests/fake_file0.js'}], 'suites': {
|
|
'suite1': [{'ticket': 'fake_ticket2', 'test_file': 'jstests/fake_file2.js'}]
|
|
}
|
|
}
|
|
|
|
expected = {
|
|
'selector': {
|
|
'js_test': {'jstests/fake_file1.js': ['suite1_backport_required_multiversion']}
|
|
}
|
|
}
|
|
|
|
self.patch_and_run(latest_yaml, last_stable_yaml)
|
|
self.assert_contents(expected)
|
|
|
|
def test_create_yaml_suite1_and_suite2(self):
|
|
latest_yaml = {
|
|
'all': [{'ticket': 'fake_ticket0', 'test_file': 'jstests/fake_file0.js'}], 'suites': {
|
|
'suite1': [{'ticket': 'fake_ticket1', 'test_file': 'jstests/fake_file1.js'},
|
|
{'ticket': 'fake_ticket2', 'test_file': 'jstests/fake_file2.js'}],
|
|
'suite2': [{'ticket': 'fake_ticket1', 'test_file': 'jstests/fake_file1.js'}]
|
|
}
|
|
}
|
|
|
|
last_stable_yaml = {
|
|
'all': [{'ticket': 'fake_ticket0', 'test_file': 'jstests/fake_file0.js'}], 'suites': {
|
|
'suite1': [{'ticket': 'fake_ticket2', 'test_file': 'jstests/fake_file2.js'}]
|
|
}
|
|
}
|
|
|
|
expected = {
|
|
'selector': {
|
|
'js_test': {
|
|
'jstests/fake_file1.js': [
|
|
'suite1_backport_required_multiversion',
|
|
'suite2_backport_required_multiversion'
|
|
]
|
|
}
|
|
}
|
|
}
|
|
|
|
self.patch_and_run(latest_yaml, last_stable_yaml)
|
|
self.assert_contents(expected)
|
|
|
|
def test_both_all_are_none(self):
|
|
latest_yaml = {
|
|
'all': None, 'suites': {
|
|
'suite1': [{'ticket': 'fake_ticket1', 'test_file': 'jstests/fake_file1.js'},
|
|
{'ticket': 'fake_ticket2', 'test_file': 'jstests/fake_file2.js'}]
|
|
}
|
|
}
|
|
|
|
last_stable_yaml = {
|
|
'all': None, 'suites': {
|
|
'suite1': [{'ticket': 'fake_ticket2', 'test_file': 'jstests/fake_file2.js'}]
|
|
}
|
|
}
|
|
|
|
expected = {
|
|
'selector': {
|
|
'js_test': {'jstests/fake_file1.js': ['suite1_backport_required_multiversion']}
|
|
}
|
|
}
|
|
|
|
self.patch_and_run(latest_yaml, last_stable_yaml)
|
|
self.assert_contents(expected)
|
|
|
|
def test_old_all_is_none(self):
|
|
latest_yaml = {
|
|
'all': [{'ticket': 'fake_ticket0', 'test_file': 'jstests/fake_file0.js'}], 'suites': {
|
|
'suite1': [{'ticket': 'fake_ticket1', 'test_file': 'jstests/fake_file1.js'},
|
|
{'ticket': 'fake_ticket2', 'test_file': 'jstests/fake_file2.js'}]
|
|
}
|
|
}
|
|
|
|
last_stable_yaml = {
|
|
'all': None, 'suites': {
|
|
'suite1': [{'ticket': 'fake_ticket2', 'test_file': 'jstests/fake_file2.js'}]
|
|
}
|
|
}
|
|
|
|
expected = {
|
|
'selector': {
|
|
'js_test': {
|
|
'jstests/fake_file1.js': ['suite1_backport_required_multiversion'],
|
|
'jstests/fake_file0.js': ['backport_required_multiversion']
|
|
}
|
|
}
|
|
}
|
|
|
|
self.patch_and_run(latest_yaml, last_stable_yaml)
|
|
self.assert_contents(expected)
|
|
|
|
def test_create_yaml_suite1_and_all(self):
|
|
latest_yaml = {
|
|
'all': [{'ticket': 'fake_ticket0', 'test_file': 'jstests/fake_file0.js'},
|
|
{'ticket': 'fake_ticket4', 'test_file': 'jstests/fake_file4.js'}], 'suites': {
|
|
'suite1': [{'ticket': 'fake_ticket1', 'test_file': 'jstests/fake_file1.js'},
|
|
{'ticket': 'fake_ticket2', 'test_file': 'jstests/fake_file2.js'}]
|
|
}
|
|
}
|
|
|
|
last_stable_yaml = {
|
|
'all': [{'ticket': 'fake_ticket0', 'test_file': 'jstests/fake_file0.js'}], 'suites': {
|
|
'suite1': [{'ticket': 'fake_ticket2', 'test_file': 'jstests/fake_file2.js'}]
|
|
}
|
|
}
|
|
|
|
expected = {
|
|
'selector': {
|
|
'js_test': {
|
|
'jstests/fake_file1.js': ['suite1_backport_required_multiversion'],
|
|
'jstests/fake_file4.js': ['backport_required_multiversion']
|
|
}
|
|
}
|
|
}
|
|
|
|
self.patch_and_run(latest_yaml, last_stable_yaml)
|
|
self.assert_contents(expected)
|
|
|
|
# Can delete after backporting the changed yml syntax.
|
|
def test_not_backported(self):
|
|
latest_yaml = {
|
|
'all': [{'ticket': 'fake_ticket0', 'test_file': 'jstests/fake_file0.js'}], 'suites': {
|
|
'suite1': [{'ticket': 'fake_ticket2', 'test_file': 'jstests/fake_file2.js'},
|
|
{'ticket': 'fake_ticket3', 'test_file': 'jstests/fake_file3.js'}]
|
|
}
|
|
}
|
|
|
|
last_stable_yaml = {
|
|
'suite1': [{'ticket': 'fake_ticket2', 'test_file': 'jstests/fake_file2.js'}]
|
|
}
|
|
|
|
expected = {
|
|
'selector': {
|
|
'js_test': {
|
|
'jstests/fake_file0.js': ['backport_required_multiversion'],
|
|
'jstests/fake_file3.js': ['suite1_backport_required_multiversion']
|
|
}
|
|
}
|
|
}
|
|
|
|
self.patch_and_run(latest_yaml, last_stable_yaml)
|
|
self.assert_contents(expected)
|
|
|
|
|
|
EXPANSIONS = """task: t
|
|
build_variant: bv
|
|
fallback_num_sub_suites: 5
|
|
project: p
|
|
task_id: t0
|
|
task_name: t
|
|
use_multiversion: "true"
|
|
"""
|
|
|
|
if __name__ == '__main__':
|
|
unittest.main()
|