Return-Path: Delivered-To: apmail-couchdb-dev-archive@www.apache.org Received: (qmail 28400 invoked from network); 12 Apr 2010 05:52:09 -0000 Received: from unknown (HELO mail.apache.org) (140.211.11.3) by 140.211.11.9 with SMTP; 12 Apr 2010 05:52:09 -0000 Received: (qmail 85529 invoked by uid 500); 12 Apr 2010 05:52:08 -0000 Delivered-To: apmail-couchdb-dev-archive@couchdb.apache.org Received: (qmail 85367 invoked by uid 500); 12 Apr 2010 05:52:08 -0000 Mailing-List: contact dev-help@couchdb.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@couchdb.apache.org Delivered-To: mailing list dev@couchdb.apache.org Received: (qmail 85359 invoked by uid 99); 12 Apr 2010 05:52:07 -0000 Received: from nike.apache.org (HELO nike.apache.org) (192.87.106.230) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 12 Apr 2010 05:52:07 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=10.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.22] (HELO thor.apache.org) (140.211.11.22) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 12 Apr 2010 05:52:03 +0000 Received: from thor (localhost [127.0.0.1]) by thor.apache.org (8.13.8+Sun/8.13.8) with ESMTP id o3C5pgIH022830 for ; Mon, 12 Apr 2010 01:51:42 -0400 (EDT) Message-ID: <23055523.17551271051502071.JavaMail.jira@thor> Date: Mon, 12 Apr 2010 01:51:42 -0400 (EDT) From: "Matt Lyon (JIRA)" To: dev@couchdb.apache.org Subject: [jira] Created: (COUCHDB-731) Improved Query Server tests MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 7bit X-JIRA-FingerPrint: 30527f35849b9dde25b450d4833f0394 X-Virus-Checked: Checked by ClamAV on apache.org 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 contact one of the administrators: https://issues.apache.org/jira/secure/Administrators.jspa - For more information on JIRA, see: http://www.atlassian.com/software/jira