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, "").