1# 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
4
5import test.test_support
6import sys
7import unittest
8from test.script_helper import (
9    assert_python_ok, assert_python_failure, spawn_python, kill_python,
10    python_exit_code
11)
12
13
14class CmdLineTest(unittest.TestCase):
15    def start_python(self, *args):
16        p = spawn_python(*args)
17        return kill_python(p)
18
19    def exit_code(self, *args):
20        return python_exit_code(*args)
21
22    def test_directories(self):
23        self.assertNotEqual(self.exit_code('.'), 0)
24        self.assertNotEqual(self.exit_code('< .'), 0)
25
26    def verify_valid_flag(self, cmd_line):
27        data = self.start_python(cmd_line)
28        self.assertTrue(data == '' or data.endswith('\n'))
29        self.assertNotIn('Traceback', data)
30
31    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):
45        self.assertIn('usage', self.start_python('-h'))
46
47    def test_version(self):
48        version = 'Python %d.%d' % sys.version_info[:2]
49        self.assertTrue(self.start_python('-V').startswith(version))
50
51    def test_run_module(self):
52        # Test expected operation of the '-m' switch
53        # Switch needs an argument
54        self.assertNotEqual(self.exit_code('-m'), 0)
55        # Check we get an error for a nonexistent module
56        self.assertNotEqual(
57            self.exit_code('-m', 'fnord43520xyz'),
58            0)
59        # Check the runpy module also gives an error for
60        # a nonexistent module
61        self.assertNotEqual(
62            self.exit_code('-m', 'runpy', 'fnord43520xyz'),
63            0)
64        # All good if module is located and run successfully
65        self.assertEqual(
66            self.exit_code('-m', 'timeit', '-n', '1'),
67            0)
68
69    def test_run_module_bug1764407(self):
70        # -m and -i need to play well together
71        # Runs the timeit module and checks the __main__
72        # namespace has been populated appropriately
73        p = spawn_python('-i', '-m', 'timeit', '-n', '1')
74        p.stdin.write('Timer\n')
75        p.stdin.write('exit()\n')
76        data = kill_python(p)
77        self.assertTrue(data.startswith('1 loop'))
78        self.assertIn('__main__.Timer', data)
79
80    def test_run_code(self):
81        # Test expected operation of the '-c' switch
82        # Switch needs an argument
83        self.assertNotEqual(self.exit_code('-c'), 0)
84        # Check we get an error for an uncaught exception
85        self.assertNotEqual(
86            self.exit_code('-c', 'raise Exception'),
87            0)
88        # All good if execution is successful
89        self.assertEqual(
90            self.exit_code('-c', 'pass'),
91            0)
92
93    def test_hash_randomization(self):
94        # Verify that -R enables hash randomization:
95        self.verify_valid_flag('-R')
96        hashes = []
97        for i in range(2):
98            code = 'print(hash("spam"))'
99            data = self.start_python('-R', '-c', code)
100            hashes.append(data)
101        self.assertNotEqual(hashes[0], hashes[1])
102
103        # Verify that sys.flags contains hash_randomization
104        code = 'import sys; print sys.flags'
105        data = self.start_python('-R', '-c', code)
106        self.assertTrue('hash_randomization=1' in data)
107
108    def test_del___main__(self):
109        # Issue #15001: PyRun_SimpleFileExFlags() did crash because it kept a
110        # borrowed reference to the dict of __main__ module and later modify
111        # the dict whereas the module was destroyed
112        filename = test.test_support.TESTFN
113        self.addCleanup(test.test_support.unlink, filename)
114        with open(filename, "w") as script:
115            print >>script, "import sys"
116            print >>script, "del sys.modules['__main__']"
117        assert_python_ok(filename)
118
119    def test_unknown_options(self):
120        rc, out, err = assert_python_failure('-E', '-z')
121        self.assertIn(b'Unknown option: -z', err)
122        self.assertEqual(err.splitlines().count(b'Unknown option: -z'), 1)
123        self.assertEqual(b'', out)
124        # Add "without='-E'" to prevent _assert_python to append -E
125        # to env_vars and change the output of stderr
126        rc, out, err = assert_python_failure('-z', without='-E')
127        self.assertIn(b'Unknown option: -z', err)
128        self.assertEqual(err.splitlines().count(b'Unknown option: -z'), 1)
129        self.assertEqual(b'', out)
130        rc, out, err = assert_python_failure('-a', '-z', without='-E')
131        self.assertIn(b'Unknown option: -a', err)
132        # only the first unknown option is reported
133        self.assertNotIn(b'Unknown option: -z', err)
134        self.assertEqual(err.splitlines().count(b'Unknown option: -a'), 1)
135        self.assertEqual(b'', out)
136
137
138def test_main():
139    test.test_support.run_unittest(CmdLineTest)
140    test.test_support.reap_children()
141
142if __name__ == "__main__":
143    test_main()
144