From 29f789e66f71f08434985df0c7622407f0b54102 Mon Sep 17 00:00:00 2001 From: Filipe David Borba Manana Date: Wed, 14 Jul 2010 21:12:19 +0000 Subject: Adapt test to change introduced in revision 963725 - deleted documents can now have non-empty bodies. git-svn-id: https://svn.apache.org/repos/asf/couchdb/trunk@964201 13f79535-47bb-0310-9956-ffa450edef68 --- test/etap/031-doc-to-json.t | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'test') diff --git a/test/etap/031-doc-to-json.t b/test/etap/031-doc-to-json.t index 05425d38..605a6d00 100755 --- a/test/etap/031-doc-to-json.t +++ b/test/etap/031-doc-to-json.t @@ -78,8 +78,8 @@ test_to_json_success() -> }, { #doc{deleted=true, body={[{<<"foo">>, <<"bar">>}]}}, - {[{<<"_id">>, <<>>}, {<<"_deleted">>, true}]}, - "Deleted docs drop body members." + {[{<<"_id">>, <<>>}, {<<"foo">>, <<"bar">>}, {<<"_deleted">>, true}]}, + "Deleted docs no longer drop body members." }, { #doc{meta=[ -- cgit v1.2.3 From 3423f13fe715cea15fdbc35ce03ace3ef45b4c1a Mon Sep 17 00:00:00 2001 From: John Christopher Anderson Date: Sun, 8 Aug 2010 20:00:21 +0000 Subject: fix the db-info assertion to match with the new committed_update_seq field git-svn-id: https://svn.apache.org/repos/asf/couchdb/trunk@983476 13f79535-47bb-0310-9956-ffa450edef68 --- test/etap/160-vhosts.t | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'test') diff --git a/test/etap/160-vhosts.t b/test/etap/160-vhosts.t index 77d9d58b..eb704d31 100755 --- a/test/etap/160-vhosts.t +++ b/test/etap/160-vhosts.t @@ -105,7 +105,7 @@ test_regular_request() -> test_vhost_request() -> case ibrowse:send_req(server(), [], get, [], [{host_header, "example.com"}]) of {ok, _, _, Body} -> - {[{<<"db_name">>, <<"etap-test-db">>},_,_,_,_,_,_,_,_]} + {[{<<"db_name">>, <<"etap-test-db">>},_,_,_,_,_,_,_,_,_]} = couch_util:json_decode(Body), etap:is(true, true, "should return database info"); _Else -> false -- cgit v1.2.3 From b94a613f2cdb3966ab30a8036af41943091f4de4 Mon Sep 17 00:00:00 2001 From: Benoit Chesneau Date: Sun, 15 Aug 2010 14:07:46 +0000 Subject: add requested_path to the req so we know original path in shows/lists & updates function. git-svn-id: https://svn.apache.org/repos/asf/couchdb/trunk@985678 13f79535-47bb-0310-9956-ffa450edef68 --- test/etap/160-vhosts.t | 53 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 51 insertions(+), 2 deletions(-) (limited to 'test') diff --git a/test/etap/160-vhosts.t b/test/etap/160-vhosts.t index eb704d31..45b3f893 100755 --- a/test/etap/160-vhosts.t +++ b/test/etap/160-vhosts.t @@ -54,7 +54,7 @@ config_files() -> main(_) -> test_util:init_code_path(), - etap:plan(4), + etap:plan(6), case (catch test()) of ok -> etap:end_tests(); @@ -76,16 +76,41 @@ test() -> {<<"_id">>, <<"doc1">>}, {<<"value">>, 666} ]}), - {ok, _} = couch_db:update_docs(Db, [Doc]), + + Doc1 = couch_doc:from_json_obj({[ + {<<"_id">>, <<"_design/doc1">>}, + {<<"shows">>, {[ + {<<"test">>, <<"function(doc, req) { + return { json: { + requested_path: '/' + req.requested_path.join('/'), + path: '/' + req.path.join('/') + }}; +}">>} + ]}}, + {<<"rewrites">>, [ + {[ + {<<"from">>, <<"/">>}, + {<<"to">>, <<"_show/test">>} + ]} + ]} + ]}), + + {ok, _} = couch_db:update_docs(Db, [Doc, Doc1]), + couch_db:ensure_full_commit(Db), %% end boilerplate, start test couch_config:set("vhosts", "example.com", "/etap-test-db", false), + couch_config:set("vhosts", "example1.com", +"/etap-test-db/_design/doc1/_rewrite/", false), + test_regular_request(), test_vhost_request(), test_vhost_request_with_qs(), test_vhost_request_with_global(), + test_vhost_requested_path(), + test_vhost_requested_path_path(), %% restart boilerplate couch_db:close(Db), @@ -129,3 +154,27 @@ test_vhost_request_with_global() -> etap:is(true, true, "should serve /_utils even inside vhosts"); _Else -> false end. + +test_vhost_requested_path() -> + case ibrowse:send_req(server(), [], get, [], [{host_header, "example1.com"}]) of + {ok, _, _, Body} -> + {Json} = couch_util:json_decode(Body), + etap:is(case proplists:get_value(<<"requested_path">>, Json) of + <<"/">> -> true; + _ -> false + end, true, <<"requested path in req ok">>); + _Else -> false + end. + + +test_vhost_requested_path_path() -> + case ibrowse:send_req(server(), [], get, [], [{host_header, "example1.com"}]) of + {ok, _, _, Body} -> + {Json} = couch_util:json_decode(Body), + etap:is(case proplists:get_value(<<"path">>, Json) of + <<"/etap-test-db/_design/doc1/_show/test">> -> true; + _ -> false + end, true, <<"path in req ok">>); + _Else -> false + end. + -- cgit v1.2.3 From 84ad2322c28a4d40463dbe031ee0778d50d6b18a Mon Sep 17 00:00:00 2001 From: Benoit Chesneau Date: Tue, 17 Aug 2010 04:11:02 +0000 Subject: New vhost manager. allows dynamic add of vhosts without restart, wildcard in vhost and dynamic routing via pattern matching. Close #COUCHDB-855. git-svn-id: https://svn.apache.org/repos/asf/couchdb/trunk@986182 13f79535-47bb-0310-9956-ffa450edef68 --- test/etap/160-vhosts.t | 65 +++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 59 insertions(+), 6 deletions(-) (limited to 'test') diff --git a/test/etap/160-vhosts.t b/test/etap/160-vhosts.t index 45b3f893..b1050d7f 100755 --- a/test/etap/160-vhosts.t +++ b/test/etap/160-vhosts.t @@ -54,7 +54,7 @@ config_files() -> main(_) -> test_util:init_code_path(), - etap:plan(6), + etap:plan(10), case (catch test()) of ok -> etap:end_tests(); @@ -69,6 +69,7 @@ test() -> ibrowse:start(), crypto:start(), + timer:sleep(1000), couch_server:delete(list_to_binary(dbname()), [admin_user_ctx()]), {ok, Db} = couch_db:create(list_to_binary(dbname()), [admin_user_ctx()]), @@ -101,9 +102,16 @@ test() -> %% end boilerplate, start test - couch_config:set("vhosts", "example.com", "/etap-test-db", false), - couch_config:set("vhosts", "example1.com", -"/etap-test-db/_design/doc1/_rewrite/", false), + ok = couch_config:set("vhosts", "example.com", "/etap-test-db", false), + ok = couch_config:set("vhosts", "*.example.com", + "/etap-test-db/_design/doc1/_rewrite", false), + ok = couch_config:set("vhosts", "example1.com", + "/etap-test-db/_design/doc1/_rewrite/", false), + ok = couch_config:set("vhosts","$appname.$dbname.example1.com", + "/$dbname/_design/$appname/_rewrite/", false), + ok = couch_config:set("vhosts", "$dbname.example1.com", "/$dbname", false), + ok = couch_config:set("vhosts", "*.example2.com", "/*", false), + test_regular_request(), test_vhost_request(), @@ -111,10 +119,16 @@ test() -> test_vhost_request_with_global(), test_vhost_requested_path(), test_vhost_requested_path_path(), + test_vhost_request_wildcard(), + test_vhost_request_replace_var(), + test_vhost_request_replace_var1(), + test_vhost_request_replace_wildcard(), %% restart boilerplate couch_db:close(Db), - couch_server:delete(list_to_binary(dbname()), []), + timer:sleep(3000), + couch_server_sup:stop(), + ok. test_regular_request() -> @@ -166,7 +180,6 @@ test_vhost_requested_path() -> _Else -> false end. - test_vhost_requested_path_path() -> case ibrowse:send_req(server(), [], get, [], [{host_header, "example1.com"}]) of {ok, _, _, Body} -> @@ -178,3 +191,43 @@ test_vhost_requested_path_path() -> _Else -> false end. +test_vhost_request_wildcard()-> + case ibrowse:send_req(server(), [], get, [], [{host_header, "test.example.com"}]) of + {ok, _, _, Body} -> + {Json} = couch_util:json_decode(Body), + etap:is(case proplists:get_value(<<"path">>, Json) of + <<"/etap-test-db/_design/doc1/_show/test">> -> true; + _ -> false + end, true, <<"wildcard ok">>); + _Else -> false + end. + + +test_vhost_request_replace_var() -> + case ibrowse:send_req(server(), [], get, [], [{host_header,"etap-test-db.example1.com"}]) of + {ok, _, _, Body} -> + {[{<<"db_name">>, <<"etap-test-db">>},_,_,_,_,_,_,_,_,_]} + = couch_util:json_decode(Body), + etap:is(true, true, "should return database info"); + _Else -> false + end. + +test_vhost_request_replace_var1() -> + case ibrowse:send_req(server(), [], get, [], [{host_header, "doc1.etap-test-db.example1.com"}]) of + {ok, _, _, Body} -> + {Json} = couch_util:json_decode(Body), + etap:is(case proplists:get_value(<<"path">>, Json) of + <<"/etap-test-db/_design/doc1/_show/test">> -> true; + _ -> false + end, true, <<"wildcard ok">>); + _Else -> false + end. + +test_vhost_request_replace_wildcard() -> + case ibrowse:send_req(server(), [], get, [], [{host_header,"etap-test-db.example2.com"}]) of + {ok, _, _, Body} -> + {[{<<"db_name">>, <<"etap-test-db">>},_,_,_,_,_,_,_,_,_]} + = couch_util:json_decode(Body), + etap:is(true, true, "should return database info"); + _Else -> false + end. -- cgit v1.2.3 From d18d7036788acf2d5ddab608d0352158139de189 Mon Sep 17 00:00:00 2001 From: Robert Newson Date: Wed, 18 Aug 2010 11:41:10 +0000 Subject: COUCHDB-161 - support Range header for attachments. Attachments are upgraded to support the Range header on compaction. git-svn-id: https://svn.apache.org/repos/asf/couchdb/trunk@986629 13f79535-47bb-0310-9956-ffa450edef68 --- test/etap/050-stream.t | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'test') diff --git a/test/etap/050-stream.t b/test/etap/050-stream.t index 545dd524..d30b524a 100755 --- a/test/etap/050-stream.t +++ b/test/etap/050-stream.t @@ -43,7 +43,7 @@ test() -> "Writing an empty binary does nothing."), {Ptrs, Length, _, _, _} = couch_stream:close(Stream), - etap:is(Ptrs, [0], "Close returns the file pointers."), + etap:is(Ptrs, [{0, 8}], "Close returns the file pointers."), etap:is(Length, 8, "Close also returns the number of bytes written."), etap:is(<<"foodfoob">>, read_all(Fd, Ptrs), "Returned pointers are valid."), @@ -59,7 +59,7 @@ test() -> "Successfully wrote 80 0 bits."), {Ptrs2, Length2, _, _, _} = couch_stream:close(Stream2), - etap:is(Ptrs2, [ExpPtr], "Closing stream returns the file pointers."), + etap:is(Ptrs2, [{ExpPtr, 20}], "Closing stream returns the file pointers."), etap:is(Length2, 20, "Length written is 160 bytes."), AllBits = iolist_to_binary([OneBits,ZeroBits]), @@ -80,7 +80,7 @@ test() -> % + 4 bytes for the term_to_binary adding a length header % + 1 byte every 4K for tail append headers SecondPtr = ExpPtr2 + 4095 + 5 + 4 + 1, - etap:is(Ptrs3, [ExpPtr2, SecondPtr], "Pointers every 4K bytes."), + etap:is(Ptrs3, [{ExpPtr2, 4100}, {SecondPtr, 1020}], "Pointers every 4K bytes."), etap:is(Length3, 5120, "Wrote the expected 5K bytes."), couch_file:close(Fd), -- cgit v1.2.3 From 04d3501301031fde6bce119a8c9275ef9e8830d5 Mon Sep 17 00:00:00 2001 From: Benoit Chesneau Date: Fri, 20 Aug 2010 06:22:41 +0000 Subject: sysadmins were shocked that we can use $ for anything else than a shell environment variable. use ":" instead. use ":" instead like we do in _rewrite handler. like we do in _rewrite handler. git-svn-id: https://svn.apache.org/repos/asf/couchdb/trunk@987384 13f79535-47bb-0310-9956-ffa450edef68 --- test/etap/160-vhosts.t | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'test') diff --git a/test/etap/160-vhosts.t b/test/etap/160-vhosts.t index b1050d7f..7eaf2874 100755 --- a/test/etap/160-vhosts.t +++ b/test/etap/160-vhosts.t @@ -107,9 +107,9 @@ test() -> "/etap-test-db/_design/doc1/_rewrite", false), ok = couch_config:set("vhosts", "example1.com", "/etap-test-db/_design/doc1/_rewrite/", false), - ok = couch_config:set("vhosts","$appname.$dbname.example1.com", - "/$dbname/_design/$appname/_rewrite/", false), - ok = couch_config:set("vhosts", "$dbname.example1.com", "/$dbname", false), + ok = couch_config:set("vhosts",":appname.:dbname.example1.com", + "/:dbname/_design/:appname/_rewrite/", false), + ok = couch_config:set("vhosts", ":dbname.example1.com", "/:dbname", false), ok = couch_config:set("vhosts", "*.example2.com", "/*", false), -- cgit v1.2.3 From ec75b49cc9385495d6fa40cac50f825def9433d8 Mon Sep 17 00:00:00 2001 From: Benoit Chesneau Date: Tue, 7 Sep 2010 23:35:28 +0000 Subject: fix issue #COUCHDB-230 . now it's possible to do */test = /db/_design/test or even example.com/test = /db/_design/test and other stuff already possible with vhost manager. git-svn-id: https://svn.apache.org/repos/asf/couchdb/trunk@993558 13f79535-47bb-0310-9956-ffa450edef68 --- test/etap/160-vhosts.t | 57 +++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 54 insertions(+), 3 deletions(-) (limited to 'test') diff --git a/test/etap/160-vhosts.t b/test/etap/160-vhosts.t index 7eaf2874..aea2e829 100755 --- a/test/etap/160-vhosts.t +++ b/test/etap/160-vhosts.t @@ -54,7 +54,7 @@ config_files() -> main(_) -> test_util:init_code_path(), - etap:plan(10), + etap:plan(14), case (catch test()) of ok -> etap:end_tests(); @@ -105,13 +105,18 @@ test() -> ok = couch_config:set("vhosts", "example.com", "/etap-test-db", false), ok = couch_config:set("vhosts", "*.example.com", "/etap-test-db/_design/doc1/_rewrite", false), + ok = couch_config:set("vhosts", "example.com/test", "/etap-test-db", false), ok = couch_config:set("vhosts", "example1.com", "/etap-test-db/_design/doc1/_rewrite/", false), ok = couch_config:set("vhosts",":appname.:dbname.example1.com", "/:dbname/_design/:appname/_rewrite/", false), ok = couch_config:set("vhosts", ":dbname.example1.com", "/:dbname", false), + ok = couch_config:set("vhosts", "*.example2.com", "/*", false), - + ok = couch_config:set("vhosts", "*/test", "/etap-test-db", false), + ok = couch_config:set("vhosts", "*.example2.com/test", "/*", false), + ok = couch_config:set("vhosts", "*/test1", + "/etap-test-db/_design/doc1/_show/test", false), test_regular_request(), test_vhost_request(), @@ -123,7 +128,11 @@ test() -> test_vhost_request_replace_var(), test_vhost_request_replace_var1(), test_vhost_request_replace_wildcard(), - + test_vhost_request_path(), + test_vhost_request_path1(), + test_vhost_request_path2(), + test_vhost_request_path3(), + %% restart boilerplate couch_db:close(Db), timer:sleep(3000), @@ -231,3 +240,45 @@ test_vhost_request_replace_wildcard() -> etap:is(true, true, "should return database info"); _Else -> false end. + +test_vhost_request_path() -> + Uri = server() ++ "test", + case ibrowse:send_req(Uri, [], get, [], [{host_header, "example.com"}]) of + {ok, _, _, Body} -> + {[{<<"db_name">>, <<"etap-test-db">>},_,_,_,_,_,_,_,_,_]} + = couch_util:json_decode(Body), + etap:is(true, true, "should return database info"); + _Else -> false + end. + +test_vhost_request_path1() -> + Url = server() ++ "test/doc1?revs_info=true", + case ibrowse:send_req(Url, [], get, [], []) of + {ok, _, _, Body} -> + {JsonProps} = couch_util:json_decode(Body), + HasRevsInfo = proplists:is_defined(<<"_revs_info">>, JsonProps), + etap:is(HasRevsInfo, true, "should return _revs_info"); + _Else -> false + end. + +test_vhost_request_path2() -> + Uri = server() ++ "test", + case ibrowse:send_req(Uri, [], get, [], [{host_header,"etap-test-db.example2.com"}]) of + {ok, _, _, Body} -> + {[{<<"db_name">>, <<"etap-test-db">>},_,_,_,_,_,_,_,_,_]} + = couch_util:json_decode(Body), + etap:is(true, true, "should return database info"); + _Else -> false + end. + +test_vhost_request_path3() -> + Uri = server() ++ "test1", + case ibrowse:send_req(Uri, [], get, [], []) of + {ok, _, _, Body} -> + {Json} = couch_util:json_decode(Body), + etap:is(case proplists:get_value(<<"path">>, Json) of + <<"/etap-test-db/_design/doc1/_show/test">> -> true; + _ -> false + end, true, <<"path in req ok">>); + _Else -> false + end. -- cgit v1.2.3 From 2b9d22d8ca64c2017443318a9d1c03fb202d273f Mon Sep 17 00:00:00 2001 From: Benoit Chesneau Date: Wed, 8 Sep 2010 00:41:22 +0000 Subject: make sure we always do a plan. git-svn-id: https://svn.apache.org/repos/asf/couchdb/trunk@993567 13f79535-47bb-0310-9956-ffa450edef68 --- test/etap/160-vhosts.t | 36 +++++++++++++++++++++--------------- 1 file changed, 21 insertions(+), 15 deletions(-) (limited to 'test') diff --git a/test/etap/160-vhosts.t b/test/etap/160-vhosts.t index aea2e829..f4bd5e27 100755 --- a/test/etap/160-vhosts.t +++ b/test/etap/160-vhosts.t @@ -141,13 +141,14 @@ test() -> ok. test_regular_request() -> - case ibrowse:send_req(server(), [], get, []) of + Result = case ibrowse:send_req(server(), [], get, []) of {ok, _, _, Body} -> {[{<<"couchdb">>, <<"Welcome">>}, {<<"version">>,_} ]} = couch_util:json_decode(Body), etap:is(true, true, "should return server info"); - _Else -> false + _Else -> + etap:is(false, true, <<"ibrowse fail">>) end. test_vhost_request() -> @@ -156,7 +157,8 @@ test_vhost_request() -> {[{<<"db_name">>, <<"etap-test-db">>},_,_,_,_,_,_,_,_,_]} = couch_util:json_decode(Body), etap:is(true, true, "should return database info"); - _Else -> false + _Else -> + etap:is(false, true, <<"ibrowse fail">>) end. test_vhost_request_with_qs() -> @@ -166,7 +168,8 @@ test_vhost_request_with_qs() -> {JsonProps} = couch_util:json_decode(Body), HasRevsInfo = proplists:is_defined(<<"_revs_info">>, JsonProps), etap:is(HasRevsInfo, true, "should return _revs_info"); - _Else -> false + _Else -> + etap:is(false, true, <<"ibrowse fail">>) end. test_vhost_request_with_global() -> @@ -175,7 +178,8 @@ test_vhost_request_with_global() -> {ok, _, _, Body2} -> " false + _Else -> + etap:is(false, true, <<"ibrowse fail">>) end. test_vhost_requested_path() -> @@ -186,7 +190,8 @@ test_vhost_requested_path() -> <<"/">> -> true; _ -> false end, true, <<"requested path in req ok">>); - _Else -> false + _Else -> + etap:is(false, true, <<"ibrowse fail">>) end. test_vhost_requested_path_path() -> @@ -197,7 +202,8 @@ test_vhost_requested_path_path() -> <<"/etap-test-db/_design/doc1/_show/test">> -> true; _ -> false end, true, <<"path in req ok">>); - _Else -> false + _Else -> + etap:is(false, true, <<"ibrowse fail">>) end. test_vhost_request_wildcard()-> @@ -208,7 +214,7 @@ test_vhost_request_wildcard()-> <<"/etap-test-db/_design/doc1/_show/test">> -> true; _ -> false end, true, <<"wildcard ok">>); - _Else -> false + _Else -> etap:is(false, true, <<"ibrowse fail">>) end. @@ -218,7 +224,7 @@ test_vhost_request_replace_var() -> {[{<<"db_name">>, <<"etap-test-db">>},_,_,_,_,_,_,_,_,_]} = couch_util:json_decode(Body), etap:is(true, true, "should return database info"); - _Else -> false + _Else -> etap:is(false, true, <<"ibrowse fail">>) end. test_vhost_request_replace_var1() -> @@ -229,7 +235,7 @@ test_vhost_request_replace_var1() -> <<"/etap-test-db/_design/doc1/_show/test">> -> true; _ -> false end, true, <<"wildcard ok">>); - _Else -> false + _Else -> etap:is(false, true, <<"ibrowse fail">>) end. test_vhost_request_replace_wildcard() -> @@ -238,7 +244,7 @@ test_vhost_request_replace_wildcard() -> {[{<<"db_name">>, <<"etap-test-db">>},_,_,_,_,_,_,_,_,_]} = couch_util:json_decode(Body), etap:is(true, true, "should return database info"); - _Else -> false + _Else -> etap:is(false, true, <<"ibrowse fail">>) end. test_vhost_request_path() -> @@ -248,7 +254,7 @@ test_vhost_request_path() -> {[{<<"db_name">>, <<"etap-test-db">>},_,_,_,_,_,_,_,_,_]} = couch_util:json_decode(Body), etap:is(true, true, "should return database info"); - _Else -> false + _Else -> etap:is(false, true, <<"ibrowse fail">>) end. test_vhost_request_path1() -> @@ -258,7 +264,7 @@ test_vhost_request_path1() -> {JsonProps} = couch_util:json_decode(Body), HasRevsInfo = proplists:is_defined(<<"_revs_info">>, JsonProps), etap:is(HasRevsInfo, true, "should return _revs_info"); - _Else -> false + _Else -> etap:is(false, true, <<"ibrowse fail">>) end. test_vhost_request_path2() -> @@ -268,7 +274,7 @@ test_vhost_request_path2() -> {[{<<"db_name">>, <<"etap-test-db">>},_,_,_,_,_,_,_,_,_]} = couch_util:json_decode(Body), etap:is(true, true, "should return database info"); - _Else -> false + _Else -> etap:is(false, true, <<"ibrowse fail">>) end. test_vhost_request_path3() -> @@ -280,5 +286,5 @@ test_vhost_request_path3() -> <<"/etap-test-db/_design/doc1/_show/test">> -> true; _ -> false end, true, <<"path in req ok">>); - _Else -> false + _Else -> etap:is(false, true, <<"ibrowse fail">>) end. -- cgit v1.2.3 From c8785113522b8486fab0ba53f2043d94e9b1507f Mon Sep 17 00:00:00 2001 From: Paul Joseph Davis Date: Fri, 5 Nov 2010 23:14:02 +0000 Subject: Enable CouchDB to manage OS process daemons. This is a simple feature that allows useres to configure CouchDB so that it maintains a given OS level process alive. If the process dies for any reason, CouchDB will restart it. If the process restarts too often, then CouchDB will mark it has halted and not attempt to restart it. The default max restart rate is three times in the last five seconds. These parameters are adjustable. Commands that are started in this manner will have access to a simple API over stdio to request configuration parameters or to add log statements to CouchDB's logs. To configure an OS process as a CouchDB os_daemon, create a section in your local.ini like such: [os_daemons] daemon_name = /path/to/command -with args This will make CouchDB bring up the command and attempt to keep it alive. To request a configuration parameter, an os_daemon can write a simple JSON message to stdout like such: ["get", "os_daemons"]\n which would return: {"daemon_name": "/path/to/command -with args"} Or: ["get", "os_daemons", "daemon_name"]\n which would return: "/path/to/command -with args" There's no restriction on what configuration variables are visible. There's also no method for altering the configuration. If you would like your OS daemon to be restarted in the event that the configuration changes, you can send the following messages: ["register", $(SECTION)]\n When anyting in that section changes, your OS process will be rebooted so it can pick up the new configuration settings. If you want to listen for changes on a specific key, you can send something like: ["register", $(SECTION), $(KEY)]\n In this case, CouchDB will only restart your daemon if that exact section/key pair changes, instead of anything in that entire section. Logging commands look like: ["log", $(JSON_MESSAGE)]\n Where $(JSON_MESSAGE) is arbitrary JSON data. These messages are logged at the 'info' level. If you want to log at a different level you can pass messages like such: ["log", $(JSON_MESSAGE), {"level": $(LEVEL)}]\n Where $(LEVEL) is one of "debug", "info", or "error". When implementing a daemon process to be managed by CouchDB you should remember to use a method like checking the parent process id or if stdin has been closed. These flags can tell you if your daemon process has been orphaned so you can exit cleanly. git-svn-id: https://svn.apache.org/repos/asf/couchdb/trunk@1031875 13f79535-47bb-0310-9956-ffa450edef68 --- test/etap/170-os-daemons.es | 26 +++++++ test/etap/170-os-daemons.t | 114 +++++++++++++++++++++++++++++ test/etap/171-os-daemons-config.es | 78 ++++++++++++++++++++ test/etap/171-os-daemons-config.t | 74 +++++++++++++++++++ test/etap/172-os-daemon-errors.1.es | 22 ++++++ test/etap/172-os-daemon-errors.2.es | 16 ++++ test/etap/172-os-daemon-errors.3.es | 17 +++++ test/etap/172-os-daemon-errors.4.es | 17 +++++ test/etap/172-os-daemon-errors.t | 126 ++++++++++++++++++++++++++++++++ test/etap/173-os-daemon-cfg-register.es | 35 +++++++++ test/etap/173-os-daemon-cfg-register.t | 98 +++++++++++++++++++++++++ test/etap/Makefile.am | 13 +++- 12 files changed, 635 insertions(+), 1 deletion(-) create mode 100755 test/etap/170-os-daemons.es create mode 100755 test/etap/170-os-daemons.t create mode 100755 test/etap/171-os-daemons-config.es create mode 100755 test/etap/171-os-daemons-config.t create mode 100644 test/etap/172-os-daemon-errors.1.es create mode 100755 test/etap/172-os-daemon-errors.2.es create mode 100755 test/etap/172-os-daemon-errors.3.es create mode 100755 test/etap/172-os-daemon-errors.4.es create mode 100755 test/etap/172-os-daemon-errors.t create mode 100755 test/etap/173-os-daemon-cfg-register.es create mode 100755 test/etap/173-os-daemon-cfg-register.t (limited to 'test') diff --git a/test/etap/170-os-daemons.es b/test/etap/170-os-daemons.es new file mode 100755 index 00000000..73974e90 --- /dev/null +++ b/test/etap/170-os-daemons.es @@ -0,0 +1,26 @@ +#! /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. + +loop() -> + loop(io:read("")). + +loop({ok, _}) -> + loop(io:read("")); +loop(eof) -> + stop; +loop({error, Reason}) -> + throw({error, Reason}). + +main([]) -> + loop(). diff --git a/test/etap/170-os-daemons.t b/test/etap/170-os-daemons.t new file mode 100755 index 00000000..6feaa1bf --- /dev/null +++ b/test/etap/170-os-daemons.t @@ -0,0 +1,114 @@ +#!/usr/bin/env escript +%% -*- erlang -*- + +% 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. + +-record(daemon, { + port, + name, + cmd, + kill, + status=running, + cfg_patterns=[], + errors=[], + buf=[] +}). + +config_files() -> + lists:map(fun test_util:build_file/1, [ + "etc/couchdb/default_dev.ini" + ]). + +daemon_cmd() -> + test_util:source_file("test/etap/170-os-daemons.es"). + +main(_) -> + test_util:init_code_path(), + + etap:plan(49), + case (catch test()) of + ok -> + etap:end_tests(); + Other -> + etap:diag(io_lib:format("Test died abnormally: ~p", [Other])), + etap:bail(Other) + end, + ok. + +test() -> + couch_config:start_link(config_files()), + couch_os_daemons:start_link(), + + etap:diag("Daemons boot after configuration added."), + couch_config:set("os_daemons", "foo", daemon_cmd(), false), + timer:sleep(1000), + + {ok, [D1]} = couch_os_daemons:info([table]), + check_daemon(D1, "foo"), + + % Check table form + {ok, Tab1} = couch_os_daemons:info(), + [T1] = ets:tab2list(Tab1), + check_daemon(T1, "foo"), + + etap:diag("Daemons stop after configuration removed."), + couch_config:delete("os_daemons", "foo", false), + timer:sleep(500), + + {ok, []} = couch_os_daemons:info([table]), + {ok, Tab2} = couch_os_daemons:info(), + etap:is(ets:tab2list(Tab2), [], "As table returns empty table."), + + etap:diag("Adding multiple daemons causes both to boot."), + couch_config:set("os_daemons", "bar", daemon_cmd(), false), + couch_config:set("os_daemons", "baz", daemon_cmd(), false), + timer:sleep(500), + {ok, Daemons} = couch_os_daemons:info([table]), + lists:foreach(fun(D) -> + check_daemon(D) + end, Daemons), + + {ok, Tab3} = couch_os_daemons:info(), + lists:foreach(fun(D) -> + check_daemon(D) + end, ets:tab2list(Tab3)), + + etap:diag("Removing one daemon leaves the other alive."), + couch_config:delete("os_daemons", "bar", false), + timer:sleep(500), + + {ok, [D2]} = couch_os_daemons:info([table]), + check_daemon(D2, "baz"), + + % Check table version + {ok, Tab4} = couch_os_daemons:info(), + [T4] = ets:tab2list(Tab4), + check_daemon(T4, "baz"), + + ok. + +check_daemon(D) -> + check_daemon(D, D#daemon.name). + +check_daemon(D, Name) -> + BaseName = "170-os-daemons.es", + BaseLen = length(BaseName), + CmdLen = length(D#daemon.cmd), + CmdName = lists:sublist(D#daemon.cmd, CmdLen-BaseLen+1, BaseLen), + + etap:is(is_port(D#daemon.port), true, "Daemon port is a port."), + etap:is(D#daemon.name, Name, "Daemon name was set correctly."), + etap:is(CmdName, BaseName, "Command name was set correctly."), + etap:isnt(D#daemon.kill, undefined, "Kill command was set."), + etap:is(D#daemon.errors, [], "No errors occurred while booting."), + etap:is(D#daemon.buf, [], "No extra data left in the buffer."). diff --git a/test/etap/171-os-daemons-config.es b/test/etap/171-os-daemons-config.es new file mode 100755 index 00000000..96e051a3 --- /dev/null +++ b/test/etap/171-os-daemons-config.es @@ -0,0 +1,78 @@ +#! /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. + +filename() -> + list_to_binary(test_util:source_file("test/etap/171-os-daemons-config.es")). + +read() -> + case io:get_line('') of + eof -> + stop; + Data -> + couch_util:json_decode(Data) + end. + +write(Mesg) -> + Data = iolist_to_binary(couch_util:json_encode(Mesg)), + io:format(binary_to_list(Data) ++ "\n", []). + +get_cfg(Section) -> + write([<<"get">>, Section]), + read(). + +get_cfg(Section, Name) -> + write([<<"get">>, Section, Name]), + read(). + +log(Mesg) -> + write([<<"log">>, Mesg]). + +log(Mesg, Level) -> + write([<<"log">>, Mesg, {[{<<"level">>, Level}]}]). + +test_get_cfg1() -> + FileName = filename(), + {[{<<"foo">>, FileName}]} = get_cfg(<<"os_daemons">>). + +test_get_cfg2() -> + FileName = filename(), + FileName = get_cfg(<<"os_daemons">>, <<"foo">>), + <<"sequential">> = get_cfg(<<"uuids">>, <<"algorithm">>). + +test_log() -> + log(<<"foobar!">>), + log(<<"some stuff!">>, <<"debug">>), + log(2), + log(true), + write([<<"log">>, <<"stuff">>, 2]), + write([<<"log">>, 3, null]), + write([<<"log">>, [1, 2], {[{<<"level">>, <<"debug">>}]}]), + write([<<"log">>, <<"true">>, {[]}]). + +do_tests() -> + test_get_cfg1(), + test_get_cfg2(), + test_log(), + loop(io:read("")). + +loop({ok, _}) -> + loop(io:read("")); +loop(eof) -> + init:stop(); +loop({error, _Reason}) -> + init:stop(). + +main([]) -> + test_util:init_code_path(), + do_tests(). diff --git a/test/etap/171-os-daemons-config.t b/test/etap/171-os-daemons-config.t new file mode 100755 index 00000000..e9dc3f32 --- /dev/null +++ b/test/etap/171-os-daemons-config.t @@ -0,0 +1,74 @@ +#!/usr/bin/env escript +%% -*- erlang -*- + +% 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. + +-record(daemon, { + port, + name, + cmd, + kill, + status=running, + cfg_patterns=[], + errors=[], + buf=[] +}). + +config_files() -> + lists:map(fun test_util:build_file/1, [ + "etc/couchdb/default_dev.ini" + ]). + +daemon_cmd() -> + test_util:source_file("test/etap/171-os-daemons-config.es"). + +main(_) -> + test_util:init_code_path(), + + etap:plan(6), + case (catch test()) of + ok -> + etap:end_tests(); + Other -> + etap:diag(io_lib:format("Test died abnormally: ~p", [Other])), + etap:bail(Other) + end, + ok. + +test() -> + couch_config:start_link(config_files()), + couch_config:set("log", "level", "debug", false), + couch_log:start_link(), + couch_os_daemons:start_link(), + + % "foo" is a required name by this test. + couch_config:set("os_daemons", "foo", daemon_cmd(), false), + timer:sleep(1000), + + {ok, [D1]} = couch_os_daemons:info([table]), + check_daemon(D1, "foo"), + + ok. + +check_daemon(D, Name) -> + BaseName = "171-os-daemons-config.es", + BaseLen = length(BaseName), + CmdLen = length(D#daemon.cmd), + CmdName = lists:sublist(D#daemon.cmd, CmdLen-BaseLen+1, BaseLen), + + etap:is(is_port(D#daemon.port), true, "Daemon port is a port."), + etap:is(D#daemon.name, Name, "Daemon name was set correctly."), + etap:is(CmdName, BaseName, "Command name was set correctly."), + etap:isnt(D#daemon.kill, undefined, "Kill command was set."), + etap:is(D#daemon.errors, [], "No errors occurred while booting."), + etap:is(D#daemon.buf, [], "No extra data left in the buffer."). diff --git a/test/etap/172-os-daemon-errors.1.es b/test/etap/172-os-daemon-errors.1.es new file mode 100644 index 00000000..a9defba1 --- /dev/null +++ b/test/etap/172-os-daemon-errors.1.es @@ -0,0 +1,22 @@ +#! /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. + +% Please do not make this file executable as that's the error being tested. + +loop() -> + timer:sleep(5000), + loop(). + +main([]) -> + loop(). diff --git a/test/etap/172-os-daemon-errors.2.es b/test/etap/172-os-daemon-errors.2.es new file mode 100755 index 00000000..52de0401 --- /dev/null +++ b/test/etap/172-os-daemon-errors.2.es @@ -0,0 +1,16 @@ +#! /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. + +main([]) -> + init:stop(). diff --git a/test/etap/172-os-daemon-errors.3.es b/test/etap/172-os-daemon-errors.3.es new file mode 100755 index 00000000..64229800 --- /dev/null +++ b/test/etap/172-os-daemon-errors.3.es @@ -0,0 +1,17 @@ +#! /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. + +main([]) -> + timer:sleep(1000), + init:stop(). diff --git a/test/etap/172-os-daemon-errors.4.es b/test/etap/172-os-daemon-errors.4.es new file mode 100755 index 00000000..577f3410 --- /dev/null +++ b/test/etap/172-os-daemon-errors.4.es @@ -0,0 +1,17 @@ +#! /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. + +main([]) -> + timer:sleep(2000), + init:stop(). diff --git a/test/etap/172-os-daemon-errors.t b/test/etap/172-os-daemon-errors.t new file mode 100755 index 00000000..287a0812 --- /dev/null +++ b/test/etap/172-os-daemon-errors.t @@ -0,0 +1,126 @@ +#!/usr/bin/env escript +%% -*- erlang -*- + +% 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. + +-record(daemon, { + port, + name, + cmd, + kill, + status=running, + cfg_patterns=[], + errors=[], + buf=[] +}). + +config_files() -> + lists:map(fun test_util:build_file/1, [ + "etc/couchdb/default_dev.ini" + ]). + +bad_perms() -> + test_util:source_file("test/etap/172-os-daemon-errors.1.es"). + +die_on_boot() -> + test_util:source_file("test/etap/172-os-daemon-errors.2.es"). + +die_quickly() -> + test_util:source_file("test/etap/172-os-daemon-errors.3.es"). + +can_reboot() -> + test_util:source_file("test/etap/172-os-daemon-errors.4.es"). + +main(_) -> + test_util:init_code_path(), + + etap:plan(36), + case (catch test()) of + ok -> + etap:end_tests(); + Other -> + etap:diag(io_lib:format("Test died abnormally: ~p", [Other])), + etap:bail(Other) + end, + ok. + +test() -> + couch_config:start_link(config_files()), + couch_os_daemons:start_link(), + + etap:diag("Daemon not executable."), + test_halts("foo", bad_perms(), 1000), + + etap:diag("Daemon dies on boot."), + test_halts("bar", die_on_boot(), 1000), + + etap:diag("Daemon dies quickly after boot."), + test_halts("baz", die_quickly(), 4000), + + etap:diag("Daemon dies, but not quickly enough to be halted."), + test_runs("bam", can_reboot()), + + ok. + +test_halts(Name, Cmd, Time) -> + couch_config:set("os_daemons", Name, Cmd ++ " 2> /dev/null", false), + timer:sleep(Time), + {ok, [D]} = couch_os_daemons:info([table]), + check_dead(D, Name, Cmd), + couch_config:delete("os_daemons", Name, false). + +test_runs(Name, Cmd) -> + couch_config:set("os_daemons", Name, Cmd, false), + + timer:sleep(1000), + {ok, [D1]} = couch_os_daemons:info([table]), + check_daemon(D1, Name, Cmd, 0), + + % Should reboot every two seconds. We're at 1s, so wait + % utnil 3s to be in the middle of the next invocation's + % life span. + timer:sleep(2000), + {ok, [D2]} = couch_os_daemons:info([table]), + check_daemon(D2, Name, Cmd, 1), + + % If the kill command changed, that means we rebooted the process. + etap:isnt(D1#daemon.kill, D2#daemon.kill, "Kill command changed."). + +check_dead(D, Name, Cmd) -> + BaseName = filename:basename(Cmd) ++ " 2> /dev/null", + BaseLen = length(BaseName), + CmdLen = length(D#daemon.cmd), + CmdName = lists:sublist(D#daemon.cmd, CmdLen-BaseLen+1, BaseLen), + + etap:is(is_port(D#daemon.port), true, "Daemon port is a port."), + etap:is(D#daemon.name, Name, "Daemon name was set correctly."), + etap:is(CmdName, BaseName, "Command name was set correctly."), + etap:isnt(D#daemon.kill, undefined, "Kill command was set."), + etap:is(D#daemon.status, halted, "Daemon has been halted."), + etap:is(D#daemon.errors, nil, "Errors have been disabled."), + etap:is(D#daemon.buf, nil, "Buffer has been switched off."). + +check_daemon(D, Name, Cmd, Errs) -> + BaseName = filename:basename(Cmd), + BaseLen = length(BaseName), + CmdLen = length(D#daemon.cmd), + CmdName = lists:sublist(D#daemon.cmd, CmdLen-BaseLen+1, BaseLen), + + etap:is(is_port(D#daemon.port), true, "Daemon port is a port."), + etap:is(D#daemon.name, Name, "Daemon name was set correctly."), + etap:is(CmdName, BaseName, "Command name was set correctly."), + etap:isnt(D#daemon.kill, undefined, "Kill command was set."), + etap:is(D#daemon.status, running, "Daemon still running."), + etap:is(length(D#daemon.errors), Errs, "Found expected number of errors."), + etap:is(D#daemon.buf, [], "No extra data left in the buffer."). + diff --git a/test/etap/173-os-daemon-cfg-register.es b/test/etap/173-os-daemon-cfg-register.es new file mode 100755 index 00000000..3d536dc7 --- /dev/null +++ b/test/etap/173-os-daemon-cfg-register.es @@ -0,0 +1,35 @@ +#! /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. + +write(Mesg) -> + Data = iolist_to_binary(couch_util:json_encode(Mesg)), + io:format(binary_to_list(Data) ++ "\n", []). + +cfg_register(Section) -> + write([<<"register">>, Section]). + +cfg_register(Section, Key) -> + write([<<"register">>, Section, Key]). + +wait(_) -> + init:stop(). + +do_tests() -> + cfg_register(<<"s1">>), + cfg_register(<<"s2">>, <<"k">>), + wait(io:read("")). + +main([]) -> + test_util:init_code_path(), + do_tests(). diff --git a/test/etap/173-os-daemon-cfg-register.t b/test/etap/173-os-daemon-cfg-register.t new file mode 100755 index 00000000..3ee2969a --- /dev/null +++ b/test/etap/173-os-daemon-cfg-register.t @@ -0,0 +1,98 @@ +#!/usr/bin/env escript +%% -*- erlang -*- + +% 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. + +-record(daemon, { + port, + name, + cmd, + kill, + status=running, + cfg_patterns=[], + errors=[], + buf=[] +}). + +config_files() -> + lists:map(fun test_util:build_file/1, [ + "etc/couchdb/default_dev.ini" + ]). + +daemon_name() -> + "wheee". + +daemon_cmd() -> + test_util:source_file("test/etap/173-os-daemon-cfg-register.es"). + +main(_) -> + test_util:init_code_path(), + + etap:plan(27), + case (catch test()) of + ok -> + etap:end_tests(); + Other -> + etap:diag(io_lib:format("Test died abnormally: ~p", [Other])), + etap:bail(Other) + end, + ok. + +test() -> + couch_config:start_link(config_files()), + couch_os_daemons:start_link(), + + DaemonCmd = daemon_cmd() ++ " 2> /dev/null", + + etap:diag("Booting the daemon"), + couch_config:set("os_daemons", daemon_name(), DaemonCmd, false), + timer:sleep(1000), + {ok, [D1]} = couch_os_daemons:info([table]), + check_daemon(D1, running), + + etap:diag("Daemon restarts when section changes."), + couch_config:set("s1", "k", "foo", false), + timer:sleep(1000), + {ok, [D2]} = couch_os_daemons:info([table]), + check_daemon(D2, running), + etap:isnt(D2#daemon.kill, D1#daemon.kill, "Kill command shows restart."), + + etap:diag("Daemon doesn't restart for ignored section key."), + couch_config:set("s2", "k2", "baz", false), + timer:sleep(1000), + {ok, [D3]} = couch_os_daemons:info([table]), + etap:is(D3, D2, "Same daemon info after ignored config change."), + + etap:diag("Daemon restarts for specific section/key pairs."), + couch_config:set("s2", "k", "bingo", false), + timer:sleep(1000), + {ok, [D4]} = couch_os_daemons:info([table]), + check_daemon(D4, running), + etap:isnt(D4#daemon.kill, D3#daemon.kill, "Kill command changed again."), + + ok. + +check_daemon(D, Status) -> + BaseName = filename:basename(daemon_cmd()) ++ " 2> /dev/null", + BaseLen = length(BaseName), + CmdLen = length(D#daemon.cmd), + CmdName = lists:sublist(D#daemon.cmd, CmdLen-BaseLen+1, BaseLen), + + etap:is(is_port(D#daemon.port), true, "Daemon port is a port."), + etap:is(D#daemon.name, daemon_name(), "Daemon name was set correctly."), + etap:is(CmdName, BaseName, "Command name was set correctly."), + etap:isnt(D#daemon.kill, undefined, "Kill command was set."), + etap:is(D#daemon.status, Status, "Daemon status is correct."), + etap:is(D#daemon.cfg_patterns, [{"s1"}, {"s2", "k"}], "Cfg patterns set"), + etap:is(D#daemon.errors, [], "No errors have occurred."), + etap:isnt(D#daemon.buf, nil, "Buffer is active."). diff --git a/test/etap/Makefile.am b/test/etap/Makefile.am index bdab95aa..26c214d9 100644 --- a/test/etap/Makefile.am +++ b/test/etap/Makefile.am @@ -66,4 +66,15 @@ EXTRA_DIST = \ 130-attachments-md5.t \ 140-attachment-comp.t \ 150-invalid-view-seq.t \ - 160-vhosts.t + 160-vhosts.t \ + 170-os-daemons.es \ + 170-os-daemons.t \ + 171-os-daemons-config.es \ + 171-os-daemons-config.t \ + 172-os-daemon-errors.1.es \ + 172-os-daemon-errors.2.es \ + 172-os-daemon-errors.3.es \ + 172-os-daemon-errors.4.es \ + 172-os-daemon-errors.t \ + 173-os-daemon-cfg-register.es \ + 173-os-daemon-cfg-register.t -- cgit v1.2.3 From 11469d902b15145d361f9f7ec66a09ac3d04757c Mon Sep 17 00:00:00 2001 From: Paul Joseph Davis Date: Fri, 5 Nov 2010 23:26:21 +0000 Subject: HTTP proxy handler. The second of two new features to replace the _externals protocols. This allows users to configure CouchDB to proxy requests to an external HTTP server. The external HTTP server is not required to be on the same host running CouchDB. The configuration looks like such: [httpd_global_handlers] _google = {couch_httpd_proxy, handle_proxy_req, <<"http://www.google.com">>} You can then hit this proxy at the url: http://127.0.0.1:5984/_google If you add any path after the proxy name, or make a request with a query string, those will be appended to the URL specified in the configuration. Ie: http://127.0.0.1:5984/_google/search?q=plankton would translate to: http://www.google.com/search?q=plankton Obviously, request bodies are handled as expected. git-svn-id: https://svn.apache.org/repos/asf/couchdb/trunk@1031877 13f79535-47bb-0310-9956-ffa450edef68 --- test/etap/180-http-proxy.ini | 20 +++ test/etap/180-http-proxy.t | 357 +++++++++++++++++++++++++++++++++++++++++++ test/etap/Makefile.am | 7 +- test/etap/test_web.erl | 99 ++++++++++++ 4 files changed, 481 insertions(+), 2 deletions(-) create mode 100644 test/etap/180-http-proxy.ini create mode 100644 test/etap/180-http-proxy.t create mode 100644 test/etap/test_web.erl (limited to 'test') diff --git a/test/etap/180-http-proxy.ini b/test/etap/180-http-proxy.ini new file mode 100644 index 00000000..72a63f66 --- /dev/null +++ b/test/etap/180-http-proxy.ini @@ -0,0 +1,20 @@ +; Licensed to the Apache Software Foundation (ASF) under one +; or more contributor license agreements. See the NOTICE file +; distributed with this work for additional information +; regarding copyright ownership. The ASF licenses this file +; to you 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. + +[httpd_global_handlers] +_test = {couch_httpd_proxy, handle_proxy_req, <<"http://127.0.0.1:5985/">>} +_error = {couch_httpd_proxy, handle_proxy_req, <<"http://127.0.0.1:5986/">>} \ No newline at end of file diff --git a/test/etap/180-http-proxy.t b/test/etap/180-http-proxy.t new file mode 100644 index 00000000..b91d901b --- /dev/null +++ b/test/etap/180-http-proxy.t @@ -0,0 +1,357 @@ +#!/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. + +-record(req, {method=get, path="", headers=[], body="", opts=[]}). + +default_config() -> + [ + test_util:build_file("etc/couchdb/default_dev.ini"), + test_util:source_file("test/etap/180-http-proxy.ini") + ]. + +server() -> "http://127.0.0.1:5984/_test/". +proxy() -> "http://127.0.0.1:5985/". +external() -> "https://www.google.com/". + +main(_) -> + test_util:init_code_path(), + + etap:plan(61), + case (catch test()) of + ok -> + etap:end_tests(); + Other -> + etap:diag("Test died abnormally: ~p", [Other]), + etap:bail("Bad return value.") + end, + ok. + +check_request(Name, Req, Remote, Local) -> + case Remote of + no_remote -> ok; + _ -> test_web:set_assert(Remote) + end, + Url = case proplists:lookup(url, Req#req.opts) of + none -> server() ++ Req#req.path; + {url, DestUrl} -> DestUrl + end, + Opts = [{headers_as_is, true} | Req#req.opts], + Resp =ibrowse:send_req( + Url, Req#req.headers, Req#req.method, Req#req.body, Opts + ), + %etap:diag("ibrowse response: ~p", [Resp]), + case Local of + no_local -> ok; + _ -> etap:fun_is(Local, Resp, Name) + end, + case {Remote, Local} of + {no_remote, _} -> + ok; + {_, no_local} -> + ok; + _ -> + etap:is(test_web:check_last(), was_ok, Name ++ " - request handled") + end, + Resp. + +test() -> + couch_server_sup:start_link(default_config()), + ibrowse:start(), + crypto:start(), + test_web:start_link(), + + test_basic(), + test_alternate_status(), + test_trailing_slash(), + test_passes_header(), + test_passes_host_header(), + test_passes_header_back(), + test_rewrites_location_headers(), + test_doesnt_rewrite_external_locations(), + test_rewrites_relative_location(), + test_uses_same_version(), + test_passes_body(), + test_passes_eof_body_back(), + test_passes_chunked_body(), + test_passes_chunked_body_back(), + + test_connect_error(), + + ok. + +test_basic() -> + Remote = fun(Req) -> + 'GET' = Req:get(method), + "/" = Req:get(path), + undefined = Req:get(body_length), + undefined = Req:recv_body(), + {ok, {200, [{"Content-Type", "text/plain"}], "ok"}} + end, + Local = fun({ok, "200", _, "ok"}) -> true; (_) -> false end, + check_request("Basic proxy test", #req{}, Remote, Local). + +test_alternate_status() -> + Remote = fun(Req) -> + "/alternate_status" = Req:get(path), + {ok, {201, [], "ok"}} + end, + Local = fun({ok, "201", _, "ok"}) -> true; (_) -> false end, + Req = #req{path="alternate_status"}, + check_request("Alternate status", Req, Remote, Local). + +test_trailing_slash() -> + Remote = fun(Req) -> + "/trailing_slash/" = Req:get(path), + {ok, {200, [], "ok"}} + end, + Local = fun({ok, "200", _, "ok"}) -> true; (_) -> false end, + Req = #req{path="trailing_slash/"}, + check_request("Trailing slash", Req, Remote, Local). + +test_passes_header() -> + Remote = fun(Req) -> + "/passes_header" = Req:get(path), + "plankton" = Req:get_header_value("X-CouchDB-Ralph"), + {ok, {200, [], "ok"}} + end, + Local = fun({ok, "200", _, "ok"}) -> true; (_) -> false end, + Req = #req{ + path="passes_header", + headers=[{"X-CouchDB-Ralph", "plankton"}] + }, + check_request("Passes header", Req, Remote, Local). + +test_passes_host_header() -> + Remote = fun(Req) -> + "/passes_host_header" = Req:get(path), + "www.google.com" = Req:get_header_value("Host"), + {ok, {200, [], "ok"}} + end, + Local = fun({ok, "200", _, "ok"}) -> true; (_) -> false end, + Req = #req{ + path="passes_host_header", + headers=[{"Host", "www.google.com"}] + }, + check_request("Passes host header", Req, Remote, Local). + +test_passes_header_back() -> + Remote = fun(Req) -> + "/passes_header_back" = Req:get(path), + {ok, {200, [{"X-CouchDB-Plankton", "ralph"}], "ok"}} + end, + Local = fun + ({ok, "200", Headers, "ok"}) -> + lists:member({"X-CouchDB-Plankton", "ralph"}, Headers); + (_) -> + false + end, + Req = #req{path="passes_header_back"}, + check_request("Passes header back", Req, Remote, Local). + +test_rewrites_location_headers() -> + etap:diag("Testing location header rewrites."), + do_rewrite_tests([ + {"Location", proxy() ++ "foo/bar", server() ++ "foo/bar"}, + {"Content-Location", proxy() ++ "bing?q=2", server() ++ "bing?q=2"}, + {"Uri", proxy() ++ "zip#frag", server() ++ "zip#frag"}, + {"Destination", proxy(), server()} + ]). + +test_doesnt_rewrite_external_locations() -> + etap:diag("Testing no rewrite of external locations."), + do_rewrite_tests([ + {"Location", external() ++ "search", external() ++ "search"}, + {"Content-Location", external() ++ "s?q=2", external() ++ "s?q=2"}, + {"Uri", external() ++ "f#f", external() ++ "f#f"}, + {"Destination", external() ++ "f?q=2#f", external() ++ "f?q=2#f"} + ]). + +test_rewrites_relative_location() -> + etap:diag("Testing relative rewrites."), + do_rewrite_tests([ + {"Location", "/foo", server() ++ "foo"}, + {"Content-Location", "bar", server() ++ "bar"}, + {"Uri", "/zing?q=3", server() ++ "zing?q=3"}, + {"Destination", "bing?q=stuff#yay", server() ++ "bing?q=stuff#yay"} + ]). + +do_rewrite_tests(Tests) -> + lists:foreach(fun({Header, Location, Url}) -> + do_rewrite_test(Header, Location, Url) + end, Tests). + +do_rewrite_test(Header, Location, Url) -> + Remote = fun(Req) -> + "/rewrite_test" = Req:get(path), + {ok, {302, [{Header, Location}], "ok"}} + end, + Local = fun + ({ok, "302", Headers, "ok"}) -> + etap:is( + couch_util:get_value(Header, Headers), + Url, + "Header rewritten correctly." + ), + true; + (_) -> + false + end, + Req = #req{path="rewrite_test"}, + Label = "Rewrite test for ", + check_request(Label ++ Header, Req, Remote, Local). + +test_uses_same_version() -> + Remote = fun(Req) -> + "/uses_same_version" = Req:get(path), + {1, 0} = Req:get(version), + {ok, {200, [], "ok"}} + end, + Local = fun({ok, "200", _, "ok"}) -> true; (_) -> false end, + Req = #req{ + path="uses_same_version", + opts=[{http_vsn, {1, 0}}] + }, + check_request("Uses same version", Req, Remote, Local). + +test_passes_body() -> + Remote = fun(Req) -> + 'PUT' = Req:get(method), + "/passes_body" = Req:get(path), + <<"Hooray!">> = Req:recv_body(), + {ok, {201, [], "ok"}} + end, + Local = fun({ok, "201", _, "ok"}) -> true; (_) -> false end, + Req = #req{ + method=put, + path="passes_body", + body="Hooray!" + }, + check_request("Passes body", Req, Remote, Local). + +test_passes_eof_body_back() -> + BodyChunks = [<<"foo">>, <<"bar">>, <<"bazinga">>], + Remote = fun(Req) -> + 'GET' = Req:get(method), + "/passes_eof_body" = Req:get(path), + {raw, {200, [{"Connection", "close"}], BodyChunks}} + end, + Local = fun({ok, "200", _, "foobarbazinga"}) -> true; (_) -> false end, + Req = #req{path="passes_eof_body"}, + check_request("Passes eof body", Req, Remote, Local). + +test_passes_chunked_body() -> + BodyChunks = [<<"foo">>, <<"bar">>, <<"bazinga">>], + Remote = fun(Req) -> + 'POST' = Req:get(method), + "/passes_chunked_body" = Req:get(path), + RecvBody = fun + ({Length, Chunk}, [Chunk | Rest]) -> + Length = size(Chunk), + Rest; + ({0, []}, []) -> + ok + end, + ok = Req:stream_body(1024*1024, RecvBody, BodyChunks), + {ok, {201, [], "ok"}} + end, + Local = fun({ok, "201", _, "ok"}) -> true; (_) -> false end, + Req = #req{ + method=post, + path="passes_chunked_body", + headers=[{"Transfer-Encoding", "chunked"}], + body=mk_chunked_body(BodyChunks) + }, + check_request("Passes chunked body", Req, Remote, Local). + +test_passes_chunked_body_back() -> + Name = "Passes chunked body back", + Remote = fun(Req) -> + 'GET' = Req:get(method), + "/passes_chunked_body_back" = Req:get(path), + BodyChunks = [<<"foo">>, <<"bar">>, <<"bazinga">>], + {chunked, {200, [{"Transfer-Encoding", "chunked"}], BodyChunks}} + end, + Req = #req{ + path="passes_chunked_body_back", + opts=[{stream_to, self()}] + }, + + Resp = check_request(Name, Req, Remote, no_local), + + etap:fun_is( + fun({ibrowse_req_id, _}) -> true; (_) -> false end, + Resp, + "Received an ibrowse request id." + ), + {_, ReqId} = Resp, + + % Grab headers from response + receive + {ibrowse_async_headers, ReqId, "200", Headers} -> + etap:is( + proplists:get_value("Transfer-Encoding", Headers), + "chunked", + "Response included the Transfer-Encoding: chunked header" + ), + ibrowse:stream_next(ReqId) + after 1000 -> + throw({error, timeout}) + end, + + % Check body received + % TODO: When we upgrade to ibrowse >= 2.0.0 this check needs to + % check that the chunks returned are what we sent from the + % Remote test. + etap:diag("TODO: UPGRADE IBROWSE"), + etap:is(recv_body(ReqId, []), <<"foobarbazinga">>, "Decoded chunked body."), + + % Check test_web server. + etap:is(test_web:check_last(), was_ok, Name ++ " - request handled"). + +test_connect_error() -> + Local = fun({ok, "500", _Headers, _Body}) -> true; (_) -> false end, + Req = #req{opts=[{url, "http://127.0.0.1:5984/_error"}]}, + check_request("Connect error", Req, no_remote, Local). + + +mk_chunked_body(Chunks) -> + mk_chunked_body(Chunks, []). + +mk_chunked_body([], Acc) -> + iolist_to_binary(lists:reverse(Acc, "0\r\n\r\n")); +mk_chunked_body([Chunk | Rest], Acc) -> + Size = to_hex(size(Chunk)), + mk_chunked_body(Rest, ["\r\n", Chunk, "\r\n", Size | Acc]). + +to_hex(Val) -> + to_hex(Val, []). + +to_hex(0, Acc) -> + Acc; +to_hex(Val, Acc) -> + to_hex(Val div 16, [hex_char(Val rem 16) | Acc]). + +hex_char(V) when V < 10 -> $0 + V; +hex_char(V) -> $A + V - 10. + +recv_body(ReqId, Acc) -> + receive + {ibrowse_async_response, ReqId, Data} -> + recv_body(ReqId, [Data | Acc]); + {ibrowse_async_response_end, ReqId} -> + iolist_to_binary(lists:reverse(Acc)); + Else -> + throw({error, unexpected_mesg, Else}) + after 5000 -> + throw({error, timeout}) + end. diff --git a/test/etap/Makefile.am b/test/etap/Makefile.am index 26c214d9..59d21cda 100644 --- a/test/etap/Makefile.am +++ b/test/etap/Makefile.am @@ -11,7 +11,7 @@ ## the License. noinst_SCRIPTS = run -noinst_DATA = test_util.beam +noinst_DATA = test_util.beam test_web.beam %.beam: %.erl $(ERLC) $< @@ -27,6 +27,7 @@ DISTCLEANFILES = temp.* EXTRA_DIST = \ run.tpl \ + test_web.erl \ 001-load.t \ 002-icu-driver.t \ 010-file-basics.t \ @@ -77,4 +78,6 @@ EXTRA_DIST = \ 172-os-daemon-errors.4.es \ 172-os-daemon-errors.t \ 173-os-daemon-cfg-register.es \ - 173-os-daemon-cfg-register.t + 173-os-daemon-cfg-register.t \ + 180-http-proxy.ini \ + 180-http-proxy.t diff --git a/test/etap/test_web.erl b/test/etap/test_web.erl new file mode 100644 index 00000000..16438b31 --- /dev/null +++ b/test/etap/test_web.erl @@ -0,0 +1,99 @@ +% 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. + +-module(test_web). +-behaviour(gen_server). + +-export([start_link/0, loop/1, get_port/0, set_assert/1, check_last/0]). +-export([init/1, terminate/2, code_change/3]). +-export([handle_call/3, handle_cast/2, handle_info/2]). + +-define(SERVER, test_web_server). +-define(HANDLER, test_web_handler). + +start_link() -> + gen_server:start({local, ?HANDLER}, ?MODULE, [], []), + mochiweb_http:start([ + {name, ?SERVER}, + {loop, {?MODULE, loop}}, + {port, 5985} + ]). + +loop(Req) -> + %etap:diag("Handling request: ~p", [Req]), + case gen_server:call(?HANDLER, {check_request, Req}) of + {ok, RespInfo} -> + {ok, Req:respond(RespInfo)}; + {raw, {Status, Headers, BodyChunks}} -> + Resp = Req:start_response({Status, Headers}), + lists:foreach(fun(C) -> Resp:send(C) end, BodyChunks), + erlang:put(mochiweb_request_force_close, true), + {ok, Resp}; + {chunked, {Status, Headers, BodyChunks}} -> + Resp = Req:respond({Status, Headers, chunked}), + timer:sleep(500), + lists:foreach(fun(C) -> Resp:write_chunk(C) end, BodyChunks), + Resp:write_chunk([]), + {ok, Resp}; + {error, Reason} -> + etap:diag("Error: ~p", [Reason]), + Body = lists:flatten(io_lib:format("Error: ~p", [Reason])), + {ok, Req:respond({200, [], Body})} + end. + +get_port() -> + mochiweb_socket_server:get(?SERVER, port). + +set_assert(Fun) -> + ok = gen_server:call(?HANDLER, {set_assert, Fun}). + +check_last() -> + gen_server:call(?HANDLER, last_status). + +init(_) -> + {ok, nil}. + +terminate(_Reason, _State) -> + ok. + +handle_call({check_request, Req}, _From, State) when is_function(State, 1) -> + Resp2 = case (catch State(Req)) of + {ok, Resp} -> {reply, {ok, Resp}, was_ok}; + {raw, Resp} -> {reply, {raw, Resp}, was_ok}; + {chunked, Resp} -> {reply, {chunked, Resp}, was_ok}; + Error -> {reply, {error, Error}, not_ok} + end, + Req:cleanup(), + Resp2; +handle_call({check_request, _Req}, _From, _State) -> + {reply, {error, no_assert_function}, not_ok}; +handle_call(last_status, _From, State) when is_atom(State) -> + {reply, State, nil}; +handle_call(last_status, _From, State) -> + {reply, {error, not_checked}, State}; +handle_call({set_assert, Fun}, _From, nil) -> + {reply, ok, Fun}; +handle_call({set_assert, _}, _From, State) -> + {reply, {error, assert_function_set}, State}; +handle_call(Msg, _From, State) -> + {reply, {ignored, Msg}, State}. + +handle_cast(Msg, State) -> + etap:diag("Ignoring cast message: ~p", [Msg]), + {noreply, State}. + +handle_info(Msg, State) -> + etap:diag("Ignoring info message: ~p", [Msg]), + {noreply, State}. + +code_change(_OldVsn, State, _Extra) -> + {ok, State}. -- cgit v1.2.3 From 96aee7d6b6a94040787d935dc14d4ebda6981dcf Mon Sep 17 00:00:00 2001 From: Paul Joseph Davis Date: Fri, 5 Nov 2010 23:59:14 +0000 Subject: Don't choke on unknown configuration settings. git-svn-id: https://svn.apache.org/repos/asf/couchdb/trunk@1031884 13f79535-47bb-0310-9956-ffa450edef68 --- test/etap/171-os-daemons-config.es | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'test') diff --git a/test/etap/171-os-daemons-config.es b/test/etap/171-os-daemons-config.es index 96e051a3..1f68ddc6 100755 --- a/test/etap/171-os-daemons-config.es +++ b/test/etap/171-os-daemons-config.es @@ -50,6 +50,10 @@ test_get_cfg2() -> FileName = get_cfg(<<"os_daemons">>, <<"foo">>), <<"sequential">> = get_cfg(<<"uuids">>, <<"algorithm">>). +test_get_unknown_cfg() -> + {[]} = get_cfg(<<"aal;3p4">>), + null = get_cfg(<<"aal;3p4">>, <<"313234kjhsdfl">>). + test_log() -> log(<<"foobar!">>), log(<<"some stuff!">>, <<"debug">>), @@ -63,6 +67,7 @@ test_log() -> do_tests() -> test_get_cfg1(), test_get_cfg2(), + test_get_unknown_cfg(), test_log(), loop(io:read("")). -- cgit v1.2.3 From c4542b989a27f7883316a94fc75aaf8a69529732 Mon Sep 17 00:00:00 2001 From: Paul Joseph Davis Date: Sat, 6 Nov 2010 00:15:54 +0000 Subject: Fix executable status. I must've tried to set svn:executable before doing an svn add. git-svn-id: https://svn.apache.org/repos/asf/couchdb/trunk@1031888 13f79535-47bb-0310-9956-ffa450edef68 --- test/etap/180-http-proxy.t | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 test/etap/180-http-proxy.t (limited to 'test') diff --git a/test/etap/180-http-proxy.t b/test/etap/180-http-proxy.t old mode 100644 new mode 100755 -- cgit v1.2.3 From 93eb31323d932e57b73973a12b5ccf42d1b1b8b1 Mon Sep 17 00:00:00 2001 From: Paul Joseph Davis Date: Mon, 8 Nov 2010 16:52:37 +0000 Subject: Fixed a couple typos. git-svn-id: https://svn.apache.org/repos/asf/couchdb/trunk@1032637 13f79535-47bb-0310-9956-ffa450edef68 --- test/etap/021-btree-reductions.t | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'test') diff --git a/test/etap/021-btree-reductions.t b/test/etap/021-btree-reductions.t index 3e19c767..331e49af 100755 --- a/test/etap/021-btree-reductions.t +++ b/test/etap/021-btree-reductions.t @@ -106,7 +106,7 @@ test()-> (_) -> false end, couch_btree:fold_reduce(Btree2, FoldFun, [], [{dir, fwd}, {key_group_fun, GroupFun}, {start_key, SK1}, {end_key, EK1}]), - "Reducing foward over first half works with a startkey and endkey." + "Reducing forward over first half works with a startkey and endkey." ), etap:fun_is( @@ -115,7 +115,7 @@ test()-> (_) -> false end, couch_btree:fold_reduce(Btree2, FoldFun, [], [{dir, fwd}, {key_group_fun, GroupFun}, {start_key, SK2}, {end_key, EK2}]), - "Reducing foward over second half works with second startkey and endkey" + "Reducing forward over second half works with second startkey and endkey" ), etap:fun_is( -- cgit v1.2.3 From 4c6355483d3e97971a97a9a3935263ecf47f7ca8 Mon Sep 17 00:00:00 2001 From: Filipe David Borba Manana Date: Mon, 8 Nov 2010 19:22:01 +0000 Subject: =?UTF-8?q?Preserve=20attachment=20identity=20length=20when=20doin?= =?UTF-8?q?g=20local=20to=20local=20replications.=20Closes=20COUCHDB-930.?= =?UTF-8?q?=20Patch=20by=20Juuso=20V=C3=A4=C3=A4n=C3=A4nen.=20Thanks.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit git-svn-id: https://svn.apache.org/repos/asf/couchdb/trunk@1032673 13f79535-47bb-0310-9956-ffa450edef68 --- test/etap/113-replication-attachment-comp.t | 46 ++++++++++++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) (limited to 'test') diff --git a/test/etap/113-replication-attachment-comp.t b/test/etap/113-replication-attachment-comp.t index 30f602ef..19c48fc6 100755 --- a/test/etap/113-replication-attachment-comp.t +++ b/test/etap/113-replication-attachment-comp.t @@ -30,7 +30,7 @@ test_db_b_name() -> main(_) -> test_util:init_code_path(), - etap:plan(30), + etap:plan(45), case (catch test()) of ok -> etap:end_tests(); @@ -102,6 +102,33 @@ test() -> check_server_can_decompress_att(test_db_b_name()), check_att_stubs(test_db_a_name(), test_db_b_name()), + % + % test local replication + % + + delete_db(test_db_a_name()), + delete_db(test_db_b_name()), + create_db(test_db_a_name()), + create_db(test_db_b_name()), + + % enable compression + couch_config:set("attachments", "compression_level", "8"), + couch_config:set("attachments", "compressible_types", "text/*"), + + % store doc with text attachment in DB A + put_text_att(test_db_a_name()), + + % disable attachment compression + couch_config:set("attachments", "compression_level", "0"), + + % do local-local replication + do_local_replication(test_db_a_name(), test_db_b_name()), + + % verify that DB B has the attachment stored in compressed form + check_att_is_compressed(test_db_b_name()), + check_server_can_decompress_att(test_db_b_name()), + check_att_stubs(test_db_a_name(), test_db_b_name()), + timer:sleep(3000), % to avoid mochiweb socket closed exceptions delete_db(test_db_a_name()), delete_db(test_db_b_name()), @@ -152,6 +179,23 @@ do_push_replication(SourceDbName, TargetDbName) -> etap:is(RepOk, true, "Push replication completed with success"), ok. +do_local_replication(SourceDbName, TargetDbName) -> + RepObj = {[ + {<<"source">>, SourceDbName}, + {<<"target">>, TargetDbName} + ]}, + {ok, {{_, Code, _}, _Headers, Body}} = http:request( + post, + {rep_url(), [], + "application/json", list_to_binary(couch_util:json_encode(RepObj))}, + [], + [{sync, true}]), + etap:is(Code, 200, "Local replication successfully triggered"), + Json = couch_util:json_decode(Body), + RepOk = couch_util:get_nested_json_value(Json, [<<"ok">>]), + etap:is(RepOk, true, "Local replication completed with success"), + ok. + check_att_is_compressed(DbName) -> {ok, {{_, Code, _}, Headers, Body}} = http:request( get, -- cgit v1.2.3 From 67bf92e65483a1ee5cab5cb0b735bb215c2e6e78 Mon Sep 17 00:00:00 2001 From: Filipe David Borba Manana Date: Thu, 11 Nov 2010 00:59:40 +0000 Subject: Micro optimization: when reading an iolist, read up to 8Kbs instead of the 4 bytes length prefix only in the first file read operation. For reads of small terms/iolist (up to 8Kbs), this speeds up the whole operation. No impact on larger terms/iolists. git-svn-id: https://svn.apache.org/repos/asf/couchdb/trunk@1033790 13f79535-47bb-0310-9956-ffa450edef68 --- test/etap/010-file-basics.t | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'test') diff --git a/test/etap/010-file-basics.t b/test/etap/010-file-basics.t index a3599f1a..ed71f5e8 100755 --- a/test/etap/010-file-basics.t +++ b/test/etap/010-file-basics.t @@ -84,7 +84,8 @@ test() -> % append_binary == append_iolist? % Possible bug in pread_iolist or iolist() -> append_binary {ok, IOLPos} = couch_file:append_binary(Fd, ["foo", $m, <<"bam">>]), - etap:is({ok, [<<"foombam">>]}, couch_file:pread_iolist(Fd, IOLPos), + {ok, IoList} = couch_file:pread_iolist(Fd, IOLPos), + etap:is(<<"foombam">>, iolist_to_binary(IoList), "Reading an results in a binary form of the written iolist()"), % XXX: How does on test fsync? -- cgit v1.2.3 From 0fdfbaedfa757f4f5f3fdf550c6ded9d5a46c464 Mon Sep 17 00:00:00 2001 From: Filipe David Borba Manana Date: Fri, 12 Nov 2010 20:17:03 +0000 Subject: Proper verification of the request's accepted media types. Uses the new function mochiweb_request:accepts_content_type/1. git-svn-id: https://svn.apache.org/repos/asf/couchdb/trunk@1034554 13f79535-47bb-0310-9956-ffa450edef68 --- test/etap/140-attachment-comp.t | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'test') diff --git a/test/etap/140-attachment-comp.t b/test/etap/140-attachment-comp.t index 98d37abc..1a90bf0b 100755 --- a/test/etap/140-attachment-comp.t +++ b/test/etap/140-attachment-comp.t @@ -301,7 +301,8 @@ test_get_1st_png_att_with_accept_encoding_deflate() -> test_get_doc_with_1st_text_att() -> {ok, {{_, Code, _}, _Headers, Body}} = http:request( get, - {db_url() ++ "/testdoc1?attachments=true", []}, + {db_url() ++ "/testdoc1?attachments=true", + [{"Accept", "application/json"}]}, [], [{sync, true}]), etap:is(Code, 200, "HTTP response code is 200"), @@ -367,7 +368,8 @@ test_1st_text_att_stub() -> test_get_doc_with_1st_png_att() -> {ok, {{_, Code, _}, _Headers, Body}} = http:request( get, - {db_url() ++ "/testdoc2?attachments=true", []}, + {db_url() ++ "/testdoc2?attachments=true", + [{"Accept", "application/json"}]}, [], [{sync, true}]), etap:is(Code, 200, "HTTP response code is 200"), @@ -492,7 +494,8 @@ test_get_2nd_png_att_with_accept_encoding_gzip() -> test_get_doc_with_2nd_text_att() -> {ok, {{_, Code, _}, _Headers, Body}} = http:request( get, - {db_url() ++ "/testdoc3?attachments=true", []}, + {db_url() ++ "/testdoc3?attachments=true", + [{"Accept", "application/json"}]}, [], [{sync, true}]), etap:is(Code, 200, "HTTP response code is 200"), @@ -554,7 +557,8 @@ test_2nd_text_att_stub() -> test_get_doc_with_2nd_png_att() -> {ok, {{_, Code, _}, _Headers, Body}} = http:request( get, - {db_url() ++ "/testdoc4?attachments=true", []}, + {db_url() ++ "/testdoc4?attachments=true", + [{"Accept", "application/json"}]}, [], [{sync, true}]), etap:is(Code, 200, "HTTP response code is 200"), -- cgit v1.2.3 From 1074767a6b2a254fc6abcb08ec8ccc156e5aa6e9 Mon Sep 17 00:00:00 2001 From: Filipe David Borba Manana Date: Fri, 19 Nov 2010 01:38:41 +0000 Subject: Make sure that after a local database compaction the old database reference counters don't get unreleased forever because of a continuous (or long) replication is going on. Same type of issue as in COUCHDB-926. Thanks Adam Kocoloski for some suggestions. git-svn-id: https://svn.apache.org/repos/asf/couchdb/trunk@1036705 13f79535-47bb-0310-9956-ffa450edef68 --- test/etap/112-replication-missing-revs.t | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) (limited to 'test') diff --git a/test/etap/112-replication-missing-revs.t b/test/etap/112-replication-missing-revs.t index 750334b9..71971088 100755 --- a/test/etap/112-replication-missing-revs.t +++ b/test/etap/112-replication-missing-revs.t @@ -188,8 +188,21 @@ start_changes_feed(remote, Since, Continuous) -> Db = #http_db{url = "http://127.0.0.1:5984/etap-test-source/"}, couch_rep_changes_feed:start_link(self(), Db, Since, Props). +couch_rep_pid(Db) -> + spawn(fun() -> couch_rep_pid_loop(Db) end). + +couch_rep_pid_loop(Db) -> + receive + {'$gen_call', From, get_target_db} -> + gen_server:reply(From, {ok, Db}) + end, + couch_rep_pid_loop(Db). + start_missing_revs(local, Changes) -> - couch_rep_missing_revs:start_link(self(), get_db(target), Changes, []); + TargetDb = get_db(target), + MainPid = couch_rep_pid(TargetDb), + couch_rep_missing_revs:start_link(MainPid, TargetDb, Changes, []); start_missing_revs(remote, Changes) -> - Db = #http_db{url = "http://127.0.0.1:5984/etap-test-target/"}, - couch_rep_missing_revs:start_link(self(), Db, Changes, []). + TargetDb = #http_db{url = "http://127.0.0.1:5984/etap-test-target/"}, + MainPid = couch_rep_pid(TargetDb), + couch_rep_missing_revs:start_link(MainPid, TargetDb, Changes, []). -- cgit v1.2.3 From eb3d803e24e3b9f09a037c48cbac15a356067772 Mon Sep 17 00:00:00 2001 From: Adam Kocoloski Date: Wed, 8 Dec 2010 15:48:46 +0000 Subject: Prefer values from old tree when merging, COUCHDB-968 This commit represents a substantial refactor of the key tree merging logic, some of which is not strictly necessary for the resolution of COUCHDB-968. Two etap test cases checking the ability to merge in a non-linear tree are removed because the functionality is no longer supported. CouchDB only ever merged a linear revision history into an existing revision tree. git-svn-id: https://svn.apache.org/repos/asf/couchdb/branches/1.1.x@1043460 13f79535-47bb-0310-9956-ffa450edef68 --- test/etap/060-kt-merging.t | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) (limited to 'test') diff --git a/test/etap/060-kt-merging.t b/test/etap/060-kt-merging.t index d6b13d6d..73744e52 100755 --- a/test/etap/060-kt-merging.t +++ b/test/etap/060-kt-merging.t @@ -15,7 +15,7 @@ main(_) -> test_util:init_code_path(), - etap:plan(16), + etap:plan(14), case (catch test()) of ok -> etap:end_tests(); @@ -88,24 +88,12 @@ test() -> "Merging a tree with a stem." ), - etap:is( - {TwoChildSibs, no_conflicts}, - couch_key_tree:merge(Stemmed1b, TwoChildSibs), - "Merging in the opposite direction." - ), - etap:is( {TwoChildSibs2, no_conflicts}, couch_key_tree:merge(TwoChildSibs2, Stemmed1bb), "Merging a stem at a deeper level." ), - etap:is( - {TwoChildSibs2, no_conflicts}, - couch_key_tree:merge(Stemmed1bb, TwoChildSibs2), - "Merging a deeper level in opposite order." - ), - etap:is( {TwoChild, no_conflicts}, couch_key_tree:merge(TwoChild, Stemmed1aa), -- cgit v1.2.3 From 9dfee1dbbd7f6cbb255094db860f836c79ace274 Mon Sep 17 00:00:00 2001 From: Adam Kocoloski Date: Wed, 8 Dec 2010 15:48:59 +0000 Subject: Change key_tree merge to take path as 2nd arg, add type specs git-svn-id: https://svn.apache.org/repos/asf/couchdb/branches/1.1.x@1043462 13f79535-47bb-0310-9956-ffa450edef68 --- test/etap/060-kt-merging.t | 81 +++++++++++++++++++--------------------------- 1 file changed, 34 insertions(+), 47 deletions(-) (limited to 'test') diff --git a/test/etap/060-kt-merging.t b/test/etap/060-kt-merging.t index 73744e52..5a8571ac 100755 --- a/test/etap/060-kt-merging.t +++ b/test/etap/060-kt-merging.t @@ -15,7 +15,7 @@ main(_) -> test_util:init_code_path(), - etap:plan(14), + etap:plan(12), case (catch test()) of ok -> etap:end_tests(); @@ -26,101 +26,88 @@ main(_) -> ok. test() -> - EmptyTree = [], - One = [{0, {"1","foo",[]}}], + One = {0, {"1","foo",[]}}, TwoSibs = [{0, {"1","foo",[]}}, {0, {"2","foo",[]}}], - OneChild = [{0, {"1","foo",[{"1a", "bar", []}]}}], - TwoChild = [{0, {"1","foo", [{"1a", "bar", [{"1aa", "bar", []}]}]}}], - TwoChildSibs = [{0, {"1","foo", [{"1a", "bar", []}, - {"1b", "bar", []}]}}], - TwoChildSibs2 = [{0, {"1","foo", [{"1a", "bar", []}, - {"1b", "bar", [{"1bb", "boo", []}]}]}}], - Stemmed1b = [{1, {"1a", "bar", []}}], - Stemmed1a = [{1, {"1a", "bar", [{"1aa", "bar", []}]}}], - Stemmed1aa = [{2, {"1aa", "bar", []}}], - Stemmed1bb = [{2, {"1bb", "boo", []}}], + OneChild = {0, {"1","foo",[{"1a", "bar", []}]}}, + TwoChild = {0, {"1","foo", [{"1a", "bar", [{"1aa", "bar", []}]}]}}, + TwoChildSibs = {0, {"1","foo", [{"1a", "bar", []}, + {"1b", "bar", []}]}}, + TwoChildSibs2 = {0, {"1","foo", [{"1a", "bar", []}, + {"1b", "bar", [{"1bb", "boo", []}]}]}}, + Stemmed1b = {1, {"1a", "bar", []}}, + Stemmed1a = {1, {"1a", "bar", [{"1aa", "bar", []}]}}, + Stemmed1aa = {2, {"1aa", "bar", []}}, + Stemmed1bb = {2, {"1bb", "boo", []}}, etap:is( - {EmptyTree, no_conflicts}, - couch_key_tree:merge(EmptyTree, EmptyTree), - "Merging two empty trees yields an empty tree." - ), - - etap:is( - {One, no_conflicts}, - couch_key_tree:merge(EmptyTree, One), + {[One], no_conflicts}, + couch_key_tree:merge([], One), "The empty tree is the identity for merge." ), - etap:is( - {One, no_conflicts}, - couch_key_tree:merge(One, EmptyTree), - "Merging is commutative." - ), - etap:is( {TwoSibs, no_conflicts}, - couch_key_tree:merge(One, TwoSibs), + couch_key_tree:merge(TwoSibs, One), "Merging a prefix of a tree with the tree yields the tree." ), etap:is( - {One, no_conflicts}, - couch_key_tree:merge(One, One), + {[One], no_conflicts}, + couch_key_tree:merge([One], One), "Merging is reflexive." ), etap:is( - {TwoChild, no_conflicts}, - couch_key_tree:merge(TwoChild, TwoChild), + {[TwoChild], no_conflicts}, + couch_key_tree:merge([TwoChild], TwoChild), "Merging two children is still reflexive." ), etap:is( - {TwoChildSibs, no_conflicts}, - couch_key_tree:merge(TwoChildSibs, TwoChildSibs), + {[TwoChildSibs], no_conflicts}, + couch_key_tree:merge([TwoChildSibs], TwoChildSibs), "Merging a tree to itself is itself."), etap:is( - {TwoChildSibs, no_conflicts}, - couch_key_tree:merge(TwoChildSibs, Stemmed1b), + {[TwoChildSibs], no_conflicts}, + couch_key_tree:merge([TwoChildSibs], Stemmed1b), "Merging a tree with a stem." ), etap:is( - {TwoChildSibs2, no_conflicts}, - couch_key_tree:merge(TwoChildSibs2, Stemmed1bb), + {[TwoChildSibs2], no_conflicts}, + couch_key_tree:merge([TwoChildSibs2], Stemmed1bb), "Merging a stem at a deeper level." ), etap:is( - {TwoChild, no_conflicts}, - couch_key_tree:merge(TwoChild, Stemmed1aa), + {[TwoChild], no_conflicts}, + couch_key_tree:merge([TwoChild], Stemmed1aa), "Merging a single tree with a deeper stem." ), etap:is( - {TwoChild, no_conflicts}, - couch_key_tree:merge(TwoChild, Stemmed1a), + {[TwoChild], no_conflicts}, + couch_key_tree:merge([TwoChild], Stemmed1a), "Merging a larger stem." ), etap:is( - {Stemmed1a, no_conflicts}, - couch_key_tree:merge(Stemmed1a, Stemmed1aa), + {[Stemmed1a], no_conflicts}, + couch_key_tree:merge([Stemmed1a], Stemmed1aa), "More merging." ), - Expect1 = OneChild ++ Stemmed1aa, + Expect1 = [OneChild, Stemmed1aa], etap:is( {Expect1, conflicts}, - couch_key_tree:merge(OneChild, Stemmed1aa), + couch_key_tree:merge([OneChild], Stemmed1aa), "Merging should create conflicts." ), etap:is( - {TwoChild, no_conflicts}, + {[TwoChild], no_conflicts}, couch_key_tree:merge(Expect1, TwoChild), "Merge should have no conflicts." ), -- cgit v1.2.3 From 0067f2e76ddcb1143d17de73fee878f68286aaae Mon Sep 17 00:00:00 2001 From: Filipe David Borba Manana Date: Wed, 22 Dec 2010 19:08:23 +0000 Subject: Merged revision 1052031 from trunk: Make sure attachments get compressed when their MIME type lists parameters Closes COUCHDB-996. git-svn-id: https://svn.apache.org/repos/asf/couchdb/branches/1.1.x@1052032 13f79535-47bb-0310-9956-ffa450edef68 --- test/etap/140-attachment-comp.t | 54 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 53 insertions(+), 1 deletion(-) (limited to 'test') diff --git a/test/etap/140-attachment-comp.t b/test/etap/140-attachment-comp.t index 1a90bf0b..21922f99 100755 --- a/test/etap/140-attachment-comp.t +++ b/test/etap/140-attachment-comp.t @@ -22,7 +22,7 @@ test_db_name() -> main(_) -> test_util:init_code_path(), - etap:plan(78), + etap:plan(86), case (catch test()) of ok -> etap:end_tests(); @@ -75,6 +75,8 @@ test() -> "compress" ), + test_compressible_type_with_parameters(), + timer:sleep(3000), % to avoid mochiweb socket closed exceptions couch_server:delete(test_db_name(), []), couch_server_sup:stop(), @@ -702,6 +704,56 @@ test_create_already_compressed_att_with_invalid_content_encoding( ), ok. +test_compressible_type_with_parameters() -> + {ok, {{_, Code, _}, _Headers, _Body}} = http:request( + put, + {db_url() ++ "/testdoc5/readme.txt", [], + "text/plain; charset=UTF-8", test_text_data()}, + [], + [{sync, true}]), + etap:is(Code, 201, "Created text attachment with MIME type " + "'text/plain; charset=UTF-8' using the standalone api"), + {ok, {{_, Code2, _}, Headers2, Body}} = http:request( + get, + {db_url() ++ "/testdoc5/readme.txt", [{"Accept-Encoding", "gzip"}]}, + [], + [{sync, true}]), + etap:is(Code2, 200, "HTTP response code is 200"), + Gziped = lists:member({"content-encoding", "gzip"}, Headers2), + etap:is(Gziped, true, "received body is gziped"), + Uncompressed = binary_to_list(zlib:gunzip(list_to_binary(Body))), + etap:is(Uncompressed, test_text_data(), "received data is gzipped"), + {ok, {{_, Code3, _}, _Headers3, Body3}} = http:request( + get, + {db_url() ++ "/testdoc5?att_encoding_info=true", []}, + [], + [{sync, true}]), + etap:is(Code3, 200, "HTTP response code is 200"), + Json = couch_util:json_decode(Body3), + {TextAttJson} = couch_util:get_nested_json_value( + Json, + [<<"_attachments">>, <<"readme.txt">>] + ), + TextAttLength = couch_util:get_value(<<"length">>, TextAttJson), + etap:is( + TextAttLength, + length(test_text_data()), + "text attachment stub length matches the uncompressed length" + ), + TextAttEncoding = couch_util:get_value(<<"encoding">>, TextAttJson), + etap:is( + TextAttEncoding, + <<"gzip">>, + "text attachment stub has the encoding field set to gzip" + ), + TextAttEncLength = couch_util:get_value(<<"encoded_length">>, TextAttJson), + etap:is( + TextAttEncLength, + iolist_size(zlib:gzip(test_text_data())), + "text attachment stub encoded_length matches the compressed length" + ), + ok. + test_png_data() -> {ok, Data} = file:read_file( test_util:source_file("share/www/image/logo.png") -- cgit v1.2.3 From 3c71d543dd863a4b34a779a6b05de1f10b57a3a0 Mon Sep 17 00:00:00 2001 From: Adam Kocoloski Date: Wed, 29 Dec 2010 03:01:01 +0000 Subject: Skip recursive path merging, COUCHDB-968 This patch ensures that we only ever merge a linear path into the tree. It relies on the stemming code to collapse paths that could have been merged together by a recursive use of merge_one. git-svn-id: https://svn.apache.org/repos/asf/couchdb/branches/1.1.x@1053512 13f79535-47bb-0310-9956-ffa450edef68 --- test/etap/060-kt-merging.t | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'test') diff --git a/test/etap/060-kt-merging.t b/test/etap/060-kt-merging.t index 5a8571ac..971e49bf 100755 --- a/test/etap/060-kt-merging.t +++ b/test/etap/060-kt-merging.t @@ -15,7 +15,7 @@ main(_) -> test_util:init_code_path(), - etap:plan(12), + etap:plan(14), case (catch test()) of ok -> etap:end_tests(); @@ -106,10 +106,13 @@ test() -> "Merging should create conflicts." ), + {MultiPaths, NoConflicts} = couch_key_tree:merge(Expect1, TwoChild), + etap:is(NoConflicts, no_conflicts, "Merge should have no conflicts."), + etap:is(length(MultiPaths), 2, "Should have two paths before stemming."), etap:is( - {[TwoChild], no_conflicts}, - couch_key_tree:merge(Expect1, TwoChild), - "Merge should have no conflicts." + couch_key_tree:stem(MultiPaths, 10), + [TwoChild], + "Stemming should collapse the paths." ), ok. -- cgit v1.2.3 From 538848259b9d80ccfca5ddb515ebc491f0489c56 Mon Sep 17 00:00:00 2001 From: Adam Kocoloski Date: Wed, 29 Dec 2010 03:01:12 +0000 Subject: Stem revision trees after merging a path, COUCHDB-968 git-svn-id: https://svn.apache.org/repos/asf/couchdb/branches/1.1.x@1053513 13f79535-47bb-0310-9956-ffa450edef68 --- test/etap/060-kt-merging.t | 33 +++++++++++++++------------------ 1 file changed, 15 insertions(+), 18 deletions(-) (limited to 'test') diff --git a/test/etap/060-kt-merging.t b/test/etap/060-kt-merging.t index 971e49bf..0e481a52 100755 --- a/test/etap/060-kt-merging.t +++ b/test/etap/060-kt-merging.t @@ -15,7 +15,7 @@ main(_) -> test_util:init_code_path(), - etap:plan(14), + etap:plan(12), case (catch test()) of ok -> etap:end_tests(); @@ -42,77 +42,74 @@ test() -> etap:is( {[One], no_conflicts}, - couch_key_tree:merge([], One), + couch_key_tree:merge([], One, 10), "The empty tree is the identity for merge." ), etap:is( {TwoSibs, no_conflicts}, - couch_key_tree:merge(TwoSibs, One), + couch_key_tree:merge(TwoSibs, One, 10), "Merging a prefix of a tree with the tree yields the tree." ), etap:is( {[One], no_conflicts}, - couch_key_tree:merge([One], One), + couch_key_tree:merge([One], One, 10), "Merging is reflexive." ), etap:is( {[TwoChild], no_conflicts}, - couch_key_tree:merge([TwoChild], TwoChild), + couch_key_tree:merge([TwoChild], TwoChild, 10), "Merging two children is still reflexive." ), etap:is( {[TwoChildSibs], no_conflicts}, - couch_key_tree:merge([TwoChildSibs], TwoChildSibs), + couch_key_tree:merge([TwoChildSibs], TwoChildSibs, 10), "Merging a tree to itself is itself."), etap:is( {[TwoChildSibs], no_conflicts}, - couch_key_tree:merge([TwoChildSibs], Stemmed1b), + couch_key_tree:merge([TwoChildSibs], Stemmed1b, 10), "Merging a tree with a stem." ), etap:is( {[TwoChildSibs2], no_conflicts}, - couch_key_tree:merge([TwoChildSibs2], Stemmed1bb), + couch_key_tree:merge([TwoChildSibs2], Stemmed1bb, 10), "Merging a stem at a deeper level." ), etap:is( {[TwoChild], no_conflicts}, - couch_key_tree:merge([TwoChild], Stemmed1aa), + couch_key_tree:merge([TwoChild], Stemmed1aa, 10), "Merging a single tree with a deeper stem." ), etap:is( {[TwoChild], no_conflicts}, - couch_key_tree:merge([TwoChild], Stemmed1a), + couch_key_tree:merge([TwoChild], Stemmed1a, 10), "Merging a larger stem." ), etap:is( {[Stemmed1a], no_conflicts}, - couch_key_tree:merge([Stemmed1a], Stemmed1aa), + couch_key_tree:merge([Stemmed1a], Stemmed1aa, 10), "More merging." ), Expect1 = [OneChild, Stemmed1aa], etap:is( {Expect1, conflicts}, - couch_key_tree:merge([OneChild], Stemmed1aa), + couch_key_tree:merge([OneChild], Stemmed1aa, 10), "Merging should create conflicts." ), - {MultiPaths, NoConflicts} = couch_key_tree:merge(Expect1, TwoChild), - etap:is(NoConflicts, no_conflicts, "Merge should have no conflicts."), - etap:is(length(MultiPaths), 2, "Should have two paths before stemming."), etap:is( - couch_key_tree:stem(MultiPaths, 10), - [TwoChild], - "Stemming should collapse the paths." + {[TwoChild], no_conflicts}, + couch_key_tree:merge(Expect1, TwoChild, 10), + "Merge should have no conflicts." ), ok. -- cgit v1.2.3 From 883819bb3069837791cccd08d38f146a0eae4948 Mon Sep 17 00:00:00 2001 From: Adam Kocoloski Date: Wed, 29 Dec 2010 03:01:17 +0000 Subject: Fix 180-http-proxy tests after Mochiweb upgrade. Content-Length and the HTTP body are returned as 0 and an empty binary instead of undefined. git-svn-id: https://svn.apache.org/repos/asf/couchdb/branches/1.1.x@1053514 13f79535-47bb-0310-9956-ffa450edef68 --- test/etap/180-http-proxy.t | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'test') diff --git a/test/etap/180-http-proxy.t b/test/etap/180-http-proxy.t index b91d901b..cf1c2783 100755 --- a/test/etap/180-http-proxy.t +++ b/test/etap/180-http-proxy.t @@ -93,8 +93,8 @@ test_basic() -> Remote = fun(Req) -> 'GET' = Req:get(method), "/" = Req:get(path), - undefined = Req:get(body_length), - undefined = Req:recv_body(), + 0 = Req:get(body_length), + <<>> = Req:recv_body(), {ok, {200, [{"Content-Type", "text/plain"}], "ok"}} end, Local = fun({ok, "200", _, "ok"}) -> true; (_) -> false end, -- cgit v1.2.3 From f8c7e2a63e6244a209c9db34b332c276c8bee8de Mon Sep 17 00:00:00 2001 From: Adam Kocoloski Date: Wed, 2 Feb 2011 19:11:28 +0000 Subject: Make server listen on an unused port during unit tests This prevents the tests from failing when another instance of CouchDB is already running on the same machine. Also merging in the fixup of the _error resource from r1066590. COUCHDB-1049 git-svn-id: https://svn.apache.org/repos/asf/couchdb/branches/1.1.x@1066591 13f79535-47bb-0310-9956-ffa450edef68 --- test/etap/030-doc-from-json.t | 5 +--- test/etap/031-doc-to-json.t | 5 +--- test/etap/070-couch-db.t | 4 +-- test/etap/110-replication-httpc.t | 14 ++++------ test/etap/111-replication-changes-feed.t | 15 +++++----- test/etap/112-replication-missing-revs.t | 12 ++++++-- test/etap/113-replication-attachment-comp.t | 7 ++--- test/etap/130-attachments-md5.t | 8 ++---- test/etap/140-attachment-comp.t | 7 ++--- test/etap/150-invalid-view-seq.t | 10 +++---- test/etap/160-vhosts.t | 17 ++++++------ test/etap/173-os-daemon-cfg-register.t | 7 +---- test/etap/180-http-proxy.ini | 4 +-- test/etap/180-http-proxy.t | 43 +++++++++++++++++++++-------- test/etap/random_port.ini | 19 +++++++++++++ test/etap/test_util.erl.in | 8 +++++- test/etap/test_web.erl | 2 +- 17 files changed, 106 insertions(+), 81 deletions(-) create mode 100644 test/etap/random_port.ini (limited to 'test') diff --git a/test/etap/030-doc-from-json.t b/test/etap/030-doc-from-json.t index c4ef649a..1090fc38 100755 --- a/test/etap/030-doc-from-json.t +++ b/test/etap/030-doc-from-json.t @@ -20,9 +20,6 @@ -record(att, {name, type, att_len, disk_len, md5= <<>>, revpos=0, data, encoding=identity}). -default_config() -> - test_util:build_file("etc/couchdb/default_dev.ini"). - main(_) -> test_util:init_code_path(), etap:plan(26), @@ -36,7 +33,7 @@ main(_) -> ok. test() -> - couch_config:start_link([default_config()]), + couch_config:start_link(test_util:config_files()), couch_config:set("attachments", "compression_level", "0"), ok = test_from_json_success(), ok = test_from_json_errors(), diff --git a/test/etap/031-doc-to-json.t b/test/etap/031-doc-to-json.t index 605a6d00..4deeb0f2 100755 --- a/test/etap/031-doc-to-json.t +++ b/test/etap/031-doc-to-json.t @@ -20,9 +20,6 @@ -record(att, {name, type, att_len, disk_len, md5= <<>>, revpos=0, data, encoding=identity}). -default_config() -> - test_util:build_file("etc/couchdb/default_dev.ini"). - main(_) -> test_util:init_code_path(), etap:plan(12), @@ -36,7 +33,7 @@ main(_) -> ok. test() -> - couch_config:start_link([default_config()]), + couch_config:start_link(test_util:config_files()), couch_config:set("attachments", "compression_level", "0"), ok = test_to_json_success(), ok. diff --git a/test/etap/070-couch-db.t b/test/etap/070-couch-db.t index 4b14aba6..787d6c6a 100755 --- a/test/etap/070-couch-db.t +++ b/test/etap/070-couch-db.t @@ -28,9 +28,7 @@ main(_) -> test() -> - couch_server_sup:start_link( - ["etc/couchdb/default_dev.ini", "etc/couchdb/local_dev.ini"] - ), + couch_server_sup:start_link(test_util:config_files()), couch_db:create(<<"etap-test-db">>, []), {ok, AllDbs} = couch_server:all_databases(), diff --git a/test/etap/110-replication-httpc.t b/test/etap/110-replication-httpc.t index 529239c5..39b0755e 100755 --- a/test/etap/110-replication-httpc.t +++ b/test/etap/110-replication-httpc.t @@ -35,15 +35,13 @@ conn = nil }). -server() -> "http://127.0.0.1:5984/". -dbname() -> "etap-test-db". - -config_files() -> - lists:map(fun test_util:build_file/1, [ - "etc/couchdb/default_dev.ini", - "etc/couchdb/local_dev.ini" +server() -> + lists:concat([ + "http://127.0.0.1:", mochiweb_socket_server:get(couch_httpd, port), "/" ]). +dbname() -> "etap-test-db". + main(_) -> test_util:init_code_path(), @@ -58,7 +56,7 @@ main(_) -> ok. test() -> - couch_server_sup:start_link(config_files()), + couch_server_sup:start_link(test_util:config_files()), ibrowse:start(), crypto:start(), diff --git a/test/etap/111-replication-changes-feed.t b/test/etap/111-replication-changes-feed.t index 778b99dd..358bf1e2 100755 --- a/test/etap/111-replication-changes-feed.t +++ b/test/etap/111-replication-changes-feed.t @@ -38,12 +38,6 @@ conn = nil }). -config_files() -> - lists:map(fun test_util:build_file/1, [ - "etc/couchdb/default_dev.ini", - "etc/couchdb/local_dev.ini" - ]). - main(_) -> test_util:init_code_path(), @@ -58,7 +52,7 @@ main(_) -> ok. test() -> - couch_server_sup:start_link(config_files()), + couch_server_sup:start_link(test_util:config_files()), ibrowse:start(), crypto:start(), @@ -237,7 +231,12 @@ get_db() -> get_dbname(local) -> "etap-test-db"; get_dbname(remote) -> - "http://127.0.0.1:5984/etap-test-db/". + server() ++ "etap-test-db/". + +server() -> + lists:concat([ + "http://127.0.0.1:", mochiweb_socket_server:get(couch_httpd, port), "/" + ]). get_update_seq() -> Db = get_db(), diff --git a/test/etap/112-replication-missing-revs.t b/test/etap/112-replication-missing-revs.t index 71971088..ebaa05ed 100755 --- a/test/etap/112-replication-missing-revs.t +++ b/test/etap/112-replication-missing-revs.t @@ -42,7 +42,8 @@ config_files() -> lists:map(fun test_util:build_file/1, [ "etc/couchdb/default_dev.ini", - "etc/couchdb/local_dev.ini" + "etc/couchdb/local_dev.ini", + "test/etap/random_port.ini" ]). main(_) -> @@ -185,9 +186,14 @@ start_changes_feed(local, Since, Continuous) -> couch_rep_changes_feed:start_link(self(), get_db(source), Since, Props); start_changes_feed(remote, Since, Continuous) -> Props = [{<<"continuous">>, Continuous}], - Db = #http_db{url = "http://127.0.0.1:5984/etap-test-source/"}, + Db = #http_db{url = server() ++ "etap-test-source/"}, couch_rep_changes_feed:start_link(self(), Db, Since, Props). +server() -> + lists:concat([ + "http://127.0.0.1:", mochiweb_socket_server:get(couch_httpd, port), "/" + ]). + couch_rep_pid(Db) -> spawn(fun() -> couch_rep_pid_loop(Db) end). @@ -203,6 +209,6 @@ start_missing_revs(local, Changes) -> MainPid = couch_rep_pid(TargetDb), couch_rep_missing_revs:start_link(MainPid, TargetDb, Changes, []); start_missing_revs(remote, Changes) -> - TargetDb = #http_db{url = "http://127.0.0.1:5984/etap-test-target/"}, + TargetDb = #http_db{url = server() ++ "etap-test-target/"}, MainPid = couch_rep_pid(TargetDb), couch_rep_missing_revs:start_link(MainPid, TargetDb, Changes, []). diff --git a/test/etap/113-replication-attachment-comp.t b/test/etap/113-replication-attachment-comp.t index 19c48fc6..1f2b63f2 100755 --- a/test/etap/113-replication-attachment-comp.t +++ b/test/etap/113-replication-attachment-comp.t @@ -19,9 +19,6 @@ handler }). -default_config() -> - test_util:build_file("etc/couchdb/default_dev.ini"). - test_db_a_name() -> <<"couch_test_rep_att_comp_a">>. @@ -41,9 +38,9 @@ main(_) -> ok. test() -> - couch_server_sup:start_link([default_config()]), + couch_server_sup:start_link(test_util:config_files()), put(addr, couch_config:get("httpd", "bind_address", "127.0.0.1")), - put(port, couch_config:get("httpd", "port", "5984")), + put(port, integer_to_list(mochiweb_socket_server:get(couch_httpd, port))), application:start(inets), ibrowse:start(), timer:sleep(1000), diff --git a/test/etap/130-attachments-md5.t b/test/etap/130-attachments-md5.t index 4c40f83a..6296e08a 100755 --- a/test/etap/130-attachments-md5.t +++ b/test/etap/130-attachments-md5.t @@ -11,9 +11,6 @@ % License for the specific language governing permissions and limitations under % the License. -default_config() -> - test_util:build_file("etc/couchdb/default_dev.ini"). - test_db_name() -> <<"etap-test-db">>. @@ -41,11 +38,10 @@ main(_) -> ok. test() -> - couch_server_sup:start_link([default_config()]), + couch_server_sup:start_link(test_util:config_files()), Addr = couch_config:get("httpd", "bind_address", any), - Port = list_to_integer(couch_config:get("httpd", "port", "5984")), put(addr, Addr), - put(port, Port), + put(port, mochiweb_socket_server:get(couch_httpd, port)), timer:sleep(1000), couch_server:delete(test_db_name(), []), diff --git a/test/etap/140-attachment-comp.t b/test/etap/140-attachment-comp.t index 21922f99..bf1b21c4 100755 --- a/test/etap/140-attachment-comp.t +++ b/test/etap/140-attachment-comp.t @@ -13,9 +13,6 @@ % License for the specific language governing permissions and limitations under % the License. -default_config() -> - test_util:build_file("etc/couchdb/default_dev.ini"). - test_db_name() -> <<"couch_test_atts_compression">>. @@ -33,9 +30,9 @@ main(_) -> ok. test() -> - couch_server_sup:start_link([default_config()]), + couch_server_sup:start_link(test_util:config_files()), put(addr, couch_config:get("httpd", "bind_address", "127.0.0.1")), - put(port, couch_config:get("httpd", "port", "5984")), + put(port, integer_to_list(mochiweb_socket_server:get(couch_httpd, port))), application:start(inets), timer:sleep(1000), couch_server:delete(test_db_name(), []), diff --git a/test/etap/150-invalid-view-seq.t b/test/etap/150-invalid-view-seq.t index 0664c116..594d3416 100755 --- a/test/etap/150-invalid-view-seq.t +++ b/test/etap/150-invalid-view-seq.t @@ -19,9 +19,6 @@ handler }). -default_config() -> - test_util:build_file("etc/couchdb/default_dev.ini"). - test_db_name() -> <<"couch_test_invalid_view_seq">>. @@ -42,7 +39,7 @@ main(_) -> %% a huge and ugly but harmless stack trace is sent to stderr %% test() -> - couch_server_sup:start_link([default_config()]), + couch_server_sup:start_link(test_util:config_files()), timer:sleep(1000), delete_db(), create_db(), @@ -54,7 +51,7 @@ test() -> backup_db_file(), put(addr, couch_config:get("httpd", "bind_address", "127.0.0.1")), - put(port, couch_config:get("httpd", "port", "5984")), + put(port, integer_to_list(mochiweb_socket_server:get(couch_httpd, port))), application:start(inets), create_new_doc(), @@ -168,8 +165,9 @@ restore_backup_db_file() -> binary_to_list(test_db_name()) ++ ".couch"), ok = file:delete(DbFile), ok = file:rename(DbFile ++ ".backup", DbFile), - couch_server_sup:start_link([default_config()]), + couch_server_sup:start_link(test_util:config_files()), timer:sleep(1000), + put(port, integer_to_list(mochiweb_socket_server:get(couch_httpd, port))), ok. query_view_after_restore_backup() -> diff --git a/test/etap/160-vhosts.t b/test/etap/160-vhosts.t index f4bd5e27..c7dc8f99 100755 --- a/test/etap/160-vhosts.t +++ b/test/etap/160-vhosts.t @@ -41,16 +41,14 @@ handler }). -server() -> "http://127.0.0.1:5984/". +server() -> + lists:concat([ + "http://127.0.0.1:", mochiweb_socket_server:get(couch_httpd, port), "/" + ]). + dbname() -> "etap-test-db". admin_user_ctx() -> {user_ctx, #user_ctx{roles=[<<"_admin">>]}}. -config_files() -> - lists:map(fun test_util:build_file/1, [ - "etc/couchdb/default_dev.ini", - "etc/couchdb/local_dev.ini" - ]). - main(_) -> test_util:init_code_path(), @@ -65,7 +63,7 @@ main(_) -> ok. test() -> - couch_server_sup:start_link(config_files()), + couch_server_sup:start_link(test_util:config_files()), ibrowse:start(), crypto:start(), @@ -118,6 +116,9 @@ test() -> ok = couch_config:set("vhosts", "*/test1", "/etap-test-db/_design/doc1/_show/test", false), + % let couch_httpd restart + timer:sleep(100), + test_regular_request(), test_vhost_request(), test_vhost_request_with_qs(), diff --git a/test/etap/173-os-daemon-cfg-register.t b/test/etap/173-os-daemon-cfg-register.t index 3ee2969a..af9cbaa0 100755 --- a/test/etap/173-os-daemon-cfg-register.t +++ b/test/etap/173-os-daemon-cfg-register.t @@ -24,11 +24,6 @@ buf=[] }). -config_files() -> - lists:map(fun test_util:build_file/1, [ - "etc/couchdb/default_dev.ini" - ]). - daemon_name() -> "wheee". @@ -49,7 +44,7 @@ main(_) -> ok. test() -> - couch_config:start_link(config_files()), + couch_config:start_link(test_util:config_files()), couch_os_daemons:start_link(), DaemonCmd = daemon_cmd() ++ " 2> /dev/null", diff --git a/test/etap/180-http-proxy.ini b/test/etap/180-http-proxy.ini index 72a63f66..3e2ba137 100644 --- a/test/etap/180-http-proxy.ini +++ b/test/etap/180-http-proxy.ini @@ -15,6 +15,6 @@ ; specific language governing permissions and limitations ; under the License. +; 49151 is IANA Reserved, let's assume no one is listening there [httpd_global_handlers] -_test = {couch_httpd_proxy, handle_proxy_req, <<"http://127.0.0.1:5985/">>} -_error = {couch_httpd_proxy, handle_proxy_req, <<"http://127.0.0.1:5986/">>} \ No newline at end of file +_error = {couch_httpd_proxy, handle_proxy_req, <<"http://127.0.0.1:49151/">>} diff --git a/test/etap/180-http-proxy.t b/test/etap/180-http-proxy.t index cf1c2783..3d31b95a 100755 --- a/test/etap/180-http-proxy.t +++ b/test/etap/180-http-proxy.t @@ -13,14 +13,16 @@ -record(req, {method=get, path="", headers=[], body="", opts=[]}). -default_config() -> - [ - test_util:build_file("etc/couchdb/default_dev.ini"), - test_util:source_file("test/etap/180-http-proxy.ini") - ]. - -server() -> "http://127.0.0.1:5984/_test/". -proxy() -> "http://127.0.0.1:5985/". +server() -> + lists:concat([ + "http://127.0.0.1:", + mochiweb_socket_server:get(couch_httpd, port), + "/_test/" + ]). + +proxy() -> + "http://127.0.0.1:" ++ integer_to_list(test_web:get_port()) ++ "/". + external() -> "https://www.google.com/". main(_) -> @@ -65,11 +67,25 @@ check_request(Name, Req, Remote, Local) -> Resp. test() -> - couch_server_sup:start_link(default_config()), + couch_server_sup:start_link([ + test_util:build_file("test/etap/180-http-proxy.ini") | + test_util:config_files() + ]), ibrowse:start(), crypto:start(), + + % start the test_web server on a random port test_web:start_link(), - + Url = lists:concat([ + "{couch_httpd_proxy, handle_proxy_req, <<\"http://127.0.0.1:", + test_web:get_port(), + "/\">>}" + ]), + couch_config:set("httpd_global_handlers", "_test", Url, false), + + % let couch_httpd restart + timer:sleep(100), + test_basic(), test_alternate_status(), test_trailing_slash(), @@ -320,7 +336,12 @@ test_passes_chunked_body_back() -> test_connect_error() -> Local = fun({ok, "500", _Headers, _Body}) -> true; (_) -> false end, - Req = #req{opts=[{url, "http://127.0.0.1:5984/_error"}]}, + Url = lists:concat([ + "http://127.0.0.1:", + mochiweb_socket_server:get(couch_httpd, port), + "/_error" + ]), + Req = #req{opts=[{url, Url}]}, check_request("Connect error", Req, no_remote, Local). diff --git a/test/etap/random_port.ini b/test/etap/random_port.ini new file mode 100644 index 00000000..ada3c13d --- /dev/null +++ b/test/etap/random_port.ini @@ -0,0 +1,19 @@ +; Licensed to the Apache Software Foundation (ASF) under one +; or more contributor license agreements. See the NOTICE file +; distributed with this work for additional information +; regarding copyright ownership. The ASF licenses this file +; to you 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. + +[httpd] +port = 0 diff --git a/test/etap/test_util.erl.in b/test/etap/test_util.erl.in index 4c42edb1..59bbc59a 100644 --- a/test/etap/test_util.erl.in +++ b/test/etap/test_util.erl.in @@ -13,7 +13,7 @@ -module(test_util). -export([init_code_path/0]). --export([source_file/1, build_file/1]). +-export([source_file/1, build_file/1, config_files/0]). srcdir() -> "@abs_top_srcdir@". @@ -33,3 +33,9 @@ source_file(Name) -> build_file(Name) -> filename:join([builddir(), Name]). +config_files() -> + lists:map(fun build_file/1, [ + "etc/couchdb/default_dev.ini", + "etc/couchdb/local_dev.ini", + "test/etap/random_port.ini" + ]). diff --git a/test/etap/test_web.erl b/test/etap/test_web.erl index 16438b31..ed78651f 100644 --- a/test/etap/test_web.erl +++ b/test/etap/test_web.erl @@ -25,7 +25,7 @@ start_link() -> mochiweb_http:start([ {name, ?SERVER}, {loop, {?MODULE, loop}}, - {port, 5985} + {port, 0} ]). loop(Req) -> -- cgit v1.2.3 From 579eadac058a82bcc609fea0473047ba6d90ea7c Mon Sep 17 00:00:00 2001 From: Jan Lehnardt Date: Sat, 26 Mar 2011 21:02:47 +0000 Subject: Prefer local src paths for etap. Closes COUCHDB-1056 Patch by Randall Leeds. git-svn-id: https://svn.apache.org/repos/asf/couchdb/branches/1.1.x@1085801 13f79535-47bb-0310-9956-ffa450edef68 --- test/etap/test_util.erl.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'test') diff --git a/test/etap/test_util.erl.in b/test/etap/test_util.erl.in index 59bbc59a..87b474ae 100644 --- a/test/etap/test_util.erl.in +++ b/test/etap/test_util.erl.in @@ -24,7 +24,7 @@ builddir() -> init_code_path() -> Paths = ["etap", "couchdb", "erlang-oauth", "ibrowse", "mochiweb"], lists:foreach(fun(Name) -> - code:add_pathz(filename:join([builddir(), "src", Name])) + code:add_patha(filename:join([builddir(), "src", Name])) end, Paths). source_file(Name) -> -- cgit v1.2.3 From 76ce001c041d6dfef1117f14a9e1e20f77f9df39 Mon Sep 17 00:00:00 2001 From: Filipe David Borba Manana Date: Tue, 19 Apr 2011 20:38:59 +0000 Subject: Merged revision 1095200 from trunk Don't set Content-Encoding headers with value "identity" This is dictated by RFC 2616 and causes problems with Microsoft's ISA 2006 proxy. Closes COUCHDB-1128. Thanks Paul Davis and Andrew Gleave. git-svn-id: https://svn.apache.org/repos/asf/couchdb/branches/1.1.x@1095204 13f79535-47bb-0310-9956-ffa450edef68 --- test/etap/140-attachment-comp.t | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) (limited to 'test') diff --git a/test/etap/140-attachment-comp.t b/test/etap/140-attachment-comp.t index bf1b21c4..abe98432 100755 --- a/test/etap/140-attachment-comp.t +++ b/test/etap/140-attachment-comp.t @@ -19,7 +19,7 @@ test_db_name() -> main(_) -> test_util:init_code_path(), - etap:plan(86), + etap:plan(85), case (catch test()) of ok -> etap:end_tests(); @@ -254,8 +254,8 @@ test_get_1st_png_att_without_accept_encoding_header() -> [], [{sync, true}]), etap:is(Code, 200, "HTTP response code is 200"), - Gziped = lists:member({"content-encoding", "gzip"}, Headers), - etap:is(Gziped, false, "received body is not gziped"), + Encoding = couch_util:get_value("content-encoding", Headers), + etap:is(Encoding, undefined, "received body is not gziped"), etap:is( Body, test_png_data(), @@ -270,8 +270,8 @@ test_get_1st_png_att_with_accept_encoding_gzip() -> [], [{sync, true}]), etap:is(Code, 200, "HTTP response code is 200"), - Gziped = lists:member({"content-encoding", "gzip"}, Headers), - etap:is(Gziped, false, "received body is not gziped"), + Encoding = couch_util:get_value("content-encoding", Headers), + etap:is(Encoding, undefined, "received body is not gziped"), etap:is( Body, test_png_data(), @@ -286,10 +286,8 @@ test_get_1st_png_att_with_accept_encoding_deflate() -> [], [{sync, true}]), etap:is(Code, 200, "HTTP response code is 200"), - Deflated = lists:member({"content-encoding", "deflate"}, Headers), - etap:is(Deflated, false, "received body is not deflated"), - Gziped = lists:member({"content-encoding", "gzip"}, Headers), - etap:is(Gziped, false, "received body is not gziped"), + Encoding = couch_util:get_value("content-encoding", Headers), + etap:is(Encoding, undefined, "received body is in identity form"), etap:is( Body, test_png_data(), -- cgit v1.2.3 From 6783ea04a1a95bfc36ddecfca3d1be79174413ef Mon Sep 17 00:00:00 2001 From: Paul Joseph Davis Date: Thu, 21 Apr 2011 00:30:04 +0000 Subject: Fix config file paths for etap tests. Partial backport of 1066932 from trunk. git-svn-id: https://svn.apache.org/repos/asf/couchdb/branches/1.1.x@1095576 13f79535-47bb-0310-9956-ffa450edef68 --- test/etap/test_util.erl.in | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'test') diff --git a/test/etap/test_util.erl.in b/test/etap/test_util.erl.in index 87b474ae..460b0293 100644 --- a/test/etap/test_util.erl.in +++ b/test/etap/test_util.erl.in @@ -34,8 +34,9 @@ build_file(Name) -> filename:join([builddir(), Name]). config_files() -> - lists:map(fun build_file/1, [ - "etc/couchdb/default_dev.ini", - "etc/couchdb/local_dev.ini", - "test/etap/random_port.ini" - ]). + [ + build_file("etc/couchdb/default_dev.ini"), + build_file("etc/couchdb/local_dev.ini"), + source_file("test/etap/random_port.ini") + ]. + -- cgit v1.2.3 From d0a0ac2a37d576bbab7aaa92aa05d07e52860d61 Mon Sep 17 00:00:00 2001 From: Paul Joseph Davis Date: Thu, 21 Apr 2011 00:38:12 +0000 Subject: Missing config file in EXTRA_DIST git-svn-id: https://svn.apache.org/repos/asf/couchdb/branches/1.1.x@1095578 13f79535-47bb-0310-9956-ffa450edef68 --- test/etap/Makefile.am | 1 + 1 file changed, 1 insertion(+) (limited to 'test') diff --git a/test/etap/Makefile.am b/test/etap/Makefile.am index 59d21cda..6d7fe12b 100644 --- a/test/etap/Makefile.am +++ b/test/etap/Makefile.am @@ -28,6 +28,7 @@ DISTCLEANFILES = temp.* EXTRA_DIST = \ run.tpl \ test_web.erl \ + random_port.ini \ 001-load.t \ 002-icu-driver.t \ 010-file-basics.t \ -- cgit v1.2.3 From 6f922dd546b5302db50a14e54357fefa73a1b697 Mon Sep 17 00:00:00 2001 From: Paul Joseph Davis Date: Thu, 21 Apr 2011 01:03:48 +0000 Subject: Make local_dev.ini the last file in the config chain. Backport of 1095581 from trunk. git-svn-id: https://svn.apache.org/repos/asf/couchdb/branches/1.1.x@1095582 13f79535-47bb-0310-9956-ffa450edef68 --- test/etap/test_util.erl.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'test') diff --git a/test/etap/test_util.erl.in b/test/etap/test_util.erl.in index 460b0293..b0c97a14 100644 --- a/test/etap/test_util.erl.in +++ b/test/etap/test_util.erl.in @@ -36,7 +36,7 @@ build_file(Name) -> config_files() -> [ build_file("etc/couchdb/default_dev.ini"), - build_file("etc/couchdb/local_dev.ini"), - source_file("test/etap/random_port.ini") + source_file("test/etap/random_port.ini"), + build_file("etc/couchdb/local_dev.ini") ]. -- cgit v1.2.3 From 8ff7a1b5a20c65d8444d06709ac74b0f786c0fe4 Mon Sep 17 00:00:00 2001 From: Paul Joseph Davis Date: Thu, 21 Apr 2011 01:24:38 +0000 Subject: Do not persist config values in etap tests. git-svn-id: https://svn.apache.org/repos/asf/couchdb/branches/1.1.x@1095584 13f79535-47bb-0310-9956-ffa450edef68 --- test/etap/030-doc-from-json.t | 2 +- test/etap/031-doc-to-json.t | 2 +- test/etap/081-config-override.t | 2 +- test/etap/083-config-no-files.t | 2 +- test/etap/113-replication-attachment-comp.t | 18 +++++++++--------- test/etap/140-attachment-comp.t | 4 ++-- 6 files changed, 15 insertions(+), 15 deletions(-) (limited to 'test') diff --git a/test/etap/030-doc-from-json.t b/test/etap/030-doc-from-json.t index 1090fc38..b0c393ef 100755 --- a/test/etap/030-doc-from-json.t +++ b/test/etap/030-doc-from-json.t @@ -34,7 +34,7 @@ main(_) -> test() -> couch_config:start_link(test_util:config_files()), - couch_config:set("attachments", "compression_level", "0"), + couch_config:set("attachments", "compression_level", "0", false), ok = test_from_json_success(), ok = test_from_json_errors(), ok. diff --git a/test/etap/031-doc-to-json.t b/test/etap/031-doc-to-json.t index 4deeb0f2..ce950f95 100755 --- a/test/etap/031-doc-to-json.t +++ b/test/etap/031-doc-to-json.t @@ -34,7 +34,7 @@ main(_) -> test() -> couch_config:start_link(test_util:config_files()), - couch_config:set("attachments", "compression_level", "0"), + couch_config:set("attachments", "compression_level", "0", false), ok = test_to_json_success(), ok. diff --git a/test/etap/081-config-override.t b/test/etap/081-config-override.t index 01f8b4c2..95baa023 100755 --- a/test/etap/081-config-override.t +++ b/test/etap/081-config-override.t @@ -148,7 +148,7 @@ test() -> ), etap:is( - couch_config:set("httpd", "port", "8080"), + couch_config:set("httpd", "port", "8080", false), ok, "Writing {httpd, port} is kosher." ), diff --git a/test/etap/083-config-no-files.t b/test/etap/083-config-no-files.t index 675feb59..bc40ec9d 100755 --- a/test/etap/083-config-no-files.t +++ b/test/etap/083-config-no-files.t @@ -45,7 +45,7 @@ test() -> "Created a new non-persisted k/v pair." ), - ok = couch_config:set("httpd", "bind_address", "127.0.0.1"), + ok = couch_config:set("httpd", "bind_address", "127.0.0.1", false), etap:is( couch_config:get("httpd", "bind_address"), "127.0.0.1", diff --git a/test/etap/113-replication-attachment-comp.t b/test/etap/113-replication-attachment-comp.t index 1f2b63f2..e30a96bc 100755 --- a/test/etap/113-replication-attachment-comp.t +++ b/test/etap/113-replication-attachment-comp.t @@ -55,14 +55,14 @@ test() -> create_db(test_db_b_name()), % enable compression - couch_config:set("attachments", "compression_level", "8"), - couch_config:set("attachments", "compressible_types", "text/*"), + couch_config:set("attachments", "compression_level", "8", false), + couch_config:set("attachments", "compressible_types", "text/*", false), % store doc with text attachment in DB A put_text_att(test_db_a_name()), % disable attachment compression - couch_config:set("attachments", "compression_level", "0"), + couch_config:set("attachments", "compression_level", "0", false), % do pull replication do_pull_replication(test_db_a_name(), test_db_b_name()), @@ -82,14 +82,14 @@ test() -> create_db(test_db_b_name()), % enable compression - couch_config:set("attachments", "compression_level", "8"), - couch_config:set("attachments", "compressible_types", "text/*"), + couch_config:set("attachments", "compression_level", "8", false), + couch_config:set("attachments", "compressible_types", "text/*", false), % store doc with text attachment in DB A put_text_att(test_db_a_name()), % disable attachment compression - couch_config:set("attachments", "compression_level", "0"), + couch_config:set("attachments", "compression_level", "0", false), % do push replication do_push_replication(test_db_a_name(), test_db_b_name()), @@ -109,14 +109,14 @@ test() -> create_db(test_db_b_name()), % enable compression - couch_config:set("attachments", "compression_level", "8"), - couch_config:set("attachments", "compressible_types", "text/*"), + couch_config:set("attachments", "compression_level", "8", false), + couch_config:set("attachments", "compressible_types", "text/*", false), % store doc with text attachment in DB A put_text_att(test_db_a_name()), % disable attachment compression - couch_config:set("attachments", "compression_level", "0"), + couch_config:set("attachments", "compression_level", "0", false), % do local-local replication do_local_replication(test_db_a_name(), test_db_b_name()), diff --git a/test/etap/140-attachment-comp.t b/test/etap/140-attachment-comp.t index abe98432..475f4fb0 100755 --- a/test/etap/140-attachment-comp.t +++ b/test/etap/140-attachment-comp.t @@ -38,8 +38,8 @@ test() -> couch_server:delete(test_db_name(), []), couch_db:create(test_db_name(), []), - couch_config:set("attachments", "compression_level", "8"), - couch_config:set("attachments", "compressible_types", "text/*"), + couch_config:set("attachments", "compression_level", "8", false), + couch_config:set("attachments", "compressible_types", "text/*", false), create_1st_text_att(), create_1st_png_att(), -- cgit v1.2.3 From 9391566c6fa2bcc165f70032f047c905283e0783 Mon Sep 17 00:00:00 2001 From: Paul Joseph Davis Date: Thu, 21 Apr 2011 01:25:07 +0000 Subject: Instead of trying to write values we just don't write values. git-svn-id: https://svn.apache.org/repos/asf/couchdb/branches/1.1.x@1095585 13f79535-47bb-0310-9956-ffa450edef68 --- test/etap/test_util.erl.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'test') diff --git a/test/etap/test_util.erl.in b/test/etap/test_util.erl.in index b0c97a14..460b0293 100644 --- a/test/etap/test_util.erl.in +++ b/test/etap/test_util.erl.in @@ -36,7 +36,7 @@ build_file(Name) -> config_files() -> [ build_file("etc/couchdb/default_dev.ini"), - source_file("test/etap/random_port.ini"), - build_file("etc/couchdb/local_dev.ini") + build_file("etc/couchdb/local_dev.ini"), + source_file("test/etap/random_port.ini") ]. -- cgit v1.2.3 From d277f7173a10910cab990b5b18e7b01bfc5034f2 Mon Sep 17 00:00:00 2001 From: Paul Joseph Davis Date: Thu, 21 Apr 2011 23:04:29 +0000 Subject: More fixes for the build system. git-svn-id: https://svn.apache.org/repos/asf/couchdb/branches/1.1.x@1095842 13f79535-47bb-0310-9956-ffa450edef68 --- test/etap/081-config-override.t | 2 +- test/etap/112-replication-missing-revs.t | 9 +-------- 2 files changed, 2 insertions(+), 9 deletions(-) (limited to 'test') diff --git a/test/etap/081-config-override.t b/test/etap/081-config-override.t index 95baa023..01f8b4c2 100755 --- a/test/etap/081-config-override.t +++ b/test/etap/081-config-override.t @@ -148,7 +148,7 @@ test() -> ), etap:is( - couch_config:set("httpd", "port", "8080", false), + couch_config:set("httpd", "port", "8080"), ok, "Writing {httpd, port} is kosher." ), diff --git a/test/etap/112-replication-missing-revs.t b/test/etap/112-replication-missing-revs.t index ebaa05ed..39280aee 100755 --- a/test/etap/112-replication-missing-revs.t +++ b/test/etap/112-replication-missing-revs.t @@ -39,13 +39,6 @@ conn = nil }). -config_files() -> - lists:map(fun test_util:build_file/1, [ - "etc/couchdb/default_dev.ini", - "etc/couchdb/local_dev.ini", - "test/etap/random_port.ini" - ]). - main(_) -> test_util:init_code_path(), @@ -60,7 +53,7 @@ main(_) -> ok. test() -> - couch_server_sup:start_link(config_files()), + couch_server_sup:start_link(test_util:config_files()), ibrowse:start(), crypto:start(), -- cgit v1.2.3 From d47d7e98819363e31f81a7954fed8bccc5d7d03b Mon Sep 17 00:00:00 2001 From: Paul Joseph Davis Date: Sat, 23 Apr 2011 00:59:25 +0000 Subject: Fix random errors in 173-os-daemon-cfg-register.t This is a backport of 1096098 from trunk. git-svn-id: https://svn.apache.org/repos/asf/couchdb/branches/1.1.x@1096099 13f79535-47bb-0310-9956-ffa450edef68 --- test/etap/173-os-daemon-cfg-register.es | 35 --------------------------------- test/etap/173-os-daemon-cfg-register.t | 2 +- test/etap/Makefile.am | 8 ++++++-- test/etap/test_cfg_register.c | 30 ++++++++++++++++++++++++++++ 4 files changed, 37 insertions(+), 38 deletions(-) delete mode 100755 test/etap/173-os-daemon-cfg-register.es create mode 100644 test/etap/test_cfg_register.c (limited to 'test') diff --git a/test/etap/173-os-daemon-cfg-register.es b/test/etap/173-os-daemon-cfg-register.es deleted file mode 100755 index 3d536dc7..00000000 --- a/test/etap/173-os-daemon-cfg-register.es +++ /dev/null @@ -1,35 +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. - -write(Mesg) -> - Data = iolist_to_binary(couch_util:json_encode(Mesg)), - io:format(binary_to_list(Data) ++ "\n", []). - -cfg_register(Section) -> - write([<<"register">>, Section]). - -cfg_register(Section, Key) -> - write([<<"register">>, Section, Key]). - -wait(_) -> - init:stop(). - -do_tests() -> - cfg_register(<<"s1">>), - cfg_register(<<"s2">>, <<"k">>), - wait(io:read("")). - -main([]) -> - test_util:init_code_path(), - do_tests(). diff --git a/test/etap/173-os-daemon-cfg-register.t b/test/etap/173-os-daemon-cfg-register.t index af9cbaa0..71181aa2 100755 --- a/test/etap/173-os-daemon-cfg-register.t +++ b/test/etap/173-os-daemon-cfg-register.t @@ -28,7 +28,7 @@ daemon_name() -> "wheee". daemon_cmd() -> - test_util:source_file("test/etap/173-os-daemon-cfg-register.es"). + test_util:build_file("test/etap/test_cfg_register"). main(_) -> test_util:init_code_path(), diff --git a/test/etap/Makefile.am b/test/etap/Makefile.am index 6d7fe12b..005b99ee 100644 --- a/test/etap/Makefile.am +++ b/test/etap/Makefile.am @@ -13,6 +13,10 @@ noinst_SCRIPTS = run noinst_DATA = test_util.beam test_web.beam +noinst_PROGRAMS = test_cfg_register +test_cfg_register_SOURCES = test_cfg_register.c +test_cfg_register_CFLAGS = -D_BSD_SOURCE + %.beam: %.erl $(ERLC) $< @@ -78,7 +82,7 @@ EXTRA_DIST = \ 172-os-daemon-errors.3.es \ 172-os-daemon-errors.4.es \ 172-os-daemon-errors.t \ - 173-os-daemon-cfg-register.es \ 173-os-daemon-cfg-register.t \ 180-http-proxy.ini \ - 180-http-proxy.t + 180-http-proxy.t \ + 190-json-stream-parse.t diff --git a/test/etap/test_cfg_register.c b/test/etap/test_cfg_register.c new file mode 100644 index 00000000..7161eb55 --- /dev/null +++ b/test/etap/test_cfg_register.c @@ -0,0 +1,30 @@ +// 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. + +#include + +int +main(int argc, const char * argv[]) +{ + char c = '\0'; + size_t num = 1; + + fprintf(stdout, "[\"register\", \"s1\"]\n"); + fprintf(stdout, "[\"register\", \"s2\", \"k\"]\n"); + fflush(stdout); + + while(c != '\n' && num > 0) { + num = fread(&c, 1, 1, stdin); + } + + exit(0); +} -- cgit v1.2.3 From 50c01724da662759ae87b70b95e17f19f952daec Mon Sep 17 00:00:00 2001 From: Filipe David Borba Manana Date: Sat, 23 Apr 2011 22:20:44 +0000 Subject: Removed test 190-json-stream-parse.t from Makefile.am This test doesn't exist in this branch and was accidently added in revision 1096099. git-svn-id: https://svn.apache.org/repos/asf/couchdb/branches/1.1.x@1096247 13f79535-47bb-0310-9956-ffa450edef68 --- test/etap/Makefile.am | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'test') diff --git a/test/etap/Makefile.am b/test/etap/Makefile.am index 005b99ee..756b8758 100644 --- a/test/etap/Makefile.am +++ b/test/etap/Makefile.am @@ -84,5 +84,4 @@ EXTRA_DIST = \ 172-os-daemon-errors.t \ 173-os-daemon-cfg-register.t \ 180-http-proxy.ini \ - 180-http-proxy.t \ - 190-json-stream-parse.t + 180-http-proxy.t -- cgit v1.2.3 From 97c606ab56cd1590043ad1d4db4e4238d1c8a77c Mon Sep 17 00:00:00 2001 From: Filipe David Borba Manana Date: Sat, 23 Apr 2011 22:58:53 +0000 Subject: Merged revision 1096252 from trunk View groups: only open the databases when needed View groups keep the databases open all the time. This is a problem once the server reaches max_dbs_open open databases, as it prevents the server from closing inactive databases via the LRU system. Closes COUCHDB-1138. git-svn-id: https://svn.apache.org/repos/asf/couchdb/branches/1.1.x@1096253 13f79535-47bb-0310-9956-ffa450edef68 --- test/etap/200-view-group-no-db-leaks.t | 239 +++++++++++++++++++++++++++++++++ test/etap/Makefile.am | 3 +- 2 files changed, 241 insertions(+), 1 deletion(-) create mode 100644 test/etap/200-view-group-no-db-leaks.t (limited to 'test') diff --git a/test/etap/200-view-group-no-db-leaks.t b/test/etap/200-view-group-no-db-leaks.t new file mode 100644 index 00000000..87181d84 --- /dev/null +++ b/test/etap/200-view-group-no-db-leaks.t @@ -0,0 +1,239 @@ +#!/usr/bin/env escript +%% -*- erlang -*- + +% 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. + +-record(user_ctx, { + name = null, + roles = [], + handler +}). + +-define(LATEST_DISK_VERSION, 5). + +-record(db_header, + {disk_version = ?LATEST_DISK_VERSION, + update_seq = 0, + unused = 0, + fulldocinfo_by_id_btree_state = nil, + docinfo_by_seq_btree_state = nil, + local_docs_btree_state = nil, + purge_seq = 0, + purged_docs = nil, + security_ptr = nil, + revs_limit = 1000 +}). + +-record(db, { + main_pid = nil, + update_pid = nil, + compactor_pid = nil, + instance_start_time, % number of microsecs since jan 1 1970 as a binary string + fd, + fd_ref_counter, + header = #db_header{}, + committed_update_seq, + fulldocinfo_by_id_btree, + docinfo_by_seq_btree, + local_docs_btree, + update_seq, + name, + filepath, + validate_doc_funs = [], + security = [], + security_ptr = nil, + user_ctx = #user_ctx{}, + waiting_delayed_commit = nil, + revs_limit = 1000, + fsync_options = [], + is_sys_db = false +}). + +test_db_name() -> <<"couch_test_view_group_db_leaks">>. +ddoc_name() -> <<"foo">>. + +main(_) -> + test_util:init_code_path(), + + etap:plan(13), + case (catch test()) of + ok -> + etap:end_tests(); + Other -> + etap:diag(io_lib:format("Test died abnormally: ~p", [Other])), + etap:bail(Other) + end, + ok. + +test() -> + couch_server_sup:start_link(test_util:config_files()), + timer:sleep(1000), + put(addr, couch_config:get("httpd", "bind_address", "127.0.0.1")), + put(port, integer_to_list(mochiweb_socket_server:get(couch_httpd, port))), + application:start(inets), + + delete_db(), + create_db(), + + create_docs(), + create_design_doc(), + query_view(), + check_db_ref_count(), + + create_new_doc(<<"doc1000">>), + query_view(), + check_db_ref_count(), + + Ref1 = get_db_ref_counter(), + compact_db(), + check_db_ref_count(), + Ref2 = get_db_ref_counter(), + etap:isnt(Ref1, Ref2, "DB ref counter changed"), + etap:is(false, is_process_alive(Ref1), "old DB ref counter is not alive"), + + compact_view_group(), + check_db_ref_count(), + Ref3 = get_db_ref_counter(), + etap:is(Ref3, Ref2, "DB ref counter didn't change"), + + create_new_doc(<<"doc1001">>), + query_view(), + check_db_ref_count(), + + ok = timer:sleep(1000), + delete_db(), + couch_server_sup:stop(), + ok. + +admin_user_ctx() -> + {user_ctx, #user_ctx{roles=[<<"_admin">>]}}. + +create_db() -> + {ok, Db} = couch_db:create(test_db_name(), [admin_user_ctx()]), + ok = couch_db:close(Db). + +delete_db() -> + couch_server:delete(test_db_name(), [admin_user_ctx()]). + +compact_db() -> + {ok, Db} = couch_db:open_int(test_db_name(), []), + ok = couch_db:start_compact(Db), + ok = couch_db:close(Db), + wait_db_compact_done(10). + +wait_db_compact_done(0) -> + etap:is(true, false, "DB compaction didn't finish"); +wait_db_compact_done(N) -> + {ok, Db} = couch_db:open_int(test_db_name(), []), + ok = couch_db:close(Db), + case is_pid(Db#db.compactor_pid) of + false -> + ok; + true -> + ok = timer:sleep(500), + wait_db_compact_done(N - 1) + end. + +compact_view_group() -> + ok = couch_view_compactor:start_compact(test_db_name(), ddoc_name()), + wait_view_compact_done(10). + +wait_view_compact_done(0) -> + etap:is(true, false, "view group compaction didn't finish"); +wait_view_compact_done(N) -> + {ok, {{_, Code, _}, _Headers, Body}} = http:request( + get, + {db_url() ++ "/_design/" ++ binary_to_list(ddoc_name()) ++ "/_info", []}, + [], + [{sync, true}]), + etap:is(Code, 200, "got view group info"), + {Info} = couch_util:json_decode(Body), + {IndexInfo} = couch_util:get_value(<<"view_index">>, Info), + CompactRunning = couch_util:get_value(<<"compact_running">>, IndexInfo), + case CompactRunning of + false -> + ok; + true -> + ok = timer:sleep(500), + wait_view_compact_done(N - 1) + end. + +get_db_ref_counter() -> + {ok, #db{fd_ref_counter = Ref} = Db} = couch_db:open_int(test_db_name(), []), + ok = couch_db:close(Db), + Ref. + +check_db_ref_count() -> + {ok, #db{fd_ref_counter = Ref} = Db} = couch_db:open_int(test_db_name(), []), + ok = couch_db:close(Db), + etap:is(couch_ref_counter:count(Ref), 2, + "DB ref counter is only held by couch_db and couch_db_updater"), + ok. + +create_docs() -> + {ok, Db} = couch_db:open(test_db_name(), [admin_user_ctx()]), + Doc1 = couch_doc:from_json_obj({[ + {<<"_id">>, <<"doc1">>}, + {<<"value">>, 1} + ]}), + Doc2 = couch_doc:from_json_obj({[ + {<<"_id">>, <<"doc2">>}, + {<<"value">>, 2} + + ]}), + Doc3 = couch_doc:from_json_obj({[ + {<<"_id">>, <<"doc3">>}, + {<<"value">>, 3} + ]}), + {ok, _} = couch_db:update_docs(Db, [Doc1, Doc2, Doc3]), + couch_db:ensure_full_commit(Db), + couch_db:close(Db). + +create_design_doc() -> + {ok, Db} = couch_db:open(test_db_name(), [admin_user_ctx()]), + DDoc = couch_doc:from_json_obj({[ + {<<"_id">>, <<"_design/", (ddoc_name())/binary>>}, + {<<"language">>, <<"javascript">>}, + {<<"views">>, {[ + {<<"bar">>, {[ + {<<"map">>, <<"function(doc) { emit(doc._id, null); }">>} + ]}} + ]}} + ]}), + {ok, _} = couch_db:update_docs(Db, [DDoc]), + couch_db:ensure_full_commit(Db), + couch_db:close(Db). + +create_new_doc(Id) -> + {ok, Db} = couch_db:open(test_db_name(), [admin_user_ctx()]), + Doc666 = couch_doc:from_json_obj({[ + {<<"_id">>, Id}, + {<<"value">>, 999} + ]}), + {ok, _} = couch_db:update_docs(Db, [Doc666]), + couch_db:ensure_full_commit(Db), + couch_db:close(Db). + +db_url() -> + "http://" ++ get(addr) ++ ":" ++ get(port) ++ "/" ++ + binary_to_list(test_db_name()). + +query_view() -> + {ok, {{_, Code, _}, _Headers, _Body}} = http:request( + get, + {db_url() ++ "/_design/" ++ binary_to_list(ddoc_name()) ++ + "/_view/bar", []}, + [], + [{sync, true}]), + etap:is(Code, 200, "got view response"), + ok. diff --git a/test/etap/Makefile.am b/test/etap/Makefile.am index 756b8758..9ba3fcfa 100644 --- a/test/etap/Makefile.am +++ b/test/etap/Makefile.am @@ -84,4 +84,5 @@ EXTRA_DIST = \ 172-os-daemon-errors.t \ 173-os-daemon-cfg-register.t \ 180-http-proxy.ini \ - 180-http-proxy.t + 180-http-proxy.t \ + 200-view-group-no-db-leaks.t -- cgit v1.2.3 From b9c5282ea2220e09332c70ad5fbeae4b3be75b76 Mon Sep 17 00:00:00 2001 From: Paul Joseph Davis Date: Sun, 24 Apr 2011 18:04:30 +0000 Subject: Fixed 180 failure in distcheck. VPATH builds are teh awesome. git-svn-id: https://svn.apache.org/repos/asf/couchdb/branches/1.1.x@1096354 13f79535-47bb-0310-9956-ffa450edef68 --- test/etap/180-http-proxy.t | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'test') diff --git a/test/etap/180-http-proxy.t b/test/etap/180-http-proxy.t index 3d31b95a..41c77631 100755 --- a/test/etap/180-http-proxy.t +++ b/test/etap/180-http-proxy.t @@ -68,7 +68,7 @@ check_request(Name, Req, Remote, Local) -> test() -> couch_server_sup:start_link([ - test_util:build_file("test/etap/180-http-proxy.ini") | + test_util:source_file("test/etap/180-http-proxy.ini") | test_util:config_files() ]), ibrowse:start(), -- cgit v1.2.3 From 0e0e8d3375cb4b7ebb1edd25ac9302f6e22e2b93 Mon Sep 17 00:00:00 2001 From: Jan Lehnardt Date: Mon, 25 Apr 2011 23:46:12 +0000 Subject: Fix vhosts for https and fix vhost dependence on sorting of values in the config system which isn't guaranteed. Make vhost test cases more robust. Closes COUCHDB-1103 Source patch by Benoit and tests patch by me. git-svn-id: https://svn.apache.org/repos/asf/couchdb/branches/1.1.x@1096636 13f79535-47bb-0310-9956-ffa450edef68 --- test/etap/160-vhosts.t | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) (limited to 'test') diff --git a/test/etap/160-vhosts.t b/test/etap/160-vhosts.t index c7dc8f99..8dac53e5 100755 --- a/test/etap/160-vhosts.t +++ b/test/etap/160-vhosts.t @@ -155,9 +155,9 @@ test_regular_request() -> test_vhost_request() -> case ibrowse:send_req(server(), [], get, [], [{host_header, "example.com"}]) of {ok, _, _, Body} -> - {[{<<"db_name">>, <<"etap-test-db">>},_,_,_,_,_,_,_,_,_]} - = couch_util:json_decode(Body), - etap:is(true, true, "should return database info"); + {JsonBody} = couch_util:json_decode(Body), + HasDbNameInfo = proplists:is_defined(<<"db_name">>, JsonBody), + etap:is(HasDbNameInfo, true, "should return database info"); _Else -> etap:is(false, true, <<"ibrowse fail">>) end. @@ -222,9 +222,9 @@ test_vhost_request_wildcard()-> test_vhost_request_replace_var() -> case ibrowse:send_req(server(), [], get, [], [{host_header,"etap-test-db.example1.com"}]) of {ok, _, _, Body} -> - {[{<<"db_name">>, <<"etap-test-db">>},_,_,_,_,_,_,_,_,_]} - = couch_util:json_decode(Body), - etap:is(true, true, "should return database info"); + {JsonBody} = couch_util:json_decode(Body), + HasDbNameInfo = proplists:is_defined(<<"db_name">>, JsonBody), + etap:is(HasDbNameInfo, true, "should return database info"); _Else -> etap:is(false, true, <<"ibrowse fail">>) end. @@ -242,9 +242,9 @@ test_vhost_request_replace_var1() -> test_vhost_request_replace_wildcard() -> case ibrowse:send_req(server(), [], get, [], [{host_header,"etap-test-db.example2.com"}]) of {ok, _, _, Body} -> - {[{<<"db_name">>, <<"etap-test-db">>},_,_,_,_,_,_,_,_,_]} - = couch_util:json_decode(Body), - etap:is(true, true, "should return database info"); + {JsonBody} = couch_util:json_decode(Body), + HasDbNameInfo = proplists:is_defined(<<"db_name">>, JsonBody), + etap:is(HasDbNameInfo, true, "should return database info"); _Else -> etap:is(false, true, <<"ibrowse fail">>) end. @@ -252,9 +252,9 @@ test_vhost_request_path() -> Uri = server() ++ "test", case ibrowse:send_req(Uri, [], get, [], [{host_header, "example.com"}]) of {ok, _, _, Body} -> - {[{<<"db_name">>, <<"etap-test-db">>},_,_,_,_,_,_,_,_,_]} - = couch_util:json_decode(Body), - etap:is(true, true, "should return database info"); + {JsonBody} = couch_util:json_decode(Body), + HasDbNameInfo = proplists:is_defined(<<"db_name">>, JsonBody), + etap:is(HasDbNameInfo, true, "should return database info"); _Else -> etap:is(false, true, <<"ibrowse fail">>) end. @@ -272,9 +272,9 @@ test_vhost_request_path2() -> Uri = server() ++ "test", case ibrowse:send_req(Uri, [], get, [], [{host_header,"etap-test-db.example2.com"}]) of {ok, _, _, Body} -> - {[{<<"db_name">>, <<"etap-test-db">>},_,_,_,_,_,_,_,_,_]} - = couch_util:json_decode(Body), - etap:is(true, true, "should return database info"); + {JsonBody} = couch_util:json_decode(Body), + HasDbNameInfo = proplists:is_defined(<<"db_name">>, JsonBody), + etap:is(HasDbNameInfo, true, "should return database info"); _Else -> etap:is(false, true, <<"ibrowse fail">>) end. -- cgit v1.2.3 From 66c6654288a25aa42af274511c87a61ea86ce0e7 Mon Sep 17 00:00:00 2001 From: Jan Lehnardt Date: Thu, 28 Apr 2011 00:13:36 +0000 Subject: make test case executable git-svn-id: https://svn.apache.org/repos/asf/couchdb/branches/1.1.x@1097292 13f79535-47bb-0310-9956-ffa450edef68 --- test/etap/200-view-group-no-db-leaks.t | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 test/etap/200-view-group-no-db-leaks.t (limited to 'test') diff --git a/test/etap/200-view-group-no-db-leaks.t b/test/etap/200-view-group-no-db-leaks.t old mode 100644 new mode 100755 -- cgit v1.2.3 From 742c29989b9f8b10f248596c02ccdd51e13134b1 Mon Sep 17 00:00:00 2001 From: Paul Joseph Davis Date: Thu, 28 Apr 2011 01:04:38 +0000 Subject: Make test count for test/etap/200-*.t deterministic. This is a backport of 1097300 from trunk. git-svn-id: https://svn.apache.org/repos/asf/couchdb/branches/1.1.x@1097301 13f79535-47bb-0310-9956-ffa450edef68 --- test/etap/200-view-group-no-db-leaks.t | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'test') diff --git a/test/etap/200-view-group-no-db-leaks.t b/test/etap/200-view-group-no-db-leaks.t index 87181d84..bbfd0833 100755 --- a/test/etap/200-view-group-no-db-leaks.t +++ b/test/etap/200-view-group-no-db-leaks.t @@ -65,7 +65,7 @@ ddoc_name() -> <<"foo">>. main(_) -> test_util:init_code_path(), - etap:plan(13), + etap:plan(11), case (catch test()) of ok -> etap:end_tests(); @@ -132,7 +132,7 @@ compact_db() -> wait_db_compact_done(10). wait_db_compact_done(0) -> - etap:is(true, false, "DB compaction didn't finish"); + etap:bail("DB compaction failed to finish."); wait_db_compact_done(N) -> {ok, Db} = couch_db:open_int(test_db_name(), []), ok = couch_db:close(Db), @@ -149,14 +149,17 @@ compact_view_group() -> wait_view_compact_done(10). wait_view_compact_done(0) -> - etap:is(true, false, "view group compaction didn't finish"); + etap:bail("View group compaction failed to finish."); wait_view_compact_done(N) -> {ok, {{_, Code, _}, _Headers, Body}} = http:request( get, {db_url() ++ "/_design/" ++ binary_to_list(ddoc_name()) ++ "/_info", []}, [], [{sync, true}]), - etap:is(Code, 200, "got view group info"), + case Code of + 200 -> ok; + _ -> etap:bail("Invalid view group info.") + end, {Info} = couch_util:json_decode(Body), {IndexInfo} = couch_util:get_value(<<"view_index">>, Info), CompactRunning = couch_util:get_value(<<"compact_running">>, IndexInfo), -- cgit v1.2.3 From d5bf524c1dafd301a0fced8449ed90f7608beb72 Mon Sep 17 00:00:00 2001 From: Filipe David Borba Manana Date: Fri, 13 May 2011 11:18:37 +0000 Subject: Merged revision 1102137 from trunk Make sure view group shutdowns when database is deleted or dies Added more assertions to test 200-view-group-no-db-leaks.t to ensure this doesn't happen anymore. git-svn-id: https://svn.apache.org/repos/asf/couchdb/branches/1.1.x@1102678 13f79535-47bb-0310-9956-ffa450edef68 --- test/etap/200-view-group-no-db-leaks.t | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) (limited to 'test') diff --git a/test/etap/200-view-group-no-db-leaks.t b/test/etap/200-view-group-no-db-leaks.t index bbfd0833..9c77f1a8 100755 --- a/test/etap/200-view-group-no-db-leaks.t +++ b/test/etap/200-view-group-no-db-leaks.t @@ -65,7 +65,7 @@ ddoc_name() -> <<"foo">>. main(_) -> test_util:init_code_path(), - etap:plan(11), + etap:plan(18), case (catch test()) of ok -> etap:end_tests(); @@ -87,12 +87,20 @@ test() -> create_docs(), create_design_doc(), + + ViewGroup = couch_view:get_group_server( + test_db_name(), <<"_design/", (ddoc_name())/binary>>), + etap:is(is_pid(ViewGroup), true, "got view group pid"), + etap:is(is_process_alive(ViewGroup), true, "view group pid is alive"), + query_view(), check_db_ref_count(), + etap:is(is_process_alive(ViewGroup), true, "view group pid is alive"), create_new_doc(<<"doc1000">>), query_view(), check_db_ref_count(), + etap:is(is_process_alive(ViewGroup), true, "view group pid is alive"), Ref1 = get_db_ref_counter(), compact_db(), @@ -100,15 +108,27 @@ test() -> Ref2 = get_db_ref_counter(), etap:isnt(Ref1, Ref2, "DB ref counter changed"), etap:is(false, is_process_alive(Ref1), "old DB ref counter is not alive"), + etap:is(is_process_alive(ViewGroup), true, "view group pid is alive"), compact_view_group(), check_db_ref_count(), Ref3 = get_db_ref_counter(), etap:is(Ref3, Ref2, "DB ref counter didn't change"), + etap:is(is_process_alive(ViewGroup), true, "view group pid is alive"), create_new_doc(<<"doc1001">>), query_view(), check_db_ref_count(), + etap:is(is_process_alive(ViewGroup), true, "view group pid is alive"), + + MonRef = erlang:monitor(process, ViewGroup), + ok = couch_server:delete(test_db_name(), []), + receive + {'DOWN', MonRef, _, _, _} -> + etap:diag("view group is dead after DB deletion") + after 5000 -> + etap:bail("view group did not die after DB deletion") + end, ok = timer:sleep(1000), delete_db(), -- cgit v1.2.3 From d618f75fe229d6ca4ebe24822ba498baf80278dc Mon Sep 17 00:00:00 2001 From: Robert Newson Date: Tue, 17 May 2011 20:31:32 +0000 Subject: backport oauth fix - COUCHDB-1144 git-svn-id: https://svn.apache.org/repos/asf/couchdb/branches/1.1.x@1104530 13f79535-47bb-0310-9956-ffa450edef68 --- test/etap/190-oauth.t | 31 +++++++++++++++++++++++++++++++ test/etap/Makefile.am | 1 + 2 files changed, 32 insertions(+) create mode 100755 test/etap/190-oauth.t (limited to 'test') diff --git a/test/etap/190-oauth.t b/test/etap/190-oauth.t new file mode 100755 index 00000000..09922049 --- /dev/null +++ b/test/etap/190-oauth.t @@ -0,0 +1,31 @@ +#!/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. + +main(_) -> + test_util:init_code_path(), + etap:plan(1), + case (catch test()) of + ok -> + etap:end_tests(); + Other -> + etap:diag(io_lib:format("Test died abnormally: ~p", [Other])), + etap:bail(Other) + end, + ok. + +test() -> + etap:is( + oauth_uri:params_from_string("realm=http://localhost:5984"), + [{"realm","http://localhost:5984"}], + "decode should handle non-percent encoded input."), + ok. diff --git a/test/etap/Makefile.am b/test/etap/Makefile.am index 9ba3fcfa..1b14b9e1 100644 --- a/test/etap/Makefile.am +++ b/test/etap/Makefile.am @@ -85,4 +85,5 @@ EXTRA_DIST = \ 173-os-daemon-cfg-register.t \ 180-http-proxy.ini \ 180-http-proxy.t \ + 190-oauth.t \ 200-view-group-no-db-leaks.t -- cgit v1.2.3 From aea9ddf21eedc566afa01892778081425fc131ac Mon Sep 17 00:00:00 2001 From: Paul Joseph Davis Date: Tue, 17 May 2011 23:14:25 +0000 Subject: Backported os daemon tests from trunk. This reduces the chance that these tests fail due to timing differences by avoding booting of an Erlang VM as an os daemon. git-svn-id: https://svn.apache.org/repos/asf/couchdb/branches/1.1.x@1104622 13f79535-47bb-0310-9956-ffa450edef68 --- test/etap/172-os-daemon-errors.1.es | 22 ---------------------- test/etap/172-os-daemon-errors.1.sh | 17 +++++++++++++++++ test/etap/172-os-daemon-errors.2.es | 16 ---------------- test/etap/172-os-daemon-errors.2.sh | 15 +++++++++++++++ test/etap/172-os-daemon-errors.3.es | 17 ----------------- test/etap/172-os-daemon-errors.3.sh | 15 +++++++++++++++ test/etap/172-os-daemon-errors.4.es | 17 ----------------- test/etap/172-os-daemon-errors.4.sh | 15 +++++++++++++++ test/etap/172-os-daemon-errors.t | 8 ++++---- test/etap/Makefile.am | 8 ++++---- 10 files changed, 70 insertions(+), 80 deletions(-) delete mode 100644 test/etap/172-os-daemon-errors.1.es create mode 100644 test/etap/172-os-daemon-errors.1.sh delete mode 100755 test/etap/172-os-daemon-errors.2.es create mode 100755 test/etap/172-os-daemon-errors.2.sh delete mode 100755 test/etap/172-os-daemon-errors.3.es create mode 100755 test/etap/172-os-daemon-errors.3.sh delete mode 100755 test/etap/172-os-daemon-errors.4.es create mode 100755 test/etap/172-os-daemon-errors.4.sh (limited to 'test') diff --git a/test/etap/172-os-daemon-errors.1.es b/test/etap/172-os-daemon-errors.1.es deleted file mode 100644 index a9defba1..00000000 --- a/test/etap/172-os-daemon-errors.1.es +++ /dev/null @@ -1,22 +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. - -% Please do not make this file executable as that's the error being tested. - -loop() -> - timer:sleep(5000), - loop(). - -main([]) -> - loop(). diff --git a/test/etap/172-os-daemon-errors.1.sh b/test/etap/172-os-daemon-errors.1.sh new file mode 100644 index 00000000..345c8b40 --- /dev/null +++ b/test/etap/172-os-daemon-errors.1.sh @@ -0,0 +1,17 @@ +#!/bin/sh -e +# +# 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. +# +# Please do not make this file executable as that's the error being tested. + +sleep 5 diff --git a/test/etap/172-os-daemon-errors.2.es b/test/etap/172-os-daemon-errors.2.es deleted file mode 100755 index 52de0401..00000000 --- a/test/etap/172-os-daemon-errors.2.es +++ /dev/null @@ -1,16 +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. - -main([]) -> - init:stop(). diff --git a/test/etap/172-os-daemon-errors.2.sh b/test/etap/172-os-daemon-errors.2.sh new file mode 100755 index 00000000..256ee793 --- /dev/null +++ b/test/etap/172-os-daemon-errors.2.sh @@ -0,0 +1,15 @@ +#!/bin/sh -e +# +# 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. + +exit 1 diff --git a/test/etap/172-os-daemon-errors.3.es b/test/etap/172-os-daemon-errors.3.es deleted file mode 100755 index 64229800..00000000 --- a/test/etap/172-os-daemon-errors.3.es +++ /dev/null @@ -1,17 +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. - -main([]) -> - timer:sleep(1000), - init:stop(). diff --git a/test/etap/172-os-daemon-errors.3.sh b/test/etap/172-os-daemon-errors.3.sh new file mode 100755 index 00000000..f5a13684 --- /dev/null +++ b/test/etap/172-os-daemon-errors.3.sh @@ -0,0 +1,15 @@ +#!/bin/sh -e +# +# 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. + +sleep 1 diff --git a/test/etap/172-os-daemon-errors.4.es b/test/etap/172-os-daemon-errors.4.es deleted file mode 100755 index 577f3410..00000000 --- a/test/etap/172-os-daemon-errors.4.es +++ /dev/null @@ -1,17 +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. - -main([]) -> - timer:sleep(2000), - init:stop(). diff --git a/test/etap/172-os-daemon-errors.4.sh b/test/etap/172-os-daemon-errors.4.sh new file mode 100755 index 00000000..5bc10e83 --- /dev/null +++ b/test/etap/172-os-daemon-errors.4.sh @@ -0,0 +1,15 @@ +#!/bin/sh -e +# +# 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. + +sleep 2 diff --git a/test/etap/172-os-daemon-errors.t b/test/etap/172-os-daemon-errors.t index 287a0812..bde5c6ff 100755 --- a/test/etap/172-os-daemon-errors.t +++ b/test/etap/172-os-daemon-errors.t @@ -30,16 +30,16 @@ config_files() -> ]). bad_perms() -> - test_util:source_file("test/etap/172-os-daemon-errors.1.es"). + test_util:source_file("test/etap/172-os-daemon-errors.1.sh"). die_on_boot() -> - test_util:source_file("test/etap/172-os-daemon-errors.2.es"). + test_util:source_file("test/etap/172-os-daemon-errors.2.sh"). die_quickly() -> - test_util:source_file("test/etap/172-os-daemon-errors.3.es"). + test_util:source_file("test/etap/172-os-daemon-errors.3.sh"). can_reboot() -> - test_util:source_file("test/etap/172-os-daemon-errors.4.es"). + test_util:source_file("test/etap/172-os-daemon-errors.4.sh"). main(_) -> test_util:init_code_path(), diff --git a/test/etap/Makefile.am b/test/etap/Makefile.am index 1b14b9e1..ce52d430 100644 --- a/test/etap/Makefile.am +++ b/test/etap/Makefile.am @@ -77,10 +77,10 @@ EXTRA_DIST = \ 170-os-daemons.t \ 171-os-daemons-config.es \ 171-os-daemons-config.t \ - 172-os-daemon-errors.1.es \ - 172-os-daemon-errors.2.es \ - 172-os-daemon-errors.3.es \ - 172-os-daemon-errors.4.es \ + 172-os-daemon-errors.1.sh \ + 172-os-daemon-errors.2.sh \ + 172-os-daemon-errors.3.sh \ + 172-os-daemon-errors.4.sh \ 172-os-daemon-errors.t \ 173-os-daemon-cfg-register.t \ 180-http-proxy.ini \ -- cgit v1.2.3 From 218f61ca2844ef4326157c6db958574c29c1ea40 Mon Sep 17 00:00:00 2001 From: Randall Leeds Date: Wed, 8 Jun 2011 18:57:43 +0000 Subject: backport r1133312 from trunk _view_cleanup with no _design docs - COUCHDB-1136 git-svn-id: https://svn.apache.org/repos/asf/couchdb/branches/1.1.x@1133510 13f79535-47bb-0310-9956-ffa450edef68 --- test/etap/072-cleanup.t | 130 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 130 insertions(+) create mode 100755 test/etap/072-cleanup.t (limited to 'test') diff --git a/test/etap/072-cleanup.t b/test/etap/072-cleanup.t new file mode 100755 index 00000000..61790bc6 --- /dev/null +++ b/test/etap/072-cleanup.t @@ -0,0 +1,130 @@ +#!/usr/bin/env escript +%% -*- erlang -*- + +% 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. + +-define(TEST_DB, <<"etap-test-db">>). + +-record(user_ctx, { + name = null, + roles = [], + handler +}). + +-define(ADMIN_USER, #user_ctx{roles=[<<"_admin">>]}). + +main(_) -> + test_util:init_code_path(), + + etap:plan(7), + try test() of + ok -> + etap:end_tests() + catch + Other -> + etap:diag(io_lib:format("Test died abnormally: ~p", [Other])), + timer:sleep(1000), + etap:bail(Other) + end, + ok. + +test() -> + + {ok, _} = couch_server_sup:start_link(test_util:config_files()), + ok = application:start(inets), + couch_server:delete(?TEST_DB, []), + timer:sleep(1000), + + couch_db:create(?TEST_DB, []), + + {ok, AllDbs} = couch_server:all_databases(), + etap:ok(lists:member(?TEST_DB, AllDbs), "Database was created."), + + FooRev = create_design_doc(<<"_design/foo">>, <<"bar">>), + query_view("foo", "bar"), + + BoozRev = create_design_doc(<<"_design/booz">>, <<"baz">>), + query_view("booz", "baz"), + + {ok, Db} = couch_db:open(?TEST_DB, [{user_ctx, ?ADMIN_USER}]), + view_cleanup(), + etap:is(count_index_files(), 2, + "Two index files before any deletions."), + + delete_design_doc(<<"_design/foo">>, FooRev), + view_cleanup(), + etap:is(count_index_files(), 1, + "One index file after first deletion and cleanup."), + + delete_design_doc(<<"_design/booz">>, BoozRev), + view_cleanup(), + etap:is(count_index_files(), 0, + "No index files after second deletion and cleanup."), + + couch_server:delete(?TEST_DB, []), + {ok, AllDbs2} = couch_server:all_databases(), + etap:ok(not lists:member(?TEST_DB, AllDbs2), + "Database was deleted."), + ok. + +create_design_doc(DDName, ViewName) -> + {ok, Db} = couch_db:open(?TEST_DB, [{user_ctx, ?ADMIN_USER}]), + DDoc = couch_doc:from_json_obj({[ + {<<"_id">>, DDName}, + {<<"language">>, <<"javascript">>}, + {<<"views">>, {[ + {ViewName, {[ + {<<"map">>, <<"function(doc) { emit(doc.value, 1); }">>} + ]}} + ]}} + ]}), + {ok, Rev} = couch_db:update_doc(Db, DDoc, []), + couch_db:ensure_full_commit(Db), + couch_db:close(Db), + Rev. + +delete_design_doc(DDName, Rev) -> + {ok, Db} = couch_db:open(?TEST_DB, [{user_ctx, ?ADMIN_USER}]), + DDoc = couch_doc:from_json_obj({[ + {<<"_id">>, DDName}, + {<<"_rev">>, couch_doc:rev_to_str(Rev)}, + {<<"_deleted">>, true} + ]}), + {ok, _} = couch_db:update_doc(Db, DDoc, [Rev]), + couch_db:close(Db). + +db_url() -> + Addr = couch_config:get("httpd", "bind_address", "127.0.0.1"), + Port = integer_to_list(mochiweb_socket_server:get(couch_httpd, port)), + "http://" ++ Addr ++ ":" ++ Port ++ "/" ++ + binary_to_list(?TEST_DB). + +query_view(DDoc, View) -> + {ok, {{_, Code, _}, _Headers, _Body}} = http:request( + get, + {db_url() ++ "/_design/" ++ DDoc ++ "/_view/" ++ View, []}, + [], + [{sync, true}]), + etap:is(Code, 200, "Built view index for " ++ DDoc ++ "."), + ok. + +view_cleanup() -> + {ok, Db} = couch_db:open(?TEST_DB, [{user_ctx, ?ADMIN_USER}]), + couch_view:cleanup_index_files(Db), + couch_db:close(Db). + +count_index_files() -> + % call server to fetch the index files + RootDir = couch_config:get("couchdb", "view_index_dir"), + length(filelib:wildcard(RootDir ++ "/." ++ + binary_to_list(?TEST_DB) ++ "_design"++"/*")). -- cgit v1.2.3 From a217146276375f6247b027305723b0734ab280f5 Mon Sep 17 00:00:00 2001 From: Randall Leeds Date: Sat, 11 Jun 2011 19:14:16 +0000 Subject: Backport r113686 from trunk add 072-cleanup.t to etap Makefile.am git-svn-id: https://svn.apache.org/repos/asf/couchdb/branches/1.1.x@1134729 13f79535-47bb-0310-9956-ffa450edef68 --- test/etap/Makefile.am | 1 + 1 file changed, 1 insertion(+) (limited to 'test') diff --git a/test/etap/Makefile.am b/test/etap/Makefile.am index ce52d430..ecbc3a93 100644 --- a/test/etap/Makefile.am +++ b/test/etap/Makefile.am @@ -53,6 +53,7 @@ EXTRA_DIST = \ 064-kt-counting.t \ 065-kt-stemming.t \ 070-couch-db.t \ + 072-cleanup.t \ 080-config-get-set.t \ 081-config-override.1.ini \ 081-config-override.2.ini \ -- cgit v1.2.3 From 0827cb483ef4cf74123313e8f2d0d2bd5ce8e46b Mon Sep 17 00:00:00 2001 From: Robert Newson Date: Mon, 20 Jun 2011 21:22:02 +0000 Subject: Fix spurious declarations of new merge conflicts This patch also adds extra tests of the key tree merging logic as well as edoc-formatted documentation for the module and a few of the merge functions. Closes COUCHDB-902. Thanks Paul Davis, Bob Dionne, Klaus Trainer. backported from trunk@1065471 Conflicts: src/couchdb/couch_key_tree.erl git-svn-id: https://svn.apache.org/repos/asf/couchdb/branches/1.1.x@1137789 13f79535-47bb-0310-9956-ffa450edef68 --- test/etap/060-kt-merging.t | 95 +++++++++++++++++++++++++++++++++++++--------- 1 file changed, 78 insertions(+), 17 deletions(-) (limited to 'test') diff --git a/test/etap/060-kt-merging.t b/test/etap/060-kt-merging.t index 0e481a52..efbdbf69 100755 --- a/test/etap/060-kt-merging.t +++ b/test/etap/060-kt-merging.t @@ -15,7 +15,7 @@ main(_) -> test_util:init_code_path(), - etap:plan(12), + etap:plan(16), case (catch test()) of ok -> etap:end_tests(); @@ -26,25 +26,21 @@ main(_) -> ok. test() -> - One = {0, {"1","foo",[]}}, - TwoSibs = [{0, {"1","foo",[]}}, - {0, {"2","foo",[]}}], - OneChild = {0, {"1","foo",[{"1a", "bar", []}]}}, - TwoChild = {0, {"1","foo", [{"1a", "bar", [{"1aa", "bar", []}]}]}}, - TwoChildSibs = {0, {"1","foo", [{"1a", "bar", []}, - {"1b", "bar", []}]}}, - TwoChildSibs2 = {0, {"1","foo", [{"1a", "bar", []}, - {"1b", "bar", [{"1bb", "boo", []}]}]}}, - Stemmed1b = {1, {"1a", "bar", []}}, - Stemmed1a = {1, {"1a", "bar", [{"1aa", "bar", []}]}}, - Stemmed1aa = {2, {"1aa", "bar", []}}, - Stemmed1bb = {2, {"1bb", "boo", []}}, + One = {1, {"1","foo",[]}}, etap:is( {[One], no_conflicts}, couch_key_tree:merge([], One, 10), "The empty tree is the identity for merge." ), + etap:is( + {[One], no_conflicts}, + couch_key_tree:merge([One], One, 10), + "Merging is reflexive." + ), + + TwoSibs = [{1, {"1","foo",[]}}, + {1, {"2","foo",[]}}], etap:is( {TwoSibs, no_conflicts}, @@ -52,41 +48,75 @@ test() -> "Merging a prefix of a tree with the tree yields the tree." ), + Three = {1, {"3","foo",[]}}, + ThreeSibs = [{1, {"1","foo",[]}}, + {1, {"2","foo",[]}}, + {1, {"3","foo",[]}}], + etap:is( - {[One], no_conflicts}, - couch_key_tree:merge([One], One, 10), - "Merging is reflexive." + {ThreeSibs, conflicts}, + couch_key_tree:merge(TwoSibs, Three, 10), + "Merging a third unrelated branch leads to a conflict." ), + + TwoChild = {1, {"1","foo", [{"1a", "bar", [{"1aa", "bar", []}]}]}}, + etap:is( {[TwoChild], no_conflicts}, couch_key_tree:merge([TwoChild], TwoChild, 10), "Merging two children is still reflexive." ), + TwoChildSibs = {1, {"1","foo", [{"1a", "bar", []}, + {"1b", "bar", []}]}}, etap:is( {[TwoChildSibs], no_conflicts}, couch_key_tree:merge([TwoChildSibs], TwoChildSibs, 10), "Merging a tree to itself is itself."), + TwoChildPlusSibs = + {1, {"1","foo", [{"1a", "bar", [{"1aa", "bar", []}]}, + {"1b", "bar", []}]}}, + + etap:is( + {[TwoChildPlusSibs], no_conflicts}, + couch_key_tree:merge([TwoChild], TwoChildSibs, 10), + "Merging tree of uneven length at node 2."), + + Stemmed1b = {2, {"1a", "bar", []}}, etap:is( {[TwoChildSibs], no_conflicts}, couch_key_tree:merge([TwoChildSibs], Stemmed1b, 10), "Merging a tree with a stem." ), + TwoChildSibs2 = {1, {"1","foo", [{"1a", "bar", []}, + {"1b", "bar", [{"1bb", "boo", []}]}]}}, + Stemmed1bb = {3, {"1bb", "boo", []}}, etap:is( {[TwoChildSibs2], no_conflicts}, couch_key_tree:merge([TwoChildSibs2], Stemmed1bb, 10), "Merging a stem at a deeper level." ), + StemmedTwoChildSibs2 = [{2,{"1a", "bar", []}}, + {2,{"1b", "bar", [{"1bb", "boo", []}]}}], + + etap:is( + {StemmedTwoChildSibs2, no_conflicts}, + couch_key_tree:merge(StemmedTwoChildSibs2, Stemmed1bb, 10), + "Merging a stem at a deeper level against paths at deeper levels." + ), + + Stemmed1aa = {3, {"1aa", "bar", []}}, etap:is( {[TwoChild], no_conflicts}, couch_key_tree:merge([TwoChild], Stemmed1aa, 10), "Merging a single tree with a deeper stem." ), + Stemmed1a = {2, {"1a", "bar", [{"1aa", "bar", []}]}}, etap:is( {[TwoChild], no_conflicts}, couch_key_tree:merge([TwoChild], Stemmed1a, 10), @@ -99,6 +129,7 @@ test() -> "More merging." ), + OneChild = {1, {"1","foo",[{"1a", "bar", []}]}}, Expect1 = [OneChild, Stemmed1aa], etap:is( {Expect1, conflicts}, @@ -112,4 +143,34 @@ test() -> "Merge should have no conflicts." ), + %% this test is based on couch-902-test-case2.py + %% foo has conflicts from replication at depth two + %% foo3 is the current value + Foo = {1, {"foo", + "val1", + [{"foo2","val2",[]}, + {"foo3", "val3", []} + ]}}, + %% foo now has an attachment added, which leads to foo4 and val4 + %% off foo3 + Bar = {1, {"foo", + [], + [{"foo3", + [], + [{"foo4","val4",[]} + ]}]}}, + %% this is what the merge returns + %% note that it ignore the conflicting branch as there's no match + FooBar = {1, {"foo", + "val1", + [{"foo2","val2",[]}, + {"foo3", "val3", [{"foo4","val4",[]}]} + ]}}, + + etap:is( + {[FooBar], no_conflicts}, + couch_key_tree:merge([Foo],Bar,10), + "Merging trees with conflicts ought to behave." + ), + ok. -- cgit v1.2.3