diff options
author | Giampaolo Rodola <g.rodola@gmail.com> | 2018-06-19 15:27:29 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-06-19 15:27:29 (GMT) |
commit | c7f02a965936f197354d7f4e6360f4cfc86817ed (patch) | |
tree | 9402cdb5daa1881eefce00dbc70c8b2dfc7f40f7 /Lib/test/test_shutil.py | |
parent | 936f03e7fafc28fd6fdfba11d162c776b89c0167 (diff) | |
download | cpython-c7f02a965936f197354d7f4e6360f4cfc86817ed.zip cpython-c7f02a965936f197354d7f4e6360f4cfc86817ed.tar.gz cpython-c7f02a965936f197354d7f4e6360f4cfc86817ed.tar.bz2 |
bpo-33671 / shutil.copyfile: use memoryview() with dynamic size on Windows (#7681)
bpo-33671
* use memoryview() with size == file size on Windows, see https://github.com/python/cpython/pull/7160#discussion_r195405230
* release intermediate (sliced) memoryview immediately
* replace "OSX" occurrences with "macOS"
* add some unittests for copyfileobj()
Diffstat (limited to 'Lib/test/test_shutil.py')
-rw-r--r-- | Lib/test/test_shutil.py | 88 |
1 files changed, 81 insertions, 7 deletions
diff --git a/Lib/test/test_shutil.py b/Lib/test/test_shutil.py index 8d51994..7e0a329 100644 --- a/Lib/test/test_shutil.py +++ b/Lib/test/test_shutil.py @@ -33,7 +33,7 @@ from test import support from test.support import TESTFN, FakePath TESTFN2 = TESTFN + "2" -OSX = sys.platform.startswith("darwin") +MACOS = sys.platform.startswith("darwin") try: import grp import pwd @@ -1808,7 +1808,7 @@ class TestCopyFile(unittest.TestCase): self.assertRaises(OSError, shutil.copyfile, 'srcfile', 'destfile') - @unittest.skipIf(OSX, "skipped on OSX") + @unittest.skipIf(MACOS, "skipped on macOS") def test_w_dest_open_fails(self): srcfile = self.Faux() @@ -1828,7 +1828,7 @@ class TestCopyFile(unittest.TestCase): self.assertEqual(srcfile._exited_with[1].args, ('Cannot open "destfile"',)) - @unittest.skipIf(OSX, "skipped on OSX") + @unittest.skipIf(MACOS, "skipped on macOS") def test_w_dest_close_fails(self): srcfile = self.Faux() @@ -1851,7 +1851,7 @@ class TestCopyFile(unittest.TestCase): self.assertEqual(srcfile._exited_with[1].args, ('Cannot close',)) - @unittest.skipIf(OSX, "skipped on OSX") + @unittest.skipIf(MACOS, "skipped on macOS") def test_w_source_close_fails(self): srcfile = self.Faux(True) @@ -1892,6 +1892,80 @@ class TestCopyFile(unittest.TestCase): os.rmdir(dst_dir) +class TestCopyFileObj(unittest.TestCase): + FILESIZE = 2 * 1024 * 1024 + + @classmethod + def setUpClass(cls): + write_test_file(TESTFN, cls.FILESIZE) + + @classmethod + def tearDownClass(cls): + support.unlink(TESTFN) + support.unlink(TESTFN2) + + def tearDown(self): + support.unlink(TESTFN2) + + @contextlib.contextmanager + def get_files(self): + with open(TESTFN, "rb") as src: + with open(TESTFN2, "wb") as dst: + yield (src, dst) + + def assert_files_eq(self, src, dst): + with open(src, 'rb') as fsrc: + with open(dst, 'rb') as fdst: + self.assertEqual(fsrc.read(), fdst.read()) + + def test_content(self): + with self.get_files() as (src, dst): + shutil.copyfileobj(src, dst) + self.assert_files_eq(TESTFN, TESTFN2) + + def test_file_not_closed(self): + with self.get_files() as (src, dst): + shutil.copyfileobj(src, dst) + assert not src.closed + assert not dst.closed + + def test_file_offset(self): + with self.get_files() as (src, dst): + shutil.copyfileobj(src, dst) + self.assertEqual(src.tell(), self.FILESIZE) + self.assertEqual(dst.tell(), self.FILESIZE) + + @unittest.skipIf(os.name != 'nt', "Windows only") + def test_win_impl(self): + # Make sure alternate Windows implementation is called. + with unittest.mock.patch("shutil._copyfileobj_readinto") as m: + shutil.copyfile(TESTFN, TESTFN2) + assert m.called + + # File size is 2 MiB but max buf size should be 1 MiB. + self.assertEqual(m.call_args[0][2], 1 * 1024 * 1024) + + # If file size < 1 MiB memoryview() length must be equal to + # the actual file size. + with tempfile.NamedTemporaryFile(delete=False) as f: + f.write(b'foo') + fname = f.name + self.addCleanup(support.unlink, fname) + with unittest.mock.patch("shutil._copyfileobj_readinto") as m: + shutil.copyfile(fname, TESTFN2) + self.assertEqual(m.call_args[0][2], 3) + + # Empty files should not rely on readinto() variant. + with tempfile.NamedTemporaryFile(delete=False) as f: + pass + fname = f.name + self.addCleanup(support.unlink, fname) + with unittest.mock.patch("shutil._copyfileobj_readinto") as m: + shutil.copyfile(fname, TESTFN2) + assert not m.called + self.assert_files_eq(fname, TESTFN2) + + class _ZeroCopyFileTest(object): """Tests common to all zero-copy APIs.""" FILESIZE = (10 * 1024 * 1024) # 10 MiB @@ -2111,12 +2185,12 @@ class TestZeroCopySendfile(_ZeroCopyFileTest, unittest.TestCase): shutil._HAS_SENDFILE = True -@unittest.skipIf(not OSX, 'OSX only') -class TestZeroCopyOSX(_ZeroCopyFileTest, unittest.TestCase): +@unittest.skipIf(not MACOS, 'macOS only') +class TestZeroCopyMACOS(_ZeroCopyFileTest, unittest.TestCase): PATCHPOINT = "posix._fcopyfile" def zerocopy_fun(self, src, dst): - return shutil._fastcopy_osx(src, dst, posix._COPYFILE_DATA) + return shutil._fastcopy_fcopyfile(src, dst, posix._COPYFILE_DATA) class TermsizeTests(unittest.TestCase): |