blob: a0e9238724afc087aed7154c3bde1199e6046cc9 [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_util_tests).
-include_lib("couch/include/couch_eunit.hrl").
setup() ->
%% We cannot start driver from here since it becomes bounded to eunit
%% master process and the next couch_server_sup:start_link call will
%% fail because server couldn't load driver since it already is.
%%
%% On other hand, we cannot unload driver here due to
%% {error, not_loaded_by_this_process} while it is. Any ideas is welcome.
%%
Ctx = test_util:start_couch(),
%% config:start_link(?CONFIG_CHAIN),
%% {ok, _} = couch_drv:start_link(),
Ctx.
teardown(Ctx) ->
ok = test_util:stop_couch(Ctx),
%% config:stop(),
%% erl_ddll:unload_driver(couch_icu_driver),
ok.
collation_test_() ->
{
"Collation tests",
[
{
setup,
fun setup/0, fun teardown/1,
[
should_collate_ascii(),
should_collate_non_ascii()
]
}
]
}.
validate_callback_exists_test_() ->
{
"validate_callback_exists tests",
[
fun should_succeed_for_existent_cb/0,
should_fail_for_missing_cb()
]
}.
should_collate_ascii() ->
?_assertEqual(1, couch_util:collate(<<"foo">>, <<"bar">>)).
should_collate_non_ascii() ->
?_assertEqual(-1, couch_util:collate(<<"A">>, <<"aa">>)).
to_existed_atom_test() ->
?assert(couch_util:to_existing_atom(true)),
?assertMatch(foo, couch_util:to_existing_atom(<<"foo">>)),
?assertMatch(foobarbaz, couch_util:to_existing_atom("foobarbaz")).
implode_test() ->
?assertEqual([1, 38, 2, 38, 3], couch_util:implode([1, 2, 3], "&")).
trim_test() ->
lists:map(fun(S) -> ?assertEqual("foo", couch_util:trim(S)) end,
[" foo", "foo ", "\tfoo", " foo ", "foo\t", "foo\n", "\nfoo"]).
abs_pathname_test() ->
{ok, Cwd} = file:get_cwd(),
?assertEqual(Cwd ++ "/foo", couch_util:abs_pathname("./foo")).
flush_test() ->
?assertNot(couch_util:should_flush()),
AcquireMem = fun() ->
_IntsToAGazillion = lists:seq(1, 200000),
_LotsOfData = lists:map(fun(_) -> <<"foobar">> end,
lists:seq(1, 500000)),
_BigBin = list_to_binary(_LotsOfData),
%% Allocation 200K tuples puts us above the memory threshold
%% Originally, there should be:
%% ?assertNot(should_flush())
%% however, unlike for etap test, GC collects all allocated bits
%% making this conditions fail. So we have to invert the condition
%% since GC works, cleans the memory and everything is fine.
?assertNot(couch_util:should_flush())
end,
AcquireMem(),
%% Checking to flush invokes GC
?assertNot(couch_util:should_flush()).
verify_test() ->
?assert(couch_util:verify("It4Vooya", "It4Vooya")),
?assertNot(couch_util:verify("It4VooyaX", "It4Vooya")),
?assert(couch_util:verify(<<"ahBase3r">>, <<"ahBase3r">>)),
?assertNot(couch_util:verify(<<"ahBase3rX">>, <<"ahBase3r">>)),
?assertNot(couch_util:verify(nil, <<"ahBase3r">>)).
find_in_binary_test_() ->
Cases = [
{<<"foo">>, <<"foobar">>, {exact, 0}},
{<<"foo">>, <<"foofoo">>, {exact, 0}},
{<<"foo">>, <<"barfoo">>, {exact, 3}},
{<<"foo">>, <<"barfo">>, {partial, 3}},
{<<"f">>, <<"fobarfff">>, {exact, 0}},
{<<"f">>, <<"obarfff">>, {exact, 4}},
{<<"f">>, <<"obarggf">>, {exact, 6}},
{<<"f">>, <<"f">>, {exact, 0}},
{<<"f">>, <<"g">>, not_found},
{<<"foo">>, <<"f">>, {partial, 0}},
{<<"foo">>, <<"g">>, not_found},
{<<"foo">>, <<"">>, not_found},
{<<"fofo">>, <<"foofo">>, {partial, 3}},
{<<"foo">>, <<"gfobarfo">>, {partial, 6}},
{<<"foo">>, <<"gfobarf">>, {partial, 6}},
{<<"foo">>, <<"gfobar">>, not_found},
{<<"fog">>, <<"gbarfogquiz">>, {exact, 4}},
{<<"ggg">>, <<"ggg">>, {exact, 0}},
{<<"ggg">>, <<"ggggg">>, {exact, 0}},
{<<"ggg">>, <<"bggg">>, {exact, 1}},
{<<"ggg">>, <<"bbgg">>, {partial, 2}},
{<<"ggg">>, <<"bbbg">>, {partial, 3}},
{<<"ggg">>, <<"bgbggbggg">>, {exact, 6}},
{<<"ggg">>, <<"bgbggb">>, not_found}
],
lists:map(
fun({Needle, Haystack, Result}) ->
Msg = lists:flatten(io_lib:format("Looking for ~s in ~s",
[Needle, Haystack])),
{Msg, ?_assertMatch(Result,
couch_util:find_in_binary(Needle, Haystack))}
end, Cases).
should_succeed_for_existent_cb() ->
?_assert(couch_util:validate_callback_exists(lists, any, 2)).
should_fail_for_missing_cb() ->
Cases = [
{unknown_module, any, 1},
{erlang, unknown_function, 1},
{erlang, whereis, 100}
],
lists:map(
fun({M, F, A} = MFA) ->
Name = lists:flatten(io_lib:format("~w:~w/~w", [M, F, A])),
{Name, ?_assertThrow(
{error, {undefined_callback, Name, MFA}},
couch_util:validate_callback_exists(M, F, A))}
end, Cases).
to_hex_test_() ->
[
?_assertEqual("", couch_util:to_hex([])),
?_assertEqual("010203faff", couch_util:to_hex([1, 2, 3, 250, 255])),
?_assertEqual("", couch_util:to_hex(<<>>)),
?_assertEqual("010203faff", couch_util:to_hex(<<1, 2, 3, 250, 255>>))
].