Skip to content

Commit

Permalink
Rewrote IO.copy_stream specs.
Browse files Browse the repository at this point in the history
  • Loading branch information
Brian Ford authored and brixen committed Sep 13, 2011
1 parent 75291ec commit f892140
Show file tree
Hide file tree
Showing 3 changed files with 180 additions and 30 deletions.
194 changes: 164 additions & 30 deletions core/io/copy_stream_spec.rb
@@ -1,50 +1,184 @@
require File.expand_path('../../../spec_helper', __FILE__)
require File.expand_path('../fixtures/classes', __FILE__)

ruby_version_is "1.9" do
describe "IO.copy_stream" do
it "needs to be reviewed for spec completeness"
describe :io_copy_stream_to_file, :shared => true do
it "copies the entire IO contents to the file" do
IO.copy_stream(@object.from, @to_name)
@to_name.should have_data(@content)
end

it "returns the number of bytes copied" do
IO.copy_stream(@object.from, @to_name).should == @size
end

it "copies only length bytes when specified" do
IO.copy_stream(@object.from, @to_name, 8).should == 8
@to_name.should have_data("Line one")
end

it "copies only length bytes from the offset" do
IO.copy_stream(@object.from, @to_name, 8, 4).should == 8
@to_name.should have_data(" one\n\nLi")
end

it "calls #to_path to convert on object to a file name" do
obj = mock("io_copy_stream_to")
obj.should_receive(:to_path).and_return(@to_name)

IO.copy_stream(@object.from, obj)
@to_name.should have_data(@content)
end

it "raises a TypeError if #to_path does not return a String" do
obj = mock("io_copy_stream_to")
obj.should_receive(:to_path).and_return(1)

lambda { IO.copy_stream(@object.from, obj) }.should raise_error(TypeError)
end
end

describe "IO.copy_stream" do
before :each do
# TODO: multi-line content (esp. on Windows!)
@content = "one-two-three"
describe :io_copy_stream_to_io, :shared => true do
it "copies the entire IO contents to the IO" do
IO.copy_stream(@object.from, @to_io)
@to_name.should have_data(@content)
end

@filename_src = tmp("source")
touch(@filename_src) { |f| f.write(@content) }
@io_src = new_io(@filename_src, "rb")
it "returns the number of bytes copied" do
IO.copy_stream(@object.from, @to_io).should == @size
end

@filename_dest = tmp("destination")
# TODO: new_io doesn't work here due to bug in mspsec
# @io_dest = new_io(@filename_dest, "w")
@io_dest = File.open(@filename_dest, "wb")
it "starts writing at the destination IO's current position" do
@to_io.write("prelude ")
IO.copy_stream(@object.from, @to_io)
@to_name.should have_data("prelude " + @content)
end

after :each do
@io_src.close unless @io_src.closed?
@io_dest.close unless @io_dest.closed?
File.unlink @filename_src
File.unlink @filename_dest
it "leaves the destination IO position at the last write" do
IO.copy_stream(@object.from, @to_io)
@to_io.pos.should == @size
end

it "copies from an IO instance to a named file" do
IO.copy_stream(@io_src, @filename_dest).should == @content.size
File.read(@filename_dest).should == @content
it "raises an IOError if the destination IO is not open for writing" do
@to_io.close
@to_io = File.open @to_name, "r"
lambda { IO.copy_stream @object.from, @to_io }.should raise_error(IOError)
end

it "copies from a named file to a named file" do
IO.copy_stream(@filename_src, @filename_dest).should == @content.size
File.read(@filename_dest).should == @content
it "does not close the destination IO" do
IO.copy_stream(@object.from, @to_io)
@to_io.closed?.should be_false
end

it "copies from a named file to an IO instance" do
IO.copy_stream(@filename_src, @io_dest).should == @content.size
File.read(@filename_dest).should == @content
it "copies only length bytes when specified" do
IO.copy_stream(@object.from, @to_io, 8).should == 8
@to_name.should have_data("Line one")
end

it "copies from an IO instance to an IO instance" do
IO.copy_stream(@io_src, @io_dest).should == @content.size
File.read(@filename_dest).should == @content
it "copies only length bytes from the offset" do
IO.copy_stream(@object.from, @to_io, 8, 4).should == 8
@to_name.should have_data(" one\n\nLi")
end
end

describe "IO.copy_stream" do
before :each do
@from_name = fixture __FILE__, "copy_stream.txt"
@to_name = tmp("io_copy_stream_io_name")

@content = IO.read(@from_name)
@size = @content.size
end

after :each do
rm_r @to_name
end

describe "from an IO" do
before :each do
@from_io = File.open @from_name, "rb"
IOSpecs::CopyStream.from = @from_io
end

after :each do
@from_io.close
end

it "raises an IOError if the source IO is not open for reading" do
@from_io.close
@from_io = File.open @from_name, "a"
lambda { IO.copy_stream @from_io, @to_name }.should raise_error(IOError)
end

it "does not close the source IO" do
IO.copy_stream(@from_io, @to_name)
@from_io.closed?.should be_false
end

it "does not change the IO offset when an offset is specified" do
@from_io.pos = 10
IO.copy_stream(@from_io, @to_name, 8, 4)
@from_io.pos.should == 10
end

it "does change the IO offset when an offset is not specified" do
@from_io.pos = 10
IO.copy_stream(@from_io, @to_name)
@from_io.pos.should == 42
end

describe "to a file name" do
it_behaves_like :io_copy_stream_to_file, nil, IOSpecs::CopyStream
end

describe "to an IO" do
before :each do
@to_io = File.open @to_name, "wb"
end

after :each do
@to_io.close
end

it_behaves_like :io_copy_stream_to_io, nil, IOSpecs::CopyStream
end
end

describe "from a file name" do
before :each do
IOSpecs::CopyStream.from = @from_name
end

it "calls #to_path to convert on object to a file name" do
obj = mock("io_copy_stream_from")
obj.should_receive(:to_path).and_return(@from_name)

IO.copy_stream(obj, @to_name)
@to_name.should have_data(@content)
end

it "raises a TypeError if #to_path does not return a String" do
obj = mock("io_copy_stream_from")
obj.should_receive(:to_path).and_return(1)

lambda { IO.copy_stream(obj, @to_name) }.should raise_error(TypeError)
end

describe "to a file name" do
it_behaves_like :io_copy_stream_to_file, nil, IOSpecs::CopyStream
end

describe "to an IO" do
before :each do
@to_io = File.open @to_name, "wb"
end

after :each do
@to_io.close
end

it_behaves_like :io_copy_stream_to_io, nil, IOSpecs::CopyStream
end
end
end
end
10 changes: 10 additions & 0 deletions core/io/fixtures/classes.rb
Expand Up @@ -74,4 +74,14 @@ def self.closed_io
def self.io_mock(obj, method, &block)
obj.singleton_class.send(:define_method, method, &block)
end

module CopyStream
def self.from=(from)
@from = from
end

def self.from
@from
end
end
end
6 changes: 6 additions & 0 deletions core/io/fixtures/copy_stream.txt
@@ -0,0 +1,6 @@
Line one

Line three
Line four

Line last

0 comments on commit f892140

Please sign in to comment.