summaryrefslogtreecommitdiff
path: root/spec/ruby/library
diff options
context:
space:
mode:
authorBenoit Daloze <eregontp@gmail.com>2023-04-25 17:04:25 +0200
committerBenoit Daloze <eregontp@gmail.com>2023-04-25 17:09:53 +0200
commitd562663e4098801c1d7fa7c64a335ea71231a598 (patch)
tree5b2ab2c9fbb86b4223263485fc5a3224562ae78d /spec/ruby/library
parentd3da01cd110ca99dd0249ee9af92e12cf845998c (diff)
Update to ruby/spec@7f69c86
Diffstat (limited to 'spec/ruby/library')
-rw-r--r--spec/ruby/library/fiber/current_spec.rb6
-rw-r--r--spec/ruby/library/io-wait/fixtures/classes.rb12
-rw-r--r--spec/ruby/library/io-wait/wait_spec.rb147
-rw-r--r--spec/ruby/library/monitor/exit_spec.rb10
-rw-r--r--spec/ruby/library/objectspace/dump_all_spec.rb114
-rw-r--r--spec/ruby/library/objectspace/dump_spec.rb74
-rw-r--r--spec/ruby/library/set/shared/inspect.rb8
-rw-r--r--spec/ruby/library/stringio/set_encoding_spec.rb8
-rw-r--r--spec/ruby/library/stringio/shared/write.rb21
9 files changed, 400 insertions, 0 deletions
diff --git a/spec/ruby/library/fiber/current_spec.rb b/spec/ruby/library/fiber/current_spec.rb
index e67d7d050a..e18603f069 100644
--- a/spec/ruby/library/fiber/current_spec.rb
+++ b/spec/ruby/library/fiber/current_spec.rb
@@ -3,6 +3,12 @@ require_relative '../../spec_helper'
require 'fiber'
describe "Fiber.current" do
+ ruby_version_is "3.1" do
+ it "is available without an extra require" do
+ ruby_exe("print Fiber.current.class", options: '--disable-gems --disable-did-you-mean').should == "Fiber"
+ end
+ end
+
it "returns the root Fiber when called outside of a Fiber" do
root = Fiber.current
root.should be_an_instance_of(Fiber)
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_spec.rb b/spec/ruby/library/io-wait/wait_spec.rb
new file mode 100644
index 0000000000..669ee70561
--- /dev/null
+++ b/spec/ruby/library/io-wait/wait_spec.rb
@@ -0,0 +1,147 @@
+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
+ @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
+
+ ruby_version_is "3.0" do
+ context "[events, timeout] passed" do
+ ruby_version_is "3.0"..."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
+
+ ruby_version_is "3.0" do
+ 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
+
+ thread.join
+ 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
+
+ thread.join
+ 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
+ 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/monitor/exit_spec.rb b/spec/ruby/library/monitor/exit_spec.rb
new file mode 100644
index 0000000000..952ad9525d
--- /dev/null
+++ b/spec/ruby/library/monitor/exit_spec.rb
@@ -0,0 +1,10 @@
+require_relative '../../spec_helper'
+require 'monitor'
+
+describe "Monitor#exit" do
+ it "raises ThreadError when monitor is not entered" do
+ m = Monitor.new
+
+ -> { m.exit }.should raise_error(ThreadError)
+ end
+end
diff --git a/spec/ruby/library/objectspace/dump_all_spec.rb b/spec/ruby/library/objectspace/dump_all_spec.rb
new file mode 100644
index 0000000000..dbf5bf1f76
--- /dev/null
+++ b/spec/ruby/library/objectspace/dump_all_spec.rb
@@ -0,0 +1,114 @@
+require_relative '../../spec_helper'
+require 'objspace'
+
+describe "ObjectSpace.dump_all" do
+ it "dumps Ruby heap to string when passed output: :string" do
+ stdout = ruby_exe(<<~RUBY, options: "-robjspace")
+ string = "abc"
+ dump = ObjectSpace.dump_all(output: :string)
+ puts dump.class
+ puts dump.include?('"value":"abc"')
+ RUBY
+
+ stdout.should == "String\ntrue\n"
+ end
+
+ it "dumps Ruby heap to a temporary file when passed output: :file" do
+ stdout = ruby_exe(<<~RUBY, options: "-robjspace")
+ string = "abc"
+ file = ObjectSpace.dump_all(output: :file)
+
+ begin
+ file.flush
+ file.rewind
+ content = file.read
+
+ puts file.class
+ puts content.include?('"value":"abc"')
+ ensure
+ file.close
+ File.unlink file.path
+ end
+ RUBY
+
+ stdout.should == "File\ntrue\n"
+ end
+
+ it "dumps Ruby heap to a temporary file when :output not specified" do
+ stdout = ruby_exe(<<~RUBY, options: "-robjspace")
+ string = "abc"
+ file = ObjectSpace.dump_all
+
+ begin
+ file.flush
+ file.rewind
+ content = file.read
+
+ puts file.class
+ puts content.include?('"value":"abc"')
+ ensure
+ file.close
+ File.unlink file.path
+ end
+ RUBY
+
+ stdout.should == "File\ntrue\n"
+ end
+
+ ruby_version_is "3.0" do
+ it "dumps Ruby heap to a temporary file when passed output: :nil" do
+ stdout = ruby_exe(<<~RUBY, options: "-robjspace")
+ string = "abc"
+ file = ObjectSpace.dump_all(output: nil)
+
+ begin
+ file.flush
+ file.rewind
+ content = file.read
+
+ puts file.class
+ puts content.include?('"value":"abc"')
+ ensure
+ file.close
+ File.unlink file.path
+ end
+ RUBY
+
+ stdout.should == "File\ntrue\n"
+ end
+ end
+
+ it "dumps Ruby heap to stdout when passed output: :stdout" do
+ stdout = ruby_exe(<<~RUBY, options: "-robjspace")
+ string = "abc"
+ ObjectSpace.dump_all(output: :stdout)
+ RUBY
+
+ stdout.should include('"value":"abc"')
+ end
+
+ it "dumps Ruby heap to provided IO when passed output: IO" do
+ stdout = ruby_exe(<<~RUBY, options: "-robjspace -rtempfile")
+ string = "abc"
+ io = Tempfile.create("object_space_dump_all")
+
+ begin
+ result = ObjectSpace.dump_all(output: io)
+ io.rewind
+ content = io.read
+
+ puts result.equal?(io)
+ puts content.include?('"value":"abc"')
+ ensure
+ io.close
+ File.unlink io.path
+ end
+ RUBY
+
+ stdout.should == "true\ntrue\n"
+ end
+
+ it "raises ArgumentError when passed not supported :output value" do
+ -> { ObjectSpace.dump_all(output: Object.new) }.should raise_error(ArgumentError, /wrong output option/)
+ end
+end
diff --git a/spec/ruby/library/objectspace/dump_spec.rb b/spec/ruby/library/objectspace/dump_spec.rb
new file mode 100644
index 0000000000..eacce51ba5
--- /dev/null
+++ b/spec/ruby/library/objectspace/dump_spec.rb
@@ -0,0 +1,74 @@
+require_relative '../../spec_helper'
+require 'objspace'
+
+describe "ObjectSpace.dump" do
+ it "dumps the content of object as JSON" do
+ require 'json'
+ string = ObjectSpace.dump("abc")
+ dump = JSON.parse(string)
+
+ dump['type'].should == "STRING"
+ dump['value'].should == "abc"
+ end
+
+ it "dumps to string when passed output: :string" do
+ string = ObjectSpace.dump("abc", output: :string)
+ string.should be_kind_of(String)
+ string.should include('"value":"abc"')
+ end
+
+ it "dumps to string when :output not specified" do
+ string = ObjectSpace.dump("abc")
+ string.should be_kind_of(String)
+ string.should include('"value":"abc"')
+ end
+
+ ruby_version_is "3.0" do
+ it "dumps to a temporary file when passed output: :file" do
+ file = ObjectSpace.dump("abc", output: :file)
+ file.should be_kind_of(File)
+
+ file.rewind
+ content = file.read
+ content.should include('"value":"abc"')
+ ensure
+ file.close
+ File.unlink file.path
+ end
+
+ it "dumps to a temporary file when passed output: :nil" do
+ file = ObjectSpace.dump("abc", output: nil)
+ file.should be_kind_of(File)
+
+ file.rewind
+ file.read.should include('"value":"abc"')
+ ensure
+ file.close
+ File.unlink file.path
+ end
+ end
+
+ it "dumps to stdout when passed output: :stdout" do
+ stdout = ruby_exe('ObjectSpace.dump("abc", output: :stdout)', options: "-robjspace").chomp
+ stdout.should include('"value":"abc"')
+ end
+
+ ruby_version_is "3.0" do
+ it "dumps to provided IO when passed output: IO" do
+ filename = tmp("io_read.txt")
+ io = File.open(filename, "w+")
+ result = ObjectSpace.dump("abc", output: io)
+ result.should.equal? io
+
+ io.rewind
+ io.read.should include('"value":"abc"')
+ ensure
+ io.close
+ rm_r filename
+ end
+ end
+
+ it "raises ArgumentError when passed not supported :output value" do
+ -> { ObjectSpace.dump("abc", output: Object.new) }.should raise_error(ArgumentError, /wrong output option/)
+ end
+end
diff --git a/spec/ruby/library/set/shared/inspect.rb b/spec/ruby/library/set/shared/inspect.rb
index 69fbdd12f6..564020e90e 100644
--- a/spec/ruby/library/set/shared/inspect.rb
+++ b/spec/ruby/library/set/shared/inspect.rb
@@ -7,6 +7,14 @@ describe "set_inspect", shared: true do
Set[:a, "b", Set[?c]].send(@method).should be_kind_of(String)
end
+ it "does include the elements of the set" do
+ Set["1"].send(@method).should == '#<Set: {"1"}>'
+ end
+
+ it "puts spaces between the elements" do
+ Set["1", "2"].send(@method).should include('", "')
+ end
+
it "correctly handles self-references" do
(set = Set[]) << set
set.send(@method).should be_kind_of(String)
diff --git a/spec/ruby/library/stringio/set_encoding_spec.rb b/spec/ruby/library/stringio/set_encoding_spec.rb
index 21d45750f3..19ca0875bf 100644
--- a/spec/ruby/library/stringio/set_encoding_spec.rb
+++ b/spec/ruby/library/stringio/set_encoding_spec.rb
@@ -17,4 +17,12 @@ describe "StringIO#set_encoding" do
io.set_encoding Encoding::UTF_8
io.string.encoding.should == Encoding::US_ASCII
end
+
+ it "accepts a String" do
+ str = "".encode(Encoding::US_ASCII)
+ io = StringIO.new(str)
+ io.set_encoding("ASCII-8BIT")
+ io.external_encoding.should == Encoding::BINARY
+ str.encoding.should == Encoding::BINARY
+ end
end
diff --git a/spec/ruby/library/stringio/shared/write.rb b/spec/ruby/library/stringio/shared/write.rb
index d9c21028e0..b91e6ecec1 100644
--- a/spec/ruby/library/stringio/shared/write.rb
+++ b/spec/ruby/library/stringio/shared/write.rb
@@ -88,6 +88,27 @@ describe :stringio_write_string, shared: true do
@io.write "fghi"
@io.string.should == "12fghi"
end
+
+ it "transcodes the given string when the external encoding is set and neither is BINARY" do
+ utf8_str = "hello"
+ io = StringIO.new.set_encoding(Encoding::UTF_16BE)
+ io.external_encoding.should == Encoding::UTF_16BE
+
+ io.send(@method, utf8_str)
+
+ expected = [0, 104, 0, 101, 0, 108, 0, 108, 0, 111] # UTF-16BE bytes for "hello"
+ io.string.bytes.should == expected
+ end
+
+ it "does not transcode the given string when the external encoding is set and the string encoding is BINARY" do
+ str = "été".b
+ io = StringIO.new.set_encoding(Encoding::UTF_16BE)
+ io.external_encoding.should == Encoding::UTF_16BE
+
+ io.send(@method, str)
+
+ io.string.bytes.should == str.bytes
+ end
end
describe :stringio_write_not_writable, shared: true do