diff options
author | Brad Anderson <brad@cloudant.com> | 2010-08-18 16:16:09 -0400 |
---|---|---|
committer | Adam Kocoloski <adam@cloudant.com> | 2010-08-18 17:19:37 -0400 |
commit | 6d18638d747374cb0e90e9bcbefbc71d959254fd (patch) | |
tree | 51ee2c2fd1020550e56febb03c740582af04dfce /test/view_server | |
parent | 1fda1aa8f69d5870c5711b0068971c7d4594e6cc (diff) |
clear out root folder a bit, moving couch bits into apps/couch or rel/
Diffstat (limited to 'test/view_server')
-rw-r--r-- | test/view_server/query_server_spec.rb | 824 | ||||
-rwxr-xr-x | test/view_server/run_native_process.es | 59 |
2 files changed, 0 insertions, 883 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 diff --git a/test/view_server/run_native_process.es b/test/view_server/run_native_process.es deleted file mode 100755 index fcf16d75..00000000 --- a/test/view_server/run_native_process.es +++ /dev/null @@ -1,59 +0,0 @@ -#! /usr/bin/env escript - -% 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. - -read() -> - case io:get_line('') of - eof -> stop; - Data -> couch_util:json_decode(Data) - end. - -send(Data) when is_binary(Data) -> - send(binary_to_list(Data)); -send(Data) when is_list(Data) -> - io:format(Data ++ "\n", []). - -write(Data) -> - % log("~p", [Data]), - case (catch couch_util:json_encode(Data)) of - % when testing, this is what prints your errors - {json_encode, Error} -> write({[{<<"error">>, Error}]}); - Json -> send(Json) - end. - -% log(Mesg) -> -% log(Mesg, []). -% log(Mesg, Params) -> -% io:format(standard_error, Mesg, Params). -% jlog(Mesg) -> -% write([<<"log">>, list_to_binary(io_lib:format("~p",[Mesg]))]). - -loop(Pid) -> - case read() of - stop -> ok; - Json -> - case (catch couch_native_process:prompt(Pid, Json)) of - {error, Reason} -> - ok = write([error, Reason, Reason]); - Resp -> - ok = write(Resp), - loop(Pid) - end - end. - -main([]) -> - code:add_pathz("src/couchdb"), - code:add_pathz("src/mochiweb"), - {ok, Pid} = couch_native_process:start_link(), - loop(Pid). - |