Skip to content

Commit 85fa157

Browse files
committed
Update test_os from CPython v3.12.3
1 parent 1068219 commit 85fa157

File tree

1 file changed

+74
-151
lines changed

1 file changed

+74
-151
lines changed

Lib/test/test_os.py

Lines changed: 74 additions & 151 deletions
Original file line numberDiff line numberDiff line change
@@ -3637,97 +3637,8 @@ def test_set_get_priority(self):
36373637
self.assertEqual(new_prio, base + 1)
36383638

36393639

3640-
import asyncore
3641-
import asynchat
3642-
import threading
3643-
class SendfileTestServer(asyncore.dispatcher, threading.Thread):
3644-
3645-
class Handler(asynchat.async_chat):
3646-
3647-
def __init__(self, conn):
3648-
asynchat.async_chat.__init__(self, conn)
3649-
self.in_buffer = []
3650-
self.accumulate = True
3651-
self.closed = False
3652-
self.push(b"220 ready\r\n")
3653-
3654-
def handle_read(self):
3655-
data = self.recv(4096)
3656-
if self.accumulate:
3657-
self.in_buffer.append(data)
3658-
3659-
def get_data(self):
3660-
return b''.join(self.in_buffer)
3661-
3662-
def handle_close(self):
3663-
self.close()
3664-
self.closed = True
3665-
3666-
def handle_error(self):
3667-
raise
3668-
3669-
def __init__(self, address):
3670-
threading.Thread.__init__(self)
3671-
asyncore.dispatcher.__init__(self)
3672-
self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
3673-
self.bind(address)
3674-
self.listen(5)
3675-
self.host, self.port = self.socket.getsockname()[:2]
3676-
self.handler_instance = None
3677-
self._active = False
3678-
self._active_lock = threading.Lock()
3679-
3680-
# --- public API
3681-
3682-
@property
3683-
def running(self):
3684-
return self._active
3685-
3686-
def start(self):
3687-
assert not self.running
3688-
self.__flag = threading.Event()
3689-
threading.Thread.start(self)
3690-
self.__flag.wait()
3691-
3692-
def stop(self):
3693-
assert self.running
3694-
self._active = False
3695-
self.join()
3696-
3697-
def wait(self):
3698-
# wait for handler connection to be closed, then stop the server
3699-
while not getattr(self.handler_instance, "closed", False):
3700-
time.sleep(0.001)
3701-
self.stop()
3702-
3703-
# --- internals
3704-
3705-
def run(self):
3706-
self._active = True
3707-
self.__flag.set()
3708-
while self._active and asyncore.socket_map:
3709-
self._active_lock.acquire()
3710-
asyncore.loop(timeout=0.001, count=1)
3711-
self._active_lock.release()
3712-
asyncore.close_all()
3713-
3714-
def handle_accept(self):
3715-
conn, addr = self.accept()
3716-
self.handler_instance = self.Handler(conn)
3717-
3718-
def handle_connect(self):
3719-
self.close()
3720-
handle_read = handle_connect
3721-
3722-
def writable(self):
3723-
return 0
3724-
3725-
def handle_error(self):
3726-
raise
3727-
3728-
37293640
@unittest.skipUnless(hasattr(os, 'sendfile'), "test needs os.sendfile()")
3730-
class TestSendfile(unittest.TestCase):
3641+
class TestSendfile(unittest.IsolatedAsyncioTestCase):
37313642

37323643
DATA = b"12345abcde" * 16 * 1024 # 160 KiB
37333644
SUPPORT_HEADERS_TRAILERS = not sys.platform.startswith("linux") and \
@@ -3746,32 +3657,46 @@ def setUpClass(cls):
37463657
def tearDownClass(cls):
37473658
os_helper.unlink(os_helper.TESTFN)
37483659

