bpo-37096: Add large-file tests for modules using sendfile(2) (GH-13676) · python/cpython@5bcc6d8 (original) (raw)
`@@ -5,17 +5,19 @@
`
5
5
`import stat
`
6
6
`import sys
`
7
7
`import unittest
`
8
``
`-
from test.support import TESTFN, requires, unlink, bigmemtest
`
``
8
`+
import socket
`
``
9
`+
import shutil
`
``
10
`+
import threading
`
``
11
`+
from test.support import TESTFN, requires, unlink, bigmemtest, find_unused_port
`
9
12
`import io # C implementation of io
`
10
13
`import _pyio as pyio # Python implementation of io
`
11
14
``
12
15
`# size of file to create (>2 GiB; 2 GiB == 2,147,483,648 bytes)
`
13
16
`size = 2_500_000_000
`
``
17
`+
TESTFN2 = TESTFN + '2'
`
``
18
+
14
19
``
15
20
`class LargeFileTest:
`
16
``
`-
"""Test that each file function works as expected for large
`
17
``
`-
(i.e. > 2 GiB) files.
`
18
``
`-
"""
`
19
21
``
20
22
`def setUp(self):
`
21
23
`if os.path.exists(TESTFN):
`
`@@ -44,6 +46,13 @@ def tearDownClass(cls):
`
44
46
`if not os.stat(TESTFN)[stat.ST_SIZE] == 0:
`
45
47
`raise cls.failureException('File was not truncated by opening '
`
46
48
`'with mode "wb"')
`
``
49
`+
unlink(TESTFN2)
`
``
50
+
``
51
+
``
52
`+
class TestFileMethods(LargeFileTest):
`
``
53
`+
"""Test that each file function works as expected for large
`
``
54
`+
(i.e. > 2 GiB) files.
`
``
55
`+
"""
`
47
56
``
48
57
`# _pyio.FileIO.readall() uses a temporary bytearray then casted to bytes,
`
49
58
`# so memuse=2 is needed
`
`@@ -140,6 +149,72 @@ def test_seekable(self):
`
140
149
`f.seek(pos)
`
141
150
`self.assertTrue(f.seekable())
`
142
151
``
``
152
+
``
153
`+
class TestCopyfile(LargeFileTest, unittest.TestCase):
`
``
154
`+
open = staticmethod(io.open)
`
``
155
+
``
156
`+
def test_it(self):
`
``
157
`+
Internally shutil.copyfile() can use "fast copy" methods like
`
``
158
`+
os.sendfile().
`
``
159
`+
size = os.path.getsize(TESTFN)
`
``
160
`+
shutil.copyfile(TESTFN, TESTFN2)
`
``
161
`+
self.assertEqual(os.path.getsize(TESTFN2), size)
`
``
162
`+
with open(TESTFN2, 'rb') as f:
`
``
163
`+
self.assertEqual(f.read(5), b'z\x00\x00\x00\x00')
`
``
164
`+
f.seek(size - 5)
`
``
165
`+
self.assertEqual(f.read(), b'\x00\x00\x00\x00a')
`
``
166
+
``
167
+
``
168
`+
@unittest.skipIf(not hasattr(os, 'sendfile'), 'sendfile not supported')
`
``
169
`+
class TestSocketSendfile(LargeFileTest, unittest.TestCase):
`
``
170
`+
open = staticmethod(io.open)
`
``
171
`+
timeout = 3
`
``
172
+
``
173
`+
def setUp(self):
`
``
174
`+
super().setUp()
`
``
175
`+
self.thread = None
`
``
176
+
``
177
`+
def tearDown(self):
`
``
178
`+
super().tearDown()
`
``
179
`+
if self.thread is not None:
`
``
180
`+
self.thread.join(self.timeout)
`
``
181
`+
self.thread = None
`
``
182
+
``
183
`+
def tcp_server(self, sock):
`
``
184
`+
def run(sock):
`
``
185
`+
with sock:
`
``
186
`+
conn, _ = sock.accept()
`
``
187
`+
with conn, open(TESTFN2, 'wb') as f:
`
``
188
`+
event.wait(self.timeout)
`
``
189
`+
while True:
`
``
190
`+
chunk = conn.recv(65536)
`
``
191
`+
if not chunk:
`
``
192
`+
return
`
``
193
`+
f.write(chunk)
`
``
194
+
``
195
`+
event = threading.Event()
`
``
196
`+
sock.settimeout(self.timeout)
`
``
197
`+
self.thread = threading.Thread(target=run, args=(sock, ))
`
``
198
`+
self.thread.start()
`
``
199
`+
event.set()
`
``
200
+
``
201
`+
def test_it(self):
`
``
202
`+
port = find_unused_port()
`
``
203
`+
with socket.create_server(("", port)) as sock:
`
``
204
`+
self.tcp_server(sock)
`
``
205
`+
with socket.create_connection(("127.0.0.1", port)) as client:
`
``
206
`+
with open(TESTFN, 'rb') as f:
`
``
207
`+
client.sendfile(f)
`
``
208
`+
self.tearDown()
`
``
209
+
``
210
`+
size = os.path.getsize(TESTFN)
`
``
211
`+
self.assertEqual(os.path.getsize(TESTFN2), size)
`
``
212
`+
with open(TESTFN2, 'rb') as f:
`
``
213
`+
self.assertEqual(f.read(5), b'z\x00\x00\x00\x00')
`
``
214
`+
f.seek(size - 5)
`
``
215
`+
self.assertEqual(f.read(), b'\x00\x00\x00\x00a')
`
``
216
+
``
217
+
143
218
`def setUpModule():
`
144
219
`try:
`
145
220
`import signal
`
`@@ -176,14 +251,18 @@ def setUpModule():
`
176
251
`unlink(TESTFN)
`
177
252
``
178
253
``
179
``
`-
class CLargeFileTest(LargeFileTest, unittest.TestCase):
`
``
254
`+
class CLargeFileTest(TestFileMethods, unittest.TestCase):
`
180
255
`open = staticmethod(io.open)
`
181
256
``
182
``
`-
class PyLargeFileTest(LargeFileTest, unittest.TestCase):
`
``
257
+
``
258
`+
class PyLargeFileTest(TestFileMethods, unittest.TestCase):
`
183
259
`open = staticmethod(pyio.open)
`
184
260
``
``
261
+
185
262
`def tearDownModule():
`
186
263
`unlink(TESTFN)
`
``
264
`+
unlink(TESTFN2)
`
``
265
+
187
266
``
188
267
`if name == 'main':
`
189
268
`unittest.main()
`