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

Side by Side Diff: tests/subprocess2_test.py

Issue 8749015: Reimplement r109239 but using Popen.communicate() instead. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/tools/depot_tools
Patch Set: Address comments Created 9 years 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « subprocess2.py ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 #!/usr/bin/env python 1 #!/usr/bin/env python
2 # Copyright (c) 2011 The Chromium Authors. All rights reserved. 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 3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file. 4 # found in the LICENSE file.
5 5
6 """Unit tests for subprocess2.py.""" 6 """Unit tests for subprocess2.py."""
7 7
8 import logging 8 import logging
9 import optparse 9 import optparse
10 import os 10 import os
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
70 def _fake_Popen(self): 70 def _fake_Popen(self):
71 """Mocks the whole subprocess2.Popen class.""" 71 """Mocks the whole subprocess2.Popen class."""
72 results = {} 72 results = {}
73 class fake_Popen(object): 73 class fake_Popen(object):
74 returncode = -8 74 returncode = -8
75 def __init__(self, args, **kwargs): 75 def __init__(self, args, **kwargs):
76 assert not results 76 assert not results
77 results.update(kwargs) 77 results.update(kwargs)
78 results['args'] = args 78 results['args'] = args
79 @staticmethod 79 @staticmethod
80 def communicate(): 80 def communicate(input=None, timeout=None): # pylint: disable=W0622
81 return None, None 81 return None, None
82 self.mock(subprocess2, 'Popen', fake_Popen) 82 self.mock(subprocess2, 'Popen', fake_Popen)
83 return results 83 return results
84 84
85 def _fake_subprocess_Popen(self): 85 def _fake_subprocess_Popen(self):
86 """Mocks the base class subprocess.Popen only.""" 86 """Mocks the base class subprocess.Popen only."""
87 results = {} 87 results = {}
88 def __init__(self, args, **kwargs): 88 def __init__(self, args, **kwargs):
89 assert not results 89 assert not results
90 results.update(kwargs) 90 results.update(kwargs)
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
173 if fcntl: 173 if fcntl:
174 for v in (sys.stdin, sys.stdout, sys.stderr): 174 for v in (sys.stdin, sys.stdout, sys.stderr):
175 fileno = v.fileno() 175 fileno = v.fileno()
176 self.states[fileno] = fcntl.fcntl(fileno, fcntl.F_GETFL) 176 self.states[fileno] = fcntl.fcntl(fileno, fcntl.F_GETFL)
177 177
178 def tearDown(self): 178 def tearDown(self):
179 for fileno, fl in self.states.iteritems(): 179 for fileno, fl in self.states.iteritems():
180 self.assertEquals(fl, fcntl.fcntl(fileno, fcntl.F_GETFL)) 180 self.assertEquals(fl, fcntl.fcntl(fileno, fcntl.F_GETFL))
181 super(BaseTestCase, self).tearDown() 181 super(BaseTestCase, self).tearDown()
182 182
183 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
183 189
184 class RegressionTest(BaseTestCase): 190 class RegressionTest(BaseTestCase):
185 # Regression tests to ensure that subprocess and subprocess2 have the same 191 # Regression tests to ensure that subprocess and subprocess2 have the same
186 # behavior. 192 # behavior.
187 def _run_test(self, function): 193 def _run_test(self, function):
188 """Runs tests in 12 combinations: 194 """Runs tests in 12 combinations:
189 - LF output with universal_newlines=False 195 - LF output with universal_newlines=False
190 - CR output with universal_newlines=False 196 - CR output with universal_newlines=False
191 - CRLF output with universal_newlines=False 197 - CRLF output with universal_newlines=False
192 - LF output with universal_newlines=True 198 - LF output with universal_newlines=True
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
292 self._run_test(fn) 298 self._run_test(fn)
293 299
294 def test_check_call_throw(self): 300 def test_check_call_throw(self):
295 for subp in (subprocess, subprocess2): 301 for subp in (subprocess, subprocess2):
296 try: 302 try:
297 subp.check_call(self.exe + ['--fail', '--stderr']) 303 subp.check_call(self.exe + ['--fail', '--stderr'])
298 self.fail() 304 self.fail()
299 except subp.CalledProcessError, e: 305 except subp.CalledProcessError, e:
300 self._check_exception(subp, e, None, None, 64) 306 self._check_exception(subp, e, None, None, 64)
301 307
308 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
302 329
303 class S2Test(BaseTestCase): 330 class S2Test(BaseTestCase):
304 # Tests that can only run in subprocess2, e.g. new functionalities. 331 # Tests that can only run in subprocess2, e.g. new functionalities.
305 # In particular, subprocess2.communicate() doesn't exist in subprocess. 332 # In particular, subprocess2.communicate() doesn't exist in subprocess.
306 def _run_test(self, function): 333 def _run_test(self, function):
307 """Runs tests in 6 combinations: 334 """Runs tests in 6 combinations:
308 - LF output with universal_newlines=False 335 - LF output with universal_newlines=False
309 - CR output with universal_newlines=False 336 - CR output with universal_newlines=False
310 - CRLF output with universal_newlines=False 337 - CRLF output with universal_newlines=False
311 - LF output with universal_newlines=True 338 - LF output with universal_newlines=True
312 - CR output with universal_newlines=True 339 - CR output with universal_newlines=True
313 - CRLF output with universal_newlines=True 340 - CRLF output with universal_newlines=True
314 341
315 First |function| argument is the convertion for the origianl expected LF 342 First |function| argument is the convertion for the origianl expected LF
316 string to the right EOL. 343 string to the right EOL.
317 Second |function| argument is the executable and initial flag to run, to 344 Second |function| argument is the executable and initial flag to run, to
318 control what EOL is used by the child process. 345 control what EOL is used by the child process.
319 Third |function| argument is universal_newlines value. 346 Third |function| argument is universal_newlines value.
320 """ 347 """
321 noop = lambda x: x 348 noop = lambda x: x
322 function(noop, self.exe, False) 349 function(noop, self.exe, False)
323 function(convert_to_cr, self.exe + ['--cr'], False) 350 function(convert_to_cr, self.exe + ['--cr'], False)
324 function(convert_to_crlf, self.exe + ['--crlf'], False) 351 function(convert_to_crlf, self.exe + ['--crlf'], False)
325 function(noop, self.exe, True) 352 function(noop, self.exe, True)
326 function(noop, self.exe + ['--cr'], True) 353 function(noop, self.exe + ['--cr'], True)
327 function(noop, self.exe + ['--crlf'], True) 354 function(noop, self.exe + ['--crlf'], True)
328 355
329 def _check_res(self, res, stdout, stderr, returncode): 356 def _check_exception(self, e, stdout, stderr, returncode):
330 (out, err), code = res 357 """On exception, look if the exception members are set correctly."""
331 self.assertEquals(stdout, out) 358 self.assertEquals(returncode, e.returncode)
332 self.assertEquals(stderr, err) 359 self.assertEquals(stdout, e.stdout)
333 self.assertEquals(returncode, code) 360 self.assertEquals(stderr, e.stderr)
334 361
335 def test_timeout(self): 362 def test_timeout(self):
336 # timeout doesn't exist in subprocess. 363 # timeout doesn't exist in subprocess.
337 def fn(c, e, un): 364 def fn(c, e, un):
338 res = subprocess2.communicate( 365 res = subprocess2.communicate(
339 self.exe + ['--sleep_first', '--stdout'], 366 self.exe + ['--sleep_first', '--stdout'],
340 timeout=0.01, 367 timeout=0.01,
341 stdout=PIPE, 368 stdout=PIPE,
342 shell=False) 369 shell=False)
343 self._check_res(res, '', None, TIMED_OUT) 370 self._check_res(res, '', None, TIMED_OUT)
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
376 def test_stdout_void_stderr_redirect(self): 403 def test_stdout_void_stderr_redirect(self):
377 def fn(c, e, un): 404 def fn(c, e, un):
378 res = subprocess2.communicate( 405 res = subprocess2.communicate(
379 e + ['--stdout', '--stderr'], 406 e + ['--stdout', '--stderr'],
380 stdout=VOID, 407 stdout=VOID,
381 stderr=STDOUT, 408 stderr=STDOUT,
382 universal_newlines=un) 409 universal_newlines=un)
383 self._check_res(res, None, None, 0) 410 self._check_res(res, None, None, 0)
384 self._run_test(fn) 411 self._run_test(fn)
385 412
386 def test_check_output_redirect_stderr_to_stdout_pipe(self): 413 def test_tee_stderr(self):
387 def fn(c, e, un): 414 def fn(c, e, un):
388 # stderr output into stdout. 415 stderr = []
389 res = subprocess2.communicate( 416 res = subprocess2.communicate(
390 e + ['--stderr'], 417 e + ['--stderr'], stderr=stderr.append, universal_newlines=un)
391 stdout=PIPE, 418 self.assertEquals(c('a\nbb\nccc\n'), ''.join(stderr))
392 stderr=STDOUT, 419 self._check_res(res, None, None, 0)
393 universal_newlines=un)
394 self._check_res(res, c('a\nbb\nccc\n'), None, 0)
395 self._run_test(fn) 420 self._run_test(fn)
396 421
397 def test_check_output_redirect_stderr_to_stdout(self): 422 def test_tee_stdout_stderr(self):
398 def fn(c, e, un): 423 def fn(c, e, un):
399 # stderr output into stdout but stdout is not piped. 424 stdout = []
425 stderr = []
400 res = subprocess2.communicate( 426 res = subprocess2.communicate(
401 e + ['--stderr'], stderr=STDOUT, universal_newlines=un) 427 e + ['--stdout', '--stderr'],
428 stdout=stdout.append,
429 stderr=stderr.append,
430 universal_newlines=un)
431 self.assertEquals(c('A\nBB\nCCC\n'), ''.join(stdout))
432 self.assertEquals(c('a\nbb\nccc\n'), ''.join(stderr))
402 self._check_res(res, None, None, 0) 433 self._check_res(res, None, None, 0)
403 self._run_test(fn) 434 self._run_test(fn)
404 435
436 def test_tee_stdin(self):
437 def fn(c, e, un):
438 stdout = []
439 stdin = '0123456789'
440 res = subprocess2.communicate(
441 e + ['--stdout', '--read'], stdin=stdin, stdout=stdout.append,
442 universal_newlines=un)
443 self.assertEquals(c('A\nBB\nCCC\n'), ''.join(stdout))
444 self._check_res(res, None, None, 0)
445 self._run_test(fn)
446
447 def test_tee_throw(self):
448 def fn(c, e, un):
449 stderr = []
450 try:
451 subprocess2.check_output(
452 e + ['--stderr', '--fail'], stderr=stderr.append,
453 universal_newlines=un)
454 self.fail()
455 except subprocess2.CalledProcessError, e:
456 self._check_exception(e, '', None, 64)
457 self.assertEquals(c('a\nbb\nccc\n'), ''.join(stderr))
458 self._run_test(fn)
459
460 def test_tee_timeout_stdout_void(self):
461 def fn(c, e, un):
462 stderr = []
463 res = subprocess2.communicate(
464 e + ['--stdout', '--stderr', '--fail'],
465 stdout=VOID,
466 stderr=stderr.append,
467 shell=False,
468 timeout=10,
469 universal_newlines=un)
470 self._check_res(res, None, None, 64)
471 self.assertEquals(c('a\nbb\nccc\n'), ''.join(stderr))
472 self._run_test(fn)
473
474 def test_tee_timeout_stderr_void(self):
475 def fn(c, e, un):
476 stdout = []
477 res = subprocess2.communicate(
478 e + ['--stdout', '--stderr', '--fail'],
479 stdout=stdout.append,
480 stderr=VOID,
481 shell=False,
482 timeout=10,
483 universal_newlines=un)
484 self._check_res(res, None, None, 64)
485 self.assertEquals(c('A\nBB\nCCC\n'), ''.join(stdout))
486 self._run_test(fn)
487
488 def test_tee_timeout_stderr_stdout(self):
489 def fn(c, e, un):
490 stdout = []
491 res = subprocess2.communicate(
492 e + ['--stdout', '--stderr', '--fail'],
493 stdout=stdout.append,
494 stderr=STDOUT,
495 shell=False,
496 timeout=10,
497 universal_newlines=un)
498 self._check_res(res, None, None, 64)
499 # Ordering is random due to buffering.
500 self.assertEquals(
501 set(c('a\nbb\nccc\nA\nBB\nCCC\n').splitlines(True)),
502 set(''.join(stdout).splitlines(True)))
503 self._run_test(fn)
504
505 def test_tee_large(self):
506 stdout = []
507 # Read 128kb. On my workstation it takes >2s. Welcome to 2011.
508 res = subprocess2.communicate(self.exe + ['--large'], stdout=stdout.append)
509 self.assertEquals(128*1024, len(''.join(stdout)))
510 self._check_res(res, None, None, 0)
511
512 def test_tee_large_stdin(self):
513 stdout = []
514 # Write 128kb.
515 stdin = '0123456789abcdef' * (8*1024)
516 res = subprocess2.communicate(
517 self.exe + ['--large', '--read'], stdin=stdin, stdout=stdout.append)
518 self.assertEquals(128*1024, len(''.join(stdout)))
519 self._check_res(res, None, None, 0)
520
521 def test_tee_cb_throw(self):
522 # Having a callback throwing up should not cause side-effects. It's a bit
523 # hard to measure.
524 class Blow(Exception):
525 pass
526 def blow(_):
527 raise Blow()
528 proc = subprocess2.Popen(self.exe + ['--stdout'], stdout=blow)
529 try:
530 proc.communicate()
531 self.fail()
532 except Blow:
533 self.assertNotEquals(0, proc.returncode)
534
405 535
406 def child_main(args): 536 def child_main(args):
407 if sys.platform == 'win32': 537 if sys.platform == 'win32':
408 # Annoying, make sure the output is not translated on Windows. 538 # Annoying, make sure the output is not translated on Windows.
409 # pylint: disable=E1101,F0401 539 # pylint: disable=E1101,F0401
410 import msvcrt 540 import msvcrt
411 msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY) 541 msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY)
412 msvcrt.setmode(sys.stderr.fileno(), os.O_BINARY) 542 msvcrt.setmode(sys.stderr.fileno(), os.O_BINARY)
413 543
414 parser = optparse.OptionParser() 544 parser = optparse.OptionParser()
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
460 return options.return_value 590 return options.return_value
461 591
462 592
463 if __name__ == '__main__': 593 if __name__ == '__main__':
464 logging.basicConfig(level= 594 logging.basicConfig(level=
465 [logging.WARNING, logging.INFO, logging.DEBUG][ 595 [logging.WARNING, logging.INFO, logging.DEBUG][
466 min(2, sys.argv.count('-v'))]) 596 min(2, sys.argv.count('-v'))])
467 if len(sys.argv) > 1 and sys.argv[1] == '--child': 597 if len(sys.argv) > 1 and sys.argv[1] == '--child':
468 sys.exit(child_main(sys.argv[2:])) 598 sys.exit(child_main(sys.argv[2:]))
469 unittest.main() 599 unittest.main()
OLDNEW
« no previous file with comments | « subprocess2.py ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698