Skip to content

Commit

Permalink
Streamer should protect against bad responses.
Browse files Browse the repository at this point in the history
  • Loading branch information
erickt committed Dec 2, 2011
1 parent f613722 commit 5fc533e
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 8 deletions.
18 changes: 10 additions & 8 deletions lib/couchrest/helper/streamer.rb
Expand Up @@ -27,14 +27,19 @@ def escape_quotes(data)

def open_pipe(cmd, &block)
first = nil
prev = nil
IO.popen(cmd) do |f|
first = f.gets # discard header
while line = f.gets
row = parse_line(line)
block.call row unless row.nil? # last line "}]" discarded
prev = line
end
end
parse_first(first)

raise RestClient::ServerBrokeConnection if $? && $?.exitstatus != 0

parse_first(first, prev)
end

def parse_line line
Expand All @@ -44,14 +49,11 @@ def parse_line line
end
end

def parse_first first
def parse_first first, last
return nil unless first
parts = first.split(',')
parts.pop
line = parts.join(',')
MultiJson.decode("#{line}}")
rescue
nil
header = MultiJson.decode(last ? first + last : first)
header.delete("rows")
header
end

end
Expand Down
72 changes: 72 additions & 0 deletions spec/couchrest/helpers/streamer_spec.rb
Expand Up @@ -40,6 +40,78 @@
count.should == 5
header.should == {"total_rows" => 1001, "offset" => 0}
end

it "should GET no rows in a view with limit=0" do
count = 0
header = @streamer.get("#{@db.root}/_all_docs?include_docs=true&limit=0") do |row|
count += 1
end
count.should == 0
header.should == {"total_rows" => 1001, "offset" => 0}
end

it "should raise an exception receives malformed data" do
IO.stub(:popen) do |cmd, block|
class F
def initialize
@lines = [
'{"total_rows": 123, "offset": "0", "rows": [',
'{"foo": 1},',
'{"foo": 2},',
]
end

def gets
@lines.shift
end
end

f = F.new
block.call f

IO.unstub(:popen)
IO.popen 'true' do; end
end

count = 0
expect do
@streamer.get("#{@db.root}/_all_docs?include_docs=true&limit=0") do |row|
count += 1
end
end.should raise_error(MultiJson::DecodeError)
end

it "should raise an exception if the couch connection fails" do
IO.stub(:popen) do |cmd, block|
class F
def initialize
@lines = [
'{"total_rows": 123, "offset": "0", "rows": [',
'{"foo": 1},',
'{"foo": 2},',
]
end

def gets
@lines.shift
end
end

block.call F.new

IO.unstub(:popen)
IO.popen 'false' do; end
end

count = 0

expect do
@streamer.get("#{@db.root}/_all_docs?include_docs=true&limit=0") do |row|
count += 1
end
end.should raise_error(RestClient::ServerBrokeConnection)

count.should == 2
end

it "should POST for each row in a view" do
Expand Down

0 comments on commit 5fc533e

Please sign in to comment.