diff --git a/UnitTests/HttpInterface/api-batch-spec.rb b/UnitTests/HttpInterface/api-batch-spec.rb index 9b6773bb2e..26d361d1e3 100644 --- a/UnitTests/HttpInterface/api-batch-spec.rb +++ b/UnitTests/HttpInterface/api-batch-spec.rb @@ -52,24 +52,135 @@ describe ArangoDB do end +################################################################################ +## checking invalid posts +################################################################################ + + context "checking wrong/missing content-type/boundary:" do + it "checks missing content-type" do + cmd = "/_api/batch" + + doc = ArangoDB.log_post("#{prefix}-post-ct-none", cmd, :body => "xx" ) + + doc.code.should eq(400) + doc.parsed_response['error'].should eq(true) + doc.parsed_response['code'].should eq(400) + end + + it "checks invalid content-type (xxx)" do + cmd = "/_api/batch" + + doc = ArangoDB.log_post("#{prefix}-post-ct-wrong-1", cmd, :body => "xx", :headers => { "Content-Type" => "xxx/xxx" } ) + + doc.code.should eq(400) + doc.parsed_response['error'].should eq(true) + doc.parsed_response['code'].should eq(400) + end + + it "checks invalid content-type (json)" do + cmd = "/_api/batch" + + doc = ArangoDB.log_post("#{prefix}-post-ct-wrong-2", cmd, :body => "xx", :headers => { "Content-Type" => "application/json" } ) + + doc.code.should eq(400) + doc.parsed_response['error'].should eq(true) + doc.parsed_response['code'].should eq(400) + end + + it "checks valid content-type with missing boundary" do + cmd = "/_api/batch" + + doc = ArangoDB.log_post("#{prefix}-post-boundary-wrong-1", cmd, :body => "xx", :headers => { "Content-Type" => "multipart/form-data" } ) + + doc.code.should eq(400) + doc.parsed_response['error'].should eq(true) + doc.parsed_response['code'].should eq(400) + end + + it "checks valid content-type with unexpected boundary" do + cmd = "/_api/batch" + + doc = ArangoDB.log_post("#{prefix}-post-boundary-wrong-2", cmd, :body => "xx", :headers => { "Content-Type" => "multipart/form-data; peng" } ) + + doc.code.should eq(400) + doc.parsed_response['error'].should eq(true) + doc.parsed_response['code'].should eq(400) + end + + it "checks valid content-type with broken boundary" do + cmd = "/_api/batch" + + doc = ArangoDB.log_post("#{prefix}-post-boundary-wrong-3", cmd, :body => "xx", :headers => { "Content-Type" => "multipart/form-data; boundary=" } ) + + doc.code.should eq(400) + doc.parsed_response['error'].should eq(true) + doc.parsed_response['code'].should eq(400) + end + + it "checks valid content-type with too short boundary" do + cmd = "/_api/batch" + + doc = ArangoDB.log_post("#{prefix}-post-boundary-wrong-4", cmd, :body => "xx", :headers => { "Content-Type" => "multipart/form-data; boundary=a" } ) + + doc.code.should eq(400) + doc.parsed_response['error'].should eq(true) + doc.parsed_response['code'].should eq(400) + end + end + ################################################################################ ## checking simple batches ################################################################################ context "checking simple requests:" do + + it "checks an empty operation multipart message" do + cmd = "/_api/batch" - it "checks whether POST is allowed on /_api/batch" do + multipart = ArangoMultipartBody.new() + + doc = ArangoDB.log_post("#{prefix}-post-version-empty", cmd, :body => multipart.to_s, :format => :json, :headers => { "Content-Type" => "multipart/form-data; boundary=" + multipart.getBoundary }) + + doc.code.should eq(400) + doc.parsed_response['error'].should eq(true) + doc.parsed_response['code'].should eq(400) + end + + it "checks a multipart message with a single operation" do cmd = "/_api/batch" multipart = ArangoMultipartBody.new() multipart.addPart("GET", "/_api/version", { }, "") -# multipart.addPart("GET", "/_api/version", { }, "") - doc = ArangoDB.log_post("#{prefix}-post-version1", cmd, :body => multipart.to_s, :format => :plain, :headers => { "Content-Type" => "multipart/form-data; boundary=" + multipart.getBoundary }) + doc = ArangoDB.log_post("#{prefix}-post-version-one", cmd, :body => multipart.to_s, :format => :plain, :headers => { "Content-Type" => "multipart/form-data; boundary=" + multipart.getBoundary }) doc.code.should eq(200) -# doc.parsed_response['error'].should eq(false) -# doc.parsed_response['code'].should eq(200) + + parts = multipart.getParts(multipart.getBoundary, doc.response.body) + + parts.each do|part| + part[:status].should eq(200) + end + end + + it "checks a multipart message with a multiple operations" do + cmd = "/_api/batch" + + multipart = ArangoMultipartBody.new() + + multipart.addPart("GET", "/_api/version", { }, "") + multipart.addPart("GET", "/_api/version", { }, "") + multipart.addPart("GET", "/_api/version", { }, "") + multipart.addPart("GET", "/_api/version", { }, "") + doc = ArangoDB.log_post("#{prefix}-post-version-mult", cmd, :body => multipart.to_s, :format => :plain, :headers => { "Content-Type" => "multipart/form-data; boundary=" + multipart.getBoundary }) + + doc.code.should eq(200) + + parts = multipart.getParts(multipart.getBoundary, doc.response.body) + + parts.each do|part| + part[:status].should eq(200) + end end end diff --git a/UnitTests/HttpInterface/arangomultipartbody.rb b/UnitTests/HttpInterface/arangomultipartbody.rb index c69a415711..8eab50000d 100644 --- a/UnitTests/HttpInterface/arangomultipartbody.rb +++ b/UnitTests/HttpInterface/arangomultipartbody.rb @@ -36,6 +36,86 @@ class ArangoMultipartBody @parts.push(part) end +################################################################################ +## split the response body into its individual parts +################################################################################ + + def getParts (boundary, body) + parts = [ ] + valid = false + + while 1 + position = body.index("--" + boundary) + + break if position != 0 or position == nil + + follow = body.slice(position + boundary.length + 2, 2) + + break if follow != "\r\n" and follow != "--" + + if follow == "--" + valid = true + break + end if + + # strip boundary start from body + body = body.slice(position + boundary.length + 4, body.length) + + # look for boundary end + final = body.index("--" + boundary) + + break if final == nil + + # extract the part + partTotal = body.slice(0, final) + + # look for envelope bounds + position = partTotal.index("\r\n\r\n"); + break if position == nil + + # strip envelope + partTotal = partTotal.slice(position + 4, partTotal.length) + + # look for actual header & body + partHeader, partBody = "", "" + position = partTotal.index("\r\n\r\n"); + + break if position == nil + + partHeader = partTotal.slice(0, position) + partBody = partTotal.slice(position + 4, partTotal.length) + + partHeaders = { } + status = 500 + lineNumber = 0 + + # parse headers and status code + + partHeader.each_line("\r\n") do |line| + if lineNumber == 0 + position = line.index("HTTP/1.1 ") + break if position == nil + status = line.slice(9, 3).to_i + else + key, void, value = line.partition(":") + partHeaders[key.strip] = value.strip + end + lineNumber = lineNumber + 1 + end + + part = { :headers => partHeaders, :body => partBody, :status => status } + parts.push(part) + + body = body.slice(final, body.length) + end + + if not valid + raise "invalid multipart response received" + end + + parts + end + ################################################################################ ## get the string representation of a multipart message body ################################################################################