You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by ji...@apache.org on 2024/01/02 21:27:19 UTC
(couchdb) 01/01: Add tests for `_changes` with different parameters
This is an automated email from the ASF dual-hosted git repository.
jiahuili430 pushed a commit to branch test-changes
in repository https://gitbox.apache.org/repos/asf/couchdb.git
commit f8d650f7e18d771006040e98f43c4210b15c563d
Author: Jiahui Li <li...@gmail.com>
AuthorDate: Tue Dec 5 21:21:52 2023 -0600
Add tests for `_changes` with different parameters
- style=all_docs
- include_docs=true
- conflicts=true
---
src/chttpd/test/eunit/chttpd_changes_test.erl | 399 ++++++++++++++++++++++++--
1 file changed, 379 insertions(+), 20 deletions(-)
diff --git a/src/chttpd/test/eunit/chttpd_changes_test.erl b/src/chttpd/test/eunit/chttpd_changes_test.erl
index d0590a83a..b3a7652f0 100644
--- a/src/chttpd/test/eunit/chttpd_changes_test.erl
+++ b/src/chttpd/test/eunit/chttpd_changes_test.erl
@@ -104,11 +104,11 @@ changes_q8_test_() ->
])
}.
-% These tests are separate as they create aditional design docs during
+% These tests are separate as they create additional design docs during
% the test. That ends up bumping the update sequence in the db, so
% last_seq and other sequences returned become dependent on the test
% order. To avoid that dependence, run them in a separate suite with
-% a foreach construct insted of a setup one. This way setup/teardown
+% a foreach construct instead of a setup one. This way setup/teardown
% happens for each individual test case.
%
changes_js_filters_test_() ->
@@ -125,6 +125,32 @@ changes_js_filters_test_() ->
]
}.
+changes_include_docs_test_() ->
+ {
+ foreach,
+ fun setup_basic/0,
+ fun teardown_basic/1,
+ [
+ ?TDEF_FE(t_include_docs),
+ ?TDEF_FE(t_all_docs_include_docs),
+ ?TDEF_FE(t_selector_include_docs),
+ ?TDEF_FE(t_selector_all_docs_include_docs),
+ ?TDEF_FE(t_conflicts),
+ ?TDEF_FE(t_conflicts_all_docs),
+ ?TDEF_FE(t_conflicts_include_docs),
+ ?TDEF_FE(t_conflicts_all_docs_include_docs),
+ ?TDEF_FE(t_conflicts_selector_include_docs),
+ ?TDEF_FE(t_conflicts_selector_all_docs_include_docs),
+ ?TDEF_FE(t_js_filter_include_docs),
+ ?TDEF_FE(t_js_filter_conflicts_include_docs),
+ ?TDEF_FE(t_js_filter_all_docs_conflicts_include_docs1),
+ ?TDEF_FE(t_js_filter_all_docs_conflicts_include_docs2),
+ ?TDEF_FE(t_view_include_docs),
+ ?TDEF_FE(t_view_conflicts_include_docs),
+ ?TDEF_FE(t_view_all_docs_conflicts_include_docs)
+ ]
+ }.
+
t_basic({_, DbUrl}) ->
Res = {Seq, Pending, Rows} = changes(DbUrl),
?assertEqual(7, Seq),
@@ -465,32 +491,349 @@ t_js_filter_with_query_param({_, DbUrl}) ->
{200, #{}} = req(delete, DDocUrl ++ "?rev=" ++ binary_to_list(Rev)).
t_view_filter({_, DbUrl}) ->
- DDocId = "_design/views",
- ViewFun = <<"function(doc) {if (doc._id == 'doc1') {emit(1, 1);}}">>,
- DDoc = #{<<"views">> => #{<<"v">> => #{<<"map">> => ViewFun}}},
- DDocUrl = DbUrl ++ "/" ++ DDocId,
- {_, #{<<"rev">> := Rev, <<"ok">> := true}} = req(put, DDocUrl, DDoc),
+ {DDocUrl, Rev} = create_ddocs_view(DbUrl, ?DOC1),
Params = "?filter=_view&view=views/v",
{Seq, Pending, Rows} = changes(DbUrl, Params),
?assertEqual(8, Seq),
?assertEqual(0, Pending),
- ?assertEqual(
- [
- {5, {?DOC1, <<"2-c">>}, ?LEAFREV}
- ],
- Rows
- ),
- {200, #{}} = req(delete, DDocUrl ++ "?rev=" ++ binary_to_list(Rev)).
+ ?assertEqual([{5, {?DOC1, <<"2-c">>}, ?LEAFREV}], Rows),
+ {200, #{}} = req(delete, DDocUrl ++ "?rev=" ++ Rev).
t_view_filter_no_match({_, DbUrl}) ->
- DDocId = "_design/views",
- ViewFun = <<"function(doc) {if (doc._id == 'docX') {emit(1, 1);}}">>,
- DDoc = #{<<"views">> => #{<<"v">> => #{<<"map">> => ViewFun}}},
- DDocUrl = DbUrl ++ "/" ++ DDocId,
- {_, #{<<"rev">> := Rev, <<"ok">> := true}} = req(put, DDocUrl, DDoc),
+ {DDocUrl, Rev} = create_ddocs_view(DbUrl, <<"docX">>),
Params = "?filter=_view&view=views/v",
?assertEqual({8, 0, []}, changes(DbUrl, Params)),
- {200, #{}} = req(delete, DDocUrl ++ "?rev=" ++ binary_to_list(Rev)).
+ {200, #{}} = req(delete, DDocUrl ++ "?rev=" ++ Rev).
+
+t_include_docs({_, DbUrl}) ->
+ Params = "?include_docs=true",
+ {200, #{<<"results">> := Res1}} = req(get, DbUrl ++ "/_changes" ++ Params),
+ ?assertMatch(
+ [
+ #{
+ <<"changes">> := [#{<<"rev">> := <<"2-c">>}],
+ <<"doc">> := #{<<"_id">> := ?DOC1, <<"_rev">> := <<"2-c">>}
+ },
+ #{
+ <<"changes">> := [#{<<"rev">> := <<"2-b">>}],
+ <<"deleted">> := ?DELETED,
+ <<"doc">> := #{
+ <<"_id">> := ?DOC3, <<"_rev">> := <<"2-b">>, <<"_deleted">> := ?DELETED
+ }
+ },
+ #{
+ <<"changes">> := [#{<<"rev">> := <<"2-c">>}],
+ <<"doc">> := #{<<"_id">> := ?DDOC2, <<"_rev">> := <<"2-c">>}
+ }
+ ],
+ Res1
+ ),
+ {200, #{<<"results">> := Res2}} = req(post, DbUrl ++ "/_changes" ++ Params),
+ ?assertEqual(Res1, Res2).
+
+t_all_docs_include_docs({_, DbUrl}) ->
+ Params = "?style=all_docs&include_docs=true",
+ {200, #{<<"results">> := Res1}} = req(get, DbUrl ++ "/_changes" ++ Params),
+ ?assertMatch(
+ [
+ #{
+ <<"changes">> := [#{<<"rev">> := <<"2-c">>}, #{<<"rev">> := <<"2-b">>}],
+ <<"doc">> := #{<<"_id">> := ?DOC1, <<"_rev">> := <<"2-c">>}
+ },
+ #{
+ <<"changes">> := [#{<<"rev">> := <<"2-b">>}],
+ <<"deleted">> := ?DELETED,
+ <<"doc">> := #{
+ <<"_id">> := ?DOC3, <<"_rev">> := <<"2-b">>, <<"_deleted">> := ?DELETED
+ }
+ },
+ #{
+ <<"changes">> := [#{<<"rev">> := <<"2-c">>}],
+ <<"doc">> := #{<<"_id">> := ?DDOC2, <<"_rev">> := <<"2-c">>}
+ }
+ ],
+ Res1
+ ),
+ {200, #{<<"results">> := Res2}} = req(post, DbUrl ++ "/_changes" ++ Params),
+ ?assertEqual(Res1, Res2).
+
+t_selector_include_docs({_, DbUrl}) ->
+ Body = #{<<"selector">> => #{<<"_id">> => ?DOC1}},
+ Params = "?filter=_selector&include_docs=true",
+ {200, #{<<"results">> := Res}} = req(post, DbUrl ++ "/_changes" ++ Params, Body),
+ ?assertMatch(
+ [
+ #{
+ <<"changes">> := [#{<<"rev">> := <<"2-c">>}],
+ <<"doc">> := #{<<"_id">> := ?DOC1, <<"_rev">> := <<"2-c">>}
+ }
+ ],
+ Res
+ ).
+
+t_selector_all_docs_include_docs({_, DbUrl}) ->
+ Body = #{<<"selector">> => #{<<"_id">> => ?DOC1}},
+ Params = "?filter=_selector&style=all_docs&include_docs=true",
+ {200, #{<<"results">> := Res}} = req(post, DbUrl ++ "/_changes" ++ Params, Body),
+ ?assertMatch(
+ [
+ #{
+ <<"changes">> := [#{<<"rev">> := <<"2-c">>}, #{<<"rev">> := <<"2-b">>}],
+ <<"doc">> := #{<<"_id">> := ?DOC1, <<"_rev">> := <<"2-c">>}
+ }
+ ],
+ Res
+ ).
+
+t_conflicts({_, DbUrl}) ->
+ Params = "?conflicts=true",
+ {200, #{<<"results">> := Res1}} = req(get, DbUrl ++ "/_changes" ++ Params),
+ ?assertMatch(
+ [
+ #{<<"changes">> := [#{<<"rev">> := <<"2-c">>}]},
+ #{<<"changes">> := [#{<<"rev">> := <<"2-b">>}]},
+ #{<<"changes">> := [#{<<"rev">> := <<"2-c">>}]}
+ ],
+ Res1
+ ),
+ {200, #{<<"results">> := Res2}} = req(post, DbUrl ++ "/_changes" ++ Params),
+ ?assertEqual(Res1, Res2).
+
+t_conflicts_all_docs({_, DbUrl}) ->
+ Params = "?conflicts=true&style=all_docs",
+ {200, #{<<"results">> := Res1}} = req(get, DbUrl ++ "/_changes" ++ Params),
+ ?assertMatch(
+ [
+ #{<<"changes">> := [#{<<"rev">> := <<"2-c">>}, #{<<"rev">> := <<"2-b">>}]},
+ #{<<"changes">> := [#{<<"rev">> := <<"2-b">>}]},
+ #{<<"changes">> := [#{<<"rev">> := <<"2-c">>}]}
+ ],
+ Res1
+ ),
+ {200, #{<<"results">> := Res2}} = req(post, DbUrl ++ "/_changes" ++ Params),
+ ?assertEqual(Res1, Res2).
+
+t_conflicts_include_docs({_, DbUrl}) ->
+ Params = "?conflicts=true&include_docs=true",
+ {200, #{<<"results">> := Res1}} = req(get, DbUrl ++ "/_changes" ++ Params),
+ ?assertMatch(
+ [
+ #{
+ <<"changes">> := [#{<<"rev">> := <<"2-c">>}],
+ <<"doc">> := #{
+ <<"_id">> := ?DOC1, <<"_rev">> := <<"2-c">>, <<"_conflicts">> := [<<"2-b">>]
+ }
+ },
+ #{
+ <<"changes">> := [#{<<"rev">> := <<"2-b">>}],
+ <<"deleted">> := ?DELETED,
+ <<"doc">> := #{
+ <<"_id">> := ?DOC3, <<"_rev">> := <<"2-b">>, <<"_deleted">> := ?DELETED
+ }
+ },
+ #{
+ <<"changes">> := [#{<<"rev">> := <<"2-c">>}],
+ <<"doc">> := #{<<"_id">> := ?DDOC2, <<"_rev">> := <<"2-c">>}
+ }
+ ],
+ Res1
+ ),
+ {200, #{<<"results">> := Res2}} = req(post, DbUrl ++ "/_changes" ++ Params),
+ ?assertEqual(Res1, Res2).
+
+t_conflicts_all_docs_include_docs({_, DbUrl}) ->
+ Params = "?conflicts=true&style=all_docs&include_docs=true",
+ {200, #{<<"results">> := Res1}} = req(get, DbUrl ++ "/_changes" ++ Params),
+ ?assertMatch(
+ [
+ #{
+ <<"changes">> := [#{<<"rev">> := <<"2-c">>}, #{<<"rev">> := <<"2-b">>}],
+ <<"doc">> := #{
+ <<"_id">> := ?DOC1, <<"_rev">> := <<"2-c">>, <<"_conflicts">> := [<<"2-b">>]
+ }
+ },
+ #{
+ <<"changes">> := [#{<<"rev">> := <<"2-b">>}],
+ <<"deleted">> := ?DELETED,
+ <<"doc">> := #{
+ <<"_id">> := ?DOC3, <<"_rev">> := <<"2-b">>, <<"_deleted">> := ?DELETED
+ }
+ },
+ #{
+ <<"changes">> := [#{<<"rev">> := <<"2-c">>}],
+ <<"doc">> := #{<<"_id">> := ?DDOC2, <<"_rev">> := <<"2-c">>}
+ }
+ ],
+ Res1
+ ),
+ {200, #{<<"results">> := Res2}} = req(post, DbUrl ++ "/_changes" ++ Params),
+ ?assertEqual(Res1, Res2).
+
+t_conflicts_selector_include_docs({_, DbUrl}) ->
+ Body = #{<<"selector">> => #{<<"_id">> => ?DOC1}},
+ Params = "?conflicts=true&filter=_selector&include_docs=true",
+ {200, #{<<"results">> := Res}} = req(post, DbUrl ++ "/_changes" ++ Params, Body),
+ ?assertMatch(
+ [
+ #{
+ <<"changes">> := [#{<<"rev">> := <<"2-c">>}],
+ <<"doc">> := #{
+ <<"_id">> := ?DOC1, <<"_rev">> := <<"2-c">>, <<"_conflicts">> := [<<"2-b">>]
+ }
+ }
+ ],
+ Res
+ ).
+
+t_conflicts_selector_all_docs_include_docs({_, DbUrl}) ->
+ Body = #{<<"selector">> => #{<<"_id">> => ?DOC1}},
+ Params = "?conflicts=true&filter=_selector&style=all_docs&include_docs=true",
+ {200, #{<<"results">> := Res}} = req(post, DbUrl ++ "/_changes" ++ Params, Body),
+ ?assertMatch(
+ [
+ #{
+ <<"changes">> := [#{<<"rev">> := <<"2-c">>}, #{<<"rev">> := <<"2-b">>}],
+ <<"doc">> := #{
+ <<"_id">> := ?DOC1, <<"_rev">> := <<"2-c">>, <<"_conflicts">> := [<<"2-b">>]
+ }
+ }
+ ],
+ Res
+ ).
+
+t_js_filter_include_docs({_, DbUrl}) ->
+ {DDocUrl, Rev} = create_ddocs_custom(DbUrl, ?DOC3),
+ Params = "?filter=filters/f&include_docs=true",
+ {200, #{<<"results">> := Res1}} = req(get, DbUrl ++ "/_changes" ++ Params),
+ ?assertMatch(
+ [
+ #{
+ <<"changes">> := [#{<<"rev">> := <<"2-b">>}],
+ <<"deleted">> := ?DELETED,
+ <<"doc">> := #{
+ <<"_id">> := ?DOC3, <<"_rev">> := <<"2-b">>, <<"_deleted">> := ?DELETED
+ }
+ }
+ ],
+ Res1
+ ),
+ {200, #{<<"results">> := Res2}} = req(post, DbUrl ++ "/_changes" ++ Params),
+ ?assertEqual(Res1, Res2),
+ {200, #{}} = req(delete, DDocUrl ++ "?rev=" ++ Rev).
+
+t_js_filter_conflicts_include_docs({_, DbUrl}) ->
+ {DDocUrl, Rev} = create_ddocs_custom(DbUrl, ?DOC3),
+ Params = "?filter=filters/f&conflicts=true&include_docs=true",
+ {200, #{<<"results">> := Res1}} = req(get, DbUrl ++ "/_changes" ++ Params),
+ ?assertMatch(
+ [
+ #{
+ <<"changes">> := [#{<<"rev">> := <<"2-b">>}],
+ <<"deleted">> := ?DELETED,
+ <<"doc">> := #{
+ <<"_id">> := ?DOC3, <<"_rev">> := <<"2-b">>, <<"_deleted">> := ?DELETED
+ }
+ }
+ ],
+ Res1
+ ),
+ {200, #{<<"results">> := Res2}} = req(post, DbUrl ++ "/_changes" ++ Params),
+ ?assertEqual(Res1, Res2),
+ {200, #{}} = req(delete, DDocUrl ++ "?rev=" ++ Rev).
+
+t_js_filter_all_docs_conflicts_include_docs1({_, DbUrl}) ->
+ {DDocUrl, Rev} = create_ddocs_custom(DbUrl, ?DOC1),
+ Params = "?filter=filters/f&style=all_docs&conflicts=true&include_docs=true",
+ {200, #{<<"results">> := Res1}} = req(get, DbUrl ++ "/_changes" ++ Params),
+ ?assertMatch(
+ [
+ #{
+ <<"changes">> := [#{<<"rev">> := <<"2-c">>}, #{<<"rev">> := <<"2-b">>}],
+ <<"doc">> := #{
+ <<"_id">> := ?DOC1, <<"_rev">> := <<"2-c">>, <<"_conflicts">> := [<<"2-b">>]
+ }
+ }
+ ],
+ Res1
+ ),
+ {200, #{<<"results">> := Res2}} = req(post, DbUrl ++ "/_changes" ++ Params),
+ ?assertEqual(Res1, Res2),
+ {200, #{}} = req(delete, DDocUrl ++ "?rev=" ++ Rev).
+
+t_js_filter_all_docs_conflicts_include_docs2({_, DbUrl}) ->
+ {DDocUrl, Rev} = create_ddocs_custom(DbUrl, ?DOC3),
+ Params = "?filter=filters/f&style=all_docs&conflicts=true&include_docs=true",
+ {200, #{<<"results">> := Res1}} = req(get, DbUrl ++ "/_changes" ++ Params),
+ ?assertMatch(
+ [
+ #{
+ <<"changes">> := [#{<<"rev">> := <<"2-b">>}],
+ <<"deleted">> := ?DELETED,
+ <<"doc">> := #{
+ <<"_id">> := ?DOC3, <<"_rev">> := <<"2-b">>, <<"_deleted">> := ?DELETED
+ }
+ }
+ ],
+ Res1
+ ),
+ {200, #{<<"results">> := Res2}} = req(post, DbUrl ++ "/_changes" ++ Params),
+ ?assertEqual(Res1, Res2),
+ {200, #{}} = req(delete, DDocUrl ++ "?rev=" ++ Rev).
+
+t_view_include_docs({_, DbUrl}) ->
+ {DDocUrl, Rev} = create_ddocs_view(DbUrl, ?DOC1),
+ Params = "?filter=_view&view=views/v&include_docs=true",
+ {200, #{<<"results">> := Res1}} = req(get, DbUrl ++ "/_changes" ++ Params),
+ ?assertMatch(
+ [
+ #{
+ <<"changes">> := [#{<<"rev">> := <<"2-c">>}],
+ <<"doc">> := #{<<"_id">> := ?DOC1, <<"_rev">> := <<"2-c">>}
+ }
+ ],
+ Res1
+ ),
+ {200, #{<<"results">> := Res2}} = req(post, DbUrl ++ "/_changes" ++ Params),
+ ?assertEqual(Res1, Res2),
+ {200, #{}} = req(delete, DDocUrl ++ "?rev=" ++ Rev).
+
+t_view_conflicts_include_docs({_, DbUrl}) ->
+ {DDocUrl, Rev} = create_ddocs_view(DbUrl, ?DOC1),
+ Params = "?filter=_view&view=views/v&conflicts=true&include_docs=true",
+ {200, #{<<"results">> := Res1}} = req(get, DbUrl ++ "/_changes" ++ Params),
+ ?assertMatch(
+ [
+ #{
+ <<"changes">> := [#{<<"rev">> := <<"2-c">>}],
+ <<"doc">> := #{
+ <<"_id">> := ?DOC1, <<"_rev">> := <<"2-c">>, <<"_conflicts">> := [<<"2-b">>]
+ }
+ }
+ ],
+ Res1
+ ),
+ {200, #{<<"results">> := Res2}} = req(post, DbUrl ++ "/_changes" ++ Params),
+ ?assertEqual(Res1, Res2),
+ {200, #{}} = req(delete, DDocUrl ++ "?rev=" ++ Rev).
+
+t_view_all_docs_conflicts_include_docs({_, DbUrl}) ->
+ {DDocUrl, Rev} = create_ddocs_view(DbUrl, ?DOC1),
+ Params = "?filter=_view&view=views/v&style=all_docs&conflicts=true&include_docs=true",
+ {200, #{<<"results">> := Res1}} = req(get, DbUrl ++ "/_changes" ++ Params),
+ ?assertMatch(
+ [
+ #{
+ <<"changes">> := [#{<<"rev">> := <<"2-c">>}, #{<<"rev">> := <<"2-b">>}],
+ <<"doc">> := #{
+ <<"_id">> := ?DOC1, <<"_rev">> := <<"2-c">>, <<"_conflicts">> := [<<"2-b">>]
+ }
+ }
+ ],
+ Res1
+ ),
+ {200, #{<<"results">> := Res2}} = req(post, DbUrl ++ "/_changes" ++ Params),
+ ?assertEqual(Res1, Res2),
+ {200, #{}} = req(delete, DDocUrl ++ "?rev=" ++ Rev).
% Utility functions
@@ -567,6 +910,22 @@ create_docs(DbUrl, DocRevs) ->
lists:map(fun doc_fun/1, DocRevs)
).
+create_ddocs_custom(DbUrl, DocId) ->
+ DDocId = "_design/filters",
+ FilterFun = <<"function(doc, req) {return (doc._id == '", DocId/binary, "')}">>,
+ DDoc = #{<<"filters">> => #{<<"f">> => FilterFun}},
+ DDocUrl = DbUrl ++ "/" ++ DDocId,
+ {_, #{<<"rev">> := Rev, <<"ok">> := true}} = req(put, DDocUrl, DDoc),
+ {DDocUrl, binary_to_list(Rev)}.
+
+create_ddocs_view(DbUrl, DocId) ->
+ DDocId = "_design/views",
+ ViewFun = <<"function(doc) {if (doc._id == '", DocId/binary, "') {emit(1, 1);}}">>,
+ DDoc = #{<<"views">> => #{<<"v">> => #{<<"map">> => ViewFun}}},
+ DDocUrl = DbUrl ++ "/" ++ DDocId,
+ {_, #{<<"rev">> := Rev, <<"ok">> := true}} = req(put, DDocUrl, DDoc),
+ {DDocUrl, binary_to_list(Rev)}.
+
changes(DbUrl) ->
changes(DbUrl, "").