Christian Heimes | 9cd1775 | 2007-11-18 19:35:23 +0000 | [diff] [blame] | 1 | # Tests command line execution of scripts |
Christian Heimes | 9cd1775 | 2007-11-18 19:35:23 +0000 | [diff] [blame] | 2 | |
| 3 | import unittest |
| 4 | import os |
| 5 | import os.path |
| 6 | import sys |
Benjamin Peterson | ee8712c | 2008-05-20 21:35:26 +0000 | [diff] [blame] | 7 | import test.support |
Christian Heimes | 9cd1775 | 2007-11-18 19:35:23 +0000 | [diff] [blame] | 8 | import tempfile |
| 9 | import subprocess |
| 10 | import py_compile |
| 11 | import contextlib |
| 12 | import shutil |
| 13 | import zipfile |
| 14 | |
Benjamin Peterson | ee8712c | 2008-05-20 21:35:26 +0000 | [diff] [blame] | 15 | verbose = test.support.verbose |
Christian Heimes | 9cd1775 | 2007-11-18 19:35:23 +0000 | [diff] [blame] | 16 | |
Benjamin Peterson | ee8712c | 2008-05-20 21:35:26 +0000 | [diff] [blame] | 17 | # XXX ncoghlan: Should we consider moving these to support? |
Guido van Rossum | 87afcbf | 2007-11-19 15:56:44 +0000 | [diff] [blame] | 18 | from test.test_cmd_line import _spawn_python, _kill_python |
Christian Heimes | 9cd1775 | 2007-11-18 19:35:23 +0000 | [diff] [blame] | 19 | |
| 20 | def _run_python(*args): |
| 21 | if __debug__: |
| 22 | p = _spawn_python(*args) |
| 23 | else: |
| 24 | p = _spawn_python('-O', *args) |
| 25 | stdout_data = _kill_python(p) |
| 26 | return p.wait(), stdout_data.decode() |
| 27 | |
| 28 | @contextlib.contextmanager |
| 29 | def temp_dir(): |
| 30 | dirname = tempfile.mkdtemp() |
Guido van Rossum | 87c0f1d | 2007-11-19 18:03:44 +0000 | [diff] [blame] | 31 | dirname = os.path.realpath(dirname) |
Christian Heimes | 9cd1775 | 2007-11-18 19:35:23 +0000 | [diff] [blame] | 32 | try: |
| 33 | yield dirname |
| 34 | finally: |
| 35 | shutil.rmtree(dirname) |
| 36 | |
Christian Heimes | cbf3b5c | 2007-12-03 21:02:03 +0000 | [diff] [blame] | 37 | test_source = """\ |
Christian Heimes | 9cd1775 | 2007-11-18 19:35:23 +0000 | [diff] [blame] | 38 | # Script may be run with optimisation enabled, so don't rely on assert |
| 39 | # statements being executed |
| 40 | def assertEqual(lhs, rhs): |
| 41 | if lhs != rhs: |
Christian Heimes | cbf3b5c | 2007-12-03 21:02:03 +0000 | [diff] [blame] | 42 | raise AssertionError('%r != %r' % (lhs, rhs)) |
Christian Heimes | 9cd1775 | 2007-11-18 19:35:23 +0000 | [diff] [blame] | 43 | def assertIdentical(lhs, rhs): |
| 44 | if lhs is not rhs: |
Christian Heimes | cbf3b5c | 2007-12-03 21:02:03 +0000 | [diff] [blame] | 45 | raise AssertionError('%r is not %r' % (lhs, rhs)) |
Christian Heimes | 9cd1775 | 2007-11-18 19:35:23 +0000 | [diff] [blame] | 46 | # Check basic code execution |
| 47 | result = ['Top level assignment'] |
| 48 | def f(): |
| 49 | result.append('Lower level reference') |
| 50 | f() |
| 51 | assertEqual(result, ['Top level assignment', 'Lower level reference']) |
| 52 | # Check population of magic variables |
| 53 | assertEqual(__name__, '__main__') |
| 54 | print('__file__==%r' % __file__) |
Christian Heimes | cbf3b5c | 2007-12-03 21:02:03 +0000 | [diff] [blame] | 55 | print('__package__==%r' % __package__) |
Christian Heimes | 9cd1775 | 2007-11-18 19:35:23 +0000 | [diff] [blame] | 56 | # Check the sys module |
| 57 | import sys |
| 58 | assertIdentical(globals(), sys.modules[__name__].__dict__) |
| 59 | print('sys.argv[0]==%r' % sys.argv[0]) |
Christian Heimes | cbf3b5c | 2007-12-03 21:02:03 +0000 | [diff] [blame] | 60 | """ |
Christian Heimes | 9cd1775 | 2007-11-18 19:35:23 +0000 | [diff] [blame] | 61 | |
Christian Heimes | cbf3b5c | 2007-12-03 21:02:03 +0000 | [diff] [blame] | 62 | def _make_test_script(script_dir, script_basename, source=test_source): |
| 63 | script_filename = script_basename+os.path.extsep+'py' |
Christian Heimes | 9cd1775 | 2007-11-18 19:35:23 +0000 | [diff] [blame] | 64 | script_name = os.path.join(script_dir, script_filename) |
Christian Heimes | cbf3b5c | 2007-12-03 21:02:03 +0000 | [diff] [blame] | 65 | script_file = open(script_name, 'w') |
| 66 | script_file.write(source) |
Christian Heimes | 9cd1775 | 2007-11-18 19:35:23 +0000 | [diff] [blame] | 67 | script_file.close() |
| 68 | return script_name |
| 69 | |
| 70 | def _compile_test_script(script_name): |
| 71 | py_compile.compile(script_name, doraise=True) |
| 72 | if __debug__: |
| 73 | compiled_name = script_name + 'c' |
| 74 | else: |
| 75 | compiled_name = script_name + 'o' |
| 76 | return compiled_name |
| 77 | |
| 78 | def _make_test_zip(zip_dir, zip_basename, script_name): |
| 79 | zip_filename = zip_basename+os.path.extsep+"zip" |
| 80 | zip_name = os.path.join(zip_dir, zip_filename) |
| 81 | zip_file = zipfile.ZipFile(zip_name, 'w') |
| 82 | zip_file.write(script_name, os.path.basename(script_name)) |
| 83 | zip_file.close() |
| 84 | # if verbose: |
| 85 | # zip_file = zipfile.ZipFile(zip_name, 'r') |
Guido van Rossum | 87c0f1d | 2007-11-19 18:03:44 +0000 | [diff] [blame] | 86 | # print("Contents of %r:" % zip_name) |
Christian Heimes | 9cd1775 | 2007-11-18 19:35:23 +0000 | [diff] [blame] | 87 | # zip_file.printdir() |
| 88 | # zip_file.close() |
| 89 | return zip_name |
| 90 | |
Christian Heimes | cbf3b5c | 2007-12-03 21:02:03 +0000 | [diff] [blame] | 91 | def _make_test_pkg(pkg_dir): |
| 92 | os.mkdir(pkg_dir) |
| 93 | _make_test_script(pkg_dir, '__init__', '') |
| 94 | |
| 95 | # There's no easy way to pass the script directory in to get |
| 96 | # -m to work (avoiding that is the whole point of making |
| 97 | # directories and zipfiles executable!) |
| 98 | # So we fake it for testing purposes with a custom launch script |
| 99 | launch_source = """\ |
| 100 | import sys, os.path, runpy |
| 101 | sys.path[0:0] = os.path.dirname(__file__) |
| 102 | runpy._run_module_as_main(%r) |
| 103 | """ |
| 104 | |
| 105 | def _make_launch_script(script_dir, script_basename, module_name): |
| 106 | return _make_test_script(script_dir, script_basename, |
| 107 | launch_source % module_name) |
| 108 | |
Christian Heimes | 9cd1775 | 2007-11-18 19:35:23 +0000 | [diff] [blame] | 109 | class CmdLineTest(unittest.TestCase): |
Christian Heimes | cbf3b5c | 2007-12-03 21:02:03 +0000 | [diff] [blame] | 110 | def _check_script(self, script_name, expected_file, |
| 111 | expected_argv0, expected_package, |
| 112 | *cmd_line_switches): |
| 113 | run_args = cmd_line_switches + (script_name,) |
| 114 | exit_code, data = _run_python(*run_args) |
Guido van Rossum | 87c0f1d | 2007-11-19 18:03:44 +0000 | [diff] [blame] | 115 | if verbose: |
| 116 | print("Output from test script %r:" % script_name) |
| 117 | print(data) |
Christian Heimes | cbf3b5c | 2007-12-03 21:02:03 +0000 | [diff] [blame] | 118 | self.assertEqual(exit_code, 0) |
Christian Heimes | 9cd1775 | 2007-11-18 19:35:23 +0000 | [diff] [blame] | 119 | printed_file = '__file__==%r' % expected_file |
| 120 | printed_argv0 = 'sys.argv[0]==%r' % expected_argv0 |
Christian Heimes | cbf3b5c | 2007-12-03 21:02:03 +0000 | [diff] [blame] | 121 | printed_package = '__package__==%r' % expected_package |
| 122 | if verbose: |
| 123 | print('Expected output:') |
| 124 | print(printed_file) |
| 125 | print(printed_package) |
| 126 | print(printed_argv0) |
| 127 | self.assert_(printed_file in data) |
| 128 | self.assert_(printed_package in data) |
| 129 | self.assert_(printed_argv0 in data) |
Christian Heimes | 9cd1775 | 2007-11-18 19:35:23 +0000 | [diff] [blame] | 130 | |
| 131 | def test_basic_script(self): |
| 132 | with temp_dir() as script_dir: |
Christian Heimes | cbf3b5c | 2007-12-03 21:02:03 +0000 | [diff] [blame] | 133 | script_name = _make_test_script(script_dir, 'script') |
| 134 | self._check_script(script_name, script_name, script_name, None) |
Christian Heimes | 9cd1775 | 2007-11-18 19:35:23 +0000 | [diff] [blame] | 135 | |
| 136 | def test_script_compiled(self): |
| 137 | with temp_dir() as script_dir: |
Christian Heimes | cbf3b5c | 2007-12-03 21:02:03 +0000 | [diff] [blame] | 138 | script_name = _make_test_script(script_dir, 'script') |
Christian Heimes | 9cd1775 | 2007-11-18 19:35:23 +0000 | [diff] [blame] | 139 | compiled_name = _compile_test_script(script_name) |
| 140 | os.remove(script_name) |
Christian Heimes | cbf3b5c | 2007-12-03 21:02:03 +0000 | [diff] [blame] | 141 | self._check_script(compiled_name, compiled_name, compiled_name, None) |
Christian Heimes | 9cd1775 | 2007-11-18 19:35:23 +0000 | [diff] [blame] | 142 | |
| 143 | def test_directory(self): |
| 144 | with temp_dir() as script_dir: |
Christian Heimes | cbf3b5c | 2007-12-03 21:02:03 +0000 | [diff] [blame] | 145 | script_name = _make_test_script(script_dir, '__main__') |
| 146 | self._check_script(script_dir, script_name, script_dir, '') |
Christian Heimes | 9cd1775 | 2007-11-18 19:35:23 +0000 | [diff] [blame] | 147 | |
| 148 | def test_directory_compiled(self): |
| 149 | with temp_dir() as script_dir: |
Christian Heimes | cbf3b5c | 2007-12-03 21:02:03 +0000 | [diff] [blame] | 150 | script_name = _make_test_script(script_dir, '__main__') |
Christian Heimes | 9cd1775 | 2007-11-18 19:35:23 +0000 | [diff] [blame] | 151 | compiled_name = _compile_test_script(script_name) |
| 152 | os.remove(script_name) |
Christian Heimes | cbf3b5c | 2007-12-03 21:02:03 +0000 | [diff] [blame] | 153 | self._check_script(script_dir, compiled_name, script_dir, '') |
Christian Heimes | 9cd1775 | 2007-11-18 19:35:23 +0000 | [diff] [blame] | 154 | |
| 155 | def test_zipfile(self): |
| 156 | with temp_dir() as script_dir: |
Christian Heimes | cbf3b5c | 2007-12-03 21:02:03 +0000 | [diff] [blame] | 157 | script_name = _make_test_script(script_dir, '__main__') |
| 158 | zip_name = _make_test_zip(script_dir, 'test_zip', script_name) |
| 159 | self._check_script(zip_name, None, zip_name, '') |
Christian Heimes | 9cd1775 | 2007-11-18 19:35:23 +0000 | [diff] [blame] | 160 | |
| 161 | def test_zipfile_compiled(self): |
| 162 | with temp_dir() as script_dir: |
Christian Heimes | cbf3b5c | 2007-12-03 21:02:03 +0000 | [diff] [blame] | 163 | script_name = _make_test_script(script_dir, '__main__') |
Christian Heimes | 9cd1775 | 2007-11-18 19:35:23 +0000 | [diff] [blame] | 164 | compiled_name = _compile_test_script(script_name) |
Christian Heimes | cbf3b5c | 2007-12-03 21:02:03 +0000 | [diff] [blame] | 165 | zip_name = _make_test_zip(script_dir, 'test_zip', compiled_name) |
| 166 | self._check_script(zip_name, None, zip_name, '') |
| 167 | |
| 168 | def test_module_in_package(self): |
| 169 | with temp_dir() as script_dir: |
| 170 | pkg_dir = os.path.join(script_dir, 'test_pkg') |
| 171 | _make_test_pkg(pkg_dir) |
| 172 | script_name = _make_test_script(pkg_dir, 'script') |
| 173 | launch_name = _make_launch_script(script_dir, 'launch', 'test_pkg.script') |
| 174 | self._check_script(launch_name, script_name, |
| 175 | script_name, 'test_pkg') |
Christian Heimes | 9cd1775 | 2007-11-18 19:35:23 +0000 | [diff] [blame] | 176 | |
| 177 | |
| 178 | def test_main(): |
Benjamin Peterson | ee8712c | 2008-05-20 21:35:26 +0000 | [diff] [blame] | 179 | test.support.run_unittest(CmdLineTest) |
| 180 | test.support.reap_children() |
Christian Heimes | 9cd1775 | 2007-11-18 19:35:23 +0000 | [diff] [blame] | 181 | |
Christian Heimes | cbf3b5c | 2007-12-03 21:02:03 +0000 | [diff] [blame] | 182 | if __name__ == '__main__': |
Christian Heimes | 9cd1775 | 2007-11-18 19:35:23 +0000 | [diff] [blame] | 183 | test_main() |