Skip to content

Commit 452c877

Browse files
author
Bojan Nikolic
committed
Add test for ENODATA handling
1 parent 5917a6b commit 452c877

File tree

2 files changed

+37
-1
lines changed

2 files changed

+37
-1
lines changed

Lib/shutil.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,7 @@ def _fastcopy_sendfile(fsrc, fdst):
223223
# input fd to the correct position before falling
224224
# back on POSIX read/write method
225225
os.lseek(infd, dstpos, os.SEEK_SET)
226-
226+
227227
raise _GiveupOnFastCopy(err)
228228

229229
if err.errno == errno.ENOSPC: # filesystem is full

Lib/test/test_shutil.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3365,6 +3365,42 @@ def test_file2file_not_supported(self):
33653365
finally:
33663366
shutil._USE_CP_SENDFILE = True
33673367

3368+
def test_exception_on_enodata_call(self):
3369+
# Test logic when sendfile(2) call returns ENODATA error on
3370+
# the not-first call on the file and we need to fall back to
3371+
# traditional POSIX while preserving the position of where we
3372+
# got to in writing
3373+
def syscall(*args, **kwargs):
3374+
if not flag:
3375+
flag.append(None)
3376+
return orig_syscall(*args, **kwargs)
3377+
else:
3378+
raise OSError(errno.ENODATA, "yo")
3379+
3380+
flag = []
3381+
orig_syscall = eval(self.PATCHPOINT)
3382+
# Reduce block size so that multiple syscalls are needed
3383+
mock = unittest.mock.Mock()
3384+
mock.st_size = 65536 + 1
3385+
with unittest.mock.patch('os.fstat', return_value=mock) as m:
3386+
with unittest.mock.patch(self.PATCHPOINT, create=True,
3387+
side_effect=syscall) as m2:
3388+
with self.get_files() as (src, dst):
3389+
with self.assertRaises(_GiveupOnFastCopy) as cm:
3390+
self.zerocopy_fun(src, dst)
3391+
3392+
# Reset flag so that second syscall fails again
3393+
flag = []
3394+
with unittest.mock.patch(self.PATCHPOINT, create=True,
3395+
side_effect=syscall) as m2:
3396+
shutil._USE_CP_SENDFILE = True
3397+
shutil.copyfile(TESTFN, TESTFN2)
3398+
assert m2.called
3399+
shutil._USE_CP_SENDFILE = True
3400+
assert flag
3401+
self.assertEqual(read_file(TESTFN2, binary=True), self.FILEDATA)
3402+
3403+
33683404

33693405
@unittest.skipUnless(shutil._USE_CP_COPY_FILE_RANGE, "os.copy_file_range() not supported")
33703406
class TestZeroCopyCopyFileRange(_ZeroCopyFileLinuxTest, unittest.TestCase):

0 commit comments

Comments
 (0)