blob: ab493a9696000c3dcabdd5d461934a101fa68358 [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_index_compaction_tests).
-include_lib("couch/include/couch_eunit.hrl").
-include_lib("couch/include/couch_db.hrl").
-define(WAIT_TIMEOUT, 1000).
setup_all() ->
Ctx = test_util:start_couch(),
meck:new([test_index], [non_strict]),
Ctx.
teardown_all(Ctx) ->
meck:unload(),
test_util:stop_couch(Ctx).
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: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(_) ->
ok.
compaction_test_() ->
{
"Check compaction",
{
setup,
fun setup_all/0,
fun teardown_all/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 /= [].