blob: 62ec207755969a11e2493009c1ffbac44f9b9bef [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").
validate_callback_exists_test_() ->
{
"validate_callback_exists tests",
[
fun should_succeed_for_existent_cb/0,
should_fail_for_missing_cb()
]
}.
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)
),
_ = 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(<<>>, couch_util:to_hex_bin(<<>>)),
?_assertEqual(<<"00">>, couch_util:to_hex_bin(<<0>>)),
?_assertEqual(<<"01">>, couch_util:to_hex_bin(<<1>>)),
?_assertEqual("010203faff", couch_util:to_hex([1, 2, 3, 250, 255])),
?_assertEqual(<<"010203faff">>, couch_util:to_hex_bin(<<1, 2, 3, 250, 255>>)),
?_assertEqual("", couch_util:to_hex(<<>>)),
?_assertEqual("010203faff", couch_util:to_hex(<<1, 2, 3, 250, 255>>))
].
to_hex_range_test() ->
lists:foreach(
fun(PrefixSize) ->
lists:foreach(
fun(I) ->
Prefix = list_to_binary(lists:duplicate(PrefixSize, 1)),
Bin = <<Prefix/binary, I:8/integer>>,
?assertEqual(list_to_binary(to_hex_simple(Bin)), couch_util:to_hex_bin(Bin))
end,
lists:seq(0, 16#ff)
)
end,
lists:seq(0, 8)
).
% Use previous implementation from couch_util for validation
%
to_hex_simple(<<Hi:4, Lo:4, Rest/binary>>) ->
[nibble_to_hex(Hi), nibble_to_hex(Lo) | to_hex_simple(Rest)];
to_hex_simple(<<>>) ->
[].
nibble_to_hex(0) -> $0;
nibble_to_hex(1) -> $1;
nibble_to_hex(2) -> $2;
nibble_to_hex(3) -> $3;
nibble_to_hex(4) -> $4;
nibble_to_hex(5) -> $5;
nibble_to_hex(6) -> $6;
nibble_to_hex(7) -> $7;
nibble_to_hex(8) -> $8;
nibble_to_hex(9) -> $9;
nibble_to_hex(10) -> $a;
nibble_to_hex(11) -> $b;
nibble_to_hex(12) -> $c;
nibble_to_hex(13) -> $d;
nibble_to_hex(14) -> $e;
nibble_to_hex(15) -> $f.
json_decode_test_() ->
[
?_assertEqual({[]}, couch_util:json_decode(<<"{}">>)),
?_assertEqual({[]}, couch_util:json_decode(<<"{}">>, [])),
?_assertEqual(#{}, couch_util:json_decode(<<"{}">>, [return_maps]))
].