358 строки
14 KiB
Erlang
358 строки
14 KiB
Erlang
-module(jid_SUITE).
|
|
|
|
-include_lib("proper/include/proper.hrl").
|
|
-include_lib("eunit/include/eunit.hrl").
|
|
-include_lib("common_test/include/ct.hrl").
|
|
-include("jid.hrl").
|
|
|
|
-export([all/0, groups/0, init_per_suite/1, end_per_suite/1]).
|
|
|
|
-export([
|
|
binary_to_jid_succeeds_with_valid_binaries/1,
|
|
binary_to_jid_fails_with_invalid_binaries/1,
|
|
binary_to_jid_fails_with_empty_binary/1,
|
|
make_jid_fails_on_binaries_that_are_too_long/1,
|
|
make_is_independent_of_the_input_format/1,
|
|
make_noprep_and_make_have_equal_raw_jid/1,
|
|
make_noprep_is_independent_of_the_input_format/1,
|
|
jid_to_lower_fails_if_any_binary_is_invalid/1,
|
|
jid_replace_resource_failes_for_invalid_resource/1,
|
|
nodeprep_fails_with_too_long_username/1,
|
|
nameprep_fails_with_too_long_domain/1,
|
|
resourceprep_fails_with_too_long_resource/1,
|
|
from_binary_fails_with_too_long_input/1,
|
|
nodeprep_fails_with_incorrect_username/1,
|
|
resourceprep_fails_with_incorrect_resource/1,
|
|
nameprep_fails_with_incorrect_domain/1,
|
|
is_nodename_fails_for_empty_binary/1,
|
|
compare_bare_jids/1,
|
|
compare_bare_jids_doesnt_depend_on_the_order/1,
|
|
compare_bare_with_jids_structs_and_bare_jids/1,
|
|
binary_to_bare_equals_binary_and_then_bare/1,
|
|
to_lower_to_bare_equals_to_bare_to_lower/1,
|
|
make_to_lus_equals_to_lower_to_lus/1
|
|
]).
|
|
|
|
-export([
|
|
with_nif_to_binary/1,
|
|
with_nif_from_binary/1
|
|
]).
|
|
|
|
|
|
all() -> [
|
|
{group, common},
|
|
{group, old_comparison}
|
|
].
|
|
|
|
groups() ->
|
|
[
|
|
{common, [parallel], [
|
|
binary_to_jid_succeeds_with_valid_binaries,
|
|
binary_to_jid_fails_with_invalid_binaries,
|
|
binary_to_jid_fails_with_empty_binary,
|
|
make_jid_fails_on_binaries_that_are_too_long,
|
|
make_is_independent_of_the_input_format,
|
|
make_noprep_and_make_have_equal_raw_jid,
|
|
make_noprep_is_independent_of_the_input_format,
|
|
jid_to_lower_fails_if_any_binary_is_invalid,
|
|
jid_replace_resource_failes_for_invalid_resource,
|
|
nodeprep_fails_with_too_long_username,
|
|
nameprep_fails_with_too_long_domain,
|
|
resourceprep_fails_with_too_long_resource,
|
|
from_binary_fails_with_too_long_input,
|
|
nodeprep_fails_with_incorrect_username,
|
|
resourceprep_fails_with_incorrect_resource,
|
|
nameprep_fails_with_incorrect_domain,
|
|
is_nodename_fails_for_empty_binary,
|
|
compare_bare_jids,
|
|
compare_bare_jids_doesnt_depend_on_the_order,
|
|
compare_bare_with_jids_structs_and_bare_jids,
|
|
binary_to_bare_equals_binary_and_then_bare,
|
|
to_lower_to_bare_equals_to_bare_to_lower,
|
|
make_to_lus_equals_to_lower_to_lus
|
|
]},
|
|
{old_comparison, [parallel], [
|
|
with_nif_from_binary,
|
|
with_nif_to_binary
|
|
]}
|
|
].
|
|
|
|
init_per_suite(C) ->
|
|
{ok, _} = application:ensure_all_started(jid),
|
|
C.
|
|
|
|
end_per_suite(C) ->
|
|
C.
|
|
|
|
binary_to_jid_succeeds_with_valid_binaries(_C) ->
|
|
Prop = ?FORALL(BinJid, (jid_gen:jid()),
|
|
(is_record(jid:from_binary(BinJid), jid))),
|
|
run_property(Prop, 200, 1, 100).
|
|
|
|
|
|
binary_to_jid_fails_with_invalid_binaries(_C) ->
|
|
Prop = ?FORALL(BinJid, jid_gen:invalid_jid(),
|
|
error == jid:from_binary(BinJid)),
|
|
run_property(Prop, 200, 1, 100).
|
|
|
|
binary_to_jid_fails_with_empty_binary(_) ->
|
|
error = jid:from_binary(<<>>).
|
|
|
|
make_jid_fails_on_binaries_that_are_too_long(_) ->
|
|
Prop = ?FORALL({U, S, R},
|
|
{jid_gen:username(), jid_gen:domain(), jid_gen:resource()},
|
|
case element_length_is_too_big([U,S,R]) of
|
|
true -> error == jid:make(U,S,R);
|
|
false -> is_record(jid:make(U,S,R), jid)
|
|
end),
|
|
run_property(Prop, 50, 500, 1500).
|
|
|
|
make_is_independent_of_the_input_format(_) ->
|
|
Prop = ?FORALL({U, S, R},
|
|
{jid_gen:username(), jid_gen:domain(), jid_gen:resource()},
|
|
jid:make(U,S,R) == jid:make({U,S,R})),
|
|
run_property(Prop, 100, 1, 500).
|
|
|
|
make_noprep_and_make_have_equal_raw_jid(_) ->
|
|
Prop = ?FORALL({U, S, R},
|
|
{jid_gen:username(), jid_gen:domain(), jid_gen:resource()},
|
|
begin
|
|
#jid{user = U, server = S, resource = R} = jid:make(U, S, R),
|
|
#jid{user = U, server = S, resource = R} = jid:make_noprep(U, S, R),
|
|
true
|
|
end
|
|
),
|
|
run_property(Prop, 10, 1, 500).
|
|
|
|
|
|
make_noprep_is_independent_of_the_input_format(_) ->
|
|
Prop = ?FORALL({U, S, R},
|
|
{jid_gen:username(), jid_gen:domain(), jid_gen:resource()},
|
|
jid:make_noprep(U,S,R) == jid:make_noprep({U,S,R})),
|
|
run_property(Prop, 10, 1, 500).
|
|
|
|
element_length_is_too_big(Els) ->
|
|
lists:any(fun(El) -> size(El) >= 1024 end, Els).
|
|
|
|
jid_to_lower_fails_if_any_binary_is_invalid(_) ->
|
|
Prop = ?FORALL({U, S, R},
|
|
{jid_gen:maybe_valid_username(), jid_gen:maybe_valid_domain(), jid_gen:maybe_valid_resource()},
|
|
case jid:to_lower({U, S, R}) of
|
|
{LU, LS, LR} ->
|
|
jid:nodeprep(U) == LU andalso
|
|
jid:nameprep(S) == LS andalso
|
|
jid:resourceprep(R) == LR;
|
|
error ->
|
|
jid:nodeprep(U) == error orelse
|
|
jid:nameprep(S) == error orelse
|
|
jid:resourceprep(R) == error
|
|
end),
|
|
|
|
run_property(Prop, 150, 1, 42).
|
|
|
|
nodeprep_fails_with_too_long_username(_C) ->
|
|
Prop = ?FORALL(Bin, jid_gen:username(),
|
|
error == jid:nodeprep(Bin)),
|
|
run_property(Prop, 10, 1024, 2048).
|
|
|
|
nameprep_fails_with_too_long_domain(_C) ->
|
|
Prop = ?FORALL(Bin, jid_gen:domain(),
|
|
error == jid:nameprep(Bin)),
|
|
run_property(Prop, 10, 1024, 2048).
|
|
|
|
resourceprep_fails_with_too_long_resource(_C) ->
|
|
Prop = ?FORALL(Bin, jid_gen:resource(),
|
|
error == jid:resourceprep(Bin)),
|
|
run_property(Prop, 10, 1024, 2048).
|
|
|
|
from_binary_fails_with_too_long_input(_C) ->
|
|
Prop = ?FORALL(Bin, jid_gen:jid(),
|
|
error == jid:from_binary(Bin)),
|
|
run_property(Prop, 5, 3071, 5048).
|
|
|
|
jid_replace_resource_failes_for_invalid_resource(_) ->
|
|
Prop = ?FORALL({BinJid, MaybeCorrectRes},
|
|
{jid_gen:bare_jid(), jid_gen:maybe_valid_resource()},
|
|
jid_replace_resource(BinJid, MaybeCorrectRes)),
|
|
run_property(Prop, 100, 1, 42).
|
|
|
|
jid_replace_resource(BinJid, Res) ->
|
|
Jid = jid:from_binary(BinJid),
|
|
Jid2 = jid:replace_resource(Jid, Res),
|
|
check_jid_replace_resource_output(Res, Jid2).
|
|
|
|
check_jid_replace_resource_output(Resource, error) ->
|
|
jid:resourceprep(Resource) == error;
|
|
check_jid_replace_resource_output(Resource, #jid{}) ->
|
|
jid:resourceprep(Resource) =/= error.
|
|
|
|
|
|
nodeprep_fails_with_incorrect_username(_) ->
|
|
Prop = ?FORALL(Bin, jid_gen:invalid_username(),
|
|
error == jid:nodeprep(Bin)),
|
|
run_property(Prop, 100, 1, 500).
|
|
|
|
resourceprep_fails_with_incorrect_resource(_) ->
|
|
Prop = ?FORALL(Bin, jid_gen:invalid_resource(),
|
|
error == jid:resourceprep(Bin)),
|
|
run_property(Prop, 100, 1, 500).
|
|
|
|
nameprep_fails_with_incorrect_domain(_) ->
|
|
Prop = ?FORALL(Bin, jid_gen:invalid_domain(),
|
|
error == jid:nameprep(Bin)),
|
|
run_property(Prop, 100, 1, 500).
|
|
|
|
is_nodename_fails_for_empty_binary(_) ->
|
|
false = jid:is_nodename(<<>>).
|
|
|
|
compare_bare_jids_doesnt_depend_on_the_order(_) ->
|
|
Prop = ?FORALL(Val,
|
|
oneof([
|
|
{jid_gen:username(), jid_gen:domain(), jid_gen:resource()},
|
|
jid_gen:maybe_valid_jid()
|
|
]),
|
|
begin
|
|
{AA, BB} = case Val of
|
|
A when is_tuple(A) -> {A, A};
|
|
X when is_binary(X) -> {jid:from_binary(X), jid:from_binary(X)}
|
|
end,
|
|
equals(jid:are_bare_equal(BB, AA),
|
|
jid:are_bare_equal(AA, BB))
|
|
end),
|
|
run_property(Prop, 200, 1, 100).
|
|
|
|
compare_bare_with_jids_structs_and_bare_jids(_) ->
|
|
Prop = ?FORALL({U, S, R}, {jid_gen:username(), jid_gen:domain(), jid_gen:resource()},
|
|
begin
|
|
AA = {U, S, R},
|
|
BB = jid:make_noprep(U, S, R),
|
|
equals(jid:are_bare_equal(BB, AA),
|
|
jid:are_bare_equal(AA, BB))
|
|
end),
|
|
run_property(Prop, 200, 1, 100).
|
|
|
|
compare_bare_jids(_) ->
|
|
Prop = ?FORALL(Val, oneof([
|
|
{jid_gen:maybe_valid_jid(), jid_gen:maybe_valid_jid()},
|
|
jid_gen:maybe_valid_jid()
|
|
]),
|
|
begin
|
|
{A, B} = case Val of {X, Y} -> {X, Y}; X -> {X, X} end,
|
|
AA = jid:from_binary(A),
|
|
BB = jid:from_binary(B),
|
|
equals(jid:are_equal(jid:to_bare(AA), jid:to_bare(BB)),
|
|
jid:are_bare_equal(AA, BB))
|
|
end),
|
|
run_property(Prop, 200, 1, 100).
|
|
|
|
binary_to_bare_equals_binary_and_then_bare(_) ->
|
|
Prop = ?FORALL(A, jid_gen:maybe_valid_jid(),
|
|
equals(jid:to_bare(jid:from_binary(A)), jid:binary_to_bare(A))),
|
|
run_property(Prop, 200, 1, 100).
|
|
|
|
to_lower_to_bare_equals_to_bare_to_lower(_) ->
|
|
Prop = ?FORALL(JID, oneof([jid_gen:jid_struct(),
|
|
{jid_gen:maybe_valid_username(),
|
|
jid_gen:maybe_valid_domain(),
|
|
jid_gen:resource()}]),
|
|
equals(jid:to_bare(jid:to_lower(JID)),
|
|
jid:to_lower(jid:to_bare(JID)))),
|
|
run_property(Prop, 200, 1, 100).
|
|
|
|
make_to_lus_equals_to_lower_to_lus(_) ->
|
|
Prop = ?FORALL({U, S, R}, {jid_gen:maybe_valid_username(),
|
|
jid_gen:maybe_valid_domain(),
|
|
jid_gen:maybe_valid_resource()},
|
|
equals(jid:to_lus(jid:make(U, S, R)),
|
|
jid:to_lus(jid:to_lower({U, S, R})))),
|
|
run_property(Prop, 200, 1, 100).
|
|
|
|
|
|
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
% Original code kept for documentation purposes
|
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
|
|
with_nif_to_binary(_C) ->
|
|
Prop = ?FORALL(L, jid_gen:jid(), from_binary(L) =:= jid:from_binary(L)),
|
|
run_property(Prop, 100, 1, 42).
|
|
|
|
with_nif_from_binary(_C) ->
|
|
Prop = ?FORALL(L, jid_gen:from_jid(), to_binary(L) =:= jid:to_binary(L)),
|
|
run_property(Prop, 100, 1, 42).
|
|
|
|
% Some property based testing to check for equivalence
|
|
% Original code
|
|
-spec from_binary(binary()) -> error | jid:jid().
|
|
from_binary(J) ->
|
|
binary_to_jid1(J, []).
|
|
|
|
-spec binary_to_jid1(binary(), [byte()]) -> 'error' | jid:jid().
|
|
binary_to_jid1(<<$@, _J/binary>>, []) ->
|
|
error;
|
|
binary_to_jid1(<<$@, J/binary>>, N) ->
|
|
binary_to_jid2(J, lists:reverse(N), []);
|
|
binary_to_jid1(<<$/, _J/binary>>, []) ->
|
|
error;
|
|
binary_to_jid1(<<$/, J/binary>>, N) ->
|
|
binary_to_jid3(J, [], lists:reverse(N), []);
|
|
binary_to_jid1(<<C, J/binary>>, N) ->
|
|
binary_to_jid1(J, [C | N]);
|
|
binary_to_jid1(<<>>, []) ->
|
|
error;
|
|
binary_to_jid1(<<>>, N) ->
|
|
jid:make(<<>>, list_to_binary(lists:reverse(N)), <<>>).
|
|
|
|
%% @doc Only one "@" is admitted per JID
|
|
-spec binary_to_jid2(binary(), [byte()], [byte()]) -> 'error' | jid:jid().
|
|
binary_to_jid2(<<$@, _J/binary>>, _N, _S) ->
|
|
error;
|
|
binary_to_jid2(<<$/, _J/binary>>, _N, []) ->
|
|
error;
|
|
binary_to_jid2(<<$/, J/binary>>, N, S) ->
|
|
binary_to_jid3(J, N, lists:reverse(S), []);
|
|
binary_to_jid2(<<C, J/binary>>, N, S) ->
|
|
binary_to_jid2(J, N, [C | S]);
|
|
binary_to_jid2(<<>>, _N, []) ->
|
|
error;
|
|
binary_to_jid2(<<>>, N, S) ->
|
|
jid:make(list_to_binary(N), list_to_binary(lists:reverse(S)), <<>>).
|
|
|
|
-spec binary_to_jid3(binary(), [byte()], [byte()], [byte()]) -> 'error' | jid:jid().
|
|
binary_to_jid3(<<C, J/binary>>, N, S, R) ->
|
|
binary_to_jid3(J, N, S, [C | R]);
|
|
binary_to_jid3(<<>>, N, S, R) ->
|
|
jid:make(list_to_binary(N), list_to_binary(S), list_to_binary(lists:reverse(R))).
|
|
|
|
-spec to_binary(jid:simple_jid() | jid:simple_bare_jid() | jid:jid()) -> binary().
|
|
to_binary(Jid) when is_binary(Jid) ->
|
|
% sometimes it is used to format error messages
|
|
Jid;
|
|
to_binary(#jid{user = User, server = Server, resource = Resource}) ->
|
|
to_binary({User, Server, Resource});
|
|
to_binary({User, Server}) ->
|
|
to_binary({User, Server, <<>>});
|
|
to_binary({Node, Server, Resource}) ->
|
|
S1 = case Node of
|
|
<<>> ->
|
|
<<>>;
|
|
_ ->
|
|
<<Node/binary, "@">>
|
|
end,
|
|
S2 = <<S1/binary, Server/binary>>,
|
|
S3 = case Resource of
|
|
<<>> ->
|
|
S2;
|
|
_ ->
|
|
<<S2/binary, "/", Resource/binary>>
|
|
end,
|
|
S3.
|
|
|
|
|
|
%% HELPERS
|
|
run_property(Prop, NumTest, StartSize, StopSize) ->
|
|
?assert(proper:quickcheck(Prop, [verbose, long_result,
|
|
{numtests, NumTest},
|
|
{start_size, StartSize},
|
|
{max_size, StopSize}])).
|