blob: ef3c1099503f0765819a49b4118b49c3d4d7c4b6 [file] [log] [blame]
Christian Heimes9cd17752007-11-18 19:35:23 +00001# Tests invocation of the interpreter with various command line arguments
2# All tests are executed with environment variables ignored
3# See test_cmd_line_script.py for testing of script execution
Neal Norwitz11bd1192005-10-03 00:54:56 +00004
Philip Jenveyab7481a2009-05-22 05:46:35 +00005import os
Benjamin Petersonee8712c2008-05-20 21:35:26 +00006import test.support, unittest
Antoine Pitrou87695762008-08-14 22:44:29 +00007import os
Neal Norwitz11bd1192005-10-03 00:54:56 +00008import sys
Walter Dörwald9356fb92005-11-25 15:22:10 +00009import subprocess
Neal Norwitz11bd1192005-10-03 00:54:56 +000010
Thomas Woutersed03b412007-08-28 21:37:11 +000011def _spawn_python(*args):
Antoine Pitrou87695762008-08-14 22:44:29 +000012 cmd_line = [sys.executable]
13 # When testing -S, we need PYTHONPATH to work (see test_site_flag())
14 if '-S' not in args:
15 cmd_line.append('-E')
Thomas Woutersed03b412007-08-28 21:37:11 +000016 cmd_line.extend(args)
17 return subprocess.Popen(cmd_line, stdin=subprocess.PIPE,
18 stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
19
20def _kill_python(p):
Trent Nelson39e307e2008-03-19 06:45:48 +000021 return _kill_python_and_exit_code(p)[0]
22
23def _kill_python_and_exit_code(p):
Thomas Woutersed03b412007-08-28 21:37:11 +000024 p.stdin.close()
25 data = p.stdout.read()
26 p.stdout.close()
27 # try to cleanup the child so we don't appear to leak when running
28 # with regrtest -R. This should be a no-op on Windows.
29 subprocess._cleanup()
Trent Nelson39e307e2008-03-19 06:45:48 +000030 returncode = p.wait()
31 return data, returncode
Thomas Woutersed03b412007-08-28 21:37:11 +000032
Neal Norwitz11bd1192005-10-03 00:54:56 +000033class CmdLineTest(unittest.TestCase):
Thomas Woutersed03b412007-08-28 21:37:11 +000034 def start_python(self, *args):
Trent Nelson39e307e2008-03-19 06:45:48 +000035 return self.start_python_and_exit_code(*args)[0]
36
37 def start_python_and_exit_code(self, *args):
Thomas Woutersed03b412007-08-28 21:37:11 +000038 p = _spawn_python(*args)
Trent Nelson39e307e2008-03-19 06:45:48 +000039 return _kill_python_and_exit_code(p)
Neal Norwitz11bd1192005-10-03 00:54:56 +000040
Thomas Wouters477c8d52006-05-27 19:21:47 +000041 def exit_code(self, *args):
Thomas Wouters1b7f8912007-09-19 03:06:30 +000042 cmd_line = [sys.executable, '-E']
Thomas Wouters477c8d52006-05-27 19:21:47 +000043 cmd_line.extend(args)
Philip Jenveyab7481a2009-05-22 05:46:35 +000044 with open(os.devnull, 'w') as devnull:
45 return subprocess.call(cmd_line, stdout=devnull,
46 stderr=subprocess.STDOUT)
Walter Dörwald9356fb92005-11-25 15:22:10 +000047
Neal Norwitz11bd1192005-10-03 00:54:56 +000048 def test_directories(self):
Neal Norwitz72c2c062006-03-09 05:58:11 +000049 self.assertNotEqual(self.exit_code('.'), 0)
50 self.assertNotEqual(self.exit_code('< .'), 0)
Neal Norwitz11bd1192005-10-03 00:54:56 +000051
52 def verify_valid_flag(self, cmd_line):
53 data = self.start_python(cmd_line)
Guido van Rossuma1c42a92007-08-29 03:47:36 +000054 self.assertTrue(data == b'' or data.endswith(b'\n'))
Guido van Rossumf074b642007-07-11 06:56:16 +000055 self.assertTrue(b'Traceback' not in data)
Neal Norwitz11bd1192005-10-03 00:54:56 +000056
Neal Norwitz11bd1192005-10-03 00:54:56 +000057 def test_optimize(self):
58 self.verify_valid_flag('-O')
59 self.verify_valid_flag('-OO')
60
61 def test_q(self):
62 self.verify_valid_flag('-Qold')
63 self.verify_valid_flag('-Qnew')
64 self.verify_valid_flag('-Qwarn')
65 self.verify_valid_flag('-Qwarnall')
66
67 def test_site_flag(self):
Antoine Pitrou87695762008-08-14 22:44:29 +000068 if os.name == 'posix':
69 # Workaround bug #586680 by adding the extension dir to PYTHONPATH
70 from distutils.util import get_platform
71 s = "./build/lib.%s-%.3s" % (get_platform(), sys.version)
72 if hasattr(sys, 'gettotalrefcount'):
73 s += '-pydebug'
74 p = os.environ.get('PYTHONPATH', '')
75 if p:
76 p += ':'
77 os.environ['PYTHONPATH'] = p + s
Neal Norwitz11bd1192005-10-03 00:54:56 +000078 self.verify_valid_flag('-S')
79
80 def test_usage(self):
Guido van Rossumf074b642007-07-11 06:56:16 +000081 self.assertTrue(b'usage' in self.start_python('-h'))
Neal Norwitz11bd1192005-10-03 00:54:56 +000082
83 def test_version(self):
Guido van Rossuma1c42a92007-08-29 03:47:36 +000084 version = ('Python %d.%d' % sys.version_info[:2]).encode("ascii")
Neal Norwitz11bd1192005-10-03 00:54:56 +000085 self.assertTrue(self.start_python('-V').startswith(version))
86
Trent Nelson39e307e2008-03-19 06:45:48 +000087 def test_verbose(self):
88 # -v causes imports to write to stderr. If the write to
89 # stderr itself causes an import to happen (for the output
90 # codec), a recursion loop can occur.
91 data, rc = self.start_python_and_exit_code('-v')
92 self.assertEqual(rc, 0)
93 self.assertTrue(b'stack overflow' not in data)
94 data, rc = self.start_python_and_exit_code('-vv')
95 self.assertEqual(rc, 0)
96 self.assertTrue(b'stack overflow' not in data)
97
Thomas Wouters477c8d52006-05-27 19:21:47 +000098 def test_run_module(self):
99 # Test expected operation of the '-m' switch
100 # Switch needs an argument
101 self.assertNotEqual(self.exit_code('-m'), 0)
102 # Check we get an error for a nonexistent module
103 self.assertNotEqual(
104 self.exit_code('-m', 'fnord43520xyz'),
105 0)
106 # Check the runpy module also gives an error for
107 # a nonexistent module
108 self.assertNotEqual(
109 self.exit_code('-m', 'runpy', 'fnord43520xyz'),
110 0)
111 # All good if module is located and run successfully
112 self.assertEqual(
113 self.exit_code('-m', 'timeit', '-n', '1'),
114 0)
115
Thomas Woutersed03b412007-08-28 21:37:11 +0000116 def test_run_module_bug1764407(self):
117 # -m and -i need to play well together
118 # Runs the timeit module and checks the __main__
119 # namespace has been populated appropriately
120 p = _spawn_python('-i', '-m', 'timeit', '-n', '1')
Guido van Rossuma1c42a92007-08-29 03:47:36 +0000121 p.stdin.write(b'Timer\n')
122 p.stdin.write(b'exit()\n')
Thomas Woutersed03b412007-08-28 21:37:11 +0000123 data = _kill_python(p)
124 self.assertTrue(data.find(b'1 loop') != -1)
125 self.assertTrue(data.find(b'__main__.Timer') != -1)
126
Thomas Wouters477c8d52006-05-27 19:21:47 +0000127 def test_run_code(self):
128 # Test expected operation of the '-c' switch
129 # Switch needs an argument
130 self.assertNotEqual(self.exit_code('-c'), 0)
131 # Check we get an error for an uncaught exception
132 self.assertNotEqual(
133 self.exit_code('-c', 'raise Exception'),
134 0)
135 # All good if execution is successful
136 self.assertEqual(
137 self.exit_code('-c', 'pass'),
138 0)
139
Amaury Forgeot d'Arc9a5499b2008-11-11 23:04:59 +0000140 # Test handling of non-ascii data
Amaury Forgeot d'Arce2557642008-11-12 00:59:11 +0000141 if sys.getfilesystemencoding() != 'ascii':
142 command = "assert(ord('\xe9') == 0xe9)"
143 self.assertEqual(
144 self.exit_code('-c', command),
145 0)
Amaury Forgeot d'Arc9a5499b2008-11-11 23:04:59 +0000146
Antoine Pitrou05608432009-01-09 18:53:14 +0000147 def test_unbuffered_output(self):
148 # Test expected operation of the '-u' switch
149 for stream in ('stdout', 'stderr'):
150 # Binary is unbuffered
151 code = ("import os, sys; sys.%s.buffer.write(b'x'); os._exit(0)"
152 % stream)
153 data, rc = self.start_python_and_exit_code('-u', '-c', code)
154 self.assertEqual(rc, 0)
155 self.assertEqual(data, b'x', "binary %s not unbuffered" % stream)
156 # Text is line-buffered
157 code = ("import os, sys; sys.%s.write('x\\n'); os._exit(0)"
158 % stream)
159 data, rc = self.start_python_and_exit_code('-u', '-c', code)
160 self.assertEqual(rc, 0)
161 self.assertEqual(data.strip(), b'x',
162 "text %s not line-buffered" % stream)
163
Antoine Pitrou27fe9fc2009-01-26 21:48:00 +0000164 def test_unbuffered_input(self):
165 # sys.stdin still works with '-u'
166 code = ("import sys; sys.stdout.write(sys.stdin.read(1))")
167 p = _spawn_python('-u', '-c', code)
168 p.stdin.write(b'x')
169 p.stdin.flush()
170 data, rc = _kill_python_and_exit_code(p)
171 self.assertEqual(rc, 0)
Antoine Pitrou39df6102009-01-26 22:00:21 +0000172 self.assert_(data.startswith(b'x'), data)
Antoine Pitrou27fe9fc2009-01-26 21:48:00 +0000173
Amaury Forgeot d'Arc66f8c432009-06-09 21:30:01 +0000174 def test_large_PYTHONPATH(self):
175 with test.support.EnvironmentVarGuard() as env:
176 path1 = "ABCDE" * 100
177 path2 = "FGHIJ" * 100
178 env['PYTHONPATH'] = path1 + os.pathsep + path2
179 p = _spawn_python('-S', '-c', 'import sys; print(sys.path)')
180 stdout, _ = p.communicate()
181 self.assert_(path1.encode('ascii') in stdout)
182 self.assert_(path2.encode('ascii') in stdout)
183
Thomas Wouters477c8d52006-05-27 19:21:47 +0000184
Neal Norwitz11bd1192005-10-03 00:54:56 +0000185def test_main():
Benjamin Petersonee8712c2008-05-20 21:35:26 +0000186 test.support.run_unittest(CmdLineTest)
187 test.support.reap_children()
Neal Norwitz11bd1192005-10-03 00:54:56 +0000188
189if __name__ == "__main__":
190 test_main()