diff --git a/spec/mfile_spec.cr b/spec/mfile_spec.cr new file mode 100644 index 0000000000..e9f5e92bb5 --- /dev/null +++ b/spec/mfile_spec.cr @@ -0,0 +1,63 @@ +require "spec" +require "../src/lavinmq/mfile" + +module MFileSpec + def self.with_file(&) + file = File.tempfile "mfile_spec" + yield file + ensure + file.delete unless file.nil? + end + + describe MFile do + describe "#write" do + it "should raise ClosedError if closed" do + with_file do |file| + mfile = MFile.new file.path + mfile.close + expect_raises(MFile::ClosedError) { mfile.write "foo".to_slice } + end + end + end + describe "#read" do + it "should raise ClosedError if closed" do + with_file do |file| + mfile = MFile.new file.path + mfile.close + data = Bytes.new(1) + expect_raises(MFile::ClosedError) { mfile.read data } + end + end + end + describe "#to_slice" do + describe "without position and size" do + it "should raise ClosedError if closed" do + with_file do |file| + mfile = MFile.new file.path + mfile.close + expect_raises(MFile::ClosedError) { mfile.to_slice } + end + end + end + describe "with position and size" do + it "should raise ClosedError if closed" do + with_file do |file| + mfile = MFile.new file.path + mfile.close + expect_raises(MFile::ClosedError) { mfile.to_slice(1, 1) } + end + end + end + end + describe "#copy_to" do + it "should raise ClosedError if closed" do + with_file do |file| + mfile = MFile.new file.path + mfile.close + data = IO::Memory.new + expect_raises(MFile::ClosedError) { mfile.copy_to data } + end + end + end + end +end diff --git a/src/lavinmq/mfile.cr b/src/lavinmq/mfile.cr index d5f080c237..fd4406b40c 100644 --- a/src/lavinmq/mfile.cr +++ b/src/lavinmq/mfile.cr @@ -18,6 +18,12 @@ end # not `size` large, only on graceful close is the file truncated to its `size`. # The file does not expand further than initial `capacity`, unless manually expanded. class MFile < IO + class ClosedError < IO::Error + def initialize + super("MFile closed") + end + end + getter pos : Int64 = 0i64 getter? closed : Bool = false getter size : Int64 = 0i64 @@ -136,6 +142,7 @@ class MFile < IO # Copies the file to another IO # Won't mmap the file if it's unmapped already def copy_to(output : IO, size = @size) : Int64 + raise ClosedError.new if @closed if unmapped? # don't remap unmapped files io = IO::FileDescriptor.new(@fd, blocking: true, close_on_finalize: false) io.rewind @@ -170,7 +177,7 @@ class MFile < IO end def write(slice : Bytes) : Nil - raise IO::Error.new("MFile closed") if @closed + raise ClosedError.new if @closed size = @size new_size = size + slice.size raise IO::EOFError.new if new_size > @capacity @@ -179,7 +186,7 @@ class MFile < IO end def read(slice : Bytes) - raise IO::Error.new("MFile closed") if @closed + raise ClosedError.new if @closed pos = @pos new_pos = pos + slice.size raise IO::EOFError.new if new_pos > @size @@ -225,12 +232,12 @@ class MFile < IO end def to_slice - raise IO::Error.new("MFile closed") if @closed + raise ClosedError.new if @closed Bytes.new(buffer, @size, read_only: true) end def to_slice(pos, size) - raise IO::Error.new("MFile closed") if @closed + raise ClosedError.new if @closed raise IO::EOFError.new if pos + size > @size Bytes.new(buffer + pos, size, read_only: true) end