summaryrefslogtreecommitdiffstats
path: root/Lib/test/test_os.py
diff options
context:
space:
mode:
authorPablo Galindo <Pablogsal@gmail.com>2019-05-31 18:39:47 (GMT)
committerGitHub <noreply@github.com>2019-05-31 18:39:47 (GMT)
commitaac4d0342c3e692731c189d003dbd73a8c681a34 (patch)
treeb888c0e2423d1b3422765db1cea5f3e0cf5c97f4 /Lib/test/test_os.py
parent545a3b8814dbf2a5391e830d69e796fb1a1d62ec (diff)
downloadcpython-aac4d0342c3e692731c189d003dbd73a8c681a34.zip
cpython-aac4d0342c3e692731c189d003dbd73a8c681a34.tar.gz
cpython-aac4d0342c3e692731c189d003dbd73a8c681a34.tar.bz2
bpo-26826: Expose copy_file_range in the os module (GH-7255)
Diffstat (limited to 'Lib/test/test_os.py')
-rw-r--r--Lib/test/test_os.py83
1 files changed, 83 insertions, 0 deletions
diff --git a/Lib/test/test_os.py b/Lib/test/test_os.py
index f17a19a..a8eae61 100644
--- a/Lib/test/test_os.py
+++ b/Lib/test/test_os.py
@@ -231,6 +231,89 @@ class FileTests(unittest.TestCase):
except (NotImplementedError, OSError):
pass # No OS support or unprivileged user
+ @unittest.skipUnless(hasattr(os, 'copy_file_range'), 'test needs os.copy_file_range()')
+ def test_copy_file_range_invalid_values(self):
+ with self.assertRaises(ValueError):
+ os.copy_file_range(0, 1, -10)
+
+ @unittest.skipUnless(hasattr(os, 'copy_file_range'), 'test needs os.copy_file_range()')
+ def test_copy_file_range(self):
+ TESTFN2 = support.TESTFN + ".3"
+ data = b'0123456789'
+
+ create_file(support.TESTFN, data)
+ self.addCleanup(support.unlink, support.TESTFN)
+
+ in_file = open(support.TESTFN, 'rb')
+ self.addCleanup(in_file.close)
+ in_fd = in_file.fileno()
+
+ out_file = open(TESTFN2, 'w+b')
+ self.addCleanup(support.unlink, TESTFN2)
+ self.addCleanup(out_file.close)
+ out_fd = out_file.fileno()
+
+ try:
+ i = os.copy_file_range(in_fd, out_fd, 5)
+ except OSError as e:
+ # Handle the case in which Python was compiled
+ # in a system with the syscall but without support
+ # in the kernel.
+ if e.errno != errno.ENOSYS:
+ raise
+ self.skipTest(e)
+ else:
+ # The number of copied bytes can be less than
+ # the number of bytes originally requested.
+ self.assertIn(i, range(0, 6));
+
+ with open(TESTFN2, 'rb') as in_file:
+ self.assertEqual(in_file.read(), data[:i])
+
+ @unittest.skipUnless(hasattr(os, 'copy_file_range'), 'test needs os.copy_file_range()')
+ def test_copy_file_range_offset(self):
+ TESTFN4 = support.TESTFN + ".4"
+ data = b'0123456789'
+ bytes_to_copy = 6
+ in_skip = 3
+ out_seek = 5
+
+ create_file(support.TESTFN, data)
+ self.addCleanup(support.unlink, support.TESTFN)
+
+ in_file = open(support.TESTFN, 'rb')
+ self.addCleanup(in_file.close)
+ in_fd = in_file.fileno()
+
+ out_file = open(TESTFN4, 'w+b')
+ self.addCleanup(support.unlink, TESTFN4)
+ self.addCleanup(out_file.close)
+ out_fd = out_file.fileno()
+
+ try:
+ i = os.copy_file_range(in_fd, out_fd, bytes_to_copy,
+ offset_src=in_skip,
+ offset_dst=out_seek)
+ except OSError as e:
+ # Handle the case in which Python was compiled
+ # in a system with the syscall but without support
+ # in the kernel.
+ if e.errno != errno.ENOSYS:
+ raise
+ self.skipTest(e)
+ else:
+ # The number of copied bytes can be less than
+ # the number of bytes originally requested.
+ self.assertIn(i, range(0, bytes_to_copy+1));
+
+ with open(TESTFN4, 'rb') as in_file:
+ read = in_file.read()
+ # seeked bytes (5) are zero'ed
+ self.assertEqual(read[:out_seek], b'\x00'*out_seek)
+ # 012 are skipped (in_skip)
+ # 345678 are copied in the file (in_skip + bytes_to_copy)
+ self.assertEqual(read[out_seek:],
+ data[in_skip:in_skip+i])
# Test attributes on return values from os.*stat* family.
class StatAttributeTests(unittest.TestCase):