summaryrefslogtreecommitdiff
path: root/src/couch/src/test_engine_ref_counting.erl
blob: 18e75fb5ac960b3ae583217e1008a4656a09ab4f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
% 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(test_engine_ref_counting).
-compile(export_all).


-include_lib("eunit/include/eunit.hrl").
-include_lib("couch/include/couch_db.hrl").


-define(NUM_CLIENTS, 1000).


cet_empty_monitors() ->
    {ok, Engine, St} = test_engine_util:init_engine(),
    Pids = Engine:monitored_by(St),
    ?assert(is_list(Pids)),
    ?assertEqual([], Pids -- [self(), whereis(couch_stats_process_tracker)]).


cet_incref_decref() ->
    {ok, Engine, St} = test_engine_util:init_engine(),

    {Pid, _} = Client = start_client(Engine, St),
    wait_client(Client),

    Pids1 = Engine:monitored_by(St),
    ?assert(lists:member(Pid, Pids1)),

    close_client(Client),

    Pids2 = Engine:monitored_by(St),
    ?assert(not lists:member(Pid, Pids2)).


cet_incref_decref_many() ->
    {ok, Engine, St} = test_engine_util:init_engine(),
    Clients = lists:map(fun(_) ->
        start_client(Engine, St)
    end, lists:seq(1, ?NUM_CLIENTS)),

    lists:foreach(fun(C) -> wait_client(C) end, Clients),

    Pids1 = Engine:monitored_by(St),
    % +2 for db pid and process tracker
    ?assertEqual(?NUM_CLIENTS + 2, length(Pids1)),

    lists:foreach(fun(C) -> close_client(C) end, Clients),

    Pids2 = Engine:monitored_by(St),
    ?assertEqual(2, length(Pids2)).


start_client(Engine, St1) ->
    spawn_monitor(fun() ->
        {ok, St2} = Engine:incref(St1),

        receive
            {waiting, Pid} ->
                Pid ! go
        after 1000 ->
            erlang:error(timeout)
        end,

        receive
            close ->
                ok
        after 1000 ->
            erlang:error(timeout)
        end,

        Engine:decref(St2)
    end).


wait_client({Pid, _Ref}) ->
    Pid ! {waiting, self()},
    receive
        go -> ok
    after 1000 ->
        erlang:error(timeout)
    end.


close_client({Pid, Ref}) ->
    Pid ! close,
    receive
        {'DOWN', Ref, _, _, _} ->
            ok
    after 1000 ->
        erlang:error(timeout)
    end.