Skip to content

Commit 14ed8f1

Browse files
test: add regression test
1 parent 3a68a17 commit 14ed8f1

1 file changed

Lines changed: 51 additions & 0 deletions

File tree

Lib/test/test_free_threading/test_io.py

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import codecs
22
import io
3+
import os
4+
import tempfile
35
import _pyio as pyio
46
import threading
57
from unittest import TestCase
@@ -170,3 +172,52 @@ def reset_worker():
170172
decoder.reset()
171173

172174
run_concurrently([decode_worker] * 2 + [reset_worker] * 2)
175+
176+
177+
class TestFileIO(TestCase):
178+
NTHREADS = 4
179+
ITERS = 200
180+
181+
def _run_io_vs_close(self, open_mode: str, io_func, data: bytes = b"") -> None:
182+
"""Repeatedly race io_func against close on a fresh FileIO object."""
183+
for _ in range(self.ITERS):
184+
with tempfile.NamedTemporaryFile(delete=False) as tmp:
185+
if data:
186+
tmp.write(data)
187+
name = tmp.name
188+
try:
189+
f = io.FileIO(name, open_mode)
190+
191+
def io_worker(f: io.FileIO = f) -> None:
192+
for _ in range(10):
193+
try:
194+
io_func(f)
195+
except (ValueError, OSError):
196+
pass
197+
198+
def closer(f: io.FileIO = f) -> None:
199+
try:
200+
f.close()
201+
except OSError:
202+
pass
203+
204+
run_concurrently([io_worker] * self.NTHREADS + [closer])
205+
finally:
206+
os.unlink(name)
207+
208+
@threading_helper.requires_working_threading()
209+
def test_concurrent_read_and_close(self):
210+
self._run_io_vs_close("rb", lambda f: f.read(256), data=b"x" * 4096)
211+
212+
@threading_helper.requires_working_threading()
213+
def test_concurrent_readinto_and_close(self):
214+
buf = bytearray(256)
215+
self._run_io_vs_close("rb", lambda f: f.readinto(buf), data=b"x" * 4096)
216+
217+
@threading_helper.requires_working_threading()
218+
def test_concurrent_write_and_close(self):
219+
self._run_io_vs_close("wb", lambda f: f.write(b"x" * 256))
220+
221+
@threading_helper.requires_working_threading()
222+
def test_concurrent_seek_and_close(self):
223+
self._run_io_vs_close("rb", lambda f: f.seek(0), data=b"x" * 256)

0 commit comments

Comments
 (0)