summaryrefslogtreecommitdiff
path: root/src/couch_replicator/test/eunit/couch_replicator_retain_stats_between_job_runs.erl
diff options
context:
space:
mode:
Diffstat (limited to 'src/couch_replicator/test/eunit/couch_replicator_retain_stats_between_job_runs.erl')
-rw-r--r--src/couch_replicator/test/eunit/couch_replicator_retain_stats_between_job_runs.erl160
1 files changed, 160 insertions, 0 deletions
diff --git a/src/couch_replicator/test/eunit/couch_replicator_retain_stats_between_job_runs.erl b/src/couch_replicator/test/eunit/couch_replicator_retain_stats_between_job_runs.erl
new file mode 100644
index 000000000..3b7377b78
--- /dev/null
+++ b/src/couch_replicator/test/eunit/couch_replicator_retain_stats_between_job_runs.erl
@@ -0,0 +1,160 @@
+% 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(couch_replicator_retain_stats_between_job_runs).
+
+-include_lib("couch/include/couch_eunit.hrl").
+-include_lib("couch/include/couch_db.hrl").
+-include_lib("couch_replicator/src/couch_replicator.hrl").
+
+-define(DELAY, 500).
+-define(TIMEOUT, 60000).
+-define(i2l(I), integer_to_list(I)).
+-define(io2b(Io), iolist_to_binary(Io)).
+
+
+setup() ->
+ Ctx = test_util:start_couch([couch_replicator]),
+ Source = setup_db(),
+ Target = setup_db(),
+ {Ctx, {Source, Target}}.
+
+
+teardown({Ctx, {Source, Target}}) ->
+ teardown_db(Source),
+ teardown_db(Target),
+ ok = application:stop(couch_replicator),
+ ok = test_util:stop_couch(Ctx).
+
+
+stats_retained_test_() ->
+ {
+ setup,
+ fun setup/0,
+ fun teardown/1,
+ fun t_stats_retained/1
+ }.
+
+
+t_stats_retained({_Ctx, {Source, Target}}) ->
+ ?_test(begin
+ populate_db(Source, 42),
+ {ok, RepPid, RepId} = replicate(Source, Target),
+ wait_target_in_sync(Source, Target),
+ check_active_tasks(42, 42),
+ reschedule_job(RepPid),
+ check_active_tasks(42, 42),
+ couch_replicator_scheduler:remove_job(RepId)
+ end).
+
+
+setup_db() ->
+ DbName = ?tempdb(),
+ {ok, Db} = couch_db:create(DbName, [?ADMIN_CTX]),
+ ok = couch_db:close(Db),
+ DbName.
+
+
+teardown_db(DbName) ->
+ ok = couch_server:delete(DbName, [?ADMIN_CTX]),
+ ok.
+
+
+reschedule_job(RepPid) ->
+ Ref = erlang:monitor(process, RepPid),
+ gen_server:cast(couch_replicator_scheduler, {set_max_jobs, 0}),
+ couch_replicator_scheduler:reschedule(),
+ receive
+ {'DOWN', Ref, _, _, _} -> ok
+ after ?TIMEOUT ->
+ erlang:error(timeout)
+ end,
+ gen_server:cast(couch_replicator_scheduler, {set_max_jobs, 500}),
+ couch_replicator_scheduler:reschedule().
+
+
+check_active_tasks(DocsRead, DocsWritten) ->
+ RepTask = wait_for_task_status(),
+ ?assertNotEqual(timeout, RepTask),
+ ?assertEqual(DocsRead, couch_util:get_value(docs_read, RepTask)),
+ ?assertEqual(DocsWritten, couch_util:get_value(docs_written, RepTask)).
+
+
+replication_tasks() ->
+ lists:filter(fun(P) ->
+ couch_util:get_value(type, P) =:= replication
+ end, couch_task_status:all()).
+
+
+wait_for_task_status() ->
+ test_util:wait(fun() ->
+ case replication_tasks() of
+ [] -> wait;
+ [RepTask] -> RepTask
+ end
+ end).
+
+
+populate_db(DbName, DocCount) ->
+ {ok, Db} = couch_db:open_int(DbName, []),
+ Docs = lists:foldl(
+ fun(DocIdCounter, Acc) ->
+ Id = ?io2b(["doc", ?i2l(DocIdCounter)]),
+ Doc = #doc{id = Id, body = {[]}},
+ [Doc | Acc]
+ end,
+ [], lists:seq(1, DocCount)),
+ {ok, _} = couch_db:update_docs(Db, Docs, []),
+ ok = couch_db:close(Db).
+
+
+wait_target_in_sync(Source, Target) ->
+ {ok, SourceDb} = couch_db:open_int(Source, []),
+ {ok, SourceInfo} = couch_db:get_db_info(SourceDb),
+ ok = couch_db:close(SourceDb),
+ SourceDocCount = couch_util:get_value(doc_count, SourceInfo),
+ wait_target_in_sync_loop(SourceDocCount, Target, 300).
+
+
+wait_target_in_sync_loop(_DocCount, _TargetName, 0) ->
+ erlang:error({assertion_failed, [
+ {module, ?MODULE}, {line, ?LINE},
+ {reason, "Could not get source and target databases in sync"}
+ ]});
+
+wait_target_in_sync_loop(DocCount, TargetName, RetriesLeft) ->
+ {ok, Target} = couch_db:open_int(TargetName, []),
+ {ok, TargetInfo} = couch_db:get_db_info(Target),
+ ok = couch_db:close(Target),
+ TargetDocCount = couch_util:get_value(doc_count, TargetInfo),
+ case TargetDocCount == DocCount of
+ true ->
+ true;
+ false ->
+ ok = timer:sleep(?DELAY),
+ wait_target_in_sync_loop(DocCount, TargetName, RetriesLeft - 1)
+ end.
+
+
+replicate(Source, Target) ->
+ SrcUrl = couch_replicator_test_helper:db_url(Source),
+ TgtUrl = couch_replicator_test_helper:db_url(Target),
+ RepObject = {[
+ {<<"source">>, SrcUrl},
+ {<<"target">>, TgtUrl},
+ {<<"continuous">>, true}
+ ]},
+ {ok, Rep} = couch_replicator_utils:parse_rep_doc(RepObject, ?ADMIN_USER),
+ ok = couch_replicator_scheduler:add_job(Rep),
+ couch_replicator_scheduler:reschedule(),
+ Pid = couch_replicator_test_helper:get_pid(Rep#rep.id),
+ {ok, Pid, Rep#rep.id}.