You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by da...@apache.org on 2018/04/27 18:27:08 UTC
[couchdb] 05/05: [SQUERGE] couch_db_purge_docs_tests cleanup
This is an automated email from the ASF dual-hosted git repository.
davisp pushed a commit to branch COUCHDB-3326-clustered-purge-davisp-refactor-2
in repository https://gitbox.apache.org/repos/asf/couchdb.git
commit 8f3d668e167c155291545581f23990c1b1f562b0
Author: Paul J. Davis <pa...@gmail.com>
AuthorDate: Fri Apr 27 13:25:10 2018 -0500
[SQUERGE] couch_db_purge_docs_tests cleanup
I've taken some liberty cleaning up the tests for purges in this module
by using a few helper functions and some minor reformatting. Currently
the repeated docid test is failing because there's a bug in the
purge_docs logic in couch_db_updater where its not accounting for the
fact that a user may have specified a doc id multiple times.
As for doc updates we'll have to apply purges from the first purge infos
and return responses that correspond to which updates actually took
effect.
---
src/couch/test/couch_db_purge_docs_tests.erl | 1192 ++++++++++++++------------
1 file changed, 654 insertions(+), 538 deletions(-)
diff --git a/src/couch/test/couch_db_purge_docs_tests.erl b/src/couch/test/couch_db_purge_docs_tests.erl
index 6f8c5d9..3486695 100644
--- a/src/couch/test/couch_db_purge_docs_tests.erl
+++ b/src/couch/test/couch_db_purge_docs_tests.erl
@@ -16,14 +16,8 @@
-include_lib("couch/include/couch_db.hrl").
-setup() ->
- DbName = ?tempdb(),
- {ok, _Db} = create_db(DbName),
- DbName.
+-define(REV_DEPTH, 100).
-teardown(DbName) ->
- delete_db(DbName),
- ok.
couch_db_purge_docs_test_() ->
{
@@ -31,584 +25,706 @@ couch_db_purge_docs_test_() ->
[
{
setup,
- fun test_util:start_couch/0, fun test_util:stop_couch/1,
- [couch_db_purge_docs()]
+ fun test_util:start_couch/0,
+ fun test_util:stop_couch/1,
+ [
+ couch_db_purge_docs()
+ ]
},
- purge_with_replication()
+ {
+ setup,
+ fun start_with_replicator/0,
+ fun test_util:stop_couch/1,
+ [
+ couch_db_purge_with_replication()
+ ]
+ }
]
-
}.
couch_db_purge_docs() ->
{
- foreach,
- fun setup/0, fun teardown/1,
- [
- fun test_purge_2_to_purge_3/1,
- fun test_purge_all/1,
- fun test_purge_some/1,
- fun test_purge_none/1,
- fun test_purge_missing_docid/1,
- fun test_purge_repeated_docid/1,
- fun test_purge_repeated_rev/1, % improving
- fun test_purge_partial/1,
- fun test_all_removal_purges/1,
- fun test_purge_invalid_rev/1,
- fun test_purge_duplicate_UUID/1,
- fun purge_id_not_exist/1,
- fun purge_non_leaf_rev/1,
- fun purge_deep_tree/1
- ]
+ foreach,
+ fun setup/0,
+ fun teardown/1,
+ [
+ fun test_purge_2_to_purge_3/1,
+ fun test_purge_all/1,
+ fun test_purge_some/1,
+ fun test_purge_none/1,
+ fun test_purge_missing_docid/1,
+ fun test_purge_repeated_docid/1,
+ fun test_purge_repeated_rev/1,
+ fun test_purge_partial/1,
+ fun test_all_removal_purges/1,
+ fun test_purge_invalid_rev/1,
+ fun test_purge_duplicate_UUID/1,
+ fun test_purge_id_not_exist/1,
+ fun test_purge_non_leaf_rev/1,
+ fun test_purge_deep_tree/1
+ ]
+ }.
+
+
+couch_db_purge_with_replication() ->
+ {
+ foreach,
+ fun setup_replicator/0,
+ fun teardown_replicator/1,
+ [
+ fun test_purge_with_replication/1
+ ]
}.
+start_with_replicator() ->
+ test_util:start_couch([couch_replicator]).
+
+
+setup() ->
+ DbName = ?tempdb(),
+ {ok, _Db} = create_db(DbName),
+ DbName.
+
+
+teardown(DbName) ->
+ delete_db(DbName),
+ ok.
+
+
+setup_replicator() ->
+ Source = ?tempdb(),
+ Target = ?tempdb(),
+ {ok, _} = create_db(Source),
+ {ok, _} = create_db(Target),
+ {Source, Target}.
+
+
+teardown_replicator({Source, Target}) ->
+ delete_db(Source),
+ delete_db(Target),
+ ok.
+
+
test_purge_2_to_purge_3(DbName) ->
- ?_test(
- begin
- {ok, Db} = couch_db:open_int(DbName, []),
- Doc1 = {[{<<"_id">>, <<"foo1">>}, {<<"vsn">>, 1.1}]},
- {ok, Rev} = save_doc(Db, Doc1),
- couch_db:ensure_full_commit(Db),
- {ok, Db2} = couch_db:reopen(Db),
- UUID = couch_uuids:new(),
- {ok, [{ok, PRevs}]} = couch_db:purge_docs(
- Db2, [{UUID, <<"foo1">>, [Rev]}]
- ),
- ?assertEqual([Rev], PRevs),
- {ok, Db3} = couch_db:reopen(Db2),
- {ok, _PIdsRevs} = couch_db:fold_purge_infos(
- Db3, 0, fun fold_fun/2, [], []),
- ?assertEqual(0, couch_db_engine:get_doc_count(Db3)),
- ?assertEqual(1, couch_db_engine:get_purge_seq(Db3))
- end).
+ ?_test(begin
+ {ok, Rev} = save_doc(DbName, {[{'_id', foo1}, {vsn, 1.1}]}),
+
+ PurgeInfos = [
+ {uuid(), <<"foo1">>, [Rev]}
+ ],
+
+ {ok, [{ok, PRevs}]} = purge(DbName, PurgeInfos),
+ ?assertEqual([Rev], PRevs),
+
+ assertProps(DbName, [
+ {doc_count, 0},
+ {purge_seq, 1},
+ {purge_infos, PurgeInfos}
+ ])
+ end).
test_purge_all(DbName) ->
- ?_test(
- begin
- {ok, Db} = couch_db:open_int(DbName, []),
- Doc1 = {[{<<"_id">>, <<"foo1">>}, {<<"vsn">>, 1.1}]},
- Doc2 = {[{<<"_id">>, <<"foo2">>}, {<<"vsn">>, 1.2}]},
- {ok, Rev} = save_doc(Db, Doc1),
- {ok, Rev2} = save_doc(Db, Doc2),
- couch_db:ensure_full_commit(Db),
-
- {ok, Db2} = couch_db:reopen(Db),
- ?assertEqual(2, couch_db_engine:get_doc_count(Db2)),
- ?assertEqual(0, couch_db_engine:get_del_doc_count(Db2)),
- ?assertEqual(2, couch_db_engine:get_update_seq(Db2)),
- ?assertEqual(0, couch_db_engine:get_purge_seq(Db2)),
-
- UUID = couch_uuids:new(), UUID2 = couch_uuids:new(),
- {ok, [{ok, PRevs}, {ok, PRevs2}]} = couch_db:purge_docs(
- Db2, [{UUID, <<"foo1">>, [Rev]}, {UUID2, <<"foo2">>, [Rev2]}]
- ),
-
- ?assertEqual([Rev], PRevs),
- ?assertEqual([Rev2], PRevs2),
-
- {ok, Db3} = couch_db:reopen(Db2),
- {ok, PIdsRevs} = couch_db:fold_purge_infos(
- Db3, 0, fun fold_fun/2, [], []),
- ?assertEqual(0, couch_db_engine:get_doc_count(Db3)),
- ?assertEqual(0, couch_db_engine:get_del_doc_count(Db3)),
- ?assertEqual(3, couch_db_engine:get_update_seq(Db3)),
- ?assertEqual(2, couch_db_engine:get_purge_seq(Db3)),
- ?assertEqual([{<<"foo2">>, [Rev2]}, {<<"foo1">>, [Rev]}], PIdsRevs)
- end).
+ ?_test(begin
+ {ok, [Rev1, Rev2]} = save_docs(DbName, [
+ {[{'_id', foo1}, {vsn, 1.1}]},
+ {[{'_id', foo2}, {vsn, 1.2}]}
+ ]),
+
+ assertProps(DbName, [
+ {doc_count, 2},
+ {del_doc_count, 0},
+ {update_seq, 2},
+ {purge_seq, 0},
+ {purge_infos, []}
+ ]),
+
+ PurgeInfos = [
+ {uuid(), <<"foo1">>, [Rev1]},
+ {uuid(), <<"foo2">>, [Rev2]}
+ ],
+
+ {ok, [{ok, PRevs1}, {ok, PRevs2}]} = purge(DbName, PurgeInfos),
+
+ ?assertEqual([Rev1], PRevs1),
+ ?assertEqual([Rev2], PRevs2),
+
+ assertProps(DbName, [
+ {doc_count, 0},
+ {del_doc_count, 0},
+ {update_seq, 3},
+ {purge_seq, 2},
+ {purge_infos, PurgeInfos}
+ ])
+ end).
test_all_removal_purges(DbName) ->
- ?_test(
- begin
- {ok, Db0} = couch_db:open_int(DbName, []),
- Doc0 = {[{<<"_id">>,<<"foo">>}, {<<"vsn">>, 1}]},
- {ok, Rev} = save_doc(Db0, Doc0),
- couch_db:ensure_full_commit(Db0),
- {ok, Db1} = couch_db:reopen(Db0),
-
- Doc1 = {[
- {<<"_id">>, <<"foo">>}, {<<"vsn">>, 2},
- {<<"_rev">>, couch_doc:rev_to_str(Rev)},
- {<<"_deleted">>, true}]
- },
- {ok, Rev2} = save_doc(Db1, Doc1),
- couch_db:ensure_full_commit(Db1),
-
- {ok, Db2} = couch_db:reopen(Db1),
- {ok, PIdsRevs1} = couch_db:fold_purge_infos(
- Db2, 0, fun fold_fun/2, [], []),
- ?assertEqual(0, couch_db_engine:get_doc_count(Db2)),
- ?assertEqual(1, couch_db_engine:get_del_doc_count(Db2)),
- ?assertEqual(2, couch_db_engine:get_update_seq(Db2)),
- ?assertEqual(0, couch_db_engine:get_purge_seq(Db2)),
- ?assertEqual([], PIdsRevs1),
-
- UUID = couch_uuids:new(),
- {ok, [{ok, PRevs}]} = couch_db:purge_docs(
- Db2, [{UUID, <<"foo">>, [Rev2]}]),
- ?assertEqual([Rev2], PRevs),
-
- {ok, Db3} = couch_db:reopen(Db2),
- {ok, PIdsRevs2} = couch_db:fold_purge_infos(
- Db3, 0, fun fold_fun/2, [], []),
- ?assertEqual(0, couch_db_engine:get_doc_count(Db3)),
- ?assertEqual(0, couch_db_engine:get_del_doc_count(Db3)),
- ?assertEqual(3, couch_db_engine:get_update_seq(Db3)),
- ?assertEqual(1, couch_db_engine:get_purge_seq(Db3)),
- ?assertEqual([{<<"foo">>, [Rev2]}], PIdsRevs2)
- end).
+ ?_test(begin
+ {ok, Rev1} = save_doc(DbName, {[{'_id', foo}, {vsn, 1}]}),
+ Update = {[
+ {<<"_id">>, <<"foo">>},
+ {<<"_rev">>, couch_doc:rev_to_str(Rev1)},
+ {<<"_deleted">>, true},
+ {<<"vsn">>, 2}
+ ]},
+ {ok, Rev2} = save_doc(DbName, Update),
+
+ assertProps(DbName, [
+ {doc_count, 0},
+ {del_doc_count, 1},
+ {update_seq, 2},
+ {purge_seq, 0},
+ {purge_infos, []}
+ ]),
+
+ PurgeInfos = [
+ {uuid(), <<"foo">>, [Rev2]}
+ ],
+
+ {ok, [{ok, PRevs}]} = purge(DbName, PurgeInfos),
+
+ ?assertEqual([Rev2], PRevs),
+
+ assertProps(DbName, [
+ {doc_count, 0},
+ {del_doc_count, 0},
+ {update_seq, 3},
+ {purge_seq, 1},
+ {purge_infos, PurgeInfos}
+ ])
+ end).
test_purge_some(DbName) ->
- ?_test(
- begin
- {ok, Db} = couch_db:open_int(DbName, []),
- Doc1 = {[{<<"_id">>, <<"foo1">>}, {<<"vsn">>, 1}]},
- Doc2 = {[{<<"_id">>, <<"foo2">>}, {<<"vsn">>, 2}]},
- {ok, Rev} = save_doc(Db, Doc1),
- {ok, _Rev2} = save_doc(Db, Doc2),
- couch_db:ensure_full_commit(Db),
-
- {ok, Db2} = couch_db:reopen(Db),
- ?assertEqual(2, couch_db_engine:get_doc_count(Db2)),
- ?assertEqual(0, couch_db_engine:get_del_doc_count(Db2)),
- ?assertEqual(2, couch_db_engine:get_update_seq(Db2)),
- ?assertEqual(0, couch_db_engine:get_purge_seq(Db2)),
-
- UUID = couch_uuids:new(),
- {ok, [{ok, PRevs}]} = couch_db:purge_docs(Db2,
- [{UUID, <<"foo1">>, [Rev]}]),
- ?assertEqual([Rev], PRevs),
-
- {ok, Db3} = couch_db:reopen(Db2),
- {ok, PIdsRevs} = couch_db:fold_purge_infos(
- Db3, 0, fun fold_fun/2, [], []),
- ?assertEqual(1, couch_db_engine:get_doc_count(Db3)),
- ?assertEqual(0, couch_db_engine:get_del_doc_count(Db3)),
- ?assertEqual(3, couch_db_engine:get_update_seq(Db3)),
- ?assertEqual(1, couch_db_engine:get_purge_seq(Db3)),
- ?assertEqual([{<<"foo1">>, [Rev]}], PIdsRevs)
- end).
+ ?_test(begin
+ {ok, [Rev1, _Rev2]} = save_docs(DbName, [
+ {[{'_id', foo1}, {vsn, 1}]},
+ {[{'_id', foo2}, {vsn, 2}]}
+ ]),
+
+ assertProps(DbName, [
+ {doc_count, 2},
+ {del_doc_count, 0},
+ {update_seq, 2},
+ {purge_seq, 0},
+ {purge_infos, []}
+ ]),
+
+ PurgeInfos = [
+ {uuid(), <<"foo1">>, [Rev1]}
+ ],
+ {ok, [{ok, PRevs}]} = purge(DbName, PurgeInfos),
+
+ ?assertEqual([Rev1], PRevs),
+
+ assertProps(DbName, [
+ {doc_count, 1},
+ {del_doc_count, 0},
+ {update_seq, 3},
+ {purge_seq, 1},
+ {purge_infos, PurgeInfos}
+ ])
+ end).
test_purge_none(DbName) ->
- ?_test(
- begin
- {ok, Db} = couch_db:open_int(DbName, []),
- Doc1 = {[{<<"_id">>, <<"foo1">>}, {<<"vsn">>, 1}]},
- Doc2 = {[{<<"_id">>, <<"foo2">>}, {<<"vsn">>, 2}]},
- {ok, _Rev} = save_doc(Db, Doc1),
- {ok, _Rev2} = save_doc(Db, Doc2),
- couch_db:ensure_full_commit(Db),
-
- {ok, Db2} = couch_db:reopen(Db),
- ?assertEqual(2, couch_db_engine:get_doc_count(Db2)),
- ?assertEqual(0, couch_db_engine:get_del_doc_count(Db2)),
- ?assertEqual(2, couch_db_engine:get_update_seq(Db2)),
- ?assertEqual(0, couch_db_engine:get_purge_seq(Db2)),
-
- {ok, []} = couch_db:purge_docs(Db2, []),
-
- {ok, Db3} = couch_db:reopen(Db2),
- {ok, PIdsRevs} = couch_db:fold_purge_infos(
- Db3, 0, fun fold_fun/2, [], []),
- ?assertEqual(2, couch_db_engine:get_doc_count(Db3)),
- ?assertEqual(0, couch_db_engine:get_del_doc_count(Db3)),
- ?assertEqual(2, couch_db_engine:get_update_seq(Db3)),
- ?assertEqual(0, couch_db_engine:get_purge_seq(Db3)),
- ?assertEqual([], PIdsRevs)
- end).
+ ?_test(begin
+ {ok, [_Rev1, _Rev2]} = save_docs(DbName, [
+ {[{'_id', foo1}, {vsn, 1}]},
+ {[{'_id', foo2}, {vsn, 2}]}
+ ]),
+
+ assertProps(DbName, [
+ {doc_count, 2},
+ {del_doc_count, 0},
+ {update_seq, 2},
+ {purge_seq, 0},
+ {purge_infos, []}
+ ]),
+
+ {ok, []} = purge(DbName, []),
+
+ assertProps(DbName, [
+ {doc_count, 2},
+ {del_doc_count, 0},
+ {update_seq, 2},
+ {purge_seq, 0},
+ {purge_infos, []}
+ ])
+ end).
test_purge_missing_docid(DbName) ->
- ?_test(
- begin
- {ok, Db} = couch_db:open_int(DbName, []),
- Doc1 = {[{<<"_id">>, <<"foo1">>}, {<<"vsn">>, 1}]},
- Doc2 = {[{<<"_id">>, <<"foo2">>}, {<<"vsn">>, 2}]},
- {ok, Rev} = save_doc(Db, Doc1),
- {ok, _Rev2} = save_doc(Db, Doc2),
- couch_db:ensure_full_commit(Db),
-
- {ok, Db2} = couch_db:reopen(Db),
- ?assertEqual(2, couch_db_engine:get_doc_count(Db2)),
- ?assertEqual(0, couch_db_engine:get_del_doc_count(Db2)),
- ?assertEqual(2, couch_db_engine:get_update_seq(Db2)),
- ?assertEqual(0, couch_db_engine:get_purge_seq(Db2)),
-
- UUID = couch_uuids:new(),
- {ok, [{ok, PRevs}]} = couch_db:purge_docs(Db2,
- [{UUID, <<"">>, [Rev]}]),
- ?assertEqual([], PRevs),
-
- {ok, Db3} = couch_db:reopen(Db2),
- {ok, _PIdsRevs} = couch_db:fold_purge_infos(
- Db3, 0, fun fold_fun/2, [], []),
- ?assertEqual(2, couch_db_engine:get_doc_count(Db3)),
- ?assertEqual(0, couch_db_engine:get_del_doc_count(Db3)),
- ?assertEqual(2, couch_db_engine:get_update_seq(Db3)),
- ?assertEqual(0, couch_db_engine:get_purge_seq(Db3))
- end).
+ ?_test(begin
+ {ok, [Rev1, _Rev2]} = save_docs(DbName, [
+ {[{'_id', foo1}, {vsn, 1}]},
+ {[{'_id', foo2}, {vsn, 2}]}
+ ]),
+
+ assertProps(DbName, [
+ {doc_count, 2},
+ {del_doc_count, 0},
+ {update_seq, 2},
+ {purge_seq, 0},
+ {purge_infos, []}
+ ]),
+
+ PurgeInfos = [
+ {uuid(), <<"baz">>, [Rev1]}
+ ],
+
+ {ok, [{ok, []}]} = purge(DbName, PurgeInfos),
+
+ assertProps(DbName, [
+ {doc_count, 2},
+ {del_doc_count, 0},
+ {update_seq, 3},
+ {purge_seq, 1},
+ {purge_infos, PurgeInfos}
+ ])
+ end).
test_purge_repeated_docid(DbName) ->
- ?_test(
- begin
- {ok, Db} = couch_db:open_int(DbName, []),
- Doc1 = {[{<<"_id">>, <<"foo1">>}, {<<"vsn">>, 1}]},
- Doc2 = {[{<<"_id">>, <<"foo2">>}, {<<"vsn">>, 2}]},
- {ok, Rev} = save_doc(Db, Doc1),
- {ok, _Rev2} = save_doc(Db, Doc2),
- couch_db:ensure_full_commit(Db),
-
- {ok, Db2} = couch_db:reopen(Db),
- ?assertEqual(2, couch_db_engine:get_doc_count(Db2)),
- ?assertEqual(0, couch_db_engine:get_del_doc_count(Db2)),
- ?assertEqual(2, couch_db_engine:get_update_seq(Db2)),
- ?assertEqual(0, couch_db_engine:get_purge_seq(Db2)),
-
- UUID = couch_uuids:new(),
- UUID2 = couch_uuids:new(),
- {ok, [{ok, PRevs}, {ok, PRevs}]} = couch_db:purge_docs(Db2,
- [{UUID, <<"foo1">>, [Rev]}, {UUID2, <<"foo1">>, [Rev]}]
- ),
- ?assertEqual([Rev], PRevs),
-
- {ok, Db3} = couch_db:reopen(Db2),
- {ok, _PIdsRevs} = couch_db:fold_purge_infos(
- Db3, 0, fun fold_fun/2, [], []),
- ?assertEqual(1, couch_db_engine:get_doc_count(Db3)),
- ?assertEqual(0, couch_db_engine:get_del_doc_count(Db3)),
- ?assertEqual(3, couch_db_engine:get_update_seq(Db3)),
- ?assertEqual(2, couch_db_engine:get_purge_seq(Db3))
- end).
-
-
-purge_id_not_exist(DbName) ->
- ?_test(
- begin
- {ok, Db} = couch_db:open_int(DbName, []),
- UUID = couch_uuids:new(),
- {ok, [{ok, PRevs}]} = couch_db:purge_docs(Db,
- [{UUID, <<"foo">>, [{0, <<0>>}]}]),
- ?assertEqual([], PRevs),
-
- {ok, Db2} = couch_db:reopen(Db),
- {ok, PIdsRevs} = couch_db:fold_purge_infos(
- Db2, 0, fun fold_fun/2, [], []),
- ?assertEqual(0, couch_db_engine:get_doc_count(Db2)),
- ?assertEqual(0, couch_db_engine:get_del_doc_count(Db2)),
- ?assertEqual(0, couch_db_engine:get_update_seq(Db2)),
- ?assertEqual(0, couch_db_engine:get_purge_seq(Db2)),
- ?assertEqual([], PIdsRevs)
- end).
-
-
-purge_non_leaf_rev(DbName) ->
- ?_test(
- begin
- {ok, Db} = couch_db:open_int(DbName, []),
- Doc0 = {[{<<"_id">>, <<"foo">>}, {<<"vsn">>, 1}]},
- {ok, Rev} = save_doc(Db, Doc0),
- couch_db:ensure_full_commit(Db),
- {ok, Db2} = couch_db:reopen(Db),
-
- Doc1 = {[
- {<<"_id">>, <<"foo">>}, {<<"vsn">>, 2},
- {<<"_rev">>, couch_doc:rev_to_str(Rev)}
- ]},
- {ok, _Rev2} = save_doc(Db2, Doc1),
- couch_db:ensure_full_commit(Db2),
- {ok, Db3} = couch_db:reopen(Db2),
-
- UUID = couch_uuids:new(),
- {ok, [{ok, PRevs}]} = couch_db:purge_docs(Db3,
- [{UUID, <<"foo">>, [Rev]}]),
- ?assertEqual([], PRevs),
-
- {ok, Db4} = couch_db:reopen(Db3),
- {ok, PIdsRevs} = couch_db:fold_purge_infos(
- Db4, 0, fun fold_fun/2, [], []
- ),
- ?assertEqual(1, couch_db_engine:get_doc_count(Db4)),
- ?assertEqual(2, couch_db_engine:get_update_seq(Db4)),
- ?assertEqual(0, couch_db_engine:get_purge_seq(Db4)),
- ?assertEqual([], PIdsRevs)
- end).
+ ?_test(begin
+ {ok, [Rev1, _Rev2]} = save_docs(DbName, [
+ {[{'_id', foo1}, {vsn, 1}]},
+ {[{'_id', foo2}, {vsn, 2}]}
+ ]),
+
+ assertProps(DbName, [
+ {doc_count, 2},
+ {del_doc_count, 0},
+ {update_seq, 2},
+ {purge_seq, 0},
+ {changes, 1},
+ {purge_infos, []}
+ ]),
+
+ PurgeInfos = [
+ {uuid(), <<"foo1">>, [Rev1]},
+ {uuid(), <<"foo1">>, [Rev1]}
+ ],
+
+ {ok, Resp} = purge(DbName, PurgeInfos),
+ %?assertEqual([{ok, [Rev1]}, {ok, []}], Resp),
+
+ assertProps(DbName, [
+ {doc_count, 1},
+ {del_doc_count, 0},
+ {update_seq, 3},
+ {purge_seq, 2},
+ {changes, 1},
+ {purge_infos, PurgeInfos}
+ ])
+ end).
+
+
+test_purge_id_not_exist(DbName) ->
+ ?_test(begin
+ PurgeInfos = [
+ {uuid(), <<"foo">>, [{0, <<0>>}]}
+ ],
+
+ {ok, [{ok, PRevs}]} = purge(DbName, PurgeInfos),
+ ?assertEqual([], PRevs),
+
+ assertProps(DbName, [
+ {doc_count, 0},
+ {del_doc_count, 0},
+ {update_seq, 1},
+ {purge_seq, 1},
+ {purge_infos, PurgeInfos}
+ ])
+ end).
+
+
+test_purge_non_leaf_rev(DbName) ->
+ ?_test(begin
+ {ok, Rev1} = save_doc(DbName, {[{'_id', foo}, {vsn, 1}]}),
+ Update = {[
+ {'_id', foo},
+ {'_rev', couch_doc:rev_to_str(Rev1)},
+ {vsn, 2}
+ ]},
+ {ok, _Rev2} = save_doc(DbName, Update),
+
+ PurgeInfos = [
+ {couch_uuids:new(), <<"foo">>, [Rev1]}
+ ],
+
+ {ok, [{ok, PRevs}]} = purge(DbName, PurgeInfos),
+ ?assertEqual([], PRevs),
+
+ assertProps(DbName, [
+ {doc_count, 1},
+ {del_doc_count, 0},
+ {update_seq, 3},
+ {purge_seq, 1},
+ {purge_infos, PurgeInfos}
+ ])
+ end).
test_purge_invalid_rev(DbName) ->
- ?_test(
- begin
- {ok, Db} = couch_db:open_int(DbName, []),
- Doc1 = {[{<<"_id">>, <<"foo1">>}, {<<"vsn">>, 1}]},
- Doc2 = {[{<<"_id">>, <<"foo2">>}, {<<"vsn">>, 2}]},
- {ok, _Rev} = save_doc(Db, Doc1),
- {ok, Rev2} = save_doc(Db, Doc2),
- couch_db:ensure_full_commit(Db),
- {ok, Db2} = couch_db:reopen(Db),
-
- UUID = couch_uuids:new(),
- {ok, [{ok, PRevs}]} = couch_db:purge_docs(Db2,
- [{UUID, <<"foo1">>, [Rev2]}]),
- ?assertEqual([], PRevs),
-
- {ok, Db3} = couch_db:reopen(Db2),
- {ok, PIdsRevs} = couch_db:fold_purge_infos(
- Db3, 0, fun fold_fun/2, [], []
- ),
- ?assertEqual(2, couch_db_engine:get_doc_count(Db3)),
- ?assertEqual(2, couch_db_engine:get_update_seq(Db3)),
- ?assertEqual(0, couch_db_engine:get_purge_seq(Db3)),
- ?assertEqual([], PIdsRevs)
- end).
+ ?_test(begin
+ {ok, [_Rev1, Rev2]} = save_docs(DbName, [
+ {[{'_id', foo1}, {vsn, 1}]},
+ {[{'_id', foo2}, {vsn, 2}]}
+ ]),
+
+ PurgeInfos = [
+ {uuid(), <<"foo1">>, [Rev2]}
+ ],
+
+ {ok, [{ok, PRevs}]} = purge(DbName, PurgeInfos),
+ ?assertEqual([], PRevs),
+
+ assertProps(DbName, [
+ {doc_count, 2},
+ {del_doc_count, 0},
+ {update_seq, 3},
+ {purge_seq, 1},
+ {purge_infos, PurgeInfos}
+ ])
+ end).
test_purge_partial(DbName) ->
- ?_test(
- begin
- {ok, Db} = couch_db:open_int(DbName, []),
- Doc = {[{<<"_id">>, <<"foo">>}, {<<"vsn">>, <<"v1.1">>}]},
- {ok, Rev} = save_doc(Db, Doc),
- couch_db:ensure_full_commit(Db),
- {ok, Db2} = couch_db:reopen(Db),
-
- % create a conflict
- DocConflict = #doc{
- id = <<"foo">>,
- revs = {1, [crypto:hash(md5, <<"v1.2">>)]},
- body = {[ {<<"vsn">>, <<"v1.2">>}]}
- },
- {ok, _} = couch_db:update_doc(
- Db2, DocConflict, [], replicated_changes
- ),
- couch_db:ensure_full_commit(Db2),
- {ok, Db3} = couch_db:reopen(Db2),
-
- UUID = couch_uuids:new(),
- {ok, [{ok, PRevs}]} = couch_db:purge_docs(Db3,
- [{UUID, <<"foo">>, [Rev]}]),
- ?assertEqual([Rev], PRevs),
-
- {ok, Db4} = couch_db:reopen(Db3),
- {ok, PIdsRevs} = couch_db:fold_purge_infos(
- Db4, 0, fun fold_fun/2, [], []
- ),
- % still has one doc
- ?assertEqual(1, couch_db_engine:get_doc_count(Db4)),
- ?assertEqual(0, couch_db_engine:get_del_doc_count(Db4)),
- ?assertEqual(3, couch_db_engine:get_update_seq(Db4)),
- ?assertEqual(1, couch_db_engine:get_purge_seq(Db4)),
- ?assertEqual([{<<"foo">>, [Rev]}], PIdsRevs)
- end).
+ ?_test(begin
+ {ok, Rev1} = save_doc(DbName, {[{'_id', foo}, {vsn, <<"v1.1">>}]}),
+ Update = {[
+ {'_id', foo},
+ {'_rev', couch_doc:rev_to_str({1, [crypto:hash(md5, <<"v1.2">>)]})},
+ {vsn, <<"v1.2">>}
+ ]},
+ {ok, [_Rev2]} = save_docs(DbName, [Update], [replicated_changes]),
+
+ PurgeInfos = [
+ {uuid(), <<"foo">>, [Rev1]}
+ ],
+
+ {ok, [{ok, PRevs}]} = purge(DbName, PurgeInfos),
+ ?assertEqual([Rev1], PRevs),
+
+ assertProps(DbName, [
+ {doc_count, 1},
+ {del_doc_count, 0},
+ {update_seq, 3},
+ {purge_seq, 1},
+ {purge_infos, PurgeInfos}
+ ])
+ end).
test_purge_repeated_rev(DbName) ->
- ?_test(
- begin
- {ok, Db} = couch_db:open_int(DbName, []),
- Doc = {[{<<"_id">>, <<"foo">>}, {<<"vsn">>, <<"v1.1">>}]},
- {ok, Rev} = save_doc(Db, Doc),
- couch_db:ensure_full_commit(Db),
- {ok, Db2} = couch_db:reopen(Db),
-
- % create a conflict
- DocConflict = #doc{
- id = <<"foo">>,
- revs = {1, [crypto:hash(md5, <<"v1.2">>)]},
- body = {[ {<<"vsn">>, <<"v1.2">>}]}
- },
- {ok, _} = couch_db:update_doc(
- Db2, DocConflict, [], replicated_changes
- ),
- couch_db:ensure_full_commit(Db2),
- {ok, Db3} = couch_db:reopen(Db2),
-
- ?assertEqual(1, couch_db_engine:get_doc_count(Db3)),
- ?assertEqual(0, couch_db_engine:get_del_doc_count(Db3)),
- ?assertEqual(2, couch_db_engine:get_update_seq(Db3)),
- ?assertEqual(0, couch_db_engine:get_purge_seq(Db3)),
-
- UUID1 = couch_uuids:new(),
- UUID2 = couch_uuids:new(),
-
- FDI = couch_db:get_full_doc_info(Db3, <<"foo">>),
- Revs2 = FDI#full_doc_info.rev_tree,
-
- [{1, {Rev1, _Leaf1, []}}, {1, {Rev2, _Leaf2, []}}] = Revs2,
- {ok, [{ok, _PRevs2}]} = couch_db:purge_docs(Db3,
- [{UUID2, <<"foo">>, [{1, Rev2}]}]
- ),
- {ok, Db4} = couch_db:reopen(Db3),
- {ok, PIdsRevs4} = couch_db:fold_purge_infos(
- Db4, 0, fun fold_fun/2, [], []),
-
- % still has one doc
- ?assertEqual(1, couch_db_engine:get_doc_count(Db4)),
- ?assertEqual(0, couch_db_engine:get_del_doc_count(Db4)),
- ?assertEqual(3, couch_db_engine:get_update_seq(Db4)),
- ?assertEqual(1, couch_db_engine:get_purge_seq(Db4)),
- ?assertEqual([{<<"foo">>, [{1, Rev2}]}], PIdsRevs4),
-
- {ok, [{ok, _}]} = couch_db:purge_docs(Db4,
- [{UUID1, <<"foo">>, [{1, Rev1}]}]),
- {ok, Db5} = couch_db:reopen(Db4),
- {ok, PIdsRevs5} = couch_db:fold_purge_infos(
- Db5, 0, fun fold_fun/2, [], []),
-
- % Completely cleared
- ?assertEqual(0, couch_db_engine:get_doc_count(Db5)),
- ?assertEqual(0, couch_db_engine:get_del_doc_count(Db5)),
- ?assertEqual(4, couch_db_engine:get_update_seq(Db5)),
- ?assertEqual(2, couch_db_engine:get_purge_seq(Db5)),
- ?assertEqual([{<<"foo">>, [{1, Rev1}]}, {<<"foo">>, [{1, Rev2}]}],
- PIdsRevs5)
- end).
-
-
-purge_deep_tree(DbName) ->
- ?_test(
- begin
- NRevs = 100,
- {ok, Db0} = couch_db:open_int(DbName, []),
- Doc0 = {[{<<"_id">>, <<"bar">>}, {<<"vsn">>, 0}]},
- {ok, InitRev} = save_doc(Db0, Doc0),
- ok = couch_db:close(Db0),
- LastRev = lists:foldl(fun(V, PrevRev) ->
- {ok, Db} = couch_db:open_int(DbName, []),
- {ok, Rev} = save_doc(Db,
- {[{<<"_id">>, <<"bar">>},
- {<<"vsn">>, V},
- {<<"_rev">>, couch_doc:rev_to_str(PrevRev)}]}
- ),
- ok = couch_db:close(Db),
- Rev
- end, InitRev, lists:seq(2, NRevs)),
- {ok, Db1} = couch_db:open_int(DbName, []),
-
- % purge doc
- UUID = couch_uuids:new(),
- {ok, [{ok, PRevs}]} = couch_db:purge_docs(Db1,
- [{UUID, <<"bar">>, [LastRev]}]),
- ?assertEqual([LastRev], PRevs),
-
- {ok, Db2} = couch_db:reopen(Db1),
- % no docs left
- ?assertEqual(0, couch_db_engine:get_doc_count(Db2)),
- ?assertEqual(0, couch_db_engine:get_del_doc_count(Db2)),
- ?assertEqual(1, couch_db_engine:get_purge_seq(Db2)),
- ?assertEqual(NRevs + 1 , couch_db_engine:get_update_seq(Db2))
- end).
+ ?_test(begin
+ {ok, Rev1} = save_doc(DbName, {[{'_id', foo}, {vsn, <<"v1.1">>}]}),
+ Update = {[
+ {'_id', foo},
+ {'_rev', couch_doc:rev_to_str({1, [crypto:hash(md5, <<"v1.2">>)]})},
+ {vsn, <<"v1.2">>}
+ ]},
+ {ok, [Rev2]} = save_docs(DbName, [Update], [replicated_changes]),
+
+ assertProps(DbName, [
+ {doc_count, 1},
+ {del_doc_count, 0},
+ {update_seq, 2},
+ {purge_seq, 0},
+ {purge_infos, []}
+ ]),
+
+ PurgeInfos1 = [
+ {uuid(), <<"foo">>, [Rev1]}
+ ],
+
+ {ok, [{ok, PRevs1}]} = purge(DbName, PurgeInfos1),
+ ?assertEqual([Rev1], PRevs1),
+
+ assertProps(DbName, [
+ {doc_count, 1},
+ {del_doc_count, 0},
+ {update_seq, 3},
+ {purge_seq, 1},
+ {purge_infos, PurgeInfos1}
+ ]),
+
+ PurgeInfos2 = [
+ {uuid(), <<"foo">>, [Rev2]}
+ ],
+ {ok, [{ok, PRevs2}]} = purge(DbName, PurgeInfos2),
+ ?assertEqual([Rev2], PRevs2),
+
+ assertProps(DbName, [
+ {doc_count, 0},
+ {del_doc_count, 0},
+ {update_seq, 4},
+ {purge_seq, 2},
+ {purge_infos, PurgeInfos1 ++ PurgeInfos2}
+ ])
+ end).
+
+
+test_purge_deep_tree(DbName) ->
+ ?_test(begin
+ {ok, InitRev} = save_doc(DbName, {[{'_id', bar}, {vsn, 0}]}),
+ LastRev = lists:foldl(fun(Count, PrevRev) ->
+ Update = {[
+ {'_id', bar},
+ {'_rev', couch_doc:rev_to_str(PrevRev)},
+ {vsn, Count}
+ ]},
+ {ok, NewRev} = save_doc(DbName, Update),
+ NewRev
+ end, InitRev, lists:seq(1, ?REV_DEPTH)),
+ PurgeInfos = [
+ {uuid(), <<"bar">>, [LastRev]}
+ ],
+
+ {ok, [{ok, PRevs}]} = purge(DbName, PurgeInfos),
+ ?assertEqual([LastRev], PRevs),
+
+ assertProps(DbName, [
+ {doc_count, 0},
+ {del_doc_count, 0},
+ {update_seq, ?REV_DEPTH + 2},
+ {purge_seq, 1},
+ {purge_infos, PurgeInfos}
+ ])
+ end).
-test_purge_duplicate_UUID(DbName) ->
- ?_test(
- begin
- {ok, Db} = couch_db:open_int(DbName, []),
- Doc1 = {[{<<"_id">>, <<"foo1">>}, {<<"vsn">>, 1.1}]},
- {ok, Rev} = save_doc(Db, Doc1),
- couch_db:ensure_full_commit(Db),
-
- {ok, Db2} = couch_db:reopen(Db),
- ?assertEqual(1, couch_db_engine:get_doc_count(Db2)),
- ?assertEqual(0, couch_db_engine:get_del_doc_count(Db2)),
- ?assertEqual(1, couch_db_engine:get_update_seq(Db2)),
- ?assertEqual(0, couch_db_engine:get_purge_seq(Db2)),
-
- {ok, [{ok, PRevs}]} = couch_db:purge_docs(
- Db2, [{uuid, <<"foo1">>, [Rev]}]
- ),
- {ok, [{ok, PRevs2}]} = couch_db:purge_docs(
- Db2, [{uuid, <<"foo1">>, [Rev]}]
- ),
- ?assertEqual([Rev], PRevs),
- ?assertEqual([], PRevs2),
-
- {ok, Db3} = couch_db:reopen(Db2),
- {ok, _PIdsRevs} = couch_db:fold_purge_infos(
- Db3, 0, fun fold_fun/2, [], []),
- ?assertEqual(0, couch_db_engine:get_doc_count(Db3)),
- ?assertEqual(0, couch_db_engine:get_del_doc_count(Db3)),
- ?assertEqual(2, couch_db_engine:get_update_seq(Db3)),
- ?assertEqual(1, couch_db_engine:get_purge_seq(Db3))
- end).
-
-
-purge_with_replication() ->
- ?_test(
- begin
- Ctx = test_util:start_couch([couch_replicator]),
- Source = ?tempdb(),
- {ok, SourceDb} = create_db(Source),
- Target = ?tempdb(),
- {ok, _Db} = create_db(Target),
-
- % create Doc and do replication to Target
- {ok, Rev} = save_doc(SourceDb,
- {[{<<"_id">>, <<"foo">>}, {<<"vsn">>, 1}]}),
- couch_db:ensure_full_commit(SourceDb),
- {ok, SourceDb2} = couch_db:reopen(SourceDb),
- RepObject = {[
- {<<"source">>, Source},
- {<<"target">>, Target}
- ]},
- {ok, _} = couch_replicator:replicate(RepObject, ?ADMIN_USER),
- {ok, TargetDb} = couch_db:open_int(Target, []),
- {ok, Doc} = couch_db:get_doc_info(TargetDb, <<"foo">>),
-
- % purge Doc on Source and do replication to Target
- % assert purges don't get replicated to Target
- UUID = couch_uuids:new(),
- {ok, _} = couch_db:purge_docs(
- SourceDb2, [{UUID, <<"foo">>, [Rev]}]
- ),
- {ok, SourceDb3} = couch_db:reopen(SourceDb2),
- {ok, _} = couch_replicator:replicate(RepObject, ?ADMIN_USER),
- {ok, TargetDb2} = couch_db:open_int(Target, []),
- {ok, Doc2} = couch_db:get_doc_info(TargetDb2, <<"foo">>),
- [Rev2] = Doc2#doc_info.revs,
- ?assertEqual(Rev, Rev2#rev_info.rev),
- ?assertEqual(Doc, Doc2),
- ?assertEqual(0, couch_db_engine:get_doc_count(SourceDb3)),
- ?assertEqual(1, couch_db_engine:get_purge_seq(SourceDb3)),
- ?assertEqual(1, couch_db_engine:get_doc_count(TargetDb2)),
- ?assertEqual(0, couch_db_engine:get_purge_seq(TargetDb2)),
-
- % replicate from Target to Source
- % assert that Doc reappears on Source
- RepObject2 = {[
- {<<"source">>, Target},
- {<<"target">>, Source}
- ]},
- {ok, _} = couch_replicator:replicate(RepObject2, ?ADMIN_USER),
- {ok, SourceDb4} = couch_db:reopen(SourceDb3),
- {ok, Doc3} = couch_db:get_doc_info(SourceDb4, <<"foo">>),
- [Rev3] = Doc3#doc_info.revs,
- ?assertEqual(Rev, Rev3#rev_info.rev),
- ?assertEqual(1, couch_db_engine:get_doc_count(SourceDb4)),
- ?assertEqual(1, couch_db_engine:get_purge_seq(SourceDb4)),
- delete_db(Source),
- delete_db(Target),
- ok = application:stop(couch_replicator),
- ok = test_util:stop_couch(Ctx)
- end).
+test_purge_duplicate_UUID(DbName) ->
+ ?_test(begin
+ {ok, Rev} = save_doc(DbName, {[{'_id', foo1}, {vsn, 1.1}]}),
+
+ assertProps(DbName, [
+ {doc_count, 1},
+ {del_doc_count, 0},
+ {update_seq, 1},
+ {purge_seq, 0},
+ {purge_infos, []}
+ ]),
+
+ PurgeInfos = [
+ {uuid(), <<"foo1">>, [Rev]}
+ ],
+
+ {ok, [{ok, PRevs1}]} = purge(DbName, PurgeInfos),
+ ?assertEqual([Rev], PRevs1),
+
+ % Attempting to purge a repeated UUID is an error
+ ?assertThrow({badreq, _}, purge(DbName, PurgeInfos)),
+
+ % Although we can replicate it in
+ {ok, []} = purge(DbName, PurgeInfos, [replicated_changes]),
+
+ assertProps(DbName, [
+ {doc_count, 0},
+ {del_doc_count, 0},
+ {update_seq, 2},
+ {purge_seq, 1},
+ {purge_infos, PurgeInfos}
+ ])
+ end).
+
+
+test_purge_with_replication({Source, Target}) ->
+ ?_test(begin
+ {ok, Rev1} = save_doc(Source, {[{'_id', foo}, {vsn, 1}]}),
+
+ assertProps(Source, [
+ {doc_count, 1},
+ {del_doc_count, 0},
+ {update_seq, 1},
+ {purge_seq, 0},
+ {purge_infos, []}
+ ]),
+
+ RepObject = {[
+ {<<"source">>, Source},
+ {<<"target">>, Target}
+ ]},
+
+ {ok, _} = couch_replicator:replicate(RepObject, ?ADMIN_USER),
+ {ok, Doc1} = open_doc(Target, foo),
+
+ assertProps(Target, [
+ {doc_count, 1},
+ {del_doc_count, 0},
+ {update_seq, 1},
+ {purge_seq, 0},
+ {purge_infos, []}
+ ]),
+
+ PurgeInfos = [
+ {uuid(), <<"foo">>, [Rev1]}
+ ],
+
+ {ok, [{ok, PRevs}]} = purge(Source, PurgeInfos),
+ ?assertEqual([Rev1], PRevs),
+
+ assertProps(Source, [
+ {doc_count, 0},
+ {del_doc_count, 0},
+ {update_seq, 2},
+ {purge_seq, 1},
+ {purge_infos, PurgeInfos}
+ ]),
+
+ % Show that a purge on the source is
+ % not replicated to the target
+ {ok, _} = couch_replicator:replicate(RepObject, ?ADMIN_USER),
+ {ok, Doc2} = open_doc(Target, foo),
+ [Rev2] = Doc2#doc_info.revs,
+ ?assertEqual(Rev1, Rev2#rev_info.rev),
+ ?assertEqual(Doc1, Doc2),
+
+ assertProps(Target, [
+ {doc_count, 1},
+ {del_doc_count, 0},
+ {update_seq, 1},
+ {purge_seq, 0},
+ {purge_infos, []}
+ ]),
+
+ % Show that replicating from the target
+ % back to the source reintroduces the doc
+ RepObject2 = {[
+ {<<"source">>, Target},
+ {<<"target">>, Source}
+ ]},
+
+ {ok, _} = couch_replicator:replicate(RepObject2, ?ADMIN_USER),
+ {ok, Doc3} = open_doc(Source, foo),
+ [Revs3] = Doc3#doc_info.revs,
+ ?assertEqual(Rev1, Revs3#rev_info.rev),
+
+ assertProps(Source, [
+ {doc_count, 1},
+ {del_doc_count, 0},
+ {update_seq, 3},
+ {purge_seq, 1},
+ {purge_infos, PurgeInfos}
+ ])
+ end).
create_db(DbName) ->
couch_db:create(DbName, [?ADMIN_CTX, overwrite]).
+
delete_db(DbName) ->
couch_server:delete(DbName, [?ADMIN_CTX]).
-save_doc(Db, Json) ->
- Doc = couch_doc:from_json_obj(Json),
- couch_db:update_doc(Db, Doc, []).
-
-fold_fun({_PSeq, _UUID, Id, Revs}, Acc) ->
- {ok, [{Id, Revs} | Acc]}.
-fold_docs_fun(Doc, Acc) ->
- {ok, [Doc | Acc]}.
+save_doc(DbName, Json) ->
+ {ok, [Rev]} = save_docs(DbName, [Json], []),
+ {ok, Rev}.
+
+
+save_docs(DbName, JsonDocs) ->
+ save_docs(DbName, JsonDocs, []).
+
+
+save_docs(DbName, JsonDocs, Options) ->
+ Docs = lists:map(fun(JDoc) ->
+ couch_doc:from_json_obj(?JSON_DECODE(?JSON_ENCODE(JDoc)))
+ end, JsonDocs),
+ Opts = [full_commit | Options],
+ {ok, Db} = couch_db:open_int(DbName, []),
+ try
+ case lists:member(replicated_changes, Options) of
+ true ->
+ {ok, []} = couch_db:update_docs(
+ Db, Docs, Opts, replicated_changes),
+ {ok, lists:map(fun(Doc) ->
+ {Pos, [RevId | _]} = Doc#doc.revs,
+ {Pos, RevId}
+ end, Docs)};
+ false ->
+ {ok, Resp} = couch_db:update_docs(Db, Docs, Opts),
+ {ok, [Rev || {ok, Rev} <- Resp]}
+ end
+ after
+ couch_db:close(Db)
+ end.
+
+
+open_doc(DbName, DocId0) ->
+ DocId = ?JSON_DECODE(?JSON_ENCODE(DocId0)),
+ {ok, Db} = couch_db:open_int(DbName, []),
+ try
+ couch_db:get_doc_info(Db, DocId)
+ after
+ couch_db:close(Db)
+ end.
+
+
+purge(DbName, PurgeInfos) ->
+ purge(DbName, PurgeInfos, []).
+
+
+purge(DbName, PurgeInfos0, Options) when is_list(PurgeInfos0) ->
+ PurgeInfos = lists:map(fun({UUID, DocIdJson, Revs}) ->
+ {UUID, ?JSON_DECODE(?JSON_ENCODE(DocIdJson)), Revs}
+ end, PurgeInfos0),
+ {ok, Db} = couch_db:open_int(DbName, []),
+ try
+ couch_db:purge_docs(Db, PurgeInfos, Options)
+ after
+ couch_db:close(Db)
+ end.
+
+
+assertProps(DbName, Props) when is_binary(DbName) ->
+ {ok, Db} = couch_db:open_int(DbName, []),
+ try
+ assertEachProp(Db, Props)
+ after
+ couch_db:close(Db)
+ end.
+
+
+assertEachProp(_Db, []) ->
+ ok;
+assertEachProp(Db, [{doc_count, Expect} | Rest]) ->
+ {ok, DocCount} = couch_db:get_doc_count(Db),
+ ?assertEqual(Expect, DocCount),
+ assertEachProp(Db, Rest);
+assertEachProp(Db, [{del_doc_count, Expect} | Rest]) ->
+ {ok, DelDocCount} = couch_db:get_del_doc_count(Db),
+ ?assertEqual(Expect, DelDocCount),
+ assertEachProp(Db, Rest);
+assertEachProp(Db, [{update_seq, Expect} | Rest]) ->
+ UpdateSeq = couch_db:get_update_seq(Db),
+ ?assertEqual(Expect, UpdateSeq),
+ assertEachProp(Db, Rest);
+assertEachProp(Db, [{changes, Expect} | Rest]) ->
+ {ok, NumChanges} = couch_db:fold_changes(Db, 0, fun fold_changes/2, 0, []),
+ ?assertEqual(Expect, NumChanges),
+ assertEachProp(Db, Rest);
+assertEachProp(Db, [{purge_seq, Expect} | Rest]) ->
+ {ok, PurgeSeq} = couch_db:get_purge_seq(Db),
+ ?assertEqual(Expect, PurgeSeq),
+ assertEachProp(Db, Rest);
+assertEachProp(Db, [{purge_infos, Expect} | Rest]) ->
+ {ok, PurgeInfos} = couch_db:fold_purge_infos(Db, 0, fun fold_fun/2, [], []),
+ ?assertEqual(Expect, lists:reverse(PurgeInfos)),
+ assertEachProp(Db, Rest).
+
+
+fold_fun({_PSeq, UUID, Id, Revs}, Acc) ->
+ {ok, [{UUID, Id, Revs} | Acc]}.
+
+
+fold_changes(_, Acc) ->
+ {ok, Acc + 1}.
+
+
+uuid() -> couch_uuids:random().
--
To stop receiving notification emails like this one, please contact
davisp@apache.org.