| Index: lib/cros_build_lib_unittest.py
|
| diff --git a/lib/cros_build_lib_unittest.py b/lib/cros_build_lib_unittest.py
|
| index 527815e4028fcc05818bd2ccbb1413772ed3fda0..ab89f01ad00ec948b681755bb152e31653a8f8da 100755
|
| --- a/lib/cros_build_lib_unittest.py
|
| +++ b/lib/cros_build_lib_unittest.py
|
| @@ -7,6 +7,7 @@
|
| import errno
|
| import os
|
| import shutil
|
| +import signal
|
| import subprocess
|
| import tempfile
|
| import unittest
|
| @@ -17,13 +18,19 @@ import mox
|
| class TestRunCommand(unittest.TestCase):
|
|
|
| def setUp(self):
|
| + # Get the original value for SIGINT so our signal() mock can return the
|
| + # correct thing.
|
| + self._old_sigint = signal.getsignal(signal.SIGINT)
|
| +
|
| self.mox = mox.Mox()
|
| self.mox.StubOutWithMock(subprocess, 'Popen', use_mock_anything=True)
|
| + self.mox.StubOutWithMock(signal, 'signal')
|
| self.proc_mock = self.mox.CreateMockAnything()
|
| self.error = 'test error'
|
| self.output = 'test output'
|
|
|
| def tearDown(self):
|
| + # Unset anything that we set with mox.
|
| self.mox.UnsetStubs()
|
|
|
| def _AssertCrEqual(self, expected, actual):
|
| @@ -59,7 +66,7 @@ class TestRunCommand(unittest.TestCase):
|
| expected_result.returncode = self.proc_mock.returncode
|
|
|
| arg_dict = dict()
|
| - for attr in 'cwd stdin stdout stderr shell'.split():
|
| + for attr in 'cwd env stdin stdout stderr shell'.split():
|
| if attr in sp_kv:
|
| arg_dict[attr] = sp_kv[attr]
|
| else:
|
| @@ -68,20 +75,41 @@ class TestRunCommand(unittest.TestCase):
|
| else:
|
| arg_dict[attr] = None
|
|
|
| + # If requested, RunCommand will ignore sigints; record that.
|
| + if rc_kv.get('ignore_sigint'):
|
| + signal.signal(signal.SIGINT, signal.SIG_IGN).AndReturn(self._old_sigint)
|
| +
|
| subprocess.Popen(real_cmd, **arg_dict).AndReturn(self.proc_mock)
|
| self.proc_mock.communicate(None).AndReturn((self.output, self.error))
|
|
|
| + # If it ignored them, RunCommand will restore sigints; record that.
|
| + if rc_kv.get('ignore_sigint'):
|
| + signal.signal(signal.SIGINT, self._old_sigint).AndReturn(signal.SIG_IGN)
|
| +
|
| self.mox.ReplayAll()
|
| actual_result = cros_build_lib.RunCommand(cmd, **rc_kv)
|
| self.mox.VerifyAll()
|
|
|
| self._AssertCrEqual(expected_result, actual_result)
|
|
|
| - def testReturnCodeZeroWithArrayCmd(self):
|
| - """--enter_chroot=False and --cmd is an array of strings."""
|
| + def testReturnCodeZeroWithArrayCmd(self, ignore_sigint=False):
|
| + """--enter_chroot=False and --cmd is an array of strings.
|
| +
|
| + Parameterized so this can also be used by some other tests w/ alternate
|
| + params to RunCommand().
|
| +
|
| + Args:
|
| + ignore_sigint: If True, we'll tell RunCommand to ignore sigint.
|
| + """
|
| self.proc_mock.returncode = 0
|
| cmd_list = ['foo', 'bar', 'roger']
|
| - self._TestCmd(cmd_list, cmd_list, rc_kv=dict(exit_code=True))
|
| + self._TestCmd(cmd_list, cmd_list, rc_kv=dict(exit_code=True,
|
| + ignore_sigint=ignore_sigint))
|
| +
|
| + def testSignalRestoreNormalCase(self):
|
| + """Test RunCommand() properly sets/restores sigint. Normal case."""
|
| + self.testReturnCodeZeroWithArrayCmd(ignore_sigint=True)
|
| +
|
|
|
| def testReturnCodeZeroWithArrayCmdEnterChroot(self):
|
| """--enter_chroot=True and --cmd is an array of strings."""
|
| @@ -96,17 +124,39 @@ class TestRunCommand(unittest.TestCase):
|
| cmd = 'test cmd'
|
| self._TestCmd(cmd, cmd, rc_kv=dict(error_ok=True))
|
|
|
| - def testSubprocessCommunicateExceptionRaisesError(self):
|
| - """Verify error raised by communicate() is caught."""
|
| + def testSubprocessCommunicateExceptionRaisesError(self, ignore_sigint=False):
|
| + """Verify error raised by communicate() is caught.
|
| +
|
| + Parameterized so this can also be used by some other tests w/ alternate
|
| + params to RunCommand().
|
| +
|
| + Args:
|
| + ignore_sigint: If True, we'll tell RunCommand to ignore sigint.
|
| + """
|
| cmd = 'test cmd'
|
| - subprocess.Popen(cmd, cwd=None, stdin=None, stdout=None, stderr=None,
|
| +
|
| + # If requested, RunCommand will ignore sigints; record that.
|
| + if ignore_sigint:
|
| + signal.signal(signal.SIGINT, signal.SIG_IGN).AndReturn(self._old_sigint)
|
| +
|
| + subprocess.Popen(cmd, cwd=None, env=None,
|
| + stdin=None, stdout=None, stderr=None,
|
| shell=False).AndReturn(self.proc_mock)
|
| self.proc_mock.communicate(None).AndRaise(ValueError)
|
|
|
| + # If it ignored them, RunCommand will restore sigints; record that.
|
| + if ignore_sigint:
|
| + signal.signal(signal.SIGINT, self._old_sigint).AndReturn(signal.SIG_IGN)
|
| +
|
| self.mox.ReplayAll()
|
| - self.assertRaises(ValueError, cros_build_lib.RunCommand, cmd)
|
| + self.assertRaises(ValueError, cros_build_lib.RunCommand, cmd,
|
| + ignore_sigint=ignore_sigint)
|
| self.mox.VerifyAll()
|
|
|
| + def testSignalRestoreExceptionCase(self):
|
| + """Test RunCommand() properly sets/restores sigint. Exception case."""
|
| + self.testSubprocessCommunicateExceptionRaisesError(ignore_sigint=True)
|
| +
|
| def testSubprocessCommunicateExceptionNotRaisesError(self):
|
| """Don't re-raise error from communicate() when --error_ok=True."""
|
| cmd = 'test cmd'
|
| @@ -114,7 +164,8 @@ class TestRunCommand(unittest.TestCase):
|
| expected_result = cros_build_lib.CommandResult()
|
| expected_result.cmd = real_cmd
|
|
|
| - subprocess.Popen(real_cmd, cwd=None, stdin=None, stdout=None, stderr=None,
|
| + subprocess.Popen(real_cmd, cwd=None, env=None,
|
| + stdin=None, stdout=None, stderr=None,
|
| shell=False).AndReturn(self.proc_mock)
|
| self.proc_mock.communicate(None).AndRaise(ValueError)
|
|
|
| @@ -125,6 +176,22 @@ class TestRunCommand(unittest.TestCase):
|
|
|
| self._AssertCrEqual(expected_result, actual_result)
|
|
|
| + def testEnvWorks(self):
|
| + """Test RunCommand(..., env=xyz) works."""
|
| + # We'll put this bogus environment together, just to make sure
|
| + # subprocess.Popen gets passed it.
|
| + env = {'Tom': 'Jerry', 'Itchy': 'Scratchy'}
|
| +
|
| + # This is a simple case, copied from testReturnCodeZeroWithArrayCmd()
|
| + self.proc_mock.returncode = 0
|
| + cmd_list = ['foo', 'bar', 'roger']
|
| +
|
| + # Run. We expect the env= to be passed through from sp (subprocess.Popen)
|
| + # to rc (RunCommand).
|
| + self._TestCmd(cmd_list, cmd_list,
|
| + sp_kv=dict(env=env),
|
| + rc_kv=dict(env=env, exit_code=True))
|
| +
|
|
|
| class TestListFiles(unittest.TestCase):
|
|
|
|
|