blob: dfc91f6078e225c348b032a4f7ef5a2f42eb62ca [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__
[email protected]c98c0c52011-04-06 13:39:4331 self.exe = [sys.executable, 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)
[email protected]f08b09c2011-04-06 13:14:27104 expected = {
105 'args': ['foo'],
106 'a': True,
107 'shell': bool(sys.platform=='win32'),
[email protected]f08b09c2011-04-06 13:14:27108 }
[email protected]c98c0c52011-04-06 13:39:43109 if sys.platform != 'win32':
110 env = os.environ.copy()
111 is_english = lambda name: env.get(name, 'en').startswith('en')
112 if not is_english('LANG'):
113 env['LANG'] = 'en_US.UTF-8'
114 expected['env'] = env
115 if not is_english('LANGUAGE'):
116 env['LANGUAGE'] = 'en_US.UTF-8'
117 expected['env'] = env
[email protected]f08b09c2011-04-06 13:14:27118 self.assertEquals(expected, results)
119
[email protected]eba40222011-04-05 14:52:48120 def test_check_output_defaults(self):
[email protected]f08b09c2011-04-06 13:14:27121 results = self._fake_call()
[email protected]eba40222011-04-05 14:52:48122 # It's discarding 'stderr' because it assumes stderr=subprocess2.STDOUT but
123 # fake_call() doesn't 'implement' that.
124 self.assertEquals('stdout', subprocess2.check_output(['foo'], a=True))
125 expected = {
126 'args': ['foo'],
127 'a':True,
128 'stdout': subprocess2.PIPE,
129 'stderr': subprocess2.STDOUT,
130 }
131 self.assertEquals(expected, results)
132
133 def test_timeout(self):
134 # It'd be better to not discard stdout.
135 out, returncode = subprocess2.call(
136 self.exe + ['--sleep', '--stdout'],
137 timeout=0.01,
138 stdout=subprocess2.PIPE)
139 self.assertEquals(-9, returncode)
140 self.assertEquals(['', None], out)
141
142 def test_void(self):
143 out = subprocess2.check_output(
144 self.exe + ['--stdout', '--stderr'],
145 stdout=subprocess2.VOID)
146 self.assertEquals(None, out)
147 out = subprocess2.check_output(
148 self.exe + ['--stdout', '--stderr'],
[email protected]c98c0c52011-04-06 13:39:43149 universal_newlines=True,
[email protected]eba40222011-04-05 14:52:48150 stderr=subprocess2.VOID)
151 self.assertEquals('A\nBB\nCCC\n', out)
152
153 def test_check_output_throw(self):
154 try:
[email protected]c98c0c52011-04-06 13:39:43155 subprocess2.check_output(
156 self.exe + ['--fail', '--stderr'], universal_newlines=True)
[email protected]eba40222011-04-05 14:52:48157 self.fail()
158 except subprocess2.CalledProcessError, e:
159 self.assertEquals('a\nbb\nccc\n', e.stdout)
160 self.assertEquals(None, e.stderr)
161 self.assertEquals(64, e.returncode)
162
163 def test_check_call_throw(self):
164 try:
165 subprocess2.check_call(self.exe + ['--fail', '--stderr'])
166 self.fail()
167 except subprocess2.CalledProcessError, e:
168 self.assertEquals(None, e.stdout)
169 self.assertEquals(None, e.stderr)
170 self.assertEquals(64, e.returncode)
171
172
173def child_main(args):
174 parser = optparse.OptionParser()
175 parser.add_option(
176 '--fail',
177 dest='return_value',
178 action='store_const',
179 default=0,
180 const=64)
181 parser.add_option('--stdout', action='store_true')
182 parser.add_option('--stderr', action='store_true')
183 parser.add_option('--sleep', action='store_true')
184 options, args = parser.parse_args(args)
185 if args:
186 parser.error('Internal error')
187
188 def do(string):
189 if options.stdout:
190 print >> sys.stdout, string.upper()
191 if options.stderr:
192 print >> sys.stderr, string.lower()
193
194 do('A')
195 do('BB')
196 do('CCC')
197 if options.sleep:
198 time.sleep(10)
199 return options.return_value
200
201
202if __name__ == '__main__':
203 if len(sys.argv) > 1 and sys.argv[1] == '--child':
204 sys.exit(child_main(sys.argv[2:]))
205 unittest.main()