Chromium Code Reviews| Index: scripts/slave/recipe_modules/test_utils/api.py |
| diff --git a/scripts/slave/recipe_modules/test_utils/api.py b/scripts/slave/recipe_modules/test_utils/api.py |
| index a91b801feb820c1bbfeac33cb411ff90788e3e52..012e3f748980e9e23069d44ab2eb76aad7a7843a 100644 |
| --- a/scripts/slave/recipe_modules/test_utils/api.py |
| +++ b/scripts/slave/recipe_modules/test_utils/api.py |
| @@ -40,6 +40,8 @@ class TestUtilsApi(recipe_api.RecipeApi): |
| Base class for tests that can be retried after deapplying a previously |
| applied patch. |
| """ |
| + # If True, 'trigger' and 'collect' should be used instead of 'run'. |
|
M-A Ruel
2014/06/04 00:52:53
If I were another reader that didn't know about sw
Vadim Sh.
2014/06/04 02:58:26
Added more explanation, mentioned swarming.
|
| + async = False |
| @property |
| def name(self): # pragma: no cover |
| @@ -50,6 +52,14 @@ class TestUtilsApi(recipe_api.RecipeApi): |
| """Run the test. suffix is 'with patch' or 'without patch'.""" |
| raise NotImplementedError() |
| + def trigger(self, suffix): # pragma: no cover |
| + """Launch the test asynchronously, used if self.async == True.""" |
| + raise NotImplementedError() |
| + |
| + def collect(self, suffix): # pragma: no cover |
| + """Wait for triggered test to finish, used if self.async == True.""" |
| + raise NotImplementedError() |
| + |
| def has_valid_results(self, suffix): # pragma: no cover |
| """ |
| Returns True if results (failures) are valid. |
| @@ -79,6 +89,9 @@ class TestUtilsApi(recipe_api.RecipeApi): |
| deapply_patch_fn - function that takes a list of failing tests |
| and undoes any effect of the previously applied patch |
| """ |
| + # Convert iterable to list, since it is enumerated multiple times. |
| + tests = list(tests) |
| + |
| if self.m.step_history.failed: |
| yield self.m.python.inline( |
| 'Aborting due to failed build state.', |
| @@ -86,7 +99,17 @@ class TestUtilsApi(recipe_api.RecipeApi): |
| always_run=True, abort_on_failure=True) |
| return # won't actually hit this, but be explicit |
| - yield (t.run('with patch') for t in tests) |
| + def run(prefix, tests): |
| + """Runs synchronous and asynchronous tests.""" |
|
M-A Ruel
2014/06/04 00:52:53
Add a note about how test can run magically in par
Vadim Sh.
2014/06/04 02:58:26
Done.
|
| + # Trigger all async tests first, so that they are running in parallel |
| + # with synchronous tests. |
| + yield (t.trigger(prefix) for t in tests if t.async) |
| + # Now block on all synchronous tests. |
| + yield (t.run(prefix) for t in tests if not t.async) |
| + # And finally wait for all pending asynchronous tests to complete. |
| + yield (t.collect(prefix) for t in tests if t.async) |
| + |
| + yield run('with patch', tests) |
| failing_tests = [] |
| for t in tests: |
| @@ -106,7 +129,7 @@ class TestUtilsApi(recipe_api.RecipeApi): |
| yield deapply_patch_fn(failing_tests) |
| - yield (t.run('without patch') for t in failing_tests) |
| + yield run('without patch', failing_tests) |
| yield (self._summarize_retried_test(t) for t in failing_tests) |
| def _summarize_retried_test(self, test): |