Add default timeouts to tests.

Tests in the engine used the default build timeout causing tests leaking
processes to fail as cancelled instead of test failure. Furthermore
tests leaking processes were using all the allocated time for a single
run rather than failing fast and retrying.

Bug: https://github.com/flutter/flutter/issues/143021
Change-Id: I831f8050547c48ae16bbacaa1b4c5d8bf9cfcb1d
Reviewed-on: https://flutter-review.googlesource.com/c/recipes/+/55162
Reviewed-by: Ricardo Amador <ricardoamador@google.com>
Reviewed-by: Keyong Han <keyonghan@google.com>
Commit-Queue: Godofredo Contreras <godofredoc@google.com>
diff --git a/recipes/engine_v2/builder.expected/basic.json b/recipes/engine_v2/builder.expected/basic.json
index e224f57..ff26f96 100644
--- a/recipes/engine_v2/builder.expected/basic.json
+++ b/recipes/engine_v2/builder.expected/basic.json
@@ -3182,7 +3182,8 @@
         "hostname": "rdbhost"
       }
     },
-    "name": "test: mytest"
+    "name": "test: mytest",
+    "timeout": 1800
   },
   {
     "cmd": [],
diff --git a/recipes/engine_v2/builder.expected/dart-internal-flutter-success.json b/recipes/engine_v2/builder.expected/dart-internal-flutter-success.json
index 34ec103..f88da53 100644
--- a/recipes/engine_v2/builder.expected/dart-internal-flutter-success.json
+++ b/recipes/engine_v2/builder.expected/dart-internal-flutter-success.json
@@ -2323,7 +2323,8 @@
         "hostname": "rdbhost"
       }
     },
-    "name": "test: mytest"
+    "name": "test: mytest",
+    "timeout": 1800
   },
   {
     "cmd": [],
diff --git a/recipes/engine_v2/builder.expected/mac.json b/recipes/engine_v2/builder.expected/mac.json
index 3ca135a..09d2e98 100644
--- a/recipes/engine_v2/builder.expected/mac.json
+++ b/recipes/engine_v2/builder.expected/mac.json
@@ -3725,7 +3725,8 @@
         "hostname": "rdbhost"
       }
     },
-    "name": "test: mytest"
+    "name": "test: mytest",
+    "timeout": 1800
   },
   {
     "cmd": [],
diff --git a/recipes/engine_v2/builder.expected/monorepo.json b/recipes/engine_v2/builder.expected/monorepo.json
index a8725de..b96192f 100644
--- a/recipes/engine_v2/builder.expected/monorepo.json
+++ b/recipes/engine_v2/builder.expected/monorepo.json
@@ -3036,7 +3036,8 @@
         "hostname": "rdbhost"
       }
     },
-    "name": "test: mytest"
+    "name": "test: mytest",
+    "timeout": 1800
   },
   {
     "cmd": [],
diff --git a/recipes/engine_v2/builder.expected/monorepo_tryjob.json b/recipes/engine_v2/builder.expected/monorepo_tryjob.json
index a5adc35..32e4702 100644
--- a/recipes/engine_v2/builder.expected/monorepo_tryjob.json
+++ b/recipes/engine_v2/builder.expected/monorepo_tryjob.json
@@ -3123,7 +3123,8 @@
         "hostname": "rdbhost"
       }
     },
-    "name": "test: mytest"
+    "name": "test: mytest",
+    "timeout": 1800
   },
   {
     "cmd": [],
diff --git a/recipes/engine_v2/builder.py b/recipes/engine_v2/builder.py
index 1c23446..8e87a3b 100644
--- a/recipes/engine_v2/builder.py
+++ b/recipes/engine_v2/builder.py
@@ -78,6 +78,9 @@
 # Used for mock paths
 DIRECTORY = 'DIRECTORY'
 
+# Default timeout for tests running as part of the build.
+DEFAULT_TEST_TIMEOUT_SECS = 30 * 60
+
 
 def run_generators(api, pub_dirs, generator_tasks, checkout, env, env_prefixes):
   """Runs sub-builds generators."""
@@ -130,12 +133,15 @@
       command.append(checkout.join(test.get('script')))
       command.extend(test.get('parameters', []))
       step_name = api.test_utils.test_step_name(test.get('name'))
+      test_timeout_secs = test.get(
+          'test_timeout_secs', DEFAULT_TEST_TIMEOUT_SECS
+      )
 
       # pylint: disable=cell-var-from-loop
       def run_test():
         # Replace MAGIC_ENVS
         updated_command = api.os_utils.replace_magic_envs(command, tmp_env)
-        return api.step(step_name, updated_command)
+        return api.step(step_name, updated_command, timeout=test_timeout_secs)
 
       # Rerun test step 3 times by default if failing.
       # TODO(keyonghan): notify tree gardener for test failures/flakes:
@@ -256,6 +262,7 @@
         file, bucket, gcs_path_without_bucket
     )
 
+
 def RunSteps(api):
   # Collect memory/cpu/process before task execution.
   api.os_utils.collect_os_info()
@@ -287,7 +294,9 @@
     env, env_prefixes = api.repo_util.engine_environment(
         api.path['cache'].join('builder')
     )
-    api.repo_util.engine_checkout(cache_root, env, env_prefixes, gclient_variables = gclient_variables)
+    api.repo_util.engine_checkout(
+        cache_root, env, env_prefixes, gclient_variables=gclient_variables
+    )
   outputs = {}
   api.logs_util.initialize_logs_collection(env)
   try:
diff --git a/recipes/engine_v2/tester_engine.expected/basic.json b/recipes/engine_v2/tester_engine.expected/basic.json
index 2d9d50c..0b817f8 100644
--- a/recipes/engine_v2/tester_engine.expected/basic.json
+++ b/recipes/engine_v2/tester_engine.expected/basic.json
@@ -800,7 +800,8 @@
         "RECIPE_REPO[depot_tools]"
       ]
     },
-    "name": "test: felt test: chrome-unit-linux"
+    "name": "test: felt test: chrome-unit-linux",
+    "timeout": 1800
   },
   {
     "cmd": [],
diff --git a/recipes/engine_v2/tester_engine.py b/recipes/engine_v2/tester_engine.py
index 75f49cd..7c36544 100644
--- a/recipes/engine_v2/tester_engine.py
+++ b/recipes/engine_v2/tester_engine.py
@@ -71,6 +71,8 @@
     'recipe_engine/step',
 ]
 
+DEFAULT_TEST_TIMEOUT_SECS = 30 * 60
+
 
 def run_tests(api, test, checkout, env, env_prefixes):
   """Runs sub-build tests."""
@@ -95,9 +97,10 @@
     command.append(checkout.join(task.get('script')))
     command.extend(task.get('parameters', []))
     step_name = api.test_utils.test_step_name(task.get('name'))
+    test_timeout_secs = task.get('test_timeout_secs', DEFAULT_TEST_TIMEOUT_SECS)
 
     def run_test():
-      return api.step(step_name, command)
+      return api.step(step_name, command, timeout=test_timeout_secs)
 
     api.logs_util.initialize_logs_collection(env)
     try: