blob: b7e97b41b1d326c5ee1eec976193e98ffbfa954b [file] [log] [blame]
% 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_ref_counter_tests).
-include("couch_eunit.hrl").
-include_lib("couchdb/couch_db.hrl").
-define(TIMEOUT, 1000).
setup() ->
{ok, RefCtr} = couch_ref_counter:start([]),
ChildPid = spawn(fun() -> loop() end),
{RefCtr, ChildPid}.
teardown({_, ChildPid}) ->
erlang:monitor(process, ChildPid),
ChildPid ! close,
wait().
couch_ref_counter_test_() ->
{
"CouchDB reference counter tests",
{
foreach,
fun setup/0, fun teardown/1,
[
fun should_initialize_with_calling_process_as_referrer/1,
fun should_ignore_unknown_pid/1,
fun should_increment_counter_on_pid_add/1,
fun should_not_increase_counter_on_readding_same_pid/1,
fun should_drop_ref_for_double_added_pid/1,
fun should_decrement_counter_on_pid_drop/1,
fun should_add_after_drop/1,
fun should_decrement_counter_on_process_exit/1
]
}
}.
should_initialize_with_calling_process_as_referrer({RefCtr, _}) ->
?_assertEqual(1, couch_ref_counter:count(RefCtr)).
should_ignore_unknown_pid({RefCtr, ChildPid}) ->
?_assertEqual(ok, couch_ref_counter:drop(RefCtr, ChildPid)).
should_increment_counter_on_pid_add({RefCtr, ChildPid}) ->
couch_ref_counter:add(RefCtr, ChildPid),
?_assertEqual(2, couch_ref_counter:count(RefCtr)).
should_not_increase_counter_on_readding_same_pid({RefCtr, ChildPid}) ->
couch_ref_counter:add(RefCtr, ChildPid),
couch_ref_counter:add(RefCtr, ChildPid),
?_assertEqual(2, couch_ref_counter:count(RefCtr)).
should_drop_ref_for_double_added_pid({RefCtr, ChildPid}) ->
couch_ref_counter:add(RefCtr, ChildPid),
couch_ref_counter:add(RefCtr, ChildPid),
couch_ref_counter:drop(RefCtr, ChildPid),
?_assertEqual(2, couch_ref_counter:count(RefCtr)).
should_decrement_counter_on_pid_drop({RefCtr, ChildPid}) ->
couch_ref_counter:add(RefCtr, ChildPid),
couch_ref_counter:drop(RefCtr, ChildPid),
?_assertEqual(1, couch_ref_counter:count(RefCtr)).
should_add_after_drop({RefCtr, ChildPid}) ->
couch_ref_counter:add(RefCtr, ChildPid),
couch_ref_counter:drop(RefCtr, ChildPid),
couch_ref_counter:add(RefCtr, ChildPid),
?_assertEqual(2, couch_ref_counter:count(RefCtr)).
should_decrement_counter_on_process_exit({RefCtr, ChildPid}) ->
?_assertEqual(1,
begin
couch_ref_counter:add(RefCtr, ChildPid),
erlang:monitor(process, ChildPid),
ChildPid ! close,
wait(),
couch_ref_counter:count(RefCtr)
end).
loop() ->
receive
close -> ok
end.
wait() ->
receive
{'DOWN', _, _, _, _} ->
ok
after ?TIMEOUT ->
throw(timeout_error)
end.