| % 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(fabric2_update_docs_tests). |
| |
| -include_lib("couch/include/couch_db.hrl"). |
| -include_lib("couch/include/couch_eunit.hrl"). |
| -include_lib("eunit/include/eunit.hrl"). |
| -include("fabric2_test.hrl"). |
| |
| update_docs_test_() -> |
| { |
| "Test update_docs", |
| { |
| setup, |
| fun setup_all/0, |
| fun teardown_all/1, |
| { |
| foreach, |
| fun setup/0, |
| fun cleanup/1, |
| [ |
| ?TDEF_FE(update_docs), |
| ?TDEF_FE(update_docs_replicated), |
| ?TDEF_FE(update_docs_batches), |
| ?TDEF_FE(update_docs_replicated_batches), |
| ?TDEF_FE(update_docs_duplicate_ids_conflict), |
| ?TDEF_FE(update_docs_duplicate_ids_with_batches), |
| ?TDEF_FE(update_docs_replicate_batches_duplicate_id) |
| ] |
| } |
| } |
| }. |
| |
| setup_all() -> |
| test_util:start_couch([fabric]). |
| |
| teardown_all(Ctx) -> |
| test_util:stop_couch(Ctx). |
| |
| setup() -> |
| {ok, Db} = fabric2_db:create(?tempdb(), [{user_ctx, ?ADMIN_USER}]), |
| Db. |
| |
| cleanup(#{} = Db) -> |
| ok = fabric2_db:delete(fabric2_db:name(Db), []). |
| |
| update_docs(Db) -> |
| ?assertEqual({ok, []}, fabric2_db:update_docs(Db, [])), |
| |
| Doc1 = doc(), |
| Res1 = fabric2_db:update_docs(Db, [Doc1]), |
| ?assertMatch({ok, [_]}, Res1), |
| {ok, [Doc1Res]} = Res1, |
| ?assertMatch({ok, {1, <<_/binary>>}}, Doc1Res), |
| {ok, {1, Rev1}} = Doc1Res, |
| {ok, Doc1Open} = fabric2_db:open_doc(Db, Doc1#doc.id), |
| ?assertEqual(Doc1#doc{revs = {1, [Rev1]}}, Doc1Open), |
| |
| Doc2 = doc(), |
| Doc3 = doc(), |
| Res2 = fabric2_db:update_docs(Db, [Doc2, Doc3]), |
| ?assertMatch({ok, [_, _]}, Res2), |
| {ok, [Doc2Res, Doc3Res]} = Res2, |
| ?assertMatch({ok, {1, <<_/binary>>}}, Doc2Res), |
| ?assertMatch({ok, {1, <<_/binary>>}}, Doc3Res). |
| |
| update_docs_replicated(Db) -> |
| Opts = [replicated_changes], |
| |
| ?assertEqual({ok, []}, fabric2_db:update_docs(Db, [], Opts)), |
| |
| Doc1 = doc(10, {1, [rev()]}), |
| ?assertMatch({ok, []}, fabric2_db:update_docs(Db, [Doc1], Opts)), |
| {ok, Doc1Open} = fabric2_db:open_doc(Db, Doc1#doc.id), |
| ?assertEqual(Doc1, Doc1Open), |
| |
| Doc2 = doc(10, {1, [rev()]}), |
| Doc3 = doc(10, {1, [rev()]}), |
| ?assertMatch({ok, []}, fabric2_db:update_docs(Db, [Doc2, Doc3], Opts)), |
| {ok, Doc2Open} = fabric2_db:open_doc(Db, Doc2#doc.id), |
| ?assertEqual(Doc2, Doc2Open), |
| {ok, Doc3Open} = fabric2_db:open_doc(Db, Doc3#doc.id), |
| ?assertEqual(Doc3, Doc3Open). |
| |
| update_docs_batches(Db) -> |
| Opts = [{batch_size, 5000}], |
| |
| Docs1 = [doc(9000), doc(9000)], |
| |
| ?assertMatch({ok, [_ | _]}, fabric2_db:update_docs(Db, Docs1, Opts)), |
| |
| lists:foreach( |
| fun(#doc{} = Doc) -> |
| ?assertMatch({ok, #doc{}}, fabric2_db:open_doc(Db, Doc#doc.id)) |
| end, |
| Docs1 |
| ), |
| |
| Docs2 = [doc(10), doc(10), doc(9000), doc(10)], |
| |
| ?assertMatch({ok, [_ | _]}, fabric2_db:update_docs(Db, Docs2, Opts)), |
| |
| lists:foreach( |
| fun(#doc{} = Doc) -> |
| ?assertMatch({ok, #doc{}}, fabric2_db:open_doc(Db, Doc#doc.id)) |
| end, |
| Docs2 |
| ). |
| |
| update_docs_replicated_batches(Db) -> |
| Opts = [{batch_size, 5000}, replicated_changes], |
| |
| Docs1 = [doc(Size, {1, [rev()]}) || Size <- [9000, 9000]], |
| |
| ?assertMatch({ok, []}, fabric2_db:update_docs(Db, Docs1, Opts)), |
| |
| lists:foreach( |
| fun(#doc{} = Doc) -> |
| ?assertEqual({ok, Doc}, fabric2_db:open_doc(Db, Doc#doc.id)) |
| end, |
| Docs1 |
| ), |
| |
| Docs2 = [doc(Size, {1, [rev()]}) || Size <- [10, 10, 9000, 10]], |
| |
| ?assertMatch({ok, []}, fabric2_db:update_docs(Db, Docs2, Opts)), |
| |
| lists:foreach( |
| fun(#doc{} = Doc) -> |
| ?assertEqual({ok, Doc}, fabric2_db:open_doc(Db, Doc#doc.id)) |
| end, |
| Docs2 |
| ). |
| |
| update_docs_duplicate_ids_conflict(Db) -> |
| Doc = doc(), |
| |
| Res = fabric2_db:update_docs(Db, [Doc, doc(), Doc]), |
| ?assertMatch({ok, [_, _, _]}, Res), |
| |
| {ok, [Doc1Res, Doc2Res, Doc3Res]} = Res, |
| ?assertMatch({ok, {1, <<_/binary>>}}, Doc1Res), |
| ?assertMatch({ok, {1, <<_/binary>>}}, Doc2Res), |
| ?assertMatch(conflict, Doc3Res). |
| |
| update_docs_duplicate_ids_with_batches(Db) -> |
| Opts = [{batch_size, 5000}], |
| |
| Doc = doc(9000), |
| |
| Res = fabric2_db:update_docs(Db, [Doc, doc(9000), Doc], Opts), |
| ?assertMatch({ok, [_, _, _]}, Res), |
| |
| {ok, [Doc1Res, Doc2Res, Doc3Res]} = Res, |
| ?assertMatch({ok, {1, <<_/binary>>}}, Doc1Res), |
| ?assertMatch({ok, {1, <<_/binary>>}}, Doc2Res), |
| ?assertMatch(conflict, Doc3Res). |
| |
| update_docs_replicate_batches_duplicate_id(Db) -> |
| Opts = [replicated_changes], |
| |
| Doc = doc(10, {1, [rev()]}), |
| Docs = [Doc, Doc], |
| |
| ?assertMatch({ok, []}, fabric2_db:update_docs(Db, Docs, Opts)), |
| |
| ?assertEqual({ok, Doc}, fabric2_db:open_doc(Db, Doc#doc.id)). |
| |
| % Utility functions |
| |
| doc() -> |
| doc(2). |
| |
| doc(Size) -> |
| doc(Size, undefined). |
| |
| doc(Size, Revs) -> |
| Doc = #doc{ |
| id = fabric2_util:uuid(), |
| body = doc_body(Size) |
| }, |
| case Revs of |
| undefined -> Doc; |
| _ -> Doc#doc{revs = Revs} |
| end. |
| |
| rev() -> |
| fabric2_util:to_hex(crypto:strong_rand_bytes(16)). |
| |
| doc_body(Size) when is_integer(Size), Size >= 2 -> |
| Val = fabric2_util:to_hex(crypto:strong_rand_bytes(Size div 2)), |
| {[{<<"x">>, Val}]}. |