blob: 57508c7530b70b2a00878617f202cc29be98e5a1 [file] [log] [blame]
Christian Heimes9cd17752007-11-18 19:35:23 +00001# Tests invocation of the interpreter with various command line arguments
Nick Coghland26c18a2010-08-17 13:06:11 +00002# Most tests are executed with environment variables ignored
Christian Heimes9cd17752007-11-18 19:35:23 +00003# See test_cmd_line_script.py for testing of script execution
Neal Norwitz11bd1192005-10-03 00:54:56 +00004
Benjamin Petersonee8712c2008-05-20 21:35:26 +00005import test.support, unittest
Antoine Pitrou87695762008-08-14 22:44:29 +00006import os
Neal Norwitz11bd1192005-10-03 00:54:56 +00007import sys
Nick Coghlan260bd3e2009-11-16 06:49:25 +00008import subprocess
Victor Stinnerc0f1a1a2011-02-23 12:07:37 +00009import tempfile
Antoine Pitrou9bc35682010-11-09 21:33:55 +000010from test.script_helper import spawn_python, kill_python, assert_python_ok, assert_python_failure
Thomas Woutersed03b412007-08-28 21:37:11 +000011
Trent Nelson39e307e2008-03-19 06:45:48 +000012
Nick Coghlan260bd3e2009-11-16 06:49:25 +000013# XXX (ncoghlan): Move to script_helper and make consistent with run_python
Trent Nelson39e307e2008-03-19 06:45:48 +000014def _kill_python_and_exit_code(p):
Nick Coghlan260bd3e2009-11-16 06:49:25 +000015 data = kill_python(p)
Trent Nelson39e307e2008-03-19 06:45:48 +000016 returncode = p.wait()
17 return data, returncode
Thomas Woutersed03b412007-08-28 21:37:11 +000018
Neal Norwitz11bd1192005-10-03 00:54:56 +000019class CmdLineTest(unittest.TestCase):
Neal Norwitz11bd1192005-10-03 00:54:56 +000020 def test_directories(self):
Antoine Pitrouf51d8d32010-10-08 18:05:42 +000021 assert_python_failure('.')
22 assert_python_failure('< .')
Neal Norwitz11bd1192005-10-03 00:54:56 +000023
24 def verify_valid_flag(self, cmd_line):
Antoine Pitrouf51d8d32010-10-08 18:05:42 +000025 rc, out, err = assert_python_ok(*cmd_line)
26 self.assertTrue(out == b'' or out.endswith(b'\n'))
27 self.assertNotIn(b'Traceback', out)
28 self.assertNotIn(b'Traceback', err)
Neal Norwitz11bd1192005-10-03 00:54:56 +000029
Neal Norwitz11bd1192005-10-03 00:54:56 +000030 def test_optimize(self):
31 self.verify_valid_flag('-O')
32 self.verify_valid_flag('-OO')
33
Neal Norwitz11bd1192005-10-03 00:54:56 +000034 def test_site_flag(self):
35 self.verify_valid_flag('-S')
36
37 def test_usage(self):
Antoine Pitrouf51d8d32010-10-08 18:05:42 +000038 rc, out, err = assert_python_ok('-h')
39 self.assertIn(b'usage', out)
Neal Norwitz11bd1192005-10-03 00:54:56 +000040
41 def test_version(self):
Guido van Rossuma1c42a92007-08-29 03:47:36 +000042 version = ('Python %d.%d' % sys.version_info[:2]).encode("ascii")
Antoine Pitrouf51d8d32010-10-08 18:05:42 +000043 rc, out, err = assert_python_ok('-V')
44 self.assertTrue(err.startswith(version))
Neal Norwitz11bd1192005-10-03 00:54:56 +000045
Trent Nelson39e307e2008-03-19 06:45:48 +000046 def test_verbose(self):
47 # -v causes imports to write to stderr. If the write to
48 # stderr itself causes an import to happen (for the output
49 # codec), a recursion loop can occur.
Antoine Pitrouf51d8d32010-10-08 18:05:42 +000050 rc, out, err = assert_python_ok('-v')
51 self.assertNotIn(b'stack overflow', err)
52 rc, out, err = assert_python_ok('-vv')
53 self.assertNotIn(b'stack overflow', err)
Trent Nelson39e307e2008-03-19 06:45:48 +000054
Antoine Pitrou9583cac2010-10-21 13:42:28 +000055 def test_xoptions(self):
56 rc, out, err = assert_python_ok('-c', 'import sys; print(sys._xoptions)')
57 opts = eval(out.splitlines()[0])
58 self.assertEqual(opts, {})
59 rc, out, err = assert_python_ok(
60 '-Xa', '-Xb=c,d=e', '-c', 'import sys; print(sys._xoptions)')
61 opts = eval(out.splitlines()[0])
62 self.assertEqual(opts, {'a': True, 'b': 'c,d=e'})
63
Thomas Wouters477c8d52006-05-27 19:21:47 +000064 def test_run_module(self):
65 # Test expected operation of the '-m' switch
66 # Switch needs an argument
Antoine Pitrouf51d8d32010-10-08 18:05:42 +000067 assert_python_failure('-m')
Thomas Wouters477c8d52006-05-27 19:21:47 +000068 # Check we get an error for a nonexistent module
Antoine Pitrouf51d8d32010-10-08 18:05:42 +000069 assert_python_failure('-m', 'fnord43520xyz')
Thomas Wouters477c8d52006-05-27 19:21:47 +000070 # Check the runpy module also gives an error for
71 # a nonexistent module
Antoine Pitrouf51d8d32010-10-08 18:05:42 +000072 assert_python_failure('-m', 'runpy', 'fnord43520xyz'),
Thomas Wouters477c8d52006-05-27 19:21:47 +000073 # All good if module is located and run successfully
Antoine Pitrouf51d8d32010-10-08 18:05:42 +000074 assert_python_ok('-m', 'timeit', '-n', '1'),
Thomas Wouters477c8d52006-05-27 19:21:47 +000075
Thomas Woutersed03b412007-08-28 21:37:11 +000076 def test_run_module_bug1764407(self):
77 # -m and -i need to play well together
78 # Runs the timeit module and checks the __main__
79 # namespace has been populated appropriately
Nick Coghlan260bd3e2009-11-16 06:49:25 +000080 p = spawn_python('-i', '-m', 'timeit', '-n', '1')
Guido van Rossuma1c42a92007-08-29 03:47:36 +000081 p.stdin.write(b'Timer\n')
82 p.stdin.write(b'exit()\n')
Nick Coghlan260bd3e2009-11-16 06:49:25 +000083 data = kill_python(p)
Thomas Woutersed03b412007-08-28 21:37:11 +000084 self.assertTrue(data.find(b'1 loop') != -1)
85 self.assertTrue(data.find(b'__main__.Timer') != -1)
86
Thomas Wouters477c8d52006-05-27 19:21:47 +000087 def test_run_code(self):
88 # Test expected operation of the '-c' switch
89 # Switch needs an argument
Antoine Pitrouf51d8d32010-10-08 18:05:42 +000090 assert_python_failure('-c')
Thomas Wouters477c8d52006-05-27 19:21:47 +000091 # Check we get an error for an uncaught exception
Antoine Pitrouf51d8d32010-10-08 18:05:42 +000092 assert_python_failure('-c', 'raise Exception')
Thomas Wouters477c8d52006-05-27 19:21:47 +000093 # All good if execution is successful
Antoine Pitrouf51d8d32010-10-08 18:05:42 +000094 assert_python_ok('-c', 'pass')
Thomas Wouters477c8d52006-05-27 19:21:47 +000095
Victor Stinner073f7592010-10-20 21:56:55 +000096 @unittest.skipIf(sys.getfilesystemencoding() == 'ascii',
97 'need a filesystem encoding different than ASCII')
98 def test_non_ascii(self):
Amaury Forgeot d'Arc9a5499b2008-11-11 23:04:59 +000099 # Test handling of non-ascii data
Victor Stinner073f7592010-10-20 21:56:55 +0000100 if test.support.verbose:
101 import locale
102 print('locale encoding = %s, filesystem encoding = %s'
103 % (locale.getpreferredencoding(), sys.getfilesystemencoding()))
104 command = "assert(ord('\xe9') == 0xe9)"
105 assert_python_ok('-c', command)
Amaury Forgeot d'Arc9a5499b2008-11-11 23:04:59 +0000106
Victor Stinnerf6211ed2010-10-20 21:52:33 +0000107 # On Windows, pass bytes to subprocess doesn't test how Python decodes the
108 # command line, but how subprocess does decode bytes to unicode. Python
109 # doesn't decode the command line because Windows provides directly the
110 # arguments as unicode (using wmain() instead of main()).
111 @unittest.skipIf(sys.platform == 'win32',
112 'Windows has a native unicode API')
113 def test_undecodable_code(self):
114 undecodable = b"\xff"
115 env = os.environ.copy()
116 # Use C locale to get ascii for the locale encoding
117 env['LC_ALL'] = 'C'
118 code = (
119 b'import locale; '
120 b'print(ascii("' + undecodable + b'"), '
121 b'locale.getpreferredencoding())')
122 p = subprocess.Popen(
123 [sys.executable, "-c", code],
124 stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
125 env=env)
126 stdout, stderr = p.communicate()
127 if p.returncode == 1:
128 # _Py_char2wchar() decoded b'\xff' as '\udcff' (b'\xff' is not
129 # decodable from ASCII) and run_command() failed on
130 # PyUnicode_AsUTF8String(). This is the expected behaviour on
131 # Linux.
132 pattern = b"Unable to decode the command from the command line:"
133 elif p.returncode == 0:
134 # _Py_char2wchar() decoded b'\xff' as '\xff' even if the locale is
135 # C and the locale encoding is ASCII. It occurs on FreeBSD, Solaris
136 # and Mac OS X.
137 pattern = b"'\\xff' "
138 # The output is followed by the encoding name, an alias to ASCII.
139 # Examples: "US-ASCII" or "646" (ISO 646, on Solaris).
140 else:
141 raise AssertionError("Unknown exit code: %s, output=%a" % (p.returncode, stdout))
142 if not stdout.startswith(pattern):
143 raise AssertionError("%a doesn't start with %a" % (stdout, pattern))
144
Victor Stinnerf933e1a2010-10-20 22:58:25 +0000145 @unittest.skipUnless(sys.platform == 'darwin', 'test specific to Mac OS X')
146 def test_osx_utf8(self):
147 def check_output(text):
Marc-André Lemburg8f36af72011-02-25 15:42:01 +0000148 decoded = text.decode('utf-8', 'surrogateescape')
Victor Stinnerf933e1a2010-10-20 22:58:25 +0000149 expected = ascii(decoded).encode('ascii') + b'\n'
150
151 env = os.environ.copy()
152 # C locale gives ASCII locale encoding, but Python uses UTF-8
153 # to parse the command line arguments on Mac OS X
154 env['LC_ALL'] = 'C'
155
156 p = subprocess.Popen(
157 (sys.executable, "-c", "import sys; print(ascii(sys.argv[1]))", text),
158 stdout=subprocess.PIPE,
159 env=env)
160 stdout, stderr = p.communicate()
161 self.assertEqual(stdout, expected)
162 self.assertEqual(p.returncode, 0)
163
164 # test valid utf-8
165 text = 'e:\xe9, euro:\u20ac, non-bmp:\U0010ffff'.encode('utf-8')
166 check_output(text)
167
168 # test invalid utf-8
169 text = (
170 b'\xff' # invalid byte
171 b'\xc3\xa9' # valid utf-8 character
172 b'\xc3\xff' # invalid byte sequence
173 b'\xed\xa0\x80' # lone surrogate character (invalid)
174 )
175 check_output(text)
176
Antoine Pitrou05608432009-01-09 18:53:14 +0000177 def test_unbuffered_output(self):
178 # Test expected operation of the '-u' switch
179 for stream in ('stdout', 'stderr'):
180 # Binary is unbuffered
181 code = ("import os, sys; sys.%s.buffer.write(b'x'); os._exit(0)"
182 % stream)
Antoine Pitrouf51d8d32010-10-08 18:05:42 +0000183 rc, out, err = assert_python_ok('-u', '-c', code)
184 data = err if stream == 'stderr' else out
Antoine Pitrou05608432009-01-09 18:53:14 +0000185 self.assertEqual(data, b'x', "binary %s not unbuffered" % stream)
186 # Text is line-buffered
187 code = ("import os, sys; sys.%s.write('x\\n'); os._exit(0)"
188 % stream)
Antoine Pitrouf51d8d32010-10-08 18:05:42 +0000189 rc, out, err = assert_python_ok('-u', '-c', code)
190 data = err if stream == 'stderr' else out
Antoine Pitrou05608432009-01-09 18:53:14 +0000191 self.assertEqual(data.strip(), b'x',
192 "text %s not line-buffered" % stream)
193
Antoine Pitrou27fe9fc2009-01-26 21:48:00 +0000194 def test_unbuffered_input(self):
195 # sys.stdin still works with '-u'
196 code = ("import sys; sys.stdout.write(sys.stdin.read(1))")
Nick Coghlan260bd3e2009-11-16 06:49:25 +0000197 p = spawn_python('-u', '-c', code)
Antoine Pitrou27fe9fc2009-01-26 21:48:00 +0000198 p.stdin.write(b'x')
199 p.stdin.flush()
200 data, rc = _kill_python_and_exit_code(p)
201 self.assertEqual(rc, 0)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000202 self.assertTrue(data.startswith(b'x'), data)
Antoine Pitrou27fe9fc2009-01-26 21:48:00 +0000203
Amaury Forgeot d'Arc66f8c432009-06-09 21:30:01 +0000204 def test_large_PYTHONPATH(self):
Antoine Pitrou9bc35682010-11-09 21:33:55 +0000205 path1 = "ABCDE" * 100
206 path2 = "FGHIJ" * 100
207 path = path1 + os.pathsep + path2
Victor Stinner76cf6872010-04-16 15:10:27 +0000208
Antoine Pitrou9bc35682010-11-09 21:33:55 +0000209 code = """if 1:
210 import sys
211 path = ":".join(sys.path)
212 path = path.encode("ascii", "backslashreplace")
213 sys.stdout.buffer.write(path)"""
214 rc, out, err = assert_python_ok('-S', '-c', code,
215 PYTHONPATH=path)
216 self.assertIn(path1.encode('ascii'), out)
217 self.assertIn(path2.encode('ascii'), out)
Amaury Forgeot d'Arc66f8c432009-06-09 21:30:01 +0000218
Victor Stinner13d49ee2010-12-04 17:24:33 +0000219 def test_displayhook_unencodable(self):
Marc-André Lemburg8f36af72011-02-25 15:42:01 +0000220 for encoding in ('ascii', 'latin-1', 'utf-8'):
Victor Stinner13d49ee2010-12-04 17:24:33 +0000221 env = os.environ.copy()
222 env['PYTHONIOENCODING'] = encoding
223 p = subprocess.Popen(
224 [sys.executable, '-i'],
225 stdin=subprocess.PIPE,
226 stdout=subprocess.PIPE,
227 stderr=subprocess.STDOUT,
228 env=env)
229 # non-ascii, surrogate, non-BMP printable, non-BMP unprintable
230 text = "a=\xe9 b=\uDC80 c=\U00010000 d=\U0010FFFF"
231 p.stdin.write(ascii(text).encode('ascii') + b"\n")
232 p.stdin.write(b'exit()\n')
233 data = kill_python(p)
234 escaped = repr(text).encode(encoding, 'backslashreplace')
235 self.assertIn(escaped, data)
236
Victor Stinnerc0f1a1a2011-02-23 12:07:37 +0000237 def check_input(self, code, expected):
238 with tempfile.NamedTemporaryFile("wb+") as stdin:
239 sep = os.linesep.encode('ASCII')
240 stdin.write(sep.join((b'abc', b'def')))
241 stdin.flush()
242 stdin.seek(0)
243 with subprocess.Popen(
244 (sys.executable, "-c", code),
245 stdin=stdin, stdout=subprocess.PIPE) as proc:
246 stdout, stderr = proc.communicate()
247 self.assertEqual(stdout.rstrip(), expected)
248
249 def test_stdin_readline(self):
250 # Issue #11272: check that sys.stdin.readline() replaces '\r\n' by '\n'
251 # on Windows (sys.stdin is opened in binary mode)
252 self.check_input(
253 "import sys; print(repr(sys.stdin.readline()))",
254 b"'abc\\n'")
255
256 def test_builtin_input(self):
257 # Issue #11272: check that input() strips newlines ('\n' or '\r\n')
258 self.check_input(
259 "print(repr(input()))",
260 b"'abc'")
261
Thomas Wouters477c8d52006-05-27 19:21:47 +0000262
Neal Norwitz11bd1192005-10-03 00:54:56 +0000263def test_main():
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000264 test.support.run_unittest(CmdLineTest)
265 test.support.reap_children()
Neal Norwitz11bd1192005-10-03 00:54:56 +0000266
267if __name__ == "__main__":
268 test_main()