diff options
Diffstat (limited to 'src/couch/test/eunit/couchdb_update_conflicts_tests.erl')
-rw-r--r-- | src/couch/test/eunit/couchdb_update_conflicts_tests.erl | 280 |
1 files changed, 0 insertions, 280 deletions
diff --git a/src/couch/test/eunit/couchdb_update_conflicts_tests.erl b/src/couch/test/eunit/couchdb_update_conflicts_tests.erl deleted file mode 100644 index 1329aba27..000000000 --- a/src/couch/test/eunit/couchdb_update_conflicts_tests.erl +++ /dev/null @@ -1,280 +0,0 @@ -% 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(couchdb_update_conflicts_tests). - --include_lib("couch/include/couch_eunit.hrl"). --include_lib("couch/include/couch_db.hrl"). - --define(i2l(I), integer_to_list(I)). --define(DOC_ID, <<"foobar">>). --define(LOCAL_DOC_ID, <<"_local/foobar">>). --define(NUM_CLIENTS, [100, 500, 1000, 2000, 5000, 10000]). --define(TIMEOUT, 20000). - -start() -> - test_util:start_couch(). - - -setup() -> - DbName = ?tempdb(), - {ok, Db} = couch_db:create(DbName, [?ADMIN_CTX, overwrite]), - Doc = couch_doc:from_json_obj({[{<<"_id">>, ?DOC_ID}, - {<<"value">>, 0}]}), - {ok, Rev} = couch_db:update_doc(Db, Doc, []), - ok = couch_db:close(Db), - RevStr = couch_doc:rev_to_str(Rev), - {DbName, RevStr}. -setup(_) -> - setup(). - -teardown({DbName, _}) -> - ok = couch_server:delete(DbName, []), - ok. -teardown(_, {DbName, _RevStr}) -> - teardown({DbName, _RevStr}). - - -view_indexes_cleanup_test_() -> - { - "Update conflicts", - { - setup, - fun start/0, fun test_util:stop_couch/1, - [ - concurrent_updates(), - bulk_docs_updates() - ] - } - }. - -concurrent_updates()-> - { - "Concurrent updates", - { - foreachx, - fun setup/1, fun teardown/2, - [{NumClients, fun should_concurrently_update_doc/2} - || NumClients <- ?NUM_CLIENTS] - } - }. - -bulk_docs_updates()-> - { - "Bulk docs updates", - { - foreach, - fun setup/0, fun teardown/1, - [ - fun should_bulk_create_delete_doc/1, - fun should_bulk_create_local_doc/1, - fun should_ignore_invalid_local_doc/1 - ] - } - }. - - -should_concurrently_update_doc(NumClients, {DbName, InitRev})-> - {?i2l(NumClients) ++ " clients", - {inorder, - [{"update doc", - {timeout, ?TIMEOUT div 1000, - ?_test(concurrent_doc_update(NumClients, DbName, InitRev))}}, - {"ensure in single leaf", - ?_test(ensure_in_single_revision_leaf(DbName))}]}}. - -should_bulk_create_delete_doc({DbName, InitRev})-> - ?_test(bulk_delete_create(DbName, InitRev)). - -should_bulk_create_local_doc({DbName, _})-> - ?_test(bulk_create_local_doc(DbName)). - -should_ignore_invalid_local_doc({DbName, _})-> - ?_test(ignore_invalid_local_doc(DbName)). - - -concurrent_doc_update(NumClients, DbName, InitRev) -> - Clients = lists:map( - fun(Value) -> - ClientDoc = couch_doc:from_json_obj({[ - {<<"_id">>, ?DOC_ID}, - {<<"_rev">>, InitRev}, - {<<"value">>, Value} - ]}), - Pid = spawn_client(DbName, ClientDoc), - {Value, Pid, erlang:monitor(process, Pid)} - end, - lists:seq(1, NumClients)), - - lists:foreach(fun({_, Pid, _}) -> Pid ! go end, Clients), - - {NumConflicts, SavedValue} = lists:foldl( - fun({Value, Pid, MonRef}, {AccConflicts, AccValue}) -> - receive - {'DOWN', MonRef, process, Pid, {ok, _NewRev}} -> - {AccConflicts, Value}; - {'DOWN', MonRef, process, Pid, conflict} -> - {AccConflicts + 1, AccValue}; - {'DOWN', MonRef, process, Pid, Error} -> - erlang:error({assertion_failed, - [{module, ?MODULE}, - {line, ?LINE}, - {reason, "Client " ++ ?i2l(Value) - ++ " got update error: " - ++ couch_util:to_list(Error)}]}) - after ?TIMEOUT div 2 -> - erlang:error({assertion_failed, - [{module, ?MODULE}, - {line, ?LINE}, - {reason, "Timeout waiting for client " - ++ ?i2l(Value) ++ " to die"}]}) - end - end, {0, nil}, Clients), - ?assertEqual(NumClients - 1, NumConflicts), - - {ok, Db} = couch_db:open_int(DbName, []), - {ok, Leaves} = couch_db:open_doc_revs(Db, ?DOC_ID, all, []), - ok = couch_db:close(Db), - ?assertEqual(1, length(Leaves)), - - [{ok, Doc2}] = Leaves, - {JsonDoc} = couch_doc:to_json_obj(Doc2, []), - ?assertEqual(SavedValue, couch_util:get_value(<<"value">>, JsonDoc)). - -ensure_in_single_revision_leaf(DbName) -> - {ok, Db} = couch_db:open_int(DbName, []), - {ok, Leaves} = couch_db:open_doc_revs(Db, ?DOC_ID, all, []), - ok = couch_db:close(Db), - [{ok, Doc}] = Leaves, - - %% FIXME: server restart won't work from test side - %% stop(ok), - %% start(), - - {ok, Db2} = couch_db:open_int(DbName, []), - {ok, Leaves2} = couch_db:open_doc_revs(Db2, ?DOC_ID, all, []), - ok = couch_db:close(Db2), - ?assertEqual(1, length(Leaves2)), - - [{ok, Doc2}] = Leaves, - ?assertEqual(Doc, Doc2). - -bulk_delete_create(DbName, InitRev) -> - {ok, Db} = couch_db:open_int(DbName, []), - - DeletedDoc = couch_doc:from_json_obj({[ - {<<"_id">>, ?DOC_ID}, - {<<"_rev">>, InitRev}, - {<<"_deleted">>, true} - ]}), - NewDoc = couch_doc:from_json_obj({[ - {<<"_id">>, ?DOC_ID}, - {<<"value">>, 666} - ]}), - - {ok, Results} = couch_db:update_docs(Db, [DeletedDoc, NewDoc], []), - ok = couch_db:close(Db), - - ?assertEqual(2, length([ok || {ok, _} <- Results])), - [{ok, Rev1}, {ok, Rev2}] = Results, - - {ok, Db2} = couch_db:open_int(DbName, []), - {ok, [{ok, Doc1}]} = couch_db:open_doc_revs( - Db2, ?DOC_ID, [Rev1], [conflicts, deleted_conflicts]), - {ok, [{ok, Doc2}]} = couch_db:open_doc_revs( - Db2, ?DOC_ID, [Rev2], [conflicts, deleted_conflicts]), - ok = couch_db:close(Db2), - - {Doc1Props} = couch_doc:to_json_obj(Doc1, []), - {Doc2Props} = couch_doc:to_json_obj(Doc2, []), - - %% Document was deleted - ?assert(couch_util:get_value(<<"_deleted">>, Doc1Props)), - %% New document not flagged as deleted - ?assertEqual(undefined, couch_util:get_value(<<"_deleted">>, - Doc2Props)), - %% New leaf revision has the right value - ?assertEqual(666, couch_util:get_value(<<"value">>, - Doc2Props)), - %% Deleted document has no conflicts - ?assertEqual(undefined, couch_util:get_value(<<"_conflicts">>, - Doc1Props)), - %% Deleted document has no deleted conflicts - ?assertEqual(undefined, couch_util:get_value(<<"_deleted_conflicts">>, - Doc1Props)), - %% New leaf revision doesn't have conflicts - ?assertEqual(undefined, couch_util:get_value(<<"_conflicts">>, - Doc1Props)), - %% New leaf revision doesn't have deleted conflicts - ?assertEqual(undefined, couch_util:get_value(<<"_deleted_conflicts">>, - Doc1Props)), - - %% Deleted revision has position 2 - ?assertEqual(2, element(1, Rev1)), - %% New leaf revision has position 3 - ?assertEqual(3, element(1, Rev2)). - - -bulk_create_local_doc(DbName) -> - {ok, Db} = couch_db:open_int(DbName, []), - - LocalDoc = couch_doc:from_json_obj({[ - {<<"_id">>, ?LOCAL_DOC_ID}, - {<<"_rev">>, <<"0-1">>} - ]}), - - {ok, Results} = couch_db:update_docs(Db, [LocalDoc], - [], replicated_changes), - ok = couch_db:close(Db), - ?assertEqual([], Results), - - {ok, Db2} = couch_db:open_int(DbName, []), - {ok, LocalDoc1} = couch_db:open_doc_int(Db2, ?LOCAL_DOC_ID, []), - ok = couch_db:close(Db2), - ?assertEqual(?LOCAL_DOC_ID, LocalDoc1#doc.id), - ?assertEqual({0, [<<"2">>]}, LocalDoc1#doc.revs). - - -ignore_invalid_local_doc(DbName) -> - {ok, Db} = couch_db:open_int(DbName, []), - - LocalDoc = couch_doc:from_json_obj({[ - {<<"_id">>, ?LOCAL_DOC_ID}, - {<<"_rev">>, <<"0-abcdef">>} - ]}), - - {ok, Results} = couch_db:update_docs(Db, [LocalDoc], - [], replicated_changes), - ok = couch_db:close(Db), - ?assertEqual([], Results), - - {ok, Db2} = couch_db:open_int(DbName, []), - Result2 = couch_db:open_doc_int(Db2, ?LOCAL_DOC_ID, []), - ok = couch_db:close(Db2), - ?assertEqual({not_found, missing}, Result2). - - -spawn_client(DbName, Doc) -> - spawn(fun() -> - {ok, Db} = couch_db:open_int(DbName, []), - receive - go -> ok - end, - erlang:yield(), - Result = try - couch_db:update_doc(Db, Doc, []) - catch _:Error -> - Error - end, - ok = couch_db:close(Db), - exit(Result) - end). |