summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Vatamaniuc <vatamane@apache.org>2022-09-29 10:13:41 -0400
committerNick Vatamaniuc <nickva@users.noreply.github.com>2022-09-29 12:08:20 -0400
commit4f852a69e59b42b8c7cb3ec0612acb7e9f4f2ab2 (patch)
treed67341de35b9d7e1e9b9e5ef0edc125a8ab09d4e
parent1407a51ee6898c39eeb551a9c3cd9d69751e7baa (diff)
downloadcouchdb-4f852a69e59b42b8c7cb3ec0612acb7e9f4f2ab2.tar.gz
Clean up fabric_doc_open_revs tests
Use the TDEF_FE macro to save 2 lines per test.
-rw-r--r--src/fabric/src/fabric_doc_open_revs.erl626
1 files 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].