aboutsummaryrefslogtreecommitdiffstats
path: root/lib/dialyzer/test
diff options
context:
space:
mode:
Diffstat (limited to 'lib/dialyzer/test')
-rw-r--r--lib/dialyzer/test/Makefile3
-rw-r--r--lib/dialyzer/test/abstract_SUITE.erl3
-rw-r--r--lib/dialyzer/test/behaviour_SUITE_data/results/gen_server_incorrect_args3
-rw-r--r--lib/dialyzer/test/behaviour_SUITE_data/results/gen_server_missing_callbacks1
-rw-r--r--lib/dialyzer/test/behaviour_SUITE_data/results/vars_in_beh_spec2
-rw-r--r--lib/dialyzer/test/plt_SUITE.erl37
-rw-r--r--lib/dialyzer/test/typer_SUITE.erl158
7 files changed, 189 insertions, 18 deletions
diff --git a/lib/dialyzer/test/Makefile b/lib/dialyzer/test/Makefile
index 0d8fba438c..43c8a61ce1 100644
--- a/lib/dialyzer/test/Makefile
+++ b/lib/dialyzer/test/Makefile
@@ -13,7 +13,8 @@ AUXILIARY_FILES=\
file_utils.erl\
dialyzer_SUITE.erl\
abstract_SUITE.erl\
- plt_SUITE.erl
+ plt_SUITE.erl\
+ typer_SUITE.erl
# ----------------------------------------------------
# Release directory specification
diff --git a/lib/dialyzer/test/abstract_SUITE.erl b/lib/dialyzer/test/abstract_SUITE.erl
index 0e84dfab24..37fb39cf27 100644
--- a/lib/dialyzer/test/abstract_SUITE.erl
+++ b/lib/dialyzer/test/abstract_SUITE.erl
@@ -83,7 +83,8 @@ generated_case(Config) when is_list(Config) ->
Config, [], []),
ok.
-test(Prog, Config, COpts, DOpts) ->
+test(Prog0, Config, COpts, DOpts) ->
+ Prog = erl_parse:anno_from_term(Prog0),
{ok, BeamFile} = compile(Config, Prog, COpts),
run_dialyzer(Config, succ_typings, [BeamFile], DOpts).
diff --git a/lib/dialyzer/test/behaviour_SUITE_data/results/gen_server_incorrect_args b/lib/dialyzer/test/behaviour_SUITE_data/results/gen_server_incorrect_args
index 3e98da785f..2f504d3c72 100644
--- a/lib/dialyzer/test/behaviour_SUITE_data/results/gen_server_incorrect_args
+++ b/lib/dialyzer/test/behaviour_SUITE_data/results/gen_server_incorrect_args
@@ -1,8 +1,5 @@
-gen_server_incorrect_args.erl:3: Undefined callback function code_change/3 (behaviour 'gen_server')
gen_server_incorrect_args.erl:3: Undefined callback function handle_cast/2 (behaviour 'gen_server')
-gen_server_incorrect_args.erl:3: Undefined callback function handle_info/2 (behaviour 'gen_server')
gen_server_incorrect_args.erl:3: Undefined callback function init/1 (behaviour 'gen_server')
-gen_server_incorrect_args.erl:3: Undefined callback function terminate/2 (behaviour 'gen_server')
gen_server_incorrect_args.erl:7: The inferred return type of handle_call/3 ({'no'} | {'ok'}) has nothing in common with {'noreply',_} | {'noreply',_,'hibernate' | 'infinity' | non_neg_integer()} | {'reply',_,_} | {'stop',_,_} | {'reply',_,_,'hibernate' | 'infinity' | non_neg_integer()} | {'stop',_,_,_}, which is the expected return type for the callback of gen_server behaviour
gen_server_incorrect_args.erl:7: The inferred type for the 2nd argument of handle_call/3 ('boo' | 'foo') is not a supertype of {pid(),_}, which is expected type for this argument in the callback of the gen_server behaviour
diff --git a/lib/dialyzer/test/behaviour_SUITE_data/results/gen_server_missing_callbacks b/lib/dialyzer/test/behaviour_SUITE_data/results/gen_server_missing_callbacks
index 5e0ed5fd27..0a7642a9b5 100644
--- a/lib/dialyzer/test/behaviour_SUITE_data/results/gen_server_missing_callbacks
+++ b/lib/dialyzer/test/behaviour_SUITE_data/results/gen_server_missing_callbacks
@@ -1,3 +1,2 @@
gen_server_missing_callbacks.erl:3: Undefined callback function handle_cast/2 (behaviour 'gen_server')
-gen_server_missing_callbacks.erl:3: Undefined callback function handle_info/2 (behaviour 'gen_server')
diff --git a/lib/dialyzer/test/behaviour_SUITE_data/results/vars_in_beh_spec b/lib/dialyzer/test/behaviour_SUITE_data/results/vars_in_beh_spec
index 5284e412f0..512dcdd758 100644
--- a/lib/dialyzer/test/behaviour_SUITE_data/results/vars_in_beh_spec
+++ b/lib/dialyzer/test/behaviour_SUITE_data/results/vars_in_beh_spec
@@ -1,6 +1,4 @@
vars_in_beh_spec.erl:3: Undefined callback function handle_call/3 (behaviour 'gen_server')
vars_in_beh_spec.erl:3: Undefined callback function handle_cast/2 (behaviour 'gen_server')
-vars_in_beh_spec.erl:3: Undefined callback function handle_info/2 (behaviour 'gen_server')
vars_in_beh_spec.erl:3: Undefined callback function init/1 (behaviour 'gen_server')
-vars_in_beh_spec.erl:3: Undefined callback function terminate/2 (behaviour 'gen_server')
diff --git a/lib/dialyzer/test/plt_SUITE.erl b/lib/dialyzer/test/plt_SUITE.erl
index fbfa979e1b..92c63bdb0c 100644
--- a/lib/dialyzer/test/plt_SUITE.erl
+++ b/lib/dialyzer/test/plt_SUITE.erl
@@ -259,24 +259,41 @@ remove_plt(Config) ->
{init_plt, Plt}] ++ Opts),
ok.
+%% ERL-283, OTP-13979. As of OTP-14323 this test no longer does what
+%% it is designed to do--the linter stops every attempt to run the
+%% checks of Dialyzer's on bad dialyzer attributes. For the time
+%% being, the linter's error message are checked instead. The test
+%% needs to be updated when/if the Dialyzer can analyze Core Erlang
+%% without compiling abstract code.
bad_dialyzer_attr(Config) ->
+ PrivDir = ?config(priv_dir, Config),
+ Source = lists:concat([dial, ".erl"]),
+ Filename = filename:join(PrivDir, Source),
+ ok = dialyzer_common:check_plt(PrivDir),
+ PltFilename = dialyzer_common:plt_file(PrivDir),
+ Opts = [{files, [Filename]},
+ {check_plt, false},
+ {from, src_code},
+ {init_plt, PltFilename}],
+
Prog1 = <<"-module(dial).
-dialyzer({no_return, [undef/0]}).">>,
- {ok, Beam1} = compile(Config, Prog1, dial, []),
+ ok = file:write_file(Filename, Prog1),
{dialyzer_error,
- "Analysis failed with error:\n"
- "Could not scan the following file(s):\n"
- " Unknown function undef/0 in line " ++ _} =
- (catch run_dialyzer(plt_build, [Beam1], [])),
+ "Analysis failed with error:\n" ++ Str1} =
+ (catch dialyzer:run(Opts)),
+ P1 = string:str(Str1, "dial.erl:2: function undef/0 undefined"),
+ true = P1 > 0,
Prog2 = <<"-module(dial).
-dialyzer({no_return, [{undef,1,2}]}).">>,
- {ok, Beam2} = compile(Config, Prog2, dial, []),
+ ok = file:write_file(Filename, Prog2),
{dialyzer_error,
- "Analysis failed with error:\n"
- "Could not scan the following file(s):\n"
- " Bad function {undef,1,2} in line " ++ _} =
- (catch run_dialyzer(plt_build, [Beam2], [])),
+ "Analysis failed with error:\n" ++ Str2} =
+ (catch dialyzer:run(Opts)),
+ P2 = string:str(Str2, "dial.erl:2: badly formed dialyzer "
+ "attribute: {no_return,{undef,1,2}}"),
+ true = P2 > 0,
ok.
diff --git a/lib/dialyzer/test/typer_SUITE.erl b/lib/dialyzer/test/typer_SUITE.erl
new file mode 100644
index 0000000000..da5b961643
--- /dev/null
+++ b/lib/dialyzer/test/typer_SUITE.erl
@@ -0,0 +1,158 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2017. All Rights Reserved.
+%%
+%% 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.
+%%
+%% %CopyrightEnd%
+%%
+-module(typer_SUITE).
+
+-export([all/0,suite/0,groups/0,init_per_suite/1,end_per_suite/1,
+ init_per_group/2,end_per_group/2,
+ smoke/1]).
+
+-include_lib("common_test/include/ct.hrl").
+
+suite() -> [{ct_hooks,[ts_install_cth]}].
+
+all() ->
+ [smoke].
+
+groups() ->
+ [].
+
+init_per_suite(Config) ->
+ OutDir = proplists:get_value(priv_dir, Config),
+ case dialyzer_common:check_plt(OutDir) of
+ fail -> {skip, "Plt creation/check failed."};
+ ok -> [{dialyzer_options, []}|Config]
+ end.
+
+end_per_suite(_Config) ->
+ ok.
+
+init_per_group(_GroupName, Config) ->
+ Config.
+
+end_per_group(_GroupName, Config) ->
+ Config.
+
+smoke(Config) ->
+ Code = <<"-module(typer_test_module).
+ -compile([export_all,nowarn_export_all]).
+ a(L) ->
+ L ++ [1,2,3].">>,
+ PrivDir = proplists:get_value(priv_dir, Config),
+ Src = filename:join(PrivDir, "typer_test_module.erl"),
+ ok = file:write_file(Src, Code),
+ Args = "--plt " ++ PrivDir ++ "dialyzer_plt",
+ Res = ["^$",
+ "^%% File:",
+ "^%% ----",
+ "^-spec a",
+ "^_OK_"],
+ run(Config, Args, Src, Res),
+ ok.
+
+typer() ->
+ case os:find_executable("typer") of
+ false ->
+ ct:fail("Can't find typer");
+ Typer ->
+ Typer
+ end.
+
+%% Runs a command.
+
+run(Config, Args0, Name, Expect) ->
+ Args = Args0 ++ " " ++ Name,
+ Result = run_command(Config, Args),
+ verify_result(Result, Expect).
+
+verify_result(Result, Expect) ->
+ Messages = split(Result, [], []),
+ io:format("Result: ~p", [Messages]),
+ io:format("Expected: ~p", [Expect]),
+ match_messages(Messages, Expect).
+
+split([$\n|Rest], Current, Lines) ->
+ split(Rest, [], [lists:reverse(Current)|Lines]);
+split([$\r|Rest], Current, Lines) ->
+ split(Rest, Current, Lines);
+split([Char|Rest], Current, Lines) ->
+ split(Rest, [Char|Current], Lines);
+split([], [], Lines) ->
+ lists:reverse(Lines);
+split([], Current, Lines) ->
+ split([], [], [lists:reverse(Current)|Lines]).
+
+match_messages([Msg|Rest1], [Regexp|Rest2]) ->
+ case re:run(Msg, Regexp, [{capture,none}, unicode]) of
+ match ->
+ ok;
+ nomatch ->
+ io:format("Not matching: ~s\n", [Msg]),
+ io:format("Regexp : ~s\n", [Regexp]),
+ ct:fail(message_mismatch)
+ end,
+ match_messages(Rest1, Rest2);
+match_messages([], [Expect|Rest]) ->
+ ct:fail({too_few_messages, [Expect|Rest]});
+match_messages([Msg|Rest], []) ->
+ ct:fail({too_many_messages, [Msg|Rest]});
+match_messages([], []) ->
+ ok.
+
+%% Runs the command using os:cmd/1.
+%%
+%% Returns the output from the command (as a list of characters with
+%% embedded newlines). The very last line will indicate the
+%% exit status of the command, where _OK_ means zero, and _ERROR_
+%% a non-zero exit status.
+
+run_command(Config, Args) ->
+ TmpDir = filename:join(proplists:get_value(priv_dir, Config), "tmp"),
+ file:make_dir(TmpDir),
+ {RunFile, Run, Script} = run_command(TmpDir, os:type(), Args),
+ ok = file:write_file(filename:join(TmpDir, RunFile),
+ unicode:characters_to_binary(Script)),
+ io:format("~ts\n", [Script]),
+ os:cmd(Run).
+
+run_command(Dir, {win32, _}, Args) ->
+ BatchFile = filename:join(Dir, "run.bat"),
+ Run = re:replace(filename:rootname(BatchFile), "/", "\\",
+ [global,{return,list}]),
+ Typer = typer(),
+ {BatchFile,
+ Run,
+ ["@echo off\r\n",
+ "\"",Typer,"\" ",Args, "\r\n",
+ "if errorlevel 1 echo _ERROR_\r\n",
+ "if not errorlevel 1 echo _OK_\r\n"]};
+run_command(Dir, {unix, _}, Args) ->
+ TyperDir = filename:dirname(typer()),
+ Name = filename:join(Dir, "run"),
+ {Name,
+ "/bin/sh " ++ Name,
+ ["#!/bin/sh\n",
+ "PATH=\"",TyperDir,":$PATH\"\n",
+ "typer ",Args,"\n",
+ "case $? in\n",
+ " 0) echo '_OK_';;\n",
+ " *) echo '_ERROR_';;\n",
+ "esac\n"]};
+run_command(_Dir, Other, _Args) ->
+ ct:fail("Don't know how to test exit code for ~p", [Other]).