3749-
def setUp(self):
3750-
self.server = SendfileTestServer((socket_helper.HOST, 0))
3751-
self.server.start()
3660+
@staticmethod
3661+
async def chunks(reader):
3662+
while not reader.at_eof():
3663+
yield await reader.read()
3664+
3665+
async def handle_new_client(self, reader, writer):
3666+
self.server_buffer = b''.join([x async for x in self.chunks(reader)])
3667+
writer.close()
3668+
self.server.close() # The test server processes a single client only
3669+
3670+
async def asyncSetUp(self):
3671+
self.server_buffer = b''
3672+
self.server = await asyncio.start_server(self.handle_new_client,
3673+
socket_helper.HOSTv4)
3674+
server_name = self.server.sockets[0].getsockname()
37523675
self.client = socket.socket()
3753-
self.client.connect((self.server.host, self.server.port))
3754-
self.client.settimeout(1)
3755-
# synchronize by waiting for "220 ready" response
3756-
self.client.recv(1024)
3676+
self.client.setblocking(False)
3677+
await asyncio.get_running_loop().sock_connect(self.client, server_name)
37573678
self.sockno = self.client.fileno()
37583679
self.file = open(os_helper.TESTFN, 'rb')
37593680
self.fileno = self.file.fileno()
37603681

3761-
def tearDown(self):
3682+
async def asyncTearDown(self):
37623683
self.file.close()
37633684
self.client.close()
3764-
if self.server.running:
3765-
self.server.stop()
3766-
self.server = None
3685+
await self.server.wait_closed()
3686+
3687+
# Use the test subject instead of asyncio.loop.sendfile
3688+
@staticmethod
3689+
async def async_sendfile(*args, **kwargs):
3690+
return await asyncio.to_thread(os.sendfile, *args, **kwargs)
37673691

3768-
def sendfile_wrapper(self, *args, **kwargs):
3692+
@staticmethod
3693+
async def sendfile_wrapper(*args, **kwargs):
37693694
"""A higher level wrapper representing how an application is
37703695
supposed to use sendfile().
37713696
"""
37723697
while True:
37733698
try:
3774-
return os.sendfile(*args, **kwargs)
3699+
return await TestSendfile.async_sendfile(*args, **kwargs)
37753700
except OSError as err:
37763701
if err.errno == errno.ECONNRESET:
37773702
# disconnected
@@ -3782,13 +3707,14 @@ def sendfile_wrapper(self, *args, **kwargs):
37823707
else:
37833708
raise
37843709

3785-
def test_send_whole_file(self):
3710+
async def test_send_whole_file(self):
37863711
# normal send
37873712
total_sent = 0
37883713
offset = 0
37893714
nbytes = 4096
37903715
while total_sent < len(self.DATA):
3791-
sent = self.sendfile_wrapper(self.sockno, self.fileno, offset, nbytes)
3716+
sent = await self.sendfile_wrapper(self.sockno, self.fileno,
3717+
offset, nbytes)
37923718
if sent == 0:
37933719
break
37943720
offset += sent
@@ -3799,19 +3725,19 @@ def test_send_whole_file(self):
37993725
self.assertEqual(total_sent, len(self.DATA))
38003726
self.client.shutdown(socket.SHUT_RDWR)
38013727
self.client.close()
3802-
self.server.wait()
3803-
data = self.server.handler_instance.get_data()
3804-
self.assertEqual(len(data), len(self.DATA))
3805-
self.assertEqual(data, self.DATA)
3728+
await self.server.wait_closed()
3729+
self.assertEqual(len(self.server_buffer), len(self.DATA))
3730+
self.assertEqual(self.server_buffer, self.DATA)
38063731

