diff options
Diffstat (limited to 'src/fabric/src/fabric_doc_open_revs.erl')
-rw-r--r-- | src/fabric/src/fabric_doc_open_revs.erl | 361 |
1 files changed, 164 insertions, 197 deletions
diff --git a/src/fabric/src/fabric_doc_open_revs.erl b/src/fabric/src/fabric_doc_open_revs.erl index 3d7b9dc3c..284187bff 100644 --- a/src/fabric/src/fabric_doc_open_revs.erl +++ b/src/fabric/src/fabric_doc_open_revs.erl @@ -34,8 +34,11 @@ }). go(DbName, Id, Revs, Options) -> - Workers = fabric_util:submit_jobs(mem3:shards(DbName,Id), open_revs, - [Id, Revs, Options]), + Workers = fabric_util:submit_jobs( + mem3:shards(DbName, Id), + open_revs, + [Id, Revs, Options] + ), R = couch_util:get_value(r, Options, integer_to_list(mem3:quorum(DbName))), State = #state{ dbname = DbName, @@ -48,34 +51,31 @@ go(DbName, Id, Revs, Options) -> }, RexiMon = fabric_util:create_monitors(Workers), try fabric_util:recv(Workers, #shard.ref, fun handle_message/3, State) of - {ok, all_workers_died} -> - {error, all_workers_died}; - {ok, Replies} -> - {ok, Replies}; - {timeout, #state{workers=DefunctWorkers}} -> - fabric_util:log_timeout(DefunctWorkers, "open_revs"), - {error, timeout}; - Else -> - Else + {ok, all_workers_died} -> + {error, all_workers_died}; + {ok, Replies} -> + {ok, Replies}; + {timeout, #state{workers = DefunctWorkers}} -> + fabric_util:log_timeout(DefunctWorkers, "open_revs"), + {error, timeout}; + Else -> + Else after rexi_monitor:stop(RexiMon) end. - -handle_message({rexi_DOWN, _, {_,NodeRef},_}, _Worker, #state{workers=Workers}=State) -> +handle_message({rexi_DOWN, _, {_, NodeRef}, _}, _Worker, #state{workers = Workers} = State) -> NewState = State#state{ workers = lists:keydelete(NodeRef, #shard.node, Workers), reply_error_count = State#state.reply_error_count + 1 }, handle_message({ok, []}, nil, NewState); - -handle_message({rexi_EXIT, _}, Worker, #state{workers=Workers}=State) -> +handle_message({rexi_EXIT, _}, Worker, #state{workers = Workers} = State) -> NewState = State#state{ workers = lists:delete(Worker, Workers), reply_error_count = State#state.reply_error_count + 1 }, handle_message({ok, []}, nil, NewState); - handle_message({ok, RawReplies}, Worker, State) -> #state{ dbname = DbName, @@ -96,30 +96,40 @@ handle_message({ok, RawReplies}, Worker, State) -> % Do not count error replies when checking quorum RealReplyCount = ReplyCount + 1 - ReplyErrorCount, QuorumReplies = RealReplyCount >= R, - {NewReplies, QuorumMet, Repair} = case IsTree of - true -> - {NewReplies0, AllInternal, Repair0} = + {NewReplies, QuorumMet, Repair} = + case IsTree of + true -> + {NewReplies0, AllInternal, Repair0} = tree_replies(PrevReplies, tree_sort(RawReplies)), - NumLeafs = couch_key_tree:count_leafs(PrevReplies), - SameNumRevs = length(RawReplies) == NumLeafs, - QMet = AllInternal andalso SameNumRevs andalso QuorumReplies, - % Don't set repair=true on the first reply - {NewReplies0, QMet, (ReplyCount > 0) and Repair0}; - false -> - {NewReplies0, MinCount} = dict_replies(PrevReplies, RawReplies), - {NewReplies0, MinCount >= R, false} - end, - NewNodeRevs = if Worker == nil -> PrevNodeRevs; true -> - IdRevs = lists:foldl(fun - ({ok, #doc{revs = {Pos, [Rev | _]}}}, Acc) -> - [{Pos, Rev} | Acc]; - (_, Acc) -> - Acc - end, [], RawReplies), - if IdRevs == [] -> PrevNodeRevs; true -> - [{Worker#shard.node, IdRevs} | PrevNodeRevs] - end - end, + NumLeafs = couch_key_tree:count_leafs(PrevReplies), + SameNumRevs = length(RawReplies) == NumLeafs, + QMet = AllInternal andalso SameNumRevs andalso QuorumReplies, + % Don't set repair=true on the first reply + {NewReplies0, QMet, (ReplyCount > 0) and Repair0}; + false -> + {NewReplies0, MinCount} = dict_replies(PrevReplies, RawReplies), + {NewReplies0, MinCount >= R, false} + end, + NewNodeRevs = + if + Worker == nil -> + PrevNodeRevs; + true -> + IdRevs = lists:foldl( + fun + ({ok, #doc{revs = {Pos, [Rev | _]}}}, Acc) -> + [{Pos, Rev} | Acc]; + (_, Acc) -> + Acc + end, + [], + RawReplies + ), + if + IdRevs == [] -> PrevNodeRevs; + true -> [{Worker#shard.node, IdRevs} | PrevNodeRevs] + end + end, Complete = (ReplyCount =:= (WorkerCount - 1)), @@ -127,13 +137,13 @@ handle_message({ok, RawReplies}, Worker, State) -> true -> fabric_util:cleanup(lists:delete(Worker, Workers)), maybe_read_repair( - DbName, - IsTree, - NewReplies, - NewNodeRevs, - ReplyCount + 1, - InRepair orelse Repair - ), + DbName, + IsTree, + NewReplies, + NewNodeRevs, + ReplyCount + 1, + InRepair orelse Repair + ), {stop, format_reply(IsTree, NewReplies, RealReplyCount)}; false -> {ok, State#state{ @@ -145,10 +155,8 @@ handle_message({ok, RawReplies}, Worker, State) -> }} end. - tree_replies(RevTree, []) -> {RevTree, true, false}; - tree_replies(RevTree0, [{ok, Doc} | Rest]) -> {RevTree1, Done, Repair} = tree_replies(RevTree0, Rest), Path = couch_doc:to_path(Doc), @@ -160,7 +168,6 @@ tree_replies(RevTree0, [{ok, Doc} | Rest]) -> {RevTree2, _} -> {RevTree2, false, true} end; - tree_replies(RevTree0, [{{not_found, missing}, {Pos, Rev}} | Rest]) -> {RevTree1, Done, Repair} = tree_replies(RevTree0, Rest), Node = {Rev, ?REV_MISSING, []}, @@ -172,34 +179,30 @@ tree_replies(RevTree0, [{{not_found, missing}, {Pos, Rev}} | Rest]) -> {RevTree2, false, Repair} end. - tree_sort(Replies) -> SortFun = fun(A, B) -> sort_key(A) =< sort_key(B) end, lists:sort(SortFun, Replies). - sort_key({ok, #doc{revs = {Pos, [Rev | _]}}}) -> {Pos, Rev}; sort_key({{not_found, _}, {Pos, Rev}}) -> {Pos, Rev}. - dict_replies(Dict, []) -> case [Count || {_Key, {_Reply, Count}} <- Dict] of [] -> {Dict, 0}; Counts -> {Dict, lists:min(Counts)} end; - dict_replies(Dict, [Reply | Rest]) -> NewDict = fabric_util:update_counter(Reply, 1, Dict), dict_replies(NewDict, Rest). - maybe_read_repair(Db, IsTree, Replies, NodeRevs, ReplyCount, DoRepair) -> - Docs = case IsTree of - true -> tree_repair_docs(Replies, DoRepair); - false -> dict_repair_docs(Replies, ReplyCount) - end, + Docs = + case IsTree of + true -> tree_repair_docs(Replies, DoRepair); + false -> dict_repair_docs(Replies, ReplyCount) + end, case Docs of [] -> ok; @@ -207,22 +210,19 @@ maybe_read_repair(Db, IsTree, Replies, NodeRevs, ReplyCount, DoRepair) -> erlang:spawn(fun() -> read_repair(Db, Docs, NodeRevs) end) end. - tree_repair_docs(_Replies, false) -> []; - tree_repair_docs(Replies, true) -> Leafs = couch_key_tree:get_all_leafs(Replies), [Doc || {Doc, {_Pos, _}} <- Leafs, is_record(Doc, doc)]. - dict_repair_docs(Replies, ReplyCount) -> NeedsRepair = lists:any(fun({_, {_, C}}) -> C < ReplyCount end, Replies), - if not NeedsRepair -> []; true -> - [Doc || {_, {{ok, Doc}, _}} <- Replies] + if + not NeedsRepair -> []; + true -> [Doc || {_, {{ok, Doc}, _}} <- Replies] end. - read_repair(Db, Docs, NodeRevs) -> Opts = [?ADMIN_CTX, replicated_changes, {read_repair, NodeRevs}], Res = fabric:update_docs(Db, Docs, Opts), @@ -235,57 +235,63 @@ read_repair(Db, Docs, NodeRevs) -> couch_log:notice("read_repair ~s ~s ~p", [Db, Id, Res]) end. - format_reply(_, _, RealReplyCount) when RealReplyCount =< 0 -> all_workers_died; - format_reply(true, Replies, _) -> tree_format_replies(Replies); - format_reply(false, Replies, _) -> dict_format_replies(Replies). - tree_format_replies(RevTree) -> Leafs = couch_key_tree:get_all_leafs(RevTree), - lists:sort(lists:map(fun(Reply) -> - case Reply of - {?REV_MISSING, {Pos, [Rev]}} -> - {{not_found, missing}, {Pos, Rev}}; - {Doc, _} when is_record(Doc, doc) -> - {ok, Doc} - end - end, Leafs)). - + lists:sort( + lists:map( + fun(Reply) -> + case Reply of + {?REV_MISSING, {Pos, [Rev]}} -> + {{not_found, missing}, {Pos, Rev}}; + {Doc, _} when is_record(Doc, doc) -> + {ok, Doc} + end + end, + Leafs + ) + ). dict_format_replies(Dict) -> Replies0 = [Reply || {_, {Reply, _}} <- Dict], - AllFoundRevs = lists:foldl(fun(Reply, Acc) -> - case Reply of - {ok, #doc{revs = {Pos, [RevId | _]}}} -> - [{Pos, RevId} | Acc]; - _ -> - Acc - end - end, [], Replies0), + AllFoundRevs = lists:foldl( + fun(Reply, Acc) -> + case Reply of + {ok, #doc{revs = {Pos, [RevId | _]}}} -> + [{Pos, RevId} | Acc]; + _ -> + Acc + end + end, + [], + Replies0 + ), %% Drop any not_found replies for which we %% found the revision on a different node. - Replies1 = lists:filter(fun(Reply) -> - case Reply of - {{not_found, missing}, Rev} -> - not lists:member(Rev, AllFoundRevs); - _ -> - true - end - end, Replies0), + Replies1 = lists:filter( + fun(Reply) -> + case Reply of + {{not_found, missing}, Rev} -> + not lists:member(Rev, AllFoundRevs); + _ -> + true + end + end, + Replies0 + ), % Remove replies with shorter revision % paths for a given revision. collapse_duplicate_revs(Replies1). - collapse_duplicate_revs(Replies) -> % The collapse logic requires that replies are % sorted so that shorter rev paths are in @@ -296,27 +302,23 @@ collapse_duplicate_revs(Replies) -> % of C. collapse_duplicate_revs_int(lists:sort(Replies)). - collapse_duplicate_revs_int([]) -> []; - collapse_duplicate_revs_int([{ok, Doc1}, {ok, Doc2} | Rest]) -> {D1, R1} = Doc1#doc.revs, {D2, R2} = Doc2#doc.revs, - Head = case D1 == D2 andalso lists:prefix(R1, R2) of - true -> []; - false -> [{ok, Doc1}] - end, + Head = + case D1 == D2 andalso lists:prefix(R1, R2) of + true -> []; + false -> [{ok, Doc1}] + end, Head ++ collapse_duplicate_revs([{ok, Doc2} | Rest]); - collapse_duplicate_revs_int([Reply | Rest]) -> [Reply | collapse_duplicate_revs(Rest)]. - -ifdef(TEST). -include_lib("eunit/include/eunit.hrl"). - setup_all() -> config:start_link([]), meck:new([fabric, couch_stats, couch_log]), @@ -326,13 +328,10 @@ setup_all() -> meck:expect(couch_log, notice, fun(_, _) -> ok end), meck:expect(fabric_util, cleanup, fun(_) -> ok end). - - teardown_all(_) -> meck:unload(), config:stop(). - setup() -> meck:reset([ couch_log, @@ -341,37 +340,31 @@ setup() -> fabric_util ]). - teardown(_) -> ok. - state0(Revs, Latest) -> #state{ worker_count = 3, workers = - [#shard{node='node1'}, #shard{node='node2'}, #shard{node='node3'}], + [#shard{node = 'node1'}, #shard{node = 'node2'}, #shard{node = 'node3'}], r = 2, revs = Revs, latest = Latest }. - -revs() -> [{1,<<"foo">>}, {1,<<"bar">>}, {1,<<"baz">>}]. - +revs() -> [{1, <<"foo">>}, {1, <<"bar">>}, {1, <<"baz">>}]. foo1() -> {ok, #doc{revs = {1, [<<"foo">>]}}}. foo2() -> {ok, #doc{revs = {2, [<<"foo2">>, <<"foo">>]}}}. foo2stemmed() -> {ok, #doc{revs = {2, [<<"foo2">>]}}}. -fooNF() -> {{not_found, missing}, {1,<<"foo">>}}. +fooNF() -> {{not_found, missing}, {1, <<"foo">>}}. foo2NF() -> {{not_found, missing}, {2, <<"foo2">>}}. bar1() -> {ok, #doc{revs = {1, [<<"bar">>]}}}. -barNF() -> {{not_found, missing}, {1,<<"bar">>}}. -bazNF() -> {{not_found, missing}, {1,<<"baz">>}}. +barNF() -> {{not_found, missing}, {1, <<"bar">>}}. +bazNF() -> {{not_found, missing}, {1, <<"baz">>}}. baz1() -> {ok, #doc{revs = {1, [<<"baz">>]}}}. - - open_doc_revs_test_() -> { setup, @@ -414,52 +407,47 @@ open_doc_revs_test_() -> } }. - % Tests for revs=all - check_empty_response_not_quorum() -> % Simple smoke test that we don't think we're % done with a first empty response - W1 = #shard{node='node1'}, - W2 = #shard{node='node2'}, - W3 = #shard{node='node3'}, + W1 = #shard{node = 'node1'}, + W2 = #shard{node = 'node2'}, + W3 = #shard{node = 'node3'}, ?_assertMatch( {ok, #state{workers = [W2, W3]}}, handle_message({ok, []}, W1, state0(all, false)) ). - check_basic_response() -> % Check that we've handle a response - W1 = #shard{node='node1'}, - W2 = #shard{node='node2'}, - W3 = #shard{node='node3'}, + W1 = #shard{node = 'node1'}, + W2 = #shard{node = 'node2'}, + W3 = #shard{node = 'node3'}, ?_assertMatch( {ok, #state{reply_count = 1, workers = [W2, W3]}}, handle_message({ok, [foo1(), bar1()]}, W1, state0(all, false)) ). - check_finish_quorum() -> % Two messages with the same revisions means we're done ?_test(begin - W1 = #shard{node='node1'}, - W2 = #shard{node='node2'}, + W1 = #shard{node = 'node1'}, + W2 = #shard{node = 'node2'}, S0 = state0(all, false), {ok, S1} = handle_message({ok, [foo1(), bar1()]}, W1, S0), Expect = {stop, [bar1(), foo1()]}, ?assertEqual(Expect, handle_message({ok, [foo1(), bar1()]}, W2, S1)) end). - check_finish_quorum_newer() -> % We count a descendant of a revision for quorum so % foo1 should count for foo2 which means we're finished. % We also validate that read_repair was triggered. ?_test(begin - W1 = #shard{node='node1'}, - W2 = #shard{node='node2'}, + W1 = #shard{node = 'node1'}, + W2 = #shard{node = 'node2'}, S0 = state0(all, false), {ok, S1} = handle_message({ok, [foo1(), bar1()]}, W1, S0), Expect = {stop, [bar1(), foo2()]}, @@ -472,14 +460,13 @@ check_finish_quorum_newer() -> ) end). - check_no_quorum_on_second() -> % Quorum not yet met for the foo revision so we % would wait for w3 ?_test(begin - W1 = #shard{node='node1'}, - W2 = #shard{node='node2'}, - W3 = #shard{node='node3'}, + W1 = #shard{node = 'node1'}, + W2 = #shard{node = 'node2'}, + W3 = #shard{node = 'node3'}, S0 = state0(all, false), {ok, S1} = handle_message({ok, [foo1(), bar1()]}, W1, S0), ?assertMatch( @@ -488,15 +475,14 @@ check_no_quorum_on_second() -> ) end). - check_done_on_third() -> % The third message of three means we're done no matter % what. Every revision seen in this pattern should be % included. ?_test(begin - W1 = #shard{node='node1'}, - W2 = #shard{node='node2'}, - W3 = #shard{node='node3'}, + W1 = #shard{node = 'node1'}, + W2 = #shard{node = 'node2'}, + W3 = #shard{node = 'node3'}, S0 = state0(all, false), {ok, S1} = handle_message({ok, [foo1(), bar1()]}, W1, S0), {ok, S2} = handle_message({ok, [bar1()]}, W2, S1), @@ -504,15 +490,13 @@ check_done_on_third() -> ?assertEqual(Expect, handle_message({ok, [bar1()]}, W3, S2)) end). - % Tests for a specific list of revs - check_specific_revs_first_msg() -> ?_test(begin - W1 = #shard{node='node1'}, - W2 = #shard{node='node2'}, - W3 = #shard{node='node3'}, + W1 = #shard{node = 'node1'}, + W2 = #shard{node = 'node2'}, + W3 = #shard{node = 'node3'}, S0 = state0(revs(), false), ?assertMatch( {ok, #state{reply_count = 1, workers = [W2, W3]}}, @@ -520,11 +504,10 @@ check_specific_revs_first_msg() -> ) end). - check_revs_done_on_agreement() -> ?_test(begin - W1 = #shard{node='node1'}, - W2 = #shard{node='node2'}, + W1 = #shard{node = 'node1'}, + W2 = #shard{node = 'node2'}, S0 = state0(revs(), false), Msg = {ok, [foo1(), bar1(), bazNF()]}, {ok, S1} = handle_message(Msg, W1, S0), @@ -532,11 +515,10 @@ check_revs_done_on_agreement() -> ?assertEqual(Expect, handle_message(Msg, W2, S1)) end). - check_latest_true() -> ?_test(begin - W1 = #shard{node='node1'}, - W2 = #shard{node='node2'}, + W1 = #shard{node = 'node1'}, + W2 = #shard{node = 'node2'}, S0 = state0(revs(), true), Msg1 = {ok, [foo2(), bar1(), bazNF()]}, Msg2 = {ok, [foo2(), bar1(), bazNF()]}, @@ -545,11 +527,10 @@ check_latest_true() -> ?assertEqual(Expect, handle_message(Msg2, W2, S1)) end). - check_ancestor_counted_in_quorum() -> ?_test(begin - W1 = #shard{node='node1'}, - W2 = #shard{node='node2'}, + W1 = #shard{node = 'node1'}, + W2 = #shard{node = 'node2'}, S0 = state0(revs(), true), Msg1 = {ok, [foo1(), bar1(), bazNF()]}, Msg2 = {ok, [foo2(), bar1(), bazNF()]}, @@ -564,11 +545,10 @@ check_ancestor_counted_in_quorum() -> ?assertEqual(Expect, handle_message(Msg1, W1, S2)) end). - check_not_found_counts_for_descendant() -> ?_test(begin - W1 = #shard{node='node1'}, - W2 = #shard{node='node2'}, + W1 = #shard{node = 'node1'}, + W2 = #shard{node = 'node2'}, S0 = state0(revs(), true), Msg1 = {ok, [foo1(), bar1(), bazNF()]}, Msg2 = {ok, [foo1(), bar1(), baz1()]}, @@ -583,12 +563,11 @@ check_not_found_counts_for_descendant() -> ?assertEqual(Expect, handle_message(Msg1, W1, S2)) end). - check_worker_error_skipped() -> ?_test(begin - W1 = #shard{node='node1'}, - W2 = #shard{node='node2'}, - W3 = #shard{node='node3'}, + W1 = #shard{node = 'node1'}, + W2 = #shard{node = 'node2'}, + W3 = #shard{node = 'node3'}, S0 = state0(revs(), true), Msg1 = {ok, [foo1(), bar1(), baz1()]}, Msg2 = {rexi_EXIT, reason}, @@ -600,12 +579,11 @@ check_worker_error_skipped() -> ?assertEqual(Expect, handle_message(Msg3, W3, S2)) end). - check_quorum_only_counts_valid_responses() -> ?_test(begin - W1 = #shard{node='node1'}, - W2 = #shard{node='node2'}, - W3 = #shard{node='node3'}, + W1 = #shard{node = 'node1'}, + W2 = #shard{node = 'node2'}, + W3 = #shard{node = 'node3'}, S0 = state0(revs(), true), Msg1 = {rexi_EXIT, reason}, Msg2 = {rexi_EXIT, reason}, @@ -617,12 +595,11 @@ check_quorum_only_counts_valid_responses() -> ?assertEqual(Expect, handle_message(Msg3, W3, S2)) end). - check_empty_list_when_no_workers_reply() -> ?_test(begin - W1 = #shard{node='node1'}, - W2 = #shard{node='node2'}, - W3 = #shard{node='node3'}, + W1 = #shard{node = 'node1'}, + W2 = #shard{node = 'node2'}, + W3 = #shard{node = 'node3'}, S0 = state0(revs(), true), Msg1 = {rexi_EXIT, reason}, Msg2 = {rexi_EXIT, reason}, @@ -634,7 +611,6 @@ check_empty_list_when_no_workers_reply() -> ?assertEqual(Expect, handle_message(Msg3, W3, S2)) end). - check_node_rev_stored() -> ?_test(begin W1 = #shard{node = node1}, @@ -644,7 +620,6 @@ check_node_rev_stored() -> ?assertEqual([{node1, [{1, <<"foo">>}]}], S1#state.node_revs) end). - check_node_rev_store_head_only() -> ?_test(begin W1 = #shard{node = node1}, @@ -654,7 +629,6 @@ check_node_rev_store_head_only() -> ?assertEqual([{node1, [{2, <<"foo2">>}]}], S1#state.node_revs) end). - check_node_rev_store_multiple() -> ?_test(begin W1 = #shard{node = node1}, @@ -662,12 +636,11 @@ check_node_rev_store_multiple() -> {ok, S1} = handle_message({ok, [foo1(), foo2()]}, W1, S0), ?assertEqual( - [{node1, [{2, <<"foo2">>}, {1, <<"foo">>}]}], - S1#state.node_revs - ) + [{node1, [{2, <<"foo2">>}, {1, <<"foo">>}]}], + S1#state.node_revs + ) end). - check_node_rev_dont_store_errors() -> ?_test(begin W1 = #shard{node = node1}, @@ -677,7 +650,6 @@ check_node_rev_dont_store_errors() -> ?assertEqual([], S1#state.node_revs) end). - check_node_rev_store_non_errors() -> ?_test(begin W1 = #shard{node = node1}, @@ -687,7 +659,6 @@ check_node_rev_store_non_errors() -> ?assertEqual([{node1, [{1, <<"foo">>}]}], S1#state.node_revs) end). - check_node_rev_store_concatenate() -> ?_test(begin W2 = #shard{node = node2}, @@ -696,12 +667,11 @@ check_node_rev_store_concatenate() -> {ok, S2} = handle_message({ok, [foo2()]}, W2, S1), ?assertEqual( - [{node2, [{2, <<"foo2">>}]}, {node1, [{1, <<"foo">>}]}], - S2#state.node_revs - ) + [{node2, [{2, <<"foo2">>}]}, {node1, [{1, <<"foo">>}]}], + S2#state.node_revs + ) end). - check_node_rev_store_concantenate_multiple() -> ?_test(begin W2 = #shard{node = node2}, @@ -710,15 +680,14 @@ check_node_rev_store_concantenate_multiple() -> {ok, S2} = handle_message({ok, [foo2(), bar1()]}, W2, S1), ?assertEqual( - [ - {node2, [{1, <<"bar">>}, {2, <<"foo2">>}]}, - {node1, [{1, <<"foo">>}]} - ], - S2#state.node_revs - ) + [ + {node2, [{1, <<"bar">>}, {2, <<"foo2">>}]}, + {node1, [{1, <<"foo">>}]} + ], + S2#state.node_revs + ) end). - check_node_rev_unmodified_on_down_or_exit() -> ?_test(begin W2 = #shard{node = node2}, @@ -728,19 +697,18 @@ check_node_rev_unmodified_on_down_or_exit() -> Down = {rexi_DOWN, nodedown, {nil, node()}, nil}, {ok, S2} = handle_message(Down, W2, S1), ?assertEqual( - [{node1, [{1, <<"foo">>}]}], - S2#state.node_revs - ), + [{node1, [{1, <<"foo">>}]}], + S2#state.node_revs + ), Exit = {rexi_EXIT, reason}, {ok, S3} = handle_message(Exit, W2, S1), ?assertEqual( - [{node1, [{1, <<"foo">>}]}], - S3#state.node_revs - ) + [{node1, [{1, <<"foo">>}]}], + S3#state.node_revs + ) end). - check_not_found_replies_are_removed_when_doc_found() -> ?_test(begin Replies = replies_to_dict([foo1(), bar1(), fooNF()]), @@ -786,7 +754,6 @@ check_not_found_removed_and_longer_rev_list() -> ?assertEqual(Expect, dict_format_replies(Replies)) end). - replies_to_dict(Replies) -> [reply_to_element(R) || R <- Replies]. |