This is an automated email from the ASF dual-hosted git repository. jiahuili430 pushed a commit to branch fix-changes-stats in repository https://gitbox.apache.org/repos/asf/couchdb.git
commit ad669bf1be66ee6393029fa2e69e0fbe309dfd37 Author: Jiahui Li <[email protected]> AuthorDate: Thu Jan 4 16:20:17 2024 -0600 Verify the number of calls to `open_doc/3` when requesting `_changes` --- src/chttpd/test/eunit/chttpd_changes_test.erl | 66 ++++++++++++++++++++++++++- 1 file changed, 65 insertions(+), 1 deletion(-) diff --git a/src/chttpd/test/eunit/chttpd_changes_test.erl b/src/chttpd/test/eunit/chttpd_changes_test.erl index b08eb65fd..d2375cde8 100644 --- a/src/chttpd/test/eunit/chttpd_changes_test.erl +++ b/src/chttpd/test/eunit/chttpd_changes_test.erl @@ -153,6 +153,18 @@ changes_include_docs_test_() -> ] }. +changes_open_doc_times_test_() -> + { + foreach, + fun setup_basic/0, + fun teardown_basic/1, + [ + ?TDEF_FE(t_selector_open_doc_times), + ?TDEF_FE(t_js_filter_open_doc_times), + ?TDEF_FE(t_view_open_doc_times) + ] + }. + t_basic({_, DbUrl}) -> Res = {Seq, Pending, Rows} = changes(DbUrl), ?assertEqual(8, Seq), @@ -853,8 +865,39 @@ t_view_all_docs_conflicts_include_docs({_, DbUrl}) -> ?assertEqual(Res1, Res2), delete_ddocs(DDocUrl, Rev). -% Utility functions +t_selector_open_doc_times({_, DbUrl}) -> + Body = #{<<"selector">> => #{<<"_id">> => ?DOC1}}, + F = "?filter=_selector", + I = "&include_docs=true", + S = "&style=all_docs", + Filter = called_times(fun() -> changes_post(DbUrl, Body, F) end, DbUrl), + FilterDocs = called_times(fun() -> changes_post(DbUrl, Body, F ++ I) end, DbUrl), + FilterAllDocs = called_times(fun() -> changes_post(DbUrl, Body, F ++ I ++ S) end, DbUrl), + ?assertEqual({3, 4, 6}, {Filter, FilterDocs, FilterAllDocs}). + +t_js_filter_open_doc_times({_, DbUrl}) -> + {DDocUrl, Rev} = create_ddocs(DbUrl, ?DOC1, custom), + F = "?filter=filters/f", + I = "&include_docs=true", + S = "&style=all_docs", + Filter = called_times(fun() -> changes(DbUrl, F) end, DbUrl), + FilterDocs = called_times(fun() -> changes(DbUrl, F ++ I) end, DbUrl), + FilterAllDocs = called_times(fun() -> changes(DbUrl, F ++ I ++ S) end, DbUrl), + ?assertEqual({4, 5, 7}, {Filter, FilterDocs, FilterAllDocs}), + delete_ddocs(DDocUrl, Rev). + +t_view_open_doc_times({_, DbUrl}) -> + {DDocUrl, Rev} = create_ddocs(DbUrl, ?DOC1, view), + F = "?filter=_view&view=views/v", + I = "&include_docs=true", + S = "&style=all_docs", + Filter = called_times(fun() -> changes(DbUrl, F) end, DbUrl), + FilterDocs = called_times(fun() -> changes(DbUrl, F ++ I) end, DbUrl), + FilterAllDocs = called_times(fun() -> changes(DbUrl, F ++ S ++ I) end, DbUrl), + ?assertEqual({4, 5, 7}, {Filter, FilterDocs, FilterAllDocs}), + delete_ddocs(DDocUrl, Rev). +% Utility functions setup_ctx(DbCreateParams) -> Ctx = test_util:start_couch([chttpd]), Hashed = couch_passwords:hash_admin_password(?PASS), @@ -883,6 +926,7 @@ setup_basic() -> CfgKey = "changes_doc_ids_optimization_threshold", ok = config:set("couchdb", CfgKey, "2", _Persist = false), meck:new(couch_changes, [passthrough]), + meck:new(couch_db, [passthrough]), {Ctx, DbUrl}. teardown_basic({Ctx, DbUrl}) -> @@ -1033,3 +1077,23 @@ seq(<<_/binary>> = Seq) -> binary_to_integer(NumStr); seq(null) -> null. + +called_times(ReqFun, DbUrl) -> + meck:reset(couch_db), + ReqFun(), + open_doc_calls(DbUrl). + +open_doc_calls(DbUrl) -> + #{path := "/" ++ DbName0} = uri_string:parse(DbUrl), + DbName = ?l2b(DbName0), + FoldFun = + fun([Db, IdOrDocInfo, _Opts], Acc) -> + case {mem3:dbname(couch_db:name(Db)), IdOrDocInfo} of + {DbName, #doc_info{}} -> Acc + 1; + _ -> Acc + end + end, + lists:foldl(FoldFun, 0, meck_history(couch_db, open_doc, 3)). + +meck_history(Mod, Fun, Arity) -> + [A || {_Pid, {_M, F, A}, _R} <- meck:history(Mod), F =:= Fun, length(A) =:= Arity].
