summaryrefslogtreecommitdiff
path: root/src/couch_index/test/eunit/couch_index_compaction_tests.erl
blob: 53316d944ae6bf8759e2046b49b4248412e051dc (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
104
105
106
% 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_index_compaction_tests).

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

-define(WAIT_TIMEOUT, 1000).

setup() ->
    DbName = ?tempdb(),
    {ok, Db} = couch_db:create(DbName, [?ADMIN_CTX]),
    couch_db:close(Db),
    fake_index(DbName),
    {ok, IndexerPid} = couch_index_server:get_index(test_index, Db, undefined),
    ?assertNot(is_opened(Db)),
    {Db, IndexerPid}.

fake_index(DbName) ->
    ok = meck:new([test_index], [non_strict]),
    ok = meck:expect(test_index, init, ['_', '_'], {ok, 10}),
    ok = meck:expect(test_index, open, fun(_Db, State) ->
        {ok, State}
    end),
    ok = meck:expect(test_index, compact, ['_', '_', '_'],
        meck:seq([{ok, 9}, {ok, 10}])), %% to trigger recompaction
    ok = meck:expect(test_index, commit, ['_'], ok),
    ok = meck:expect(test_index, get, fun
        (db_name, _) ->
            DbName;
        (idx_name, _) ->
            <<"idx_name">>;
        (signature, _) ->
            <<61,237,157,230,136,93,96,201,204,17,137,186,50,249,44,135>>;
        (update_seq, Seq) ->
            Seq
    end),
    ok = meck:expect(test_index, close, ['_'], ok),
    ok = meck:expect(test_index, swap_compacted, fun(_, NewState) ->
        {ok, NewState}
    end).

teardown(_) ->
    meck:unload(test_index).

compaction_test_() ->
    {
        "Check compaction",
        {
            setup,
            fun() -> test_util:start_couch([]) end, fun test_util:stop_couch/1,
            {
                foreach,
                fun setup/0, fun teardown/1,
                [
                    fun hold_db_for_recompaction/1
                ]
            }
        }
    }.


hold_db_for_recompaction({Db, Idx}) ->
    ?_test(begin
        ?assertNot(is_opened(Db)),
        ok = meck:reset(test_index),
        {ok, Monitor} = couch_index:compact(Idx, [monitor]),

        %% we expect Mod:commit/1 to be called twice
        %% once for compact and once for recompact
        meck:wait(2, test_index, commit, ['_'], 5000),
        ?assertEqual(1, meck:num_calls(test_index, compact, ['_', '_', []])),
        ?assertEqual(1, meck:num_calls(test_index, compact, ['_', '_', [recompact]])),

        %% wait compaction finish
        receive
            {'DOWN', Monitor, _, _, _} -> ok
        after 5000 ->
            throw(timeout)
        end,

        ?assertEqual(ok, wait_db_close(Db)),
        ok
    end).

wait_db_close(Db) ->
    test_util:wait(fun() ->
        case is_opened(Db) of
            false -> ok;
            true -> wait
        end
    end, ?WAIT_TIMEOUT).

is_opened(Db) ->
    Monitors = [M || M <- couch_db:monitored_by(Db), M =/= self()],
    Monitors /= [].