diff options
Diffstat (limited to 'spec/ruby/library/stringio/reopen_spec.rb')
| -rw-r--r-- | spec/ruby/library/stringio/reopen_spec.rb | 251 |
1 files changed, 251 insertions, 0 deletions
diff --git a/spec/ruby/library/stringio/reopen_spec.rb b/spec/ruby/library/stringio/reopen_spec.rb new file mode 100644 index 0000000000..3d4ae3a698 --- /dev/null +++ b/spec/ruby/library/stringio/reopen_spec.rb @@ -0,0 +1,251 @@ +require_relative '../../spec_helper' +require_relative 'fixtures/classes' + +describe "StringIO#reopen when passed [Object, Integer]" do + before :each do + @io = StringIO.new("example") + end + + it "reopens self with the passed Object in the passed mode" do + @io.reopen("reopened", IO::RDONLY) + @io.closed_read?.should == false + @io.closed_write?.should == true + @io.string.should == "reopened" + + @io.reopen(+"reopened, twice", IO::WRONLY) + @io.closed_read?.should == true + @io.closed_write?.should == false + @io.string.should == "reopened, twice" + + @io.reopen(+"reopened, another time", IO::RDWR) + @io.closed_read?.should == false + @io.closed_write?.should == false + @io.string.should == "reopened, another time" + 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") + @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 + -> { @io.reopen(Object.new, IO::RDWR) }.should.raise(TypeError) + end + + it "raises an Errno::EACCES when trying to reopen self with a frozen String in write-mode" do + -> { @io.reopen("burn".freeze, IO::WRONLY) }.should.raise(Errno::EACCES) + -> { @io.reopen("burn".freeze, IO::WRONLY | IO::APPEND) }.should.raise(Errno::EACCES) + end + + 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(FrozenError) + end + + it "does not raise IOError when passed a frozen String in read-mode" do + @io.reopen("burn".freeze, IO::RDONLY) + @io.string.should == "burn" + end +end + +describe "StringIO#reopen when passed [Object, Object]" do + before :each do + @io = StringIO.new("example") + end + + it "reopens self with the passed Object in the passed mode" do + @io.reopen("reopened", "r") + @io.closed_read?.should == false + @io.closed_write?.should == true + @io.string.should == "reopened" + + @io.reopen(+"reopened, twice", "r+") + @io.closed_read?.should == false + @io.closed_write?.should == false + @io.string.should == "reopened, twice" + + @io.reopen(+"reopened, another", "w+") + @io.closed_read?.should == false + @io.closed_write?.should == false + @io.string.should == "" + + @io.reopen(+"reopened, another time", "r+") + @io.closed_read?.should == false + @io.closed_write?.should == false + @io.string.should == "reopened, another time" + end + + it "truncates the passed String when opened in truncate mode" do + @io.reopen(str = +"reopened", "w") + str.should == "" + 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") + @io.reopen(obj, "r") + @io.string.should == "to_str" + end + + it "raises a TypeError when the passed Object can't be converted to a String using #to_str" do + -> { @io.reopen(Object.new, "r") }.should.raise(TypeError) + end + + it "resets self's position to 0" do + @io.read(5) + @io.reopen(+"reopened") + @io.pos.should.eql?(0) + end + + it "resets self's line number to 0" do + @io.gets + @io.reopen(+"reopened") + @io.lineno.should.eql?(0) + end + + it "tries to convert the passed mode Object to an Integer using #to_str" do + obj = mock("to_str") + obj.should_receive(:to_str).and_return("r") + @io.reopen("reopened", obj) + @io.closed_read?.should == false + @io.closed_write?.should == true + @io.string.should == "reopened" + end + + it "raises an Errno::EACCES error when trying to reopen self with a frozen String in write-mode" do + -> { @io.reopen("burn".freeze, 'w') }.should.raise(Errno::EACCES) + -> { @io.reopen("burn".freeze, 'w+') }.should.raise(Errno::EACCES) + -> { @io.reopen("burn".freeze, 'a') }.should.raise(Errno::EACCES) + -> { @io.reopen("burn".freeze, "r+") }.should.raise(Errno::EACCES) + end + + it "does not raise IOError if a frozen string is passed in read mode" do + @io.reopen("burn".freeze, "r") + @io.string.should == "burn" + end +end + +describe "StringIO#reopen when passed [String]" do + before :each do + @io = StringIO.new("example") + end + + it "reopens self with the passed String in read-write mode" do + @io.close + + @io.reopen(+"reopened") + + @io.closed_write?.should == false + @io.closed_read?.should == false + + @io.string.should == "reopened" + end + + it "resets self's position to 0" do + @io.read(5) + @io.reopen(+"reopened") + @io.pos.should.eql?(0) + end + + it "resets self's line number to 0" do + @io.gets + @io.reopen(+"reopened") + @io.lineno.should.eql?(0) + end +end + +describe "StringIO#reopen when passed [Object]" do + before :each do + @io = StringIO.new("example") + end + + it "raises a TypeError when passed an Object that can't be converted to a StringIO" do + -> { @io.reopen(Object.new) }.should.raise(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) + -> { @io.reopen(obj) }.should.raise(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")) + @io.reopen(obj) + @io.string.should == "to_strio" + end +end + +describe "StringIO#reopen when passed no arguments" do + before :each do + @io = StringIO.new("example\nsecond line") + end + + it "resets self's mode to read-write" do + @io.close + @io.reopen + @io.closed_read?.should == false + @io.closed_write?.should == false + end + + it "resets self's position to 0" do + @io.read(5) + @io.reopen + @io.pos.should.eql?(0) + end + + it "resets self's line number to 0" do + @io.gets + @io.reopen + @io.lineno.should.eql?(0) + end +end + +# NOTE: Some reopen specs disabled due to MRI bugs. See: +# http://rubyforge.org/tracker/index.php?func=detail&aid=13919&group_id=426&atid=1698 +# for details. +describe "StringIO#reopen" do + before :each do + @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.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.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.string.should == '' + @io << 'x' + @io.string.should == 'x' + end + + it "truncates the given string, not a copy" do + str = +'goodbye' + @io.reopen(str, 'w') + @io.string.should == '' + str.should == '' + 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.write("BLAH") # make sure the content is not empty + + @io.reopen(orig_io) + @io.string.should == "BLAH" + end + +end |
