# Licensed under the Apache License: http://www.apache.org/licenses/LICENSE-2.0 # For details: https://bitbucket.org/ned/coveragepy/src/default/NOTICE.txt """Tests for coverage.execfile""" import compileall import json import os import os.path import re from coverage import env from coverage.backward import binary_bytes from coverage.execfile import run_python_file, run_python_module from coverage.misc import NoCode, NoSource from tests.coveragetest import CoverageTest, TESTS_DIR, UsingModulesMixin TRY_EXECFILE = os.path.join(TESTS_DIR, "modules/process_test/try_execfile.py") class RunFileTest(CoverageTest): """Test cases for `run_python_file`.""" def test_run_python_file(self): run_python_file(TRY_EXECFILE, [TRY_EXECFILE, "arg1", "arg2"]) mod_globs = json.loads(self.stdout()) # The file should think it is __main__ self.assertEqual(mod_globs['__name__'], "__main__") # It should seem to come from a file named try_execfile.py dunder_file = os.path.basename(mod_globs['__file__']) self.assertEqual(dunder_file, "try_execfile.py") # It should have its correct module data. self.assertEqual(mod_globs['__doc__'].splitlines()[0], "Test file for run_python_file.") self.assertEqual(mod_globs['DATA'], "xyzzy") self.assertEqual(mod_globs['FN_VAL'], "my_fn('fooey')") # It must be self-importable as __main__. self.assertEqual(mod_globs['__main__.DATA'], "xyzzy") # Argv should have the proper values. self.assertEqual(mod_globs['argv0'], TRY_EXECFILE) self.assertEqual(mod_globs['argv1-n'], ["arg1", "arg2"]) # __builtins__ should have the right values, like open(). self.assertEqual(mod_globs['__builtins__.has_open'], True) def test_no_extra_file(self): # Make sure that running a file doesn't create an extra compiled file. self.make_file("xxx", """\ desc = "a non-.py file!" """) self.assertEqual(os.listdir("."), ["xxx"]) run_python_file("xxx", ["xxx"]) self.assertEqual(os.listdir("."), ["xxx"]) def test_universal_newlines(self): # Make sure we can read any sort of line ending. pylines = """# try newlines|print('Hello, world!')|""".split('|') for nl in ('\n', '\r\n', '\r'): with open('nl.py', 'wb') as fpy: fpy.write(nl.join(pylines).encode('utf-8')) run_python_file('nl.py', ['nl.py']) self.assertEqual(self.stdout(), "Hello, world!\n"*3) def test_missing_final_newline(self): # Make sure we can deal with a Python file with no final newline. self.make_file("abrupt.py", """\ if 1: a = 1 print("a is %r" % a) #""") with open("abrupt.py") as f: abrupt = f.read() self.assertEqual(abrupt[-1], '#') run_python_file("abrupt.py", ["abrupt.py"]) self.assertEqual(self.stdout(), "a is 1\n") def test_no_such_file(self): with self.assertRaises(NoSource): run_python_file("xyzzy.py", []) def test_directory_with_main(self): self.make_file("with_main/__main__.py", """\ print("I am __main__") """) run_python_file("with_main", ["with_main"]) self.assertEqual(self.stdout(), "I am __main__\n") def test_directory_without_main(self): self.make_file("without_main/__init__.py", "") with self.assertRaisesRegex(NoSource, "Can't find '__main__' module in 'without_main'"): run_python_file("without_main", ["without_main"]) class RunPycFileTest(CoverageTest): """Test cases for `run_python_file`.""" def make_pyc(self): # pylint: disable=inconsistent-return-statements """Create a .pyc file, and return the relative path to it.""" if env.JYTHON: self.skipTest("Can't make .pyc files on Jython") self.make_file("compiled.py", """\ def doit(): print("I am here!") doit() """) compileall.compile_dir(".", quiet=True) os.remove("compiled.py") # Find the .pyc file! for there, _, files in os.walk("."): # pragma: part covered for f in files: if f.endswith(".pyc"): # pragma: part covered return os.path.join(there, f) def test_running_pyc(self): pycfile = self.make_pyc() run_python_file(pycfile, [pycfile]) self.assertEqual(self.stdout(), "I am here!\n") def test_running_pyo(self): pycfile = self.make_pyc() pyofile = re.sub(r"[.]pyc$", ".pyo", pycfile) self.assertNotEqual(pycfile, pyofile) os.rename(pycfile, pyofile) run_python_file(pyofile, [pyofile]) self.assertEqual(self.stdout(), "I am here!\n") def test_running_pyc_from_wrong_python(self): pycfile = self.make_pyc() # Jam Python 2.1 magic number into the .pyc file. with open(pycfile, "r+b") as fpyc: fpyc.seek(0) fpyc.write(binary_bytes([0x2a, 0xeb, 0x0d, 0x0a])) with self.assertRaisesRegex(NoCode, "Bad magic number in .pyc file"): run_python_file(pycfile, [pycfile]) def test_no_such_pyc_file(self): with self.assertRaisesRegex(NoCode, "No file to run: 'xyzzy.pyc'"): run_python_file("xyzzy.pyc", []) def test_running_py_from_binary(self): # Use make_file to get the bookkeeping. Ideally, it would # be able to write binary files. bf = self.make_file("binary") with open(bf, "wb") as f: f.write(b'\x7fELF\x02\x01\x01\x00\x00\x00') msg = ( r"Couldn't run 'binary' as Python code: " r"(TypeError|ValueError): " r"(" r"compile\(\) expected string without null bytes" # for py2 r"|" r"source code string cannot contain null bytes" # for py3 r")" ) with self.assertRaisesRegex(Exception, msg): run_python_file(bf, [bf]) class RunModuleTest(UsingModulesMixin, CoverageTest): """Test run_python_module.""" run_in_temp_dir = False def test_runmod1(self): run_python_module("runmod1", ["runmod1", "hello"]) self.assertEqual(self.stderr(), "") self.assertEqual(self.stdout(), "runmod1: passed hello\n") def test_runmod2(self): run_python_module("pkg1.runmod2", ["runmod2", "hello"]) self.assertEqual(self.stderr(), "") self.assertEqual(self.stdout(), "pkg1.__init__: pkg1\nrunmod2: passed hello\n") def test_runmod3(self): run_python_module("pkg1.sub.runmod3", ["runmod3", "hello"]) self.assertEqual(self.stderr(), "") self.assertEqual(self.stdout(), "pkg1.__init__: pkg1\nrunmod3: passed hello\n") def test_pkg1_main(self): run_python_module("pkg1", ["pkg1", "hello"]) self.assertEqual(self.stderr(), "") self.assertEqual(self.stdout(), "pkg1.__init__: pkg1\npkg1.__main__: passed hello\n") def test_pkg1_sub_main(self): run_python_module("pkg1.sub", ["pkg1.sub", "hello"]) self.assertEqual(self.stderr(), "") self.assertEqual(self.stdout(), "pkg1.__init__: pkg1\npkg1.sub.__main__: passed hello\n") def test_pkg1_init(self): run_python_module("pkg1.__init__", ["pkg1.__init__", "wut?"]) self.assertEqual(self.stderr(), "") self.assertEqual(self.stdout(), "pkg1.__init__: pkg1\npkg1.__init__: __main__\n") def test_no_such_module(self): with self.assertRaises(NoSource): run_python_module("i_dont_exist", []) with self.assertRaises(NoSource): run_python_module("i.dont_exist", []) with self.assertRaises(NoSource): run_python_module("i.dont.exist", []) def test_no_main(self): with self.assertRaises(NoSource): run_python_module("pkg2", ["pkg2", "hi"])