You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@couchdb.apache.org by "Jan Lehnardt (Commented) (JIRA)" <ji...@apache.org> on 2011/10/30 22:18:32 UTC

[jira] [Commented] (COUCHDB-731) Improved Query Server tests

    [ https://issues.apache.org/jira/browse/COUCHDB-731?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=13139776#comment-13139776 ] 

Jan Lehnardt commented on COUCHDB-731:
--------------------------------------

This needs a rebase against master.
                
> 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.
If you think it was sent incorrectly, please contact your JIRA administrators: https://issues.apache.org/jira/secure/ContactAdministrators!default.jspa
For more information on JIRA, see: http://www.atlassian.com/software/jira