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 | 23 | ||||
| -rw-r--r-- | spec/ruby/library/io-wait/wait_spec.rb | 142 | ||||
| -rw-r--r-- | spec/ruby/library/io-wait/wait_writable_spec.rb | 25 |
4 files changed, 120 insertions, 82 deletions
diff --git a/spec/ruby/library/io-wait/fixtures/classes.rb b/spec/ruby/library/io-wait/fixtures/classes.rb deleted file mode 100644 index 837c7edd06..0000000000 --- a/spec/ruby/library/io-wait/fixtures/classes.rb +++ /dev/null @@ -1,12 +0,0 @@ -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 index 06ffbda5c8..d7473f029f 100644 --- a/spec/ruby/library/io-wait/wait_readable_spec.rb +++ b/spec/ruby/library/io-wait/wait_readable_spec.rb @@ -1,9 +1,5 @@ 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__ ) @@ -24,4 +20,23 @@ describe "IO#wait_readable" do it "waits for the IO to become readable with the given large timeout" do @io.wait_readable(365 * 24 * 60 * 60).should == @io end + + it "can be interrupted" do + rd, wr = IO.pipe + start = Process.clock_gettime(Process::CLOCK_MONOTONIC) + + t = Thread.new do + rd.wait_readable(10) + end + + Thread.pass until t.stop? + t.kill + t.join + + finish = Process.clock_gettime(Process::CLOCK_MONOTONIC) + (finish - start).should < 9 + ensure + rd.close + wr.close + end end diff --git a/spec/ruby/library/io-wait/wait_spec.rb b/spec/ruby/library/io-wait/wait_spec.rb index 3861281277..1d784e7aa4 100644 --- a/spec/ruby/library/io-wait/wait_spec.rb +++ b/spec/ruby/library/io-wait/wait_spec.rb @@ -1,9 +1,5 @@ require_relative '../../spec_helper' -require_relative 'fixtures/classes' - -ruby_version_is ''...'3.2' do - require 'io/wait' -end +require_relative '../../fixtures/io' describe "IO#wait" do before :each do @@ -25,48 +21,28 @@ describe "IO#wait" do 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 + 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 - 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 + it "returns events mask when the WRITABLE event is ready during the timeout" do + @w.wait(IO::WRITABLE, 0).should == IO::WRITABLE end it "waits for the READABLE event to be ready" do - queue = Queue.new - thread = Thread.new { queue.pop; sleep 1; @w.write('data to read') }; - - queue.push('signal'); - @r.wait(IO::READABLE, 2).should_not == nil + @r.wait(IO::READABLE, 0).should == nil - thread.join + @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) - - queue = Queue.new - thread = Thread.new { queue.pop; sleep 1; @r.read(written_bytes) }; - - queue.push('signal'); - @w.wait(IO::WRITABLE, 2).should_not == nil + written_bytes = IOSpec.exhaust_write_buffer(@w) + @w.wait(IO::WRITABLE, 0).should == nil - thread.join + @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 @@ -74,21 +50,71 @@ describe "IO#wait" do end it "returns nil when the WRITABLE event is not ready during the timeout" do - IOWaitSpec.exhaust_write_buffer(@w) + IOSpec.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") + -> { @io.wait(IO::READABLE, 0) }.should.raise(IOError, "closed stream") + end + + it "raises ArgumentError when events is not positive" do + -> { @w.wait(0, 0) }.should.raise(ArgumentError, "Events must be positive integer!") + -> { @w.wait(-1, 0) }.should.raise(ArgumentError, "Events must be positive integer!") 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!") + 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 + + # https://github.com/ruby/ruby/actions/runs/11948300522/job/33305664284?pr=12139 + platform_is_not :windows do + it "changes thread status to 'sleep' when waits for WRITABLE event" do + IOSpec.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 + + it "can be interrupted when waiting for READABLE event" do + start = Process.clock_gettime(Process::CLOCK_MONOTONIC) + + t = Thread.new do + @r.wait(IO::READABLE, 10) + end + + Thread.pass until t.stop? + t.kill + t.join # Thread#kill doesn't wait for the thread to end + + finish = Process.clock_gettime(Process::CLOCK_MONOTONIC) + (finish - start).should < 9 + end + + it "can be interrupted when waiting for WRITABLE event" do + IOSpec.exhaust_write_buffer(@w) + start = Process.clock_gettime(Process::CLOCK_MONOTONIC) + + t = Thread.new do + @w.wait(IO::WRITABLE, 10) + end + + Thread.pass until t.stop? + t.kill + t.join # Thread#kill doesn't wait for the thread to end + + finish = Process.clock_gettime(Process::CLOCK_MONOTONIC) + (finish - start).should < 9 + end end context "[timeout, mode] passed" do @@ -111,34 +137,26 @@ describe "IO#wait" do end it "accepts a list of modes" do - @io.wait(0, :r, :w, :rw).should == @io + @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 + 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 it "raises ArgumentError when passed wrong Symbol value as mode argument" do - -> { @io.wait(0, :wrong) }.should raise_error(ArgumentError, "unsupported mode: wrong") + -> { @io.wait(0, :wrong) }.should.raise(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 + it "raises ArgumentError when several Integer arguments passed" do + -> { @w.wait(0, 10, :r) }.should.raise(ArgumentError, "timeout given more than once") 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 + it "raises IOError when io is closed (closed stream (IOError))" do + @io.close + -> { @io.wait(0, :r) }.should.raise(IOError, "closed stream") 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 index 8c44780d39..2017817caa 100644 --- a/spec/ruby/library/io-wait/wait_writable_spec.rb +++ b/spec/ruby/library/io-wait/wait_writable_spec.rb @@ -1,8 +1,5 @@ require_relative '../../spec_helper' - -ruby_version_is ''...'3.2' do - require 'io/wait' -end +require_relative '../../fixtures/io' describe "IO#wait_writable" do it "waits for the IO to become writable with no timeout" do @@ -17,4 +14,24 @@ describe "IO#wait_writable" do # Represents one year and is larger than a 32-bit int STDOUT.wait_writable(365 * 24 * 60 * 60).should == STDOUT end + + it "can be interrupted" do + rd, wr = IO.pipe + IOSpec.exhaust_write_buffer(wr) + start = Process.clock_gettime(Process::CLOCK_MONOTONIC) + + t = Thread.new do + wr.wait_writable(10) + end + + Thread.pass until t.stop? + t.kill + t.join + + finish = Process.clock_gettime(Process::CLOCK_MONOTONIC) + (finish - start).should < 9 + ensure + rd.close unless rd.closed? + wr.close unless wr.closed? + end end |
