blob: d9321797b0398396813184601aaed800198710d4 [file] [log] [blame]
[email protected]eba40222011-04-05 14:52:481#!/usr/bin/env python
2# Copyright (c) 2011 The Chromium Authors. All rights reserved.
3# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5
6"""Unit tests for subprocess2.py."""
7
[email protected]4942e4a2011-11-15 15:50:508import logging
[email protected]eba40222011-04-05 14:52:489import optparse
10import os
11import sys
12import time
13import unittest
14
[email protected]4942e4a2011-11-15 15:50:5015try:
16 import fcntl
17except ImportError:
18 fcntl = None
19
[email protected]428342a2011-11-10 15:46:3320sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
[email protected]eba40222011-04-05 14:52:4821
[email protected]db59bfc2011-11-30 14:03:1422import subprocess
[email protected]eba40222011-04-05 14:52:4823import subprocess2
24
[email protected]7bb06bb2011-11-29 15:22:0625from testing_support import auto_stub
26
[email protected]4942e4a2011-11-15 15:50:5027# Method could be a function
28# pylint: disable=R0201
29
30
[email protected]a8e81632011-12-01 00:35:2431# Create aliases for subprocess2 specific tests. They shouldn't be used for
32# regression tests.
33TIMED_OUT = subprocess2.TIMED_OUT
34VOID = subprocess2.VOID
35PIPE = subprocess2.PIPE
36STDOUT = subprocess2.STDOUT
37
38
[email protected]4942e4a2011-11-15 15:50:5039def convert_to_crlf(string):
40 """Unconditionally convert LF to CRLF."""
41 return string.replace('\n', '\r\n')
42
43
44def convert_to_cr(string):
45 """Unconditionally convert LF to CR."""
46 return string.replace('\n', '\r')
47
48
49def convert_win(string):
50 """Converts string to CRLF on Windows only."""
51 if sys.platform == 'win32':
52 return string.replace('\n', '\r\n')
53 return string
54
55
[email protected]7bb06bb2011-11-29 15:22:0656class DefaultsTest(auto_stub.TestCase):
57 # TODO(maruel): Do a reopen() on sys.__stdout__ and sys.__stderr__ so they
58 # can be trapped in the child process for better coverage.
59 def _fake_communicate(self):
[email protected]ef77f9e2011-11-24 15:24:0260 """Mocks subprocess2.communicate()."""
[email protected]eba40222011-04-05 14:52:4861 results = {}
[email protected]1f063db2011-04-18 19:04:5262 def fake_communicate(args, **kwargs):
[email protected]f08b09c2011-04-06 13:14:2763 assert not results
[email protected]eba40222011-04-05 14:52:4864 results.update(kwargs)
65 results['args'] = args
[email protected]ef77f9e2011-11-24 15:24:0266 return ('stdout', 'stderr'), 0
[email protected]7bb06bb2011-11-29 15:22:0667 self.mock(subprocess2, 'communicate', fake_communicate)
[email protected]eba40222011-04-05 14:52:4868 return results
69
[email protected]7bb06bb2011-11-29 15:22:0670 def _fake_Popen(self):
[email protected]ef77f9e2011-11-24 15:24:0271 """Mocks the whole subprocess2.Popen class."""
[email protected]f08b09c2011-04-06 13:14:2772 results = {}
73 class fake_Popen(object):
74 returncode = -8
75 def __init__(self, args, **kwargs):
76 assert not results
77 results.update(kwargs)
78 results['args'] = args
[email protected]428342a2011-11-10 15:46:3379 @staticmethod
[email protected]94c712f2011-12-01 15:04:5780 def communicate(input=None, timeout=None): # pylint: disable=W0622
[email protected]f08b09c2011-04-06 13:14:2781 return None, None
[email protected]7bb06bb2011-11-29 15:22:0682 self.mock(subprocess2, 'Popen', fake_Popen)
[email protected]f08b09c2011-04-06 13:14:2783 return results
84
[email protected]7bb06bb2011-11-29 15:22:0685 def _fake_subprocess_Popen(self):
[email protected]ef77f9e2011-11-24 15:24:0286 """Mocks the base class subprocess.Popen only."""
[email protected]f08b09c2011-04-06 13:14:2787 results = {}
[email protected]ef77f9e2011-11-24 15:24:0288 def __init__(self, args, **kwargs):
89 assert not results
90 results.update(kwargs)
91 results['args'] = args
92 def communicate():
93 return None, None
[email protected]db59bfc2011-11-30 14:03:1494 self.mock(subprocess.Popen, '__init__', __init__)
95 self.mock(subprocess.Popen, 'communicate', communicate)
[email protected]f08b09c2011-04-06 13:14:2796 return results
97
[email protected]eba40222011-04-05 14:52:4898 def test_check_call_defaults(self):
[email protected]1f063db2011-04-18 19:04:5299 results = self._fake_communicate()
[email protected]eba40222011-04-05 14:52:48100 self.assertEquals(
[email protected]ef77f9e2011-11-24 15:24:02101 ('stdout', 'stderr'), subprocess2.check_call_out(['foo'], a=True))
[email protected]eba40222011-04-05 14:52:48102 expected = {
103 'args': ['foo'],
104 'a':True,
105 }
106 self.assertEquals(expected, results)
107
[email protected]87e6d332011-09-09 19:01:28108 def test_capture_defaults(self):
109 results = self._fake_communicate()
110 self.assertEquals(
111 'stdout', subprocess2.capture(['foo'], a=True))
112 expected = {
113 'args': ['foo'],
114 'a':True,
115 'stdin': subprocess2.VOID,
116 'stdout': subprocess2.PIPE,
117 }
118 self.assertEquals(expected, results)
119
[email protected]1f063db2011-04-18 19:04:52120 def test_communicate_defaults(self):
[email protected]f08b09c2011-04-06 13:14:27121 results = self._fake_Popen()
[email protected]1f063db2011-04-18 19:04:52122 self.assertEquals(
123 ((None, None), -8), subprocess2.communicate(['foo'], a=True))
[email protected]f08b09c2011-04-06 13:14:27124 expected = {
125 'args': ['foo'],
126 'a': True,
127 }
128 self.assertEquals(expected, results)
129
130 def test_Popen_defaults(self):
131 results = self._fake_subprocess_Popen()
132 proc = subprocess2.Popen(['foo'], a=True)
[email protected]ef77f9e2011-11-24 15:24:02133 # Cleanup code in subprocess.py needs this member to be set.
134 # pylint: disable=W0201
135 proc._child_created = None
[email protected]f08b09c2011-04-06 13:14:27136 expected = {
137 'args': ['foo'],
138 'a': True,
139 'shell': bool(sys.platform=='win32'),
[email protected]f08b09c2011-04-06 13:14:27140 }
[email protected]c98c0c52011-04-06 13:39:43141 if sys.platform != 'win32':
142 env = os.environ.copy()
143 is_english = lambda name: env.get(name, 'en').startswith('en')
144 if not is_english('LANG'):
145 env['LANG'] = 'en_US.UTF-8'
146 expected['env'] = env
147 if not is_english('LANGUAGE'):
148 env['LANGUAGE'] = 'en_US.UTF-8'
149 expected['env'] = env
[email protected]f08b09c2011-04-06 13:14:27150 self.assertEquals(expected, results)
[email protected]dd9837f2011-11-30 01:55:22151 self.assertTrue(time.time() >= proc.start)
[email protected]f08b09c2011-04-06 13:14:27152
[email protected]eba40222011-04-05 14:52:48153 def test_check_output_defaults(self):
[email protected]1f063db2011-04-18 19:04:52154 results = self._fake_communicate()
[email protected]eba40222011-04-05 14:52:48155 # It's discarding 'stderr' because it assumes stderr=subprocess2.STDOUT but
[email protected]1f063db2011-04-18 19:04:52156 # fake_communicate() doesn't 'implement' that.
[email protected]eba40222011-04-05 14:52:48157 self.assertEquals('stdout', subprocess2.check_output(['foo'], a=True))
158 expected = {
159 'args': ['foo'],
160 'a':True,
[email protected]4a982272011-04-12 20:49:37161 'stdin': subprocess2.VOID,
[email protected]eba40222011-04-05 14:52:48162 'stdout': subprocess2.PIPE,
[email protected]eba40222011-04-05 14:52:48163 }
164 self.assertEquals(expected, results)
165
[email protected]4942e4a2011-11-15 15:50:50166
[email protected]db59bfc2011-11-30 14:03:14167class BaseTestCase(unittest.TestCase):
[email protected]4942e4a2011-11-15 15:50:50168 def setUp(self):
[email protected]db59bfc2011-11-30 14:03:14169 super(BaseTestCase, self).setUp()
[email protected]4942e4a2011-11-15 15:50:50170 self.exe_path = __file__
171 self.exe = [sys.executable, self.exe_path, '--child']
172 self.states = {}
173 if fcntl:
174 for v in (sys.stdin, sys.stdout, sys.stderr):
175 fileno = v.fileno()
176 self.states[fileno] = fcntl.fcntl(fileno, fcntl.F_GETFL)
177
178 def tearDown(self):
179 for fileno, fl in self.states.iteritems():
180 self.assertEquals(fl, fcntl.fcntl(fileno, fcntl.F_GETFL))
[email protected]db59bfc2011-11-30 14:03:14181 super(BaseTestCase, self).tearDown()
[email protected]4942e4a2011-11-15 15:50:50182
[email protected]94c712f2011-12-01 15:04:57183 def _check_res(self, res, stdout, stderr, returncode):
184 (out, err), code = res
185 self.assertEquals(stdout, out)
186 self.assertEquals(stderr, err)
187 self.assertEquals(returncode, code)
188
[email protected]db59bfc2011-11-30 14:03:14189
190class RegressionTest(BaseTestCase):
191 # Regression tests to ensure that subprocess and subprocess2 have the same
192 # behavior.
193 def _run_test(self, function):
194 """Runs tests in 12 combinations:
195 - LF output with universal_newlines=False
196 - CR output with universal_newlines=False
197 - CRLF output with universal_newlines=False
198 - LF output with universal_newlines=True
199 - CR output with universal_newlines=True
200 - CRLF output with universal_newlines=True
201
202 Once with subprocess, once with subprocess2.
203
204 First |function| argument is the conversion for the original expected LF
205 string to the right EOL.
206 Second |function| argument is the executable and initial flag to run, to
207 control what EOL is used by the child process.
208 Third |function| argument is universal_newlines value.
209 """
210 noop = lambda x: x
211 for subp in (subprocess, subprocess2):
212 function(noop, self.exe, False, subp)
213 function(convert_to_cr, self.exe + ['--cr'], False, subp)
214 function(convert_to_crlf, self.exe + ['--crlf'], False, subp)
215 function(noop, self.exe, True, subp)
216 function(noop, self.exe + ['--cr'], True, subp)
217 function(noop, self.exe + ['--crlf'], True, subp)
218
[email protected]a8e81632011-12-01 00:35:24219 def _check_exception(self, subp, e, stdout, stderr, returncode):
[email protected]db59bfc2011-11-30 14:03:14220 """On exception, look if the exception members are set correctly."""
[email protected]a8e81632011-12-01 00:35:24221 self.assertEquals(returncode, e.returncode)
[email protected]db59bfc2011-11-30 14:03:14222 if subp is subprocess:
223 # subprocess never save the output.
224 self.assertFalse(hasattr(e, 'stdout'))
225 self.assertFalse(hasattr(e, 'stderr'))
226 elif subp is subprocess2:
227 self.assertEquals(stdout, e.stdout)
228 self.assertEquals(stderr, e.stderr)
229 else:
230 self.fail()
231
232 def test_check_output_no_stdout(self):
233 try:
234 subprocess2.check_output(self.exe, stdout=subprocess2.PIPE)
235 self.fail()
236 except ValueError:
237 pass
238
239 if (sys.version_info[0] * 10 + sys.version_info[1]) >= 27:
240 # python 2.7+
241 try:
242 # pylint: disable=E1101
243 subprocess.check_output(self.exe, stdout=subprocess.PIPE)
244 self.fail()
245 except ValueError:
246 pass
247
248 def test_check_output_throw_stdout(self):
249 def fn(c, e, un, subp):
250 if not hasattr(subp, 'check_output'):
251 return
252 try:
253 subp.check_output(
254 e + ['--fail', '--stdout'], universal_newlines=un)
255 self.fail()
256 except subp.CalledProcessError, e:
[email protected]a8e81632011-12-01 00:35:24257 self._check_exception(subp, e, c('A\nBB\nCCC\n'), None, 64)
[email protected]db59bfc2011-11-30 14:03:14258 self._run_test(fn)
259
260 def test_check_output_throw_no_stderr(self):
261 def fn(c, e, un, subp):
262 if not hasattr(subp, 'check_output'):
263 return
264 try:
265 subp.check_output(
266 e + ['--fail', '--stderr'], universal_newlines=un)
267 self.fail()
268 except subp.CalledProcessError, e:
[email protected]a8e81632011-12-01 00:35:24269 self._check_exception(subp, e, c(''), None, 64)
[email protected]db59bfc2011-11-30 14:03:14270 self._run_test(fn)
271
272 def test_check_output_throw_stderr(self):
273 def fn(c, e, un, subp):
274 if not hasattr(subp, 'check_output'):
275 return
276 try:
277 subp.check_output(
278 e + ['--fail', '--stderr'],
279 stderr=subp.PIPE,
280 universal_newlines=un)
281 self.fail()
282 except subp.CalledProcessError, e:
[email protected]a8e81632011-12-01 00:35:24283 self._check_exception(subp, e, '', c('a\nbb\nccc\n'), 64)
[email protected]db59bfc2011-11-30 14:03:14284 self._run_test(fn)
285
286 def test_check_output_throw_stderr_stdout(self):
287 def fn(c, e, un, subp):
288 if not hasattr(subp, 'check_output'):
289 return
290 try:
291 subp.check_output(
292 e + ['--fail', '--stderr'],
293 stderr=subp.STDOUT,
294 universal_newlines=un)
295 self.fail()
296 except subp.CalledProcessError, e:
[email protected]a8e81632011-12-01 00:35:24297 self._check_exception(subp, e, c('a\nbb\nccc\n'), None, 64)
[email protected]db59bfc2011-11-30 14:03:14298 self._run_test(fn)
299
300 def test_check_call_throw(self):
301 for subp in (subprocess, subprocess2):
302 try:
303 subp.check_call(self.exe + ['--fail', '--stderr'])
304 self.fail()
305 except subp.CalledProcessError, e:
[email protected]a8e81632011-12-01 00:35:24306 self._check_exception(subp, e, None, None, 64)
[email protected]db59bfc2011-11-30 14:03:14307
[email protected]94c712f2011-12-01 15:04:57308 def test_redirect_stderr_to_stdout_pipe(self):
309 def fn(c, e, un, subp):
310 # stderr output into stdout.
311 proc = subp.Popen(
312 e + ['--stderr'],
313 stdout=subp.PIPE,
314 stderr=subp.STDOUT,
315 universal_newlines=un)
316 res = proc.communicate(), proc.returncode
317 self._check_res(res, c('a\nbb\nccc\n'), None, 0)
318 self._run_test(fn)
319
320 def test_redirect_stderr_to_stdout(self):
321 def fn(c, e, un, subp):
322 # stderr output into stdout but stdout is not piped.
323 proc = subp.Popen(
324 e + ['--stderr'], stderr=STDOUT, universal_newlines=un)
325 res = proc.communicate(), proc.returncode
326 self._check_res(res, None, None, 0)
327 self._run_test(fn)
328
[email protected]db59bfc2011-11-30 14:03:14329
330class S2Test(BaseTestCase):
331 # Tests that can only run in subprocess2, e.g. new functionalities.
332 # In particular, subprocess2.communicate() doesn't exist in subprocess.
[email protected]4942e4a2011-11-15 15:50:50333 def _run_test(self, function):
334 """Runs tests in 6 combinations:
335 - LF output with universal_newlines=False
336 - CR output with universal_newlines=False
337 - CRLF output with universal_newlines=False
338 - LF output with universal_newlines=True
339 - CR output with universal_newlines=True
340 - CRLF output with universal_newlines=True
341
342 First |function| argument is the convertion for the origianl expected LF
343 string to the right EOL.
344 Second |function| argument is the executable and initial flag to run, to
345 control what EOL is used by the child process.
346 Third |function| argument is universal_newlines value.
347 """
348 noop = lambda x: x
349 function(noop, self.exe, False)
350 function(convert_to_cr, self.exe + ['--cr'], False)
351 function(convert_to_crlf, self.exe + ['--crlf'], False)
352 function(noop, self.exe, True)
353 function(noop, self.exe + ['--cr'], True)
354 function(noop, self.exe + ['--crlf'], True)
355
[email protected]94c712f2011-12-01 15:04:57356 def _check_exception(self, e, stdout, stderr, returncode):
357 """On exception, look if the exception members are set correctly."""
358 self.assertEquals(returncode, e.returncode)
359 self.assertEquals(stdout, e.stdout)
360 self.assertEquals(stderr, e.stderr)
[email protected]a8e81632011-12-01 00:35:24361
[email protected]f2dca4e2011-11-09 19:24:48362 def test_timeout(self):
[email protected]db59bfc2011-11-30 14:03:14363 # timeout doesn't exist in subprocess.
364 def fn(c, e, un):
[email protected]a8e81632011-12-01 00:35:24365 res = subprocess2.communicate(
[email protected]db59bfc2011-11-30 14:03:14366 self.exe + ['--sleep_first', '--stdout'],
367 timeout=0.01,
[email protected]a8e81632011-12-01 00:35:24368 stdout=PIPE,
[email protected]db59bfc2011-11-30 14:03:14369 shell=False)
[email protected]a8e81632011-12-01 00:35:24370 self._check_res(res, '', None, TIMED_OUT)
371 self._run_test(fn)
372
373 def test_timeout_shell_throws(self):
374 def fn(c, e, un):
375 try:
376 # With shell=True, it needs a string.
377 subprocess2.communicate(' '.join(self.exe), timeout=0.01, shell=True)
378 self.fail()
379 except TypeError:
380 pass
[email protected]db59bfc2011-11-30 14:03:14381 self._run_test(fn)
[email protected]87e6d332011-09-09 19:01:28382
[email protected]bc3a53c2011-12-05 23:38:19383 def test_stdin(self):
384 def fn(c, e, un):
385 stdin = '0123456789'
386 res = subprocess2.communicate(
387 e + ['--read'],
388 stdin=stdin,
389 universal_newlines=un)
390 self._check_res(res, None, None, 10)
391 self._run_test(fn)
392
393 def test_stdin_unicode(self):
394 def fn(c, e, un):
395 stdin = u'0123456789'
396 res = subprocess2.communicate(
397 e + ['--read'],
398 stdin=stdin,
399 universal_newlines=un)
400 self._check_res(res, None, None, 10)
401 self._run_test(fn)
402
[email protected]740a6c02011-12-05 23:46:44403 def test_stdin_empty(self):
404 def fn(c, e, un):
405 stdin = ''
406 res = subprocess2.communicate(
407 e + ['--read'],
408 stdin=stdin,
409 universal_newlines=un)
410 self._check_res(res, None, None, 0)
411 self._run_test(fn)
412
[email protected]bc3a53c2011-12-05 23:38:19413 def test_stdin_void(self):
414 res = subprocess2.communicate(self.exe + ['--read'], stdin=VOID)
415 self._check_res(res, None, None, 0)
416
417 def test_stdin_void_stdout_timeout(self):
418 # Make sure a mix of VOID, PIPE and timeout works.
419 def fn(c, e, un):
420 res = subprocess2.communicate(
421 e + ['--stdout', '--read'],
422 stdin=VOID,
423 stdout=PIPE,
424 timeout=10,
425 universal_newlines=un)
426 self._check_res(res, c('A\nBB\nCCC\n'), None, 0)
427 self._run_test(fn)
428
[email protected]87e6d332011-09-09 19:01:28429 def test_stdout_void(self):
[email protected]4942e4a2011-11-15 15:50:50430 def fn(c, e, un):
[email protected]a8e81632011-12-01 00:35:24431 res = subprocess2.communicate(
[email protected]4942e4a2011-11-15 15:50:50432 e + ['--stdout', '--stderr'],
[email protected]a8e81632011-12-01 00:35:24433 stdout=VOID,
434 stderr=PIPE,
[email protected]4942e4a2011-11-15 15:50:50435 universal_newlines=un)
[email protected]a8e81632011-12-01 00:35:24436 self._check_res(res, None, c('a\nbb\nccc\n'), 0)
[email protected]4942e4a2011-11-15 15:50:50437 self._run_test(fn)
[email protected]87e6d332011-09-09 19:01:28438
439 def test_stderr_void(self):
[email protected]4942e4a2011-11-15 15:50:50440 def fn(c, e, un):
[email protected]a8e81632011-12-01 00:35:24441 res = subprocess2.communicate(
[email protected]4942e4a2011-11-15 15:50:50442 e + ['--stdout', '--stderr'],
[email protected]a8e81632011-12-01 00:35:24443 stdout=PIPE,
444 stderr=VOID,
[email protected]4942e4a2011-11-15 15:50:50445 universal_newlines=un)
[email protected]a8e81632011-12-01 00:35:24446 self._check_res(res, c('A\nBB\nCCC\n'), None, 0)
447 self._run_test(fn)
448
449 def test_stdout_void_stderr_redirect(self):
450 def fn(c, e, un):
451 res = subprocess2.communicate(
452 e + ['--stdout', '--stderr'],
453 stdout=VOID,
454 stderr=STDOUT,
455 universal_newlines=un)
456 self._check_res(res, None, None, 0)
[email protected]4942e4a2011-11-15 15:50:50457 self._run_test(fn)
[email protected]eba40222011-04-05 14:52:48458
[email protected]94c712f2011-12-01 15:04:57459 def test_tee_stderr(self):
[email protected]93e21372011-11-24 15:57:19460 def fn(c, e, un):
[email protected]94c712f2011-12-01 15:04:57461 stderr = []
[email protected]a8e81632011-12-01 00:35:24462 res = subprocess2.communicate(
[email protected]94c712f2011-12-01 15:04:57463 e + ['--stderr'], stderr=stderr.append, universal_newlines=un)
464 self.assertEquals(c('a\nbb\nccc\n'), ''.join(stderr))
[email protected]a8e81632011-12-01 00:35:24465 self._check_res(res, None, None, 0)
[email protected]93e21372011-11-24 15:57:19466 self._run_test(fn)
467
[email protected]94c712f2011-12-01 15:04:57468 def test_tee_stdout_stderr(self):
469 def fn(c, e, un):
470 stdout = []
471 stderr = []
472 res = subprocess2.communicate(
473 e + ['--stdout', '--stderr'],
474 stdout=stdout.append,
475 stderr=stderr.append,
476 universal_newlines=un)
477 self.assertEquals(c('A\nBB\nCCC\n'), ''.join(stdout))
478 self.assertEquals(c('a\nbb\nccc\n'), ''.join(stderr))
479 self._check_res(res, None, None, 0)
480 self._run_test(fn)
481
482 def test_tee_stdin(self):
483 def fn(c, e, un):
[email protected]bc3a53c2011-12-05 23:38:19484 # Mix of stdin input and stdout callback.
[email protected]94c712f2011-12-01 15:04:57485 stdout = []
486 stdin = '0123456789'
487 res = subprocess2.communicate(
[email protected]bc3a53c2011-12-05 23:38:19488 e + ['--stdout', '--read'],
489 stdin=stdin,
490 stdout=stdout.append,
[email protected]94c712f2011-12-01 15:04:57491 universal_newlines=un)
492 self.assertEquals(c('A\nBB\nCCC\n'), ''.join(stdout))
[email protected]bc3a53c2011-12-05 23:38:19493 self._check_res(res, None, None, 10)
[email protected]94c712f2011-12-01 15:04:57494 self._run_test(fn)
495
496 def test_tee_throw(self):
497 def fn(c, e, un):
[email protected]bc3a53c2011-12-05 23:38:19498 # Make sure failure still returns stderr completely.
[email protected]94c712f2011-12-01 15:04:57499 stderr = []
500 try:
501 subprocess2.check_output(
[email protected]bc3a53c2011-12-05 23:38:19502 e + ['--stderr', '--fail'],
503 stderr=stderr.append,
[email protected]94c712f2011-12-01 15:04:57504 universal_newlines=un)
505 self.fail()
506 except subprocess2.CalledProcessError, e:
507 self._check_exception(e, '', None, 64)
508 self.assertEquals(c('a\nbb\nccc\n'), ''.join(stderr))
509 self._run_test(fn)
510
511 def test_tee_timeout_stdout_void(self):
512 def fn(c, e, un):
513 stderr = []
514 res = subprocess2.communicate(
515 e + ['--stdout', '--stderr', '--fail'],
516 stdout=VOID,
517 stderr=stderr.append,
518 shell=False,
519 timeout=10,
520 universal_newlines=un)
521 self._check_res(res, None, None, 64)
522 self.assertEquals(c('a\nbb\nccc\n'), ''.join(stderr))
523 self._run_test(fn)
524
525 def test_tee_timeout_stderr_void(self):
526 def fn(c, e, un):
527 stdout = []
528 res = subprocess2.communicate(
529 e + ['--stdout', '--stderr', '--fail'],
530 stdout=stdout.append,
531 stderr=VOID,
532 shell=False,
533 timeout=10,
534 universal_newlines=un)
535 self._check_res(res, None, None, 64)
536 self.assertEquals(c('A\nBB\nCCC\n'), ''.join(stdout))
537 self._run_test(fn)
538
539 def test_tee_timeout_stderr_stdout(self):
540 def fn(c, e, un):
541 stdout = []
542 res = subprocess2.communicate(
543 e + ['--stdout', '--stderr', '--fail'],
544 stdout=stdout.append,
545 stderr=STDOUT,
546 shell=False,
547 timeout=10,
548 universal_newlines=un)
549 self._check_res(res, None, None, 64)
550 # Ordering is random due to buffering.
551 self.assertEquals(
552 set(c('a\nbb\nccc\nA\nBB\nCCC\n').splitlines(True)),
553 set(''.join(stdout).splitlines(True)))
554 self._run_test(fn)
555
556 def test_tee_large(self):
557 stdout = []
558 # Read 128kb. On my workstation it takes >2s. Welcome to 2011.
559 res = subprocess2.communicate(self.exe + ['--large'], stdout=stdout.append)
560 self.assertEquals(128*1024, len(''.join(stdout)))
561 self._check_res(res, None, None, 0)
562
563 def test_tee_large_stdin(self):
564 stdout = []
565 # Write 128kb.
566 stdin = '0123456789abcdef' * (8*1024)
567 res = subprocess2.communicate(
568 self.exe + ['--large', '--read'], stdin=stdin, stdout=stdout.append)
569 self.assertEquals(128*1024, len(''.join(stdout)))
570 self._check_res(res, None, None, 0)
571
572 def test_tee_cb_throw(self):
573 # Having a callback throwing up should not cause side-effects. It's a bit
574 # hard to measure.
575 class Blow(Exception):
576 pass
577 def blow(_):
578 raise Blow()
579 proc = subprocess2.Popen(self.exe + ['--stdout'], stdout=blow)
580 try:
581 proc.communicate()
582 self.fail()
583 except Blow:
584 self.assertNotEquals(0, proc.returncode)
585
[email protected]eba40222011-04-05 14:52:48586
587def child_main(args):
[email protected]4942e4a2011-11-15 15:50:50588 if sys.platform == 'win32':
589 # Annoying, make sure the output is not translated on Windows.
590 # pylint: disable=E1101,F0401
591 import msvcrt
592 msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY)
593 msvcrt.setmode(sys.stderr.fileno(), os.O_BINARY)
594
[email protected]eba40222011-04-05 14:52:48595 parser = optparse.OptionParser()
596 parser.add_option(
597 '--fail',
598 dest='return_value',
599 action='store_const',
600 default=0,
601 const=64)
[email protected]4942e4a2011-11-15 15:50:50602 parser.add_option(
603 '--crlf', action='store_const', const='\r\n', dest='eol', default='\n')
604 parser.add_option(
605 '--cr', action='store_const', const='\r', dest='eol')
[email protected]eba40222011-04-05 14:52:48606 parser.add_option('--stdout', action='store_true')
607 parser.add_option('--stderr', action='store_true')
[email protected]4942e4a2011-11-15 15:50:50608 parser.add_option('--sleep_first', action='store_true')
609 parser.add_option('--sleep_last', action='store_true')
610 parser.add_option('--large', action='store_true')
611 parser.add_option('--read', action='store_true')
[email protected]eba40222011-04-05 14:52:48612 options, args = parser.parse_args(args)
613 if args:
614 parser.error('Internal error')
[email protected]4942e4a2011-11-15 15:50:50615 if options.sleep_first:
616 time.sleep(10)
[email protected]eba40222011-04-05 14:52:48617
618 def do(string):
619 if options.stdout:
[email protected]4942e4a2011-11-15 15:50:50620 sys.stdout.write(string.upper())
621 sys.stdout.write(options.eol)
[email protected]eba40222011-04-05 14:52:48622 if options.stderr:
[email protected]4942e4a2011-11-15 15:50:50623 sys.stderr.write(string.lower())
624 sys.stderr.write(options.eol)
[email protected]eba40222011-04-05 14:52:48625
626 do('A')
627 do('BB')
628 do('CCC')
[email protected]4942e4a2011-11-15 15:50:50629 if options.large:
630 # Print 128kb.
631 string = '0123456789abcdef' * (8*1024)
632 sys.stdout.write(string)
633 if options.read:
[email protected]bc3a53c2011-12-05 23:38:19634 assert options.return_value is 0
[email protected]4942e4a2011-11-15 15:50:50635 try:
[email protected]bc3a53c2011-12-05 23:38:19636 while sys.stdin.read(1):
637 options.return_value += 1
[email protected]4942e4a2011-11-15 15:50:50638 except OSError:
639 pass
640 if options.sleep_last:
[email protected]f2dca4e2011-11-09 19:24:48641 time.sleep(10)
[email protected]eba40222011-04-05 14:52:48642 return options.return_value
643
644
645if __name__ == '__main__':
[email protected]4942e4a2011-11-15 15:50:50646 logging.basicConfig(level=
647 [logging.WARNING, logging.INFO, logging.DEBUG][
648 min(2, sys.argv.count('-v'))])
[email protected]eba40222011-04-05 14:52:48649 if len(sys.argv) > 1 and sys.argv[1] == '--child':
650 sys.exit(child_main(sys.argv[2:]))
651 unittest.main()