[
https://issues.apache.org/jira/browse/COUCHDB-731?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Paul Joseph Davis updated COUCHDB-731:
--------------------------------------
Skill Level: New Contributors Level (Easy)
> Improved Query Server tests
> ---------------------------
>
> Key: COUCHDB-731
> URL: https://issues.apache.org/jira/browse/COUCHDB-731
> Project: CouchDB
> Issue Type: Improvement
> Components: Test Suite
> Reporter: Matt Lyon
> Priority: Trivial
>
> In the process of writing a ruby version of the query server, I wrote a few
> more tests for the javascript and erlang ones to help determine the proper
> behavior of certain cases. The ones pertaining to handling syntax errors will
> fail for erlang, but pass on javascript; apparently this is by design.
> Anyway, here they are, my hope is that other people attempting an
> implementation of the query server find them useful.
> diff --git a/test/view_server/query_server_spec.rb
> b/test/view_server/query_server_spec.rb
> index 1de8e5b..c427e35 100644
> --- a/test/view_server/query_server_spec.rb
> +++ b/test/view_server/query_server_spec.rb
> @@ -508,34 +623,70 @@ describe "query server normal case" do
> [{:title => "Best ever", :body => "Doc body"}, {}]).should ==
> ["resp", {"body" => "Best ever - Doc body"}]
> end
> -
> - it "should run map funs" do
> - @qs.reset!
> - @qs.run(["add_fun", functions["emit-twice"][LANGUAGE]]).should == true
> + it "should clear map functions on reset" do
> @qs.run(["add_fun", functions["emit-once"][LANGUAGE]]).should == true
> - rows = @qs.run(["map_doc", {:a => "b"}])
> - rows[0][0].should == ["foo", "b"]
> - rows[0][1].should == ["bar", "b"]
> - rows[1][0].should == ["baz", "b"]
> + @qs.run(["map_doc", {:a => "b"}]).size.should be > 0
> + @qs.run(["reset"])
> + @qs.run(["map_doc", {:a => "b"}]).size.should == 0
> end
> +
> + describe "map functions" do
> + before do
> + @qs.reset!
> + end
> + it "should run map funs" do
> + @qs.run(["add_fun", functions["emit-twice"][LANGUAGE]]).should == true
> + @qs.run(["add_fun", functions["emit-once"][LANGUAGE]]).should == true
> + rows = @qs.run(["map_doc", {:a => "b"}])
> + rows[0][0].should == ["foo", "b"]
> + rows[0][1].should == ["bar", "b"]
> + rows[1][0].should == ["baz", "b"]
> + end
> +
> + it "should return error on invalid expressions" do
> + response = @qs.run(["add_fun",
> functions["map-invalid-expression"][LANGUAGE]])
> + response.should be_kind_of Array
> + response[0].should == 'error'
> + response[1].should == 'compilation_error'
> + end
> +
> + it "should return error on non-function expressions" do
> + response = @qs.run(["add_fun",
> functions["map-non-function-expression"][LANGUAGE]])
> + response.should be_kind_of Array
> + response[0].should == 'error'
> + response[1].should == 'compilation_error'
> + end
> +
> + it "has access to the logger" do
> + @qs.run(["add_fun", functions["map-logging"][LANGUAGE]])
> + @qs.rrun(["map_doc", {:a => "b"}])
> + response = JSON.parse @qs.rgets
> + response.should == ["log", "{\"a\":\"b\"}"]
> + response = @qs.jsgets
> + response.should == [[[ "logged", "b" ]]]
> + end
> + end
> +
> describe "reduce" do
> before(:all) do
> @fun = functions["reduce-values-length"][LANGUAGE]
> + @fun2 = functions["reduce-values-sum"][LANGUAGE]
> @qs.reset!
> end
> it "should reduce" do
> kvs = (0...10).collect{|i|[i,i*2]}
> - @qs.run(["reduce", [...@fun], kvs]).should == [true, [10]]
> + @qs.run(["reduce", [...@fun, @fun2], kvs]).should == [true, [10, 90]]
> end
> end
> describe "rereduce" do
> before(:all) do
> @fun = functions["reduce-values-sum"][LANGUAGE]
> + @fun2 = functions["reduce-values-length"][LANGUAGE]
> @qs.reset!
> end
> it "should rereduce" do
> vs = (0...10).collect{|i|i}
> - @qs.run(["rereduce", [...@fun], vs]).should == [true, [45]]
> + @qs.run(["rereduce", [...@fun, @fun2], vs]).should == [true, [45, 10]]
> end
> end
>
> @@ -648,6 +799,15 @@ describe "query server normal case" do
> doc.should == {"foo" => "gnarly", "world" => "hello"}
> resp["body"].should == "hello doc"
> end
> + # TODO: fails in erlang, passes in javascript. does it matter or not?
> + it "should reject GET requests" do
> + err, name, msg = @qs.ddoc_run(@ddoc,
> + ["updates","basic"],
> + [{"foo" => "gnarly"}, {"method" => "GET"}]
> + )
> + err.should == "error"
> + name.should == "method_not_allowed"
> + end
> end
>
> # end
> @@ -655,99 +815,100 @@ describe "query server normal case" do
> # __END__
>
> describe "ddoc list" do
> - before(:all) do
> - @ddoc = {
> - "_id" => "foo",
> - "lists" => {
> - "simple" => functions["list-simple"][LANGUAGE],
> - "headers" => functions["show-sends"][LANGUAGE],
> - "rows" => functions["show-while-get-rows"][LANGUAGE],
> - "buffer-chunks" =>
> functions["show-while-get-rows-multi-send"][LANGUAGE],
> - "chunky" => functions["list-chunky"][LANGUAGE]
> - }
> + before(:all) do
> + @ddoc = {
> + "_id" => "foo",
> + "lists" => {
> + "simple" => functions["list-simple"][LANGUAGE],
> + "headers" => functions["show-sends"][LANGUAGE],
> + "rows" => functions["show-while-get-rows"][LANGUAGE],
> + "buffer-chunks" =>
> functions["show-while-get-rows-multi-send"][LANGUAGE],
> + "chunky" => functions["list-chunky"][LANGUAGE]
> }
> - @qs.teach_ddoc(@ddoc)
> - end
> -
> - describe "example list" do
> - it "should run normal" do
> - @qs.ddoc_run(@ddoc,
> - ["lists","simple"],
> - [{"foo"=>"bar"}, {"q" => "ok"}]
> - ).should == ["start", ["first chunk", "ok"], {"headers"=>{}}]
> - @qs.run(["list_row", {"key"=>"baz"}]).should == ["chunks",
> ["baz"]]
> - @qs.run(["list_row", {"key"=>"bam"}]).should == ["chunks",
> ["bam"]]
> - @qs.run(["list_row", {"key"=>"foom"}]).should == ["chunks",
> ["foom"]]
> - @qs.run(["list_row", {"key"=>"fooz"}]).should == ["chunks",
> ["fooz"]]
> - @qs.run(["list_row", {"key"=>"foox"}]).should == ["chunks",
> ["foox"]]
> - @qs.run(["list_end"]).should == ["end" , ["early"]]
> - end
> + }
> + @qs.teach_ddoc(@ddoc)
> + end
> +
> + describe "example list" do
> + it "should run normal" do
> + @qs.ddoc_run(@ddoc,
> + ["lists","simple"],
> + [{"foo"=>"bar"}, {"q" => "ok"}]
> + ).should == ["start", ["first chunk", "ok"], {"headers"=>{}}]
> + @qs.run(["list_row", {"key"=>"baz"}]).should == ["chunks", ["baz"]]
> + @qs.run(["list_row", {"key"=>"bam"}]).should == ["chunks", ["bam"]]
> + @qs.run(["list_row", {"key"=>"foom"}]).should == ["chunks", ["foom"]]
> + @qs.run(["list_row", {"key"=>"fooz"}]).should == ["chunks", ["fooz"]]
> + @qs.run(["list_row", {"key"=>"foox"}]).should == ["chunks", ["foox"]]
> + @qs.run(["list_end"]).should == ["end" , ["early"]]
> end
> -
> - describe "headers" do
> - it "should do headers proper" do
> - @qs.ddoc_run(@ddoc, ["lists","headers"],
> - [{"total_rows"=>1000}, {"q" => "ok"}]
> - ).should == ["start", ["first chunk", 'second "chunk"'],
> - {"headers"=>{"Content-Type"=>"text/plain"}}]
> - @qs.rrun(["list_end"])
> - @qs.jsgets.should == ["end", ["tail"]]
> - end
> + end
> +
> + describe "headers" do
> + it "should do headers proper" do
> + @qs.ddoc_run(@ddoc, ["lists","headers"],
> + [{"total_rows"=>1000}, {"q" => "ok"}]
> + ).should == ["start", ["first chunk", 'second "chunk"'],
> + {"headers"=>{"Content-Type"=>"text/plain"}}]
> + @qs.rrun(["list_end"])
> + @qs.jsgets.should == ["end", ["tail"]]
> end
> + end
>
> - describe "with rows" do
> - it "should list em" do
> - @qs.ddoc_run(@ddoc, ["lists","rows"],
> - [{"foo"=>"bar"}, {"q" => "ok"}]).
> - should == ["start", ["first chunk", "ok"], {"headers"=>{}}]
> - @qs.rrun(["list_row", {"key"=>"baz"}])
> - @qs.get_chunks.should == ["baz"]
> - @qs.rrun(["list_row", {"key"=>"bam"}])
> - @qs.get_chunks.should == ["bam"]
> - @qs.rrun(["list_end"])
> - @qs.jsgets.should == ["end", ["tail"]]
> - end
> - it "should work with zero rows" do
> - @qs.ddoc_run(@ddoc, ["lists","rows"],
> - [{"foo"=>"bar"}, {"q" => "ok"}]).
> - should == ["start", ["first chunk", "ok"], {"headers"=>{}}]
> - @qs.rrun(["list_end"])
> - @qs.jsgets.should == ["end", ["tail"]]
> - end
> - end
> -
> - describe "should buffer multiple chunks sent for a single row." do
> - it "should should buffer em" do
> - @qs.ddoc_run(@ddoc, ["lists","buffer-chunks"],
> - [{"foo"=>"bar"}, {"q" => "ok"}]).
> - should == ["start", ["bacon"], {"headers"=>{}}]
> - @qs.rrun(["list_row", {"key"=>"baz"}])
> - @qs.get_chunks.should == ["baz", "eggs"]
> - @qs.rrun(["list_row", {"key"=>"bam"}])
> - @qs.get_chunks.should == ["bam", "eggs"]
> - @qs.rrun(["list_end"])
> - @qs.jsgets.should == ["end", ["tail"]]
> - end
> + describe "with rows" do
> + it "should list em" do
> + @qs.ddoc_run(@ddoc, ["lists","rows"],
> + [{"foo"=>"bar"}, {"q" => "ok"}]).
> + should == ["start", ["first chunk", "ok"], {"headers"=>{}}]
> + @qs.rrun(["list_row", {"key"=>"baz"}])
> + @qs.get_chunks.should == ["baz"]
> + @qs.rrun(["list_row", {"key"=>"bam"}])
> + @qs.get_chunks.should == ["bam"]
> + @qs.rrun(["list_end"])
> + @qs.jsgets.should == ["end", ["tail"]]
> end
> - it "should end after 2" do
> - @qs.ddoc_run(@ddoc, ["lists","chunky"],
> + it "should work with zero rows" do
> + @qs.ddoc_run(@ddoc, ["lists","rows"],
> [{"foo"=>"bar"}, {"q" => "ok"}]).
> should == ["start", ["first chunk", "ok"], {"headers"=>{}}]
> -
> - @qs.run(["list_row", {"key"=>"baz"}]).
> - should == ["chunks", ["baz"]]
> -
> - @qs.run(["list_row", {"key"=>"bam"}]).
> - should == ["chunks", ["bam"]]
> -
> - @qs.run(["list_row", {"key"=>"foom"}]).
> - should == ["end", ["foom", "early tail"]]
> - # here's where js has to discard quit properly
> - @qs.run(["reset"]).
> - should == true
> + @qs.rrun(["list_end"])
> + @qs.jsgets.should == ["end", ["tail"]]
> + end
> + end
> +
> + describe "should buffer multiple chunks sent for a single row." do
> + it "should should buffer em" do
> + @qs.ddoc_run(@ddoc, ["lists","buffer-chunks"],
> + [{"foo"=>"bar"}, {"q" => "ok"}]).
> + should == ["start", ["bacon"], {"headers"=>{}}]
> + @qs.rrun(["list_row", {"key"=>"baz"}])
> + @qs.get_chunks.should == ["baz", "eggs"]
> + @qs.rrun(["list_row", {"key"=>"bam"}])
> + @qs.get_chunks.should == ["bam", "eggs"]
> + @qs.rrun(["list_end"])
> + @qs.jsgets.should == ["end", ["tail"]]
> end
> end
> +
> + it "should end after 2" do
> + @qs.ddoc_run(@ddoc, ["lists","chunky"],
> + [{"foo"=>"bar"}, {"q" => "ok"}]).
> + should == ["start", ["first chunk", "ok"], {"headers"=>{}}]
> +
> + @qs.run(["list_row", {"key"=>"baz"}]).
> + should == ["chunks", ["baz"]]
> +
> + @qs.run(["list_row", {"key"=>"bam"}]).
> + should == ["chunks", ["bam"]]
> +
> + @qs.run(["list_row", {"key"=>"foom"}]).
> + should == ["end", ["foom", "early tail"]]
> + # here's where js has to discard quit properly
> + @qs.run(["reset"]).
> + should == true
> + end
> end
> +end
>
>
>
> @@ -762,58 +923,60 @@ def should_have_exited qs
> end
> end
>
> -describe "query server that exits" do
> - before(:each) do
> - @qs = QueryServerRunner.run
> - @ddoc = {
> - "_id" => "foo",
> - "lists" => {
> - "capped" => functions["list-capped"][LANGUAGE],
> - "raw" => functions["list-raw"][LANGUAGE]
> - },
> - "shows" => {
> - "fatal" => functions["fatal"][LANGUAGE]
> +if LANGUAGE=='js'
> + describe "query server that exits" do
> + before(:each) do
> + @qs = QueryServerRunner.run
> + @ddoc = {
> + "_id" => "foo",
> + "lists" => {
> + "capped" => functions["list-capped"][LANGUAGE],
> + "raw" => functions["list-raw"][LANGUAGE]
> + },
> + "shows" => {
> + "fatal" => functions["fatal"][LANGUAGE]
> + }
> }
> - }
> - @qs.teach_ddoc(@ddoc)
> - end
> - after(:each) do
> - @qs.close
> - end
> + @qs.teach_ddoc(@ddoc)
> + end
> + after(:each) do
> + @qs.close
> + end
>
> - describe "only goes to 2 list" do
> - it "should exit if erlang sends too many rows" do
> - @qs.ddoc_run(@ddoc, ["lists","capped"],
> - [{"foo"=>"bar"}, {"q" => "ok"}]).
> - should == ["start", ["bacon"], {"headers"=>{}}]
> - @qs.run(["list_row", {"key"=>"baz"}]).should == ["chunks", ["baz"]]
> - @qs.run(["list_row", {"key"=>"foom"}]).should == ["chunks", ["foom"]]
> - @qs.run(["list_row", {"key"=>"fooz"}]).should == ["end", ["fooz",
> "early"]]
> - e = @qs.run(["list_row", {"key"=>"foox"}])
> - e[0].should == "error"
> - e[1].should == "unknown_command"
> - should_have_exited @qs
> + describe "only goes to 2 list" do
> + it "should exit if erlang sends too many rows" do
> + @qs.ddoc_run(@ddoc, ["lists","capped"],
> + [{"foo"=>"bar"}, {"q" => "ok"}]).
> + should == ["start", ["bacon"], {"headers"=>{}}]
> + @qs.run(["list_row", {"key"=>"baz"}]).should == ["chunks", ["baz"]]
> + @qs.run(["list_row", {"key"=>"foom"}]).should == ["chunks", ["foom"]]
> + @qs.run(["list_row", {"key"=>"fooz"}]).should == ["end", ["fooz",
> "early"]]
> + e = @qs.run(["list_row", {"key"=>"foox"}])
> + e[0].should == "error"
> + e[1].should == "unknown_command"
> + should_have_exited @qs
> + end
> end
> - end
>
> - describe "raw list" do
> - it "should exit if it gets a non-row in the middle" do
> - @qs.ddoc_run(@ddoc, ["lists","raw"],
> - [{"foo"=>"bar"}, {"q" => "ok"}]).
> - should == ["start", ["first chunk", "ok"], {"headers"=>{}}]
> - e = @qs.run(["reset"])
> - e[0].should == "error"
> - e[1].should == "list_error"
> - should_have_exited @qs
> + describe "raw list" do
> + it "should exit if it gets a non-row in the middle" do
> + @qs.ddoc_run(@ddoc, ["lists","raw"],
> + [{"foo"=>"bar"}, {"q" => "ok"}]).
> + should == ["start", ["first chunk", "ok"], {"headers"=>{}}]
> + e = @qs.run(["reset"])
> + e[0].should == "error"
> + e[1].should == "list_error"
> + should_have_exited @qs
> + end
> end
> - end
> -
> - describe "fatal error" do
> - it "should exit" do
> - @qs.ddoc_run(@ddoc, ["shows","fatal"],
> - [{"foo"=>"bar"}, {"q" => "ok"}]).
> - should == ["error", "error_key", "testing"]
> - should_have_exited @qs
> +
> + describe "fatal error" do
> + it "should exit" do
> + @qs.ddoc_run(@ddoc, ["shows","fatal"],
> + [{"foo"=>"bar"}, {"q" => "ok"}]).
> + should == ["error", "error_key", "testing"]
> + should_have_exited @qs
> + end
> end
> end
> end
> @@ -821,4 +984,4 @@ end
> describe "thank you for using the tests" do
> it "for more info run with QS_TRACE=true or see query_server_spec.rb file
> header" do
> end
> -end
> \ No newline at end of file
> +end
--
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.