diff options
Diffstat (limited to 'spec/ruby/core/io')
97 files changed, 2526 insertions, 768 deletions
diff --git a/spec/ruby/core/io/advise_spec.rb b/spec/ruby/core/io/advise_spec.rb index 651fc52378..b77ed53ad4 100644 --- a/spec/ruby/core/io/advise_spec.rb +++ b/spec/ruby/core/io/advise_spec.rb @@ -14,73 +14,73 @@ describe "IO#advise" do it "raises a TypeError if advise is not a Symbol" do -> { @io.advise("normal") - }.should raise_error(TypeError) + }.should.raise(TypeError) end it "raises a TypeError if offset cannot be coerced to an Integer" do -> { @io.advise(:normal, "wat") - }.should raise_error(TypeError) + }.should.raise(TypeError) end it "raises a TypeError if len cannot be coerced to an Integer" do -> { @io.advise(:normal, 0, "wat") - }.should raise_error(TypeError) + }.should.raise(TypeError) end it "raises a RangeError if offset is too big" do -> { @io.advise(:normal, 10 ** 32) - }.should raise_error(RangeError) + }.should.raise(RangeError) end it "raises a RangeError if len is too big" do -> { @io.advise(:normal, 0, 10 ** 32) - }.should raise_error(RangeError) + }.should.raise(RangeError) end it "raises a NotImplementedError if advise is not recognized" do ->{ @io.advise(:foo) - }.should raise_error(NotImplementedError) + }.should.raise(NotImplementedError) end it "supports the normal advice type" do - @io.advise(:normal).should be_nil + @io.advise(:normal).should == nil end it "supports the sequential advice type" do - @io.advise(:sequential).should be_nil + @io.advise(:sequential).should == nil end it "supports the random advice type" do - @io.advise(:random).should be_nil + @io.advise(:random).should == nil end it "supports the dontneed advice type" do - @io.advise(:dontneed).should be_nil + @io.advise(:dontneed).should == nil end it "supports the noreuse advice type" do - @io.advise(:noreuse).should be_nil + @io.advise(:noreuse).should == nil end platform_is_not :linux do it "supports the willneed advice type" do - @io.advise(:willneed).should be_nil + @io.advise(:willneed).should == nil end end guard -> { platform_is :linux and kernel_version_is '3.6' } do # [ruby-core:65355] tmpfs is not supported it "supports the willneed advice type" do - @io.advise(:willneed).should be_nil + @io.advise(:willneed).should == nil end end it "raises an IOError if the stream is closed" do @io.close - -> { @io.advise(:normal) }.should raise_error(IOError) + -> { @io.advise(:normal) }.should.raise(IOError) end end diff --git a/spec/ruby/core/io/autoclose_spec.rb b/spec/ruby/core/io/autoclose_spec.rb index 715ada7c93..596f3d6934 100644 --- a/spec/ruby/core/io/autoclose_spec.rb +++ b/spec/ruby/core/io/autoclose_spec.rb @@ -17,7 +17,7 @@ describe "IO#autoclose?" do it "cannot be queried on a closed IO object" do @io.close - -> { @io.autoclose? }.should raise_error(IOError, /closed stream/) + -> { @io.autoclose? }.should.raise(IOError, /closed stream/) end end @@ -72,6 +72,6 @@ describe "IO#autoclose=" do it "cannot be set on a closed IO object" do @io.close - -> { @io.autoclose = false }.should raise_error(IOError, /closed stream/) + -> { @io.autoclose = false }.should.raise(IOError, /closed stream/) end end diff --git a/spec/ruby/core/io/binmode_spec.rb b/spec/ruby/core/io/binmode_spec.rb index 342cac2a9b..8117229c91 100644 --- a/spec/ruby/core/io/binmode_spec.rb +++ b/spec/ruby/core/io/binmode_spec.rb @@ -13,11 +13,11 @@ describe "IO#binmode" do it "returns self" do @io = new_io(@name) - @io.binmode.should equal(@io) + @io.binmode.should.equal?(@io) end it "raises an IOError on closed stream" do - -> { IOSpecs.closed_io.binmode }.should raise_error(IOError) + -> { IOSpecs.closed_io.binmode }.should.raise(IOError) end it "sets external encoding to binary" do @@ -47,9 +47,9 @@ describe "IO#binmode?" do end it "is true after a call to IO#binmode" do - @file.binmode?.should be_false + @file.binmode?.should == false @file.binmode - @file.binmode?.should be_true + @file.binmode?.should == true end it "propagates to dup'ed IO objects" do @@ -59,6 +59,6 @@ describe "IO#binmode?" do end it "raises an IOError on closed stream" do - -> { IOSpecs.closed_io.binmode? }.should raise_error(IOError) + -> { IOSpecs.closed_io.binmode? }.should.raise(IOError) end end diff --git a/spec/ruby/core/io/binread_spec.rb b/spec/ruby/core/io/binread_spec.rb index 418e89213b..3023c7f177 100644 --- a/spec/ruby/core/io/binread_spec.rb +++ b/spec/ruby/core/io/binread_spec.rb @@ -38,14 +38,14 @@ describe "IO.binread" do end it "raises an ArgumentError when not passed a valid length" do - -> { IO.binread @fname, -1 }.should raise_error(ArgumentError) + -> { IO.binread @fname, -1 }.should.raise(ArgumentError) end it "raises an Errno::EINVAL when not passed a valid offset" do - -> { IO.binread @fname, 0, -1 }.should raise_error(Errno::EINVAL) + -> { IO.binread @fname, 0, -1 }.should.raise(Errno::EINVAL) end - ruby_version_is "3.3" do + ruby_version_is ""..."4.0" do # https://bugs.ruby-lang.org/issues/19630 it "warns about deprecation given a path with a pipe" do cmd = "|echo ok" diff --git a/spec/ruby/core/io/buffer/and_spec.rb b/spec/ruby/core/io/buffer/and_spec.rb new file mode 100644 index 0000000000..3cea163b0e --- /dev/null +++ b/spec/ruby/core/io/buffer/and_spec.rb @@ -0,0 +1,62 @@ +require_relative '../../../spec_helper' + +describe :io_buffer_and, shared: true do + it "applies the argument buffer as an AND bit mask across the whole buffer" do + IO::Buffer.for(+"12345") do |buffer| + IO::Buffer.for(+"\xF8\x8F") do |mask| + result = buffer.send(@method, mask) + result.get_string.should == "\x30\x02\x30\x04\x30".b + result.free + end + end + end + + it "ignores extra parts of mask if it is longer than source buffer" do + IO::Buffer.for(+"12345") do |buffer| + IO::Buffer.for(+"\xF8\x8F\x00\x00\x00\xFF\xFF") do |mask| + result = buffer.send(@method, mask) + result.get_string.should == "\x30\x02\x00\x00\x00".b + result.free + end + end + end + + it "raises TypeError if mask is not an IO::Buffer" do + IO::Buffer.for(+"12345") do |buffer| + -> { buffer.send(@method, "\xF8\x8F") }.should.raise(TypeError, "wrong argument type String (expected IO::Buffer)") + -> { buffer.send(@method, 0xF8) }.should.raise(TypeError, "wrong argument type Integer (expected IO::Buffer)") + -> { buffer.send(@method, nil) }.should.raise(TypeError, "wrong argument type nil (expected IO::Buffer)") + end + end +end + +describe "IO::Buffer#&" do + it_behaves_like :io_buffer_and, :& + + it "creates a new internal buffer of the same size" do + IO::Buffer.for(+"12345") do |buffer| + IO::Buffer.for(+"\xF8\x8F") do |mask| + result = buffer & mask + result.should_not.equal? buffer + result.should.internal? + result.size.should == buffer.size + result.free + buffer.get_string.should == "12345".b + end + end + end +end + +describe "IO::Buffer#and!" do + it_behaves_like :io_buffer_and, :and! + + it "modifies the buffer in place" do + IO::Buffer.for(+"12345") do |buffer| + IO::Buffer.for(+"\xF8\x8F") do |mask| + result = buffer.and!(mask) + result.should.equal? buffer + result.should.external? + end + end + end +end diff --git a/spec/ruby/core/io/buffer/bit_count_spec.rb b/spec/ruby/core/io/buffer/bit_count_spec.rb new file mode 100644 index 0000000000..62f56f5b98 --- /dev/null +++ b/spec/ruby/core/io/buffer/bit_count_spec.rb @@ -0,0 +1,64 @@ +require_relative '../../../spec_helper' + +ruby_version_is "4.1" do + describe "IO::Buffer#bit_count" do + it "counts all set bits in the whole buffer" do + IO::Buffer.for(+"\xFF\x00\x0F") do |buffer| + buffer.bit_count.should == 12 + end + end + + it "returns 0 for a buffer of all zero bytes" do + IO::Buffer.for(+"\x00\x00\x00") do |buffer| + buffer.bit_count.should == 0 + end + end + + it "returns 8 * size for a buffer of all 0xFF bytes" do + IO::Buffer.for(+"\xFF" * 9) do |buffer| + buffer.bit_count.should == 72 + end + end + + it "returns 0 for an empty buffer" do + IO::Buffer.new(0).bit_count.should == 0 + end + + it "accepts an offset to start counting from (length defaults to remaining bytes)" do + IO::Buffer.for(+"\xFF\x00\x0F") do |buffer| + buffer.bit_count(0).should == 12 # offset=0 => entire buffer + buffer.bit_count(1).should == 4 # offset=1 => 0x00 + 0x0F + buffer.bit_count(2).should == 4 # offset=2 => 0x0F only + end + end + + it "accepts an offset and length to restrict the counted region" do + IO::Buffer.for(+"\xFF\x00\x0F") do |buffer| + buffer.bit_count(0, 1).should == 8 # just 0xFF + buffer.bit_count(1, 1).should == 0 # just 0x00 + buffer.bit_count(2, 1).should == 4 # just 0x0F + buffer.bit_count(1, 2).should == 4 # 0x00 + 0x0F + end + end + + it "handles 8-byte aligned buffers efficiently" do + IO::Buffer.for(+"\xAA" * 8) do |buffer| + # 0xAA = 10101010 => 4 bits per byte => 32 total + buffer.bit_count.should == 32 + end + end + + it "raises ArgumentError when offset + length exceeds buffer size" do + IO::Buffer.for(+"\xFF") do |buffer| + -> { buffer.bit_count(0, 2) }.should.raise(ArgumentError) + -> { buffer.bit_count(1, 1) }.should.raise(ArgumentError) + end + end + + it "returns an Integer" do + IO::Buffer.for(+"\xFF") do |buffer| + buffer.bit_count.should.is_a?(Integer) + end + end + end +end diff --git a/spec/ruby/core/io/buffer/empty_spec.rb b/spec/ruby/core/io/buffer/empty_spec.rb new file mode 100644 index 0000000000..4cceb4dc0d --- /dev/null +++ b/spec/ruby/core/io/buffer/empty_spec.rb @@ -0,0 +1,27 @@ +require_relative '../../../spec_helper' +require_relative 'shared/null_and_empty' + +describe "IO::Buffer#empty?" do + after :each do + @buffer&.free + @buffer = nil + end + + it_behaves_like :io_buffer_null_and_empty, :empty? + + it "is true for a 0-length String-backed buffer created with .for" do + @buffer = IO::Buffer.for("") + @buffer.empty?.should == true + end + + it "is true for a 0-length String-backed buffer created with .string" do + IO::Buffer.string(0) do |buffer| + buffer.empty?.should == true + end + end + + it "is true for a 0-length slice of a buffer with size > 0" do + @buffer = IO::Buffer.new(4) + @buffer.slice(3, 0).empty?.should == true + end +end diff --git a/spec/ruby/core/io/buffer/external_spec.rb b/spec/ruby/core/io/buffer/external_spec.rb new file mode 100644 index 0000000000..18b2ee0d06 --- /dev/null +++ b/spec/ruby/core/io/buffer/external_spec.rb @@ -0,0 +1,23 @@ +require_relative '../../../spec_helper' + +describe "IO::Buffer#external?" do + after :each do + @buffer&.free + @buffer = nil + end + + it "is true for a buffer with externally-managed memory" do + @buffer = IO::Buffer.for("string") + @buffer.external?.should == true + end + + it "is false for a buffer with self-managed memory" do + @buffer = IO::Buffer.new(12, IO::Buffer::MAPPED) + @buffer.external?.should == false + end + + it "is false for a null buffer" do + @buffer = IO::Buffer.new(0) + @buffer.external?.should == false + end +end diff --git a/spec/ruby/core/io/buffer/for_spec.rb b/spec/ruby/core/io/buffer/for_spec.rb new file mode 100644 index 0000000000..7971ce0b71 --- /dev/null +++ b/spec/ruby/core/io/buffer/for_spec.rb @@ -0,0 +1,94 @@ +require_relative '../../../spec_helper' + +describe "IO::Buffer.for" do + before :each do + @string = +"för striñg" + end + + after :each do + @buffer&.free + @buffer = nil + end + + context "without a block" do + it "copies string's contents, creating a separate read-only buffer" do + @buffer = IO::Buffer.for(@string) + + @buffer.size.should == @string.bytesize + @buffer.get_string.should == @string.b + + @string[0] = "d" + @buffer.get_string(0, 1).should == "f".b + + -> { @buffer.set_string("d") }.should.raise(IO::Buffer::AccessError, "Buffer is not writable!") + end + + it "creates an external, read-only buffer" do + @buffer = IO::Buffer.for(@string) + + @buffer.should_not.internal? + @buffer.should_not.mapped? + @buffer.should.external? + + @buffer.should_not.empty? + @buffer.should_not.null? + + @buffer.should_not.shared? + @buffer.should_not.private? + @buffer.should.readonly? + + @buffer.should_not.locked? + @buffer.should.valid? + end + end + + context "with a block" do + it "returns the last value in the block" do + value = + IO::Buffer.for(@string) do |buffer| + buffer.size * 3 + end + value.should == @string.bytesize * 3 + end + + it "frees the buffer at the end of the block" do + IO::Buffer.for(@string) do |buffer| + @buffer = buffer + @buffer.should_not.null? + end + @buffer.should.null? + end + + context "if string is not frozen" do + it "creates a modifiable string-backed buffer" do + IO::Buffer.for(@string) do |buffer| + buffer.size.should == @string.bytesize + buffer.get_string.should == @string.b + + buffer.should_not.readonly? + + buffer.set_string("ghost shell") + @string.should == "ghost shellg" + end + end + + it "locks the original string to prevent modification" do + IO::Buffer.for(@string) do |_buffer| + -> { @string[0] = "t" }.should.raise(RuntimeError, "can't modify string; temporarily locked") + end + @string[1] = "u" + @string.should == "fur striñg" + end + end + + context "if string is frozen" do + it "creates a read-only string-backed buffer" do + IO::Buffer.for(@string.freeze) do |buffer| + buffer.should.readonly? + + -> { buffer.set_string("ghost shell") }.should.raise(IO::Buffer::AccessError, "Buffer is not writable!") + end + end + end + end +end diff --git a/spec/ruby/core/io/buffer/free_spec.rb b/spec/ruby/core/io/buffer/free_spec.rb new file mode 100644 index 0000000000..20fb7b901f --- /dev/null +++ b/spec/ruby/core/io/buffer/free_spec.rb @@ -0,0 +1,102 @@ +require_relative '../../../spec_helper' + +describe "IO::Buffer#free" do + context "with a buffer created with .new" do + it "frees internal memory and nullifies the buffer" do + buffer = IO::Buffer.new(4) + buffer.free + buffer.null?.should == true + end + + it "frees mapped memory and nullifies the buffer" do + buffer = IO::Buffer.new(4, IO::Buffer::MAPPED) + buffer.free + buffer.null?.should == true + end + end + + context "with a file-backed buffer created with .map" do + it "frees mapped memory and nullifies the buffer" do + File.open(__FILE__, "r") do |file| + buffer = IO::Buffer.map(file, nil, 0, IO::Buffer::READONLY) + buffer.free + buffer.null?.should == true + end + end + end + + context "with a String-backed buffer created with .for" do + context "without a block" do + it "disassociates the buffer from the string and nullifies the buffer" do + string = +"test" + buffer = IO::Buffer.for(string) + # Read-only buffer, can't modify the string. + buffer.free + buffer.null?.should == true + end + end + + context "with a block" do + it "disassociates the buffer from the string and nullifies the buffer" do + string = +"test" + IO::Buffer.for(string) do |buffer| + buffer.set_string("meat") + buffer.free + buffer.null?.should == true + end + string.should == "meat" + end + end + end + + context "with a String-backed buffer created with .string" do + it "disassociates the buffer from the string and nullifies the buffer" do + string = + IO::Buffer.string(4) do |buffer| + buffer.set_string("meat") + buffer.free + buffer.null?.should == true + end + string.should == "meat" + end + end + + it "can be called repeatedly without an error" do + buffer = IO::Buffer.new(4) + buffer.free + buffer.null?.should == true + buffer.free + buffer.null?.should == true + end + + it "is disallowed while locked, raising IO::Buffer::LockedError" do + buffer = IO::Buffer.new(4) + buffer.locked do + -> { buffer.free }.should.raise(IO::Buffer::LockedError, "Buffer is locked!") + end + buffer.free + buffer.null?.should == true + end + + context "with a slice of a buffer" do + it "nullifies the slice, not touching the buffer" do + buffer = IO::Buffer.new(4) + slice = buffer.slice(0, 2) + + slice.free + slice.null?.should == true + buffer.null?.should == false + + buffer.free + end + + it "nullifies buffer, invalidating the slice" do + buffer = IO::Buffer.new(4) + slice = buffer.slice(0, 2) + + buffer.free + slice.null?.should == false + slice.valid?.should == false + end + end +end diff --git a/spec/ruby/core/io/buffer/initialize_spec.rb b/spec/ruby/core/io/buffer/initialize_spec.rb new file mode 100644 index 0000000000..dba6fddc79 --- /dev/null +++ b/spec/ruby/core/io/buffer/initialize_spec.rb @@ -0,0 +1,119 @@ +require_relative '../../../spec_helper' + +describe "IO::Buffer#initialize" do + after :each do + @buffer&.free + @buffer = nil + end + + it "creates a new zero-filled buffer with default size" do + @buffer = IO::Buffer.new + @buffer.size.should == IO::Buffer::DEFAULT_SIZE + @buffer.each(:U8).should.all? { |_offset, value| value.eql?(0) } + end + + it "creates a buffer with default state" do + @buffer = IO::Buffer.new + + @buffer.should_not.external? + + @buffer.should_not.shared? + @buffer.should_not.private? + @buffer.should_not.readonly? + + @buffer.should_not.empty? + @buffer.should_not.null? + + @buffer.should_not.locked? + @buffer.should.valid? + end + + context "with size argument" do + it "creates a new internal buffer if size is less than IO::Buffer::PAGE_SIZE" do + size = IO::Buffer::PAGE_SIZE - 1 + @buffer = IO::Buffer.new(size) + @buffer.size.should == size + @buffer.should_not.empty? + + @buffer.should.internal? + @buffer.should_not.mapped? + end + + it "creates a new mapped buffer if size is greater than or equal to IO::Buffer::PAGE_SIZE" do + size = IO::Buffer::PAGE_SIZE + @buffer = IO::Buffer.new(size) + @buffer.size.should == size + @buffer.should_not.empty? + + @buffer.should_not.internal? + @buffer.should.mapped? + end + + it "creates a null buffer if size is 0" do + @buffer = IO::Buffer.new(0) + @buffer.should.null? + @buffer.should.empty? + end + + it "raises TypeError if size is not an Integer" do + -> { IO::Buffer.new(nil) }.should.raise(TypeError, "not an Integer") + -> { IO::Buffer.new(10.0) }.should.raise(TypeError, "not an Integer") + end + + it "raises ArgumentError if size is negative" do + -> { IO::Buffer.new(-1) }.should.raise(ArgumentError, "Size can't be negative!") + end + end + + context "with size and flags arguments" do + it "forces mapped buffer with IO::Buffer::MAPPED flag" do + @buffer = IO::Buffer.new(IO::Buffer::PAGE_SIZE - 1, IO::Buffer::MAPPED) + @buffer.should.mapped? + @buffer.should_not.internal? + @buffer.should_not.empty? + end + + it "forces internal buffer with IO::Buffer::INTERNAL flag" do + @buffer = IO::Buffer.new(IO::Buffer::PAGE_SIZE, IO::Buffer::INTERNAL) + @buffer.should.internal? + @buffer.should_not.mapped? + @buffer.should_not.empty? + end + + it "allows extra flags" do + @buffer = IO::Buffer.new(10, IO::Buffer::INTERNAL | IO::Buffer::SHARED | IO::Buffer::READONLY) + @buffer.should.internal? + @buffer.should.shared? + @buffer.should.readonly? + end + + it "ignores flags if size is 0" do + @buffer = IO::Buffer.new(0, 0xffff) + @buffer.should.null? + @buffer.should.empty? + + @buffer.should_not.internal? + @buffer.should_not.mapped? + @buffer.should_not.external? + + @buffer.should_not.shared? + @buffer.should_not.readonly? + + @buffer.should_not.locked? + @buffer.should.valid? + end + + it "raises IO::Buffer::AllocationError if neither IO::Buffer::MAPPED nor IO::Buffer::INTERNAL is given" do + -> { IO::Buffer.new(10, IO::Buffer::READONLY) }.should.raise(IO::Buffer::AllocationError, "Could not allocate buffer!") + -> { IO::Buffer.new(10, 0) }.should.raise(IO::Buffer::AllocationError, "Could not allocate buffer!") + end + + it "raises ArgumentError if flags is negative" do + -> { IO::Buffer.new(10, -1) }.should.raise(ArgumentError, "Flags can't be negative!") + end + + it "raises TypeError with non-Integer flags" do + -> { IO::Buffer.new(10, 0.0) }.should.raise(TypeError, "not an Integer") + end + end +end diff --git a/spec/ruby/core/io/buffer/internal_spec.rb b/spec/ruby/core/io/buffer/internal_spec.rb new file mode 100644 index 0000000000..73e19eb85e --- /dev/null +++ b/spec/ruby/core/io/buffer/internal_spec.rb @@ -0,0 +1,23 @@ +require_relative '../../../spec_helper' + +describe "IO::Buffer#internal?" do + after :each do + @buffer&.free + @buffer = nil + end + + it "is true for an internally-allocated buffer" do + @buffer = IO::Buffer.new(12) + @buffer.internal?.should == true + end + + it "is false for an externally-allocated buffer" do + @buffer = IO::Buffer.new(12, IO::Buffer::MAPPED) + @buffer.internal?.should == false + end + + it "is false for a null buffer" do + @buffer = IO::Buffer.new(0) + @buffer.internal?.should == false + end +end diff --git a/spec/ruby/core/io/buffer/locked_spec.rb b/spec/ruby/core/io/buffer/locked_spec.rb new file mode 100644 index 0000000000..249026aa8a --- /dev/null +++ b/spec/ruby/core/io/buffer/locked_spec.rb @@ -0,0 +1,75 @@ +require_relative '../../../spec_helper' + +describe "IO::Buffer#locked" do + after :each do + @buffer&.free + @buffer = nil + end + + context "when buffer is locked" do + it "allows reading and writing operations on the buffer" do + @buffer = IO::Buffer.new(4) + @buffer.set_string("test") + @buffer.locked do + @buffer.get_string.should == "test" + @buffer.set_string("meat") + end + @buffer.get_string.should == "meat" + end + + it "disallows operations changing buffer itself, raising IO::Buffer::LockedError" do + @buffer = IO::Buffer.new(4) + @buffer.locked do + # Just an example, each method is responsible for checking the lock state. + -> { @buffer.resize(8) }.should.raise(IO::Buffer::LockedError) + end + end + end + + it "disallows reentrant locking, raising IO::Buffer::LockedError" do + @buffer = IO::Buffer.new(4) + @buffer.locked do + -> { @buffer.locked {} }.should.raise(IO::Buffer::LockedError, "Buffer already locked!") + end + end + + it "does not propagate to buffer's slices" do + @buffer = IO::Buffer.new(4) + slice = @buffer.slice(0, 2) + @buffer.locked do + @buffer.locked?.should == true + slice.locked?.should == false + slice.locked { slice.locked?.should == true } + end + end + + it "does not propagate backwards from buffer's slices" do + @buffer = IO::Buffer.new(4) + slice = @buffer.slice(0, 2) + slice.locked do + slice.locked?.should == true + @buffer.locked?.should == false + @buffer.locked { @buffer.locked?.should == true } + end + end +end + +describe "IO::Buffer#locked?" do + after :each do + @buffer&.free + @buffer = nil + end + + it "is false by default" do + @buffer = IO::Buffer.new(4) + @buffer.locked?.should == false + end + + it "is true only inside of #locked block" do + @buffer = IO::Buffer.new(4) + @buffer.locked do + @buffer.locked?.should == true + end + @buffer.locked?.should == false + end +end diff --git a/spec/ruby/core/io/buffer/map_spec.rb b/spec/ruby/core/io/buffer/map_spec.rb new file mode 100644 index 0000000000..23e837ce07 --- /dev/null +++ b/spec/ruby/core/io/buffer/map_spec.rb @@ -0,0 +1,343 @@ +require_relative '../../../spec_helper' + +describe "IO::Buffer.map" do + before :all do + @tmp_files = [] + + @big_file_name = nil + @small_file_name = nil + end + + after :all do + @tmp_files.each {|file| File.delete(file)} + end + + def open_fixture + unless @small_file_name + @small_file_name = tmp("read_text.txt") + File.copy_stream(fixture(__dir__, "read_text.txt"), @small_file_name) + @tmp_files << @small_file_name + end + File.open(@small_file_name, "rb+") + end + + def open_big_file_fixture + unless @big_file_name + @big_file_name = tmp("big_file") + # Usually 4 kibibytes + 16 bytes + File.write(@big_file_name, "12345678" * (IO::Buffer::PAGE_SIZE / 8 + 2)) + @tmp_files << @big_file_name + end + File.open(@big_file_name, "rb+") + end + + after :each do + @buffer&.free + @buffer = nil + @file&.close + @file = nil + end + + it "creates a new buffer mapped from a file" do + @file = open_fixture + @buffer = IO::Buffer.map(@file) + + @buffer.size.should == 9 + @buffer.get_string.should == "abcâdef\n".b + end + + it "allows to close the file after creating buffer, retaining mapping" do + file = open_fixture + @buffer = IO::Buffer.map(file) + file.close + + @buffer.get_string.should == "abcâdef\n".b + end + + it "creates a mapped, external, shared buffer" do + @file = open_fixture + @buffer = IO::Buffer.map(@file) + + @buffer.should_not.internal? + @buffer.should.mapped? + @buffer.should.external? + + @buffer.should_not.empty? + @buffer.should_not.null? + + @buffer.should.shared? + @buffer.should_not.private? + @buffer.should_not.readonly? + + @buffer.should_not.locked? + @buffer.should.valid? + end + + platform_is_not :windows, :openbsd do + it "is shareable across processes" do + file_name = tmp("shared_buffer") + @file = File.open(file_name, "w+") + @file << "I'm private" + @file.rewind + @buffer = IO::Buffer.map(@file) + + IO.popen("-") do |child_pipe| + if child_pipe + # Synchronize on child's output. + child_pipe.readlines.first.chomp.should == @buffer.to_s + @buffer.get_string.should == "I'm shared!" + + @file.read.should == "I'm shared!" + else + @buffer.set_string("I'm shared!") + puts @buffer + end + ensure + child_pipe&.close + end + ensure + File.unlink(file_name) + end + end + + context "with an empty file" do + ruby_version_is "4.0" do + it "raises ArgumentError" do + file_name = tmp("empty.txt") + @file = File.open(file_name, "wb+") + @tmp_files << file_name + -> { IO::Buffer.map(@file) }.should.raise(ArgumentError, "Invalid negative or zero file size!") + end + end + end + + context "with a file opened only for reading" do + it "raises a SystemCallError unless read-only" do + @file = File.open(fixture(__dir__, "read_text.txt"), "rb") + -> { IO::Buffer.map(@file) }.should.raise(SystemCallError) + end + end + + context "with size argument" do + it "limits the buffer to the specified size in bytes, starting from the start of the file" do + @file = open_fixture + @buffer = IO::Buffer.map(@file, 4) + + @buffer.size.should == 4 + @buffer.get_string.should == "abc\xC3".b + end + + it "maps the whole file if size is nil" do + @file = open_fixture + @buffer = IO::Buffer.map(@file, nil) + + @buffer.size.should == 9 + end + + context "if size is 0" do + ruby_version_is "4.0" do + it "raises ArgumentError" do + @file = open_fixture + -> { IO::Buffer.map(@file, 0) }.should.raise(ArgumentError, "Size can't be zero!") + end + end + end + + it "raises TypeError if size is not an Integer or nil" do + @file = open_fixture + -> { IO::Buffer.map(@file, "10") }.should.raise(TypeError, "not an Integer") + -> { IO::Buffer.map(@file, 10.0) }.should.raise(TypeError, "not an Integer") + end + + it "raises ArgumentError if size is negative" do + @file = open_fixture + -> { IO::Buffer.map(@file, -1) }.should.raise(ArgumentError, "Size can't be negative!") + end + + ruby_version_is ""..."4.0" do + # May or may not cause a crash on access. + it "is undefined behavior if size is larger than file size" + end + + ruby_version_is "4.0" do + it "raises ArgumentError if size is larger than file size" do + @file = open_fixture + -> { IO::Buffer.map(@file, 8192) }.should.raise(ArgumentError, "Size can't be larger than file size!") + end + end + end + + context "with size and offset arguments" do + # Neither Windows nor macOS have clear, stable behavior with non-zero offset. + # https://bugs.ruby-lang.org/issues/21700 + platform_is :linux do + context "if offset is an allowed value for system call" do + it "maps the span specified by size starting from the offset" do + @file = open_big_file_fixture + @buffer = IO::Buffer.map(@file, 14, IO::Buffer::PAGE_SIZE) + + @buffer.size.should == 14 + @buffer.get_string(0, 14).should == "12345678123456" + end + + context "if size is nil" do + ruby_version_is ""..."4.0" do + it "maps the rest of the file" do + @file = open_big_file_fixture + @buffer = IO::Buffer.map(@file, nil, IO::Buffer::PAGE_SIZE) + + @buffer.get_string(0, 1).should == "1" + end + + it "incorrectly sets buffer's size to file's full size" do + @file = open_big_file_fixture + @buffer = IO::Buffer.map(@file, nil, IO::Buffer::PAGE_SIZE) + + @buffer.size.should == @file.size + end + end + + ruby_version_is "4.0" do + it "maps the rest of the file" do + @file = open_big_file_fixture + @buffer = IO::Buffer.map(@file, nil, IO::Buffer::PAGE_SIZE) + + @buffer.get_string(0, 1).should == "1" + end + + it "sets buffer's size to file's remaining size" do + @file = open_big_file_fixture + @buffer = IO::Buffer.map(@file, nil, IO::Buffer::PAGE_SIZE) + + @buffer.size.should == (@file.size - IO::Buffer::PAGE_SIZE) + end + end + end + end + end + + it "maps the file from the start if offset is 0" do + @file = open_fixture + @buffer = IO::Buffer.map(@file, 4, 0) + + @buffer.size.should == 4 + @buffer.get_string.should == "abc\xC3".b + end + + ruby_version_is ""..."4.0" do + # May or may not cause a crash on access. + it "is undefined behavior if offset+size is larger than file size" + end + + ruby_version_is "4.0" do + it "raises ArgumentError if offset+size is larger than file size" do + @file = open_big_file_fixture + -> { IO::Buffer.map(@file, 17, IO::Buffer::PAGE_SIZE) }.should.raise(ArgumentError, "Offset too large!") + ensure + # Windows requires the file to be closed before deletion. + @file.close unless @file.closed? + end + end + + it "raises TypeError if offset is not convertible to Integer" do + @file = open_fixture + -> { IO::Buffer.map(@file, 4, "4096") }.should.raise(TypeError, /no implicit conversion/) + -> { IO::Buffer.map(@file, 4, nil) }.should.raise(TypeError, /no implicit conversion/) + end + + ruby_version_is "4.0" do + it "raises ArgumentError if offset is negative" do + @file = open_fixture + -> { IO::Buffer.map(@file, 4, -1) }.should.raise(ArgumentError, "Offset can't be negative!") + end + end + end + + context "with flags argument" do + context "when READONLY flag is specified" do + it "sets readonly flag on the buffer, allowing only reads" do + @file = open_fixture + @buffer = IO::Buffer.map(@file, nil, 0, IO::Buffer::READONLY) + + @buffer.should.readonly? + + @buffer.get_string.should == "abc\xC3\xA2def\n".b + end + + it "allows mapping read-only files" do + @file = File.open(fixture(__dir__, "read_text.txt"), "rb") + @buffer = IO::Buffer.map(@file, nil, 0, IO::Buffer::READONLY) + + @buffer.should.readonly? + + @buffer.get_string.should == "abc\xC3\xA2def\n".b + end + + it "causes IO::Buffer::AccessError on write" do + @file = open_fixture + @buffer = IO::Buffer.map(@file, nil, 0, IO::Buffer::READONLY) + + -> { @buffer.set_string("test") }.should.raise(IO::Buffer::AccessError, "Buffer is not writable!") + end + end + + context "when PRIVATE is specified" do + it "sets private flag on the buffer, making it freely modifiable" do + @file = open_fixture + @buffer = IO::Buffer.map(@file, nil, 0, IO::Buffer::PRIVATE) + + @buffer.should.private? + @buffer.should_not.shared? + @buffer.should_not.external? + + @buffer.get_string.should == "abc\xC3\xA2def\n".b + @buffer.set_string("test12345") + @buffer.get_string.should == "test12345".b + + @file.read.should == "abcâdef\n".b + end + + it "allows mapping read-only files and modifying the buffer" do + @file = File.open(fixture(__dir__, "read_text.txt"), "rb") + @buffer = IO::Buffer.map(@file, nil, 0, IO::Buffer::PRIVATE) + + @buffer.should.private? + @buffer.should_not.shared? + @buffer.should_not.external? + + @buffer.get_string.should == "abc\xC3\xA2def\n".b + @buffer.set_string("test12345") + @buffer.get_string.should == "test12345".b + + @file.read.should == "abcâdef\n".b + end + + platform_is_not :windows do + it "is not shared across processes" do + file_name = tmp("shared_buffer") + @file = File.open(file_name, "w+") + @file << "I'm private" + @file.rewind + @buffer = IO::Buffer.map(@file, nil, 0, IO::Buffer::PRIVATE) + + IO.popen("-") do |child_pipe| + if child_pipe + # Synchronize on child's output. + child_pipe.readlines.first.chomp.should == @buffer.to_s + @buffer.get_string.should == "I'm private" + + @file.read.should == "I'm private" + else + @buffer.set_string("I'm shared!") + puts @buffer + end + ensure + child_pipe&.close + end + ensure + File.unlink(file_name) + end + end + end + end +end diff --git a/spec/ruby/core/io/buffer/mapped_spec.rb b/spec/ruby/core/io/buffer/mapped_spec.rb new file mode 100644 index 0000000000..0decb97704 --- /dev/null +++ b/spec/ruby/core/io/buffer/mapped_spec.rb @@ -0,0 +1,23 @@ +require_relative '../../../spec_helper' + +describe "IO::Buffer#mapped?" do + after :each do + @buffer&.free + @buffer = nil + end + + it "is true for a buffer with mapped memory" do + @buffer = IO::Buffer.new(12, IO::Buffer::MAPPED) + @buffer.mapped?.should == true + end + + it "is false for a buffer with non-mapped memory" do + @buffer = IO::Buffer.for("string") + @buffer.mapped?.should == false + end + + it "is false for a null buffer" do + @buffer = IO::Buffer.new(0) + @buffer.mapped?.should == false + end +end diff --git a/spec/ruby/core/io/buffer/not_spec.rb b/spec/ruby/core/io/buffer/not_spec.rb new file mode 100644 index 0000000000..4737a30bde --- /dev/null +++ b/spec/ruby/core/io/buffer/not_spec.rb @@ -0,0 +1,37 @@ +require_relative '../../../spec_helper' + +describe :io_buffer_not, shared: true do + it "inverts every bit of the buffer" do + IO::Buffer.for(+"12345") do |buffer| + result = buffer.send(@method) + result.get_string.should == "\xCE\xCD\xCC\xCB\xCA".b + result.free + end + end +end + +describe "IO::Buffer#~" do + it_behaves_like :io_buffer_not, :~ + + it "creates a new internal buffer of the same size" do + IO::Buffer.for(+"12345") do |buffer| + result = ~buffer + result.should_not.equal? buffer + result.should.internal? + result.size.should == buffer.size + result.free + end + end +end + +describe "IO::Buffer#not!" do + it_behaves_like :io_buffer_not, :not! + + it "modifies the buffer in place" do + IO::Buffer.for(+"12345") do |buffer| + result = buffer.not! + result.should.equal? buffer + result.should.external? + end + end +end diff --git a/spec/ruby/core/io/buffer/null_spec.rb b/spec/ruby/core/io/buffer/null_spec.rb new file mode 100644 index 0000000000..380a98bde1 --- /dev/null +++ b/spec/ruby/core/io/buffer/null_spec.rb @@ -0,0 +1,27 @@ +require_relative '../../../spec_helper' +require_relative 'shared/null_and_empty' + +describe "IO::Buffer#null?" do + after :each do + @buffer&.free + @buffer = nil + end + + it_behaves_like :io_buffer_null_and_empty, :null? + + it "is false for a 0-length String-backed buffer created with .for" do + @buffer = IO::Buffer.for("") + @buffer.null?.should == false + end + + it "is false for a 0-length String-backed buffer created with .string" do + IO::Buffer.string(0) do |buffer| + buffer.null?.should == false + end + end + + it "is false for a 0-length slice of a buffer with size > 0" do + @buffer = IO::Buffer.new(4) + @buffer.slice(3, 0).null?.should == false + end +end diff --git a/spec/ruby/core/io/buffer/or_spec.rb b/spec/ruby/core/io/buffer/or_spec.rb new file mode 100644 index 0000000000..3e627c216c --- /dev/null +++ b/spec/ruby/core/io/buffer/or_spec.rb @@ -0,0 +1,62 @@ +require_relative '../../../spec_helper' + +describe :io_buffer_or, shared: true do + it "applies the argument buffer as an OR bit mask across the whole buffer" do + IO::Buffer.for(+"12345") do |buffer| + IO::Buffer.for(+"\xF8\x8F") do |mask| + result = buffer.send(@method, mask) + result.get_string.should == "\xF9\xBF\xFB\xBF\xFD".b + result.free + end + end + end + + it "ignores extra parts of mask if it is longer than source buffer" do + IO::Buffer.for(+"12345") do |buffer| + IO::Buffer.for(+"\xF8\x8F\x00\x00\x00\xFF\xFF") do |mask| + result = buffer.send(@method, mask) + result.get_string.should == "\xF9\xBF345".b + result.free + end + end + end + + it "raises TypeError if mask is not an IO::Buffer" do + IO::Buffer.for(+"12345") do |buffer| + -> { buffer.send(@method, "\xF8\x8F") }.should.raise(TypeError, "wrong argument type String (expected IO::Buffer)") + -> { buffer.send(@method, 0xF8) }.should.raise(TypeError, "wrong argument type Integer (expected IO::Buffer)") + -> { buffer.send(@method, nil) }.should.raise(TypeError, "wrong argument type nil (expected IO::Buffer)") + end + end +end + +describe "IO::Buffer#|" do + it_behaves_like :io_buffer_or, :| + + it "creates a new internal buffer of the same size" do + IO::Buffer.for(+"12345") do |buffer| + IO::Buffer.for(+"\xF8\x8F") do |mask| + result = buffer | mask + result.should_not.equal? buffer + result.should.internal? + result.size.should == buffer.size + result.free + buffer.get_string.should == "12345".b + end + end + end +end + +describe "IO::Buffer#or!" do + it_behaves_like :io_buffer_or, :or! + + it "modifies the buffer in place" do + IO::Buffer.for(+"12345") do |buffer| + IO::Buffer.for(+"\xF8\x8F") do |mask| + result = buffer.or!(mask) + result.should.equal? buffer + result.should.external? + end + end + end +end diff --git a/spec/ruby/core/io/buffer/private_spec.rb b/spec/ruby/core/io/buffer/private_spec.rb new file mode 100644 index 0000000000..6e6afee34c --- /dev/null +++ b/spec/ruby/core/io/buffer/private_spec.rb @@ -0,0 +1,23 @@ +require_relative '../../../spec_helper' + +describe "IO::Buffer#private?" do + after :each do + @buffer&.free + @buffer = nil + end + + it "is true for a buffer created with PRIVATE flag" do + @buffer = IO::Buffer.new(12, IO::Buffer::INTERNAL | IO::Buffer::PRIVATE) + @buffer.private?.should == true + end + + it "is false for a buffer created without PRIVATE flag" do + @buffer = IO::Buffer.new(12, IO::Buffer::INTERNAL) + @buffer.private?.should == false + end + + it "is false for a null buffer" do + @buffer = IO::Buffer.new(0) + @buffer.private?.should == false + end +end diff --git a/spec/ruby/core/io/buffer/readonly_spec.rb b/spec/ruby/core/io/buffer/readonly_spec.rb new file mode 100644 index 0000000000..4eefc9f29f --- /dev/null +++ b/spec/ruby/core/io/buffer/readonly_spec.rb @@ -0,0 +1,28 @@ +require_relative '../../../spec_helper' + +describe "IO::Buffer#readonly?" do + after :each do + @buffer&.free + @buffer = nil + end + + it "is true for a buffer created with READONLY flag" do + @buffer = IO::Buffer.new(12, IO::Buffer::INTERNAL | IO::Buffer::READONLY) + @buffer.readonly?.should == true + end + + it "is true for a buffer that is non-writable" do + @buffer = IO::Buffer.for("string") + @buffer.readonly?.should == true + end + + it "is false for a modifiable buffer" do + @buffer = IO::Buffer.new(12) + @buffer.readonly?.should == false + end + + it "is false for a null buffer" do + @buffer = IO::Buffer.new(0) + @buffer.readonly?.should == false + end +end diff --git a/spec/ruby/core/io/buffer/resize_spec.rb b/spec/ruby/core/io/buffer/resize_spec.rb new file mode 100644 index 0000000000..6e684475f3 --- /dev/null +++ b/spec/ruby/core/io/buffer/resize_spec.rb @@ -0,0 +1,151 @@ +require_relative '../../../spec_helper' + +describe "IO::Buffer#resize" do + after :each do + @buffer&.free + @buffer = nil + end + + context "with a buffer created with .new" do + it "resizes internal buffer, preserving type" do + @buffer = IO::Buffer.new(4) + @buffer.resize(IO::Buffer::PAGE_SIZE) + @buffer.size.should == IO::Buffer::PAGE_SIZE + @buffer.internal?.should == true + @buffer.mapped?.should == false + end + + platform_is :linux do + it "resizes mapped buffer, preserving type" do + @buffer = IO::Buffer.new(IO::Buffer::PAGE_SIZE, IO::Buffer::MAPPED) + @buffer.resize(4) + @buffer.size.should == 4 + @buffer.internal?.should == false + @buffer.mapped?.should == true + end + end + + platform_is_not :linux do + it "resizes mapped buffer, changing type to internal" do + @buffer = IO::Buffer.new(IO::Buffer::PAGE_SIZE, IO::Buffer::MAPPED) + @buffer.resize(4) + @buffer.size.should == 4 + @buffer.internal?.should == true + @buffer.mapped?.should == false + end + end + end + + context "with a file-backed buffer created with .map" do + it "disallows resizing shared buffer, raising IO::Buffer::AccessError" do + File.open(__FILE__, "r+") do |file| + @buffer = IO::Buffer.map(file) + -> { @buffer.resize(10) }.should.raise(IO::Buffer::AccessError, "Cannot resize external buffer!") + end + end + + it "resizes private buffer, discarding excess contents" do + File.open(__FILE__, "r") do |file| + @buffer = IO::Buffer.map(file, nil, 0, IO::Buffer::PRIVATE) + @buffer.resize(10) + @buffer.size.should == 10 + @buffer.get_string.should == "require_re" + @buffer.resize(12) + @buffer.size.should == 12 + @buffer.get_string.should == "require_re\0\0" + end + end + end + + context "with a String-backed buffer created with .for" do + context "without a block" do + it "disallows resizing, raising IO::Buffer::AccessError" do + @buffer = IO::Buffer.for(+"test") + -> { @buffer.resize(10) }.should.raise(IO::Buffer::AccessError, "Cannot resize external buffer!") + end + end + + context "with a block" do + it "disallows resizing, raising IO::Buffer::AccessError" do + IO::Buffer.for(+'test') do |buffer| + -> { buffer.resize(10) }.should.raise(IO::Buffer::AccessError, "Cannot resize external buffer!") + end + end + end + end + + context "with a String-backed buffer created with .string" do + it "disallows resizing, raising IO::Buffer::AccessError" do + IO::Buffer.string(4) do |buffer| + -> { buffer.resize(10) }.should.raise(IO::Buffer::AccessError, "Cannot resize external buffer!") + end + end + end + + context "with a null buffer" do + it "allows resizing a 0-sized buffer, creating a regular buffer according to new size" do + @buffer = IO::Buffer.new(0) + @buffer.resize(IO::Buffer::PAGE_SIZE) + @buffer.size.should == IO::Buffer::PAGE_SIZE + @buffer.internal?.should == false + @buffer.mapped?.should == true + end + + it "allows resizing after a free, creating a regular buffer according to new size" do + @buffer = IO::Buffer.for("test") + @buffer.free + @buffer.resize(10) + @buffer.size.should == 10 + @buffer.internal?.should == true + @buffer.mapped?.should == false + end + end + + it "allows resizing to 0, freeing memory" do + @buffer = IO::Buffer.new(4) + @buffer.resize(0) + @buffer.null?.should == true + end + + it "can be called repeatedly" do + @buffer = IO::Buffer.new(4) + @buffer.resize(10) + @buffer.resize(27) + @buffer.resize(1) + @buffer.size.should == 1 + end + + it "always clears extra memory" do + @buffer = IO::Buffer.new(4) + @buffer.set_string("test") + # This should not cause a re-allocation, just a technical resizing, + # even with very aggressive memory allocation. + @buffer.resize(2) + @buffer.resize(4) + @buffer.get_string.should == "te\0\0" + end + + it "is disallowed while locked, raising IO::Buffer::LockedError" do + @buffer = IO::Buffer.new(4) + @buffer.locked do + -> { @buffer.resize(10) }.should.raise(IO::Buffer::LockedError, "Cannot resize locked buffer!") + end + end + + it "raises ArgumentError if size is negative" do + @buffer = IO::Buffer.new(4) + -> { @buffer.resize(-1) }.should.raise(ArgumentError, "Size can't be negative!") + end + + it "raises TypeError if size is not an Integer" do + @buffer = IO::Buffer.new(4) + -> { @buffer.resize(nil) }.should.raise(TypeError, "not an Integer") + -> { @buffer.resize(10.0) }.should.raise(TypeError, "not an Integer") + end + + context "with a slice of a buffer" do + # Current behavior of slice resizing seems unintended (it's undocumented, too). + # It either creates a completely new buffer, or breaks the slice on size 0. + it "needs to be reviewed for spec completeness" + end +end diff --git a/spec/ruby/core/io/buffer/shared/null_and_empty.rb b/spec/ruby/core/io/buffer/shared/null_and_empty.rb new file mode 100644 index 0000000000..f8abc5f0fc --- /dev/null +++ b/spec/ruby/core/io/buffer/shared/null_and_empty.rb @@ -0,0 +1,57 @@ +describe :io_buffer_null_and_empty, shared: true do + it "is false for a buffer with size > 0" do + @buffer = IO::Buffer.new(1) + @buffer.send(@method).should == false + end + + it "is false for a slice with length > 0" do + @buffer = IO::Buffer.new(4) + @buffer.slice(1, 2).send(@method).should == false + end + + it "is false for a file-mapped buffer" do + File.open(__FILE__, "rb") do |file| + @buffer = IO::Buffer.map(file, nil, 0, IO::Buffer::READONLY) + @buffer.send(@method).should == false + end + end + + it "is false for a non-empty String-backed buffer created with .for" do + @buffer = IO::Buffer.for("test") + @buffer.send(@method).should == false + end + + it "is false for a non-empty String-backed buffer created with .string" do + IO::Buffer.string(4) do |buffer| + buffer.send(@method).should == false + end + end + + it "is true for a 0-sized buffer" do + @buffer = IO::Buffer.new(0) + @buffer.send(@method).should == true + end + + it "is true for a slice of a 0-sized buffer" do + @buffer = IO::Buffer.new(0) + @buffer.slice(0, 0).send(@method).should == true + end + + it "is true for a freed buffer" do + @buffer = IO::Buffer.new(1) + @buffer.free + @buffer.send(@method).should == true + end + + it "is true for a buffer resized to 0" do + @buffer = IO::Buffer.new(1) + @buffer.resize(0) + @buffer.send(@method).should == true + end + + it "is true for a buffer whose memory was transferred" do + buffer = IO::Buffer.new(1) + @buffer = buffer.transfer + buffer.send(@method).should == true + end +end diff --git a/spec/ruby/core/io/buffer/shared_spec.rb b/spec/ruby/core/io/buffer/shared_spec.rb new file mode 100644 index 0000000000..daaa66c5ad --- /dev/null +++ b/spec/ruby/core/io/buffer/shared_spec.rb @@ -0,0 +1,35 @@ +require_relative '../../../spec_helper' + +describe "IO::Buffer#shared?" do + after :each do + @buffer&.free + @buffer = nil + end + + it "is true for a buffer created with SHARED flag" do + @buffer = IO::Buffer.new(12, IO::Buffer::INTERNAL | IO::Buffer::SHARED) + @buffer.shared?.should == true + end + + it "is true for a non-private buffer created with .map" do + path = tmp("read_text.txt") + File.copy_stream(fixture(__dir__, "read_text.txt"), path) + file = File.open(path, "r+") + @buffer = IO::Buffer.map(file) + @buffer.shared?.should == true + ensure + @buffer.free + file.close + File.unlink(path) + end + + it "is false for an unshared buffer" do + @buffer = IO::Buffer.new(12) + @buffer.shared?.should == false + end + + it "is false for a null buffer" do + @buffer = IO::Buffer.new(0) + @buffer.shared?.should == false + end +end diff --git a/spec/ruby/core/io/buffer/string_spec.rb b/spec/ruby/core/io/buffer/string_spec.rb new file mode 100644 index 0000000000..4c73ba5e1e --- /dev/null +++ b/spec/ruby/core/io/buffer/string_spec.rb @@ -0,0 +1,62 @@ +require_relative '../../../spec_helper' + +describe "IO::Buffer.string" do + it "creates a modifiable buffer for the duration of the block" do + IO::Buffer.string(7) do |buffer| + @buffer = buffer + + buffer.size.should == 7 + buffer.get_string.should == "\0\0\0\0\0\0\0".b + + buffer.set_string("test") + buffer.get_string.should == "test\0\0\0" + end + @buffer.should.null? + end + + it "returns contents of the buffer as a binary string" do + string = + IO::Buffer.string(7) do |buffer| + buffer.set_string("ä test") + end + string.should == "\xC3\xA4 test".b + end + + it "creates an external buffer" do + IO::Buffer.string(8) do |buffer| + buffer.should_not.internal? + buffer.should_not.mapped? + buffer.should.external? + + buffer.should_not.empty? + buffer.should_not.null? + + buffer.should_not.shared? + buffer.should_not.private? + buffer.should_not.readonly? + + buffer.should_not.locked? + buffer.should.valid? + end + end + + it "returns an empty string if size is 0" do + string = + IO::Buffer.string(0) do |buffer| + buffer.size.should == 0 + end + string.should == "" + end + + it "raises ArgumentError if size is negative" do + -> { IO::Buffer.string(-1) {} }.should.raise(ArgumentError, "negative string size (or size too big)") + end + + it "raises RangeError if size is too large" do + -> { IO::Buffer.string(2 ** 232) {} }.should.raise(RangeError, /\Abignum too big to convert into [`']long'\z/) + end + + it "raises LocalJumpError if no block is given" do + -> { IO::Buffer.string(7) }.should.raise(LocalJumpError, "no block given") + end +end diff --git a/spec/ruby/core/io/buffer/transfer_spec.rb b/spec/ruby/core/io/buffer/transfer_spec.rb new file mode 100644 index 0000000000..02e029016a --- /dev/null +++ b/spec/ruby/core/io/buffer/transfer_spec.rb @@ -0,0 +1,116 @@ +require_relative '../../../spec_helper' + +describe "IO::Buffer#transfer" do + after :each do + @buffer&.free + @buffer = nil + end + + context "with a buffer created with .new" do + it "transfers internal memory to a new buffer, nullifying the original" do + buffer = IO::Buffer.new(4) + info = buffer.to_s + @buffer = buffer.transfer + @buffer.to_s.should == info + buffer.null?.should == true + end + + it "transfers mapped memory to a new buffer, nullifying the original" do + buffer = IO::Buffer.new(4, IO::Buffer::MAPPED) + info = buffer.to_s + @buffer = buffer.transfer + @buffer.to_s.should == info + buffer.null?.should == true + end + end + + context "with a file-backed buffer created with .map" do + it "transfers mapped memory to a new buffer, nullifying the original" do + File.open(__FILE__, "r") do |file| + buffer = IO::Buffer.map(file, nil, 0, IO::Buffer::READONLY) + info = buffer.to_s + @buffer = buffer.transfer + @buffer.to_s.should == info + buffer.null?.should == true + end + end + end + + context "with a String-backed buffer created with .for" do + context "without a block" do + it "transfers memory to a new buffer, nullifying the original" do + buffer = IO::Buffer.for("test") + info = buffer.to_s + @buffer = buffer.transfer + @buffer.to_s.should == info + buffer.null?.should == true + end + end + + context "with a block" do + it "transfers memory to a new buffer, breaking the transaction by nullifying the original" do + IO::Buffer.for(+"test") do |buffer| + info = buffer.to_s + @buffer = buffer.transfer + @buffer.to_s.should == info + buffer.null?.should == true + end + @buffer.null?.should == false + end + end + end + + context "with a String-backed buffer created with .string" do + it "transfers memory to a new buffer, breaking the transaction by nullifying the original" do + IO::Buffer.string(4) do |buffer| + info = buffer.to_s + @buffer = buffer.transfer + @buffer.to_s.should == info + buffer.null?.should == true + end + @buffer.null?.should == false + end + end + + it "allows multiple transfers" do + buffer_1 = IO::Buffer.new(4) + buffer_2 = buffer_1.transfer + @buffer = buffer_2.transfer + buffer_1.null?.should == true + buffer_2.null?.should == true + @buffer.null?.should == false + end + + it "is disallowed while locked, raising IO::Buffer::LockedError" do + @buffer = IO::Buffer.new(4) + @buffer.locked do + -> { @buffer.transfer }.should.raise(IO::Buffer::LockedError, "Cannot transfer ownership of locked buffer!") + end + end + + context "with a slice of a buffer" do + it "transfers source to a new slice, not touching the buffer" do + @buffer = IO::Buffer.new(4) + slice = @buffer.slice(0, 2) + @buffer.set_string("test") + + new_slice = slice.transfer + slice.null?.should == true + new_slice.null?.should == false + @buffer.null?.should == false + + new_slice.set_string("ea") + @buffer.get_string.should == "east" + end + + it "nullifies buffer, invalidating the slice" do + buffer = IO::Buffer.new(4) + slice = buffer.slice(0, 2) + @buffer = buffer.transfer + + slice.null?.should == false + slice.valid?.should == false + -> { slice.get_string }.should.raise(IO::Buffer::InvalidatedError, "Buffer has been invalidated!") + end + end +end diff --git a/spec/ruby/core/io/buffer/valid_spec.rb b/spec/ruby/core/io/buffer/valid_spec.rb new file mode 100644 index 0000000000..0a40172869 --- /dev/null +++ b/spec/ruby/core/io/buffer/valid_spec.rb @@ -0,0 +1,110 @@ +require_relative '../../../spec_helper' + +describe "IO::Buffer#valid?" do + after :each do + @buffer&.free + @buffer = nil + end + + # Non-slices are always valid + context "with a non-slice buffer" do + it "is true for a regular buffer" do + @buffer = IO::Buffer.new(4) + @buffer.valid?.should == true + end + + it "is true for a 0-size buffer" do + @buffer = IO::Buffer.new(0) + @buffer.valid?.should == true + end + + it "is true for a freed buffer" do + @buffer = IO::Buffer.new(4) + @buffer.free + @buffer.valid?.should == true + end + + it "is true for a freed file-backed buffer" do + File.open(__FILE__, "r") do |file| + @buffer = IO::Buffer.map(file, nil, 0, IO::Buffer::READONLY) + @buffer.valid?.should == true + @buffer.free + @buffer.valid?.should == true + end + end + + it "is true for a freed string-backed buffer" do + @buffer = IO::Buffer.for("hello") + @buffer.valid?.should == true + @buffer.free + @buffer.valid?.should == true + end + end + + # "A buffer becomes invalid if it is a slice of another buffer (or string) + # which has been freed or re-allocated at a different address." + context "with a slice" do + it "is true for a slice of a live buffer" do + @buffer = IO::Buffer.new(4) + slice = @buffer.slice(0, 2) + slice.valid?.should == true + end + + context "when buffer is resized" do + it "is false when slice becomes outside the buffer" do + @buffer = IO::Buffer.new(4) + slice = @buffer.slice(2, 2) + @buffer.resize(3) + slice.valid?.should == false + end + + platform_is_not :linux do + # This test does not cause a copy-resize on Linux. + # `#resize` MAY cause the buffer to move, but there is no guarantee. + it "is false when buffer is copied on resize" do + @buffer = IO::Buffer.new(4, IO::Buffer::MAPPED) + slice = @buffer.slice(0, 2) + @buffer.resize(8) + slice.valid?.should == false + end + end + end + + it "is false for a slice of a transferred buffer" do + buffer = IO::Buffer.new(4) + slice = buffer.slice(0, 2) + @buffer = buffer.transfer + slice.valid?.should == false + end + + it "is false for a slice of a freed buffer" do + @buffer = IO::Buffer.new(4) + slice = @buffer.slice(0, 2) + @buffer.free + slice.valid?.should == false + end + + it "is false for a slice of a freed file-backed buffer" do + File.open(__FILE__, "r") do |file| + @buffer = IO::Buffer.map(file, nil, 0, IO::Buffer::READONLY) + slice = @buffer.slice(0, 2) + slice.valid?.should == true + @buffer.free + slice.valid?.should == false + end + end + + it "is true for a slice of a freed string-backed buffer while string is alive" do + @buffer = IO::Buffer.for("alive") + slice = @buffer.slice(0, 2) + slice.valid?.should == true + @buffer.free + slice.valid?.should == true + end + + # There probably should be a test with a garbage-collected string, + # but it's not clear how to force that. + + it "needs to be reviewed for spec completeness" + end +end diff --git a/spec/ruby/core/io/buffer/xor_spec.rb b/spec/ruby/core/io/buffer/xor_spec.rb new file mode 100644 index 0000000000..9287611f7f --- /dev/null +++ b/spec/ruby/core/io/buffer/xor_spec.rb @@ -0,0 +1,62 @@ +require_relative '../../../spec_helper' + +describe :io_buffer_xor, shared: true do + it "applies the argument buffer as an XOR bit mask across the whole buffer" do + IO::Buffer.for(+"12345") do |buffer| + IO::Buffer.for(+"\xF8\x8F") do |mask| + result = buffer.send(@method, mask) + result.get_string.should == "\xC9\xBD\xCB\xBB\xCD".b + result.free + end + end + end + + it "ignores extra parts of mask if it is longer than source buffer" do + IO::Buffer.for(+"12345") do |buffer| + IO::Buffer.for(+"\xF8\x8F\x00\x00\x00\xFF\xFF") do |mask| + result = buffer.send(@method, mask) + result.get_string.should == "\xC9\xBD345".b + result.free + end + end + end + + it "raises TypeError if mask is not an IO::Buffer" do + IO::Buffer.for(+"12345") do |buffer| + -> { buffer.send(@method, "\xF8\x8F") }.should.raise(TypeError, "wrong argument type String (expected IO::Buffer)") + -> { buffer.send(@method, 0xF8) }.should.raise(TypeError, "wrong argument type Integer (expected IO::Buffer)") + -> { buffer.send(@method, nil) }.should.raise(TypeError, "wrong argument type nil (expected IO::Buffer)") + end + end +end + +describe "IO::Buffer#^" do + it_behaves_like :io_buffer_xor, :^ + + it "creates a new internal buffer of the same size" do + IO::Buffer.for(+"12345") do |buffer| + IO::Buffer.for(+"\xF8\x8F") do |mask| + result = buffer ^ mask + result.should_not.equal? buffer + result.should.internal? + result.size.should == buffer.size + result.free + buffer.get_string.should == "12345".b + end + end + end +end + +describe "IO::Buffer#xor!" do + it_behaves_like :io_buffer_xor, :xor! + + it "modifies the buffer in place" do + IO::Buffer.for(+"12345") do |buffer| + IO::Buffer.for(+"\xF8\x8F") do |mask| + result = buffer.xor!(mask) + result.should.equal? buffer + result.should.external? + end + end + end +end diff --git a/spec/ruby/core/io/close_on_exec_spec.rb b/spec/ruby/core/io/close_on_exec_spec.rb index 4e89e08d61..28cdb967b9 100644 --- a/spec/ruby/core/io/close_on_exec_spec.rb +++ b/spec/ruby/core/io/close_on_exec_spec.rb @@ -42,7 +42,7 @@ describe "IO#close_on_exec=" do it "raises IOError if called on a closed IO" do @io.close - -> { @io.close_on_exec = true }.should raise_error(IOError) + -> { @io.close_on_exec = true }.should.raise(IOError) end end end @@ -70,7 +70,7 @@ describe "IO#close_on_exec?" do it "raises IOError if called on a closed IO" do @io.close - -> { @io.close_on_exec? }.should raise_error(IOError) + -> { @io.close_on_exec? }.should.raise(IOError) end end end diff --git a/spec/ruby/core/io/close_read_spec.rb b/spec/ruby/core/io/close_read_spec.rb index e700e85bd9..c505289d72 100644 --- a/spec/ruby/core/io/close_read_spec.rb +++ b/spec/ruby/core/io/close_read_spec.rb @@ -17,26 +17,26 @@ describe "IO#close_read" do it "closes the read end of a duplex I/O stream" do @io.close_read - -> { @io.read }.should raise_error(IOError) + -> { @io.read }.should.raise(IOError) end it "does nothing on subsequent invocations" do @io.close_read - @io.close_read.should be_nil + @io.close_read.should == nil end it "allows subsequent invocation of close" do @io.close_read - -> { @io.close }.should_not raise_error + -> { @io.close }.should_not.raise end it "raises an IOError if the stream is writable and not duplexed" do io = File.open @path, 'w' begin - -> { io.close_read }.should raise_error(IOError) + -> { io.close_read }.should.raise(IOError) ensure io.close unless io.closed? end @@ -56,6 +56,6 @@ describe "IO#close_read" do it "does nothing on closed stream" do @io.close - @io.close_read.should be_nil + @io.close_read.should == nil end end diff --git a/spec/ruby/core/io/close_spec.rb b/spec/ruby/core/io/close_spec.rb index 3a44cc8b17..afd84ba101 100644 --- a/spec/ruby/core/io/close_spec.rb +++ b/spec/ruby/core/io/close_spec.rb @@ -23,25 +23,25 @@ describe "IO#close" do it "raises an IOError reading from a closed IO" do @io.close - -> { @io.read }.should raise_error(IOError) + -> { @io.read }.should.raise(IOError) end it "raises an IOError writing to a closed IO" do @io.close - -> { @io.write "data" }.should raise_error(IOError) + -> { @io.write "data" }.should.raise(IOError) end it 'does not close the stream if autoclose is false' do other_io = IO.new(@io.fileno) other_io.autoclose = false other_io.close - -> { @io.write "data" }.should_not raise_error(IOError) + -> { @io.write "data" }.should_not.raise(IOError) end it "does nothing if already closed" do @io.close - @io.close.should be_nil + @io.close.should == nil end it "does not call the #flush method but flushes the stream internally" do @@ -80,7 +80,7 @@ describe "IO#close" do matching_exception&.tap {|ex| raise ex} end - end.should raise_error(IOError, IOSpecs::THREAD_CLOSE_ERROR_MESSAGE) + end.should.raise(IOError, IOSpecs::THREAD_CLOSE_ERROR_MESSAGE) end end @@ -93,7 +93,7 @@ describe "IO#close on an IO.popen stream" do io.close - -> { io.pid }.should raise_error(IOError) + -> { io.pid }.should.raise(IOError) end it "sets $?" do diff --git a/spec/ruby/core/io/close_write_spec.rb b/spec/ruby/core/io/close_write_spec.rb index 70610a3e9d..60b41505c3 100644 --- a/spec/ruby/core/io/close_write_spec.rb +++ b/spec/ruby/core/io/close_write_spec.rb @@ -16,26 +16,26 @@ describe "IO#close_write" do it "closes the write end of a duplex I/O stream" do @io.close_write - -> { @io.write "attempt to write" }.should raise_error(IOError) + -> { @io.write "attempt to write" }.should.raise(IOError) end it "does nothing on subsequent invocations" do @io.close_write - @io.close_write.should be_nil + @io.close_write.should == nil end it "allows subsequent invocation of close" do @io.close_write - -> { @io.close }.should_not raise_error + -> { @io.close }.should_not.raise end it "raises an IOError if the stream is readable and not duplexed" do io = File.open @path, 'w+' begin - -> { io.close_write }.should raise_error(IOError) + -> { io.close_write }.should.raise(IOError) ensure io.close unless io.closed? end @@ -63,6 +63,6 @@ describe "IO#close_write" do it "does nothing on closed stream" do @io.close - @io.close_write.should be_nil + @io.close_write.should == nil end end diff --git a/spec/ruby/core/io/closed_spec.rb b/spec/ruby/core/io/closed_spec.rb index 7316546a0d..1f10858e28 100644 --- a/spec/ruby/core/io/closed_spec.rb +++ b/spec/ruby/core/io/closed_spec.rb @@ -11,10 +11,10 @@ describe "IO#closed?" do end it "returns true on closed stream" do - IOSpecs.closed_io.closed?.should be_true + IOSpecs.closed_io.closed?.should == true end it "returns false on open stream" do - @io.closed?.should be_false + @io.closed?.should == false end end diff --git a/spec/ruby/core/io/copy_stream_spec.rb b/spec/ruby/core/io/copy_stream_spec.rb index ffa2ea992c..31383f9b0f 100644 --- a/spec/ruby/core/io/copy_stream_spec.rb +++ b/spec/ruby/core/io/copy_stream_spec.rb @@ -31,7 +31,7 @@ describe :io_copy_stream_to_file, shared: true do obj = mock("io_copy_stream_to") obj.should_receive(:to_path).and_return(1) - -> { IO.copy_stream(@object.from, obj) }.should raise_error(TypeError) + -> { IO.copy_stream(@object.from, obj) }.should.raise(TypeError) end end @@ -71,7 +71,7 @@ describe :io_copy_stream_to_io, shared: true do it "raises an IOError if the destination IO is not open for writing" do to_io = new_io __FILE__, "r" begin - -> { IO.copy_stream @object.from, to_io }.should raise_error(IOError) + -> { IO.copy_stream @object.from, to_io }.should.raise(IOError) ensure to_io.close end @@ -79,7 +79,7 @@ describe :io_copy_stream_to_io, shared: true do it "does not close the destination IO" do IO.copy_stream(@object.from, @to_io) - @to_io.closed?.should be_false + @to_io.closed?.should == false end it "copies only length bytes when specified" do @@ -129,12 +129,12 @@ describe "IO.copy_stream" do it "raises an IOError if the source IO is not open for reading" do @from_io.close @from_io = new_io @from_bigfile, "a" - -> { IO.copy_stream @from_io, @to_name }.should raise_error(IOError) + -> { IO.copy_stream @from_io, @to_name }.should.raise(IOError) end it "does not close the source IO" do IO.copy_stream(@from_io, @to_name) - @from_io.closed?.should be_false + @from_io.closed?.should == false end platform_is_not :windows do @@ -206,7 +206,7 @@ describe "IO.copy_stream" do obj = mock("io_copy_stream_from") obj.should_receive(:to_path).and_return(1) - -> { IO.copy_stream(obj, @to_name) }.should raise_error(TypeError) + -> { IO.copy_stream(obj, @to_name) }.should.raise(TypeError) end describe "to a file name" do @@ -240,12 +240,12 @@ describe "IO.copy_stream" do it "does not close the source IO" do IO.copy_stream(@from_io, @to_name) - @from_io.closed?.should be_false + @from_io.closed?.should == false end platform_is_not :windows do it "raises an error when an offset is specified" do - -> { IO.copy_stream(@from_io, @to_name, 8, 4) }.should raise_error(Errno::ESPIPE) + -> { IO.copy_stream(@from_io, @to_name, 8, 4) }.should.raise(Errno::ESPIPE) end end @@ -300,6 +300,14 @@ describe "IO.copy_stream" do @io.should_not_receive(:pos) IO.copy_stream(@io, @to_name) end + + it "does not call #read on the source or #write on the destination if zero length is given" do + from = mock("io_copy_stream_to_object_zero_length_read") + to = mock("io_copy_stream_to_object_zero_length_write") + from.should_not_receive(:read) + to.should_not_receive(:write) + IO.copy_stream(from, to, 0) + end end describe "with a destination that does partial reads" do diff --git a/spec/ruby/core/io/dup_spec.rb b/spec/ruby/core/io/dup_spec.rb index 564e007438..db4e9fe641 100644 --- a/spec/ruby/core/io/dup_spec.rb +++ b/spec/ruby/core/io/dup_spec.rb @@ -49,7 +49,7 @@ describe "IO#dup" do it "allows closing the new IO without affecting the original" do @i.close - -> { @f.gets }.should_not raise_error(Exception) + -> { @f.gets }.should_not.raise(Exception) @i.should.closed? @f.should_not.closed? @@ -57,14 +57,14 @@ describe "IO#dup" do it "allows closing the original IO without affecting the new one" do @f.close - -> { @i.gets }.should_not raise_error(Exception) + -> { @i.gets }.should_not.raise(Exception) @i.should_not.closed? @f.should.closed? end it "raises IOError on closed stream" do - -> { IOSpecs.closed_io.dup }.should raise_error(IOError) + -> { IOSpecs.closed_io.dup }.should.raise(IOError) end it "always sets the close-on-exec flag for the new IO object" do diff --git a/spec/ruby/core/io/each_byte_spec.rb b/spec/ruby/core/io/each_byte_spec.rb index ea618e8c0c..fe299f0fba 100644 --- a/spec/ruby/core/io/each_byte_spec.rb +++ b/spec/ruby/core/io/each_byte_spec.rb @@ -12,7 +12,7 @@ describe "IO#each_byte" do end it "raises IOError on closed stream" do - -> { IOSpecs.closed_io.each_byte {} }.should raise_error(IOError) + -> { IOSpecs.closed_io.each_byte {} }.should.raise(IOError) end it "yields each byte" do @@ -28,7 +28,7 @@ describe "IO#each_byte" do describe "when no block is given" do it "returns an Enumerator" do enum = @io.each_byte - enum.should be_an_instance_of(Enumerator) + enum.should.instance_of?(Enumerator) enum.first(5).should == [86, 111, 105, 99, 105] end @@ -52,6 +52,6 @@ describe "IO#each_byte" do end it "returns self on an empty stream" do - @io.each_byte { |b| }.should equal(@io) + @io.each_byte { |b| }.should.equal?(@io) end end diff --git a/spec/ruby/core/io/each_codepoint_spec.rb b/spec/ruby/core/io/each_codepoint_spec.rb index 07a4037c8a..26cc87fc0e 100644 --- a/spec/ruby/core/io/each_codepoint_spec.rb +++ b/spec/ruby/core/io/each_codepoint_spec.rb @@ -24,7 +24,7 @@ describe "IO#each_codepoint" do end it "returns self" do - @io.each_codepoint { |l| l }.should equal(@io) + @io.each_codepoint { |l| l }.should.equal?(@io) end end @@ -38,6 +38,6 @@ describe "IO#each_codepoint" do end it "raises an exception at incomplete character before EOF when conversion takes place" do - -> { @io.each_codepoint {} }.should raise_error(ArgumentError) + -> { @io.each_codepoint {} }.should.raise(ArgumentError) end end diff --git a/spec/ruby/core/io/eof_spec.rb b/spec/ruby/core/io/eof_spec.rb index b4850df437..c8955abde0 100644 --- a/spec/ruby/core/io/eof_spec.rb +++ b/spec/ruby/core/io/eof_spec.rb @@ -18,7 +18,7 @@ describe "IO#eof?" do it "raises IOError on stream not opened for reading" do -> do File.open(@name, "w") { |f| f.eof? } - end.should raise_error(IOError) + end.should.raise(IOError) end end @@ -67,12 +67,12 @@ describe "IO#eof?" do end it "raises IOError on closed stream" do - -> { IOSpecs.closed_io.eof? }.should raise_error(IOError) + -> { IOSpecs.closed_io.eof? }.should.raise(IOError) end it "raises IOError on stream closed for reading by close_read" do @io.close_read - -> { @io.eof? }.should raise_error(IOError) + -> { @io.eof? }.should.raise(IOError) end it "returns true on one-byte stream after single-byte read" do diff --git a/spec/ruby/core/io/external_encoding_spec.rb b/spec/ruby/core/io/external_encoding_spec.rb index 7765c6c0f5..72d246cc2b 100644 --- a/spec/ruby/core/io/external_encoding_spec.rb +++ b/spec/ruby/core/io/external_encoding_spec.rb @@ -10,19 +10,19 @@ describe :io_external_encoding_write, shared: true do it "returns nil" do @io = new_io @name, @object Encoding.default_external = Encoding::IBM437 - @io.external_encoding.should be_nil + @io.external_encoding.should == nil end it "returns the external encoding specified when the instance was created" do @io = new_io @name, "#{@object}:ibm866" Encoding.default_external = Encoding::IBM437 - @io.external_encoding.should equal(Encoding::IBM866) + @io.external_encoding.should.equal?(Encoding::IBM866) end it "returns the encoding set by #set_encoding" do @io = new_io @name, "#{@object}:ibm866" @io.set_encoding Encoding::EUC_JP, nil - @io.external_encoding.should equal(Encoding::EUC_JP) + @io.external_encoding.should.equal?(Encoding::EUC_JP) end end @@ -35,19 +35,19 @@ describe :io_external_encoding_write, shared: true do it "returns the value of Encoding.default_external when the instance was created" do @io = new_io @name, @object Encoding.default_external = Encoding::UTF_8 - @io.external_encoding.should equal(Encoding::IBM437) + @io.external_encoding.should.equal?(Encoding::IBM437) end it "returns the external encoding specified when the instance was created" do @io = new_io @name, "#{@object}:ibm866" Encoding.default_external = Encoding::IBM437 - @io.external_encoding.should equal(Encoding::IBM866) + @io.external_encoding.should.equal?(Encoding::IBM866) end it "returns the encoding set by #set_encoding" do @io = new_io @name, "#{@object}:ibm866" @io.set_encoding Encoding::EUC_JP, nil - @io.external_encoding.should equal(Encoding::EUC_JP) + @io.external_encoding.should.equal?(Encoding::EUC_JP) end end @@ -60,19 +60,19 @@ describe :io_external_encoding_write, shared: true do it "returns the value of Encoding.default_external when the instance was created" do @io = new_io @name, @object Encoding.default_external = Encoding::UTF_8 - @io.external_encoding.should equal(Encoding::IBM866) + @io.external_encoding.should.equal?(Encoding::IBM866) end it "returns the external encoding specified when the instance was created" do @io = new_io @name, "#{@object}:ibm866" Encoding.default_external = Encoding::IBM437 - @io.external_encoding.should equal(Encoding::IBM866) + @io.external_encoding.should.equal?(Encoding::IBM866) end it "returns the encoding set by #set_encoding" do @io = new_io @name, "#{@object}:ibm866" @io.set_encoding Encoding::EUC_JP, nil - @io.external_encoding.should equal(Encoding::EUC_JP) + @io.external_encoding.should.equal?(Encoding::EUC_JP) end end end @@ -97,7 +97,7 @@ describe "IO#external_encoding" do it "can be retrieved from a closed stream" do io = IOSpecs.io_fixture("lines.txt", "r") io.close - io.external_encoding.should equal(Encoding.default_external) + io.external_encoding.should.equal?(Encoding.default_external) end describe "with 'r' mode" do @@ -109,25 +109,25 @@ describe "IO#external_encoding" do it "returns Encoding.default_external if the external encoding is not set" do @io = new_io @name, "r" - @io.external_encoding.should equal(Encoding::IBM866) + @io.external_encoding.should.equal?(Encoding::IBM866) end it "returns Encoding.default_external when that encoding is changed after the instance is created" do @io = new_io @name, "r" Encoding.default_external = Encoding::IBM437 - @io.external_encoding.should equal(Encoding::IBM437) + @io.external_encoding.should.equal?(Encoding::IBM437) end it "returns the external encoding specified when the instance was created" do @io = new_io @name, "r:utf-8" Encoding.default_external = Encoding::IBM437 - @io.external_encoding.should equal(Encoding::UTF_8) + @io.external_encoding.should.equal?(Encoding::UTF_8) end it "returns the encoding set by #set_encoding" do @io = new_io @name, "r:utf-8" @io.set_encoding Encoding::EUC_JP, nil - @io.external_encoding.should equal(Encoding::EUC_JP) + @io.external_encoding.should.equal?(Encoding::EUC_JP) end end @@ -140,19 +140,19 @@ describe "IO#external_encoding" do it "returns the value of Encoding.default_external when the instance was created" do @io = new_io @name, "r" Encoding.default_external = Encoding::IBM437 - @io.external_encoding.should equal(Encoding::IBM866) + @io.external_encoding.should.equal?(Encoding::IBM866) end it "returns the external encoding specified when the instance was created" do @io = new_io @name, "r:utf-8" Encoding.default_external = Encoding::IBM437 - @io.external_encoding.should equal(Encoding::UTF_8) + @io.external_encoding.should.equal?(Encoding::UTF_8) end it "returns the encoding set by #set_encoding" do @io = new_io @name, "r:utf-8" @io.set_encoding Encoding::EUC_JP, nil - @io.external_encoding.should equal(Encoding::EUC_JP) + @io.external_encoding.should.equal?(Encoding::EUC_JP) end end @@ -166,13 +166,13 @@ describe "IO#external_encoding" do it "returns the external encoding specified when the instance was created" do @io = new_io @name, "r:utf-8" Encoding.default_external = Encoding::IBM437 - @io.external_encoding.should equal(Encoding::UTF_8) + @io.external_encoding.should.equal?(Encoding::UTF_8) end it "returns the encoding set by #set_encoding" do @io = new_io @name, "r:utf-8" @io.set_encoding Encoding::EUC_JP, nil - @io.external_encoding.should equal(Encoding::EUC_JP) + @io.external_encoding.should.equal?(Encoding::EUC_JP) end end end @@ -180,12 +180,12 @@ describe "IO#external_encoding" do describe "with 'rb' mode" do it "returns Encoding::BINARY" do @io = new_io @name, "rb" - @io.external_encoding.should equal(Encoding::BINARY) + @io.external_encoding.should.equal?(Encoding::BINARY) end it "returns the external encoding specified by the mode argument" do @io = new_io @name, "rb:ibm437" - @io.external_encoding.should equal(Encoding::IBM437) + @io.external_encoding.should.equal?(Encoding::IBM437) end end @@ -200,12 +200,12 @@ describe "IO#external_encoding" do describe "with 'wb' mode" do it "returns Encoding::BINARY" do @io = new_io @name, "wb" - @io.external_encoding.should equal(Encoding::BINARY) + @io.external_encoding.should.equal?(Encoding::BINARY) end it "returns the external encoding specified by the mode argument" do @io = new_io @name, "wb:ibm437" - @io.external_encoding.should equal(Encoding::IBM437) + @io.external_encoding.should.equal?(Encoding::IBM437) end end diff --git a/spec/ruby/core/io/fcntl_spec.rb b/spec/ruby/core/io/fcntl_spec.rb index 30b4876fe3..be6d06c672 100644 --- a/spec/ruby/core/io/fcntl_spec.rb +++ b/spec/ruby/core/io/fcntl_spec.rb @@ -3,6 +3,6 @@ require_relative 'fixtures/classes' describe "IO#fcntl" do it "raises IOError on closed stream" do - -> { IOSpecs.closed_io.fcntl(5, 5) }.should raise_error(IOError) + -> { IOSpecs.closed_io.fcntl(5, 5) }.should.raise(IOError) end end diff --git a/spec/ruby/core/io/fileno_spec.rb b/spec/ruby/core/io/fileno_spec.rb index 647609bf42..22fd68d166 100644 --- a/spec/ruby/core/io/fileno_spec.rb +++ b/spec/ruby/core/io/fileno_spec.rb @@ -7,6 +7,6 @@ describe "IO#fileno" do end it "raises IOError on closed stream" do - -> { IOSpecs.closed_io.fileno }.should raise_error(IOError) + -> { IOSpecs.closed_io.fileno }.should.raise(IOError) end end diff --git a/spec/ruby/core/io/flush_spec.rb b/spec/ruby/core/io/flush_spec.rb index f7d5ba77fc..4c3e8d12af 100644 --- a/spec/ruby/core/io/flush_spec.rb +++ b/spec/ruby/core/io/flush_spec.rb @@ -3,7 +3,7 @@ require_relative 'fixtures/classes' describe "IO#flush" do it "raises IOError on closed stream" do - -> { IOSpecs.closed_io.flush }.should raise_error(IOError) + -> { IOSpecs.closed_io.flush }.should.raise(IOError) end describe "on a pipe" do @@ -29,8 +29,8 @@ describe "IO#flush" do @w.write "foo" @r.close - -> { @w.flush }.should raise_error(Errno::EPIPE, /Broken pipe/) - -> { @w.close }.should raise_error(Errno::EPIPE, /Broken pipe/) + -> { @w.flush }.should.raise(Errno::EPIPE, /Broken pipe/) + -> { @w.close }.should.raise(Errno::EPIPE, /Broken pipe/) end end end diff --git a/spec/ruby/core/io/foreach_spec.rb b/spec/ruby/core/io/foreach_spec.rb index c361d27879..015988f9fb 100644 --- a/spec/ruby/core/io/foreach_spec.rb +++ b/spec/ruby/core/io/foreach_spec.rb @@ -14,45 +14,45 @@ describe "IO.foreach" do IO.foreach(@name) { $..should == @count += 1 } end - describe "when the filename starts with |" do - it "gets data from the standard out of the subprocess" do - cmd = "|sh -c 'echo hello;echo line2'" - platform_is :windows do - cmd = "|cmd.exe /C echo hello&echo line2" - end + ruby_version_is ""..."4.0" do + describe "when the filename starts with |" do + it "gets data from the standard out of the subprocess" do + cmd = "|sh -c 'echo hello;echo line2'" + platform_is :windows do + cmd = "|cmd.exe /C echo hello&echo line2" + end - suppress_warning do # https://bugs.ruby-lang.org/issues/19630 - IO.foreach(cmd) { |l| ScratchPad << l } + suppress_warning do # https://bugs.ruby-lang.org/issues/19630 + IO.foreach(cmd) { |l| ScratchPad << l } + end + ScratchPad.recorded.should == ["hello\n", "line2\n"] end - ScratchPad.recorded.should == ["hello\n", "line2\n"] - end - platform_is_not :windows do - it "gets data from a fork when passed -" do - parent_pid = $$ + platform_is_not :windows do + it "gets data from a fork when passed -" do + parent_pid = $$ - suppress_warning do # https://bugs.ruby-lang.org/issues/19630 - IO.foreach("|-") { |l| ScratchPad << l } - end + suppress_warning do # https://bugs.ruby-lang.org/issues/19630 + IO.foreach("|-") { |l| ScratchPad << l } + end - if $$ == parent_pid - ScratchPad.recorded.should == ["hello\n", "from a fork\n"] - else # child - puts "hello" - puts "from a fork" - exit! + if $$ == parent_pid + ScratchPad.recorded.should == ["hello\n", "from a fork\n"] + else # child + puts "hello" + puts "from a fork" + exit! + end end end end - ruby_version_is "3.3" do - # https://bugs.ruby-lang.org/issues/19630 - it "warns about deprecation given a path with a pipe" do - cmd = "|echo ok" - -> { - IO.foreach(cmd).to_a - }.should complain(/IO process creation with a leading '\|'/) - end + # https://bugs.ruby-lang.org/issues/19630 + it "warns about deprecation given a path with a pipe" do + cmd = "|echo ok" + -> { + IO.foreach(cmd).to_a + }.should complain(/IO process creation with a leading '\|'/) end end end @@ -73,12 +73,12 @@ describe "IO.foreach" do it "sets $_ to nil" do $_ = "test" IO.foreach(@name) { } - $_.should be_nil + $_.should == nil end describe "when no block is given" do it "returns an Enumerator" do - IO.foreach(@name).should be_an_instance_of(Enumerator) + IO.foreach(@name).should.instance_of?(Enumerator) IO.foreach(@name).to_a.should == IOSpecs.lines end diff --git a/spec/ruby/core/io/fsync_spec.rb b/spec/ruby/core/io/fsync_spec.rb index 6e6123de94..0317cbc805 100644 --- a/spec/ruby/core/io/fsync_spec.rb +++ b/spec/ruby/core/io/fsync_spec.rb @@ -12,7 +12,7 @@ describe "IO#fsync" do end it "raises an IOError on closed stream" do - -> { IOSpecs.closed_io.fsync }.should raise_error(IOError) + -> { IOSpecs.closed_io.fsync }.should.raise(IOError) end it "writes the buffered data to permanent storage" do diff --git a/spec/ruby/core/io/getbyte_spec.rb b/spec/ruby/core/io/getbyte_spec.rb index b4351160e6..668d81519c 100644 --- a/spec/ruby/core/io/getbyte_spec.rb +++ b/spec/ruby/core/io/getbyte_spec.rb @@ -23,7 +23,7 @@ describe "IO#getbyte" do end it "raises an IOError on closed stream" do - -> { IOSpecs.closed_io.getbyte }.should raise_error(IOError) + -> { IOSpecs.closed_io.getbyte }.should.raise(IOError) end end @@ -53,6 +53,6 @@ describe "IO#getbyte" do end it "raises an IOError if the stream is not readable" do - -> { @io.getbyte }.should raise_error(IOError) + -> { @io.getbyte }.should.raise(IOError) end end diff --git a/spec/ruby/core/io/getc_spec.rb b/spec/ruby/core/io/getc_spec.rb index 3949b5cb28..3be86203c0 100644 --- a/spec/ruby/core/io/getc_spec.rb +++ b/spec/ruby/core/io/getc_spec.rb @@ -19,11 +19,11 @@ describe "IO#getc" do it "returns nil when invoked at the end of the stream" do @io.read - @io.getc.should be_nil + @io.getc.should == nil end it "raises IOError on closed stream" do - -> { IOSpecs.closed_io.getc }.should raise_error(IOError) + -> { IOSpecs.closed_io.getc }.should.raise(IOError) end end @@ -37,6 +37,6 @@ describe "IO#getc" do end it "returns nil on empty stream" do - @io.getc.should be_nil + @io.getc.should == nil end end diff --git a/spec/ruby/core/io/gets_spec.rb b/spec/ruby/core/io/gets_spec.rb index ca64bf860e..ce3ee73b94 100644 --- a/spec/ruby/core/io/gets_spec.rb +++ b/spec/ruby/core/io/gets_spec.rb @@ -27,7 +27,7 @@ describe "IO#gets" do it "sets $_ to nil after the last line has been read" do while @io.gets end - $_.should be_nil + $_.should == nil end it "returns nil if called at the end of the stream" do @@ -36,7 +36,7 @@ describe "IO#gets" do end it "raises IOError on closed stream" do - -> { IOSpecs.closed_io.gets }.should raise_error(IOError) + -> { IOSpecs.closed_io.gets }.should.raise(IOError) end describe "with no separator" do @@ -156,11 +156,11 @@ describe "IO#gets" do end it "raises exception when options passed as Hash" do - -> { @io.gets({ chomp: true }) }.should raise_error(TypeError) + -> { @io.gets({ chomp: true }) }.should.raise(TypeError) -> { @io.gets("\n", 1, { chomp: true }) - }.should raise_error(ArgumentError, "wrong number of arguments (given 3, expected 0..2)") + }.should.raise(ArgumentError, "wrong number of arguments (given 3, expected 0..2)") end end end @@ -175,11 +175,11 @@ describe "IO#gets" do end it "raises an IOError if the stream is opened for append only" do - -> { File.open(@name, "a:utf-8") { |f| f.gets } }.should raise_error(IOError) + -> { File.open(@name, "a:utf-8") { |f| f.gets } }.should.raise(IOError) end it "raises an IOError if the stream is opened for writing only" do - -> { File.open(@name, "w:utf-8") { |f| f.gets } }.should raise_error(IOError) + -> { File.open(@name, "w:utf-8") { |f| f.gets } }.should.raise(IOError) end end @@ -251,7 +251,7 @@ describe "IO#gets" do end it "does not accept limit that doesn't fit in a C off_t" do - -> { @io.gets(2**128) }.should raise_error(RangeError) + -> { @io.gets(2**128) }.should.raise(RangeError) end end @@ -338,23 +338,11 @@ describe "IO#gets" do @io.gets.encoding.should == Encoding::BINARY end - ruby_version_is ''...'3.3' do - it "transcodes to internal encoding if the IO object's external encoding is BINARY" do - Encoding.default_external = Encoding::BINARY - Encoding.default_internal = Encoding::UTF_8 - @io = new_io @name, 'r' - @io.set_encoding Encoding::BINARY, Encoding::UTF_8 - @io.gets.encoding.should == Encoding::UTF_8 - end - end - - ruby_version_is '3.3' do - it "ignores the internal encoding if the IO object's external encoding is BINARY" do - Encoding.default_external = Encoding::BINARY - Encoding.default_internal = Encoding::UTF_8 - @io = new_io @name, 'r' - @io.set_encoding Encoding::BINARY, Encoding::UTF_8 - @io.gets.encoding.should == Encoding::BINARY - end + it "ignores the internal encoding if the IO object's external encoding is BINARY" do + Encoding.default_external = Encoding::BINARY + Encoding.default_internal = Encoding::UTF_8 + @io = new_io @name, 'r' + @io.set_encoding Encoding::BINARY, Encoding::UTF_8 + @io.gets.encoding.should == Encoding::BINARY end end diff --git a/spec/ruby/core/io/initialize_spec.rb b/spec/ruby/core/io/initialize_spec.rb index 026252a13d..3425e5ac37 100644 --- a/spec/ruby/core/io/initialize_spec.rb +++ b/spec/ruby/core/io/initialize_spec.rb @@ -35,26 +35,26 @@ describe "IO#initialize" do -> { @io.send(:initialize, fd, "w", {flags: File::CREAT}) - }.should raise_error(ArgumentError, "wrong number of arguments (given 3, expected 1..2)") + }.should.raise(ArgumentError, "wrong number of arguments (given 3, expected 1..2)") end it "raises a TypeError when passed an IO" do - -> { @io.send :initialize, STDOUT, 'w' }.should raise_error(TypeError) + -> { @io.send :initialize, STDOUT, 'w' }.should.raise(TypeError) end it "raises a TypeError when passed nil" do - -> { @io.send :initialize, nil, 'w' }.should raise_error(TypeError) + -> { @io.send :initialize, nil, 'w' }.should.raise(TypeError) end it "raises a TypeError when passed a String" do - -> { @io.send :initialize, "4", 'w' }.should raise_error(TypeError) + -> { @io.send :initialize, "4", 'w' }.should.raise(TypeError) end it "raises IOError on closed stream" do - -> { @io.send :initialize, IOSpecs.closed_io.fileno }.should raise_error(IOError) + -> { @io.send :initialize, IOSpecs.closed_io.fileno }.should.raise(IOError) end it "raises an Errno::EBADF when given an invalid file descriptor" do - -> { @io.send :initialize, -1, 'w' }.should raise_error(Errno::EBADF) + -> { @io.send :initialize, -1, 'w' }.should.raise(Errno::EBADF) end end diff --git a/spec/ruby/core/io/inspect_spec.rb b/spec/ruby/core/io/inspect_spec.rb index c653c307c4..37dc459f22 100644 --- a/spec/ruby/core/io/inspect_spec.rb +++ b/spec/ruby/core/io/inspect_spec.rb @@ -8,13 +8,13 @@ describe "IO#inspect" do it "contains the file descriptor number" do @r, @w = IO.pipe - @r.inspect.should include("fd #{@r.fileno}") + @r.inspect.should.include?("fd #{@r.fileno}") end it "contains \"(closed)\" if the stream is closed" do @r, @w = IO.pipe @r.close - @r.inspect.should include("(closed)") + @r.inspect.should.include?("(closed)") end it "reports IO as its Method object's owner" do diff --git a/spec/ruby/core/io/internal_encoding_spec.rb b/spec/ruby/core/io/internal_encoding_spec.rb index 7a583d4bcb..9963a93f33 100644 --- a/spec/ruby/core/io/internal_encoding_spec.rb +++ b/spec/ruby/core/io/internal_encoding_spec.rb @@ -9,25 +9,25 @@ describe :io_internal_encoding, shared: true do it "returns nil if the internal encoding is not set" do @io = new_io @name, @object - @io.internal_encoding.should be_nil + @io.internal_encoding.should == nil end it "returns nil if Encoding.default_internal is changed after the instance is created" do @io = new_io @name, @object Encoding.default_internal = Encoding::IBM437 - @io.internal_encoding.should be_nil + @io.internal_encoding.should == nil end it "returns the value set when the instance was created" do @io = new_io @name, "#{@object}:utf-8:euc-jp" Encoding.default_internal = Encoding::IBM437 - @io.internal_encoding.should equal(Encoding::EUC_JP) + @io.internal_encoding.should.equal?(Encoding::EUC_JP) end it "returns the value set by #set_encoding" do @io = new_io @name, @object @io.set_encoding(Encoding::US_ASCII, Encoding::IBM437) - @io.internal_encoding.should equal(Encoding::IBM437) + @io.internal_encoding.should.equal?(Encoding::IBM437) end end @@ -39,13 +39,13 @@ describe :io_internal_encoding, shared: true do it "returns nil" do @io = new_io @name, @object - @io.internal_encoding.should be_nil + @io.internal_encoding.should == nil end it "returns nil regardless of Encoding.default_internal changes" do @io = new_io @name, @object Encoding.default_internal = Encoding::IBM437 - @io.internal_encoding.should be_nil + @io.internal_encoding.should == nil end end @@ -57,41 +57,41 @@ describe :io_internal_encoding, shared: true do it "returns the value of Encoding.default_internal when the instance was created if the internal encoding is not set" do @io = new_io @name, @object - @io.internal_encoding.should equal(Encoding::IBM866) + @io.internal_encoding.should.equal?(Encoding::IBM866) end it "does not change when Encoding.default_internal is changed" do @io = new_io @name, @object Encoding.default_internal = Encoding::IBM437 - @io.internal_encoding.should equal(Encoding::IBM866) + @io.internal_encoding.should.equal?(Encoding::IBM866) end it "returns the internal encoding set when the instance was created" do @io = new_io @name, "#{@object}:utf-8:euc-jp" - @io.internal_encoding.should equal(Encoding::EUC_JP) + @io.internal_encoding.should.equal?(Encoding::EUC_JP) end it "does not change when set and Encoding.default_internal is changed" do @io = new_io @name, "#{@object}:utf-8:euc-jp" Encoding.default_internal = Encoding::IBM437 - @io.internal_encoding.should equal(Encoding::EUC_JP) + @io.internal_encoding.should.equal?(Encoding::EUC_JP) end it "returns the value set by #set_encoding" do @io = new_io @name, @object @io.set_encoding(Encoding::US_ASCII, Encoding::IBM437) - @io.internal_encoding.should equal(Encoding::IBM437) + @io.internal_encoding.should.equal?(Encoding::IBM437) end it "returns nil when Encoding.default_external is BINARY and the internal encoding is not set" do Encoding.default_external = Encoding::BINARY @io = new_io @name, @object - @io.internal_encoding.should be_nil + @io.internal_encoding.should == nil end it "returns nil when the external encoding is BINARY and the internal encoding is not set" do @io = new_io @name, "#{@object}:binary" - @io.internal_encoding.should be_nil + @io.internal_encoding.should == nil end end end @@ -116,7 +116,7 @@ describe "IO#internal_encoding" do it "can be retrieved from a closed stream" do io = IOSpecs.io_fixture("lines.txt", "r") io.close - io.internal_encoding.should equal(Encoding.default_internal) + io.internal_encoding.should.equal?(Encoding.default_internal) end describe "with 'r' mode" do diff --git a/spec/ruby/core/io/ioctl_spec.rb b/spec/ruby/core/io/ioctl_spec.rb index 3f7b5ad5d7..15a5d6ec22 100644 --- a/spec/ruby/core/io/ioctl_spec.rb +++ b/spec/ruby/core/io/ioctl_spec.rb @@ -4,7 +4,7 @@ require_relative 'fixtures/classes' describe "IO#ioctl" do platform_is_not :windows do it "raises IOError on closed stream" do - -> { IOSpecs.closed_io.ioctl(5, 5) }.should raise_error(IOError) + -> { IOSpecs.closed_io.ioctl(5, 5) }.should.raise(IOError) end end @@ -15,7 +15,7 @@ describe "IO#ioctl" do buffer = +'' # FIONREAD in /usr/include/asm-generic/ioctls.h f.ioctl 0x541B, buffer - buffer.unpack('I').first.should be_kind_of(Integer) + buffer.unpack('I').first.should.is_a?(Integer) end end end @@ -25,7 +25,7 @@ describe "IO#ioctl" do -> { # TIOCGWINSZ in /usr/include/asm-generic/ioctls.h f.ioctl 0x5413, nil - }.should raise_error(SystemCallError) + }.should.raise(SystemCallError) end end end diff --git a/spec/ruby/core/io/lineno_spec.rb b/spec/ruby/core/io/lineno_spec.rb index e82cdd9f17..93b505652a 100644 --- a/spec/ruby/core/io/lineno_spec.rb +++ b/spec/ruby/core/io/lineno_spec.rb @@ -11,14 +11,14 @@ describe "IO#lineno" do end it "raises an IOError on a closed stream" do - -> { IOSpecs.closed_io.lineno }.should raise_error(IOError) + -> { IOSpecs.closed_io.lineno }.should.raise(IOError) end it "raises an IOError on a write-only stream" do name = tmp("io_lineno.txt") begin File.open(name, 'w') do |f| - -> { f.lineno }.should raise_error(IOError) + -> { f.lineno }.should.raise(IOError) end ensure rm_r name @@ -29,7 +29,7 @@ describe "IO#lineno" do cmd = platform_is(:windows) ? 'rem' : 'cat' IO.popen(cmd, 'r+') do |p| p.close_read - -> { p.lineno }.should raise_error(IOError) + -> { p.lineno }.should.raise(IOError) end end @@ -56,14 +56,14 @@ describe "IO#lineno=" do end it "raises an IOError on a closed stream" do - -> { IOSpecs.closed_io.lineno = 5 }.should raise_error(IOError) + -> { IOSpecs.closed_io.lineno = 5 }.should.raise(IOError) end it "raises an IOError on a write-only stream" do name = tmp("io_lineno.txt") begin File.open(name, 'w') do |f| - -> { f.lineno = 0 }.should raise_error(IOError) + -> { f.lineno = 0 }.should.raise(IOError) end ensure rm_r name @@ -74,7 +74,7 @@ describe "IO#lineno=" do cmd = platform_is(:windows) ? 'rem' : 'cat' IO.popen(cmd, 'r+') do |p| p.close_read - -> { p.lineno = 0 }.should raise_error(IOError) + -> { p.lineno = 0 }.should.raise(IOError) end end @@ -95,12 +95,12 @@ describe "IO#lineno=" do end it "raises TypeError if cannot convert argument to Integer implicitly" do - -> { @io.lineno = "1" }.should raise_error(TypeError, 'no implicit conversion of String into Integer') - -> { @io.lineno = nil }.should raise_error(TypeError, 'no implicit conversion from nil to integer') + -> { @io.lineno = "1" }.should.raise(TypeError, 'no implicit conversion of String into Integer') + -> { @io.lineno = nil }.should raise_consistent_error(TypeError, 'no implicit conversion of nil into Integer') end it "does not accept Integers that don't fit in a C int" do - -> { @io.lineno = 2**32 }.should raise_error(RangeError) + -> { @io.lineno = 2**32 }.should.raise(RangeError) end it "sets the current line number to the given value" do diff --git a/spec/ruby/core/io/open_spec.rb b/spec/ruby/core/io/open_spec.rb index d151da9ce5..ff22d14685 100644 --- a/spec/ruby/core/io/open_spec.rb +++ b/spec/ruby/core/io/open_spec.rb @@ -32,7 +32,7 @@ describe "IO.open" do super() ScratchPad.record :called end - io.closed?.should be_false + io.closed?.should == false end ScratchPad.recorded.should == :called end @@ -46,7 +46,7 @@ describe "IO.open" do end raise Exception end - end.should raise_error(Exception) + end.should.raise(Exception) ScratchPad.recorded.should == :called end @@ -59,7 +59,7 @@ describe "IO.open" do raise Exception end end - end.should raise_error(Exception) + end.should.raise(Exception) ScratchPad.recorded.should == :called end @@ -72,7 +72,7 @@ describe "IO.open" do raise StandardError end end - end.should raise_error(StandardError) + end.should.raise(StandardError) ScratchPad.recorded.should == :called end diff --git a/spec/ruby/core/io/output_spec.rb b/spec/ruby/core/io/output_spec.rb index 2aafb305f4..0decf8c95b 100644 --- a/spec/ruby/core/io/output_spec.rb +++ b/spec/ruby/core/io/output_spec.rb @@ -16,7 +16,7 @@ describe "IO#<<" do it "raises an error if the stream is closed" do io = IOSpecs.closed_io - -> { io << "test" }.should raise_error(IOError) + -> { io << "test" }.should.raise(IOError) end it "returns self" do diff --git a/spec/ruby/core/io/path_spec.rb b/spec/ruby/core/io/path_spec.rb index 8145c32f39..798adb2163 100644 --- a/spec/ruby/core/io/path_spec.rb +++ b/spec/ruby/core/io/path_spec.rb @@ -1,14 +1,12 @@ require_relative '../../spec_helper' describe "IO#path" do - ruby_version_is "3.2" do - it "returns the path of the file associated with the IO object" do - path = tmp("io_path.txt") - File.open(path, "w") do |file| - IO.new(file.fileno, path: file.path, autoclose: false).path.should == file.path - end - ensure - File.unlink(path) + it "returns the path of the file associated with the IO object" do + path = tmp("io_path.txt") + File.open(path, "w") do |file| + IO.new(file.fileno, path: file.path, autoclose: false).path.should == file.path end + ensure + File.unlink(path) end end diff --git a/spec/ruby/core/io/pid_spec.rb b/spec/ruby/core/io/pid_spec.rb index bc09fe7c3b..04956887ff 100644 --- a/spec/ruby/core/io/pid_spec.rb +++ b/spec/ruby/core/io/pid_spec.rb @@ -25,11 +25,11 @@ describe "IO#pid" do end it "returns the ID of a process associated with stream" do - @io.pid.should_not be_nil + @io.pid.should_not == nil end it "raises an IOError on closed stream" do @io.close - -> { @io.pid }.should raise_error(IOError) + -> { @io.pid }.should.raise(IOError) end end diff --git a/spec/ruby/core/io/pipe_spec.rb b/spec/ruby/core/io/pipe_spec.rb index aee0d9003f..9f1b01a5cd 100644 --- a/spec/ruby/core/io/pipe_spec.rb +++ b/spec/ruby/core/io/pipe_spec.rb @@ -16,14 +16,14 @@ describe "IO.pipe" do it "returns two IO objects" do @r, @w = IO.pipe - @r.should be_kind_of(IO) - @w.should be_kind_of(IO) + @r.should.is_a?(IO) + @w.should.is_a?(IO) end it "returns instances of a subclass when called on a subclass" do @r, @w = IOSpecs::SubIO.pipe - @r.should be_an_instance_of(IOSpecs::SubIO) - @w.should be_an_instance_of(IOSpecs::SubIO) + @r.should.instance_of?(IOSpecs::SubIO) + @w.should.instance_of?(IOSpecs::SubIO) end it "does not use IO.new method to create pipes and allows its overriding" do @@ -33,8 +33,8 @@ describe "IO.pipe" do @r, @w = IOSpecs::SubIOWithRedefinedNew.pipe ScratchPad.recorded.should == [:call_original_initialize, :call_original_initialize] # called 2 times - for each pipe (r and w) - @r.should be_an_instance_of(IOSpecs::SubIOWithRedefinedNew) - @w.should be_an_instance_of(IOSpecs::SubIOWithRedefinedNew) + @r.should.instance_of?(IOSpecs::SubIOWithRedefinedNew) + @w.should.instance_of?(IOSpecs::SubIOWithRedefinedNew) end end @@ -42,8 +42,8 @@ describe "IO.pipe" do describe "passed a block" do it "yields two IO objects" do IO.pipe do |r, w| - r.should be_kind_of(IO) - w.should be_kind_of(IO) + r.should.is_a?(IO) + w.should.is_a?(IO) end end @@ -67,7 +67,7 @@ describe "IO.pipe" do w = _w raise RuntimeError end - end.should raise_error(RuntimeError) + end.should.raise(RuntimeError) r.should.closed? w.should.closed? end @@ -100,7 +100,7 @@ describe "IO.pipe" do IO.pipe do |r, w| r.external_encoding.should == Encoding::ISO_8859_1 - r.internal_encoding.should be_nil + r.internal_encoding.should == nil end end @@ -120,14 +120,14 @@ describe "IO.pipe" do IO.pipe do |r, w| r.external_encoding.should == Encoding::UTF_8 - r.internal_encoding.should be_nil + r.internal_encoding.should == nil end end it "sets the external encoding of the read end when passed an Encoding argument" do IO.pipe(Encoding::UTF_8) do |r, w| r.external_encoding.should == Encoding::UTF_8 - r.internal_encoding.should be_nil + r.internal_encoding.should == nil end end @@ -141,14 +141,14 @@ describe "IO.pipe" do it "sets the external encoding of the read end when passed the name of an Encoding" do IO.pipe("UTF-8") do |r, w| r.external_encoding.should == Encoding::UTF_8 - r.internal_encoding.should be_nil + r.internal_encoding.should == nil end end it "accepts 'bom|' prefix for external encoding" do IO.pipe("BOM|UTF-8") do |r, w| r.external_encoding.should == Encoding::UTF_8 - r.internal_encoding.should be_nil + r.internal_encoding.should == nil end end @@ -213,13 +213,13 @@ describe "IO.pipe" do it "sets no external encoding for the write end" do IO.pipe(Encoding::UTF_8) do |r, w| - w.external_encoding.should be_nil + w.external_encoding.should == nil end end it "sets no internal encoding for the write end" do IO.pipe(Encoding::UTF_8) do |r, w| - w.external_encoding.should be_nil + w.external_encoding.should == nil end end end diff --git a/spec/ruby/core/io/popen_spec.rb b/spec/ruby/core/io/popen_spec.rb index e9d32c5c7d..b5747bf255 100644 --- a/spec/ruby/core/io/popen_spec.rb +++ b/spec/ruby/core/io/popen_spec.rb @@ -21,7 +21,7 @@ describe "IO.popen" do it "returns an open IO" do @io = IO.popen(ruby_cmd('exit'), "r") - @io.closed?.should be_false + @io.closed?.should == false end it "reads a read-only pipe" do @@ -31,7 +31,7 @@ describe "IO.popen" do it "raises IOError when writing a read-only pipe" do @io = IO.popen('echo foo', "r") - -> { @io.write('bar') }.should raise_error(IOError) + -> { @io.write('bar') }.should.raise(IOError) @io.read.should == "foo\n" end @@ -52,7 +52,7 @@ describe "IO.popen" do it "raises IOError when reading a write-only pipe" do @io = IO.popen(ruby_cmd('IO.copy_stream(STDIN,STDOUT)'), "w") - -> { @io.read }.should raise_error(IOError) + -> { @io.read }.should.raise(IOError) end it "reads and writes a read/write pipe" do @@ -86,7 +86,7 @@ describe "IO.popen" do it "returns an instance of a subclass when called on a subclass" do @io = IOSpecs::SubIO.popen(ruby_cmd('exit'), "r") - @io.should be_an_instance_of(IOSpecs::SubIO) + @io.should.instance_of?(IOSpecs::SubIO) end it "coerces mode argument with #to_str" do @@ -95,27 +95,43 @@ describe "IO.popen" do @io = IO.popen(ruby_cmd('exit 0'), mode) end + it "accepts a path using the chdir: keyword argument" do + path = File.dirname(@fname) + + @io = IO.popen(ruby_cmd("puts Dir.pwd"), "r", chdir: path) + @io.read.chomp.should == path + end + + it "accepts a path using the chdir: keyword argument and a coercible path" do + path = File.dirname(@fname) + object = mock("path") + object.should_receive(:to_path).and_return(path) + + @io = IO.popen(ruby_cmd("puts Dir.pwd"), "r", chdir: object) + @io.read.chomp.should == path + end + describe "with a block" do it "yields an open IO to the block" do IO.popen(ruby_cmd('exit'), "r") do |io| - io.closed?.should be_false + io.closed?.should == false end end it "yields an instance of a subclass when called on a subclass" do IOSpecs::SubIO.popen(ruby_cmd('exit'), "r") do |io| - io.should be_an_instance_of(IOSpecs::SubIO) + io.should.instance_of?(IOSpecs::SubIO) end end it "closes the IO after yielding" do io = IO.popen(ruby_cmd('exit'), "r") { |_io| _io } - io.closed?.should be_true + io.closed?.should == true end it "allows the IO to be closed inside the block" do io = IO.popen(ruby_cmd('exit'), 'r') { |_io| _io.close; _io } - io.closed?.should be_true + io.closed?.should == true end it "returns the value of the block" do @@ -153,7 +169,7 @@ describe "IO.popen" do it "sets the internal encoding to nil if it's the same as the external encoding" do @io = IO.popen(ruby_cmd('exit'), external_encoding: Encoding::EUC_JP, internal_encoding: Encoding::EUC_JP) - @io.internal_encoding.should be_nil + @io.internal_encoding.should == nil end context "with a leading ENV Hash" do diff --git a/spec/ruby/core/io/pread_spec.rb b/spec/ruby/core/io/pread_spec.rb index dc7bcedf3e..cfb8dc4c68 100644 --- a/spec/ruby/core/io/pread_spec.rb +++ b/spec/ruby/core/io/pread_spec.rb @@ -1,140 +1,138 @@ # -*- encoding: utf-8 -*- require_relative '../../spec_helper' -guard -> { platform_is_not :windows or ruby_version_is "3.3" } do - describe "IO#pread" do - before :each do - @fname = tmp("io_pread.txt") - @contents = "1234567890" - touch(@fname) { |f| f.write @contents } - @file = File.open(@fname, "r+") - end +describe "IO#pread" do + before :each do + @fname = tmp("io_pread.txt") + @contents = "1234567890" + touch(@fname) { |f| f.write @contents } + @file = File.open(@fname, "r+") + end - after :each do - @file.close - rm_r @fname - end + after :each do + @file.close + rm_r @fname + end - it "accepts a length, and an offset" do - @file.pread(4, 0).should == "1234" - @file.pread(3, 4).should == "567" - end + it "accepts a length, and an offset" do + @file.pread(4, 0).should == "1234" + @file.pread(3, 4).should == "567" + end - it "accepts a length, an offset, and an output buffer" do - buffer = +"foo" - @file.pread(3, 4, buffer).should.equal?(buffer) - buffer.should == "567" - end + it "accepts a length, an offset, and an output buffer" do + buffer = +"foo" + @file.pread(3, 4, buffer).should.equal?(buffer) + buffer.should == "567" + end - it "shrinks the buffer in case of less bytes read" do - buffer = +"foo" - @file.pread(1, 0, buffer) - buffer.should == "1" - end + it "shrinks the buffer in case of less bytes read" do + buffer = +"foo" + @file.pread(1, 0, buffer) + buffer.should == "1" + end - it "grows the buffer in case of more bytes read" do - buffer = +"foo" - @file.pread(5, 0, buffer) - buffer.should == "12345" - end + it "grows the buffer in case of more bytes read" do + buffer = +"foo" + @file.pread(5, 0, buffer) + buffer.should == "12345" + end - it "preserves the encoding of the given buffer" do - buffer = ''.encode(Encoding::ISO_8859_1) - @file.pread(10, 0, buffer) + it "preserves the encoding of the given buffer" do + buffer = ''.encode(Encoding::ISO_8859_1) + @file.pread(10, 0, buffer) - buffer.encoding.should == Encoding::ISO_8859_1 - end + buffer.encoding.should == Encoding::ISO_8859_1 + end - it "does not advance the file pointer" do - @file.pread(4, 0).should == "1234" - @file.read.should == "1234567890" - end + it "does not advance the file pointer" do + @file.pread(4, 0).should == "1234" + @file.read.should == "1234567890" + end - it "ignores the current offset" do - @file.pos = 3 - @file.pread(4, 0).should == "1234" - end + it "ignores the current offset" do + @file.pos = 3 + @file.pread(4, 0).should == "1234" + end - it "returns an empty string for maxlen = 0" do - @file.pread(0, 4).should == "" - end + it "returns an empty string for maxlen = 0" do + @file.pread(0, 4).should == "" + end - it "returns a buffer for maxlen = 0 when buffer specified" do - buffer = +"foo" - @file.pread(0, 4, buffer).should.equal?(buffer) - buffer.should == "foo" - end + it "returns a buffer for maxlen = 0 when buffer specified" do + buffer = +"foo" + @file.pread(0, 4, buffer).should.equal?(buffer) + buffer.should == "foo" + end - it "ignores the offset for maxlen = 0, even if it is out of file bounds" do - @file.pread(0, 400).should == "" - end + it "ignores the offset for maxlen = 0, even if it is out of file bounds" do + @file.pread(0, 400).should == "" + end - it "does not reset the buffer when reading with maxlen = 0" do - buffer = +"foo" - @file.pread(0, 4, buffer) - buffer.should == "foo" + it "does not reset the buffer when reading with maxlen = 0" do + buffer = +"foo" + @file.pread(0, 4, buffer) + buffer.should == "foo" - @file.pread(0, 400, buffer) - buffer.should == "foo" - end + @file.pread(0, 400, buffer) + buffer.should == "foo" + end - it "converts maxlen to Integer using #to_int" do - maxlen = mock('maxlen') - maxlen.should_receive(:to_int).and_return(4) - @file.pread(maxlen, 0).should == "1234" - end + it "converts maxlen to Integer using #to_int" do + maxlen = mock('maxlen') + maxlen.should_receive(:to_int).and_return(4) + @file.pread(maxlen, 0).should == "1234" + end - it "converts offset to Integer using #to_int" do - offset = mock('offset') - offset.should_receive(:to_int).and_return(0) - @file.pread(4, offset).should == "1234" - end + it "converts offset to Integer using #to_int" do + offset = mock('offset') + offset.should_receive(:to_int).and_return(0) + @file.pread(4, offset).should == "1234" + end - it "converts a buffer to String using to_str" do - buffer = mock('buffer') - buffer.should_receive(:to_str).at_least(1).and_return(+"foo") - @file.pread(4, 0, buffer) - buffer.should_not.is_a?(String) - buffer.to_str.should == "1234" - end + it "converts a buffer to String using to_str" do + buffer = mock('buffer') + buffer.should_receive(:to_str).at_least(1).and_return(+"foo") + @file.pread(4, 0, buffer) + buffer.should_not.is_a?(String) + buffer.to_str.should == "1234" + end - it "raises TypeError if maxlen is not an Integer and cannot be coerced into Integer" do - maxlen = Object.new - -> { @file.pread(maxlen, 0) }.should raise_error(TypeError, 'no implicit conversion of Object into Integer') - end + it "raises TypeError if maxlen is not an Integer and cannot be coerced into Integer" do + maxlen = Object.new + -> { @file.pread(maxlen, 0) }.should.raise(TypeError, 'no implicit conversion of Object into Integer') + end - it "raises TypeError if offset is not an Integer and cannot be coerced into Integer" do - offset = Object.new - -> { @file.pread(4, offset) }.should raise_error(TypeError, 'no implicit conversion of Object into Integer') - end + it "raises TypeError if offset is not an Integer and cannot be coerced into Integer" do + offset = Object.new + -> { @file.pread(4, offset) }.should.raise(TypeError, 'no implicit conversion of Object into Integer') + end - it "raises ArgumentError for negative values of maxlen" do - -> { @file.pread(-4, 0) }.should raise_error(ArgumentError, 'negative string size (or size too big)') - end + it "raises ArgumentError for negative values of maxlen" do + -> { @file.pread(-4, 0) }.should.raise(ArgumentError, 'negative string size (or size too big)') + end - it "raised Errno::EINVAL for negative values of offset" do - -> { @file.pread(4, -1) }.should raise_error(Errno::EINVAL, /Invalid argument/) - end + it "raised Errno::EINVAL for negative values of offset" do + -> { @file.pread(4, -1) }.should.raise(Errno::EINVAL, /Invalid argument/) + end - it "raises TypeError if the buffer is not a String and cannot be coerced into String" do - buffer = Object.new - -> { @file.pread(4, 0, buffer) }.should raise_error(TypeError, 'no implicit conversion of Object into String') - end + it "raises TypeError if the buffer is not a String and cannot be coerced into String" do + buffer = Object.new + -> { @file.pread(4, 0, buffer) }.should.raise(TypeError, 'no implicit conversion of Object into String') + end - it "raises EOFError if end-of-file is reached" do - -> { @file.pread(1, 10) }.should raise_error(EOFError) - end + it "raises EOFError if end-of-file is reached" do + -> { @file.pread(1, 10) }.should.raise(EOFError) + end - it "raises IOError when file is not open in read mode" do - File.open(@fname, "w") do |file| - -> { file.pread(1, 1) }.should raise_error(IOError) - end + it "raises IOError when file is not open in read mode" do + File.open(@fname, "w") do |file| + -> { file.pread(1, 1) }.should.raise(IOError) end + end - it "raises IOError when file is closed" do - file = File.open(@fname, "r+") - file.close - -> { file.pread(1, 1) }.should raise_error(IOError) - end + it "raises IOError when file is closed" do + file = File.open(@fname, "r+") + file.close + -> { file.pread(1, 1) }.should.raise(IOError) end end diff --git a/spec/ruby/core/io/print_spec.rb b/spec/ruby/core/io/print_spec.rb index 085852024c..065cb3b8cb 100644 --- a/spec/ruby/core/io/print_spec.rb +++ b/spec/ruby/core/io/print_spec.rb @@ -21,7 +21,7 @@ describe "IO#print" do end it "returns nil" do - touch(@name) { |f| f.print.should be_nil } + touch(@name) { |f| f.print.should == nil } end it "writes $_.to_s followed by $\\ (if any) to the stream if no arguments given" do @@ -61,6 +61,6 @@ describe "IO#print" do end it "raises IOError on closed stream" do - -> { IOSpecs.closed_io.print("stuff") }.should raise_error(IOError) + -> { IOSpecs.closed_io.print("stuff") }.should.raise(IOError) end end diff --git a/spec/ruby/core/io/printf_spec.rb b/spec/ruby/core/io/printf_spec.rb index baa00f14ce..d5519bdaa3 100644 --- a/spec/ruby/core/io/printf_spec.rb +++ b/spec/ruby/core/io/printf_spec.rb @@ -27,6 +27,6 @@ describe "IO#printf" do end it "raises IOError on closed stream" do - -> { IOSpecs.closed_io.printf("stuff") }.should raise_error(IOError) + -> { IOSpecs.closed_io.printf("stuff") }.should.raise(IOError) end end diff --git a/spec/ruby/core/io/puts_spec.rb b/spec/ruby/core/io/puts_spec.rb index a186ddaa5d..df526ea56a 100644 --- a/spec/ruby/core/io/puts_spec.rb +++ b/spec/ruby/core/io/puts_spec.rb @@ -111,7 +111,7 @@ describe "IO#puts" do end it "raises IOError on closed stream" do - -> { IOSpecs.closed_io.puts("stuff") }.should raise_error(IOError) + -> { IOSpecs.closed_io.puts("stuff") }.should.raise(IOError) end it "writes crlf when IO is opened with newline: :crlf" do diff --git a/spec/ruby/core/io/pwrite_spec.rb b/spec/ruby/core/io/pwrite_spec.rb index 2bc508b37d..c318d551bc 100644 --- a/spec/ruby/core/io/pwrite_spec.rb +++ b/spec/ruby/core/io/pwrite_spec.rb @@ -1,69 +1,67 @@ # -*- encoding: utf-8 -*- require_relative '../../spec_helper' -guard -> { platform_is_not :windows or ruby_version_is "3.3" } do - describe "IO#pwrite" do - before :each do - @fname = tmp("io_pwrite.txt") - @file = File.open(@fname, "w+") - end +describe "IO#pwrite" do + before :each do + @fname = tmp("io_pwrite.txt") + @file = File.open(@fname, "w+") + end - after :each do - @file.close - rm_r @fname - end + after :each do + @file.close + rm_r @fname + end - it "returns the number of bytes written" do - @file.pwrite("foo", 0).should == 3 - end + it "returns the number of bytes written" do + @file.pwrite("foo", 0).should == 3 + end - it "accepts a string and an offset" do - @file.pwrite("foo", 2) - @file.pread(3, 2).should == "foo" - end + it "accepts a string and an offset" do + @file.pwrite("foo", 2) + @file.pread(3, 2).should == "foo" + end - it "does not advance the pointer in the file" do - @file.pwrite("bar", 3) - @file.write("foo") - @file.pread(6, 0).should == "foobar" - end + it "does not advance the pointer in the file" do + @file.pwrite("bar", 3) + @file.write("foo") + @file.pread(6, 0).should == "foobar" + end - it "calls #to_s on the object to be written" do - object = mock("to_s") - object.should_receive(:to_s).and_return("foo") - @file.pwrite(object, 0) - @file.pread(3, 0).should == "foo" - end + it "calls #to_s on the object to be written" do + object = mock("to_s") + object.should_receive(:to_s).and_return("foo") + @file.pwrite(object, 0) + @file.pread(3, 0).should == "foo" + end - it "calls #to_int on the offset" do - offset = mock("to_int") - offset.should_receive(:to_int).and_return(2) - @file.pwrite("foo", offset) - @file.pread(3, 2).should == "foo" - end + it "calls #to_int on the offset" do + offset = mock("to_int") + offset.should_receive(:to_int).and_return(2) + @file.pwrite("foo", offset) + @file.pread(3, 2).should == "foo" + end - it "raises IOError when file is not open in write mode" do - File.open(@fname, "r") do |file| - -> { file.pwrite("foo", 1) }.should raise_error(IOError, "not opened for writing") - end + it "raises IOError when file is not open in write mode" do + File.open(@fname, "r") do |file| + -> { file.pwrite("foo", 1) }.should.raise(IOError, "not opened for writing") end + end - it "raises IOError when file is closed" do - file = File.open(@fname, "w+") - file.close - -> { file.pwrite("foo", 1) }.should raise_error(IOError, "closed stream") - end + it "raises IOError when file is closed" do + file = File.open(@fname, "w+") + file.close + -> { file.pwrite("foo", 1) }.should.raise(IOError, "closed stream") + end - it "raises a NoMethodError if object does not respond to #to_s" do - -> { - @file.pwrite(BasicObject.new, 0) - }.should raise_error(NoMethodError, /undefined method [`']to_s'/) - end + it "raises a NoMethodError if object does not respond to #to_s" do + -> { + @file.pwrite(BasicObject.new, 0) + }.should.raise(NoMethodError, /undefined method [`']to_s'/) + end - it "raises a TypeError if the offset cannot be converted to an Integer" do - -> { - @file.pwrite("foo", Object.new) - }.should raise_error(TypeError, "no implicit conversion of Object into Integer") - end + it "raises a TypeError if the offset cannot be converted to an Integer" do + -> { + @file.pwrite("foo", Object.new) + }.should.raise(TypeError, "no implicit conversion of Object into Integer") end end diff --git a/spec/ruby/core/io/read_nonblock_spec.rb b/spec/ruby/core/io/read_nonblock_spec.rb index 51e7cd6bd2..511cf03263 100644 --- a/spec/ruby/core/io/read_nonblock_spec.rb +++ b/spec/ruby/core/io/read_nonblock_spec.rb @@ -12,12 +12,12 @@ describe "IO#read_nonblock" do end it "raises an exception extending IO::WaitReadable when there is no data" do - -> { @read.read_nonblock(5) }.should raise_error(IO::WaitReadable) { |e| + -> { @read.read_nonblock(5) }.should.raise(IO::WaitReadable) { |e| platform_is_not :windows do - e.should be_kind_of(Errno::EAGAIN) + e.should.is_a?(Errno::EAGAIN) end platform_is :windows do - e.should be_kind_of(Errno::EWOULDBLOCK) + e.should.is_a?(Errno::EWOULDBLOCK) end } end @@ -36,7 +36,7 @@ describe "IO#read_nonblock" do @read.read_nonblock(5) - @read.read_nonblock(5, exception: false).should be_nil + @read.read_nonblock(5, exception: false).should == nil end end end @@ -73,7 +73,7 @@ describe "IO#read_nonblock" do ) c = @read.getc @read.ungetc(c) - -> { @read.read_nonblock(3).should == "foo" }.should raise_error(IOError) + -> { @read.read_nonblock(3).should == "foo" }.should.raise(IOError) end it "returns less data if that is all that is available" do @@ -92,7 +92,7 @@ describe "IO#read_nonblock" do end it "raises ArgumentError when length is less than 0" do - -> { @read.read_nonblock(-1) }.should raise_error(ArgumentError) + -> { @read.read_nonblock(-1) }.should.raise(ArgumentError) end it "reads into the passed buffer" do @@ -106,7 +106,7 @@ describe "IO#read_nonblock" do buffer = +"" @write.write("1") output = @read.read_nonblock(1, buffer) - output.should equal(buffer) + output.should.equal?(buffer) end it "discards the existing buffer content upon successful read" do @@ -120,12 +120,12 @@ describe "IO#read_nonblock" do it "discards the existing buffer content upon error" do buffer = +"existing content" @write.close - -> { @read.read_nonblock(1, buffer) }.should raise_error(EOFError) - buffer.should be_empty + -> { @read.read_nonblock(1, buffer) }.should.raise(EOFError) + buffer.should.empty? end it "raises IOError on closed stream" do - -> { IOSpecs.closed_io.read_nonblock(5) }.should raise_error(IOError) + -> { IOSpecs.closed_io.read_nonblock(5) }.should.raise(IOError) end it "raises EOFError when the end is reached" do @@ -134,7 +134,7 @@ describe "IO#read_nonblock" do @read.read_nonblock(5) - -> { @read.read_nonblock(5) }.should raise_error(EOFError) + -> { @read.read_nonblock(5) }.should.raise(EOFError) end it "preserves the encoding of the given buffer" do diff --git a/spec/ruby/core/io/read_spec.rb b/spec/ruby/core/io/read_spec.rb index 567daa55df..dd787c9b60 100644 --- a/spec/ruby/core/io/read_spec.rb +++ b/spec/ruby/core/io/read_spec.rb @@ -29,7 +29,7 @@ describe "IO.read" do -> { IO.read(@fname, 3, 0, {mode: "r+"}) - }.should raise_error(ArgumentError, /wrong number of arguments/) + }.should.raise(ArgumentError, /wrong number of arguments/) end it "accepts an empty options Hash" do @@ -45,11 +45,11 @@ describe "IO.read" do end it "raises an IOError if the options Hash specifies write mode" do - -> { IO.read(@fname, 3, 0, mode: "w") }.should raise_error(IOError) + -> { IO.read(@fname, 3, 0, mode: "w") }.should.raise(IOError) end it "raises an IOError if the options Hash specifies append only mode" do - -> { IO.read(@fname, mode: "a") }.should raise_error(IOError) + -> { IO.read(@fname, mode: "a") }.should.raise(IOError) end it "reads the file if the options Hash includes read mode" do @@ -65,15 +65,6 @@ describe "IO.read" do end platform_is_not :windows do - ruby_version_is ""..."3.3" do - it "uses an :open_args option" do - string = IO.read(@fname, nil, 0, open_args: ["r", nil, {encoding: Encoding::US_ASCII}]) - string.encoding.should == Encoding::US_ASCII - - string = IO.read(@fname, nil, 0, open_args: ["r", nil, {}]) - string.encoding.should == Encoding::UTF_8 - end - end end it "disregards other options if :open_args is given" do @@ -124,29 +115,20 @@ describe "IO.read" do it "raises an Errno::ENOENT when the requested file does not exist" do rm_r @fname - -> { IO.read @fname }.should raise_error(Errno::ENOENT) + -> { IO.read @fname }.should.raise(Errno::ENOENT) end it "raises a TypeError when not passed a String type" do - -> { IO.read nil }.should raise_error(TypeError) + -> { IO.read nil }.should.raise(TypeError) end it "raises an ArgumentError when not passed a valid length" do - -> { IO.read @fname, -1 }.should raise_error(ArgumentError) - end - - ruby_version_is ''...'3.3' do - it "raises an Errno::EINVAL when not passed a valid offset" do - -> { IO.read @fname, 0, -1 }.should raise_error(Errno::EINVAL) - -> { IO.read @fname, -1, -1 }.should raise_error(Errno::EINVAL) - end + -> { IO.read @fname, -1 }.should.raise(ArgumentError) end - ruby_version_is '3.3' do - it "raises an ArgumentError when not passed a valid offset" do - -> { IO.read @fname, 0, -1 }.should raise_error(ArgumentError) - -> { IO.read @fname, -1, -1 }.should raise_error(ArgumentError) - end + it "raises an ArgumentError when not passed a valid offset" do + -> { IO.read @fname, 0, -1 }.should.raise(ArgumentError) + -> { IO.read @fname, -1, -1 }.should.raise(ArgumentError) end it "uses the external encoding specified via the :external_encoding option" do @@ -168,72 +150,72 @@ describe "IO.read" do end end -describe "IO.read from a pipe" do - it "runs the rest as a subprocess and returns the standard output" do - cmd = "|sh -c 'echo hello'" - platform_is :windows do - cmd = "|cmd.exe /C echo hello" - end - - suppress_warning do # https://bugs.ruby-lang.org/issues/19630 - IO.read(cmd).should == "hello\n" - end - end - - platform_is_not :windows do - it "opens a pipe to a fork if the rest is -" do - str = nil - suppress_warning do # https://bugs.ruby-lang.org/issues/19630 - str = IO.read("|-") +ruby_version_is ""..."4.0" do + describe "IO.read from a pipe" do + it "runs the rest as a subprocess and returns the standard output" do + cmd = "|sh -c 'echo hello'" + platform_is :windows do + cmd = "|cmd.exe /C echo hello" end - if str # parent - str.should == "hello from child\n" - else #child - puts "hello from child" - exit! + suppress_warning do # https://bugs.ruby-lang.org/issues/19630 + IO.read(cmd).should == "hello\n" end end - end - it "reads only the specified number of bytes requested" do - cmd = "|sh -c 'echo hello'" - platform_is :windows do - cmd = "|cmd.exe /C echo hello" - end + platform_is_not :windows do + it "opens a pipe to a fork if the rest is -" do + str = nil + suppress_warning do # https://bugs.ruby-lang.org/issues/19630 + str = IO.read("|-") + end - suppress_warning do # https://bugs.ruby-lang.org/issues/19630 - IO.read(cmd, 1).should == "h" + if str # parent + str.should == "hello from child\n" + else #child + puts "hello from child" + exit! + end + end end - end - platform_is_not :windows do - it "raises Errno::ESPIPE if passed an offset" do - -> { - suppress_warning do # https://bugs.ruby-lang.org/issues/19630 - IO.read("|sh -c 'echo hello'", 1, 1) - end - }.should raise_error(Errno::ESPIPE) + it "reads only the specified number of bytes requested" do + cmd = "|sh -c 'echo hello'" + platform_is :windows do + cmd = "|cmd.exe /C echo hello" + end + + suppress_warning do # https://bugs.ruby-lang.org/issues/19630 + IO.read(cmd, 1).should == "h" + end end - end - quarantine! do # The process tried to write to a nonexistent pipe. - platform_is :windows do - # TODO: It should raise Errno::ESPIPE on Windows as well - # once https://bugs.ruby-lang.org/issues/12230 is fixed. - it "raises Errno::EINVAL if passed an offset" do + platform_is_not :windows do + it "raises Errno::ESPIPE if passed an offset" do -> { suppress_warning do # https://bugs.ruby-lang.org/issues/19630 - IO.read("|cmd.exe /C echo hello", 1, 1) + IO.read("|sh -c 'echo hello'", 1, 1) end - }.should raise_error(Errno::EINVAL) + }.should.raise(Errno::ESPIPE) + end + end + + quarantine! do # The process tried to write to a nonexistent pipe. + platform_is :windows do + # TODO: It should raise Errno::ESPIPE on Windows as well + # once https://bugs.ruby-lang.org/issues/12230 is fixed. + it "raises Errno::EINVAL if passed an offset" do + -> { + suppress_warning do # https://bugs.ruby-lang.org/issues/19630 + IO.read("|cmd.exe /C echo hello", 1, 1) + end + }.should.raise(Errno::EINVAL) + end end end - end - ruby_version_is "3.3" do # https://bugs.ruby-lang.org/issues/19630 - it "warns about deprecation given a path with a pipe" do + it "warns about deprecation" do cmd = "|echo ok" -> { IO.read(cmd) @@ -288,7 +270,7 @@ describe "IO#read" do end it "raises an ArgumentError when not passed a valid length" do - -> { @io.read(-1) }.should raise_error(ArgumentError) + -> { @io.read(-1) }.should.raise(ArgumentError) end it "clears the output buffer if there is nothing to read" do @@ -315,16 +297,14 @@ describe "IO#read" do it "raise FrozenError if the output buffer is frozen" do @io.read - -> { @io.read(0, 'frozen-string'.freeze) }.should raise_error(FrozenError) - -> { @io.read(1, 'frozen-string'.freeze) }.should raise_error(FrozenError) - -> { @io.read(nil, 'frozen-string'.freeze) }.should raise_error(FrozenError) + -> { @io.read(0, 'frozen-string'.freeze) }.should.raise(FrozenError) + -> { @io.read(1, 'frozen-string'.freeze) }.should.raise(FrozenError) + -> { @io.read(nil, 'frozen-string'.freeze) }.should.raise(FrozenError) end - ruby_bug "", ""..."3.3" do - it "raise FrozenError if the output buffer is frozen (2)" do - @io.read - -> { @io.read(1, ''.freeze) }.should raise_error(FrozenError) - end + it "raise FrozenError if the output buffer is frozen (2)" do + @io.read + -> { @io.read(1, ''.freeze) }.should.raise(FrozenError) end it "consumes zero bytes when reading zero bytes" do @@ -394,14 +374,14 @@ describe "IO#read" do it "returns the given buffer" do buf = +"" - @io.read(nil, buf).should equal buf + @io.read(nil, buf).should.equal? buf end it "returns the given buffer when there is nothing to read" do buf = +"" @io.read - @io.read(nil, buf).should equal buf + @io.read(nil, buf).should.equal? buf end it "coerces the second argument to string and uses it as a buffer" do @@ -409,7 +389,7 @@ describe "IO#read" do obj = mock("buff") obj.should_receive(:to_str).any_number_of_times.and_return(buf) - @io.read(15, obj).should_not equal obj + @io.read(15, obj).should_not.equal? obj buf.should == @contents end @@ -443,11 +423,11 @@ describe "IO#read" do end it "raises IOError on closed stream" do - -> { IOSpecs.closed_io.read }.should raise_error(IOError) + -> { IOSpecs.closed_io.read }.should.raise(IOError) end it "raises ArgumentError when length is less than 0" do - -> { @io.read(-1) }.should raise_error(ArgumentError) + -> { @io.read(-1) }.should.raise(ArgumentError) end platform_is_not :windows do @@ -464,7 +444,7 @@ describe "IO#read" do Thread.pass until t.stop? r.close t.join - t.value.should be_kind_of(IOError) + t.value.should.is_a?(IOError) w.close end end @@ -598,20 +578,20 @@ describe :io_read_internal_encoding, shared: true do end it "sets the String encoding to the internal encoding" do - @io.read.encoding.should equal(Encoding::UTF_8) + @io.read.encoding.should.equal?(Encoding::UTF_8) end describe "when passed nil for limit" do it "sets the buffer to a transcoded String" do result = @io.read(nil, buf = +"") - buf.should equal(result) + buf.should.equal?(result) buf.should == "ありがとう\n" end it "sets the buffer's encoding to the internal encoding" do buf = "".dup.force_encoding Encoding::ISO_8859_1 @io.read(nil, buf) - buf.encoding.should equal(Encoding::UTF_8) + buf.encoding.should.equal?(Encoding::UTF_8) end end end @@ -622,24 +602,24 @@ describe :io_read_size_internal_encoding, shared: true do end it "returns a String in BINARY when passed a size" do - @io.read(4).encoding.should equal(Encoding::BINARY) - @io.read(0).encoding.should equal(Encoding::BINARY) + @io.read(4).encoding.should.equal?(Encoding::BINARY) + @io.read(0).encoding.should.equal?(Encoding::BINARY) end it "does not change the buffer's encoding when passed a limit" do buf = "".dup.force_encoding Encoding::ISO_8859_1 @io.read(4, buf) buf.should == [164, 162, 164, 234].pack('C*').force_encoding(Encoding::ISO_8859_1) - buf.encoding.should equal(Encoding::ISO_8859_1) + buf.encoding.should.equal?(Encoding::ISO_8859_1) end it "truncates the buffer but does not change the buffer's encoding when no data remains" do buf = "abc".dup.force_encoding Encoding::ISO_8859_1 @io.read - @io.read(1, buf).should be_nil + @io.read(1, buf).should == nil buf.size.should == 0 - buf.encoding.should equal(Encoding::ISO_8859_1) + buf.encoding.should.equal?(Encoding::ISO_8859_1) end end @@ -657,7 +637,7 @@ describe "IO#read" do end it "sets the String encoding to Encoding.default_external" do - @io.read.encoding.should equal(Encoding.default_external) + @io.read.encoding.should.equal?(Encoding.default_external) end end @@ -676,7 +656,7 @@ describe "IO#read" do end it "sets the String encoding to the external encoding" do - @io.read.encoding.should equal(Encoding::EUC_JP) + @io.read.encoding.should.equal?(Encoding::EUC_JP) end it_behaves_like :io_read_size_internal_encoding, nil diff --git a/spec/ruby/core/io/readbyte_spec.rb b/spec/ruby/core/io/readbyte_spec.rb index 14426c28ac..07da1da919 100644 --- a/spec/ruby/core/io/readbyte_spec.rb +++ b/spec/ruby/core/io/readbyte_spec.rb @@ -19,6 +19,6 @@ describe "IO#readbyte" do @io.seek(999999) -> do @io.readbyte - end.should raise_error EOFError + end.should.raise EOFError end end diff --git a/spec/ruby/core/io/readchar_spec.rb b/spec/ruby/core/io/readchar_spec.rb index a66773851a..29d14880ff 100644 --- a/spec/ruby/core/io/readchar_spec.rb +++ b/spec/ruby/core/io/readchar_spec.rb @@ -7,7 +7,7 @@ describe :io_readchar_internal_encoding, shared: true do end it "sets the String encoding to the internal encoding" do - @io.readchar.encoding.should equal(Encoding::UTF_8) + @io.readchar.encoding.should.equal?(Encoding::UTF_8) end end @@ -31,11 +31,11 @@ describe "IO#readchar" do it "raises an EOFError when invoked at the end of the stream" do @io.read - -> { @io.readchar }.should raise_error(EOFError) + -> { @io.readchar }.should.raise(EOFError) end it "raises IOError on closed stream" do - -> { IOSpecs.closed_io.readchar }.should raise_error(IOError) + -> { IOSpecs.closed_io.readchar }.should.raise(IOError) end end @@ -54,7 +54,7 @@ describe "IO#readchar with internal encoding" do end it "sets the String encoding to the external encoding" do - @io.readchar.encoding.should equal(Encoding::EUC_JP) + @io.readchar.encoding.should.equal?(Encoding::EUC_JP) end end @@ -105,6 +105,6 @@ describe "IO#readchar" do end it "raises EOFError on empty stream" do - -> { @io.readchar }.should raise_error(EOFError) + -> { @io.readchar }.should.raise(EOFError) end end diff --git a/spec/ruby/core/io/readline_spec.rb b/spec/ruby/core/io/readline_spec.rb index a814c1be90..009687710a 100644 --- a/spec/ruby/core/io/readline_spec.rb +++ b/spec/ruby/core/io/readline_spec.rb @@ -29,11 +29,11 @@ describe "IO#readline" do it "raises EOFError on end of stream" do IOSpecs.lines.length.times { @io.readline } - -> { @io.readline }.should raise_error(EOFError) + -> { @io.readline }.should.raise(EOFError) end it "raises IOError on closed stream" do - -> { IOSpecs.closed_io.readline }.should raise_error(IOError) + -> { IOSpecs.closed_io.readline }.should.raise(IOError) end it "assigns the returned line to $_" do @@ -53,7 +53,7 @@ describe "IO#readline" do end it "does not accept Integers that don't fit in a C off_t" do - -> { @io.readline(2**128) }.should raise_error(RangeError) + -> { @io.readline(2**128) }.should.raise(RangeError) end end @@ -74,11 +74,11 @@ describe "IO#readline" do end it "raises exception when options passed as Hash" do - -> { @io.readline({ chomp: true }) }.should raise_error(TypeError) + -> { @io.readline({ chomp: true }) }.should.raise(TypeError) -> { @io.readline("\n", 1, { chomp: true }) - }.should raise_error(ArgumentError, "wrong number of arguments (given 3, expected 0..2)") + }.should.raise(ArgumentError, "wrong number of arguments (given 3, expected 0..2)") end end end diff --git a/spec/ruby/core/io/readlines_spec.rb b/spec/ruby/core/io/readlines_spec.rb index 3a6ff3d0f3..640e253200 100644 --- a/spec/ruby/core/io/readlines_spec.rb +++ b/spec/ruby/core/io/readlines_spec.rb @@ -17,7 +17,7 @@ describe "IO#readlines" do it "raises an IOError if the stream is closed" do @io.close - -> { @io.readlines }.should raise_error(IOError) + -> { @io.readlines }.should.raise(IOError) end describe "when passed no arguments" do @@ -37,12 +37,12 @@ describe "IO#readlines" do describe "when passed no arguments" do it "updates self's position" do @io.readlines - @io.pos.should eql(137) + @io.pos.should.eql?(137) end it "updates self's lineno based on the number of lines read" do @io.readlines - @io.lineno.should eql(9) + @io.lineno.should.eql?(9) end it "does not change $_" do @@ -81,12 +81,12 @@ describe "IO#readlines" do it "updates self's lineno based on the number of lines read" do @io.readlines("r") - @io.lineno.should eql(5) + @io.lineno.should.eql?(5) end it "updates self's position based on the number of characters read" do @io.readlines("r") - @io.pos.should eql(137) + @io.pos.should.eql?(137) end it "does not change $_" do @@ -104,11 +104,11 @@ describe "IO#readlines" do describe "when passed limit" do it "raises ArgumentError when passed 0 as a limit" do - -> { @io.readlines(0) }.should raise_error(ArgumentError) + -> { @io.readlines(0) }.should.raise(ArgumentError) end it "does not accept Integers that don't fit in a C off_t" do - -> { @io.readlines(2**128) }.should raise_error(RangeError) + -> { @io.readlines(2**128) }.should.raise(RangeError) end end @@ -118,11 +118,11 @@ describe "IO#readlines" do end it "raises exception when options passed as Hash" do - -> { @io.readlines({ chomp: true }) }.should raise_error(TypeError) + -> { @io.readlines({ chomp: true }) }.should.raise(TypeError) -> { @io.readlines("\n", 1, { chomp: true }) - }.should raise_error(ArgumentError, "wrong number of arguments (given 3, expected 0..2)") + }.should.raise(ArgumentError, "wrong number of arguments (given 3, expected 0..2)") end end @@ -145,13 +145,13 @@ describe "IO#readlines" do it "raises an IOError if the stream is opened for append only" do -> do File.open(@name, "a:utf-8") { |f| f.readlines } - end.should raise_error(IOError) + end.should.raise(IOError) end it "raises an IOError if the stream is opened for write only" do -> do File.open(@name, "w:utf-8") { |f| f.readlines } - end.should raise_error(IOError) + end.should.raise(IOError) end end @@ -174,39 +174,39 @@ describe "IO.readlines" do $_.should == "test" end - describe "when passed a string that starts with a |" do - it "gets data from the standard out of the subprocess" do - cmd = "|sh -c 'echo hello;echo line2'" - platform_is :windows do - cmd = "|cmd.exe /C echo hello&echo line2" - end - - lines = nil - suppress_warning do # https://bugs.ruby-lang.org/issues/19630 - lines = IO.readlines(cmd) - end - lines.should == ["hello\n", "line2\n"] - end + ruby_version_is ""..."4.0" do + describe "when passed a string that starts with a |" do + it "gets data from the standard out of the subprocess" do + cmd = "|sh -c 'echo hello;echo line2'" + platform_is :windows do + cmd = "|cmd.exe /C echo hello&echo line2" + end - platform_is_not :windows do - it "gets data from a fork when passed -" do lines = nil suppress_warning do # https://bugs.ruby-lang.org/issues/19630 - lines = IO.readlines("|-") + lines = IO.readlines(cmd) end + lines.should == ["hello\n", "line2\n"] + end - if lines # parent - lines.should == ["hello\n", "from a fork\n"] - else - puts "hello" - puts "from a fork" - exit! + platform_is_not :windows do + it "gets data from a fork when passed -" do + lines = nil + suppress_warning do # https://bugs.ruby-lang.org/issues/19630 + lines = IO.readlines("|-") + end + + if lines # parent + lines.should == ["hello\n", "from a fork\n"] + else + puts "hello" + puts "from a fork" + exit! + end end end end - end - ruby_version_is "3.3" do # https://bugs.ruby-lang.org/issues/19630 it "warns about deprecation given a path with a pipe" do cmd = "|echo ok" @@ -237,7 +237,7 @@ describe "IO.readlines" do it "encodes lines using the default external encoding" do Encoding.default_external = Encoding::UTF_8 lines = IO.readlines(@name) - lines.all? { |s| s.encoding == Encoding::UTF_8 }.should be_true + lines.all? { |s| s.encoding == Encoding::UTF_8 }.should == true end it "encodes lines using the default internal encoding, when set" do @@ -245,13 +245,13 @@ describe "IO.readlines" do Encoding.default_internal = Encoding::UTF_16 suppress_warning {$/ = $/.encode Encoding::UTF_16} lines = IO.readlines(@name) - lines.all? { |s| s.encoding == Encoding::UTF_16 }.should be_true + lines.all? { |s| s.encoding == Encoding::UTF_16 }.should == true end it "ignores the default internal encoding if the external encoding is BINARY" do Encoding.default_external = Encoding::BINARY Encoding.default_internal = Encoding::UTF_8 lines = IO.readlines(@name) - lines.all? { |s| s.encoding == Encoding::BINARY }.should be_true + lines.all? { |s| s.encoding == Encoding::BINARY }.should == true end end diff --git a/spec/ruby/core/io/readpartial_spec.rb b/spec/ruby/core/io/readpartial_spec.rb index 547da0677d..d3f5545c8f 100644 --- a/spec/ruby/core/io/readpartial_spec.rb +++ b/spec/ruby/core/io/readpartial_spec.rb @@ -1,4 +1,4 @@ -# -*- encoding: binary -*- +# encoding: binary require_relative '../../spec_helper' require_relative 'fixtures/classes' @@ -15,10 +15,10 @@ describe "IO#readpartial" do end it "raises IOError on closed stream" do - -> { IOSpecs.closed_io.readpartial(10) }.should raise_error(IOError) + -> { IOSpecs.closed_io.readpartial(10) }.should.raise(IOError) @rd.close - -> { @rd.readpartial(10) }.should raise_error(IOError) + -> { @rd.readpartial(10) }.should.raise(IOError) end it "reads at most the specified number of bytes" do @@ -70,29 +70,34 @@ describe "IO#readpartial" do @wr.write("abc") @wr.close @rd.readpartial(10).should == 'abc' - -> { @rd.readpartial(10) }.should raise_error(EOFError) + -> { @rd.readpartial(10) }.should.raise(EOFError) end it "discards the existing buffer content upon error" do buffer = +'hello' @wr.close - -> { @rd.readpartial(1, buffer) }.should raise_error(EOFError) - buffer.should be_empty + -> { @rd.readpartial(1, buffer) }.should.raise(EOFError) + buffer.should.empty? end it "raises IOError if the stream is closed" do @wr.close - -> { @rd.readpartial(1) }.should raise_error(IOError) + -> { @rd.readpartial(1) }.should.raise(IOError) end it "raises ArgumentError if the negative argument is provided" do - -> { @rd.readpartial(-1) }.should raise_error(ArgumentError) + -> { @rd.readpartial(-1) }.should.raise(ArgumentError) end it "immediately returns an empty string if the length argument is 0" do @rd.readpartial(0).should == "" end + it "raises IOError if the stream is closed and the length argument is 0" do + @rd.close + -> { @rd.readpartial(0) }.should.raise(IOError, "closed stream") + end + it "clears and returns the given buffer if the length argument is 0" do buffer = +"existing content" @rd.readpartial(0, buffer).should == buffer diff --git a/spec/ruby/core/io/reopen_spec.rb b/spec/ruby/core/io/reopen_spec.rb index 8ff0f217f4..3b972d8978 100644 --- a/spec/ruby/core/io/reopen_spec.rb +++ b/spec/ruby/core/io/reopen_spec.rb @@ -27,35 +27,35 @@ describe "IO#reopen" do it "changes the class of the instance to the class of the object returned by #to_io" do obj = mock("io") obj.should_receive(:to_io).and_return(@other_io) - @io.reopen(obj).should be_an_instance_of(File) + @io.reopen(obj).should.instance_of?(File) end it "raises an IOError if the object returned by #to_io is closed" do obj = mock("io") obj.should_receive(:to_io).and_return(IOSpecs.closed_io) - -> { @io.reopen obj }.should raise_error(IOError) + -> { @io.reopen obj }.should.raise(IOError) end it "raises a TypeError if #to_io does not return an IO instance" do obj = mock("io") obj.should_receive(:to_io).and_return("something else") - -> { @io.reopen obj }.should raise_error(TypeError) + -> { @io.reopen obj }.should.raise(TypeError) end it "raises an IOError when called on a closed stream with an object" do @io.close obj = mock("io") obj.should_not_receive(:to_io) - -> { @io.reopen(STDOUT) }.should raise_error(IOError) + -> { @io.reopen(STDOUT) }.should.raise(IOError) end it "raises an IOError if the IO argument is closed" do - -> { @io.reopen(IOSpecs.closed_io) }.should raise_error(IOError) + -> { @io.reopen(IOSpecs.closed_io) }.should.raise(IOError) end it "raises an IOError when called on a closed stream with an IO" do @io.close - -> { @io.reopen(STDOUT) }.should raise_error(IOError) + -> { @io.reopen(STDOUT) }.should.raise(IOError) end end @@ -77,12 +77,12 @@ describe "IO#reopen with a String" do it "does not raise an exception when called on a closed stream with a path" do @io.close @io.reopen @name, "r" - @io.closed?.should be_false + @io.closed?.should == false @io.gets.should == "Line 1: One\n" end it "returns self" do - @io.reopen(@name).should equal(@io) + @io.reopen(@name).should.equal?(@io) end it "positions a newly created instance at the beginning of the new stream" do @@ -188,7 +188,7 @@ describe "IO#reopen with a String" do it "raises an Errno::ENOENT if the file does not exist and the IO is not opened in write mode" do @io = new_io @name, "r" - -> { @io.reopen(@other_name) }.should raise_error(Errno::ENOENT) + -> { @io.reopen(@other_name) }.should.raise(Errno::ENOENT) end end @@ -214,9 +214,9 @@ describe "IO#reopen with an IO at EOF" do end it "resets the EOF status to false" do - @io.eof?.should be_true + @io.eof?.should == true @io.reopen @other_io - @io.eof?.should be_false + @io.eof?.should == false end end @@ -244,7 +244,7 @@ describe "IO#reopen with an IO" do # MRI actually changes the class of @io in the call to #reopen # but does not preserve the existing singleton class of @io. def @io.to_io; flunk; end - @io.reopen(@other_io).should be_an_instance_of(IO) + @io.reopen(@other_io).should.instance_of?(IO) end it "does not change the object_id" do @@ -303,7 +303,7 @@ describe "IO#reopen with an IO" do it "may change the class of the instance" do @io.reopen @other_io - @io.should be_an_instance_of(File) + @io.should.instance_of?(File) end it "sets path equals to the other IO's path if other IO is File" do diff --git a/spec/ruby/core/io/rewind_spec.rb b/spec/ruby/core/io/rewind_spec.rb index 5579cbd988..43834ef307 100644 --- a/spec/ruby/core/io/rewind_spec.rb +++ b/spec/ruby/core/io/rewind_spec.rb @@ -48,6 +48,6 @@ describe "IO#rewind" do end it "raises IOError on closed stream" do - -> { IOSpecs.closed_io.rewind }.should raise_error(IOError) + -> { IOSpecs.closed_io.rewind }.should.raise(IOError) end end diff --git a/spec/ruby/core/io/seek_spec.rb b/spec/ruby/core/io/seek_spec.rb index 2fa4a73ac9..d26629fb89 100644 --- a/spec/ruby/core/io/seek_spec.rb +++ b/spec/ruby/core/io/seek_spec.rb @@ -17,7 +17,7 @@ describe "IO#seek" do end it "moves the read position relative to the current position with SEEK_CUR" do - -> { @io.seek(-1) }.should raise_error(Errno::EINVAL) + -> { @io.seek(-1) }.should.raise(Errno::EINVAL) @io.seek(10, IO::SEEK_CUR) @io.readline.should == "igne une.\n" @io.seek(-5, IO::SEEK_CUR) diff --git a/spec/ruby/core/io/select_spec.rb b/spec/ruby/core/io/select_spec.rb index 3893e7620f..0a43fc6f5f 100644 --- a/spec/ruby/core/io/select_spec.rb +++ b/spec/ruby/core/io/select_spec.rb @@ -18,6 +18,10 @@ describe "IO.select" do @wr.syswrite("be ready") IO.pipe do |_, wr| result = IO.select [@rd], [wr], nil, 0 + unless result + # On some platforms (e.g., Windows), pipe readiness may not be immediate + result = IO.select [@rd], [wr], nil, 2 + end result.should == [[@rd], [wr], []] end end @@ -91,28 +95,38 @@ describe "IO.select" do end it "raises TypeError if supplied objects are not IO" do - -> { IO.select([Object.new]) }.should raise_error(TypeError) - -> { IO.select(nil, [Object.new]) }.should raise_error(TypeError) + -> { IO.select([Object.new]) }.should.raise(TypeError) + -> { IO.select(nil, [Object.new]) }.should.raise(TypeError) obj = mock("io") obj.should_receive(:to_io).any_number_of_times.and_return(nil) - -> { IO.select([obj]) }.should raise_error(TypeError) - -> { IO.select(nil, [obj]) }.should raise_error(TypeError) + -> { IO.select([obj]) }.should.raise(TypeError) + -> { IO.select(nil, [obj]) }.should.raise(TypeError) end it "raises a TypeError if the specified timeout value is not Numeric" do - -> { IO.select([@rd], nil, nil, Object.new) }.should raise_error(TypeError) + -> { IO.select([@rd], nil, nil, Object.new) }.should.raise(TypeError) end it "raises TypeError if the first three arguments are not Arrays" do - -> { IO.select(Object.new)}.should raise_error(TypeError) - -> { IO.select(nil, Object.new)}.should raise_error(TypeError) - -> { IO.select(nil, nil, Object.new)}.should raise_error(TypeError) + -> { IO.select(Object.new)}.should.raise(TypeError) + -> { IO.select(nil, Object.new)}.should.raise(TypeError) + -> { IO.select(nil, nil, Object.new)}.should.raise(TypeError) end it "raises an ArgumentError when passed a negative timeout" do - -> { IO.select(nil, nil, nil, -5)}.should raise_error(ArgumentError) + -> { IO.select(nil, nil, nil, -5)}.should.raise(ArgumentError, "time interval must not be negative") + end + + ruby_version_is "4.0" do + it "raises an ArgumentError when passed negative infinity as timeout" do + -> { IO.select(nil, nil, nil, -Float::INFINITY)}.should.raise(ArgumentError, "time interval must not be negative") + end + end + + it "raises an RangeError when passed NaN as timeout" do + -> { IO.select(nil, nil, nil, Float::NAN)}.should.raise(RangeError, "NaN out of Time range") end describe "returns the available descriptors when the file descriptor" do @@ -149,16 +163,28 @@ describe "IO.select" do end end -describe "IO.select when passed nil for timeout" do - it "sleeps forever and sets the thread status to 'sleep'" do - t = Thread.new do - IO.select(nil, nil, nil, nil) +describe "IO.select with infinite timeout" do + describe :io_select_infinite_timeout, shared: true do + it "sleeps forever and sets the thread status to 'sleep'" do + t = Thread.new do + IO.select(nil, nil, nil, @method) + end + + Thread.pass while t.status && t.status != "sleep" + t.join unless t.status + t.status.should == "sleep" + t.kill + t.join end + end - Thread.pass while t.status && t.status != "sleep" - t.join unless t.status - t.status.should == "sleep" - t.kill - t.join + describe "IO.select when passed nil for timeout" do + it_behaves_like :io_select_infinite_timeout, nil + end + + ruby_version_is "4.0" do + describe "IO.select when passed Float::INFINITY for timeout" do + it_behaves_like :io_select_infinite_timeout, Float::INFINITY + end end end diff --git a/spec/ruby/core/io/set_encoding_by_bom_spec.rb b/spec/ruby/core/io/set_encoding_by_bom_spec.rb index 30d5ce5a5a..5436879f11 100644 --- a/spec/ruby/core/io/set_encoding_by_bom_spec.rb +++ b/spec/ruby/core/io/set_encoding_by_bom_spec.rb @@ -15,7 +15,7 @@ describe "IO#set_encoding_by_bom" do it "returns nil if not readable" do not_readable_io = new_io(@name, 'wb') - not_readable_io.set_encoding_by_bom.should be_nil + not_readable_io.set_encoding_by_bom.should == nil not_readable_io.external_encoding.should == Encoding::ASCII_8BIT ensure not_readable_io.close @@ -102,7 +102,7 @@ describe "IO#set_encoding_by_bom" do end it "returns nil if io is empty" do - @io.set_encoding_by_bom.should be_nil + @io.set_encoding_by_bom.should == nil @io.external_encoding.should == Encoding::ASCII_8BIT end @@ -243,7 +243,7 @@ describe "IO#set_encoding_by_bom" do it 'returns exception if io not in binary mode' do not_binary_io = new_io(@name, 'r') - -> { not_binary_io.set_encoding_by_bom }.should raise_error(ArgumentError, 'ASCII incompatible encoding needs binmode') + -> { not_binary_io.set_encoding_by_bom }.should.raise(ArgumentError, 'ASCII incompatible encoding needs binmode') ensure not_binary_io.close end @@ -251,12 +251,12 @@ describe "IO#set_encoding_by_bom" do it 'returns exception if encoding already set' do @io.set_encoding("utf-8") - -> { @io.set_encoding_by_bom }.should raise_error(ArgumentError, 'encoding is set to UTF-8 already') + -> { @io.set_encoding_by_bom }.should.raise(ArgumentError, 'encoding is set to UTF-8 already') end it 'returns exception if encoding conversion is already set' do @io.set_encoding(Encoding::UTF_8, Encoding::UTF_16BE) - -> { @io.set_encoding_by_bom }.should raise_error(ArgumentError, 'encoding conversion is set') + -> { @io.set_encoding_by_bom }.should.raise(ArgumentError, 'encoding conversion is set') end end diff --git a/spec/ruby/core/io/set_encoding_spec.rb b/spec/ruby/core/io/set_encoding_spec.rb index 22d9017635..237251de5b 100644 --- a/spec/ruby/core/io/set_encoding_spec.rb +++ b/spec/ruby/core/io/set_encoding_spec.rb @@ -5,21 +5,21 @@ describe :io_set_encoding_write, shared: true do @io = new_io @name, "#{@object}:ibm437:ibm866" @io.set_encoding nil, nil - @io.external_encoding.should be_nil - @io.internal_encoding.should be_nil + @io.external_encoding.should == nil + @io.internal_encoding.should == nil end it "sets the encodings to nil when the IO is built with no explicit encoding" do @io = new_io @name, @object # Checking our assumptions first - @io.external_encoding.should be_nil - @io.internal_encoding.should be_nil + @io.external_encoding.should == nil + @io.internal_encoding.should == nil @io.set_encoding nil, nil - @io.external_encoding.should be_nil - @io.internal_encoding.should be_nil + @io.external_encoding.should == nil + @io.internal_encoding.should == nil end it "prevents the encodings from changing when Encoding defaults are changed" do @@ -29,8 +29,8 @@ describe :io_set_encoding_write, shared: true do Encoding.default_external = Encoding::IBM437 Encoding.default_internal = Encoding::IBM866 - @io.external_encoding.should be_nil - @io.internal_encoding.should be_nil + @io.external_encoding.should == nil + @io.internal_encoding.should == nil end it "sets the encodings to the current Encoding defaults" do @@ -75,8 +75,8 @@ describe "IO#set_encoding when passed nil, nil" do Encoding.default_internal = Encoding::IBM866 @io.set_encoding nil, nil - @io.external_encoding.should equal(Encoding::IBM437) - @io.internal_encoding.should equal(Encoding::IBM866) + @io.external_encoding.should.equal?(Encoding::IBM437) + @io.internal_encoding.should.equal?(Encoding::IBM866) end it "prevents the #internal_encoding from changing when Encoding.default_internal is changed" do @@ -85,7 +85,7 @@ describe "IO#set_encoding when passed nil, nil" do Encoding.default_internal = Encoding::IBM437 - @io.internal_encoding.should be_nil + @io.internal_encoding.should == nil end it "allows the #external_encoding to change when Encoding.default_external is changed" do @@ -94,17 +94,17 @@ describe "IO#set_encoding when passed nil, nil" do Encoding.default_external = Encoding::IBM437 - @io.external_encoding.should equal(Encoding::IBM437) + @io.external_encoding.should.equal?(Encoding::IBM437) end end describe "with 'rb' mode" do it "returns Encoding.default_external" do @io = new_io @name, "rb" - @io.external_encoding.should equal(Encoding::BINARY) + @io.external_encoding.should.equal?(Encoding::BINARY) @io.set_encoding nil, nil - @io.external_encoding.should equal(Encoding.default_external) + @io.external_encoding.should.equal?(Encoding.default_external) end end @@ -158,13 +158,13 @@ describe "IO#set_encoding" do end it "returns self" do - @io.set_encoding(Encoding::UTF_8).should equal(@io) + @io.set_encoding(Encoding::UTF_8).should.equal?(@io) end it "sets the external encoding when passed an Encoding argument" do @io.set_encoding(Encoding::UTF_8) @io.external_encoding.should == Encoding::UTF_8 - @io.internal_encoding.should be_nil + @io.internal_encoding.should == nil end it "sets the external and internal encoding when passed two Encoding arguments" do @@ -176,19 +176,19 @@ describe "IO#set_encoding" do it "sets the external encoding when passed the name of an Encoding" do @io.set_encoding("utf-8") @io.external_encoding.should == Encoding::UTF_8 - @io.internal_encoding.should be_nil + @io.internal_encoding.should == nil end it "ignores the internal encoding if the same as external when passed Encoding objects" do @io.set_encoding(Encoding::UTF_8, Encoding::UTF_8) @io.external_encoding.should == Encoding::UTF_8 - @io.internal_encoding.should be_nil + @io.internal_encoding.should == nil end it "ignores the internal encoding if the same as external when passed encoding names separated by ':'" do @io.set_encoding("utf-8:utf-8") @io.external_encoding.should == Encoding::UTF_8 - @io.internal_encoding.should be_nil + @io.internal_encoding.should == nil end it "sets the external and internal encoding when passed the names of Encodings separated by ':'" do @@ -229,10 +229,10 @@ describe "IO#set_encoding" do end it "raises ArgumentError when no arguments are given" do - -> { @io.set_encoding() }.should raise_error(ArgumentError) + -> { @io.set_encoding() }.should.raise(ArgumentError) end it "raises ArgumentError when too many arguments are given" do - -> { @io.set_encoding(1, 2, 3) }.should raise_error(ArgumentError) + -> { @io.set_encoding(1, 2, 3) }.should.raise(ArgumentError) end end diff --git a/spec/ruby/core/io/shared/binwrite.rb b/spec/ruby/core/io/shared/binwrite.rb index e51093329b..64793b1936 100644 --- a/spec/ruby/core/io/shared/binwrite.rb +++ b/spec/ruby/core/io/shared/binwrite.rb @@ -26,7 +26,7 @@ describe :io_binwrite, shared: true do -> { IO.send(@method, @filename, "hi", 0, {flags: File::CREAT}) - }.should raise_error(ArgumentError, "wrong number of arguments (given 4, expected 2..3)") + }.should.raise(ArgumentError, "wrong number of arguments (given 4, expected 2..3)") end it "creates a file if missing" do @@ -81,7 +81,7 @@ describe :io_binwrite, shared: true do end it "raises an error if readonly mode is specified" do - -> { IO.send(@method, @filename, "abcde", mode: "r") }.should raise_error(IOError) + -> { IO.send(@method, @filename, "abcde", mode: "r") }.should.raise(IOError) end it "truncates if empty :opts provided and offset skipped" do diff --git a/spec/ruby/core/io/shared/chars.rb b/spec/ruby/core/io/shared/chars.rb index 266566f221..efd4d5ee10 100644 --- a/spec/ruby/core/io/shared/chars.rb +++ b/spec/ruby/core/io/shared/chars.rb @@ -24,7 +24,7 @@ describe :io_chars, shared: true do describe "when no block is given" do it "returns an Enumerator" do enum = @io.send(@method) - enum.should be_an_instance_of(Enumerator) + enum.should.instance_of?(Enumerator) enum.first(5).should == ["V", "o", "i", "c", "i"] end @@ -38,19 +38,19 @@ describe :io_chars, shared: true do end it "returns itself" do - @io.send(@method) { |c| }.should equal(@io) + @io.send(@method) { |c| }.should.equal?(@io) end it "returns an enumerator for a closed stream" do - IOSpecs.closed_io.send(@method).should be_an_instance_of(Enumerator) + IOSpecs.closed_io.send(@method).should.instance_of?(Enumerator) end it "raises an IOError when an enumerator created on a closed stream is accessed" do - -> { IOSpecs.closed_io.send(@method).first }.should raise_error(IOError) + -> { IOSpecs.closed_io.send(@method).first }.should.raise(IOError) end it "raises IOError on closed stream" do - -> { IOSpecs.closed_io.send(@method) {} }.should raise_error(IOError) + -> { IOSpecs.closed_io.send(@method) {} }.should.raise(IOError) end end diff --git a/spec/ruby/core/io/shared/codepoints.rb b/spec/ruby/core/io/shared/codepoints.rb index 6872846c1a..21c756986f 100644 --- a/spec/ruby/core/io/shared/codepoints.rb +++ b/spec/ruby/core/io/shared/codepoints.rb @@ -13,7 +13,7 @@ describe :io_codepoints, shared: true do describe "when no block is given" do it "returns an Enumerator" do - @enum.should be_an_instance_of(Enumerator) + @enum.should.instance_of?(Enumerator) end describe "returned Enumerator" do @@ -39,7 +39,7 @@ describe :io_codepoints, shared: true do it "raises an error if reading invalid sequence" do @io.pos = 60 # inside of a multibyte sequence - -> { @enum.first }.should raise_error(ArgumentError) + -> { @enum.first }.should.raise(ArgumentError) end it "does not change $_" do @@ -49,6 +49,6 @@ describe :io_codepoints, shared: true do end it "raises an IOError when self is not readable" do - -> { IOSpecs.closed_io.send(@method).to_a }.should raise_error(IOError) + -> { IOSpecs.closed_io.send(@method).to_a }.should.raise(IOError) end end diff --git a/spec/ruby/core/io/shared/each.rb b/spec/ruby/core/io/shared/each.rb index aca622834f..ae60c3506a 100644 --- a/spec/ruby/core/io/shared/each.rb +++ b/spec/ruby/core/io/shared/each.rb @@ -24,7 +24,7 @@ describe :io_each, shared: true do end it "returns self" do - @io.send(@method) { |l| l }.should equal(@io) + @io.send(@method) { |l| l }.should.equal?(@io) end it "does not change $_" do @@ -34,7 +34,7 @@ describe :io_each, shared: true do end it "raises an IOError when self is not readable" do - -> { IOSpecs.closed_io.send(@method) {} }.should raise_error(IOError) + -> { IOSpecs.closed_io.send(@method) {} }.should.raise(IOError) end it "makes line count accessible via lineno" do @@ -50,7 +50,7 @@ describe :io_each, shared: true do describe "when no block is given" do it "returns an Enumerator" do enum = @io.send(@method) - enum.should be_an_instance_of(Enumerator) + enum.should.instance_of?(Enumerator) enum.each { |l| ScratchPad << l } ScratchPad.recorded.should == IOSpecs.lines @@ -70,12 +70,12 @@ describe :io_each, shared: true do describe "when limit is 0" do it "raises an ArgumentError" do # must pass block so Enumerator is evaluated and raises - -> { @io.send(@method, 0){} }.should raise_error(ArgumentError) + -> { @io.send(@method, 0){} }.should.raise(ArgumentError) end end it "does not accept Integers that don't fit in a C off_t" do - -> { @io.send(@method, 2**128){} }.should raise_error(RangeError) + -> { @io.send(@method, 2**128){} }.should.raise(RangeError) end end @@ -126,7 +126,7 @@ describe :io_each, shared: true do describe "when no block is given" do it "returns an Enumerator" do enum = @io.send(@method, nil, 1024) - enum.should be_an_instance_of(Enumerator) + enum.should.instance_of?(Enumerator) enum.each { |l| ScratchPad << l } ScratchPad.recorded.should == [IOSpecs.lines.join] @@ -143,7 +143,7 @@ describe :io_each, shared: true do describe "when a block is given" do it "accepts an empty block" do - @io.send(@method, nil, 1024) {}.should equal(@io) + @io.send(@method, nil, 1024) {}.should.equal?(@io) end describe "when passed nil as a separator" do @@ -179,11 +179,11 @@ describe :io_each, shared: true do it "raises exception when options passed as Hash" do -> { @io.send(@method, { chomp: true }) { |s| } - }.should raise_error(TypeError) + }.should.raise(TypeError) -> { @io.send(@method, "\n", 1, { chomp: true }) { |s| } - }.should raise_error(ArgumentError, "wrong number of arguments (given 3, expected 0..2)") + }.should.raise(ArgumentError, "wrong number of arguments (given 3, expected 0..2)") end end @@ -202,20 +202,10 @@ describe :io_each, shared: true do end describe "when passed chomp and nil as a separator" do - ruby_version_is "3.2" do - it "yields self's content" do - @io.pos = 100 - @io.send(@method, nil, chomp: true) { |s| ScratchPad << s } - ScratchPad.recorded.should == ["qui a linha cinco.\nHere is line six.\n"] - end - end - - ruby_version_is ""..."3.2" do - it "yields self's content without trailing new line character" do - @io.pos = 100 - @io.send(@method, nil, chomp: true) { |s| ScratchPad << s } - ScratchPad.recorded.should == ["qui a linha cinco.\nHere is line six."] - end + it "yields self's content" do + @io.pos = 100 + @io.send(@method, nil, chomp: true) { |s| ScratchPad << s } + ScratchPad.recorded.should == ["qui a linha cinco.\nHere is line six.\n"] end end @@ -237,7 +227,7 @@ describe :io_each, shared: true do it "raises ArgumentError" do -> { @io.send(@method, "", 1, "excess argument", chomp: true) {} - }.should raise_error(ArgumentError) + }.should.raise(ArgumentError) end end end diff --git a/spec/ruby/core/io/shared/gets_ascii.rb b/spec/ruby/core/io/shared/gets_ascii.rb index 2a8fe3c9a5..2bd5470d99 100644 --- a/spec/ruby/core/io/shared/gets_ascii.rb +++ b/spec/ruby/core/io/shared/gets_ascii.rb @@ -1,4 +1,4 @@ -# -*- encoding: binary -*- +# encoding: binary describe :io_gets_ascii, shared: true do describe "with ASCII separator" do before :each do diff --git a/spec/ruby/core/io/shared/new.rb b/spec/ruby/core/io/shared/new.rb index cba5f33ebf..6f318ddee5 100644 --- a/spec/ruby/core/io/shared/new.rb +++ b/spec/ruby/core/io/shared/new.rb @@ -22,7 +22,7 @@ describe :io_new, shared: true do it "creates an IO instance from an Integer argument" do @io = IO.send(@method, @fd, "w") - @io.should be_an_instance_of(IO) + @io.should.instance_of?(IO) end it "creates an IO instance when STDOUT is closed" do @@ -32,7 +32,7 @@ describe :io_new, shared: true do begin @io = IO.send(@method, @fd, "w") - @io.should be_an_instance_of(IO) + @io.should.instance_of?(IO) ensure STDOUT = stdout rm_r stdout_file @@ -49,7 +49,7 @@ describe :io_new, shared: true do begin @io = IO.send(@method, @fd, "w") - @io.should be_an_instance_of(IO) + @io.should.instance_of?(IO) ensure STDERR = stderr rm_r stderr_file @@ -61,7 +61,7 @@ describe :io_new, shared: true do obj = mock("file descriptor") obj.should_receive(:to_int).and_return(@fd) @io = IO.send(@method, obj, "w") - @io.should be_an_instance_of(IO) + @io.should.instance_of?(IO) end it "accepts options as keyword arguments" do @@ -70,7 +70,7 @@ describe :io_new, shared: true do -> { IO.send(@method, @fd, "w", {flags: File::CREAT}) - }.should raise_error(ArgumentError, "wrong number of arguments (given 3, expected 1..2)") + }.should.raise(ArgumentError, "wrong number of arguments (given 3, expected 1..2)") end it "accepts a :mode option" do @@ -208,10 +208,30 @@ describe :io_new, shared: true do @io.internal_encoding.to_s.should == 'IBM866' end + it "does not use binary encoding when mode encoding is specified along with binmode: true option" do + @io = IO.send(@method, @fd, 'w:iso-8859-1', binmode: true) + @io.external_encoding.to_s.should == 'ISO-8859-1' + end + + it "does not use textmode argument when mode encoding is specified" do + @io = IO.send(@method, @fd, 'w:ascii-8bit', textmode: true) + @io.external_encoding.to_s.should == 'ASCII-8BIT' + end + + it "does not use binmode argument when external encoding is specified via the :external_encoding option" do + @io = IO.send(@method, @fd, 'w', binmode: true, external_encoding: 'iso-8859-1') + @io.external_encoding.to_s.should == 'ISO-8859-1' + end + + it "does not use textmode argument when external encoding is specified via the :external_encoding option" do + @io = IO.send(@method, @fd, 'w', textmode: true, external_encoding: 'ascii-8bit') + @io.external_encoding.to_s.should == 'ASCII-8BIT' + end + it "raises ArgumentError for nil options" do -> { IO.send(@method, @fd, 'w', nil) - }.should raise_error(ArgumentError) + }.should.raise(ArgumentError) end it "coerces mode with #to_str" do @@ -294,97 +314,100 @@ describe :io_new_errors, shared: true do end it "raises an Errno::EBADF if the file descriptor is not valid" do - -> { IO.send(@method, -1, "w") }.should raise_error(Errno::EBADF) + -> { IO.send(@method, -1, "w") }.should.raise(Errno::EBADF) end it "raises an IOError if passed a closed stream" do - -> { IO.send(@method, IOSpecs.closed_io.fileno, 'w') }.should raise_error(IOError) + -> { IO.send(@method, IOSpecs.closed_io.fileno, 'w') }.should.raise(IOError) end platform_is_not :windows do it "raises an Errno::EINVAL if the new mode is not compatible with the descriptor's current mode" do - -> { IO.send(@method, @fd, "r") }.should raise_error(Errno::EINVAL) + -> { IO.send(@method, @fd, "r") }.should.raise(Errno::EINVAL) end end it "raises ArgumentError if passed an empty mode string" do - -> { IO.send(@method, @fd, "") }.should raise_error(ArgumentError) + -> { IO.send(@method, @fd, "") }.should.raise(ArgumentError) end it "raises an error if passed modes two ways" do -> { IO.send(@method, @fd, "w", mode: "w") - }.should raise_error(ArgumentError) + }.should.raise(ArgumentError) end it "raises an error if passed encodings two ways" do -> { @io = IO.send(@method, @fd, 'w:ISO-8859-1', encoding: 'ISO-8859-1') - }.should raise_error(ArgumentError) + }.should.raise(ArgumentError) -> { @io = IO.send(@method, @fd, 'w:ISO-8859-1', external_encoding: 'ISO-8859-1') - }.should raise_error(ArgumentError) + }.should.raise(ArgumentError) + -> { + @io = IO.send(@method, @fd, 'w:ISO-8859-1', internal_encoding: 'ISO-8859-1') + }.should.raise(ArgumentError) -> { @io = IO.send(@method, @fd, 'w:ISO-8859-1:UTF-8', internal_encoding: 'ISO-8859-1') - }.should raise_error(ArgumentError) + }.should.raise(ArgumentError) end it "raises an error if passed matching binary/text mode two ways" do -> { @io = IO.send(@method, @fd, "wb", binmode: true) - }.should raise_error(ArgumentError) + }.should.raise(ArgumentError) -> { @io = IO.send(@method, @fd, "wt", textmode: true) - }.should raise_error(ArgumentError) + }.should.raise(ArgumentError) -> { @io = IO.send(@method, @fd, "wb", textmode: false) - }.should raise_error(ArgumentError) + }.should.raise(ArgumentError) -> { @io = IO.send(@method, @fd, "wt", binmode: false) - }.should raise_error(ArgumentError) + }.should.raise(ArgumentError) end it "raises an error if passed conflicting binary/text mode two ways" do -> { @io = IO.send(@method, @fd, "wb", binmode: false) - }.should raise_error(ArgumentError) + }.should.raise(ArgumentError) -> { @io = IO.send(@method, @fd, "wt", textmode: false) - }.should raise_error(ArgumentError) + }.should.raise(ArgumentError) -> { @io = IO.send(@method, @fd, "wb", textmode: true) - }.should raise_error(ArgumentError) + }.should.raise(ArgumentError) -> { @io = IO.send(@method, @fd, "wt", binmode: true) - }.should raise_error(ArgumentError) + }.should.raise(ArgumentError) end it "raises an error when trying to set both binmode and textmode" do -> { @io = IO.send(@method, @fd, "w", textmode: true, binmode: true) - }.should raise_error(ArgumentError) + }.should.raise(ArgumentError) -> { @io = IO.send(@method, @fd, File::Constants::WRONLY, textmode: true, binmode: true) - }.should raise_error(ArgumentError) + }.should.raise(ArgumentError) end it "raises ArgumentError if not passed a hash or nil for options" do -> { @io = IO.send(@method, @fd, 'w', false) - }.should raise_error(ArgumentError) + }.should.raise(ArgumentError) -> { @io = IO.send(@method, @fd, false, false) - }.should raise_error(ArgumentError) + }.should.raise(ArgumentError) -> { @io = IO.send(@method, @fd, nil, false) - }.should raise_error(ArgumentError) + }.should.raise(ArgumentError) end it "raises ArgumentError if passed a hash for mode and nil for options" do -> { @io = IO.send(@method, @fd, {mode: 'w'}, nil) - }.should raise_error(ArgumentError) + }.should.raise(ArgumentError) end end diff --git a/spec/ruby/core/io/shared/pos.rb b/spec/ruby/core/io/shared/pos.rb index 3fdd3eb2b3..f4d0405863 100644 --- a/spec/ruby/core/io/shared/pos.rb +++ b/spec/ruby/core/io/shared/pos.rb @@ -19,7 +19,7 @@ describe :io_pos, shared: true do end it "raises IOError on closed stream" do - -> { IOSpecs.closed_io.send(@method) }.should raise_error(IOError) + -> { IOSpecs.closed_io.send(@method) }.should.raise(IOError) end it "resets #eof?" do @@ -62,17 +62,17 @@ describe :io_set_pos, shared: true do it "raises TypeError when cannot convert implicitly argument to Integer" do File.open @fname do |io| - -> { io.send @method, Object.new }.should raise_error(TypeError, "no implicit conversion of Object into Integer") + -> { io.send @method, Object.new }.should.raise(TypeError, "no implicit conversion of Object into Integer") end end it "does not accept Integers that don't fit in a C off_t" do File.open @fname do |io| - -> { io.send @method, 2**128 }.should raise_error(RangeError) + -> { io.send @method, 2**128 }.should.raise(RangeError) end end it "raises IOError on closed stream" do - -> { IOSpecs.closed_io.send @method, 0 }.should raise_error(IOError) + -> { IOSpecs.closed_io.send @method, 0 }.should.raise(IOError) end end diff --git a/spec/ruby/core/io/shared/readlines.rb b/spec/ruby/core/io/shared/readlines.rb index 6c1fa11a59..f54fccc2e3 100644 --- a/spec/ruby/core/io/shared/readlines.rb +++ b/spec/ruby/core/io/shared/readlines.rb @@ -1,11 +1,11 @@ describe :io_readlines, shared: true do it "raises TypeError if the first parameter is nil" do - -> { IO.send(@method, nil, &@object) }.should raise_error(TypeError) + -> { IO.send(@method, nil, &@object) }.should.raise(TypeError) end it "raises an Errno::ENOENT if the file does not exist" do name = tmp("nonexistent.txt") - -> { IO.send(@method, name, &@object) }.should raise_error(Errno::ENOENT) + -> { IO.send(@method, name, &@object) }.should.raise(Errno::ENOENT) end it "yields a single string with entire content when the separator is nil" do @@ -80,14 +80,12 @@ describe :io_readlines_options_19, shared: true do end it "does not accept Integers that don't fit in a C off_t" do - -> { IO.send(@method, @name, 2**128, &@object) }.should raise_error(RangeError) + -> { IO.send(@method, @name, 2**128, &@object) }.should.raise(RangeError) end - ruby_bug "#18767", ""..."3.3" do - describe "when passed limit" do - it "raises ArgumentError when passed 0 as a limit" do - -> { IO.send(@method, @name, 0, &@object) }.should raise_error(ArgumentError) - end + describe "when passed limit" do + it "raises ArgumentError when passed 0 as a limit" do + -> { IO.send(@method, @name, 0, &@object) }.should.raise(ArgumentError) end end end @@ -108,7 +106,7 @@ describe :io_readlines_options_19, shared: true do it "raises TypeError exception" do -> { IO.send(@method, @name, { chomp: true }, &@object) - }.should raise_error(TypeError) + }.should.raise(TypeError) end end @@ -118,7 +116,7 @@ describe :io_readlines_options_19, shared: true do -> { IO.send(@method, @name, obj, &@object) - }.should raise_error(TypeError) + }.should.raise(TypeError) end end end @@ -172,7 +170,7 @@ describe :io_readlines_options_19, shared: true do -> { IO.send(@method, @name, " ", obj, &@object) - }.should raise_error(TypeError) + }.should.raise(TypeError) end end @@ -180,7 +178,7 @@ describe :io_readlines_options_19, shared: true do it "raises TypeError exception" do -> { IO.send(@method, @name, "", { chomp: true }, &@object) - }.should raise_error(TypeError) + }.should.raise(TypeError) end end end @@ -190,7 +188,7 @@ describe :io_readlines_options_19, shared: true do it "uses the keyword arguments as options" do -> do IO.send(@method, @filename, 10, mode: "w", &@object) - end.should raise_error(IOError) + end.should.raise(IOError) end end @@ -198,7 +196,7 @@ describe :io_readlines_options_19, shared: true do it "uses the keyword arguments as options" do -> do IO.send(@method, @filename, " ", mode: "w", &@object) - end.should raise_error(IOError) + end.should.raise(IOError) end end @@ -209,7 +207,7 @@ describe :io_readlines_options_19, shared: true do -> do IO.send(@method, @filename, sep, mode: "w", &@object) - end.should raise_error(IOError) + end.should.raise(IOError) end end end @@ -239,7 +237,7 @@ describe :io_readlines_options_19, shared: true do it "uses the keyword arguments as options" do -> do IO.send(@method, @filename, " ", 10, mode: "w", &@object) - end.should raise_error(IOError) + end.should.raise(IOError) end describe "when passed chomp, nil as a separator, and a limit" do diff --git a/spec/ruby/core/io/shared/tty.rb b/spec/ruby/core/io/shared/tty.rb index 89ac08ec86..1dc0e95739 100644 --- a/spec/ruby/core/io/shared/tty.rb +++ b/spec/ruby/core/io/shared/tty.rb @@ -19,6 +19,6 @@ describe :io_tty, shared: true do end it "raises IOError on closed stream" do - -> { IOSpecs.closed_io.send @method }.should raise_error(IOError) + -> { IOSpecs.closed_io.send @method }.should.raise(IOError) end end diff --git a/spec/ruby/core/io/shared/write.rb b/spec/ruby/core/io/shared/write.rb index 964064746a..5de9fe4335 100644 --- a/spec/ruby/core/io/shared/write.rb +++ b/spec/ruby/core/io/shared/write.rb @@ -23,7 +23,7 @@ describe :io_write, shared: true do end it "checks if the file is writable if writing more than zero bytes" do - -> { @readonly_file.send(@method, "abcde") }.should raise_error(IOError) + -> { @readonly_file.send(@method, "abcde") }.should.raise(IOError) end it "returns the number of bytes written" do @@ -66,7 +66,7 @@ describe :io_write, shared: true do end it "raises IOError on closed stream" do - -> { IOSpecs.closed_io.send(@method, "hello") }.should raise_error(IOError) + -> { IOSpecs.closed_io.send(@method, "hello") }.should.raise(IOError) end describe "on a pipe" do @@ -92,7 +92,7 @@ describe :io_write, shared: true do guard_not -> { defined?(RubyVM::RJIT) && RubyVM::RJIT.enabled? } do it "raises Errno::EPIPE if the read end is closed and does not die from SIGPIPE" do @r.close - -> { @w.send(@method, "foo") }.should raise_error(Errno::EPIPE, /Broken pipe/) + -> { @w.send(@method, "foo") }.should.raise(Errno::EPIPE, /Broken pipe/) end end end @@ -126,7 +126,7 @@ describe :io_write_transcode, shared: true do File.open(@transcode_filename, "w", external_encoding: Encoding::UTF_16BE) do |file| file.external_encoding.should == Encoding::UTF_16BE - -> { file.send(@method, str) }.should raise_error(Encoding::UndefinedConversionError) + -> { file.send(@method, str) }.should.raise(Encoding::UndefinedConversionError) end end end diff --git a/spec/ruby/core/io/stat_spec.rb b/spec/ruby/core/io/stat_spec.rb index 717c45d0a3..f9fc232ee0 100644 --- a/spec/ruby/core/io/stat_spec.rb +++ b/spec/ruby/core/io/stat_spec.rb @@ -12,14 +12,14 @@ describe "IO#stat" do end it "raises IOError on closed stream" do - -> { IOSpecs.closed_io.stat }.should raise_error(IOError) + -> { IOSpecs.closed_io.stat }.should.raise(IOError) end it "returns a File::Stat object for the stream" do - STDOUT.stat.should be_an_instance_of(File::Stat) + STDOUT.stat.should.instance_of?(File::Stat) end it "can stat pipes" do - @io.stat.should be_an_instance_of(File::Stat) + @io.stat.should.instance_of?(File::Stat) end end diff --git a/spec/ruby/core/io/sync_spec.rb b/spec/ruby/core/io/sync_spec.rb index 993b7ee244..b537db335b 100644 --- a/spec/ruby/core/io/sync_spec.rb +++ b/spec/ruby/core/io/sync_spec.rb @@ -27,7 +27,7 @@ describe "IO#sync=" do end it "raises an IOError on closed stream" do - -> { IOSpecs.closed_io.sync = true }.should raise_error(IOError) + -> { IOSpecs.closed_io.sync = true }.should.raise(IOError) end end @@ -45,7 +45,7 @@ describe "IO#sync" do end it "raises an IOError on closed stream" do - -> { IOSpecs.closed_io.sync }.should raise_error(IOError) + -> { IOSpecs.closed_io.sync }.should.raise(IOError) end end diff --git a/spec/ruby/core/io/sysopen_spec.rb b/spec/ruby/core/io/sysopen_spec.rb index 7ad379df3a..325d51ed23 100644 --- a/spec/ruby/core/io/sysopen_spec.rb +++ b/spec/ruby/core/io/sysopen_spec.rb @@ -13,16 +13,16 @@ describe "IO.sysopen" do it "returns the file descriptor for a given path" do @fd = IO.sysopen(@filename, "w") - @fd.should be_kind_of(Integer) - @fd.should_not equal(0) + @fd.should.is_a?(Integer) + @fd.should_not.equal?(0) end # opening a directory is not supported on Windows platform_is_not :windows do it "works on directories" do @fd = IO.sysopen(tmp("")) # /tmp - @fd.should be_kind_of(Integer) - @fd.should_not equal(0) + @fd.should.is_a?(Integer) + @fd.should_not.equal?(0) end end @@ -33,18 +33,18 @@ describe "IO.sysopen" do end it "accepts a mode as second argument" do - -> { @fd = IO.sysopen(@filename, "w") }.should_not raise_error - @fd.should_not equal(0) + -> { @fd = IO.sysopen(@filename, "w") }.should_not.raise + @fd.should_not.equal?(0) end it "accepts permissions as third argument" do @fd = IO.sysopen(@filename, "w", 777) - @fd.should_not equal(0) + @fd.should_not.equal?(0) end it "accepts mode & permission that are nil" do touch @filename # create the file @fd = IO.sysopen(@filename, nil, nil) - @fd.should_not equal(0) + @fd.should_not.equal?(0) end end diff --git a/spec/ruby/core/io/sysread_spec.rb b/spec/ruby/core/io/sysread_spec.rb index 8851214283..2d58db2250 100644 --- a/spec/ruby/core/io/sysread_spec.rb +++ b/spec/ruby/core/io/sysread_spec.rb @@ -52,7 +52,7 @@ describe "IO#sysread on a file" do it "raises an error when called after buffered reads" do @file.readline - -> { @file.sysread(5) }.should raise_error(IOError) + -> { @file.sysread(5) }.should.raise(IOError) end it "reads normally even when called immediately after a buffered IO#read" do @@ -63,13 +63,13 @@ describe "IO#sysread on a file" do it "does not raise error if called after IO#read followed by IO#write" do @file.read(5) @file.write("abcde") - -> { @file.sysread(5) }.should_not raise_error(IOError) + -> { @file.sysread(5) }.should_not.raise(IOError) end it "does not raise error if called after IO#read followed by IO#syswrite" do @file.read(5) @file.syswrite("abcde") - -> { @file.sysread(5) }.should_not raise_error(IOError) + -> { @file.sysread(5) }.should_not.raise(IOError) end it "reads updated content after the flushed buffered IO#write" do @@ -82,7 +82,7 @@ describe "IO#sysread on a file" do end it "raises IOError on closed stream" do - -> { IOSpecs.closed_io.sysread(5) }.should raise_error(IOError) + -> { IOSpecs.closed_io.sysread(5) }.should.raise(IOError) end it "immediately returns an empty string if the length argument is 0" do @@ -104,8 +104,8 @@ describe "IO#sysread on a file" do it "discards the existing buffer content upon error" do buffer = +"existing content" @file.seek(0, :END) - -> { @file.sysread(1, buffer) }.should raise_error(EOFError) - buffer.should be_empty + -> { @file.sysread(1, buffer) }.should.raise(EOFError) + buffer.should.empty? end it "preserves the encoding of the given buffer" do @@ -131,9 +131,7 @@ describe "IO#sysread" do @read.sysread(3).should == "ab" end - guard_not -> { platform_is :windows and ruby_version_is ""..."3.2" } do # https://bugs.ruby-lang.org/issues/18880 - it "raises ArgumentError when length is less than 0" do - -> { @read.sysread(-1) }.should raise_error(ArgumentError) - end + it "raises ArgumentError when length is less than 0" do + -> { @read.sysread(-1) }.should.raise(ArgumentError) end end diff --git a/spec/ruby/core/io/sysseek_spec.rb b/spec/ruby/core/io/sysseek_spec.rb index 002f2a14eb..2384895dc5 100644 --- a/spec/ruby/core/io/sysseek_spec.rb +++ b/spec/ruby/core/io/sysseek_spec.rb @@ -23,7 +23,7 @@ describe "IO#sysseek" do it "raises an error when called after buffered reads" do @io.readline - -> { @io.sysseek(-5, IO::SEEK_CUR) }.should raise_error(IOError) + -> { @io.sysseek(-5, IO::SEEK_CUR) }.should.raise(IOError) end it "seeks normally even when called immediately after a buffered IO#read" do @@ -41,7 +41,7 @@ describe "IO#sysseek" do # this is the safest way of checking the EOF when # sys-* methods are invoked - -> { @io.sysread(1) }.should raise_error(EOFError) + -> { @io.sysread(1) }.should.raise(EOFError) @io.sysseek(-25, IO::SEEK_END) @io.sysread(7).should == "cinco.\n" diff --git a/spec/ruby/core/io/to_i_spec.rb b/spec/ruby/core/io/to_i_spec.rb index acf138c663..1d0cf2a1f6 100644 --- a/spec/ruby/core/io/to_i_spec.rb +++ b/spec/ruby/core/io/to_i_spec.rb @@ -7,6 +7,6 @@ describe "IO#to_i" do end it "raises IOError on closed stream" do - -> { IOSpecs.closed_io.to_i }.should raise_error(IOError) + -> { IOSpecs.closed_io.to_i }.should.raise(IOError) end end diff --git a/spec/ruby/core/io/to_io_spec.rb b/spec/ruby/core/io/to_io_spec.rb index 55a0977740..0b1809dffa 100644 --- a/spec/ruby/core/io/to_io_spec.rb +++ b/spec/ruby/core/io/to_io_spec.rb @@ -11,11 +11,11 @@ describe "IO#to_io" do end it "returns self for open stream" do - @io.to_io.should equal(@io) + @io.to_io.should.equal?(@io) end it "returns self for closed stream" do io = IOSpecs.closed_io - io.to_io.should equal(io) + io.to_io.should.equal?(io) end end diff --git a/spec/ruby/core/io/try_convert_spec.rb b/spec/ruby/core/io/try_convert_spec.rb index a9e99de7aa..7600b01b75 100644 --- a/spec/ruby/core/io/try_convert_spec.rb +++ b/spec/ruby/core/io/try_convert_spec.rb @@ -13,7 +13,7 @@ describe "IO.try_convert" do end it "returns the passed IO object" do - IO.try_convert(@io).should equal(@io) + IO.try_convert(@io).should.equal?(@io) end it "does not call #to_io on an IO instance" do @@ -24,26 +24,26 @@ describe "IO.try_convert" do it "calls #to_io to coerce an object" do obj = mock("io") obj.should_receive(:to_io).and_return(@io) - IO.try_convert(obj).should equal(@io) + IO.try_convert(obj).should.equal?(@io) end it "returns nil when the passed object does not respond to #to_io" do - IO.try_convert(mock("io")).should be_nil + IO.try_convert(mock("io")).should == nil end it "return nil when BasicObject is passed" do - IO.try_convert(BasicObject.new).should be_nil + IO.try_convert(BasicObject.new).should == nil end it "raises a TypeError if the object does not return an IO from #to_io" do obj = mock("io") obj.should_receive(:to_io).and_return("io") - -> { IO.try_convert(obj) }.should raise_error(TypeError, "can't convert MockObject to IO (MockObject#to_io gives String)") + -> { IO.try_convert(obj) }.should raise_consistent_error(TypeError, "can't convert MockObject into IO (MockObject#to_io gives String)") end it "propagates an exception raised by #to_io" do obj = mock("io") obj.should_receive(:to_io).and_raise(TypeError.new) - ->{ IO.try_convert(obj) }.should raise_error(TypeError) + ->{ IO.try_convert(obj) }.should.raise(TypeError) end end diff --git a/spec/ruby/core/io/ungetbyte_spec.rb b/spec/ruby/core/io/ungetbyte_spec.rb index 716743a6af..e0615cd76c 100644 --- a/spec/ruby/core/io/ungetbyte_spec.rb +++ b/spec/ruby/core/io/ungetbyte_spec.rb @@ -13,12 +13,12 @@ describe "IO#ungetbyte" do end it "does nothing when passed nil" do - @io.ungetbyte(nil).should be_nil + @io.ungetbyte(nil).should == nil @io.getbyte.should == 97 end it "puts back each byte in a String argument" do - @io.ungetbyte("cat").should be_nil + @io.ungetbyte("cat").should == nil @io.getbyte.should == 99 @io.getbyte.should == 97 @io.getbyte.should == 116 @@ -29,7 +29,7 @@ describe "IO#ungetbyte" do str = mock("io ungetbyte") str.should_receive(:to_str).and_return("dog") - @io.ungetbyte(str).should be_nil + @io.ungetbyte(str).should == nil @io.getbyte.should == 100 @io.getbyte.should == 111 @io.getbyte.should == 103 @@ -38,17 +38,17 @@ describe "IO#ungetbyte" do it "never raises RangeError" do for i in [4095, 0x4f7574206f6620636861722072616e67ff] do - @io.ungetbyte(i).should be_nil + @io.ungetbyte(i).should == nil @io.getbyte.should == 255 end end it "raises IOError on stream not opened for reading" do - -> { STDOUT.ungetbyte(42) }.should raise_error(IOError, "not opened for reading") + -> { STDOUT.ungetbyte(42) }.should.raise(IOError, "not opened for reading") end it "raises an IOError if the IO is closed" do @io.close - -> { @io.ungetbyte(42) }.should raise_error(IOError) + -> { @io.ungetbyte(42) }.should.raise(IOError) end end diff --git a/spec/ruby/core/io/ungetc_spec.rb b/spec/ruby/core/io/ungetc_spec.rb index 47a4e99ebf..4a9e67f126 100644 --- a/spec/ruby/core/io/ungetc_spec.rb +++ b/spec/ruby/core/io/ungetc_spec.rb @@ -100,17 +100,17 @@ describe "IO#ungetc" do it "makes subsequent unbuffered operations to raise IOError" do @io.getc @io.ungetc(100) - -> { @io.sysread(1) }.should raise_error(IOError) + -> { @io.sysread(1) }.should.raise(IOError) end it "raises TypeError if passed nil" do @io.getc.should == ?V - proc{@io.ungetc(nil)}.should raise_error(TypeError) + proc{@io.ungetc(nil)}.should.raise(TypeError) end it "puts one or more characters back in the stream" do @io.gets - @io.ungetc("Aquí ").should be_nil + @io.ungetc("Aquí ").should == nil @io.gets.chomp.should == "Aquí Qui è la linea due." end @@ -118,21 +118,21 @@ describe "IO#ungetc" do chars = mock("io ungetc") chars.should_receive(:to_str).and_return("Aquí ") - @io.ungetc(chars).should be_nil + @io.ungetc(chars).should == nil @io.gets.chomp.should == "Aquí Voici la ligne une." end it "returns nil when invoked on stream that was not yet read" do - @io.ungetc(100).should be_nil + @io.ungetc(100).should == nil end it "raises IOError on stream not opened for reading" do - -> { STDOUT.ungetc(100) }.should raise_error(IOError, "not opened for reading") + -> { STDOUT.ungetc(100) }.should.raise(IOError, "not opened for reading") end it "raises IOError on closed stream" do @io.getc @io.close - -> { @io.ungetc(100) }.should raise_error(IOError) + -> { @io.ungetc(100) }.should.raise(IOError) end end diff --git a/spec/ruby/core/io/write_nonblock_spec.rb b/spec/ruby/core/io/write_nonblock_spec.rb index 5bfc690f9b..a6bd43c058 100644 --- a/spec/ruby/core/io/write_nonblock_spec.rb +++ b/spec/ruby/core/io/write_nonblock_spec.rb @@ -44,7 +44,7 @@ platform_is_not :windows do it "checks if the file is writable if writing zero bytes" do -> { @readonly_file.write_nonblock("") - }.should raise_error(IOError) + }.should.raise(IOError) end end @@ -67,12 +67,12 @@ describe 'IO#write_nonblock' do it "raises an exception extending IO::WaitWritable when the write would block" do -> { loop { @write.write_nonblock('a' * 10_000) } - }.should raise_error(IO::WaitWritable) { |e| + }.should.raise(IO::WaitWritable) { |e| platform_is_not :windows do - e.should be_kind_of(Errno::EAGAIN) + e.should.is_a?(Errno::EAGAIN) end platform_is :windows do - e.should be_kind_of(Errno::EWOULDBLOCK) + e.should.is_a?(Errno::EWOULDBLOCK) end } end diff --git a/spec/ruby/core/io/write_spec.rb b/spec/ruby/core/io/write_spec.rb index 4a26f8dbaf..1a745ba012 100644 --- a/spec/ruby/core/io/write_spec.rb +++ b/spec/ruby/core/io/write_spec.rb @@ -21,7 +21,7 @@ describe "IO#write on a file" do end it "does not check if the file is writable if writing zero bytes" do - -> { @readonly_file.write("") }.should_not raise_error + -> { @readonly_file.write("") }.should_not.raise end before :each do @@ -102,11 +102,18 @@ describe "IO#write on a file" do File.binread(@filename).should == "h\u0000\u0000\u0000i\u0000\u0000\u0000" end + it "ignores the 'bom|' prefix" do + File.open(@filename, "w", encoding: 'bom|utf-8') do |file| + file.write("hi") + end + File.binread(@filename).should == "hi" + end + it "raises a invalid byte sequence error if invalid bytes are being written" do # pack "\xFEhi" to avoid utf-8 conflict xFEhi = ([254].pack('C*') + 'hi').force_encoding('utf-8') File.open(@filename, "w", encoding: Encoding::US_ASCII) do |file| - -> { file.write(xFEhi) }.should raise_error(Encoding::InvalidByteSequenceError) + -> { file.write(xFEhi) }.should.raise(Encoding::InvalidByteSequenceError) end end @@ -150,7 +157,7 @@ describe "IO.write" do it "requires mode to be specified in :open_args" do -> { IO.write(@filename, 'hi', open_args: [{encoding: Encoding::UTF_32LE, binmode: true}]) - }.should raise_error(IOError, "not opened for writing") + }.should.raise(IOError, "not opened for writing") IO.write(@filename, 'hi', open_args: ["w", {encoding: Encoding::UTF_32LE, binmode: true}]).should == 8 IO.write(@filename, 'hi', open_args: [{encoding: Encoding::UTF_32LE, binmode: true, mode: "w"}]).should == 8 @@ -159,7 +166,7 @@ describe "IO.write" do it "requires mode to be specified in :open_args even if flags option passed" do -> { IO.write(@filename, 'hi', open_args: [{encoding: Encoding::UTF_32LE, binmode: true, flags: File::CREAT}]) - }.should raise_error(IOError, "not opened for writing") + }.should.raise(IOError, "not opened for writing") IO.write(@filename, 'hi', open_args: ["w", {encoding: Encoding::UTF_32LE, binmode: true, flags: File::CREAT}]).should == 8 IO.write(@filename, 'hi', open_args: [{encoding: Encoding::UTF_32LE, binmode: true, flags: File::CREAT, mode: "w"}]).should == 8 @@ -172,11 +179,11 @@ describe "IO.write" do it "raises ArgumentError if encoding is specified in mode parameter and is given as :encoding option" do -> { IO.write(@filename, 'hi', mode: "w:UTF-16LE:UTF-16BE", encoding: Encoding::UTF_32LE) - }.should raise_error(ArgumentError, "encoding specified twice") + }.should.raise(ArgumentError, "encoding specified twice") -> { IO.write(@filename, 'hi', mode: "w:UTF-16BE", encoding: Encoding::UTF_32LE) - }.should raise_error(ArgumentError, "encoding specified twice") + }.should.raise(ArgumentError, "encoding specified twice") end it "writes the file with the permissions in the :perm parameter" do @@ -220,7 +227,7 @@ describe "IO.write" do end end - ruby_version_is "3.3" do + ruby_version_is ""..."4.0" do # https://bugs.ruby-lang.org/issues/19630 it "warns about deprecation given a path with a pipe" do -> { |
