Home | History | Annotate | Download | only in test
      1 # Tests command line execution of scripts
      2 
      3 import unittest
      4 import os
      5 import os.path
      6 import test.test_support
      7 from test.script_helper import (run_python,
      8                                 temp_dir, make_script, compile_script,
      9                                 assert_python_failure, make_pkg,
     10                                 make_zip_script, make_zip_pkg)
     11 
     12 verbose = test.test_support.verbose
     13 
     14 
     15 example_args = ['test1', 'test2', 'test3']
     16 
     17 test_source = """\
     18 # Script may be run with optimisation enabled, so don't rely on assert
     19 # statements being executed
     20 def assertEqual(lhs, rhs):
     21     if lhs != rhs:
     22         raise AssertionError('%r != %r' % (lhs, rhs))
     23 def assertIdentical(lhs, rhs):
     24     if lhs is not rhs:
     25         raise AssertionError('%r is not %r' % (lhs, rhs))
     26 # Check basic code execution
     27 result = ['Top level assignment']
     28 def f():
     29     result.append('Lower level reference')
     30 f()
     31 assertEqual(result, ['Top level assignment', 'Lower level reference'])
     32 # Check population of magic variables
     33 assertEqual(__name__, '__main__')
     34 print '__file__==%r' % __file__
     35 print '__package__==%r' % __package__
     36 # Check the sys module
     37 import sys
     38 assertIdentical(globals(), sys.modules[__name__].__dict__)
     39 print 'sys.argv[0]==%r' % sys.argv[0]
     40 """
     41 
     42 def _make_test_script(script_dir, script_basename, source=test_source):
     43     return make_script(script_dir, script_basename, source)
     44 
     45 def _make_test_zip_pkg(zip_dir, zip_basename, pkg_name, script_basename,
     46                        source=test_source, depth=1):
     47     return make_zip_pkg(zip_dir, zip_basename, pkg_name, script_basename,
     48                         source, depth)
     49 
     50 # There's no easy way to pass the script directory in to get
     51 # -m to work (avoiding that is the whole point of making
     52 # directories and zipfiles executable!)
     53 # So we fake it for testing purposes with a custom launch script
     54 launch_source = """\
     55 import sys, os.path, runpy
     56 sys.path.insert(0, %s)
     57 runpy._run_module_as_main(%r)
     58 """
     59 
     60 def _make_launch_script(script_dir, script_basename, module_name, path=None):
     61     if path is None:
     62         path = "os.path.dirname(__file__)"
     63     else:
     64         path = repr(path)
     65     source = launch_source % (path, module_name)
     66     return make_script(script_dir, script_basename, source)
     67 
     68 class CmdLineTest(unittest.TestCase):
     69     def _check_script(self, script_name, expected_file,
     70                             expected_argv0, expected_package,
     71                             *cmd_line_switches):
     72         run_args = cmd_line_switches + (script_name,)
     73         exit_code, data = run_python(*run_args)
     74         if verbose:
     75             print 'Output from test script %r:' % script_name
     76             print data
     77         self.assertEqual(exit_code, 0)
     78         printed_file = '__file__==%r' % expected_file
     79         printed_argv0 = 'sys.argv[0]==%r' % expected_argv0
     80         printed_package = '__package__==%r' % expected_package
     81         if verbose:
     82             print 'Expected output:'
     83             print printed_file
     84             print printed_package
     85             print printed_argv0
     86         self.assertIn(printed_file, data)
     87         self.assertIn(printed_package, data)
     88         self.assertIn(printed_argv0, data)
     89 
     90     def _check_import_error(self, script_name, expected_msg,
     91                             *cmd_line_switches):
     92         run_args = cmd_line_switches + (script_name,)
     93         exit_code, data = run_python(*run_args)
     94         if verbose:
     95             print 'Output from test script %r:' % script_name
     96             print data
     97             print 'Expected output: %r' % expected_msg
     98         self.assertIn(expected_msg, data)
     99 
    100     def test_basic_script(self):
    101         with temp_dir() as script_dir:
    102             script_name = _make_test_script(script_dir, 'script')
    103             self._check_script(script_name, script_name, script_name, None)
    104 
    105     def test_script_compiled(self):
    106         with temp_dir() as script_dir:
    107             script_name = _make_test_script(script_dir, 'script')
    108             compiled_name = compile_script(script_name)
    109             os.remove(script_name)
    110             self._check_script(compiled_name, compiled_name, compiled_name, None)
    111 
    112     def test_directory(self):
    113         with temp_dir() as script_dir:
    114             script_name = _make_test_script(script_dir, '__main__')
    115             self._check_script(script_dir, script_name, script_dir, '')
    116 
    117     def test_directory_compiled(self):
    118         with temp_dir() as script_dir:
    119             script_name = _make_test_script(script_dir, '__main__')
    120             compiled_name = compile_script(script_name)
    121             os.remove(script_name)
    122             self._check_script(script_dir, compiled_name, script_dir, '')
    123 
    124     def test_directory_error(self):
    125         with temp_dir() as script_dir:
    126             msg = "can't find '__main__' module in %r" % script_dir
    127             self._check_import_error(script_dir, msg)
    128 
    129     def test_zipfile(self):
    130         with temp_dir() as script_dir:
    131             script_name = _make_test_script(script_dir, '__main__')
    132             zip_name, run_name = make_zip_script(script_dir, 'test_zip', script_name)
    133             self._check_script(zip_name, run_name, zip_name, '')
    134 
    135     def test_zipfile_compiled(self):
    136         with temp_dir() as script_dir:
    137             script_name = _make_test_script(script_dir, '__main__')
    138             compiled_name = compile_script(script_name)
    139             zip_name, run_name = make_zip_script(script_dir, 'test_zip', compiled_name)
    140             self._check_script(zip_name, run_name, zip_name, '')
    141 
    142     def test_zipfile_error(self):
    143         with temp_dir() as script_dir:
    144             script_name = _make_test_script(script_dir, 'not_main')
    145             zip_name, run_name = make_zip_script(script_dir, 'test_zip', script_name)
    146             msg = "can't find '__main__' module in %r" % zip_name
    147             self._check_import_error(zip_name, msg)
    148 
    149     def test_module_in_package(self):
    150         with temp_dir() as script_dir:
    151             pkg_dir = os.path.join(script_dir, 'test_pkg')
    152             make_pkg(pkg_dir)
    153             script_name = _make_test_script(pkg_dir, 'script')
    154             launch_name = _make_launch_script(script_dir, 'launch', 'test_pkg.script')
    155             self._check_script(launch_name, script_name, script_name, 'test_pkg')
    156 
    157     def test_module_in_package_in_zipfile(self):
    158         with temp_dir() as script_dir:
    159             zip_name, run_name = _make_test_zip_pkg(script_dir, 'test_zip', 'test_pkg', 'script')
    160             launch_name = _make_launch_script(script_dir, 'launch', 'test_pkg.script', zip_name)
    161             self._check_script(launch_name, run_name, run_name, 'test_pkg')
    162 
    163     def test_module_in_subpackage_in_zipfile(self):
    164         with temp_dir() as script_dir:
    165             zip_name, run_name = _make_test_zip_pkg(script_dir, 'test_zip', 'test_pkg', 'script', depth=2)
    166             launch_name = _make_launch_script(script_dir, 'launch', 'test_pkg.test_pkg.script', zip_name)
    167             self._check_script(launch_name, run_name, run_name, 'test_pkg.test_pkg')
    168 
    169     def test_package(self):
    170         with temp_dir() as script_dir:
    171             pkg_dir = os.path.join(script_dir, 'test_pkg')
    172             make_pkg(pkg_dir)
    173             script_name = _make_test_script(pkg_dir, '__main__')
    174             launch_name = _make_launch_script(script_dir, 'launch', 'test_pkg')
    175             self._check_script(launch_name, script_name,
    176                                script_name, 'test_pkg')
    177 
    178     def test_package_compiled(self):
    179         with temp_dir() as script_dir:
    180             pkg_dir = os.path.join(script_dir, 'test_pkg')
    181             make_pkg(pkg_dir)
    182             script_name = _make_test_script(pkg_dir, '__main__')
    183             compiled_name = compile_script(script_name)
    184             os.remove(script_name)
    185             launch_name = _make_launch_script(script_dir, 'launch', 'test_pkg')
    186             self._check_script(launch_name, compiled_name,
    187                                compiled_name, 'test_pkg')
    188 
    189     def test_package_error(self):
    190         with temp_dir() as script_dir:
    191             pkg_dir = os.path.join(script_dir, 'test_pkg')
    192             make_pkg(pkg_dir)
    193             msg = ("'test_pkg' is a package and cannot "
    194                    "be directly executed")
    195             launch_name = _make_launch_script(script_dir, 'launch', 'test_pkg')
    196             self._check_import_error(launch_name, msg)
    197 
    198     def test_package_recursion(self):
    199         with temp_dir() as script_dir:
    200             pkg_dir = os.path.join(script_dir, 'test_pkg')
    201             make_pkg(pkg_dir)
    202             main_dir = os.path.join(pkg_dir, '__main__')
    203             make_pkg(main_dir)
    204             msg = ("Cannot use package as __main__ module; "
    205                    "'test_pkg' is a package and cannot "
    206                    "be directly executed")
    207             launch_name = _make_launch_script(script_dir, 'launch', 'test_pkg')
    208             self._check_import_error(launch_name, msg)
    209 
    210     def test_dash_m_error_code_is_one(self):
    211         # If a module is invoked with the -m command line flag
    212         # and results in an error that the return code to the
    213         # shell is '1'
    214         with temp_dir() as script_dir:
    215             pkg_dir = os.path.join(script_dir, 'test_pkg')
    216             make_pkg(pkg_dir)
    217             script_name = _make_test_script(pkg_dir, 'other', "if __name__ == '__main__': raise ValueError")
    218             rc, out, err = assert_python_failure('-m', 'test_pkg.other', *example_args)
    219             if verbose > 1:
    220                 print(out)
    221             self.assertEqual(rc, 1)
    222 
    223 
    224 def test_main():
    225     test.test_support.run_unittest(CmdLineTest)
    226     test.test_support.reap_children()
    227 
    228 if __name__ == '__main__':
    229     test_main()
    230