summaryrefslogtreecommitdiff
path: root/src/couch/test/eunit/couch_util_tests.erl
diff options
context:
space:
mode:
Diffstat (limited to 'src/couch/test/eunit/couch_util_tests.erl')
-rw-r--r--src/couch/test/eunit/couch_util_tests.erl170
1 files changed, 170 insertions, 0 deletions
diff --git a/src/couch/test/eunit/couch_util_tests.erl b/src/couch/test/eunit/couch_util_tests.erl
new file mode 100644
index 000000000..3e145c4f6
--- /dev/null
+++ b/src/couch/test/eunit/couch_util_tests.erl
@@ -0,0 +1,170 @@
+% 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)),
+ _ = 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>>))
+ ].