require 'spec_helper' require 'file_reader/shared_context' require 'stringio' require 'td/file_reader' include TreasureData describe 'FileReader filters' do include_context 'error_proc' let :delimiter do "\t" end let :dataset do [ ['hoge', 12345, true, 'null', Time.now.to_s], ['foo', 34567, false, 'null', Time.now.to_s], ['piyo', 56789, true, nil, Time.now.to_s], ] end let :lines do dataset.map { |data| data.map(&:to_s).join(delimiter) } end let :parser do io = StringIO.new(lines.join("\n")) reader = FileReader::LineReader.new(io, error, {}) FileReader::DelimiterParser.new(reader, error, :delimiter_expr => delimiter) end describe FileReader::AutoTypeConvertParserFilter do let :options do { :null_expr => /\A(?:nil||\-|\\N)\z/i, :true_expr => /\A(?:true)\z/i, :false_expr => /\A(?:false)\z/i, } end it 'initialize' do filter = FileReader::AutoTypeConvertParserFilter.new(parser, error, options) expect(filter).not_to be_nil end context 'after initialization' do let :filter do FileReader::AutoTypeConvertParserFilter.new(parser, error, options) end it 'forward returns one converted line' do expect(filter.forward).to eq(dataset[0]) end it 'feeds all lines' do begin i = 0 while line = filter.forward expect(line).to eq(dataset[i]) i += 1 end rescue end end end end describe FileReader::HashBuilder do let :columns do ['str', 'num', 'bool', 'null', 'log_at'] end let :built_dataset do # [{"str" => "hoge", "num" => "12345", "bool" => "true" , "null" =>"null", "log_at" => "2012-12-26 05:14:09 +0900"}, ...] dataset.map { |data| Hash[columns.zip(data.map(&:to_s))]} end it 'initialize' do builder = FileReader::HashBuilder.new(parser, error, columns) expect(builder).not_to be_nil end context 'after initialization' do let :builder do FileReader::HashBuilder.new(parser, error, columns) end it 'forward returns one converted line' do expect(builder.forward).to eq(built_dataset[0]) end it 'feeds all lines' do begin i = 0 while line = builder.forward expect(line).to eq(built_dataset[i]) i += 1 end rescue end end describe FileReader::TimeParserFilter do it "can't be initialized without :time_column option" do expect { FileReader::TimeParserFilter.new(parser, error, {}) }.to raise_error(Exception, /--time-column/) end it 'initialize' do filter = FileReader::TimeParserFilter.new(builder, error, :time_column => 'log_at') expect(filter).not_to be_nil end context 'after initialization' do let :timed_dataset do require 'time' built_dataset.each { |data| data['time'] = Time.parse(data['log_at']).to_i } end let :filter do FileReader::TimeParserFilter.new(builder, error, :time_column => 'log_at') end it 'forward returns one parse line with parsed log_at' do expect(filter.forward).to eq(timed_dataset[0]) end it 'feeds all lines' do begin i = 0 while line = filter.forward expect(line).to eq(timed_dataset[i]) i += 1 end rescue end end context 'missing log_at column lines' do let :columns do ['str', 'num', 'bool', 'null', 'created_at'] end let :error_pattern do /^time column 'log_at' is missing/ end it 'feeds all lines' do i = 0 begin while line = filter.forward i += 1 end rescue RSpec::Expectations::ExpectationNotMetError => e fail rescue expect(i).to eq(0) end end end context 'invalid time format' do let :error_pattern do /^invalid time format/ end [{:time_column => 'log_at', :time_format => "%d"}, {:time_column => 'str'}].each { |options| let :filter do FileReader::TimeParserFilter.new(builder, error, options) end it 'feeds all lines' do i = 0 begin while line = filter.forward i += 1 end rescue RSpec::Expectations::ExpectationNotMetError => e fail rescue expect(i).to eq(0) end end } end end end describe FileReader::SetTimeParserFilter do it "can't be initialized without :time_value option" do expect { FileReader::SetTimeParserFilter.new(parser, error, {}) }.to raise_error(Exception, /--time-value/) end it 'initialize' do filter = FileReader::SetTimeParserFilter.new(builder, error, :time_value => Time.now.to_i) expect(filter).not_to be_nil end context 'after initialization' do let :time_value do Time.now.to_i end let :timed_dataset do built_dataset.each { |data| data['time'] = time_value } end let :filter do FileReader::SetTimeParserFilter.new(builder, error, :time_value => time_value) end it 'forward returns one converted line with time' do expect(filter.forward).to eq(timed_dataset[0]) end it 'feeds all lines' do begin i = 0 while line = filter.forward expect(line).to eq(timed_dataset[i]) i += 1 end rescue end end end end end end end