test/line_reader_test.rb in iostreams-0.15.0 vs test/line_reader_test.rb in iostreams-0.16.0
- old
+ new
@@ -14,44 +14,10 @@
end
end
data
end
- describe '#initialize' do
- it 'does not strip invalid characters' do
- bad_lines = [
- "New M\xE9xico,NE",
- 'good line',
- "New M\xE9xico,SF"
- ]
- input = StringIO.new(bad_lines.join("\n"))
- lines = []
- IOStreams::Line::Reader.open(input) do |io|
- assert_equal false, io.strip_non_printable
- assert_raises ArgumentError do
- io.each { |line| lines << line }
- end
- end
- end
-
- it 'strips invalid characters' do
- bad_lines = [
- "New M\xE9xico,NE",
- 'good line',
- "New M\xE9xico,SF"
- ]
- fixed_lines = bad_lines.collect { |line| line.force_encoding('BINARY').gsub(/[^[:print:]|\r|\n]/, '') }
- input = StringIO.new(bad_lines.join("\n"))
- lines = []
- IOStreams::Line::Reader.open(input, strip_non_printable: true) do |io|
- assert_equal true, io.strip_non_printable
- io.each { |line| lines << line }
- end
- assert_equal fixed_lines, lines
- end
- end
-
describe '#each' do
it 'each_line file' do
lines = []
IOStreams::Line::Reader.open(file_name) do |io|
io.each { |line| lines << line }
@@ -67,19 +33,28 @@
end
end
assert_equal data, lines
end
- ["\r\n", "\n\r", "\n", "\r"].each do |delimiter|
+ ["\r\n", "\n", "\r"].each do |delimiter|
it "autodetect delimiter: #{delimiter.inspect}" do
lines = []
stream = StringIO.new(data.join(delimiter))
IOStreams::Line::Reader.open(stream, buffer_size: 15) do |io|
io.each { |line| lines << line }
end
assert_equal data, lines
end
+
+ it "single read autodetect delimiter: #{delimiter.inspect}" do
+ lines = []
+ stream = StringIO.new(data.join(delimiter))
+ IOStreams::Line::Reader.open(stream) do |io|
+ io.each { |line| lines << line }
+ end
+ assert_equal data, lines
+ end
end
['@', 'BLAH'].each do |delimiter|
it "reads delimited #{delimiter.inspect}" do
lines = []
@@ -92,14 +67,182 @@
end
it 'reads binary delimited' do
delimiter = "\x01"
lines = []
- stream = StringIO.new(data.join(delimiter))
- IOStreams::Line::Reader.open(stream, buffer_size: 15, delimiter: delimiter, encoding: IOStreams::BINARY_ENCODING) do |io|
+ stream = StringIO.new(data.join(delimiter).encode('ASCII-8BIT'))
+ IOStreams::Line::Reader.open(stream, buffer_size: 15, delimiter: delimiter) do |io|
io.each { |line| lines << line }
end
assert_equal data, lines
+ end
+
+ describe '#readline' do
+ let(:short_line) { '0123456789' }
+ let(:longer_line) { 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' }
+ let(:delimiter) { "\r\n" }
+
+ it 'reads delimiter in first block, no delimiter at end' do
+ data = [short_line, longer_line].join(delimiter)
+ buffer_size = short_line.length + delimiter.size + (longer_line.size / 2)
+
+ stream = StringIO.new(data)
+ IOStreams::Line::Reader.open(stream, buffer_size: buffer_size) do |io|
+ refute io.eof?
+ assert_equal delimiter, io.delimiter, -> { io.delimiter.ai }
+
+ assert_equal short_line, io.readline
+ assert_equal longer_line, io.readline
+
+ assert io.eof?
+ assert_nil io.readline
+ end
+ end
+
+ it 'reads delimiter in second block, no delimiter at end' do
+ data = [longer_line, short_line, short_line].join(delimiter)
+ buffer_size = (longer_line.length + delimiter.size + 5) / 2
+
+ stream = StringIO.new(data)
+ IOStreams::Line::Reader.open(stream, buffer_size: buffer_size) do |io|
+ refute io.eof?
+ assert_equal delimiter, io.delimiter, -> { io.delimiter.ai }
+ assert_equal longer_line, io.readline
+ assert_equal short_line, io.readline
+ assert_equal short_line, io.readline
+ assert io.eof?
+ assert_nil io.readline
+ end
+ end
+
+ it 'reads delimiter split across first and second blocks' do
+ data = [longer_line, short_line, short_line].join(delimiter)
+ buffer_size = longer_line.length + 1
+
+ stream = StringIO.new(data)
+ IOStreams::Line::Reader.open(stream, buffer_size: buffer_size) do |io|
+ refute io.eof?
+ assert_equal delimiter, io.delimiter, -> { io.delimiter.ai }
+ assert_equal longer_line, io.readline
+ assert_equal short_line, io.readline
+ assert_equal short_line, io.readline
+ assert io.eof?
+ assert_nil io.readline
+ end
+ end
+
+ it 'reads file with no matching delimiter' do
+ delimiter = '@'
+ data = [longer_line, short_line, longer_line].join(delimiter) + delimiter
+ buffer_size = longer_line.length + 1
+
+ stream = StringIO.new(data)
+ IOStreams::Line::Reader.open(stream, buffer_size: buffer_size) do |io|
+ refute io.eof?
+ assert_equal "\n", io.delimiter, -> { io.delimiter.ai }
+ assert_equal data, io.readline
+ assert io.eof?
+ assert_nil io.readline
+ end
+ end
+
+ it 'reads small file with no matching delimiter' do
+ data = short_line
+ buffer_size = short_line.length + 100
+
+ stream = StringIO.new(data)
+ IOStreams::Line::Reader.open(stream, buffer_size: buffer_size) do |io|
+ refute io.eof?
+ assert_equal "\n", io.delimiter, -> { io.delimiter.ai }
+ assert_equal short_line, io.readline
+ assert io.eof?
+ assert_nil io.readline
+ end
+ end
+
+ it 'reads last line with the delimiter as the last character' do
+ delimiter = '@'
+ data = [longer_line, short_line, longer_line].join(delimiter) + delimiter
+ buffer_size = longer_line.length + 1
+
+ stream = StringIO.new(data)
+ IOStreams::Line::Reader.open(stream, buffer_size: buffer_size, delimiter: delimiter) do |io|
+ refute io.eof?
+ assert_equal delimiter, io.delimiter, -> { io.delimiter.ai }
+ assert_equal longer_line, io.readline
+ assert_equal short_line, io.readline
+ assert_equal longer_line, io.readline
+ assert_nil io.readline
+ assert io.eof?
+ end
+ end
+
+ it 'reads last line with the multi-byte delimiter as the last bytes' do
+ data = [longer_line, short_line, longer_line].join(delimiter) + delimiter
+ buffer_size = longer_line.length + 1
+
+ stream = StringIO.new(data)
+ IOStreams::Line::Reader.open(stream, buffer_size: buffer_size) do |io|
+ refute io.eof?
+ assert_equal delimiter, io.delimiter, -> { io.delimiter.ai }
+ assert_equal longer_line, io.readline
+ assert_equal short_line, io.readline
+ assert_equal longer_line, io.readline
+ assert_nil io.readline
+ assert io.eof?
+ end
+ end
+
+ describe 'read 1 char at a time' do
+ let(:buffer_size) { 1 }
+
+ it 'delimiter at the end' do
+ data = [longer_line, short_line, longer_line].join(delimiter) + delimiter
+
+ stream = StringIO.new(data)
+ IOStreams::Line::Reader.open(stream, buffer_size: buffer_size) do |io|
+ refute io.eof?
+ assert_equal delimiter, io.delimiter, -> { io.delimiter.ai }
+ assert_equal longer_line, io.readline
+ assert_equal short_line, io.readline
+ assert_equal longer_line, io.readline
+ assert_nil io.readline
+ assert io.eof?
+ end
+ end
+
+ it 'no delimiter at the end' do
+ data = [longer_line, short_line, longer_line].join(delimiter)
+
+ stream = StringIO.new(data)
+ IOStreams::Line::Reader.open(stream, buffer_size: buffer_size) do |io|
+ refute io.eof?
+ assert_equal delimiter, io.delimiter, -> { io.delimiter.ai }
+ assert_equal longer_line, io.readline
+ assert_equal short_line, io.readline
+ assert_equal longer_line, io.readline
+ assert_nil io.readline
+ assert io.eof?
+ end
+ end
+ end
+
+ it 'reads empty file' do
+ stream = StringIO.new
+ IOStreams::Line::Reader.open(stream) do |io|
+ assert io.eof?
+ end
+ end
+
+ it 'prevents denial of service' do
+ data = 'a' * IOStreams::Line::Reader::MAX_BLOCKS_MULTIPLIER + 'a'
+ stream = StringIO.new(data)
+ assert_raises IOStreams::Errors::DelimiterNotFound do
+ IOStreams::Line::Reader.open(stream, buffer_size: 1) do |io|
+ end
+ end
+
+ end
end
end
end
end