aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/common_test/src/ct.erl2
-rw-r--r--lib/common_test/src/ct_config.erl47
-rw-r--r--lib/common_test/src/ct_framework.erl10
-rw-r--r--lib/common_test/src/ct_ftp.erl2
-rw-r--r--lib/common_test/src/ct_groups.erl16
-rw-r--r--lib/common_test/src/ct_hooks.erl3
-rw-r--r--lib/common_test/src/ct_hooks_lock.erl2
-rw-r--r--lib/common_test/src/ct_logs.erl77
-rw-r--r--lib/common_test/src/ct_master.erl24
-rw-r--r--lib/common_test/src/ct_master_logs.erl43
-rw-r--r--lib/common_test/src/ct_property_test.erl8
-rw-r--r--lib/common_test/src/ct_release_test.erl38
-rw-r--r--lib/common_test/src/ct_repeat.erl6
-rw-r--r--lib/common_test/src/ct_rpc.erl6
-rw-r--r--lib/common_test/src/ct_run.erl98
-rw-r--r--lib/common_test/src/ct_slave.erl6
-rw-r--r--lib/common_test/src/ct_snmp.erl80
-rw-r--r--lib/common_test/src/ct_ssh.erl4
-rw-r--r--lib/common_test/src/ct_telnet.erl6
-rw-r--r--lib/common_test/src/ct_telnet_client.erl4
-rw-r--r--lib/common_test/src/ct_util.erl23
-rw-r--r--lib/common_test/src/ct_webtool.erl39
-rw-r--r--lib/common_test/src/cth_conn_log.erl2
-rw-r--r--lib/common_test/src/erl2html2.erl18
-rw-r--r--lib/common_test/src/test_server.erl3
-rw-r--r--lib/common_test/src/test_server_ctrl.erl4
-rw-r--r--lib/common_test/test/ct_gen_conn_SUITE_data/conn_SUITE.erl68
-rw-r--r--lib/common_test/test/ct_netconfc_SUITE.erl32
-rw-r--r--lib/common_test/test/ct_netconfc_SUITE_data/netconfc1_SUITE.erl9
-rw-r--r--lib/common_test/test/ct_netconfc_SUITE_data/netconfc_remote_SUITE.erl15
-rw-r--r--lib/common_test/test/ct_netconfc_SUITE_data/ns.erl2
-rw-r--r--lib/common_test/test/ct_test_support.erl6
-rw-r--r--lib/common_test/test/telnet_server.erl42
-rw-r--r--lib/dialyzer/src/dialyzer_contracts.erl11
-rw-r--r--lib/dialyzer/src/dialyzer_dataflow.erl58
-rw-r--r--lib/dialyzer/test/map_SUITE_data/results/exact2
-rw-r--r--lib/dialyzer/test/map_SUITE_data/results/guard_update2
-rw-r--r--lib/dialyzer/test/map_SUITE_data/results/map_in_guard22
-rw-r--r--lib/dialyzer/test/map_SUITE_data/results/typeflow2
-rw-r--r--lib/dialyzer/test/map_SUITE_data/results/typesig4
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/higher_order_discrepancy5
-rw-r--r--lib/dialyzer/test/small_SUITE_data/results/maps12
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/higher_order_discrepancy.erl5
-rw-r--r--lib/dialyzer/test/small_SUITE_data/src/loopy.erl17
-rw-r--r--lib/dialyzer/test/user_SUITE_data/results/wpc_hlines3
-rw-r--r--lib/dialyzer/test/user_SUITE_data/src/wpc_hlines.erl22
-rw-r--r--lib/edoc/priv/edoc.dtd6
-rw-r--r--lib/edoc/src/edoc_layout.erl18
-rw-r--r--lib/edoc/src/edoc_parser.yrl11
-rw-r--r--lib/edoc/src/edoc_scanner.erl2
-rw-r--r--lib/edoc/src/edoc_specs.erl6
-rw-r--r--lib/edoc/src/edoc_types.erl4
-rw-r--r--lib/edoc/src/edoc_types.hrl2
-rw-r--r--lib/erl_docgen/src/docgen_otp_specs.erl32
-rw-r--r--lib/hipe/cerl/erl_types.erl1
-rw-r--r--lib/inets/test/httpc_SUITE.erl7
-rw-r--r--lib/kernel/doc/src/gen_tcp.xml21
-rw-r--r--lib/kernel/doc/src/gen_udp.xml19
-rw-r--r--lib/kernel/doc/src/inet.xml53
-rw-r--r--lib/kernel/src/gen_tcp.erl12
-rw-r--r--lib/kernel/src/gen_udp.erl10
-rw-r--r--lib/kernel/src/inet.erl92
-rw-r--r--lib/kernel/src/inet_int.hrl1
-rw-r--r--lib/kernel/src/local_tcp.erl10
-rw-r--r--lib/kernel/src/local_udp.erl9
-rw-r--r--lib/runtime_tools/c_src/dyntrace_lttng.h50
-rw-r--r--lib/runtime_tools/doc/src/LTTng.xml26
-rw-r--r--lib/runtime_tools/test/dyntrace_lttng_SUITE.erl134
-rw-r--r--lib/ssh/test/ssh_algorithms_SUITE.erl60
-rw-r--r--lib/ssh/test/ssh_basic_SUITE.erl3
-rw-r--r--lib/ssh/test/ssh_connection_SUITE.erl151
-rw-r--r--lib/ssh/test/ssh_echo_server.erl35
-rw-r--r--lib/ssh/test/ssh_options_SUITE.erl4
-rw-r--r--lib/ssh/test/ssh_protocol_SUITE.erl3
-rw-r--r--lib/ssh/test/ssh_renegotiate_SUITE.erl3
-rw-r--r--lib/ssh/test/ssh_sftp_SUITE.erl13
-rw-r--r--lib/ssh/test/ssh_sftpd_SUITE.erl20
-rw-r--r--lib/ssh/test/ssh_sftpd_erlclient_SUITE.erl26
-rw-r--r--lib/ssh/test/ssh_sup_SUITE.erl13
-rw-r--r--lib/ssh/test/ssh_test_lib.hrl10
-rw-r--r--lib/ssh/test/ssh_to_openssh_SUITE.erl15
-rw-r--r--lib/ssh/test/ssh_upgrade_SUITE.erl17
-rw-r--r--lib/ssl/doc/src/ssl.xml17
-rw-r--r--lib/ssl/src/ssl.erl29
-rw-r--r--lib/ssl/src/ssl_crl.erl16
-rw-r--r--lib/ssl/src/ssl_socket.erl7
-rw-r--r--lib/ssl/test/ssl_basic_SUITE.erl74
-rw-r--r--lib/stdlib/src/erl_parse.yrl3
-rw-r--r--lib/stdlib/src/erl_pp.erl20
-rw-r--r--lib/stdlib/test/erl_pp_SUITE.erl5
-rw-r--r--lib/syntax_tools/src/erl_prettypr.erl39
-rw-r--r--lib/syntax_tools/test/syntax_tools_SUITE_data/type_specs.erl9
-rw-r--r--lib/tools/src/xref_base.erl215
-rw-r--r--lib/tools/src/xref_utils.erl8
94 files changed, 1447 insertions, 774 deletions
diff --git a/lib/common_test/src/ct.erl b/lib/common_test/src/ct.erl
index cae7bea406..d7ae81a5ce 100644
--- a/lib/common_test/src/ct.erl
+++ b/lib/common_test/src/ct.erl
@@ -282,7 +282,7 @@ step(TestDir,Suite,Case,Opts) ->
%%% <c>&gt; ct_telnet:cmd(unix_telnet, "ls .").</c><br/>
%%% <c>{ok,["ls","file1 ...",...]}</c></p>
start_interactive() ->
- ct_util:start(interactive),
+ _ = ct_util:start(interactive),
ok.
%%%-----------------------------------------------------------------
diff --git a/lib/common_test/src/ct_config.erl b/lib/common_test/src/ct_config.erl
index b499bc8b05..99de311570 100644
--- a/lib/common_test/src/ct_config.erl
+++ b/lib/common_test/src/ct_config.erl
@@ -119,7 +119,8 @@ call(Msg) ->
end.
return({To,Ref},Result) ->
- To ! {Ref, Result}.
+ To ! {Ref, Result},
+ ok.
loop(StartDir) ->
receive
@@ -128,11 +129,11 @@ loop(StartDir) ->
return(From,Result),
loop(StartDir);
{{set_default_config,{Config,Scope}},From} ->
- set_config(Config,{true,Scope}),
+ _ = set_config(Config,{true,Scope}),
return(From,ok),
loop(StartDir);
{{set_default_config,{Name,Config,Scope}},From} ->
- set_config(Name,Config,{true,Scope}),
+ _ = set_config(Name,Config,{true,Scope}),
return(From,ok),
loop(StartDir);
{{delete_default_config,Scope},From} ->
@@ -149,7 +150,7 @@ loop(StartDir) ->
loop(StartDir);
{{stop},From} ->
ets:delete(?attr_table),
- file:set_cwd(StartDir),
+ ok = file:set_cwd(StartDir),
return(From,ok)
end.
@@ -257,7 +258,7 @@ read_config_files(Opts) ->
read_config_files_int([{Callback, File}|Files], FunToSave) ->
case Callback:read_config(File) of
{ok, Config} ->
- FunToSave(Config, Callback, File),
+ _ = FunToSave(Config, Callback, File),
read_config_files_int(Files, FunToSave);
{error, {ErrorName, ErrorDetail}} ->
{user_error, {ErrorName, File, ErrorDetail}};
@@ -267,6 +268,15 @@ read_config_files_int([{Callback, File}|Files], FunToSave) ->
read_config_files_int([], _FunToSave) ->
ok.
+
+read_config_files(ConfigFiles, FunToSave) ->
+ case read_config_files_int(ConfigFiles, FunToSave) of
+ {user_error, Error} ->
+ {error, Error};
+ ok ->
+ ok
+ end.
+
store_config(Config, Callback, File) when is_tuple(Config) ->
store_config([Config], Callback, File);
@@ -455,8 +465,12 @@ reload_conf(KeyOrName) ->
undefined;
HandlerList ->
HandlerList2 = lists:usort(HandlerList),
- read_config_files_int(HandlerList2, fun rewrite_config/3),
- get_config(KeyOrName)
+ case read_config_files(HandlerList2, fun rewrite_config/3) of
+ ok ->
+ get_config(KeyOrName);
+ Error ->
+ Error
+ end
end.
release_allocated() ->
@@ -490,16 +504,16 @@ associate(Name,_Key,Configs) ->
associate_int(Name,Configs,os:getenv("COMMON_TEST_ALIAS_TOP")).
associate_int(Name,Configs,"true") ->
- lists:map(fun({K,_Config}) ->
+ lists:foreach(fun({K,_Config}) ->
Cs = ets:match_object(
?attr_table,
#ct_conf{key=element(1,K),
name='_UNDEF',_='_'}),
[ets:insert(?attr_table,C#ct_conf{name=Name})
|| C <- Cs]
- end,Configs);
+ end,Configs);
associate_int(Name,Configs,_) ->
- lists:map(fun({K,Config}) ->
+ lists:foreach(fun({K,Config}) ->
Key = if is_tuple(K) -> element(1,K);
is_atom(K) -> K
end,
@@ -511,7 +525,7 @@ associate_int(Name,Configs,_) ->
[ets:insert(?attr_table,C#ct_conf{name=Name,
value=Config})
|| C <- Cs]
- end,Configs).
+ end,Configs).
@@ -576,7 +590,7 @@ encrypt_config_file(SrcFileName, EncryptFileName, {file,KeyFile}) ->
end;
encrypt_config_file(SrcFileName, EncryptFileName, {key,Key}) ->
- crypto:start(),
+ _ = crypto:start(),
{Key,IVec} = make_crypto_key(Key),
case file:read_file(SrcFileName) of
{ok,Bin0} ->
@@ -615,7 +629,7 @@ decrypt_config_file(EncryptFileName, TargetFileName, {file,KeyFile}) ->
end;
decrypt_config_file(EncryptFileName, TargetFileName, {key,Key}) ->
- crypto:start(),
+ _ = crypto:start(),
{Key,IVec} = make_crypto_key(Key),
case file:read_file(EncryptFileName) of
{ok,Bin} ->
@@ -778,14 +792,13 @@ prepare_config_list(Args) ->
% TODO: add logging of the loaded configuration file to the CT FW log!!!
add_config(Callback, []) ->
- read_config_files_int([{Callback, []}], fun store_config/3);
+ read_config_files([{Callback, []}], fun store_config/3);
add_config(Callback, [File|_Files]=Config) when is_list(File) ->
lists:foreach(fun(CfgStr) ->
- read_config_files_int([{Callback, CfgStr}], fun store_config/3) end,
+ read_config_files([{Callback, CfgStr}], fun store_config/3) end,
Config);
add_config(Callback, [C|_]=Config) when is_integer(C) ->
- read_config_files_int([{Callback, Config}], fun store_config/3),
- ok.
+ read_config_files([{Callback, Config}], fun store_config/3).
remove_config(Callback, Config) ->
ets:match_delete(?attr_table,
diff --git a/lib/common_test/src/ct_framework.erl b/lib/common_test/src/ct_framework.erl
index eb32f7f3fc..104515e57e 100644
--- a/lib/common_test/src/ct_framework.erl
+++ b/lib/common_test/src/ct_framework.erl
@@ -128,7 +128,7 @@ init_tc1(?MODULE,_,error_in_suite,_,[Config0]) when is_list(Config0) ->
ct_event:notify(#event{name=tc_start,
node=node(),
data={?MODULE,error_in_suite}}),
- ct_suite_init(?MODULE,error_in_suite,[],Config0),
+ _ = ct_suite_init(?MODULE,error_in_suite,[],Config0),
case ?val(error,Config0) of
undefined ->
{fail,"unknown_error_in_suite"};
@@ -212,7 +212,7 @@ init_tc2(Mod,Suite,Func,HookFunc,SuiteInfo,MergeResult,Config) ->
%% timetrap must be handled before require
MergedInfo = timetrap_first(MergeResult, [], []),
%% tell logger to use specified style sheet
- case lists:keysearch(stylesheet,1,MergeResult++Config) of
+ _ = case lists:keysearch(stylesheet,1,MergeResult++Config) of
{value,{stylesheet,SSFile}} ->
ct_logs:set_stylesheet(Func,add_data_dir(SSFile,Config));
_ ->
@@ -632,10 +632,10 @@ try_set_default(Name,Key,Info,Where) ->
{_,[]} ->
no_default;
{'_UNDEF',_} ->
- [ct_config:set_default_config([CfgVal],Where) || CfgVal <- CfgElems],
+ _ = [ct_config:set_default_config([CfgVal],Where) || CfgVal <- CfgElems],
ok;
_ ->
- [ct_config:set_default_config(Name,[CfgVal],Where) || CfgVal <- CfgElems],
+ _ = [ct_config:set_default_config(Name,[CfgVal],Where) || CfgVal <- CfgElems],
ok
end.
@@ -1315,7 +1315,7 @@ report(What,Data) ->
%% top level test index page needs to be refreshed
TestName = filename:basename(?val(topdir, Data), ".logs"),
RunDir = ?val(rundir, Data),
- ct_logs:make_all_suites_index({TestName,RunDir}),
+ _ = ct_logs:make_all_suites_index({TestName,RunDir}),
ok;
tests_start ->
ok;
diff --git a/lib/common_test/src/ct_ftp.erl b/lib/common_test/src/ct_ftp.erl
index 48914864e4..84e664b387 100644
--- a/lib/common_test/src/ct_ftp.erl
+++ b/lib/common_test/src/ct_ftp.erl
@@ -292,7 +292,7 @@ init(KeyOrName,{IP,Port},{Username,Password}) ->
end.
ftp_connect(IP,Port,Username,Password) ->
- inets:start(),
+ _ = inets:start(),
case inets:start(ftpc,[{host,IP},{port,Port}]) of
{ok,FtpPid} ->
case ftp:user(FtpPid,Username,Password) of
diff --git a/lib/common_test/src/ct_groups.erl b/lib/common_test/src/ct_groups.erl
index dd04c5410a..1375e7dcc7 100644
--- a/lib/common_test/src/ct_groups.erl
+++ b/lib/common_test/src/ct_groups.erl
@@ -402,12 +402,7 @@ expand(Mod, Name, Defs) ->
end.
make_all_conf(Dir, Mod, Props, TestSpec) ->
- case code:is_loaded(Mod) of
- false ->
- code:load_abs(filename:join(Dir,atom_to_list(Mod)));
- _ ->
- ok
- end,
+ _ = load_abs(Dir, Mod),
make_all_conf(Mod, Props, TestSpec).
make_all_conf(Mod, Props, TestSpec) ->
@@ -428,16 +423,19 @@ make_all_conf(Mod, Props, TestSpec) ->
end.
make_conf(Dir, Mod, Name, Props, TestSpec) ->
+ _ = load_abs(Dir, Mod),
+ make_conf(Mod, Name, Props, TestSpec).
+
+load_abs(Dir, Mod) ->
case code:is_loaded(Mod) of
false ->
code:load_abs(filename:join(Dir,atom_to_list(Mod)));
_ ->
ok
- end,
- make_conf(Mod, Name, Props, TestSpec).
+ end.
make_conf(Mod, Name, Props, TestSpec) ->
- case code:is_loaded(Mod) of
+ _ = case code:is_loaded(Mod) of
false ->
code:load_file(Mod);
_ ->
diff --git a/lib/common_test/src/ct_hooks.erl b/lib/common_test/src/ct_hooks.erl
index 5422d449fd..c9a4abb5ee 100644
--- a/lib/common_test/src/ct_hooks.erl
+++ b/lib/common_test/src/ct_hooks.erl
@@ -408,7 +408,8 @@ catch_apply(M,F,A, Default) ->
maybe_start_locker(Mod,GroupName,Opts) ->
case lists:member(parallel,Opts) of
true ->
- {ok, _Pid} = ct_hooks_lock:start({Mod,GroupName});
+ {ok, _Pid} = ct_hooks_lock:start({Mod,GroupName}),
+ ok;
false ->
ok
end.
diff --git a/lib/common_test/src/ct_hooks_lock.erl b/lib/common_test/src/ct_hooks_lock.erl
index f41f259f7b..fea298e535 100644
--- a/lib/common_test/src/ct_hooks_lock.erl
+++ b/lib/common_test/src/ct_hooks_lock.erl
@@ -82,7 +82,7 @@ init(Id) ->
%% @doc Handling call messages
handle_call({stop,Id}, _From, #state{ id = Id, requests = Reqs } = State) ->
- [gen_server:reply(Req, locker_stopped) || {Req,_ReqId} <- Reqs],
+ _ = [gen_server:reply(Req, locker_stopped) || {Req,_ReqId} <- Reqs],
{stop, normal, stopped, State};
handle_call({stop,_Id}, _From, State) ->
{reply, stopped, State};
diff --git a/lib/common_test/src/ct_logs.erl b/lib/common_test/src/ct_logs.erl
index e6d683c8a9..53245c596a 100644
--- a/lib/common_test/src/ct_logs.erl
+++ b/lib/common_test/src/ct_logs.erl
@@ -137,7 +137,8 @@ close(Info, StartDir) ->
%% so we need to use a local copy of the log cache data
LogCacheBin =
case make_last_run_index() of
- {error,_} -> % log server not responding
+ {error, Reason} -> % log server not responding
+ io:format("Warning! ct_logs not responding: ~p~n", [Reason]),
undefined;
LCB ->
LCB
@@ -149,7 +150,7 @@ close(Info, StartDir) ->
ok;
CacheBin ->
%% save final version of the log cache to file
- file:write_file(?log_cache_name,CacheBin),
+ _ = file:write_file(?log_cache_name,CacheBin),
put(ct_log_cache,undefined)
end
end,
@@ -175,12 +176,12 @@ close(Info, StartDir) ->
Error ->
io:format("Warning! Cleanup failed: ~p~n", [Error])
end,
- make_all_suites_index(stop),
+ _ = make_all_suites_index(stop),
make_all_runs_index(stop),
Cache2File();
true ->
- file:set_cwd(".."),
- make_all_suites_index(stop),
+ ok = file:set_cwd(".."),
+ _ = make_all_suites_index(stop),
make_all_runs_index(stop),
Cache2File(),
case ct_util:get_profile_data(browser, StartDir) of
@@ -240,7 +241,7 @@ call(Msg) ->
Pid ->
MRef = erlang:monitor(process,Pid),
Ref = make_ref(),
- ?MODULE ! {Msg,{self(),Ref}},
+ Pid ! {Msg,{self(),Ref}},
receive
{Ref, Result} ->
erlang:demonitor(MRef, [flush]),
@@ -251,16 +252,30 @@ call(Msg) ->
end.
return({To,Ref},Result) ->
- To ! {Ref, Result}.
+ To ! {Ref, Result},
+ ok.
cast(Msg) ->
case whereis(?MODULE) of
undefined ->
- {error,does_not_exist};
+ io:format("Warning: ct_logs not started~n"),
+ {_,_,_,_,_,_,Content,_} = Msg,
+ FormatArgs = get_format_args(Content),
+ _ = [io:format(Format, Args) || {Format, Args} <- FormatArgs],
+ ok;
_Pid ->
- ?MODULE ! Msg
+ ?MODULE ! Msg,
+ ok
end.
+get_format_args(Content) ->
+ lists:map(fun(C) ->
+ case C of
+ {_, FA, _} -> FA;
+ {_, _} -> C
+ end
+ end, Content).
+
%%%-----------------------------------------------------------------
%%% @spec init_tc(RefreshLog) -> ok
%%%
@@ -631,7 +646,7 @@ logger(Parent, Mode, Verbosity) ->
end,
%%! <---
- file:make_dir(Dir),
+ _ = file:make_dir(Dir),
AbsDir = ?abs(Dir),
put(ct_run_dir, AbsDir),
@@ -671,7 +686,7 @@ logger(Parent, Mode, Verbosity) ->
end
end,
- test_server_io:start_link(),
+ _ = test_server_io:start_link(),
MiscIoName = filename:join(Dir, ?misc_io_log),
{ok,MiscIoFd} = file:open(MiscIoName,
[write,{encoding,utf8}]),
@@ -701,13 +716,13 @@ logger(Parent, Mode, Verbosity) ->
ct_event:notify(#event{name=start_logging,node=node(),
data=AbsDir}),
make_all_runs_index(start),
- make_all_suites_index(start),
+ _ = make_all_suites_index(start),
case Mode of
interactive -> interactive_link();
_ -> ok
end,
- file:set_cwd(Dir),
- make_last_run_index(Time),
+ ok = file:set_cwd(Dir),
+ _ = make_last_run_index(Time),
CtLogFd = open_ctlog(?misc_io_log),
io:format(CtLogFd,int_header()++int_footer(),
[log_timestamp(?now),"Common Test Logger started"]),
@@ -721,13 +736,13 @@ logger(Parent, Mode, Verbosity) ->
GenLvl -> io:format(CtLogFd, "~-25s~3w~n",
["general level",GenLvl])
end,
- [begin put({verbosity,Cat},VLvl),
- if Cat == '$unspecified' ->
+ _ = [begin put({verbosity,Cat},VLvl),
+ if Cat == '$unspecified' ->
ok;
- true ->
+ true ->
io:format(CtLogFd, "~-25w~3w~n", [Cat,VLvl])
- end
- end || {Cat,VLvl} <- Verbosity],
+ end
+ end || {Cat,VLvl} <- Verbosity],
io:nl(CtLogFd),
TcEscChars = case application:get_env(common_test, esc_chars) of
{ok,ECBool} -> ECBool;
@@ -804,7 +819,7 @@ logger_loop(State) ->
print_style(GL, IoFormat, State#logger_state.stylesheet),
set_evmgr_gl(GL),
TCGLs = add_tc_gl(TCPid,GL,State),
- if not RefreshLog ->
+ _ = if not RefreshLog ->
ok;
true ->
make_last_run_index(State#logger_state.start_time)
@@ -831,7 +846,7 @@ logger_loop(State) ->
return(From,{ok,filename:basename(State#logger_state.log_dir)}),
logger_loop(State);
{make_last_run_index,From} ->
- make_last_run_index(State#logger_state.start_time),
+ _ = make_last_run_index(State#logger_state.start_time),
return(From,get(ct_log_cache)),
logger_loop(State);
{set_stylesheet,_,SSFile} when State#logger_state.stylesheet ==
@@ -1169,7 +1184,7 @@ print_style_error(Fd, IoFormat, StyleSheet, Reason) ->
close_ctlog(Fd) ->
io:format(Fd, "\n</pre>\n", []),
io:format(Fd, [xhtml("<br><br>\n", "<br /><br />\n") | footer()], []),
- file:close(Fd).
+ ok = file:close(Fd).
%%%-----------------------------------------------------------------
%%% tc_io_format/3
@@ -1773,7 +1788,7 @@ count_cases(Dir) ->
%% file yet.
{0,0,0,0};
Summary ->
- write_summary(SumFile, Summary),
+ _ = write_summary(SumFile, Summary),
Summary
end;
{error, Reason} ->
@@ -2088,7 +2103,7 @@ interactive_link() ->
"</body>\n",
"</html>\n"
],
- file:write_file("last_interactive.html",unicode:characters_to_binary(Body)),
+ _ = file:write_file("last_interactive.html",unicode:characters_to_binary(Body)),
io:format("~n~nUpdated ~ts\n"
"Any CT activities will be logged here\n",
[?abs("last_interactive.html")]).
@@ -2219,9 +2234,9 @@ runentry(Dir, _, _) ->
write_totals_file(Name,Label,Logs,Totals) ->
AbsName = ?abs(Name),
notify_and_lock_file(AbsName),
- force_write_file(AbsName,
- term_to_binary({atom_to_list(node()),
- Label,Logs,Totals})),
+ _ = force_write_file(AbsName,
+ term_to_binary({atom_to_list(node()),
+ Label,Logs,Totals})),
notify_and_unlock_file(AbsName).
%% this function needs to convert from old formats to new so that old
@@ -2266,7 +2281,7 @@ read_totals_file(Name) ->
Result.
force_write_file(Name,Contents) ->
- force_delete(Name),
+ _ = force_delete(Name),
file:write_file(Name,Contents).
force_delete(Name) ->
@@ -2817,18 +2832,18 @@ get_cache_data({ok,CacheBin}) ->
true ->
{ok,CacheRec};
false ->
- file:delete(?log_cache_name),
+ _ = file:delete(?log_cache_name),
{error,old_cache_file}
end;
_ ->
- file:delete(?log_cache_name),
+ _ = file:delete(?log_cache_name),
{error,invalid_cache_file}
end;
get_cache_data(NoCache) ->
NoCache.
cache_vsn() ->
- application:load(common_test),
+ _ = application:load(common_test),
case application:get_key(common_test,vsn) of
{ok,VSN} ->
VSN;
diff --git a/lib/common_test/src/ct_master.erl b/lib/common_test/src/ct_master.erl
index c4905b316f..4eef27d2a5 100644
--- a/lib/common_test/src/ct_master.erl
+++ b/lib/common_test/src/ct_master.erl
@@ -376,7 +376,7 @@ init_master(Parent,NodeOptsList,EvHandlers,MasterLogDir,LogDirs,
end,
%% start master event manager and add default handler
- ct_master_event:start_link(),
+ {ok, _} = start_ct_master_event(),
ct_master_event:add_handler(),
%% add user handlers for master event manager
Add = fun({H,Args}) ->
@@ -398,6 +398,14 @@ init_master(Parent,NodeOptsList,EvHandlers,MasterLogDir,LogDirs,
end,
init_master1(Parent,NodeOptsList,InitOptions,LogDirs).
+start_ct_master_event() ->
+ case ct_master_event:start_link() of
+ {error, {already_started, Pid}} ->
+ {ok, Pid};
+ Else ->
+ Else
+ end.
+
init_master1(Parent,NodeOptsList,InitOptions,LogDirs) ->
{Inaccessible,NodeOptsList1,InitOptions1} = init_nodes(NodeOptsList,
InitOptions),
@@ -658,7 +666,7 @@ refresh_logs([D|Dirs],Refreshed) ->
{ok,Cwd} = file:get_cwd(),
case catch ct_run:refresh_logs(D) of
{'EXIT',Reason} ->
- file:set_cwd(Cwd),
+ ok = file:set_cwd(Cwd),
refresh_logs(Dirs,[{D,{error,Reason}}|Refreshed]);
Result ->
refresh_logs(Dirs,[{D,Result}|Refreshed])
@@ -701,7 +709,7 @@ init_node_ctrl(MasterPid,Cookie,Opts) ->
end,
%% start a local event manager
- ct_event:start_link(),
+ {ok, _} = start_ct_event(),
ct_event:add_handler([{master,MasterPid}]),
%% log("Running test with options: ~p~n", [Opts]),
@@ -721,6 +729,14 @@ init_node_ctrl(MasterPid,Cookie,Opts) ->
"Can't report result!~n~n", [MasterNode])
end.
+start_ct_event() ->
+ case ct_event:start_link() of
+ {error, {already_started, Pid}} ->
+ {ok, Pid};
+ Else ->
+ Else
+ end.
+
%%%-----------------------------------------------------------------
%%% Event handling
%%%-----------------------------------------------------------------
@@ -778,7 +794,7 @@ reply(Result,To) ->
ok.
init_nodes(NodeOptions, InitOptions)->
- ping_nodes(NodeOptions),
+ _ = ping_nodes(NodeOptions),
start_nodes(InitOptions),
eval_on_nodes(InitOptions),
{Inaccessible, NodeOptions1}=ping_nodes(NodeOptions),
diff --git a/lib/common_test/src/ct_master_logs.erl b/lib/common_test/src/ct_master_logs.erl
index 39f87a7f09..a2542171f8 100644
--- a/lib/common_test/src/ct_master_logs.erl
+++ b/lib/common_test/src/ct_master_logs.erl
@@ -91,8 +91,8 @@ init(Parent,LogDir,Nodes) ->
Time = calendar:local_time(),
RunDir = make_dirname(Time),
RunDirAbs = filename:join(LogDir,RunDir),
- file:make_dir(RunDirAbs),
- write_details_file(RunDirAbs,{node(),Nodes}),
+ ok = make_dir(RunDirAbs),
+ _ = write_details_file(RunDirAbs,{node(),Nodes}),
case basic_html() of
true ->
@@ -128,7 +128,7 @@ init(Parent,LogDir,Nodes) ->
end
end,
- make_all_runs_index(LogDir),
+ _ = make_all_runs_index(LogDir),
CtLogFd = open_ct_master_log(RunDirAbs),
NodeStr =
lists:flatten(lists:map(fun(N) ->
@@ -181,7 +181,7 @@ loop(State) ->
lists:foreach(Fun,List),
loop(State);
{make_all_runs_index,From} ->
- make_all_runs_index(State#state.logdir),
+ _ = make_all_runs_index(State#state.logdir),
return(From,State#state.logdir),
loop(State);
{{nodedir,Node,RunDir},From} ->
@@ -189,12 +189,12 @@ loop(State) ->
return(From,ok),
loop(State);
stop ->
- make_all_runs_index(State#state.logdir),
+ _ = make_all_runs_index(State#state.logdir),
io:format(State#state.log_fd,
int_header()++int_footer(),
[log_timestamp(?now),"Finished!"]),
- close_ct_master_log(State#state.log_fd),
- close_nodedir_index(State#state.nodedir_ix_fd),
+ _ = close_ct_master_log(State#state.log_fd),
+ _ = close_nodedir_index(State#state.nodedir_ix_fd),
ok
end.
@@ -496,7 +496,7 @@ make_relative(Dir) ->
ct_logs:make_relative(Dir).
force_write_file(Name,Contents) ->
- force_delete(Name),
+ _ = force_delete(Name),
file:write_file(Name,Contents).
force_delete(Name) ->
@@ -534,13 +534,34 @@ call(Msg) ->
end.
return({To,Ref},Result) ->
- To ! {Ref, Result}.
+ To ! {Ref, Result},
+ ok.
cast(Msg) ->
case whereis(?MODULE) of
undefined ->
- {error,does_not_exist};
+ io:format("Warning: ct_master_logs not started~n"),
+ {_,_,Content} = Msg,
+ FormatArgs = get_format_args(Content),
+ _ = [io:format(Format, Args) || {Format, Args} <- FormatArgs],
+ ok;
_Pid ->
- ?MODULE ! Msg
+ ?MODULE ! Msg,
+ ok
end.
+get_format_args(Content) ->
+ lists:map(fun(C) ->
+ case C of
+ {_, FA, _} -> FA;
+ _ -> C
+ end
+ end, Content).
+
+make_dir(Dir) ->
+ case file:make_dir(Dir) of
+ {error, exist} ->
+ ok;
+ Else ->
+ Else
+ end.
diff --git a/lib/common_test/src/ct_property_test.erl b/lib/common_test/src/ct_property_test.erl
index 7dc78e949a..12c3d726d3 100644
--- a/lib/common_test/src/ct_property_test.erl
+++ b/lib/common_test/src/ct_property_test.erl
@@ -161,7 +161,9 @@ property_tests_path(Dir, Config) ->
add_code_pathz(Dir) ->
case lists:member(Dir, code:get_path()) of
true -> ok;
- false -> code:add_pathz(Dir)
+ false ->
+ true = code:add_pathz(Dir),
+ ok
end.
compile_tests(Path, ToolModule) ->
@@ -171,10 +173,10 @@ compile_tests(Path, ToolModule) ->
{ok,FileNames} = file:list_dir("."),
BeamFiles = [F || F<-FileNames,
filename:extension(F) == ".beam"],
- [file:delete(F) || F<-BeamFiles],
+ _ = [file:delete(F) || F<-BeamFiles],
ct:pal("Compiling in ~p:~n Deleted ~p~n MacroDefs=~p",[Path,BeamFiles,MacroDefs]),
Result = make:all([load|MacroDefs]),
- file:set_cwd(Cwd),
+ ok = file:set_cwd(Cwd),
Result.
diff --git a/lib/common_test/src/ct_release_test.erl b/lib/common_test/src/ct_release_test.erl
index 4e0f88cf5f..d783f8d04e 100644
--- a/lib/common_test/src/ct_release_test.erl
+++ b/lib/common_test/src/ct_release_test.erl
@@ -342,7 +342,7 @@ cleanup(Config) ->
end
end,
AllNodes),
- [rpc:call(Node,erlang,halt,[]) || Node <- Nodes],
+ _ = [rpc:call(Node,erlang,halt,[]) || Node <- Nodes],
Config.
%%-----------------------------------------------------------------
@@ -552,14 +552,14 @@ target_system(Apps,CreateDir,InstallDir,{FromVsn,_,AllAppsVsns,Path}) ->
%% Add bin and log dirs
BinDir = filename:join([InstallDir, "bin"]),
- file:make_dir(BinDir),
- file:make_dir(filename:join(InstallDir,"log")),
+ ok = make_dir(BinDir),
+ ok = make_dir(filename:join(InstallDir,"log")),
%% Delete start scripts - they will be added later
ErtsBinDir = filename:join([InstallDir, "erts-" ++ ErtsVsn, "bin"]),
- file:delete(filename:join([ErtsBinDir, "erl"])),
- file:delete(filename:join([ErtsBinDir, "start"])),
- file:delete(filename:join([ErtsBinDir, "start_erl"])),
+ ok = delete_file(filename:join([ErtsBinDir, "erl"])),
+ ok = delete_file(filename:join([ErtsBinDir, "start"])),
+ ok = delete_file(filename:join([ErtsBinDir, "start_erl"])),
%% Copy .boot to bin/start.boot
copy_file(RelName++".boot",filename:join([BinDir, "start.boot"])),
@@ -680,7 +680,7 @@ do_upgrade({Cb,InitState},FromVsn,FromAppsVsns,ToRel,ToAppsVsns,InstallDir) ->
%% even if install_release returned {ok,...} there might be an
%% emulator restart (instruction restart_emulator), so we must
%% always make sure the node is running.
- wait_node_up(current,ToVsn,ToAppsVsns),
+ {ok, _} = wait_node_up(current,ToVsn,ToAppsVsns),
[{"OTP upgrade test",ToVsn,_,current},
{"OTP upgrade test",FromVsn,_,permanent}] =
@@ -703,7 +703,7 @@ do_upgrade({Cb,InitState},FromVsn,FromAppsVsns,ToRel,ToAppsVsns,InstallDir) ->
%% even if install_release returned {ok,...} there might be an
%% emulator restart (instruction restart_emulator), so we must
%% always make sure the node is running.
- wait_node_up(current,FromVsn,FromAppsVsns),
+ {ok, _} = wait_node_up(current,FromVsn,FromAppsVsns),
[{"OTP upgrade test",ToVsn,_,permanent},
{"OTP upgrade test",FromVsn,_,current}] =
@@ -854,7 +854,7 @@ copy_file(Src, Dest, Opts) ->
case lists:member(preserve, Opts) of
true ->
{ok, FileInfo} = file:read_file_info(Src),
- file:write_file_info(Dest, FileInfo);
+ ok = file:write_file_info(Dest, FileInfo);
false ->
ok
end.
@@ -862,8 +862,8 @@ copy_file(Src, Dest, Opts) ->
write_file(FName, Conts) ->
Enc = file:native_name_encoding(),
{ok, Fd} = file:open(FName, [write]),
- file:write(Fd, unicode:characters_to_binary(Conts,Enc,Enc)),
- file:close(Fd).
+ ok = file:write(Fd, unicode:characters_to_binary(Conts,Enc,Enc)),
+ ok = file:close(Fd).
%% Substitute all occurrences of %Var% for Val in the given scripts
subst_src_scripts(Scripts, SrcDir, DestDir, Vars, Opts) ->
@@ -944,3 +944,19 @@ rm_rf(Dir) ->
_ ->
ok
end.
+
+delete_file(FileName) ->
+ case file:delete(FileName) of
+ {error, enoent} ->
+ ok;
+ Else ->
+ Else
+ end.
+
+make_dir(Dir) ->
+ case file:make_dir(Dir) of
+ {error, eexist} ->
+ ok;
+ Else ->
+ Else
+ end.
diff --git a/lib/common_test/src/ct_repeat.erl b/lib/common_test/src/ct_repeat.erl
index 31c5755c7e..dac596a135 100644
--- a/lib/common_test/src/ct_repeat.erl
+++ b/lib/common_test/src/ct_repeat.erl
@@ -44,13 +44,13 @@ loop_test(If,Args) when is_list(Args) ->
false;
E = {error,_} ->
io:format("Common Test error: ~p\n\n",[E]),
- file:set_cwd(Cwd),
+ ok = file:set_cwd(Cwd),
E;
{repeat,N} ->
io:format("\nCommon Test: Will repeat tests ~w times.\n\n",[N]),
Args1 = [{loop_info,[{repeat,1,N}]} | Args],
Result = loop(If,repeat,0,N,undefined,Args1,undefined,[]),
- file:set_cwd(Cwd),
+ ok = file:set_cwd(Cwd),
Result;
{stop_time,StopTime} ->
Result =
@@ -76,7 +76,7 @@ loop_test(If,Args) when is_list(Args) ->
Args1 = [{loop_info,[{stop_time,Secs,StopTime,1}]} | Args],
loop(If,stop_time,0,Secs,StopTime,Args1,TPid,[])
end,
- file:set_cwd(Cwd),
+ ok = file:set_cwd(Cwd),
Result
end.
diff --git a/lib/common_test/src/ct_rpc.erl b/lib/common_test/src/ct_rpc.erl
index cbcc212bb8..b4a0bc9d74 100644
--- a/lib/common_test/src/ct_rpc.erl
+++ b/lib/common_test/src/ct_rpc.erl
@@ -81,7 +81,7 @@ app_node(App, [], _, _) ->
app_node(App, _Candidates = [CandidateNode | Nodes], FailOnBadRPC, Cookie) ->
Cookie0 = set_the_cookie(Cookie),
Result = rpc:call(CandidateNode, application, which_applications, []),
- set_the_cookie(Cookie0),
+ _ = set_the_cookie(Cookie0),
case Result of
{badrpc,Reason} when FailOnBadRPC == true ->
ct:fail({Reason,CandidateNode});
@@ -145,7 +145,7 @@ call({Fun, FunArgs}, Module, Function, Args, TimeOut, Cookie) ->
call(Node, Module, Function, Args, TimeOut, Cookie) when is_atom(Node) ->
Cookie0 = set_the_cookie(Cookie),
Result = rpc:call(Node, Module, Function, Args, TimeOut),
- set_the_cookie(Cookie0),
+ _ = set_the_cookie(Cookie0),
Result.
%%% @spec cast(Node, Module, Function, Args) -> ok
@@ -190,7 +190,7 @@ cast({Fun, FunArgs}, Module, Function, Args, Cookie) ->
cast(Node, Module, Function, Args, Cookie) when is_atom(Node) ->
Cookie0 = set_the_cookie(Cookie),
true = rpc:cast(Node, Module, Function, Args),
- set_the_cookie(Cookie0),
+ _ = set_the_cookie(Cookie0),
ok.
diff --git a/lib/common_test/src/ct_run.erl b/lib/common_test/src/ct_run.erl
index 1e5f935198..fbb9c7ab60 100644
--- a/lib/common_test/src/ct_run.erl
+++ b/lib/common_test/src/ct_run.erl
@@ -400,21 +400,21 @@ run_or_refresh(Opts = #opts{logdir = LogDir}, Args) ->
[RefreshDir] -> ?abs(RefreshDir)
end,
{ok,Cwd} = file:get_cwd(),
- file:set_cwd(LogDir1),
+ ok = file:set_cwd(LogDir1),
%% give the shell time to print version etc
timer:sleep(500),
io:nl(),
case catch ct_logs:make_all_runs_index(refresh) of
{'EXIT',ARReason} ->
- file:set_cwd(Cwd),
+ ok = file:set_cwd(Cwd),
{error,{all_runs_index,ARReason}};
_ ->
case catch ct_logs:make_all_suites_index(refresh) of
{'EXIT',ASReason} ->
- file:set_cwd(Cwd),
+ ok = file:set_cwd(Cwd),
{error,{all_suites_index,ASReason}};
_ ->
- file:set_cwd(Cwd),
+ ok = file:set_cwd(Cwd),
io:format("Logs in ~ts refreshed!~n~n",
[LogDir1]),
timer:sleep(500), % time to flush io before quitting
@@ -756,8 +756,8 @@ script_start4(#opts{label = Label, profile = Profile,
{ct_hooks, CTHooks},
{enable_builtin_hooks,EnableBuiltinHooks}]) of
ok ->
- ct_util:start(interactive, LogDir,
- add_verbosity_defaults(Verbosity)),
+ _ = ct_util:start(interactive, LogDir,
+ add_verbosity_defaults(Verbosity)),
ct_util:set_testdata({logopts, LogOpts}),
log_ts_names(Specs),
io:nl(),
@@ -901,9 +901,8 @@ install(Opts, LogDir) ->
VarFile = variables_file_name(LogDir),
case file:open(VarFile, [write]) of
{ok,Fd} ->
- [io:format(Fd, "~p.\n", [Opt]) || Opt <- ConfOpts ],
- file:close(Fd),
- ok;
+ _ = [io:format(Fd, "~p.\n", [Opt]) || Opt <- ConfOpts],
+ ok = file:close(Fd);
{error,Reason} ->
io:format("CT failed to install configuration data. Please "
"verify that the log directory exists and that "
@@ -960,7 +959,7 @@ run_test1(StartOpts) when is_list(StartOpts) ->
false ->
case catch run_test2(StartOpts) of
{'EXIT',Reason} ->
- file:set_cwd(Cwd),
+ ok = file:set_cwd(Cwd),
{error,Reason};
Result ->
Result
@@ -971,7 +970,7 @@ run_test1(StartOpts) when is_list(StartOpts) ->
stop_trace(Tracing),
exit(Res);
RefreshDir ->
- refresh_logs(?abs(RefreshDir)),
+ ok = refresh_logs(?abs(RefreshDir)),
exit(done)
end.
@@ -1209,7 +1208,6 @@ run_all_specs([], _, _, TotResult) ->
end;
run_all_specs([{Specs,TS} | TSs], Opts, StartOpts, TotResult) ->
- log_ts_names(Specs),
Combined = #opts{config = TSConfig} = combine_test_opts(TS, Specs, Opts),
AllConfig = merge_vals([Opts#opts.config, TSConfig]),
try run_one_spec(TS,
@@ -1430,7 +1428,7 @@ run_testspec1(TestSpec) ->
io:format("~nCommon Test starting (cwd is ~ts)~n~n", [Cwd]),
case catch run_testspec2(TestSpec) of
{'EXIT',Reason} ->
- file:set_cwd(Cwd),
+ ok = file:set_cwd(Cwd),
exit({error,Reason});
Result ->
exit(Result)
@@ -1562,15 +1560,15 @@ refresh_logs(LogDir) ->
_ ->
case catch ct_logs:make_all_suites_index(refresh) of
{'EXIT',ASReason} ->
- file:set_cwd(Cwd),
+ ok = file:set_cwd(Cwd),
{error,{all_suites_index,ASReason}};
_ ->
case catch ct_logs:make_all_runs_index(refresh) of
{'EXIT',ARReason} ->
- file:set_cwd(Cwd),
+ ok = file:set_cwd(Cwd),
{error,{all_runs_index,ARReason}};
_ ->
- file:set_cwd(Cwd),
+ ok = file:set_cwd(Cwd),
io:format("Logs in ~ts refreshed!~n",[LogDir]),
ok
end
@@ -1610,22 +1608,34 @@ delistify(E) -> E.
%%% @hidden
%%% @equiv ct:run/3
run(TestDir, Suite, Cases) ->
- install([]),
- reformat_result(catch do_run(tests(TestDir, Suite, Cases), [])).
+ case install([]) of
+ ok ->
+ reformat_result(catch do_run(tests(TestDir, Suite, Cases), []));
+ Error ->
+ Error
+ end.
%%%-----------------------------------------------------------------
%%% @hidden
%%% @equiv ct:run/2
run(TestDir, Suite) when is_list(TestDir), is_integer(hd(TestDir)) ->
- install([]),
- reformat_result(catch do_run(tests(TestDir, Suite), [])).
+ case install([]) of
+ ok ->
+ reformat_result(catch do_run(tests(TestDir, Suite), []));
+ Error ->
+ Error
+ end.
%%%-----------------------------------------------------------------
%%% @hidden
%%% @equiv ct:run/1
run(TestDirs) ->
- install([]),
- reformat_result(catch do_run(tests(TestDirs), [])).
+ case install([]) of
+ ok ->
+ reformat_result(catch do_run(tests(TestDirs), []));
+ Error ->
+ Error
+ end.
reformat_result({'EXIT',{user_error,Reason}}) ->
{error,Reason};
@@ -2017,7 +2027,7 @@ save_make_errors(Errors) ->
"Error compiling or locating the "
"following suites: ~n~p",[Suites]),
%% save the info for logger
- file:write_file(?missing_suites_info,term_to_binary(Errors)),
+ ok = file:write_file(?missing_suites_info,term_to_binary(Errors)),
Errors.
get_bad_suites([{{_TestDir,_Suite},Failed}|Errors], BadSuites) ->
@@ -2234,7 +2244,7 @@ do_run_test(Tests, Skip, Opts0) ->
end,
application:set_env(test_server, esc_chars, EscChars),
- test_server_ctrl:start_link(local),
+ {ok, _} = test_server_ctrl:start_link(local),
%% let test_server expand the test tuples and count no of cases
{Suites,NoOfCases} = count_test_cases(Tests, Skip),
@@ -2295,7 +2305,7 @@ do_run_test(Tests, Skip, Opts0) ->
lists:foreach(fun(Suite) ->
maybe_cleanup_interpret(Suite, Opts#opts.step)
end, CleanUp),
- [code:del_path(Dir) || Dir <- AddedToPath],
+ _ = [code:del_path(Dir) || Dir <- AddedToPath],
%% If a severe error has occurred in the test_server,
%% we will generate an exception here.
@@ -2422,7 +2432,7 @@ count_test_cases(Tests, Skip) ->
SendResult = fun(Me, Result) -> Me ! {no_of_cases,Result} end,
TSPid = test_server_ctrl:start_get_totals(SendResult),
Ref = erlang:monitor(process, TSPid),
- add_jobs(Tests, Skip, #opts{}, []),
+ _ = add_jobs(Tests, Skip, #opts{}, []),
Counted = (catch count_test_cases1(length(Tests), 0, [], Ref)),
erlang:demonitor(Ref, [flush]),
case Counted of
@@ -2776,14 +2786,14 @@ maybe_interpret1(Suite, Cases, StepOpts) when is_list(Cases) ->
maybe_interpret2(Suite, Cases, StepOpts) ->
set_break_on_config(Suite, StepOpts),
- [begin try i:ib(Suite, Case, 1) of
+ _ = [begin try i:ib(Suite, Case, 1) of
_ -> ok
catch
_:_Error ->
io:format(user, "Invalid breakpoint: ~w:~w/1~n",
[Suite,Case])
end
- end || Case <- Cases, is_atom(Case)],
+ end || Case <- Cases, is_atom(Case)],
test_server_ctrl:multiply_timetraps(infinity),
WinOp = case lists:member(keep_inactive, ensure_atom(StepOpts)) of
true -> no_kill;
@@ -2802,12 +2812,12 @@ set_break_on_config(Suite, StepOpts) ->
false -> ok
end
end,
- SetBPIfExists(init_per_suite, 1),
- SetBPIfExists(init_per_group, 2),
- SetBPIfExists(init_per_testcase, 2),
- SetBPIfExists(end_per_testcase, 2),
- SetBPIfExists(end_per_group, 2),
- SetBPIfExists(end_per_suite, 1);
+ ok = SetBPIfExists(init_per_suite, 1),
+ ok = SetBPIfExists(init_per_group, 2),
+ ok = SetBPIfExists(init_per_testcase, 2),
+ ok = SetBPIfExists(end_per_testcase, 2),
+ ok = SetBPIfExists(end_per_group, 2),
+ ok = SetBPIfExists(end_per_suite, 1);
false ->
ok
end.
@@ -2984,31 +2994,31 @@ add_verbosity_defaults(VLvls) ->
%% relative dirs "post run_test erl_args" is not kept!
rel_to_abs(CtArgs) ->
{PA,PZ} = get_pa_pz(CtArgs, [], []),
- [begin
+ _ = [begin
Dir = rm_trailing_slash(D),
Abs = make_abs(Dir),
- if Dir /= Abs ->
- code:del_path(Dir),
- code:del_path(Abs),
+ _ = if Dir /= Abs ->
+ _ = code:del_path(Dir),
+ _ = code:del_path(Abs),
io:format(user, "Converting ~p to ~p and re-inserting "
"with add_pathz/1~n",
[Dir, Abs]);
true ->
- code:del_path(Dir)
+ _ = code:del_path(Dir)
end,
code:add_pathz(Abs)
end || D <- PZ],
- [begin
+ _ = [begin
Dir = rm_trailing_slash(D),
Abs = make_abs(Dir),
- if Dir /= Abs ->
- code:del_path(Dir),
- code:del_path(Abs),
+ _ = if Dir /= Abs ->
+ _ = code:del_path(Dir),
+ _ = code:del_path(Abs),
io:format(user, "Converting ~p to ~p and re-inserting "
"with add_patha/1~n",
[Dir, Abs]);
true ->
- code:del_path(Dir)
+ _ = code:del_path(Dir)
end,
code:add_patha(Abs)
end || D <- PA],
diff --git a/lib/common_test/src/ct_slave.erl b/lib/common_test/src/ct_slave.erl
index 3ad3937548..571958ca03 100644
--- a/lib/common_test/src/ct_slave.erl
+++ b/lib/common_test/src/ct_slave.erl
@@ -325,7 +325,7 @@ do_start(Host, Node, Options) ->
Functions
end,
MasterHost = gethostname(),
- if
+ _ = if
MasterHost == Host ->
spawn_local_node(Node, Options);
true->
@@ -359,7 +359,7 @@ do_start(Host, Node, Options) ->
pang->
{error, boot_timeout, ENode}
end,
- case Result of
+ _ = case Result of
{ok, ENode}->
ok;
{error, Timeout, ENode}
@@ -422,7 +422,7 @@ spawn_remote_node(Host, Node, Options) ->
{_, _}->
[{user, Username}, {password, Password}]
end ++ [{silently_accept_hosts, true}] ++ SSHOpts,
- application:ensure_all_started(ssh),
+ {ok, _} = application:ensure_all_started(ssh),
{ok, SSHConnRef} = ssh:connect(atom_to_list(Host), SSHPort, SSHOptions),
{ok, SSHChannelId} = ssh_connection:session_channel(SSHConnRef, infinity),
ssh_setenv(SSHConnRef, SSHChannelId, Env),
diff --git a/lib/common_test/src/ct_snmp.erl b/lib/common_test/src/ct_snmp.erl
index bb0167eb22..2c59b19196 100644
--- a/lib/common_test/src/ct_snmp.erl
+++ b/lib/common_test/src/ct_snmp.erl
@@ -221,9 +221,17 @@ start(Config, MgrAgentConfName, SnmpAppConfName) ->
Config, SysName, AgentManagerIP, IP),
setup_manager(StartManager, MgrAgentConfName, SnmpAppConfName,
Config, AgentManagerIP),
- application:start(snmp),
+ ok = start_application(snmp),
manager_register(StartManager, MgrAgentConfName).
+
+start_application(App) ->
+ case application:start(App) of
+ {error, {already_started, App}} ->
+ ok;
+ Else ->
+ Else
+ end.
%%% @spec stop(Config) -> ok
%%% Config = [{Key, Value}]
@@ -233,8 +241,8 @@ start(Config, MgrAgentConfName, SnmpAppConfName) ->
%%% @doc Stops the snmp manager and/or agent removes all files created.
stop(Config) ->
PrivDir = ?config(priv_dir, Config),
- application:stop(snmp),
- application:stop(mnesia),
+ ok = application:stop(snmp),
+ ok = application:stop(mnesia),
MgrDir = filename:join(PrivDir,"mgr"),
ConfDir = filename:join(PrivDir, "conf"),
DbDir = filename:join(PrivDir,"db"),
@@ -311,7 +319,7 @@ set_info(Config) ->
SetLogFile = filename:join(PrivDir, ?CT_SNMP_LOG_FILE),
case file:consult(SetLogFile) of
{ok, SetInfo} ->
- file:delete(SetLogFile),
+ ok = delete_file(SetLogFile),
lists:reverse(SetInfo);
_ ->
[]
@@ -513,7 +521,7 @@ unload_mibs(Mibs) ->
prepare_snmp_env() ->
%% To make sure application:set_env is not overwritten by any
%% app-file settings.
- application:load(snmp),
+ _ = application:load(snmp),
%% Fix for older versions of snmp where there are some
%% inappropriate default values for alway starting an
@@ -533,7 +541,7 @@ setup_manager(true, MgrConfName, SnmpConfName, Config, IP) ->
Users = [],
Agents = [],
Usms = [],
- file:make_dir(MgrDir),
+ ok = make_dir(MgrDir),
snmp_config:write_manager_snmp_files(MgrDir, IP, Port, MaxMsgSize,
EngineID, Users, Agents, Usms),
@@ -549,7 +557,7 @@ setup_agent(false,_, _, _, _, _, _) ->
ok;
setup_agent(true, AgentConfName, SnmpConfName,
Config, SysName, ManagerIP, AgentIP) ->
- application:start(mnesia),
+ ok = start_application(mnesia),
PrivDir = ?config(priv_dir, Config),
Vsns = ct:get_config({AgentConfName, agent_vsns}, ?CONF_FILE_VER),
TrapUdp = ct:get_config({AgentConfName, agent_trap_udp}, ?TRAP_UDP),
@@ -565,8 +573,8 @@ setup_agent(true, AgentConfName, SnmpConfName,
ConfDir = filename:join(PrivDir, "conf"),
DbDir = filename:join(PrivDir,"db"),
- file:make_dir(ConfDir),
- file:make_dir(DbDir),
+ ok = make_dir(ConfDir),
+ ok = make_dir(DbDir),
snmp_config:write_agent_snmp_files(ConfDir, Vsns, ManagerIP, TrapUdp,
AgentIP, AgentUdp, SysName,
NotifType, SecType, Passwd,
@@ -684,7 +692,7 @@ log(PrivDir, Agent, {_, _, Varbinds}, NewVarsAndVals) ->
File = filename:join(PrivDir, ?CT_SNMP_LOG_FILE),
{ok, Fd} = file:open(File, [write, append]),
io:format(Fd, "~p.~n", [{Agent, OldVarsAndVals, NewVarsAndVals}]),
- file:close(Fd),
+ ok = file:close(Fd),
ok.
%%%---------------------------------------------------------------------------
del_dir(Dir) ->
@@ -692,7 +700,7 @@ del_dir(Dir) ->
FullPathFiles = lists:map(fun(File) -> filename:join(Dir, File) end,
Files),
lists:foreach(fun file:delete/1, FullPathFiles),
- file:del_dir(Dir),
+ ok = delete_dir(Dir),
ok.
%%%---------------------------------------------------------------------------
agent_conf(Agent, MgrAgentConfName) ->
@@ -738,8 +746,8 @@ override_contexts(Config, {data_dir_file, File}) ->
override_contexts(Config, Contexts) ->
Dir = filename:join(?config(priv_dir, Config),"conf"),
File = filename:join(Dir,"context.conf"),
- file:delete(File),
- snmp_config:write_agent_context_config(Dir, "", Contexts).
+ ok = delete_file(File),
+ ok = snmp_config:write_agent_context_config(Dir, "", Contexts).
%%%---------------------------------------------------------------------------
override_sysinfo(_, undefined) ->
@@ -754,8 +762,8 @@ override_sysinfo(Config, {data_dir_file, File}) ->
override_sysinfo(Config, SysInfo) ->
Dir = filename:join(?config(priv_dir, Config),"conf"),
File = filename:join(Dir,"standard.conf"),
- file:delete(File),
- snmp_config:write_agent_standard_config(Dir, "", SysInfo).
+ ok = delete_file(File),
+ ok = snmp_config:write_agent_standard_config(Dir, "", SysInfo).
%%%---------------------------------------------------------------------------
override_target_address(_, undefined) ->
@@ -769,8 +777,8 @@ override_target_address(Config, {data_dir_file, File}) ->
override_target_address(Config, TargetAddressConf) ->
Dir = filename:join(?config(priv_dir, Config),"conf"),
File = filename:join(Dir,"target_addr.conf"),
- file:delete(File),
- snmp_config:write_agent_target_addr_config(Dir, "", TargetAddressConf).
+ ok = delete_file(File),
+ ok = snmp_config:write_agent_target_addr_config(Dir, "", TargetAddressConf).
%%%---------------------------------------------------------------------------
@@ -785,8 +793,8 @@ override_target_params(Config, {data_dir_file, File}) ->
override_target_params(Config, TargetParamsConf) ->
Dir = filename:join(?config(priv_dir, Config),"conf"),
File = filename:join(Dir,"target_params.conf"),
- file:delete(File),
- snmp_config:write_agent_target_params_config(Dir, "", TargetParamsConf).
+ ok = delete_file(File),
+ ok = snmp_config:write_agent_target_params_config(Dir, "", TargetParamsConf).
%%%---------------------------------------------------------------------------
override_notify(_, undefined) ->
@@ -800,8 +808,8 @@ override_notify(Config, {data_dir_file, File}) ->
override_notify(Config, NotifyConf) ->
Dir = filename:join(?config(priv_dir, Config),"conf"),
File = filename:join(Dir,"notify.conf"),
- file:delete(File),
- snmp_config:write_agent_notify_config(Dir, "", NotifyConf).
+ ok = delete_file(File),
+ ok = snmp_config:write_agent_notify_config(Dir, "", NotifyConf).
%%%---------------------------------------------------------------------------
override_usm(_, undefined) ->
@@ -815,8 +823,8 @@ override_usm(Config, {data_dir_file, File}) ->
override_usm(Config, UsmConf) ->
Dir = filename:join(?config(priv_dir, Config),"conf"),
File = filename:join(Dir,"usm.conf"),
- file:delete(File),
- snmp_config:write_agent_usm_config(Dir, "", UsmConf).
+ ok = delete_file(File),
+ ok = snmp_config:write_agent_usm_config(Dir, "", UsmConf).
%%%--------------------------------------------------------------------------
override_community(_, undefined) ->
@@ -830,8 +838,8 @@ override_community(Config, {data_dir_file, File}) ->
override_community(Config, CommunityConf) ->
Dir = filename:join(?config(priv_dir, Config),"conf"),
File = filename:join(Dir,"community.conf"),
- file:delete(File),
- snmp_config:write_agent_community_config(Dir, "", CommunityConf).
+ ok = delete_file(File),
+ ok = snmp_config:write_agent_community_config(Dir, "", CommunityConf).
%%%---------------------------------------------------------------------------
@@ -846,8 +854,8 @@ override_vacm(Config, {data_dir_file, File}) ->
override_vacm(Config, VacmConf) ->
Dir = filename:join(?config(priv_dir, Config),"conf"),
File = filename:join(Dir,"vacm.conf"),
- file:delete(File),
- snmp_config:write_agent_vacm_config(Dir, "", VacmConf).
+ ok = delete_file(File),
+ ok = snmp_config:write_agent_vacm_config(Dir, "", VacmConf).
%%%---------------------------------------------------------------------------
@@ -861,3 +869,21 @@ while_ok(Fun,[H|T]) ->
end;
while_ok(_Fun,[]) ->
ok.
+
+delete_file(FileName) ->
+ case file:delete(FileName) of
+ {error, enoent} -> ok;
+ Else -> Else
+ end.
+
+make_dir(Dir) ->
+ case file:make_dir(Dir) of
+ {error, eexist} -> ok;
+ Else -> Else
+ end.
+
+delete_dir(Dir) ->
+ case file:del_dir(Dir) of
+ {error, enoent} -> ok;
+ Else -> Else
+ end.
diff --git a/lib/common_test/src/ct_ssh.erl b/lib/common_test/src/ct_ssh.erl
index 92d912052e..6ab3bf036c 100644
--- a/lib/common_test/src/ct_ssh.erl
+++ b/lib/common_test/src/ct_ssh.erl
@@ -962,8 +962,8 @@ init(KeyOrName, {ConnType,Addr,Port}, AllOpts) ->
end, [], AllOpts1),
FinalOptions = [{silently_accept_hosts,true},
{user_interaction,false} | Options],
- crypto:start(),
- ssh:start(),
+ _ = crypto:start(),
+ _ = ssh:start(),
Result = case ConnType of
ssh ->
ssh:connect(Addr, Port, FinalOptions);
diff --git a/lib/common_test/src/ct_telnet.erl b/lib/common_test/src/ct_telnet.erl
index f5f4f648f4..8fb411ec4f 100644
--- a/lib/common_test/src/ct_telnet.erl
+++ b/lib/common_test/src/ct_telnet.erl
@@ -605,7 +605,7 @@ init(Name,{Ip,Port,Type},{TargetMod,KeepAlive,Extra}) ->
set_telnet_defaults(Settings,#state{})
end,
%% Handle old user versions of TargetMod
- code:ensure_loaded(TargetMod),
+ _ = code:ensure_loaded(TargetMod),
try
case erlang:function_exported(TargetMod,connect,7) of
true ->
@@ -688,7 +688,7 @@ handle_msg({cmd,Cmd,Opts},State) ->
debug_cont_gen_log("Throwing Buffer:",[]),
debug_log_lines(State#state.buffer),
- case {State#state.type,State#state.prompt} of
+ _ = case {State#state.type,State#state.prompt} of
{ts,_} ->
silent_teln_expect(State#state.name,
State#state.teln_pid,
@@ -735,7 +735,7 @@ handle_msg({send,Cmd,Opts},State) ->
debug_cont_gen_log("Throwing Buffer:",[]),
debug_log_lines(State#state.buffer),
- case {State#state.type,State#state.prompt} of
+ _ = case {State#state.type,State#state.prompt} of
{ts,_} ->
silent_teln_expect(State#state.name,
State#state.teln_pid,
diff --git a/lib/common_test/src/ct_telnet_client.erl b/lib/common_test/src/ct_telnet_client.erl
index 1f1311776f..5df7e279ac 100644
--- a/lib/common_test/src/ct_telnet_client.erl
+++ b/lib/common_test/src/ct_telnet_client.erl
@@ -272,7 +272,7 @@ send(Data, Sock, ConnName) ->
_:_ -> ok
end
end,
- gen_tcp:send(Sock, Data),
+ ok = gen_tcp:send(Sock, Data),
ok.
%% [IAC,IAC] = buffer data value 255
@@ -284,7 +284,7 @@ check_msg(Sock, [?IAC | Cs], Acc) ->
case get_cmd(Cs) of
{Cmd,Cs1} ->
cmd_dbg("Got",Cmd),
- respond_cmd(Cmd, Sock),
+ ok = respond_cmd(Cmd, Sock),
check_msg(Sock, Cs1, Acc);
error ->
Acc
diff --git a/lib/common_test/src/ct_util.erl b/lib/common_test/src/ct_util.erl
index d5a8e3fbc0..82a8743cf0 100644
--- a/lib/common_test/src/ct_util.erl
+++ b/lib/common_test/src/ct_util.erl
@@ -131,14 +131,14 @@ do_start(Parent, Mode, LogDir, Verbosity) ->
create_table(?suite_table,#suite_data.key),
create_table(?verbosity_table,1),
- [ets:insert(?verbosity_table,{Cat,Lvl}) || {Cat,Lvl} <- Verbosity],
+ _ = [ets:insert(?verbosity_table,{Cat,Lvl}) || {Cat,Lvl} <- Verbosity],
{ok,StartDir} = file:get_cwd(),
case file:set_cwd(LogDir) of
ok -> ok;
E -> exit(E)
end,
- DoExit = fun(Reason) -> file:set_cwd(StartDir), exit(Reason) end,
+ DoExit = fun(Reason) -> ok = file:set_cwd(StartDir), exit(Reason) end,
Opts = case read_opts() of
{ok,Opts1} ->
Opts1;
@@ -169,7 +169,7 @@ do_start(Parent, Mode, LogDir, Verbosity) ->
end,
%% add user event handlers
- case lists:keysearch(event_handler,1,Opts) of
+ _ = case lists:keysearch(event_handler,1,Opts) of
{value,{_,Handlers}} ->
Add = fun({H,Args}) ->
case catch gen_event:add_handler(?CT_EVMGR_REF,H,Args) of
@@ -195,7 +195,7 @@ do_start(Parent, Mode, LogDir, Verbosity) ->
data={StartTime,
lists:flatten(TestLogDir)}}),
%% Initialize ct_hooks
- try ct_hooks:init(Opts) of
+ _ = try ct_hooks:init(Opts) of
ok ->
Parent ! {self(),started};
{fail,CTHReason} ->
@@ -228,7 +228,8 @@ create_table(TableName,KeyPos) ->
create_table(TableName,set,KeyPos).
create_table(TableName,Type,KeyPos) ->
catch ets:delete(TableName),
- ets:new(TableName,[Type,named_table,public,{keypos,KeyPos}]).
+ _ = ets:new(TableName,[Type,named_table,public,{keypos,KeyPos}]),
+ ok.
read_opts() ->
case file:consult(ct_run:variables_file_name("./")) of
@@ -473,7 +474,7 @@ loop(Mode,TestData,StartDir) ->
ct_logs:close(Info, StartDir),
ct_event:stop(),
ct_config:stop(),
- file:set_cwd(StartDir),
+ ok = file:set_cwd(StartDir),
return(From, Info);
{Ref, _Msg} when is_reference(Ref) ->
%% This clause is used when doing cast operations.
@@ -505,7 +506,7 @@ loop(Mode,TestData,StartDir) ->
%% Let process crash in case of error, this shouldn't happen!
io:format("\n\nct_util_server got EXIT "
"from ~w: ~p\n\n", [Pid,Reason]),
- file:set_cwd(StartDir),
+ ok = file:set_cwd(StartDir),
exit(Reason)
end
end.
@@ -1035,10 +1036,12 @@ call(Msg, Timeout) ->
end.
return({To,Ref},Result) ->
- To ! {Ref, Result}.
+ To ! {Ref, Result},
+ ok.
cast(Msg) ->
- ct_util_server ! {Msg, {ct_util_server, make_ref()}}.
+ ct_util_server ! {Msg, {ct_util_server, make_ref()}},
+ ok.
seconds(T) ->
test_server:seconds(T).
@@ -1074,7 +1077,7 @@ abs_name2([],Acc) ->
open_url(iexplore, Args, URL) ->
{ok,R} = win32reg:open([read]),
ok = win32reg:change_key(R,"applications\\iexplore.exe\\shell\\open\\command"),
- case win32reg:values(R) of
+ _ = case win32reg:values(R) of
{ok, Paths} ->
Path = proplists:get_value(default, Paths),
[Cmd | _] = string:tokens(Path, "%"),
diff --git a/lib/common_test/src/ct_webtool.erl b/lib/common_test/src/ct_webtool.erl
index 6cbcd98cc3..87af442fd3 100644
--- a/lib/common_test/src/ct_webtool.erl
+++ b/lib/common_test/src/ct_webtool.erl
@@ -84,27 +84,27 @@
%% Function = {FunctionName,Arity} | FunctionName |
%% {Module, FunctionName, Arity} | {Module,FunctionName}
debug(F) ->
- ttb:tracer(all,[{file,"webtool.trc"}]), % tracing all nodes
- ttb:p(all,[call,timestamp]),
+ {ok, _} = ttb:tracer(all,[{file,"webtool.trc"}]), % tracing all nodes
+ {ok, _} = ttb:p(all,[call,timestamp]),
MS = [{'_',[],[{return_trace},{message,{caller}}]}],
- tp(F,MS),
- ttb:ctp(?MODULE,stop_debug), % don't want tracing of the stop_debug func
+ _ = tp(F,MS),
+ {ok, _} = ttb:ctp(?MODULE,stop_debug), % don't want tracing of the stop_debug func
ok.
tp(local,MS) -> % all functions
ttb:tpl(?MODULE,MS);
tp(global,MS) -> % all exported functions
ttb:tp(?MODULE,MS);
tp([{M,F,A}|T],MS) -> % Other module
- ttb:tpl(M,F,A,MS),
+ {ok, _} = ttb:tpl(M,F,A,MS),
tp(T,MS);
tp([{M,F}|T],MS) when is_atom(F) -> % Other module
- ttb:tpl(M,F,MS),
+ {ok, _} = ttb:tpl(M,F,MS),
tp(T,MS);
tp([{F,A}|T],MS) -> % function/arity
- ttb:tpl(?MODULE,F,A,MS),
+ {ok, _} = ttb:tpl(?MODULE,F,A,MS),
tp(T,MS);
tp([F|T],MS) -> % function
- ttb:tpl(?MODULE,F,MS),
+ {ok, _} = ttb:tpl(?MODULE,F,MS),
tp(T,MS);
tp([],_MS) ->
ok.
@@ -112,10 +112,10 @@ stop_debug() ->
ttb:stop([format]).
debug_app(Mod) ->
- ttb:tracer(all,[{file,"webtool_app.trc"},{handler,{fun out/4,true}}]),
- ttb:p(all,[call,timestamp]),
+ {ok, _} = ttb:tracer(all,[{file,"webtool_app.trc"},{handler,{fun out/4,true}}]),
+ {ok, _} = ttb:p(all,[call,timestamp]),
MS = [{'_',[],[{return_trace},{message,{caller}}]}],
- ttb:tp(Mod,MS),
+ {ok, _} = ttb:tp(Mod,MS),
ok.
out(_,{trace_ts,Pid,call,MFA={M,F,A},{W,_,_},TS},_,S)
@@ -145,7 +145,7 @@ script_start([App]) ->
script_start([App,DefaultBrowser]);
script_start([App,Browser]) ->
io:format("Starting webtool...\n"),
- start(),
+ {ok, _} = start(),
AvailableApps = get_applications(),
{OSType,_} = os:type(),
case lists:keysearch(App,1,AvailableApps) of
@@ -159,14 +159,14 @@ script_start([App,Browser]) ->
_ ->
"http://localhost:" ++ PortStr ++ "/" ++ StartPage
end,
- case Browser of
+ _ = case Browser of
none ->
ok;
iexplore when OSType == win32->
io:format("Starting internet explorer...\n"),
{ok,R} = win32reg:open(""),
Key="\\local_machine\\SOFTWARE\\Microsoft\\IE Setup\\Setup",
- win32reg:change_key(R,Key),
+ ok = win32reg:change_key(R,Key),
{ok,Val} = win32reg:value(R,"Path"),
IExplore=filename:join(win32reg:expand(Val),"iexplore.exe"),
os:cmd("\"" ++ IExplore ++ "\" " ++ Url);
@@ -186,7 +186,7 @@ script_start([App,Browser]) ->
{Port,{exit_status,_Error}} ->
io:format(" not running, starting ~w...\n",
[Browser]),
- os:cmd(BStr ++ " " ++ Url),
+ _ = os:cmd(BStr ++ " " ++ Url),
ok
after ?SEND_URL_TIMEOUT ->
io:format(" failed, starting ~w...\n",[Browser]),
@@ -206,7 +206,7 @@ script_start([App,Browser]) ->
usage() ->
io:format("Starting webtool...\n"),
- start(),
+ {ok, _} = start(),
Apps = lists:map(fun({A,_}) -> A end,get_applications()),
io:format(
"\nUsage: start_webtool application [ browser ]\n"
@@ -254,7 +254,12 @@ start(Path,Port) when is_integer(Port)->
start(Path,Data0)->
Data = Data0 ++ rest_of_standard_data(),
- gen_server:start({local,ct_web_tool},ct_webtool,{Path,Data},[]).
+ case gen_server:start({local,ct_web_tool},ct_webtool,{Path,Data},[]) of
+ {error, {already_started, Pid}} ->
+ {ok, Pid};
+ Else ->
+ Else
+ end.
stop()->
gen_server:call(ct_web_tool,stoppit).
diff --git a/lib/common_test/src/cth_conn_log.erl b/lib/common_test/src/cth_conn_log.erl
index 0501c6ed1c..883da0da0a 100644
--- a/lib/common_test/src/cth_conn_log.erl
+++ b/lib/common_test/src/cth_conn_log.erl
@@ -170,7 +170,7 @@ post_end_per_testcase(TestCase,_Config,Return,CthState) ->
end,
case ct_util:update_testdata(?MODULE, Update) of
deleted ->
- [ct_util:delete_testdata({?MODULE,ConnMod}) ||
+ _ = [ct_util:delete_testdata({?MODULE,ConnMod}) ||
{ConnMod,_} <- CthState],
error_logger:delete_report_handler(ct_conn_log_h);
{error,no_response} ->
diff --git a/lib/common_test/src/erl2html2.erl b/lib/common_test/src/erl2html2.erl
index a1e0bf3879..e819f345de 100644
--- a/lib/common_test/src/erl2html2.erl
+++ b/lib/common_test/src/erl2html2.erl
@@ -62,15 +62,15 @@ convert(File, Dest, InclPath, Header) ->
{ok,SFd} ->
case file:open(Dest,[write,raw]) of
{ok,DFd} ->
- file:write(DFd,[Header,"<pre>\n"]),
+ ok = file:write(DFd,[Header,"<pre>\n"]),
_Lines = build_html(SFd,DFd,encoding(File),Functions),
- file:write(DFd,["</pre>\n",footer(),
+ ok = file:write(DFd,["</pre>\n",footer(),
"</body>\n</html>\n"]),
%% {_, Time2} = statistics(runtime),
%% io:format("Converted ~p lines in ~.2f Seconds.~n",
%% [_Lines, Time2/1000]),
- file:close(SFd),
- file:close(DFd),
+ ok = file:close(SFd),
+ ok = file:close(DFd),
ok;
Error ->
Error
@@ -138,7 +138,7 @@ parse_non_preprocessed_file(File) ->
case file:open(File, []) of
{ok,Epp} ->
Forms = parse_non_preprocessed_file(Epp, File, 1),
- file:close(Epp),
+ ok = file:close(Epp),
{ok,Forms};
Error = {error,_E} ->
Error
@@ -205,14 +205,14 @@ build_html(SFd,DFd,Encoding,FuncsAndCs) ->
%% line of last expression in function found
build_html(SFd,DFd,Enc,{ok,Str},LastL,FuncsAndCs,_IsFuncDef,{F,LastL}) ->
LastLineLink = test_server_ctrl:uri_encode(F++"-last_expr",utf8),
- file:write(DFd,["<a name=\"",
- to_raw_list(LastLineLink,Enc),"\"/>"]),
+ ok = file:write(DFd,["<a name=\"",
+ to_raw_list(LastLineLink,Enc),"\"/>"]),
build_html(SFd,DFd,Enc,{ok,Str},LastL,FuncsAndCs,true,undefined);
%% function start line found
build_html(SFd,DFd,Enc,{ok,Str},L0,[{F,A,L0,LastL}|FuncsAndCs],
_IsFuncDef,_FAndLastL) ->
FALink = test_server_ctrl:uri_encode(F++"-"++integer_to_list(A),utf8),
- file:write(DFd,["<a name=\"",to_raw_list(FALink,Enc),"\"/>"]),
+ ok = file:write(DFd,["<a name=\"",to_raw_list(FALink,Enc),"\"/>"]),
build_html(SFd,DFd,Enc,{ok,Str},L0,FuncsAndCs,true,{F,LastL});
build_html(SFd,DFd,Enc,{ok,Str},L,[{clause,L}|FuncsAndCs],
_IsFuncDef,FAndLastL) ->
@@ -220,7 +220,7 @@ build_html(SFd,DFd,Enc,{ok,Str},L,[{clause,L}|FuncsAndCs],
build_html(SFd,DFd,Enc,{ok,Str},L,FuncsAndCs,IsFuncDef,FAndLastL) ->
LStr = line_number(L),
Str1 = line(Str,IsFuncDef),
- file:write(DFd,[LStr,Str1]),
+ ok = file:write(DFd,[LStr,Str1]),
build_html(SFd,DFd,Enc,file:read_line(SFd),L+1,FuncsAndCs,false,FAndLastL);
build_html(_SFd,_DFd,_Enc,eof,L,_FuncsAndCs,_IsFuncDef,_FAndLastL) ->
L.
diff --git a/lib/common_test/src/test_server.erl b/lib/common_test/src/test_server.erl
index bd677e971b..924086f2bd 100644
--- a/lib/common_test/src/test_server.erl
+++ b/lib/common_test/src/test_server.erl
@@ -1653,7 +1653,8 @@ messages_get() ->
%%
%% Make sure proceeding IO from FromPid won't get rejected
permit_io(GroupLeader, FromPid) ->
- GroupLeader ! {permit_io,FromPid}.
+ GroupLeader ! {permit_io,FromPid},
+ ok.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% sleep(Time) -> ok
diff --git a/lib/common_test/src/test_server_ctrl.erl b/lib/common_test/src/test_server_ctrl.erl
index 84e35e7371..b52e4bef9b 100644
--- a/lib/common_test/src/test_server_ctrl.erl
+++ b/lib/common_test/src/test_server_ctrl.erl
@@ -294,7 +294,7 @@ start_link(_) ->
start() ->
case gen_server:start({local,?MODULE}, ?MODULE, [], []) of
- {ok, Pid} ->
+ {error, {already_started, Pid}} ->
{ok, Pid};
Other ->
Other
@@ -302,7 +302,7 @@ start() ->
start_link() ->
case gen_server:start_link({local,?MODULE}, ?MODULE, [], []) of
- {ok, Pid} ->
+ {error, {already_started, Pid}} ->
{ok, Pid};
Other ->
Other
diff --git a/lib/common_test/test/ct_gen_conn_SUITE_data/conn_SUITE.erl b/lib/common_test/test/ct_gen_conn_SUITE_data/conn_SUITE.erl
index 1404df6410..19eb1211fa 100644
--- a/lib/common_test/test/ct_gen_conn_SUITE_data/conn_SUITE.erl
+++ b/lib/common_test/test/ct_gen_conn_SUITE_data/conn_SUITE.erl
@@ -73,24 +73,28 @@ handles_to_multi_conn_pids(_Config) ->
ConnPid3 = ct_gen_conn:get_conn_pid(Handle3),
{true,true} = {is_process_alive(Handle3),is_process_alive(ConnPid3)},
+ monitor_procs([Handle1,ConnPid1,Handle2,ConnPid2,Handle3,ConnPid3]),
+
ok = proto:close(Handle1),
- ct:sleep(100),
+ ok = wait_procs_down([Handle1,ConnPid1]),
{false,false} = {is_process_alive(Handle1),is_process_alive(ConnPid1)},
{true,true} = {is_process_alive(Handle2),is_process_alive(ConnPid2)},
ok = proto:kill_conn_proc(Handle2),
- ct:sleep(100),
+ ok = wait_procs_down([ConnPid2]),
{true,false} = {is_process_alive(Handle2),is_process_alive(ConnPid2)},
ConnPid2x = ct_gen_conn:get_conn_pid(Handle2),
true = is_process_alive(ConnPid2x),
+ monitor_procs([ConnPid2x]),
+
ok = proto:close(Handle2),
- ct:sleep(100),
+ ok = wait_procs_down([Handle2,ConnPid2x]),
{false,false} = {is_process_alive(Handle2),is_process_alive(ConnPid2x)},
application:set_env(ct_test, reconnect, false),
ok = proto:kill_conn_proc(Handle3),
- ct:sleep(100),
+ ok = wait_procs_down([Handle3,ConnPid3]),
{false,false} = {is_process_alive(Handle3),is_process_alive(ConnPid3)},
ok.
@@ -116,24 +120,28 @@ handles_to_single_conn_pids(_Config) ->
{undefined,Handle3,_,_}] = lists:sort(ct_util:get_connections(ConnPid)),
ct:pal("CONNS = ~n~p", [Conns]),
+ monitor_procs([Handle1,Handle2,Handle3,ConnPid]),
ok = proto:close(Handle1),
- ct:sleep(100),
+ ok = wait_procs_down([Handle1]),
{false,true} = {is_process_alive(Handle1),is_process_alive(ConnPid)},
ok = proto:kill_conn_proc(Handle2),
- ct:sleep(100),
+ ok = wait_procs_down([ConnPid]),
NewConnPid = ct_gen_conn:get_conn_pid(Handle2),
NewConnPid = ct_gen_conn:get_conn_pid(Handle3),
true = is_process_alive(Handle2),
true = is_process_alive(Handle3),
+ false = is_process_alive(ConnPid),
+
+ monitor_procs([NewConnPid]),
ok = proto:close(Handle2),
- ct:sleep(100),
+ ok = wait_procs_down([Handle2]),
{false,true} = {is_process_alive(Handle2),is_process_alive(NewConnPid)},
application:set_env(ct_test, reconnect, false),
ok = proto:kill_conn_proc(Handle3),
- ct:sleep(100),
+ ok = wait_procs_down([Handle3,NewConnPid]),
{false,false} = {is_process_alive(Handle3),is_process_alive(NewConnPid)},
ok.
@@ -158,30 +166,37 @@ names_to_multi_conn_pids(_Config) ->
Handle1 = proto:open(mconn1),
+ monitor_procs([Handle1,ConnPid1,Handle2,ConnPid2,Handle3,ConnPid3]),
+
ok = proto:close(mconn1),
- ct:sleep(100),
+ ok = wait_procs_down([Handle1,ConnPid1]),
{false,false} = {is_process_alive(Handle1),is_process_alive(ConnPid1)},
ok = proto:kill_conn_proc(Handle2),
- ct:sleep(100),
+ ok = wait_procs_down([ConnPid2]),
Handle2 = proto:open(mconn2), % should've been reconnected already
{true,false} = {is_process_alive(Handle2),is_process_alive(ConnPid2)},
ConnPid2x = ct_gen_conn:get_conn_pid(Handle2),
true = is_process_alive(ConnPid2x),
+ monitor_procs([ConnPid2x]),
+
ok = proto:close(mconn2),
- ct:sleep(100),
+ ok = wait_procs_down([Handle2,ConnPid2x]),
{false,false} = {is_process_alive(Handle2),is_process_alive(ConnPid2x)},
Handle2y = proto:open(mconn2),
ConnPid2y = ct_gen_conn:get_conn_pid(Handle2y),
{true,true} = {is_process_alive(Handle2y),is_process_alive(ConnPid2y)},
+
+ monitor_procs([Handle2y,ConnPid2y]),
+
ok = proto:close(mconn2),
- ct:sleep(100),
+ ok = wait_procs_down([Handle2y,ConnPid2y]),
{false,false} = {is_process_alive(Handle2y),is_process_alive(ConnPid2y)},
application:set_env(ct_test, reconnect, false),
ok = proto:kill_conn_proc(Handle3),
- ct:sleep(100),
+ ok = wait_procs_down([Handle3,ConnPid3]),
{false,false} = {is_process_alive(Handle3),is_process_alive(ConnPid3)},
ok.
@@ -211,16 +226,20 @@ names_to_single_conn_pids(_Config) ->
{sconn3,Handle3,_,_}] = lists:sort(ct_util:get_connections(ConnPid)),
ct:pal("CONNS on ~p = ~n~p", [ConnPid,Conns]),
+ monitor_procs([Handle1,Handle2,Handle3,ConnPid]),
+
ok = proto:close(sconn1),
- ct:sleep(100),
+ ok = wait_procs_down([Handle1]),
{false,true} = {is_process_alive(Handle1),is_process_alive(ConnPid)},
ok = proto:kill_conn_proc(Handle2),
- ct:sleep(100),
+ ok = wait_procs_down([ConnPid]),
{true,false} = {is_process_alive(Handle2),is_process_alive(ConnPid)},
Handle2 = proto:open(sconn2), % should've been reconnected already
NewConnPid = ct_gen_conn:get_conn_pid(Handle2),
true = is_process_alive(NewConnPid),
+
+ monitor_procs([NewConnPid]),
Conns1 = [{sconn2,Handle2,_,_},
{sconn3,Handle3,_,_}] =
@@ -228,14 +247,29 @@ names_to_single_conn_pids(_Config) ->
ct:pal("CONNS on ~p = ~n~p", [NewConnPid,Conns1]),
ok = proto:close(sconn2),
- ct:sleep(100),
+ ok = wait_procs_down([Handle2]),
{false,true} = {is_process_alive(Handle2),is_process_alive(NewConnPid)},
application:set_env(ct_test, reconnect, false),
ok = proto:kill_conn_proc(Handle3),
- ct:sleep(100),
+ ok = wait_procs_down([Handle3,NewConnPid]),
{false,false} = {is_process_alive(Handle3),is_process_alive(NewConnPid)},
ok.
+%%%-----------------------------------------------------------------
+monitor_procs(Pids) ->
+ [erlang:monitor(process,Pid) || Pid <- Pids],
+ ok.
+
+wait_procs_down([]) ->
+ ok;
+wait_procs_down(Pids) ->
+ receive
+ {'DOWN',_,process,Pid,_} ->
+ wait_procs_down(lists:delete(Pid,Pids))
+ after 2000 ->
+ timeout
+ end.
+
diff --git a/lib/common_test/test/ct_netconfc_SUITE.erl b/lib/common_test/test/ct_netconfc_SUITE.erl
index 03fbc17bd2..2919f01605 100644
--- a/lib/common_test/test/ct_netconfc_SUITE.erl
+++ b/lib/common_test/test/ct_netconfc_SUITE.erl
@@ -44,16 +44,28 @@
%% there will be clashes with logging processes etc).
%%--------------------------------------------------------------------
init_per_suite(Config) ->
- case application:load(crypto) of
- {error,Reason} when Reason=/={already_loaded,crypto} ->
- {skip, Reason};
- _ ->
- case application:load(ssh) of
- {error,Reason} when Reason=/={already_loaded,ssh} ->
- {skip, Reason};
- _ ->
- ct_test_support:init_per_suite(Config)
- end
+ case check_crypto_and_ssh() of
+ ok ->
+ ct_test_support:init_per_suite(Config);
+ Skip ->
+ Skip
+ end.
+
+check_crypto_and_ssh() ->
+ (catch code:load_file(crypto)),
+ case code:is_loaded(crypto) of
+ {file,_} ->
+ case ssh:start() of
+ Ok when Ok==ok; Ok=={error,{already_started,ssh}} ->
+ ct:log("ssh started",[]),
+ ok;
+ Other ->
+ ct:log("could not start ssh: ~p",[Other]),
+ {skip, "SSH could not be started!"}
+ end;
+ Other ->
+ ct:log("could not load crypto: ~p",[Other]),
+ {skip, "crypto could not be loaded!"}
end.
end_per_suite(Config) ->
diff --git a/lib/common_test/test/ct_netconfc_SUITE_data/netconfc1_SUITE.erl b/lib/common_test/test/ct_netconfc_SUITE_data/netconfc1_SUITE.erl
index f34969683c..2aa6c4d354 100644
--- a/lib/common_test/test/ct_netconfc_SUITE_data/netconfc1_SUITE.erl
+++ b/lib/common_test/test/ct_netconfc_SUITE_data/netconfc1_SUITE.erl
@@ -124,8 +124,9 @@ end_per_testcase(_Case, _Config) ->
ok.
init_per_suite(Config) ->
- case catch ssh:start() of
- Ok when Ok==ok; Ok=={error,{already_started,ssh}} ->
+ (catch code:load_file(crypto)),
+ case {ssh:start(),code:is_loaded(crypto)} of
+ {Ok,{file,_}} when Ok==ok; Ok=={error,{already_started,ssh}} ->
ct:log("ssh started",[]),
SshDir = filename:join(filename:dirname(code:which(?MODULE)),
"ssh_dir"),
@@ -133,7 +134,7 @@ init_per_suite(Config) ->
ct:log("netconf server started",[]),
[{netconf_server,Server},{ssh_dir,SshDir}|Config];
Other ->
- ct:log("could not start ssh: ~p",[Other]),
+ ct:log("could not start ssh or load crypto: ~p",[Other]),
{skip, "SSH could not be started!"}
end.
@@ -360,7 +361,7 @@ get(Config) ->
get_a_lot(Config) ->
SshDir = ?config(ssh_dir,Config),
{ok,Client} = open_success(SshDir),
- Descr = lists:append(lists:duplicate(1000,"Description of myserver! ")),
+ Descr = lists:append(lists:duplicate(100,"Description of myserver! ")),
Server = {server,[{xmlns,"myns"}],[{name,[],["myserver"]},
{description,[],[Descr]}]},
Data = lists:duplicate(100,Server),
diff --git a/lib/common_test/test/ct_netconfc_SUITE_data/netconfc_remote_SUITE.erl b/lib/common_test/test/ct_netconfc_SUITE_data/netconfc_remote_SUITE.erl
index 0a49cdabbb..a65275da43 100644
--- a/lib/common_test/test/ct_netconfc_SUITE_data/netconfc_remote_SUITE.erl
+++ b/lib/common_test/test/ct_netconfc_SUITE_data/netconfc_remote_SUITE.erl
@@ -62,14 +62,15 @@ stop_node(Case) ->
init_per_suite(Config) ->
- case ssh:start() of
- Ok when Ok==ok; Ok=={error,{already_started,ssh}} ->
+ (catch code:load_file(crypto)),
+ case {ssh:start(),code:is_loaded(crypto)} of
+ {Ok,{file,_}} when Ok==ok; Ok=={error,{already_started,ssh}} ->
ct:log("SSH started locally",[]),
SshDir = filename:join(filename:dirname(code:which(?MODULE)),
"ssh_dir"),
[{ssh_dir,SshDir}|Config];
Other ->
- ct:log("could not start ssh locally: ~p",[Other]),
+ ct:log("could not start ssh or load crypto locally: ~p",[Other]),
{skip, "SSH could not be started locally!"}
end.
@@ -85,15 +86,15 @@ remote_crash(Config) ->
{ok,Node} = ct_slave:start(nc_remote_crash),
Pa = filename:dirname(code:which(?NS)),
true = rpc:call(Node,code,add_patha,[Pa]),
-
- case rpc:call(Node,ssh,start,[]) of
- Ok when Ok==ok; Ok=={error,{already_started,ssh}} ->
+ rpc:call(Node,code,load_file,[crypto]),
+ case {rpc:call(Node,ssh,start,[]),rpc:call(Node,code,is_loaded,[crypto])} of
+ {Ok,{file,_}} when Ok==ok; Ok=={error,{already_started,ssh}} ->
ct:log("SSH started remote",[]),
ns(Node,start,[?config(ssh_dir,Config)]),
ct:log("netconf server started remote",[]),
remote_crash(Node,Config);
Other ->
- ct:log("could not start ssh remote: ~p",[Other]),
+ ct:log("could not start ssh or load crypto remote: ~p",[Other]),
{skip, "SSH could not be started remote!"}
end.
diff --git a/lib/common_test/test/ct_netconfc_SUITE_data/ns.erl b/lib/common_test/test/ct_netconfc_SUITE_data/ns.erl
index 9fb1fb6547..e62bc617fa 100644
--- a/lib/common_test/test/ct_netconfc_SUITE_data/ns.erl
+++ b/lib/common_test/test/ct_netconfc_SUITE_data/ns.erl
@@ -279,7 +279,7 @@ send({CM,Ch},Data) ->
%%% Split into many small parts and send to client
send_frag({CM,Ch},Data) ->
- Sz = rand:uniform(2000),
+ Sz = rand:uniform(1000),
case Data of
<<Chunk:Sz/binary,Rest/binary>> ->
ssh_connection:send(CM, Ch, Chunk),
diff --git a/lib/common_test/test/ct_test_support.erl b/lib/common_test/test/ct_test_support.erl
index 477fcb8a26..e926abd885 100644
--- a/lib/common_test/test/ct_test_support.erl
+++ b/lib/common_test/test/ct_test_support.erl
@@ -484,7 +484,8 @@ get_events(_, Config) ->
{event_receiver,CTNode} ! {self(),get_events},
Events = receive {event_receiver,Evs} -> Evs end,
test_server:format(Level, "Stopping event receiver!~n", []),
- {event_receiver,CTNode} ! stop,
+ {event_receiver,CTNode} ! {self(),stop},
+ receive {event_receiver,stopped} -> ok end,
Events.
er() ->
@@ -499,8 +500,9 @@ er_loop(Evs) ->
{From,get_events} ->
From ! {event_receiver,lists:reverse(Evs)},
er_loop(Evs);
- stop ->
+ {From,stop} ->
unregister(event_receiver),
+ From ! {event_receiver,stopped},
ok
end.
diff --git a/lib/common_test/test/telnet_server.erl b/lib/common_test/test/telnet_server.erl
index 2c33cb268a..65300b0bdf 100644
--- a/lib/common_test/test/telnet_server.erl
+++ b/lib/common_test/test/telnet_server.erl
@@ -117,38 +117,64 @@ init_client(#state{client=Sock}=State) ->
dbg("Server sending: ~p~n",["login: "]),
R = case gen_tcp:send(Sock,"login: ") of
ok ->
- loop(State, 1);
+ loop(State);
Error ->
Error
end,
_ = gen_tcp:close(Sock),
R.
-loop(State, N) ->
+loop(State=#state{client=Sock}) ->
receive
- {tcp,_,Data} ->
+ {tcp,Sock,Data} ->
try handle_data(Data,State) of
{ok,State1} ->
- loop(State1, N);
+ loop(State1);
closed ->
+ _ = flush(State),
closed
catch
throw:Error ->
+ _ = flush(State),
Error
end;
- {tcp_closed, _} ->
+ {tcp_closed,Sock} ->
closed;
- {tcp_error,_,Error} ->
+ {tcp_error,Sock,Error} ->
{error,tcp,Error};
disconnect ->
- Sock = State#state.client,
dbg("Server closing connection on socket ~p~n", [Sock]),
+ timer:sleep(1000),
ok = gen_tcp:close(Sock),
- closed;
+ _ = flush(State);
stop ->
+ _ = flush(State),
stopped
end.
+flush(State=#state{client=Sock}) ->
+ receive
+ {tcp,Sock,Data} = M->
+ dbg("Message flushed after close or error: ~p~n", [M]),
+ try handle_data(Data,State) of
+ {ok,State1} ->
+ flush(State1);
+ closed ->
+ flush(State)
+ catch
+ throw:Error ->
+ Error
+ end;
+ {tcp_closed,Sock} = M ->
+ dbg("Message flushed after close or error: ~p~n", [M]),
+ ok;
+ {tcp_error,Sock,Error} = M ->
+ dbg("Message flushed after close or error: ~p~n", [M]),
+ {error,tcp,Error}
+ after 100 ->
+ ok
+ end.
+
handle_data(Cmd,#state{break=true}=State) ->
dbg("Server got data when in break mode: ~p~n",[Cmd]),
handle_break_cmd(Cmd,State);
diff --git a/lib/dialyzer/src/dialyzer_contracts.erl b/lib/dialyzer/src/dialyzer_contracts.erl
index d1ffa07706..272ad10e90 100644
--- a/lib/dialyzer/src/dialyzer_contracts.erl
+++ b/lib/dialyzer/src/dialyzer_contracts.erl
@@ -591,10 +591,13 @@ remove_uses([{Var, Use}|ToRemove], Constrs0) ->
remove_uses(_Var, _Use, []) -> [];
remove_uses(Var, Use, [Constr|Constrs]) ->
{V, Form} = Constr,
- case erl_types:t_var_name(V) =:= Var of
- true -> [{V, remove_use(Form, Use)}|Constrs];
- false -> [Constr|remove_uses(Var, Use, Constrs)]
- end.
+ NewConstr = case erl_types:t_var_name(V) =:= Var of
+ true ->
+ {V, remove_use(Form, Use)};
+ false ->
+ Constr
+ end,
+ [NewConstr|remove_uses(Var, Use, Constrs)].
remove_use({var, L, V}, V) -> {var, L, '_'};
remove_use(T, V) when is_tuple(T) ->
diff --git a/lib/dialyzer/src/dialyzer_dataflow.erl b/lib/dialyzer/src/dialyzer_dataflow.erl
index 5ab0c39c04..3349b12932 100644
--- a/lib/dialyzer/src/dialyzer_dataflow.erl
+++ b/lib/dialyzer/src/dialyzer_dataflow.erl
@@ -430,17 +430,35 @@ handle_apply(Tree, Map, State) ->
handle_apply_or_call(FunInfoList, Args, ArgTypes, Map, Tree, State) ->
None = t_none(),
+ %% Call-site analysis may be inaccurate and consider more funs than those that
+ %% are actually possible. If all of them are incorrect, then warnings can be
+ %% emitted. If at least one fun is ok, however, then no warning is emitted,
+ %% just in case the bad ones are not really possible. The last argument is
+ %% used for this, with the following encoding:
+ %% Initial value: {none, []}
+ %% First fun checked: {one, <List of warns>}
+ %% More funs checked: {many, <List of warns>}
+ %% A '{one, []}' can only become '{many, []}'.
+ %% If at any point an fun does not add warnings, then the list is also
+ %% replaced with an empty list.
handle_apply_or_call(FunInfoList, Args, ArgTypes, Map, Tree, State,
- [None || _ <- ArgTypes], None, false).
+ [None || _ <- ArgTypes], None, false, {none, []}).
handle_apply_or_call([{local, external}|Left], Args, ArgTypes, Map, Tree, State,
- _AccArgTypes, _AccRet, _HadExternal) ->
+ _AccArgTypes, _AccRet, _HadExternal, Warns) ->
+ {HowMany, _} = Warns,
+ NewHowMany =
+ case HowMany of
+ none -> one;
+ _ -> many
+ end,
+ NewWarns = {NewHowMany, []},
handle_apply_or_call(Left, Args, ArgTypes, Map, Tree, State,
- ArgTypes, t_any(), true);
+ ArgTypes, t_any(), true, NewWarns);
handle_apply_or_call([{TypeOfApply, {Fun, Sig, Contr, LocalRet}}|Left],
Args, ArgTypes, Map, Tree,
#state{opaques = Opaques} = State,
- AccArgTypes, AccRet, HadExternal) ->
+ AccArgTypes, AccRet, HadExternal, Warns) ->
Any = t_any(),
AnyArgs = [Any || _ <- Args],
GenSig = {AnyArgs, fun(_) -> t_any() end},
@@ -586,16 +604,32 @@ handle_apply_or_call([{TypeOfApply, {Fun, Sig, Contr, LocalRet}}|Left],
end,
NewAccRet = t_sup(AccRet, TotalRet),
?debug("NewAccRet: ~s\n", [t_to_string(NewAccRet)]),
+ {NewWarnings, State4} = state__remove_added_warnings(State, State3),
+ {HowMany, OldWarnings} = Warns,
+ NewWarns =
+ case HowMany of
+ none -> {one, NewWarnings};
+ _ ->
+ case OldWarnings =:= [] of
+ true -> {many, []};
+ false ->
+ case NewWarnings =:= [] of
+ true -> {many, []};
+ false -> {many, NewWarnings ++ OldWarnings}
+ end
+ end
+ end,
handle_apply_or_call(Left, Args, ArgTypes, Map, Tree,
- State3, NewAccArgTypes, NewAccRet, HadExternal);
+ State4, NewAccArgTypes, NewAccRet, HadExternal, NewWarns);
handle_apply_or_call([], Args, _ArgTypes, Map, _Tree, State,
- AccArgTypes, AccRet, HadExternal) ->
+ AccArgTypes, AccRet, HadExternal, {_, Warnings}) ->
+ State1 = state__add_warnings(Warnings, State),
case HadExternal of
false ->
NewMap = enter_type_lists(Args, AccArgTypes, Map),
- {State, NewMap, AccRet};
+ {State1, NewMap, AccRet};
true ->
- {had_external, State}
+ {had_external, State1}
end.
apply_fail_reason(FailedSig, FailedBif, FailedContract) ->
@@ -3038,6 +3072,14 @@ state__add_warning(#state{warnings = Warnings, warning_mode = true} = State,
end
end.
+state__remove_added_warnings(OldState, NewState) ->
+ #state{warnings = OldWarnings} = OldState,
+ #state{warnings = NewWarnings} = NewState,
+ {NewWarnings -- OldWarnings, NewState#state{warnings = OldWarnings}}.
+
+state__add_warnings(Warns, #state{warnings = Warnings} = State) ->
+ State#state{warnings = Warns ++ Warnings}.
+
-spec state__set_curr_fun(curr_fun(), state()) -> state().
state__set_curr_fun(undefined, State) ->
diff --git a/lib/dialyzer/test/map_SUITE_data/results/exact b/lib/dialyzer/test/map_SUITE_data/results/exact
index 374ada8869..ea00e61330 100644
--- a/lib/dialyzer/test/map_SUITE_data/results/exact
+++ b/lib/dialyzer/test/map_SUITE_data/results/exact
@@ -1,3 +1,3 @@
exact.erl:15: Function t2/1 has no local return
-exact.erl:19: The variable _ can never match since previous clauses completely covered the type #{'a':=_, ...}
+exact.erl:19: The variable _ can never match since previous clauses completely covered the type #{'a':=_, _=>_}
diff --git a/lib/dialyzer/test/map_SUITE_data/results/guard_update b/lib/dialyzer/test/map_SUITE_data/results/guard_update
index e4bc892195..98df23907f 100644
--- a/lib/dialyzer/test/map_SUITE_data/results/guard_update
+++ b/lib/dialyzer/test/map_SUITE_data/results/guard_update
@@ -1,5 +1,5 @@
guard_update.erl:5: Function t/0 has no local return
-guard_update.erl:6: The call guard_update:f(#{'a':=2}) will never return since it differs in the 1st argument from the success typing arguments: (#{'b':=_, ...})
+guard_update.erl:6: The call guard_update:f(#{'a':=2}) will never return since it differs in the 1st argument from the success typing arguments: (#{'b':=_, _=>_})
guard_update.erl:8: Clause guard cannot succeed. The variable M was matched against the type #{'a':=2}
guard_update.erl:8: Function f/1 has no local return
diff --git a/lib/dialyzer/test/map_SUITE_data/results/map_in_guard2 b/lib/dialyzer/test/map_SUITE_data/results/map_in_guard2
index 6bc0c010d7..f6fb98a863 100644
--- a/lib/dialyzer/test/map_SUITE_data/results/map_in_guard2
+++ b/lib/dialyzer/test/map_SUITE_data/results/map_in_guard2
@@ -1,7 +1,7 @@
map_in_guard2.erl:10: The call map_in_guard2:assoc_guard_clause('not_a_map') will never return since it differs in the 1st argument from the success typing arguments: (map())
map_in_guard2.erl:12: The pattern 'true' can never match the type 'false'
-map_in_guard2.erl:14: The call map_in_guard2:exact_guard_clause(#{}) will never return since it differs in the 1st argument from the success typing arguments: (#{'a':=_, ...})
+map_in_guard2.erl:14: The call map_in_guard2:exact_guard_clause(#{}) will never return since it differs in the 1st argument from the success typing arguments: (#{'a':=_, _=>_})
map_in_guard2.erl:17: Clause guard cannot succeed. The variable M was matched against the type 'not_a_map'
map_in_guard2.erl:20: Function assoc_update/1 has no local return
map_in_guard2.erl:20: Guard test is_map(M::'not_a_map') can never succeed
diff --git a/lib/dialyzer/test/map_SUITE_data/results/typeflow b/lib/dialyzer/test/map_SUITE_data/results/typeflow
index e3378a24bb..acfb7f551e 100644
--- a/lib/dialyzer/test/map_SUITE_data/results/typeflow
+++ b/lib/dialyzer/test/map_SUITE_data/results/typeflow
@@ -1,4 +1,4 @@
typeflow.erl:14: Function t2/1 has no local return
typeflow.erl:16: The call lists:sort(integer()) will never return since it differs in the 1st argument from the success typing arguments: ([any()])
-typeflow.erl:9: The variable _ can never match since previous clauses completely covered the type #{'a':=integer(), ...}
+typeflow.erl:9: The variable _ can never match since previous clauses completely covered the type #{'a':=integer(), _=>_}
diff --git a/lib/dialyzer/test/map_SUITE_data/results/typesig b/lib/dialyzer/test/map_SUITE_data/results/typesig
index 3049402860..fb2f851a7d 100644
--- a/lib/dialyzer/test/map_SUITE_data/results/typesig
+++ b/lib/dialyzer/test/map_SUITE_data/results/typesig
@@ -1,5 +1,5 @@
typesig.erl:5: Function t1/0 has no local return
-typesig.erl:5: The call typesig:test(#{'a':=1}) will never return since it differs in the 1st argument from the success typing arguments: (#{'a':={number()}, ...})
+typesig.erl:5: The call typesig:test(#{'a':=1}) will never return since it differs in the 1st argument from the success typing arguments: (#{'a':={number()}, _=>_})
typesig.erl:6: Function t2/0 has no local return
-typesig.erl:6: The call typesig:test(#{'a':={'b'}}) will never return since it differs in the 1st argument from the success typing arguments: (#{'a':={number()}, ...})
+typesig.erl:6: The call typesig:test(#{'a':={'b'}}) will never return since it differs in the 1st argument from the success typing arguments: (#{'a':={number()}, _=>_})
diff --git a/lib/dialyzer/test/small_SUITE_data/results/higher_order_discrepancy b/lib/dialyzer/test/small_SUITE_data/results/higher_order_discrepancy
index 7ce440a60d..11b9ecade6 100644
--- a/lib/dialyzer/test/small_SUITE_data/results/higher_order_discrepancy
+++ b/lib/dialyzer/test/small_SUITE_data/results/higher_order_discrepancy
@@ -1,4 +1,3 @@
-higher_order_discrepancy.erl:11: The call higher_order_discrepancy:g('foo') will never return since it differs in the 1st argument from the success typing arguments: ('bar')
-higher_order_discrepancy.erl:14: Function g/1 has no local return
-higher_order_discrepancy.erl:14: The pattern 'bar' can never match the type 'foo'
+higher_order_discrepancy.erl:19: Function g/1 has no local return
+higher_order_discrepancy.erl:19: The pattern 'bar' can never match the type 'foo'
diff --git a/lib/dialyzer/test/small_SUITE_data/results/maps1 b/lib/dialyzer/test/small_SUITE_data/results/maps1
index a178e96b20..f36f7f4926 100644
--- a/lib/dialyzer/test/small_SUITE_data/results/maps1
+++ b/lib/dialyzer/test/small_SUITE_data/results/maps1
@@ -1,4 +1,4 @@
maps1.erl:43: Function t3/0 has no local return
-maps1.erl:44: The call maps1:foo(#{'greger'=>3, #{'arne'=>'anka'}=>45},1) will never return since it differs in the 1st and 2nd argument from the success typing arguments: (#{'beta':=_, ...},'b')
+maps1.erl:44: The call maps1:foo(#{'greger'=>3, #{'arne'=>'anka'}=>45},1) will never return since it differs in the 1st and 2nd argument from the success typing arguments: (#{'beta':=_, _=>_},'b')
maps1.erl:52: The variable Mod can never match since previous clauses completely covered the type #{}
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
index ff5ee6bac4..f9547d4929 100644
--- a/lib/dialyzer/test/small_SUITE_data/src/higher_order_discrepancy.erl
+++ b/lib/dialyzer/test/small_SUITE_data/src/higher_order_discrepancy.erl
@@ -1,3 +1,8 @@
+%% With the patch introduced to avoid false warnings in
+%% user_SUITE_data/src/wpc_hlines.erl we can unfortunately no longer precisely
+%% catch problems like this one... The refinement procedure is still enough to
+%% keep some of the details, nevertheless.
+
-module(higher_order_discrepancy).
-export([test/1]).
diff --git a/lib/dialyzer/test/small_SUITE_data/src/loopy.erl b/lib/dialyzer/test/small_SUITE_data/src/loopy.erl
new file mode 100644
index 0000000000..28125ec3d9
--- /dev/null
+++ b/lib/dialyzer/test/small_SUITE_data/src/loopy.erl
@@ -0,0 +1,17 @@
+%% ERL-157, OTP-13653.
+%% Would cause Dialyzer to go into an infinite loop.
+
+-module(loopy).
+
+-export([loop/1]).
+
+
+-spec loop(Args) -> ok when
+ Args :: [{Module, Args}],
+ Module :: module(),
+ Args :: any().
+loop([{Module, Args} | Rest]) ->
+ Module:init(Args),
+ loop(Rest);
+loop([]) ->
+ ok.
diff --git a/lib/dialyzer/test/user_SUITE_data/results/wpc_hlines b/lib/dialyzer/test/user_SUITE_data/results/wpc_hlines
new file mode 100644
index 0000000000..d6e3f29ab9
--- /dev/null
+++ b/lib/dialyzer/test/user_SUITE_data/results/wpc_hlines
@@ -0,0 +1,3 @@
+
+wpc_hlines.erl:22: Function bad/1 has no local return
+wpc_hlines.erl:22: The pattern 'false' can never match the type 'true'
diff --git a/lib/dialyzer/test/user_SUITE_data/src/wpc_hlines.erl b/lib/dialyzer/test/user_SUITE_data/src/wpc_hlines.erl
new file mode 100644
index 0000000000..8c205a8247
--- /dev/null
+++ b/lib/dialyzer/test/user_SUITE_data/src/wpc_hlines.erl
@@ -0,0 +1,22 @@
+%% Bug reported by Dan Gudmundsson, test shrunk down by Magnus LÃ¥ng.
+
+%% The problem is that dialyzer_dep generates edges from the fun
+%% application to both of the functions, and then during the warning pass
+%% dialyzer_dataflow:handle_apply_or_call generates warnings for any such
+%% edge that won't return.
+
+%% Since dialyzer_dep is currently supposed to overapproximate rather than
+%% underapproximate, the fix was to modify handle_apply_or_call to not generate
+%% warnings if some of the possible funs can succeed.
+
+-module(wpc_hlines).
+
+-export([do_export/0]).
+
+do_export() ->
+ {Proj, _} = % The culprit seems to be putting the funs in a tuple
+ {fun good/1, fun bad/1},
+ Proj(true).
+
+good(_) -> ok.
+bad(false) -> ok.
diff --git a/lib/edoc/priv/edoc.dtd b/lib/edoc/priv/edoc.dtd
index 4278a9e643..89058f5d85 100644
--- a/lib/edoc/priv/edoc.dtd
+++ b/lib/edoc/priv/edoc.dtd
@@ -103,7 +103,7 @@
<!ATTLIST type name CDATA #IMPLIED>
<!ELEMENT union (typevar | atom | integer | float | nil | list | tuple |
- fun | record | abstype)+>
+ fun | record | map | abstype)+>
<!ELEMENT typevar EMPTY>
<!ATTLIST typevar name CDATA #REQUIRED>
@@ -129,6 +129,10 @@
<!ELEMENT field (atom, type)>
+<!ELEMENT map (map_field)*>
+
+<!ELEMENT map_field (type, type)>
+
<!ELEMENT abstype (erlangName, type*)>
<!ATTLIST abstype
href CDATA #IMPLIED>
diff --git a/lib/edoc/src/edoc_layout.erl b/lib/edoc/src/edoc_layout.erl
index f723cd8373..ef57b7b084 100644
--- a/lib/edoc/src/edoc_layout.erl
+++ b/lib/edoc/src/edoc_layout.erl
@@ -898,8 +898,14 @@ t_map(Es) ->
Fs = get_elem(map_field, Es),
["#{"] ++ seq(fun t_map_field/1, Fs, ["}"]).
-t_map_field(#xmlElement{content = [K,V]}) ->
- t_utype_elem(K) ++ [" => "] ++ t_utype_elem(V).
+t_map_field(#xmlElement{content = [K,V]}=E) ->
+ KElem = t_utype_elem(K),
+ VElem = t_utype_elem(V),
+ AS = case get_attrval(assoc_type, E) of
+ "assoc" -> " => ";
+ "exact" -> " := "
+ end,
+ KElem ++ [AS] ++ VElem.
t_record(E, Es) ->
Name = ["#"] ++ t_type(get_elem(atom, Es)),
@@ -1133,8 +1139,12 @@ ot_tuple(Es) ->
ot_map(Es) ->
{type,0,map,[ot_map_field(E) || E <- get_elem(map_field,Es)]}.
-ot_map_field(#xmlElement{content=[K,V]}) ->
- {type,0,map_field_assoc,ot_utype_elem(K), ot_utype_elem(V)}.
+ot_map_field(#xmlElement{content=[K,V]}=E) ->
+ A = case get_attrval(assoc_type, E) of
+ "assoc" -> map_field_assoc;
+ "exact" -> map_field_exact
+ end,
+ {type,0,A,[ot_utype_elem(K), ot_utype_elem(V)]}.
ot_fun(Es) ->
Range = ot_utype(get_elem(type, Es)),
diff --git a/lib/edoc/src/edoc_parser.yrl b/lib/edoc/src/edoc_parser.yrl
index 835e7ccaa6..68a3439f10 100644
--- a/lib/edoc/src/edoc_parser.yrl
+++ b/lib/edoc/src/edoc_parser.yrl
@@ -36,8 +36,8 @@ Terminals
atom float integer var an_var string start_spec start_typedef start_throws
start_ref
-'(' ')' ',' '.' '=>' '->' '{' '}' '[' ']' '|' '+' ':' '::' '=' '/' '//' '*'
-'#' 'where' '<<' '>>' '..' '...'.
+'(' ')' ',' '.' '=>' ':=' '->' '{' '}' '[' ']' '|' '+' ':' '::' '=' '/' '//'
+'*' '#' 'where' '<<' '>>' '..' '...'.
Rootsymbol start.
@@ -76,7 +76,12 @@ utype_map_fields -> '$empty' : [].
utype_map_fields -> utype_map_field : ['$1'].
utype_map_fields -> utype_map_fields ',' utype_map_field : ['$3' | '$1'].
-utype_map_field -> utype '=>' utype : #t_map_field{ k_type = '$1', v_type = '$3'}.
+utype_map_field -> utype '=>' utype : #t_map_field{assoc_type = assoc,
+ k_type = '$1',
+ v_type = '$3'}.
+utype_map_field -> utype ':=' utype : #t_map_field{assoc_type = exact,
+ k_type = '$1',
+ v_type = '$3'}.
utype_tuple -> '{' utypes '}' : lists:reverse('$2').
diff --git a/lib/edoc/src/edoc_scanner.erl b/lib/edoc/src/edoc_scanner.erl
index 36423d63f8..f1d5e1d4b9 100644
--- a/lib/edoc/src/edoc_scanner.erl
+++ b/lib/edoc/src/edoc_scanner.erl
@@ -146,6 +146,8 @@ scan1([$>,$>|Cs], Toks, Pos) ->
scan1(Cs, [{'>>',Pos}|Toks], Pos);
scan1([$-,$>|Cs], Toks, Pos) ->
scan1(Cs, [{'->',Pos}|Toks], Pos);
+scan1([$:,$=|Cs], Toks, Pos) ->
+ scan1(Cs, [{':=',Pos}|Toks], Pos);
scan1([$:,$:|Cs], Toks, Pos) ->
scan1(Cs, [{'::',Pos}|Toks], Pos);
scan1([$/,$/|Cs], Toks, Pos) ->
diff --git a/lib/edoc/src/edoc_specs.erl b/lib/edoc/src/edoc_specs.erl
index faee8adf7b..c15dfd328f 100644
--- a/lib/edoc/src/edoc_specs.erl
+++ b/lib/edoc/src/edoc_specs.erl
@@ -369,11 +369,11 @@ d2e({type,_,map,any}, _Prec) ->
d2e({type,_,map,Es}, _Prec) ->
#t_map{types = d2e(Es) };
d2e({type,_,map_field_assoc,[K,V]}, Prec) ->
- T = #t_map_field{k_type = d2e(K), v_type=d2e(V) },
+ T = #t_map_field{assoc_type = assoc, k_type = d2e(K), v_type=d2e(V) },
{P,_R} = erl_parse:type_preop_prec('#'),
maybe_paren(P, Prec, T);
-d2e({type,_,map_field_exact,K,V}, Prec) ->
- T = #t_map_field{k_type = d2e(K), v_type=d2e(V) },
+d2e({type,_,map_field_exact,[K,V]}, Prec) ->
+ T = #t_map_field{assoc_type = exact, k_type = d2e(K), v_type=d2e(V) },
{P,_R} = erl_parse:type_preop_prec('#'),
maybe_paren(P, Prec, T);
d2e({type,_,tuple,Ts0}, _Prec) ->
diff --git a/lib/edoc/src/edoc_types.erl b/lib/edoc/src/edoc_types.erl
index 65fba61a72..5bb68e79fb 100644
--- a/lib/edoc/src/edoc_types.erl
+++ b/lib/edoc/src/edoc_types.erl
@@ -89,8 +89,8 @@ to_xml(#t_fun{args = As, range = T}, Env) ->
wrap_utype(T, Env)]};
to_xml(#t_map{ types = Ts}, Env) ->
{map, map(fun to_xml/2, Ts, Env)};
-to_xml(#t_map_field{ k_type=K, v_type=V}, Env) ->
- {map_field, [wrap_utype(K,Env), wrap_utype(V, Env)]};
+to_xml(#t_map_field{assoc_type = AT, k_type=K, v_type=V}, Env) ->
+ {map_field, [{assoc_type, AT}], [wrap_utype(K,Env), wrap_utype(V, Env)]};
to_xml(#t_tuple{types = Ts}, Env) ->
{tuple, map(fun wrap_utype/2, Ts, Env)};
to_xml(#t_list{type = T}, Env) ->
diff --git a/lib/edoc/src/edoc_types.hrl b/lib/edoc/src/edoc_types.hrl
index 7fec10d936..3e5e91484f 100644
--- a/lib/edoc/src/edoc_types.hrl
+++ b/lib/edoc/src/edoc_types.hrl
@@ -157,5 +157,5 @@
-record(t_paren, {a=[], type}). % parentheses
-record(t_map, {a=[], types=[]}).
--record(t_map_field, {a=[], k_type, v_type}).
+-record(t_map_field, {a=[], assoc_type, k_type, v_type}).
diff --git a/lib/erl_docgen/src/docgen_otp_specs.erl b/lib/erl_docgen/src/docgen_otp_specs.erl
index e154323f07..6c41147e27 100644
--- a/lib/erl_docgen/src/docgen_otp_specs.erl
+++ b/lib/erl_docgen/src/docgen_otp_specs.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 1996-2015. All Rights Reserved.
+%% Copyright Ericsson AB 1996-2016. 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.
@@ -389,10 +389,10 @@ t_type([#xmlElement{name = list, content = Es}]) ->
t_list(Es);
t_type([#xmlElement{name = nonempty_list, content = Es}]) ->
t_nonempty_list(Es);
-t_type([#xmlElement{name = tuple, content = Es}]) ->
- t_tuple(Es);
t_type([#xmlElement{name = map, content = Es}]) ->
t_map(Es);
+t_type([#xmlElement{name = tuple, content = Es}]) ->
+ t_tuple(Es);
t_type([#xmlElement{name = 'fun', content = Es}]) ->
["fun("] ++ t_fun(Es) ++ [")"];
t_type([E = #xmlElement{name = record, content = Es}]) ->
@@ -435,16 +435,22 @@ t_nonempty_list(Es) ->
t_tuple(Es) ->
["{"] ++ seq(fun t_utype_elem/1, Es, ["}"]).
+t_fun(Es) ->
+ ["("] ++ seq(fun t_utype_elem/1, get_content(argtypes, Es),
+ [") -> "] ++ t_utype(get_elem(type, Es))).
+
t_map(Es) ->
Fs = get_elem(map_field, Es),
["#{"] ++ seq(fun t_map_field/1, Fs, ["}"]).
-t_map_field(#xmlElement{content = [K,V]}) ->
- [t_utype_elem(K) ++ " => " ++ t_utype_elem(V)].
-
-t_fun(Es) ->
- ["("] ++ seq(fun t_utype_elem/1, get_content(argtypes, Es),
- [") -> "] ++ t_utype(get_elem(type, Es))).
+t_map_field(#xmlElement{content = [K,V]}=E) ->
+ KElem = t_utype_elem(K),
+ VElem = t_utype_elem(V),
+ AS = case get_attrval(assoc_type, E) of
+ "assoc" -> " => ";
+ "exact" -> " := "
+ end,
+ KElem ++ [AS] ++ VElem.
t_record(E, Es) ->
Name = ["#"] ++ t_type(get_elem(atom, Es)),
@@ -618,8 +624,12 @@ ot_tuple(Es) ->
ot_map(Es) ->
{type,0,map,[ot_map_field(E) || E <- get_elem(map_field,Es)]}.
-ot_map_field(#xmlElement{content=[K,V]}) ->
- {type,0,map_field_assoc,[ot_utype_elem(K),ot_utype_elem(V)]}.
+ot_map_field(#xmlElement{content=[K,V]}=E) ->
+ A = case get_attrval(assoc_type, E) of
+ "assoc" -> map_field_assoc;
+ "exact" -> map_field_exact
+ end,
+ {type,0,A,[ot_utype_elem(K), ot_utype_elem(V)]}.
ot_fun(Es) ->
Range = ot_utype(get_elem(type, Es)),
diff --git a/lib/hipe/cerl/erl_types.erl b/lib/hipe/cerl/erl_types.erl
index c383541020..705fc73613 100644
--- a/lib/hipe/cerl/erl_types.erl
+++ b/lib/hipe/cerl/erl_types.erl
@@ -4302,7 +4302,6 @@ t_to_string(?map(Pairs0,DefK,DefV), RecDict) ->
{Pairs, ExtraEl} =
case {DefK, DefV} of
{?none, ?none} -> {Pairs0, []};
- {?any, ?any} -> {Pairs0, ["..."]};
_ -> {Pairs0 ++ [{DefK,?opt,DefV}], []}
end,
Tos = fun(T) -> case T of
diff --git a/lib/inets/test/httpc_SUITE.erl b/lib/inets/test/httpc_SUITE.erl
index 42772923e4..932567ec55 100644
--- a/lib/inets/test/httpc_SUITE.erl
+++ b/lib/inets/test/httpc_SUITE.erl
@@ -2080,7 +2080,7 @@ run_clients(NumClients, ServerPort, SeqNumServer) ->
end
end),
MRef = erlang:monitor(process, Pid),
- timer:sleep(10 + random:uniform(1334)),
+ timer:sleep(10 + rand:uniform(1334)),
{Id, Pid, MRef}
end,
lists:seq(1, NumClients)).
@@ -2169,7 +2169,7 @@ slowly_send_response(CSock, Answer) ->
[length(Answer), Answer])),
lists:foreach(
fun(Char) ->
- timer:sleep(random:uniform(500)),
+ timer:sleep(rand:uniform(500)),
gen_tcp:send(CSock, <<Char>>)
end,
Response).
@@ -2189,9 +2189,8 @@ parse_connection_type(Request) ->
set_random_seed() ->
Unique = erlang:unique_integer(),
-
A = erlang:phash2([make_ref(), self(), Unique]),
- random:seed(A, A, A).
+ rand:seed(exsplus, {A, A, A}).
otp_8739(doc) ->
diff --git a/lib/kernel/doc/src/gen_tcp.xml b/lib/kernel/doc/src/gen_tcp.xml
index b75d42d198..88135ea43d 100644
--- a/lib/kernel/doc/src/gen_tcp.xml
+++ b/lib/kernel/doc/src/gen_tcp.xml
@@ -153,17 +153,17 @@ do_recv(Sock, Bs) ->
<c><anno>Address</anno></c> can be a hostname or an IP address.</p>
<p>The following options are available:</p>
<taglist>
- <tag><c>{ip, ip_address()}</c></tag>
+ <tag><c>{ip, Address}</c></tag>
<item><p>If the host has many network interfaces, this option
specifies which one to use.</p></item>
- <tag><c>{ifaddr, ip_address()}</c></tag>
- <item><p>Same as <c>{ip, ip_address()}</c>. If the host has many
+ <tag><c>{ifaddr, Address}</c></tag>
+ <item><p>Same as <c>{ip, Address}</c>. If the host has many
network interfaces, this option specifies which one to use.</p>
</item>
<tag><c>{fd, integer() >= 0}</c></tag>
<item><p>If a socket has somehow been connected without using
<c>gen_tcp</c>, use this option to pass the file descriptor
- for it. If <c>{ip, ip_address()}</c> and/or
+ for it. If <c>{ip, Address}</c> and/or
<c>{port, port_number()}</c> is combined with this option, the
<c>fd</c> is bound to the specified interface and port before
connecting. If these options are not specified, it is assumed that
@@ -175,9 +175,10 @@ do_recv(Sock, Bs) ->
<tag><c>local</c></tag>
<item>
<p>
- Sets up the socket for local address family. This option is only
- valid together with <c>{fd, integer()}</c> when the file descriptor
- is of local address family (e.g. a Unix Domain Socket)
+ Sets up a Unix Domain Socket. See
+ <seealso marker="inet#type-local_address">
+ <c>inet:local_address()</c>
+ </seealso>
</p>
</item>
<tag><c>{port, Port}</c></tag>
@@ -254,7 +255,7 @@ do_recv(Sock, Bs) ->
<item><p><c>B</c> is an integer &gt;= <c>0</c>. The backlog value
defines the maximum length that the queue of pending connections
can grow to. Defaults to <c>5</c>.</p></item>
- <tag><c>{ip, ip_address()}</c></tag>
+ <tag><c>{ip, Address}</c></tag>
<item><p>If the host has many network interfaces, this option
specifies which one to listen on.</p></item>
<tag><c>{port, Port}</c></tag>
@@ -263,8 +264,8 @@ do_recv(Sock, Bs) ->
<item><p>If a socket has somehow been connected without using
<c>gen_tcp</c>, use this option to pass the file
descriptor for it.</p></item>
- <tag><c>{ifaddr, ip_address()}</c></tag>
- <item><p>Same as <c>{ip, ip_address()}</c>. If the host has many
+ <tag><c>{ifaddr, Address}</c></tag>
+ <item><p>Same as <c>{ip, Address}</c>. If the host has many
network interfaces, this option specifies which one to use.</p>
</item>
<tag><c>inet6</c></tag>
diff --git a/lib/kernel/doc/src/gen_udp.xml b/lib/kernel/doc/src/gen_udp.xml
index ca9d9c978c..3f88a0272d 100644
--- a/lib/kernel/doc/src/gen_udp.xml
+++ b/lib/kernel/doc/src/gen_udp.xml
@@ -85,11 +85,11 @@
<item><p>Received <c>Packet</c> is delivered as a list.</p></item>
<tag><c>binary</c></tag>
<item><p>Received <c>Packet</c> is delivered as a binary.</p></item>
- <tag><c>{ip, ip_address()}</c></tag>
+ <tag><c>{ip, Address}</c></tag>
<item><p>If the host has many network interfaces, this option
specifies which one to use.</p></item>
- <tag><c>{ifaddr, ip_address()}</c></tag>
- <item><p>Same as <c>{ip, ip_address()}</c>. If the host has many
+ <tag><c>{ifaddr, Address}</c></tag>
+ <item><p>Same as <c>{ip, Address}</c>. If the host has many
network interfaces, this option specifies which one to
use.</p></item>
<tag><c>{fd, integer() >= 0}</c></tag>
@@ -107,9 +107,10 @@
<tag><c>local</c></tag>
<item>
<p>
- Sets up the socket for local address family. This option is only
- valid together with <c>{fd, integer()}</c> when the file descriptor
- is of local address family (e.g. a Unix Domain Socket)
+ Sets up a Unix Domain Socket. See
+ <seealso marker="inet#type-local_address">
+ <c>inet:local_address()</c>
+ </seealso>
</p>
</item>
<tag><c>{udp_module, module()}</c></tag>
@@ -184,8 +185,10 @@
<name name="send" arity="4"/>
<fsummary>Send a packet.</fsummary>
<desc>
- <p>Sends a packet to the specified address and port. Argument
- <c><anno>Address</anno></c> can be a hostname or an IP address.</p>
+ <p>
+ Sends a packet to the specified address and port. Argument
+ <c><anno>Address</anno></c> can be a hostname or a socket address.
+ </p>
</desc>
</func>
</funcs>
diff --git a/lib/kernel/doc/src/inet.xml b/lib/kernel/doc/src/inet.xml
index 5ff167bcb3..c0dce2f50c 100644
--- a/lib/kernel/doc/src/inet.xml
+++ b/lib/kernel/doc/src/inet.xml
@@ -118,6 +118,59 @@ fe80::204:acff:fe17:bf38
<name name="port_number"/>
</datatype>
<datatype>
+ <name name="local_address"/>
+ <desc>
+ <p>
+ This address family only works on Unix-like systems.
+ </p>
+ <p>
+ <c><anno>File</anno></c> is normally a file pathname
+ in a local filesystem. It is limited in length by the
+ operating system, traditionally to 108 bytes.
+ </p>
+ <p>
+ A <c>binary()</c> is passed as is to the operating system,
+ but a <c>string()</c> is encoded according to the
+ <seealso marker="file#native_name_encoding/0">
+ system filename encoding mode.
+ </seealso>
+ </p>
+ <p>
+ Other addresses are possible, for example Linux implements
+ "Abstract Addresses". See the documentation for
+ Unix Domain Sockets on your system,
+ normally <c>unix</c> in manual section 7.
+ </p>
+ <p>
+ In most API functions where you can use
+ this address family the port number must be <c>0</c>.
+ </p>
+ </desc>
+ </datatype>
+ <datatype>
+ <name name="socket_address"/>
+ </datatype>
+ <datatype>
+ <name name="returned_non_ip_address"/>
+ <desc>
+ <p>
+ Addresses besides
+ <seealso marker="#type-ip_address">
+ <c>ip_address()</c>
+ </seealso>
+ ones that are returned from socket API functions.
+ See in particular
+ <seealso marker="#type-local_address">
+ <c>local_address()</c>.
+ </seealso>
+ The <c>unspec</c> family corresponds to AF_UNSPEC and can
+ occur if the other side has no socket address.
+ The <c>undefined</c> family can only occur in the unlikely
+ event of an address family that the VM does not recognize.
+ </p>
+ </desc>
+ </datatype>
+ <datatype>
<name name="posix"/>
<desc>
<p>An atom that is named from the POSIX error codes used in Unix,
diff --git a/lib/kernel/src/gen_tcp.erl b/lib/kernel/src/gen_tcp.erl
index 2b3afcd44c..1a21541b7c 100644
--- a/lib/kernel/src/gen_tcp.erl
+++ b/lib/kernel/src/gen_tcp.erl
@@ -96,17 +96,17 @@
tos |
ipv6_v6only.
-type connect_option() ::
- {ip, inet:ip_address()} |
+ {ip, inet:socket_address()} |
{fd, Fd :: non_neg_integer()} |
- {ifaddr, inet:ip_address()} |
+ {ifaddr, inet:socket_address()} |
inet:address_family() |
{port, inet:port_number()} |
{tcp_module, module()} |
option().
-type listen_option() ::
- {ip, inet:ip_address()} |
+ {ip, inet:socket_address()} |
{fd, Fd :: non_neg_integer()} |
- {ifaddr, inet:ip_address()} |
+ {ifaddr, inet:socket_address()} |
inet:address_family() |
{port, inet:port_number()} |
{backlog, B :: non_neg_integer()} |
@@ -122,7 +122,7 @@
%%
-spec connect(Address, Port, Options) -> {ok, Socket} | {error, Reason} when
- Address :: inet:ip_address() | inet:hostname(),
+ Address :: inet:socket_address() | inet:hostname(),
Port :: inet:port_number(),
Options :: [connect_option()],
Socket :: socket(),
@@ -133,7 +133,7 @@ connect(Address, Port, Opts) ->
-spec connect(Address, Port, Options, Timeout) ->
{ok, Socket} | {error, Reason} when
- Address :: inet:ip_address() | inet:hostname(),
+ Address :: inet:socket_address() | inet:hostname(),
Port :: inet:port_number(),
Options :: [connect_option()],
Timeout :: timeout(),
diff --git a/lib/kernel/src/gen_udp.erl b/lib/kernel/src/gen_udp.erl
index 2227bb3562..98d2f0bcfb 100644
--- a/lib/kernel/src/gen_udp.erl
+++ b/lib/kernel/src/gen_udp.erl
@@ -92,9 +92,9 @@ open(Port) ->
-spec open(Port, Opts) -> {ok, Socket} | {error, Reason} when
Port :: inet:port_number(),
Opts :: [Option],
- Option :: {ip, inet:ip_address()}
+ Option :: {ip, inet:socket_address()}
| {fd, non_neg_integer()}
- | {ifaddr, inet:ip_address()}
+ | {ifaddr, inet:socket_address()}
| inet:address_family()
| {port, inet:port_number()}
| option(),
@@ -114,7 +114,7 @@ close(S) ->
-spec send(Socket, Address, Port, Packet) -> ok | {error, Reason} when
Socket :: socket(),
- Address :: inet:ip_address() | inet:hostname(),
+ Address :: inet:socket_address() | inet:hostname(),
Port :: inet:port_number(),
Packet :: iodata(),
Reason :: not_owner | inet:posix().
@@ -148,7 +148,7 @@ send(S, Packet) when is_port(S) ->
{ok, {Address, Port, Packet}} | {error, Reason} when
Socket :: socket(),
Length :: non_neg_integer(),
- Address :: inet:ip_address(),
+ Address :: inet:ip_address() | inet:returned_non_ip_address(),
Port :: inet:port_number(),
Packet :: string() | binary(),
Reason :: not_owner | inet:posix().
@@ -166,7 +166,7 @@ recv(S,Len) when is_port(S), is_integer(Len) ->
Socket :: socket(),
Length :: non_neg_integer(),
Timeout :: timeout(),
- Address :: inet:ip_address(),
+ Address :: inet:ip_address() | inet:returned_non_ip_address(),
Port :: inet:port_number(),
Packet :: string() | binary(),
Reason :: not_owner | inet:posix().
diff --git a/lib/kernel/src/inet.erl b/lib/kernel/src/inet.erl
index de43ea792b..9fc685e728 100644
--- a/lib/kernel/src/inet.erl
+++ b/lib/kernel/src/inet.erl
@@ -73,9 +73,9 @@
-export([start_timer/1, timeout/1, timeout/2, stop_timer/1]).
-export_type([address_family/0, hostent/0, hostname/0, ip4_address/0,
- ip6_address/0, ip_address/0, posix/0, socket/0,
- port_number/0]).
-
+ ip6_address/0, ip_address/0, port_number/0,
+ local_address/0, socket_address/0, returned_non_ip_address/0,
+ posix/0, socket/0, stat_option/0]).
%% imports
-import(lists, [append/1, duplicate/2, filter/2, foldl/3]).
@@ -98,6 +98,11 @@
0..65535,0..65535,0..65535,0..65535}.
-type ip_address() :: ip4_address() | ip6_address().
-type port_number() :: 0..65535.
+-type local_address() :: {local, File :: binary() | string()}.
+-type returned_non_ip_address() ::
+ {local, binary()} |
+ {unspec, <<>>} |
+ {undefined, any()}.
-type posix() :: exbadport | exbadseq | file:posix().
-type socket() :: port().
@@ -138,7 +143,7 @@
-type socket_protocol() :: 'tcp' | 'udp' | 'sctp'.
-type socket_type() :: 'stream' | 'dgram' | 'seqpacket'.
-type socket_address() ::
- ip_address() | {address_family(), any()} | 'any' | 'loopback'.
+ ip_address() | 'any' | 'loopback' | local_address().
-type stat_option() ::
'recv_cnt' | 'recv_max' | 'recv_avg' | 'recv_oct' | 'recv_dvi' |
'send_cnt' | 'send_max' | 'send_avg' | 'send_oct' | 'send_pend'.
@@ -163,26 +168,33 @@ close(Socket) ->
end.
--spec peername(Socket) -> {ok, {Address, Port}} | {error, posix()} when
- Socket :: socket(),
- Address :: ip_address(),
- Port :: non_neg_integer().
+-spec peername(Socket :: socket()) ->
+ {ok,
+ {ip_address(), port_number()} |
+ returned_non_ip_address()} |
+ {error, posix()}.
peername(Socket) ->
prim_inet:peername(Socket).
--spec setpeername(Socket :: socket(), Address :: {ip_address(), port_number()}) ->
- 'ok' | {'error', any()}.
+-spec setpeername(
+ Socket :: socket(),
+ Address ::
+ {ip_address() | 'any' | 'loopback',
+ port_number()} |
+ socket_address()) ->
+ 'ok' | {'error', any()}.
setpeername(Socket, {IP,Port}) ->
prim_inet:setpeername(Socket, {IP,Port});
setpeername(Socket, undefined) ->
prim_inet:setpeername(Socket, undefined).
--spec peernames(Socket) -> {ok, [{Address, Port}]} | {error, posix()} when
- Socket :: socket(),
- Address :: ip_address(),
- Port :: non_neg_integer().
+-spec peernames(Socket :: socket()) ->
+ {ok,
+ [{ip_address(), port_number()} |
+ returned_non_ip_address()]} |
+ {error, posix()}.
peernames(Socket) ->
prim_inet:peernames(Socket).
@@ -198,15 +210,21 @@ peernames(Socket, Assoc) ->
prim_inet:peernames(Socket, Assoc).
--spec sockname(Socket) -> {ok, {Address, Port}} | {error, posix()} when
- Socket :: socket(),
- Address :: ip_address(),
- Port :: non_neg_integer().
+-spec sockname(Socket :: socket()) ->
+ {ok,
+ {ip_address(), port_number()} |
+ returned_non_ip_address()} |
+ {error, posix()}.
sockname(Socket) ->
prim_inet:sockname(Socket).
--spec setsockname(Socket :: socket(), Address :: {ip_address(), port_number()}) ->
+-spec setsockname(
+ Socket :: socket(),
+ Address ::
+ {ip_address() | 'any' | 'loopback',
+ port_number()} |
+ socket_address()) ->
'ok' | {'error', any()}.
setsockname(Socket, {IP,Port}) ->
@@ -214,10 +232,11 @@ setsockname(Socket, {IP,Port}) ->
setsockname(Socket, undefined) ->
prim_inet:setsockname(Socket, undefined).
--spec socknames(Socket) -> {ok, [{Address, Port}]} | {error, posix()} when
- Socket :: socket(),
- Address :: ip_address(),
- Port :: non_neg_integer().
+-spec socknames(Socket :: socket()) ->
+ {ok,
+ [{ip_address(), port_number()} |
+ returned_non_ip_address()]} |
+ {error, posix()}.
socknames(Socket) ->
prim_inet:socknames(Socket).
@@ -1296,7 +1315,17 @@ gethostbyaddr_tm_native(Addr, Timer, Opts) ->
end.
-spec open(Fd_or_OpenOpts :: integer() | list(),
- Addr :: socket_address(),
+ Addr ::
+ socket_address() |
+ {ip_address() | 'any' | 'loopback', % Unofficial
+ port_number()} |
+ {inet, % Unofficial
+ {ip4_address() | 'any' | 'loopback',
+ port_number()}} |
+ {inet6, % Unofficial
+ {ip6_address() | 'any' | 'loopback',
+ port_number()}} |
+ undefined, % Internal - no bind()
Port :: port_number(),
Opts :: [socket_setopt()],
Protocol :: socket_protocol(),
@@ -1316,11 +1345,16 @@ open(FdO, Addr, Port, Opts, Protocol, Family, Type, Module)
{ok,S} ->
case prim_inet:setopts(S, Opts) of
ok ->
- case if is_list(Addr) ->
- bindx(S, Addr, Port);
- true ->
- prim_inet:bind(S, Addr, Port)
- end of
+ case
+ case Addr of
+ undefined ->
+ {ok, undefined};
+ _ when is_list(Addr) ->
+ bindx(S, Addr, Port);
+ _ ->
+ prim_inet:bind(S, Addr, Port)
+ end
+ of
{ok, _} ->
inet_db:register_socket(S, Module),
{ok,S};
diff --git a/lib/kernel/src/inet_int.hrl b/lib/kernel/src/inet_int.hrl
index 32d09fb63c..c8a8962e78 100644
--- a/lib/kernel/src/inet_int.hrl
+++ b/lib/kernel/src/inet_int.hrl
@@ -25,6 +25,7 @@
%%
%% family codes to open
+-define(INET_AF_UNSPEC, 0).
-define(INET_AF_INET, 1).
-define(INET_AF_INET6, 2).
-define(INET_AF_ANY, 3). % Fake for ANY in any address family
diff --git a/lib/kernel/src/local_tcp.erl b/lib/kernel/src/local_tcp.erl
index 64085ec42e..e3c67dfbb7 100644
--- a/lib/kernel/src/local_tcp.erl
+++ b/lib/kernel/src/local_tcp.erl
@@ -107,8 +107,14 @@ do_connect(Addr = {?FAMILY, _}, 0, Opts, Time) ->
when tuple_size(BAddr) =:= 2, element(1, BAddr) =:= ?FAMILY;
BAddr =:= any ->
case inet:open(
- Fd, BAddr, 0, SockOpts,
- ?PROTO, ?FAMILY, ?TYPE, ?MODULE) of
+ Fd,
+ case BAddr of
+ any ->
+ undefined;
+ _ ->
+ BAddr
+ end,
+ 0, SockOpts, ?PROTO, ?FAMILY, ?TYPE, ?MODULE) of
{ok, S} ->
case prim_inet:connect(S, Addr, 0, Time) of
ok -> {ok,S};
diff --git a/lib/kernel/src/local_udp.erl b/lib/kernel/src/local_udp.erl
index ebb4d2b33f..481a8c4910 100644
--- a/lib/kernel/src/local_udp.erl
+++ b/lib/kernel/src/local_udp.erl
@@ -59,7 +59,14 @@ open(0, Opts) ->
when tuple_size(BAddr) =:= 2, element(1, BAddr) =:= ?FAMILY;
BAddr =:= any ->
inet:open(
- Fd, BAddr, 0, SockOpts, ?PROTO, ?FAMILY, ?TYPE, ?MODULE);
+ Fd,
+ case BAddr of
+ any ->
+ undefined;
+ _ ->
+ BAddr
+ end,
+ 0, SockOpts, ?PROTO, ?FAMILY, ?TYPE, ?MODULE);
{ok, _} -> exit(badarg)
end.
diff --git a/lib/runtime_tools/c_src/dyntrace_lttng.h b/lib/runtime_tools/c_src/dyntrace_lttng.h
index 2a3224e191..5e838892d6 100644
--- a/lib/runtime_tools/c_src/dyntrace_lttng.h
+++ b/lib/runtime_tools/c_src/dyntrace_lttng.h
@@ -19,7 +19,7 @@
*/
#undef TRACEPOINT_PROVIDER
-#define TRACEPOINT_PROVIDER com_ericsson_dyntrace
+#define TRACEPOINT_PROVIDER org_erlang_dyntrace
#if !defined(DYNTRACE_LTTNG_H) || defined(TRACEPOINT_HEADER_MULTI_READ)
#define DYNTRACE_LTTNG_H
@@ -27,22 +27,22 @@
#include <lttng/tracepoint.h>
#define LTTNG1(Name, Arg1) \
- tracepoint(com_ericsson_dyntrace, Name, (Arg1))
+ tracepoint(org_erlang_dyntrace, Name, (Arg1))
#define LTTNG2(Name, Arg1, Arg2) \
- tracepoint(com_ericsson_dyntrace, Name, (Arg1), (Arg2))
+ tracepoint(org_erlang_dyntrace, Name, (Arg1), (Arg2))
#define LTTNG3(Name, Arg1, Arg2, Arg3) \
- tracepoint(com_ericsson_dyntrace, Name, (Arg1), (Arg2), (Arg3))
+ tracepoint(org_erlang_dyntrace, Name, (Arg1), (Arg2), (Arg3))
#define LTTNG4(Name, Arg1, Arg2, Arg3, Arg4) \
- tracepoint(com_ericsson_dyntrace, Name, (Arg1), (Arg2), (Arg3), (Arg4))
+ tracepoint(org_erlang_dyntrace, Name, (Arg1), (Arg2), (Arg3), (Arg4))
#define LTTNG5(Name, Arg1, Arg2, Arg3, Arg4, Arg5) \
- tracepoint(com_ericsson_dyntrace, Name, (Arg1), (Arg2), (Arg3), (Arg4), (Arg5))
+ tracepoint(org_erlang_dyntrace, Name, (Arg1), (Arg2), (Arg3), (Arg4), (Arg5))
#define LTTNG_ENABLED(Name) \
- tracepoint_enabled(com_ericsson_dyntrace, Name)
+ tracepoint_enabled(org_erlang_dyntrace, Name)
#define LTTNG_BUFFER_SZ (256)
#define LTTNG_PROC_BUFFER_SZ (16)
@@ -76,7 +76,7 @@
/* Process scheduling */
TRACEPOINT_EVENT(
- com_ericsson_dyntrace,
+ org_erlang_dyntrace,
process_spawn,
TP_ARGS(
char*, p,
@@ -91,7 +91,7 @@ TRACEPOINT_EVENT(
)
TRACEPOINT_EVENT(
- com_ericsson_dyntrace,
+ org_erlang_dyntrace,
process_link,
TP_ARGS(
char*, from,
@@ -106,7 +106,7 @@ TRACEPOINT_EVENT(
)
TRACEPOINT_EVENT(
- com_ericsson_dyntrace,
+ org_erlang_dyntrace,
process_exit,
TP_ARGS(
char*, p,
@@ -119,7 +119,7 @@ TRACEPOINT_EVENT(
)
TRACEPOINT_EVENT(
- com_ericsson_dyntrace,
+ org_erlang_dyntrace,
process_register,
TP_ARGS(
char*, pid,
@@ -136,7 +136,7 @@ TRACEPOINT_EVENT(
/* Scheduled */
TRACEPOINT_EVENT(
- com_ericsson_dyntrace,
+ org_erlang_dyntrace,
process_scheduled,
TP_ARGS(
char*, p,
@@ -154,7 +154,7 @@ TRACEPOINT_EVENT(
TRACEPOINT_EVENT(
- com_ericsson_dyntrace,
+ org_erlang_dyntrace,
port_open,
TP_ARGS(
char*, pid,
@@ -169,7 +169,7 @@ TRACEPOINT_EVENT(
)
TRACEPOINT_EVENT(
- com_ericsson_dyntrace,
+ org_erlang_dyntrace,
port_exit,
TP_ARGS(
char*, port,
@@ -182,7 +182,7 @@ TRACEPOINT_EVENT(
)
TRACEPOINT_EVENT(
- com_ericsson_dyntrace,
+ org_erlang_dyntrace,
port_link,
TP_ARGS(
char*, from,
@@ -197,7 +197,7 @@ TRACEPOINT_EVENT(
)
TRACEPOINT_EVENT(
- com_ericsson_dyntrace,
+ org_erlang_dyntrace,
port_scheduled,
TP_ARGS(
char*, p,
@@ -214,7 +214,7 @@ TRACEPOINT_EVENT(
/* Call tracing */
TRACEPOINT_EVENT(
- com_ericsson_dyntrace,
+ org_erlang_dyntrace,
function_call,
TP_ARGS(
char*, pid,
@@ -229,7 +229,7 @@ TRACEPOINT_EVENT(
)
TRACEPOINT_EVENT(
- com_ericsson_dyntrace,
+ org_erlang_dyntrace,
function_return,
TP_ARGS(
char*, pid,
@@ -244,7 +244,7 @@ TRACEPOINT_EVENT(
)
TRACEPOINT_EVENT(
- com_ericsson_dyntrace,
+ org_erlang_dyntrace,
function_exception,
TP_ARGS(
char*, pid,
@@ -261,7 +261,7 @@ TRACEPOINT_EVENT(
/* Process messages */
TRACEPOINT_EVENT(
- com_ericsson_dyntrace,
+ org_erlang_dyntrace,
message_send,
TP_ARGS(
char*, sender,
@@ -276,7 +276,7 @@ TRACEPOINT_EVENT(
)
TRACEPOINT_EVENT(
- com_ericsson_dyntrace,
+ org_erlang_dyntrace,
message_receive,
TP_ARGS(
char*, receiver,
@@ -291,7 +291,7 @@ TRACEPOINT_EVENT(
/* Process Memory */
TRACEPOINT_EVENT(
- com_ericsson_dyntrace,
+ org_erlang_dyntrace,
gc_minor_start,
TP_ARGS(
char*, p,
@@ -308,7 +308,7 @@ TRACEPOINT_EVENT(
)
TRACEPOINT_EVENT(
- com_ericsson_dyntrace,
+ org_erlang_dyntrace,
gc_minor_end,
TP_ARGS(
char*, p,
@@ -325,7 +325,7 @@ TRACEPOINT_EVENT(
)
TRACEPOINT_EVENT(
- com_ericsson_dyntrace,
+ org_erlang_dyntrace,
gc_major_start,
TP_ARGS(
char*, p,
@@ -342,7 +342,7 @@ TRACEPOINT_EVENT(
)
TRACEPOINT_EVENT(
- com_ericsson_dyntrace,
+ org_erlang_dyntrace,
gc_major_end,
TP_ARGS(
char*, p,
diff --git a/lib/runtime_tools/doc/src/LTTng.xml b/lib/runtime_tools/doc/src/LTTng.xml
index 9b490a27a0..82a4c79379 100644
--- a/lib/runtime_tools/doc/src/LTTng.xml
+++ b/lib/runtime_tools/doc/src/LTTng.xml
@@ -66,7 +66,7 @@ $ make </code>
<section>
<title>Dyntrace Tracepoints</title>
- <p>All tracepoints are in the domain of <c>com_ericsson_dyntrace</c></p>
+ <p>All tracepoints are in the domain of <c>org_erlang_dyntrace</c></p>
<p>All Erlang types are the string equivalent in LTTng.</p>
<p><em>process_spawn</em></p>
@@ -310,7 +310,7 @@ $ make </code>
<section>
<title>BEAM Tracepoints</title>
- <p>All tracepoints are in the domain of <c>com_ericsson_otp</c></p>
+ <p>All tracepoints are in the domain of <c>org_erlang_otp</c></p>
<p>All Erlang types are the string equivalent in LTTng.</p>
<p><em>scheduler_poll</em></p>
@@ -550,8 +550,8 @@ Eshell V8.0 (abort with ^G)
<p>Enable the process_register LTTng tracepoint for Erlang.</p>
- <pre>$ lttng enable-event -u com_ericsson_dyntrace:process_register
-UST event com_ericsson_dyntrace:process_register created in channel channel0</pre>
+ <pre>$ lttng enable-event -u org_erlang_dyntrace:process_register
+UST event org_erlang_dyntrace:process_register created in channel channel0</pre>
<p>Enable process tracing for new processes and use <c>dyntrace</c> as tracer backend.</p>
@@ -573,23 +573,23 @@ Tracing started for session erlang-demo</pre>
<pre>$ lttng stop
Tracing stopped for session erlang-demo
$ lttng view
-[17:20:42.561168759] (+?.?????????) elxd1168lx9 com_ericsson_dyntrace:process_register: \
+[17:20:42.561168759] (+?.?????????) elxd1168lx9 org_erlang_dyntrace:process_register: \
{ cpu_id = 5 }, { pid = "&lt;0.66.0&gt;", name = "sasl_sup", type = "register" }
-[17:20:42.561215519] (+0.000046760) elxd1168lx9 com_ericsson_dyntrace:process_register: \
+[17:20:42.561215519] (+0.000046760) elxd1168lx9 org_erlang_dyntrace:process_register: \
{ cpu_id = 5 }, { pid = "&lt;0.67.0&gt;", name = "sasl_safe_sup", type = "register" }
-[17:20:42.562149024] (+0.000933505) elxd1168lx9 com_ericsson_dyntrace:process_register: \
+[17:20:42.562149024] (+0.000933505) elxd1168lx9 org_erlang_dyntrace:process_register: \
{ cpu_id = 5 }, { pid = "&lt;0.68.0&gt;", name = "alarm_handler", type = "register" }
-[17:20:42.571035803] (+0.008886779) elxd1168lx9 com_ericsson_dyntrace:process_register: \
+[17:20:42.571035803] (+0.008886779) elxd1168lx9 org_erlang_dyntrace:process_register: \
{ cpu_id = 5 }, { pid = "&lt;0.69.0&gt;", name = "release_handler", type = "register" }
-[17:20:42.574939868] (+0.003904065) elxd1168lx9 com_ericsson_dyntrace:process_register: \
+[17:20:42.574939868] (+0.003904065) elxd1168lx9 org_erlang_dyntrace:process_register: \
{ cpu_id = 5 }, { pid = "&lt;0.74.0&gt;", name = "os_mon_sup", type = "register" }
-[17:20:42.576818712] (+0.001878844) elxd1168lx9 com_ericsson_dyntrace:process_register: \
+[17:20:42.576818712] (+0.001878844) elxd1168lx9 org_erlang_dyntrace:process_register: \
{ cpu_id = 5 }, { pid = "&lt;0.75.0&gt;", name = "disksup", type = "register" }
-[17:20:42.580032013] (+0.003213301) elxd1168lx9 com_ericsson_dyntrace:process_register: \
+[17:20:42.580032013] (+0.003213301) elxd1168lx9 org_erlang_dyntrace:process_register: \
{ cpu_id = 5 }, { pid = "&lt;0.76.0&gt;", name = "memsup", type = "register" }
-[17:20:42.583046339] (+0.003014326) elxd1168lx9 com_ericsson_dyntrace:process_register: \
+[17:20:42.583046339] (+0.003014326) elxd1168lx9 org_erlang_dyntrace:process_register: \
{ cpu_id = 5 }, { pid = "&lt;0.78.0&gt;", name = "cpu_sup", type = "register" }
-[17:20:42.586206242] (+0.003159903) elxd1168lx9 com_ericsson_dyntrace:process_register: \
+[17:20:42.586206242] (+0.003159903) elxd1168lx9 org_erlang_dyntrace:process_register: \
{ cpu_id = 5 }, { pid = "&lt;0.82.0&gt;", name = "timer_server", type = "register" }</pre>
</section>
</chapter>
diff --git a/lib/runtime_tools/test/dyntrace_lttng_SUITE.erl b/lib/runtime_tools/test/dyntrace_lttng_SUITE.erl
index 07707c6a12..a98ac6e99c 100644
--- a/lib/runtime_tools/test/dyntrace_lttng_SUITE.erl
+++ b/lib/runtime_tools/test/dyntrace_lttng_SUITE.erl
@@ -84,25 +84,25 @@ end_per_testcase(Case, _Config) ->
%% tracepoints
%%
-%% com_ericsson_dyntrace:gc_major_end
-%% com_ericsson_dyntrace:gc_major_start
-%% com_ericsson_dyntrace:gc_minor_end
-%% com_ericsson_dyntrace:gc_minor_start
-%% com_ericsson_dyntrace:message_receive
-%% com_ericsson_dyntrace:message_send
-%% -com_ericsson_dyntrace:message_queued
-%% com_ericsson_dyntrace:function_exception
-%% com_ericsson_dyntrace:function_return
-%% com_ericsson_dyntrace:function_call
-%% com_ericsson_dyntrace:port_link
-%% com_ericsson_dyntrace:port_exit
-%% com_ericsson_dyntrace:port_open
-%% com_ericsson_dyntrace:port_scheduled
-%% com_ericsson_dyntrace:process_scheduled
-%% com_ericsson_dyntrace:process_register
-%% com_ericsson_dyntrace:process_exit
-%% com_ericsson_dyntrace:process_link
-%% com_ericsson_dyntrace:process_spawn
+%% org_erlang_dyntrace:gc_major_end
+%% org_erlang_dyntrace:gc_major_start
+%% org_erlang_dyntrace:gc_minor_end
+%% org_erlang_dyntrace:gc_minor_start
+%% org_erlang_dyntrace:message_receive
+%% org_erlang_dyntrace:message_send
+%% -org_erlang_dyntrace:message_queued
+%% org_erlang_dyntrace:function_exception
+%% org_erlang_dyntrace:function_return
+%% org_erlang_dyntrace:function_call
+%% org_erlang_dyntrace:port_link
+%% org_erlang_dyntrace:port_exit
+%% org_erlang_dyntrace:port_open
+%% org_erlang_dyntrace:port_scheduled
+%% org_erlang_dyntrace:process_scheduled
+%% org_erlang_dyntrace:process_register
+%% org_erlang_dyntrace:process_exit
+%% org_erlang_dyntrace:process_link
+%% org_erlang_dyntrace:process_spawn
%%
%% Testcases
%%
@@ -112,7 +112,7 @@ t_lttng_list(_Config) ->
ok.
t_procs(Config) when is_list(Config) ->
- ok = lttng_start_event("com_ericsson_dyntrace:process_*", Config),
+ ok = lttng_start_event("org_erlang_dyntrace:process_*", Config),
_ = erlang:trace(new, true, [{tracer, dyntrace, []},procs]),
Pid = spawn_link(fun() -> waiter() end),
@@ -122,27 +122,27 @@ t_procs(Config) when is_list(Config) ->
_ = erlang:trace(all, false, [procs]),
Res = lttng_stop_and_view(Config),
- ok = check_tracepoint("com_ericsson_dyntrace:process_spawn", Res),
- ok = check_tracepoint("com_ericsson_dyntrace:process_link", Res),
- ok = check_tracepoint("com_ericsson_dyntrace:process_exit", Res),
- ok = check_tracepoint("com_ericsson_dyntrace:process_register", Res),
+ ok = check_tracepoint("org_erlang_dyntrace:process_spawn", Res),
+ ok = check_tracepoint("org_erlang_dyntrace:process_link", Res),
+ ok = check_tracepoint("org_erlang_dyntrace:process_exit", Res),
+ ok = check_tracepoint("org_erlang_dyntrace:process_register", Res),
ok.
t_ports(Config) when is_list(Config) ->
- ok = lttng_start_event("com_ericsson_dyntrace:port_*", Config),
+ ok = lttng_start_event("org_erlang_dyntrace:port_*", Config),
_ = erlang:trace(new, true, [{tracer, dyntrace, []},ports]),
_ = os:cmd("ls"),
_ = erlang:trace(all, false, [{tracer, dyntrace, []},ports]),
Res = lttng_stop_and_view(Config),
- ok = check_tracepoint("com_ericsson_dyntrace:port_open", Res),
- ok = check_tracepoint("com_ericsson_dyntrace:port_link", Res),
- ok = check_tracepoint("com_ericsson_dyntrace:port_exit", Res),
+ ok = check_tracepoint("org_erlang_dyntrace:port_open", Res),
+ ok = check_tracepoint("org_erlang_dyntrace:port_link", Res),
+ ok = check_tracepoint("org_erlang_dyntrace:port_exit", Res),
ok.
t_running_process(Config) when is_list(Config) ->
- ok = lttng_start_event("com_ericsson_dyntrace:process_scheduled", Config),
+ ok = lttng_start_event("org_erlang_dyntrace:process_scheduled", Config),
_ = erlang:trace(new, true, [{tracer, dyntrace, []},running]),
Pid = spawn_link(fun() -> waiter() end),
@@ -152,11 +152,11 @@ t_running_process(Config) when is_list(Config) ->
_ = erlang:trace(all, false, [running]),
Res = lttng_stop_and_view(Config),
- ok = check_tracepoint("com_ericsson_dyntrace:process_scheduled", Res),
+ ok = check_tracepoint("org_erlang_dyntrace:process_scheduled", Res),
ok.
t_running_port(Config) when is_list(Config) ->
- ok = lttng_start_event("com_ericsson_dyntrace:port_scheduled", Config),
+ ok = lttng_start_event("org_erlang_dyntrace:port_scheduled", Config),
_ = erlang:trace(new, true, [{tracer, dyntrace, []},running_ports]),
_ = os:cmd("ls"),
@@ -164,12 +164,12 @@ t_running_port(Config) when is_list(Config) ->
_ = erlang:trace(all, false, [running_ports]),
Res = lttng_stop_and_view(Config),
- ok = check_tracepoint("com_ericsson_dyntrace:port_scheduled", Res),
+ ok = check_tracepoint("org_erlang_dyntrace:port_scheduled", Res),
ok.
t_call(Config) when is_list(Config) ->
- ok = lttng_start_event("com_ericsson_dyntrace:function_*", Config),
+ ok = lttng_start_event("org_erlang_dyntrace:function_*", Config),
_ = erlang:trace(new, true, [{tracer, dyntrace, []}, call]),
_ = erlang:trace_pattern({?MODULE, '_', '_'}, [{'_',[],[{exception_trace}]}], [local]),
@@ -184,13 +184,13 @@ t_call(Config) when is_list(Config) ->
_ = erlang:trace_pattern({?MODULE, '_', '_'}, false, [local]),
_ = erlang:trace(all, false, [call]),
Res = lttng_stop_and_view(Config),
- ok = check_tracepoint("com_ericsson_dyntrace:function_call", Res),
- ok = check_tracepoint("com_ericsson_dyntrace:function_return", Res),
- ok = check_tracepoint("com_ericsson_dyntrace:function_exception", Res),
+ ok = check_tracepoint("org_erlang_dyntrace:function_call", Res),
+ ok = check_tracepoint("org_erlang_dyntrace:function_return", Res),
+ ok = check_tracepoint("org_erlang_dyntrace:function_exception", Res),
ok.
t_send(Config) when is_list(Config) ->
- ok = lttng_start_event("com_ericsson_dyntrace:message_send", Config),
+ ok = lttng_start_event("org_erlang_dyntrace:message_send", Config),
_ = erlang:trace(new, true, [{tracer, dyntrace, []},send]),
Pid = spawn_link(fun() -> waiter() end),
@@ -201,11 +201,11 @@ t_send(Config) when is_list(Config) ->
_ = erlang:trace(all, false, [send]),
Res = lttng_stop_and_view(Config),
- ok = check_tracepoint("com_ericsson_dyntrace:message_send", Res),
+ ok = check_tracepoint("org_erlang_dyntrace:message_send", Res),
ok.
t_call_return_to(Config) when is_list(Config) ->
- ok = lttng_start_event("com_ericsson_dyntrace:function_*", Config),
+ ok = lttng_start_event("org_erlang_dyntrace:function_*", Config),
_ = erlang:trace(new, true, [{tracer, dyntrace, []}, call, return_to]),
_ = erlang:trace_pattern({lists, '_', '_'}, true, [local]),
_ = erlang:trace_pattern({?MODULE, '_', '_'}, true, [local]),
@@ -219,11 +219,11 @@ t_call_return_to(Config) when is_list(Config) ->
_ = erlang:trace_pattern({lists, '_', '_'}, false, [local]),
_ = erlang:trace(all, false, [call,return_to]),
Res = lttng_stop_and_view(Config),
- ok = check_tracepoint("com_ericsson_dyntrace:function_call", Res),
+ ok = check_tracepoint("org_erlang_dyntrace:function_call", Res),
ok.
t_call_silent(Config) when is_list(Config) ->
- ok = lttng_start_event("com_ericsson_dyntrace:function_*", Config),
+ ok = lttng_start_event("org_erlang_dyntrace:function_*", Config),
_ = erlang:trace(new, true, [{tracer, dyntrace, []}, call, silent]),
_ = erlang:trace_pattern({?MODULE, '_', '_'}, [{'_',[],[{exception_trace}]}], [local]),
@@ -238,14 +238,14 @@ t_call_silent(Config) when is_list(Config) ->
_ = erlang:trace_pattern({?MODULE, '_', '_'}, false, [local]),
_ = erlang:trace(all, false, [call]),
Res = lttng_stop_and_view(Config),
- notfound = check_tracepoint("com_ericsson_dyntrace:function_call", Res),
- notfound = check_tracepoint("com_ericsson_dyntrace:function_return", Res),
- notfound = check_tracepoint("com_ericsson_dyntrace:function_exception", Res),
+ notfound = check_tracepoint("org_erlang_dyntrace:function_call", Res),
+ notfound = check_tracepoint("org_erlang_dyntrace:function_return", Res),
+ notfound = check_tracepoint("org_erlang_dyntrace:function_exception", Res),
ok.
t_receive(Config) when is_list(Config) ->
- ok = lttng_start_event("com_ericsson_dyntrace:message_receive", Config),
+ ok = lttng_start_event("org_erlang_dyntrace:message_receive", Config),
_ = erlang:trace(new, true, [{tracer, dyntrace, []},'receive']),
timer:sleep(20),
@@ -260,11 +260,11 @@ t_receive(Config) when is_list(Config) ->
timer:sleep(10),
_ = erlang:trace(all, false, ['receive']),
Res = lttng_stop_and_view(Config),
- ok = check_tracepoint("com_ericsson_dyntrace:message_receive", Res),
+ ok = check_tracepoint("org_erlang_dyntrace:message_receive", Res),
ok.
t_garbage_collection(Config) when is_list(Config) ->
- ok = lttng_start_event("com_ericsson_dyntrace:gc_*", Config),
+ ok = lttng_start_event("org_erlang_dyntrace:gc_*", Config),
_ = erlang:trace(new, true, [{tracer, dyntrace, []},garbage_collection]),
Pid = spawn_link(fun() -> gcfier() end),
@@ -273,14 +273,14 @@ t_garbage_collection(Config) when is_list(Config) ->
timer:sleep(10),
_ = erlang:trace(all, false, [garbage_collection]),
Res = lttng_stop_and_view(Config),
- ok = check_tracepoint("com_ericsson_dyntrace:gc_major_start", Res),
- ok = check_tracepoint("com_ericsson_dyntrace:gc_major_end", Res),
- ok = check_tracepoint("com_ericsson_dyntrace:gc_minor_start", Res),
- ok = check_tracepoint("com_ericsson_dyntrace:gc_minor_end", Res),
+ ok = check_tracepoint("org_erlang_dyntrace:gc_major_start", Res),
+ ok = check_tracepoint("org_erlang_dyntrace:gc_major_end", Res),
+ ok = check_tracepoint("org_erlang_dyntrace:gc_minor_start", Res),
+ ok = check_tracepoint("org_erlang_dyntrace:gc_minor_end", Res),
ok.
t_all(Config) when is_list(Config) ->
- ok = lttng_start_event("com_ericsson_dyntrace:*", Config),
+ ok = lttng_start_event("org_erlang_dyntrace:*", Config),
_ = erlang:trace(new, true, [{tracer, dyntrace, []},all]),
Pid1 = spawn_link(fun() -> waiter() end),
@@ -297,21 +297,21 @@ t_all(Config) when is_list(Config) ->
_ = erlang:trace(all, false, [all]),
Res = lttng_stop_and_view(Config),
- ok = check_tracepoint("com_ericsson_dyntrace:process_spawn", Res),
- ok = check_tracepoint("com_ericsson_dyntrace:process_link", Res),
- ok = check_tracepoint("com_ericsson_dyntrace:process_exit", Res),
- ok = check_tracepoint("com_ericsson_dyntrace:process_register", Res),
- ok = check_tracepoint("com_ericsson_dyntrace:port_open", Res),
- ok = check_tracepoint("com_ericsson_dyntrace:port_link", Res),
- ok = check_tracepoint("com_ericsson_dyntrace:port_exit", Res),
- ok = check_tracepoint("com_ericsson_dyntrace:process_scheduled", Res),
- ok = check_tracepoint("com_ericsson_dyntrace:port_scheduled", Res),
- ok = check_tracepoint("com_ericsson_dyntrace:message_send", Res),
- ok = check_tracepoint("com_ericsson_dyntrace:message_receive", Res),
- ok = check_tracepoint("com_ericsson_dyntrace:gc_major_start", Res),
- ok = check_tracepoint("com_ericsson_dyntrace:gc_major_end", Res),
- ok = check_tracepoint("com_ericsson_dyntrace:gc_minor_start", Res),
- ok = check_tracepoint("com_ericsson_dyntrace:gc_minor_end", Res),
+ ok = check_tracepoint("org_erlang_dyntrace:process_spawn", Res),
+ ok = check_tracepoint("org_erlang_dyntrace:process_link", Res),
+ ok = check_tracepoint("org_erlang_dyntrace:process_exit", Res),
+ ok = check_tracepoint("org_erlang_dyntrace:process_register", Res),
+ ok = check_tracepoint("org_erlang_dyntrace:port_open", Res),
+ ok = check_tracepoint("org_erlang_dyntrace:port_link", Res),
+ ok = check_tracepoint("org_erlang_dyntrace:port_exit", Res),
+ ok = check_tracepoint("org_erlang_dyntrace:process_scheduled", Res),
+ ok = check_tracepoint("org_erlang_dyntrace:port_scheduled", Res),
+ ok = check_tracepoint("org_erlang_dyntrace:message_send", Res),
+ ok = check_tracepoint("org_erlang_dyntrace:message_receive", Res),
+ ok = check_tracepoint("org_erlang_dyntrace:gc_major_start", Res),
+ ok = check_tracepoint("org_erlang_dyntrace:gc_major_end", Res),
+ ok = check_tracepoint("org_erlang_dyntrace:gc_minor_start", Res),
+ ok = check_tracepoint("org_erlang_dyntrace:gc_minor_end", Res),
ok.
diff --git a/lib/ssh/test/ssh_algorithms_SUITE.erl b/lib/ssh/test/ssh_algorithms_SUITE.erl
index ed9e7aacaa..0f68130a05 100644
--- a/lib/ssh/test/ssh_algorithms_SUITE.erl
+++ b/lib/ssh/test/ssh_algorithms_SUITE.erl
@@ -24,6 +24,7 @@
-include_lib("common_test/include/ct.hrl").
-include_lib("ssh/src/ssh_transport.hrl").
+-include("ssh_test_lib.hrl").
%% Note: This directive should only be used in test suites.
-compile(export_all).
@@ -70,32 +71,39 @@ two_way_tags() -> [cipher,mac,compression].
%%--------------------------------------------------------------------
init_per_suite(Config) ->
- ct:log("~n"
- "Environment:~n============~n"
- "os:getenv(\"HOME\") = ~p~n"
- "init:get_argument(home) = ~p~n~n~n"
- "OS ssh:~n=======~n~p~n~n~n"
- "Erl ssh:~n========~n~p~n~n~n"
- "Installed ssh client:~n=====================~n~p~n~n~n"
- "Installed ssh server:~n=====================~n~p~n~n~n"
- "Misc values:~n============~n"
- " -- Default dh group exchange parameters ({min,def,max}): ~p~n"
- " -- dh_default_groups: ~p~n"
- " -- Max num algorithms: ~p~n"
- ,[os:getenv("HOME"),
- init:get_argument(home),
- os:cmd("ssh -V"),
- ssh:default_algorithms(),
- ssh_test_lib:default_algorithms(sshc),
- ssh_test_lib:default_algorithms(sshd),
- {?DEFAULT_DH_GROUP_MIN,?DEFAULT_DH_GROUP_NBITS,?DEFAULT_DH_GROUP_MAX},
- public_key:dh_gex_group_sizes(),
- ?MAX_NUM_ALGORITHMS
- ]),
- ct:log("all() ->~n ~p.~n~ngroups()->~n ~p.~n",[all(),groups()]),
- ssh:start(),
- [{std_simple_sftp_size,25000} % Sftp transferred data size
- | setup_pubkey(Config)].
+ ?CHECK_CRYPTO(
+ begin
+ ct:log("~n"
+ "Environment:~n============~n"
+ "os:getenv(\"HOME\") = ~p~n"
+ "init:get_argument(home) = ~p~n~n~n"
+ "OS ssh:~n=======~n~p~n~n~n"
+ "Erl ssh:~n========~n~p~n~n~n"
+ "crypto:info_lib():~n========~n~p~n~n~n"
+ "Installed ssh client:~n=====================~n~p~n~n~n"
+ "Installed ssh server:~n=====================~n~p~n~n~n"
+ "Misc values:~n============~n"
+ " -- Default dh group exchange parameters ({min,def,max}): ~p~n"
+ " -- dh_default_groups: ~p~n"
+ " -- Max num algorithms: ~p~n"
+ ,[os:getenv("HOME"),
+ init:get_argument(home),
+ os:cmd("ssh -V"),
+ ssh:default_algorithms(),
+ crypto:info_lib(),
+ ssh_test_lib:default_algorithms(sshc),
+ ssh_test_lib:default_algorithms(sshd),
+ {?DEFAULT_DH_GROUP_MIN,?DEFAULT_DH_GROUP_NBITS,?DEFAULT_DH_GROUP_MAX},
+ public_key:dh_gex_group_sizes(),
+ ?MAX_NUM_ALGORITHMS
+ ]),
+ ct:log("all() ->~n ~p.~n~ngroups()->~n ~p.~n",[all(),groups()]),
+ ssh:start(),
+ [{std_simple_sftp_size,25000} % Sftp transferred data size
+ | setup_pubkey(Config)]
+ end
+ ).
+
end_per_suite(_Config) ->
ssh:stop().
diff --git a/lib/ssh/test/ssh_basic_SUITE.erl b/lib/ssh/test/ssh_basic_SUITE.erl
index 4991816850..733414e23a 100644
--- a/lib/ssh/test/ssh_basic_SUITE.erl
+++ b/lib/ssh/test/ssh_basic_SUITE.erl
@@ -25,6 +25,7 @@
-include_lib("common_test/include/ct.hrl").
-include_lib("kernel/include/inet.hrl").
-include_lib("kernel/include/file.hrl").
+-include("ssh_test_lib.hrl").
%% Note: This directive should only be used in test suites.
%%-compile(export_all).
@@ -130,7 +131,7 @@ basic_tests() ->
%%--------------------------------------------------------------------
init_per_suite(Config) ->
- Config.
+ ?CHECK_CRYPTO(Config).
end_per_suite(_Config) ->
ssh:stop().
diff --git a/lib/ssh/test/ssh_connection_SUITE.erl b/lib/ssh/test/ssh_connection_SUITE.erl
index a52633a269..bcf3b01824 100644
--- a/lib/ssh/test/ssh_connection_SUITE.erl
+++ b/lib/ssh/test/ssh_connection_SUITE.erl
@@ -43,6 +43,7 @@ suite() ->
all() ->
[
{group, openssh},
+ small_interrupted_send,
interrupted_send,
start_shell,
start_shell_exec,
@@ -81,7 +82,7 @@ sock() ->
%%--------------------------------------------------------------------
init_per_suite(Config) ->
- Config.
+ ?CHECK_CRYPTO(Config).
end_per_suite(Config) ->
Config.
@@ -124,7 +125,7 @@ simple_exec(Config) when is_list(Config) ->
do_simple_exec(ConnectionRef).
-simple_exec_sock(Config) ->
+simple_exec_sock(_Config) ->
{ok, Sock} = gen_tcp:connect("localhost", ?SSH_DEFAULT_PORT, [{active,false}]),
{ok, ConnectionRef} = ssh:connect(Sock, [{silently_accept_hosts, true},
{user_interaction, false}]),
@@ -361,44 +362,96 @@ ptty_alloc_pixel(Config) when is_list(Config) ->
ssh:close(ConnectionRef).
%%--------------------------------------------------------------------
+small_interrupted_send(Config) ->
+ K = 1024,
+ M = K*K,
+ do_interrupted_send(Config, 10*M, 4*K).
interrupted_send(Config) ->
+ M = 1024*1024,
+ do_interrupted_send(Config, 10*M, 4*M).
+
+do_interrupted_send(Config, SendSize, EchoSize) ->
PrivDir = proplists:get_value(priv_dir, Config),
UserDir = filename:join(PrivDir, nopubkey), % to make sure we don't use public-key-auth
file:make_dir(UserDir),
SysDir = proplists:get_value(data_dir, Config),
+ EchoSS_spec = {ssh_echo_server, [EchoSize,[{dbg,true}]]},
{Pid, Host, Port} = ssh_test_lib:daemon([{system_dir, SysDir},
{user_dir, UserDir},
{password, "morot"},
- {subsystems, [{"echo_n", {ssh_echo_server, [4000000]}}]}]),
-
+ {subsystems, [{"echo_n",EchoSS_spec}]}]),
+
+ ct:log("connect", []),
ConnectionRef = ssh_test_lib:connect(Host, Port, [{silently_accept_hosts, true},
{user, "foo"},
{password, "morot"},
{user_interaction, false},
{user_dir, UserDir}]),
-
- {ok, ChannelId} = ssh_connection:session_channel(ConnectionRef, infinity),
-
- success = ssh_connection:subsystem(ConnectionRef, ChannelId, "echo_n", infinity),
-
- %% build 10MB binary
- Data = << <<X:32>> || X <- lists:seq(1,2500000)>>,
-
- %% expect remote end to send us 4MB back
- <<ExpectedData:4000000/binary, _/binary>> = Data,
-
- %% pre-adjust receive window so the other end doesn't block
- ssh_connection:adjust_window(ConnectionRef, ChannelId, size(ExpectedData) + 1),
-
- case ssh_connection:send(ConnectionRef, ChannelId, Data, 10000) of
- {error, closed} ->
- ok;
- Msg ->
- ct:fail({expected,{error,closed}, got, Msg})
- end,
- receive_data(ExpectedData, ConnectionRef, ChannelId),
- ssh:close(ConnectionRef),
- ssh:stop_daemon(Pid).
+ ct:log("connected", []),
+
+ %% build big binary
+ Data = << <<X:32>> || X <- lists:seq(1,SendSize div 4)>>,
+
+ %% expect remote end to send us EchoSize back
+ <<ExpectedData:EchoSize/binary, _/binary>> = Data,
+
+ %% Spawn listener. Otherwise we could get a deadlock due to filled buffers
+ Parent = self(),
+ ResultPid = spawn(
+ fun() ->
+ ct:log("open channel",[]),
+ {ok, ChannelId} = ssh_connection:session_channel(ConnectionRef, infinity),
+ ct:log("start subsystem", []),
+ case ssh_connection:subsystem(ConnectionRef, ChannelId, "echo_n", infinity) of
+ success ->
+ Parent ! {self(), channelId, ChannelId},
+
+ Result =
+ try collect_data(ConnectionRef, ChannelId)
+ of
+ ExpectedData ->
+ ok;
+ _ ->
+ {fail,"unexpected result"}
+ catch
+ Class:Exception ->
+ {fail, io_lib:format("Exception ~p:~p",[Class,Exception])}
+ end,
+ Parent ! {self(), Result};
+ Other ->
+ Parent ! {self(), channelId, error, Other}
+ end
+ end),
+
+ receive
+ {ResultPid, channelId, ChannelId} ->
+ %% pre-adjust receive window so the other end doesn't block
+ ct:log("adjust window", []),
+ ssh_connection:adjust_window(ConnectionRef, ChannelId, size(ExpectedData) + 1),
+
+ ct:log("going to send ~p bytes", [size(Data)]),
+ case ssh_connection:send(ConnectionRef, ChannelId, Data, 30000) of
+ {error, closed} ->
+ ct:log("{error,closed} - That's what we expect :)", []),
+ ok;
+ Msg ->
+ ct:log("Got ~p - that's bad, very bad indeed",[Msg]),
+ ct:fail({expected,{error,closed}, got, Msg})
+ end,
+ ct:log("going to check the result (if it is available)", []),
+ receive
+ {ResultPid, Result} ->
+ ct:log("Got result: ~p", [Result]),
+ ssh:close(ConnectionRef),
+ ssh:stop_daemon(Pid),
+ Result
+ end;
+
+ {ResultPid, channelId, error, Other} ->
+ ssh:close(ConnectionRef),
+ ssh:stop_daemon(Pid),
+ {fail, io_lib:format("ssh_connection:subsystem: ~p",[Other])}
+ end.
%%--------------------------------------------------------------------
start_shell() ->
@@ -549,10 +602,10 @@ start_shell_sock_daemon_exec(Config) ->
spawn_link(fun() ->
{ok,Ss} = gen_tcp:connect("localhost", Port, [{active,false}]),
- {ok, Pid} = ssh:daemon(Ss, [{system_dir, SysDir},
- {user_dir, UserDir},
- {password, "morot"},
- {exec, fun ssh_exec/1}])
+ {ok, _Pid} = ssh:daemon(Ss, [{system_dir, SysDir},
+ {user_dir, UserDir},
+ {password, "morot"},
+ {exec, fun ssh_exec/1}])
end),
{ok,Sc} = gen_tcp:accept(Sl),
{ok,ConnectionRef} = ssh:connect(Sc, [{silently_accept_hosts, true},
@@ -856,20 +909,36 @@ big_cat_rx(ConnectionRef, ChannelId, Acc) ->
timeout
end.
-receive_data(ExpectedData, ConnectionRef, ChannelId) ->
- ExpectedData = collect_data(ConnectionRef, ChannelId).
-
collect_data(ConnectionRef, ChannelId) ->
- collect_data(ConnectionRef, ChannelId, []).
+ ct:log("Listener ~p running! ConnectionRef=~p, ChannelId=~p",[self(),ConnectionRef,ChannelId]),
+ collect_data(ConnectionRef, ChannelId, [], 0).
-collect_data(ConnectionRef, ChannelId, Acc) ->
+collect_data(ConnectionRef, ChannelId, Acc, Sum) ->
+ TO = 5000,
receive
- {ssh_cm, ConnectionRef, {data, ChannelId, 0, Data}} ->
- collect_data(ConnectionRef, ChannelId, [Data | Acc]);
+ {ssh_cm, ConnectionRef, {data, ChannelId, 0, Data}} when is_binary(Data) ->
+ ct:log("collect_data: received ~p bytes. total ~p bytes",[size(Data),Sum+size(Data)]),
+ collect_data(ConnectionRef, ChannelId, [Data | Acc], Sum+size(Data));
{ssh_cm, ConnectionRef, {eof, ChannelId}} ->
- iolist_to_binary(lists:reverse(Acc))
- after 5000 ->
- timeout
+ try
+ iolist_to_binary(lists:reverse(Acc))
+ of
+ Bin ->
+ ct:log("collect_data: received eof.~nGot in total ~p bytes",[size(Bin)]),
+ Bin
+ catch
+ C:E ->
+ ct:log("collect_data: received eof.~nAcc is strange...~nException=~p:~p~nAcc=~p",
+ [C,E,Acc]),
+ {error,{C,E}}
+ end;
+ Msg ->
+ ct:log("collect_data: ***** unexpected message *****~n~p",[Msg]),
+ collect_data(ConnectionRef, ChannelId, Acc, Sum)
+
+ after TO ->
+ ct:log("collect_data: ----- Nothing received for ~p seconds -----~n",[]),
+ collect_data(ConnectionRef, ChannelId, Acc, Sum)
end.
%%%-------------------------------------------------------------------
diff --git a/lib/ssh/test/ssh_echo_server.erl b/lib/ssh/test/ssh_echo_server.erl
index ed9bbe1b67..5387d21efd 100644
--- a/lib/ssh/test/ssh_echo_server.erl
+++ b/lib/ssh/test/ssh_echo_server.erl
@@ -26,15 +26,29 @@
-record(state, {
n,
id,
- cm
+ cm,
+ dbg = false
}).
-export([init/1, handle_msg/2, handle_ssh_msg/2, terminate/2]).
+-define(DBG(State,Fmt,Args),
+ case State#state.dbg of
+ true -> ct:log("~p:~p ~p "++Fmt, [?MODULE,?LINE,self()|Args]);
+ false -> ok
+ end).
+
+
init([N]) ->
- ct:pal("Echo server: ~p",[self()]),
- {ok, #state{n = N}}.
+ {ok, #state{n = N}};
+init([N,Opts]) ->
+ State = #state{n = N,
+ dbg = proplists:get_value(dbg,Opts,false)
+ },
+ ?DBG(State, "init([~p])",[N]),
+ {ok, State}.
handle_msg({ssh_channel_up, ChannelId, ConnectionManager}, State) ->
+ ?DBG(State, "ssh_channel_up Cid=~p ConnMngr=~p",[ChannelId,ConnectionManager]),
{ok, State#state{id = ChannelId,
cm = ConnectionManager}}.
@@ -42,32 +56,39 @@ handle_ssh_msg({ssh_cm, CM, {data, ChannelId, 0, Data}}, #state{n = N} = State)
M = N - size(Data),
case M > 0 of
true ->
+ ?DBG(State, "ssh_cm data Cid=~p size(Data)=~p M=~p",[ChannelId,size(Data),M]),
ssh_connection:send(CM, ChannelId, Data),
{ok, State#state{n = M}};
false ->
<<SendData:N/binary, _/binary>> = Data,
+ ?DBG(State, "ssh_cm data Cid=~p size(Data)=~p M=~p size(SendData)=~p~nSend eof",[ChannelId,size(Data),M,size(SendData)]),
ssh_connection:send(CM, ChannelId, SendData),
ssh_connection:send_eof(CM, ChannelId),
{stop, ChannelId, State}
end;
handle_ssh_msg({ssh_cm, _ConnectionManager,
{data, _ChannelId, 1, Data}}, State) ->
+ ?DBG(State, "stderr: ~p",[Data]),
error_logger:format(standard_error, " ~p~n", [binary_to_list(Data)]),
{ok, State};
handle_ssh_msg({ssh_cm, _ConnectionManager, {eof, _ChannelId}}, State) ->
+ ?DBG(State, "{eof ~p}",[_ChannelId]),
{ok, State};
-handle_ssh_msg({ssh_cm, _, {signal, _, _}}, State) ->
+handle_ssh_msg({ssh_cm, _, _Sig={signal, _, _}}, State) ->
%% Ignore signals according to RFC 4254 section 6.9.
+ ?DBG(State, "~p",[_Sig]),
{ok, State};
-handle_ssh_msg({ssh_cm, _, {exit_signal, ChannelId, _, _Error, _}},
- State) ->
+handle_ssh_msg({ssh_cm, _, _Sig={exit_signal, ChannelId, _, _Error, _}}, State) ->
+ ?DBG(State, "~p",[_Sig]),
{stop, ChannelId, State};
-handle_ssh_msg({ssh_cm, _, {exit_status, ChannelId, _Status}}, State) ->
+handle_ssh_msg({ssh_cm, _, _Sig={exit_status, ChannelId, _Status}}, State) ->
+ ?DBG(State, "~p",[_Sig]),
{stop, ChannelId, State}.
terminate(_Reason, _State) ->
+ ?DBG(_State, "terminate ~p",[_Reason]),
ok.
diff --git a/lib/ssh/test/ssh_options_SUITE.erl b/lib/ssh/test/ssh_options_SUITE.erl
index d1e3d6cb0e..61883c0647 100644
--- a/lib/ssh/test/ssh_options_SUITE.erl
+++ b/lib/ssh/test/ssh_options_SUITE.erl
@@ -27,7 +27,7 @@
-include_lib("common_test/include/ct.hrl").
-include_lib("kernel/include/file.hrl").
-
+-include("ssh_test_lib.hrl").
%%% Test cases
-export([connectfun_disconnectfun_client/1,
@@ -126,7 +126,7 @@ groups() ->
%%--------------------------------------------------------------------
init_per_suite(Config) ->
- Config.
+ ?CHECK_CRYPTO(Config).
end_per_suite(_Config) ->
ssh:stop().
diff --git a/lib/ssh/test/ssh_protocol_SUITE.erl b/lib/ssh/test/ssh_protocol_SUITE.erl
index 41faf951e1..4fac1f718a 100644
--- a/lib/ssh/test/ssh_protocol_SUITE.erl
+++ b/lib/ssh/test/ssh_protocol_SUITE.erl
@@ -26,6 +26,7 @@
-include_lib("ssh/src/ssh.hrl"). % ?UINT32, ?BYTE, #ssh{} ...
-include_lib("ssh/src/ssh_transport.hrl").
-include_lib("ssh/src/ssh_auth.hrl").
+-include("ssh_test_lib.hrl").
%% Note: This directive should only be used in test suites.
-compile(export_all).
@@ -87,7 +88,7 @@ groups() ->
init_per_suite(Config) ->
- start_std_daemon( setup_dirs( start_apps(Config))).
+ ?CHECK_CRYPTO(start_std_daemon( setup_dirs( start_apps(Config)))).
end_per_suite(Config) ->
stop_apps(Config).
diff --git a/lib/ssh/test/ssh_renegotiate_SUITE.erl b/lib/ssh/test/ssh_renegotiate_SUITE.erl
index 300816276a..b10ec3707f 100644
--- a/lib/ssh/test/ssh_renegotiate_SUITE.erl
+++ b/lib/ssh/test/ssh_renegotiate_SUITE.erl
@@ -21,6 +21,7 @@
-module(ssh_renegotiate_SUITE).
-include_lib("common_test/include/ct.hrl").
+-include("ssh_test_lib.hrl").
%% Note: This directive should only be used in test suites.
-compile(export_all).
@@ -45,7 +46,7 @@ tests() -> [rekey, rekey_limit, renegotiate1, renegotiate2].
%%--------------------------------------------------------------------
init_per_suite(Config) ->
- Config.
+ ?CHECK_CRYPTO(Config).
end_per_suite(_Config) ->
ssh:stop().
diff --git a/lib/ssh/test/ssh_sftp_SUITE.erl b/lib/ssh/test/ssh_sftp_SUITE.erl
index 19cf6d446e..19ad81e7da 100644
--- a/lib/ssh/test/ssh_sftp_SUITE.erl
+++ b/lib/ssh/test/ssh_sftp_SUITE.erl
@@ -26,7 +26,7 @@
-include_lib("common_test/include/ct.hrl").
-include_lib("kernel/include/file.hrl").
-
+-include("ssh_test_lib.hrl").
% Default timetrap timeout
-define(default_timeout, ?t:minutes(1)).
@@ -45,10 +45,13 @@ all() ->
init_per_suite(Config) ->
- ct:log("file:native_name_encoding() = ~p,~nio:getopts() = ~p",
- [file:native_name_encoding(),io:getopts()]),
- ssh:start(),
- Config.
+ ?CHECK_CRYPTO(
+ begin
+ ct:log("file:native_name_encoding() = ~p,~nio:getopts() = ~p",
+ [file:native_name_encoding(),io:getopts()]),
+ ssh:start(),
+ Config
+ end).
end_per_suite(_onfig) ->
ssh:stop().
diff --git a/lib/ssh/test/ssh_sftpd_SUITE.erl b/lib/ssh/test/ssh_sftpd_SUITE.erl
index 4a69fd36b3..52a26110c4 100644
--- a/lib/ssh/test/ssh_sftpd_SUITE.erl
+++ b/lib/ssh/test/ssh_sftpd_SUITE.erl
@@ -28,6 +28,7 @@
-include_lib("kernel/include/file.hrl").
-include("ssh_xfer.hrl").
-include("ssh.hrl").
+-include("ssh_test_lib.hrl").
-define(USER, "Alladin").
-define(PASSWD, "Sesame").
@@ -72,14 +73,17 @@ groups() ->
%%--------------------------------------------------------------------
init_per_suite(Config) ->
- DataDir = proplists:get_value(data_dir, Config),
- PrivDir = proplists:get_value(priv_dir, Config),
- ssh_test_lib:setup_dsa(DataDir, PrivDir),
- %% to make sure we don't use public-key-auth
- %% this should be tested by other test suites
- UserDir = filename:join(proplists:get_value(priv_dir, Config), nopubkey),
- file:make_dir(UserDir),
- Config.
+ ?CHECK_CRYPTO(
+ begin
+ DataDir = proplists:get_value(data_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
+ ssh_test_lib:setup_dsa(DataDir, PrivDir),
+ %% to make sure we don't use public-key-auth
+ %% this should be tested by other test suites
+ UserDir = filename:join(proplists:get_value(priv_dir, Config), nopubkey),
+ file:make_dir(UserDir),
+ Config
+ end).
end_per_suite(Config) ->
SysDir = proplists:get_value(priv_dir, Config),
diff --git a/lib/ssh/test/ssh_sftpd_erlclient_SUITE.erl b/lib/ssh/test/ssh_sftpd_erlclient_SUITE.erl
index 75b5090c2b..56a33d6349 100644
--- a/lib/ssh/test/ssh_sftpd_erlclient_SUITE.erl
+++ b/lib/ssh/test/ssh_sftpd_erlclient_SUITE.erl
@@ -26,6 +26,7 @@
-include_lib("common_test/include/ct.hrl").
-include_lib("kernel/include/file.hrl").
+-include("ssh_test_lib.hrl").
-define(USER, "Alladin").
-define(PASSWD, "Sesame").
@@ -53,17 +54,20 @@ groups() ->
%%--------------------------------------------------------------------
init_per_suite(Config) ->
- catch ssh:stop(),
- DataDir = proplists:get_value(data_dir, Config),
- PrivDir = proplists:get_value(priv_dir, Config),
- FileAlt = filename:join(DataDir, "ssh_sftpd_file_alt.erl"),
- c:c(FileAlt),
- FileName = filename:join(DataDir, "test.txt"),
- {ok, FileInfo} = file:read_file_info(FileName),
- ok = file:write_file_info(FileName,
- FileInfo#file_info{mode = 8#400}),
- ssh_test_lib:setup_dsa(DataDir, PrivDir),
- Config.
+ ?CHECK_CRYPTO(
+ begin
+ catch ssh:stop(),
+ DataDir = proplists:get_value(data_dir, Config),
+ PrivDir = proplists:get_value(priv_dir, Config),
+ FileAlt = filename:join(DataDir, "ssh_sftpd_file_alt.erl"),
+ c:c(FileAlt),
+ FileName = filename:join(DataDir, "test.txt"),
+ {ok, FileInfo} = file:read_file_info(FileName),
+ ok = file:write_file_info(FileName,
+ FileInfo#file_info{mode = 8#400}),
+ ssh_test_lib:setup_dsa(DataDir, PrivDir),
+ Config
+ end).
end_per_suite(Config) ->
UserDir = filename:join(proplists:get_value(priv_dir, Config), nopubkey),
diff --git a/lib/ssh/test/ssh_sup_SUITE.erl b/lib/ssh/test/ssh_sup_SUITE.erl
index 574564f6e9..ff53e1c4c6 100644
--- a/lib/ssh/test/ssh_sup_SUITE.erl
+++ b/lib/ssh/test/ssh_sup_SUITE.erl
@@ -53,11 +53,14 @@ end_per_group(_GroupName, Config) ->
Config.
init_per_suite(Config) ->
- Port = ssh_test_lib:inet_port(node()),
- PrivDir = proplists:get_value(priv_dir, Config),
- UserDir = filename:join(PrivDir, nopubkey), % to make sure we don't use public-key-auth
- file:make_dir(UserDir),
- [{userdir, UserDir},{port, Port}, {host, "localhost"}, {host_ip, any} | Config].
+ ?CHECK_CRYPTO(
+ begin
+ Port = ssh_test_lib:inet_port(node()),
+ PrivDir = proplists:get_value(priv_dir, Config),
+ UserDir = filename:join(PrivDir, nopubkey), % to make sure we don't use public-key-auth
+ file:make_dir(UserDir),
+ [{userdir, UserDir},{port, Port}, {host, "localhost"}, {host_ip, any} | Config]
+ end).
end_per_suite(_) ->
ok.
diff --git a/lib/ssh/test/ssh_test_lib.hrl b/lib/ssh/test/ssh_test_lib.hrl
index 7cb7edeaa8..54c93b7e87 100644
--- a/lib/ssh/test/ssh_test_lib.hrl
+++ b/lib/ssh/test/ssh_test_lib.hrl
@@ -1,4 +1,14 @@
%%-------------------------------------------------------------------------
+%% Check for usable crypt
+%%-------------------------------------------------------------------------
+-define(CHECK_CRYPTO(Available),
+ try crypto:start()
+ of _ -> Available
+ catch _:_ -> {skip, "Can't start crypto"}
+ end
+ ).
+
+%%-------------------------------------------------------------------------
%% Help macro
%%-------------------------------------------------------------------------
-define(wait_match(Pattern, FunctionCall, Bind, Timeout, Ntries),
diff --git a/lib/ssh/test/ssh_to_openssh_SUITE.erl b/lib/ssh/test/ssh_to_openssh_SUITE.erl
index f96a2cc62b..a914938c41 100644
--- a/lib/ssh/test/ssh_to_openssh_SUITE.erl
+++ b/lib/ssh/test/ssh_to_openssh_SUITE.erl
@@ -22,6 +22,7 @@
-module(ssh_to_openssh_SUITE).
-include_lib("common_test/include/ct.hrl").
+-include("ssh_test_lib.hrl").
%% Note: This directive should only be used in test suites.
-compile(export_all).
@@ -62,12 +63,14 @@ groups() ->
].
init_per_suite(Config) ->
- case gen_tcp:connect("localhost", 22, []) of
- {error,econnrefused} ->
- {skip,"No openssh deamon"};
- _ ->
- ssh_test_lib:openssh_sanity_check(Config)
- end.
+ ?CHECK_CRYPTO(
+ case gen_tcp:connect("localhost", 22, []) of
+ {error,econnrefused} ->
+ {skip,"No openssh deamon"};
+ _ ->
+ ssh_test_lib:openssh_sanity_check(Config)
+ end
+ ).
end_per_suite(_Config) ->
ok.
diff --git a/lib/ssh/test/ssh_upgrade_SUITE.erl b/lib/ssh/test/ssh_upgrade_SUITE.erl
index 9d9b2b78fb..b5b27c369a 100644
--- a/lib/ssh/test/ssh_upgrade_SUITE.erl
+++ b/lib/ssh/test/ssh_upgrade_SUITE.erl
@@ -23,6 +23,7 @@
-compile(export_all).
-include_lib("common_test/include/ct.hrl").
+-include("ssh_test_lib.hrl").
-record(state, {
config,
@@ -48,13 +49,15 @@ all() ->
].
init_per_suite(Config0) ->
- case ct_release_test:init(Config0) of
- {skip, Reason} ->
- {skip, Reason};
- Config ->
- ssh:start(),
- Config
- end.
+ ?CHECK_CRYPTO(
+ case ct_release_test:init(Config0) of
+ {skip, Reason} ->
+ {skip, Reason};
+ Config ->
+ ssh:start(),
+ Config
+ end
+ ).
end_per_suite(Config) ->
ct_release_test:cleanup(Config),
diff --git a/lib/ssl/doc/src/ssl.xml b/lib/ssl/doc/src/ssl.xml
index 62f6263e9e..bed82cdb91 100644
--- a/lib/ssl/doc/src/ssl.xml
+++ b/lib/ssl/doc/src/ssl.xml
@@ -901,6 +901,23 @@ fun(srp, Username :: string(), UserState :: term()) ->
</func>
<func>
+ <name>getstat(Socket) ->
+ {ok, OptionValues} | {error, inet:posix()}</name>
+ <name>getstat(Socket, OptionNames) ->
+ {ok, OptionValues} | {error, inet:posix()}</name>
+ <fsummary>Get one or more statistic options for a socket</fsummary>
+ <type>
+ <v>Socket = sslsocket()</v>
+ <v>OptionNames = [atom()]</v>
+ <v>OptionValues = [{inet:stat_option(), integer()}]</v>
+ </type>
+ <desc>
+ <p>Gets one or more statistic options for the underlying TCP socket.</p>
+ <p>See inet:getstat/2 for statistic options description.</p>
+ </desc>
+ </func>
+
+ <func>
<name>listen(Port, Options) ->
{ok, ListenSocket} | {error, Reason}</name>
<fsummary>Creates an SSL listen socket.</fsummary>
diff --git a/lib/ssl/src/ssl.erl b/lib/ssl/src/ssl.erl
index 0058e5ec9a..d2aeb3258f 100644
--- a/lib/ssl/src/ssl.erl
+++ b/lib/ssl/src/ssl.erl
@@ -34,7 +34,8 @@
listen/2, transport_accept/1, transport_accept/2,
ssl_accept/1, ssl_accept/2, ssl_accept/3,
controlling_process/2, peername/1, peercert/1, sockname/1,
- close/1, close/2, shutdown/2, recv/2, recv/3, send/2, getopts/2, setopts/2
+ close/1, close/2, shutdown/2, recv/2, recv/3, send/2,
+ getopts/2, setopts/2, getstat/1, getstat/2
]).
%% SSL/TLS protocol handling
-export([cipher_suites/0, cipher_suites/1,
@@ -469,6 +470,32 @@ setopts(#sslsocket{}, Options) ->
{error, {options,{not_a_proplist, Options}}}.
%%---------------------------------------------------------------
+-spec getstat(Socket) ->
+ {ok, OptionValues} | {error, inet:posix()} when
+ Socket :: #sslsocket{},
+ OptionValues :: [{inet:stat_option(), integer()}].
+%%
+%% Description: Get all statistic options for a socket.
+%%--------------------------------------------------------------------
+getstat(Socket) ->
+ getstat(Socket, inet:stats()).
+
+%%---------------------------------------------------------------
+-spec getstat(Socket, Options) ->
+ {ok, OptionValues} | {error, inet:posix()} when
+ Socket :: #sslsocket{},
+ Options :: [inet:stat_option()],
+ OptionValues :: [{inet:stat_option(), integer()}].
+%%
+%% Description: Get one or more statistic options for a socket.
+%%--------------------------------------------------------------------
+getstat(#sslsocket{pid = {Listen, #config{transport_info = {Transport, _, _, _}}}}, Options) when is_port(Listen), is_list(Options) ->
+ ssl_socket:getstat(Transport, Listen, Options);
+
+getstat(#sslsocket{pid = Pid, fd = {Transport, Socket, _, _}}, Options) when is_pid(Pid), is_list(Options) ->
+ ssl_socket:getstat(Transport, Socket, Options).
+
+%%---------------------------------------------------------------
-spec shutdown(#sslsocket{}, read | write | read_write) -> ok | {error, reason()}.
%%
%% Description: Same as gen_tcp:shutdown/2
diff --git a/lib/ssl/src/ssl_crl.erl b/lib/ssl/src/ssl_crl.erl
index faf5007b16..d9f21e04ac 100644
--- a/lib/ssl/src/ssl_crl.erl
+++ b/lib/ssl/src/ssl_crl.erl
@@ -39,13 +39,12 @@ trusted_cert_and_path(CRL, {SerialNumber, Issuer},{Db, DbRef} = DbHandle) ->
end;
trusted_cert_and_path(CRL, issuer_not_found, {Db, DbRef} = DbHandle) ->
- try find_issuer(CRL, DbHandle) of
- OtpCert ->
+ case find_issuer(CRL, DbHandle) of
+ {ok, OtpCert} ->
{ok, Root, Chain} = ssl_certificate:certificate_chain(OtpCert, Db, DbRef),
- {ok, Root, lists:reverse(Chain)}
- catch
- throw:_ ->
- {error, issuer_not_found}
+ {ok, Root, lists:reverse(Chain)};
+ {error, issuer_not_found} ->
+ {ok, unknown_crl_ca, []}
end.
find_issuer(CRL, {Db,_}) ->
@@ -61,11 +60,10 @@ find_issuer(CRL, {Db,_}) ->
issuer_not_found ->
{error, issuer_not_found}
catch
- {ok, IssuerCert} ->
- IssuerCert
+ {ok, _} = Result ->
+ Result
end.
-
verify_crl_issuer(CRL, ErlCertCandidate, Issuer, NotIssuer) ->
TBSCert = ErlCertCandidate#'OTPCertificate'.tbsCertificate,
case public_key:pkix_normalize_name(TBSCert#'OTPTBSCertificate'.subject) of
diff --git a/lib/ssl/src/ssl_socket.erl b/lib/ssl/src/ssl_socket.erl
index 95a70a4602..b2aea2ba9c 100644
--- a/lib/ssl/src/ssl_socket.erl
+++ b/lib/ssl/src/ssl_socket.erl
@@ -24,7 +24,7 @@
-include("ssl_internal.hrl").
-include("ssl_api.hrl").
--export([socket/5, setopts/3, getopts/3, peername/2, sockname/2, port/2]).
+-export([socket/5, setopts/3, getopts/3, getstat/3, peername/2, sockname/2, port/2]).
-export([emulated_options/0, internal_inet_values/0, default_inet_values/0,
init/1, start_link/3, terminate/2, inherit_tracker/3, get_emulated_opts/1,
set_emulated_opts/2, get_all_opts/1, handle_call/3, handle_cast/2,
@@ -74,6 +74,11 @@ getopts(gen_tcp, Socket, Options) ->
getopts(Transport, Socket, Options) ->
Transport:getopts(Socket, Options).
+getstat(gen_tcp, Socket, Options) ->
+ inet:getstat(Socket, Options);
+getstat(Transport, Socket, Options) ->
+ Transport:getstat(Socket, Options).
+
peername(gen_tcp, Socket) ->
inet:peername(Socket);
peername(Transport, Socket) ->
diff --git a/lib/ssl/test/ssl_basic_SUITE.erl b/lib/ssl/test/ssl_basic_SUITE.erl
index efe996e57c..93b6ae66dc 100644
--- a/lib/ssl/test/ssl_basic_SUITE.erl
+++ b/lib/ssl/test/ssl_basic_SUITE.erl
@@ -150,6 +150,7 @@ api_tests() ->
sockname,
versions,
controlling_process,
+ getstat,
close_with_timeout,
hibernate,
hibernate_right_away,
@@ -691,6 +692,75 @@ controlling_process(Config) when is_list(Config) ->
ssl_test_lib:close(Client).
%%--------------------------------------------------------------------
+getstat() ->
+ [{doc,"Test API function getstat/2"}].
+
+getstat(Config) when is_list(Config) ->
+ ClientOpts = ?config(client_opts, Config),
+ ServerOpts = ?config(server_opts, Config),
+ {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+ Server1 =
+ ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
+ {from, self()},
+ {mfa, {ssl_test_lib, send_recv_result, []}},
+ {options, [{active, false} | ServerOpts]}]),
+ Port1 = ssl_test_lib:inet_port(Server1),
+ Server2 =
+ ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
+ {from, self()},
+ {mfa, {ssl_test_lib, send_recv_result, []}},
+ {options, [{active, false} | ServerOpts]}]),
+ Port2 = ssl_test_lib:inet_port(Server2),
+ {ok, ActiveC} = rpc:call(ClientNode, ssl, connect,
+ [Hostname,Port1,[{active, once}|ClientOpts]]),
+ {ok, PassiveC} = rpc:call(ClientNode, ssl, connect,
+ [Hostname,Port2,[{active, false}|ClientOpts]]),
+
+ ct:log("Testcase ~p, Client ~p Servers ~p, ~p ~n",
+ [self(), self(), Server1, Server2]),
+
+ %% We only check that the values are non-zero initially
+ %% (due to the handshake), and that sending more changes the values.
+
+ %% Passive socket.
+
+ {ok, InitialStats} = ssl:getstat(PassiveC),
+ ct:pal("InitialStats ~p~n", [InitialStats]),
+ [true] = lists:usort([0 =/= proplists:get_value(Name, InitialStats)
+ || Name <- [recv_cnt, recv_oct, recv_avg, recv_max, send_cnt, send_oct, send_avg, send_max]]),
+
+ ok = ssl:send(PassiveC, "Hello world"),
+ wait_for_send(PassiveC),
+ {ok, SStats} = ssl:getstat(PassiveC, [send_cnt, send_oct]),
+ ct:pal("SStats ~p~n", [SStats]),
+ [true] = lists:usort([proplists:get_value(Name, SStats) =/= proplists:get_value(Name, InitialStats)
+ || Name <- [send_cnt, send_oct]]),
+
+ %% Active socket.
+
+ {ok, InitialAStats} = ssl:getstat(ActiveC),
+ ct:pal("InitialAStats ~p~n", [InitialAStats]),
+ [true] = lists:usort([0 =/= proplists:get_value(Name, InitialAStats)
+ || Name <- [recv_cnt, recv_oct, recv_avg, recv_max, send_cnt, send_oct, send_avg, send_max]]),
+
+ _ = receive
+ {ssl, ActiveC, _} ->
+ ok
+ after
+ ?SLEEP ->
+ exit(timeout)
+ end,
+
+ ok = ssl:send(ActiveC, "Hello world"),
+ wait_for_send(ActiveC),
+ {ok, ASStats} = ssl:getstat(ActiveC, [send_cnt, send_oct]),
+ ct:pal("ASStats ~p~n", [ASStats]),
+ [true] = lists:usort([proplists:get_value(Name, ASStats) =/= proplists:get_value(Name, InitialAStats)
+ || Name <- [send_cnt, send_oct]]),
+
+ ok.
+
+%%--------------------------------------------------------------------
controller_dies() ->
[{doc,"Test that the socket is closed after controlling process dies"}].
controller_dies(Config) when is_list(Config) ->
@@ -4592,4 +4662,6 @@ first_rsa_suite([{rsa, _, _, _} = Suite| _]) ->
first_rsa_suite([_ | Rest]) ->
first_rsa_suite(Rest).
-
+wait_for_send(Socket) ->
+ %% Make sure TLS process processed send message event
+ _ = ssl:connection_information(Socket).
diff --git a/lib/stdlib/src/erl_parse.yrl b/lib/stdlib/src/erl_parse.yrl
index a896de4f1c..1de09aae62 100644
--- a/lib/stdlib/src/erl_parse.yrl
+++ b/lib/stdlib/src/erl_parse.yrl
@@ -170,9 +170,6 @@ fun_type -> '(' top_types ')' '->' top_type
: {type, ?anno('$1'), 'fun',
[{type, ?anno('$1'), product, '$2'},'$5']}.
-map_pair_types -> '...' : [{type, ?anno('$1'), map_field_assoc,
- [{type, ?anno('$1'), any, []},
- {type, ?anno('$1'), any, []}]}].
map_pair_types -> map_pair_type : ['$1'].
map_pair_types -> map_pair_type ',' map_pair_types : ['$1'|'$3'].
diff --git a/lib/stdlib/src/erl_pp.erl b/lib/stdlib/src/erl_pp.erl
index ca764675fc..4009300a32 100644
--- a/lib/stdlib/src/erl_pp.erl
+++ b/lib/stdlib/src/erl_pp.erl
@@ -344,27 +344,9 @@ binary_type(I1, I2) ->
map_type(Fs) ->
{first,[$#],map_pair_types(Fs)}.
-map_pair_types(Fs0) ->
- Fs = replace_any_map(Fs0),
+map_pair_types(Fs) ->
tuple_type(Fs, fun map_pair_type/2).
-replace_any_map([{type,Line,map_field_assoc,[KType,VType]}]=Fs) ->
- IsAny = fun({type,_,any,[]}) -> true;
- %% ({var,_,'_'}) -> true;
- (_) -> false
- end,
- case IsAny(KType) andalso IsAny(VType) of
- true ->
- [{type,Line,map_field_assoc,any}];
- false ->
- Fs
- end;
-replace_any_map([F|Fs]) ->
- [F|replace_any_map(Fs)];
-replace_any_map([]) -> [].
-
-map_pair_type({type,_Line,map_field_assoc,any}, _Prec) ->
- leaf("...");
map_pair_type({type,_Line,map_field_assoc,[KType,VType]}, Prec) ->
{list,[{cstep,[ltype(KType, Prec),leaf(" =>")],ltype(VType, Prec)}]};
map_pair_type({type,_Line,map_field_exact,[KType,VType]}, Prec) ->
diff --git a/lib/stdlib/test/erl_pp_SUITE.erl b/lib/stdlib/test/erl_pp_SUITE.erl
index a48ba7b5b7..951a17d3eb 100644
--- a/lib/stdlib/test/erl_pp_SUITE.erl
+++ b/lib/stdlib/test/erl_pp_SUITE.erl
@@ -1112,15 +1112,14 @@ pr_1014(Config) ->
ok = pp_forms(<<"-type t() :: #{any() => _}. ">>),
ok = pp_forms(<<"-type t() :: #{_ => any()}. ">>),
ok = pp_forms(<<"-type t() :: #{any() => any()}. ">>),
- ok = pp_forms(<<"-type t() :: #{...}. ">>),
- ok = pp_forms(<<"-type t() :: #{atom() := integer(), ...}. ">>),
+ ok = pp_forms(<<"-type t() :: #{atom() := integer(), any() => any()}. ">>),
FileName = filename('pr_1014.erl', Config),
C = <<"-module pr_1014.\n"
"-compile export_all.\n"
"-type m() :: #{..., a := integer()}.\n">>,
ok = file:write_file(FileName, C),
- {error,[{_,[{3,erl_parse,["syntax error before: ","','"]}]}],_} =
+ {error,[{_,[{3,erl_parse,["syntax error before: ","'...'"]}]}],_} =
compile:file(FileName, [return]),
ok.
diff --git a/lib/syntax_tools/src/erl_prettypr.erl b/lib/syntax_tools/src/erl_prettypr.erl
index 119d375746..f1615b2610 100644
--- a/lib/syntax_tools/src/erl_prettypr.erl
+++ b/lib/syntax_tools/src/erl_prettypr.erl
@@ -1130,13 +1130,14 @@ lay_2(Node, Ctxt) ->
any_size ->
text("map()");
Fs ->
- {Prec, _PrecR} = type_preop_prec('#'),
- Es = lay_map_fields(Fs,
- floating(text(",")),
- reset_prec(Ctxt)),
+ Ctxt1 = reset_prec(Ctxt),
+ Es = seq(Fs,
+ floating(text(",")), Ctxt1,
+ fun lay/2),
D = beside(floating(text("#{")),
beside(par(Es),
floating(text("}")))),
+ {Prec, _PrecR} = type_preop_prec('#'),
maybe_parentheses(D, Prec, Ctxt)
end;
@@ -1400,36 +1401,6 @@ lay_error_info(T, Ctxt) ->
lay_concrete(T, Ctxt) ->
lay(erl_syntax:abstract(T), Ctxt).
-lay_map_fields([H | T], Separator, Ctxt) ->
- case T of
- [] ->
- [case erl_syntax:type(H) of
- map_type_assoc ->
- lay_last_type_assoc(H, Ctxt);
- _ ->
- lay(H, Ctxt)
- end];
- _ ->
- [maybe_append(Separator, lay(H, Ctxt))
- | lay_map_fields(T, Separator, Ctxt)]
- end;
-lay_map_fields([], _, _) ->
- [empty()].
-
-lay_last_type_assoc(Node, Ctxt) ->
- Name = erl_syntax:map_type_assoc_name(Node),
- Value = erl_syntax:map_type_assoc_value(Node),
- IsAny = fun({type,_,any,[]}) -> true;
- %% ({var,_,'_'}) -> true;
- (_) -> false
- end,
- case IsAny(Name) andalso IsAny(Value) of
- true ->
- text("...");
- false ->
- lay_type_assoc(Name, Value, Ctxt)
- end.
-
lay_type_assoc(Name, Value, Ctxt) ->
Ctxt1 = reset_prec(Ctxt),
D1 = lay(Name, Ctxt1),
diff --git a/lib/syntax_tools/test/syntax_tools_SUITE_data/type_specs.erl b/lib/syntax_tools/test/syntax_tools_SUITE_data/type_specs.erl
index 5621d3a293..e4f8a1c3de 100644
--- a/lib/syntax_tools/test/syntax_tools_SUITE_data/type_specs.erl
+++ b/lib/syntax_tools/test/syntax_tools_SUITE_data/type_specs.erl
@@ -49,9 +49,12 @@
-type m1() :: #{} | map().
-type m2() :: #{a := m1(), b => #{} | fy:m2()}.
--type m3() :: #{...}.
--type m4() :: #{_ => _, ...}.
--type m5() :: #{any() => any(), ...}. % Currently printed as `#{..., ...}'.
+%-type m3() :: #{...}.
+%-type m4() :: #{_ => _, ...}.
+%-type m5() :: #{any() => any(), ...}.
+-type m3() :: #{any() => any()}.
+-type m4() :: #{_ => _, any() => any()}.
+-type m5() :: #{any() => any(), any() => any()}.
-type b1() :: B1 :: binary() | (BitString :: bitstring()).
-define(PAIR(A, B), {(A), (B)}).
diff --git a/lib/tools/src/xref_base.erl b/lib/tools/src/xref_base.erl
index 4322943c59..bb9815f9b0 100644
--- a/lib/tools/src/xref_base.erl
+++ b/lib/tools/src/xref_base.erl
@@ -669,16 +669,45 @@ do_add_directory(Dir, AppName, Bui, Rec, Ver, War, State) ->
warnings(War, unreadable, Unreadable),
case Errors of
[] ->
- do_add_modules(FileNames, AppName, Bui, Ver, War, State, []);
+ do_add_modules(FileNames, AppName, Bui, Ver, War, State);
[Error | _] ->
throw(Error)
end.
-do_add_modules([], _AppName, _OB, _OV, _OW, State, Modules) ->
+do_add_modules(Files, AppName, OB, OV, OW, State0) ->
+ NFiles = length(Files),
+ Reader = fun(SplitName, State) ->
+ _Pid = read_module(SplitName, AppName, OB, OV, OW, State)
+ end,
+ N = parallelism(),
+ Files1 = start_readers(Files, Reader, State0, N),
+ %% Increase the number of readers towards the end to decrease the
+ %% waiting time for the collecting process:
+ Nx = N,
+ add_mods(Files1, Reader, State0, [], NFiles, Nx).
+
+add_mods(_, _ReaderFun, State, Modules, 0, _Nx) ->
{ok, sort(Modules), State};
-do_add_modules([File | Files], AppName, OB, OV, OW, State, Modules) ->
- {ok, M, NewState} = do_add_module(File, AppName, OB, OV, OW, State),
- do_add_modules(Files, AppName, OB, OV, OW, NewState, M ++ Modules).
+add_mods(Files, ReaderFun, State, Modules, N, Nx) ->
+ {I, Nx1} = case Nx > 0 of
+ false -> {1, Nx};
+ true -> {2, Nx - 1}
+ end,
+ Files1 = start_readers(Files, ReaderFun, State, I),
+ {ok, M, NewState} = process_module(State),
+ add_mods(Files1, ReaderFun, NewState, M ++ Modules, N - 1, Nx1).
+
+start_readers([SplitName|Files], ReaderFun, State, N) when N > 0 ->
+ _Pid = ReaderFun(SplitName, State),
+ start_readers(Files, ReaderFun, State, N - 1);
+start_readers(Files, _ReaderFun, _State, _) ->
+ Files.
+
+parallelism() ->
+ case erlang:system_info(multi_scheduling) of
+ enabled -> erlang:system_info(schedulers_online);
+ _ -> 1
+ end.
%% -> {ok, Module, State} | throw(Error)
do_add_a_module(File, AppName, Builtins, Verbose, Warnings, State) ->
@@ -692,50 +721,75 @@ do_add_a_module(File, AppName, Builtins, Verbose, Warnings, State) ->
%% -> {ok, Module, State} | throw(Error)
%% Options: verbose, warnings, builtins
-do_add_module({Dir, Basename}, AppName, Builtins, Verbose, Warnings, State) ->
- File = filename:join(Dir, Basename),
- {ok, M, Bad, NewState} =
- do_add_module1(Dir, File, AppName, Builtins, Verbose, Warnings, State),
- _ = filter(fun({Tag,B}) -> warnings(Warnings, Tag, [[File,B]]) end, Bad),
- {ok, M, NewState}.
-
-do_add_module1(Dir, File, AppName, Builtins, Verbose, Warnings, State) ->
- message(Verbose, reading_beam, [File]),
- Mode = State#xref.mode,
+do_add_module(SplitName, AppName, Builtins, Verbose, Warnings, State) ->
+ _Pid = read_module(SplitName, AppName, Builtins, Verbose, Warnings, State),
+ process_module(State).
+
+read_module(SplitName, AppName, Builtins, Verbose, Warnings, State) ->
Me = self(),
- Fun = fun() -> Me ! {self(), abst(File, Builtins, Mode)} end,
- case xref_utils:subprocess(Fun, [link, {min_heap_size,100000}]) of
+ #xref{mode = Mode} = State,
+ Fun =
+ fun() ->
+ Me ! {?MODULE,
+ read_a_module(SplitName, AppName, Builtins, Verbose,
+ Warnings, Mode)}
+ end,
+ spawn_opt(Fun, [link, {min_heap_size, 1000000}, {priority, high}]).
+
+read_a_module({Dir, BaseName}, AppName, Builtins, Verbose, Warnings, Mode) ->
+ File = filename:join(Dir, BaseName),
+ case abst(File, Builtins, Mode) of
{ok, _M, no_abstract_code} when Verbose ->
- message(Verbose, skipped_beam, []),
- {ok, [], [], State};
+ message(Verbose, no_debug_info, [File]),
+ no;
{ok, _M, no_abstract_code} when not Verbose ->
message(Warnings, no_debug_info, [File]),
- {ok, [], [], State};
+ no;
{ok, M, Data, UnresCalls0} ->
- %% Remove duplicates. Identical unresolved calls on the
- %% same line are counted as _one_ unresolved call.
- UnresCalls = usort(UnresCalls0),
- message(Verbose, done, []),
- NoUnresCalls = length(UnresCalls),
- case NoUnresCalls of
- 0 -> ok;
- 1 -> warnings(Warnings, unresolved_summary1, [[M]]);
- N -> warnings(Warnings, unresolved_summary, [[M, N]])
- end,
- T = case xref_utils:file_info(File) of
- {ok, {_, _, _, Time}} -> Time;
- Error -> throw(Error)
- end,
- XMod = #xref_mod{name = M, app_name = AppName, dir = Dir,
- mtime = T, builtins = Builtins,
- no_unresolved = NoUnresCalls},
- do_add_module(State, XMod, UnresCalls, Data);
+ message(Verbose, done, [File]),
+ %% Remove duplicates. Identical unresolved calls on the
+ %% same line are counted as _one_ unresolved call.
+ UnresCalls = usort(UnresCalls0),
+ NoUnresCalls = length(UnresCalls),
+ case NoUnresCalls of
+ 0 -> ok;
+ 1 -> warnings(Warnings, unresolved_summary1, [[M]]);
+ N -> warnings(Warnings, unresolved_summary, [[M, N]])
+ end,
+ case xref_utils:file_info(File) of
+ {ok, {_, _, _, Time}} ->
+ XMod = #xref_mod{name = M, app_name = AppName,
+ dir = Dir, mtime = Time,
+ builtins = Builtins,
+ no_unresolved = NoUnresCalls},
+ {ok, PrepMod, Bad} =
+ prepare_module(Mode, XMod, UnresCalls, Data),
+ foreach(fun({Tag,B}) ->
+ warnings(Warnings, Tag,
+ [[File,B]])
+ end, Bad),
+ {ok, PrepMod};
+ Error -> Error
+ end;
Error ->
message(Verbose, error, []),
- throw(Error)
+ Error
end.
-abst(File, Builtins, Mode) when Mode =:= functions ->
+process_module(State) ->
+ receive
+ {?MODULE, Reply} ->
+ case Reply of
+ no ->
+ {ok, [], State};
+ {ok, PrepMod} ->
+ finish_module(PrepMod, State);
+ Error ->
+ throw(Error)
+ end
+ end.
+
+abst(File, Builtins, _Mode = functions) ->
case beam_lib:chunks(File, [abstract_code, exports, attributes]) of
{ok, {M,[{abstract_code,NoA},_X,_A]}} when NoA =:= no_abstract_code ->
{ok, M, NoA};
@@ -762,7 +816,7 @@ abst(File, Builtins, Mode) when Mode =:= functions ->
Error when element(1, Error) =:= error ->
Error
end;
-abst(File, Builtins, Mode) when Mode =:= modules ->
+abst(File, Builtins, _Mode = modules) ->
case beam_lib:chunks(File, [exports, imports, attributes]) of
{ok, {Mod, [{exports,X0}, {imports,I0}, {attributes,At}]}} ->
X1 = mfa_exports(X0, At, Mod),
@@ -856,19 +910,13 @@ deprecated_flag(_) -> undefined.
%% dom CallAt = LC U XC
%% Attrs is collected from the attribute 'xref' (experimental).
do_add_module(S, XMod, Unres, Data) ->
- M = XMod#xref_mod.name,
- case dict:find(M, S#xref.modules) of
- {ok, OldXMod} ->
- BF2 = module_file(XMod),
- BF1 = module_file(OldXMod),
- throw_error({module_clash, {M, BF1, BF2}});
- error ->
- do_add_module(S, M, XMod, Unres, Data)
- end.
+ #xref{mode = Mode} = S,
+ Mode = S#xref.mode,
+ {ok, PrepMod, Bad} = prepare_module(Mode, XMod, Unres, Data),
+ {ok, Ms, NS} = finish_module(PrepMod, S),
+ {ok, Ms, Bad, NS}.
-%%do_add_module(S, M, _XMod, _Unres, Data)->
-%% {ok, M, [], S};
-do_add_module(S, M, XMod, Unres0, Data) when S#xref.mode =:= functions ->
+prepare_module(_Mode = functions, XMod, Unres0, Data) ->
{DefAt0, LPreCAt0, XPreCAt0, LC0, XC0, X0, Attrs, Depr} = Data,
%% Bad is a list of bad values of 'xref' attributes.
{ALC0,AXC0,Bad0} = Attrs,
@@ -904,26 +952,27 @@ do_add_module(S, M, XMod, Unres0, Data) when S#xref.mode =:= functions ->
LC = union(LC1, ALC),
{DF1,DF_11,DF_21,DF_31,DBad} = depr_mod(Depr, X),
+ {EE, ECallAt} = inter_graph(X, L, LC, XC, CallAt),
+ {ok, {functions, XMod, [DefAt,L,X,LCallAt,XCallAt,CallAt,LC,XC,EE,ECallAt,
+ DF1,DF_11,DF_21,DF_31], NoCalls, Unres},
+ DBad++Bad};
+prepare_module(_Mode = modules, XMod, _Unres, Data) ->
+ {X0, I0, Depr} = Data,
+ X1 = xref_utils:xset(X0, [tspec(func)]),
+ I1 = xref_utils:xset(I0, [tspec(func)]),
+ {DF1,DF_11,DF_21,DF_31,DBad} = depr_mod(Depr, X1),
+ {ok, {modules, XMod, [X1,I1,DF1,DF_11,DF_21,DF_31]}, DBad}.
- %% {EE, ECallAt} = inter_graph(X, L, LC, XC, LCallAt, XCallAt),
- Self = self(),
- Fun = fun() -> inter_graph(Self, X, L, LC, XC, CallAt) end,
- {EE, ECallAt} =
- xref_utils:subprocess(Fun, [link, {min_heap_size,100000}]),
-
+finish_module({functions, XMod, List, NoCalls, Unres}, S) ->
+ ok = check_module(XMod, S),
[DefAt2,L2,X2,LCallAt2,XCallAt2,CallAt2,LC2,XC2,EE2,ECallAt2,
- DF2,DF_12,DF_22,DF_32] =
- pack([DefAt,L,X,LCallAt,XCallAt,CallAt,LC,XC,EE,ECallAt,
- DF1,DF_11,DF_21,DF_31]),
-
- %% Foo = [DefAt2,L2,X2,LCallAt2,XCallAt2,CallAt2,LC2,XC2,EE2,ECallAt2,
- %% DF2,DF_12,DF_22,DF_32],
- %% io:format("{~p, ~p, ~p},~n", [M, pack:lsize(Foo), pack:usize(Foo)]),
+ DF2,DF_12,DF_22,DF_32] = pack(List),
LU = range(LC2),
LPredefined = predefined_funs(LU),
+ M = XMod#xref_mod.name,
MS = xref_utils:xset(M, atom),
T = from_sets({MS,DefAt2,L2,X2,LCallAt2,XCallAt2,CallAt2,
LC2,XC2,LU,EE2,ECallAt2,Unres,LPredefined,
@@ -934,19 +983,28 @@ do_add_module(S, M, XMod, Unres0, Data) when S#xref.mode =:= functions ->
XMod1 = XMod#xref_mod{data = T, info = Info},
S1 = S#xref{modules = dict:store(M, XMod1, S#xref.modules)},
- {ok, [M], DBad++Bad, take_down(S1)};
-do_add_module(S, M, XMod, _Unres, Data) when S#xref.mode =:= modules ->
- {X0, I0, Depr} = Data,
- X1 = xref_utils:xset(X0, [tspec(func)]),
- I1 = xref_utils:xset(I0, [tspec(func)]),
- {DF1,DF_11,DF_21,DF_31,DBad} = depr_mod(Depr, X1),
- [X2,I2,DF2,DF_12,DF_22,DF_32] = pack([X1,I1,DF1,DF_11,DF_21,DF_31]),
+ {ok, [M], take_down(S1)};
+finish_module({modules, XMod, List}, S) ->
+ ok = check_module(XMod, S),
+ [X2,I2,DF2,DF_12,DF_22,DF_32] = pack(List),
+ M = XMod#xref_mod.name,
MS = xref_utils:xset(M, atom),
T = from_sets({MS, X2, I2, DF2, DF_12, DF_22, DF_32}),
Info = [],
XMod1 = XMod#xref_mod{data = T, info = Info},
S1 = S#xref{modules = dict:store(M, XMod1, S#xref.modules)},
- {ok, [M], DBad, take_down(S1)}.
+ {ok, [M], take_down(S1)}.
+
+check_module(XMod, State) ->
+ M = XMod#xref_mod.name,
+ case dict:find(M, State#xref.modules) of
+ {ok, OldXMod} ->
+ BF2 = module_file(XMod),
+ BF1 = module_file(OldXMod),
+ throw_error({module_clash, {M, BF1, BF2}});
+ error ->
+ ok
+ end.
depr_mod({Depr,Bad0}, X) ->
%% Bad0 are badly formed deprecated attributes.
@@ -992,9 +1050,6 @@ no_info(X, L, LC, XC, EE, Unres, NoCalls, NoUnresCalls) ->
%% Note: this is overwritten in do_set_up():
{no_inter_function_calls, no_elements(EE)}].
-inter_graph(Pid, X, L, LC, XC, CallAt) ->
- Pid ! {self(), inter_graph(X, L, LC, XC, CallAt)}.
-
%% Inter Call Graph.
%inter_graph(_X, _L, _LC, _XC, _CallAt) ->
% {empty_set(), empty_set()};
@@ -1766,10 +1821,6 @@ tpack(T, I, L) ->
message(true, What, Arg) ->
case What of
- reading_beam ->
- io:format("~ts... ", Arg);
- skipped_beam ->
- io:format("skipped (no debug information)~n", Arg);
no_debug_info ->
io:format("Skipping ~ts (no debug information)~n", Arg);
unresolved_summary1 ->
@@ -1791,7 +1842,7 @@ message(true, What, Arg) ->
set_up ->
io:format("Setting up...", Arg);
done ->
- io:format("done~n", Arg);
+ io:format("done reading ~ts~n", Arg);
error ->
io:format("error~n", Arg);
Else ->
diff --git a/lib/tools/src/xref_utils.erl b/lib/tools/src/xref_utils.erl
index f69aa70244..b0c168e018 100644
--- a/lib/tools/src/xref_utils.erl
+++ b/lib/tools/src/xref_utils.erl
@@ -47,8 +47,6 @@
-export([options/2]).
--export([subprocess/2]).
-
-export([format_error/1]).
-import(lists, [append/1, delete/2, filter/2, foldl/3, foreach/2,
@@ -512,12 +510,6 @@ find_beam(Culprit) ->
options(Options, Valid) ->
split_options(Options, [], [], [], Valid).
-subprocess(Fun, Opts) ->
- Pid = spawn_opt(Fun, Opts),
- receive
- {Pid, Reply} -> Reply
- end.
-
format_error({error, Module, Error}) ->
Module:format_error(Error);
format_error({file_error, FileName, Reason}) ->