blob: e12f3055424428d6b15290ef912602c739628104 [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 Stinner02bfdb32011-02-23 12:10:23 +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
35 def test_q(self):
36 self.verify_valid_flag('-Qold')
37 self.verify_valid_flag('-Qnew')
38 self.verify_valid_flag('-Qwarn')
39 self.verify_valid_flag('-Qwarnall')
40
41 def test_site_flag(self):
42 self.verify_valid_flag('-S')
43
44 def test_usage(self):
Antoine Pitrouf51d8d32010-10-08 18:05:42 +000045 rc, out, err = assert_python_ok('-h')
46 self.assertIn(b'usage', out)
Neal Norwitz11bd1192005-10-03 00:54:56 +000047
48 def test_version(self):
Guido van Rossuma1c42a92007-08-29 03:47:36 +000049 version = ('Python %d.%d' % sys.version_info[:2]).encode("ascii")
Antoine Pitrouf51d8d32010-10-08 18:05:42 +000050 rc, out, err = assert_python_ok('-V')
51 self.assertTrue(err.startswith(version))
Neal Norwitz11bd1192005-10-03 00:54:56 +000052
Trent Nelson39e307e2008-03-19 06:45:48 +000053 def test_verbose(self):
54 # -v causes imports to write to stderr. If the write to
55 # stderr itself causes an import to happen (for the output
56 # codec), a recursion loop can occur.
Antoine Pitrouf51d8d32010-10-08 18:05:42 +000057 rc, out, err = assert_python_ok('-v')
58 self.assertNotIn(b'stack overflow', err)
59 rc, out, err = assert_python_ok('-vv')
60 self.assertNotIn(b'stack overflow', err)
Trent Nelson39e307e2008-03-19 06:45:48 +000061
Antoine Pitrou9583cac2010-10-21 13:42:28 +000062 def test_xoptions(self):
63 rc, out, err = assert_python_ok('-c', 'import sys; print(sys._xoptions)')
64 opts = eval(out.splitlines()[0])
65 self.assertEqual(opts, {})
66 rc, out, err = assert_python_ok(
67 '-Xa', '-Xb=c,d=e', '-c', 'import sys; print(sys._xoptions)')
68 opts = eval(out.splitlines()[0])
69 self.assertEqual(opts, {'a': True, 'b': 'c,d=e'})
70
Thomas Wouters477c8d52006-05-27 19:21:47 +000071 def test_run_module(self):
72 # Test expected operation of the '-m' switch
73 # Switch needs an argument
Antoine Pitrouf51d8d32010-10-08 18:05:42 +000074 assert_python_failure('-m')
Thomas Wouters477c8d52006-05-27 19:21:47 +000075 # Check we get an error for a nonexistent module
Antoine Pitrouf51d8d32010-10-08 18:05:42 +000076 assert_python_failure('-m', 'fnord43520xyz')
Thomas Wouters477c8d52006-05-27 19:21:47 +000077 # Check the runpy module also gives an error for
78 # a nonexistent module
Antoine Pitrouf51d8d32010-10-08 18:05:42 +000079 assert_python_failure('-m', 'runpy', 'fnord43520xyz'),
Thomas Wouters477c8d52006-05-27 19:21:47 +000080 # All good if module is located and run successfully
Antoine Pitrouf51d8d32010-10-08 18:05:42 +000081 assert_python_ok('-m', 'timeit', '-n', '1'),
Thomas Wouters477c8d52006-05-27 19:21:47 +000082
Thomas Woutersed03b412007-08-28 21:37:11 +000083 def test_run_module_bug1764407(self):
84 # -m and -i need to play well together
85 # Runs the timeit module and checks the __main__
86 # namespace has been populated appropriately
Nick Coghlan260bd3e2009-11-16 06:49:25 +000087 p = spawn_python('-i', '-m', 'timeit', '-n', '1')
Guido van Rossuma1c42a92007-08-29 03:47:36 +000088 p.stdin.write(b'Timer\n')
89 p.stdin.write(b'exit()\n')
Nick Coghlan260bd3e2009-11-16 06:49:25 +000090 data = kill_python(p)
Thomas Woutersed03b412007-08-28 21:37:11 +000091 self.assertTrue(data.find(b'1 loop') != -1)
92 self.assertTrue(data.find(b'__main__.Timer') != -1)
93
Thomas Wouters477c8d52006-05-27 19:21:47 +000094 def test_run_code(self):
95 # Test expected operation of the '-c' switch
96 # Switch needs an argument
Antoine Pitrouf51d8d32010-10-08 18:05:42 +000097 assert_python_failure('-c')
Thomas Wouters477c8d52006-05-27 19:21:47 +000098 # Check we get an error for an uncaught exception
Antoine Pitrouf51d8d32010-10-08 18:05:42 +000099 assert_python_failure('-c', 'raise Exception')
Thomas Wouters477c8d52006-05-27 19:21:47 +0000100 # All good if execution is successful
Antoine Pitrouf51d8d32010-10-08 18:05:42 +0000101 assert_python_ok('-c', 'pass')
Thomas Wouters477c8d52006-05-27 19:21:47 +0000102
Victor Stinner073f7592010-10-20 21:56:55 +0000103 @unittest.skipIf(sys.getfilesystemencoding() == 'ascii',
104 'need a filesystem encoding different than ASCII')
105 def test_non_ascii(self):
Amaury Forgeot d'Arc9a5499b2008-11-11 23:04:59 +0000106 # Test handling of non-ascii data
Victor Stinner073f7592010-10-20 21:56:55 +0000107 if test.support.verbose:
108 import locale
109 print('locale encoding = %s, filesystem encoding = %s'
110 % (locale.getpreferredencoding(), sys.getfilesystemencoding()))
111 command = "assert(ord('\xe9') == 0xe9)"
112 assert_python_ok('-c', command)
Amaury Forgeot d'Arc9a5499b2008-11-11 23:04:59 +0000113
Victor Stinnerf6211ed2010-10-20 21:52:33 +0000114 # On Windows, pass bytes to subprocess doesn't test how Python decodes the
115 # command line, but how subprocess does decode bytes to unicode. Python
116 # doesn't decode the command line because Windows provides directly the
117 # arguments as unicode (using wmain() instead of main()).
118 @unittest.skipIf(sys.platform == 'win32',
119 'Windows has a native unicode API')
120 def test_undecodable_code(self):
121 undecodable = b"\xff"
122 env = os.environ.copy()
123 # Use C locale to get ascii for the locale encoding
124 env['LC_ALL'] = 'C'
125 code = (
126 b'import locale; '
127 b'print(ascii("' + undecodable + b'"), '
128 b'locale.getpreferredencoding())')
129 p = subprocess.Popen(
130 [sys.executable, "-c", code],
131 stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
132 env=env)
133 stdout, stderr = p.communicate()
134 if p.returncode == 1:
135 # _Py_char2wchar() decoded b'\xff' as '\udcff' (b'\xff' is not
136 # decodable from ASCII) and run_command() failed on
137 # PyUnicode_AsUTF8String(). This is the expected behaviour on
138 # Linux.
139 pattern = b"Unable to decode the command from the command line:"
140 elif p.returncode == 0:
141 # _Py_char2wchar() decoded b'\xff' as '\xff' even if the locale is
142 # C and the locale encoding is ASCII. It occurs on FreeBSD, Solaris
143 # and Mac OS X.
144 pattern = b"'\\xff' "
145 # The output is followed by the encoding name, an alias to ASCII.
146 # Examples: "US-ASCII" or "646" (ISO 646, on Solaris).
147 else:
148 raise AssertionError("Unknown exit code: %s, output=%a" % (p.returncode, stdout))
149 if not stdout.startswith(pattern):
150 raise AssertionError("%a doesn't start with %a" % (stdout, pattern))
151
Victor Stinnerf933e1a2010-10-20 22:58:25 +0000152 @unittest.skipUnless(sys.platform == 'darwin', 'test specific to Mac OS X')
153 def test_osx_utf8(self):
154 def check_output(text):
155 decoded = text.decode('utf8', 'surrogateescape')
156 expected = ascii(decoded).encode('ascii') + b'\n'
157
158 env = os.environ.copy()
159 # C locale gives ASCII locale encoding, but Python uses UTF-8
160 # to parse the command line arguments on Mac OS X
161 env['LC_ALL'] = 'C'
162
163 p = subprocess.Popen(
164 (sys.executable, "-c", "import sys; print(ascii(sys.argv[1]))", text),
165 stdout=subprocess.PIPE,
166 env=env)
167 stdout, stderr = p.communicate()
168 self.assertEqual(stdout, expected)
169 self.assertEqual(p.returncode, 0)
170
171 # test valid utf-8
172 text = 'e:\xe9, euro:\u20ac, non-bmp:\U0010ffff'.encode('utf-8')
173 check_output(text)
174
175 # test invalid utf-8
176 text = (
177 b'\xff' # invalid byte
178 b'\xc3\xa9' # valid utf-8 character
179 b'\xc3\xff' # invalid byte sequence
180 b'\xed\xa0\x80' # lone surrogate character (invalid)
181 )
182 check_output(text)
183
Antoine Pitrou05608432009-01-09 18:53:14 +0000184 def test_unbuffered_output(self):
185 # Test expected operation of the '-u' switch
186 for stream in ('stdout', 'stderr'):
187 # Binary is unbuffered
188 code = ("import os, sys; sys.%s.buffer.write(b'x'); os._exit(0)"
189 % stream)
Antoine Pitrouf51d8d32010-10-08 18:05:42 +0000190 rc, out, err = assert_python_ok('-u', '-c', code)
191 data = err if stream == 'stderr' else out
Antoine Pitrou05608432009-01-09 18:53:14 +0000192 self.assertEqual(data, b'x', "binary %s not unbuffered" % stream)
193 # Text is line-buffered
194 code = ("import os, sys; sys.%s.write('x\\n'); os._exit(0)"
195 % stream)
Antoine Pitrouf51d8d32010-10-08 18:05:42 +0000196 rc, out, err = assert_python_ok('-u', '-c', code)
197 data = err if stream == 'stderr' else out
Antoine Pitrou05608432009-01-09 18:53:14 +0000198 self.assertEqual(data.strip(), b'x',
199 "text %s not line-buffered" % stream)
200
Antoine Pitrou27fe9fc2009-01-26 21:48:00 +0000201 def test_unbuffered_input(self):
202 # sys.stdin still works with '-u'
203 code = ("import sys; sys.stdout.write(sys.stdin.read(1))")
Nick Coghlan260bd3e2009-11-16 06:49:25 +0000204 p = spawn_python('-u', '-c', code)
Antoine Pitrou27fe9fc2009-01-26 21:48:00 +0000205 p.stdin.write(b'x')
206 p.stdin.flush()
207 data, rc = _kill_python_and_exit_code(p)
208 self.assertEqual(rc, 0)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000209 self.assertTrue(data.startswith(b'x'), data)
Antoine Pitrou27fe9fc2009-01-26 21:48:00 +0000210
Amaury Forgeot d'Arc66f8c432009-06-09 21:30:01 +0000211 def test_large_PYTHONPATH(self):
Antoine Pitrou9bc35682010-11-09 21:33:55 +0000212 path1 = "ABCDE" * 100
213 path2 = "FGHIJ" * 100
214 path = path1 + os.pathsep + path2
Victor Stinner76cf6872010-04-16 15:10:27 +0000215
Antoine Pitrou9bc35682010-11-09 21:33:55 +0000216 code = """if 1:
217 import sys
218 path = ":".join(sys.path)
219 path = path.encode("ascii", "backslashreplace")
220 sys.stdout.buffer.write(path)"""
221 rc, out, err = assert_python_ok('-S', '-c', code,
222 PYTHONPATH=path)
223 self.assertIn(path1.encode('ascii'), out)
224 self.assertIn(path2.encode('ascii'), out)
Amaury Forgeot d'Arc66f8c432009-06-09 21:30:01 +0000225
Victor Stinner13d49ee2010-12-04 17:24:33 +0000226 def test_displayhook_unencodable(self):
227 for encoding in ('ascii', 'latin1', 'utf8'):
228 env = os.environ.copy()
229 env['PYTHONIOENCODING'] = encoding
230 p = subprocess.Popen(
231 [sys.executable, '-i'],
232 stdin=subprocess.PIPE,
233 stdout=subprocess.PIPE,
234 stderr=subprocess.STDOUT,
235 env=env)
236 # non-ascii, surrogate, non-BMP printable, non-BMP unprintable
237 text = "a=\xe9 b=\uDC80 c=\U00010000 d=\U0010FFFF"
238 p.stdin.write(ascii(text).encode('ascii') + b"\n")
239 p.stdin.write(b'exit()\n')
240 data = kill_python(p)
241 escaped = repr(text).encode(encoding, 'backslashreplace')
242 self.assertIn(escaped, data)
243
Victor Stinner02bfdb32011-02-23 12:10:23 +0000244 def check_input(self, code, expected):
245 with tempfile.NamedTemporaryFile("wb+") as stdin:
246 sep = os.linesep.encode('ASCII')
247 stdin.write(sep.join((b'abc', b'def')))
248 stdin.flush()
249 stdin.seek(0)
250 with subprocess.Popen(
251 (sys.executable, "-c", code),
252 stdin=stdin, stdout=subprocess.PIPE) as proc:
253 stdout, stderr = proc.communicate()
254 self.assertEqual(stdout.rstrip(), expected)
255
256 def test_stdin_readline(self):
257 # Issue #11272: check that sys.stdin.readline() replaces '\r\n' by '\n'
258 # on Windows (sys.stdin is opened in binary mode)
259 self.check_input(
260 "import sys; print(repr(sys.stdin.readline()))",
261 b"'abc\\n'")
262
263 def test_builtin_input(self):
264 # Issue #11272: check that input() strips newlines ('\n' or '\r\n')
265 self.check_input(
266 "print(repr(input()))",
267 b"'abc'")
268
Victor Stinner90ef7472012-08-04 01:37:32 +0200269 def test_output_newline(self):
270 # Issue 13119 Newline for print() should be \r\n on Windows.
271 code = """if 1:
272 import sys
273 print(1)
274 print(2)
275 print(3, file=sys.stderr)
276 print(4, file=sys.stderr)"""
277 rc, out, err = assert_python_ok('-c', code)
278
279 if sys.platform == 'win32':
280 self.assertEqual(b'1\r\n2\r\n', out)
281 self.assertEqual(b'3\r\n4', err)
282 else:
283 self.assertEqual(b'1\n2\n', out)
284 self.assertEqual(b'3\n4', err)
285
R David Murraye697e372011-06-24 13:26:31 -0400286 def test_unmached_quote(self):
287 # Issue #10206: python program starting with unmatched quote
288 # spewed spaces to stdout
289 rc, out, err = assert_python_failure('-c', "'")
290 self.assertRegex(err.decode('ascii', 'ignore'), 'SyntaxError')
291 self.assertEqual(b'', out)
292
Antoine Pitroud7c8fbf2011-11-26 21:59:36 +0100293 def test_stdout_flush_at_shutdown(self):
294 # Issue #5319: if stdout.flush() fails at shutdown, an error should
295 # be printed out.
296 code = """if 1:
297 import os, sys
298 sys.stdout.write('x')
299 os.close(sys.stdout.fileno())"""
300 rc, out, err = assert_python_ok('-c', code)
301 self.assertEqual(b'', out)
302 self.assertRegex(err.decode('ascii', 'ignore'),
303 'Exception IOError: .* ignored')
304
305 def test_closed_stdout(self):
306 # Issue #13444: if stdout has been explicitly closed, we should
307 # not attempt to flush it at shutdown.
308 code = "import sys; sys.stdout.close()"
309 rc, out, err = assert_python_ok('-c', code)
310 self.assertEqual(b'', err)
311
Antoine Pitrou11942a52011-11-28 19:08:36 +0100312 # Issue #7111: Python should work without standard streams
313
314 @unittest.skipIf(os.name != 'posix', "test needs POSIX semantics")
315 def _test_no_stdio(self, streams):
316 code = """if 1:
317 import os, sys
318 for i, s in enumerate({streams}):
319 if getattr(sys, s) is not None:
320 os._exit(i + 1)
321 os._exit(42)""".format(streams=streams)
322 def preexec():
323 if 'stdin' in streams:
324 os.close(0)
325 if 'stdout' in streams:
326 os.close(1)
327 if 'stderr' in streams:
328 os.close(2)
329 p = subprocess.Popen(
330 [sys.executable, "-E", "-c", code],
331 stdin=subprocess.PIPE,
332 stdout=subprocess.PIPE,
333 stderr=subprocess.PIPE,
334 preexec_fn=preexec)
335 out, err = p.communicate()
336 self.assertEqual(test.support.strip_python_stderr(err), b'')
337 self.assertEqual(p.returncode, 42)
338
339 def test_no_stdin(self):
340 self._test_no_stdio(['stdin'])
341
342 def test_no_stdout(self):
343 self._test_no_stdio(['stdout'])
344
345 def test_no_stderr(self):
346 self._test_no_stdio(['stderr'])
347
348 def test_no_std_streams(self):
349 self._test_no_stdio(['stdin', 'stdout', 'stderr'])
350
Georg Brandl2daf6ae2012-02-20 19:54:16 +0100351 def test_hash_randomization(self):
352 # Verify that -R enables hash randomization:
353 self.verify_valid_flag('-R')
354 hashes = []
355 for i in range(2):
356 code = 'print(hash("spam"))'
Georg Brandl09a7c722012-02-20 21:31:46 +0100357 rc, out, err = assert_python_ok('-R', '-c', code)
Georg Brandl2daf6ae2012-02-20 19:54:16 +0100358 self.assertEqual(rc, 0)
Georg Brandl09a7c722012-02-20 21:31:46 +0100359 hashes.append(out)
Georg Brandl2daf6ae2012-02-20 19:54:16 +0100360 self.assertNotEqual(hashes[0], hashes[1])
361
362 # Verify that sys.flags contains hash_randomization
363 code = 'import sys; print("random is", sys.flags.hash_randomization)'
Georg Brandl09a7c722012-02-20 21:31:46 +0100364 rc, out, err = assert_python_ok('-R', '-c', code)
Georg Brandl2daf6ae2012-02-20 19:54:16 +0100365 self.assertEqual(rc, 0)
Georg Brandl09a7c722012-02-20 21:31:46 +0100366 self.assertIn(b'random is 1', out)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000367
Hynek Schlawack5c6b3e22012-11-07 09:02:24 +0100368 def test_del___main__(self):
369 # Issue #15001: PyRun_SimpleFileExFlags() did crash because it kept a
370 # borrowed reference to the dict of __main__ module and later modify
371 # the dict whereas the module was destroyed
372 filename = test.support.TESTFN
373 self.addCleanup(test.support.unlink, filename)
374 with open(filename, "w") as script:
375 print("import sys", file=script)
376 print("del sys.modules['__main__']", file=script)
377 assert_python_ok(filename)
378
Ezio Melotti7c663192012-11-18 13:55:52 +0200379 def test_unknown_options(self):
Ezio Melottia0dd22e2012-11-23 18:48:32 +0200380 rc, out, err = assert_python_failure('-E', '-z')
381 self.assertIn(b'Unknown option: -z', err)
Ezio Melotti7c663192012-11-18 13:55:52 +0200382 self.assertEqual(err.splitlines().count(b'Unknown option: -z'), 1)
383 self.assertEqual(b'', out)
Ezio Melottia0dd22e2012-11-23 18:48:32 +0200384 # Add "without='-E'" to prevent _assert_python to append -E
385 # to env_vars and change the output of stderr
386 rc, out, err = assert_python_failure('-z', without='-E')
387 self.assertIn(b'Unknown option: -z', err)
388 self.assertEqual(err.splitlines().count(b'Unknown option: -z'), 1)
389 self.assertEqual(b'', out)
390 rc, out, err = assert_python_failure('-a', '-z', without='-E')
391 self.assertIn(b'Unknown option: -a', err)
392 # only the first unknown option is reported
393 self.assertNotIn(b'Unknown option: -z', err)
394 self.assertEqual(err.splitlines().count(b'Unknown option: -a'), 1)
395 self.assertEqual(b'', out)
396
Ezio Melotti7c663192012-11-18 13:55:52 +0200397
Neal Norwitz11bd1192005-10-03 00:54:56 +0000398def test_main():
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000399 test.support.run_unittest(CmdLineTest)
400 test.support.reap_children()
Neal Norwitz11bd1192005-10-03 00:54:56 +0000401
402if __name__ == "__main__":
403 test_main()