You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@couchdb.apache.org by GitBox <gi...@apache.org> on 2022/10/15 01:20:35 UTC
[GitHub] [couchdb] nickva opened a new pull request, #4209: Add bulk_get tests
nickva opened a new pull request, #4209:
URL: https://github.com/apache/couchdb/pull/4209
Add an integration test suite for `_bulk_get`. Test various errors, missing docs, bad revs, various `atts_since`, `latest`, `attachments` options, as well as a test for multiple documents.
This is related to the effort of optimizing our bulk_get implementation [1]. In order get some confidence we haven't broken something in the process we're adding a bunch of tests.
Normally these tests would be a bit cumbersome, due to a deep level of nesting in the results with all the `ok`, `results`, `docs`, etc. levels of nesting. However, the `?assertMatch/2` EUnit macro macro and Erlang maps came to the rescue, and we're able to match just the parts which interest us in an elegant way.
[1] https://github.com/apache/couchdb/issues/4183
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: notifications-unsubscribe@couchdb.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [couchdb] nickva commented on a diff in pull request #4209: Add bulk_get tests
Posted by GitBox <gi...@apache.org>.
nickva commented on code in PR #4209:
URL: https://github.com/apache/couchdb/pull/4209#discussion_r997333116
##########
src/chttpd/test/eunit/chttpd_bulk_get_test.erl:
##########
@@ -0,0 +1,785 @@
+% Licensed under the Apache License, Version 2.0 (the "License"); you may not
+% use this file except in compliance with the License. You may obtain a copy of
+% the License at
+%
+% http://www.apache.org/licenses/LICENSE-2.0
+%
+% Unless required by applicable law or agreed to in writing, software
+% distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+% WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+% License for the specific language governing permissions and limitations under
+% the License.
+
+-module(chttpd_bulk_get_test).
+
+-include_lib("couch/include/couch_db.hrl").
+-include_lib("couch/include/couch_eunit.hrl").
+
+-define(USER, "chttpd_bulk_get_test_admin").
+-define(PASS, "pass").
+-define(AUTH, {basic_auth, {?USER, ?PASS}}).
+-define(JSON, {"Content-Type", "application/json"}).
+
+-define(DOC, <<"doc">>).
+-define(REVA, <<"reva">>).
+-define(REVB, <<"revb">>).
+-define(REVC, <<"revc">>).
+-define(ATT, <<"att">>).
+-define(ATT_DATA, <<"dGhlZGF0YQ==">>).
+
+-define(DOC_COUNT, 2000).
+
+test_docs_revs() ->
+ [
+ {?DOC, [?REVA]},
+ {?DOC, [?REVB, ?REVA]},
+ {?DOC, [?REVC, ?REVA]}
+ ].
+
+bulk_get_test_() ->
+ {
+ setup,
+ fun setup_basic/0,
+ fun teardown/1,
+ with([
+ ?TDEF(t_empty_request),
+ ?TDEF(t_no_docs),
+ ?TDEF(t_invalid_doc),
+ ?TDEF(t_doc_no_id),
+ ?TDEF(t_missing_doc),
+ ?TDEF(t_invalid_rev),
+ ?TDEF(t_missing_rev),
+ ?TDEF(t_doc_all_revs),
+ ?TDEF(t_specific_rev),
+ ?TDEF(t_specific_rev_latest),
+ ?TDEF(t_ancestor_rev_latest),
+ ?TDEF(t_revs_true),
+ ?TDEF(t_attachments_true),
+ ?TDEF(t_atts_since),
+ ?TDEF(t_atts_since_returns_attachment),
+ ?TDEF(t_atts_since_attachments_true),
+ ?TDEF(t_atts_since_multiple),
+ ?TDEF(t_atts_since_multiple_attachments_true),
+ ?TDEF(t_missing_rev_latest)
+ ])
+ }.
+
+bulk_get_multiple_docs_test_() ->
+ {
+ foreach,
+ fun setup_multiple/0,
+ fun teardown/1,
+ [
+ ?TDEF_FE(t_multiple_docs, 10)
+ ]
+ }.
+
+t_empty_request({_, DbUrl}) ->
+ {Code, Res} = bulk_get(DbUrl, []),
+ ?assertEqual(200, Code),
+ ?assertEqual([], Res).
+
+t_no_docs({_, DbUrl}) ->
+ {Code, #{}} = req(post, DbUrl ++ "/_bulk_get", #{}),
+ ?assertEqual(400, Code).
+
+t_invalid_doc({_, DbUrl}) ->
+ {Code, Res} = bulk_get(DbUrl, [<<"foo">>]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"error">> := #{
+ <<"id">> := null,
+ <<"rev">> := null,
+ <<"error">> := <<"bad_request">>
+ }
+ }
+ ],
+ <<"id">> := null
+ }
+ ],
+ Res
+ ).
+
+t_doc_no_id({_, DbUrl}) ->
+ {Code, Res} = bulk_get(DbUrl, [#{<<"rev">> => <<"1-foo">>}]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"error">> := #{
+ <<"id">> := null,
+ <<"rev">> := null,
+ <<"error">> := <<"bad_request">>
+ }
+ }
+ ],
+ <<"id">> := null
+ }
+ ],
+ Res
+ ).
+
+t_missing_doc({_, DbUrl}) ->
+ {Code, Res} = bulk_get(DbUrl, [#{<<"id">> => <<"missing">>}]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"error">> := #{
+ <<"error">> := <<"not_found">>,
+ <<"id">> := <<"missing">>,
+ <<"rev">> := <<"undefined">>
+ }
+ }
+ ],
+ <<"id">> := <<"missing">>
+ }
+ ],
+ Res
+ ).
+
+t_invalid_rev({_, DbUrl}) ->
+ Doc = #{<<"id">> => ?DOC, <<"rev">> => 42},
+ {Code, Res} = bulk_get(DbUrl, [Doc]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"error">> := #{
+ <<"error">> := <<"bad_request">>,
+ <<"id">> := ?DOC,
+ <<"rev">> := 42
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_missing_rev({_, DbUrl}) ->
+ Doc = #{<<"id">> => ?DOC, <<"rev">> => <<"1-x">>},
+ {Code, Res} = bulk_get(DbUrl, [Doc]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"error">> := #{
+ <<"error">> := <<"not_found">>,
+ <<"id">> := ?DOC,
+ <<"rev">> := <<"1-x">>
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_doc_all_revs({_, DbUrl}) ->
+ {Code, Res} = bulk_get(DbUrl, [#{<<"id">> => ?DOC}]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"ok">> := #{
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revb">>,
+ <<"_attachments">> := #{
+ ?ATT := #{<<"stub">> := true}
+ }
+ }
+ },
+ #{
+ <<"ok">> := #{
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revc">>,
+ <<"_attachments">> := #{
+ ?ATT := #{<<"stub">> := true}
+ }
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_specific_rev({_, DbUrl}) ->
+ Doc = #{<<"id">> => ?DOC, <<"rev">> => <<"2-revb">>},
+ {Code, Res} = bulk_get(DbUrl, [Doc]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"ok">> := #{
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revb">>,
+ <<"_attachments">> := #{
+ ?ATT := #{<<"stub">> := true}
+ }
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_specific_rev_latest({_, DbUrl}) ->
+ Doc = #{<<"id">> => ?DOC, <<"rev">> => <<"2-revb">>},
+ {Code, Res} = bulk_get(DbUrl, [Doc], "?latest=true"),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"ok">> := #{
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revb">>,
+ <<"_attachments">> := #{
+ ?ATT := #{<<"stub">> := true}
+ }
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_ancestor_rev_latest({_, DbUrl}) ->
+ Doc = #{<<"id">> => ?DOC, <<"rev">> => <<"1-reva">>},
+ {Code, Res} = bulk_get(DbUrl, [Doc], "?latest=true"),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"ok">> := #{
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revb">>,
+ <<"_attachments">> := #{
+ ?ATT := #{<<"stub">> := true}
+ }
+ }
+ },
+ #{
+ <<"ok">> := #{
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revc">>,
+ <<"_attachments">> := #{
+ ?ATT := #{<<"stub">> := true}
+ }
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_revs_true({_, DbUrl}) ->
+ Doc = #{
+ <<"id">> => ?DOC,
+ <<"rev">> => <<"1-reva">>
+ },
+ {Code, Res} = bulk_get(DbUrl, [Doc], "?revs=true"),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"ok">> := #{
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"1-reva">>,
+ <<"_revisions">> :=
+ #{<<"ids">> := [<<"reva">>], <<"start">> := 1},
+ <<"_attachments">> := #{
+ ?ATT := #{<<"stub">> := true}
+ }
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_attachments_true({_, DbUrl}) ->
+ Doc = #{
+ <<"id">> => ?DOC,
+ <<"rev">> => <<"1-reva">>
+ },
+ {Code, Res} = bulk_get(DbUrl, [Doc], "?attachments=true"),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"ok">> := #{
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"1-reva">>,
+ <<"_attachments">> := #{
+ ?ATT := #{<<"data">> := ?ATT_DATA}
+ }
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_atts_since({_, DbUrl}) ->
+ % Attachment should not be returned as 2 from 2-revb is not stricly greater
+ % than 1 from our attachment's revpos
+ Doc = #{
+ <<"id">> => ?DOC,
+ <<"rev">> => <<"2-revb">>,
+ <<"atts_since">> => [<<"2-revb">>]
+ },
+ {Code, Res} = bulk_get(DbUrl, [Doc]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"ok">> := #{
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revb">>,
+ <<"_attachments">> := #{
+ ?ATT := #{<<"stub">> := true}
+ }
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_atts_since_returns_attachment({_, DbUrl}) ->
+ % 0-baz revpos 0 is less than revpos 1 of our attachment
+ Doc = #{
+ <<"id">> => ?DOC,
+ <<"rev">> => <<"2-revb">>,
+ <<"atts_since">> => [<<"0-baz">>]
+ },
+ {Code, Res} = bulk_get(DbUrl, [Doc]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"ok">> := #{
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revb">>,
+ <<"_attachments">> := #{
+ ?ATT := #{<<"data">> := ?ATT_DATA}
+ }
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_atts_since_attachments_true({_, DbUrl}) ->
+ % Check that atts_since overrides attachments=true
+ Doc = #{
+ <<"id">> => ?DOC,
+ <<"rev">> => <<"2-revb">>,
+ <<"atts_since">> => [<<"2-revb">>]
+ },
+ {Code, Res} = bulk_get(DbUrl, [Doc], "?attachments=true"),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"ok">> := #{
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revb">>,
+ <<"_attachments">> := #{
+ ?ATT := #{
+ <<"stub">> := true
+ }
+ }
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_atts_since_multiple({_, DbUrl}) ->
+ % Attachment revpos is 1 so we do not expect this attachment body
+ Docs = [
+ #{
+ <<"id">> => ?DOC,
+ <<"rev">> => <<"2-revb">>,
+ <<"atts_since">> => [<<"2-revb">>]
+ },
+ % Should get the attachment revpos=1 is greater than 0-foo
+ #{
+ <<"id">> => ?DOC,
+ <<"rev">> => <<"2-revb">>,
+ <<"atts_since">> => [<<"0-foo">>]
+ },
+ % Empty atts_since. Do not expect to get the attachment
+ #{
+ <<"id">> => ?DOC,
+ <<"rev">> => <<"2-revb">>,
+ <<"atts_since">> => []
+ },
+ % Add a document without atts_since to ensure atts_since applies only to
+ % individual requests
+ #{
+ <<"id">> => ?DOC,
+ <<"rev">> => <<"2-revb">>
+ }
+ ],
+ {Code, Res} = bulk_get(DbUrl, Docs),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"ok">> := #{
+ <<"_attachments">> := #{
+ ?ATT := #{<<"stub">> := true}
+ },
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revb">>
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ },
+ #{
+ <<"docs">> := [
+ #{
+ <<"ok">> := #{
+ <<"_attachments">> := #{
+ ?ATT := #{<<"data">> := ?ATT_DATA}
+ },
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revb">>
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ },
+ #{
+ <<"docs">> := [
+ #{
+ <<"ok">> := #{
+ <<"_attachments">> := #{
+ ?ATT := #{<<"stub">> := true}
+ },
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revb">>
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ },
+ #{
+ <<"docs">> := [
+ #{
+ <<"ok">> := #{
+ <<"_attachments">> :=
+ #{?ATT := #{<<"stub">> := true}},
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revb">>
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_atts_since_multiple_attachments_true({_, DbUrl}) ->
+ % Since attachments=true, expect to always get the attachments, unless
+ % there is an atts_since present and atts_since would prevent the
+ % attachment from being returned.
+ Docs = [
+ % Attachment revpos is 1 so we do not expect this attachment body
+ #{
+ <<"id">> => ?DOC,
+ <<"rev">> => <<"2-revb">>,
+ <<"atts_since">> => [<<"2-revb">>]
+ },
+ % Should get the attachment revpos=1 is greater than 0-foo
+ #{
+ <<"id">> => ?DOC,
+ <<"rev">> => <<"2-revb">>,
+ <<"atts_since">> => [<<"0-foo">>]
+ },
+ % Should get the attachment as it is set as a default option
+ #{
+ <<"id">> => ?DOC,
+ <<"rev">> => <<"2-revb">>,
+ <<"atts_since">> => []
+ },
+ % Check a doc without atts_since to ensure atts_since applies only to
+ % individual requests, otherwise default options apply
+ #{
+ <<"id">> => ?DOC,
+ <<"rev">> => <<"2-revb">>
+ }
+ ],
+ {Code, Res} = bulk_get(DbUrl, Docs, "?attachments=true"),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"ok">> := #{
+ <<"_attachments">> := #{
+ ?ATT := #{<<"stub">> := true}
+ },
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revb">>
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ },
+ #{
+ <<"docs">> := [
+ #{
+ <<"ok">> := #{
+ <<"_attachments">> := #{
+ ?ATT := #{<<"data">> := ?ATT_DATA}
+ },
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revb">>
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ },
+ #{
+ <<"docs">> := [
+ #{
+ <<"ok">> := #{
+ <<"_attachments">> := #{
+ ?ATT := #{<<"data">> := ?ATT_DATA}
+ },
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revb">>
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ },
+ #{
+ <<"docs">> := [
+ #{
+ <<"ok">> := #{
+ <<"_attachments">> :=
+ #{?ATT := #{<<"data">> := ?ATT_DATA}},
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revb">>
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_missing_rev_latest({_, DbUrl}) ->
+ % Check the case of latest and a missing
+ Doc = #{<<"id">> => ?DOC, <<"rev">> => <<"1-x">>},
+ {Code, Res} = bulk_get(DbUrl, [Doc], "?latest=true"),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"error">> := #{
+ <<"error">> := <<"not_found">>,
+ <<"id">> := ?DOC,
+ <<"rev">> := <<"1-x">>
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_multiple_docs({_, DbUrl}) ->
+ Reqs = [#{<<"id">> => integer_to_binary(I)} || I <- lists:seq(1, ?DOC_COUNT)],
+ {Code, Res} = bulk_get(DbUrl, Reqs),
+ ?assertEqual(200, Code),
+ ?assertMatch([#{<<"docs">> := _} | _], Res),
+ ?assertEqual(?DOC_COUNT, length(Res)),
+ lists:foreach(
+ fun({I, Docs}) ->
+ Id = integer_to_binary(I),
+ ?assertMatch(
+ #{
+ <<"docs">> := [
+ #{
+ <<"ok">> := #{
+ <<"_id">> := Id,
+ <<"_rev">> := <<"1-reva">>
+ }
+ }
+ ],
+ <<"id">> := Id
+ },
+ Docs
+ )
+ end,
+ lists:zip(lists:seq(1, ?DOC_COUNT), Res)
+ ).
+
+% Utility functions
+
+setup_ctx() ->
+ Ctx = test_util:start_couch([chttpd]),
+ Hashed = couch_passwords:hash_admin_password(?PASS),
+ ok = config:set("admins", ?USER, ?b2l(Hashed), _Persist = false),
+ Addr = config:get("chttpd", "bind_address", "127.0.0.1"),
+ Db = binary_to_list(?tempdb()),
Review Comment:
Oh, good idea
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: notifications-unsubscribe@couchdb.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [couchdb] nickva commented on a diff in pull request #4209: Add bulk_get tests
Posted by GitBox <gi...@apache.org>.
nickva commented on code in PR #4209:
URL: https://github.com/apache/couchdb/pull/4209#discussion_r997332296
##########
src/chttpd/test/eunit/chttpd_bulk_get_test.erl:
##########
@@ -0,0 +1,785 @@
+% Licensed under the Apache License, Version 2.0 (the "License"); you may not
+% use this file except in compliance with the License. You may obtain a copy of
+% the License at
+%
+% http://www.apache.org/licenses/LICENSE-2.0
+%
+% Unless required by applicable law or agreed to in writing, software
+% distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+% WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+% License for the specific language governing permissions and limitations under
+% the License.
+
+-module(chttpd_bulk_get_test).
+
+-include_lib("couch/include/couch_db.hrl").
+-include_lib("couch/include/couch_eunit.hrl").
+
+-define(USER, "chttpd_bulk_get_test_admin").
+-define(PASS, "pass").
+-define(AUTH, {basic_auth, {?USER, ?PASS}}).
+-define(JSON, {"Content-Type", "application/json"}).
+
+-define(DOC, <<"doc">>).
+-define(REVA, <<"reva">>).
+-define(REVB, <<"revb">>).
+-define(REVC, <<"revc">>).
+-define(ATT, <<"att">>).
+-define(ATT_DATA, <<"dGhlZGF0YQ==">>).
+
+-define(DOC_COUNT, 2000).
+
+test_docs_revs() ->
+ [
+ {?DOC, [?REVA]},
+ {?DOC, [?REVB, ?REVA]},
+ {?DOC, [?REVC, ?REVA]}
+ ].
+
+bulk_get_test_() ->
+ {
+ setup,
+ fun setup_basic/0,
+ fun teardown/1,
+ with([
+ ?TDEF(t_empty_request),
+ ?TDEF(t_no_docs),
+ ?TDEF(t_invalid_doc),
+ ?TDEF(t_doc_no_id),
+ ?TDEF(t_missing_doc),
+ ?TDEF(t_invalid_rev),
+ ?TDEF(t_missing_rev),
+ ?TDEF(t_doc_all_revs),
+ ?TDEF(t_specific_rev),
+ ?TDEF(t_specific_rev_latest),
+ ?TDEF(t_ancestor_rev_latest),
+ ?TDEF(t_revs_true),
+ ?TDEF(t_attachments_true),
+ ?TDEF(t_atts_since),
+ ?TDEF(t_atts_since_returns_attachment),
+ ?TDEF(t_atts_since_attachments_true),
+ ?TDEF(t_atts_since_multiple),
+ ?TDEF(t_atts_since_multiple_attachments_true),
+ ?TDEF(t_missing_rev_latest)
+ ])
+ }.
+
+bulk_get_multiple_docs_test_() ->
+ {
+ foreach,
+ fun setup_multiple/0,
+ fun teardown/1,
+ [
+ ?TDEF_FE(t_multiple_docs, 10)
+ ]
+ }.
+
+t_empty_request({_, DbUrl}) ->
+ {Code, Res} = bulk_get(DbUrl, []),
+ ?assertEqual(200, Code),
+ ?assertEqual([], Res).
+
+t_no_docs({_, DbUrl}) ->
+ {Code, #{}} = req(post, DbUrl ++ "/_bulk_get", #{}),
+ ?assertEqual(400, Code).
+
+t_invalid_doc({_, DbUrl}) ->
+ {Code, Res} = bulk_get(DbUrl, [<<"foo">>]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"error">> := #{
+ <<"id">> := null,
+ <<"rev">> := null,
+ <<"error">> := <<"bad_request">>
+ }
+ }
+ ],
+ <<"id">> := null
+ }
+ ],
+ Res
+ ).
+
+t_doc_no_id({_, DbUrl}) ->
+ {Code, Res} = bulk_get(DbUrl, [#{<<"rev">> => <<"1-foo">>}]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"error">> := #{
+ <<"id">> := null,
+ <<"rev">> := null,
+ <<"error">> := <<"bad_request">>
+ }
+ }
+ ],
+ <<"id">> := null
+ }
+ ],
+ Res
+ ).
+
+t_missing_doc({_, DbUrl}) ->
+ {Code, Res} = bulk_get(DbUrl, [#{<<"id">> => <<"missing">>}]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"error">> := #{
+ <<"error">> := <<"not_found">>,
+ <<"id">> := <<"missing">>,
+ <<"rev">> := <<"undefined">>
+ }
+ }
+ ],
+ <<"id">> := <<"missing">>
+ }
+ ],
+ Res
+ ).
+
+t_invalid_rev({_, DbUrl}) ->
+ Doc = #{<<"id">> => ?DOC, <<"rev">> => 42},
+ {Code, Res} = bulk_get(DbUrl, [Doc]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"error">> := #{
+ <<"error">> := <<"bad_request">>,
+ <<"id">> := ?DOC,
+ <<"rev">> := 42
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_missing_rev({_, DbUrl}) ->
+ Doc = #{<<"id">> => ?DOC, <<"rev">> => <<"1-x">>},
+ {Code, Res} = bulk_get(DbUrl, [Doc]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"error">> := #{
+ <<"error">> := <<"not_found">>,
+ <<"id">> := ?DOC,
+ <<"rev">> := <<"1-x">>
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_doc_all_revs({_, DbUrl}) ->
+ {Code, Res} = bulk_get(DbUrl, [#{<<"id">> => ?DOC}]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"ok">> := #{
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revb">>,
+ <<"_attachments">> := #{
+ ?ATT := #{<<"stub">> := true}
+ }
+ }
+ },
+ #{
+ <<"ok">> := #{
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revc">>,
+ <<"_attachments">> := #{
+ ?ATT := #{<<"stub">> := true}
+ }
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_specific_rev({_, DbUrl}) ->
+ Doc = #{<<"id">> => ?DOC, <<"rev">> => <<"2-revb">>},
+ {Code, Res} = bulk_get(DbUrl, [Doc]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"ok">> := #{
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revb">>,
+ <<"_attachments">> := #{
+ ?ATT := #{<<"stub">> := true}
+ }
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_specific_rev_latest({_, DbUrl}) ->
+ Doc = #{<<"id">> => ?DOC, <<"rev">> => <<"2-revb">>},
+ {Code, Res} = bulk_get(DbUrl, [Doc], "?latest=true"),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"ok">> := #{
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revb">>,
+ <<"_attachments">> := #{
+ ?ATT := #{<<"stub">> := true}
+ }
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_ancestor_rev_latest({_, DbUrl}) ->
+ Doc = #{<<"id">> => ?DOC, <<"rev">> => <<"1-reva">>},
+ {Code, Res} = bulk_get(DbUrl, [Doc], "?latest=true"),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"ok">> := #{
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revb">>,
+ <<"_attachments">> := #{
+ ?ATT := #{<<"stub">> := true}
+ }
+ }
+ },
+ #{
+ <<"ok">> := #{
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revc">>,
+ <<"_attachments">> := #{
+ ?ATT := #{<<"stub">> := true}
+ }
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_revs_true({_, DbUrl}) ->
+ Doc = #{
+ <<"id">> => ?DOC,
+ <<"rev">> => <<"1-reva">>
+ },
+ {Code, Res} = bulk_get(DbUrl, [Doc], "?revs=true"),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"ok">> := #{
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"1-reva">>,
+ <<"_revisions">> :=
+ #{<<"ids">> := [<<"reva">>], <<"start">> := 1},
+ <<"_attachments">> := #{
+ ?ATT := #{<<"stub">> := true}
+ }
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_attachments_true({_, DbUrl}) ->
+ Doc = #{
+ <<"id">> => ?DOC,
+ <<"rev">> => <<"1-reva">>
+ },
+ {Code, Res} = bulk_get(DbUrl, [Doc], "?attachments=true"),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"ok">> := #{
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"1-reva">>,
+ <<"_attachments">> := #{
+ ?ATT := #{<<"data">> := ?ATT_DATA}
+ }
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_atts_since({_, DbUrl}) ->
+ % Attachment should not be returned as 2 from 2-revb is not stricly greater
+ % than 1 from our attachment's revpos
+ Doc = #{
+ <<"id">> => ?DOC,
+ <<"rev">> => <<"2-revb">>,
+ <<"atts_since">> => [<<"2-revb">>]
+ },
+ {Code, Res} = bulk_get(DbUrl, [Doc]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"ok">> := #{
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revb">>,
+ <<"_attachments">> := #{
+ ?ATT := #{<<"stub">> := true}
+ }
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_atts_since_returns_attachment({_, DbUrl}) ->
+ % 0-baz revpos 0 is less than revpos 1 of our attachment
+ Doc = #{
+ <<"id">> => ?DOC,
+ <<"rev">> => <<"2-revb">>,
+ <<"atts_since">> => [<<"0-baz">>]
+ },
+ {Code, Res} = bulk_get(DbUrl, [Doc]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"ok">> := #{
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revb">>,
+ <<"_attachments">> := #{
+ ?ATT := #{<<"data">> := ?ATT_DATA}
+ }
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_atts_since_attachments_true({_, DbUrl}) ->
+ % Check that atts_since overrides attachments=true
+ Doc = #{
+ <<"id">> => ?DOC,
+ <<"rev">> => <<"2-revb">>,
+ <<"atts_since">> => [<<"2-revb">>]
+ },
+ {Code, Res} = bulk_get(DbUrl, [Doc], "?attachments=true"),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"ok">> := #{
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revb">>,
+ <<"_attachments">> := #{
+ ?ATT := #{
+ <<"stub">> := true
+ }
+ }
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_atts_since_multiple({_, DbUrl}) ->
+ % Attachment revpos is 1 so we do not expect this attachment body
+ Docs = [
+ #{
+ <<"id">> => ?DOC,
+ <<"rev">> => <<"2-revb">>,
+ <<"atts_since">> => [<<"2-revb">>]
+ },
+ % Should get the attachment revpos=1 is greater than 0-foo
Review Comment:
yes, good find
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: notifications-unsubscribe@couchdb.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [couchdb] nickva commented on a diff in pull request #4209: Add bulk_get tests
Posted by GitBox <gi...@apache.org>.
nickva commented on code in PR #4209:
URL: https://github.com/apache/couchdb/pull/4209#discussion_r997330197
##########
src/chttpd/test/eunit/chttpd_bulk_get_test.erl:
##########
@@ -0,0 +1,785 @@
+% Licensed under the Apache License, Version 2.0 (the "License"); you may not
+% use this file except in compliance with the License. You may obtain a copy of
+% the License at
+%
+% http://www.apache.org/licenses/LICENSE-2.0
+%
+% Unless required by applicable law or agreed to in writing, software
+% distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+% WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+% License for the specific language governing permissions and limitations under
+% the License.
+
+-module(chttpd_bulk_get_test).
+
+-include_lib("couch/include/couch_db.hrl").
+-include_lib("couch/include/couch_eunit.hrl").
+
+-define(USER, "chttpd_bulk_get_test_admin").
+-define(PASS, "pass").
+-define(AUTH, {basic_auth, {?USER, ?PASS}}).
+-define(JSON, {"Content-Type", "application/json"}).
+
+-define(DOC, <<"doc">>).
+-define(REVA, <<"reva">>).
+-define(REVB, <<"revb">>).
+-define(REVC, <<"revc">>).
+-define(ATT, <<"att">>).
+-define(ATT_DATA, <<"dGhlZGF0YQ==">>).
+
+-define(DOC_COUNT, 2000).
+
+test_docs_revs() ->
+ [
+ {?DOC, [?REVA]},
+ {?DOC, [?REVB, ?REVA]},
+ {?DOC, [?REVC, ?REVA]}
+ ].
+
+bulk_get_test_() ->
+ {
+ setup,
+ fun setup_basic/0,
+ fun teardown/1,
+ with([
+ ?TDEF(t_empty_request),
+ ?TDEF(t_no_docs),
+ ?TDEF(t_invalid_doc),
+ ?TDEF(t_doc_no_id),
+ ?TDEF(t_missing_doc),
+ ?TDEF(t_invalid_rev),
+ ?TDEF(t_missing_rev),
+ ?TDEF(t_doc_all_revs),
+ ?TDEF(t_specific_rev),
+ ?TDEF(t_specific_rev_latest),
+ ?TDEF(t_ancestor_rev_latest),
+ ?TDEF(t_revs_true),
+ ?TDEF(t_attachments_true),
+ ?TDEF(t_atts_since),
+ ?TDEF(t_atts_since_returns_attachment),
+ ?TDEF(t_atts_since_attachments_true),
+ ?TDEF(t_atts_since_multiple),
+ ?TDEF(t_atts_since_multiple_attachments_true),
+ ?TDEF(t_missing_rev_latest)
+ ])
+ }.
+
+bulk_get_multiple_docs_test_() ->
+ {
+ foreach,
+ fun setup_multiple/0,
+ fun teardown/1,
+ [
+ ?TDEF_FE(t_multiple_docs, 10)
+ ]
+ }.
+
+t_empty_request({_, DbUrl}) ->
+ {Code, Res} = bulk_get(DbUrl, []),
+ ?assertEqual(200, Code),
+ ?assertEqual([], Res).
+
+t_no_docs({_, DbUrl}) ->
+ {Code, #{}} = req(post, DbUrl ++ "/_bulk_get", #{}),
+ ?assertEqual(400, Code).
+
+t_invalid_doc({_, DbUrl}) ->
+ {Code, Res} = bulk_get(DbUrl, [<<"foo">>]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"error">> := #{
+ <<"id">> := null,
+ <<"rev">> := null,
+ <<"error">> := <<"bad_request">>
+ }
+ }
+ ],
+ <<"id">> := null
+ }
+ ],
+ Res
+ ).
+
+t_doc_no_id({_, DbUrl}) ->
+ {Code, Res} = bulk_get(DbUrl, [#{<<"rev">> => <<"1-foo">>}]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"error">> := #{
+ <<"id">> := null,
+ <<"rev">> := null,
+ <<"error">> := <<"bad_request">>
+ }
+ }
+ ],
+ <<"id">> := null
+ }
+ ],
+ Res
+ ).
+
+t_missing_doc({_, DbUrl}) ->
+ {Code, Res} = bulk_get(DbUrl, [#{<<"id">> => <<"missing">>}]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"error">> := #{
+ <<"error">> := <<"not_found">>,
+ <<"id">> := <<"missing">>,
+ <<"rev">> := <<"undefined">>
+ }
+ }
+ ],
+ <<"id">> := <<"missing">>
+ }
+ ],
+ Res
+ ).
+
+t_invalid_rev({_, DbUrl}) ->
+ Doc = #{<<"id">> => ?DOC, <<"rev">> => 42},
+ {Code, Res} = bulk_get(DbUrl, [Doc]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"error">> := #{
+ <<"error">> := <<"bad_request">>,
+ <<"id">> := ?DOC,
+ <<"rev">> := 42
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_missing_rev({_, DbUrl}) ->
+ Doc = #{<<"id">> => ?DOC, <<"rev">> => <<"1-x">>},
+ {Code, Res} = bulk_get(DbUrl, [Doc]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"error">> := #{
+ <<"error">> := <<"not_found">>,
+ <<"id">> := ?DOC,
+ <<"rev">> := <<"1-x">>
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_doc_all_revs({_, DbUrl}) ->
+ {Code, Res} = bulk_get(DbUrl, [#{<<"id">> => ?DOC}]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"ok">> := #{
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revb">>,
+ <<"_attachments">> := #{
+ ?ATT := #{<<"stub">> := true}
+ }
+ }
+ },
+ #{
+ <<"ok">> := #{
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revc">>,
+ <<"_attachments">> := #{
+ ?ATT := #{<<"stub">> := true}
+ }
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_specific_rev({_, DbUrl}) ->
+ Doc = #{<<"id">> => ?DOC, <<"rev">> => <<"2-revb">>},
+ {Code, Res} = bulk_get(DbUrl, [Doc]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"ok">> := #{
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revb">>,
+ <<"_attachments">> := #{
+ ?ATT := #{<<"stub">> := true}
+ }
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_specific_rev_latest({_, DbUrl}) ->
+ Doc = #{<<"id">> => ?DOC, <<"rev">> => <<"2-revb">>},
+ {Code, Res} = bulk_get(DbUrl, [Doc], "?latest=true"),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"ok">> := #{
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revb">>,
+ <<"_attachments">> := #{
+ ?ATT := #{<<"stub">> := true}
+ }
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_ancestor_rev_latest({_, DbUrl}) ->
+ Doc = #{<<"id">> => ?DOC, <<"rev">> => <<"1-reva">>},
+ {Code, Res} = bulk_get(DbUrl, [Doc], "?latest=true"),
Review Comment:
Good idea to document it. We document it for doc GETs https://docs.couchdb.org/en/3.2.2-docs/api/document/common.html#get--db-docid and we cheat for the _bulk_get but allowing passing most of the same option.
`latest` as implemented today means, given a particular revision, we don't want to return that revision only but all the latest descendants (leafs) of that revision.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: notifications-unsubscribe@couchdb.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [couchdb] jaydoane commented on a diff in pull request #4209: Add bulk_get tests
Posted by GitBox <gi...@apache.org>.
jaydoane commented on code in PR #4209:
URL: https://github.com/apache/couchdb/pull/4209#discussion_r997291823
##########
src/chttpd/test/eunit/chttpd_bulk_get_test.erl:
##########
@@ -0,0 +1,785 @@
+% Licensed under the Apache License, Version 2.0 (the "License"); you may not
+% use this file except in compliance with the License. You may obtain a copy of
+% the License at
+%
+% http://www.apache.org/licenses/LICENSE-2.0
+%
+% Unless required by applicable law or agreed to in writing, software
+% distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+% WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+% License for the specific language governing permissions and limitations under
+% the License.
+
+-module(chttpd_bulk_get_test).
+
+-include_lib("couch/include/couch_db.hrl").
+-include_lib("couch/include/couch_eunit.hrl").
+
+-define(USER, "chttpd_bulk_get_test_admin").
+-define(PASS, "pass").
+-define(AUTH, {basic_auth, {?USER, ?PASS}}).
+-define(JSON, {"Content-Type", "application/json"}).
+
+-define(DOC, <<"doc">>).
+-define(REVA, <<"reva">>).
+-define(REVB, <<"revb">>).
+-define(REVC, <<"revc">>).
+-define(ATT, <<"att">>).
+-define(ATT_DATA, <<"dGhlZGF0YQ==">>).
+
+-define(DOC_COUNT, 2000).
+
+test_docs_revs() ->
+ [
+ {?DOC, [?REVA]},
+ {?DOC, [?REVB, ?REVA]},
+ {?DOC, [?REVC, ?REVA]}
+ ].
+
+bulk_get_test_() ->
+ {
+ setup,
+ fun setup_basic/0,
+ fun teardown/1,
+ with([
+ ?TDEF(t_empty_request),
+ ?TDEF(t_no_docs),
+ ?TDEF(t_invalid_doc),
+ ?TDEF(t_doc_no_id),
+ ?TDEF(t_missing_doc),
+ ?TDEF(t_invalid_rev),
+ ?TDEF(t_missing_rev),
+ ?TDEF(t_doc_all_revs),
+ ?TDEF(t_specific_rev),
+ ?TDEF(t_specific_rev_latest),
+ ?TDEF(t_ancestor_rev_latest),
+ ?TDEF(t_revs_true),
+ ?TDEF(t_attachments_true),
+ ?TDEF(t_atts_since),
+ ?TDEF(t_atts_since_returns_attachment),
+ ?TDEF(t_atts_since_attachments_true),
+ ?TDEF(t_atts_since_multiple),
+ ?TDEF(t_atts_since_multiple_attachments_true),
+ ?TDEF(t_missing_rev_latest)
+ ])
+ }.
+
+bulk_get_multiple_docs_test_() ->
+ {
+ foreach,
+ fun setup_multiple/0,
+ fun teardown/1,
+ [
+ ?TDEF_FE(t_multiple_docs, 10)
+ ]
+ }.
+
+t_empty_request({_, DbUrl}) ->
+ {Code, Res} = bulk_get(DbUrl, []),
+ ?assertEqual(200, Code),
+ ?assertEqual([], Res).
+
+t_no_docs({_, DbUrl}) ->
+ {Code, #{}} = req(post, DbUrl ++ "/_bulk_get", #{}),
+ ?assertEqual(400, Code).
+
+t_invalid_doc({_, DbUrl}) ->
+ {Code, Res} = bulk_get(DbUrl, [<<"foo">>]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"error">> := #{
+ <<"id">> := null,
+ <<"rev">> := null,
+ <<"error">> := <<"bad_request">>
+ }
+ }
+ ],
+ <<"id">> := null
+ }
+ ],
+ Res
+ ).
+
+t_doc_no_id({_, DbUrl}) ->
+ {Code, Res} = bulk_get(DbUrl, [#{<<"rev">> => <<"1-foo">>}]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"error">> := #{
+ <<"id">> := null,
+ <<"rev">> := null,
+ <<"error">> := <<"bad_request">>
+ }
+ }
+ ],
+ <<"id">> := null
+ }
+ ],
+ Res
+ ).
+
+t_missing_doc({_, DbUrl}) ->
+ {Code, Res} = bulk_get(DbUrl, [#{<<"id">> => <<"missing">>}]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"error">> := #{
+ <<"error">> := <<"not_found">>,
+ <<"id">> := <<"missing">>,
+ <<"rev">> := <<"undefined">>
+ }
+ }
+ ],
+ <<"id">> := <<"missing">>
+ }
+ ],
+ Res
+ ).
+
+t_invalid_rev({_, DbUrl}) ->
+ Doc = #{<<"id">> => ?DOC, <<"rev">> => 42},
+ {Code, Res} = bulk_get(DbUrl, [Doc]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"error">> := #{
+ <<"error">> := <<"bad_request">>,
+ <<"id">> := ?DOC,
+ <<"rev">> := 42
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_missing_rev({_, DbUrl}) ->
+ Doc = #{<<"id">> => ?DOC, <<"rev">> => <<"1-x">>},
+ {Code, Res} = bulk_get(DbUrl, [Doc]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"error">> := #{
+ <<"error">> := <<"not_found">>,
+ <<"id">> := ?DOC,
+ <<"rev">> := <<"1-x">>
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_doc_all_revs({_, DbUrl}) ->
+ {Code, Res} = bulk_get(DbUrl, [#{<<"id">> => ?DOC}]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"ok">> := #{
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revb">>,
+ <<"_attachments">> := #{
+ ?ATT := #{<<"stub">> := true}
+ }
+ }
+ },
+ #{
+ <<"ok">> := #{
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revc">>,
+ <<"_attachments">> := #{
+ ?ATT := #{<<"stub">> := true}
+ }
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_specific_rev({_, DbUrl}) ->
+ Doc = #{<<"id">> => ?DOC, <<"rev">> => <<"2-revb">>},
+ {Code, Res} = bulk_get(DbUrl, [Doc]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"ok">> := #{
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revb">>,
+ <<"_attachments">> := #{
+ ?ATT := #{<<"stub">> := true}
+ }
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_specific_rev_latest({_, DbUrl}) ->
+ Doc = #{<<"id">> => ?DOC, <<"rev">> => <<"2-revb">>},
+ {Code, Res} = bulk_get(DbUrl, [Doc], "?latest=true"),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"ok">> := #{
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revb">>,
+ <<"_attachments">> := #{
+ ?ATT := #{<<"stub">> := true}
+ }
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_ancestor_rev_latest({_, DbUrl}) ->
+ Doc = #{<<"id">> => ?DOC, <<"rev">> => <<"1-reva">>},
+ {Code, Res} = bulk_get(DbUrl, [Doc], "?latest=true"),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"ok">> := #{
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revb">>,
+ <<"_attachments">> := #{
+ ?ATT := #{<<"stub">> := true}
+ }
+ }
+ },
+ #{
+ <<"ok">> := #{
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revc">>,
+ <<"_attachments">> := #{
+ ?ATT := #{<<"stub">> := true}
+ }
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_revs_true({_, DbUrl}) ->
+ Doc = #{
+ <<"id">> => ?DOC,
+ <<"rev">> => <<"1-reva">>
+ },
+ {Code, Res} = bulk_get(DbUrl, [Doc], "?revs=true"),
Review Comment:
Also not seeing docs for bulk_get `revs=true`.
##########
src/chttpd/test/eunit/chttpd_bulk_get_test.erl:
##########
@@ -0,0 +1,785 @@
+% Licensed under the Apache License, Version 2.0 (the "License"); you may not
+% use this file except in compliance with the License. You may obtain a copy of
+% the License at
+%
+% http://www.apache.org/licenses/LICENSE-2.0
+%
+% Unless required by applicable law or agreed to in writing, software
+% distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+% WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+% License for the specific language governing permissions and limitations under
+% the License.
+
+-module(chttpd_bulk_get_test).
+
+-include_lib("couch/include/couch_db.hrl").
+-include_lib("couch/include/couch_eunit.hrl").
+
+-define(USER, "chttpd_bulk_get_test_admin").
+-define(PASS, "pass").
+-define(AUTH, {basic_auth, {?USER, ?PASS}}).
+-define(JSON, {"Content-Type", "application/json"}).
+
+-define(DOC, <<"doc">>).
+-define(REVA, <<"reva">>).
+-define(REVB, <<"revb">>).
+-define(REVC, <<"revc">>).
+-define(ATT, <<"att">>).
+-define(ATT_DATA, <<"dGhlZGF0YQ==">>).
+
+-define(DOC_COUNT, 2000).
+
+test_docs_revs() ->
+ [
+ {?DOC, [?REVA]},
+ {?DOC, [?REVB, ?REVA]},
+ {?DOC, [?REVC, ?REVA]}
+ ].
+
+bulk_get_test_() ->
+ {
+ setup,
+ fun setup_basic/0,
+ fun teardown/1,
+ with([
+ ?TDEF(t_empty_request),
+ ?TDEF(t_no_docs),
+ ?TDEF(t_invalid_doc),
+ ?TDEF(t_doc_no_id),
+ ?TDEF(t_missing_doc),
+ ?TDEF(t_invalid_rev),
+ ?TDEF(t_missing_rev),
+ ?TDEF(t_doc_all_revs),
+ ?TDEF(t_specific_rev),
+ ?TDEF(t_specific_rev_latest),
+ ?TDEF(t_ancestor_rev_latest),
+ ?TDEF(t_revs_true),
+ ?TDEF(t_attachments_true),
+ ?TDEF(t_atts_since),
+ ?TDEF(t_atts_since_returns_attachment),
+ ?TDEF(t_atts_since_attachments_true),
+ ?TDEF(t_atts_since_multiple),
+ ?TDEF(t_atts_since_multiple_attachments_true),
+ ?TDEF(t_missing_rev_latest)
+ ])
+ }.
+
+bulk_get_multiple_docs_test_() ->
+ {
+ foreach,
+ fun setup_multiple/0,
+ fun teardown/1,
+ [
+ ?TDEF_FE(t_multiple_docs, 10)
+ ]
+ }.
+
+t_empty_request({_, DbUrl}) ->
+ {Code, Res} = bulk_get(DbUrl, []),
+ ?assertEqual(200, Code),
+ ?assertEqual([], Res).
+
+t_no_docs({_, DbUrl}) ->
+ {Code, #{}} = req(post, DbUrl ++ "/_bulk_get", #{}),
+ ?assertEqual(400, Code).
+
+t_invalid_doc({_, DbUrl}) ->
+ {Code, Res} = bulk_get(DbUrl, [<<"foo">>]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"error">> := #{
+ <<"id">> := null,
+ <<"rev">> := null,
+ <<"error">> := <<"bad_request">>
+ }
+ }
+ ],
+ <<"id">> := null
+ }
+ ],
+ Res
+ ).
+
+t_doc_no_id({_, DbUrl}) ->
+ {Code, Res} = bulk_get(DbUrl, [#{<<"rev">> => <<"1-foo">>}]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"error">> := #{
+ <<"id">> := null,
+ <<"rev">> := null,
+ <<"error">> := <<"bad_request">>
+ }
+ }
+ ],
+ <<"id">> := null
+ }
+ ],
+ Res
+ ).
+
+t_missing_doc({_, DbUrl}) ->
+ {Code, Res} = bulk_get(DbUrl, [#{<<"id">> => <<"missing">>}]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"error">> := #{
+ <<"error">> := <<"not_found">>,
+ <<"id">> := <<"missing">>,
+ <<"rev">> := <<"undefined">>
+ }
+ }
+ ],
+ <<"id">> := <<"missing">>
+ }
+ ],
+ Res
+ ).
+
+t_invalid_rev({_, DbUrl}) ->
+ Doc = #{<<"id">> => ?DOC, <<"rev">> => 42},
+ {Code, Res} = bulk_get(DbUrl, [Doc]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"error">> := #{
+ <<"error">> := <<"bad_request">>,
+ <<"id">> := ?DOC,
+ <<"rev">> := 42
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_missing_rev({_, DbUrl}) ->
+ Doc = #{<<"id">> => ?DOC, <<"rev">> => <<"1-x">>},
+ {Code, Res} = bulk_get(DbUrl, [Doc]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"error">> := #{
+ <<"error">> := <<"not_found">>,
+ <<"id">> := ?DOC,
+ <<"rev">> := <<"1-x">>
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_doc_all_revs({_, DbUrl}) ->
+ {Code, Res} = bulk_get(DbUrl, [#{<<"id">> => ?DOC}]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"ok">> := #{
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revb">>,
+ <<"_attachments">> := #{
+ ?ATT := #{<<"stub">> := true}
+ }
+ }
+ },
+ #{
+ <<"ok">> := #{
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revc">>,
+ <<"_attachments">> := #{
+ ?ATT := #{<<"stub">> := true}
+ }
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_specific_rev({_, DbUrl}) ->
+ Doc = #{<<"id">> => ?DOC, <<"rev">> => <<"2-revb">>},
+ {Code, Res} = bulk_get(DbUrl, [Doc]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"ok">> := #{
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revb">>,
+ <<"_attachments">> := #{
+ ?ATT := #{<<"stub">> := true}
+ }
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_specific_rev_latest({_, DbUrl}) ->
+ Doc = #{<<"id">> => ?DOC, <<"rev">> => <<"2-revb">>},
+ {Code, Res} = bulk_get(DbUrl, [Doc], "?latest=true"),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"ok">> := #{
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revb">>,
+ <<"_attachments">> := #{
+ ?ATT := #{<<"stub">> := true}
+ }
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_ancestor_rev_latest({_, DbUrl}) ->
+ Doc = #{<<"id">> => ?DOC, <<"rev">> => <<"1-reva">>},
+ {Code, Res} = bulk_get(DbUrl, [Doc], "?latest=true"),
Review Comment:
I looked for docs on `latest=true` [here](https://docs.couchdb.org/en/3.2.2-docs/api/database/bulk-api.html#db-bulk-get) but didn't see anything. Should we improve the docs, or is this an undocumented parameter?
##########
src/chttpd/test/eunit/chttpd_bulk_get_test.erl:
##########
@@ -0,0 +1,785 @@
+% Licensed under the Apache License, Version 2.0 (the "License"); you may not
+% use this file except in compliance with the License. You may obtain a copy of
+% the License at
+%
+% http://www.apache.org/licenses/LICENSE-2.0
+%
+% Unless required by applicable law or agreed to in writing, software
+% distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+% WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+% License for the specific language governing permissions and limitations under
+% the License.
+
+-module(chttpd_bulk_get_test).
+
+-include_lib("couch/include/couch_db.hrl").
+-include_lib("couch/include/couch_eunit.hrl").
+
+-define(USER, "chttpd_bulk_get_test_admin").
+-define(PASS, "pass").
+-define(AUTH, {basic_auth, {?USER, ?PASS}}).
+-define(JSON, {"Content-Type", "application/json"}).
+
+-define(DOC, <<"doc">>).
+-define(REVA, <<"reva">>).
+-define(REVB, <<"revb">>).
+-define(REVC, <<"revc">>).
+-define(ATT, <<"att">>).
+-define(ATT_DATA, <<"dGhlZGF0YQ==">>).
+
+-define(DOC_COUNT, 2000).
+
+test_docs_revs() ->
+ [
+ {?DOC, [?REVA]},
+ {?DOC, [?REVB, ?REVA]},
+ {?DOC, [?REVC, ?REVA]}
+ ].
+
+bulk_get_test_() ->
+ {
+ setup,
+ fun setup_basic/0,
+ fun teardown/1,
+ with([
+ ?TDEF(t_empty_request),
+ ?TDEF(t_no_docs),
+ ?TDEF(t_invalid_doc),
+ ?TDEF(t_doc_no_id),
+ ?TDEF(t_missing_doc),
+ ?TDEF(t_invalid_rev),
+ ?TDEF(t_missing_rev),
+ ?TDEF(t_doc_all_revs),
+ ?TDEF(t_specific_rev),
+ ?TDEF(t_specific_rev_latest),
+ ?TDEF(t_ancestor_rev_latest),
+ ?TDEF(t_revs_true),
+ ?TDEF(t_attachments_true),
+ ?TDEF(t_atts_since),
+ ?TDEF(t_atts_since_returns_attachment),
+ ?TDEF(t_atts_since_attachments_true),
+ ?TDEF(t_atts_since_multiple),
+ ?TDEF(t_atts_since_multiple_attachments_true),
+ ?TDEF(t_missing_rev_latest)
+ ])
+ }.
+
+bulk_get_multiple_docs_test_() ->
+ {
+ foreach,
+ fun setup_multiple/0,
+ fun teardown/1,
+ [
+ ?TDEF_FE(t_multiple_docs, 10)
+ ]
+ }.
+
+t_empty_request({_, DbUrl}) ->
+ {Code, Res} = bulk_get(DbUrl, []),
+ ?assertEqual(200, Code),
+ ?assertEqual([], Res).
+
+t_no_docs({_, DbUrl}) ->
+ {Code, #{}} = req(post, DbUrl ++ "/_bulk_get", #{}),
+ ?assertEqual(400, Code).
+
+t_invalid_doc({_, DbUrl}) ->
+ {Code, Res} = bulk_get(DbUrl, [<<"foo">>]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"error">> := #{
+ <<"id">> := null,
+ <<"rev">> := null,
+ <<"error">> := <<"bad_request">>
+ }
+ }
+ ],
+ <<"id">> := null
+ }
+ ],
+ Res
+ ).
+
+t_doc_no_id({_, DbUrl}) ->
+ {Code, Res} = bulk_get(DbUrl, [#{<<"rev">> => <<"1-foo">>}]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"error">> := #{
+ <<"id">> := null,
+ <<"rev">> := null,
+ <<"error">> := <<"bad_request">>
+ }
+ }
+ ],
+ <<"id">> := null
+ }
+ ],
+ Res
+ ).
+
+t_missing_doc({_, DbUrl}) ->
+ {Code, Res} = bulk_get(DbUrl, [#{<<"id">> => <<"missing">>}]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"error">> := #{
+ <<"error">> := <<"not_found">>,
+ <<"id">> := <<"missing">>,
+ <<"rev">> := <<"undefined">>
+ }
+ }
+ ],
+ <<"id">> := <<"missing">>
+ }
+ ],
+ Res
+ ).
+
+t_invalid_rev({_, DbUrl}) ->
+ Doc = #{<<"id">> => ?DOC, <<"rev">> => 42},
+ {Code, Res} = bulk_get(DbUrl, [Doc]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"error">> := #{
+ <<"error">> := <<"bad_request">>,
+ <<"id">> := ?DOC,
+ <<"rev">> := 42
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_missing_rev({_, DbUrl}) ->
+ Doc = #{<<"id">> => ?DOC, <<"rev">> => <<"1-x">>},
+ {Code, Res} = bulk_get(DbUrl, [Doc]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"error">> := #{
+ <<"error">> := <<"not_found">>,
+ <<"id">> := ?DOC,
+ <<"rev">> := <<"1-x">>
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_doc_all_revs({_, DbUrl}) ->
+ {Code, Res} = bulk_get(DbUrl, [#{<<"id">> => ?DOC}]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"ok">> := #{
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revb">>,
+ <<"_attachments">> := #{
+ ?ATT := #{<<"stub">> := true}
+ }
+ }
+ },
+ #{
+ <<"ok">> := #{
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revc">>,
+ <<"_attachments">> := #{
+ ?ATT := #{<<"stub">> := true}
+ }
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_specific_rev({_, DbUrl}) ->
+ Doc = #{<<"id">> => ?DOC, <<"rev">> => <<"2-revb">>},
+ {Code, Res} = bulk_get(DbUrl, [Doc]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"ok">> := #{
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revb">>,
+ <<"_attachments">> := #{
+ ?ATT := #{<<"stub">> := true}
+ }
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_specific_rev_latest({_, DbUrl}) ->
+ Doc = #{<<"id">> => ?DOC, <<"rev">> => <<"2-revb">>},
+ {Code, Res} = bulk_get(DbUrl, [Doc], "?latest=true"),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"ok">> := #{
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revb">>,
+ <<"_attachments">> := #{
+ ?ATT := #{<<"stub">> := true}
+ }
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_ancestor_rev_latest({_, DbUrl}) ->
+ Doc = #{<<"id">> => ?DOC, <<"rev">> => <<"1-reva">>},
+ {Code, Res} = bulk_get(DbUrl, [Doc], "?latest=true"),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"ok">> := #{
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revb">>,
+ <<"_attachments">> := #{
+ ?ATT := #{<<"stub">> := true}
+ }
+ }
+ },
+ #{
+ <<"ok">> := #{
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revc">>,
+ <<"_attachments">> := #{
+ ?ATT := #{<<"stub">> := true}
+ }
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_revs_true({_, DbUrl}) ->
+ Doc = #{
+ <<"id">> => ?DOC,
+ <<"rev">> => <<"1-reva">>
+ },
+ {Code, Res} = bulk_get(DbUrl, [Doc], "?revs=true"),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"ok">> := #{
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"1-reva">>,
+ <<"_revisions">> :=
+ #{<<"ids">> := [<<"reva">>], <<"start">> := 1},
+ <<"_attachments">> := #{
+ ?ATT := #{<<"stub">> := true}
+ }
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_attachments_true({_, DbUrl}) ->
+ Doc = #{
+ <<"id">> => ?DOC,
+ <<"rev">> => <<"1-reva">>
+ },
+ {Code, Res} = bulk_get(DbUrl, [Doc], "?attachments=true"),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"ok">> := #{
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"1-reva">>,
+ <<"_attachments">> := #{
+ ?ATT := #{<<"data">> := ?ATT_DATA}
+ }
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_atts_since({_, DbUrl}) ->
+ % Attachment should not be returned as 2 from 2-revb is not stricly greater
+ % than 1 from our attachment's revpos
+ Doc = #{
+ <<"id">> => ?DOC,
+ <<"rev">> => <<"2-revb">>,
+ <<"atts_since">> => [<<"2-revb">>]
+ },
+ {Code, Res} = bulk_get(DbUrl, [Doc]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"ok">> := #{
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revb">>,
+ <<"_attachments">> := #{
+ ?ATT := #{<<"stub">> := true}
+ }
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_atts_since_returns_attachment({_, DbUrl}) ->
+ % 0-baz revpos 0 is less than revpos 1 of our attachment
+ Doc = #{
+ <<"id">> => ?DOC,
+ <<"rev">> => <<"2-revb">>,
+ <<"atts_since">> => [<<"0-baz">>]
+ },
+ {Code, Res} = bulk_get(DbUrl, [Doc]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"ok">> := #{
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revb">>,
+ <<"_attachments">> := #{
+ ?ATT := #{<<"data">> := ?ATT_DATA}
+ }
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_atts_since_attachments_true({_, DbUrl}) ->
+ % Check that atts_since overrides attachments=true
+ Doc = #{
+ <<"id">> => ?DOC,
+ <<"rev">> => <<"2-revb">>,
+ <<"atts_since">> => [<<"2-revb">>]
+ },
+ {Code, Res} = bulk_get(DbUrl, [Doc], "?attachments=true"),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"ok">> := #{
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revb">>,
+ <<"_attachments">> := #{
+ ?ATT := #{
+ <<"stub">> := true
+ }
+ }
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_atts_since_multiple({_, DbUrl}) ->
+ % Attachment revpos is 1 so we do not expect this attachment body
+ Docs = [
+ #{
+ <<"id">> => ?DOC,
+ <<"rev">> => <<"2-revb">>,
+ <<"atts_since">> => [<<"2-revb">>]
+ },
+ % Should get the attachment revpos=1 is greater than 0-foo
+ #{
+ <<"id">> => ?DOC,
+ <<"rev">> => <<"2-revb">>,
+ <<"atts_since">> => [<<"0-foo">>]
+ },
+ % Empty atts_since. Do not expect to get the attachment
+ #{
+ <<"id">> => ?DOC,
+ <<"rev">> => <<"2-revb">>,
+ <<"atts_since">> => []
+ },
+ % Add a document without atts_since to ensure atts_since applies only to
+ % individual requests
+ #{
+ <<"id">> => ?DOC,
+ <<"rev">> => <<"2-revb">>
+ }
+ ],
+ {Code, Res} = bulk_get(DbUrl, Docs),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"ok">> := #{
+ <<"_attachments">> := #{
+ ?ATT := #{<<"stub">> := true}
+ },
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revb">>
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ },
+ #{
+ <<"docs">> := [
+ #{
+ <<"ok">> := #{
+ <<"_attachments">> := #{
+ ?ATT := #{<<"data">> := ?ATT_DATA}
+ },
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revb">>
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ },
+ #{
+ <<"docs">> := [
+ #{
+ <<"ok">> := #{
+ <<"_attachments">> := #{
+ ?ATT := #{<<"stub">> := true}
+ },
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revb">>
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ },
+ #{
+ <<"docs">> := [
+ #{
+ <<"ok">> := #{
+ <<"_attachments">> :=
+ #{?ATT := #{<<"stub">> := true}},
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revb">>
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_atts_since_multiple_attachments_true({_, DbUrl}) ->
+ % Since attachments=true, expect to always get the attachments, unless
+ % there is an atts_since present and atts_since would prevent the
+ % attachment from being returned.
+ Docs = [
+ % Attachment revpos is 1 so we do not expect this attachment body
+ #{
+ <<"id">> => ?DOC,
+ <<"rev">> => <<"2-revb">>,
+ <<"atts_since">> => [<<"2-revb">>]
+ },
+ % Should get the attachment revpos=1 is greater than 0-foo
+ #{
+ <<"id">> => ?DOC,
+ <<"rev">> => <<"2-revb">>,
+ <<"atts_since">> => [<<"0-foo">>]
+ },
+ % Should get the attachment as it is set as a default option
+ #{
+ <<"id">> => ?DOC,
+ <<"rev">> => <<"2-revb">>,
+ <<"atts_since">> => []
+ },
+ % Check a doc without atts_since to ensure atts_since applies only to
+ % individual requests, otherwise default options apply
+ #{
+ <<"id">> => ?DOC,
+ <<"rev">> => <<"2-revb">>
+ }
+ ],
+ {Code, Res} = bulk_get(DbUrl, Docs, "?attachments=true"),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"ok">> := #{
+ <<"_attachments">> := #{
+ ?ATT := #{<<"stub">> := true}
+ },
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revb">>
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ },
+ #{
+ <<"docs">> := [
+ #{
+ <<"ok">> := #{
+ <<"_attachments">> := #{
+ ?ATT := #{<<"data">> := ?ATT_DATA}
+ },
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revb">>
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ },
+ #{
+ <<"docs">> := [
+ #{
+ <<"ok">> := #{
+ <<"_attachments">> := #{
+ ?ATT := #{<<"data">> := ?ATT_DATA}
+ },
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revb">>
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ },
+ #{
+ <<"docs">> := [
+ #{
+ <<"ok">> := #{
+ <<"_attachments">> :=
+ #{?ATT := #{<<"data">> := ?ATT_DATA}},
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revb">>
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_missing_rev_latest({_, DbUrl}) ->
+ % Check the case of latest and a missing
Review Comment:
should this be "and a missing _rev_"?
##########
src/chttpd/test/eunit/chttpd_bulk_get_test.erl:
##########
@@ -0,0 +1,785 @@
+% Licensed under the Apache License, Version 2.0 (the "License"); you may not
+% use this file except in compliance with the License. You may obtain a copy of
+% the License at
+%
+% http://www.apache.org/licenses/LICENSE-2.0
+%
+% Unless required by applicable law or agreed to in writing, software
+% distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+% WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+% License for the specific language governing permissions and limitations under
+% the License.
+
+-module(chttpd_bulk_get_test).
+
+-include_lib("couch/include/couch_db.hrl").
+-include_lib("couch/include/couch_eunit.hrl").
+
+-define(USER, "chttpd_bulk_get_test_admin").
+-define(PASS, "pass").
+-define(AUTH, {basic_auth, {?USER, ?PASS}}).
+-define(JSON, {"Content-Type", "application/json"}).
+
+-define(DOC, <<"doc">>).
+-define(REVA, <<"reva">>).
+-define(REVB, <<"revb">>).
+-define(REVC, <<"revc">>).
+-define(ATT, <<"att">>).
+-define(ATT_DATA, <<"dGhlZGF0YQ==">>).
+
+-define(DOC_COUNT, 2000).
+
+test_docs_revs() ->
+ [
+ {?DOC, [?REVA]},
+ {?DOC, [?REVB, ?REVA]},
+ {?DOC, [?REVC, ?REVA]}
+ ].
+
+bulk_get_test_() ->
+ {
+ setup,
+ fun setup_basic/0,
+ fun teardown/1,
+ with([
+ ?TDEF(t_empty_request),
+ ?TDEF(t_no_docs),
+ ?TDEF(t_invalid_doc),
+ ?TDEF(t_doc_no_id),
+ ?TDEF(t_missing_doc),
+ ?TDEF(t_invalid_rev),
+ ?TDEF(t_missing_rev),
+ ?TDEF(t_doc_all_revs),
+ ?TDEF(t_specific_rev),
+ ?TDEF(t_specific_rev_latest),
+ ?TDEF(t_ancestor_rev_latest),
+ ?TDEF(t_revs_true),
+ ?TDEF(t_attachments_true),
+ ?TDEF(t_atts_since),
+ ?TDEF(t_atts_since_returns_attachment),
+ ?TDEF(t_atts_since_attachments_true),
+ ?TDEF(t_atts_since_multiple),
+ ?TDEF(t_atts_since_multiple_attachments_true),
+ ?TDEF(t_missing_rev_latest)
+ ])
+ }.
+
+bulk_get_multiple_docs_test_() ->
+ {
+ foreach,
+ fun setup_multiple/0,
+ fun teardown/1,
+ [
+ ?TDEF_FE(t_multiple_docs, 10)
+ ]
+ }.
+
+t_empty_request({_, DbUrl}) ->
+ {Code, Res} = bulk_get(DbUrl, []),
+ ?assertEqual(200, Code),
+ ?assertEqual([], Res).
+
+t_no_docs({_, DbUrl}) ->
+ {Code, #{}} = req(post, DbUrl ++ "/_bulk_get", #{}),
+ ?assertEqual(400, Code).
+
+t_invalid_doc({_, DbUrl}) ->
+ {Code, Res} = bulk_get(DbUrl, [<<"foo">>]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"error">> := #{
+ <<"id">> := null,
+ <<"rev">> := null,
+ <<"error">> := <<"bad_request">>
+ }
+ }
+ ],
+ <<"id">> := null
+ }
+ ],
+ Res
+ ).
+
+t_doc_no_id({_, DbUrl}) ->
+ {Code, Res} = bulk_get(DbUrl, [#{<<"rev">> => <<"1-foo">>}]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"error">> := #{
+ <<"id">> := null,
+ <<"rev">> := null,
+ <<"error">> := <<"bad_request">>
+ }
+ }
+ ],
+ <<"id">> := null
+ }
+ ],
+ Res
+ ).
+
+t_missing_doc({_, DbUrl}) ->
+ {Code, Res} = bulk_get(DbUrl, [#{<<"id">> => <<"missing">>}]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"error">> := #{
+ <<"error">> := <<"not_found">>,
+ <<"id">> := <<"missing">>,
+ <<"rev">> := <<"undefined">>
+ }
+ }
+ ],
+ <<"id">> := <<"missing">>
+ }
+ ],
+ Res
+ ).
+
+t_invalid_rev({_, DbUrl}) ->
+ Doc = #{<<"id">> => ?DOC, <<"rev">> => 42},
+ {Code, Res} = bulk_get(DbUrl, [Doc]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"error">> := #{
+ <<"error">> := <<"bad_request">>,
Review Comment:
Seems like it would be nice to say _why_ it's a bad request (invalid rev in this case), but I guess that ship has sailed?
##########
src/chttpd/test/eunit/chttpd_bulk_get_test.erl:
##########
@@ -0,0 +1,785 @@
+% Licensed under the Apache License, Version 2.0 (the "License"); you may not
+% use this file except in compliance with the License. You may obtain a copy of
+% the License at
+%
+% http://www.apache.org/licenses/LICENSE-2.0
+%
+% Unless required by applicable law or agreed to in writing, software
+% distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+% WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+% License for the specific language governing permissions and limitations under
+% the License.
+
+-module(chttpd_bulk_get_test).
+
+-include_lib("couch/include/couch_db.hrl").
+-include_lib("couch/include/couch_eunit.hrl").
+
+-define(USER, "chttpd_bulk_get_test_admin").
+-define(PASS, "pass").
+-define(AUTH, {basic_auth, {?USER, ?PASS}}).
+-define(JSON, {"Content-Type", "application/json"}).
+
+-define(DOC, <<"doc">>).
+-define(REVA, <<"reva">>).
+-define(REVB, <<"revb">>).
+-define(REVC, <<"revc">>).
+-define(ATT, <<"att">>).
+-define(ATT_DATA, <<"dGhlZGF0YQ==">>).
+
+-define(DOC_COUNT, 2000).
+
+test_docs_revs() ->
+ [
+ {?DOC, [?REVA]},
+ {?DOC, [?REVB, ?REVA]},
+ {?DOC, [?REVC, ?REVA]}
+ ].
+
+bulk_get_test_() ->
+ {
+ setup,
+ fun setup_basic/0,
+ fun teardown/1,
+ with([
+ ?TDEF(t_empty_request),
+ ?TDEF(t_no_docs),
+ ?TDEF(t_invalid_doc),
+ ?TDEF(t_doc_no_id),
+ ?TDEF(t_missing_doc),
+ ?TDEF(t_invalid_rev),
+ ?TDEF(t_missing_rev),
+ ?TDEF(t_doc_all_revs),
+ ?TDEF(t_specific_rev),
+ ?TDEF(t_specific_rev_latest),
+ ?TDEF(t_ancestor_rev_latest),
+ ?TDEF(t_revs_true),
+ ?TDEF(t_attachments_true),
+ ?TDEF(t_atts_since),
+ ?TDEF(t_atts_since_returns_attachment),
+ ?TDEF(t_atts_since_attachments_true),
+ ?TDEF(t_atts_since_multiple),
+ ?TDEF(t_atts_since_multiple_attachments_true),
+ ?TDEF(t_missing_rev_latest)
+ ])
+ }.
+
+bulk_get_multiple_docs_test_() ->
+ {
+ foreach,
+ fun setup_multiple/0,
+ fun teardown/1,
+ [
+ ?TDEF_FE(t_multiple_docs, 10)
+ ]
+ }.
+
+t_empty_request({_, DbUrl}) ->
+ {Code, Res} = bulk_get(DbUrl, []),
+ ?assertEqual(200, Code),
+ ?assertEqual([], Res).
+
+t_no_docs({_, DbUrl}) ->
+ {Code, #{}} = req(post, DbUrl ++ "/_bulk_get", #{}),
+ ?assertEqual(400, Code).
+
+t_invalid_doc({_, DbUrl}) ->
+ {Code, Res} = bulk_get(DbUrl, [<<"foo">>]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"error">> := #{
+ <<"id">> := null,
+ <<"rev">> := null,
+ <<"error">> := <<"bad_request">>
+ }
+ }
+ ],
+ <<"id">> := null
+ }
+ ],
+ Res
+ ).
+
+t_doc_no_id({_, DbUrl}) ->
+ {Code, Res} = bulk_get(DbUrl, [#{<<"rev">> => <<"1-foo">>}]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"error">> := #{
+ <<"id">> := null,
+ <<"rev">> := null,
+ <<"error">> := <<"bad_request">>
+ }
+ }
+ ],
+ <<"id">> := null
+ }
+ ],
+ Res
+ ).
+
+t_missing_doc({_, DbUrl}) ->
+ {Code, Res} = bulk_get(DbUrl, [#{<<"id">> => <<"missing">>}]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"error">> := #{
+ <<"error">> := <<"not_found">>,
+ <<"id">> := <<"missing">>,
+ <<"rev">> := <<"undefined">>
+ }
+ }
+ ],
+ <<"id">> := <<"missing">>
+ }
+ ],
+ Res
+ ).
+
+t_invalid_rev({_, DbUrl}) ->
+ Doc = #{<<"id">> => ?DOC, <<"rev">> => 42},
+ {Code, Res} = bulk_get(DbUrl, [Doc]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"error">> := #{
+ <<"error">> := <<"bad_request">>,
+ <<"id">> := ?DOC,
+ <<"rev">> := 42
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_missing_rev({_, DbUrl}) ->
+ Doc = #{<<"id">> => ?DOC, <<"rev">> => <<"1-x">>},
+ {Code, Res} = bulk_get(DbUrl, [Doc]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"error">> := #{
+ <<"error">> := <<"not_found">>,
+ <<"id">> := ?DOC,
+ <<"rev">> := <<"1-x">>
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_doc_all_revs({_, DbUrl}) ->
+ {Code, Res} = bulk_get(DbUrl, [#{<<"id">> => ?DOC}]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"ok">> := #{
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revb">>,
+ <<"_attachments">> := #{
+ ?ATT := #{<<"stub">> := true}
+ }
+ }
+ },
+ #{
+ <<"ok">> := #{
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revc">>,
+ <<"_attachments">> := #{
+ ?ATT := #{<<"stub">> := true}
+ }
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_specific_rev({_, DbUrl}) ->
+ Doc = #{<<"id">> => ?DOC, <<"rev">> => <<"2-revb">>},
+ {Code, Res} = bulk_get(DbUrl, [Doc]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"ok">> := #{
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revb">>,
+ <<"_attachments">> := #{
+ ?ATT := #{<<"stub">> := true}
+ }
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_specific_rev_latest({_, DbUrl}) ->
+ Doc = #{<<"id">> => ?DOC, <<"rev">> => <<"2-revb">>},
+ {Code, Res} = bulk_get(DbUrl, [Doc], "?latest=true"),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"ok">> := #{
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revb">>,
+ <<"_attachments">> := #{
+ ?ATT := #{<<"stub">> := true}
+ }
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_ancestor_rev_latest({_, DbUrl}) ->
+ Doc = #{<<"id">> => ?DOC, <<"rev">> => <<"1-reva">>},
+ {Code, Res} = bulk_get(DbUrl, [Doc], "?latest=true"),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"ok">> := #{
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revb">>,
+ <<"_attachments">> := #{
+ ?ATT := #{<<"stub">> := true}
+ }
+ }
+ },
+ #{
+ <<"ok">> := #{
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revc">>,
+ <<"_attachments">> := #{
+ ?ATT := #{<<"stub">> := true}
+ }
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_revs_true({_, DbUrl}) ->
+ Doc = #{
+ <<"id">> => ?DOC,
+ <<"rev">> => <<"1-reva">>
+ },
+ {Code, Res} = bulk_get(DbUrl, [Doc], "?revs=true"),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"ok">> := #{
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"1-reva">>,
+ <<"_revisions">> :=
+ #{<<"ids">> := [<<"reva">>], <<"start">> := 1},
+ <<"_attachments">> := #{
+ ?ATT := #{<<"stub">> := true}
+ }
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_attachments_true({_, DbUrl}) ->
+ Doc = #{
+ <<"id">> => ?DOC,
+ <<"rev">> => <<"1-reva">>
+ },
+ {Code, Res} = bulk_get(DbUrl, [Doc], "?attachments=true"),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"ok">> := #{
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"1-reva">>,
+ <<"_attachments">> := #{
+ ?ATT := #{<<"data">> := ?ATT_DATA}
+ }
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_atts_since({_, DbUrl}) ->
+ % Attachment should not be returned as 2 from 2-revb is not stricly greater
+ % than 1 from our attachment's revpos
+ Doc = #{
+ <<"id">> => ?DOC,
+ <<"rev">> => <<"2-revb">>,
+ <<"atts_since">> => [<<"2-revb">>]
+ },
+ {Code, Res} = bulk_get(DbUrl, [Doc]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"ok">> := #{
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revb">>,
+ <<"_attachments">> := #{
+ ?ATT := #{<<"stub">> := true}
+ }
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_atts_since_returns_attachment({_, DbUrl}) ->
+ % 0-baz revpos 0 is less than revpos 1 of our attachment
+ Doc = #{
+ <<"id">> => ?DOC,
+ <<"rev">> => <<"2-revb">>,
+ <<"atts_since">> => [<<"0-baz">>]
+ },
+ {Code, Res} = bulk_get(DbUrl, [Doc]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"ok">> := #{
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revb">>,
+ <<"_attachments">> := #{
+ ?ATT := #{<<"data">> := ?ATT_DATA}
+ }
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_atts_since_attachments_true({_, DbUrl}) ->
+ % Check that atts_since overrides attachments=true
+ Doc = #{
+ <<"id">> => ?DOC,
+ <<"rev">> => <<"2-revb">>,
+ <<"atts_since">> => [<<"2-revb">>]
+ },
+ {Code, Res} = bulk_get(DbUrl, [Doc], "?attachments=true"),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"ok">> := #{
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revb">>,
+ <<"_attachments">> := #{
+ ?ATT := #{
+ <<"stub">> := true
+ }
+ }
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_atts_since_multiple({_, DbUrl}) ->
+ % Attachment revpos is 1 so we do not expect this attachment body
+ Docs = [
+ #{
+ <<"id">> => ?DOC,
+ <<"rev">> => <<"2-revb">>,
+ <<"atts_since">> => [<<"2-revb">>]
+ },
+ % Should get the attachment revpos=1 is greater than 0-foo
Review Comment:
missing "since" between attachment and revpos=1?
##########
src/chttpd/test/eunit/chttpd_bulk_get_test.erl:
##########
@@ -0,0 +1,785 @@
+% Licensed under the Apache License, Version 2.0 (the "License"); you may not
+% use this file except in compliance with the License. You may obtain a copy of
+% the License at
+%
+% http://www.apache.org/licenses/LICENSE-2.0
+%
+% Unless required by applicable law or agreed to in writing, software
+% distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+% WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+% License for the specific language governing permissions and limitations under
+% the License.
+
+-module(chttpd_bulk_get_test).
+
+-include_lib("couch/include/couch_db.hrl").
+-include_lib("couch/include/couch_eunit.hrl").
+
+-define(USER, "chttpd_bulk_get_test_admin").
+-define(PASS, "pass").
+-define(AUTH, {basic_auth, {?USER, ?PASS}}).
+-define(JSON, {"Content-Type", "application/json"}).
+
+-define(DOC, <<"doc">>).
+-define(REVA, <<"reva">>).
+-define(REVB, <<"revb">>).
+-define(REVC, <<"revc">>).
+-define(ATT, <<"att">>).
+-define(ATT_DATA, <<"dGhlZGF0YQ==">>).
+
+-define(DOC_COUNT, 2000).
+
+test_docs_revs() ->
+ [
+ {?DOC, [?REVA]},
+ {?DOC, [?REVB, ?REVA]},
+ {?DOC, [?REVC, ?REVA]}
+ ].
+
+bulk_get_test_() ->
+ {
+ setup,
+ fun setup_basic/0,
+ fun teardown/1,
+ with([
+ ?TDEF(t_empty_request),
+ ?TDEF(t_no_docs),
+ ?TDEF(t_invalid_doc),
+ ?TDEF(t_doc_no_id),
+ ?TDEF(t_missing_doc),
+ ?TDEF(t_invalid_rev),
+ ?TDEF(t_missing_rev),
+ ?TDEF(t_doc_all_revs),
+ ?TDEF(t_specific_rev),
+ ?TDEF(t_specific_rev_latest),
+ ?TDEF(t_ancestor_rev_latest),
+ ?TDEF(t_revs_true),
+ ?TDEF(t_attachments_true),
+ ?TDEF(t_atts_since),
+ ?TDEF(t_atts_since_returns_attachment),
+ ?TDEF(t_atts_since_attachments_true),
+ ?TDEF(t_atts_since_multiple),
+ ?TDEF(t_atts_since_multiple_attachments_true),
+ ?TDEF(t_missing_rev_latest)
+ ])
+ }.
+
+bulk_get_multiple_docs_test_() ->
+ {
+ foreach,
+ fun setup_multiple/0,
+ fun teardown/1,
+ [
+ ?TDEF_FE(t_multiple_docs, 10)
+ ]
+ }.
+
+t_empty_request({_, DbUrl}) ->
+ {Code, Res} = bulk_get(DbUrl, []),
+ ?assertEqual(200, Code),
+ ?assertEqual([], Res).
+
+t_no_docs({_, DbUrl}) ->
+ {Code, #{}} = req(post, DbUrl ++ "/_bulk_get", #{}),
+ ?assertEqual(400, Code).
+
+t_invalid_doc({_, DbUrl}) ->
+ {Code, Res} = bulk_get(DbUrl, [<<"foo">>]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"error">> := #{
+ <<"id">> := null,
+ <<"rev">> := null,
+ <<"error">> := <<"bad_request">>
+ }
+ }
+ ],
+ <<"id">> := null
+ }
+ ],
+ Res
+ ).
+
+t_doc_no_id({_, DbUrl}) ->
+ {Code, Res} = bulk_get(DbUrl, [#{<<"rev">> => <<"1-foo">>}]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"error">> := #{
+ <<"id">> := null,
+ <<"rev">> := null,
+ <<"error">> := <<"bad_request">>
+ }
+ }
+ ],
+ <<"id">> := null
+ }
+ ],
+ Res
+ ).
+
+t_missing_doc({_, DbUrl}) ->
+ {Code, Res} = bulk_get(DbUrl, [#{<<"id">> => <<"missing">>}]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"error">> := #{
+ <<"error">> := <<"not_found">>,
+ <<"id">> := <<"missing">>,
+ <<"rev">> := <<"undefined">>
+ }
+ }
+ ],
+ <<"id">> := <<"missing">>
+ }
+ ],
+ Res
+ ).
+
+t_invalid_rev({_, DbUrl}) ->
+ Doc = #{<<"id">> => ?DOC, <<"rev">> => 42},
+ {Code, Res} = bulk_get(DbUrl, [Doc]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"error">> := #{
+ <<"error">> := <<"bad_request">>,
+ <<"id">> := ?DOC,
+ <<"rev">> := 42
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_missing_rev({_, DbUrl}) ->
+ Doc = #{<<"id">> => ?DOC, <<"rev">> => <<"1-x">>},
+ {Code, Res} = bulk_get(DbUrl, [Doc]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"error">> := #{
+ <<"error">> := <<"not_found">>,
+ <<"id">> := ?DOC,
+ <<"rev">> := <<"1-x">>
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_doc_all_revs({_, DbUrl}) ->
+ {Code, Res} = bulk_get(DbUrl, [#{<<"id">> => ?DOC}]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"ok">> := #{
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revb">>,
+ <<"_attachments">> := #{
+ ?ATT := #{<<"stub">> := true}
+ }
+ }
+ },
+ #{
+ <<"ok">> := #{
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revc">>,
+ <<"_attachments">> := #{
+ ?ATT := #{<<"stub">> := true}
+ }
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_specific_rev({_, DbUrl}) ->
+ Doc = #{<<"id">> => ?DOC, <<"rev">> => <<"2-revb">>},
+ {Code, Res} = bulk_get(DbUrl, [Doc]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"ok">> := #{
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revb">>,
+ <<"_attachments">> := #{
+ ?ATT := #{<<"stub">> := true}
+ }
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_specific_rev_latest({_, DbUrl}) ->
+ Doc = #{<<"id">> => ?DOC, <<"rev">> => <<"2-revb">>},
+ {Code, Res} = bulk_get(DbUrl, [Doc], "?latest=true"),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"ok">> := #{
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revb">>,
+ <<"_attachments">> := #{
+ ?ATT := #{<<"stub">> := true}
+ }
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_ancestor_rev_latest({_, DbUrl}) ->
+ Doc = #{<<"id">> => ?DOC, <<"rev">> => <<"1-reva">>},
+ {Code, Res} = bulk_get(DbUrl, [Doc], "?latest=true"),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"ok">> := #{
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revb">>,
+ <<"_attachments">> := #{
+ ?ATT := #{<<"stub">> := true}
+ }
+ }
+ },
+ #{
+ <<"ok">> := #{
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revc">>,
+ <<"_attachments">> := #{
+ ?ATT := #{<<"stub">> := true}
+ }
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_revs_true({_, DbUrl}) ->
+ Doc = #{
+ <<"id">> => ?DOC,
+ <<"rev">> => <<"1-reva">>
+ },
+ {Code, Res} = bulk_get(DbUrl, [Doc], "?revs=true"),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"ok">> := #{
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"1-reva">>,
+ <<"_revisions">> :=
+ #{<<"ids">> := [<<"reva">>], <<"start">> := 1},
+ <<"_attachments">> := #{
+ ?ATT := #{<<"stub">> := true}
+ }
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_attachments_true({_, DbUrl}) ->
+ Doc = #{
+ <<"id">> => ?DOC,
+ <<"rev">> => <<"1-reva">>
+ },
+ {Code, Res} = bulk_get(DbUrl, [Doc], "?attachments=true"),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"ok">> := #{
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"1-reva">>,
+ <<"_attachments">> := #{
+ ?ATT := #{<<"data">> := ?ATT_DATA}
+ }
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_atts_since({_, DbUrl}) ->
+ % Attachment should not be returned as 2 from 2-revb is not stricly greater
+ % than 1 from our attachment's revpos
+ Doc = #{
+ <<"id">> => ?DOC,
+ <<"rev">> => <<"2-revb">>,
+ <<"atts_since">> => [<<"2-revb">>]
+ },
+ {Code, Res} = bulk_get(DbUrl, [Doc]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"ok">> := #{
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revb">>,
+ <<"_attachments">> := #{
+ ?ATT := #{<<"stub">> := true}
+ }
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_atts_since_returns_attachment({_, DbUrl}) ->
+ % 0-baz revpos 0 is less than revpos 1 of our attachment
+ Doc = #{
+ <<"id">> => ?DOC,
+ <<"rev">> => <<"2-revb">>,
+ <<"atts_since">> => [<<"0-baz">>]
+ },
+ {Code, Res} = bulk_get(DbUrl, [Doc]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"ok">> := #{
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revb">>,
+ <<"_attachments">> := #{
+ ?ATT := #{<<"data">> := ?ATT_DATA}
+ }
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_atts_since_attachments_true({_, DbUrl}) ->
+ % Check that atts_since overrides attachments=true
+ Doc = #{
+ <<"id">> => ?DOC,
+ <<"rev">> => <<"2-revb">>,
+ <<"atts_since">> => [<<"2-revb">>]
+ },
+ {Code, Res} = bulk_get(DbUrl, [Doc], "?attachments=true"),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"ok">> := #{
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revb">>,
+ <<"_attachments">> := #{
+ ?ATT := #{
+ <<"stub">> := true
+ }
+ }
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_atts_since_multiple({_, DbUrl}) ->
+ % Attachment revpos is 1 so we do not expect this attachment body
+ Docs = [
+ #{
+ <<"id">> => ?DOC,
+ <<"rev">> => <<"2-revb">>,
+ <<"atts_since">> => [<<"2-revb">>]
+ },
+ % Should get the attachment revpos=1 is greater than 0-foo
+ #{
+ <<"id">> => ?DOC,
+ <<"rev">> => <<"2-revb">>,
+ <<"atts_since">> => [<<"0-foo">>]
+ },
+ % Empty atts_since. Do not expect to get the attachment
+ #{
+ <<"id">> => ?DOC,
+ <<"rev">> => <<"2-revb">>,
+ <<"atts_since">> => []
+ },
+ % Add a document without atts_since to ensure atts_since applies only to
+ % individual requests
+ #{
+ <<"id">> => ?DOC,
+ <<"rev">> => <<"2-revb">>
+ }
+ ],
+ {Code, Res} = bulk_get(DbUrl, Docs),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"ok">> := #{
+ <<"_attachments">> := #{
+ ?ATT := #{<<"stub">> := true}
+ },
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revb">>
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ },
+ #{
+ <<"docs">> := [
+ #{
+ <<"ok">> := #{
+ <<"_attachments">> := #{
+ ?ATT := #{<<"data">> := ?ATT_DATA}
+ },
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revb">>
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ },
+ #{
+ <<"docs">> := [
+ #{
+ <<"ok">> := #{
+ <<"_attachments">> := #{
+ ?ATT := #{<<"stub">> := true}
+ },
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revb">>
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ },
+ #{
+ <<"docs">> := [
+ #{
+ <<"ok">> := #{
+ <<"_attachments">> :=
+ #{?ATT := #{<<"stub">> := true}},
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revb">>
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_atts_since_multiple_attachments_true({_, DbUrl}) ->
+ % Since attachments=true, expect to always get the attachments, unless
+ % there is an atts_since present and atts_since would prevent the
+ % attachment from being returned.
+ Docs = [
+ % Attachment revpos is 1 so we do not expect this attachment body
+ #{
+ <<"id">> => ?DOC,
+ <<"rev">> => <<"2-revb">>,
+ <<"atts_since">> => [<<"2-revb">>]
+ },
+ % Should get the attachment revpos=1 is greater than 0-foo
+ #{
+ <<"id">> => ?DOC,
+ <<"rev">> => <<"2-revb">>,
+ <<"atts_since">> => [<<"0-foo">>]
+ },
+ % Should get the attachment as it is set as a default option
+ #{
+ <<"id">> => ?DOC,
+ <<"rev">> => <<"2-revb">>,
+ <<"atts_since">> => []
+ },
+ % Check a doc without atts_since to ensure atts_since applies only to
+ % individual requests, otherwise default options apply
+ #{
+ <<"id">> => ?DOC,
+ <<"rev">> => <<"2-revb">>
+ }
+ ],
+ {Code, Res} = bulk_get(DbUrl, Docs, "?attachments=true"),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"ok">> := #{
+ <<"_attachments">> := #{
+ ?ATT := #{<<"stub">> := true}
+ },
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revb">>
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ },
+ #{
+ <<"docs">> := [
+ #{
+ <<"ok">> := #{
+ <<"_attachments">> := #{
+ ?ATT := #{<<"data">> := ?ATT_DATA}
+ },
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revb">>
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ },
+ #{
+ <<"docs">> := [
+ #{
+ <<"ok">> := #{
+ <<"_attachments">> := #{
+ ?ATT := #{<<"data">> := ?ATT_DATA}
+ },
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revb">>
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ },
+ #{
+ <<"docs">> := [
+ #{
+ <<"ok">> := #{
+ <<"_attachments">> :=
+ #{?ATT := #{<<"data">> := ?ATT_DATA}},
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revb">>
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_missing_rev_latest({_, DbUrl}) ->
+ % Check the case of latest and a missing
+ Doc = #{<<"id">> => ?DOC, <<"rev">> => <<"1-x">>},
+ {Code, Res} = bulk_get(DbUrl, [Doc], "?latest=true"),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"error">> := #{
+ <<"error">> := <<"not_found">>,
+ <<"id">> := ?DOC,
+ <<"rev">> := <<"1-x">>
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_multiple_docs({_, DbUrl}) ->
+ Reqs = [#{<<"id">> => integer_to_binary(I)} || I <- lists:seq(1, ?DOC_COUNT)],
+ {Code, Res} = bulk_get(DbUrl, Reqs),
+ ?assertEqual(200, Code),
+ ?assertMatch([#{<<"docs">> := _} | _], Res),
+ ?assertEqual(?DOC_COUNT, length(Res)),
+ lists:foreach(
+ fun({I, Docs}) ->
+ Id = integer_to_binary(I),
+ ?assertMatch(
+ #{
+ <<"docs">> := [
+ #{
+ <<"ok">> := #{
+ <<"_id">> := Id,
+ <<"_rev">> := <<"1-reva">>
+ }
+ }
+ ],
+ <<"id">> := Id
+ },
+ Docs
+ )
+ end,
+ lists:zip(lists:seq(1, ?DOC_COUNT), Res)
+ ).
+
+% Utility functions
+
+setup_ctx() ->
+ Ctx = test_util:start_couch([chttpd]),
+ Hashed = couch_passwords:hash_admin_password(?PASS),
+ ok = config:set("admins", ?USER, ?b2l(Hashed), _Persist = false),
+ Addr = config:get("chttpd", "bind_address", "127.0.0.1"),
+ Db = binary_to_list(?tempdb()),
Review Comment:
Maybe use either `?b2l` or `binary_to_list` rather than both? I prefer the latter personally.
##########
src/chttpd/test/eunit/chttpd_bulk_get_test.erl:
##########
@@ -0,0 +1,785 @@
+% Licensed under the Apache License, Version 2.0 (the "License"); you may not
+% use this file except in compliance with the License. You may obtain a copy of
+% the License at
+%
+% http://www.apache.org/licenses/LICENSE-2.0
+%
+% Unless required by applicable law or agreed to in writing, software
+% distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+% WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+% License for the specific language governing permissions and limitations under
+% the License.
+
+-module(chttpd_bulk_get_test).
+
+-include_lib("couch/include/couch_db.hrl").
+-include_lib("couch/include/couch_eunit.hrl").
+
+-define(USER, "chttpd_bulk_get_test_admin").
+-define(PASS, "pass").
+-define(AUTH, {basic_auth, {?USER, ?PASS}}).
+-define(JSON, {"Content-Type", "application/json"}).
+
+-define(DOC, <<"doc">>).
+-define(REVA, <<"reva">>).
+-define(REVB, <<"revb">>).
+-define(REVC, <<"revc">>).
+-define(ATT, <<"att">>).
+-define(ATT_DATA, <<"dGhlZGF0YQ==">>).
+
+-define(DOC_COUNT, 2000).
+
+test_docs_revs() ->
+ [
+ {?DOC, [?REVA]},
+ {?DOC, [?REVB, ?REVA]},
+ {?DOC, [?REVC, ?REVA]}
+ ].
+
+bulk_get_test_() ->
+ {
+ setup,
+ fun setup_basic/0,
+ fun teardown/1,
+ with([
+ ?TDEF(t_empty_request),
+ ?TDEF(t_no_docs),
+ ?TDEF(t_invalid_doc),
+ ?TDEF(t_doc_no_id),
+ ?TDEF(t_missing_doc),
+ ?TDEF(t_invalid_rev),
+ ?TDEF(t_missing_rev),
+ ?TDEF(t_doc_all_revs),
+ ?TDEF(t_specific_rev),
+ ?TDEF(t_specific_rev_latest),
+ ?TDEF(t_ancestor_rev_latest),
+ ?TDEF(t_revs_true),
+ ?TDEF(t_attachments_true),
+ ?TDEF(t_atts_since),
+ ?TDEF(t_atts_since_returns_attachment),
+ ?TDEF(t_atts_since_attachments_true),
+ ?TDEF(t_atts_since_multiple),
+ ?TDEF(t_atts_since_multiple_attachments_true),
+ ?TDEF(t_missing_rev_latest)
+ ])
+ }.
+
+bulk_get_multiple_docs_test_() ->
+ {
+ foreach,
+ fun setup_multiple/0,
+ fun teardown/1,
+ [
+ ?TDEF_FE(t_multiple_docs, 10)
+ ]
+ }.
+
+t_empty_request({_, DbUrl}) ->
+ {Code, Res} = bulk_get(DbUrl, []),
+ ?assertEqual(200, Code),
+ ?assertEqual([], Res).
+
+t_no_docs({_, DbUrl}) ->
+ {Code, #{}} = req(post, DbUrl ++ "/_bulk_get", #{}),
+ ?assertEqual(400, Code).
+
+t_invalid_doc({_, DbUrl}) ->
+ {Code, Res} = bulk_get(DbUrl, [<<"foo">>]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"error">> := #{
+ <<"id">> := null,
+ <<"rev">> := null,
+ <<"error">> := <<"bad_request">>
+ }
+ }
+ ],
+ <<"id">> := null
+ }
+ ],
+ Res
+ ).
+
+t_doc_no_id({_, DbUrl}) ->
+ {Code, Res} = bulk_get(DbUrl, [#{<<"rev">> => <<"1-foo">>}]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"error">> := #{
+ <<"id">> := null,
+ <<"rev">> := null,
+ <<"error">> := <<"bad_request">>
+ }
+ }
+ ],
+ <<"id">> := null
+ }
+ ],
+ Res
+ ).
+
+t_missing_doc({_, DbUrl}) ->
+ {Code, Res} = bulk_get(DbUrl, [#{<<"id">> => <<"missing">>}]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"error">> := #{
+ <<"error">> := <<"not_found">>,
+ <<"id">> := <<"missing">>,
+ <<"rev">> := <<"undefined">>
+ }
+ }
+ ],
+ <<"id">> := <<"missing">>
+ }
+ ],
+ Res
+ ).
+
+t_invalid_rev({_, DbUrl}) ->
+ Doc = #{<<"id">> => ?DOC, <<"rev">> => 42},
+ {Code, Res} = bulk_get(DbUrl, [Doc]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"error">> := #{
+ <<"error">> := <<"bad_request">>,
+ <<"id">> := ?DOC,
+ <<"rev">> := 42
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_missing_rev({_, DbUrl}) ->
+ Doc = #{<<"id">> => ?DOC, <<"rev">> => <<"1-x">>},
+ {Code, Res} = bulk_get(DbUrl, [Doc]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"error">> := #{
+ <<"error">> := <<"not_found">>,
+ <<"id">> := ?DOC,
+ <<"rev">> := <<"1-x">>
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_doc_all_revs({_, DbUrl}) ->
+ {Code, Res} = bulk_get(DbUrl, [#{<<"id">> => ?DOC}]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"ok">> := #{
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revb">>,
+ <<"_attachments">> := #{
+ ?ATT := #{<<"stub">> := true}
+ }
+ }
+ },
+ #{
+ <<"ok">> := #{
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revc">>,
+ <<"_attachments">> := #{
+ ?ATT := #{<<"stub">> := true}
+ }
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_specific_rev({_, DbUrl}) ->
+ Doc = #{<<"id">> => ?DOC, <<"rev">> => <<"2-revb">>},
+ {Code, Res} = bulk_get(DbUrl, [Doc]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"ok">> := #{
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revb">>,
+ <<"_attachments">> := #{
+ ?ATT := #{<<"stub">> := true}
+ }
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_specific_rev_latest({_, DbUrl}) ->
+ Doc = #{<<"id">> => ?DOC, <<"rev">> => <<"2-revb">>},
+ {Code, Res} = bulk_get(DbUrl, [Doc], "?latest=true"),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"ok">> := #{
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revb">>,
+ <<"_attachments">> := #{
+ ?ATT := #{<<"stub">> := true}
+ }
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_ancestor_rev_latest({_, DbUrl}) ->
+ Doc = #{<<"id">> => ?DOC, <<"rev">> => <<"1-reva">>},
+ {Code, Res} = bulk_get(DbUrl, [Doc], "?latest=true"),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"ok">> := #{
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revb">>,
+ <<"_attachments">> := #{
+ ?ATT := #{<<"stub">> := true}
+ }
+ }
+ },
+ #{
+ <<"ok">> := #{
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revc">>,
+ <<"_attachments">> := #{
+ ?ATT := #{<<"stub">> := true}
+ }
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_revs_true({_, DbUrl}) ->
+ Doc = #{
+ <<"id">> => ?DOC,
+ <<"rev">> => <<"1-reva">>
+ },
+ {Code, Res} = bulk_get(DbUrl, [Doc], "?revs=true"),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"ok">> := #{
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"1-reva">>,
+ <<"_revisions">> :=
+ #{<<"ids">> := [<<"reva">>], <<"start">> := 1},
+ <<"_attachments">> := #{
+ ?ATT := #{<<"stub">> := true}
+ }
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_attachments_true({_, DbUrl}) ->
+ Doc = #{
+ <<"id">> => ?DOC,
+ <<"rev">> => <<"1-reva">>
+ },
+ {Code, Res} = bulk_get(DbUrl, [Doc], "?attachments=true"),
Review Comment:
ditto
##########
src/chttpd/test/eunit/chttpd_bulk_get_test.erl:
##########
@@ -0,0 +1,785 @@
+% Licensed under the Apache License, Version 2.0 (the "License"); you may not
+% use this file except in compliance with the License. You may obtain a copy of
+% the License at
+%
+% http://www.apache.org/licenses/LICENSE-2.0
+%
+% Unless required by applicable law or agreed to in writing, software
+% distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+% WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+% License for the specific language governing permissions and limitations under
+% the License.
+
+-module(chttpd_bulk_get_test).
+
+-include_lib("couch/include/couch_db.hrl").
+-include_lib("couch/include/couch_eunit.hrl").
+
+-define(USER, "chttpd_bulk_get_test_admin").
+-define(PASS, "pass").
+-define(AUTH, {basic_auth, {?USER, ?PASS}}).
+-define(JSON, {"Content-Type", "application/json"}).
+
+-define(DOC, <<"doc">>).
+-define(REVA, <<"reva">>).
+-define(REVB, <<"revb">>).
+-define(REVC, <<"revc">>).
+-define(ATT, <<"att">>).
+-define(ATT_DATA, <<"dGhlZGF0YQ==">>).
+
+-define(DOC_COUNT, 2000).
+
+test_docs_revs() ->
+ [
+ {?DOC, [?REVA]},
+ {?DOC, [?REVB, ?REVA]},
+ {?DOC, [?REVC, ?REVA]}
+ ].
+
+bulk_get_test_() ->
+ {
+ setup,
+ fun setup_basic/0,
+ fun teardown/1,
+ with([
+ ?TDEF(t_empty_request),
+ ?TDEF(t_no_docs),
+ ?TDEF(t_invalid_doc),
+ ?TDEF(t_doc_no_id),
+ ?TDEF(t_missing_doc),
+ ?TDEF(t_invalid_rev),
+ ?TDEF(t_missing_rev),
+ ?TDEF(t_doc_all_revs),
+ ?TDEF(t_specific_rev),
+ ?TDEF(t_specific_rev_latest),
+ ?TDEF(t_ancestor_rev_latest),
+ ?TDEF(t_revs_true),
+ ?TDEF(t_attachments_true),
+ ?TDEF(t_atts_since),
+ ?TDEF(t_atts_since_returns_attachment),
+ ?TDEF(t_atts_since_attachments_true),
+ ?TDEF(t_atts_since_multiple),
+ ?TDEF(t_atts_since_multiple_attachments_true),
+ ?TDEF(t_missing_rev_latest)
+ ])
+ }.
+
+bulk_get_multiple_docs_test_() ->
+ {
+ foreach,
+ fun setup_multiple/0,
+ fun teardown/1,
+ [
+ ?TDEF_FE(t_multiple_docs, 10)
+ ]
+ }.
+
+t_empty_request({_, DbUrl}) ->
+ {Code, Res} = bulk_get(DbUrl, []),
+ ?assertEqual(200, Code),
+ ?assertEqual([], Res).
+
+t_no_docs({_, DbUrl}) ->
+ {Code, #{}} = req(post, DbUrl ++ "/_bulk_get", #{}),
+ ?assertEqual(400, Code).
+
+t_invalid_doc({_, DbUrl}) ->
+ {Code, Res} = bulk_get(DbUrl, [<<"foo">>]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"error">> := #{
+ <<"id">> := null,
+ <<"rev">> := null,
+ <<"error">> := <<"bad_request">>
+ }
+ }
+ ],
+ <<"id">> := null
+ }
+ ],
+ Res
+ ).
+
+t_doc_no_id({_, DbUrl}) ->
+ {Code, Res} = bulk_get(DbUrl, [#{<<"rev">> => <<"1-foo">>}]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"error">> := #{
+ <<"id">> := null,
+ <<"rev">> := null,
+ <<"error">> := <<"bad_request">>
+ }
+ }
+ ],
+ <<"id">> := null
+ }
+ ],
+ Res
+ ).
+
+t_missing_doc({_, DbUrl}) ->
+ {Code, Res} = bulk_get(DbUrl, [#{<<"id">> => <<"missing">>}]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"error">> := #{
+ <<"error">> := <<"not_found">>,
+ <<"id">> := <<"missing">>,
+ <<"rev">> := <<"undefined">>
+ }
+ }
+ ],
+ <<"id">> := <<"missing">>
+ }
+ ],
+ Res
+ ).
+
+t_invalid_rev({_, DbUrl}) ->
+ Doc = #{<<"id">> => ?DOC, <<"rev">> => 42},
+ {Code, Res} = bulk_get(DbUrl, [Doc]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"error">> := #{
+ <<"error">> := <<"bad_request">>,
+ <<"id">> := ?DOC,
+ <<"rev">> := 42
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_missing_rev({_, DbUrl}) ->
+ Doc = #{<<"id">> => ?DOC, <<"rev">> => <<"1-x">>},
+ {Code, Res} = bulk_get(DbUrl, [Doc]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"error">> := #{
+ <<"error">> := <<"not_found">>,
Review Comment:
As a perplexed user, I might think it's the doc id that's not found rather than the rev. I guess we'd need to change existing behavior to enhance this to become e.g. `rev_not_found`?
##########
src/chttpd/test/eunit/chttpd_bulk_get_test.erl:
##########
@@ -0,0 +1,785 @@
+% Licensed under the Apache License, Version 2.0 (the "License"); you may not
+% use this file except in compliance with the License. You may obtain a copy of
+% the License at
+%
+% http://www.apache.org/licenses/LICENSE-2.0
+%
+% Unless required by applicable law or agreed to in writing, software
+% distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+% WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+% License for the specific language governing permissions and limitations under
+% the License.
+
+-module(chttpd_bulk_get_test).
+
+-include_lib("couch/include/couch_db.hrl").
+-include_lib("couch/include/couch_eunit.hrl").
+
+-define(USER, "chttpd_bulk_get_test_admin").
+-define(PASS, "pass").
+-define(AUTH, {basic_auth, {?USER, ?PASS}}).
+-define(JSON, {"Content-Type", "application/json"}).
+
+-define(DOC, <<"doc">>).
+-define(REVA, <<"reva">>).
+-define(REVB, <<"revb">>).
+-define(REVC, <<"revc">>).
+-define(ATT, <<"att">>).
+-define(ATT_DATA, <<"dGhlZGF0YQ==">>).
+
+-define(DOC_COUNT, 2000).
+
+test_docs_revs() ->
+ [
+ {?DOC, [?REVA]},
+ {?DOC, [?REVB, ?REVA]},
+ {?DOC, [?REVC, ?REVA]}
+ ].
+
+bulk_get_test_() ->
+ {
+ setup,
+ fun setup_basic/0,
+ fun teardown/1,
+ with([
+ ?TDEF(t_empty_request),
+ ?TDEF(t_no_docs),
+ ?TDEF(t_invalid_doc),
+ ?TDEF(t_doc_no_id),
+ ?TDEF(t_missing_doc),
+ ?TDEF(t_invalid_rev),
+ ?TDEF(t_missing_rev),
+ ?TDEF(t_doc_all_revs),
+ ?TDEF(t_specific_rev),
+ ?TDEF(t_specific_rev_latest),
+ ?TDEF(t_ancestor_rev_latest),
+ ?TDEF(t_revs_true),
+ ?TDEF(t_attachments_true),
+ ?TDEF(t_atts_since),
+ ?TDEF(t_atts_since_returns_attachment),
+ ?TDEF(t_atts_since_attachments_true),
+ ?TDEF(t_atts_since_multiple),
+ ?TDEF(t_atts_since_multiple_attachments_true),
+ ?TDEF(t_missing_rev_latest)
+ ])
+ }.
+
+bulk_get_multiple_docs_test_() ->
+ {
+ foreach,
+ fun setup_multiple/0,
+ fun teardown/1,
+ [
+ ?TDEF_FE(t_multiple_docs, 10)
+ ]
+ }.
+
+t_empty_request({_, DbUrl}) ->
+ {Code, Res} = bulk_get(DbUrl, []),
+ ?assertEqual(200, Code),
+ ?assertEqual([], Res).
+
+t_no_docs({_, DbUrl}) ->
+ {Code, #{}} = req(post, DbUrl ++ "/_bulk_get", #{}),
+ ?assertEqual(400, Code).
+
+t_invalid_doc({_, DbUrl}) ->
+ {Code, Res} = bulk_get(DbUrl, [<<"foo">>]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"error">> := #{
+ <<"id">> := null,
+ <<"rev">> := null,
+ <<"error">> := <<"bad_request">>
+ }
+ }
+ ],
+ <<"id">> := null
+ }
+ ],
+ Res
+ ).
+
+t_doc_no_id({_, DbUrl}) ->
+ {Code, Res} = bulk_get(DbUrl, [#{<<"rev">> => <<"1-foo">>}]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"error">> := #{
+ <<"id">> := null,
+ <<"rev">> := null,
+ <<"error">> := <<"bad_request">>
+ }
+ }
+ ],
+ <<"id">> := null
+ }
+ ],
+ Res
+ ).
+
+t_missing_doc({_, DbUrl}) ->
+ {Code, Res} = bulk_get(DbUrl, [#{<<"id">> => <<"missing">>}]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"error">> := #{
+ <<"error">> := <<"not_found">>,
+ <<"id">> := <<"missing">>,
+ <<"rev">> := <<"undefined">>
+ }
+ }
+ ],
+ <<"id">> := <<"missing">>
+ }
+ ],
+ Res
+ ).
+
+t_invalid_rev({_, DbUrl}) ->
+ Doc = #{<<"id">> => ?DOC, <<"rev">> => 42},
+ {Code, Res} = bulk_get(DbUrl, [Doc]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"error">> := #{
+ <<"error">> := <<"bad_request">>,
+ <<"id">> := ?DOC,
+ <<"rev">> := 42
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_missing_rev({_, DbUrl}) ->
+ Doc = #{<<"id">> => ?DOC, <<"rev">> => <<"1-x">>},
+ {Code, Res} = bulk_get(DbUrl, [Doc]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"error">> := #{
+ <<"error">> := <<"not_found">>,
+ <<"id">> := ?DOC,
+ <<"rev">> := <<"1-x">>
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_doc_all_revs({_, DbUrl}) ->
+ {Code, Res} = bulk_get(DbUrl, [#{<<"id">> => ?DOC}]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"ok">> := #{
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revb">>,
+ <<"_attachments">> := #{
+ ?ATT := #{<<"stub">> := true}
+ }
+ }
+ },
+ #{
+ <<"ok">> := #{
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revc">>,
+ <<"_attachments">> := #{
+ ?ATT := #{<<"stub">> := true}
+ }
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_specific_rev({_, DbUrl}) ->
+ Doc = #{<<"id">> => ?DOC, <<"rev">> => <<"2-revb">>},
+ {Code, Res} = bulk_get(DbUrl, [Doc]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"ok">> := #{
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revb">>,
+ <<"_attachments">> := #{
+ ?ATT := #{<<"stub">> := true}
+ }
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_specific_rev_latest({_, DbUrl}) ->
+ Doc = #{<<"id">> => ?DOC, <<"rev">> => <<"2-revb">>},
+ {Code, Res} = bulk_get(DbUrl, [Doc], "?latest=true"),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"ok">> := #{
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revb">>,
+ <<"_attachments">> := #{
+ ?ATT := #{<<"stub">> := true}
+ }
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_ancestor_rev_latest({_, DbUrl}) ->
+ Doc = #{<<"id">> => ?DOC, <<"rev">> => <<"1-reva">>},
+ {Code, Res} = bulk_get(DbUrl, [Doc], "?latest=true"),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"ok">> := #{
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revb">>,
+ <<"_attachments">> := #{
+ ?ATT := #{<<"stub">> := true}
+ }
+ }
+ },
+ #{
+ <<"ok">> := #{
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revc">>,
+ <<"_attachments">> := #{
+ ?ATT := #{<<"stub">> := true}
+ }
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_revs_true({_, DbUrl}) ->
+ Doc = #{
+ <<"id">> => ?DOC,
+ <<"rev">> => <<"1-reva">>
+ },
+ {Code, Res} = bulk_get(DbUrl, [Doc], "?revs=true"),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"ok">> := #{
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"1-reva">>,
+ <<"_revisions">> :=
+ #{<<"ids">> := [<<"reva">>], <<"start">> := 1},
+ <<"_attachments">> := #{
+ ?ATT := #{<<"stub">> := true}
+ }
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_attachments_true({_, DbUrl}) ->
+ Doc = #{
+ <<"id">> => ?DOC,
+ <<"rev">> => <<"1-reva">>
+ },
+ {Code, Res} = bulk_get(DbUrl, [Doc], "?attachments=true"),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"ok">> := #{
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"1-reva">>,
+ <<"_attachments">> := #{
+ ?ATT := #{<<"data">> := ?ATT_DATA}
+ }
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_atts_since({_, DbUrl}) ->
+ % Attachment should not be returned as 2 from 2-revb is not stricly greater
+ % than 1 from our attachment's revpos
+ Doc = #{
+ <<"id">> => ?DOC,
+ <<"rev">> => <<"2-revb">>,
+ <<"atts_since">> => [<<"2-revb">>]
+ },
+ {Code, Res} = bulk_get(DbUrl, [Doc]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"ok">> := #{
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revb">>,
+ <<"_attachments">> := #{
+ ?ATT := #{<<"stub">> := true}
+ }
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_atts_since_returns_attachment({_, DbUrl}) ->
+ % 0-baz revpos 0 is less than revpos 1 of our attachment
+ Doc = #{
+ <<"id">> => ?DOC,
+ <<"rev">> => <<"2-revb">>,
+ <<"atts_since">> => [<<"0-baz">>]
+ },
+ {Code, Res} = bulk_get(DbUrl, [Doc]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"ok">> := #{
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revb">>,
+ <<"_attachments">> := #{
+ ?ATT := #{<<"data">> := ?ATT_DATA}
+ }
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_atts_since_attachments_true({_, DbUrl}) ->
+ % Check that atts_since overrides attachments=true
Review Comment:
You could alternately change the name to e.g. `t_atts_since_overrides_attachments_true` and possibly avoid the comment?
##########
src/chttpd/test/eunit/chttpd_bulk_get_test.erl:
##########
@@ -0,0 +1,785 @@
+% Licensed under the Apache License, Version 2.0 (the "License"); you may not
+% use this file except in compliance with the License. You may obtain a copy of
+% the License at
+%
+% http://www.apache.org/licenses/LICENSE-2.0
+%
+% Unless required by applicable law or agreed to in writing, software
+% distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+% WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+% License for the specific language governing permissions and limitations under
+% the License.
+
+-module(chttpd_bulk_get_test).
+
+-include_lib("couch/include/couch_db.hrl").
+-include_lib("couch/include/couch_eunit.hrl").
+
+-define(USER, "chttpd_bulk_get_test_admin").
+-define(PASS, "pass").
+-define(AUTH, {basic_auth, {?USER, ?PASS}}).
+-define(JSON, {"Content-Type", "application/json"}).
+
+-define(DOC, <<"doc">>).
+-define(REVA, <<"reva">>).
+-define(REVB, <<"revb">>).
+-define(REVC, <<"revc">>).
+-define(ATT, <<"att">>).
+-define(ATT_DATA, <<"dGhlZGF0YQ==">>).
+
+-define(DOC_COUNT, 2000).
+
+test_docs_revs() ->
+ [
+ {?DOC, [?REVA]},
+ {?DOC, [?REVB, ?REVA]},
+ {?DOC, [?REVC, ?REVA]}
+ ].
+
+bulk_get_test_() ->
+ {
+ setup,
+ fun setup_basic/0,
+ fun teardown/1,
+ with([
+ ?TDEF(t_empty_request),
+ ?TDEF(t_no_docs),
+ ?TDEF(t_invalid_doc),
+ ?TDEF(t_doc_no_id),
+ ?TDEF(t_missing_doc),
+ ?TDEF(t_invalid_rev),
+ ?TDEF(t_missing_rev),
+ ?TDEF(t_doc_all_revs),
+ ?TDEF(t_specific_rev),
+ ?TDEF(t_specific_rev_latest),
+ ?TDEF(t_ancestor_rev_latest),
+ ?TDEF(t_revs_true),
+ ?TDEF(t_attachments_true),
+ ?TDEF(t_atts_since),
+ ?TDEF(t_atts_since_returns_attachment),
+ ?TDEF(t_atts_since_attachments_true),
+ ?TDEF(t_atts_since_multiple),
+ ?TDEF(t_atts_since_multiple_attachments_true),
+ ?TDEF(t_missing_rev_latest)
+ ])
+ }.
+
+bulk_get_multiple_docs_test_() ->
+ {
+ foreach,
+ fun setup_multiple/0,
+ fun teardown/1,
+ [
+ ?TDEF_FE(t_multiple_docs, 10)
+ ]
+ }.
+
+t_empty_request({_, DbUrl}) ->
+ {Code, Res} = bulk_get(DbUrl, []),
+ ?assertEqual(200, Code),
+ ?assertEqual([], Res).
+
+t_no_docs({_, DbUrl}) ->
+ {Code, #{}} = req(post, DbUrl ++ "/_bulk_get", #{}),
+ ?assertEqual(400, Code).
+
+t_invalid_doc({_, DbUrl}) ->
+ {Code, Res} = bulk_get(DbUrl, [<<"foo">>]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"error">> := #{
+ <<"id">> := null,
+ <<"rev">> := null,
+ <<"error">> := <<"bad_request">>
+ }
+ }
+ ],
+ <<"id">> := null
+ }
+ ],
+ Res
+ ).
+
+t_doc_no_id({_, DbUrl}) ->
+ {Code, Res} = bulk_get(DbUrl, [#{<<"rev">> => <<"1-foo">>}]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"error">> := #{
+ <<"id">> := null,
+ <<"rev">> := null,
+ <<"error">> := <<"bad_request">>
+ }
+ }
+ ],
+ <<"id">> := null
+ }
+ ],
+ Res
+ ).
+
+t_missing_doc({_, DbUrl}) ->
+ {Code, Res} = bulk_get(DbUrl, [#{<<"id">> => <<"missing">>}]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"error">> := #{
+ <<"error">> := <<"not_found">>,
+ <<"id">> := <<"missing">>,
+ <<"rev">> := <<"undefined">>
+ }
+ }
+ ],
+ <<"id">> := <<"missing">>
+ }
+ ],
+ Res
+ ).
+
+t_invalid_rev({_, DbUrl}) ->
+ Doc = #{<<"id">> => ?DOC, <<"rev">> => 42},
+ {Code, Res} = bulk_get(DbUrl, [Doc]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"error">> := #{
+ <<"error">> := <<"bad_request">>,
+ <<"id">> := ?DOC,
+ <<"rev">> := 42
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_missing_rev({_, DbUrl}) ->
+ Doc = #{<<"id">> => ?DOC, <<"rev">> => <<"1-x">>},
+ {Code, Res} = bulk_get(DbUrl, [Doc]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"error">> := #{
+ <<"error">> := <<"not_found">>,
+ <<"id">> := ?DOC,
+ <<"rev">> := <<"1-x">>
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_doc_all_revs({_, DbUrl}) ->
+ {Code, Res} = bulk_get(DbUrl, [#{<<"id">> => ?DOC}]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"ok">> := #{
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revb">>,
+ <<"_attachments">> := #{
+ ?ATT := #{<<"stub">> := true}
+ }
+ }
+ },
+ #{
+ <<"ok">> := #{
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revc">>,
+ <<"_attachments">> := #{
+ ?ATT := #{<<"stub">> := true}
+ }
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_specific_rev({_, DbUrl}) ->
+ Doc = #{<<"id">> => ?DOC, <<"rev">> => <<"2-revb">>},
+ {Code, Res} = bulk_get(DbUrl, [Doc]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"ok">> := #{
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revb">>,
+ <<"_attachments">> := #{
+ ?ATT := #{<<"stub">> := true}
+ }
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_specific_rev_latest({_, DbUrl}) ->
+ Doc = #{<<"id">> => ?DOC, <<"rev">> => <<"2-revb">>},
+ {Code, Res} = bulk_get(DbUrl, [Doc], "?latest=true"),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"ok">> := #{
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revb">>,
+ <<"_attachments">> := #{
+ ?ATT := #{<<"stub">> := true}
+ }
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_ancestor_rev_latest({_, DbUrl}) ->
+ Doc = #{<<"id">> => ?DOC, <<"rev">> => <<"1-reva">>},
+ {Code, Res} = bulk_get(DbUrl, [Doc], "?latest=true"),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"ok">> := #{
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revb">>,
+ <<"_attachments">> := #{
+ ?ATT := #{<<"stub">> := true}
+ }
+ }
+ },
+ #{
+ <<"ok">> := #{
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revc">>,
+ <<"_attachments">> := #{
+ ?ATT := #{<<"stub">> := true}
+ }
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_revs_true({_, DbUrl}) ->
+ Doc = #{
+ <<"id">> => ?DOC,
+ <<"rev">> => <<"1-reva">>
+ },
+ {Code, Res} = bulk_get(DbUrl, [Doc], "?revs=true"),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"ok">> := #{
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"1-reva">>,
+ <<"_revisions">> :=
+ #{<<"ids">> := [<<"reva">>], <<"start">> := 1},
+ <<"_attachments">> := #{
+ ?ATT := #{<<"stub">> := true}
+ }
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_attachments_true({_, DbUrl}) ->
+ Doc = #{
+ <<"id">> => ?DOC,
+ <<"rev">> => <<"1-reva">>
+ },
+ {Code, Res} = bulk_get(DbUrl, [Doc], "?attachments=true"),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"ok">> := #{
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"1-reva">>,
+ <<"_attachments">> := #{
+ ?ATT := #{<<"data">> := ?ATT_DATA}
+ }
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_atts_since({_, DbUrl}) ->
+ % Attachment should not be returned as 2 from 2-revb is not stricly greater
+ % than 1 from our attachment's revpos
+ Doc = #{
+ <<"id">> => ?DOC,
+ <<"rev">> => <<"2-revb">>,
+ <<"atts_since">> => [<<"2-revb">>]
+ },
+ {Code, Res} = bulk_get(DbUrl, [Doc]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"ok">> := #{
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revb">>,
+ <<"_attachments">> := #{
+ ?ATT := #{<<"stub">> := true}
+ }
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_atts_since_returns_attachment({_, DbUrl}) ->
+ % 0-baz revpos 0 is less than revpos 1 of our attachment
+ Doc = #{
+ <<"id">> => ?DOC,
+ <<"rev">> => <<"2-revb">>,
+ <<"atts_since">> => [<<"0-baz">>]
+ },
+ {Code, Res} = bulk_get(DbUrl, [Doc]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"ok">> := #{
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revb">>,
+ <<"_attachments">> := #{
+ ?ATT := #{<<"data">> := ?ATT_DATA}
+ }
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_atts_since_attachments_true({_, DbUrl}) ->
+ % Check that atts_since overrides attachments=true
+ Doc = #{
+ <<"id">> => ?DOC,
+ <<"rev">> => <<"2-revb">>,
+ <<"atts_since">> => [<<"2-revb">>]
+ },
+ {Code, Res} = bulk_get(DbUrl, [Doc], "?attachments=true"),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"ok">> := #{
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revb">>,
+ <<"_attachments">> := #{
+ ?ATT := #{
+ <<"stub">> := true
+ }
+ }
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_atts_since_multiple({_, DbUrl}) ->
+ % Attachment revpos is 1 so we do not expect this attachment body
+ Docs = [
+ #{
+ <<"id">> => ?DOC,
+ <<"rev">> => <<"2-revb">>,
+ <<"atts_since">> => [<<"2-revb">>]
+ },
+ % Should get the attachment revpos=1 is greater than 0-foo
+ #{
+ <<"id">> => ?DOC,
+ <<"rev">> => <<"2-revb">>,
+ <<"atts_since">> => [<<"0-foo">>]
+ },
+ % Empty atts_since. Do not expect to get the attachment
+ #{
+ <<"id">> => ?DOC,
+ <<"rev">> => <<"2-revb">>,
+ <<"atts_since">> => []
+ },
+ % Add a document without atts_since to ensure atts_since applies only to
Review Comment:
maybe s/Add/Include/ ?
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: notifications-unsubscribe@couchdb.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [couchdb] nickva commented on a diff in pull request #4209: Add bulk_get tests
Posted by GitBox <gi...@apache.org>.
nickva commented on code in PR #4209:
URL: https://github.com/apache/couchdb/pull/4209#discussion_r997338890
##########
src/chttpd/test/eunit/chttpd_bulk_get_test.erl:
##########
@@ -0,0 +1,785 @@
+% Licensed under the Apache License, Version 2.0 (the "License"); you may not
+% use this file except in compliance with the License. You may obtain a copy of
+% the License at
+%
+% http://www.apache.org/licenses/LICENSE-2.0
+%
+% Unless required by applicable law or agreed to in writing, software
+% distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+% WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+% License for the specific language governing permissions and limitations under
+% the License.
+
+-module(chttpd_bulk_get_test).
+
+-include_lib("couch/include/couch_db.hrl").
+-include_lib("couch/include/couch_eunit.hrl").
+
+-define(USER, "chttpd_bulk_get_test_admin").
+-define(PASS, "pass").
+-define(AUTH, {basic_auth, {?USER, ?PASS}}).
+-define(JSON, {"Content-Type", "application/json"}).
+
+-define(DOC, <<"doc">>).
+-define(REVA, <<"reva">>).
+-define(REVB, <<"revb">>).
+-define(REVC, <<"revc">>).
+-define(ATT, <<"att">>).
+-define(ATT_DATA, <<"dGhlZGF0YQ==">>).
+
+-define(DOC_COUNT, 2000).
+
+test_docs_revs() ->
+ [
+ {?DOC, [?REVA]},
+ {?DOC, [?REVB, ?REVA]},
+ {?DOC, [?REVC, ?REVA]}
+ ].
+
+bulk_get_test_() ->
+ {
+ setup,
+ fun setup_basic/0,
+ fun teardown/1,
+ with([
+ ?TDEF(t_empty_request),
+ ?TDEF(t_no_docs),
+ ?TDEF(t_invalid_doc),
+ ?TDEF(t_doc_no_id),
+ ?TDEF(t_missing_doc),
+ ?TDEF(t_invalid_rev),
+ ?TDEF(t_missing_rev),
+ ?TDEF(t_doc_all_revs),
+ ?TDEF(t_specific_rev),
+ ?TDEF(t_specific_rev_latest),
+ ?TDEF(t_ancestor_rev_latest),
+ ?TDEF(t_revs_true),
+ ?TDEF(t_attachments_true),
+ ?TDEF(t_atts_since),
+ ?TDEF(t_atts_since_returns_attachment),
+ ?TDEF(t_atts_since_attachments_true),
+ ?TDEF(t_atts_since_multiple),
+ ?TDEF(t_atts_since_multiple_attachments_true),
+ ?TDEF(t_missing_rev_latest)
+ ])
+ }.
+
+bulk_get_multiple_docs_test_() ->
+ {
+ foreach,
+ fun setup_multiple/0,
+ fun teardown/1,
+ [
+ ?TDEF_FE(t_multiple_docs, 10)
+ ]
+ }.
+
+t_empty_request({_, DbUrl}) ->
+ {Code, Res} = bulk_get(DbUrl, []),
+ ?assertEqual(200, Code),
+ ?assertEqual([], Res).
+
+t_no_docs({_, DbUrl}) ->
+ {Code, #{}} = req(post, DbUrl ++ "/_bulk_get", #{}),
+ ?assertEqual(400, Code).
+
+t_invalid_doc({_, DbUrl}) ->
+ {Code, Res} = bulk_get(DbUrl, [<<"foo">>]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"error">> := #{
+ <<"id">> := null,
+ <<"rev">> := null,
+ <<"error">> := <<"bad_request">>
+ }
+ }
+ ],
+ <<"id">> := null
+ }
+ ],
+ Res
+ ).
+
+t_doc_no_id({_, DbUrl}) ->
+ {Code, Res} = bulk_get(DbUrl, [#{<<"rev">> => <<"1-foo">>}]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"error">> := #{
+ <<"id">> := null,
+ <<"rev">> := null,
+ <<"error">> := <<"bad_request">>
+ }
+ }
+ ],
+ <<"id">> := null
+ }
+ ],
+ Res
+ ).
+
+t_missing_doc({_, DbUrl}) ->
+ {Code, Res} = bulk_get(DbUrl, [#{<<"id">> => <<"missing">>}]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"error">> := #{
+ <<"error">> := <<"not_found">>,
+ <<"id">> := <<"missing">>,
+ <<"rev">> := <<"undefined">>
+ }
+ }
+ ],
+ <<"id">> := <<"missing">>
+ }
+ ],
+ Res
+ ).
+
+t_invalid_rev({_, DbUrl}) ->
+ Doc = #{<<"id">> => ?DOC, <<"rev">> => 42},
+ {Code, Res} = bulk_get(DbUrl, [Doc]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"error">> := #{
+ <<"error">> := <<"bad_request">>,
Review Comment:
The `error` field is more general and is a text representation of the HTTP codes mostly. So if this was an individual request it would return a 400.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: notifications-unsubscribe@couchdb.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [couchdb] nickva commented on a diff in pull request #4209: Add bulk_get tests
Posted by GitBox <gi...@apache.org>.
nickva commented on code in PR #4209:
URL: https://github.com/apache/couchdb/pull/4209#discussion_r997347523
##########
src/chttpd/test/eunit/chttpd_bulk_get_test.erl:
##########
@@ -0,0 +1,785 @@
+% Licensed under the Apache License, Version 2.0 (the "License"); you may not
+% use this file except in compliance with the License. You may obtain a copy of
+% the License at
+%
+% http://www.apache.org/licenses/LICENSE-2.0
+%
+% Unless required by applicable law or agreed to in writing, software
+% distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+% WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+% License for the specific language governing permissions and limitations under
+% the License.
+
+-module(chttpd_bulk_get_test).
+
+-include_lib("couch/include/couch_db.hrl").
+-include_lib("couch/include/couch_eunit.hrl").
+
+-define(USER, "chttpd_bulk_get_test_admin").
+-define(PASS, "pass").
+-define(AUTH, {basic_auth, {?USER, ?PASS}}).
+-define(JSON, {"Content-Type", "application/json"}).
+
+-define(DOC, <<"doc">>).
+-define(REVA, <<"reva">>).
+-define(REVB, <<"revb">>).
+-define(REVC, <<"revc">>).
+-define(ATT, <<"att">>).
+-define(ATT_DATA, <<"dGhlZGF0YQ==">>).
+
+-define(DOC_COUNT, 2000).
+
+test_docs_revs() ->
+ [
+ {?DOC, [?REVA]},
+ {?DOC, [?REVB, ?REVA]},
+ {?DOC, [?REVC, ?REVA]}
+ ].
+
+bulk_get_test_() ->
+ {
+ setup,
+ fun setup_basic/0,
+ fun teardown/1,
+ with([
+ ?TDEF(t_empty_request),
+ ?TDEF(t_no_docs),
+ ?TDEF(t_invalid_doc),
+ ?TDEF(t_doc_no_id),
+ ?TDEF(t_missing_doc),
+ ?TDEF(t_invalid_rev),
+ ?TDEF(t_missing_rev),
+ ?TDEF(t_doc_all_revs),
+ ?TDEF(t_specific_rev),
+ ?TDEF(t_specific_rev_latest),
+ ?TDEF(t_ancestor_rev_latest),
+ ?TDEF(t_revs_true),
+ ?TDEF(t_attachments_true),
+ ?TDEF(t_atts_since),
+ ?TDEF(t_atts_since_returns_attachment),
+ ?TDEF(t_atts_since_attachments_true),
+ ?TDEF(t_atts_since_multiple),
+ ?TDEF(t_atts_since_multiple_attachments_true),
+ ?TDEF(t_missing_rev_latest)
+ ])
+ }.
+
+bulk_get_multiple_docs_test_() ->
+ {
+ foreach,
+ fun setup_multiple/0,
+ fun teardown/1,
+ [
+ ?TDEF_FE(t_multiple_docs, 10)
+ ]
+ }.
+
+t_empty_request({_, DbUrl}) ->
+ {Code, Res} = bulk_get(DbUrl, []),
+ ?assertEqual(200, Code),
+ ?assertEqual([], Res).
+
+t_no_docs({_, DbUrl}) ->
+ {Code, #{}} = req(post, DbUrl ++ "/_bulk_get", #{}),
+ ?assertEqual(400, Code).
+
+t_invalid_doc({_, DbUrl}) ->
+ {Code, Res} = bulk_get(DbUrl, [<<"foo">>]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"error">> := #{
+ <<"id">> := null,
+ <<"rev">> := null,
+ <<"error">> := <<"bad_request">>
+ }
+ }
+ ],
+ <<"id">> := null
+ }
+ ],
+ Res
+ ).
+
+t_doc_no_id({_, DbUrl}) ->
+ {Code, Res} = bulk_get(DbUrl, [#{<<"rev">> => <<"1-foo">>}]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"error">> := #{
+ <<"id">> := null,
+ <<"rev">> := null,
+ <<"error">> := <<"bad_request">>
+ }
+ }
+ ],
+ <<"id">> := null
+ }
+ ],
+ Res
+ ).
+
+t_missing_doc({_, DbUrl}) ->
+ {Code, Res} = bulk_get(DbUrl, [#{<<"id">> => <<"missing">>}]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"error">> := #{
+ <<"error">> := <<"not_found">>,
+ <<"id">> := <<"missing">>,
+ <<"rev">> := <<"undefined">>
+ }
+ }
+ ],
+ <<"id">> := <<"missing">>
+ }
+ ],
+ Res
+ ).
+
+t_invalid_rev({_, DbUrl}) ->
+ Doc = #{<<"id">> => ?DOC, <<"rev">> => 42},
+ {Code, Res} = bulk_get(DbUrl, [Doc]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"error">> := #{
+ <<"error">> := <<"bad_request">>,
+ <<"id">> := ?DOC,
+ <<"rev">> := 42
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_missing_rev({_, DbUrl}) ->
+ Doc = #{<<"id">> => ?DOC, <<"rev">> => <<"1-x">>},
+ {Code, Res} = bulk_get(DbUrl, [Doc]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"error">> := #{
+ <<"error">> := <<"not_found">>,
+ <<"id">> := ?DOC,
+ <<"rev">> := <<"1-x">>
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_doc_all_revs({_, DbUrl}) ->
+ {Code, Res} = bulk_get(DbUrl, [#{<<"id">> => ?DOC}]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"ok">> := #{
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revb">>,
+ <<"_attachments">> := #{
+ ?ATT := #{<<"stub">> := true}
+ }
+ }
+ },
+ #{
+ <<"ok">> := #{
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revc">>,
+ <<"_attachments">> := #{
+ ?ATT := #{<<"stub">> := true}
+ }
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_specific_rev({_, DbUrl}) ->
+ Doc = #{<<"id">> => ?DOC, <<"rev">> => <<"2-revb">>},
+ {Code, Res} = bulk_get(DbUrl, [Doc]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"ok">> := #{
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revb">>,
+ <<"_attachments">> := #{
+ ?ATT := #{<<"stub">> := true}
+ }
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_specific_rev_latest({_, DbUrl}) ->
+ Doc = #{<<"id">> => ?DOC, <<"rev">> => <<"2-revb">>},
+ {Code, Res} = bulk_get(DbUrl, [Doc], "?latest=true"),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"ok">> := #{
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revb">>,
+ <<"_attachments">> := #{
+ ?ATT := #{<<"stub">> := true}
+ }
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_ancestor_rev_latest({_, DbUrl}) ->
+ Doc = #{<<"id">> => ?DOC, <<"rev">> => <<"1-reva">>},
+ {Code, Res} = bulk_get(DbUrl, [Doc], "?latest=true"),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"ok">> := #{
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revb">>,
+ <<"_attachments">> := #{
+ ?ATT := #{<<"stub">> := true}
+ }
+ }
+ },
+ #{
+ <<"ok">> := #{
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revc">>,
+ <<"_attachments">> := #{
+ ?ATT := #{<<"stub">> := true}
+ }
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_revs_true({_, DbUrl}) ->
+ Doc = #{
+ <<"id">> => ?DOC,
+ <<"rev">> => <<"1-reva">>
+ },
+ {Code, Res} = bulk_get(DbUrl, [Doc], "?revs=true"),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"ok">> := #{
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"1-reva">>,
+ <<"_revisions">> :=
+ #{<<"ids">> := [<<"reva">>], <<"start">> := 1},
+ <<"_attachments">> := #{
+ ?ATT := #{<<"stub">> := true}
+ }
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_attachments_true({_, DbUrl}) ->
+ Doc = #{
+ <<"id">> => ?DOC,
+ <<"rev">> => <<"1-reva">>
+ },
+ {Code, Res} = bulk_get(DbUrl, [Doc], "?attachments=true"),
Review Comment:
For `_bulk_get` we could definitely use at least a mention of "most of the individual doc option would apply here too"
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: notifications-unsubscribe@couchdb.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [couchdb] nickva commented on a diff in pull request #4209: Add bulk_get tests
Posted by GitBox <gi...@apache.org>.
nickva commented on code in PR #4209:
URL: https://github.com/apache/couchdb/pull/4209#discussion_r997332036
##########
src/chttpd/test/eunit/chttpd_bulk_get_test.erl:
##########
@@ -0,0 +1,785 @@
+% Licensed under the Apache License, Version 2.0 (the "License"); you may not
+% use this file except in compliance with the License. You may obtain a copy of
+% the License at
+%
+% http://www.apache.org/licenses/LICENSE-2.0
+%
+% Unless required by applicable law or agreed to in writing, software
+% distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+% WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+% License for the specific language governing permissions and limitations under
+% the License.
+
+-module(chttpd_bulk_get_test).
+
+-include_lib("couch/include/couch_db.hrl").
+-include_lib("couch/include/couch_eunit.hrl").
+
+-define(USER, "chttpd_bulk_get_test_admin").
+-define(PASS, "pass").
+-define(AUTH, {basic_auth, {?USER, ?PASS}}).
+-define(JSON, {"Content-Type", "application/json"}).
+
+-define(DOC, <<"doc">>).
+-define(REVA, <<"reva">>).
+-define(REVB, <<"revb">>).
+-define(REVC, <<"revc">>).
+-define(ATT, <<"att">>).
+-define(ATT_DATA, <<"dGhlZGF0YQ==">>).
+
+-define(DOC_COUNT, 2000).
+
+test_docs_revs() ->
+ [
+ {?DOC, [?REVA]},
+ {?DOC, [?REVB, ?REVA]},
+ {?DOC, [?REVC, ?REVA]}
+ ].
+
+bulk_get_test_() ->
+ {
+ setup,
+ fun setup_basic/0,
+ fun teardown/1,
+ with([
+ ?TDEF(t_empty_request),
+ ?TDEF(t_no_docs),
+ ?TDEF(t_invalid_doc),
+ ?TDEF(t_doc_no_id),
+ ?TDEF(t_missing_doc),
+ ?TDEF(t_invalid_rev),
+ ?TDEF(t_missing_rev),
+ ?TDEF(t_doc_all_revs),
+ ?TDEF(t_specific_rev),
+ ?TDEF(t_specific_rev_latest),
+ ?TDEF(t_ancestor_rev_latest),
+ ?TDEF(t_revs_true),
+ ?TDEF(t_attachments_true),
+ ?TDEF(t_atts_since),
+ ?TDEF(t_atts_since_returns_attachment),
+ ?TDEF(t_atts_since_attachments_true),
+ ?TDEF(t_atts_since_multiple),
+ ?TDEF(t_atts_since_multiple_attachments_true),
+ ?TDEF(t_missing_rev_latest)
+ ])
+ }.
+
+bulk_get_multiple_docs_test_() ->
+ {
+ foreach,
+ fun setup_multiple/0,
+ fun teardown/1,
+ [
+ ?TDEF_FE(t_multiple_docs, 10)
+ ]
+ }.
+
+t_empty_request({_, DbUrl}) ->
+ {Code, Res} = bulk_get(DbUrl, []),
+ ?assertEqual(200, Code),
+ ?assertEqual([], Res).
+
+t_no_docs({_, DbUrl}) ->
+ {Code, #{}} = req(post, DbUrl ++ "/_bulk_get", #{}),
+ ?assertEqual(400, Code).
+
+t_invalid_doc({_, DbUrl}) ->
+ {Code, Res} = bulk_get(DbUrl, [<<"foo">>]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"error">> := #{
+ <<"id">> := null,
+ <<"rev">> := null,
+ <<"error">> := <<"bad_request">>
+ }
+ }
+ ],
+ <<"id">> := null
+ }
+ ],
+ Res
+ ).
+
+t_doc_no_id({_, DbUrl}) ->
+ {Code, Res} = bulk_get(DbUrl, [#{<<"rev">> => <<"1-foo">>}]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"error">> := #{
+ <<"id">> := null,
+ <<"rev">> := null,
+ <<"error">> := <<"bad_request">>
+ }
+ }
+ ],
+ <<"id">> := null
+ }
+ ],
+ Res
+ ).
+
+t_missing_doc({_, DbUrl}) ->
+ {Code, Res} = bulk_get(DbUrl, [#{<<"id">> => <<"missing">>}]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"error">> := #{
+ <<"error">> := <<"not_found">>,
+ <<"id">> := <<"missing">>,
+ <<"rev">> := <<"undefined">>
+ }
+ }
+ ],
+ <<"id">> := <<"missing">>
+ }
+ ],
+ Res
+ ).
+
+t_invalid_rev({_, DbUrl}) ->
+ Doc = #{<<"id">> => ?DOC, <<"rev">> => 42},
+ {Code, Res} = bulk_get(DbUrl, [Doc]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"error">> := #{
+ <<"error">> := <<"bad_request">>,
+ <<"id">> := ?DOC,
+ <<"rev">> := 42
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_missing_rev({_, DbUrl}) ->
+ Doc = #{<<"id">> => ?DOC, <<"rev">> => <<"1-x">>},
+ {Code, Res} = bulk_get(DbUrl, [Doc]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"error">> := #{
+ <<"error">> := <<"not_found">>,
+ <<"id">> := ?DOC,
+ <<"rev">> := <<"1-x">>
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_doc_all_revs({_, DbUrl}) ->
+ {Code, Res} = bulk_get(DbUrl, [#{<<"id">> => ?DOC}]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"ok">> := #{
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revb">>,
+ <<"_attachments">> := #{
+ ?ATT := #{<<"stub">> := true}
+ }
+ }
+ },
+ #{
+ <<"ok">> := #{
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revc">>,
+ <<"_attachments">> := #{
+ ?ATT := #{<<"stub">> := true}
+ }
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_specific_rev({_, DbUrl}) ->
+ Doc = #{<<"id">> => ?DOC, <<"rev">> => <<"2-revb">>},
+ {Code, Res} = bulk_get(DbUrl, [Doc]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"ok">> := #{
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revb">>,
+ <<"_attachments">> := #{
+ ?ATT := #{<<"stub">> := true}
+ }
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_specific_rev_latest({_, DbUrl}) ->
+ Doc = #{<<"id">> => ?DOC, <<"rev">> => <<"2-revb">>},
+ {Code, Res} = bulk_get(DbUrl, [Doc], "?latest=true"),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"ok">> := #{
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revb">>,
+ <<"_attachments">> := #{
+ ?ATT := #{<<"stub">> := true}
+ }
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_ancestor_rev_latest({_, DbUrl}) ->
+ Doc = #{<<"id">> => ?DOC, <<"rev">> => <<"1-reva">>},
+ {Code, Res} = bulk_get(DbUrl, [Doc], "?latest=true"),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"ok">> := #{
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revb">>,
+ <<"_attachments">> := #{
+ ?ATT := #{<<"stub">> := true}
+ }
+ }
+ },
+ #{
+ <<"ok">> := #{
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revc">>,
+ <<"_attachments">> := #{
+ ?ATT := #{<<"stub">> := true}
+ }
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_revs_true({_, DbUrl}) ->
+ Doc = #{
+ <<"id">> => ?DOC,
+ <<"rev">> => <<"1-reva">>
+ },
+ {Code, Res} = bulk_get(DbUrl, [Doc], "?revs=true"),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"ok">> := #{
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"1-reva">>,
+ <<"_revisions">> :=
+ #{<<"ids">> := [<<"reva">>], <<"start">> := 1},
+ <<"_attachments">> := #{
+ ?ATT := #{<<"stub">> := true}
+ }
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_attachments_true({_, DbUrl}) ->
+ Doc = #{
+ <<"id">> => ?DOC,
+ <<"rev">> => <<"1-reva">>
+ },
+ {Code, Res} = bulk_get(DbUrl, [Doc], "?attachments=true"),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"ok">> := #{
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"1-reva">>,
+ <<"_attachments">> := #{
+ ?ATT := #{<<"data">> := ?ATT_DATA}
+ }
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_atts_since({_, DbUrl}) ->
+ % Attachment should not be returned as 2 from 2-revb is not stricly greater
+ % than 1 from our attachment's revpos
+ Doc = #{
+ <<"id">> => ?DOC,
+ <<"rev">> => <<"2-revb">>,
+ <<"atts_since">> => [<<"2-revb">>]
+ },
+ {Code, Res} = bulk_get(DbUrl, [Doc]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"ok">> := #{
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revb">>,
+ <<"_attachments">> := #{
+ ?ATT := #{<<"stub">> := true}
+ }
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_atts_since_returns_attachment({_, DbUrl}) ->
+ % 0-baz revpos 0 is less than revpos 1 of our attachment
+ Doc = #{
+ <<"id">> => ?DOC,
+ <<"rev">> => <<"2-revb">>,
+ <<"atts_since">> => [<<"0-baz">>]
+ },
+ {Code, Res} = bulk_get(DbUrl, [Doc]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"ok">> := #{
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revb">>,
+ <<"_attachments">> := #{
+ ?ATT := #{<<"data">> := ?ATT_DATA}
+ }
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_atts_since_attachments_true({_, DbUrl}) ->
+ % Check that atts_since overrides attachments=true
Review Comment:
Good idea!
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: notifications-unsubscribe@couchdb.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [couchdb] nickva commented on a diff in pull request #4209: Add bulk_get tests
Posted by GitBox <gi...@apache.org>.
nickva commented on code in PR #4209:
URL: https://github.com/apache/couchdb/pull/4209#discussion_r997340328
##########
src/chttpd/test/eunit/chttpd_bulk_get_test.erl:
##########
@@ -0,0 +1,785 @@
+% Licensed under the Apache License, Version 2.0 (the "License"); you may not
+% use this file except in compliance with the License. You may obtain a copy of
+% the License at
+%
+% http://www.apache.org/licenses/LICENSE-2.0
+%
+% Unless required by applicable law or agreed to in writing, software
+% distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+% WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+% License for the specific language governing permissions and limitations under
+% the License.
+
+-module(chttpd_bulk_get_test).
+
+-include_lib("couch/include/couch_db.hrl").
+-include_lib("couch/include/couch_eunit.hrl").
+
+-define(USER, "chttpd_bulk_get_test_admin").
+-define(PASS, "pass").
+-define(AUTH, {basic_auth, {?USER, ?PASS}}).
+-define(JSON, {"Content-Type", "application/json"}).
+
+-define(DOC, <<"doc">>).
+-define(REVA, <<"reva">>).
+-define(REVB, <<"revb">>).
+-define(REVC, <<"revc">>).
+-define(ATT, <<"att">>).
+-define(ATT_DATA, <<"dGhlZGF0YQ==">>).
+
+-define(DOC_COUNT, 2000).
+
+test_docs_revs() ->
+ [
+ {?DOC, [?REVA]},
+ {?DOC, [?REVB, ?REVA]},
+ {?DOC, [?REVC, ?REVA]}
+ ].
+
+bulk_get_test_() ->
+ {
+ setup,
+ fun setup_basic/0,
+ fun teardown/1,
+ with([
+ ?TDEF(t_empty_request),
+ ?TDEF(t_no_docs),
+ ?TDEF(t_invalid_doc),
+ ?TDEF(t_doc_no_id),
+ ?TDEF(t_missing_doc),
+ ?TDEF(t_invalid_rev),
+ ?TDEF(t_missing_rev),
+ ?TDEF(t_doc_all_revs),
+ ?TDEF(t_specific_rev),
+ ?TDEF(t_specific_rev_latest),
+ ?TDEF(t_ancestor_rev_latest),
+ ?TDEF(t_revs_true),
+ ?TDEF(t_attachments_true),
+ ?TDEF(t_atts_since),
+ ?TDEF(t_atts_since_returns_attachment),
+ ?TDEF(t_atts_since_attachments_true),
+ ?TDEF(t_atts_since_multiple),
+ ?TDEF(t_atts_since_multiple_attachments_true),
+ ?TDEF(t_missing_rev_latest)
+ ])
+ }.
+
+bulk_get_multiple_docs_test_() ->
+ {
+ foreach,
+ fun setup_multiple/0,
+ fun teardown/1,
+ [
+ ?TDEF_FE(t_multiple_docs, 10)
+ ]
+ }.
+
+t_empty_request({_, DbUrl}) ->
+ {Code, Res} = bulk_get(DbUrl, []),
+ ?assertEqual(200, Code),
+ ?assertEqual([], Res).
+
+t_no_docs({_, DbUrl}) ->
+ {Code, #{}} = req(post, DbUrl ++ "/_bulk_get", #{}),
+ ?assertEqual(400, Code).
+
+t_invalid_doc({_, DbUrl}) ->
+ {Code, Res} = bulk_get(DbUrl, [<<"foo">>]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"error">> := #{
+ <<"id">> := null,
+ <<"rev">> := null,
+ <<"error">> := <<"bad_request">>
+ }
+ }
+ ],
+ <<"id">> := null
+ }
+ ],
+ Res
+ ).
+
+t_doc_no_id({_, DbUrl}) ->
+ {Code, Res} = bulk_get(DbUrl, [#{<<"rev">> => <<"1-foo">>}]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"error">> := #{
+ <<"id">> := null,
+ <<"rev">> := null,
+ <<"error">> := <<"bad_request">>
+ }
+ }
+ ],
+ <<"id">> := null
+ }
+ ],
+ Res
+ ).
+
+t_missing_doc({_, DbUrl}) ->
+ {Code, Res} = bulk_get(DbUrl, [#{<<"id">> => <<"missing">>}]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"error">> := #{
+ <<"error">> := <<"not_found">>,
+ <<"id">> := <<"missing">>,
+ <<"rev">> := <<"undefined">>
+ }
+ }
+ ],
+ <<"id">> := <<"missing">>
+ }
+ ],
+ Res
+ ).
+
+t_invalid_rev({_, DbUrl}) ->
+ Doc = #{<<"id">> => ?DOC, <<"rev">> => 42},
+ {Code, Res} = bulk_get(DbUrl, [Doc]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"error">> := #{
+ <<"error">> := <<"bad_request">>,
+ <<"id">> := ?DOC,
+ <<"rev">> := 42
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_missing_rev({_, DbUrl}) ->
+ Doc = #{<<"id">> => ?DOC, <<"rev">> => <<"1-x">>},
+ {Code, Res} = bulk_get(DbUrl, [Doc]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"error">> := #{
+ <<"error">> := <<"not_found">>,
Review Comment:
The full error message has a reason parameter like "revision not found ..." but I opted to match just the main error code only, which is the equivalent of a http code if it an individual request. So this one would be a 404, for instance.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: notifications-unsubscribe@couchdb.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [couchdb] nickva commented on a diff in pull request #4209: Add bulk_get tests
Posted by GitBox <gi...@apache.org>.
nickva commented on code in PR #4209:
URL: https://github.com/apache/couchdb/pull/4209#discussion_r997330197
##########
src/chttpd/test/eunit/chttpd_bulk_get_test.erl:
##########
@@ -0,0 +1,785 @@
+% Licensed under the Apache License, Version 2.0 (the "License"); you may not
+% use this file except in compliance with the License. You may obtain a copy of
+% the License at
+%
+% http://www.apache.org/licenses/LICENSE-2.0
+%
+% Unless required by applicable law or agreed to in writing, software
+% distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+% WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+% License for the specific language governing permissions and limitations under
+% the License.
+
+-module(chttpd_bulk_get_test).
+
+-include_lib("couch/include/couch_db.hrl").
+-include_lib("couch/include/couch_eunit.hrl").
+
+-define(USER, "chttpd_bulk_get_test_admin").
+-define(PASS, "pass").
+-define(AUTH, {basic_auth, {?USER, ?PASS}}).
+-define(JSON, {"Content-Type", "application/json"}).
+
+-define(DOC, <<"doc">>).
+-define(REVA, <<"reva">>).
+-define(REVB, <<"revb">>).
+-define(REVC, <<"revc">>).
+-define(ATT, <<"att">>).
+-define(ATT_DATA, <<"dGhlZGF0YQ==">>).
+
+-define(DOC_COUNT, 2000).
+
+test_docs_revs() ->
+ [
+ {?DOC, [?REVA]},
+ {?DOC, [?REVB, ?REVA]},
+ {?DOC, [?REVC, ?REVA]}
+ ].
+
+bulk_get_test_() ->
+ {
+ setup,
+ fun setup_basic/0,
+ fun teardown/1,
+ with([
+ ?TDEF(t_empty_request),
+ ?TDEF(t_no_docs),
+ ?TDEF(t_invalid_doc),
+ ?TDEF(t_doc_no_id),
+ ?TDEF(t_missing_doc),
+ ?TDEF(t_invalid_rev),
+ ?TDEF(t_missing_rev),
+ ?TDEF(t_doc_all_revs),
+ ?TDEF(t_specific_rev),
+ ?TDEF(t_specific_rev_latest),
+ ?TDEF(t_ancestor_rev_latest),
+ ?TDEF(t_revs_true),
+ ?TDEF(t_attachments_true),
+ ?TDEF(t_atts_since),
+ ?TDEF(t_atts_since_returns_attachment),
+ ?TDEF(t_atts_since_attachments_true),
+ ?TDEF(t_atts_since_multiple),
+ ?TDEF(t_atts_since_multiple_attachments_true),
+ ?TDEF(t_missing_rev_latest)
+ ])
+ }.
+
+bulk_get_multiple_docs_test_() ->
+ {
+ foreach,
+ fun setup_multiple/0,
+ fun teardown/1,
+ [
+ ?TDEF_FE(t_multiple_docs, 10)
+ ]
+ }.
+
+t_empty_request({_, DbUrl}) ->
+ {Code, Res} = bulk_get(DbUrl, []),
+ ?assertEqual(200, Code),
+ ?assertEqual([], Res).
+
+t_no_docs({_, DbUrl}) ->
+ {Code, #{}} = req(post, DbUrl ++ "/_bulk_get", #{}),
+ ?assertEqual(400, Code).
+
+t_invalid_doc({_, DbUrl}) ->
+ {Code, Res} = bulk_get(DbUrl, [<<"foo">>]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"error">> := #{
+ <<"id">> := null,
+ <<"rev">> := null,
+ <<"error">> := <<"bad_request">>
+ }
+ }
+ ],
+ <<"id">> := null
+ }
+ ],
+ Res
+ ).
+
+t_doc_no_id({_, DbUrl}) ->
+ {Code, Res} = bulk_get(DbUrl, [#{<<"rev">> => <<"1-foo">>}]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"error">> := #{
+ <<"id">> := null,
+ <<"rev">> := null,
+ <<"error">> := <<"bad_request">>
+ }
+ }
+ ],
+ <<"id">> := null
+ }
+ ],
+ Res
+ ).
+
+t_missing_doc({_, DbUrl}) ->
+ {Code, Res} = bulk_get(DbUrl, [#{<<"id">> => <<"missing">>}]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"error">> := #{
+ <<"error">> := <<"not_found">>,
+ <<"id">> := <<"missing">>,
+ <<"rev">> := <<"undefined">>
+ }
+ }
+ ],
+ <<"id">> := <<"missing">>
+ }
+ ],
+ Res
+ ).
+
+t_invalid_rev({_, DbUrl}) ->
+ Doc = #{<<"id">> => ?DOC, <<"rev">> => 42},
+ {Code, Res} = bulk_get(DbUrl, [Doc]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"error">> := #{
+ <<"error">> := <<"bad_request">>,
+ <<"id">> := ?DOC,
+ <<"rev">> := 42
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_missing_rev({_, DbUrl}) ->
+ Doc = #{<<"id">> => ?DOC, <<"rev">> => <<"1-x">>},
+ {Code, Res} = bulk_get(DbUrl, [Doc]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"error">> := #{
+ <<"error">> := <<"not_found">>,
+ <<"id">> := ?DOC,
+ <<"rev">> := <<"1-x">>
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_doc_all_revs({_, DbUrl}) ->
+ {Code, Res} = bulk_get(DbUrl, [#{<<"id">> => ?DOC}]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"ok">> := #{
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revb">>,
+ <<"_attachments">> := #{
+ ?ATT := #{<<"stub">> := true}
+ }
+ }
+ },
+ #{
+ <<"ok">> := #{
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revc">>,
+ <<"_attachments">> := #{
+ ?ATT := #{<<"stub">> := true}
+ }
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_specific_rev({_, DbUrl}) ->
+ Doc = #{<<"id">> => ?DOC, <<"rev">> => <<"2-revb">>},
+ {Code, Res} = bulk_get(DbUrl, [Doc]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"ok">> := #{
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revb">>,
+ <<"_attachments">> := #{
+ ?ATT := #{<<"stub">> := true}
+ }
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_specific_rev_latest({_, DbUrl}) ->
+ Doc = #{<<"id">> => ?DOC, <<"rev">> => <<"2-revb">>},
+ {Code, Res} = bulk_get(DbUrl, [Doc], "?latest=true"),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"ok">> := #{
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revb">>,
+ <<"_attachments">> := #{
+ ?ATT := #{<<"stub">> := true}
+ }
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_ancestor_rev_latest({_, DbUrl}) ->
+ Doc = #{<<"id">> => ?DOC, <<"rev">> => <<"1-reva">>},
+ {Code, Res} = bulk_get(DbUrl, [Doc], "?latest=true"),
Review Comment:
Good idea to document it. We document it for doc GETs https://docs.couchdb.org/en/3.2.2-docs/api/document/common.html#get--db-docid and we cheat for the _bulk_get but allowing passing most of the same options.
`latest` as implemented today means, given a particular revision, we don't want to return that revision only but all the latest descendants (leafs) of that revision.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: notifications-unsubscribe@couchdb.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [couchdb] nickva commented on a diff in pull request #4209: Add bulk_get tests
Posted by GitBox <gi...@apache.org>.
nickva commented on code in PR #4209:
URL: https://github.com/apache/couchdb/pull/4209#discussion_r997331724
##########
src/chttpd/test/eunit/chttpd_bulk_get_test.erl:
##########
@@ -0,0 +1,785 @@
+% Licensed under the Apache License, Version 2.0 (the "License"); you may not
+% use this file except in compliance with the License. You may obtain a copy of
+% the License at
+%
+% http://www.apache.org/licenses/LICENSE-2.0
+%
+% Unless required by applicable law or agreed to in writing, software
+% distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+% WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+% License for the specific language governing permissions and limitations under
+% the License.
+
+-module(chttpd_bulk_get_test).
+
+-include_lib("couch/include/couch_db.hrl").
+-include_lib("couch/include/couch_eunit.hrl").
+
+-define(USER, "chttpd_bulk_get_test_admin").
+-define(PASS, "pass").
+-define(AUTH, {basic_auth, {?USER, ?PASS}}).
+-define(JSON, {"Content-Type", "application/json"}).
+
+-define(DOC, <<"doc">>).
+-define(REVA, <<"reva">>).
+-define(REVB, <<"revb">>).
+-define(REVC, <<"revc">>).
+-define(ATT, <<"att">>).
+-define(ATT_DATA, <<"dGhlZGF0YQ==">>).
+
+-define(DOC_COUNT, 2000).
+
+test_docs_revs() ->
+ [
+ {?DOC, [?REVA]},
+ {?DOC, [?REVB, ?REVA]},
+ {?DOC, [?REVC, ?REVA]}
+ ].
+
+bulk_get_test_() ->
+ {
+ setup,
+ fun setup_basic/0,
+ fun teardown/1,
+ with([
+ ?TDEF(t_empty_request),
+ ?TDEF(t_no_docs),
+ ?TDEF(t_invalid_doc),
+ ?TDEF(t_doc_no_id),
+ ?TDEF(t_missing_doc),
+ ?TDEF(t_invalid_rev),
+ ?TDEF(t_missing_rev),
+ ?TDEF(t_doc_all_revs),
+ ?TDEF(t_specific_rev),
+ ?TDEF(t_specific_rev_latest),
+ ?TDEF(t_ancestor_rev_latest),
+ ?TDEF(t_revs_true),
+ ?TDEF(t_attachments_true),
+ ?TDEF(t_atts_since),
+ ?TDEF(t_atts_since_returns_attachment),
+ ?TDEF(t_atts_since_attachments_true),
+ ?TDEF(t_atts_since_multiple),
+ ?TDEF(t_atts_since_multiple_attachments_true),
+ ?TDEF(t_missing_rev_latest)
+ ])
+ }.
+
+bulk_get_multiple_docs_test_() ->
+ {
+ foreach,
+ fun setup_multiple/0,
+ fun teardown/1,
+ [
+ ?TDEF_FE(t_multiple_docs, 10)
+ ]
+ }.
+
+t_empty_request({_, DbUrl}) ->
+ {Code, Res} = bulk_get(DbUrl, []),
+ ?assertEqual(200, Code),
+ ?assertEqual([], Res).
+
+t_no_docs({_, DbUrl}) ->
+ {Code, #{}} = req(post, DbUrl ++ "/_bulk_get", #{}),
+ ?assertEqual(400, Code).
+
+t_invalid_doc({_, DbUrl}) ->
+ {Code, Res} = bulk_get(DbUrl, [<<"foo">>]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"error">> := #{
+ <<"id">> := null,
+ <<"rev">> := null,
+ <<"error">> := <<"bad_request">>
+ }
+ }
+ ],
+ <<"id">> := null
+ }
+ ],
+ Res
+ ).
+
+t_doc_no_id({_, DbUrl}) ->
+ {Code, Res} = bulk_get(DbUrl, [#{<<"rev">> => <<"1-foo">>}]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"error">> := #{
+ <<"id">> := null,
+ <<"rev">> := null,
+ <<"error">> := <<"bad_request">>
+ }
+ }
+ ],
+ <<"id">> := null
+ }
+ ],
+ Res
+ ).
+
+t_missing_doc({_, DbUrl}) ->
+ {Code, Res} = bulk_get(DbUrl, [#{<<"id">> => <<"missing">>}]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"error">> := #{
+ <<"error">> := <<"not_found">>,
+ <<"id">> := <<"missing">>,
+ <<"rev">> := <<"undefined">>
+ }
+ }
+ ],
+ <<"id">> := <<"missing">>
+ }
+ ],
+ Res
+ ).
+
+t_invalid_rev({_, DbUrl}) ->
+ Doc = #{<<"id">> => ?DOC, <<"rev">> => 42},
+ {Code, Res} = bulk_get(DbUrl, [Doc]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"error">> := #{
+ <<"error">> := <<"bad_request">>,
+ <<"id">> := ?DOC,
+ <<"rev">> := 42
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_missing_rev({_, DbUrl}) ->
+ Doc = #{<<"id">> => ?DOC, <<"rev">> => <<"1-x">>},
+ {Code, Res} = bulk_get(DbUrl, [Doc]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"error">> := #{
+ <<"error">> := <<"not_found">>,
+ <<"id">> := ?DOC,
+ <<"rev">> := <<"1-x">>
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_doc_all_revs({_, DbUrl}) ->
+ {Code, Res} = bulk_get(DbUrl, [#{<<"id">> => ?DOC}]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"ok">> := #{
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revb">>,
+ <<"_attachments">> := #{
+ ?ATT := #{<<"stub">> := true}
+ }
+ }
+ },
+ #{
+ <<"ok">> := #{
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revc">>,
+ <<"_attachments">> := #{
+ ?ATT := #{<<"stub">> := true}
+ }
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_specific_rev({_, DbUrl}) ->
+ Doc = #{<<"id">> => ?DOC, <<"rev">> => <<"2-revb">>},
+ {Code, Res} = bulk_get(DbUrl, [Doc]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"ok">> := #{
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revb">>,
+ <<"_attachments">> := #{
+ ?ATT := #{<<"stub">> := true}
+ }
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_specific_rev_latest({_, DbUrl}) ->
+ Doc = #{<<"id">> => ?DOC, <<"rev">> => <<"2-revb">>},
+ {Code, Res} = bulk_get(DbUrl, [Doc], "?latest=true"),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"ok">> := #{
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revb">>,
+ <<"_attachments">> := #{
+ ?ATT := #{<<"stub">> := true}
+ }
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_ancestor_rev_latest({_, DbUrl}) ->
+ Doc = #{<<"id">> => ?DOC, <<"rev">> => <<"1-reva">>},
+ {Code, Res} = bulk_get(DbUrl, [Doc], "?latest=true"),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"ok">> := #{
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revb">>,
+ <<"_attachments">> := #{
+ ?ATT := #{<<"stub">> := true}
+ }
+ }
+ },
+ #{
+ <<"ok">> := #{
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revc">>,
+ <<"_attachments">> := #{
+ ?ATT := #{<<"stub">> := true}
+ }
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_revs_true({_, DbUrl}) ->
+ Doc = #{
+ <<"id">> => ?DOC,
+ <<"rev">> => <<"1-reva">>
+ },
+ {Code, Res} = bulk_get(DbUrl, [Doc], "?revs=true"),
Review Comment:
Just like with `latest=true` we cheat here and accept most of the same options as a single document GET. We cheated down to the level of accepting parameters in the POST requests (we share the params parsing code), instead of having them as json fields in the request body itself.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: notifications-unsubscribe@couchdb.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [couchdb] nickva commented on a diff in pull request #4209: Add bulk_get tests
Posted by GitBox <gi...@apache.org>.
nickva commented on code in PR #4209:
URL: https://github.com/apache/couchdb/pull/4209#discussion_r997330197
##########
src/chttpd/test/eunit/chttpd_bulk_get_test.erl:
##########
@@ -0,0 +1,785 @@
+% Licensed under the Apache License, Version 2.0 (the "License"); you may not
+% use this file except in compliance with the License. You may obtain a copy of
+% the License at
+%
+% http://www.apache.org/licenses/LICENSE-2.0
+%
+% Unless required by applicable law or agreed to in writing, software
+% distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+% WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+% License for the specific language governing permissions and limitations under
+% the License.
+
+-module(chttpd_bulk_get_test).
+
+-include_lib("couch/include/couch_db.hrl").
+-include_lib("couch/include/couch_eunit.hrl").
+
+-define(USER, "chttpd_bulk_get_test_admin").
+-define(PASS, "pass").
+-define(AUTH, {basic_auth, {?USER, ?PASS}}).
+-define(JSON, {"Content-Type", "application/json"}).
+
+-define(DOC, <<"doc">>).
+-define(REVA, <<"reva">>).
+-define(REVB, <<"revb">>).
+-define(REVC, <<"revc">>).
+-define(ATT, <<"att">>).
+-define(ATT_DATA, <<"dGhlZGF0YQ==">>).
+
+-define(DOC_COUNT, 2000).
+
+test_docs_revs() ->
+ [
+ {?DOC, [?REVA]},
+ {?DOC, [?REVB, ?REVA]},
+ {?DOC, [?REVC, ?REVA]}
+ ].
+
+bulk_get_test_() ->
+ {
+ setup,
+ fun setup_basic/0,
+ fun teardown/1,
+ with([
+ ?TDEF(t_empty_request),
+ ?TDEF(t_no_docs),
+ ?TDEF(t_invalid_doc),
+ ?TDEF(t_doc_no_id),
+ ?TDEF(t_missing_doc),
+ ?TDEF(t_invalid_rev),
+ ?TDEF(t_missing_rev),
+ ?TDEF(t_doc_all_revs),
+ ?TDEF(t_specific_rev),
+ ?TDEF(t_specific_rev_latest),
+ ?TDEF(t_ancestor_rev_latest),
+ ?TDEF(t_revs_true),
+ ?TDEF(t_attachments_true),
+ ?TDEF(t_atts_since),
+ ?TDEF(t_atts_since_returns_attachment),
+ ?TDEF(t_atts_since_attachments_true),
+ ?TDEF(t_atts_since_multiple),
+ ?TDEF(t_atts_since_multiple_attachments_true),
+ ?TDEF(t_missing_rev_latest)
+ ])
+ }.
+
+bulk_get_multiple_docs_test_() ->
+ {
+ foreach,
+ fun setup_multiple/0,
+ fun teardown/1,
+ [
+ ?TDEF_FE(t_multiple_docs, 10)
+ ]
+ }.
+
+t_empty_request({_, DbUrl}) ->
+ {Code, Res} = bulk_get(DbUrl, []),
+ ?assertEqual(200, Code),
+ ?assertEqual([], Res).
+
+t_no_docs({_, DbUrl}) ->
+ {Code, #{}} = req(post, DbUrl ++ "/_bulk_get", #{}),
+ ?assertEqual(400, Code).
+
+t_invalid_doc({_, DbUrl}) ->
+ {Code, Res} = bulk_get(DbUrl, [<<"foo">>]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"error">> := #{
+ <<"id">> := null,
+ <<"rev">> := null,
+ <<"error">> := <<"bad_request">>
+ }
+ }
+ ],
+ <<"id">> := null
+ }
+ ],
+ Res
+ ).
+
+t_doc_no_id({_, DbUrl}) ->
+ {Code, Res} = bulk_get(DbUrl, [#{<<"rev">> => <<"1-foo">>}]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"error">> := #{
+ <<"id">> := null,
+ <<"rev">> := null,
+ <<"error">> := <<"bad_request">>
+ }
+ }
+ ],
+ <<"id">> := null
+ }
+ ],
+ Res
+ ).
+
+t_missing_doc({_, DbUrl}) ->
+ {Code, Res} = bulk_get(DbUrl, [#{<<"id">> => <<"missing">>}]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"error">> := #{
+ <<"error">> := <<"not_found">>,
+ <<"id">> := <<"missing">>,
+ <<"rev">> := <<"undefined">>
+ }
+ }
+ ],
+ <<"id">> := <<"missing">>
+ }
+ ],
+ Res
+ ).
+
+t_invalid_rev({_, DbUrl}) ->
+ Doc = #{<<"id">> => ?DOC, <<"rev">> => 42},
+ {Code, Res} = bulk_get(DbUrl, [Doc]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"error">> := #{
+ <<"error">> := <<"bad_request">>,
+ <<"id">> := ?DOC,
+ <<"rev">> := 42
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_missing_rev({_, DbUrl}) ->
+ Doc = #{<<"id">> => ?DOC, <<"rev">> => <<"1-x">>},
+ {Code, Res} = bulk_get(DbUrl, [Doc]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"error">> := #{
+ <<"error">> := <<"not_found">>,
+ <<"id">> := ?DOC,
+ <<"rev">> := <<"1-x">>
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_doc_all_revs({_, DbUrl}) ->
+ {Code, Res} = bulk_get(DbUrl, [#{<<"id">> => ?DOC}]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"ok">> := #{
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revb">>,
+ <<"_attachments">> := #{
+ ?ATT := #{<<"stub">> := true}
+ }
+ }
+ },
+ #{
+ <<"ok">> := #{
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revc">>,
+ <<"_attachments">> := #{
+ ?ATT := #{<<"stub">> := true}
+ }
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_specific_rev({_, DbUrl}) ->
+ Doc = #{<<"id">> => ?DOC, <<"rev">> => <<"2-revb">>},
+ {Code, Res} = bulk_get(DbUrl, [Doc]),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"ok">> := #{
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revb">>,
+ <<"_attachments">> := #{
+ ?ATT := #{<<"stub">> := true}
+ }
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_specific_rev_latest({_, DbUrl}) ->
+ Doc = #{<<"id">> => ?DOC, <<"rev">> => <<"2-revb">>},
+ {Code, Res} = bulk_get(DbUrl, [Doc], "?latest=true"),
+ ?assertEqual(200, Code),
+ ?assertMatch(
+ [
+ #{
+ <<"docs">> := [
+ #{
+ <<"ok">> := #{
+ <<"_id">> := ?DOC,
+ <<"_rev">> := <<"2-revb">>,
+ <<"_attachments">> := #{
+ ?ATT := #{<<"stub">> := true}
+ }
+ }
+ }
+ ],
+ <<"id">> := ?DOC
+ }
+ ],
+ Res
+ ).
+
+t_ancestor_rev_latest({_, DbUrl}) ->
+ Doc = #{<<"id">> => ?DOC, <<"rev">> => <<"1-reva">>},
+ {Code, Res} = bulk_get(DbUrl, [Doc], "?latest=true"),
Review Comment:
Good idea to document it. We document it for doc GETs https://docs.couchdb.org/en/3.2.2-docs/api/document/common.html#get--db-docid and we cheat for the _bulk_get but allowing passing most of the same options.
`latest` as implemented today means, given a particular revision, we don't want to return that revision all the latest descendants (leafs) of that revision.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: notifications-unsubscribe@couchdb.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org
[GitHub] [couchdb] nickva merged pull request #4209: Add bulk_get tests
Posted by GitBox <gi...@apache.org>.
nickva merged PR #4209:
URL: https://github.com/apache/couchdb/pull/4209
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: notifications-unsubscribe@couchdb.apache.org
For queries about this service, please contact Infrastructure at:
users@infra.apache.org