| OLD | NEW |
| 1 #!/usr/bin/python | 1 #!/usr/bin/python |
| 2 # | 2 # |
| 3 # Copyright (c) 2010 The Chromium OS Authors. All rights reserved. | 3 # Copyright (c) 2011 The Chromium OS Authors. All rights reserved. |
| 4 # Use of this source code is governed by a BSD-style license that can be | 4 # Use of this source code is governed by a BSD-style license that can be |
| 5 # found in the LICENSE file. | 5 # found in the LICENSE file. |
| 6 | 6 |
| 7 import errno | 7 import errno |
| 8 import os | 8 import os |
| 9 import shutil | 9 import shutil |
| 10 import shlex |
| 10 import signal | 11 import signal |
| 11 import subprocess | 12 import subprocess |
| 12 import tempfile | 13 import tempfile |
| 13 import unittest | 14 import unittest |
| 14 import cros_build_lib | 15 import cros_build_lib |
| 15 import mox | 16 import mox |
| 16 | 17 |
| 17 | 18 |
| 18 class TestRunCommand(unittest.TestCase): | 19 class TestRunCommand(unittest.TestCase): |
| 19 | 20 |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 96 """--enter_chroot=False and --cmd is an array of strings. | 97 """--enter_chroot=False and --cmd is an array of strings. |
| 97 | 98 |
| 98 Parameterized so this can also be used by some other tests w/ alternate | 99 Parameterized so this can also be used by some other tests w/ alternate |
| 99 params to RunCommand(). | 100 params to RunCommand(). |
| 100 | 101 |
| 101 Args: | 102 Args: |
| 102 ignore_sigint: If True, we'll tell RunCommand to ignore sigint. | 103 ignore_sigint: If True, we'll tell RunCommand to ignore sigint. |
| 103 """ | 104 """ |
| 104 self.proc_mock.returncode = 0 | 105 self.proc_mock.returncode = 0 |
| 105 cmd_list = ['foo', 'bar', 'roger'] | 106 cmd_list = ['foo', 'bar', 'roger'] |
| 106 self._TestCmd(cmd_list, cmd_list, rc_kv=dict(exit_code=True, | 107 self._TestCmd(cmd_list, cmd_list, |
| 107 ignore_sigint=ignore_sigint)) | 108 rc_kv=dict(exit_code=True, ignore_sigint=ignore_sigint)) |
| 108 | 109 |
| 109 def testSignalRestoreNormalCase(self): | 110 def testSignalRestoreNormalCase(self): |
| 110 """Test RunCommand() properly sets/restores sigint. Normal case.""" | 111 """Test RunCommand() properly sets/restores sigint. Normal case.""" |
| 111 self.testReturnCodeZeroWithArrayCmd(ignore_sigint=True) | 112 self.testReturnCodeZeroWithArrayCmd(ignore_sigint=True) |
| 112 | 113 |
| 113 | 114 |
| 114 def testReturnCodeZeroWithArrayCmdEnterChroot(self): | 115 def testReturnCodeZeroWithArrayCmdEnterChroot(self): |
| 115 """--enter_chroot=True and --cmd is an array of strings.""" | 116 """--enter_chroot=True and --cmd is an array of strings.""" |
| 116 self.proc_mock.returncode = 0 | 117 self.proc_mock.returncode = 0 |
| 117 cmd_list = ['foo', 'bar', 'roger'] | 118 cmd_list = ['foo', 'bar', 'roger'] |
| 118 real_cmd = ['./enter_chroot.sh', '--'] + cmd_list | 119 real_cmd = ['./enter_chroot.sh', '--'] + cmd_list |
| 119 self._TestCmd(cmd_list, real_cmd, rc_kv=dict(enter_chroot=True)) | 120 self._TestCmd(cmd_list, real_cmd, rc_kv=dict(enter_chroot=True)) |
| 120 | 121 |
| 121 def testReturnCodeNotZeroErrorOkNotRaisesError(self): | 122 def testReturnCodeNotZeroErrorOkNotRaisesError(self): |
| 122 """Raise error when proc.communicate() returns non-zero.""" | 123 """Raise error when proc.communicate() returns non-zero.""" |
| 123 self.proc_mock.returncode = 1 | 124 self.proc_mock.returncode = 1 |
| 124 cmd = 'test cmd' | 125 cmd = 'test cmd' |
| 125 self._TestCmd(cmd, cmd, rc_kv=dict(error_ok=True)) | 126 real_cmd = [ '/bin/sh', '-c', cmd ] |
| 127 self._TestCmd(cmd, real_cmd, |
| 128 rc_kv=dict(error_ok=True, shell=True)) |
| 126 | 129 |
| 127 def testSubprocessCommunicateExceptionRaisesError(self, ignore_sigint=False): | 130 def testCommandFailureRaisesError(self, ignore_sigint=False): |
| 128 """Verify error raised by communicate() is caught. | 131 """Verify error raised by communicate() is caught. |
| 129 | 132 |
| 130 Parameterized so this can also be used by some other tests w/ alternate | 133 Parameterized so this can also be used by some other tests w/ alternate |
| 131 params to RunCommand(). | 134 params to RunCommand(). |
| 132 | 135 |
| 133 Args: | 136 Args: |
| 134 ignore_sigint: If True, we'll tell RunCommand to ignore sigint. | 137 ignore_sigint: If True, we'll tell RunCommand to ignore sigint. |
| 135 """ | 138 """ |
| 136 cmd = 'test cmd' | 139 cmd = 'test cmd' |
| 137 | 140 |
| 138 # If requested, RunCommand will ignore sigints; record that. | 141 # If requested, RunCommand will ignore sigints; record that. |
| 139 if ignore_sigint: | 142 if ignore_sigint: |
| 140 signal.signal(signal.SIGINT, signal.SIG_IGN).AndReturn(self._old_sigint) | 143 signal.signal(signal.SIGINT, signal.SIG_IGN).AndReturn(self._old_sigint) |
| 141 | 144 |
| 145 subprocess.Popen(['/bin/sh', '-c', cmd ], cwd=None, env=None, |
| 146 stdin=None, stdout=None, stderr=None, |
| 147 shell=False).AndReturn(self.proc_mock) |
| 148 self.proc_mock.communicate(None).AndReturn((self.output, self.error)) |
| 149 |
| 150 # If it ignored them, RunCommand will restore sigints; record that. |
| 151 if ignore_sigint: |
| 152 signal.signal(signal.SIGINT, self._old_sigint).AndReturn(signal.SIG_IGN) |
| 153 |
| 154 self.mox.ReplayAll() |
| 155 self.assertRaises(cros_build_lib.RunCommandError, |
| 156 cros_build_lib.RunCommand, cmd, shell=True, |
| 157 ignore_sigint=ignore_sigint, error_ok=False) |
| 158 self.mox.VerifyAll() |
| 159 |
| 160 def testSubprocessCommunicateExceptionRaisesError(self, ignore_sigint=False): |
| 161 """Verify error raised by communicate() is caught. |
| 162 |
| 163 Parameterized so this can also be used by some other tests w/ alternate |
| 164 params to RunCommand(). |
| 165 |
| 166 Args: |
| 167 ignore_sigint: If True, we'll tell RunCommand to ignore sigint. |
| 168 """ |
| 169 cmd = ['test', 'cmd'] |
| 170 |
| 171 # If requested, RunCommand will ignore sigints; record that. |
| 172 if ignore_sigint: |
| 173 signal.signal(signal.SIGINT, signal.SIG_IGN).AndReturn(self._old_sigint) |
| 174 |
| 142 subprocess.Popen(cmd, cwd=None, env=None, | 175 subprocess.Popen(cmd, cwd=None, env=None, |
| 143 stdin=None, stdout=None, stderr=None, | 176 stdin=None, stdout=None, stderr=None, |
| 144 shell=False).AndReturn(self.proc_mock) | 177 shell=False).AndReturn(self.proc_mock) |
| 145 self.proc_mock.communicate(None).AndRaise(ValueError) | 178 self.proc_mock.communicate(None).AndRaise(ValueError) |
| 146 | 179 |
| 147 # If it ignored them, RunCommand will restore sigints; record that. | 180 # If it ignored them, RunCommand will restore sigints; record that. |
| 148 if ignore_sigint: | 181 if ignore_sigint: |
| 149 signal.signal(signal.SIGINT, self._old_sigint).AndReturn(signal.SIG_IGN) | 182 signal.signal(signal.SIGINT, self._old_sigint).AndReturn(signal.SIG_IGN) |
| 150 | 183 |
| 151 self.mox.ReplayAll() | 184 self.mox.ReplayAll() |
| 152 self.assertRaises(ValueError, cros_build_lib.RunCommand, cmd, | 185 self.assertRaises(ValueError, cros_build_lib.RunCommand, cmd, |
| 153 ignore_sigint=ignore_sigint) | 186 ignore_sigint=ignore_sigint) |
| 154 self.mox.VerifyAll() | 187 self.mox.VerifyAll() |
| 155 | 188 |
| 156 def testSignalRestoreExceptionCase(self): | 189 def testSignalRestoreExceptionCase(self): |
| 157 """Test RunCommand() properly sets/restores sigint. Exception case.""" | 190 """Test RunCommand() properly sets/restores sigint. Exception case.""" |
| 158 self.testSubprocessCommunicateExceptionRaisesError(ignore_sigint=True) | 191 self.testSubprocessCommunicateExceptionRaisesError(ignore_sigint=True) |
| 159 | 192 |
| 160 def testSubprocessCommunicateExceptionNotRaisesError(self): | 193 def testSubprocessCommunicateExceptionNotRaisesError(self): |
| 161 """Don't re-raise error from communicate() when --error_ok=True.""" | 194 """Don't re-raise error from communicate() when --error_ok=True.""" |
| 162 cmd = 'test cmd' | 195 cmd = ['test', 'cmd'] |
| 163 real_cmd = './enter_chroot.sh -- %s' % cmd | 196 real_cmd = ['./enter_chroot.sh', '--'] + cmd |
| 164 expected_result = cros_build_lib.CommandResult() | 197 expected_result = cros_build_lib.CommandResult() |
| 165 expected_result.cmd = real_cmd | 198 expected_result.cmd = real_cmd |
| 166 | 199 |
| 167 subprocess.Popen(real_cmd, cwd=None, env=None, | 200 subprocess.Popen(real_cmd, cwd=None, env=None, |
| 168 stdin=None, stdout=None, stderr=None, | 201 stdin=None, stdout=None, stderr=None, |
| 169 shell=False).AndReturn(self.proc_mock) | 202 shell=False).AndReturn(self.proc_mock) |
| 170 self.proc_mock.communicate(None).AndRaise(ValueError) | 203 self.proc_mock.communicate(None).AndRaise(ValueError) |
| 171 | 204 |
| 172 self.mox.ReplayAll() | 205 self.mox.ReplayAll() |
| 173 actual_result = cros_build_lib.RunCommand(cmd, error_ok=True, | 206 actual_result = cros_build_lib.RunCommand(cmd, error_ok=True, |
| (...skipping 11 matching lines...) Expand all Loading... |
| 185 # This is a simple case, copied from testReturnCodeZeroWithArrayCmd() | 218 # This is a simple case, copied from testReturnCodeZeroWithArrayCmd() |
| 186 self.proc_mock.returncode = 0 | 219 self.proc_mock.returncode = 0 |
| 187 cmd_list = ['foo', 'bar', 'roger'] | 220 cmd_list = ['foo', 'bar', 'roger'] |
| 188 | 221 |
| 189 # Run. We expect the env= to be passed through from sp (subprocess.Popen) | 222 # Run. We expect the env= to be passed through from sp (subprocess.Popen) |
| 190 # to rc (RunCommand). | 223 # to rc (RunCommand). |
| 191 self._TestCmd(cmd_list, cmd_list, | 224 self._TestCmd(cmd_list, cmd_list, |
| 192 sp_kv=dict(env=env), | 225 sp_kv=dict(env=env), |
| 193 rc_kv=dict(env=env, exit_code=True)) | 226 rc_kv=dict(env=env, exit_code=True)) |
| 194 | 227 |
| 228 def testExtraEnvOnlyWorks(self): |
| 229 """Test RunCommand(..., extra_env=xyz) works.""" |
| 230 # We'll put this bogus environment together, just to make sure |
| 231 # subprocess.Popen gets passed it. |
| 232 extra_env = {'Pinky' : 'Brain'} |
| 233 ## This is a little bit circular, since the same logic is used to compute |
| 234 ## the value inside, but at least it checks that this happens. |
| 235 total_env = os.environ.copy() |
| 236 total_env.update(extra_env) |
| 237 |
| 238 # This is a simple case, copied from testReturnCodeZeroWithArrayCmd() |
| 239 self.proc_mock.returncode = 0 |
| 240 cmd_list = ['foo', 'bar', 'roger'] |
| 241 |
| 242 # Run. We expect the env= to be passed through from sp (subprocess.Popen) |
| 243 # to rc (RunCommand). |
| 244 self._TestCmd(cmd_list, cmd_list, |
| 245 sp_kv=dict(env=total_env), |
| 246 rc_kv=dict(extra_env=extra_env, exit_code=True)) |
| 247 |
| 248 def testExtraEnvTooWorks(self): |
| 249 """Test RunCommand(..., env=xy, extra_env=z) works.""" |
| 250 # We'll put this bogus environment together, just to make sure |
| 251 # subprocess.Popen gets passed it. |
| 252 env = {'Tom': 'Jerry', 'Itchy': 'Scratchy'} |
| 253 extra_env = {'Pinky': 'Brain'} |
| 254 total_env = {'Tom': 'Jerry', 'Itchy': 'Scratchy', 'Pinky': 'Brain'} |
| 255 |
| 256 # This is a simple case, copied from testReturnCodeZeroWithArrayCmd() |
| 257 self.proc_mock.returncode = 0 |
| 258 cmd_list = ['foo', 'bar', 'roger'] |
| 259 |
| 260 # Run. We expect the env= to be passed through from sp (subprocess.Popen) |
| 261 # to rc (RunCommand). |
| 262 self._TestCmd(cmd_list, cmd_list, |
| 263 sp_kv=dict(env=total_env), |
| 264 rc_kv=dict(env=env, extra_env=extra_env, exit_code=True)) |
| 265 |
| 266 |
| 195 | 267 |
| 196 def testExceptionEquality(self): | 268 def testExceptionEquality(self): |
| 197 """Verify equality methods for RunCommandError""" | 269 """Verify equality methods for RunCommandError""" |
| 198 | 270 |
| 199 e1 = cros_build_lib.RunCommandError('Message 1', ['ls', 'arg']) | 271 e1 = cros_build_lib.RunCommandError('Message 1', ['ls', 'arg']) |
| 200 e2 = cros_build_lib.RunCommandError('Message 1', ['ls', 'arg']) | 272 e2 = cros_build_lib.RunCommandError('Message 1', ['ls', 'arg']) |
| 201 e_diff_msg = cros_build_lib.RunCommandError('Message 2', ['ls', 'arg']) | 273 e_diff_msg = cros_build_lib.RunCommandError('Message 2', ['ls', 'arg']) |
| 202 e_diff_cmd = cros_build_lib.RunCommandError('Message 1', ['ls', 'arg1']) | 274 e_diff_cmd = cros_build_lib.RunCommandError('Message 1', ['ls', 'arg1']) |
| 203 | 275 |
| 204 self.assertTrue(e1 == e2) | 276 self.assertTrue(e1 == e2) |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 334 | 406 |
| 335 def testGetChromeosVersionWithEmptyInputReturnsDefault(self): | 407 def testGetChromeosVersionWithEmptyInputReturnsDefault(self): |
| 336 self._TestChromeosVersion('') | 408 self._TestChromeosVersion('') |
| 337 | 409 |
| 338 def testGetChromeosVersionWithNoneInputReturnsDefault(self): | 410 def testGetChromeosVersionWithNoneInputReturnsDefault(self): |
| 339 self._TestChromeosVersion(None) | 411 self._TestChromeosVersion(None) |
| 340 | 412 |
| 341 | 413 |
| 342 if __name__ == '__main__': | 414 if __name__ == '__main__': |
| 343 unittest.main() | 415 unittest.main() |
| OLD | NEW |