You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by va...@apache.org on 2022/09/29 14:21:26 UTC

[couchdb] branch cleanup-fabric-doc-open-revs created (now 42da372dc)

This is an automated email from the ASF dual-hosted git repository.

vatamane pushed a change to branch cleanup-fabric-doc-open-revs
in repository https://gitbox.apache.org/repos/asf/couchdb.git


      at 42da372dc Clean up fabric_doc_open_revs tests

This branch includes the following new commits:

     new 42da372dc Clean up fabric_doc_open_revs tests

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.



[couchdb] 01/01: Clean up fabric_doc_open_revs tests

Posted by va...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

vatamane pushed a commit to branch cleanup-fabric-doc-open-revs
in repository https://gitbox.apache.org/repos/asf/couchdb.git

commit 42da372dc9964c72e651ccc350e399d5948daa8b
Author: Nick Vatamaniuc <va...@apache.org>
AuthorDate: Thu Sep 29 10:13:41 2022 -0400

    Clean up fabric_doc_open_revs tests
    
    Use the TDEF_FE macro to save 2 lines per test.
---
 src/fabric/src/fabric_doc_open_revs.erl | 626 +++++++++++++++-----------------
 1 file changed, 287 insertions(+), 339 deletions(-)

diff --git a/src/fabric/src/fabric_doc_open_revs.erl b/src/fabric/src/fabric_doc_open_revs.erl
index 71188dd51..7909e4c30 100644
--- a/src/fabric/src/fabric_doc_open_revs.erl
+++ b/src/fabric/src/fabric_doc_open_revs.erl
@@ -373,384 +373,332 @@ open_doc_revs_test_() ->
             fun setup/0,
             fun teardown/1,
             [
-                check_empty_response_not_quorum(),
-                check_basic_response(),
-                check_finish_quorum(),
-                check_finish_quorum_newer(),
-                check_no_quorum_on_second(),
-                check_done_on_third(),
-                check_specific_revs_first_msg(),
-                check_revs_done_on_agreement(),
-                check_latest_true(),
-                check_ancestor_counted_in_quorum(),
-                check_not_found_counts_for_descendant(),
-                check_worker_error_skipped(),
-                check_quorum_only_counts_valid_responses(),
-                check_empty_list_when_no_workers_reply(),
-                check_node_rev_stored(),
-                check_node_rev_store_head_only(),
-                check_node_rev_store_multiple(),
-                check_node_rev_dont_store_errors(),
-                check_node_rev_store_non_errors(),
-                check_node_rev_store_concatenate(),
-                check_node_rev_store_concantenate_multiple(),
-                check_node_rev_unmodified_on_down_or_exit(),
-                check_not_found_replies_are_removed_when_doc_found(),
-                check_not_found_returned_when_one_of_docs_not_found(),
-                check_not_found_returned_when_doc_not_found(),
-                check_longer_rev_list_returned(),
-                check_longer_rev_list_not_combined(),
-                check_not_found_removed_and_longer_rev_list()
+                ?TDEF_FE(check_empty_response_not_quorum),
+                ?TDEF_FE(check_basic_response),
+                ?TDEF_FE(check_finish_quorum),
+                ?TDEF_FE(check_finish_quorum_newer),
+                ?TDEF_FE(check_no_quorum_on_second),
+                ?TDEF_FE(check_done_on_third),
+                ?TDEF_FE(check_specific_revs_first_msg),
+                ?TDEF_FE(check_revs_done_on_agreement),
+                ?TDEF_FE(check_latest_true),
+                ?TDEF_FE(check_ancestor_counted_in_quorum),
+                ?TDEF_FE(check_not_found_counts_for_descendant),
+                ?TDEF_FE(check_worker_error_skipped),
+                ?TDEF_FE(check_quorum_only_counts_valid_responses),
+                ?TDEF_FE(check_empty_list_when_no_workers_reply),
+                ?TDEF_FE(check_node_rev_stored),
+                ?TDEF_FE(check_node_rev_store_head_only),
+                ?TDEF_FE(check_node_rev_store_multiple),
+                ?TDEF_FE(check_node_rev_dont_store_errors),
+                ?TDEF_FE(check_node_rev_store_non_errors),
+                ?TDEF_FE(check_node_rev_store_concatenate),
+                ?TDEF_FE(check_node_rev_store_concantenate_multiple),
+                ?TDEF_FE(check_node_rev_unmodified_on_down_or_exit),
+                ?TDEF_FE(check_not_found_replies_are_removed_when_doc_found),
+                ?TDEF_FE(check_not_found_returned_when_one_of_docs_not_found),
+                ?TDEF_FE(check_not_found_returned_when_doc_not_found),
+                ?TDEF_FE(check_longer_rev_list_returned),
+                ?TDEF_FE(check_longer_rev_list_not_combined),
+                ?TDEF_FE(check_not_found_removed_and_longer_rev_list)
             ]
         }
     }.
 
 % Tests for revs=all
 
