blob: a89d7e4f1094532cf11f4ed6d497a227d85c82d2 [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
Ezio Melotti7c663192012-11-18 13:55:52 +020010from test.script_helper import (spawn_python, kill_python, assert_python_ok,
11 assert_python_failure)
Thomas Woutersed03b412007-08-28 21:37:11 +000012
Trent Nelson39e307e2008-03-19 06:45:48 +000013
Nick Coghlan260bd3e2009-11-16 06:49:25 +000014# XXX (ncoghlan): Move to script_helper and make consistent with run_python
Trent Nelson39e307e2008-03-19 06:45:48 +000015def _kill_python_and_exit_code(p):
Nick Coghlan260bd3e2009-11-16 06:49:25 +000016 data = kill_python(p)
Trent Nelson39e307e2008-03-19 06:45:48 +000017 returncode = p.wait()
18 return data, returncode
Thomas Woutersed03b412007-08-28 21:37:11 +000019
Neal Norwitz11bd1192005-10-03 00:54:56 +000020class CmdLineTest(unittest.TestCase):
Neal Norwitz11bd1192005-10-03 00:54:56 +000021 def test_directories(self):
Antoine Pitrouf51d8d32010-10-08 18:05:42 +000022 assert_python_failure('.')
23 assert_python_failure('< .')
Neal Norwitz11bd1192005-10-03 00:54:56 +000024
25 def verify_valid_flag(self, cmd_line):
Antoine Pitrouf51d8d32010-10-08 18:05:42 +000026 rc, out, err = assert_python_ok(*cmd_line)
27 self.assertTrue(out == b'' or out.endswith(b'\n'))
28 self.assertNotIn(b'Traceback', out)
29 self.assertNotIn(b'Traceback', err)
Neal Norwitz11bd1192005-10-03 00:54:56 +000030
Neal Norwitz11bd1192005-10-03 00:54:56 +000031 def test_optimize(self):
32 self.verify_valid_flag('-O')
33 self.verify_valid_flag('-OO')
34
Neal Norwitz11bd1192005-10-03 00:54:56 +000035 def test_site_flag(self):
36 self.verify_valid_flag('-S')
37
38 def test_usage(self):
Antoine Pitrouf51d8d32010-10-08 18:05:42 +000039 rc, out, err = assert_python_ok('-h')
40 self.assertIn(b'usage', out)
Neal Norwitz11bd1192005-10-03 00:54:56 +000041
42 def test_version(self):
Guido van Rossuma1c42a92007-08-29 03:47:36 +000043 version = ('Python %d.%d' % sys.version_info[:2]).encode("ascii")
Antoine Pitrouf51d8d32010-10-08 18:05:42 +000044 rc, out, err = assert_python_ok('-V')
45 self.assertTrue(err.startswith(version))
Neal Norwitz11bd1192005-10-03 00:54:56 +000046
Trent Nelson39e307e2008-03-19 06:45:48 +000047 def test_verbose(self):
48 # -v causes imports to write to stderr. If the write to
49 # stderr itself causes an import to happen (for the output
50 # codec), a recursion loop can occur.
Antoine Pitrouf51d8d32010-10-08 18:05:42 +000051 rc, out, err = assert_python_ok('-v')
52 self.assertNotIn(b'stack overflow', err)
53 rc, out, err = assert_python_ok('-vv')
54 self.assertNotIn(b'stack overflow', err)
Trent Nelson39e307e2008-03-19 06:45:48 +000055
Antoine Pitrou9583cac2010-10-21 13:42:28 +000056 def test_xoptions(self):
57 rc, out, err = assert_python_ok('-c', 'import sys; print(sys._xoptions)')
58 opts = eval(out.splitlines()[0])
59 self.assertEqual(opts, {})
60 rc, out, err = assert_python_ok(
61 '-Xa', '-Xb=c,d=e', '-c', 'import sys; print(sys._xoptions)')
62 opts = eval(out.splitlines()[0])
63 self.assertEqual(opts, {'a': True, 'b': 'c,d=e'})
64
Thomas Wouters477c8d52006-05-27 19:21:47 +000065 def test_run_module(self):
66 # Test expected operation of the '-m' switch
67 # Switch needs an argument
Antoine Pitrouf51d8d32010-10-08 18:05:42 +000068 assert_python_failure('-m')
Thomas Wouters477c8d52006-05-27 19:21:47 +000069 # Check we get an error for a nonexistent module
Antoine Pitrouf51d8d32010-10-08 18:05:42 +000070 assert_python_failure('-m', 'fnord43520xyz')
Thomas Wouters477c8d52006-05-27 19:21:47 +000071 # Check the runpy module also gives an error for
72 # a nonexistent module
Antoine Pitrouf51d8d32010-10-08 18:05:42 +000073 assert_python_failure('-m', 'runpy', 'fnord43520xyz'),
Thomas Wouters477c8d52006-05-27 19:21:47 +000074 # All good if module is located and run successfully
Antoine Pitrouf51d8d32010-10-08 18:05:42 +000075 assert_python_ok('-m', 'timeit', '-n', '1'),
Thomas Wouters477c8d52006-05-27 19:21:47 +000076
Thomas Woutersed03b412007-08-28 21:37:11 +000077 def test_run_module_bug1764407(self):
78 # -m and -i need to play well together
79 # Runs the timeit module and checks the __main__
80 # namespace has been populated appropriately
Nick Coghlan260bd3e2009-11-16 06:49:25 +000081 p = spawn_python('-i', '-m', 'timeit', '-n', '1')
Guido van Rossuma1c42a92007-08-29 03:47:36 +000082 p.stdin.write(b'Timer\n')
83 p.stdin.write(b'exit()\n')
Nick Coghlan260bd3e2009-11-16 06:49:25 +000084 data = kill_python(p)
Thomas Woutersed03b412007-08-28 21:37:11 +000085 self.assertTrue(data.find(b'1 loop') != -1)
86 self.assertTrue(data.find(b'__main__.Timer') != -1)
87
Thomas Wouters477c8d52006-05-27 19:21:47 +000088 def test_run_code(self):
89 # Test expected operation of the '-c' switch
90 # Switch needs an argument
Antoine Pitrouf51d8d32010-10-08 18:05:42 +000091 assert_python_failure('-c')
Thomas Wouters477c8d52006-05-27 19:21:47 +000092 # Check we get an error for an uncaught exception
Antoine Pitrouf51d8d32010-10-08 18:05:42 +000093 assert_python_failure('-c', 'raise Exception')
Thomas Wouters477c8d52006-05-27 19:21:47 +000094 # All good if execution is successful
Antoine Pitrouf51d8d32010-10-08 18:05:42 +000095 assert_python_ok('-c', 'pass')
Thomas Wouters477c8d52006-05-27 19:21:47 +000096
Victor Stinnere667e982012-11-12 01:23:15 +010097 @unittest.skipUnless(test.support.FS_NONASCII, 'need support.FS_NONASCII')
Victor Stinner073f7592010-10-20 21:56:55 +000098 def test_non_ascii(self):
Amaury Forgeot d'Arc9a5499b2008-11-11 23:04:59 +000099 # Test handling of non-ascii data
Victor Stinnere667e982012-11-12 01:23:15 +0100100 command = ("assert(ord(%r) == %s)"
101 % (test.support.FS_NONASCII, ord(test.support.FS_NONASCII)))
Victor Stinner073f7592010-10-20 21:56:55 +0000102 assert_python_ok('-c', command)
Amaury Forgeot d'Arc9a5499b2008-11-11 23:04:59 +0000103
Victor Stinnerf6211ed2010-10-20 21:52:33 +0000104 # On Windows, pass bytes to subprocess doesn't test how Python decodes the
105 # command line, but how subprocess does decode bytes to unicode. Python
106 # doesn't decode the command line because Windows provides directly the
107 # arguments as unicode (using wmain() instead of main()).
108 @unittest.skipIf(sys.platform == 'win32',
109 'Windows has a native unicode API')
110 def test_undecodable_code(self):
111 undecodable = b"\xff"
112 env = os.environ.copy()
113 # Use C locale to get ascii for the locale encoding
114 env['LC_ALL'] = 'C'
115 code = (
116 b'import locale; '
117 b'print(ascii("' + undecodable + b'"), '
118 b'locale.getpreferredencoding())')
119 p = subprocess.Popen(
120 [sys.executable, "-c", code],
121 stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
122 env=env)
123 stdout, stderr = p.communicate()
124 if p.returncode == 1:
125 # _Py_char2wchar() decoded b'\xff' as '\udcff' (b'\xff' is not
126 # decodable from ASCII) and run_command() failed on
127 # PyUnicode_AsUTF8String(). This is the expected behaviour on
128 # Linux.
129 pattern = b"Unable to decode the command from the command line:"
130 elif p.returncode == 0:
131 # _Py_char2wchar() decoded b'\xff' as '\xff' even if the locale is
132 # C and the locale encoding is ASCII. It occurs on FreeBSD, Solaris
133 # and Mac OS X.
134 pattern = b"'\\xff' "
135 # The output is followed by the encoding name, an alias to ASCII.
136 # Examples: "US-ASCII" or "646" (ISO 646, on Solaris).
137 else:
138 raise AssertionError("Unknown exit code: %s, output=%a" % (p.returncode, stdout))
139 if not stdout.startswith(pattern):
140 raise AssertionError("%a doesn't start with %a" % (stdout, pattern))
141
Victor Stinnerf933e1a2010-10-20 22:58:25 +0000142 @unittest.skipUnless(sys.platform == 'darwin', 'test specific to Mac OS X')
143 def test_osx_utf8(self):
144 def check_output(text):
Marc-André Lemburg8f36af72011-02-25 15:42:01 +0000145 decoded = text.decode('utf-8', 'surrogateescape')
Victor Stinnerf933e1a2010-10-20 22:58:25 +0000146 expected = ascii(decoded).encode('ascii') + b'\n'
147
148 env = os.environ.copy()
149 # C locale gives ASCII locale encoding, but Python uses UTF-8
150 # to parse the command line arguments on Mac OS X
151 env['LC_ALL'] = 'C'
152
153 p = subprocess.Popen(
154 (sys.executable, "-c", "import sys; print(ascii(sys.argv[1]))", text),
155 stdout=subprocess.PIPE,
156 env=env)
157 stdout, stderr = p.communicate()
158 self.assertEqual(stdout, expected)
159 self.assertEqual(p.returncode, 0)
160
161 # test valid utf-8
162 text = 'e:\xe9, euro:\u20ac, non-bmp:\U0010ffff'.encode('utf-8')
163 check_output(text)
164
165 # test invalid utf-8
166 text = (
167 b'\xff' # invalid byte
168 b'\xc3\xa9' # valid utf-8 character
169 b'\xc3\xff' # invalid byte sequence
170 b'\xed\xa0\x80' # lone surrogate character (invalid)
171 )
172 check_output(text)
173
Antoine Pitrou05608432009-01-09 18:53:14 +0000174 def test_unbuffered_output(self):
175 # Test expected operation of the '-u' switch
176 for stream in ('stdout', 'stderr'):
177 # Binary is unbuffered
178 code = ("import os, sys; sys.%s.buffer.write(b'x'); os._exit(0)"
179 % stream)
Antoine Pitrouf51d8d32010-10-08 18:05:42 +0000180 rc, out, err = assert_python_ok('-u', '-c', code)
181 data = err if stream == 'stderr' else out
Antoine Pitrou05608432009-01-09 18:53:14 +0000182 self.assertEqual(data, b'x', "binary %s not unbuffered" % stream)
183 # Text is line-buffered
184 code = ("import os, sys; sys.%s.write('x\\n'); os._exit(0)"
185 % stream)
Antoine Pitrouf51d8d32010-10-08 18:05:42 +0000186 rc, out, err = assert_python_ok('-u', '-c', code)
187 data = err if stream == 'stderr' else out
Antoine Pitrou05608432009-01-09 18:53:14 +0000188 self.assertEqual(data.strip(), b'x',
189 "text %s not line-buffered" % stream)
190
Antoine Pitrou27fe9fc2009-01-26 21:48:00 +0000191 def test_unbuffered_input(self):
192 # sys.stdin still works with '-u'
193 code = ("import sys; sys.stdout.write(sys.stdin.read(1))")
Nick Coghlan260bd3e2009-11-16 06:49:25 +0000194 p = spawn_python('-u', '-c', code)
Antoine Pitrou27fe9fc2009-01-26 21:48:00 +0000195 p.stdin.write(b'x')
196 p.stdin.flush()
197 data, rc = _kill_python_and_exit_code(p)
198 self.assertEqual(rc, 0)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000199 self.assertTrue(data.startswith(b'x'), data)
Antoine Pitrou27fe9fc2009-01-26 21:48:00 +0000200
Amaury Forgeot d'Arc66f8c432009-06-09 21:30:01 +0000201 def test_large_PYTHONPATH(self):
Antoine Pitrou9bc35682010-11-09 21:33:55 +0000202 path1 = "ABCDE" * 100
203 path2 = "FGHIJ" * 100
204 path = path1 + os.pathsep + path2
Victor Stinner76cf6872010-04-16 15:10:27 +0000205
Antoine Pitrou9bc35682010-11-09 21:33:55 +0000206 code = """if 1:
207 import sys
208 path = ":".join(sys.path)
209 path = path.encode("ascii", "backslashreplace")
210 sys.stdout.buffer.write(path)"""
211 rc, out, err = assert_python_ok('-S', '-c', code,
212 PYTHONPATH=path)
213 self.assertIn(path1.encode('ascii'), out)
214 self.assertIn(path2.encode('ascii'), out)
Amaury Forgeot d'Arc66f8c432009-06-09 21:30:01 +0000215
Victor Stinner13d49ee2010-12-04 17:24:33 +0000216 def test_displayhook_unencodable(self):
Marc-André Lemburg8f36af72011-02-25 15:42:01 +0000217 for encoding in ('ascii', 'latin-1', 'utf-8'):
Victor Stinner13d49ee2010-12-04 17:24:33 +0000218 env = os.environ.copy()
219 env['PYTHONIOENCODING'] = encoding
220 p = subprocess.Popen(
221 [sys.executable, '-i'],
222 stdin=subprocess.PIPE,
223 stdout=subprocess.PIPE,
224 stderr=subprocess.STDOUT,
225 env=env)
226 # non-ascii, surrogate, non-BMP printable, non-BMP unprintable
227 text = "a=\xe9 b=\uDC80 c=\U00010000 d=\U0010FFFF"
228 p.stdin.write(ascii(text).encode('ascii') + b"\n")
229 p.stdin.write(b'exit()\n')
230 data = kill_python(p)
231 escaped = repr(text).encode(encoding, 'backslashreplace')
232 self.assertIn(escaped, data)
233
Victor Stinnerc0f1a1a2011-02-23 12:07:37 +0000234 def check_input(self, code, expected):
235 with tempfile.NamedTemporaryFile("wb+") as stdin:
236 sep = os.linesep.encode('ASCII')
237 stdin.write(sep.join((b'abc', b'def')))
238 stdin.flush()
239 stdin.seek(0)
240 with subprocess.Popen(
241 (sys.executable, "-c", code),
242 stdin=stdin, stdout=subprocess.PIPE) as proc:
243 stdout, stderr = proc.communicate()
244 self.assertEqual(stdout.rstrip(), expected)
245
246 def test_stdin_readline(self):
247 # Issue #11272: check that sys.stdin.readline() replaces '\r\n' by '\n'
248 # on Windows (sys.stdin is opened in binary mode)
249 self.check_input(
250 "import sys; print(repr(sys.stdin.readline()))",
251 b"'abc\\n'")
252
253 def test_builtin_input(self):
254 # Issue #11272: check that input() strips newlines ('\n' or '\r\n')
255 self.check_input(
256 "print(repr(input()))",
257 b"'abc'")
258
Victor Stinner7b3f0fa2012-08-04 01:28:00 +0200259 def test_output_newline(self):
260 # Issue 13119 Newline for print() should be \r\n on Windows.
261 code = """if 1:
262 import sys
263 print(1)
264 print(2)
265 print(3, file=sys.stderr)
266 print(4, file=sys.stderr)"""
267 rc, out, err = assert_python_ok('-c', code)
268
269 if sys.platform == 'win32':
270 self.assertEqual(b'1\r\n2\r\n', out)
271 self.assertEqual(b'3\r\n4', err)
272 else:
273 self.assertEqual(b'1\n2\n', out)
274 self.assertEqual(b'3\n4', err)
275
R David Murraye697e372011-06-24 13:26:31 -0400276 def test_unmached_quote(self):
277 # Issue #10206: python program starting with unmatched quote
278 # spewed spaces to stdout
279 rc, out, err = assert_python_failure('-c', "'")
280 self.assertRegex(err.decode('ascii', 'ignore'), 'SyntaxError')
281 self.assertEqual(b'', out)
282
Antoine Pitroud7c8fbf2011-11-26 21:59:36 +0100283 def test_stdout_flush_at_shutdown(self):
284 # Issue #5319: if stdout.flush() fails at shutdown, an error should
285 # be printed out.
286 code = """if 1:
287 import os, sys
288 sys.stdout.write('x')
289 os.close(sys.stdout.fileno())"""
290 rc, out, err = assert_python_ok('-c', code)
291 self.assertEqual(b'', out)
292 self.assertRegex(err.decode('ascii', 'ignore'),
Antoine Pitrou5604ef32011-11-26 22:02:29 +0100293 'Exception OSError: .* ignored')
Antoine Pitroud7c8fbf2011-11-26 21:59:36 +0100294
295 def test_closed_stdout(self):
296 # Issue #13444: if stdout has been explicitly closed, we should
297 # not attempt to flush it at shutdown.
298 code = "import sys; sys.stdout.close()"
299 rc, out, err = assert_python_ok('-c', code)
300 self.assertEqual(b'', err)
301
Antoine Pitrou11942a52011-11-28 19:08:36 +0100302 # Issue #7111: Python should work without standard streams
303
304 @unittest.skipIf(os.name != 'posix', "test needs POSIX semantics")
305 def _test_no_stdio(self, streams):
306 code = """if 1:
307 import os, sys
308 for i, s in enumerate({streams}):
309 if getattr(sys, s) is not None:
310 os._exit(i + 1)
311 os._exit(42)""".format(streams=streams)
312 def preexec():
313 if 'stdin' in streams:
314 os.close(0)
315 if 'stdout' in streams:
316 os.close(1)
317 if 'stderr' in streams:
318 os.close(2)
319 p = subprocess.Popen(
320 [sys.executable, "-E", "-c", code],
321 stdin=subprocess.PIPE,
322 stdout=subprocess.PIPE,
323 stderr=subprocess.PIPE,
324 preexec_fn=preexec)
325 out, err = p.communicate()
326 self.assertEqual(test.support.strip_python_stderr(err), b'')
327 self.assertEqual(p.returncode, 42)
328
329 def test_no_stdin(self):
330 self._test_no_stdio(['stdin'])
331
332 def test_no_stdout(self):
333 self._test_no_stdio(['stdout'])
334
335 def test_no_stderr(self):
336 self._test_no_stdio(['stderr'])
337
338 def test_no_std_streams(self):
339 self._test_no_stdio(['stdin', 'stdout', 'stderr'])
340
Georg Brandl2daf6ae2012-02-20 19:54:16 +0100341 def test_hash_randomization(self):
342 # Verify that -R enables hash randomization:
343 self.verify_valid_flag('-R')
344 hashes = []
345 for i in range(2):
346 code = 'print(hash("spam"))'
Benjamin Petersonc9f54cf2012-02-21 16:08:05 -0500347 rc, out, err = assert_python_ok('-c', code)
Georg Brandl2daf6ae2012-02-20 19:54:16 +0100348 self.assertEqual(rc, 0)
Georg Brandl09a7c722012-02-20 21:31:46 +0100349 hashes.append(out)
Georg Brandl2daf6ae2012-02-20 19:54:16 +0100350 self.assertNotEqual(hashes[0], hashes[1])
351
352 # Verify that sys.flags contains hash_randomization
353 code = 'import sys; print("random is", sys.flags.hash_randomization)'
Benjamin Petersonc9f54cf2012-02-21 16:08:05 -0500354 rc, out, err = assert_python_ok('-c', code)
Georg Brandl2daf6ae2012-02-20 19:54:16 +0100355 self.assertEqual(rc, 0)
Georg Brandl09a7c722012-02-20 21:31:46 +0100356 self.assertIn(b'random is 1', out)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000357
Hynek Schlawack5c6b3e22012-11-07 09:02:24 +0100358 def test_del___main__(self):
359 # Issue #15001: PyRun_SimpleFileExFlags() did crash because it kept a
360 # borrowed reference to the dict of __main__ module and later modify
361 # the dict whereas the module was destroyed
362 filename = test.support.TESTFN
363 self.addCleanup(test.support.unlink, filename)
364 with open(filename, "w") as script:
365 print("import sys", file=script)
366 print("del sys.modules['__main__']", file=script)
367 assert_python_ok(filename)
368
Ezio Melotti7c663192012-11-18 13:55:52 +0200369 def test_unknown_options(self):
Ezio Melottia0dd22e2012-11-23 18:48:32 +0200370 rc, out, err = assert_python_failure('-E', '-z')
371 self.assertIn(b'Unknown option: -z', err)
Ezio Melotti7c663192012-11-18 13:55:52 +0200372 self.assertEqual(err.splitlines().count(b'Unknown option: -z'), 1)
373 self.assertEqual(b'', out)
Ezio Melottia0dd22e2012-11-23 18:48:32 +0200374 # Add "without='-E'" to prevent _assert_python to append -E
375 # to env_vars and change the output of stderr
376 rc, out, err = assert_python_failure('-z', without='-E')
377 self.assertIn(b'Unknown option: -z', err)
378 self.assertEqual(err.splitlines().count(b'Unknown option: -z'), 1)
379 self.assertEqual(b'', out)
380 rc, out, err = assert_python_failure('-a', '-z', without='-E')
381 self.assertIn(b'Unknown option: -a', err)
382 # only the first unknown option is reported
383 self.assertNotIn(b'Unknown option: -z', err)
384 self.assertEqual(err.splitlines().count(b'Unknown option: -a'), 1)
385 self.assertEqual(b'', out)
386
Ezio Melotti7c663192012-11-18 13:55:52 +0200387
Neal Norwitz11bd1192005-10-03 00:54:56 +0000388def test_main():
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000389 test.support.run_unittest(CmdLineTest)
390 test.support.reap_children()
Neal Norwitz11bd1192005-10-03 00:54:56 +0000391
392if __name__ == "__main__":
393 test_main()