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 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
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 = [ 'sh', '-c', cmd ] |
| 127 self._TestCmd(cmd, real_cmd, rc_kv=dict(error_ok=True)) |
126 | 128 |
127 def testSubprocessCommunicateExceptionRaisesError(self, ignore_sigint=False): | 129 def testCommandFailureRaisesError(self, ignore_sigint=False): |
128 """Verify error raised by communicate() is caught. | 130 """Verify error raised by communicate() is caught. |
129 | 131 |
130 Parameterized so this can also be used by some other tests w/ alternate | 132 Parameterized so this can also be used by some other tests w/ alternate |
131 params to RunCommand(). | 133 params to RunCommand(). |
132 | 134 |
133 Args: | 135 Args: |
134 ignore_sigint: If True, we'll tell RunCommand to ignore sigint. | 136 ignore_sigint: If True, we'll tell RunCommand to ignore sigint. |
135 """ | 137 """ |
136 cmd = 'test cmd' | 138 cmd = 'test cmd' |
137 | 139 |
138 # If requested, RunCommand will ignore sigints; record that. | 140 # If requested, RunCommand will ignore sigints; record that. |
139 if ignore_sigint: | 141 if ignore_sigint: |
140 signal.signal(signal.SIGINT, signal.SIG_IGN).AndReturn(self._old_sigint) | 142 signal.signal(signal.SIGINT, signal.SIG_IGN).AndReturn(self._old_sigint) |
141 | 143 |
| 144 subprocess.Popen(['sh', '-c', cmd ], cwd=None, env=None, |
| 145 stdin=None, stdout=None, stderr=None, |
| 146 shell=False).AndReturn(self.proc_mock) |
| 147 self.proc_mock.communicate(None).AndReturn((self.output, self.error)) |
| 148 |
| 149 # If it ignored them, RunCommand will restore sigints; record that. |
| 150 if ignore_sigint: |
| 151 signal.signal(signal.SIGINT, self._old_sigint).AndReturn(signal.SIG_IGN) |
| 152 |
| 153 self.mox.ReplayAll() |
| 154 self.assertRaises(cros_build_lib.RunCommandError, |
| 155 cros_build_lib.RunCommand, cmd, |
| 156 ignore_sigint=ignore_sigint, error_ok=False) |
| 157 self.mox.VerifyAll() |
| 158 |
| 159 def testSubprocessCommunicateExceptionRaisesError(self, ignore_sigint=False): |
| 160 """Verify error raised by communicate() is caught. |
| 161 |
| 162 Parameterized so this can also be used by some other tests w/ alternate |
| 163 params to RunCommand(). |
| 164 |
| 165 Args: |
| 166 ignore_sigint: If True, we'll tell RunCommand to ignore sigint. |
| 167 """ |
| 168 cmd = ['test', 'cmd'] |
| 169 |
| 170 # If requested, RunCommand will ignore sigints; record that. |
| 171 if ignore_sigint: |
| 172 signal.signal(signal.SIGINT, signal.SIG_IGN).AndReturn(self._old_sigint) |
| 173 |
142 subprocess.Popen(cmd, cwd=None, env=None, | 174 subprocess.Popen(cmd, cwd=None, env=None, |
143 stdin=None, stdout=None, stderr=None, | 175 stdin=None, stdout=None, stderr=None, |
144 shell=False).AndReturn(self.proc_mock) | 176 shell=False).AndReturn(self.proc_mock) |
145 self.proc_mock.communicate(None).AndRaise(ValueError) | 177 self.proc_mock.communicate(None).AndRaise(ValueError) |
146 | 178 |
147 # If it ignored them, RunCommand will restore sigints; record that. | 179 # If it ignored them, RunCommand will restore sigints; record that. |
148 if ignore_sigint: | 180 if ignore_sigint: |
149 signal.signal(signal.SIGINT, self._old_sigint).AndReturn(signal.SIG_IGN) | 181 signal.signal(signal.SIGINT, self._old_sigint).AndReturn(signal.SIG_IGN) |
150 | 182 |
151 self.mox.ReplayAll() | 183 self.mox.ReplayAll() |
152 self.assertRaises(ValueError, cros_build_lib.RunCommand, cmd, | 184 self.assertRaises(ValueError, cros_build_lib.RunCommand, cmd, |
153 ignore_sigint=ignore_sigint) | 185 ignore_sigint=ignore_sigint) |
154 self.mox.VerifyAll() | 186 self.mox.VerifyAll() |
155 | 187 |
156 def testSignalRestoreExceptionCase(self): | 188 def testSignalRestoreExceptionCase(self): |
157 """Test RunCommand() properly sets/restores sigint. Exception case.""" | 189 """Test RunCommand() properly sets/restores sigint. Exception case.""" |
158 self.testSubprocessCommunicateExceptionRaisesError(ignore_sigint=True) | 190 self.testSubprocessCommunicateExceptionRaisesError(ignore_sigint=True) |
159 | 191 |
160 def testSubprocessCommunicateExceptionNotRaisesError(self): | 192 def testSubprocessCommunicateExceptionNotRaisesError(self): |
161 """Don't re-raise error from communicate() when --error_ok=True.""" | 193 """Don't re-raise error from communicate() when --error_ok=True.""" |
162 cmd = 'test cmd' | 194 cmd = ['test', 'cmd'] |
163 real_cmd = './enter_chroot.sh -- %s' % cmd | 195 real_cmd = ['./enter_chroot.sh', '--'] + cmd |
164 expected_result = cros_build_lib.CommandResult() | 196 expected_result = cros_build_lib.CommandResult() |
165 expected_result.cmd = real_cmd | 197 expected_result.cmd = real_cmd |
166 | 198 |
167 subprocess.Popen(real_cmd, cwd=None, env=None, | 199 subprocess.Popen(real_cmd, cwd=None, env=None, |
168 stdin=None, stdout=None, stderr=None, | 200 stdin=None, stdout=None, stderr=None, |
169 shell=False).AndReturn(self.proc_mock) | 201 shell=False).AndReturn(self.proc_mock) |
170 self.proc_mock.communicate(None).AndRaise(ValueError) | 202 self.proc_mock.communicate(None).AndRaise(ValueError) |
171 | 203 |
172 self.mox.ReplayAll() | 204 self.mox.ReplayAll() |
173 actual_result = cros_build_lib.RunCommand(cmd, error_ok=True, | 205 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() | 217 # This is a simple case, copied from testReturnCodeZeroWithArrayCmd() |
186 self.proc_mock.returncode = 0 | 218 self.proc_mock.returncode = 0 |
187 cmd_list = ['foo', 'bar', 'roger'] | 219 cmd_list = ['foo', 'bar', 'roger'] |
188 | 220 |
189 # Run. We expect the env= to be passed through from sp (subprocess.Popen) | 221 # Run. We expect the env= to be passed through from sp (subprocess.Popen) |
190 # to rc (RunCommand). | 222 # to rc (RunCommand). |
191 self._TestCmd(cmd_list, cmd_list, | 223 self._TestCmd(cmd_list, cmd_list, |
192 sp_kv=dict(env=env), | 224 sp_kv=dict(env=env), |
193 rc_kv=dict(env=env, exit_code=True)) | 225 rc_kv=dict(env=env, exit_code=True)) |
194 | 226 |
| 227 def testExtraEnvOnlyWorks(self): |
| 228 """Test RunCommand(..., extra_env=xyz) works.""" |
| 229 # We'll put this bogus environment together, just to make sure |
| 230 # subprocess.Popen gets passed it. |
| 231 extra_env = {'Pinky' : 'Brain'} |
| 232 ## This is a little bit circular, since the same logic is used to compute |
| 233 ## the value inside, but at least it checks that this happens. |
| 234 total_env = os.environ.copy() |
| 235 total_env.update(extra_env) |
| 236 |
| 237 # This is a simple case, copied from testReturnCodeZeroWithArrayCmd() |
| 238 self.proc_mock.returncode = 0 |
| 239 cmd_list = ['foo', 'bar', 'roger'] |
| 240 |
| 241 # Run. We expect the env= to be passed through from sp (subprocess.Popen) |
| 242 # to rc (RunCommand). |
| 243 self._TestCmd(cmd_list, cmd_list, |
| 244 sp_kv=dict(env=total_env), |
| 245 rc_kv=dict(extra_env=extra_env, exit_code=True)) |
| 246 |
| 247 def testExtraEnvTooWorks(self): |
| 248 """Test RunCommand(..., env=xy, extra_env=z) works.""" |
| 249 # We'll put this bogus environment together, just to make sure |
| 250 # subprocess.Popen gets passed it. |
| 251 env = {'Tom': 'Jerry', 'Itchy': 'Scratchy'} |
| 252 extra_env = {'Pinky': 'Brain'} |
| 253 total_env = {'Tom': 'Jerry', 'Itchy': 'Scratchy', 'Pinky': 'Brain'} |
| 254 |
| 255 # This is a simple case, copied from testReturnCodeZeroWithArrayCmd() |
| 256 self.proc_mock.returncode = 0 |
| 257 cmd_list = ['foo', 'bar', 'roger'] |
| 258 |
| 259 # Run. We expect the env= to be passed through from sp (subprocess.Popen) |
| 260 # to rc (RunCommand). |
| 261 self._TestCmd(cmd_list, cmd_list, |
| 262 sp_kv=dict(env=total_env), |
| 263 rc_kv=dict(env=env, extra_env=extra_env, exit_code=True)) |
| 264 |
| 265 |
195 | 266 |
196 def testExceptionEquality(self): | 267 def testExceptionEquality(self): |
197 """Verify equality methods for RunCommandError""" | 268 """Verify equality methods for RunCommandError""" |
198 | 269 |
199 e1 = cros_build_lib.RunCommandError('Message 1', ['ls', 'arg']) | 270 e1 = cros_build_lib.RunCommandError('Message 1', ['ls', 'arg']) |
200 e2 = cros_build_lib.RunCommandError('Message 1', ['ls', 'arg']) | 271 e2 = cros_build_lib.RunCommandError('Message 1', ['ls', 'arg']) |
201 e_diff_msg = cros_build_lib.RunCommandError('Message 2', ['ls', 'arg']) | 272 e_diff_msg = cros_build_lib.RunCommandError('Message 2', ['ls', 'arg']) |
202 e_diff_cmd = cros_build_lib.RunCommandError('Message 1', ['ls', 'arg1']) | 273 e_diff_cmd = cros_build_lib.RunCommandError('Message 1', ['ls', 'arg1']) |
203 | 274 |
204 self.assertTrue(e1 == e2) | 275 self.assertTrue(e1 == e2) |
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
334 | 405 |
335 def testGetChromeosVersionWithEmptyInputReturnsDefault(self): | 406 def testGetChromeosVersionWithEmptyInputReturnsDefault(self): |
336 self._TestChromeosVersion('') | 407 self._TestChromeosVersion('') |
337 | 408 |
338 def testGetChromeosVersionWithNoneInputReturnsDefault(self): | 409 def testGetChromeosVersionWithNoneInputReturnsDefault(self): |
339 self._TestChromeosVersion(None) | 410 self._TestChromeosVersion(None) |
340 | 411 |
341 | 412 |
342 if __name__ == '__main__': | 413 if __name__ == '__main__': |
343 unittest.main() | 414 unittest.main() |
OLD | NEW |