-check_empty_response_not_quorum() ->
+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'},
-    ?_assertMatch(
+    ?assertMatch(
         {ok, #state{workers = [W2, W3]}},
         handle_message({ok, []}, W1, state0(all, false))
     ).
 
-check_basic_response() ->
+check_basic_response(_) ->
     % Check that we've handle a response
     W1 = #shard{node = 'node1'},
     W2 = #shard{node = 'node2'},
     W3 = #shard{node = 'node3'},
-    ?_assertMatch(
+    ?assertMatch(
         {ok, #state{reply_count = 1, workers = [W2, W3]}},
         handle_message({ok, [foo1(), bar1()]}, W1, state0(all, false))
     ).
 
-check_finish_quorum() ->
+check_finish_quorum(_) ->
     % Two messages with the same revisions means we're done
-    ?_test(begin
-        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() ->
+    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)).
+
+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'},
-        S0 = state0(all, false),
-        {ok, S1} = handle_message({ok, [foo1(), bar1()]}, W1, S0),
-        Expect = {stop, [bar1(), foo2()]},
-        ok = meck:reset(fabric),
-        ?assertEqual(Expect, handle_message({ok, [foo2(), bar1()]}, W2, S1)),
-        ok = meck:wait(fabric, update_docs, '_', 5000),
-        ?assertMatch(
-            [{_, {fabric, update_docs, [_, _, _]}, _}],
-            meck:history(fabric)
-        )
-    end).
+    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()]},
+    ok = meck:reset(fabric),
+    ?assertEqual(Expect, handle_message({ok, [foo2(), bar1()]}, W2, S1)),
+    ok = meck:wait(fabric, update_docs, '_', 5000),
+    ?assertMatch(
+        [{_, {fabric, update_docs, [_, _, _]}, _}],
+        meck:history(fabric)
+    ).
 
-check_no_quorum_on_second() ->
+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'},
-        S0 = state0(all, false),
-        {ok, S1} = handle_message({ok, [foo1(), bar1()]}, W1, S0),
-        ?assertMatch(
-            {ok, #state{workers = [W3]}},
-            handle_message({ok, [bar1()]}, W2, S1)
-        )
-    end).
+    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(
+        {ok, #state{workers = [W3]}},
+        handle_message({ok, [bar1()]}, W2, S1)
+    ).
 
-check_done_on_third() ->
+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'},
-        S0 = state0(all, false),
-        {ok, S1} = handle_message({ok, [foo1(), bar1()]}, W1, S0),
-        {ok, S2} = handle_message({ok, [bar1()]}, W2, S1),
-        Expect = {stop, [bar1(), foo1()]},
-        ?assertEqual(Expect, handle_message({ok, [bar1()]}, W3, S2))
-    end).
+    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),
+    Expect = {stop, [bar1(), foo1()]},
+    ?assertEqual(Expect, handle_message({ok, [bar1()]}, W3, S2)).
 
 % 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'},