3807-
def test_send_at_certain_offset(self):
3732+
async def test_send_at_certain_offset(self):
38083733
# start sending a file at a certain offset
38093734
total_sent = 0
38103735
offset = len(self.DATA) // 2
38113736
must_send = len(self.DATA) - offset
38123737
nbytes = 4096
38133738
while total_sent < must_send:
3814-
sent = self.sendfile_wrapper(self.sockno, self.fileno, offset, nbytes)
3739+
sent = await self.sendfile_wrapper(self.sockno, self.fileno,
3740+
offset, nbytes)
38153741
if sent == 0:
38163742
break
38173743
offset += sent
@@ -3820,18 +3746,18 @@ def test_send_at_certain_offset(self):
38203746

38213747
self.client.shutdown(socket.SHUT_RDWR)
38223748
self.client.close()
3823-
self.server.wait()
3824-
data = self.server.handler_instance.get_data()
3749+
await self.server.wait_closed()
38253750
expected = self.DATA[len(self.DATA) // 2:]
38263751
self.assertEqual(total_sent, len(expected))
3827-
self.assertEqual(len(data), len(expected))
3828-
self.assertEqual(data, expected)
3752+
self.assertEqual(len(self.server_buffer), len(expected))
3753+
self.assertEqual(self.server_buffer, expected)
38293754

3830-
def test_offset_overflow(self):
3755+
async def test_offset_overflow(self):
38313756
# specify an offset > file size
38323757
offset = len(self.DATA) + 4096
38333758
try:
3834-
sent = os.sendfile(self.sockno, self.fileno, offset, 4096)
3759+
sent = await self.async_sendfile(self.sockno, self.fileno,
3760+
offset, 4096)
38353761
except OSError as e:
38363762
# Solaris can raise EINVAL if offset >= file length, ignore.
38373763
if e.errno != errno.EINVAL:
@@ -3840,39 +3766,38 @@ def test_offset_overflow(self):
38403766
self.assertEqual(sent, 0)
38413767
self.client.shutdown(socket.SHUT_RDWR)
38423768
self.client.close()
3843-
self.server.wait()
3844-
data = self.server.handler_instance.get_data()
3845-
self.assertEqual(data, b'')
3769+
await self.server.wait_closed()
3770+
self.assertEqual(self.server_buffer, b'')
38463771

3847-
def test_invalid_offset(self):
3772+
async def test_invalid_offset(self):
38483773
with self.assertRaises(OSError) as cm:
3849-
os.sendfile(self.sockno, self.fileno, -1, 4096)
3774+
await self.async_sendfile(self.sockno, self.fileno, -1, 4096)
38503775
self.assertEqual(cm.exception.errno, errno.EINVAL)
38513776

3852-
def test_keywords(self):
3777+
async def test_keywords(self):
38533778
# Keyword arguments should be supported
3854-
os.sendfile(out_fd=self.sockno, in_fd=self.fileno,
3855-
offset=0, count=4096)
3779+
await self.async_sendfile(out_fd=self.sockno, in_fd=self.fileno,
3780+
offset=0, count=4096)
38563781
if self.SUPPORT_HEADERS_TRAILERS:
3857-
os.sendfile(out_fd=self.sockno, in_fd=self.fileno,
3858-
offset=0, count=4096,
3859-
headers=(), trailers=(), flags=0)
3782+
await self.async_sendfile(out_fd=self.sockno, in_fd=self.fileno,
3783+
offset=0, count=4096,
3784+
headers=(), trailers=(), flags=0)
38603785

38613786
# --- headers / trailers tests
38623787

38633788
@requires_headers_trailers
3864-
def test_headers(self):
3789+
async def test_headers(self):
38653790
total_sent = 0
38663791
expected_data = b"x" * 512 + b"y" * 256 + self.DATA[:-1]
3867-
sent = os.sendfile(self.sockno, self.fileno, 0, 4096,
3868-
headers=[b"x" * 512, b"y" * 256])
3792+
sent = await self.async_sendfile(self.sockno, self.fileno, 0, 4096,
3793+
headers=[b"x" * 512, b"y" * 256])
38693794
self.assertLessEqual(sent, 512 + 256 + 4096)
38703795
total_sent += sent
38713796
offset = 4096
38723797
while total_sent < len(expected_data):
38733798
nbytes = min(len(expected_data) - total_sent, 4096)
3874-
sent = self.sendfile_wrapper(self.sockno, self.fileno,
3875-
offset, nbytes)
3799+
sent = await self.sendfile_wrapper(self.sockno, self.fileno,
3800+
offset, nbytes)
38763801
if sent == 0:
38773802
break
38783803
self.assertLessEqual(sent, nbytes)
@@ -3881,51 +3806,49 @@ def test_headers(self):
38813806

38823807
self.assertEqual(total_sent, len(expected_data))
38833808
self.client.close()
3884-
self.server.wait()
3885-
data = self.server.handler_instance.get_data()
3886-
self.assertEqual(hash(data), hash(expected_data))
3809+
await self.server.wait_closed()
3810+
self.assertEqual(hash(self.server_buffer), hash(expected_data))
38873811

38883812
@requires_headers_trailers
3889-
def test_trailers(self):
3813+
async def test_trailers(self):
38903814
TESTFN2 = os_helper.TESTFN + "2"
38913815
file_data = b"abcdef"
38923816

38933817
self.addCleanup(os_helper.unlink, TESTFN2)
38943818
create_file(TESTFN2, file_data)
38953819

38963820
with open(TESTFN2, 'rb') as f:
3897-
os.sendfile(self.sockno, f.fileno(), 0, 5,
3898-
trailers=[b"123456", b"789"])
3821+
await self.async_sendfile(self.sockno, f.fileno(), 0, 5,
3822+
trailers=[b"123456", b"789"])
38993823
self.client.close()
3900-
self.server.wait()
3901-
data = self.server.handler_instance.get_data()
3902-
self.assertEqual(data, b"abcde123456789")
3824+
await self.server.wait_closed()
3825+
self.assertEqual(self.server_buffer, b"abcde123456789")
39033826

39043827
@requires_headers_trailers
39053828
@requires_32b
3906-
def test_headers_overflow_32bits(self):
3829+
async def test_headers_overflow_32bits(self):
39073830
self.server.handler_instance.accumulate = False
39083831
with self.assertRaises(OSError) as cm:
3909-
os.sendfile(self.sockno, self.fileno, 0, 0,
3910-
headers=[b"x" * 2**16] * 2**15)
3832+
await self.async_sendfile(self.sockno, self.fileno, 0, 0,
3833+
headers=[b"x" * 2**16] * 2**15)
39113834
self.assertEqual(cm.exception.errno, errno.EINVAL)
39123835

39133836
@requires_headers_trailers
39143837
@requires_32b
3915-
def test_trailers_overflow_32bits(self):
3838+
async def test_trailers_overflow_32bits(self):
39163839
self.server.handler_instance.accumulate = False
39173840
with self.assertRaises(OSError) as cm:
3918-
os.sendfile(self.sockno, self.fileno, 0, 0,
3919-
trailers=[b"x" * 2**16] * 2**15)
3841+
await self.async_sendfile(self.sockno, self.fileno, 0, 0,
3842+
trailers=[b"x" * 2**16] * 2**15)
39203843
self.assertEqual(cm.exception.errno, errno.EINVAL)
39213844

39223845
@requires_headers_trailers
39233846
@unittest.skipUnless(hasattr(os, 'SF_NODISKIO'),
39243847
'test needs os.SF_NODISKIO')
3925-
def test_flags(self):
3848+
async def test_flags(self):
39263849
try:
3927-
os.sendfile(self.sockno, self.fileno, 0, 4096,
3928-
flags=os.SF_NODISKIO)
3850+
await self.async_sendfile(self.sockno, self.fileno, 0, 4096,
3851+
flags=os.SF_NODISKIO)
39293852
except OSError as err:
39303853
if err.errno not in (errno.EBUSY, errno.EAGAIN):
39313854
raise

0 commit comments

Comments
 (0)