1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131
|
require "spec"
private class PartialReaderIO < IO
@slice : Bytes
def initialize(data : String)
@slice = data.to_slice
end
def read(slice : Bytes)
return 0 if @slice.size == 0
max_read_size = {slice.size, @slice.size}.min
read_size = rand(1..max_read_size)
slice.copy_from(@slice[0, read_size])
@slice += read_size
read_size
end
def write(slice : Bytes) : NoReturn
raise "write"
end
end
describe "IO::Delimited" do
describe "#read" do
it "doesn't read past the limit" do
io = IO::Memory.new("abcderzzrfgzr")
delimited = IO::Delimited.new(io, read_delimiter: "zr")
delimited.gets_to_end.should eq("abcderz")
io.gets_to_end.should eq("fgzr")
end
it "doesn't read past the limit (char-by-char)" do
io = IO::Memory.new("abcderzzrfg")
delimited = IO::Delimited.new(io, read_delimiter: "zr")
delimited.read_char.should eq('a')
delimited.read_char.should eq('b')
delimited.read_char.should eq('c')
delimited.read_char.should eq('d')
delimited.read_char.should eq('e')
delimited.read_char.should eq('r')
delimited.read_char.should eq('z')
delimited.read_char.should eq(nil)
delimited.read_char.should eq(nil)
delimited.read_char.should eq(nil)
delimited.read_char.should eq(nil)
io.read_char.should eq('f')
io.read_char.should eq('g')
end
it "doesn't clobber active_delimiter_buffer" do
io = IO::Memory.new("ab12312")
delimited = IO::Delimited.new(io, read_delimiter: "12345")
delimited.gets_to_end.should eq("ab12312")
end
it "handles the delimiter at the start" do
io = IO::Memory.new("ab12312")
delimited = IO::Delimited.new(io, read_delimiter: "ab1")
delimited.read_char.should eq(nil)
end
it "handles the delimiter at the end" do
io = IO::Memory.new("ab12312z")
delimited = IO::Delimited.new(io, read_delimiter: "z")
delimited.gets_to_end.should eq("ab12312")
end
it "handles nearly a delimiter at the end" do
io = IO::Memory.new("ab12312")
delimited = IO::Delimited.new(io, read_delimiter: "122")
delimited.gets_to_end.should eq("ab12312")
end
it "doesn't clobber the buffer on closely-offset partial matches" do
io = IO::Memory.new("abab1234abcdefgh")
delimited = IO::Delimited.new(io, read_delimiter: "abcdefgh")
delimited.gets_to_end.should eq("abab1234")
end
it "handles partial reads" do
io = PartialReaderIO.new("abab1234abcdefgh")
delimited = IO::Delimited.new(io, read_delimiter: "abcdefgh")
delimited.gets_to_end.should eq("abab1234")
end
end
describe "#write" do
it "raises" do
delimited = IO::Delimited.new(IO::Memory.new, read_delimiter: "zr")
expect_raises(IO::Error, "Can't write to IO::Delimited") do
delimited.puts "test string"
end
end
end
describe "#close" do
it "stops reading" do
io = IO::Memory.new "abcdefg"
delimited = IO::Delimited.new(io, read_delimiter: "zr")
delimited.read_char.should eq('a')
delimited.read_char.should eq('b')
delimited.close
delimited.closed?.should eq(true)
expect_raises(IO::Error, "Closed stream") do
delimited.read_char
end
end
it "closes the underlying stream if sync_close is true" do
io = IO::Memory.new "abcdefg"
delimited = IO::Delimited.new(io, read_delimiter: "zr", sync_close: true)
delimited.sync_close?.should eq(true)
io.closed?.should eq(false)
delimited.close
io.closed?.should eq(true)
end
end
end
|