-        S0 = state0(revs(), false),
-        ?assertMatch(
-            {ok, #state{reply_count = 1, workers = [W2, W3]}},
-            handle_message({ok, [foo1(), bar1(), bazNF()]}, W1, S0)
-        )
-    end).
-
-check_revs_done_on_agreement() ->
-    ?_test(begin
-        W1 = #shard{node = 'node1'},
-        W2 = #shard{node = 'node2'},
-        S0 = state0(revs(), false),
-        Msg = {ok, [foo1(), bar1(), bazNF()]},
-        {ok, S1} = handle_message(Msg, W1, S0),
-        Expect = {stop, [bar1(), foo1(), bazNF()]},
-        ?assertEqual(Expect, handle_message(Msg, W2, S1))
-    end).
-
-check_latest_true() ->
-    ?_test(begin
-        W1 = #shard{node = 'node1'},
-        W2 = #shard{node = 'node2'},
-        S0 = state0(revs(), true),
-        Msg1 = {ok, [foo2(), bar1(), bazNF()]},
-        Msg2 = {ok, [foo2(), bar1(), bazNF()]},
-        {ok, S1} = handle_message(Msg1, W1, S0),
-        Expect = {stop, [bar1(), foo2(), bazNF()]},
-        ?assertEqual(Expect, handle_message(Msg2, W2, S1))
-    end).
-
-check_ancestor_counted_in_quorum() ->
-    ?_test(begin
-        W1 = #shard{node = 'node1'},
-        W2 = #shard{node = 'node2'},
-        S0 = state0(revs(), true),
-        Msg1 = {ok, [foo1(), bar1(), bazNF()]},
-        Msg2 = {ok, [foo2(), bar1(), bazNF()]},
-        Expect = {stop, [bar1(), foo2(), bazNF()]},
-
-        % Older first
-        {ok, S1} = handle_message(Msg1, W1, S0),
-        ?assertEqual(Expect, handle_message(Msg2, W2, S1)),
-
-        % Newer first
-        {ok, S2} = handle_message(Msg2, W2, S0),
-        ?assertEqual(Expect, handle_message(Msg1, W1, S2))
-    end).
-
-check_not_found_counts_for_descendant() ->
-    ?_test(begin
-        W1 = #shard{node = 'node1'},
-        W2 = #shard{node = 'node2'},
-        S0 = state0(revs(), true),
-        Msg1 = {ok, [foo1(), bar1(), bazNF()]},
-        Msg2 = {ok, [foo1(), bar1(), baz1()]},
-        Expect = {stop, [bar1(), baz1(), foo1()]},
-
-        % not_found first
-        {ok, S1} = handle_message(Msg1, W1, S0),
-        ?assertEqual(Expect, handle_message(Msg2, W2, S1)),
-
-        % not_found second
-        {ok, S2} = handle_message(Msg2, W2, S0),
-        ?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'},
-        S0 = state0(revs(), true),
-        Msg1 = {ok, [foo1(), bar1(), baz1()]},
-        Msg2 = {rexi_EXIT, reason},
-        Msg3 = {ok, [foo1(), bar1(), baz1()]},
-        Expect = {stop, [bar1(), baz1(), foo1()]},
-
-        {ok, S1} = handle_message(Msg1, W1, S0),
-        {ok, S2} = handle_message(Msg2, W2, S1),
-        ?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'},
-        S0 = state0(revs(), true),
-        Msg1 = {rexi_EXIT, reason},
-        Msg2 = {rexi_EXIT, reason},
-        Msg3 = {ok, [foo1(), bar1(), baz1()]},
-        Expect = {stop, [bar1(), baz1(), foo1()]},
-
-        {ok, S1} = handle_message(Msg1, W1, S0),
-        {ok, S2} = handle_message(Msg2, W2, S1),
-        ?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'},
-        S0 = state0(revs(), true),
-        Msg1 = {rexi_EXIT, reason},
-        Msg2 = {rexi_EXIT, reason},
-        Msg3 = {rexi_DOWN, nodedown, {nil, node()}, nil},
-        Expect = {stop, all_workers_died},
-
-        {ok, S1} = handle_message(Msg1, W1, S0),
-        {ok, S2} = handle_message(Msg2, W2, S1),
-        ?assertEqual(Expect, handle_message(Msg3, W3, S2))
-    end).
-
-check_node_rev_stored() ->
-    ?_test(begin
-        W1 = #shard{node = node1},
-        S0 = state0([], true),
-
-        {ok, S1} = handle_message({ok, [foo1()]}, W1, S0),
-        ?assertEqual([{node1, [{1, <<"foo">>}]}], S1#state.node_revs)
-    end).
-
-check_node_rev_store_head_only() ->
-    ?_test(begin
-        W1 = #shard{node = node1},
-        S0 = state0([], true),
-
-        {ok, S1} = handle_message({ok, [foo2()]}, W1, S0),
-        ?assertEqual([{node1, [{2, <<"foo2">>}]}], S1#state.node_revs)
-    end).
-
-check_node_rev_store_multiple() ->
-    ?_test(begin
-        W1 = #shard{node = node1},
-        S0 = state0([], true),
-
-        {ok, S1} = handle_message({ok, [foo1(), foo2()]}, W1, S0),
-        ?assertEqual(
-            [{node1, [{2, <<"foo2">>}, {1, <<"foo">>}]}],
-            S1#state.node_revs
-        )
-    end).
-
-check_node_rev_dont_store_errors() ->
-    ?_test(begin
-        W1 = #shard{node = node1},
-        S0 = state0([], true),
-
-        {ok, S1} = handle_message({ok, [barNF()]}, W1, S0),
-        ?assertEqual([], S1#state.node_revs)
-    end).
-
-check_node_rev_store_non_errors() ->
-    ?_test(begin
-        W1 = #shard{node = node1},
-        S0 = state0([], true),
-
-        {ok, S1} = handle_message({ok, [foo1(), barNF()]}, W1, S0),
-        ?assertEqual([{node1, [{1, <<"foo">>}]}], S1#state.node_revs)
-    end).
-
-check_node_rev_store_concatenate() ->
-    ?_test(begin
-        W2 = #shard{node = node2},
-        S0 = state0([], true),
-        S1 = S0#state{node_revs = [{node1, [{1, <<"foo">>}]}]},
-
-        {ok, S2} = handle_message({ok, [foo2()]}, W2, S1),
-        ?assertEqual(
-            [{node2, [{2, <<"foo2">>}]}, {node1, [{1, <<"foo">>}]}],
-            S2#state.node_revs
-        )
-    end).
+check_specific_revs_first_msg(_) ->
+    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]}},
+        handle_message({ok, [foo1(), bar1(), bazNF()]}, W1, S0)
+    ).
 
