Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(176)

Unified Diff: recipe_engine/unittests/run_test.py

Issue 1959563002: Use subprocess42 in recipe_engine to avoid threading madness. (Closed) Base URL: https://chromium.googlesource.com/external/github.com/luci/recipes-py@master
Patch Set: *sigh* presubmit Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « recipe_engine/third_party/subprocess42.py ('k') | recipe_engine/unittests/step_runner_test.py » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: recipe_engine/unittests/run_test.py
diff --git a/recipe_engine/unittests/run_test.py b/recipe_engine/unittests/run_test.py
index da6b81c15c163f500fed04959cb2a9e1417f6a4e..547f397f450dadad6d2289b1252ed6863c78d4a2 100755
--- a/recipe_engine/unittests/run_test.py
+++ b/recipe_engine/unittests/run_test.py
@@ -9,6 +9,7 @@ import re
import subprocess
import sys
import unittest
+import time
BASE_DIR = os.path.dirname(os.path.dirname(os.path.dirname(
os.path.abspath(__file__))))
@@ -21,6 +22,10 @@ import recipe_engine.step_runner
from recipe_engine import recipe_test_api
import mock
+ENABLE_SUBPROCESS42 = {
+ "$recipe_engine": {"mode_flags": {"use_subprocess42": True}}
+}
+
class RunTest(unittest.TestCase):
def _run_cmd(self, recipe, properties=None):
script_path = os.path.join(BASE_DIR, 'recipes.py')
@@ -41,15 +46,37 @@ class RunTest(unittest.TestCase):
self.assertEqual(0, exit_code)
def test_examples(self):
- self._test_recipe('step:example')
- self._test_recipe('path:example')
- self._test_recipe('raw_io:example')
- self._test_recipe('python:example')
- self._test_recipe('json:example')
- self._test_recipe('uuid:example')
+ tests = [
+ ['step:example'],
+ ['path:example'],
+ ['raw_io:example'],
+ ['python:example'],
+ ['json:example'],
+ ['uuid:example'],
+
+ ['engine_tests/depend_on/top', {'to_pass': 42}],
+ ['engine_tests/functools_partial'],
+ ]
+ for test in tests:
+ self._test_recipe(*test)
+
+ recipe = test[0]
+ props = {}
+ if len(test) > 1:
+ props = test[1]
+ props.update(ENABLE_SUBPROCESS42)
+ self._test_recipe(recipe, props)
+
+ def test_bad_subprocess(self):
+ now = time.time()
+ self._test_recipe('engine_tests/bad_subprocess', ENABLE_SUBPROCESS42)
+ after = time.time()
+
+ # Test has a daemon that holds on to stdout for 30s, but the daemon's parent
+ # process (e.g. the one that recipe engine actually runs) quits immediately.
+ # If this takes longer than 5 seconds to run, we consider it failed.
+ self.assertLess(after - now, 5)
- self._test_recipe('engine_tests/depend_on/top', {'to_pass': 42})
- self._test_recipe('engine_tests/functools_partial')
def test_nonexistent_command(self):
subp = subprocess.Popen(
@@ -60,6 +87,15 @@ class RunTest(unittest.TestCase):
self.assertRegexpMatches(stdout, 'OSError')
self.assertEqual(255, subp.returncode)
+ def test_nonexistent_command_s42(self):
+ subp = subprocess.Popen(
+ self._run_cmd('engine_tests/nonexistent_command', ENABLE_SUBPROCESS42),
+ stdout=subprocess.PIPE)
+ stdout, _ = subp.communicate()
+ self.assertRegexpMatches(stdout, '(?m)^@@@STEP_EXCEPTION@@@$')
+ self.assertRegexpMatches(stdout, 'OSError')
+ self.assertEqual(255, subp.returncode)
+
def test_trigger(self):
subp = subprocess.Popen(
self._run_cmd('engine_tests/trigger'),
@@ -71,6 +107,17 @@ class RunTest(unittest.TestCase):
blob = m.group(1)
json.loads(blob) # Raises an exception if the blob is not valid json.
+ def test_trigger_s42(self):
+ subp = subprocess.Popen(
+ self._run_cmd('engine_tests/trigger', ENABLE_SUBPROCESS42),
+ stdout=subprocess.PIPE)
+ stdout, _ = subp.communicate()
+ self.assertEqual(0, subp.returncode)
+ m = re.compile(r'^@@@STEP_TRIGGER@(.*)@@@$', re.MULTILINE).search(stdout)
+ self.assertTrue(m)
+ blob = m.group(1)
+ json.loads(blob) # Raises an exception if the blob is not valid json.
+
def test_trigger_no_such_command(self):
"""Tests that trigger still happens even if running the command fails."""
subp = subprocess.Popen(
@@ -81,6 +128,18 @@ class RunTest(unittest.TestCase):
self.assertRegexpMatches(stdout, r'(?m)^@@@STEP_TRIGGER@(.*)@@@$')
self.assertEqual(255, subp.returncode)
+ def test_trigger_no_such_command_s42(self):
+ """Tests that trigger still happens even if running the command fails."""
+ props = {'command': ['na-huh']}
+ props.update(ENABLE_SUBPROCESS42)
+ subp = subprocess.Popen(
+ self._run_cmd('engine_tests/trigger', props),
+ stdout=subprocess.PIPE)
+ stdout, _ = subp.communicate()
+ self.assertRegexpMatches(stdout, r'(?m)^@@@STEP_TRIGGER@(.*)@@@$')
+ self.assertEqual(255, subp.returncode)
+
+
def test_shell_quote(self):
# For regular-looking commands we shouldn't need any specialness.
self.assertEqual(
@@ -143,7 +202,20 @@ class RunTest(unittest.TestCase):
self._run_cmd('engine_tests/subannotations'),
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
- stdout, stderr = proc.communicate()
+ stdout, _ = proc.communicate()
+ self.assertRegexpMatches(stdout, r'(?m)^!@@@BUILD_STEP@steppy@@@$')
+ self.assertRegexpMatches(stdout, r'(?m)^@@@BUILD_STEP@pippy@@@$')
+ # Before 'Subannotate me' we expect an extra STEP_CURSOR to reset the
+ # state.
+ self.assertRegexpMatches(stdout,
+ r'(?m)^@@@STEP_CURSOR@Subannotate me@@@\n@@@STEP_CLOSED@@@$')
+
+ def test_subannotations_s42(self):
+ proc = subprocess.Popen(
+ self._run_cmd('engine_tests/subannotations', ENABLE_SUBPROCESS42),
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE)
+ stdout, _ = proc.communicate()
self.assertRegexpMatches(stdout, r'(?m)^!@@@BUILD_STEP@steppy@@@$')
self.assertRegexpMatches(stdout, r'(?m)^@@@BUILD_STEP@pippy@@@$')
# Before 'Subannotate me' we expect an extra STEP_CURSOR to reset the
« no previous file with comments | « recipe_engine/third_party/subprocess42.py ('k') | recipe_engine/unittests/step_runner_test.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698