summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Bradford <david.bradford@mongodb.com>2021-12-16 11:22:55 -0500
committerEvergreen Agent <no-reply@evergreen.mongodb.com>2021-12-16 22:27:28 +0000
commit00b7518783c6a576c0996fc27f0bb85f13c78fc3 (patch)
tree782809c063f8b43de15e4c72747c9d0ddbac3eac
parent7cb100e649c4e429719b07c9419a0b254ece3b79 (diff)
downloadmongo-00b7518783c6a576c0996fc27f0bb85f13c78fc3.tar.gz
SERVER-62097: Generated tasks should inherit timeouts specified by build variant
-rw-r--r--buildscripts/evergreen_gen_build_variant.py6
-rw-r--r--buildscripts/selected_tests.py3
-rw-r--r--buildscripts/task_generation/task_types/gentask_options.py10
-rw-r--r--buildscripts/task_generation/task_types/resmoke_tasks.py9
-rw-r--r--buildscripts/task_generation/timeout.py6
-rw-r--r--buildscripts/tests/task_generation/task_types/test_gentask_options.py2
-rw-r--r--buildscripts/tests/task_generation/task_types/test_resmoke_tasks.py22
-rw-r--r--buildscripts/tests/task_generation/test_timeout.py15
8 files changed, 66 insertions, 7 deletions
diff --git a/buildscripts/evergreen_gen_build_variant.py b/buildscripts/evergreen_gen_build_variant.py
index bd6ceffc98d..758e2f2ab0b 100644
--- a/buildscripts/evergreen_gen_build_variant.py
+++ b/buildscripts/evergreen_gen_build_variant.py
@@ -39,6 +39,7 @@ class EvgExpansions(BaseModel):
build_id: Build ID being run under.
build_variant: Build variant being generated.
+ exec_timeout_secs: Seconds to wait before considering a task timed out.
gen_task_gran: Granularity of how tasks are being generated.
is_patch: Whether generation is part of a patch build.
project: Evergreen project being run under.
@@ -50,10 +51,12 @@ class EvgExpansions(BaseModel):
task_name: Name of task running.
target_resmoke_time: Target time of generated sub-suites.
task_id: ID of task being run under.
+ timeout_secs: Seconds to wait with no output before considering a task timed out.
"""
build_id: str
build_variant: str
+ exec_timeout_secs: Optional[int] = None
is_patch: Optional[bool]
project: str
max_tests_per_suite: Optional[int] = 100
@@ -64,6 +67,7 @@ class EvgExpansions(BaseModel):
task_name: str
target_resmoke_time: Optional[int] = None
task_id: str
+ timeout_secs: Optional[int] = None
@classmethod
def from_yaml_file(cls, path: str) -> "EvgExpansions":
@@ -110,6 +114,8 @@ class EvgExpansions(BaseModel):
is_patch=self.is_patch,
generated_config_dir=GENERATED_CONFIG_DIR,
use_default_timeouts=False,
+ timeout_secs=self.timeout_secs,
+ exec_timeout_secs=self.exec_timeout_secs,
)
def config_location(self) -> str:
diff --git a/buildscripts/selected_tests.py b/buildscripts/selected_tests.py
index e772eef9eed..b1df4686e22 100644
--- a/buildscripts/selected_tests.py
+++ b/buildscripts/selected_tests.py
@@ -120,7 +120,8 @@ class EvgExpansions(BaseModel):
"""Build options needed to generate tasks."""
return GenTaskOptions(create_misc_suite=False,
generated_config_dir=SELECTED_TESTS_CONFIG_DIR, is_patch=self.is_patch
- or False, use_default_timeouts=False)
+ or False, use_default_timeouts=False, timeout_secs=None,
+ exec_timeout_secs=None)
def build_suite_split_config(self, start_date: datetime,
end_date: datetime) -> SuiteSplitConfig:
diff --git a/buildscripts/task_generation/task_types/gentask_options.py b/buildscripts/task_generation/task_types/gentask_options.py
index b78a7974979..d9616abfe96 100644
--- a/buildscripts/task_generation/task_types/gentask_options.py
+++ b/buildscripts/task_generation/task_types/gentask_options.py
@@ -2,6 +2,8 @@
import os
from typing import NamedTuple, Optional, List
+from buildscripts.patch_builds.task_generation import TimeoutInfo
+
class GenTaskOptions(NamedTuple):
"""
@@ -18,6 +20,8 @@ class GenTaskOptions(NamedTuple):
is_patch: bool
generated_config_dir: str
use_default_timeouts: bool
+ timeout_secs: Optional[int]
+ exec_timeout_secs: Optional[int]
def suite_location(self, suite_name: str) -> str:
"""
@@ -39,3 +43,9 @@ class GenTaskOptions(NamedTuple):
# here, just use the forward slash; otherwise the path separator will be treated as
# the escape character on Windows.
return "/".join([self.generated_config_dir, base_file])
+
+ def build_defualt_timeout(self) -> TimeoutInfo:
+ """Generate a timeout command that can be used if historic timing info is missing."""
+ if self.timeout_secs is not None or self.exec_timeout_secs is not None:
+ return TimeoutInfo.overridden(self.exec_timeout_secs, self.timeout_secs)
+ return TimeoutInfo.default_timeout()
diff --git a/buildscripts/task_generation/task_types/resmoke_tasks.py b/buildscripts/task_generation/task_types/resmoke_tasks.py
index 513d6da8c13..24710ffd88e 100644
--- a/buildscripts/task_generation/task_types/resmoke_tasks.py
+++ b/buildscripts/task_generation/task_types/resmoke_tasks.py
@@ -137,9 +137,12 @@ class ResmokeGenTaskService:
suite_file=suite.suite_name,
task_name=suite.task_name, params=params)
- timeout_info = timeout_est.generate_timeout_cmd(self.gen_task_options.is_patch,
- params.repeat_suites,
- self.gen_task_options.use_default_timeouts)
+ if timeout_est.is_specified():
+ timeout_info = timeout_est.generate_timeout_cmd(
+ self.gen_task_options.is_patch, params.repeat_suites,
+ self.gen_task_options.use_default_timeouts)
+ else:
+ timeout_info = self.gen_task_options.build_defualt_timeout()
commands = [
timeout_info.cmd,
diff --git a/buildscripts/task_generation/timeout.py b/buildscripts/task_generation/timeout.py
index 67db6568d65..0143cd6e8b1 100644
--- a/buildscripts/task_generation/timeout.py
+++ b/buildscripts/task_generation/timeout.py
@@ -43,6 +43,10 @@ class TimeoutEstimate(NamedTuple):
"""Create an instance with no estimation data."""
return cls(max_test_runtime=None, expected_task_runtime=None)
+ def is_specified(self) -> bool:
+ """Determine if any specific timeout value has been specified."""
+ return self.max_test_runtime is not None or self.expected_task_runtime is not None
+
def calculate_test_timeout(self, repeat_factor: int) -> Optional[int]:
"""
Calculate the timeout to use for tests.
@@ -84,7 +88,7 @@ class TimeoutEstimate(NamedTuple):
:return: Timeout info for the task.
"""
- if (self.max_test_runtime is None and self.expected_task_runtime is None) or use_default:
+ if not self.is_specified or use_default:
return TimeoutInfo.default_timeout()
test_timeout = self.calculate_test_timeout(repeat_factor)
diff --git a/buildscripts/tests/task_generation/task_types/test_gentask_options.py b/buildscripts/tests/task_generation/task_types/test_gentask_options.py
index 6d811e32577..657cf669457 100644
--- a/buildscripts/tests/task_generation/task_types/test_gentask_options.py
+++ b/buildscripts/tests/task_generation/task_types/test_gentask_options.py
@@ -13,6 +13,8 @@ def build_mock_gen_task_options(config_dir="."):
is_patch=True,
generated_config_dir=config_dir,
use_default_timeouts=False,
+ timeout_secs=None,
+ exec_timeout_secs=None,
)
diff --git a/buildscripts/tests/task_generation/task_types/test_resmoke_tasks.py b/buildscripts/tests/task_generation/task_types/test_resmoke_tasks.py
index 9ea74bde214..bd62d2bd5c7 100644
--- a/buildscripts/tests/task_generation/task_types/test_resmoke_tasks.py
+++ b/buildscripts/tests/task_generation/task_types/test_resmoke_tasks.py
@@ -29,9 +29,10 @@ class TestHelperMethods(unittest.TestCase):
self.assertEqual(False, under_test.string_contains_any_of_args(string, args))
-def build_mock_gen_options(use_default_timeouts=False):
+def build_mock_gen_options(use_default_timeouts=False, timeout_secs=None, exec_timeout_secs=None):
return GenTaskOptions(create_misc_suite=True, is_patch=True, generated_config_dir="tmpdir",
- use_default_timeouts=use_default_timeouts)
+ use_default_timeouts=use_default_timeouts, timeout_secs=timeout_secs,
+ exec_timeout_secs=exec_timeout_secs)
def build_mock_gen_params(repeat_suites=1, resmoke_args="resmoke args"):
@@ -155,3 +156,20 @@ class TestGenerateTask(unittest.TestCase):
for cmd in task.shrub_task.commands:
cmd_dict = cmd.as_dict()
self.assertNotEqual("timeout.update", cmd_dict.get("command"))
+
+ def test_suites_without_enough_info_should_inherit_bv_timeouts_if_specified(self):
+ mock_gen_options = build_mock_gen_options(timeout_secs=300, exec_timeout_secs=150)
+ params = build_mock_gen_params()
+ suites = build_mock_suite(1, include_runtimes=False)
+
+ resmoke_service = under_test.ResmokeGenTaskService(mock_gen_options)
+ tasks = resmoke_service.generate_tasks(suites, params)
+
+ self.assertEqual(2, len(tasks))
+ for resmoke_task in tasks:
+ task = resmoke_task.shrub_task
+ self.assertGreaterEqual(len(task.commands), 1)
+ timeout_cmd = task.commands[0]
+ self.assertEqual("timeout.update", timeout_cmd.command)
+ self.assertEqual(300, timeout_cmd.params["timeout_secs"])
+ self.assertEqual(150, timeout_cmd.params["exec_timeout_secs"])
diff --git a/buildscripts/tests/task_generation/test_timeout.py b/buildscripts/tests/task_generation/test_timeout.py
index 4e785897706..a7dd76464a8 100644
--- a/buildscripts/tests/task_generation/test_timeout.py
+++ b/buildscripts/tests/task_generation/test_timeout.py
@@ -32,6 +32,21 @@ class TimeoutEstimateTest(unittest.TestCase):
with self.assertRaises(ValueError):
timeout_est.generate_timeout_cmd(is_patch=True, repeat_factor=1)
+ def test_is_specified_should_return_true_when_a_test_runtime_is_specified(self):
+ timeout_est = under_test.TimeoutEstimate(max_test_runtime=3.14, expected_task_runtime=None)
+
+ self.assertTrue(timeout_est.is_specified())
+
+ def test_is_specified_should_return_true_when_a_task_runtime_is_specified(self):
+ timeout_est = under_test.TimeoutEstimate(max_test_runtime=None, expected_task_runtime=3.14)
+
+ self.assertTrue(timeout_est.is_specified())
+
+ def test_is_specified_should_return_false_when_no_data_is_specified(self):
+ timeout_est = under_test.TimeoutEstimate(max_test_runtime=None, expected_task_runtime=None)
+
+ self.assertFalse(timeout_est.is_specified())
+
class TestGenerateTimeoutCmd(unittest.TestCase):
def test_evg_config_does_not_fails_if_test_timeout_too_high_on_mainline(self):