diff options
Diffstat (limited to 'lib/dialyzer/test/small_SUITE_data/src')
12 files changed, 854 insertions, 3 deletions
diff --git a/lib/dialyzer/test/small_SUITE_data/src/binary_lc_bug.erl b/lib/dialyzer/test/small_SUITE_data/src/binary_lc_bug.erl new file mode 100644 index 0000000000..c1e82bfa59 --- /dev/null +++ b/lib/dialyzer/test/small_SUITE_data/src/binary_lc_bug.erl @@ -0,0 +1,8 @@ +-module(test). + +-export([bin_compr/0]). + +bin_compr() -> +% [ 0 || {N, V} <- [{a, b}] ]. % Works ok + << <<>> || {A, B} <- [{a, b}] >>. % Complains +% << <<>> || X <- [{a, b}] >>. % Works ok diff --git a/lib/dialyzer/test/small_SUITE_data/src/codec_can.erl b/lib/dialyzer/test/small_SUITE_data/src/codec_can.erl new file mode 100644 index 0000000000..8abf872b37 --- /dev/null +++ b/lib/dialyzer/test/small_SUITE_data/src/codec_can.erl @@ -0,0 +1,35 @@ +%%--------------------------------------------------------------------- +%% From: Peer Stritzinger +%% Date: 1 May 2011 +%% Subject: Dialyzer v2.2.0 crash +%% +%% Binaries of the form <<_:N,_:_*M>> in specs resulted in a crash: +%% dialyzer: Analysis failed with error: {{case_clause,8}, +%% [{erl_types,t_form_to_string,1}, +%% {erl_types,t_form_to_string,1}, +%% {dialyzer_contracts,contract_to_string_1,1}, +%% {dialyzer_contracts,extra_contract_warning,6}, +%% {dialyzer_contracts,picky_contract_check,7}, +%% because function erl_types:t_form_to_string/1 was not the inverse +%% of erl_types:t_to_string/2. +%% +%% Fixed on the same date and send to OTP for inclusion. +%%--------------------------------------------------------------------- +-module(codec_can). + +-export([recv/3, decode/1]). + +-record(can_pkt, {id, data :: binary(), timestamp}). + +-type can_pkt() :: #can_pkt{}. +-type channel() :: atom() | pid() | {atom(),_}. + +-spec recv(<<_:64,_:_*8>>, fun((can_pkt()) -> R), channel()) -> R. +recv(Packet, Fun, Chan) -> + #can_pkt{id = Can_id, data = Can_data} = P = decode(Packet), + Fun(P). + +-spec decode(<<_:64,_:_*8>>) -> #can_pkt{id::<<_:11>>,timestamp::char()}. +decode(<<_:12, Len:4, Timestamp:16, 0:3, Id:11/bitstring, 0:18, + Data:Len/binary, _/binary>>) -> + #can_pkt{id = Id, data = Data, timestamp = Timestamp}. diff --git a/lib/dialyzer/test/small_SUITE_data/src/common_eunit.erl b/lib/dialyzer/test/small_SUITE_data/src/common_eunit.erl new file mode 100644 index 0000000000..bca390068e --- /dev/null +++ b/lib/dialyzer/test/small_SUITE_data/src/common_eunit.erl @@ -0,0 +1,121 @@ +%%===================================================================== +%% Program with an erroneous type declaration that caused dialyzer to +%% go into an infinite loop. There are some comments that explain the +%% symptoms and the culprit: the return of test_fun() is erroneous and +%% its type should read +%% fun((config()) -> test_rep() | [test_rep()]) +%% instead. But this should not throw dialyzer into an infinite loop. +%% This concerned dialyzer in R14B02 (and probably prior). +%%===================================================================== +-module(common_eunit). + +-export([expand_cases/2]). + +-type test_name() :: atom() | {'group', atom()}. + +-type test_rep() :: {{atom(), atom(), arity()}, fun()} + | {'setup', fun(), fun()} + | {'setup', fun(), fun(), fun()} + | {atom(), test_rep()} + | {atom(), term(), test_rep()}. + +-type config() :: [proplists:property()]. + +-type control() :: tuple() | atom(). + +%% The combination of the following type and the (erroneous) spec for +%% expand_cases/2 is the reason for the infinite loop in dialyzer. +-type test_fun() :: fun((config()) -> test_rep()). + +%% If one comments out this spec the infinite loop disappears. +-spec expand_cases(atom(), test_name() | [test_name()]) -> test_fun(). +expand_cases(Module, Cases) -> + if is_list(Cases) -> + TestFuns = [expand_case(Module, Case) || Case <- Cases], + fun(Config) -> [F(Config) || F <- TestFuns] end; + is_atom(Cases); is_tuple(Cases) -> + expand_cases(Module, [Cases]) + end. + +-spec expand_case(atom(), test_name()) -> test_fun(). +expand_case(Module, CaseName) when is_atom(CaseName) -> + TestFun = fun(Config) -> + {{Module, CaseName, 1}, + fun() -> apply(Module, CaseName, [Config]) end} + end, + setup_wrapper(Module, TestFun, {init_per_testcase, [CaseName]}, + {end_per_testcase, [CaseName]}); +expand_case(Module, {group, GroupName}) -> + {Control, Cases} = group_specification(Module, GroupName), + TestFun = control_wrapper(Control, expand_cases(Module, Cases)), + setup_wrapper(Module, TestFun, {init_per_group, [GroupName]}, + {end_per_group, [GroupName]}). + +-spec control_wrapper([control()], test_fun()) -> test_fun(). +control_wrapper([Control|T], TestFun0) -> + TestFun1 = control_wrapper(T, TestFun0), + fun(Config) -> + case Control of + parallel -> + {inparallel, TestFun1(Config)}; + sequence -> + {inorder, TestFun1(Config)}; + {timetrap, Time} -> + Seconds = case Time of + {hours, Hs} -> Hs * 60 * 60; + {minutes, Ms} -> Ms * 60; + {seconds, Ss} -> Ss; + MSs -> MSs / 1000 + end, + {timeout, Seconds, TestFun1(Config)}; + C when is_atom(C) -> + {C, TestFun1(Config)}; + {C, Arg} -> + {C, Arg, TestFun1(Config)} + end + end; +control_wrapper([], TestFun) -> + TestFun. + +-spec setup_wrapper(atom(), test_fun(), Callback, Callback) -> test_fun() + when Callback :: {atom(), list()}. +setup_wrapper(Module, TestFun, {Setup, SA}, {Cleanup, CA}) -> + case erlang:function_exported(Module, Setup, length(SA) + 1) of + true -> + case erlang:function_exported(Module, Cleanup, length(CA) + 1) of + true -> + fun(Config0) -> + {setup, + fun() -> + apply(Module, Setup, SA ++ [Config0]) + end, + fun(Config1) -> + apply(Module, Cleanup, CA ++ [Config1]) + end, + TestFun} + end; + false -> + fun(Config) -> + {setup, + fun() -> + apply(Module, Setup, SA ++ [Config]) + end, + TestFun} + end + end; + false -> + TestFun + end. + +-spec group_specification(atom(), atom()) -> {[control()], [test_name()]}. +group_specification(Module, GroupName) -> + case lists:keyfind(GroupName, 1, Module:groups()) of + {_, Control, Cases} when is_list(Control), is_list(Cases) -> + {Control, Cases}; + {_, Cases} when is_list(Cases) -> + {[], Cases}; + false -> + exit({missing_group, GroupName}); + _ -> + exit({bad_group_spec, GroupName}) + end. diff --git a/lib/dialyzer/test/small_SUITE_data/src/comparisons.erl b/lib/dialyzer/test/small_SUITE_data/src/comparisons.erl new file mode 100644 index 0000000000..70e3cb6af4 --- /dev/null +++ b/lib/dialyzer/test/small_SUITE_data/src/comparisons.erl @@ -0,0 +1,322 @@ +-module(comparisons). + +-compile(export_all). + +-define(r, get(r)). + +integer() -> integer(?r). +integer(X) when is_integer(X) -> X. + +mfloat() -> float(?r). +mfloat(X) when is_float(X) -> X. + +atom() -> atom(?r). +atom(X) when is_atom(X) -> X. + +tuple() -> tuple(?r). +tuple(X) when is_tuple(X) -> X. + +list() -> list(?r). +list(X) when is_list(X) -> X. + +i() -> integer(). +f() -> mfloat(). +n() -> case ?r of 1 -> i(); 2 -> f() end. +a() -> atom(). +t() -> tuple(). +l() -> list(). +na() -> case ?r of 1 -> n(); 2 -> a() end. +at() -> case ?r of 1 -> t(); 2 -> a() end. +tl() -> case ?r of 1 -> t(); 2 -> l() end. + +test_i_ll_i() -> case i() < i() of true -> maybe; false -> maybe_too end. +test_i_le_i() -> case i() =< i() of true -> maybe; false -> maybe_too end. +test_i_gg_i() -> case i() > i() of true -> maybe; false -> maybe_too end. +test_i_ge_i() -> case i() >= i() of true -> maybe; false -> maybe_too end. +test_i_ll_f() -> case i() < f() of true -> maybe; false -> maybe_too end. +test_i_le_f() -> case i() =< f() of true -> maybe; false -> maybe_too end. +test_i_gg_f() -> case i() > f() of true -> maybe; false -> maybe_too end. +test_i_ge_f() -> case i() >= f() of true -> maybe; false -> maybe_too end. +test_i_ll_n() -> case i() < n() of true -> maybe; false -> maybe_too end. +test_i_le_n() -> case i() =< n() of true -> maybe; false -> maybe_too end. +test_i_gg_n() -> case i() > n() of true -> maybe; false -> maybe_too end. +test_i_ge_n() -> case i() >= n() of true -> maybe; false -> maybe_too end. +test_i_ll_a() -> case i() < a() of true -> always; false -> never end. +test_i_le_a() -> case i() =< a() of true -> always; false -> never end. +test_i_gg_a() -> case i() > a() of true -> never; false -> always end. +test_i_ge_a() -> case i() >= a() of true -> never; false -> always end. +test_i_ll_t() -> case i() < t() of true -> always; false -> never end. +test_i_le_t() -> case i() =< t() of true -> always; false -> never end. +test_i_gg_t() -> case i() > t() of true -> never; false -> always end. +test_i_ge_t() -> case i() >= t() of true -> never; false -> always end. +test_i_ll_l() -> case i() < l() of true -> always; false -> never end. +test_i_le_l() -> case i() =< l() of true -> always; false -> never end. +test_i_gg_l() -> case i() > l() of true -> never; false -> always end. +test_i_ge_l() -> case i() >= l() of true -> never; false -> always end. + +test_f_ll_i() -> case f() < i() of true -> maybe; false -> maybe_too end. +test_f_le_i() -> case f() =< i() of true -> maybe; false -> maybe_too end. +test_f_gg_i() -> case f() > i() of true -> maybe; false -> maybe_too end. +test_f_ge_i() -> case f() >= i() of true -> maybe; false -> maybe_too end. +test_f_ll_f() -> case f() < f() of true -> maybe; false -> maybe_too end. +test_f_le_f() -> case f() =< f() of true -> maybe; false -> maybe_too end. +test_f_gg_f() -> case f() > f() of true -> maybe; false -> maybe_too end. +test_f_ge_f() -> case f() >= f() of true -> maybe; false -> maybe_too end. +test_f_ll_n() -> case f() < n() of true -> maybe; false -> maybe_too end. +test_f_le_n() -> case f() =< n() of true -> maybe; false -> maybe_too end. +test_f_gg_n() -> case f() > n() of true -> maybe; false -> maybe_too end. +test_f_ge_n() -> case f() >= n() of true -> maybe; false -> maybe_too end. +test_f_ll_a() -> case f() < a() of true -> always; false -> never end. +test_f_le_a() -> case f() =< a() of true -> always; false -> never end. +test_f_gg_a() -> case f() > a() of true -> never; false -> always end. +test_f_ge_a() -> case f() >= a() of true -> never; false -> always end. +test_f_ll_t() -> case f() < t() of true -> always; false -> never end. +test_f_le_t() -> case f() =< t() of true -> always; false -> never end. +test_f_gg_t() -> case f() > t() of true -> never; false -> always end. +test_f_ge_t() -> case f() >= t() of true -> never; false -> always end. +test_f_ll_l() -> case f() < l() of true -> always; false -> never end. +test_f_le_l() -> case f() =< l() of true -> always; false -> never end. +test_f_gg_l() -> case f() > l() of true -> never; false -> always end. +test_f_ge_l() -> case f() >= l() of true -> never; false -> always end. + +test_n_ll_i() -> case n() < i() of true -> maybe; false -> maybe_too end. +test_n_le_i() -> case n() =< i() of true -> maybe; false -> maybe_too end. +test_n_gg_i() -> case n() > i() of true -> maybe; false -> maybe_too end. +test_n_ge_i() -> case n() >= i() of true -> maybe; false -> maybe_too end. +test_n_ll_f() -> case n() < f() of true -> maybe; false -> maybe_too end. +test_n_le_f() -> case n() =< f() of true -> maybe; false -> maybe_too end. +test_n_gg_f() -> case n() > f() of true -> maybe; false -> maybe_too end. +test_n_ge_f() -> case n() >= f() of true -> maybe; false -> maybe_too end. +test_n_ll_n() -> case n() < n() of true -> maybe; false -> maybe_too end. +test_n_le_n() -> case n() =< n() of true -> maybe; false -> maybe_too end. +test_n_gg_n() -> case n() > n() of true -> maybe; false -> maybe_too end. +test_n_ge_n() -> case n() >= n() of true -> maybe; false -> maybe_too end. +test_n_ll_a() -> case n() < a() of true -> always; false -> never end. +test_n_le_a() -> case n() =< a() of true -> always; false -> never end. +test_n_gg_a() -> case n() > a() of true -> never; false -> always end. +test_n_ge_a() -> case n() >= a() of true -> never; false -> always end. +test_n_ll_t() -> case n() < t() of true -> always; false -> never end. +test_n_le_t() -> case n() =< t() of true -> always; false -> never end. +test_n_gg_t() -> case n() > t() of true -> never; false -> always end. +test_n_ge_t() -> case n() >= t() of true -> never; false -> always end. +test_n_ll_l() -> case n() < l() of true -> always; false -> never end. +test_n_le_l() -> case n() =< l() of true -> always; false -> never end. +test_n_gg_l() -> case n() > l() of true -> never; false -> always end. +test_n_ge_l() -> case n() >= l() of true -> never; false -> always end. + +test_a_ll_i() -> case a() < i() of true -> never; false -> always end. +test_a_le_i() -> case a() =< i() of true -> never; false -> always end. +test_a_gg_i() -> case a() > i() of true -> always; false -> never end. +test_a_ge_i() -> case a() >= i() of true -> always; false -> never end. +test_a_ll_f() -> case a() < f() of true -> never; false -> always end. +test_a_le_f() -> case a() =< f() of true -> never; false -> always end. +test_a_gg_f() -> case a() > f() of true -> always; false -> never end. +test_a_ge_f() -> case a() >= f() of true -> always; false -> never end. +test_a_ll_n() -> case a() < n() of true -> never; false -> always end. +test_a_le_n() -> case a() =< n() of true -> never; false -> always end. +test_a_gg_n() -> case a() > n() of true -> always; false -> never end. +test_a_ge_n() -> case a() >= n() of true -> always; false -> never end. +test_a_ll_a() -> case a() < a() of true -> maybe; false -> maybe_too end. +test_a_le_a() -> case a() =< a() of true -> maybe; false -> maybe_too end. +test_a_gg_a() -> case a() > a() of true -> maybe; false -> maybe_too end. +test_a_ge_a() -> case a() >= a() of true -> maybe; false -> maybe_too end. +test_a_ll_t() -> case a() < t() of true -> always; false -> never end. +test_a_le_t() -> case a() =< t() of true -> always; false -> never end. +test_a_gg_t() -> case a() > t() of true -> never; false -> always end. +test_a_ge_t() -> case a() >= t() of true -> never; false -> always end. +test_a_ll_l() -> case a() < l() of true -> always; false -> never end. +test_a_le_l() -> case a() =< l() of true -> always; false -> never end. +test_a_gg_l() -> case a() > l() of true -> never; false -> always end. +test_a_ge_l() -> case a() >= l() of true -> never; false -> always end. + +test_t_ll_i() -> case t() < i() of true -> never; false -> always end. +test_t_le_i() -> case t() =< i() of true -> never; false -> always end. +test_t_gg_i() -> case t() > i() of true -> always; false -> never end. +test_t_ge_i() -> case t() >= i() of true -> always; false -> never end. +test_t_ll_f() -> case t() < f() of true -> never; false -> always end. +test_t_le_f() -> case t() =< f() of true -> never; false -> always end. +test_t_gg_f() -> case t() > f() of true -> always; false -> never end. +test_t_ge_f() -> case t() >= f() of true -> always; false -> never end. +test_t_ll_n() -> case t() < n() of true -> never; false -> always end. +test_t_le_n() -> case t() =< n() of true -> never; false -> always end. +test_t_gg_n() -> case t() > n() of true -> always; false -> never end. +test_t_ge_n() -> case t() >= n() of true -> always; false -> never end. +test_t_ll_a() -> case t() < a() of true -> never; false -> always end. +test_t_le_a() -> case t() =< a() of true -> never; false -> always end. +test_t_gg_a() -> case t() > a() of true -> always; false -> never end. +test_t_ge_a() -> case t() >= a() of true -> always; false -> never end. +test_t_ll_t() -> case t() < t() of true -> maybe; false -> maybe_too end. +test_t_le_t() -> case t() =< t() of true -> maybe; false -> maybe_too end. +test_t_gg_t() -> case t() > t() of true -> maybe; false -> maybe_too end. +test_t_ge_t() -> case t() >= t() of true -> maybe; false -> maybe_too end. +test_t_ll_l() -> case t() < l() of true -> always; false -> never end. +test_t_le_l() -> case t() =< l() of true -> always; false -> never end. +test_t_gg_l() -> case t() > l() of true -> never; false -> always end. +test_t_ge_l() -> case t() >= l() of true -> never; false -> always end. + +test_l_ll_i() -> case l() < i() of true -> never; false -> always end. +test_l_le_i() -> case l() =< i() of true -> never; false -> always end. +test_l_gg_i() -> case l() > i() of true -> always; false -> never end. +test_l_ge_i() -> case l() >= i() of true -> always; false -> never end. +test_l_ll_f() -> case l() < f() of true -> never; false -> always end. +test_l_le_f() -> case l() =< f() of true -> never; false -> always end. +test_l_gg_f() -> case l() > f() of true -> always; false -> never end. +test_l_ge_f() -> case l() >= f() of true -> always; false -> never end. +test_l_ll_n() -> case l() < n() of true -> never; false -> always end. +test_l_le_n() -> case l() =< n() of true -> never; false -> always end. +test_l_gg_n() -> case l() > n() of true -> always; false -> never end. +test_l_ge_n() -> case l() >= n() of true -> always; false -> never end. +test_l_ll_a() -> case l() < a() of true -> never; false -> always end. +test_l_le_a() -> case l() =< a() of true -> never; false -> always end. +test_l_gg_a() -> case l() > a() of true -> always; false -> never end. +test_l_ge_a() -> case l() >= a() of true -> always; false -> never end. +test_l_ll_t() -> case l() < t() of true -> never; false -> always end. +test_l_le_t() -> case l() =< t() of true -> never; false -> always end. +test_l_gg_t() -> case l() > t() of true -> always; false -> never end. +test_l_ge_t() -> case l() >= t() of true -> always; false -> never end. +test_l_ll_l() -> case l() < l() of true -> maybe; false -> maybe_too end. +test_l_le_l() -> case l() =< l() of true -> maybe; false -> maybe_too end. +test_l_gg_l() -> case l() > l() of true -> maybe; false -> maybe_too end. +test_l_ge_l() -> case l() >= l() of true -> maybe; false -> maybe_too end. + +test_n_ll_na() -> case n() < na() of true -> maybe; false -> maybe_too end. +test_n_le_na() -> case n() =< na() of true -> maybe; false -> maybe_too end. +test_n_gg_na() -> case n() > na() of true -> maybe; false -> maybe_too end. +test_n_ge_na() -> case n() >= na() of true -> maybe; false -> maybe_too end. +test_n_ll_at() -> case n() < at() of true -> always; false -> never end. +test_n_le_at() -> case n() =< at() of true -> always; false -> never end. +test_n_gg_at() -> case n() > at() of true -> never; false -> always end. +test_n_ge_at() -> case n() >= at() of true -> never; false -> always end. +test_n_ll_tl() -> case n() < tl() of true -> always; false -> never end. +test_n_le_tl() -> case n() =< tl() of true -> always; false -> never end. +test_n_gg_tl() -> case n() > tl() of true -> never; false -> always end. +test_n_ge_tl() -> case n() >= tl() of true -> never; false -> always end. + +test_a_ll_na() -> case a() < na() of true -> maybe; false -> maybe_too end. +test_a_le_na() -> case a() =< na() of true -> maybe; false -> maybe_too end. +test_a_gg_na() -> case a() > na() of true -> maybe; false -> maybe_too end. +test_a_ge_na() -> case a() >= na() of true -> maybe; false -> maybe_too end. +test_a_ll_at() -> case a() < at() of true -> maybe; false -> maybe_too end. +test_a_le_at() -> case a() =< at() of true -> maybe; false -> maybe_too end. +test_a_gg_at() -> case a() > at() of true -> maybe; false -> maybe_too end. +test_a_ge_at() -> case a() >= at() of true -> maybe; false -> maybe_too end. +test_a_ll_tl() -> case a() < tl() of true -> always; false -> never end. +test_a_le_tl() -> case a() =< tl() of true -> always; false -> never end. +test_a_gg_tl() -> case a() > tl() of true -> never; false -> always end. +test_a_ge_tl() -> case a() >= tl() of true -> never; false -> always end. + +test_t_ll_na() -> case t() < na() of true -> never; false -> always end. +test_t_le_na() -> case t() =< na() of true -> never; false -> always end. +test_t_gg_na() -> case t() > na() of true -> always; false -> never end. +test_t_ge_na() -> case t() >= na() of true -> always; false -> never end. +test_t_ll_at() -> case t() < at() of true -> maybe; false -> maybe_too end. +test_t_le_at() -> case t() =< at() of true -> maybe; false -> maybe_too end. +test_t_gg_at() -> case t() > at() of true -> maybe; false -> maybe_too end. +test_t_ge_at() -> case t() >= at() of true -> maybe; false -> maybe_too end. +test_t_ll_tl() -> case t() < tl() of true -> maybe; false -> maybe_too end. +test_t_le_tl() -> case t() =< tl() of true -> maybe; false -> maybe_too end. +test_t_gg_tl() -> case t() > tl() of true -> maybe; false -> maybe_too end. +test_t_ge_tl() -> case t() >= tl() of true -> maybe; false -> maybe_too end. + +test_l_ll_na() -> case l() < na() of true -> never; false -> always end. +test_l_le_na() -> case l() =< na() of true -> never; false -> always end. +test_l_gg_na() -> case l() > na() of true -> always; false -> never end. +test_l_ge_na() -> case l() >= na() of true -> always; false -> never end. +test_l_ll_at() -> case l() < at() of true -> never; false -> always end. +test_l_le_at() -> case l() =< at() of true -> never; false -> always end. +test_l_gg_at() -> case l() > at() of true -> always; false -> never end. +test_l_ge_at() -> case l() >= at() of true -> always; false -> never end. +test_l_ll_tl() -> case l() < tl() of true -> maybe; false -> maybe_too end. +test_l_le_tl() -> case l() =< tl() of true -> maybe; false -> maybe_too end. +test_l_gg_tl() -> case l() > tl() of true -> maybe; false -> maybe_too end. +test_l_ge_tl() -> case l() >= tl() of true -> maybe; false -> maybe_too end. + +test_na_ll_n() -> case na() < n() of true -> maybe; false -> maybe_too end. +test_na_le_n() -> case na() =< n() of true -> maybe; false -> maybe_too end. +test_na_gg_n() -> case na() > n() of true -> maybe; false -> maybe_too end. +test_na_ge_n() -> case na() >= n() of true -> maybe; false -> maybe_too end. +test_na_ll_a() -> case na() < a() of true -> maybe; false -> maybe_too end. +test_na_le_a() -> case na() =< a() of true -> maybe; false -> maybe_too end. +test_na_gg_a() -> case na() > a() of true -> maybe; false -> maybe_too end. +test_na_ge_a() -> case na() >= a() of true -> maybe; false -> maybe_too end. +test_na_ll_t() -> case na() < t() of true -> always; false -> never end. +test_na_le_t() -> case na() =< t() of true -> always; false -> never end. +test_na_gg_t() -> case na() > t() of true -> never; false -> always end. +test_na_ge_t() -> case na() >= t() of true -> never; false -> always end. +test_na_ll_l() -> case na() < l() of true -> always; false -> never end. +test_na_le_l() -> case na() =< l() of true -> always; false -> never end. +test_na_gg_l() -> case na() > l() of true -> never; false -> always end. +test_na_ge_l() -> case na() >= l() of true -> never; false -> always end. + +test_at_ll_n() -> case at() < n() of true -> never; false -> always end. +test_at_le_n() -> case at() =< n() of true -> never; false -> always end. +test_at_gg_n() -> case at() > n() of true -> always; false -> never end. +test_at_ge_n() -> case at() >= n() of true -> always; false -> never end. +test_at_ll_a() -> case at() < a() of true -> maybe; false -> maybe_too end. +test_at_le_a() -> case at() =< a() of true -> maybe; false -> maybe_too end. +test_at_gg_a() -> case at() > a() of true -> maybe; false -> maybe_too end. +test_at_ge_a() -> case at() >= a() of true -> maybe; false -> maybe_too end. +test_at_ll_t() -> case at() < t() of true -> maybe; false -> maybe_too end. +test_at_le_t() -> case at() =< t() of true -> maybe; false -> maybe_too end. +test_at_gg_t() -> case at() > t() of true -> maybe; false -> maybe_too end. +test_at_ge_t() -> case at() >= t() of true -> maybe; false -> maybe_too end. +test_at_ll_l() -> case at() < l() of true -> always; false -> never end. +test_at_le_l() -> case at() =< l() of true -> always; false -> never end. +test_at_gg_l() -> case at() > l() of true -> never; false -> always end. +test_at_ge_l() -> case at() >= l() of true -> never; false -> always end. + +test_tl_ll_n() -> case tl() < n() of true -> never; false -> always end. +test_tl_le_n() -> case tl() =< n() of true -> never; false -> always end. +test_tl_gg_n() -> case tl() > n() of true -> always; false -> never end. +test_tl_ge_n() -> case tl() >= n() of true -> always; false -> never end. +test_tl_ll_a() -> case tl() < a() of true -> never; false -> always end. +test_tl_le_a() -> case tl() =< a() of true -> never; false -> always end. +test_tl_gg_a() -> case tl() > a() of true -> always; false -> never end. +test_tl_ge_a() -> case tl() >= a() of true -> always; false -> never end. +test_tl_ll_t() -> case tl() < t() of true -> maybe; false -> maybe_too end. +test_tl_le_t() -> case tl() =< t() of true -> maybe; false -> maybe_too end. +test_tl_gg_t() -> case tl() > t() of true -> maybe; false -> maybe_too end. +test_tl_ge_t() -> case tl() >= t() of true -> maybe; false -> maybe_too end. +test_tl_ll_l() -> case tl() < l() of true -> maybe; false -> maybe_too end. +test_tl_le_l() -> case tl() =< l() of true -> maybe; false -> maybe_too end. +test_tl_gg_l() -> case tl() > l() of true -> maybe; false -> maybe_too end. +test_tl_ge_l() -> case tl() >= l() of true -> maybe; false -> maybe_too end. + +test_na_ll_na() -> case na() < na() of true -> maybe; false -> maybe_too end. +test_na_le_na() -> case na() =< na() of true -> maybe; false -> maybe_too end. +test_na_gg_na() -> case na() > na() of true -> maybe; false -> maybe_too end. +test_na_ge_na() -> case na() >= na() of true -> maybe; false -> maybe_too end. +test_na_ll_at() -> case na() < at() of true -> maybe; false -> maybe_too end. +test_na_le_at() -> case na() =< at() of true -> maybe; false -> maybe_too end. +test_na_gg_at() -> case na() > at() of true -> maybe; false -> maybe_too end. +test_na_ge_at() -> case na() >= at() of true -> maybe; false -> maybe_too end. +test_na_ll_tl() -> case na() < tl() of true -> always; false -> never end. +test_na_le_tl() -> case na() =< tl() of true -> always; false -> never end. +test_na_gg_tl() -> case na() > tl() of true -> never; false -> always end. +test_na_ge_tl() -> case na() >= tl() of true -> never; false -> always end. + +test_at_ll_na() -> case at() < na() of true -> maybe; false -> maybe_too end. +test_at_le_na() -> case at() =< na() of true -> maybe; false -> maybe_too end. +test_at_gg_na() -> case at() > na() of true -> maybe; false -> maybe_too end. +test_at_ge_na() -> case at() >= na() of true -> maybe; false -> maybe_too end. +test_at_ll_at() -> case at() < at() of true -> maybe; false -> maybe_too end. +test_at_le_at() -> case at() =< at() of true -> maybe; false -> maybe_too end. +test_at_gg_at() -> case at() > at() of true -> maybe; false -> maybe_too end. +test_at_ge_at() -> case at() >= at() of true -> maybe; false -> maybe_too end. +test_at_ll_tl() -> case at() < tl() of true -> maybe; false -> maybe_too end. +test_at_le_tl() -> case at() =< tl() of true -> maybe; false -> maybe_too end. +test_at_gg_tl() -> case at() > tl() of true -> maybe; false -> maybe_too end. +test_at_ge_tl() -> case at() >= tl() of true -> maybe; false -> maybe_too end. + +test_tl_ll_na() -> case tl() < na() of true -> never; false -> always end. +test_tl_le_na() -> case tl() =< na() of true -> never; false -> always end. +test_tl_gg_na() -> case tl() > na() of true -> always; false -> never end. +test_tl_ge_na() -> case tl() >= na() of true -> always; false -> never end. +test_tl_ll_at() -> case tl() < at() of true -> maybe; false -> maybe_too end. +test_tl_le_at() -> case tl() =< at() of true -> maybe; false -> maybe_too end. +test_tl_gg_at() -> case tl() > at() of true -> maybe; false -> maybe_too end. +test_tl_ge_at() -> case tl() >= at() of true -> maybe; false -> maybe_too end. +test_tl_ll_tl() -> case tl() < tl() of true -> maybe; false -> maybe_too end. +test_tl_le_tl() -> case tl() =< tl() of true -> maybe; false -> maybe_too end. +test_tl_gg_tl() -> case tl() > tl() of true -> maybe; false -> maybe_too end. +test_tl_ge_tl() -> case tl() >= tl() of true -> maybe; false -> maybe_too end. diff --git a/lib/dialyzer/test/small_SUITE_data/src/failing_funs.erl b/lib/dialyzer/test/small_SUITE_data/src/failing_funs.erl new file mode 100644 index 0000000000..1784c4a494 --- /dev/null +++ b/lib/dialyzer/test/small_SUITE_data/src/failing_funs.erl @@ -0,0 +1,250 @@ +-module(failing_funs). + +-compile(export_all). + +% Crashes with system call. No spec. +foo1() -> halt(). + +% Crashes with system call. With spec. +-spec foo2() -> no_return(). +foo2() -> halt(). + +% Crashes on its own. No spec. +foo3() -> case a of b -> ok end. + +% Crashes on its own. With spec. +-spec foo4() -> no_return(). +foo4() -> case a of b -> ok end. + +% Creates fun that crashes with system call. No spec. +foo5() -> fun() -> halt() end. + +% Creates fun that crashes with system call. With spec. +-spec foo6() -> fun(() -> no_return()). +foo6() -> fun() -> halt() end. + +% Creates fun from named fun that will crash. Neither have spec. +foo7() -> fun foo1/0. + +% Creates fun from named fun that will crash. Has spec. +-spec foo8() -> fun(() -> no_return()). +foo8() -> fun foo1/0. + +% Creates fun from named fun that will crash. Named has spec. +foo9() -> fun foo2/0. + +% Creates fun from named fun that will crash. Both have specs. +-spec foo10() -> fun(() -> no_return()). +foo10() -> fun foo2/0. + +% Creates fun from named fun that will crash. Neither have spec. +foo11() -> fun foo3/0. + +% Creates fun from named fun that will crash. Has spec. +-spec foo12() -> fun(() -> no_return()). +foo12() -> fun foo3/0. + +% Creates fun from named fun that will crash. Named has spec. +foo13() -> fun foo4/0. + +% Creates fun from named fun that will crash. Both have specs. +-spec foo14() -> fun(() -> no_return()). +foo14() -> fun foo4/0. + +% Creates fun calling a named fun that will crash. Neither have spec. +foo15() -> fun() -> foo1() end. + +% Creates fun calling a named fun that will crash. Has spec. +-spec foo16() -> fun(() -> no_return()). +foo16() -> fun() -> foo1() end. + +% Creates fun calling a named fun that will crash. Named has spec. +foo17() -> fun() -> foo2() end. + +% Creates fun calling a named fun that will crash. Both have specs. +-spec foo18() -> fun(() -> no_return()). +foo18() -> fun() -> foo2() end. + +% Creates fun calling a named fun that will crash. Neither have spec. +foo19() -> fun() -> foo3() end. + +% Creates fun calling a named fun that will crash. Has spec. +-spec foo20() -> fun(() -> no_return()). +foo20() -> fun() -> foo3() end. + +% Creates fun calling a named fun that will crash. Named has spec. +foo21() -> fun() -> foo4() end. + +% Creates fun calling a named fun that will crash. Both have specs. +-spec foo22() -> fun(() -> no_return()). +foo22() -> fun() -> foo4() end. + +% Creates two funs with no local return and will return one or die. No spec. +foo23() -> + Bomb = fun() -> halt() end, + case get(42) of + a -> Bomb(); + b -> fun() -> halt() end + end. + +% Creates two funs with no local return and will return one or die. With spec. +-spec foo24() -> fun(() -> no_return()). +foo24() -> + Bomb = fun() -> halt() end, + case get(42) of + a -> Bomb(); + b -> fun() -> halt() end + end. + +% Creates two funs with no local return and will return one or die. No spec. +foo25() -> + Bomb = fun() -> foo1() end, + case get(42) of + a -> Bomb(); + b -> fun() -> foo1() end + end. + +% Creates two funs with no local return and will return one or die. With spec. +-spec foo26() -> fun(() -> no_return()). +foo26() -> + Bomb = fun foo1/0, + case get(42) of + a -> Bomb(); + b -> fun foo1/0 + end. + +% Creates two funs with no local return and will return one or die. No spec. +foo27() -> + Bomb = fun foo1/0, + case get(42) of + a -> Bomb(); + b -> fun foo1/0 + end. + +% Creates two funs with no local return and will return one or die. With spec. +-spec foo28() -> fun(() -> no_return()). +foo28() -> + Bomb = fun() -> foo1() end, + case get(42) of + a -> Bomb(); + b -> fun() -> foo1() end + end. + +% Creates two funs with no local return and will return one or die. No spec. +foo29() -> + Bomb = fun() -> foo2() end, + case get(42) of + a -> Bomb(); + b -> fun() -> foo2() end + end. + +% Creates two funs with no local return and will return one or die. With spec. +-spec foo30() -> fun(() -> no_return()). +foo30() -> + Bomb = fun foo2/0, + case get(42) of + a -> Bomb(); + b -> fun foo2/0 + end. + +% Creates two funs with no local return and will return one or die. No spec. +foo31() -> + Bomb = fun foo2/0, + case get(42) of + a -> Bomb(); + b -> fun foo2/0 + end. + +% Creates two funs with no local return and will return one or die. With spec. +-spec foo32() -> fun(() -> no_return()). +foo32() -> + Bomb = fun() -> foo2() end, + case get(42) of + a -> Bomb(); + b -> fun() -> foo2() end + end. + +% Creates two funs with no local return and will return one or die. No spec. +foo33() -> + Bomb = fun() -> foo3() end, + case get(42) of + a -> Bomb(); + b -> fun() -> foo3() end + end. + +% Creates two funs with no local return and will return one or die. With spec. +-spec foo34() -> fun(() -> no_return()). +foo34() -> + Bomb = fun foo3/0, + case get(42) of + a -> Bomb(); + b -> fun foo3/0 + end. + +% Creates two funs with no local return and will return one or die. No spec. +foo35() -> + Bomb = fun foo3/0, + case get(42) of + a -> Bomb(); + b -> fun foo3/0 + end. + +% Creates two funs with no local return and will return one or die. With spec. +-spec foo36() -> fun(() -> no_return()). +foo36() -> + Bomb = fun() -> foo3() end, + case get(42) of + a -> Bomb(); + b -> fun() -> foo3() end + end. + +% Creates two funs with no local return and will return one or die. No spec. +foo37() -> + Bomb = fun() -> foo4() end, + case get(42) of + a -> Bomb(); + b -> fun() -> foo4() end + end. + +% Creates two funs with no local return and will return one or die. With spec. +-spec foo38() -> fun(() -> no_return()). +foo38() -> + Bomb = fun foo4/0, + case get(42) of + a -> Bomb(); + b -> fun foo4/0 + end. + +% Creates two funs with no local return and will return one or die. No spec. +foo39() -> + Bomb = fun foo4/0, + case get(42) of + a -> Bomb(); + b -> fun foo4/0 + end. + +% Creates two funs with no local return and will return one or die. With spec. +-spec foo40() -> fun(() -> no_return()). +foo40() -> + Bomb = fun() -> foo4() end, + case get(42) of + a -> Bomb(); + b -> fun() -> foo4() end + end. + +% Obtains two funs with no local return and will return one or die. No spec. +foo41() -> + Bomb = foo5(), + case get(42) of + a -> Bomb(); + b -> foo5() + end. + +% Obtains two funs with no local return and will return one or die. With spec. +-spec foo42() -> fun(() -> no_return()). +foo42() -> + Bomb = foo5(), + case get(42) of + a -> Bomb(); + b -> foo5() + end. diff --git a/lib/dialyzer/test/small_SUITE_data/src/file_open_encoding.erl b/lib/dialyzer/test/small_SUITE_data/src/file_open_encoding.erl index 4f1268eba8..086df3464b 100644 --- a/lib/dialyzer/test/small_SUITE_data/src/file_open_encoding.erl +++ b/lib/dialyzer/test/small_SUITE_data/src/file_open_encoding.erl @@ -6,9 +6,7 @@ -export([parse/1]). --type proplist() :: [{atom(), any()}]. - --spec parse(string()) -> proplist(). +-spec parse(string()) -> proplists:proplist(). parse(FileName) -> {ok, IoDevice} = file:open(FileName, [read, binary, {encoding, utf8}]), do_parse(IoDevice, []). diff --git a/lib/dialyzer/test/small_SUITE_data/src/higher_order_discrepancy.erl b/lib/dialyzer/test/small_SUITE_data/src/higher_order_discrepancy.erl new file mode 100644 index 0000000000..ff5ee6bac4 --- /dev/null +++ b/lib/dialyzer/test/small_SUITE_data/src/higher_order_discrepancy.erl @@ -0,0 +1,14 @@ +-module(higher_order_discrepancy). + +-export([test/1]). + +test(X) -> + F = + case X of + 1 -> fun f/1; + 2 -> fun g/1 + end, + F(foo). + +f(foo) -> ok. +g(bar) -> ok. diff --git a/lib/dialyzer/test/small_SUITE_data/src/higher_order_discrepancy_2.erl b/lib/dialyzer/test/small_SUITE_data/src/higher_order_discrepancy_2.erl new file mode 100644 index 0000000000..4b0d4f6b45 --- /dev/null +++ b/lib/dialyzer/test/small_SUITE_data/src/higher_order_discrepancy_2.erl @@ -0,0 +1,14 @@ +-module(higher_order_discrepancy_2). + +-export([test/1]). + +test(X) -> + F = + case X of + 1 -> fun f/1; + 2 -> fun g/1 + end, + F(foo). + +f(bar) -> ok. +g(baz) -> ok. diff --git a/lib/dialyzer/test/small_SUITE_data/src/list_to_bitstring.erl b/lib/dialyzer/test/small_SUITE_data/src/list_to_bitstring.erl new file mode 100644 index 0000000000..109aa88f16 --- /dev/null +++ b/lib/dialyzer/test/small_SUITE_data/src/list_to_bitstring.erl @@ -0,0 +1,21 @@ +%%===================================================================== +%% From: Ken Robinson +%% Date: 28/04/2011, 17:26 +%% +%% Program that produced bogus "Function has no local return" warnings +%% due to erlang:list_to_bitstring/1 having erroneous hard coded type +%% information, namely accepting iolist() instead of bitstrlist(). +%% Fixed 29/04/2011. +%%===================================================================== + +-module(list_to_bitstring). + +-export([l2bs/0, l2bs_ok/0]). + +%% This function was producing a warning +l2bs() -> + erlang:list_to_bitstring([<<42>>, <<42:13>>]). + +%% while this one was ok. +l2bs_ok() -> + erlang:list_to_bitstring([<<42>>, <<42,42>>]). diff --git a/lib/dialyzer/test/small_SUITE_data/src/no_return_bug.erl b/lib/dialyzer/test/small_SUITE_data/src/no_return_bug.erl new file mode 100644 index 0000000000..5c24902590 --- /dev/null +++ b/lib/dialyzer/test/small_SUITE_data/src/no_return_bug.erl @@ -0,0 +1,42 @@ +%% Dialyzer couldn't infer that monitor_diskspace would go in an infinite loop +%% instead of crashing due to the existence of list comprehensions that have a +%% normal success typing. These were added to the monitor_diskspace's SCC and +%% dialyzer_typesig didn't try to assign unit() to monitor_diskspace, as it +%% required all the members of the SCC to return none(). +%% +%% Testcase was submitted in erlang-questions mailing list by Prashanth Mundkur +%% (http://erlang.org/pipermail/erlang-questions/2011-May/058063.html) + +-module(no_return_bug). +-export([diskspace/1, monitor_diskspace/2, refresh_tags/1, monitor_launch/0]). + +-type diskinfo() :: {non_neg_integer(), non_neg_integer()}. + +-spec diskspace(nonempty_string()) -> {'ok', diskinfo()} | {'error', term()}. +diskspace(Path) -> + case Path of + "a" -> {ok, {0,0}}; + _ -> {error, error} + end. + +-spec monitor_diskspace(nonempty_string(), + [{diskinfo(), nonempty_string()}]) -> + no_return(). +monitor_diskspace(Root, Vols) -> + Df = fun(VolName) -> + diskspace(filename:join([Root, VolName])) + end, + NewVols = [{Space, VolName} + || {VolName, {ok, Space}} + <- [{VolName, Df(VolName)} + || {_OldSpace, VolName} <- Vols]], + monitor_diskspace(Root, NewVols). + +-spec refresh_tags(nonempty_string()) -> no_return(). +refresh_tags(Root) -> + {ok, _} = diskspace(Root), + refresh_tags(Root). + +monitor_launch() -> + spawn_link(fun() -> refresh_tags("abc") end), + spawn_link(fun() -> monitor_diskspace("root", [{{0,0}, "a"}]) end). diff --git a/lib/dialyzer/test/small_SUITE_data/src/nowarnunused.erl b/lib/dialyzer/test/small_SUITE_data/src/nowarnunused.erl new file mode 100644 index 0000000000..63daeee9e3 --- /dev/null +++ b/lib/dialyzer/test/small_SUITE_data/src/nowarnunused.erl @@ -0,0 +1,7 @@ +-module(nowarnunused). + +-compile({nowarn_unused_function, return_error/2}). + +-spec return_error(integer(), any()) -> no_return(). +return_error(Line, Message) -> + throw({error, {Line, ?MODULE, Message}}). diff --git a/lib/dialyzer/test/small_SUITE_data/src/rebar_no_return.erl b/lib/dialyzer/test/small_SUITE_data/src/rebar_no_return.erl new file mode 100644 index 0000000000..d3b504ae04 --- /dev/null +++ b/lib/dialyzer/test/small_SUITE_data/src/rebar_no_return.erl @@ -0,0 +1,19 @@ +-module(rebar_no_return). + +-export([t/0]). + +-spec t() -> no_return(). +t() -> + F = log_and_halt("baz"), + F("foo", 123). + +-spec log_and_halt(string()) -> fun((string(),integer()) -> no_return()). +log_and_halt(Msg) -> + fun(_, _) -> + abort(Msg) + end. + +-spec abort(string()) -> no_return(). +abort(Msg) -> + io:format("~s~n", [Msg]), + halt(1). |