diff options
author | Samuel Williams <samuel.williams@oriontransfer.co.nz> | 2023-03-31 00:48:55 +1300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-03-31 00:48:55 +1300 |
commit | 648870b5c577239b3274b0b48c82fb74910dfabf (patch) | |
tree | f944e0a1919bcb46537e1f3bd522beee9e72288c /test/fiber | |
parent | 6f122965cf8704f019445faead58040e9be2effb (diff) | |
download | ruby-648870b5c577239b3274b0b48c82fb74910dfabf.tar.gz |
Support `IO#pread` / `IO#pwrite` using fiber scheduler. (#7594)
* Skip test if non-blocking file IO is not supported.
Diffstat (limited to 'test/fiber')
-rw-r--r-- | test/fiber/scheduler.rb | 58 | ||||
-rw-r--r-- | test/fiber/test_io_buffer.rb | 41 |
2 files changed, 99 insertions, 0 deletions
diff --git a/test/fiber/scheduler.rb b/test/fiber/scheduler.rb index 71ca4d2789..5090271db1 100644 --- a/test/fiber/scheduler.rb +++ b/test/fiber/scheduler.rb @@ -366,6 +366,64 @@ class IOBufferScheduler < Scheduler return total end + def io_pread(io, buffer, from, length, offset) + total = 0 + io.nonblock = true + + while true + maximum_size = buffer.size - offset + result = blocking{buffer.pread(io, from, maximum_size, offset)} + + if result > 0 + total += result + offset += result + from += result + break if total >= length + elsif result == 0 + break + elsif result == EAGAIN + if length > 0 + self.io_wait(io, IO::READABLE, nil) + else + return result + end + elsif result < 0 + return result + end + end + + return total + end + + def io_pwrite(io, buffer, from, length, offset) + total = 0 + io.nonblock = true + + while true + maximum_size = buffer.size - offset + result = blocking{buffer.pwrite(io, from, maximum_size, offset)} + + if result > 0 + total += result + offset += result + from += result + break if total >= length + elsif result == 0 + break + elsif result == EAGAIN + if length > 0 + self.io_wait(io, IO::WRITABLE, nil) + else + return result + end + elsif result < 0 + return result + end + end + + return total + end + def blocking(&block) Fiber.blocking(&block) end diff --git a/test/fiber/test_io_buffer.rb b/test/fiber/test_io_buffer.rb index 3de70200d5..a08b1ce1a9 100644 --- a/test/fiber/test_io_buffer.rb +++ b/test/fiber/test_io_buffer.rb @@ -155,4 +155,45 @@ class TestFiberIOBuffer < Test::Unit::TestCase i&.close o&.close end + + def nonblockable?(io) + io.nonblock{} + true + rescue + false + end + + def test_io_buffer_pread_pwrite + file = Tempfile.new("test_io_buffer_pread_pwrite") + + omit "Non-blocking file IO is not supported" unless nonblockable?(file) + + source_buffer = IO::Buffer.for("Hello World!") + destination_buffer = IO::Buffer.new(source_buffer.size) + + # Test non-scheduler code path: + source_buffer.pwrite(file, 1, source_buffer.size) + destination_buffer.pread(file, 1, source_buffer.size) + assert_equal source_buffer, destination_buffer + + # Test scheduler code path: + destination_buffer.clear + file.truncate(0) + + thread = Thread.new do + scheduler = IOBufferScheduler.new + Fiber.set_scheduler scheduler + + Fiber.schedule do + source_buffer.pwrite(file, 1, source_buffer.size) + destination_buffer.pread(file, 1, source_buffer.size) + end + end + + thread.join + + assert_equal source_buffer, destination_buffer + ensure + file&.close! + end end |