-check_node_rev_store_concantenate_multiple() ->
-    ?_test(begin
-        W2 = #shard{node = node2},
-        S0 = state0([], true),
-        S1 = S0#state{node_revs = [{node1, [{1, <<"foo">>}]}]},
+check_revs_done_on_agreement(_) ->
+    W1 = #shard{node = 'node1'},
+    W2 = #shard{node = 'node2'},
+    S0 = state0(revs(), false),
+    Msg = {ok, [foo1(), bar1(), bazNF()]},
+    {ok, S1} = handle_message(Msg, W1, S0),
+    Expect = {stop, [bar1(), foo1(), bazNF()]},
+    ?assertEqual(Expect, handle_message(Msg, W2, S1)).
 
-        {ok, S2} = handle_message({ok, [foo2(), bar1()]}, W2, S1),
-        ?assertEqual(
-            [
-                {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},
-        S0 = state0([], true),
-        S1 = S0#state{node_revs = [{node1, [{1, <<"foo">>}]}]},
-
-        Down = {rexi_DOWN, nodedown, {nil, node()}, nil},
-        {ok, S2} = handle_message(Down, W2, S1),
-        ?assertEqual(
-            [{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
-        )
-    end).
-
-check_not_found_replies_are_removed_when_doc_found() ->
-    ?_test(begin
-        Replies = replies_to_dict([foo1(), bar1(), fooNF()]),
-        Expect = [bar1(), foo1()],
-        ?assertEqual(Expect, dict_format_replies(Replies))
-    end).
-
-check_not_found_returned_when_one_of_docs_not_found() ->
-    ?_test(begin
-        Replies = replies_to_dict([foo1(), foo2(), barNF()]),
-        Expect = [foo1(), foo2(), barNF()],
-        ?assertEqual(Expect, dict_format_replies(Replies))
-    end).
-
-check_not_found_returned_when_doc_not_found() ->
-    ?_test(begin
-        Replies = replies_to_dict([fooNF(), barNF(), bazNF()]),
-        Expect = [barNF(), bazNF(), fooNF()],
-        ?assertEqual(Expect, dict_format_replies(Replies))
-    end).
-
-check_longer_rev_list_returned() ->
-    ?_test(begin
-        Replies = replies_to_dict([foo2(), foo2stemmed()]),
-        Expect = [foo2()],
-        ?assertEqual(2, length(Replies)),
-        ?assertEqual(Expect, dict_format_replies(Replies))
-    end).
-
-check_longer_rev_list_not_combined() ->
-    ?_test(begin
-        Replies = replies_to_dict([foo2(), foo2stemmed(), bar1()]),
-        Expect = [bar1(), foo2()],
-        ?assertEqual(3, length(Replies)),
-        ?assertEqual(Expect, dict_format_replies(Replies))
-    end).
-
-check_not_found_removed_and_longer_rev_list() ->
-    ?_test(begin
-        Replies = replies_to_dict([foo2(), foo2stemmed(), foo2NF()]),
-        Expect = [foo2()],
-        ?assertEqual(3, length(Replies)),
-        ?assertEqual(Expect, dict_format_replies(Replies))
-    end).
+check_latest_true(_) ->
+    W1 = #shard{node = 'node1'},
+    W2 = #shard{node = 'node2'},
+    S0 = state0(revs(), true),
+    Msg1 = {ok, [foo2(), bar1(), bazNF()]},
+    Msg2 = {ok, [foo2(), bar1(), bazNF()]},
+    {ok, S1} = handle_message(Msg1, W1, S0),
+    Expect = {stop, [bar1(), foo2(), bazNF()]},
+    ?assertEqual(Expect, handle_message(Msg2, W2, S1)).
+
+check_ancestor_counted_in_quorum(_) ->
+    W1 = #shard{node = 'node1'},
+    W2 = #shard{node = 'node2'},
+    S0 = state0(revs(), true),
+    Msg1 = {ok, [foo1(), bar1(), bazNF()]},
+    Msg2 = {ok, [foo2(), bar1(), bazNF()]},
+    Expect = {stop, [bar1(), foo2(), bazNF()]},
+
+    % Older first
+    {ok, S1} = handle_message(Msg1, W1, S0),
+    ?assertEqual(Expect, handle_message(Msg2, W2, S1)),
+
+    % Newer first
+    {ok, S2} = handle_message(Msg2, W2, S0),
+    ?assertEqual(Expect, handle_message(Msg1, W1, S2)).
+
+check_not_found_counts_for_descendant(_) ->
+    W1 = #shard{node = 'node1'},
+    W2 = #shard{node = 'node2'},
+    S0 = state0(revs(), true),
+    Msg1 = {ok, [foo1(), bar1(), bazNF()]},
+    Msg2 = {ok, [foo1(), bar1(), baz1()]},
+    Expect = {stop, [bar1(), baz1(), foo1()]},
+
+    % not_found first
+    {ok, S1} = handle_message(Msg1, W1, S0),
+    ?assertEqual(Expect, handle_message(Msg2, W2, S1)),
+
+    % not_found second
+    {ok, S2} = handle_message(Msg2, W2, S0),
+    ?assertEqual(Expect, handle_message(Msg1, W1, S2)).
+
+check_worker_error_skipped(_) ->
+    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},
+    Msg3 = {ok, [foo1(), bar1(), baz1()]},
+    Expect = {stop, [bar1(), baz1(), foo1()]},
+
+    {ok, S1} = handle_message(Msg1, W1, S0),
+    {ok, S2} = handle_message(Msg2, W2, S1),
+    ?assertEqual(Expect, handle_message(Msg3, W3, S2)).
+
+check_quorum_only_counts_valid_responses(_) ->
+    W1 = #shard{node = 'node1'},
+    W2 = #shard{node = 'node2'},
+    W3 = #shard{node = 'node3'},
+    S0 = state0(revs(), true),
+    Msg1 = {rexi_EXIT, reason},
+    Msg2 = {rexi_EXIT, reason},
+    Msg3 = {ok, [foo1(), bar1(), baz1()]},
+    Expect = {stop, [bar1(), baz1(), foo1()]},
+
+    {ok, S1} = handle_message(Msg1, W1, S0),
+    {ok, S2} = handle_message(Msg2, W2, S1),
+    ?assertEqual(Expect, handle_message(Msg3, W3, S2)).
+
+check_empty_list_when_no_workers_reply(_) ->
+    W1 = #shard{node = 'node1'},
+    W2 = #shard{node = 'node2'},
+    W3 = #shard{node = 'node3'},
+    S0 = state0(revs(), true),
+    Msg1 = {rexi_EXIT, reason},
+    Msg2 = {rexi_EXIT, reason},
+    Msg3 = {rexi_DOWN, nodedown, {nil, node()}, nil},
+    Expect = {stop, all_workers_died},
+
+    {ok, S1} = handle_message(Msg1, W1, S0),
+    {ok, S2} = handle_message(Msg2, W2, S1),
+    ?assertEqual(Expect, handle_message(Msg3, W3, S2)).
+
+check_node_rev_stored(_) ->
+    W1 = #shard{node = node1},
+    S0 = state0([], true),
+
+    {ok, S1} = handle_message({ok, [foo1()]}, W1, S0),
+    ?assertEqual([{node1, [{1, <<"foo">>}]}], S1#state.node_revs).
+
+check_node_rev_store_head_only(_) ->
+    W1 = #shard{node = node1},
+    S0 = state0([], true),
+
+    {ok, S1} = handle_message({ok, [foo2()]}, W1, S0),
+    ?assertEqual([{node1, [{2, <<"foo2">>}]}], S1#state.node_revs).
+
+check_node_rev_store_multiple(_) ->
+    W1 = #shard{node = node1},
+    S0 = state0([], true),
+
+    {ok, S1} = handle_message({ok, [foo1(), foo2()]}, W1, S0),
+    ?assertEqual(
+        [{node1, [{2, <<"foo2">>}, {1, <<"foo">>}]}],
+        S1#state.node_revs
+    ).
+
+check_node_rev_dont_store_errors(_) ->
+    W1 = #shard{node = node1},
+    S0 = state0([], true),
+
+    {ok, S1} = handle_message({ok, [barNF()]}, W1, S0),
+    ?assertEqual([], S1#state.node_revs).
+
+check_node_rev_store_non_errors(_) ->
+    W1 = #shard{node = node1},
+    S0 = state0([], true),
+
+    {ok, S1} = handle_message({ok, [foo1(), barNF()]}, W1, S0),
+    ?assertEqual([{node1, [{1, <<"foo">>}]}], S1#state.node_revs).
+
+check_node_rev_store_concatenate(_) ->
+    W2 = #shard{node = node2},
+    S0 = state0([], true),
+    S1 = S0#state{node_revs = [{node1, [{1, <<"foo">>}]}]},
+
+    {ok, S2} = handle_message({ok, [foo2()]}, W2, S1),
+    ?assertEqual(
+        [{node2, [{2, <<"foo2">>}]}, {node1, [{1, <<"foo">>}]}],
+        S2#state.node_revs
+    ).
+
+check_node_rev_store_concantenate_multiple(_) ->
+    W2 = #shard{node = node2},
+    S0 = state0([], true),
+    S1 = S0#state{node_revs = [{node1, [{1, <<"foo">>}]}]},
+
+    {ok, S2} = handle_message({ok, [foo2(), bar1()]}, W2, S1),
+    ?assertEqual(
+        [
+            {node2, [{1, <<"bar">>}, {2, <<"foo2">>}]},
+            {node1, [{1, <<"foo">>}]}
+        ],
+        S2#state.node_revs
+    ).
+
+check_node_rev_unmodified_on_down_or_exit(_) ->
+    W2 = #shard{node = node2},
+    S0 = state0([], true),
+    S1 = S0#state{node_revs = [{node1, [{1, <<"foo">>}]}]},
+
+    Down = {rexi_DOWN, nodedown, {nil, node()}, nil},
+    {ok, S2} = handle_message(Down, W2, S1),
+    ?assertEqual(
+        [{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
+    ).
+
+check_not_found_replies_are_removed_when_doc_found(_) ->
+    Replies = replies_to_dict([foo1(), bar1(), fooNF()]),
+    Expect = [bar1(), foo1()],
+    ?assertEqual(Expect, dict_format_replies(Replies)).
+
+check_not_found_returned_when_one_of_docs_not_found(_) ->
+    Replies = replies_to_dict([foo1(), foo2(), barNF()]),
+    Expect = [foo1(), foo2(), barNF()],
+    ?assertEqual(Expect, dict_format_replies(Replies)).
+
+check_not_found_returned_when_doc_not_found(_) ->
+    Replies = replies_to_dict([fooNF(), barNF(), bazNF()]),
+    Expect = [barNF(), bazNF(), fooNF()],
+    ?assertEqual(Expect, dict_format_replies(Replies)).
+
+check_longer_rev_list_returned(_) ->
+    Replies = replies_to_dict([foo2(), foo2stemmed()]),
+    Expect = [foo2()],
+    ?assertEqual(2, length(Replies)),
+    ?assertEqual(Expect, dict_format_replies(Replies)).
+
+check_longer_rev_list_not_combined(_) ->
+    Replies = replies_to_dict([foo2(), foo2stemmed(), bar1()]),
+    Expect = [bar1(), foo2()],
+    ?assertEqual(3, length(Replies)),
+    ?assertEqual(Expect, dict_format_replies(Replies)).
+
+check_not_found_removed_and_longer_rev_list(_) ->
+    Replies = replies_to_dict([foo2(), foo2stemmed(), foo2NF()]),
+    Expect = [foo2()],
+    ?assertEqual(3, length(Replies)),
+    ?assertEqual(Expect, dict_format_replies(Replies)).
 
 replies_to_dict(Replies) ->
     [reply_to_element(R) || R <- Replies].