summaryrefslogtreecommitdiff
path: root/spec/ruby/library/stringio
diff options
context:
space:
mode:
Diffstat (limited to 'spec/ruby/library/stringio')
-rw-r--r--spec/ruby/library/stringio/append_spec.rb22
-rw-r--r--spec/ruby/library/stringio/binmode_spec.rb16
-rw-r--r--spec/ruby/library/stringio/bytes_spec.rb11
-rw-r--r--spec/ruby/library/stringio/chars_spec.rb11
-rw-r--r--spec/ruby/library/stringio/close_read_spec.rb8
-rw-r--r--spec/ruby/library/stringio/close_spec.rb6
-rw-r--r--spec/ruby/library/stringio/close_write_spec.rb10
-rw-r--r--spec/ruby/library/stringio/closed_read_spec.rb2
-rw-r--r--spec/ruby/library/stringio/closed_spec.rb4
-rw-r--r--spec/ruby/library/stringio/closed_write_spec.rb2
-rw-r--r--spec/ruby/library/stringio/codepoints_spec.rb9
-rw-r--r--spec/ruby/library/stringio/each_char_spec.rb2
-rw-r--r--spec/ruby/library/stringio/each_codepoint_spec.rb2
-rw-r--r--spec/ruby/library/stringio/each_line_spec.rb8
-rw-r--r--spec/ruby/library/stringio/each_spec.rb12
-rw-r--r--spec/ruby/library/stringio/fcntl_spec.rb2
-rw-r--r--spec/ruby/library/stringio/fileno_spec.rb3
-rw-r--r--spec/ruby/library/stringio/fixtures/classes.rb4
-rw-r--r--spec/ruby/library/stringio/flush_spec.rb2
-rw-r--r--spec/ruby/library/stringio/fsync_spec.rb2
-rw-r--r--spec/ruby/library/stringio/getpass_spec.rb11
-rw-r--r--spec/ruby/library/stringio/gets_spec.rb258
-rw-r--r--spec/ruby/library/stringio/initialize_spec.rb185
-rw-r--r--spec/ruby/library/stringio/inspect_spec.rb19
-rw-r--r--spec/ruby/library/stringio/lines_spec.rb19
-rw-r--r--spec/ruby/library/stringio/new_spec.rb10
-rw-r--r--spec/ruby/library/stringio/open_spec.rb78
-rw-r--r--spec/ruby/library/stringio/path_spec.rb2
-rw-r--r--spec/ruby/library/stringio/pos_spec.rb2
-rw-r--r--spec/ruby/library/stringio/print_spec.rb22
-rw-r--r--spec/ruby/library/stringio/printf_spec.rb41
-rw-r--r--spec/ruby/library/stringio/putc_spec.rb31
-rw-r--r--spec/ruby/library/stringio/puts_spec.rb41
-rw-r--r--spec/ruby/library/stringio/read_nonblock_spec.rb13
-rw-r--r--spec/ruby/library/stringio/read_spec.rb2
-rw-r--r--spec/ruby/library/stringio/readline_spec.rb139
-rw-r--r--spec/ruby/library/stringio/readlines_spec.rb29
-rw-r--r--spec/ruby/library/stringio/readpartial_spec.rb48
-rw-r--r--spec/ruby/library/stringio/reopen_spec.rb99
-rw-r--r--spec/ruby/library/stringio/seek_spec.rb14
-rw-r--r--spec/ruby/library/stringio/set_encoding_by_bom_spec.rb237
-rw-r--r--spec/ruby/library/stringio/set_encoding_spec.rb8
-rw-r--r--spec/ruby/library/stringio/shared/codepoints.rb8
-rw-r--r--spec/ruby/library/stringio/shared/each.rb109
-rw-r--r--spec/ruby/library/stringio/shared/each_byte.rb6
-rw-r--r--spec/ruby/library/stringio/shared/each_char.rb6
-rw-r--r--spec/ruby/library/stringio/shared/getc.rb6
-rw-r--r--spec/ruby/library/stringio/shared/gets.rb249
-rw-r--r--spec/ruby/library/stringio/shared/isatty.rb2
-rw-r--r--spec/ruby/library/stringio/shared/read.rb50
-rw-r--r--spec/ruby/library/stringio/shared/readchar.rb8
-rw-r--r--spec/ruby/library/stringio/shared/sysread.rb4
-rw-r--r--spec/ruby/library/stringio/shared/write.rb74
-rw-r--r--spec/ruby/library/stringio/string_spec.rb2
-rw-r--r--spec/ruby/library/stringio/sysread_spec.rb7
-rw-r--r--spec/ruby/library/stringio/truncate_spec.rb30
-rw-r--r--spec/ruby/library/stringio/ungetbyte_spec.rb38
-rw-r--r--spec/ruby/library/stringio/ungetc_spec.rb16
-rw-r--r--spec/ruby/library/stringio/write_nonblock_spec.rb6
59 files changed, 1361 insertions, 706 deletions
diff --git a/spec/ruby/library/stringio/append_spec.rb b/spec/ruby/library/stringio/append_spec.rb
index 08500bc520..cb50d73d1b 100644
--- a/spec/ruby/library/stringio/append_spec.rb
+++ b/spec/ruby/library/stringio/append_spec.rb
@@ -3,7 +3,7 @@ require_relative 'fixtures/classes'
describe "StringIO#<< when passed [Object]" do
before :each do
- @io = StringIO.new("example")
+ @io = StringIO.new(+"example")
end
it "returns self" do
@@ -29,16 +29,6 @@ describe "StringIO#<< when passed [Object]" do
@io.string.should == "example\000\000\000\000\000\000\000\000just testing"
end
- it "taints self's String when the passed argument is tainted" do
- (@io << "test".taint)
- @io.string.tainted?.should be_true
- end
-
- it "does not taint self when the passed argument is tainted" do
- (@io << "test".taint)
- @io.tainted?.should be_false
- end
-
it "updates self's position" do
@io << "test"
@io.pos.should eql(4)
@@ -54,18 +44,18 @@ end
describe "StringIO#<< when self is not writable" do
it "raises an IOError" do
- io = StringIO.new("test", "r")
- lambda { io << "test" }.should raise_error(IOError)
+ io = StringIO.new(+"test", "r")
+ -> { io << "test" }.should raise_error(IOError)
- io = StringIO.new("test")
+ io = StringIO.new(+"test")
io.close_write
- lambda { io << "test" }.should raise_error(IOError)
+ -> { io << "test" }.should raise_error(IOError)
end
end
describe "StringIO#<< when in append mode" do
before :each do
- @io = StringIO.new("example", "a")
+ @io = StringIO.new(+"example", "a")
end
it "appends the passed argument to the end of self, ignoring current position" do
diff --git a/spec/ruby/library/stringio/binmode_spec.rb b/spec/ruby/library/stringio/binmode_spec.rb
index 5d9a8c41df..9e92c63814 100644
--- a/spec/ruby/library/stringio/binmode_spec.rb
+++ b/spec/ruby/library/stringio/binmode_spec.rb
@@ -3,7 +3,21 @@ require_relative 'fixtures/classes'
describe "StringIO#binmode" do
it "returns self" do
- io = StringIO.new("example")
+ io = StringIO.new(+"example")
io.binmode.should equal(io)
end
+
+ it "changes external encoding to BINARY" do
+ io = StringIO.new
+ io.external_encoding.should == Encoding.find('external')
+ io.binmode
+ io.external_encoding.should == Encoding::BINARY
+ end
+
+ it "does not set internal encoding" do
+ io = StringIO.new
+ io.internal_encoding.should == nil
+ io.binmode
+ io.internal_encoding.should == nil
+ end
end
diff --git a/spec/ruby/library/stringio/bytes_spec.rb b/spec/ruby/library/stringio/bytes_spec.rb
deleted file mode 100644
index 692fba997f..0000000000
--- a/spec/ruby/library/stringio/bytes_spec.rb
+++ /dev/null
@@ -1,11 +0,0 @@
-require_relative '../../spec_helper'
-require 'stringio'
-require_relative 'shared/each_byte'
-
-describe "StringIO#bytes" do
- it_behaves_like :stringio_each_byte, :bytes
-end
-
-describe "StringIO#bytes when self is not readable" do
- it_behaves_like :stringio_each_byte_not_readable, :bytes
-end
diff --git a/spec/ruby/library/stringio/chars_spec.rb b/spec/ruby/library/stringio/chars_spec.rb
deleted file mode 100644
index 7dc55d4b37..0000000000
--- a/spec/ruby/library/stringio/chars_spec.rb
+++ /dev/null
@@ -1,11 +0,0 @@
-require_relative '../../spec_helper'
-require 'stringio'
-require_relative 'shared/each_char'
-
-describe "StringIO#chars" do
- it_behaves_like :stringio_each_char, :chars
-end
-
-describe "StringIO#chars when self is not readable" do
- it_behaves_like :stringio_each_char_not_readable, :chars
-end
diff --git a/spec/ruby/library/stringio/close_read_spec.rb b/spec/ruby/library/stringio/close_read_spec.rb
index 05d6c9f7d2..0f08e1ff2e 100644
--- a/spec/ruby/library/stringio/close_read_spec.rb
+++ b/spec/ruby/library/stringio/close_read_spec.rb
@@ -3,7 +3,7 @@ require_relative 'fixtures/classes'
describe "StringIO#close_read" do
before :each do
- @io = StringIO.new("example")
+ @io = StringIO.new(+"example")
end
it "returns nil" do
@@ -12,7 +12,7 @@ describe "StringIO#close_read" do
it "prevents further reading" do
@io.close_read
- lambda { @io.read(1) }.should raise_error(IOError)
+ -> { @io.read(1) }.should raise_error(IOError)
end
it "allows further writing" do
@@ -21,8 +21,8 @@ describe "StringIO#close_read" do
end
it "raises an IOError when in write-only mode" do
- io = StringIO.new("example", "w")
- lambda { io.close_read }.should raise_error(IOError)
+ io = StringIO.new(+"example", "w")
+ -> { io.close_read }.should raise_error(IOError)
io = StringIO.new("example")
io.close_read
diff --git a/spec/ruby/library/stringio/close_spec.rb b/spec/ruby/library/stringio/close_spec.rb
index a5a931aff1..520a8de782 100644
--- a/spec/ruby/library/stringio/close_spec.rb
+++ b/spec/ruby/library/stringio/close_spec.rb
@@ -12,12 +12,12 @@ describe "StringIO#close" do
it "prevents further reading and/or writing" do
@io.close
- lambda { @io.read(1) }.should raise_error(IOError)
- lambda { @io.write('x') }.should raise_error(IOError)
+ -> { @io.read(1) }.should raise_error(IOError)
+ -> { @io.write('x') }.should raise_error(IOError)
end
it "does not raise anything when self was already closed" do
@io.close
- lambda { @io.close }.should_not raise_error(IOError)
+ -> { @io.close }.should_not raise_error(IOError)
end
end
diff --git a/spec/ruby/library/stringio/close_write_spec.rb b/spec/ruby/library/stringio/close_write_spec.rb
index 8a7ac12581..c86c3f9826 100644
--- a/spec/ruby/library/stringio/close_write_spec.rb
+++ b/spec/ruby/library/stringio/close_write_spec.rb
@@ -3,7 +3,7 @@ require_relative 'fixtures/classes'
describe "StringIO#close_write" do
before :each do
- @io = StringIO.new("example")
+ @io = StringIO.new(+"example")
end
it "returns nil" do
@@ -12,7 +12,7 @@ describe "StringIO#close_write" do
it "prevents further writing" do
@io.close_write
- lambda { @io.write('x') }.should raise_error(IOError)
+ -> { @io.write('x') }.should raise_error(IOError)
end
it "allows further reading" do
@@ -21,10 +21,10 @@ describe "StringIO#close_write" do
end
it "raises an IOError when in read-only mode" do
- io = StringIO.new("example", "r")
- lambda { io.close_write }.should raise_error(IOError)
+ io = StringIO.new(+"example", "r")
+ -> { io.close_write }.should raise_error(IOError)
- io = StringIO.new("example")
+ io = StringIO.new(+"example")
io.close_write
io.close_write.should == nil
end
diff --git a/spec/ruby/library/stringio/closed_read_spec.rb b/spec/ruby/library/stringio/closed_read_spec.rb
index cb4267ac98..b4dcadc3a4 100644
--- a/spec/ruby/library/stringio/closed_read_spec.rb
+++ b/spec/ruby/library/stringio/closed_read_spec.rb
@@ -3,7 +3,7 @@ require_relative 'fixtures/classes'
describe "StringIO#closed_read?" do
it "returns true if self is not readable" do
- io = StringIO.new("example", "r+")
+ io = StringIO.new(+"example", "r+")
io.close_write
io.closed_read?.should be_false
io.close_read
diff --git a/spec/ruby/library/stringio/closed_spec.rb b/spec/ruby/library/stringio/closed_spec.rb
index ca8a2232a8..bf7ba63184 100644
--- a/spec/ruby/library/stringio/closed_spec.rb
+++ b/spec/ruby/library/stringio/closed_spec.rb
@@ -3,13 +3,13 @@ require_relative 'fixtures/classes'
describe "StringIO#closed?" do
it "returns true if self is completely closed" do
- io = StringIO.new("example", "r+")
+ io = StringIO.new(+"example", "r+")
io.close_read
io.closed?.should be_false
io.close_write
io.closed?.should be_true
- io = StringIO.new("example", "r+")
+ io = StringIO.new(+"example", "r+")
io.close
io.closed?.should be_true
end
diff --git a/spec/ruby/library/stringio/closed_write_spec.rb b/spec/ruby/library/stringio/closed_write_spec.rb
index 5c111affd8..2bd3e6fa8b 100644
--- a/spec/ruby/library/stringio/closed_write_spec.rb
+++ b/spec/ruby/library/stringio/closed_write_spec.rb
@@ -3,7 +3,7 @@ require_relative 'fixtures/classes'
describe "StringIO#closed_write?" do
it "returns true if self is not writable" do
- io = StringIO.new("example", "r+")
+ io = StringIO.new(+"example", "r+")
io.close_read
io.closed_write?.should be_false
io.close_write
diff --git a/spec/ruby/library/stringio/codepoints_spec.rb b/spec/ruby/library/stringio/codepoints_spec.rb
deleted file mode 100644
index cc2e5d1b5d..0000000000
--- a/spec/ruby/library/stringio/codepoints_spec.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# -*- encoding: utf-8 -*-
-require_relative '../../spec_helper'
-require_relative 'fixtures/classes'
-require_relative 'shared/codepoints'
-
-# See redmine #1667
-describe "StringIO#codepoints" do
- it_behaves_like :stringio_codepoints, :codepoints
-end
diff --git a/spec/ruby/library/stringio/each_char_spec.rb b/spec/ruby/library/stringio/each_char_spec.rb
index 7305162ee6..14b2f09a17 100644
--- a/spec/ruby/library/stringio/each_char_spec.rb
+++ b/spec/ruby/library/stringio/each_char_spec.rb
@@ -7,5 +7,5 @@ describe "StringIO#each_char" do
end
describe "StringIO#each_char when self is not readable" do
- it_behaves_like :stringio_each_char_not_readable, :chars
+ it_behaves_like :stringio_each_char_not_readable, :each_char
end
diff --git a/spec/ruby/library/stringio/each_codepoint_spec.rb b/spec/ruby/library/stringio/each_codepoint_spec.rb
index 85aa34d9d8..f18de22aad 100644
--- a/spec/ruby/library/stringio/each_codepoint_spec.rb
+++ b/spec/ruby/library/stringio/each_codepoint_spec.rb
@@ -5,5 +5,5 @@ require_relative 'shared/codepoints'
# See redmine #1667
describe "StringIO#each_codepoint" do
- it_behaves_like :stringio_codepoints, :codepoints
+ it_behaves_like :stringio_codepoints, :each_codepoint
end
diff --git a/spec/ruby/library/stringio/each_line_spec.rb b/spec/ruby/library/stringio/each_line_spec.rb
index 1389408399..4ac0db7c45 100644
--- a/spec/ruby/library/stringio/each_line_spec.rb
+++ b/spec/ruby/library/stringio/each_line_spec.rb
@@ -17,3 +17,11 @@ end
describe "StringIO#each_line when passed chomp" do
it_behaves_like :stringio_each_chomp, :each_line
end
+
+describe "StringIO#each_line when passed limit" do
+ it_behaves_like :stringio_each_limit, :each_line
+end
+
+describe "StringIO#each when passed separator and limit" do
+ it_behaves_like :stringio_each_separator_and_limit, :each_line
+end
diff --git a/spec/ruby/library/stringio/each_spec.rb b/spec/ruby/library/stringio/each_spec.rb
index a76460049b..7eb322f3ff 100644
--- a/spec/ruby/library/stringio/each_spec.rb
+++ b/spec/ruby/library/stringio/each_spec.rb
@@ -17,3 +17,15 @@ end
describe "StringIO#each when passed chomp" do
it_behaves_like :stringio_each_chomp, :each
end
+
+describe "StringIO#each when passed chomp" do
+ it_behaves_like :stringio_each_separator_and_chomp, :each
+end
+
+describe "StringIO#each when passed limit" do
+ it_behaves_like :stringio_each_limit, :each
+end
+
+describe "StringIO#each when passed separator and limit" do
+ it_behaves_like :stringio_each_separator_and_limit, :each
+end
diff --git a/spec/ruby/library/stringio/fcntl_spec.rb b/spec/ruby/library/stringio/fcntl_spec.rb
index e4133c0d06..a78004d868 100644
--- a/spec/ruby/library/stringio/fcntl_spec.rb
+++ b/spec/ruby/library/stringio/fcntl_spec.rb
@@ -3,6 +3,6 @@ require_relative 'fixtures/classes'
describe "StringIO#fcntl" do
it "raises a NotImplementedError" do
- lambda { StringIO.new("boom").fcntl }.should raise_error(NotImplementedError)
+ -> { StringIO.new("boom").fcntl }.should raise_error(NotImplementedError)
end
end
diff --git a/spec/ruby/library/stringio/fileno_spec.rb b/spec/ruby/library/stringio/fileno_spec.rb
index eea03a5af3..5a9f440a0f 100644
--- a/spec/ruby/library/stringio/fileno_spec.rb
+++ b/spec/ruby/library/stringio/fileno_spec.rb
@@ -1,6 +1,5 @@
require_relative '../../spec_helper'
-require_relative 'fixtures/classes'
-require_relative 'shared/each'
+require 'stringio'
describe "StringIO#fileno" do
it "returns nil" do
diff --git a/spec/ruby/library/stringio/fixtures/classes.rb b/spec/ruby/library/stringio/fixtures/classes.rb
index bb8dc354cc..832c5457d7 100644
--- a/spec/ruby/library/stringio/fixtures/classes.rb
+++ b/spec/ruby/library/stringio/fixtures/classes.rb
@@ -4,12 +4,12 @@ class StringSubclass < String; end
module StringIOSpecs
def self.build
- str = <<-EOS
+ str = <<-EOS
each
peach
pear
plum
- EOS
+ EOS
StringIO.new(str)
end
end
diff --git a/spec/ruby/library/stringio/flush_spec.rb b/spec/ruby/library/stringio/flush_spec.rb
index 17a16dfdd5..4dc58b1d48 100644
--- a/spec/ruby/library/stringio/flush_spec.rb
+++ b/spec/ruby/library/stringio/flush_spec.rb
@@ -3,7 +3,7 @@ require_relative 'fixtures/classes'
describe "StringIO#flush" do
it "returns self" do
- io = StringIO.new("flush")
+ io = StringIO.new(+"flush")
io.flush.should equal(io)
end
end
diff --git a/spec/ruby/library/stringio/fsync_spec.rb b/spec/ruby/library/stringio/fsync_spec.rb
index 8fb2b59a24..85053cb2e5 100644
--- a/spec/ruby/library/stringio/fsync_spec.rb
+++ b/spec/ruby/library/stringio/fsync_spec.rb
@@ -3,7 +3,7 @@ require_relative 'fixtures/classes'
describe "StringIO#fsync" do
it "returns zero" do
- io = StringIO.new("fsync")
+ io = StringIO.new(+"fsync")
io.fsync.should eql(0)
end
end
diff --git a/spec/ruby/library/stringio/getpass_spec.rb b/spec/ruby/library/stringio/getpass_spec.rb
new file mode 100644
index 0000000000..60fc64f0c5
--- /dev/null
+++ b/spec/ruby/library/stringio/getpass_spec.rb
@@ -0,0 +1,11 @@
+require_relative '../../spec_helper'
+require 'stringio'
+
+# This method is added by io/console on require.
+describe "StringIO#getpass" do
+ require 'io/console'
+
+ it "is defined by io/console" do
+ StringIO.new("example").should.respond_to?(:getpass)
+ end
+end
diff --git a/spec/ruby/library/stringio/gets_spec.rb b/spec/ruby/library/stringio/gets_spec.rb
index d682b2784f..ac876f0b4f 100644
--- a/spec/ruby/library/stringio/gets_spec.rb
+++ b/spec/ruby/library/stringio/gets_spec.rb
@@ -1,245 +1,61 @@
require_relative '../../spec_helper'
require "stringio"
+require_relative "shared/gets"
-describe "StringIO#gets when passed [separator]" do
- before :each do
- @io = StringIO.new("this>is>an>example")
- end
-
- it "returns the data read till the next occurrence of the passed separator" do
- @io.gets(">").should == "this>"
- @io.gets(">").should == "is>"
- @io.gets(">").should == "an>"
- @io.gets(">").should == "example"
- end
-
- it "sets $_ to the read content" do
- @io.gets(">")
- $_.should == "this>"
- @io.gets(">")
- $_.should == "is>"
- @io.gets(">")
- $_.should == "an>"
- @io.gets(">")
- $_.should == "example"
- @io.gets(">")
- $_.should be_nil
- end
-
- it "accepts string as separator" do
- @io.gets("is>")
- $_.should == "this>"
- @io.gets("an>")
- $_.should == "is>an>"
- @io.gets("example")
- $_.should == "example"
- @io.gets("ple")
- $_.should be_nil
- end
-
- it "updates self's lineno by one" do
- @io.gets(">")
- @io.lineno.should eql(1)
+describe "StringIO#gets" do
+ describe "when passed [separator]" do
+ it_behaves_like :stringio_gets_separator, :gets
- @io.gets(">")
- @io.lineno.should eql(2)
+ it "returns nil if self is at the end" do
+ @io = StringIO.new("this>is>an>example")
- @io.gets(">")
- @io.lineno.should eql(3)
- end
-
- it "returns the next paragraph when the passed separator is an empty String" do
- io = StringIO.new("this is\n\nan example")
- io.gets("").should == "this is\n\n"
- io.gets("").should == "an example"
- end
-
- it "returns the remaining content starting at the current position when passed nil" do
- io = StringIO.new("this is\n\nan example")
- io.pos = 5
- io.gets(nil).should == "is\n\nan example"
- end
-
- it "tries to convert the passed separator to a String using #to_str" do
- obj = mock('to_str')
- obj.should_receive(:to_str).and_return(">")
- @io.gets(obj).should == "this>"
- end
-end
-
-describe "StringIO#gets when passed no argument" do
- before :each do
- @io = StringIO.new("this is\nan example\nfor StringIO#gets")
- end
-
- it "returns the data read till the next occurrence of $/ or till eof" do
- @io.gets.should == "this is\n"
-
- begin
- old_sep, $/ = $/, " "
- @io.gets.should == "an "
- @io.gets.should == "example\nfor "
- @io.gets.should == "StringIO#gets"
- ensure
- $/ = old_sep
+ @io.pos = 36
+ @io.gets(">").should be_nil
+ @io.gets(">").should be_nil
end
end
- it "sets $_ to the read content" do
- @io.gets
- $_.should == "this is\n"
- @io.gets
- $_.should == "an example\n"
- @io.gets
- $_.should == "for StringIO#gets"
- @io.gets
- $_.should be_nil
- end
-
- it "updates self's position" do
- @io.gets
- @io.pos.should eql(8)
-
- @io.gets
- @io.pos.should eql(19)
-
- @io.gets
- @io.pos.should eql(36)
- end
-
- it "updates self's lineno" do
- @io.gets
- @io.lineno.should eql(1)
-
- @io.gets
- @io.lineno.should eql(2)
-
- @io.gets
- @io.lineno.should eql(3)
- end
-
- it "returns nil if self is at the end" do
- @io.pos = 36
- @io.gets.should be_nil
- @io.gets.should be_nil
- end
-end
-
-describe "StringIO#gets when passed [limit]" do
- before :each do
- @io = StringIO.new("this>is>an>example")
- end
-
- it "returns the data read until the limit is met" do
- @io.gets(4).should == "this"
- @io.gets(3).should == ">is"
- @io.gets(5).should == ">an>e"
- @io.gets(6).should == "xample"
- end
+ describe "when passed [limit]" do
+ it_behaves_like :stringio_gets_limit, :gets
- it "sets $_ to the read content" do
- @io.gets(4)
- $_.should == "this"
- @io.gets(3)
- $_.should == ">is"
- @io.gets(5)
- $_.should == ">an>e"
- @io.gets(6)
- $_.should == "xample"
- @io.gets(3)
- $_.should be_nil
- end
+ it "returns nil if self is at the end" do
+ @io = StringIO.new("this>is>an>example")
- it "updates self's lineno by one" do
- @io.gets(3)
- @io.lineno.should eql(1)
-
- @io.gets(3)
- @io.lineno.should eql(2)
-
- @io.gets(3)
- @io.lineno.should eql(3)
- end
-
- it "tries to convert the passed limit to an Integer using #to_int" do
- obj = mock('to_int')
- obj.should_receive(:to_int).and_return(4)
- @io.gets(obj).should == "this"
- end
-
- it "returns a blank string when passed a limit of 0" do
- @io.gets(0).should == ""
- end
-end
-
-describe "StringIO#gets when passed [separator] and [limit]" do
- before :each do
- @io = StringIO.new("this>is>an>example")
- end
-
- it "returns the data read until the limit is consumed or the separator is met" do
- @io.gets('>', 8).should == "this>"
- @io.gets('>', 2).should == "is"
- @io.gets('>', 10).should == ">"
- @io.gets('>', 6).should == "an>"
- @io.gets('>', 5).should == "examp"
- end
-
- it "sets $_ to the read content" do
- @io.gets('>', 8)
- $_.should == "this>"
- @io.gets('>', 2)
- $_.should == "is"
- @io.gets('>', 10)
- $_.should == ">"
- @io.gets('>', 6)
- $_.should == "an>"
- @io.gets('>', 5)
- $_.should == "examp"
+ @io.pos = 36
+ @io.gets(3).should be_nil
+ @io.gets(3).should be_nil
+ end
end
- it "updates self's lineno by one" do
- @io.gets('>', 3)
- @io.lineno.should eql(1)
+ describe "when passed [separator] and [limit]" do
+ it_behaves_like :stringio_gets_separator_and_limit, :gets
- @io.gets('>', 3)
- @io.lineno.should eql(2)
+ it "returns nil if self is at the end" do
+ @io = StringIO.new("this>is>an>example")
- @io.gets('>', 3)
- @io.lineno.should eql(3)
+ @io.pos = 36
+ @io.gets(">", 3).should be_nil
+ @io.gets(">", 3).should be_nil
+ end
end
- it "tries to convert the passed separator to a String using #to_str" do
- obj = mock('to_str')
- obj.should_receive(:to_str).and_return('>')
- @io.gets(obj, 5).should == "this>"
- end
+ describe "when passed no argument" do
+ it_behaves_like :stringio_gets_no_argument, :gets
- it "does not raise TypeError if passed separator is nil" do
- @io.gets(nil, 5).should == "this>"
- end
+ it "returns nil if self is at the end" do
+ @io = StringIO.new("this>is>an>example")
- it "tries to convert the passed limit to an Integer using #to_int" do
- obj = mock('to_int')
- obj.should_receive(:to_int).and_return(5)
- @io.gets('>', obj).should == "this>"
+ @io.pos = 36
+ @io.gets.should be_nil
+ @io.gets.should be_nil
+ end
end
-end
-
-describe "StringIO#gets when in write-only mode" do
- it "raises an IOError" do
- io = StringIO.new("xyz", "w")
- lambda { io.gets }.should raise_error(IOError)
- io = StringIO.new("xyz")
- io.close_read
- lambda { io.gets }.should raise_error(IOError)
+ describe "when passed [chomp]" do
+ it_behaves_like :stringio_gets_chomp, :gets
end
-end
-describe "StringIO#gets when passed [chomp]" do
- it "returns the data read without a trailing newline character" do
- io = StringIO.new("this>is>an>example\n")
- io.gets(chomp: true).should == "this>is>an>example"
+ describe "when in write-only mode" do
+ it_behaves_like :stringio_gets_write_only, :gets
end
end
diff --git a/spec/ruby/library/stringio/initialize_spec.rb b/spec/ruby/library/stringio/initialize_spec.rb
index b503ed2206..6f4d2e456c 100644
--- a/spec/ruby/library/stringio/initialize_spec.rb
+++ b/spec/ruby/library/stringio/initialize_spec.rb
@@ -13,112 +13,112 @@ describe "StringIO#initialize when passed [Object, mode]" do
it "sets the mode based on the passed mode" do
io = StringIO.allocate
- io.send(:initialize, "example", "r")
+ io.send(:initialize, +"example", "r")
io.closed_read?.should be_false
io.closed_write?.should be_true
io = StringIO.allocate
- io.send(:initialize, "example", "rb")
+ io.send(:initialize, +"example", "rb")
io.closed_read?.should be_false
io.closed_write?.should be_true
io = StringIO.allocate
- io.send(:initialize, "example", "r+")
+ io.send(:initialize, +"example", "r+")
io.closed_read?.should be_false
io.closed_write?.should be_false
io = StringIO.allocate
- io.send(:initialize, "example", "rb+")
+ io.send(:initialize, +"example", "rb+")
io.closed_read?.should be_false
io.closed_write?.should be_false
io = StringIO.allocate
- io.send(:initialize, "example", "w")
+ io.send(:initialize, +"example", "w")
io.closed_read?.should be_true
io.closed_write?.should be_false
io = StringIO.allocate
- io.send(:initialize, "example", "wb")
+ io.send(:initialize, +"example", "wb")
io.closed_read?.should be_true
io.closed_write?.should be_false
io = StringIO.allocate
- io.send(:initialize, "example", "w+")
+ io.send(:initialize, +"example", "w+")
io.closed_read?.should be_false
io.closed_write?.should be_false
io = StringIO.allocate
- io.send(:initialize, "example", "wb+")
+ io.send(:initialize, +"example", "wb+")
io.closed_read?.should be_false
io.closed_write?.should be_false
io = StringIO.allocate
- io.send(:initialize, "example", "a")
+ io.send(:initialize, +"example", "a")
io.closed_read?.should be_true
io.closed_write?.should be_false
io = StringIO.allocate
- io.send(:initialize, "example", "ab")
+ io.send(:initialize, +"example", "ab")
io.closed_read?.should be_true
io.closed_write?.should be_false
io = StringIO.allocate
- io.send(:initialize, "example", "a+")
+ io.send(:initialize, +"example", "a+")
io.closed_read?.should be_false
io.closed_write?.should be_false
io = StringIO.allocate
- io.send(:initialize, "example", "ab+")
+ io.send(:initialize, +"example", "ab+")
io.closed_read?.should be_false
io.closed_write?.should be_false
end
it "allows passing the mode as an Integer" do
io = StringIO.allocate
- io.send(:initialize, "example", IO::RDONLY)
+ io.send(:initialize, +"example", IO::RDONLY)
io.closed_read?.should be_false
io.closed_write?.should be_true
io = StringIO.allocate
- io.send(:initialize, "example", IO::RDWR)
+ io.send(:initialize, +"example", IO::RDWR)
io.closed_read?.should be_false
io.closed_write?.should be_false
io = StringIO.allocate
- io.send(:initialize, "example", IO::WRONLY)
+ io.send(:initialize, +"example", IO::WRONLY)
io.closed_read?.should be_true
io.closed_write?.should be_false
io = StringIO.allocate
- io.send(:initialize, "example", IO::WRONLY | IO::TRUNC)
+ io.send(:initialize, +"example", IO::WRONLY | IO::TRUNC)
io.closed_read?.should be_true
io.closed_write?.should be_false
io = StringIO.allocate
- io.send(:initialize, "example", IO::RDWR | IO::TRUNC)
+ io.send(:initialize, +"example", IO::RDWR | IO::TRUNC)
io.closed_read?.should be_false
io.closed_write?.should be_false
io = StringIO.allocate
- io.send(:initialize, "example", IO::WRONLY | IO::APPEND)
+ io.send(:initialize, +"example", IO::WRONLY | IO::APPEND)
io.closed_read?.should be_true
io.closed_write?.should be_false
io = StringIO.allocate
- io.send(:initialize, "example", IO::RDWR | IO::APPEND)
+ io.send(:initialize, +"example", IO::RDWR | IO::APPEND)
io.closed_read?.should be_false
io.closed_write?.should be_false
end
- it "raises a #{frozen_error_class} when passed a frozen String in truncate mode as StringIO backend" do
+ it "raises a FrozenError when passed a frozen String in truncate mode as StringIO backend" do
io = StringIO.allocate
- lambda { io.send(:initialize, "example".freeze, IO::TRUNC) }.should raise_error(frozen_error_class)
+ -> { io.send(:initialize, "example".freeze, IO::TRUNC) }.should raise_error(FrozenError)
end
it "tries to convert the passed mode to a String using #to_str" do
obj = mock('to_str')
obj.should_receive(:to_str).and_return("r")
- @io.send(:initialize, "example", obj)
+ @io.send(:initialize, +"example", obj)
@io.closed_read?.should be_false
@io.closed_write?.should be_true
@@ -126,9 +126,29 @@ describe "StringIO#initialize when passed [Object, mode]" do
it "raises an Errno::EACCES error when passed a frozen string with a write-mode" do
(str = "example").freeze
- lambda { @io.send(:initialize, str, "r+") }.should raise_error(Errno::EACCES)
- lambda { @io.send(:initialize, str, "w") }.should raise_error(Errno::EACCES)
- lambda { @io.send(:initialize, str, "a") }.should raise_error(Errno::EACCES)
+ -> { @io.send(:initialize, str, "r+") }.should raise_error(Errno::EACCES)
+ -> { @io.send(:initialize, str, "w") }.should raise_error(Errno::EACCES)
+ -> { @io.send(:initialize, str, "a") }.should raise_error(Errno::EACCES)
+ end
+
+ it "truncates all the content if passed w mode" do
+ io = StringIO.allocate
+ source = +"example".encode(Encoding::ISO_8859_1);
+
+ io.send(:initialize, source, "w")
+
+ io.string.should.empty?
+ io.string.encoding.should == Encoding::ISO_8859_1
+ end
+
+ it "truncates all the content if passed IO::TRUNC mode" do
+ io = StringIO.allocate
+ source = +"example".encode(Encoding::ISO_8859_1);
+
+ io.send(:initialize, source, IO::TRUNC)
+
+ io.string.should.empty?
+ io.string.encoding.should == Encoding::ISO_8859_1
end
end
@@ -142,12 +162,18 @@ describe "StringIO#initialize when passed [Object]" do
@io.string.should equal(str)
end
- it "sets the mode to read-write" do
- @io.send(:initialize, "example")
+ it "sets the mode to read-write if the string is mutable" do
+ @io.send(:initialize, +"example")
@io.closed_read?.should be_false
@io.closed_write?.should be_false
end
+ it "sets the mode to read if the string is frozen" do
+ @io.send(:initialize, -"example")
+ @io.closed_read?.should be_false
+ @io.closed_write?.should be_true
+ end
+
it "tries to convert the passed Object to a String using #to_str" do
obj = mock('to_str')
obj.should_receive(:to_str).and_return("example")
@@ -163,6 +189,91 @@ describe "StringIO#initialize when passed [Object]" do
end
end
+# NOTE: Synchronise with core/io/new_spec.rb (core/io/shared/new.rb)
+describe "StringIO#initialize when passed keyword arguments" do
+ it "sets the mode based on the passed :mode option" do
+ io = StringIO.new("example", mode: "r")
+ io.closed_read?.should be_false
+ io.closed_write?.should be_true
+ end
+
+ it "accepts a mode argument set to nil with a valid :mode option" do
+ @io = StringIO.new(+'', nil, mode: "w")
+ @io.write("foo").should == 3
+ end
+
+ it "accepts a mode argument with a :mode option set to nil" do
+ @io = StringIO.new(+'', "w", mode: nil)
+ @io.write("foo").should == 3
+ end
+
+ it "sets binmode from :binmode option" do
+ @io = StringIO.new(+'', 'w', binmode: true)
+ @io.external_encoding.to_s.should == "ASCII-8BIT" # #binmode? isn't implemented in StringIO
+ end
+
+ it "does not set binmode from false :binmode" do
+ @io = StringIO.new(+'', 'w', binmode: false)
+ @io.external_encoding.to_s.should == "UTF-8" # #binmode? isn't implemented in StringIO
+ end
+end
+
+# NOTE: Synchronise with core/io/new_spec.rb (core/io/shared/new.rb)
+describe "StringIO#initialize when passed keyword arguments and error happens" do
+ it "raises an error if passed encodings two ways" do
+ -> {
+ @io = StringIO.new(+'', 'w:ISO-8859-1', encoding: 'ISO-8859-1')
+ }.should raise_error(ArgumentError)
+ -> {
+ @io = StringIO.new(+'', 'w:ISO-8859-1', external_encoding: 'ISO-8859-1')
+ }.should raise_error(ArgumentError)
+ -> {
+ @io = StringIO.new(+'', 'w:ISO-8859-1:UTF-8', internal_encoding: 'ISO-8859-1')
+ }.should raise_error(ArgumentError)
+ end
+
+ it "raises an error if passed matching binary/text mode two ways" do
+ -> {
+ @io = StringIO.new(+'', "wb", binmode: true)
+ }.should raise_error(ArgumentError)
+ -> {
+ @io = StringIO.new(+'', "wt", textmode: true)
+ }.should raise_error(ArgumentError)
+
+ -> {
+ @io = StringIO.new(+'', "wb", textmode: false)
+ }.should raise_error(ArgumentError)
+ -> {
+ @io = StringIO.new(+'', "wt", binmode: false)
+ }.should raise_error(ArgumentError)
+ end
+
+ it "raises an error if passed conflicting binary/text mode two ways" do
+ -> {
+ @io = StringIO.new(+'', "wb", binmode: false)
+ }.should raise_error(ArgumentError)
+ -> {
+ @io = StringIO.new(+'', "wt", textmode: false)
+ }.should raise_error(ArgumentError)
+
+ -> {
+ @io = StringIO.new(+'', "wb", textmode: true)
+ }.should raise_error(ArgumentError)
+ -> {
+ @io = StringIO.new(+'', "wt", binmode: true)
+ }.should raise_error(ArgumentError)
+ end
+
+ it "raises an error when trying to set both binmode and textmode" do
+ -> {
+ @io = StringIO.new(+'', "w", textmode: true, binmode: true)
+ }.should raise_error(ArgumentError)
+ -> {
+ @io = StringIO.new(+'', File::Constants::WRONLY, textmode: true, binmode: true)
+ }.should raise_error(ArgumentError)
+ end
+end
+
describe "StringIO#initialize when passed no arguments" do
before :each do
@io = StringIO.allocate
@@ -173,7 +284,7 @@ describe "StringIO#initialize when passed no arguments" do
end
it "sets the mode to read-write" do
- @io.send(:initialize, "example")
+ @io.send(:initialize)
@io.closed_read?.should be_false
@io.closed_write?.should be_false
end
@@ -184,26 +295,34 @@ describe "StringIO#initialize when passed no arguments" do
end
end
-describe "StringIO#initialize sets the encoding to" do
+describe "StringIO#initialize sets" do
before :each do
@external = Encoding.default_external
+ @internal = Encoding.default_internal
Encoding.default_external = Encoding::ISO_8859_2
+ Encoding.default_internal = Encoding::ISO_8859_2
end
after :each do
Encoding.default_external = @external
+ Encoding.default_internal = @internal
end
- it "Encoding.default_external when passed no arguments" do
+ it "the encoding to Encoding.default_external when passed no arguments" do
io = StringIO.new
io.external_encoding.should == Encoding::ISO_8859_2
io.string.encoding.should == Encoding::ISO_8859_2
end
- it "the same as the encoding of the String when passed a String" do
- s = ''.force_encoding(Encoding::EUC_JP)
+ it "the encoding to the encoding of the String when passed a String" do
+ s = ''.dup.force_encoding(Encoding::EUC_JP)
io = StringIO.new(s)
- io.external_encoding.should == Encoding::EUC_JP
io.string.encoding.should == Encoding::EUC_JP
end
+
+ it "the #external_encoding to the encoding of the String when passed a String" do
+ s = ''.dup.force_encoding(Encoding::EUC_JP)
+ io = StringIO.new(s)
+ io.external_encoding.should == Encoding::EUC_JP
+ end
end
diff --git a/spec/ruby/library/stringio/inspect_spec.rb b/spec/ruby/library/stringio/inspect_spec.rb
new file mode 100644
index 0000000000..7c02f8d360
--- /dev/null
+++ b/spec/ruby/library/stringio/inspect_spec.rb
@@ -0,0 +1,19 @@
+require_relative '../../spec_helper'
+require "stringio"
+
+describe "StringIO#inspect" do
+ it "returns the same as #to_s" do
+ io = StringIO.new("example")
+ io.inspect.should == io.to_s
+ end
+
+ it "does not include the contents" do
+ io = StringIO.new("contents")
+ io.inspect.should_not include("contents")
+ end
+
+ it "uses the regular Object#inspect without any instance variable" do
+ io = StringIO.new("example")
+ io.inspect.should =~ /\A#<StringIO:0x\h+>\z/
+ end
+end
diff --git a/spec/ruby/library/stringio/lines_spec.rb b/spec/ruby/library/stringio/lines_spec.rb
deleted file mode 100644
index d9dd26c2e2..0000000000
--- a/spec/ruby/library/stringio/lines_spec.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-require_relative '../../spec_helper'
-require 'stringio'
-require_relative 'shared/each'
-
-describe "StringIO#lines when passed a separator" do
- it_behaves_like :stringio_each_separator, :lines
-end
-
-describe "StringIO#lines when passed no arguments" do
- it_behaves_like :stringio_each_no_arguments, :lines
-end
-
-describe "StringIO#lines when self is not readable" do
- it_behaves_like :stringio_each_not_readable, :lines
-end
-
-describe "StringIO#lines when passed chomp" do
- it_behaves_like :stringio_each_chomp, :lines
-end
diff --git a/spec/ruby/library/stringio/new_spec.rb b/spec/ruby/library/stringio/new_spec.rb
new file mode 100644
index 0000000000..ec4b32aa11
--- /dev/null
+++ b/spec/ruby/library/stringio/new_spec.rb
@@ -0,0 +1,10 @@
+require_relative '../../spec_helper'
+require 'stringio'
+
+describe "StringIO.new" do
+ it "does not use the given block and warns to use StringIO::open" do
+ -> {
+ StringIO.new { raise }
+ }.should complain(/warning: StringIO::new\(\) does not take block; use StringIO::open\(\) instead/)
+ end
+end
diff --git a/spec/ruby/library/stringio/open_spec.rb b/spec/ruby/library/stringio/open_spec.rb
index f8f3feabee..b7c90661f9 100644
--- a/spec/ruby/library/stringio/open_spec.rb
+++ b/spec/ruby/library/stringio/open_spec.rb
@@ -8,26 +8,26 @@ describe "StringIO.open when passed [Object, mode]" do
end
it "returns the blocks return value when yielding" do
- ret = StringIO.open("example", "r") { :test }
+ ret = StringIO.open(+"example", "r") { :test }
ret.should equal(:test)
end
it "yields self to the passed block" do
io = nil
- StringIO.open("example", "r") { |strio| io = strio }
+ StringIO.open(+"example", "r") { |strio| io = strio }
io.should be_kind_of(StringIO)
end
it "closes self after yielding" do
io = nil
- StringIO.open("example", "r") { |strio| io = strio }
+ StringIO.open(+"example", "r") { |strio| io = strio }
io.closed?.should be_true
end
it "even closes self when an exception is raised while yielding" do
io = nil
begin
- StringIO.open("example", "r") do |strio|
+ StringIO.open(+"example", "r") do |strio|
io = strio
raise "Error"
end
@@ -38,14 +38,14 @@ describe "StringIO.open when passed [Object, mode]" do
it "sets self's string to nil after yielding" do
io = nil
- StringIO.open("example", "r") { |strio| io = strio }
+ StringIO.open(+"example", "r") { |strio| io = strio }
io.string.should be_nil
end
it "even sets self's string to nil when an exception is raised while yielding" do
io = nil
begin
- StringIO.open("example", "r") do |strio|
+ StringIO.open(+"example", "r") do |strio|
io = strio
raise "Error"
end
@@ -55,93 +55,93 @@ describe "StringIO.open when passed [Object, mode]" do
end
it "sets the mode based on the passed mode" do
- io = StringIO.open("example", "r")
+ io = StringIO.open(+"example", "r")
io.closed_read?.should be_false
io.closed_write?.should be_true
- io = StringIO.open("example", "rb")
+ io = StringIO.open(+"example", "rb")
io.closed_read?.should be_false
io.closed_write?.should be_true
- io = StringIO.open("example", "r+")
+ io = StringIO.open(+"example", "r+")
io.closed_read?.should be_false
io.closed_write?.should be_false
- io = StringIO.open("example", "rb+")
+ io = StringIO.open(+"example", "rb+")
io.closed_read?.should be_false
io.closed_write?.should be_false
- io = StringIO.open("example", "w")
+ io = StringIO.open(+"example", "w")
io.closed_read?.should be_true
io.closed_write?.should be_false
- io = StringIO.open("example", "wb")
+ io = StringIO.open(+"example", "wb")
io.closed_read?.should be_true
io.closed_write?.should be_false
- io = StringIO.open("example", "w+")
+ io = StringIO.open(+"example", "w+")
io.closed_read?.should be_false
io.closed_write?.should be_false
- io = StringIO.open("example", "wb+")
+ io = StringIO.open(+"example", "wb+")
io.closed_read?.should be_false
io.closed_write?.should be_false
- io = StringIO.open("example", "a")
+ io = StringIO.open(+"example", "a")
io.closed_read?.should be_true
io.closed_write?.should be_false
- io = StringIO.open("example", "ab")
+ io = StringIO.open(+"example", "ab")
io.closed_read?.should be_true
io.closed_write?.should be_false
- io = StringIO.open("example", "a+")
+ io = StringIO.open(+"example", "a+")
io.closed_read?.should be_false
io.closed_write?.should be_false
- io = StringIO.open("example", "ab+")
+ io = StringIO.open(+"example", "ab+")
io.closed_read?.should be_false
io.closed_write?.should be_false
end
it "allows passing the mode as an Integer" do
- io = StringIO.open("example", IO::RDONLY)
+ io = StringIO.open(+"example", IO::RDONLY)
io.closed_read?.should be_false
io.closed_write?.should be_true
- io = StringIO.open("example", IO::RDWR)
+ io = StringIO.open(+"example", IO::RDWR)
io.closed_read?.should be_false
io.closed_write?.should be_false
- io = StringIO.open("example", IO::WRONLY)
+ io = StringIO.open(+"example", IO::WRONLY)
io.closed_read?.should be_true
io.closed_write?.should be_false
- io = StringIO.open("example", IO::WRONLY | IO::TRUNC)
+ io = StringIO.open(+"example", IO::WRONLY | IO::TRUNC)
io.closed_read?.should be_true
io.closed_write?.should be_false
- io = StringIO.open("example", IO::RDWR | IO::TRUNC)
+ io = StringIO.open(+"example", IO::RDWR | IO::TRUNC)
io.closed_read?.should be_false
io.closed_write?.should be_false
- io = StringIO.open("example", IO::WRONLY | IO::APPEND)
+ io = StringIO.open(+"example", IO::WRONLY | IO::APPEND)
io.closed_read?.should be_true
io.closed_write?.should be_false
- io = StringIO.open("example", IO::RDWR | IO::APPEND)
+ io = StringIO.open(+"example", IO::RDWR | IO::APPEND)
io.closed_read?.should be_false
io.closed_write?.should be_false
end
- it "raises a #{frozen_error_class} when passed a frozen String in truncate mode as StringIO backend" do
- lambda { StringIO.open("example".freeze, IO::TRUNC) }.should raise_error(frozen_error_class)
+ it "raises a FrozenError when passed a frozen String in truncate mode as StringIO backend" do
+ -> { StringIO.open("example".freeze, IO::TRUNC) }.should raise_error(FrozenError)
end
it "tries to convert the passed mode to a String using #to_str" do
obj = mock('to_str')
obj.should_receive(:to_str).and_return("r")
- io = StringIO.open("example", obj)
+ io = StringIO.open(+"example", obj)
io.closed_read?.should be_false
io.closed_write?.should be_true
@@ -149,9 +149,9 @@ describe "StringIO.open when passed [Object, mode]" do
it "raises an Errno::EACCES error when passed a frozen string with a write-mode" do
(str = "example").freeze
- lambda { StringIO.open(str, "r+") }.should raise_error(Errno::EACCES)
- lambda { StringIO.open(str, "w") }.should raise_error(Errno::EACCES)
- lambda { StringIO.open(str, "a") }.should raise_error(Errno::EACCES)
+ -> { StringIO.open(str, "r+") }.should raise_error(Errno::EACCES)
+ -> { StringIO.open(str, "w") }.should raise_error(Errno::EACCES)
+ -> { StringIO.open(str, "a") }.should raise_error(Errno::EACCES)
end
end
@@ -163,14 +163,18 @@ describe "StringIO.open when passed [Object]" do
it "yields self to the passed block" do
io = nil
- ret = StringIO.open("example") { |strio| io = strio }
+ ret = StringIO.open(+"example") { |strio| io = strio }
io.should equal(ret)
end
- it "sets the mode to read-write" do
- io = StringIO.open("example")
+ it "sets the mode to read-write (r+)" do
+ io = StringIO.open(+"example")
io.closed_read?.should be_false
io.closed_write?.should be_false
+
+ io = StringIO.new(+"example")
+ io.printf("%d", 123)
+ io.string.should == "123mple"
end
it "tries to convert the passed Object to a String using #to_str" do
@@ -195,10 +199,14 @@ describe "StringIO.open when passed no arguments" do
io.should equal(ret)
end
- it "sets the mode to read-write" do
+ it "sets the mode to read-write (r+)" do
io = StringIO.open
io.closed_read?.should be_false
io.closed_write?.should be_false
+
+ io = StringIO.new(+"example")
+ io.printf("%d", 123)
+ io.string.should == "123mple"
end
it "uses an empty String as the StringIO backend" do
diff --git a/spec/ruby/library/stringio/path_spec.rb b/spec/ruby/library/stringio/path_spec.rb
index 5439cf4b53..1184ca523f 100644
--- a/spec/ruby/library/stringio/path_spec.rb
+++ b/spec/ruby/library/stringio/path_spec.rb
@@ -3,6 +3,6 @@ require_relative 'fixtures/classes'
describe "StringIO#path" do
it "is not defined" do
- lambda { StringIO.new("path").path }.should raise_error(NoMethodError)
+ -> { StringIO.new("path").path }.should raise_error(NoMethodError)
end
end
diff --git a/spec/ruby/library/stringio/pos_spec.rb b/spec/ruby/library/stringio/pos_spec.rb
index 8d99294f31..81be5f01a5 100644
--- a/spec/ruby/library/stringio/pos_spec.rb
+++ b/spec/ruby/library/stringio/pos_spec.rb
@@ -17,7 +17,7 @@ describe "StringIO#pos=" do
end
it "raises an EINVAL if given a negative argument" do
- lambda { @io.pos = -10 }.should raise_error(Errno::EINVAL)
+ -> { @io.pos = -10 }.should raise_error(Errno::EINVAL)
end
it "updates the current byte offset after reaching EOF" do
diff --git a/spec/ruby/library/stringio/print_spec.rb b/spec/ruby/library/stringio/print_spec.rb
index 144a219509..00c33367dc 100644
--- a/spec/ruby/library/stringio/print_spec.rb
+++ b/spec/ruby/library/stringio/print_spec.rb
@@ -3,7 +3,7 @@ require_relative 'fixtures/classes'
describe "StringIO#print" do
before :each do
- @io = StringIO.new('example')
+ @io = StringIO.new(+'example')
end
it "prints $_ when passed no arguments" do
@@ -39,13 +39,14 @@ describe "StringIO#print" do
end
it "honors the output record separator global" do
- old_rs, $\ = $\, 'x'
+ old_rs = $\
+ suppress_warning {$\ = 'x'}
begin
@io.print(5, 6, 7, 8)
@io.string.should == '5678xle'
ensure
- $\ = old_rs
+ suppress_warning {$\ = old_rs}
end
end
@@ -58,20 +59,21 @@ describe "StringIO#print" do
end
it "correctly updates the current position when honoring the output record separator global" do
- old_rs, $\ = $\, 'x'
+ old_rs = $\
+ suppress_warning {$\ = 'x'}
begin
@io.print(5, 6, 7, 8)
@io.pos.should eql(5)
ensure
- $\ = old_rs
+ suppress_warning {$\ = old_rs}
end
end
end
describe "StringIO#print when in append mode" do
before :each do
- @io = StringIO.new("example", "a")
+ @io = StringIO.new(+"example", "a")
end
it "appends the passed argument to the end of self" do
@@ -90,11 +92,11 @@ end
describe "StringIO#print when self is not writable" do
it "raises an IOError" do
- io = StringIO.new("test", "r")
- lambda { io.print("test") }.should raise_error(IOError)
+ io = StringIO.new(+"test", "r")
+ -> { io.print("test") }.should raise_error(IOError)
- io = StringIO.new("test")
+ io = StringIO.new(+"test")
io.close_write
- lambda { io.print("test") }.should raise_error(IOError)
+ -> { io.print("test") }.should raise_error(IOError)
end
end
diff --git a/spec/ruby/library/stringio/printf_spec.rb b/spec/ruby/library/stringio/printf_spec.rb
index 3978896621..ca82e84757 100644
--- a/spec/ruby/library/stringio/printf_spec.rb
+++ b/spec/ruby/library/stringio/printf_spec.rb
@@ -4,7 +4,7 @@ require_relative '../../core/kernel/shared/sprintf'
describe "StringIO#printf" do
before :each do
- @io = StringIO.new('example')
+ @io = StringIO.new()
end
it "returns nil" do
@@ -12,9 +12,9 @@ describe "StringIO#printf" do
end
it "pads self with \\000 when the current position is after the end" do
- @io.pos = 10
+ @io.pos = 3
@io.printf("%d", 123)
- @io.string.should == "example\000\000\000123"
+ @io.string.should == "\000\000\000123"
end
it "performs format conversion" do
@@ -31,17 +31,38 @@ describe "StringIO#printf" do
end
describe "formatting" do
- it_behaves_like :kernel_sprintf, -> (format, *args) {
- io = StringIO.new
+ it_behaves_like :kernel_sprintf, -> format, *args {
+ io = StringIO.new(+"")
io.printf(format, *args)
io.string
}
end
end
+describe "StringIO#printf when in read-write mode" do
+ before :each do
+ @io = StringIO.new(+"example", "r+")
+ end
+
+ it "starts from the beginning" do
+ @io.printf("%s", "abcdefghijk")
+ @io.string.should == "abcdefghijk"
+ end
+
+ it "does not truncate existing string" do
+ @io.printf("%s", "abc")
+ @io.string.should == "abcmple"
+ end
+
+ it "correctly updates self's position" do
+ @io.printf("%s", "abc")
+ @io.pos.should eql(3)
+ end
+end
+
describe "StringIO#printf when in append mode" do
before :each do
- @io = StringIO.new("example", "a")
+ @io = StringIO.new(+"example", "a")
end
it "appends the passed argument to the end of self" do
@@ -60,11 +81,11 @@ end
describe "StringIO#printf when self is not writable" do
it "raises an IOError" do
- io = StringIO.new("test", "r")
- lambda { io.printf("test") }.should raise_error(IOError)
+ io = StringIO.new(+"test", "r")
+ -> { io.printf("test") }.should raise_error(IOError)
- io = StringIO.new("test")
+ io = StringIO.new(+"test")
io.close_write
- lambda { io.printf("test") }.should raise_error(IOError)
+ -> { io.printf("test") }.should raise_error(IOError)
end
end
diff --git a/spec/ruby/library/stringio/putc_spec.rb b/spec/ruby/library/stringio/putc_spec.rb
index eae5481d6e..9f1ac8ffb2 100644
--- a/spec/ruby/library/stringio/putc_spec.rb
+++ b/spec/ruby/library/stringio/putc_spec.rb
@@ -3,7 +3,7 @@ require_relative 'fixtures/classes'
describe "StringIO#putc when passed [String]" do
before :each do
- @io = StringIO.new('example')
+ @io = StringIO.new(+'example')
end
it "overwrites the character at the current position" do
@@ -35,11 +35,26 @@ describe "StringIO#putc when passed [String]" do
@io.putc("t")
@io.pos.should == 3
end
+
+ it "handles concurrent writes correctly" do
+ @io = StringIO.new
+ n = 8
+ go = false
+ threads = n.times.map { |i|
+ Thread.new {
+ Thread.pass until go
+ @io.putc i.to_s
+ }
+ }
+ go = true
+ threads.each(&:join)
+ @io.string.size.should == n
+ end
end
describe "StringIO#putc when passed [Object]" do
before :each do
- @io = StringIO.new('example')
+ @io = StringIO.new(+'example')
end
it "it writes the passed Integer % 256 to self" do
@@ -64,13 +79,13 @@ describe "StringIO#putc when passed [Object]" do
end
it "raises a TypeError when the passed argument can't be coerced to Integer" do
- lambda { @io.putc(Object.new) }.should raise_error(TypeError)
+ -> { @io.putc(Object.new) }.should raise_error(TypeError)
end
end
describe "StringIO#putc when in append mode" do
it "appends to the end of self" do
- io = StringIO.new("test", "a")
+ io = StringIO.new(+"test", "a")
io.putc(?t)
io.string.should == "testt"
end
@@ -78,11 +93,11 @@ end
describe "StringIO#putc when self is not writable" do
it "raises an IOError" do
- io = StringIO.new("test", "r")
- lambda { io.putc(?a) }.should raise_error(IOError)
+ io = StringIO.new(+"test", "r")
+ -> { io.putc(?a) }.should raise_error(IOError)
- io = StringIO.new("test")
+ io = StringIO.new(+"test")
io.close_write
- lambda { io.putc("t") }.should raise_error(IOError)
+ -> { io.putc("t") }.should raise_error(IOError)
end
end
diff --git a/spec/ruby/library/stringio/puts_spec.rb b/spec/ruby/library/stringio/puts_spec.rb
index 152bfb13f8..054ec8227f 100644
--- a/spec/ruby/library/stringio/puts_spec.rb
+++ b/spec/ruby/library/stringio/puts_spec.rb
@@ -30,11 +30,12 @@ describe "StringIO#puts when passed an Array" do
it "does not honor the global output record separator $\\" do
begin
- old_rs, $\ = $\, "test"
+ old_rs = $\
+ suppress_warning {$\ = "test"}
@io.puts([1, 2, 3, 4])
@io.string.should == "1\n2\n3\n4\n"
ensure
- $\ = old_rs
+ suppress_warning {$\ = old_rs}
end
end
@@ -68,11 +69,12 @@ describe "StringIO#puts when passed 1 or more objects" do
it "does not honor the global output record separator $\\" do
begin
- old_rs, $\ = $\, "test"
+ old_rs = $\
+ suppress_warning {$\ = "test"}
@io.puts(1, 2, 3, 4)
@io.string.should == "1\n2\n3\n4\n"
ensure
- $\ = old_rs
+ suppress_warning {$\ = old_rs}
end
end
@@ -99,6 +101,20 @@ describe "StringIO#puts when passed 1 or more objects" do
@io.puts ''
@io.string.should == "\n"
end
+
+ it "handles concurrent writes correctly" do
+ n = 8
+ go = false
+ threads = n.times.map { |i|
+ Thread.new {
+ Thread.pass until go
+ @io.puts i
+ }
+ }
+ go = true
+ threads.each(&:join)
+ @io.string.size.should == n.times.map { |i| "#{i}\n" }.join.size
+ end
end
describe "StringIO#puts when passed no arguments" do
@@ -117,18 +133,19 @@ describe "StringIO#puts when passed no arguments" do
it "does not honor the global output record separator $\\" do
begin
- old_rs, $\ = $\, "test"
+ old_rs = $\
+ suppress_warning {$\ = "test"}
@io.puts
@io.string.should == "\n"
ensure
- $\ = old_rs
+ suppress_warning {$\ = old_rs}
end
end
end
describe "StringIO#puts when in append mode" do
before :each do
- @io = StringIO.new("example", "a")
+ @io = StringIO.new(+"example", "a")
end
it "appends the passed argument to the end of self" do
@@ -147,18 +164,18 @@ end
describe "StringIO#puts when self is not writable" do
it "raises an IOError" do
- io = StringIO.new("test", "r")
- lambda { io.puts }.should raise_error(IOError)
+ io = StringIO.new(+"test", "r")
+ -> { io.puts }.should raise_error(IOError)
- io = StringIO.new("test")
+ io = StringIO.new(+"test")
io.close_write
- lambda { io.puts }.should raise_error(IOError)
+ -> { io.puts }.should raise_error(IOError)
end
end
describe "StringIO#puts when passed an encoded string" do
it "stores the bytes unmodified" do
- io = StringIO.new("")
+ io = StringIO.new(+"")
io.puts "\x00\x01\x02"
io.puts "æåø"
diff --git a/spec/ruby/library/stringio/read_nonblock_spec.rb b/spec/ruby/library/stringio/read_nonblock_spec.rb
index 2a8f926bd0..74736f7792 100644
--- a/spec/ruby/library/stringio/read_nonblock_spec.rb
+++ b/spec/ruby/library/stringio/read_nonblock_spec.rb
@@ -5,10 +5,21 @@ require_relative 'shared/sysread'
describe "StringIO#read_nonblock when passed length, buffer" do
it_behaves_like :stringio_read, :read_nonblock
+
+ it "accepts :exception option" do
+ io = StringIO.new("example")
+ io.read_nonblock(3, buffer = +"", exception: true)
+ buffer.should == "exa"
+ end
end
describe "StringIO#read_nonblock when passed length" do
it_behaves_like :stringio_read_length, :read_nonblock
+
+ it "accepts :exception option" do
+ io = StringIO.new("example")
+ io.read_nonblock(3, exception: true).should == "exa"
+ end
end
describe "StringIO#read_nonblock when passed nil" do
@@ -29,7 +40,7 @@ describe "StringIO#read_nonblock" do
context "when exception option is set to false" do
context "when the end is reached" do
it "returns nil" do
- stringio = StringIO.new('')
+ stringio = StringIO.new(+'')
stringio << "hello"
stringio.rewind
diff --git a/spec/ruby/library/stringio/read_spec.rb b/spec/ruby/library/stringio/read_spec.rb
index 52ab3dcf47..e49f262127 100644
--- a/spec/ruby/library/stringio/read_spec.rb
+++ b/spec/ruby/library/stringio/read_spec.rb
@@ -53,7 +53,7 @@ describe "StringIO#read when passed length and a buffer" do
end
it "reads [length] characters into the buffer" do
- buf = "foo"
+ buf = +"foo"
result = @io.read(10, buf)
buf.should == "abcdefghij"
diff --git a/spec/ruby/library/stringio/readline_spec.rb b/spec/ruby/library/stringio/readline_spec.rb
index dc396f61a9..085360707f 100644
--- a/spec/ruby/library/stringio/readline_spec.rb
+++ b/spec/ruby/library/stringio/readline_spec.rb
@@ -1,129 +1,58 @@
require_relative '../../spec_helper'
+require "stringio"
require_relative 'fixtures/classes'
+require_relative "shared/gets"
+describe "StringIO#readline" do
+ describe "when passed [separator]" do
+ it_behaves_like :stringio_gets_separator, :readline
-describe "StringIO#readline when passed [separator]" do
- before :each do
- @io = StringIO.new("this>is>an>example")
- end
-
- it "returns the data read till the next occurrence of the passed separator" do
- @io.readline(">").should == "this>"
- @io.readline(">").should == "is>"
- @io.readline(">").should == "an>"
- @io.readline(">").should == "example"
- end
-
- it "sets $_ to the read content" do
- @io.readline(">")
- $_.should == "this>"
- @io.readline(">")
- $_.should == "is>"
- @io.readline(">")
- $_.should == "an>"
- @io.readline(">")
- $_.should == "example"
- end
-
- it "updates self's lineno by one" do
- @io.readline(">")
- @io.lineno.should eql(1)
-
- @io.readline(">")
- @io.lineno.should eql(2)
-
- @io.readline(">")
- @io.lineno.should eql(3)
- end
-
- it "returns the next paragraph when the passed separator is an empty String" do
- io = StringIO.new("this is\n\nan example")
- io.readline("").should == "this is\n\n"
- io.readline("").should == "an example"
- end
-
- it "returns the remaining content starting at the current position when passed nil" do
- io = StringIO.new("this is\n\nan example")
- io.pos = 5
- io.readline(nil).should == "is\n\nan example"
- end
+ it "raises an IOError if self is at the end" do
+ @io = StringIO.new("this>is>an>example")
- it "tries to convert the passed separator to a String using #to_str" do
- obj = mock('to_str')
- obj.should_receive(:to_str).and_return(">")
- @io.readline(obj).should == "this>"
+ @io.pos = 36
+ -> { @io.readline(">") }.should raise_error(IOError)
+ end
end
-end
-describe "StringIO#readline when passed no argument" do
- before :each do
- @io = StringIO.new("this is\nan example\nfor StringIO#readline")
- end
+ describe "when passed [limit]" do
+ it_behaves_like :stringio_gets_limit, :readline
- it "returns the data read till the next occurrence of $/ or till eof" do
- @io.readline.should == "this is\n"
+ it "raises an IOError if self is at the end" do
+ @io = StringIO.new("this>is>an>example")
- begin
- old_sep, $/ = $/, " "
- @io.readline.should == "an "
- @io.readline.should == "example\nfor "
- @io.readline.should == "StringIO#readline"
- ensure
- $/ = old_sep
+ @io.pos = 36
+ -> { @io.readline(3) }.should raise_error(IOError)
end
end
- it "sets $_ to the read content" do
- @io.readline
- $_.should == "this is\n"
- @io.readline
- $_.should == "an example\n"
- @io.readline
- $_.should == "for StringIO#readline"
- end
-
- it "updates self's position" do
- @io.readline
- @io.pos.should eql(8)
+ describe "when passed [separator] and [limit]" do
+ it_behaves_like :stringio_gets_separator_and_limit, :readline
- @io.readline
- @io.pos.should eql(19)
+ it "raises an IOError if self is at the end" do
+ @io = StringIO.new("this>is>an>example")
- @io.readline
- @io.pos.should eql(40)
+ @io.pos = 36
+ -> { @io.readline(">", 3) }.should raise_error(IOError)
+ end
end
- it "updates self's lineno" do
- @io.readline
- @io.lineno.should eql(1)
+ describe "when passed no argument" do
+ it_behaves_like :stringio_gets_no_argument, :readline
- @io.readline
- @io.lineno.should eql(2)
+ it "raises an IOError if self is at the end" do
+ @io = StringIO.new("this>is>an>example")
- @io.readline
- @io.lineno.should eql(3)
- end
-
- it "raises an IOError if self is at the end" do
- @io.pos = 40
- lambda { @io.readline }.should raise_error(IOError)
+ @io.pos = 36
+ -> { @io.readline }.should raise_error(IOError)
+ end
end
-end
-
-describe "StringIO#readline when in write-only mode" do
- it "raises an IOError" do
- io = StringIO.new("xyz", "w")
- lambda { io.readline }.should raise_error(IOError)
- io = StringIO.new("xyz")
- io.close_read
- lambda { io.readline }.should raise_error(IOError)
+ describe "when passed [chomp]" do
+ it_behaves_like :stringio_gets_chomp, :readline
end
-end
-describe "StringIO#readline when passed [chomp]" do
- it "returns the data read without a trailing newline character" do
- io = StringIO.new("this>is>an>example\n")
- io.readline(chomp: true).should == "this>is>an>example"
+ describe "when in write-only mode" do
+ it_behaves_like :stringio_gets_write_only, :readline
end
end
diff --git a/spec/ruby/library/stringio/readlines_spec.rb b/spec/ruby/library/stringio/readlines_spec.rb
index 840470c09c..ed7cc22b3d 100644
--- a/spec/ruby/library/stringio/readlines_spec.rb
+++ b/spec/ruby/library/stringio/readlines_spec.rb
@@ -51,10 +51,11 @@ describe "StringIO#readlines when passed no argument" do
it "returns an Array containing lines based on $/" do
begin
- old_sep, $/ = $/, " "
+ old_sep = $/;
+ suppress_warning {$/ = " "}
@io.readlines.should == ["this ", "is\nan ", "example\nfor ", "StringIO#readlines"]
ensure
- $/ = old_sep
+ suppress_warning {$/ = old_sep}
end
end
@@ -82,12 +83,12 @@ end
describe "StringIO#readlines when in write-only mode" do
it "raises an IOError" do
- io = StringIO.new("xyz", "w")
- lambda { io.readlines }.should raise_error(IOError)
+ io = StringIO.new(+"xyz", "w")
+ -> { io.readlines }.should raise_error(IOError)
io = StringIO.new("xyz")
io.close_read
- lambda { io.readlines }.should raise_error(IOError)
+ -> { io.readlines }.should raise_error(IOError)
end
end
@@ -97,3 +98,21 @@ describe "StringIO#readlines when passed [chomp]" do
io.readlines(chomp: true).should == ["this>is", "an>example"]
end
end
+
+describe "StringIO#readlines when passed [limit]" do
+ before :each do
+ @io = StringIO.new("a b c d e\n1 2 3 4 5")
+ end
+
+ it "returns the data read until the limit is met" do
+ @io.readlines(4).should == ["a b ", "c d ", "e\n", "1 2 ", "3 4 ", "5"]
+ end
+
+ it "raises ArgumentError when limit is 0" do
+ -> { @io.readlines(0) }.should raise_error(ArgumentError)
+ end
+
+ it "ignores it when the limit is negative" do
+ @io.readlines(-4).should == ["a b c d e\n", "1 2 3 4 5"]
+ end
+end
diff --git a/spec/ruby/library/stringio/readpartial_spec.rb b/spec/ruby/library/stringio/readpartial_spec.rb
index 54e2f47004..dadefb7837 100644
--- a/spec/ruby/library/stringio/readpartial_spec.rb
+++ b/spec/ruby/library/stringio/readpartial_spec.rb
@@ -3,20 +3,14 @@ require_relative 'fixtures/classes'
describe "StringIO#readpartial" do
before :each do
- @string = StringIO.new('Stop, look, listen')
+ @string = StringIO.new(+'Stop, look, listen')
end
after :each do
@string.close unless @string.closed?
end
- it "raises IOError on closed stream" do
- @string.close
- lambda { @string.readpartial(10) }.should raise_error(IOError)
- end
-
it "reads at most the specified number of bytes" do
-
# buffered read
@string.read(1).should == 'S'
# return only specified number, not the whole buffer
@@ -30,6 +24,14 @@ describe "StringIO#readpartial" do
@string.readpartial(3).should == ", l"
end
+ it "reads after ungetc with multibyte characters in the buffer" do
+ @string = StringIO.new(+"∂φ/∂x = gaîté")
+ c = @string.getc
+ @string.ungetc(c)
+ @string.readpartial(3).should == "\xE2\x88\x82".b
+ @string.readpartial(3).should == "\xCF\x86/".b
+ end
+
it "reads after ungetc without data in the buffer" do
@string = StringIO.new
@string.write("f").should == 1
@@ -48,33 +50,53 @@ describe "StringIO#readpartial" do
end
it "discards the existing buffer content upon successful read" do
- buffer = "existing"
+ buffer = +"existing"
@string.readpartial(11, buffer)
buffer.should == "Stop, look,"
end
it "raises EOFError on EOF" do
@string.readpartial(18).should == 'Stop, look, listen'
- lambda { @string.readpartial(10) }.should raise_error(EOFError)
+ -> { @string.readpartial(10) }.should raise_error(EOFError)
end
it "discards the existing buffer content upon error" do
- buffer = 'hello'
+ buffer = +'hello'
@string.readpartial(100)
- lambda { @string.readpartial(1, buffer) }.should raise_error(EOFError)
+ -> { @string.readpartial(1, buffer) }.should raise_error(EOFError)
buffer.should be_empty
end
it "raises IOError if the stream is closed" do
@string.close
- lambda { @string.readpartial(1) }.should raise_error(IOError)
+ -> { @string.readpartial(1) }.should raise_error(IOError, "not opened for reading")
end
it "raises ArgumentError if the negative argument is provided" do
- lambda { @string.readpartial(-1) }.should raise_error(ArgumentError)
+ -> { @string.readpartial(-1) }.should raise_error(ArgumentError, "negative length -1 given")
end
it "immediately returns an empty string if the length argument is 0" do
@string.readpartial(0).should == ""
end
+
+ it "raises IOError if the stream is closed and the length argument is 0" do
+ @string.close
+ -> { @string.readpartial(0) }.should raise_error(IOError, "not opened for reading")
+ end
+
+ it "clears and returns the given buffer if the length argument is 0" do
+ buffer = +"existing content"
+ @string.readpartial(0, buffer).should == buffer
+ buffer.should == ""
+ end
+
+ version_is StringIO::VERSION, "3.1.2" do # ruby_version_is "3.4"
+ it "preserves the encoding of the given buffer" do
+ buffer = ''.encode(Encoding::ISO_8859_1)
+ @string.readpartial(10, buffer)
+
+ buffer.encoding.should == Encoding::ISO_8859_1
+ end
+ end
end
diff --git a/spec/ruby/library/stringio/reopen_spec.rb b/spec/ruby/library/stringio/reopen_spec.rb
index 51aff43ba2..7021ff17e5 100644
--- a/spec/ruby/library/stringio/reopen_spec.rb
+++ b/spec/ruby/library/stringio/reopen_spec.rb
@@ -12,44 +12,35 @@ describe "StringIO#reopen when passed [Object, Integer]" do
@io.closed_write?.should be_true
@io.string.should == "reopened"
- @io.reopen("reopened, twice", IO::WRONLY)
+ @io.reopen(+"reopened, twice", IO::WRONLY)
@io.closed_read?.should be_true
@io.closed_write?.should be_false
@io.string.should == "reopened, twice"
- @io.reopen("reopened, another time", IO::RDWR)
+ @io.reopen(+"reopened, another time", IO::RDWR)
@io.closed_read?.should be_false
@io.closed_write?.should be_false
@io.string.should == "reopened, another time"
end
- # NOTE: WEIRD!
- it "does not taint self when the passed Object was tainted" do
- @io.reopen("reopened".taint, IO::RDONLY)
- @io.tainted?.should be_false
-
- @io.reopen("reopened".taint, IO::WRONLY)
- @io.tainted?.should be_false
- end
-
it "tries to convert the passed Object to a String using #to_str" do
obj = mock("to_str")
- obj.should_receive(:to_str).and_return("to_str")
+ obj.should_receive(:to_str).and_return(+"to_str")
@io.reopen(obj, IO::RDWR)
@io.string.should == "to_str"
end
it "raises a TypeError when the passed Object can't be converted to a String" do
- lambda { @io.reopen(Object.new, IO::RDWR) }.should raise_error(TypeError)
+ -> { @io.reopen(Object.new, IO::RDWR) }.should raise_error(TypeError)
end
it "raises an Errno::EACCES when trying to reopen self with a frozen String in write-mode" do
- lambda { @io.reopen("burn".freeze, IO::WRONLY) }.should raise_error(Errno::EACCES)
- lambda { @io.reopen("burn".freeze, IO::WRONLY | IO::APPEND) }.should raise_error(Errno::EACCES)
+ -> { @io.reopen("burn".freeze, IO::WRONLY) }.should raise_error(Errno::EACCES)
+ -> { @io.reopen("burn".freeze, IO::WRONLY | IO::APPEND) }.should raise_error(Errno::EACCES)
end
- it "raises a #{frozen_error_class} when trying to reopen self with a frozen String in truncate-mode" do
- lambda { @io.reopen("burn".freeze, IO::RDONLY | IO::TRUNC) }.should raise_error(frozen_error_class)
+ it "raises a FrozenError when trying to reopen self with a frozen String in truncate-mode" do
+ -> { @io.reopen("burn".freeze, IO::RDONLY | IO::TRUNC) }.should raise_error(FrozenError)
end
it "does not raise IOError when passed a frozen String in read-mode" do
@@ -69,36 +60,27 @@ describe "StringIO#reopen when passed [Object, Object]" do
@io.closed_write?.should be_true
@io.string.should == "reopened"
- @io.reopen("reopened, twice", "r+")
+ @io.reopen(+"reopened, twice", "r+")
@io.closed_read?.should be_false
@io.closed_write?.should be_false
@io.string.should == "reopened, twice"
- @io.reopen("reopened, another", "w+")
+ @io.reopen(+"reopened, another", "w+")
@io.closed_read?.should be_false
@io.closed_write?.should be_false
@io.string.should == ""
- @io.reopen("reopened, another time", "r+")
+ @io.reopen(+"reopened, another time", "r+")
@io.closed_read?.should be_false
@io.closed_write?.should be_false
@io.string.should == "reopened, another time"
end
it "truncates the passed String when opened in truncate mode" do
- @io.reopen(str = "reopened", "w")
+ @io.reopen(str = +"reopened", "w")
str.should == ""
end
- # NOTE: WEIRD!
- it "does not taint self when the passed Object was tainted" do
- @io.reopen("reopened".taint, "r")
- @io.tainted?.should be_false
-
- @io.reopen("reopened".taint, "w")
- @io.tainted?.should be_false
- end
-
it "tries to convert the passed Object to a String using #to_str" do
obj = mock("to_str")
obj.should_receive(:to_str).and_return("to_str")
@@ -107,18 +89,18 @@ describe "StringIO#reopen when passed [Object, Object]" do
end
it "raises a TypeError when the passed Object can't be converted to a String using #to_str" do
- lambda { @io.reopen(Object.new, "r") }.should raise_error(TypeError)
+ -> { @io.reopen(Object.new, "r") }.should raise_error(TypeError)
end
it "resets self's position to 0" do
@io.read(5)
- @io.reopen("reopened")
+ @io.reopen(+"reopened")
@io.pos.should eql(0)
end
it "resets self's line number to 0" do
@io.gets
- @io.reopen("reopened")
+ @io.reopen(+"reopened")
@io.lineno.should eql(0)
end
@@ -132,10 +114,10 @@ describe "StringIO#reopen when passed [Object, Object]" do
end
it "raises an Errno::EACCES error when trying to reopen self with a frozen String in write-mode" do
- lambda { @io.reopen("burn".freeze, 'w') }.should raise_error(Errno::EACCES)
- lambda { @io.reopen("burn".freeze, 'w+') }.should raise_error(Errno::EACCES)
- lambda { @io.reopen("burn".freeze, 'a') }.should raise_error(Errno::EACCES)
- lambda { @io.reopen("burn".freeze, "r+") }.should raise_error(Errno::EACCES)
+ -> { @io.reopen("burn".freeze, 'w') }.should raise_error(Errno::EACCES)
+ -> { @io.reopen("burn".freeze, 'w+') }.should raise_error(Errno::EACCES)
+ -> { @io.reopen("burn".freeze, 'a') }.should raise_error(Errno::EACCES)
+ -> { @io.reopen("burn".freeze, "r+") }.should raise_error(Errno::EACCES)
end
it "does not raise IOError if a frozen string is passed in read mode" do
@@ -152,7 +134,7 @@ describe "StringIO#reopen when passed [String]" do
it "reopens self with the passed String in read-write mode" do
@io.close
- @io.reopen("reopened")
+ @io.reopen(+"reopened")
@io.closed_write?.should be_false
@io.closed_read?.should be_false
@@ -160,21 +142,15 @@ describe "StringIO#reopen when passed [String]" do
@io.string.should == "reopened"
end
- # NOTE: WEIRD!
- it "does not taint self when the passed Object was tainted" do
- @io.reopen("reopened".taint)
- @io.tainted?.should be_false
- end
-
it "resets self's position to 0" do
@io.read(5)
- @io.reopen("reopened")
+ @io.reopen(+"reopened")
@io.pos.should eql(0)
end
it "resets self's line number to 0" do
@io.gets
- @io.reopen("reopened")
+ @io.reopen(+"reopened")
@io.lineno.should eql(0)
end
end
@@ -185,27 +161,21 @@ describe "StringIO#reopen when passed [Object]" do
end
it "raises a TypeError when passed an Object that can't be converted to a StringIO" do
- lambda { @io.reopen(Object.new) }.should raise_error(TypeError)
+ -> { @io.reopen(Object.new) }.should raise_error(TypeError)
end
it "does not try to convert the passed Object to a String using #to_str" do
obj = mock("not to_str")
obj.should_not_receive(:to_str)
- lambda { @io.reopen(obj) }.should raise_error(TypeError)
+ -> { @io.reopen(obj) }.should raise_error(TypeError)
end
it "tries to convert the passed Object to a StringIO using #to_strio" do
obj = mock("to_strio")
- obj.should_receive(:to_strio).and_return(StringIO.new("to_strio"))
+ obj.should_receive(:to_strio).and_return(StringIO.new(+"to_strio"))
@io.reopen(obj)
@io.string.should == "to_strio"
end
-
- # NOTE: WEIRD!
- it "taints self when the passed Object was tainted" do
- @io.reopen(StringIO.new("reopened").taint)
- @io.tainted?.should be_true
- end
end
describe "StringIO#reopen when passed no arguments" do
@@ -238,47 +208,40 @@ end
# for details.
describe "StringIO#reopen" do
before :each do
- @io = StringIO.new('hello','a')
+ @io = StringIO.new(+'hello', 'a')
end
# TODO: find out if this is really a bug
it "reopens a stream when given a String argument" do
- @io.reopen('goodbye').should == @io
+ @io.reopen(+'goodbye').should == @io
@io.string.should == 'goodbye'
@io << 'x'
@io.string.should == 'xoodbye'
end
it "reopens a stream in append mode when flagged as such" do
- @io.reopen('goodbye', 'a').should == @io
+ @io.reopen(+'goodbye', 'a').should == @io
@io.string.should == 'goodbye'
@io << 'x'
@io.string.should == 'goodbyex'
end
it "reopens and truncate when reopened in write mode" do
- @io.reopen('goodbye', 'wb').should == @io
+ @io.reopen(+'goodbye', 'wb').should == @io
@io.string.should == ''
@io << 'x'
@io.string.should == 'x'
end
it "truncates the given string, not a copy" do
- str = 'goodbye'
+ str = +'goodbye'
@io.reopen(str, 'w')
@io.string.should == ''
str.should == ''
end
- it "taints self if the provided StringIO argument is tainted" do
- new_io = StringIO.new("tainted")
- new_io.taint
- @io.reopen(new_io)
- @io.tainted?.should == true
- end
-
it "does not truncate the content even when the StringIO argument is in the truncate mode" do
- orig_io = StringIO.new("Original StringIO", IO::RDWR|IO::TRUNC)
+ orig_io = StringIO.new(+"Original StringIO", IO::RDWR|IO::TRUNC)
orig_io.write("BLAH") # make sure the content is not empty
@io.reopen(orig_io)
diff --git a/spec/ruby/library/stringio/seek_spec.rb b/spec/ruby/library/stringio/seek_spec.rb
index b963b77eef..253b5027a9 100644
--- a/spec/ruby/library/stringio/seek_spec.rb
+++ b/spec/ruby/library/stringio/seek_spec.rb
@@ -33,14 +33,14 @@ describe "StringIO#seek" do
end
it "raises an Errno::EINVAL error on negative amounts when whence is IO::SEEK_SET" do
- lambda { @io.seek(-5, IO::SEEK_SET) }.should raise_error(Errno::EINVAL)
+ -> { @io.seek(-5, IO::SEEK_SET) }.should raise_error(Errno::EINVAL)
end
it "raises an Errno::EINVAL error on incorrect whence argument" do
- lambda { @io.seek(0, 3) }.should raise_error(Errno::EINVAL)
- lambda { @io.seek(0, -1) }.should raise_error(Errno::EINVAL)
- lambda { @io.seek(0, 2**16) }.should raise_error(Errno::EINVAL)
- lambda { @io.seek(0, -2**16) }.should raise_error(Errno::EINVAL)
+ -> { @io.seek(0, 3) }.should raise_error(Errno::EINVAL)
+ -> { @io.seek(0, -1) }.should raise_error(Errno::EINVAL)
+ -> { @io.seek(0, 2**16) }.should raise_error(Errno::EINVAL)
+ -> { @io.seek(0, -2**16) }.should raise_error(Errno::EINVAL)
end
it "tries to convert the passed Object to a String using #to_int" do
@@ -51,7 +51,7 @@ describe "StringIO#seek" do
end
it "raises a TypeError when the passed Object can't be converted to an Integer" do
- lambda { @io.seek(Object.new) }.should raise_error(TypeError)
+ -> { @io.seek(Object.new) }.should raise_error(TypeError)
end
end
@@ -62,6 +62,6 @@ describe "StringIO#seek when self is closed" do
end
it "raises an IOError" do
- lambda { @io.seek(5) }.should raise_error(IOError)
+ -> { @io.seek(5) }.should raise_error(IOError)
end
end
diff --git a/spec/ruby/library/stringio/set_encoding_by_bom_spec.rb b/spec/ruby/library/stringio/set_encoding_by_bom_spec.rb
new file mode 100644
index 0000000000..1030aad042
--- /dev/null
+++ b/spec/ruby/library/stringio/set_encoding_by_bom_spec.rb
@@ -0,0 +1,237 @@
+require 'stringio'
+require_relative '../../spec_helper'
+
+# Should be synced with specs for IO#set_encoding_by_bom
+describe "StringIO#set_encoding_by_bom" do
+ it "returns nil if not readable" do
+ io = StringIO.new("".b, "wb")
+
+ io.set_encoding_by_bom.should be_nil
+ io.external_encoding.should == Encoding::ASCII_8BIT
+ end
+
+ it "returns the result encoding if found BOM UTF-8 sequence" do
+ io = StringIO.new("\u{FEFF}".b, "rb")
+
+ io.set_encoding_by_bom.should == Encoding::UTF_8
+ io.external_encoding.should == Encoding::UTF_8
+ io.read.b.should == "".b
+
+ io = StringIO.new("\u{FEFF}abc".b, "rb")
+
+ io.set_encoding_by_bom.should == Encoding::UTF_8
+ io.external_encoding.should == Encoding::UTF_8
+ io.read.b.should == "abc".b
+ end
+
+ it "returns the result encoding if found BOM UTF_16LE sequence" do
+ io = StringIO.new("\xFF\xFE".b, "rb")
+
+ io.set_encoding_by_bom.should == Encoding::UTF_16LE
+ io.external_encoding.should == Encoding::UTF_16LE
+ io.read.b.should == "".b
+
+ io = StringIO.new("\xFF\xFEabc".b, "rb")
+
+ io.set_encoding_by_bom.should == Encoding::UTF_16LE
+ io.external_encoding.should == Encoding::UTF_16LE
+ io.read.b.should == "abc".b
+ end
+
+ it "returns the result encoding if found BOM UTF_16BE sequence" do
+ io = StringIO.new("\xFE\xFF".b, "rb")
+
+ io.set_encoding_by_bom.should == Encoding::UTF_16BE
+ io.external_encoding.should == Encoding::UTF_16BE
+ io.read.b.should == "".b
+
+ io = StringIO.new("\xFE\xFFabc".b, "rb")
+
+ io.set_encoding_by_bom.should == Encoding::UTF_16BE
+ io.external_encoding.should == Encoding::UTF_16BE
+ io.read.b.should == "abc".b
+ end
+
+ it "returns the result encoding if found BOM UTF_32LE sequence" do
+ io = StringIO.new("\xFF\xFE\x00\x00".b, "rb")
+
+ io.set_encoding_by_bom.should == Encoding::UTF_32LE
+ io.external_encoding.should == Encoding::UTF_32LE
+ io.read.b.should == "".b
+
+ io = StringIO.new("\xFF\xFE\x00\x00abc".b, "rb")
+
+ io.set_encoding_by_bom.should == Encoding::UTF_32LE
+ io.external_encoding.should == Encoding::UTF_32LE
+ io.read.b.should == "abc".b
+ end
+
+ it "returns the result encoding if found BOM UTF_32BE sequence" do
+ io = StringIO.new("\x00\x00\xFE\xFF".b, "rb")
+
+ io.set_encoding_by_bom.should == Encoding::UTF_32BE
+ io.external_encoding.should == Encoding::UTF_32BE
+ io.read.b.should == "".b
+
+ io = StringIO.new("\x00\x00\xFE\xFFabc".b, "rb")
+
+ io.set_encoding_by_bom.should == Encoding::UTF_32BE
+ io.external_encoding.should == Encoding::UTF_32BE
+ io.read.b.should == "abc".b
+ end
+
+ it "returns nil if io is empty" do
+ io = StringIO.new("".b, "rb")
+ io.set_encoding_by_bom.should be_nil
+ io.external_encoding.should == Encoding::ASCII_8BIT
+ end
+
+ it "returns nil if UTF-8 BOM sequence is incomplete" do
+ io = StringIO.new("\xEF".b, "rb")
+
+ io.set_encoding_by_bom.should == nil
+ io.external_encoding.should == Encoding::ASCII_8BIT
+ io.read.b.should == "\xEF".b
+
+ io = StringIO.new("\xEFa".b, "rb")
+
+ io.set_encoding_by_bom.should == nil
+ io.external_encoding.should == Encoding::ASCII_8BIT
+ io.read.b.should == "\xEFa".b
+
+ io = StringIO.new("\xEF\xBB".b, "rb")
+
+ io.set_encoding_by_bom.should == nil
+ io.external_encoding.should == Encoding::ASCII_8BIT
+ io.read.b.should == "\xEF\xBB".b
+
+ io = StringIO.new("\xEF\xBBa".b, "rb")
+
+ io.set_encoding_by_bom.should == nil
+ io.external_encoding.should == Encoding::ASCII_8BIT
+ io.read.b.should == "\xEF\xBBa".b
+ end
+
+ it "returns nil if UTF-16BE BOM sequence is incomplete" do
+ io = StringIO.new("\xFE".b, "rb")
+
+ io.set_encoding_by_bom.should == nil
+ io.external_encoding.should == Encoding::ASCII_8BIT
+ io.read.b.should == "\xFE".b
+
+ io = StringIO.new("\xFEa".b, "rb")
+
+ io.set_encoding_by_bom.should == nil
+ io.external_encoding.should == Encoding::ASCII_8BIT
+ io.read.b.should == "\xFEa".b
+ end
+
+ it "returns nil if UTF-16LE/UTF-32LE BOM sequence is incomplete" do
+ io = StringIO.new("\xFF".b, "rb")
+
+ io.set_encoding_by_bom.should == nil
+ io.external_encoding.should == Encoding::ASCII_8BIT
+ io.read.b.should == "\xFF".b
+
+ io = StringIO.new("\xFFa".b, "rb")
+
+ io.set_encoding_by_bom.should == nil
+ io.external_encoding.should == Encoding::ASCII_8BIT
+ io.read.b.should == "\xFFa".b
+ end
+
+ it "returns UTF-16LE if UTF-32LE BOM sequence is incomplete" do
+ io = StringIO.new("\xFF\xFE".b, "rb")
+
+ io.set_encoding_by_bom.should == Encoding::UTF_16LE
+ io.external_encoding.should == Encoding::UTF_16LE
+ io.read.b.should == "".b
+
+ io = StringIO.new("\xFF\xFE\x00".b, "rb")
+
+ io.set_encoding_by_bom.should == Encoding::UTF_16LE
+ io.external_encoding.should == Encoding::UTF_16LE
+ io.read.b.should == "\x00".b
+
+ io = StringIO.new("\xFF\xFE\x00a".b, "rb")
+
+ io.set_encoding_by_bom.should == Encoding::UTF_16LE
+ io.external_encoding.should == Encoding::UTF_16LE
+ io.read.b.should == "\x00a".b
+ end
+
+ it "returns nil if UTF-32BE BOM sequence is incomplete" do
+ io = StringIO.new("\x00".b, "rb")
+
+ io.set_encoding_by_bom.should == nil
+ io.external_encoding.should == Encoding::ASCII_8BIT
+ io.read.b.should == "\x00".b
+
+ io = StringIO.new("\x00a".b, "rb")
+
+ io.set_encoding_by_bom.should == nil
+ io.external_encoding.should == Encoding::ASCII_8BIT
+ io.read.b.should == "\x00a".b
+
+ io = StringIO.new("\x00\x00".b, "rb")
+
+ io.set_encoding_by_bom.should == nil
+ io.external_encoding.should == Encoding::ASCII_8BIT
+ io.read.b.should == "\x00\x00".b
+
+ io = StringIO.new("\x00\x00a".b, "rb")
+
+ io.set_encoding_by_bom.should == nil
+ io.external_encoding.should == Encoding::ASCII_8BIT
+ io.read.b.should == "\x00\x00a".b
+
+ io = StringIO.new("\x00\x00\xFE".b, "rb")
+
+ io.set_encoding_by_bom.should == nil
+ io.external_encoding.should == Encoding::ASCII_8BIT
+ io.read.b.should == "\x00\x00\xFE".b
+
+ io = StringIO.new("\x00\x00\xFEa".b, "rb")
+
+ io.set_encoding_by_bom.should == nil
+ io.external_encoding.should == Encoding::ASCII_8BIT
+ io.read.b.should == "\x00\x00\xFEa".b
+ end
+
+ it "returns nil if found BOM sequence not provided" do
+ io = StringIO.new("abc".b, "rb")
+
+ io.set_encoding_by_bom.should == nil
+ io.external_encoding.should == Encoding::ASCII_8BIT
+ io.read(3).should == "abc".b
+ end
+
+ it "does not raise exception if io not in binary mode" do
+ io = StringIO.new("", 'r')
+ io.set_encoding_by_bom.should == nil
+ end
+
+ it "does not raise exception if encoding already set" do
+ io = StringIO.new("".b, "rb")
+ io.set_encoding("utf-8")
+ io.set_encoding_by_bom.should == nil
+ end
+
+ it "does not raise exception if encoding conversion is already set" do
+ io = StringIO.new("".b, "rb")
+ io.set_encoding(Encoding::UTF_8, Encoding::UTF_16BE)
+
+ io.set_encoding_by_bom.should == nil
+ end
+
+ it "raises FrozenError when io is frozen" do
+ io = StringIO.new()
+ io.freeze
+ -> { io.set_encoding_by_bom }.should raise_error(FrozenError)
+ end
+
+ it "does not raise FrozenError when initial string is frozen" do
+ io = StringIO.new("".freeze)
+ io.set_encoding_by_bom.should == nil
+ end
+end
diff --git a/spec/ruby/library/stringio/set_encoding_spec.rb b/spec/ruby/library/stringio/set_encoding_spec.rb
index 21d45750f3..19ca0875bf 100644
--- a/spec/ruby/library/stringio/set_encoding_spec.rb
+++ b/spec/ruby/library/stringio/set_encoding_spec.rb
@@ -17,4 +17,12 @@ describe "StringIO#set_encoding" do
io.set_encoding Encoding::UTF_8
io.string.encoding.should == Encoding::US_ASCII
end
+
+ it "accepts a String" do
+ str = "".encode(Encoding::US_ASCII)
+ io = StringIO.new(str)
+ io.set_encoding("ASCII-8BIT")
+ io.external_encoding.should == Encoding::BINARY
+ str.encoding.should == Encoding::BINARY
+ end
end
diff --git a/spec/ruby/library/stringio/shared/codepoints.rb b/spec/ruby/library/stringio/shared/codepoints.rb
index c8ca03329f..25333bb0fd 100644
--- a/spec/ruby/library/stringio/shared/codepoints.rb
+++ b/spec/ruby/library/stringio/shared/codepoints.rb
@@ -20,15 +20,15 @@ describe :stringio_codepoints, shared: true do
it "raises an error if reading invalid sequence" do
@io.pos = 1 # inside of a multibyte sequence
- lambda { @enum.first }.should raise_error(ArgumentError)
+ -> { @enum.first }.should raise_error(ArgumentError)
end
it "raises an IOError if not readable" do
@io.close_read
- lambda { @enum.to_a }.should raise_error(IOError)
+ -> { @enum.to_a }.should raise_error(IOError)
- io = StringIO.new("xyz", "w")
- lambda { io.send(@method).to_a }.should raise_error(IOError)
+ io = StringIO.new(+"xyz", "w")
+ -> { io.send(@method).to_a }.should raise_error(IOError)
end
diff --git a/spec/ruby/library/stringio/shared/each.rb b/spec/ruby/library/stringio/shared/each.rb
index 55ed27c1c7..626b41a4d3 100644
--- a/spec/ruby/library/stringio/shared/each.rb
+++ b/spec/ruby/library/stringio/shared/each.rb
@@ -36,11 +36,11 @@ describe :stringio_each_separator, shared: true do
seen.should == ["2 1 2 1 2"]
end
- it "yields each paragraph when passed an empty String as separator" do
+ it "yields each paragraph with all separation characters when passed an empty String as separator" do
seen = []
io = StringIO.new("para1\n\npara2\n\n\npara3")
io.send(@method, "") {|s| seen << s}
- seen.should == ["para1\n\n", "para2\n\n", "para3"]
+ seen.should == ["para1\n\n", "para2\n\n\n", "para3"]
end
end
@@ -71,11 +71,12 @@ describe :stringio_each_no_arguments, shared: true do
it "uses $/ as the default line separator" do
seen = []
begin
- old_rs, $/ = $/, " "
+ old_rs = $/
+ suppress_warning {$/ = " "}
@io.send(@method) {|s| seen << s }
seen.should eql(["a ", "b ", "c ", "d ", "e\n1 ", "2 ", "3 ", "4 ", "5"])
ensure
- $/ = old_rs
+ suppress_warning {$/ = old_rs}
end
end
@@ -95,12 +96,12 @@ end
describe :stringio_each_not_readable, shared: true do
it "raises an IOError" do
- io = StringIO.new("a b c d e", "w")
- lambda { io.send(@method) { |b| b } }.should raise_error(IOError)
+ io = StringIO.new(+"a b c d e", "w")
+ -> { io.send(@method) { |b| b } }.should raise_error(IOError)
io = StringIO.new("a b c d e")
io.close_read
- lambda { io.send(@method) { |b| b } }.should raise_error(IOError)
+ -> { io.send(@method) { |b| b } }.should raise_error(IOError)
end
end
@@ -111,4 +112,98 @@ describe :stringio_each_chomp, shared: true do
io.send(@method, chomp: true) {|s| seen << s }
seen.should == ["a b \rc d e", "1 2 3 4 5", "the end"]
end
+
+ it "returns each line with removed newline characters when called without block" do
+ seen = []
+ io = StringIO.new("a b \rc d e\n1 2 3 4 5\r\nthe end")
+ enum = io.send(@method, chomp: true)
+ enum.each {|s| seen << s }
+ seen.should == ["a b \rc d e", "1 2 3 4 5", "the end"]
+ end
+end
+
+describe :stringio_each_separator_and_chomp, shared: true do
+ it "yields each line with removed separator to the passed block" do
+ seen = []
+ io = StringIO.new("a b \nc d e|1 2 3 4 5\n|the end")
+ io.send(@method, "|", chomp: true) {|s| seen << s }
+ seen.should == ["a b \nc d e", "1 2 3 4 5\n", "the end"]
+ end
+
+ it "returns each line with removed separator when called without block" do
+ seen = []
+ io = StringIO.new("a b \nc d e|1 2 3 4 5\n|the end")
+ enum = io.send(@method, "|", chomp: true)
+ enum.each {|s| seen << s }
+ seen.should == ["a b \nc d e", "1 2 3 4 5\n", "the end"]
+ end
+end
+
+describe :stringio_each_limit, shared: true do
+ before :each do
+ @io = StringIO.new("a b c d e\n1 2 3 4 5")
+ end
+
+ it "returns the data read until the limit is met" do
+ seen = []
+ @io.send(@method, 4) { |s| seen << s }
+ seen.should == ["a b ", "c d ", "e\n", "1 2 ", "3 4 ", "5"]
+ end
+end
+
+describe :stringio_each_separator_and_limit, shared: true do
+ before :each do
+ @io = StringIO.new("this>is>an>example")
+ end
+
+ it "returns the data read until the limit is consumed or the separator is met" do
+ @io.send(@method, '>', 8) { |s| break s }.should == "this>"
+ @io.send(@method, '>', 2) { |s| break s }.should == "is"
+ @io.send(@method, '>', 10) { |s| break s }.should == ">"
+ @io.send(@method, '>', 6) { |s| break s }.should == "an>"
+ @io.send(@method, '>', 5) { |s| break s }.should == "examp"
+ end
+
+ it "truncates the multi-character separator at the end to meet the limit" do
+ @io.send(@method, "is>an", 7) { |s| break s }.should == "this>is"
+ end
+
+ it "does not change $_" do
+ $_ = "test"
+ @io.send(@method, '>', 8) { |s| s }
+ $_.should == "test"
+ end
+
+ it "updates self's lineno by one" do
+ @io.send(@method, '>', 3) { |s| break s }
+ @io.lineno.should eql(1)
+
+ @io.send(@method, '>', 3) { |s| break s }
+ @io.lineno.should eql(2)
+
+ @io.send(@method, '>', 3) { |s| break s }
+ @io.lineno.should eql(3)
+ end
+
+ it "tries to convert the passed separator to a String using #to_str" do # TODO
+ obj = mock('to_str')
+ obj.should_receive(:to_str).and_return('>')
+
+ seen = []
+ @io.send(@method, obj, 5) { |s| seen << s }
+ seen.should == ["this>", "is>", "an>", "examp", "le"]
+ end
+
+ it "does not raise TypeError if passed separator is nil" do
+ @io.send(@method, nil, 5) { |s| break s }.should == "this>"
+ end
+
+ it "tries to convert the passed limit to an Integer using #to_int" do # TODO
+ obj = mock('to_int')
+ obj.should_receive(:to_int).and_return(5)
+
+ seen = []
+ @io.send(@method, '>', obj) { |s| seen << s }
+ seen.should == ["this>", "is>", "an>", "examp", "le"]
+ end
end
diff --git a/spec/ruby/library/stringio/shared/each_byte.rb b/spec/ruby/library/stringio/shared/each_byte.rb
index 1dc48ee437..b51fa38f2f 100644
--- a/spec/ruby/library/stringio/shared/each_byte.rb
+++ b/spec/ruby/library/stringio/shared/each_byte.rb
@@ -38,11 +38,11 @@ end
describe :stringio_each_byte_not_readable, shared: true do
it "raises an IOError" do
- io = StringIO.new("xyz", "w")
- lambda { io.send(@method) { |b| b } }.should raise_error(IOError)
+ io = StringIO.new(+"xyz", "w")
+ -> { io.send(@method) { |b| b } }.should raise_error(IOError)
io = StringIO.new("xyz")
io.close_read
- lambda { io.send(@method) { |b| b } }.should raise_error(IOError)
+ -> { io.send(@method) { |b| b } }.should raise_error(IOError)
end
end
diff --git a/spec/ruby/library/stringio/shared/each_char.rb b/spec/ruby/library/stringio/shared/each_char.rb
index 35efdcb749..197237c1c8 100644
--- a/spec/ruby/library/stringio/shared/each_char.rb
+++ b/spec/ruby/library/stringio/shared/each_char.rb
@@ -26,11 +26,11 @@ end
describe :stringio_each_char_not_readable, shared: true do
it "raises an IOError" do
- io = StringIO.new("xyz", "w")
- lambda { io.send(@method) { |b| b } }.should raise_error(IOError)
+ io = StringIO.new(+"xyz", "w")
+ -> { io.send(@method) { |b| b } }.should raise_error(IOError)
io = StringIO.new("xyz")
io.close_read
- lambda { io.send(@method) { |b| b } }.should raise_error(IOError)
+ -> { io.send(@method) { |b| b } }.should raise_error(IOError)
end
end
diff --git a/spec/ruby/library/stringio/shared/getc.rb b/spec/ruby/library/stringio/shared/getc.rb
index 3e064f9c1e..ba65040bce 100644
--- a/spec/ruby/library/stringio/shared/getc.rb
+++ b/spec/ruby/library/stringio/shared/getc.rb
@@ -33,11 +33,11 @@ end
describe :stringio_getc_not_readable, shared: true do
it "raises an IOError" do
- io = StringIO.new("xyz", "w")
- lambda { io.send(@method) }.should raise_error(IOError)
+ io = StringIO.new(+"xyz", "w")
+ -> { io.send(@method) }.should raise_error(IOError)
io = StringIO.new("xyz")
io.close_read
- lambda { io.send(@method) }.should raise_error(IOError)
+ -> { io.send(@method) }.should raise_error(IOError)
end
end
diff --git a/spec/ruby/library/stringio/shared/gets.rb b/spec/ruby/library/stringio/shared/gets.rb
new file mode 100644
index 0000000000..8396b161f1
--- /dev/null
+++ b/spec/ruby/library/stringio/shared/gets.rb
@@ -0,0 +1,249 @@
+describe :stringio_gets_separator, shared: true do
+ describe "when passed [separator]" do
+ before :each do
+ @io = StringIO.new("this>is>an>example")
+ end
+
+ it "returns the data read till the next occurrence of the passed separator" do
+ @io.send(@method, ">").should == "this>"
+ @io.send(@method, ">").should == "is>"
+ @io.send(@method, ">").should == "an>"
+ @io.send(@method, ">").should == "example"
+ end
+
+ it "sets $_ to the read content" do
+ @io.send(@method, ">")
+ $_.should == "this>"
+ @io.send(@method, ">")
+ $_.should == "is>"
+ @io.send(@method, ">")
+ $_.should == "an>"
+ @io.send(@method, ">")
+ $_.should == "example"
+ end
+
+ it "accepts string as separator" do
+ @io.send(@method, "is>")
+ $_.should == "this>"
+ @io.send(@method, "an>")
+ $_.should == "is>an>"
+ @io.send(@method, "example")
+ $_.should == "example"
+ end
+
+ it "updates self's lineno by one" do
+ @io.send(@method, ">")
+ @io.lineno.should eql(1)
+
+ @io.send(@method, ">")
+ @io.lineno.should eql(2)
+
+ @io.send(@method, ">")
+ @io.lineno.should eql(3)
+ end
+
+ it "returns the next paragraph when the passed separator is an empty String" do
+ io = StringIO.new("this is\n\nan example")
+ io.send(@method, "").should == "this is\n\n"
+ io.send(@method, "").should == "an example"
+ end
+
+ it "returns the remaining content starting at the current position when passed nil" do
+ io = StringIO.new("this is\n\nan example")
+ io.pos = 5
+ io.send(@method, nil).should == "is\n\nan example"
+ end
+
+ it "tries to convert the passed separator to a String using #to_str" do
+ obj = mock('to_str')
+ obj.should_receive(:to_str).and_return(">")
+ @io.send(@method, obj).should == "this>"
+ end
+ end
+end
+
+describe :stringio_gets_limit, shared: true do
+ describe "when passed [limit]" do
+ before :each do
+ @io = StringIO.new("this>is>an>example")
+ end
+
+ it "returns the data read until the limit is met" do
+ @io.send(@method, 4).should == "this"
+ @io.send(@method, 3).should == ">is"
+ @io.send(@method, 5).should == ">an>e"
+ @io.send(@method, 6).should == "xample"
+ end
+
+ it "sets $_ to the read content" do
+ @io.send(@method, 4)
+ $_.should == "this"
+ @io.send(@method, 3)
+ $_.should == ">is"
+ @io.send(@method, 5)
+ $_.should == ">an>e"
+ @io.send(@method, 6)
+ $_.should == "xample"
+ end
+
+ it "updates self's lineno by one" do
+ @io.send(@method, 3)
+ @io.lineno.should eql(1)
+
+ @io.send(@method, 3)
+ @io.lineno.should eql(2)
+
+ @io.send(@method, 3)
+ @io.lineno.should eql(3)
+ end
+
+ it "tries to convert the passed limit to an Integer using #to_int" do
+ obj = mock('to_int')
+ obj.should_receive(:to_int).and_return(4)
+ @io.send(@method, obj).should == "this"
+ end
+
+ it "returns a blank string when passed a limit of 0" do
+ @io.send(@method, 0).should == ""
+ end
+
+ it "ignores it when passed a negative limit" do
+ @io.send(@method, -4).should == "this>is>an>example"
+ end
+ end
+end
+
+describe :stringio_gets_separator_and_limit, shared: true do
+ describe "when passed [separator] and [limit]" do
+ before :each do
+ @io = StringIO.new("this>is>an>example")
+ end
+
+ it "returns the data read until the limit is consumed or the separator is met" do
+ @io.send(@method, '>', 8).should == "this>"
+ @io.send(@method, '>', 2).should == "is"
+ @io.send(@method, '>', 10).should == ">"
+ @io.send(@method, '>', 6).should == "an>"
+ @io.send(@method, '>', 5).should == "examp"
+ end
+
+ it "truncates the multi-character separator at the end to meet the limit" do
+ @io.send(@method, "is>an", 7).should == "this>is"
+ end
+
+ it "sets $_ to the read content" do
+ @io.send(@method, '>', 8)
+ $_.should == "this>"
+ @io.send(@method, '>', 2)
+ $_.should == "is"
+ @io.send(@method, '>', 10)
+ $_.should == ">"
+ @io.send(@method, '>', 6)
+ $_.should == "an>"
+ @io.send(@method, '>', 5)
+ $_.should == "examp"
+ end
+
+ it "updates self's lineno by one" do
+ @io.send(@method, '>', 3)
+ @io.lineno.should eql(1)
+
+ @io.send(@method, '>', 3)
+ @io.lineno.should eql(2)
+
+ @io.send(@method, '>', 3)
+ @io.lineno.should eql(3)
+ end
+
+ it "tries to convert the passed separator to a String using #to_str" do
+ obj = mock('to_str')
+ obj.should_receive(:to_str).and_return('>')
+ @io.send(@method, obj, 5).should == "this>"
+ end
+
+ it "does not raise TypeError if passed separator is nil" do
+ @io.send(@method, nil, 5).should == "this>"
+ end
+
+ it "tries to convert the passed limit to an Integer using #to_int" do
+ obj = mock('to_int')
+ obj.should_receive(:to_int).and_return(5)
+ @io.send(@method, '>', obj).should == "this>"
+ end
+ end
+end
+
+describe :stringio_gets_no_argument, shared: true do
+ describe "when passed no argument" do
+ before :each do
+ @io = StringIO.new("this is\nan example\nfor StringIO#gets")
+ end
+
+ it "returns the data read till the next occurrence of $/ or till eof" do
+ @io.send(@method).should == "this is\n"
+
+ begin
+ old_sep = $/
+ suppress_warning {$/ = " "}
+ @io.send(@method).should == "an "
+ @io.send(@method).should == "example\nfor "
+ @io.send(@method).should == "StringIO#gets"
+ ensure
+ suppress_warning {$/ = old_sep}
+ end
+ end
+
+ it "sets $_ to the read content" do
+ @io.send(@method)
+ $_.should == "this is\n"
+ @io.send(@method)
+ $_.should == "an example\n"
+ @io.send(@method)
+ $_.should == "for StringIO#gets"
+ end
+
+ it "updates self's position" do
+ @io.send(@method)
+ @io.pos.should eql(8)
+
+ @io.send(@method)
+ @io.pos.should eql(19)
+
+ @io.send(@method)
+ @io.pos.should eql(36)
+ end
+
+ it "updates self's lineno" do
+ @io.send(@method)
+ @io.lineno.should eql(1)
+
+ @io.send(@method)
+ @io.lineno.should eql(2)
+
+ @io.send(@method)
+ @io.lineno.should eql(3)
+ end
+ end
+end
+
+describe :stringio_gets_chomp, shared: true do
+ describe "when passed [chomp]" do
+ it "returns the data read without a trailing newline character" do
+ io = StringIO.new("this>is>an>example\n")
+ io.send(@method, chomp: true).should == "this>is>an>example"
+ end
+ end
+end
+
+describe :stringio_gets_write_only, shared: true do
+ describe "when in write-only mode" do
+ it "raises an IOError" do
+ io = StringIO.new(+"xyz", "w")
+ -> { io.send(@method) }.should raise_error(IOError)
+
+ io = StringIO.new("xyz")
+ io.close_read
+ -> { io.send(@method) }.should raise_error(IOError)
+ end
+ end
+end
diff --git a/spec/ruby/library/stringio/shared/isatty.rb b/spec/ruby/library/stringio/shared/isatty.rb
index 3da5999953..c9e7ee7321 100644
--- a/spec/ruby/library/stringio/shared/isatty.rb
+++ b/spec/ruby/library/stringio/shared/isatty.rb
@@ -1,5 +1,5 @@
describe :stringio_isatty, shared: true do
it "returns false" do
- StringIO.new('tty').send(@method).should be_false
+ StringIO.new("tty").send(@method).should be_false
end
end
diff --git a/spec/ruby/library/stringio/shared/read.rb b/spec/ruby/library/stringio/shared/read.rb
index 139c4fb02f..22f76b0fb0 100644
--- a/spec/ruby/library/stringio/shared/read.rb
+++ b/spec/ruby/library/stringio/shared/read.rb
@@ -5,30 +5,48 @@ describe :stringio_read, shared: true do
it "returns the passed buffer String" do
# Note: Rubinius bug:
- # @io.send(@method, 7, buffer = "").should equal(buffer)
- ret = @io.send(@method, 7, buffer = "")
+ # @io.send(@method, 7, buffer = +"").should equal(buffer)
+ ret = @io.send(@method, 7, buffer = +"")
ret.should equal(buffer)
end
it "reads length bytes and writes them to the buffer String" do
- @io.send(@method, 7, buffer = "")
+ @io.send(@method, 7, buffer = +"").should.equal?(buffer)
buffer.should == "example"
end
+ guard -> { StringIO::VERSION < "3.1.2" } do
+ it "does not preserve the encoding of the given buffer" do
+ buffer = ''.encode(Encoding::ISO_8859_1)
+ @io.send(@method, 7, buffer)
+
+ buffer.encoding.should_not == Encoding::ISO_8859_1
+ end
+ end
+
+ guard -> { StringIO::VERSION >= "3.1.2" } do
+ it "preserves the encoding of the given buffer" do
+ buffer = ''.encode(Encoding::ISO_8859_1)
+ @io.send(@method, 7, buffer)
+
+ buffer.encoding.should == Encoding::ISO_8859_1
+ end
+ end
+
it "tries to convert the passed buffer Object to a String using #to_str" do
obj = mock("to_str")
- obj.should_receive(:to_str).and_return(buffer = "")
+ obj.should_receive(:to_str).and_return(buffer = +"")
@io.send(@method, 7, obj)
buffer.should == "example"
end
it "raises a TypeError when the passed buffer Object can't be converted to a String" do
- lambda { @io.send(@method, 7, Object.new) }.should raise_error(TypeError)
+ -> { @io.send(@method, 7, Object.new) }.should raise_error(TypeError)
end
- it "raises a #{frozen_error_class} error when passed a frozen String as buffer" do
- lambda { @io.send(@method, 7, "".freeze) }.should raise_error(frozen_error_class)
+ it "raises a FrozenError error when passed a frozen String as buffer" do
+ -> { @io.send(@method, 7, "".freeze) }.should raise_error(FrozenError)
end
end
@@ -61,11 +79,11 @@ describe :stringio_read_length, shared: true do
end
it "raises a TypeError when the passed length can't be converted to an Integer" do
- lambda { @io.send(@method, Object.new) }.should raise_error(TypeError)
+ -> { @io.send(@method, Object.new) }.should raise_error(TypeError)
end
it "raises a TypeError when the passed length is negative" do
- lambda { @io.send(@method, -2) }.should raise_error(ArgumentError)
+ -> { @io.send(@method, -2) }.should raise_error(ArgumentError)
end
it "returns a binary String" do
@@ -75,7 +93,7 @@ end
describe :stringio_read_no_arguments, shared: true do
before :each do
- @io = StringIO.new("example")
+ @io = StringIO.new(+"example")
end
it "reads the whole content starting from the current position" do
@@ -89,6 +107,12 @@ describe :stringio_read_no_arguments, shared: true do
@io.send(@method)
@io.pos.should eql(7)
end
+
+ it "correctly update the current position in bytes when multi-byte characters are used" do
+ @io.print("example\u03A3") # Overwrite the original string with 8 characters containing 9 bytes.
+ @io.send(@method)
+ @io.pos.should eql(9)
+ end
end
describe :stringio_read_nil, shared: true do
@@ -111,11 +135,11 @@ end
describe :stringio_read_not_readable, shared: true do
it "raises an IOError" do
- io = StringIO.new("test", "w")
- lambda { io.send(@method) }.should raise_error(IOError)
+ io = StringIO.new(+"test", "w")
+ -> { io.send(@method) }.should raise_error(IOError)
io = StringIO.new("test")
io.close_read
- lambda { io.send(@method) }.should raise_error(IOError)
+ -> { io.send(@method) }.should raise_error(IOError)
end
end
diff --git a/spec/ruby/library/stringio/shared/readchar.rb b/spec/ruby/library/stringio/shared/readchar.rb
index 19194f0680..72d7446c36 100644
--- a/spec/ruby/library/stringio/shared/readchar.rb
+++ b/spec/ruby/library/stringio/shared/readchar.rb
@@ -13,17 +13,17 @@ describe :stringio_readchar, shared: true do
it "raises an EOFError when self is at the end" do
@io.pos = 7
- lambda { @io.send(@method) }.should raise_error(EOFError)
+ -> { @io.send(@method) }.should raise_error(EOFError)
end
end
describe :stringio_readchar_not_readable, shared: true do
it "raises an IOError" do
- io = StringIO.new("a b c d e", "w")
- lambda { io.send(@method) }.should raise_error(IOError)
+ io = StringIO.new(+"a b c d e", "w")
+ -> { io.send(@method) }.should raise_error(IOError)
io = StringIO.new("a b c d e")
io.close_read
- lambda { io.send(@method) }.should raise_error(IOError)
+ -> { io.send(@method) }.should raise_error(IOError)
end
end
diff --git a/spec/ruby/library/stringio/shared/sysread.rb b/spec/ruby/library/stringio/shared/sysread.rb
index 9800b2339b..3e23fbc233 100644
--- a/spec/ruby/library/stringio/shared/sysread.rb
+++ b/spec/ruby/library/stringio/shared/sysread.rb
@@ -1,4 +1,4 @@
-describe :stringio_sysread_length, :shared => true do
+describe :stringio_sysread_length, shared: true do
before :each do
@io = StringIO.new("example")
end
@@ -10,6 +10,6 @@ describe :stringio_sysread_length, :shared => true do
it "raises an EOFError when passed length > 0 and no data remains" do
@io.read.should == "example"
- lambda { @io.sysread(1) }.should raise_error(EOFError)
+ -> { @io.send(@method, 1) }.should raise_error(EOFError)
end
end
diff --git a/spec/ruby/library/stringio/shared/write.rb b/spec/ruby/library/stringio/shared/write.rb
index bcb548bbd0..4661658baf 100644
--- a/spec/ruby/library/stringio/shared/write.rb
+++ b/spec/ruby/library/stringio/shared/write.rb
@@ -1,6 +1,6 @@
describe :stringio_write, shared: true do
before :each do
- @io = StringIO.new('12345')
+ @io = StringIO.new(+'12345')
end
it "tries to convert the passed Object to a String using #to_s" do
@@ -13,7 +13,7 @@ end
describe :stringio_write_string, shared: true do
before :each do
- @io = StringIO.new('12345')
+ @io = StringIO.new(+'12345')
end
# TODO: RDoc says that #write appends at the current position.
@@ -45,31 +45,79 @@ describe :stringio_write_string, shared: true do
@io.pos.should eql(4)
end
- it "taints self's String when the passed argument is tainted" do
- @io.send(@method, "test".taint)
- @io.string.tainted?.should be_true
+ it "handles concurrent writes correctly" do
+ @io = StringIO.new
+ n = 8
+ go = false
+ threads = n.times.map { |i|
+ Thread.new {
+ Thread.pass until go
+ @io.write i.to_s
+ }
+ }
+ go = true
+ threads.each(&:join)
+ @io.string.size.should == n.times.map(&:to_s).join.size
end
- it "does not taint self when the passed argument is tainted" do
- @io.send(@method, "test".taint)
- @io.tainted?.should be_false
+ it "handles writing non-ASCII UTF-8 after seek" do
+ @io.binmode
+ @io << "\x80"
+ @io.pos = 0
+ @io << "\x81"
+ @io.string.should == "\x812345".b
+ end
+
+ it "handles writing with position < buffer size" do
+ @io.pos = 2
+ @io.write "abc"
+ @io.string.should == "12abc"
+
+ @io.pos = 2
+ @io.write "de"
+ @io.string.should == "12dec"
+
+ @io.pos = 2
+ @io.write "fghi"
+ @io.string.should == "12fghi"
+ end
+
+ it "transcodes the given string when the external encoding is set and neither is BINARY" do
+ utf8_str = "hello"
+ io = StringIO.new.set_encoding(Encoding::UTF_16BE)
+ io.external_encoding.should == Encoding::UTF_16BE
+
+ io.send(@method, utf8_str)
+
+ expected = [0, 104, 0, 101, 0, 108, 0, 108, 0, 111] # UTF-16BE bytes for "hello"
+ io.string.bytes.should == expected
+ end
+
+ it "does not transcode the given string when the external encoding is set and the string encoding is BINARY" do
+ str = "été_".b
+ io = StringIO.new.set_encoding(Encoding::UTF_16BE)
+ io.external_encoding.should == Encoding::UTF_16BE
+
+ io.send(@method, str)
+
+ io.string.bytes.should == str.bytes
end
end
describe :stringio_write_not_writable, shared: true do
it "raises an IOError" do
- io = StringIO.new("test", "r")
- lambda { io.send(@method, "test") }.should raise_error(IOError)
+ io = StringIO.new(+"test", "r")
+ -> { io.send(@method, "test") }.should raise_error(IOError)
- io = StringIO.new("test")
+ io = StringIO.new(+"test")
io.close_write
- lambda { io.send(@method, "test") }.should raise_error(IOError)
+ -> { io.send(@method, "test") }.should raise_error(IOError)
end
end
describe :stringio_write_append, shared: true do
before :each do
- @io = StringIO.new("example", "a")
+ @io = StringIO.new(+"example", "a")
end
it "appends the passed argument to the end of self" do
diff --git a/spec/ruby/library/stringio/string_spec.rb b/spec/ruby/library/stringio/string_spec.rb
index 384986c161..1ed5233ba6 100644
--- a/spec/ruby/library/stringio/string_spec.rb
+++ b/spec/ruby/library/stringio/string_spec.rb
@@ -45,6 +45,6 @@ describe "StringIO#string=" do
end
it "raises a TypeError when the passed Object can't be converted to an Integer" do
- lambda { @io.seek(Object.new) }.should raise_error(TypeError)
+ -> { @io.seek(Object.new) }.should raise_error(TypeError)
end
end
diff --git a/spec/ruby/library/stringio/sysread_spec.rb b/spec/ruby/library/stringio/sysread_spec.rb
index ee69801444..fabb06dd9a 100644
--- a/spec/ruby/library/stringio/sysread_spec.rb
+++ b/spec/ruby/library/stringio/sysread_spec.rb
@@ -1,6 +1,7 @@
require_relative '../../spec_helper'
require "stringio"
require_relative 'shared/read'
+require_relative 'shared/sysread'
describe "StringIO#sysread when passed length, buffer" do
it_behaves_like :stringio_read, :sysread
@@ -32,6 +33,10 @@ describe "StringIO#sysread when passed nil" do
end
end
+describe "StringIO#sysread when passed length" do
+ it_behaves_like :stringio_sysread_length, :sysread
+end
+
describe "StringIO#sysread when passed [length]" do
before :each do
@io = StringIO.new("example")
@@ -39,7 +44,7 @@ describe "StringIO#sysread when passed [length]" do
it "raises an EOFError when self's position is at the end" do
@io.pos = 7
- lambda { @io.sysread(10) }.should raise_error(EOFError)
+ -> { @io.sysread(10) }.should raise_error(EOFError)
end
it "returns an empty String when length is 0" do
diff --git a/spec/ruby/library/stringio/truncate_spec.rb b/spec/ruby/library/stringio/truncate_spec.rb
index d0d61af70a..592ca5a6e1 100644
--- a/spec/ruby/library/stringio/truncate_spec.rb
+++ b/spec/ruby/library/stringio/truncate_spec.rb
@@ -3,13 +3,11 @@ require "stringio"
describe "StringIO#truncate when passed [length]" do
before :each do
- @io = StringIO.new('123456789')
+ @io = StringIO.new(+'123456789')
end
- # TODO: Report to Ruby-Core: The RDoc says it always returns 0
- it "returns the passed length" do
- @io.truncate(4).should eql(4)
- @io.truncate(10).should eql(10)
+ it "returns an Integer" do
+ @io.truncate(4).should be_kind_of(Integer)
end
it "truncated the underlying string down to the passed length" do
@@ -18,7 +16,7 @@ describe "StringIO#truncate when passed [length]" do
end
it "does not create a copy of the underlying string" do
- io = StringIO.new(str = "123456789")
+ io = StringIO.new(str = +"123456789")
io.truncate(4)
io.string.should equal(str)
end
@@ -35,8 +33,8 @@ describe "StringIO#truncate when passed [length]" do
end
it "raises an Errno::EINVAL when the passed length is negative" do
- lambda { @io.truncate(-1) }.should raise_error(Errno::EINVAL)
- lambda { @io.truncate(-10) }.should raise_error(Errno::EINVAL)
+ -> { @io.truncate(-1) }.should raise_error(Errno::EINVAL)
+ -> { @io.truncate(-10) }.should raise_error(Errno::EINVAL)
end
it "tries to convert the passed length to an Integer using #to_int" do
@@ -47,24 +45,18 @@ describe "StringIO#truncate when passed [length]" do
@io.string.should == "1234"
end
- it "returns the passed length Object, NOT the result of #to_int" do
- obj = mock("to_int")
- obj.should_receive(:to_int).and_return(4)
- @io.truncate(obj).should equal(obj)
- end
-
it "raises a TypeError when the passed length can't be converted to an Integer" do
- lambda { @io.truncate(Object.new) }.should raise_error(TypeError)
+ -> { @io.truncate(Object.new) }.should raise_error(TypeError)
end
end
describe "StringIO#truncate when self is not writable" do
it "raises an IOError" do
- io = StringIO.new("test", "r")
- lambda { io.truncate(2) }.should raise_error(IOError)
+ io = StringIO.new(+"test", "r")
+ -> { io.truncate(2) }.should raise_error(IOError)
- io = StringIO.new("test")
+ io = StringIO.new(+"test")
io.close_write
- lambda { io.truncate(2) }.should raise_error(IOError)
+ -> { io.truncate(2) }.should raise_error(IOError)
end
end
diff --git a/spec/ruby/library/stringio/ungetbyte_spec.rb b/spec/ruby/library/stringio/ungetbyte_spec.rb
index 701463e621..87b27b837e 100644
--- a/spec/ruby/library/stringio/ungetbyte_spec.rb
+++ b/spec/ruby/library/stringio/ungetbyte_spec.rb
@@ -1,6 +1,42 @@
+# frozen_string_literal: false
require_relative '../../spec_helper'
require 'stringio'
describe "StringIO#ungetbyte" do
- it "needs to be reviewed for spec completeness"
+ it "ungets a single byte from a string starting with a single byte character" do
+ str = 'This is a simple string.'
+ io = StringIO.new("#{str}")
+ c = io.getc
+ c.should == 'T'
+ io.ungetbyte(83)
+ io.string.should == 'Shis is a simple string.'
+ end
+
+ it "ungets a single byte from a string in the middle of a multibyte character" do
+ str = "\u01a9"
+ io = StringIO.new(str)
+ b = io.getbyte
+ b.should == 0xc6 # First byte of UTF-8 encoding of \u01a9
+ io.ungetbyte(0xce) # First byte of UTF-8 encoding of \u03a9
+ io.string.should == "\u03a9"
+ end
+
+ it "constrains the value of a numeric argument to a single byte" do
+ str = 'This is a simple string.'
+ io = StringIO.new("#{str}")
+ c = io.getc
+ c.should == 'T'
+ io.ungetbyte(83 | 0xff00)
+ io.string.should == 'Shis is a simple string.'
+ end
+
+ it "ungets the bytes of a string if given a string as an argument" do
+ str = "\u01a9"
+ io = StringIO.new(str)
+ b = io.getbyte
+ b.should == 0xc6 # First byte of UTF-8 encoding of \u01a9
+ io.ungetbyte("\u01a9")
+ io.string.bytes.should == [198, 169, 169]
+ end
+
end
diff --git a/spec/ruby/library/stringio/ungetc_spec.rb b/spec/ruby/library/stringio/ungetc_spec.rb
index 8a9205f390..bceafa79ff 100644
--- a/spec/ruby/library/stringio/ungetc_spec.rb
+++ b/spec/ruby/library/stringio/ungetc_spec.rb
@@ -3,7 +3,7 @@ require_relative 'fixtures/classes'
describe "StringIO#ungetc when passed [char]" do
before :each do
- @io = StringIO.new('1234')
+ @io = StringIO.new(+'1234')
end
it "writes the passed char before the current position" do
@@ -39,20 +39,20 @@ describe "StringIO#ungetc when passed [char]" do
end
it "raises a TypeError when the passed length can't be converted to an Integer or String" do
- lambda { @io.ungetc(Object.new) }.should raise_error(TypeError)
+ -> { @io.ungetc(Object.new) }.should raise_error(TypeError)
end
end
describe "StringIO#ungetc when self is not readable" do
it "raises an IOError" do
- io = StringIO.new("test", "w")
+ io = StringIO.new(+"test", "w")
io.pos = 1
- lambda { io.ungetc(?A) }.should raise_error(IOError)
+ -> { io.ungetc(?A) }.should raise_error(IOError)
- io = StringIO.new("test")
+ io = StringIO.new(+"test")
io.pos = 1
io.close_read
- lambda { io.ungetc(?A) }.should raise_error(IOError)
+ -> { io.ungetc(?A) }.should raise_error(IOError)
end
end
@@ -60,11 +60,11 @@ end
#
# describe "StringIO#ungetc when self is not writable" do
# it "raises an IOError" do
-# io = StringIO.new("test", "r")
+# io = StringIO.new(+"test", "r")
# io.pos = 1
# lambda { io.ungetc(?A) }.should raise_error(IOError)
#
-# io = StringIO.new("test")
+# io = StringIO.new(+"test")
# io.pos = 1
# io.close_write
# lambda { io.ungetc(?A) }.should raise_error(IOError)
diff --git a/spec/ruby/library/stringio/write_nonblock_spec.rb b/spec/ruby/library/stringio/write_nonblock_spec.rb
index 4f4c5039fe..b48ef6698a 100644
--- a/spec/ruby/library/stringio/write_nonblock_spec.rb
+++ b/spec/ruby/library/stringio/write_nonblock_spec.rb
@@ -8,6 +8,12 @@ end
describe "StringIO#write_nonblock when passed [String]" do
it_behaves_like :stringio_write_string, :write_nonblock
+
+ it "accepts :exception option" do
+ io = StringIO.new(+"12345", "a")
+ io.write_nonblock("67890", exception: true)
+ io.string.should == "1234567890"
+ end
end
describe "StringIO#write_nonblock when self is not writable" do