summaryrefslogtreecommitdiff
path: root/test/view_server/query_server_spec.rb
diff options
context:
space:
mode:
Diffstat (limited to 'test/view_server/query_server_spec.rb')
-rw-r--r--test/view_server/query_server_spec.rb824
1 files changed, 0 insertions, 824 deletions
diff --git a/test/view_server/query_server_spec.rb b/test/view_server/query_server_spec.rb
deleted file mode 100644
index de1df5c1..00000000
--- a/test/view_server/query_server_spec.rb
+++ /dev/null
@@ -1,824 +0,0 @@
-# Licensed under the Apache License, Version 2.0 (the "License"); you may not
-# use this file except in compliance with the License. You may obtain a copy of
-# the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
-# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
-# License for the specific language governing permissions and limitations under
-# the License.
-
-# to run (requires ruby and rspec):
-# spec test/view_server/query_server_spec.rb -f specdoc --color
-#
-# environment options:
-# QS_TRACE=true
-# shows full output from the query server
-# QS_LANG=lang
-# run tests on the query server (for now, one of: js, erlang)
-#
-
-COUCH_ROOT = "#{File.dirname(__FILE__)}/../.." unless defined?(COUCH_ROOT)
-LANGUAGE = ENV["QS_LANG"] || "js"
-
-puts "Running query server specs for #{LANGUAGE} query server"
-
-require 'spec'
-require 'json'
-
-class OSProcessRunner
- def self.run
- trace = ENV["QS_TRACE"] || false
- puts "launching #{run_command}" if trace
- if block_given?
- IO.popen(run_command, "r+") do |io|
- qs = QueryServerRunner.new(io, trace)
- yield qs
- end
- else
- io = IO.popen(run_command, "r+")
- QueryServerRunner.new(io, trace)
- end
- end
- def initialize io, trace = false
- @qsio = io
- @trace = trace
- end
- def close
- @qsio.close
- end
- def reset!
- run(["reset"])
- end
- def add_fun(fun)
- run(["add_fun", fun])
- end
- def teach_ddoc(ddoc)
- run(["ddoc", "new", ddoc_id(ddoc), ddoc])
- end
- def ddoc_run(ddoc, fun_path, args)
- run(["ddoc", ddoc_id(ddoc), fun_path, args])
- end
- def ddoc_id(ddoc)
- d_id = ddoc["_id"]
- raise 'ddoc must have _id' unless d_id
- d_id
- end
- def get_chunks
- resp = jsgets
- raise "not a chunk" unless resp.first == "chunks"
- return resp[1]
- end
- def run json
- rrun json
- jsgets
- end
- def rrun json
- line = json.to_json
- puts "run: #{line}" if @trace
- @qsio.puts line
- end
- def rgets
- resp = @qsio.gets
- puts "got: #{resp}" if @trace
- resp
- end
- def jsgets
- resp = rgets
- # err = @qserr.gets
- # puts "err: #{err}" if err
- if resp
- begin
- rj = JSON.parse("[#{resp.chomp}]")[0]
- rescue JSON::ParserError
- puts "JSON ERROR (dump under trace mode)"
- # puts resp.chomp
- while resp = rgets
- # puts resp.chomp
- end
- end
- if rj.respond_to?(:[]) && rj.is_a?(Array)
- if rj[0] == "log"
- log = rj[1]
- puts "log: #{log}" if @trace
- rj = jsgets
- end
- end
- rj
- else
- raise "no response"
- end
- end
-end
-
-class QueryServerRunner < OSProcessRunner
-
- COMMANDS = {
- "js" => "#{COUCH_ROOT}/bin/couchjs_dev #{COUCH_ROOT}/share/server/main.js",
- "erlang" => "#{COUCH_ROOT}/test/view_server/run_native_process.es"
- }
-
- def self.run_command
- COMMANDS[LANGUAGE]
- end
-end
-
-class ExternalRunner < OSProcessRunner
- def self.run_command
- "#{COUCH_ROOT}/src/couchdb/couchjs #{COUCH_ROOT}/share/server/echo.js"
- end
-end
-
-# we could organize this into a design document per language.
-# that would make testing future languages really easy.
-
-functions = {
- "emit-twice" => {
- "js" => %{function(doc){emit("foo",doc.a); emit("bar",doc.a)}},
- "erlang" => <<-ERLANG
- fun({Doc}) ->
- A = couch_util:get_value(<<"a">>, Doc, null),
- Emit(<<"foo">>, A),
- Emit(<<"bar">>, A)
- end.
- ERLANG
- },
- "emit-once" => {
- "js" => <<-JS,
- function(doc){
- emit("baz",doc.a)
- }
- JS
- "erlang" => <<-ERLANG
- fun({Doc}) ->
- A = couch_util:get_value(<<"a">>, Doc, null),
- Emit(<<"baz">>, A)
- end.
- ERLANG
- },
- "reduce-values-length" => {
- "js" => %{function(keys, values, rereduce) { return values.length; }},
- "erlang" => %{fun(Keys, Values, ReReduce) -> length(Values) end.}
- },
- "reduce-values-sum" => {
- "js" => %{function(keys, values, rereduce) { return sum(values); }},
- "erlang" => %{fun(Keys, Values, ReReduce) -> lists:sum(Values) end.}
- },
- "validate-forbidden" => {
- "js" => <<-JS,
- function(newDoc, oldDoc, userCtx) {
- if(newDoc.bad)
- throw({forbidden:"bad doc"}); "foo bar";
- }
- JS
- "erlang" => <<-ERLANG
- fun({NewDoc}, _OldDoc, _UserCtx) ->
- case couch_util:get_value(<<"bad">>, NewDoc) of
- undefined -> 1;
- _ -> {[{forbidden, <<"bad doc">>}]}
- end
- end.
- ERLANG
- },
- "show-simple" => {
- "js" => <<-JS,
- function(doc, req) {
- log("ok");
- return [doc.title, doc.body].join(' - ');
- }
- JS
- "erlang" => <<-ERLANG
- fun({Doc}, Req) ->
- Title = couch_util:get_value(<<"title">>, Doc),
- Body = couch_util:get_value(<<"body">>, Doc),
- Resp = <<Title/binary, " - ", Body/binary>>,
- {[{<<"body">>, Resp}]}
- end.
- ERLANG
- },
- "show-headers" => {
- "js" => <<-JS,
- function(doc, req) {
- var resp = {"code":200, "headers":{"X-Plankton":"Rusty"}};
- resp.body = [doc.title, doc.body].join(' - ');
- return resp;
- }
- JS
- "erlang" => <<-ERLANG
- fun({Doc}, Req) ->
- Title = couch_util:get_value(<<"title">>, Doc),
- Body = couch_util:get_value(<<"body">>, Doc),
- Resp = <<Title/binary, " - ", Body/binary>>,
- {[
- {<<"code">>, 200},
- {<<"headers">>, {[{<<"X-Plankton">>, <<"Rusty">>}]}},
- {<<"body">>, Resp}
- ]}
- end.
- ERLANG
- },
- "show-sends" => {
- "js" => <<-JS,
- function(head, req) {
- start({headers:{"Content-Type" : "text/plain"}});
- send("first chunk");
- send('second "chunk"');
- return "tail";
- };
- JS
- "erlang" => <<-ERLANG
- fun(Head, Req) ->
- Resp = {[
- {<<"headers">>, {[{<<"Content-Type">>, <<"text/plain">>}]}}
- ]},
- Start(Resp),
- Send(<<"first chunk">>),
- Send(<<"second \\\"chunk\\\"">>),
- <<"tail">>
- end.
- ERLANG
- },
- "show-while-get-rows" => {
- "js" => <<-JS,
- function(head, req) {
- send("first chunk");
- send(req.q);
- var row;
- log("about to getRow " + typeof(getRow));
- while(row = getRow()) {
- send(row.key);
- };
- return "tail";
- };
- JS
- "erlang" => <<-ERLANG,
- fun(Head, {Req}) ->
- Send(<<"first chunk">>),
- Send(couch_util:get_value(<<"q">>, Req)),
- Fun = fun({Row}, _) ->
- Send(couch_util:get_value(<<"key">>, Row)),
- {ok, nil}
- end,
- {ok, _} = FoldRows(Fun, nil),
- <<"tail">>
- end.
- ERLANG
- },
- "show-while-get-rows-multi-send" => {
- "js" => <<-JS,
- function(head, req) {
- send("bacon");
- var row;
- log("about to getRow " + typeof(getRow));
- while(row = getRow()) {
- send(row.key);
- send("eggs");
- };
- return "tail";
- };
- JS
- "erlang" => <<-ERLANG,
- fun(Head, Req) ->
- Send(<<"bacon">>),
- Fun = fun({Row}, _) ->
- Send(couch_util:get_value(<<"key">>, Row)),
- Send(<<"eggs">>),
- {ok, nil}
- end,
- FoldRows(Fun, nil),
- <<"tail">>
- end.
- ERLANG
- },
- "list-simple" => {
- "js" => <<-JS,
- function(head, req) {
- send("first chunk");
- send(req.q);
- var row;
- while(row = getRow()) {
- send(row.key);
- };
- return "early";
- };
- JS
- "erlang" => <<-ERLANG,
- fun(Head, {Req}) ->
- Send(<<"first chunk">>),
- Send(couch_util:get_value(<<"q">>, Req)),
- Fun = fun({Row}, _) ->
- Send(couch_util:get_value(<<"key">>, Row)),
- {ok, nil}
- end,
- FoldRows(Fun, nil),
- <<"early">>
- end.
- ERLANG
- },
- "list-chunky" => {
- "js" => <<-JS,
- function(head, req) {
- send("first chunk");
- send(req.q);
- var row, i=0;
- while(row = getRow()) {
- send(row.key);
- i += 1;
- if (i > 2) {
- return('early tail');
- }
- };
- };
- JS
- "erlang" => <<-ERLANG,
- fun(Head, {Req}) ->
- Send(<<"first chunk">>),
- Send(couch_util:get_value(<<"q">>, Req)),
- Fun = fun
- ({Row}, Count) when Count < 2 ->
- Send(couch_util:get_value(<<"key">>, Row)),
- {ok, Count+1};
- ({Row}, Count) when Count == 2 ->
- Send(couch_util:get_value(<<"key">>, Row)),
- {stop, <<"early tail">>}
- end,
- {ok, Tail} = FoldRows(Fun, 0),
- Tail
- end.
- ERLANG
- },
- "list-old-style" => {
- "js" => <<-JS,
- function(head, req, foo, bar) {
- return "stuff";
- }
- JS
- "erlang" => <<-ERLANG,
- fun(Head, Req, Foo, Bar) ->
- <<"stuff">>
- end.
- ERLANG
- },
- "list-capped" => {
- "js" => <<-JS,
- function(head, req) {
- send("bacon")
- var row, i = 0;
- while(row = getRow()) {
- send(row.key);
- i += 1;
- if (i > 2) {
- return('early');
- }
- };
- }
- JS
- "erlang" => <<-ERLANG,
- fun(Head, Req) ->
- Send(<<"bacon">>),
- Fun = fun
- ({Row}, Count) when Count < 2 ->
- Send(couch_util:get_value(<<"key">>, Row)),
- {ok, Count+1};
- ({Row}, Count) when Count == 2 ->
- Send(couch_util:get_value(<<"key">>, Row)),
- {stop, <<"early">>}
- end,
- {ok, Tail} = FoldRows(Fun, 0),
- Tail
- end.
- ERLANG
- },
- "list-raw" => {
- "js" => <<-JS,
- function(head, req) {
- // log(this.toSource());
- // log(typeof send);
- send("first chunk");
- send(req.q);
- var row;
- while(row = getRow()) {
- send(row.key);
- };
- return "tail";
- };
- JS
- "erlang" => <<-ERLANG,
- fun(Head, {Req}) ->
- Send(<<"first chunk">>),
- Send(couch_util:get_value(<<"q">>, Req)),
- Fun = fun({Row}, _) ->
- Send(couch_util:get_value(<<"key">>, Row)),
- {ok, nil}
- end,
- FoldRows(Fun, nil),
- <<"tail">>
- end.
- ERLANG
- },
- "filter-basic" => {
- "js" => <<-JS,
- function(doc, req) {
- if (doc.good) {
- return true;
- }
- }
- JS
- "erlang" => <<-ERLANG,
- fun({Doc}, Req) ->
- couch_util:get_value(<<"good">>, Doc)
- end.
- ERLANG
- },
- "update-basic" => {
- "js" => <<-JS,
- function(doc, req) {
- doc.world = "hello";
- var resp = [doc, "hello doc"];
- return resp;
- }
- JS
- "erlang" => <<-ERLANG,
- fun({Doc}, Req) ->
- Doc2 = [{<<"world">>, <<"hello">>}|Doc],
- [{Doc2}, {[{<<"body">>, <<"hello doc">>}]}]
- end.
- ERLANG
- },
- "error" => {
- "js" => <<-JS,
- function() {
- throw(["error","error_key","testing"]);
- }
- JS
- "erlang" => <<-ERLANG
- fun(A, B) ->
- throw([<<"error">>,<<"error_key">>,<<"testing">>])
- end.
- ERLANG
- },
- "fatal" => {
- "js" => <<-JS,
- function() {
- throw(["fatal","error_key","testing"]);
- }
- JS
- "erlang" => <<-ERLANG
- fun(A, B) ->
- throw([<<"fatal">>,<<"error_key">>,<<"testing">>])
- end.
- ERLANG
- }
-}
-
-def make_ddoc(fun_path, fun_str)
- doc = {"_id"=>"foo"}
- d = doc
- while p = fun_path.shift
- l = p
- if !fun_path.empty?
- d[p] = {}
- d = d[p]
- end
- end
- d[l] = fun_str
- doc
-end
-
-describe "query server normal case" do
- before(:all) do
- `cd #{COUCH_ROOT} && make`
- @qs = QueryServerRunner.run
- end
- after(:all) do
- @qs.close
- end
- it "should reset" do
- @qs.run(["reset"]).should == true
- end
- it "should not erase ddocs on reset" do
- @fun = functions["show-simple"][LANGUAGE]
- @ddoc = make_ddoc(["shows","simple"], @fun)
- @qs.teach_ddoc(@ddoc)
- @qs.run(["reset"]).should == true
- @qs.ddoc_run(@ddoc,
- ["shows","simple"],
- [{: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
- @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
- describe "reduce" do
- before(:all) do
- @fun = functions["reduce-values-length"][LANGUAGE]
- @qs.reset!
- end
- it "should reduce" do
- kvs = (0...10).collect{|i|[i,i*2]}
- @qs.run(["reduce", [@fun], kvs]).should == [true, [10]]
- end
- end
- describe "rereduce" do
- before(:all) do
- @fun = functions["reduce-values-sum"][LANGUAGE]
- @qs.reset!
- end
- it "should rereduce" do
- vs = (0...10).collect{|i|i}
- @qs.run(["rereduce", [@fun], vs]).should == [true, [45]]
- end
- end
-
- describe "design docs" do
- before(:all) do
- @ddoc = {
- "_id" => "foo"
- }
- @qs.reset!
- end
- it "should learn design docs" do
- @qs.teach_ddoc(@ddoc).should == true
- end
- end
-
- # it "should validate"
- describe "validation" do
- before(:all) do
- @fun = functions["validate-forbidden"][LANGUAGE]
- @ddoc = make_ddoc(["validate_doc_update"], @fun)
- @qs.teach_ddoc(@ddoc)
- end
- it "should allow good updates" do
- @qs.ddoc_run(@ddoc,
- ["validate_doc_update"],
- [{"good" => true}, {}, {}]).should == 1
- end
- it "should reject invalid updates" do
- @qs.ddoc_run(@ddoc,
- ["validate_doc_update"],
- [{"bad" => true}, {}, {}]).should == {"forbidden"=>"bad doc"}
- end
- end
-
- describe "show" do
- before(:all) do
- @fun = functions["show-simple"][LANGUAGE]
- @ddoc = make_ddoc(["shows","simple"], @fun)
- @qs.teach_ddoc(@ddoc)
- end
- it "should show" do
- @qs.ddoc_run(@ddoc,
- ["shows","simple"],
- [{:title => "Best ever", :body => "Doc body"}, {}]).should ==
- ["resp", {"body" => "Best ever - Doc body"}]
- end
- end
-
- describe "show with headers" do
- before(:all) do
- # TODO we can make real ddocs up there.
- @fun = functions["show-headers"][LANGUAGE]
- @ddoc = make_ddoc(["shows","headers"], @fun)
- @qs.teach_ddoc(@ddoc)
- end
- it "should show headers" do
- @qs.ddoc_run(
- @ddoc,
- ["shows","headers"],
- [{:title => "Best ever", :body => "Doc body"}, {}]
- ).
- should == ["resp", {"code"=>200,"headers" => {"X-Plankton"=>"Rusty"}, "body" => "Best ever - Doc body"}]
- end
- end
-
- describe "recoverable error" do
- before(:all) do
- @fun = functions["error"][LANGUAGE]
- @ddoc = make_ddoc(["shows","error"], @fun)
- @qs.teach_ddoc(@ddoc)
- end
- it "should not exit" do
- @qs.ddoc_run(@ddoc, ["shows","error"],
- [{"foo"=>"bar"}, {"q" => "ok"}]).
- should == ["error", "error_key", "testing"]
- # still running
- @qs.run(["reset"]).should == true
- end
- end
-
- describe "changes filter" do
- before(:all) do
- @fun = functions["filter-basic"][LANGUAGE]
- @ddoc = make_ddoc(["filters","basic"], @fun)
- @qs.teach_ddoc(@ddoc)
- end
- it "should only return true for good docs" do
- @qs.ddoc_run(@ddoc,
- ["filters","basic"],
- [[{"key"=>"bam", "good" => true}, {"foo" => "bar"}, {"good" => true}], {"req" => "foo"}]
- ).
- should == [true, [true, false, true]]
- end
- end
-
- describe "update" do
- before(:all) do
- # in another patch we can remove this duplication
- # by setting up the design doc for each language ahead of time.
- @fun = functions["update-basic"][LANGUAGE]
- @ddoc = make_ddoc(["updates","basic"], @fun)
- @qs.teach_ddoc(@ddoc)
- end
- it "should return a doc and a resp body" do
- up, doc, resp = @qs.ddoc_run(@ddoc,
- ["updates","basic"],
- [{"foo" => "gnarly"}, {"method" => "POST"}]
- )
- up.should == "up"
- doc.should == {"foo" => "gnarly", "world" => "hello"}
- resp["body"].should == "hello doc"
- end
- end
-
-# end
-# LIST TESTS
-# __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]
- }
- }
- @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
- 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
- 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
-
-
-
-def should_have_exited qs
- begin
- qs.run(["reset"])
- "raise before this (except Erlang)".should == true
- rescue RuntimeError => e
- e.message.should == "no response"
- rescue Errno::EPIPE
- true.should == true
- 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]
- }
- }
- @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
- 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
- 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
- end
- end
-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