blob: f7925eb795c71e684966e9415a2cdd7b099ad78c [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
Antoine Pitrou87695762008-08-14 22:44:29 +00005import os
Nick Coghlan260bd3e2009-11-16 06:49:25 +00006import subprocess
Victor Stinnerccb04422017-11-16 03:20:31 -08007import sys
Victor Stinner5d39e042017-11-29 17:20:38 +01008import sysconfig
Victor Stinnerc0f1a1a2011-02-23 12:07:37 +00009import tempfile
Victor Stinnerccb04422017-11-16 03:20:31 -080010import unittest
11from test import support
Nick Coghlan6ea41862017-06-11 13:16:15 +100012from test.support.script_helper import (
Victor Stinnerccb04422017-11-16 03:20:31 -080013 spawn_python, kill_python, assert_python_ok, assert_python_failure,
14 interpreter_requires_environment
Nick Coghlan6ea41862017-06-11 13:16:15 +100015)
Thomas Woutersed03b412007-08-28 21:37:11 +000016
Victor Stinner747f48e2017-12-12 22:59:48 +010017
18# Debug build?
19Py_DEBUG = hasattr(sys, "gettotalrefcount")
20
21
Nick Coghlan260bd3e2009-11-16 06:49:25 +000022# XXX (ncoghlan): Move to script_helper and make consistent with run_python
Trent Nelson39e307e2008-03-19 06:45:48 +000023def _kill_python_and_exit_code(p):
Nick Coghlan260bd3e2009-11-16 06:49:25 +000024 data = kill_python(p)
Trent Nelson39e307e2008-03-19 06:45:48 +000025 returncode = p.wait()
26 return data, returncode
Thomas Woutersed03b412007-08-28 21:37:11 +000027
Neal Norwitz11bd1192005-10-03 00:54:56 +000028class CmdLineTest(unittest.TestCase):
Neal Norwitz11bd1192005-10-03 00:54:56 +000029 def test_directories(self):
Antoine Pitrouf51d8d32010-10-08 18:05:42 +000030 assert_python_failure('.')
31 assert_python_failure('< .')
Neal Norwitz11bd1192005-10-03 00:54:56 +000032
33 def verify_valid_flag(self, cmd_line):
Antoine Pitrouf51d8d32010-10-08 18:05:42 +000034 rc, out, err = assert_python_ok(*cmd_line)
35 self.assertTrue(out == b'' or out.endswith(b'\n'))
36 self.assertNotIn(b'Traceback', out)
37 self.assertNotIn(b'Traceback', err)
Neal Norwitz11bd1192005-10-03 00:54:56 +000038
Neal Norwitz11bd1192005-10-03 00:54:56 +000039 def test_optimize(self):
40 self.verify_valid_flag('-O')
41 self.verify_valid_flag('-OO')
42
Neal Norwitz11bd1192005-10-03 00:54:56 +000043 def test_site_flag(self):
44 self.verify_valid_flag('-S')
45
46 def test_usage(self):
Antoine Pitrouf51d8d32010-10-08 18:05:42 +000047 rc, out, err = assert_python_ok('-h')
48 self.assertIn(b'usage', out)
Neal Norwitz11bd1192005-10-03 00:54:56 +000049
50 def test_version(self):
Guido van Rossuma1c42a92007-08-29 03:47:36 +000051 version = ('Python %d.%d' % sys.version_info[:2]).encode("ascii")
INADA Naoki0e175a62016-11-21 20:57:14 +090052 for switch in '-V', '--version', '-VV':
Serhiy Storchakae3ed4ed2013-07-11 20:01:17 +030053 rc, out, err = assert_python_ok(switch)
54 self.assertFalse(err.startswith(version))
55 self.assertTrue(out.startswith(version))
Neal Norwitz11bd1192005-10-03 00:54:56 +000056
Trent Nelson39e307e2008-03-19 06:45:48 +000057 def test_verbose(self):
58 # -v causes imports to write to stderr. If the write to
59 # stderr itself causes an import to happen (for the output
60 # codec), a recursion loop can occur.
Antoine Pitrouf51d8d32010-10-08 18:05:42 +000061 rc, out, err = assert_python_ok('-v')
62 self.assertNotIn(b'stack overflow', err)
63 rc, out, err = assert_python_ok('-vv')
64 self.assertNotIn(b'stack overflow', err)
Trent Nelson39e307e2008-03-19 06:45:48 +000065
Steve Dower01423cb2018-02-17 18:59:03 -080066 @unittest.skipIf(interpreter_requires_environment(),
67 'Cannot run -E tests when PYTHON env vars are required.')
Antoine Pitrou9583cac2010-10-21 13:42:28 +000068 def test_xoptions(self):
Victor Stinneref8115e2013-06-25 21:54:17 +020069 def get_xoptions(*args):
Berker Peksagce643912015-05-06 06:33:17 +030070 # use subprocess module directly because test.support.script_helper adds
Victor Stinneref8115e2013-06-25 21:54:17 +020071 # "-X faulthandler" to the command line
72 args = (sys.executable, '-E') + args
73 args += ('-c', 'import sys; print(sys._xoptions)')
74 out = subprocess.check_output(args)
75 opts = eval(out.splitlines()[0])
76 return opts
77
78 opts = get_xoptions()
Antoine Pitrou9583cac2010-10-21 13:42:28 +000079 self.assertEqual(opts, {})
Victor Stinneref8115e2013-06-25 21:54:17 +020080
81 opts = get_xoptions('-Xa', '-Xb=c,d=e')
Antoine Pitrou9583cac2010-10-21 13:42:28 +000082 self.assertEqual(opts, {'a': True, 'b': 'c,d=e'})
83
Ezio Melotti1f8898a2013-03-26 01:59:56 +020084 def test_showrefcount(self):
85 def run_python(*args):
86 # this is similar to assert_python_ok but doesn't strip
87 # the refcount from stderr. It can be replaced once
88 # assert_python_ok stops doing that.
89 cmd = [sys.executable]
90 cmd.extend(args)
91 PIPE = subprocess.PIPE
92 p = subprocess.Popen(cmd, stdout=PIPE, stderr=PIPE)
93 out, err = p.communicate()
94 p.stdout.close()
95 p.stderr.close()
96 rc = p.returncode
97 self.assertEqual(rc, 0)
98 return rc, out, err
99 code = 'import sys; print(sys._xoptions)'
100 # normally the refcount is hidden
101 rc, out, err = run_python('-c', code)
102 self.assertEqual(out.rstrip(), b'{}')
103 self.assertEqual(err, b'')
104 # "-X showrefcount" shows the refcount, but only in debug builds
105 rc, out, err = run_python('-X', 'showrefcount', '-c', code)
106 self.assertEqual(out.rstrip(), b"{'showrefcount': True}")
Victor Stinner747f48e2017-12-12 22:59:48 +0100107 if Py_DEBUG:
Ezio Melotti1f8898a2013-03-26 01:59:56 +0200108 self.assertRegex(err, br'^\[\d+ refs, \d+ blocks\]')
109 else:
110 self.assertEqual(err, b'')
111
Thomas Wouters477c8d52006-05-27 19:21:47 +0000112 def test_run_module(self):
113 # Test expected operation of the '-m' switch
114 # Switch needs an argument
Antoine Pitrouf51d8d32010-10-08 18:05:42 +0000115 assert_python_failure('-m')
Thomas Wouters477c8d52006-05-27 19:21:47 +0000116 # Check we get an error for a nonexistent module
Antoine Pitrouf51d8d32010-10-08 18:05:42 +0000117 assert_python_failure('-m', 'fnord43520xyz')
Thomas Wouters477c8d52006-05-27 19:21:47 +0000118 # Check the runpy module also gives an error for
119 # a nonexistent module
Victor Stinner3fa1aae2013-03-26 01:14:08 +0100120 assert_python_failure('-m', 'runpy', 'fnord43520xyz')
Thomas Wouters477c8d52006-05-27 19:21:47 +0000121 # All good if module is located and run successfully
Victor Stinner3fa1aae2013-03-26 01:14:08 +0100122 assert_python_ok('-m', 'timeit', '-n', '1')
Thomas Wouters477c8d52006-05-27 19:21:47 +0000123
Thomas Woutersed03b412007-08-28 21:37:11 +0000124 def test_run_module_bug1764407(self):
125 # -m and -i need to play well together
126 # Runs the timeit module and checks the __main__
127 # namespace has been populated appropriately
Nick Coghlan260bd3e2009-11-16 06:49:25 +0000128 p = spawn_python('-i', '-m', 'timeit', '-n', '1')
Guido van Rossuma1c42a92007-08-29 03:47:36 +0000129 p.stdin.write(b'Timer\n')
130 p.stdin.write(b'exit()\n')
Nick Coghlan260bd3e2009-11-16 06:49:25 +0000131 data = kill_python(p)
Thomas Woutersed03b412007-08-28 21:37:11 +0000132 self.assertTrue(data.find(b'1 loop') != -1)
133 self.assertTrue(data.find(b'__main__.Timer') != -1)
134
Thomas Wouters477c8d52006-05-27 19:21:47 +0000135 def test_run_code(self):
136 # Test expected operation of the '-c' switch
137 # Switch needs an argument
Antoine Pitrouf51d8d32010-10-08 18:05:42 +0000138 assert_python_failure('-c')
Thomas Wouters477c8d52006-05-27 19:21:47 +0000139 # Check we get an error for an uncaught exception
Antoine Pitrouf51d8d32010-10-08 18:05:42 +0000140 assert_python_failure('-c', 'raise Exception')
Thomas Wouters477c8d52006-05-27 19:21:47 +0000141 # All good if execution is successful
Antoine Pitrouf51d8d32010-10-08 18:05:42 +0000142 assert_python_ok('-c', 'pass')
Thomas Wouters477c8d52006-05-27 19:21:47 +0000143
Victor Stinnerccb04422017-11-16 03:20:31 -0800144 @unittest.skipUnless(support.FS_NONASCII, 'need support.FS_NONASCII')
Victor Stinner073f7592010-10-20 21:56:55 +0000145 def test_non_ascii(self):
Amaury Forgeot d'Arc9a5499b2008-11-11 23:04:59 +0000146 # Test handling of non-ascii data
Victor Stinner8b219b22012-11-06 23:23:43 +0100147 command = ("assert(ord(%r) == %s)"
Victor Stinnerccb04422017-11-16 03:20:31 -0800148 % (support.FS_NONASCII, ord(support.FS_NONASCII)))
Victor Stinner073f7592010-10-20 21:56:55 +0000149 assert_python_ok('-c', command)
Amaury Forgeot d'Arc9a5499b2008-11-11 23:04:59 +0000150
Victor Stinnerf6211ed2010-10-20 21:52:33 +0000151 # On Windows, pass bytes to subprocess doesn't test how Python decodes the
152 # command line, but how subprocess does decode bytes to unicode. Python
153 # doesn't decode the command line because Windows provides directly the
154 # arguments as unicode (using wmain() instead of main()).
155 @unittest.skipIf(sys.platform == 'win32',
156 'Windows has a native unicode API')
157 def test_undecodable_code(self):
158 undecodable = b"\xff"
159 env = os.environ.copy()
160 # Use C locale to get ascii for the locale encoding
161 env['LC_ALL'] = 'C'
Victor Stinner06e76082018-09-19 14:56:36 -0700162 env['PYTHONCOERCECLOCALE'] = '0'
Victor Stinnerf6211ed2010-10-20 21:52:33 +0000163 code = (
164 b'import locale; '
165 b'print(ascii("' + undecodable + b'"), '
166 b'locale.getpreferredencoding())')
167 p = subprocess.Popen(
Victor Stinner06e76082018-09-19 14:56:36 -0700168 [sys.executable, "-c", code],
Victor Stinnerf6211ed2010-10-20 21:52:33 +0000169 stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
170 env=env)
171 stdout, stderr = p.communicate()
172 if p.returncode == 1:
173 # _Py_char2wchar() decoded b'\xff' as '\udcff' (b'\xff' is not
174 # decodable from ASCII) and run_command() failed on
175 # PyUnicode_AsUTF8String(). This is the expected behaviour on
176 # Linux.
177 pattern = b"Unable to decode the command from the command line:"
178 elif p.returncode == 0:
179 # _Py_char2wchar() decoded b'\xff' as '\xff' even if the locale is
180 # C and the locale encoding is ASCII. It occurs on FreeBSD, Solaris
181 # and Mac OS X.
182 pattern = b"'\\xff' "
183 # The output is followed by the encoding name, an alias to ASCII.
184 # Examples: "US-ASCII" or "646" (ISO 646, on Solaris).
185 else:
186 raise AssertionError("Unknown exit code: %s, output=%a" % (p.returncode, stdout))
187 if not stdout.startswith(pattern):
188 raise AssertionError("%a doesn't start with %a" % (stdout, pattern))
189
Victor Stinner937ee9e2018-06-26 02:11:06 +0200190 @unittest.skipUnless((sys.platform == 'darwin' or
191 support.is_android), 'test specific to Mac OS X and Android')
Xavier de Gaye76febd02016-12-15 20:59:58 +0100192 def test_osx_android_utf8(self):
Victor Stinnerf933e1a2010-10-20 22:58:25 +0000193 def check_output(text):
Marc-André Lemburg8f36af72011-02-25 15:42:01 +0000194 decoded = text.decode('utf-8', 'surrogateescape')
Victor Stinnerf933e1a2010-10-20 22:58:25 +0000195 expected = ascii(decoded).encode('ascii') + b'\n'
196
197 env = os.environ.copy()
198 # C locale gives ASCII locale encoding, but Python uses UTF-8
Xavier de Gaye76febd02016-12-15 20:59:58 +0100199 # to parse the command line arguments on Mac OS X and Android.
Victor Stinnerf933e1a2010-10-20 22:58:25 +0000200 env['LC_ALL'] = 'C'
201
202 p = subprocess.Popen(
203 (sys.executable, "-c", "import sys; print(ascii(sys.argv[1]))", text),
204 stdout=subprocess.PIPE,
205 env=env)
206 stdout, stderr = p.communicate()
207 self.assertEqual(stdout, expected)
208 self.assertEqual(p.returncode, 0)
209
210 # test valid utf-8
211 text = 'e:\xe9, euro:\u20ac, non-bmp:\U0010ffff'.encode('utf-8')
212 check_output(text)
213
214 # test invalid utf-8
215 text = (
216 b'\xff' # invalid byte
217 b'\xc3\xa9' # valid utf-8 character
218 b'\xc3\xff' # invalid byte sequence
219 b'\xed\xa0\x80' # lone surrogate character (invalid)
220 )
221 check_output(text)
222
Antoine Pitrou05608432009-01-09 18:53:14 +0000223 def test_unbuffered_output(self):
224 # Test expected operation of the '-u' switch
225 for stream in ('stdout', 'stderr'):
226 # Binary is unbuffered
227 code = ("import os, sys; sys.%s.buffer.write(b'x'); os._exit(0)"
228 % stream)
Antoine Pitrouf51d8d32010-10-08 18:05:42 +0000229 rc, out, err = assert_python_ok('-u', '-c', code)
230 data = err if stream == 'stderr' else out
Antoine Pitrou05608432009-01-09 18:53:14 +0000231 self.assertEqual(data, b'x', "binary %s not unbuffered" % stream)
Serhiy Storchaka77732be2017-10-04 20:25:40 +0300232 # Text is unbuffered
233 code = ("import os, sys; sys.%s.write('x'); os._exit(0)"
Antoine Pitrou05608432009-01-09 18:53:14 +0000234 % stream)
Antoine Pitrouf51d8d32010-10-08 18:05:42 +0000235 rc, out, err = assert_python_ok('-u', '-c', code)
236 data = err if stream == 'stderr' else out
Serhiy Storchaka77732be2017-10-04 20:25:40 +0300237 self.assertEqual(data, b'x', "text %s not unbuffered" % stream)
Antoine Pitrou05608432009-01-09 18:53:14 +0000238
Antoine Pitrou27fe9fc2009-01-26 21:48:00 +0000239 def test_unbuffered_input(self):
240 # sys.stdin still works with '-u'
241 code = ("import sys; sys.stdout.write(sys.stdin.read(1))")
Nick Coghlan260bd3e2009-11-16 06:49:25 +0000242 p = spawn_python('-u', '-c', code)
Antoine Pitrou27fe9fc2009-01-26 21:48:00 +0000243 p.stdin.write(b'x')
244 p.stdin.flush()
245 data, rc = _kill_python_and_exit_code(p)
246 self.assertEqual(rc, 0)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000247 self.assertTrue(data.startswith(b'x'), data)
Antoine Pitrou27fe9fc2009-01-26 21:48:00 +0000248
Amaury Forgeot d'Arc66f8c432009-06-09 21:30:01 +0000249 def test_large_PYTHONPATH(self):
Antoine Pitrou9bc35682010-11-09 21:33:55 +0000250 path1 = "ABCDE" * 100
251 path2 = "FGHIJ" * 100
252 path = path1 + os.pathsep + path2
Victor Stinner76cf6872010-04-16 15:10:27 +0000253
Antoine Pitrou9bc35682010-11-09 21:33:55 +0000254 code = """if 1:
255 import sys
256 path = ":".join(sys.path)
257 path = path.encode("ascii", "backslashreplace")
258 sys.stdout.buffer.write(path)"""
259 rc, out, err = assert_python_ok('-S', '-c', code,
260 PYTHONPATH=path)
261 self.assertIn(path1.encode('ascii'), out)
262 self.assertIn(path2.encode('ascii'), out)
Amaury Forgeot d'Arc66f8c432009-06-09 21:30:01 +0000263
Andrew Svetlov69032c82012-11-03 13:52:58 +0200264 def test_empty_PYTHONPATH_issue16309(self):
Ezio Melotti32f4e6e2012-11-23 01:51:20 +0200265 # On Posix, it is documented that setting PATH to the
266 # empty string is equivalent to not setting PATH at all,
267 # which is an exception to the rule that in a string like
268 # "/bin::/usr/bin" the empty string in the middle gets
269 # interpreted as '.'
Andrew Svetlov69032c82012-11-03 13:52:58 +0200270 code = """if 1:
271 import sys
272 path = ":".join(sys.path)
273 path = path.encode("ascii", "backslashreplace")
274 sys.stdout.buffer.write(path)"""
275 rc1, out1, err1 = assert_python_ok('-c', code, PYTHONPATH="")
Victor Stinnere8785ff2013-10-12 14:44:01 +0200276 rc2, out2, err2 = assert_python_ok('-c', code, __isolated=False)
Andrew Svetlov69032c82012-11-03 13:52:58 +0200277 # regarding to Posix specification, outputs should be equal
278 # for empty and unset PYTHONPATH
Ezio Melotti32f4e6e2012-11-23 01:51:20 +0200279 self.assertEqual(out1, out2)
Andrew Svetlov69032c82012-11-03 13:52:58 +0200280
Victor Stinner13d49ee2010-12-04 17:24:33 +0000281 def test_displayhook_unencodable(self):
Marc-André Lemburg8f36af72011-02-25 15:42:01 +0000282 for encoding in ('ascii', 'latin-1', 'utf-8'):
Steve Dower01423cb2018-02-17 18:59:03 -0800283 env = os.environ.copy()
Victor Stinner13d49ee2010-12-04 17:24:33 +0000284 env['PYTHONIOENCODING'] = encoding
285 p = subprocess.Popen(
286 [sys.executable, '-i'],
287 stdin=subprocess.PIPE,
288 stdout=subprocess.PIPE,
289 stderr=subprocess.STDOUT,
290 env=env)
291 # non-ascii, surrogate, non-BMP printable, non-BMP unprintable
292 text = "a=\xe9 b=\uDC80 c=\U00010000 d=\U0010FFFF"
293 p.stdin.write(ascii(text).encode('ascii') + b"\n")
294 p.stdin.write(b'exit()\n')
295 data = kill_python(p)
296 escaped = repr(text).encode(encoding, 'backslashreplace')
297 self.assertIn(escaped, data)
298
Victor Stinnerc0f1a1a2011-02-23 12:07:37 +0000299 def check_input(self, code, expected):
300 with tempfile.NamedTemporaryFile("wb+") as stdin:
301 sep = os.linesep.encode('ASCII')
302 stdin.write(sep.join((b'abc', b'def')))
303 stdin.flush()
304 stdin.seek(0)
305 with subprocess.Popen(
306 (sys.executable, "-c", code),
307 stdin=stdin, stdout=subprocess.PIPE) as proc:
308 stdout, stderr = proc.communicate()
309 self.assertEqual(stdout.rstrip(), expected)
310
311 def test_stdin_readline(self):
312 # Issue #11272: check that sys.stdin.readline() replaces '\r\n' by '\n'
313 # on Windows (sys.stdin is opened in binary mode)
314 self.check_input(
315 "import sys; print(repr(sys.stdin.readline()))",
316 b"'abc\\n'")
317
318 def test_builtin_input(self):
319 # Issue #11272: check that input() strips newlines ('\n' or '\r\n')
320 self.check_input(
321 "print(repr(input()))",
322 b"'abc'")
323
Victor Stinner7b3f0fa2012-08-04 01:28:00 +0200324 def test_output_newline(self):
325 # Issue 13119 Newline for print() should be \r\n on Windows.
326 code = """if 1:
327 import sys
328 print(1)
329 print(2)
330 print(3, file=sys.stderr)
331 print(4, file=sys.stderr)"""
332 rc, out, err = assert_python_ok('-c', code)
333
334 if sys.platform == 'win32':
335 self.assertEqual(b'1\r\n2\r\n', out)
336 self.assertEqual(b'3\r\n4', err)
337 else:
338 self.assertEqual(b'1\n2\n', out)
339 self.assertEqual(b'3\n4', err)
340
R David Murraye697e372011-06-24 13:26:31 -0400341 def test_unmached_quote(self):
342 # Issue #10206: python program starting with unmatched quote
343 # spewed spaces to stdout
344 rc, out, err = assert_python_failure('-c', "'")
345 self.assertRegex(err.decode('ascii', 'ignore'), 'SyntaxError')
346 self.assertEqual(b'', out)
347
Antoine Pitroud7c8fbf2011-11-26 21:59:36 +0100348 def test_stdout_flush_at_shutdown(self):
349 # Issue #5319: if stdout.flush() fails at shutdown, an error should
350 # be printed out.
351 code = """if 1:
Steve Dower79938f22015-03-07 20:32:16 -0800352 import os, sys, test.support
353 test.support.SuppressCrashReport().__enter__()
Antoine Pitroud7c8fbf2011-11-26 21:59:36 +0100354 sys.stdout.write('x')
355 os.close(sys.stdout.fileno())"""
Martin Panterb4ce1fc2015-11-30 03:18:29 +0000356 rc, out, err = assert_python_failure('-c', code)
Antoine Pitroud7c8fbf2011-11-26 21:59:36 +0100357 self.assertEqual(b'', out)
Martin Panterb4ce1fc2015-11-30 03:18:29 +0000358 self.assertEqual(120, rc)
Antoine Pitroud7c8fbf2011-11-26 21:59:36 +0100359 self.assertRegex(err.decode('ascii', 'ignore'),
Andrew Svetlov76bcff22012-11-03 15:56:05 +0200360 'Exception ignored in.*\nOSError: .*')
Antoine Pitroud7c8fbf2011-11-26 21:59:36 +0100361
362 def test_closed_stdout(self):
363 # Issue #13444: if stdout has been explicitly closed, we should
364 # not attempt to flush it at shutdown.
365 code = "import sys; sys.stdout.close()"
366 rc, out, err = assert_python_ok('-c', code)
367 self.assertEqual(b'', err)
368
Antoine Pitrou11942a52011-11-28 19:08:36 +0100369 # Issue #7111: Python should work without standard streams
370
371 @unittest.skipIf(os.name != 'posix', "test needs POSIX semantics")
Lihua Zhao29545502019-04-17 23:33:25 +0800372 @unittest.skipIf(sys.platform == "vxworks",
373 "test needs preexec support in subprocess.Popen")
Antoine Pitrou11942a52011-11-28 19:08:36 +0100374 def _test_no_stdio(self, streams):
375 code = """if 1:
376 import os, sys
377 for i, s in enumerate({streams}):
378 if getattr(sys, s) is not None:
379 os._exit(i + 1)
380 os._exit(42)""".format(streams=streams)
381 def preexec():
382 if 'stdin' in streams:
383 os.close(0)
384 if 'stdout' in streams:
385 os.close(1)
386 if 'stderr' in streams:
387 os.close(2)
388 p = subprocess.Popen(
389 [sys.executable, "-E", "-c", code],
390 stdin=subprocess.PIPE,
391 stdout=subprocess.PIPE,
392 stderr=subprocess.PIPE,
393 preexec_fn=preexec)
394 out, err = p.communicate()
Victor Stinnerccb04422017-11-16 03:20:31 -0800395 self.assertEqual(support.strip_python_stderr(err), b'')
Antoine Pitrou11942a52011-11-28 19:08:36 +0100396 self.assertEqual(p.returncode, 42)
397
398 def test_no_stdin(self):
399 self._test_no_stdio(['stdin'])
400
401 def test_no_stdout(self):
402 self._test_no_stdio(['stdout'])
403
404 def test_no_stderr(self):
405 self._test_no_stdio(['stderr'])
406
407 def test_no_std_streams(self):
408 self._test_no_stdio(['stdin', 'stdout', 'stderr'])
409
Georg Brandl2daf6ae2012-02-20 19:54:16 +0100410 def test_hash_randomization(self):
411 # Verify that -R enables hash randomization:
412 self.verify_valid_flag('-R')
413 hashes = []
Gregory P. Smith220ba722015-12-13 20:01:44 -0800414 if os.environ.get('PYTHONHASHSEED', 'random') != 'random':
415 env = dict(os.environ) # copy
416 # We need to test that it is enabled by default without
417 # the environment variable enabling it for us.
418 del env['PYTHONHASHSEED']
419 env['__cleanenv'] = '1' # consumed by assert_python_ok()
420 else:
421 env = {}
422 for i in range(3):
Georg Brandl2daf6ae2012-02-20 19:54:16 +0100423 code = 'print(hash("spam"))'
Gregory P. Smith220ba722015-12-13 20:01:44 -0800424 rc, out, err = assert_python_ok('-c', code, **env)
Georg Brandl2daf6ae2012-02-20 19:54:16 +0100425 self.assertEqual(rc, 0)
Georg Brandl09a7c722012-02-20 21:31:46 +0100426 hashes.append(out)
Gregory P. Smith220ba722015-12-13 20:01:44 -0800427 hashes = sorted(set(hashes)) # uniq
428 # Rare chance of failure due to 3 random seeds honestly being equal.
429 self.assertGreater(len(hashes), 1,
430 msg='3 runs produced an identical random hash '
431 ' for "spam": {}'.format(hashes))
Georg Brandl2daf6ae2012-02-20 19:54:16 +0100432
433 # Verify that sys.flags contains hash_randomization
434 code = 'import sys; print("random is", sys.flags.hash_randomization)'
Victor Stinner358e5e12017-12-15 00:51:22 +0100435 rc, out, err = assert_python_ok('-c', code, PYTHONHASHSEED='')
436 self.assertIn(b'random is 1', out)
437
438 rc, out, err = assert_python_ok('-c', code, PYTHONHASHSEED='random')
439 self.assertIn(b'random is 1', out)
440
441 rc, out, err = assert_python_ok('-c', code, PYTHONHASHSEED='0')
442 self.assertIn(b'random is 0', out)
443
444 rc, out, err = assert_python_ok('-R', '-c', code, PYTHONHASHSEED='0')
Georg Brandl09a7c722012-02-20 21:31:46 +0100445 self.assertIn(b'random is 1', out)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000446
Hynek Schlawack5c6b3e22012-11-07 09:02:24 +0100447 def test_del___main__(self):
448 # Issue #15001: PyRun_SimpleFileExFlags() did crash because it kept a
449 # borrowed reference to the dict of __main__ module and later modify
450 # the dict whereas the module was destroyed
Victor Stinnerccb04422017-11-16 03:20:31 -0800451 filename = support.TESTFN
452 self.addCleanup(support.unlink, filename)
Hynek Schlawack5c6b3e22012-11-07 09:02:24 +0100453 with open(filename, "w") as script:
454 print("import sys", file=script)
455 print("del sys.modules['__main__']", file=script)
456 assert_python_ok(filename)
457
Ezio Melotti7c663192012-11-18 13:55:52 +0200458 def test_unknown_options(self):
Ezio Melottia0dd22e2012-11-23 18:48:32 +0200459 rc, out, err = assert_python_failure('-E', '-z')
460 self.assertIn(b'Unknown option: -z', err)
Ezio Melotti7c663192012-11-18 13:55:52 +0200461 self.assertEqual(err.splitlines().count(b'Unknown option: -z'), 1)
462 self.assertEqual(b'', out)
Gregory P. Smith48e81002015-01-22 22:55:00 -0800463 # Add "without='-E'" to prevent _assert_python to append -E
464 # to env_vars and change the output of stderr
465 rc, out, err = assert_python_failure('-z', without='-E')
Ezio Melottia0dd22e2012-11-23 18:48:32 +0200466 self.assertIn(b'Unknown option: -z', err)
467 self.assertEqual(err.splitlines().count(b'Unknown option: -z'), 1)
468 self.assertEqual(b'', out)
Gregory P. Smith48e81002015-01-22 22:55:00 -0800469 rc, out, err = assert_python_failure('-a', '-z', without='-E')
Ezio Melottia0dd22e2012-11-23 18:48:32 +0200470 self.assertIn(b'Unknown option: -a', err)
471 # only the first unknown option is reported
472 self.assertNotIn(b'Unknown option: -z', err)
473 self.assertEqual(err.splitlines().count(b'Unknown option: -a'), 1)
474 self.assertEqual(b'', out)
475
Victor Stinnerccb04422017-11-16 03:20:31 -0800476 @unittest.skipIf(interpreter_requires_environment(),
Gregory P. Smithb9a3dd92015-02-04 00:59:40 -0800477 'Cannot run -I tests when PYTHON env vars are required.')
Christian Heimesad73a9c2013-08-10 16:36:18 +0200478 def test_isolatedmode(self):
479 self.verify_valid_flag('-I')
480 self.verify_valid_flag('-IEs')
481 rc, out, err = assert_python_ok('-I', '-c',
482 'from sys import flags as f; '
483 'print(f.no_user_site, f.ignore_environment, f.isolated)',
Martin Panter69332c12016-08-04 13:07:31 +0000484 # dummyvar to prevent extraneous -E
Christian Heimesad73a9c2013-08-10 16:36:18 +0200485 dummyvar="")
486 self.assertEqual(out.strip(), b'1 1 1')
Victor Stinnerccb04422017-11-16 03:20:31 -0800487 with support.temp_cwd() as tmpdir:
Christian Heimesad73a9c2013-08-10 16:36:18 +0200488 fake = os.path.join(tmpdir, "uuid.py")
489 main = os.path.join(tmpdir, "main.py")
490 with open(fake, "w") as f:
491 f.write("raise RuntimeError('isolated mode test')\n")
492 with open(main, "w") as f:
493 f.write("import uuid\n")
494 f.write("print('ok')\n")
495 self.assertRaises(subprocess.CalledProcessError,
496 subprocess.check_output,
497 [sys.executable, main], cwd=tmpdir,
498 stderr=subprocess.DEVNULL)
499 out = subprocess.check_output([sys.executable, "-I", main],
500 cwd=tmpdir)
501 self.assertEqual(out.strip(), b"ok")
502
Nick Coghland7ac0612017-10-25 12:11:26 +1000503 def test_sys_flags_set(self):
504 # Issue 31845: a startup refactoring broke reading flags from env vars
505 for value, expected in (("", 0), ("1", 1), ("text", 1), ("2", 2)):
506 env_vars = dict(
507 PYTHONDEBUG=value,
508 PYTHONOPTIMIZE=value,
509 PYTHONDONTWRITEBYTECODE=value,
510 PYTHONVERBOSE=value,
511 )
Victor Stinner53b7d4e2018-07-25 01:37:05 +0200512 dont_write_bytecode = int(bool(value))
Nick Coghland7ac0612017-10-25 12:11:26 +1000513 code = (
514 "import sys; "
515 "sys.stderr.write(str(sys.flags)); "
516 f"""sys.exit(not (
517 sys.flags.debug == sys.flags.optimize ==
Victor Stinner53b7d4e2018-07-25 01:37:05 +0200518 sys.flags.verbose ==
Nick Coghland7ac0612017-10-25 12:11:26 +1000519 {expected}
Victor Stinner53b7d4e2018-07-25 01:37:05 +0200520 and sys.flags.dont_write_bytecode == {dont_write_bytecode}
Nick Coghland7ac0612017-10-25 12:11:26 +1000521 ))"""
522 )
523 with self.subTest(envar_value=value):
524 assert_python_ok('-c', code, **env_vars)
Eric Snow6b4be192017-05-22 21:36:03 -0700525
Carl Meyerb193fa92018-06-15 22:40:56 -0600526 def test_set_pycache_prefix(self):
527 # sys.pycache_prefix can be set from either -X pycache_prefix or
528 # PYTHONPYCACHEPREFIX env var, with the former taking precedence.
529 NO_VALUE = object() # `-X pycache_prefix` with no `=PATH`
530 cases = [
531 # (PYTHONPYCACHEPREFIX, -X pycache_prefix, sys.pycache_prefix)
532 (None, None, None),
533 ('foo', None, 'foo'),
534 (None, 'bar', 'bar'),
535 ('foo', 'bar', 'bar'),
536 ('foo', '', None),
537 ('foo', NO_VALUE, None),
538 ]
539 for envval, opt, expected in cases:
540 exp_clause = "is None" if expected is None else f'== "{expected}"'
541 code = f"import sys; sys.exit(not sys.pycache_prefix {exp_clause})"
542 args = ['-c', code]
543 env = {} if envval is None else {'PYTHONPYCACHEPREFIX': envval}
544 if opt is NO_VALUE:
545 args[:0] = ['-X', 'pycache_prefix']
546 elif opt is not None:
547 args[:0] = ['-X', f'pycache_prefix={opt}']
548 with self.subTest(envval=envval, opt=opt):
549 with support.temp_cwd():
550 assert_python_ok(*args, **env)
551
Victor Stinner5e3806f2017-11-30 11:40:24 +0100552 def run_xdev(self, *args, check_exitcode=True, xdev=True):
Victor Stinnerccb04422017-11-16 03:20:31 -0800553 env = dict(os.environ)
554 env.pop('PYTHONWARNINGS', None)
Victor Stinner5e3806f2017-11-30 11:40:24 +0100555 env.pop('PYTHONDEVMODE', None)
Victor Stinnerecf411c2018-07-26 02:37:22 +0200556 env.pop('PYTHONMALLOC', None)
Victor Stinnerccb04422017-11-16 03:20:31 -0800557
Victor Stinner5e3806f2017-11-30 11:40:24 +0100558 if xdev:
559 args = (sys.executable, '-X', 'dev', *args)
560 else:
561 args = (sys.executable, *args)
Victor Stinnerccb04422017-11-16 03:20:31 -0800562 proc = subprocess.run(args,
563 stdout=subprocess.PIPE,
564 stderr=subprocess.STDOUT,
565 universal_newlines=True,
566 env=env)
567 if check_exitcode:
568 self.assertEqual(proc.returncode, 0, proc)
569 return proc.stdout.rstrip()
570
571 def test_xdev(self):
Victor Stinner5e3806f2017-11-30 11:40:24 +0100572 # sys.flags.dev_mode
573 code = "import sys; print(sys.flags.dev_mode)"
574 out = self.run_xdev("-c", code, xdev=False)
575 self.assertEqual(out, "False")
576 out = self.run_xdev("-c", code)
577 self.assertEqual(out, "True")
578
579 # Warnings
Victor Stinner94540602017-12-16 04:54:22 +0100580 code = ("import warnings; "
Victor Stinner09f3a8a2017-11-20 17:32:40 -0800581 "print(' '.join('%s::%s' % (f[0], f[2].__name__) "
582 "for f in warnings.filters))")
Victor Stinner747f48e2017-12-12 22:59:48 +0100583 if Py_DEBUG:
584 expected_filters = "default::Warning"
585 else:
586 expected_filters = ("default::Warning "
Nick Coghlan9b997472018-01-08 12:45:02 +1000587 "default::DeprecationWarning "
Victor Stinner747f48e2017-12-12 22:59:48 +0100588 "ignore::DeprecationWarning "
589 "ignore::PendingDeprecationWarning "
590 "ignore::ImportWarning "
591 "ignore::ResourceWarning")
Victor Stinner09f3a8a2017-11-20 17:32:40 -0800592
593 out = self.run_xdev("-c", code)
Victor Stinner747f48e2017-12-12 22:59:48 +0100594 self.assertEqual(out, expected_filters)
Victor Stinner09f3a8a2017-11-20 17:32:40 -0800595
596 out = self.run_xdev("-b", "-c", code)
Victor Stinner747f48e2017-12-12 22:59:48 +0100597 self.assertEqual(out, f"default::BytesWarning {expected_filters}")
Victor Stinner09f3a8a2017-11-20 17:32:40 -0800598
599 out = self.run_xdev("-bb", "-c", code)
Victor Stinner747f48e2017-12-12 22:59:48 +0100600 self.assertEqual(out, f"error::BytesWarning {expected_filters}")
Victor Stinner09f3a8a2017-11-20 17:32:40 -0800601
602 out = self.run_xdev("-Werror", "-c", code)
Victor Stinner747f48e2017-12-12 22:59:48 +0100603 self.assertEqual(out, f"error::Warning {expected_filters}")
Victor Stinnerccb04422017-11-16 03:20:31 -0800604
Victor Stinner5e3806f2017-11-30 11:40:24 +0100605 # Memory allocator debug hooks
Victor Stinnerccb04422017-11-16 03:20:31 -0800606 try:
607 import _testcapi
608 except ImportError:
609 pass
610 else:
Victor Stinner5d39e042017-11-29 17:20:38 +0100611 code = "import _testcapi; print(_testcapi.pymem_getallocatorsname())"
Victor Stinnerccb04422017-11-16 03:20:31 -0800612 with support.SuppressCrashReport():
Victor Stinner09f3a8a2017-11-20 17:32:40 -0800613 out = self.run_xdev("-c", code, check_exitcode=False)
Victor Stinner5d39e042017-11-29 17:20:38 +0100614 if support.with_pymalloc():
615 alloc_name = "pymalloc_debug"
616 else:
617 alloc_name = "malloc_debug"
618 self.assertEqual(out, alloc_name)
Victor Stinnerccb04422017-11-16 03:20:31 -0800619
Victor Stinner5e3806f2017-11-30 11:40:24 +0100620 # Faulthandler
Victor Stinnerccb04422017-11-16 03:20:31 -0800621 try:
622 import faulthandler
623 except ImportError:
624 pass
625 else:
626 code = "import faulthandler; print(faulthandler.is_enabled())"
Victor Stinner09f3a8a2017-11-20 17:32:40 -0800627 out = self.run_xdev("-c", code)
Victor Stinnerccb04422017-11-16 03:20:31 -0800628 self.assertEqual(out, "True")
629
Victor Stinner747f48e2017-12-12 22:59:48 +0100630 def check_warnings_filters(self, cmdline_option, envvar, use_pywarning=False):
631 if use_pywarning:
632 code = ("import sys; from test.support import import_fresh_module; "
633 "warnings = import_fresh_module('warnings', blocked=['_warnings']); ")
634 else:
635 code = "import sys, warnings; "
636 code += ("print(' '.join('%s::%s' % (f[0], f[2].__name__) "
637 "for f in warnings.filters))")
638 args = (sys.executable, '-W', cmdline_option, '-bb', '-c', code)
639 env = dict(os.environ)
640 env.pop('PYTHONDEVMODE', None)
641 env["PYTHONWARNINGS"] = envvar
642 proc = subprocess.run(args,
643 stdout=subprocess.PIPE,
644 stderr=subprocess.STDOUT,
645 universal_newlines=True,
646 env=env)
647 self.assertEqual(proc.returncode, 0, proc)
648 return proc.stdout.rstrip()
649
650 def test_warnings_filter_precedence(self):
651 expected_filters = ("error::BytesWarning "
652 "once::UserWarning "
653 "always::UserWarning")
654 if not Py_DEBUG:
655 expected_filters += (" "
Nick Coghlan9b997472018-01-08 12:45:02 +1000656 "default::DeprecationWarning "
Victor Stinner747f48e2017-12-12 22:59:48 +0100657 "ignore::DeprecationWarning "
658 "ignore::PendingDeprecationWarning "
659 "ignore::ImportWarning "
660 "ignore::ResourceWarning")
661
662 out = self.check_warnings_filters("once::UserWarning",
663 "always::UserWarning")
664 self.assertEqual(out, expected_filters)
665
666 out = self.check_warnings_filters("once::UserWarning",
667 "always::UserWarning",
668 use_pywarning=True)
669 self.assertEqual(out, expected_filters)
670
Victor Stinner5d39e042017-11-29 17:20:38 +0100671 def check_pythonmalloc(self, env_var, name):
672 code = 'import _testcapi; print(_testcapi.pymem_getallocatorsname())'
673 env = dict(os.environ)
Victor Stinner5e3806f2017-11-30 11:40:24 +0100674 env.pop('PYTHONDEVMODE', None)
Victor Stinner5d39e042017-11-29 17:20:38 +0100675 if env_var is not None:
676 env['PYTHONMALLOC'] = env_var
677 else:
678 env.pop('PYTHONMALLOC', None)
679 args = (sys.executable, '-c', code)
680 proc = subprocess.run(args,
681 stdout=subprocess.PIPE,
682 stderr=subprocess.STDOUT,
683 universal_newlines=True,
684 env=env)
685 self.assertEqual(proc.stdout.rstrip(), name)
686 self.assertEqual(proc.returncode, 0)
687
688 def test_pythonmalloc(self):
689 # Test the PYTHONMALLOC environment variable
Victor Stinner5d39e042017-11-29 17:20:38 +0100690 pymalloc = support.with_pymalloc()
691 if pymalloc:
Victor Stinner747f48e2017-12-12 22:59:48 +0100692 default_name = 'pymalloc_debug' if Py_DEBUG else 'pymalloc'
Victor Stinner5d39e042017-11-29 17:20:38 +0100693 default_name_debug = 'pymalloc_debug'
694 else:
Victor Stinner747f48e2017-12-12 22:59:48 +0100695 default_name = 'malloc_debug' if Py_DEBUG else 'malloc'
Victor Stinner5d39e042017-11-29 17:20:38 +0100696 default_name_debug = 'malloc_debug'
697
698 tests = [
699 (None, default_name),
700 ('debug', default_name_debug),
701 ('malloc', 'malloc'),
702 ('malloc_debug', 'malloc_debug'),
703 ]
704 if pymalloc:
705 tests.extend((
706 ('pymalloc', 'pymalloc'),
707 ('pymalloc_debug', 'pymalloc_debug'),
708 ))
709
710 for env_var, name in tests:
711 with self.subTest(env_var=env_var, name=name):
712 self.check_pythonmalloc(env_var, name)
713
Victor Stinner5e3806f2017-11-30 11:40:24 +0100714 def test_pythondevmode_env(self):
715 # Test the PYTHONDEVMODE environment variable
716 code = "import sys; print(sys.flags.dev_mode)"
717 env = dict(os.environ)
718 env.pop('PYTHONDEVMODE', None)
719 args = (sys.executable, '-c', code)
720
721 proc = subprocess.run(args, stdout=subprocess.PIPE,
722 universal_newlines=True, env=env)
723 self.assertEqual(proc.stdout.rstrip(), 'False')
724 self.assertEqual(proc.returncode, 0, proc)
725
726 env['PYTHONDEVMODE'] = '1'
727 proc = subprocess.run(args, stdout=subprocess.PIPE,
728 universal_newlines=True, env=env)
729 self.assertEqual(proc.stdout.rstrip(), 'True')
730 self.assertEqual(proc.returncode, 0, proc)
731
Steve Dower48e8c822018-02-22 10:39:26 -0800732 @unittest.skipUnless(sys.platform == 'win32',
733 'bpo-32457 only applies on Windows')
734 def test_argv0_normalization(self):
735 args = sys.executable, '-c', 'print(0)'
736 prefix, exe = os.path.split(sys.executable)
737 executable = prefix + '\\.\\.\\.\\' + exe
738
739 proc = subprocess.run(args, stdout=subprocess.PIPE,
740 executable=executable)
741 self.assertEqual(proc.returncode, 0, proc)
742 self.assertEqual(proc.stdout.strip(), b'0')
Victor Stinner09f3a8a2017-11-20 17:32:40 -0800743
Steve Dower01423cb2018-02-17 18:59:03 -0800744@unittest.skipIf(interpreter_requires_environment(),
745 'Cannot run -I tests when PYTHON env vars are required.')
Eric Snow6b4be192017-05-22 21:36:03 -0700746class IgnoreEnvironmentTest(unittest.TestCase):
747
748 def run_ignoring_vars(self, predicate, **env_vars):
749 # Runs a subprocess with -E set, even though we're passing
750 # specific environment variables
751 # Logical inversion to match predicate check to a zero return
752 # code indicating success
753 code = "import sys; sys.stderr.write(str(sys.flags)); sys.exit(not ({}))".format(predicate)
754 return assert_python_ok('-E', '-c', code, **env_vars)
755
756 def test_ignore_PYTHONPATH(self):
757 path = "should_be_ignored"
758 self.run_ignoring_vars("'{}' not in sys.path".format(path),
759 PYTHONPATH=path)
760
761 def test_ignore_PYTHONHASHSEED(self):
762 self.run_ignoring_vars("sys.flags.hash_randomization == 1",
763 PYTHONHASHSEED="0")
764
Nick Coghland7ac0612017-10-25 12:11:26 +1000765 def test_sys_flags_not_set(self):
766 # Issue 31845: a startup refactoring broke reading flags from env vars
767 expected_outcome = """
768 (sys.flags.debug == sys.flags.optimize ==
769 sys.flags.dont_write_bytecode == sys.flags.verbose == 0)
770 """
771 self.run_ignoring_vars(
772 expected_outcome,
773 PYTHONDEBUG="1",
774 PYTHONOPTIMIZE="1",
775 PYTHONDONTWRITEBYTECODE="1",
776 PYTHONVERBOSE="1",
777 )
778
Eric Snow6b4be192017-05-22 21:36:03 -0700779
Neal Norwitz11bd1192005-10-03 00:54:56 +0000780def test_main():
Victor Stinnerccb04422017-11-16 03:20:31 -0800781 support.run_unittest(CmdLineTest, IgnoreEnvironmentTest)
782 support.reap_children()
Neal Norwitz11bd1192005-10-03 00:54:56 +0000783
784if __name__ == "__main__":
785 test_main()