Return-Path: X-Original-To: apmail-couchdb-commits-archive@www.apache.org Delivered-To: apmail-couchdb-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id A451C18D41 for ; Thu, 11 Feb 2016 12:54:47 +0000 (UTC) Received: (qmail 71698 invoked by uid 500); 11 Feb 2016 12:54:47 -0000 Delivered-To: apmail-couchdb-commits-archive@couchdb.apache.org Received: (qmail 71649 invoked by uid 500); 11 Feb 2016 12:54:47 -0000 Mailing-List: contact commits-help@couchdb.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@couchdb.apache.org Delivered-To: mailing list commits@couchdb.apache.org Received: (qmail 71640 invoked by uid 99); 11 Feb 2016 12:54:47 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 11 Feb 2016 12:54:47 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id 5AC7EE0A1B; Thu, 11 Feb 2016 12:54:47 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: eiri@apache.org To: commits@couchdb.apache.org Date: Thu, 11 Feb 2016 12:54:48 -0000 Message-Id: In-Reply-To: References: X-Mailer: ASF-Git Admin Mailer Subject: [2/2] couch-replicator commit: updated refs/heads/master to 61c59b5 Fix filtered replication test Project: http://git-wip-us.apache.org/repos/asf/couchdb-couch-replicator/repo Commit: http://git-wip-us.apache.org/repos/asf/couchdb-couch-replicator/commit/b18ff40d Tree: http://git-wip-us.apache.org/repos/asf/couchdb-couch-replicator/tree/b18ff40d Diff: http://git-wip-us.apache.org/repos/asf/couchdb-couch-replicator/diff/b18ff40d Branch: refs/heads/master Commit: b18ff40d3adde03f4f85f9acff4950ddbb3b2e06 Parents: ea40886 Author: Eric Avdey Authored: Fri Feb 5 11:28:49 2016 -0400 Committer: Eric Avdey Committed: Thu Feb 11 08:28:07 2016 -0400 ---------------------------------------------------------------------- test/couch_replicator_filtered_tests.erl | 152 ++++++++------------------ 1 file changed, 47 insertions(+), 105 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/couchdb-couch-replicator/blob/b18ff40d/test/couch_replicator_filtered_tests.erl ---------------------------------------------------------------------- diff --git a/test/couch_replicator_filtered_tests.erl b/test/couch_replicator_filtered_tests.erl index c1a79e8..71aabfb 100644 --- a/test/couch_replicator_filtered_tests.erl +++ b/test/couch_replicator_filtered_tests.erl @@ -25,33 +25,16 @@ ]}} ]}). -setup() -> - DbName = ?tempdb(), - {ok, Db} = couch_db:create(DbName, [?ADMIN_CTX]), - ok = couch_db:close(Db), - upload_ddoc(DbName), - create_docs(DbName), - DbName. - -setup(local) -> - setup(); -setup(remote) -> - {remote, setup()}; -setup({A, B}) -> +setup(_) -> Ctx = test_util:start_couch([couch_replicator]), - Source = setup(A), - Target = setup(B), + Source = create_db(), + create_docs(Source), + Target = create_db(), {Ctx, {Source, Target}}. -teardown({remote, DbName}) -> - teardown(DbName); -teardown(DbName) -> - ok = couch_server:delete(DbName, [?ADMIN_CTX]), - ok. - teardown(_, {Ctx, {Source, Target}}) -> - teardown(Source), - teardown(Target), + delete_db(Source), + delete_db(Target), ok = application:stop(couch_replicator), ok = test_util:stop_couch(Ctx). @@ -63,95 +46,72 @@ filtered_replication_test_() -> { foreachx, fun setup/1, fun teardown/2, - [{Pair, fun should_succeed/2} - || Pair <- Pairs] + [{Pair, fun should_succeed/2} || Pair <- Pairs] } }. - should_succeed({From, To}, {_Ctx, {Source, Target}}) -> - {ok, RepPid, RepId} = replicate(Source, Target), + RepObject = {[ + {<<"source">>, db_url(From, Source)}, + {<<"target">>, db_url(To, Target)}, + {<<"filter">>, <<"filter_ddoc/testfilter">>} + ]}, + {ok, _} = couch_replicator:replicate(RepObject, ?ADMIN_USER), %% FilteredFun is an Erlang version of following JS function %% function(doc, req){if (doc.class == 'mammal') return true;} FilterFun = fun(_DocId, {Props}) -> couch_util:get_value(<<"class">>, Props) == <<"mammal">> end, - {lists:flatten(io_lib:format("~p -> ~p", [From, To])), - {inorder, [ - should_ensure_replication_runs(RepPid), - should_compare_databases(Source, Target, FilterFun), - should_cancel_replication(RepId, RepPid) - ]}}. - -should_ensure_replication_runs(RepPid) -> - ?_assert(begin - ?assertMatch(ok, wait_for_replicator(RepPid)), - is_process_alive(RepPid) - end). - -should_compare_databases({remote, Source}, Target, FilterFun) -> - should_compare_databases(Source, Target, FilterFun); -should_compare_databases(Source, {remote, Target}, FilterFun) -> - should_compare_databases(Source, Target, FilterFun); -should_compare_databases(Source, Target, FilterFun) -> - ?_assertEqual(1, begin - compare_dbs(Source, Target, FilterFun) - end). - -should_cancel_replication(RepId, RepPid) -> - ?_assertNot(begin - ?assertMatch({ok, _}, couch_replicator:cancel_replication(RepId)), - is_process_alive(RepPid) - end). + {ok, TargetDbInfo, AllReplies} = compare_dbs(Source, Target, FilterFun), + {lists:flatten(io_lib:format("~p -> ~p", [From, To])), [ + {"Target DB has proper number of docs", + ?_assertEqual(1, proplists:get_value(doc_count, TargetDbInfo))}, + {"Target DB doesn't have deleted docs", + ?_assertEqual(0, proplists:get_value(doc_del_count, TargetDbInfo))}, + {"All the docs filtered as expected", + ?_assert(lists:all(fun(Valid) -> Valid end, AllReplies))} + ]}. compare_dbs(Source, Target, FilterFun) -> {ok, SourceDb} = couch_db:open_int(Source, []), {ok, TargetDb} = couch_db:open_int(Target, []), + {ok, TargetDbInfo} = couch_db:get_db_info(TargetDb), Fun = fun(FullDocInfo, _, Acc) -> - {ok, DocId, SourceDoc} = read_doc(SourceDb, FullDocInfo, ?LINE), + {ok, DocId, SourceDoc} = read_doc(SourceDb, FullDocInfo), + TargetReply = read_doc(TargetDb, DocId), case FilterFun(DocId, SourceDoc) of true -> - {ok, DocId, TargetDoc} = read_doc(TargetDb, DocId, ?LINE), - ?assertEqual(SourceDoc, TargetDoc), - {ok, Acc + 1}; + ValidReply = {ok, DocId, SourceDoc} == TargetReply, + {ok, [ValidReply|Acc]}; false -> - {ok, Acc} + ValidReply = {not_found, missing} == TargetReply, + {ok, [ValidReply|Acc]} end end, - {ok, _, Acc} = couch_db:enum_docs(SourceDb, Fun, 0, []), + {ok, _, AllReplies} = couch_db:enum_docs(SourceDb, Fun, [], []), ok = couch_db:close(SourceDb), ok = couch_db:close(TargetDb), - Acc. + {ok, TargetDbInfo, AllReplies}. -read_doc(Db, DocIdOrInfo, Line) -> +read_doc(Db, DocIdOrInfo) -> case couch_db:open_doc(Db, DocIdOrInfo) of {ok, Doc} -> {Props} = couch_doc:to_json_obj(Doc, [attachments]), DocId = couch_util:get_value(<<"_id">>, Props), {ok, DocId, {Props}}; Error -> - Reason = lists:concat([ - "Error opening document '", ?b2l(doc_id(DocIdOrInfo)), - "' from target: ", couch_util:to_list(Error)]), - erlang:error( - {assertion_failed, - [{module, ?MODULE}, {line, Line}, - {reason, Reason}]}) + Error end. -doc_id(#full_doc_info{id = Id}) -> Id; -doc_id(Id) -> Id. - - -wait_for_replicator(Pid) -> - %% since replicator started asynchronously - %% we need to wait when it would be in couch_task_status - %% we query replicator:details to ensure that do_init happen - ?assertMatch({ok, _}, couch_replicator:details(Pid)), - ok. +create_db() -> + DbName = ?tempdb(), + {ok, Db} = couch_db:create(DbName, [?ADMIN_CTX]), + ok = couch_db:close(Db), + DbName. create_docs(DbName) -> {ok, Db} = couch_db:open(DbName, [?ADMIN_CTX]), + DDoc = couch_doc:from_json_obj(?DDOC), Doc1 = couch_doc:from_json_obj({[ {<<"_id">>, <<"doc1">>}, {<<"class">>, <<"mammal">>}, @@ -169,34 +129,16 @@ create_docs(DbName) -> {<<"value">>, 3} ]}), - {ok, _} = couch_db:update_docs(Db, [Doc1, Doc2, Doc3]), + {ok, _} = couch_db:update_docs(Db, [DDoc, Doc1, Doc2, Doc3]), couch_db:ensure_full_commit(Db), couch_db:close(Db). +delete_db(DbName) -> + ok = couch_server:delete(DbName, [?ADMIN_CTX]). -upload_ddoc(DbName) -> - Url = db_url(DbName) ++ "/_design/filter_ddoc", - Body = couch_util:json_encode(?DDOC), - {ok, 201, _Resp, _Body} = test_request:put(Url, Body), - ok. - -replicate({remote, Db}, Target) -> - replicate(?l2b(db_url(Db)), Target); - -replicate(Source, {remote, Db}) -> - replicate(Source, ?l2b(db_url(Db))); - -replicate(Source, Target) -> - RepObject = {[ - {<<"source">>, Source}, - {<<"target">>, Target}, - {<<"continuous">>, true} - ]}, - {ok, Rep} = couch_replicator_utils:parse_rep_doc(RepObject, ?ADMIN_USER), - {ok, Pid} = couch_replicator:async_replicate(Rep), - {ok, Pid, Rep#rep.id}. - -db_url(DbName) -> +db_url(local, DbName) -> + DbName; +db_url(remote, DbName) -> Addr = config:get("httpd", "bind_address", "127.0.0.1"), - Port = integer_to_list(mochiweb_socket_server:get(couch_httpd, port)), - "http://" ++ Addr ++ ":" ++ Port ++ "/" ++ ?b2l(DbName). + Port = mochiweb_socket_server:get(couch_httpd, port), + ?l2b(io_lib:format("http://~s:~b/~s", [Addr, Port, DbName])).