diff options
Diffstat (limited to 'spec/ruby/library/io-wait')
-rw-r--r-- | spec/ruby/library/io-wait/fixtures/classes.rb | 12 | ||||
-rw-r--r-- | spec/ruby/library/io-wait/wait_readable_spec.rb | 27 | ||||
-rw-r--r-- | spec/ruby/library/io-wait/wait_spec.rb | 155 | ||||
-rw-r--r-- | spec/ruby/library/io-wait/wait_writable_spec.rb | 20 |
4 files changed, 214 insertions, 0 deletions
diff --git a/spec/ruby/library/io-wait/fixtures/classes.rb b/spec/ruby/library/io-wait/fixtures/classes.rb new file mode 100644 index 0000000000..837c7edd06 --- /dev/null +++ b/spec/ruby/library/io-wait/fixtures/classes.rb @@ -0,0 +1,12 @@ +module IOWaitSpec + def self.exhaust_write_buffer(io) + written = 0 + buf = " " * 4096 + + begin + written += io.write_nonblock(buf) + rescue Errno::EAGAIN, Errno::EWOULDBLOCK + return written + end while true + end +end diff --git a/spec/ruby/library/io-wait/wait_readable_spec.rb b/spec/ruby/library/io-wait/wait_readable_spec.rb new file mode 100644 index 0000000000..06ffbda5c8 --- /dev/null +++ b/spec/ruby/library/io-wait/wait_readable_spec.rb @@ -0,0 +1,27 @@ +require_relative '../../spec_helper' + +ruby_version_is ''...'3.2' do + require 'io/wait' +end + +describe "IO#wait_readable" do + before :each do + @io = File.new(__FILE__ ) + end + + after :each do + @io.close + end + + it "waits for the IO to become readable with no timeout" do + @io.wait_readable.should == @io + end + + it "waits for the IO to become readable with the given timeout" do + @io.wait_readable(1).should == @io + end + + it "waits for the IO to become readable with the given large timeout" do + @io.wait_readable(365 * 24 * 60 * 60).should == @io + end +end diff --git a/spec/ruby/library/io-wait/wait_spec.rb b/spec/ruby/library/io-wait/wait_spec.rb new file mode 100644 index 0000000000..fc07c6a8d9 --- /dev/null +++ b/spec/ruby/library/io-wait/wait_spec.rb @@ -0,0 +1,155 @@ +require_relative '../../spec_helper' +require_relative 'fixtures/classes' + +ruby_version_is ''...'3.2' do + require 'io/wait' +end + +describe "IO#wait" do + before :each do + @io = File.new(__FILE__ ) + + if /mswin|mingw/ =~ RUBY_PLATFORM + require 'socket' + @r, @w = Socket.pair(Socket::AF_INET, Socket::SOCK_STREAM, 0) + else + @r, @w = IO.pipe + end + end + + after :each do + @io.close unless @io.closed? + + @r.close unless @r.closed? + @w.close unless @w.closed? + end + + context "[events, timeout] passed" do + ruby_version_is ""..."3.2" do + it "returns self when the READABLE event is ready during the timeout" do + @w.write('data to read') + @r.wait(IO::READABLE, 2).should.equal?(@r) + end + + it "returns self when the WRITABLE event is ready during the timeout" do + @w.wait(IO::WRITABLE, 0).should.equal?(@w) + end + end + + ruby_version_is "3.2" do + it "returns events mask when the READABLE event is ready during the timeout" do + @w.write('data to read') + @r.wait(IO::READABLE, 2).should == IO::READABLE + end + + it "returns events mask when the WRITABLE event is ready during the timeout" do + @w.wait(IO::WRITABLE, 0).should == IO::WRITABLE + end + end + + it "waits for the READABLE event to be ready" do + @r.wait(IO::READABLE, 0).should == nil + + @w.write('data to read') + @r.wait(IO::READABLE, 0).should_not == nil + end + + it "waits for the WRITABLE event to be ready" do + written_bytes = IOWaitSpec.exhaust_write_buffer(@w) + @w.wait(IO::WRITABLE, 0).should == nil + + @r.read(written_bytes) + @w.wait(IO::WRITABLE, 0).should_not == nil + end + + it "returns nil when the READABLE event is not ready during the timeout" do + @w.wait(IO::READABLE, 0).should == nil + end + + it "returns nil when the WRITABLE event is not ready during the timeout" do + IOWaitSpec.exhaust_write_buffer(@w) + @w.wait(IO::WRITABLE, 0).should == nil + end + + it "raises IOError when io is closed (closed stream (IOError))" do + @io.close + -> { @io.wait(IO::READABLE, 0) }.should raise_error(IOError, "closed stream") + end + + ruby_version_is "3.2" do + it "raises ArgumentError when events is not positive" do + -> { @w.wait(0, 0) }.should raise_error(ArgumentError, "Events must be positive integer!") + -> { @w.wait(-1, 0) }.should raise_error(ArgumentError, "Events must be positive integer!") + end + end + + it "changes thread status to 'sleep' when waits for READABLE event" do + t = Thread.new { @r.wait(IO::READABLE, 10) } + sleep 1 + t.status.should == 'sleep' + t.kill + t.join # Thread#kill doesn't wait for the thread to end + end + + it "changes thread status to 'sleep' when waits for WRITABLE event" do + written_bytes = IOWaitSpec.exhaust_write_buffer(@w) + + t = Thread.new { @w.wait(IO::WRITABLE, 10) } + sleep 1 + t.status.should == 'sleep' + t.kill + t.join # Thread#kill doesn't wait for the thread to end + end + end + + context "[timeout, mode] passed" do + it "accepts :r, :read, :readable mode to check READABLE event" do + @io.wait(0, :r).should == @io + @io.wait(0, :read).should == @io + @io.wait(0, :readable).should == @io + end + + it "accepts :w, :write, :writable mode to check WRITABLE event" do + @io.wait(0, :w).should == @io + @io.wait(0, :write).should == @io + @io.wait(0, :writable).should == @io + end + + it "accepts :rw, :read_write, :readable_writable mode to check READABLE and WRITABLE events" do + @io.wait(0, :rw).should == @io + @io.wait(0, :read_write).should == @io + @io.wait(0, :readable_writable).should == @io + end + + it "accepts a list of modes" do + @io.wait(0, :r, :w, :rw).should == @io + end + + # It works at least since 2.7 but by some reason may fail on 3.1 + ruby_version_is "3.2" do + it "accepts timeout and mode in any order" do + @io.wait(0, :r).should == @io + @io.wait(:r, 0).should == @io + @io.wait(:r, 0, :w).should == @io + end + end + + it "raises ArgumentError when passed wrong Symbol value as mode argument" do + -> { @io.wait(0, :wrong) }.should raise_error(ArgumentError, "unsupported mode: wrong") + end + + # It works since 3.0 but by some reason may fail on 3.1 + ruby_version_is "3.2" do + it "raises ArgumentError when several Integer arguments passed" do + -> { @w.wait(0, 10, :r) }.should raise_error(ArgumentError, "timeout given more than once") + end + end + + ruby_version_is "3.2" do + it "raises IOError when io is closed (closed stream (IOError))" do + @io.close + -> { @io.wait(0, :r) }.should raise_error(IOError, "closed stream") + end + end + end +end diff --git a/spec/ruby/library/io-wait/wait_writable_spec.rb b/spec/ruby/library/io-wait/wait_writable_spec.rb new file mode 100644 index 0000000000..8c44780d39 --- /dev/null +++ b/spec/ruby/library/io-wait/wait_writable_spec.rb @@ -0,0 +1,20 @@ +require_relative '../../spec_helper' + +ruby_version_is ''...'3.2' do + require 'io/wait' +end + +describe "IO#wait_writable" do + it "waits for the IO to become writable with no timeout" do + STDOUT.wait_writable.should == STDOUT + end + + it "waits for the IO to become writable with the given timeout" do + STDOUT.wait_writable(1).should == STDOUT + end + + it "waits for the IO to become writable with the given large timeout" do + # Represents one year and is larger than a 32-bit int + STDOUT.wait_writable(365 * 24 * 60 * 60).should == STDOUT + end +end |