blob: 376a40fb64d2a63450a487787f0fa97fc900c4c3 [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
8import optparse
9import os
10import sys
11import time
12import unittest
13
14ROOT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
15sys.path.insert(0, ROOT_DIR)
16
17import subprocess2
18
[email protected]f08b09c2011-04-06 13:14:2719# Method could be a function
20# pylint: disable=R0201
[email protected]eba40222011-04-05 14:52:4821
22class Subprocess2Test(unittest.TestCase):
23 # Can be mocked in a test.
[email protected]f08b09c2011-04-06 13:14:2724 TO_SAVE = {
25 subprocess2: ['Popen', 'call', 'check_call', 'capture', 'check_output'],
26 subprocess2.subprocess: ['Popen'],
27 }
[email protected]eba40222011-04-05 14:52:4828
29 def setUp(self):
30 self.exe_path = __file__
31 self.exe = [self.exe_path, '--child']
[email protected]f08b09c2011-04-06 13:14:2732 self.saved = {}
33 for module, names in self.TO_SAVE.iteritems():
34 self.saved[module] = dict(
35 (name, getattr(module, name)) for name in names)
[email protected]eba40222011-04-05 14:52:4836
37 def tearDown(self):
[email protected]f08b09c2011-04-06 13:14:2738 for module, saved in self.saved.iteritems():
39 for name, value in saved.iteritems():
40 setattr(module, name, value)
[email protected]eba40222011-04-05 14:52:4841
42 @staticmethod
[email protected]f08b09c2011-04-06 13:14:2743 def _fake_call():
[email protected]eba40222011-04-05 14:52:4844 results = {}
45 def fake_call(args, **kwargs):
[email protected]f08b09c2011-04-06 13:14:2746 assert not results
[email protected]eba40222011-04-05 14:52:4847 results.update(kwargs)
48 results['args'] = args
49 return ['stdout', 'stderr'], 0
50 subprocess2.call = fake_call
51 return results
52
[email protected]f08b09c2011-04-06 13:14:2753 @staticmethod
54 def _fake_Popen():
55 results = {}
56 class fake_Popen(object):
57 returncode = -8
58 def __init__(self, args, **kwargs):
59 assert not results
60 results.update(kwargs)
61 results['args'] = args
62 def communicate(self):
63 return None, None
64 subprocess2.Popen = fake_Popen
65 return results
66
67 @staticmethod
68 def _fake_subprocess_Popen():
69 results = {}
70 class fake_Popen(object):
71 returncode = -8
72 def __init__(self, args, **kwargs):
73 assert not results
74 results.update(kwargs)
75 results['args'] = args
76 def communicate(self):
77 return None, None
78 subprocess2.subprocess.Popen = fake_Popen
79 return results
80
[email protected]eba40222011-04-05 14:52:4881 def test_check_call_defaults(self):
[email protected]f08b09c2011-04-06 13:14:2782 results = self._fake_call()
[email protected]eba40222011-04-05 14:52:4883 self.assertEquals(
84 ['stdout', 'stderr'], subprocess2.check_call(['foo'], a=True))
85 expected = {
86 'args': ['foo'],
87 'a':True,
88 }
89 self.assertEquals(expected, results)
90
[email protected]f08b09c2011-04-06 13:14:2791 def test_call_defaults(self):
92 results = self._fake_Popen()
93 self.assertEquals(((None, None), -8), subprocess2.call(['foo'], a=True))
94 expected = {
95 'args': ['foo'],
96 'a': True,
97 }
98 self.assertEquals(expected, results)
99
100 def test_Popen_defaults(self):
101 results = self._fake_subprocess_Popen()
102 proc = subprocess2.Popen(['foo'], a=True)
103 self.assertEquals(-8, proc.returncode)
104 env = os.environ.copy()
105 env['LANG'] = 'en_US.UTF-8'
106 expected = {
107 'args': ['foo'],
108 'a': True,
109 'shell': bool(sys.platform=='win32'),
110 'env': env,
111 }
112 self.assertEquals(expected, results)
113
[email protected]eba40222011-04-05 14:52:48114 def test_check_output_defaults(self):
[email protected]f08b09c2011-04-06 13:14:27115 results = self._fake_call()
[email protected]eba40222011-04-05 14:52:48116 # It's discarding 'stderr' because it assumes stderr=subprocess2.STDOUT but
117 # fake_call() doesn't 'implement' that.
118 self.assertEquals('stdout', subprocess2.check_output(['foo'], a=True))
119 expected = {
120 'args': ['foo'],
121 'a':True,
122 'stdout': subprocess2.PIPE,
123 'stderr': subprocess2.STDOUT,
124 }
125 self.assertEquals(expected, results)
126
127 def test_timeout(self):
128 # It'd be better to not discard stdout.
129 out, returncode = subprocess2.call(
130 self.exe + ['--sleep', '--stdout'],
131 timeout=0.01,
132 stdout=subprocess2.PIPE)
133 self.assertEquals(-9, returncode)
134 self.assertEquals(['', None], out)
135
136 def test_void(self):
137 out = subprocess2.check_output(
138 self.exe + ['--stdout', '--stderr'],
139 stdout=subprocess2.VOID)
140 self.assertEquals(None, out)
141 out = subprocess2.check_output(
142 self.exe + ['--stdout', '--stderr'],
143 stderr=subprocess2.VOID)
144 self.assertEquals('A\nBB\nCCC\n', out)
145
146 def test_check_output_throw(self):
147 try:
148 subprocess2.check_output(self.exe + ['--fail', '--stderr'])
149 self.fail()
150 except subprocess2.CalledProcessError, e:
151 self.assertEquals('a\nbb\nccc\n', e.stdout)
152 self.assertEquals(None, e.stderr)
153 self.assertEquals(64, e.returncode)
154
155 def test_check_call_throw(self):
156 try:
157 subprocess2.check_call(self.exe + ['--fail', '--stderr'])
158 self.fail()
159 except subprocess2.CalledProcessError, e:
160 self.assertEquals(None, e.stdout)
161 self.assertEquals(None, e.stderr)
162 self.assertEquals(64, e.returncode)
163
164
165def child_main(args):
166 parser = optparse.OptionParser()
167 parser.add_option(
168 '--fail',
169 dest='return_value',
170 action='store_const',
171 default=0,
172 const=64)
173 parser.add_option('--stdout', action='store_true')
174 parser.add_option('--stderr', action='store_true')
175 parser.add_option('--sleep', action='store_true')
176 options, args = parser.parse_args(args)
177 if args:
178 parser.error('Internal error')
179
180 def do(string):
181 if options.stdout:
182 print >> sys.stdout, string.upper()
183 if options.stderr:
184 print >> sys.stderr, string.lower()
185
186 do('A')
187 do('BB')
188 do('CCC')
189 if options.sleep:
190 time.sleep(10)
191 return options.return_value
192
193
194if __name__ == '__main__':
195 if len(sys.argv) > 1 and sys.argv[1] == '--child':
196 sys.exit(child_main(sys.argv[2:]))
197 unittest.main()