summaryrefslogtreecommitdiffstats
path: root/Lib/test/test_shutil.py
diff options
context:
space:
mode:
authorGiampaolo Rodola <g.rodola@gmail.com>2018-06-19 15:27:29 (GMT)
committerGitHub <noreply@github.com>2018-06-19 15:27:29 (GMT)
commitc7f02a965936f197354d7f4e6360f4cfc86817ed (patch)
tree9402cdb5daa1881eefce00dbc70c8b2dfc7f40f7 /Lib/test/test_shutil.py
parent936f03e7fafc28fd6fdfba11d162c776b89c0167 (diff)
downloadcpython-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.py88
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):