blob: 73acb9fdfa98134f0e5b0498196c1d9effa47e29 [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
Antoine Pitrouf51d8d32010-10-08 18:05:42 +00008from test.script_helper import spawn_python, kill_python, assert_python_ok, assert_python_failure
Neal Norwitz11bd1192005-10-03 00:54:56 +00009
Nick Coghlan260bd3e2009-11-16 06:49:25 +000010# spawn_python normally enforces use of -E to avoid environmental effects
11# but one test checks PYTHONPATH behaviour explicitly
12# XXX (ncoghlan): Give script_helper.spawn_python an option to switch
13# off the -E flag that is normally inserted automatically
14import subprocess
15def _spawn_python_with_env(*args):
Antoine Pitrou87695762008-08-14 22:44:29 +000016 cmd_line = [sys.executable]
Thomas Woutersed03b412007-08-28 21:37:11 +000017 cmd_line.extend(args)
18 return subprocess.Popen(cmd_line, stdin=subprocess.PIPE,
19 stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
20
Trent Nelson39e307e2008-03-19 06:45:48 +000021
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
43 def test_q(self):
44 self.verify_valid_flag('-Qold')
45 self.verify_valid_flag('-Qnew')
46 self.verify_valid_flag('-Qwarn')
47 self.verify_valid_flag('-Qwarnall')
48
49 def test_site_flag(self):
50 self.verify_valid_flag('-S')
51
52 def test_usage(self):
Antoine Pitrouf51d8d32010-10-08 18:05:42 +000053 rc, out, err = assert_python_ok('-h')
54 self.assertIn(b'usage', out)
Neal Norwitz11bd1192005-10-03 00:54:56 +000055
56 def test_version(self):
Guido van Rossuma1c42a92007-08-29 03:47:36 +000057 version = ('Python %d.%d' % sys.version_info[:2]).encode("ascii")
Antoine Pitrouf51d8d32010-10-08 18:05:42 +000058 rc, out, err = assert_python_ok('-V')
59 self.assertTrue(err.startswith(version))
Neal Norwitz11bd1192005-10-03 00:54:56 +000060
Trent Nelson39e307e2008-03-19 06:45:48 +000061 def test_verbose(self):
62 # -v causes imports to write to stderr. If the write to
63 # stderr itself causes an import to happen (for the output
64 # codec), a recursion loop can occur.
Antoine Pitrouf51d8d32010-10-08 18:05:42 +000065 rc, out, err = assert_python_ok('-v')
66 self.assertNotIn(b'stack overflow', err)
67 rc, out, err = assert_python_ok('-vv')
68 self.assertNotIn(b'stack overflow', err)
Trent Nelson39e307e2008-03-19 06:45:48 +000069
Thomas Wouters477c8d52006-05-27 19:21:47 +000070 def test_run_module(self):
71 # Test expected operation of the '-m' switch
72 # Switch needs an argument
Antoine Pitrouf51d8d32010-10-08 18:05:42 +000073 assert_python_failure('-m')
Thomas Wouters477c8d52006-05-27 19:21:47 +000074 # Check we get an error for a nonexistent module
Antoine Pitrouf51d8d32010-10-08 18:05:42 +000075 assert_python_failure('-m', 'fnord43520xyz')
Thomas Wouters477c8d52006-05-27 19:21:47 +000076 # Check the runpy module also gives an error for
77 # a nonexistent module
Antoine Pitrouf51d8d32010-10-08 18:05:42 +000078 assert_python_failure('-m', 'runpy', 'fnord43520xyz'),
Thomas Wouters477c8d52006-05-27 19:21:47 +000079 # All good if module is located and run successfully
Antoine Pitrouf51d8d32010-10-08 18:05:42 +000080 assert_python_ok('-m', 'timeit', '-n', '1'),
Thomas Wouters477c8d52006-05-27 19:21:47 +000081
Thomas Woutersed03b412007-08-28 21:37:11 +000082 def test_run_module_bug1764407(self):
83 # -m and -i need to play well together
84 # Runs the timeit module and checks the __main__
85 # namespace has been populated appropriately
Nick Coghlan260bd3e2009-11-16 06:49:25 +000086 p = spawn_python('-i', '-m', 'timeit', '-n', '1')
Guido van Rossuma1c42a92007-08-29 03:47:36 +000087 p.stdin.write(b'Timer\n')
88 p.stdin.write(b'exit()\n')
Nick Coghlan260bd3e2009-11-16 06:49:25 +000089 data = kill_python(p)
Thomas Woutersed03b412007-08-28 21:37:11 +000090 self.assertTrue(data.find(b'1 loop') != -1)
91 self.assertTrue(data.find(b'__main__.Timer') != -1)
92
Thomas Wouters477c8d52006-05-27 19:21:47 +000093 def test_run_code(self):
94 # Test expected operation of the '-c' switch
95 # Switch needs an argument
Antoine Pitrouf51d8d32010-10-08 18:05:42 +000096 assert_python_failure('-c')
Thomas Wouters477c8d52006-05-27 19:21:47 +000097 # Check we get an error for an uncaught exception
Antoine Pitrouf51d8d32010-10-08 18:05:42 +000098 assert_python_failure('-c', 'raise Exception')
Thomas Wouters477c8d52006-05-27 19:21:47 +000099 # All good if execution is successful
Antoine Pitrouf51d8d32010-10-08 18:05:42 +0000100 assert_python_ok('-c', 'pass')
Thomas Wouters477c8d52006-05-27 19:21:47 +0000101
Victor Stinner073f7592010-10-20 21:56:55 +0000102 @unittest.skipIf(sys.getfilesystemencoding() == 'ascii',
103 'need a filesystem encoding different than ASCII')
104 def test_non_ascii(self):
Amaury Forgeot d'Arc9a5499b2008-11-11 23:04:59 +0000105 # Test handling of non-ascii data
Victor Stinner073f7592010-10-20 21:56:55 +0000106 if test.support.verbose:
107 import locale
108 print('locale encoding = %s, filesystem encoding = %s'
109 % (locale.getpreferredencoding(), sys.getfilesystemencoding()))
110 command = "assert(ord('\xe9') == 0xe9)"
111 assert_python_ok('-c', command)
Amaury Forgeot d'Arc9a5499b2008-11-11 23:04:59 +0000112
Victor Stinnerf6211ed2010-10-20 21:52:33 +0000113 # On Windows, pass bytes to subprocess doesn't test how Python decodes the
114 # command line, but how subprocess does decode bytes to unicode. Python
115 # doesn't decode the command line because Windows provides directly the
116 # arguments as unicode (using wmain() instead of main()).
117 @unittest.skipIf(sys.platform == 'win32',
118 'Windows has a native unicode API')
119 def test_undecodable_code(self):
120 undecodable = b"\xff"
121 env = os.environ.copy()
122 # Use C locale to get ascii for the locale encoding
123 env['LC_ALL'] = 'C'
124 code = (
125 b'import locale; '
126 b'print(ascii("' + undecodable + b'"), '
127 b'locale.getpreferredencoding())')
128 p = subprocess.Popen(
129 [sys.executable, "-c", code],
130 stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
131 env=env)
132 stdout, stderr = p.communicate()
133 if p.returncode == 1:
134 # _Py_char2wchar() decoded b'\xff' as '\udcff' (b'\xff' is not
135 # decodable from ASCII) and run_command() failed on
136 # PyUnicode_AsUTF8String(). This is the expected behaviour on
137 # Linux.
138 pattern = b"Unable to decode the command from the command line:"
139 elif p.returncode == 0:
140 # _Py_char2wchar() decoded b'\xff' as '\xff' even if the locale is
141 # C and the locale encoding is ASCII. It occurs on FreeBSD, Solaris
142 # and Mac OS X.
143 pattern = b"'\\xff' "
144 # The output is followed by the encoding name, an alias to ASCII.
145 # Examples: "US-ASCII" or "646" (ISO 646, on Solaris).
146 else:
147 raise AssertionError("Unknown exit code: %s, output=%a" % (p.returncode, stdout))
148 if not stdout.startswith(pattern):
149 raise AssertionError("%a doesn't start with %a" % (stdout, pattern))
150
Antoine Pitrou05608432009-01-09 18:53:14 +0000151 def test_unbuffered_output(self):
152 # Test expected operation of the '-u' switch
153 for stream in ('stdout', 'stderr'):
154 # Binary is unbuffered
155 code = ("import os, sys; sys.%s.buffer.write(b'x'); os._exit(0)"
156 % stream)
Antoine Pitrouf51d8d32010-10-08 18:05:42 +0000157 rc, out, err = assert_python_ok('-u', '-c', code)
158 data = err if stream == 'stderr' else out
Antoine Pitrou05608432009-01-09 18:53:14 +0000159 self.assertEqual(data, b'x', "binary %s not unbuffered" % stream)
160 # Text is line-buffered
161 code = ("import os, sys; sys.%s.write('x\\n'); os._exit(0)"
162 % stream)
Antoine Pitrouf51d8d32010-10-08 18:05:42 +0000163 rc, out, err = assert_python_ok('-u', '-c', code)
164 data = err if stream == 'stderr' else out
Antoine Pitrou05608432009-01-09 18:53:14 +0000165 self.assertEqual(data.strip(), b'x',
166 "text %s not line-buffered" % stream)
167
Antoine Pitrou27fe9fc2009-01-26 21:48:00 +0000168 def test_unbuffered_input(self):
169 # sys.stdin still works with '-u'
170 code = ("import sys; sys.stdout.write(sys.stdin.read(1))")
Nick Coghlan260bd3e2009-11-16 06:49:25 +0000171 p = spawn_python('-u', '-c', code)
Antoine Pitrou27fe9fc2009-01-26 21:48:00 +0000172 p.stdin.write(b'x')
173 p.stdin.flush()
174 data, rc = _kill_python_and_exit_code(p)
175 self.assertEqual(rc, 0)
Benjamin Petersonc9c0f202009-06-30 23:06:06 +0000176 self.assertTrue(data.startswith(b'x'), data)
Antoine Pitrou27fe9fc2009-01-26 21:48:00 +0000177
Amaury Forgeot d'Arc66f8c432009-06-09 21:30:01 +0000178 def test_large_PYTHONPATH(self):
179 with test.support.EnvironmentVarGuard() as env:
180 path1 = "ABCDE" * 100
181 path2 = "FGHIJ" * 100
182 env['PYTHONPATH'] = path1 + os.pathsep + path2
Victor Stinner76cf6872010-04-16 15:10:27 +0000183
184 code = """
185import sys
186path = ":".join(sys.path)
187path = path.encode("ascii", "backslashreplace")
188sys.stdout.buffer.write(path)"""
189 code = code.strip().splitlines()
190 code = '; '.join(code)
191 p = _spawn_python_with_env('-S', '-c', code)
Amaury Forgeot d'Arc66f8c432009-06-09 21:30:01 +0000192 stdout, _ = p.communicate()
Benjamin Peterson577473f2010-01-19 00:09:57 +0000193 self.assertIn(path1.encode('ascii'), stdout)
194 self.assertIn(path2.encode('ascii'), stdout)
Amaury Forgeot d'Arc66f8c432009-06-09 21:30:01 +0000195
Thomas Wouters477c8d52006-05-27 19:21:47 +0000196
Neal Norwitz11bd1192005-10-03 00:54:56 +0000197def test_main():
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000198 test.support.run_unittest(CmdLineTest)
199 test.support.reap_children()
Neal Norwitz11bd1192005-10-03 00:54:56 +0000200
201if __name__ == "__main__":
202 test_main()