diff options
Diffstat (limited to 'lib')
36 files changed, 455 insertions, 314 deletions
diff --git a/lib/common_test/doc/src/ct_hooks.xml b/lib/common_test/doc/src/ct_hooks.xml index 859ff9df14..cab6dfea51 100644 --- a/lib/common_test/doc/src/ct_hooks.xml +++ b/lib/common_test/doc/src/ct_hooks.xml @@ -450,12 +450,15 @@ </func> <func> - <name>Module:on_tc_fail(TestcaseName, Reason, CTHState) -> + <name>Module:on_tc_fail(TestName, Reason, CTHState) -> NewCTHState</name> <fsummary>Called after the CTH scope ends</fsummary> <type> - <v>TestcaseName = init_per_suite | end_per_suite | - init_per_group | end_per_group | atom()</v> + <v>TestName = init_per_suite | end_per_suite | + {init_per_group,GroupName} | {end_per_group,GroupName} | + {FuncName,GroupName} | FuncName</v> + <v>FuncName = atom()</v> + <v>GroupName = atom()</v> <v>Reason = term()</v> <v>CTHState = NewCTHState = term()</v> </type> @@ -463,14 +466,16 @@ <desc> <p> OPTIONAL </p> - <p>This function is called whenever a testcase fails. - It is called after the post function has been called for - the testcase which failed. i.e. - if init_per_suite fails this function is called after + <p>This function is called whenever a test case (or config function) + fails. It is called after the post function has been called for + the failed test case. I.e. if init_per_suite fails, this function + is called after <seealso marker="#Module:post_init_per_suite-4"> - post_init_per_suite</seealso>, and if a testcase fails it is called + post_init_per_suite</seealso>, and if a test case fails, it is called after <seealso marker="#Module:post_end_per_testcase-4"> - post_end_per_testcase</seealso>.</p> + post_end_per_testcase</seealso>. If the failed test case belongs + to a test case group, the first argument is a tuple + <c>{FuncName,GroupName}</c>, otherwise simply the function name.</p> <p>The data which comes with the Reason follows the same format as the <seealso marker="event_handler_chapter#failreason">FailReason @@ -481,12 +486,14 @@ </func> <func> - <name>Module:on_tc_skip(TestcaseName, Reason, CTHState) -> + <name>Module:on_tc_skip(TestName, Reason, CTHState) -> NewCTHState</name> <fsummary>Called after the CTH scope ends</fsummary> <type> - <v>TestcaseName = end_per_suite | {init_per_group,GroupName} | - {end_per_group,GroupName} | atom()</v> + <v>TestName = init_per_suite | end_per_suite | + {init_per_group,GroupName} | {end_per_group,GroupName} | + {FuncName,GroupName} | FuncName</v> + <v>FuncName = atom()</v> <v>GroupName = atom()</v> <v>Reason = {tc_auto_skip | tc_user_skip, term()}</v> <v>CTHState = NewCTHState = term()</v> @@ -495,14 +502,17 @@ <desc> <p> OPTIONAL </p> - <p>This function is called whenever a testcase is skipped. - It is called after the post function has been called for the - testcase which was skipped. - i.e. if init_per_group is skipped this function is called after - <seealso marker="#Module:post_init_per_suite-4">post_init_per_group - </seealso>, and if a testcase is skipped it is called after - <seealso marker="#Module:post_end_per_testcase-4">post_end_per_testcase - </seealso>.</p> + <p>This function is called whenever a test case (or config function) + is skipped. It is called after the post function has been called + for the skipped test case. I.e. if init_per_group is skipped, this + function is called after + <seealso marker="#Module:post_init_per_group-4"> + post_init_per_group</seealso>, and if a test case is skipped, + it is called after + <seealso marker="#Module:post_end_per_testcase-4"> + post_end_per_testcase</seealso>. If the skipped test case belongs to a + test case group, the first argument is a tuple <c>{FuncName,GroupName}</c>, + otherwise simply the function name.</p> <p>The data which comes with the Reason follows the same format as <seealso marker="event_handler_chapter#tc_auto_skip">tc_auto_skip diff --git a/lib/common_test/doc/src/ct_run.xml b/lib/common_test/doc/src/ct_run.xml index 39259b092a..d8e79ca80e 100644 --- a/lib/common_test/doc/src/ct_run.xml +++ b/lib/common_test/doc/src/ct_run.xml @@ -108,6 +108,7 @@ EvHandler2 InitArg2 and .. EvHandlerN InitArgN] [-include InclDir1 InclDir2 .. InclDirN] [-no_auto_compile] + [-abort_if_missing_suites] [-muliply_timetraps Multiplier] [-scale_timetraps] [-create_priv_dir auto_per_run | auto_per_tc | manual_per_tc] @@ -144,6 +145,7 @@ EvHandler2 InitArg2 and .. EvHandlerN InitArgN] [-include InclDir1 InclDir2 .. InclDirN] [-no_auto_compile] + [-abort_if_missing_suites] [-muliply_timetraps Multiplier] [-scale_timetraps] [-create_priv_dir auto_per_run | auto_per_tc | manual_per_tc] @@ -171,6 +173,7 @@ [-decrypt_key Key] | [-decrypt_file KeyFile] [-include InclDir1 InclDir2 .. InclDirN] [-no_auto_compile] + [-abort_if_missing_suites] [-muliply_timetraps Multiplier] [-scale_timetraps] [-create_priv_dir auto_per_run | auto_per_tc | manual_per_tc] diff --git a/lib/common_test/doc/src/event_handler_chapter.xml b/lib/common_test/doc/src/event_handler_chapter.xml index 47d0ba59fb..45f01c12ec 100644 --- a/lib/common_test/doc/src/event_handler_chapter.xml +++ b/lib/common_test/doc/src/event_handler_chapter.xml @@ -227,11 +227,13 @@ <item> <marker id="tc_auto_skip"></marker> - <c>#event{name = tc_auto_skip, data = {Suite,Func,Reason}}</c> + <c>#event{name = tc_auto_skip, data = {Suite,TestName,Reason}}</c> <p><c>Suite = atom()</c>, the name of the suite.</p> - <p><c>Func = atom() | {end_per_group,GroupName}</c>, the name of the test case - or configuration function.</p> - <p><c>GroupName = atom()</c>, name of the group.</p> + <p><c>TestName = init_per_suite | end_per_suite | + {init_per_group,GroupName} | {end_per_group,GroupName} | + {FuncName,GroupName} | FuncName</c></p> + <p><c>FuncName = atom()</c>, the name of the test case or configuration function.</p> + <p><c>GroupName = atom()</c>, the name of the test case group.</p> <p><c>Reason = {failed,FailReason} | {require_failed_in_suite0,RequireInfo}</c>, reason for auto skipping <c>Func</c>.</p> @@ -252,21 +254,26 @@ <c>init_per_group</c>, a failed <c>require</c> in <c>suite/0</c>, or a failed test case in a sequence. Note that this event is never received as a result of a test case getting skipped because of <c>init_per_testcase</c> failing, since that information is carried with - the <c>tc_done</c> event. + the <c>tc_done</c> event. If a failed test case belongs to a test case group, the second + data element is a tuple <c>{FuncName,GroupName}</c>, otherwise simply the function name. </p></item> - + <item> <marker id="tc_user_skip"></marker> - <c>#event{name = tc_user_skip, data = {Suite,Func,Comment}}</c> + <c>#event{name = tc_user_skip, data = {Suite,TestName,Comment}}</c> <p><c>Suite = atom()</c>, the name of the suite.</p> - <p><c>Func = atom() | {end_per_group,GroupName}</c>, the name of the test case - or configuration function.</p> - <p><c>GroupName = atom()</c>, name of the group.</p> + <p><c>TestName = init_per_suite | end_per_suite | + {init_per_group,GroupName} | {end_per_group,GroupName} | + {FuncName,GroupName} | FuncName</c></p> + <p><c>FuncName = atom()</c>, the name of the test case or configuration function.</p> + <p><c>GroupName = atom()</c>, the name of the test case group.</p> <p><c>Comment = string()</c>, reason for skipping the test case.</p> <p>This event specifies that a test case has been skipped by the user. It is only ever received if the skip was declared in a test specification. Otherwise, user skip information is received as a <c>{skipped,SkipReason}</c> - result in the <c>tc_done</c> event for the test case. + result in the <c>tc_done</c> event for the test case. If a skipped test case belongs + to a test case group, the second data element is a tuple <c>{FuncName,GroupName}</c>, + otherwise simply the function name. </p></item> <item><c>#event{name = test_stats, data = {Ok,Failed,Skipped}}</c> diff --git a/lib/common_test/doc/src/run_test_chapter.xml b/lib/common_test/doc/src/run_test_chapter.xml index ef21948f89..864f82cb63 100644 --- a/lib/common_test/doc/src/run_test_chapter.xml +++ b/lib/common_test/doc/src/run_test_chapter.xml @@ -59,7 +59,15 @@ <p>If compilation should fail for one or more suites, the compilation errors are printed to tty and the operator is asked if the test run should proceed without the missing suites, or be aborted. If the operator chooses to proceed, - it is noted in the HTML log which tests have missing suites.</p> + it is noted in the HTML log which tests have missing suites. If Common Test is + unable to prompt the user after compilation failure (if Common Test doesn't + control stdin), the test run will proceed automatically without the missing + suites. This behaviour can however be modified with the + <c><![CDATA[ct_run]]></c> flag <c><![CDATA[-abort_if_missing_suites]]></c>, + or the <c><![CDATA[ct:run_test/1]]></c> option + <c><![CDATA[{abort_if_missing_suites,TrueOrFalse}]]></c>. If + <c><![CDATA[abort_if_missing_suites]]></c> is set (to true), the test run + will stop immediately if some suites fail to compile.</p> <p>Any help module (i.e. regular Erlang module with name not ending with "_SUITE") that resides in the same test object directory as a suite @@ -167,6 +175,7 @@ <seealso marker="ct_hooks_chapter#builtin_cths">Built-in Common Test Hooks</seealso>. Default is <c>true</c>.</item> <item><c><![CDATA[-include]]></c>, specifies include directories (see above).</item> <item><c><![CDATA[-no_auto_compile]]></c>, disables the automatic test suite compilation feature (see above).</item> + <item><c><![CDATA[-abort_if_missing_suites]]></c>, aborts the test run if one or more suites fail to compile (see above).</item> <item><c><![CDATA[-multiply_timetraps <n>]]></c>, extends <seealso marker="write_test_chapter#timetraps">timetrap timeout</seealso> values.</item> <item><c><![CDATA[-scale_timetraps <bool>]]></c>, enables automatic <seealso marker="write_test_chapter#timetraps">timetrap @@ -744,6 +753,9 @@ {auto_compile, Bool}, {auto_compile, NodeRefs, Bool}, + {abort_if_missing_suites, Bool}, + {abort_if_missing_suites, NodeRefs, Bool}, + {config, ConfigFiles}. {config, ConfigDir, ConfigBaseNames}. {config, NodeRefs, ConfigFiles}. diff --git a/lib/common_test/src/ct.erl b/lib/common_test/src/ct.erl index e6732f7fc7..241cd928b7 100644 --- a/lib/common_test/src/ct.erl +++ b/lib/common_test/src/ct.erl @@ -150,7 +150,8 @@ run(TestDirs) -> %%% {silent_connections,Conns} | {stylesheet,CSSFile} | %%% {cover,CoverSpecFile} | {cover_stop,Bool} | {step,StepOpts} | %%% {event_handler,EventHandlers} | {include,InclDirs} | -%%% {auto_compile,Bool} | {create_priv_dir,CreatePrivDir} | +%%% {auto_compile,Bool} | {abort_if_missing_suites,Bool} | +%%% {create_priv_dir,CreatePrivDir} | %%% {multiply_timetraps,M} | {scale_timetraps,Bool} | %%% {repeat,N} | {duration,DurTime} | {until,StopTime} | %%% {force_stop,ForceStop} | {decrypt,DecryptKeyOrFile} | diff --git a/lib/common_test/src/ct_framework.erl b/lib/common_test/src/ct_framework.erl index 7d577462b0..9ef917a507 100644 --- a/lib/common_test/src/ct_framework.erl +++ b/lib/common_test/src/ct_framework.erl @@ -1274,7 +1274,7 @@ report(What,Data) -> ct_util:set_testdata({What,Data}), ok; tc_start -> - %% Data = {Suite,{Func,GroupName}},LogFileName} + %% Data = {{Suite,{Func,GroupName}},LogFileName} Data1 = case Data of {{Suite,{Func,undefined}},LFN} -> {{Suite,Func},LFN}; _ -> Data diff --git a/lib/common_test/src/ct_netconfc.erl b/lib/common_test/src/ct_netconfc.erl index 6fc840745d..a3861dc745 100644 --- a/lib/common_test/src/ct_netconfc.erl +++ b/lib/common_test/src/ct_netconfc.erl @@ -536,7 +536,7 @@ send(Client, SimpleXml) -> Client :: client(), SimpleXml :: simple_xml(), Timeout :: timeout(), - Result :: ok | {error,error_reason()}. + Result :: simple_xml() | {error,error_reason()}. %% @doc Send an XML document to the server. %% %% The given XML document is sent as is to the server. This function @@ -556,7 +556,7 @@ send_rpc(Client, SimpleXml) -> Client :: client(), SimpleXml :: simple_xml(), Timeout :: timeout(), - Result :: ok | {error,error_reason()}. + Result :: [simple_xml()] | {error,error_reason()}. %% @doc Send a Netconf <code>rpc</code> request to the server. %% %% The given XML document is wrapped in a valid Netconf @@ -635,7 +635,7 @@ get(Client, Filter) -> Client :: client(), Filter :: simple_xml() | xpath(), Timeout :: timeout(), - Result :: {ok,simple_xml()} | {error,error_reason()}. + Result :: {ok,[simple_xml()]} | {error,error_reason()}. %% @doc Get data. %% %% This operation returns both configuration and state data from the @@ -661,7 +661,7 @@ get_config(Client, Source, Filter) -> Source :: netconf_db(), Filter :: simple_xml() | xpath(), Timeout :: timeout(), - Result :: {ok,simple_xml()} | {error,error_reason()}. + Result :: {ok,[simple_xml()]} | {error,error_reason()}. %% @doc Get configuration data. %% %% To be able to access another source than `running', the server @@ -759,7 +759,7 @@ action(Client,Action) -> Client :: client(), Action :: simple_xml(), Timeout :: timeout(), - Result :: {ok,simple_xml()} | {error,error_reason()}. + Result :: {ok,[simple_xml()]} | {error,error_reason()}. %% @doc Execute an action. %% %% @end diff --git a/lib/common_test/src/ct_telnet.erl b/lib/common_test/src/ct_telnet.erl index bc22a99741..c9dc2338cd 100644 --- a/lib/common_test/src/ct_telnet.erl +++ b/lib/common_test/src/ct_telnet.erl @@ -46,100 +46,80 @@ %% %% == Logging == %% -%% `ct_telnet' can be configured to uses the `error_logger' for logging telnet -%% traffic. A special purpose error handler is implemented in -%% `ct_conn_log_h'. To use this error handler, add the `cth_conn_log' -%% hook in your test suite, e.g: -%% +%% The default logging behaviour of `ct_telnet' is to print information +%% to the test case HTML log about performed operations and commands +%% and their corresponding results. What won't be printed to the HTML log +%% are text strings sent from the telnet server that are not explicitly +%% received by means of a `ct_telnet' function such as `expect/3'. +%% `ct_telnet' may however be configured to use a special purpose event handler, +%% implemented in `ct_conn_log_h', for logging <b>all</b> telnet traffic. +%% To use this handler, you need to install a Common Test hook named +%% `cth_conn_log'. Example (using the test suite info function): %% %% ``` %% suite() -> -%% [{ct_hooks, [{cth_conn_log, [{conn_mod(),hook_options()}]}]}]. -%%''' +%% [{ct_hooks, [{cth_conn_log, [{conn_mod(),hook_options()}]}]}]. +%% ''' %% %% `conn_mod()' is the name of the common_test module implementing %% the connection protocol, i.e. `ct_telnet'. %% -%% The hook option `log_type' specifies the type of logging: -%% -%% <dl> -%% <dt>`raw'</dt> -%% <dd>The sent and received telnet data is logged to a separate -%% text file as is, without any formatting. A link to the file is -%% added to the test case HTML log.</dd> +%% The `cth_conn_log' hook performs unformatted logging of telnet data to +%% a separate text file. All telnet communication is captured and printed, +%% including arbitrary data sent from the server. The link to this text file +%% can be found on the top of the test case HTML log. %% -%% <dt>`html (default)'</dt> -%% <dd>The sent and received telnet traffic is pretty printed -%% directly in the test case HTML log.</dd> -%% -%% <dt>`silent'</dt> -%% <dd>Telnet traffic is not logged.</dd> -%% </dl> -%% -%% By default, all telnet traffic is logged in one single log -%% file. However, it is possible to have different connections logged -%% in separate files. To do this, use the hook option `hosts' and -%% list the names of the servers/connections that will be used in the -%% suite. Note that the connections must be named for this to work +%% By default, data for all telnet connections is logged in one common +%% file (named `default'), which might get messy e.g. if multiple telnet +%% sessions are running in parallel. It is therefore possible to create a +%% separate log file for each connection. To configure this, use the hook +%% option `hosts' and list the names of the servers/connections that will be +%% used in the suite. Note that the connections must be named for this to work %% (see the `open' function below). %% -%% The `hosts' option has no effect if `log_type' is set to `html' or -%% `silent'. +%% The hook option named `log_type' may be used to change the `cth_conn_log' +%% behaviour. The default value of this option is `raw', which results in the +%% behaviour described above. If the value is set to `html', all telnet +%% communication is printed to the test case HTML log instead. %% -%% The hook options can also be specified in a configuration file with -%% the configuration variable `ct_conn_log': +%% All `cth_conn_log' hook options described above can also be specified in +%% a configuration file with the configuration variable `ct_conn_log'. Example: %% %% ``` -%% {ct_conn_log,[{conn_mod(),hook_options()}]}. -%% ''' -%% -%% For example: -%% -%% ``` -%% {ct_conn_log,[{ct_telnet,[{log_type,raw}, -%% {hosts,[key_or_name()]}]}]} +%% {ct_conn_log, [{ct_telnet,[{log_type,raw}, +%% {hosts,[key_or_name()]}]}]} %% ''' %% %% <b>Note</b> that hook options specified in a configuration file -%% will overwrite any hardcoded hook options in the test suite. +%% will overwrite any hardcoded hook options in the test suite! %% -%% === Logging example 1 === +%% === Logging example === %% -%% The following `ct_hooks' statement will cause raw printing of -%% telnet traffic to separate logs for the connections named -%% `server1' and `server2'. Any other connections will be logged -%% to default telnet log. +%% The following `ct_hooks' statement will cause printing of telnet traffic +%% to separate logs for the connections named `server1' and `server2'. +%% Traffic for any other connections will be logged in the default telnet log. %% %% ``` %% suite() -> -%% [{ct_hooks, [{cth_conn_log, [{ct_telnet,[{log_type,raw}}, -%% {hosts,[server1,server2]}]} -%% ]}]}]. +%% [{ct_hooks, +%% [{cth_conn_log, [{ct_telnet,[{hosts,[server1,server2]}]}]}]}]. %%''' %% -%% === Logging example 2 === -%% -%% The following configuration file will cause raw logging of all -%% telnet traffic into one single text file. +%% As previously explained, the above specification could also be provided +%% by means of an entry like this in a configuration file: %% %% ``` -%% {ct_conn_log,[{ct_telnet,[{log_type,raw}]}]}. +%% {ct_conn_log, [{ct_telnet,[{hosts,[server1,server2]}]}]}. %% ''' %% -%% The `ct_hooks' statement must look like this: +%% in which case the `ct_hooks' statement in the test suite may simply look +%% like this: %% %% ``` %% suite() -> -%% [{ct_hooks, [{cth_conn_log, []}]}]. +%% [{ct_hooks, [{cth_conn_log, []}]}]. %% ''' %% -%% The same `ct_hooks' statement without the configuration file would -%% cause HTML logging of all telnet connections into the test case -%% HTML log. -%% -%% <b>Note</b> that if the `cth_conn_log' hook is not added, telnet -%% traffic is still logged in the test case HTML log file (on the legacy -%% `ct_telnet' format). %% @end %% @type connection_type() = telnet | ts1 | ts2 @@ -205,6 +185,7 @@ open(Name) -> %%% Name = target_name() %%% ConnType = ct_telnet:connection_type() %%% Handle = ct_telnet:handle() +%%% Reason = term() %%% %%% @doc Open a telnet connection to the specified target host. open(Name,ConnType) -> @@ -234,6 +215,7 @@ open(KeyOrName,ConnType,TargetMod) -> %%% TargetMod = atom() %%% Extra = term() %%% Handle = handle() +%%% Reason = term() %%% %%% @doc Open a telnet connection to the specified target host. %%% @@ -295,7 +277,8 @@ open(KeyOrName,ConnType,TargetMod,Extra) -> %%%----------------------------------------------------------------- %%% @spec close(Connection) -> ok | {error,Reason} -%%% Connection = ct_telnet:connection() +%%% Connection = ct_telnet:connection() +%%% Reason = term() %%% %%% @doc Close the telnet connection and stop the process managing it. %%% @@ -330,6 +313,7 @@ cmd(Connection,Cmd) -> %%% Cmd = string() %%% Timeout = integer() %%% Data = [string()] +%%% Reason = term() %%% @doc Send a command via telnet and wait for prompt. cmd(Connection,Cmd,Timeout) -> case get_handle(Connection) of @@ -350,6 +334,7 @@ cmdf(Connection,CmdFormat,Args) -> %%% Args = list() %%% Timeout = integer() %%% Data = [string()] +%%% Reason = term() %%% @doc Send a telnet command and wait for prompt %%% (uses a format string and list of arguments to build the command). cmdf(Connection,CmdFormat,Args,Timeout) when is_list(Args) -> @@ -360,6 +345,7 @@ cmdf(Connection,CmdFormat,Args,Timeout) when is_list(Args) -> %%% @spec get_data(Connection) -> {ok,Data} | {error,Reason} %%% Connection = ct_telnet:connection() %%% Data = [string()] +%%% Reason = term() %%% @doc Get all data which has been received by the telnet client %%% since last command was sent. get_data(Connection) -> @@ -374,6 +360,7 @@ get_data(Connection) -> %%% @spec send(Connection,Cmd) -> ok | {error,Reason} %%% Connection = ct_telnet:connection() %%% Cmd = string() +%%% Reason = term() %%% @doc Send a telnet command and return immediately. %%% %%% <p>The resulting output from the command can be read with @@ -391,6 +378,7 @@ send(Connection,Cmd) -> %%% Connection = ct_telnet:connection() %%% CmdFormat = string() %%% Args = list() +%%% Reason = term() %%% @doc Send a telnet command and return immediately (uses a format %%% string and a list of arguments to build the command). sendf(Connection,CmdFormat,Args) when is_list(Args) -> @@ -765,8 +753,8 @@ check_if_prompt_was_reached(Data,_) when is_list(Data) -> check_if_prompt_was_reached(_,_) -> false. -%%% @hidden -%% Functions for logging ct_telnet reports and telnet data +%%%----------------------------------------------------------------- +%%% Functions for logging ct_telnet reports and telnet data heading(Action,undefined) -> io_lib:format("~w ~w",[?MODULE,Action]); @@ -776,6 +764,8 @@ heading(Action,Name) -> force_log(State,Action,String,Args) -> log(State,Action,String,Args,true). +%%%----------------------------------------------------------------- +%%% @hidden log(State,Action,String,Args) when is_record(State, state) -> log(State,Action,String,Args,false); log(Name,Action,String,Args) when is_atom(Name) -> @@ -783,6 +773,8 @@ log(Name,Action,String,Args) when is_atom(Name) -> log(TelnPid,Action,String,Args) when is_pid(TelnPid) -> log(#state{teln_pid=TelnPid},Action,String,Args,false). +%%%----------------------------------------------------------------- +%%% @hidden log(undefined,String,Args) -> log(#state{},undefined,String,Args,false); log(Name,String,Args) when is_atom(Name) -> @@ -790,6 +782,8 @@ log(Name,String,Args) when is_atom(Name) -> log(TelnPid,String,Args) when is_pid(TelnPid) -> log(#state{teln_pid=TelnPid},undefined,String,Args). +%%%----------------------------------------------------------------- +%%% @hidden log(#state{name=Name,teln_pid=TelnPid,host=Host,port=Port}, Action,String,Args,ForcePrint) -> Name1 = if Name == undefined -> get({ct_telnet_pid2name,TelnPid}); @@ -839,6 +833,8 @@ log(#state{name=Name,teln_pid=TelnPid,host=Host,port=Port}, end end. +%%%----------------------------------------------------------------- +%%% @hidden start_gen_log(Heading) -> %% check if output is suppressed case ct_util:is_silenced(telnet) of @@ -846,6 +842,8 @@ start_gen_log(Heading) -> false -> ct_gen_conn:start_log(Heading) end. +%%%----------------------------------------------------------------- +%%% @hidden end_gen_log() -> %% check if output is suppressed case ct_util:is_silenced(telnet) of diff --git a/lib/common_test/src/cth_conn_log.erl b/lib/common_test/src/cth_conn_log.erl index 0e6c877c5d..1e60f2751e 100644 --- a/lib/common_test/src/cth_conn_log.erl +++ b/lib/common_test/src/cth_conn_log.erl @@ -91,12 +91,15 @@ merge_log_info([{Mod,ConfOpts}|ConfList],HookList) -> {value,{_,HookOpts},HL1} -> {ConfOpts ++ HookOpts, HL1} % ConfOpts overwrites HookOpts! end, - [{Mod,get_log_opts(Opts)} | merge_log_info(ConfList,HookList1)]; + [{Mod,get_log_opts(Mod,Opts)} | merge_log_info(ConfList,HookList1)]; merge_log_info([],HookList) -> - [{Mod,get_log_opts(Opts)} || {Mod,Opts} <- HookList]. + [{Mod,get_log_opts(Mod,Opts)} || {Mod,Opts} <- HookList]. -get_log_opts(Opts) -> - LogType = proplists:get_value(log_type,Opts,html), +get_log_opts(Mod,Opts) -> + DefaultLogType = if Mod == ct_telnet -> raw; + true -> html + end, + LogType = proplists:get_value(log_type,Opts,DefaultLogType), Hosts = proplists:get_value(hosts,Opts,[]), {LogType,Hosts}. diff --git a/lib/common_test/src/unix_telnet.erl b/lib/common_test/src/unix_telnet.erl index b05386a5ab..10666b979d 100644 --- a/lib/common_test/src/unix_telnet.erl +++ b/lib/common_test/src/unix_telnet.erl @@ -17,8 +17,8 @@ %% %CopyrightEnd% %% -%%% @doc Callback module for ct_telnet for talking telnet -%%% to a unix host. +%%% @doc Callback module for ct_telnet, for connecting to a telnet +%%% server on a unix host. %%% %%% <p>It requires the following entry in the config file:</p> %%% <pre> @@ -28,15 +28,15 @@ %%% {password,Password}, %%% {keep_alive,Bool}]}. % optional</pre> %%% -%%% <p>To talk telnet to the host specified by +%%% <p>To communicate via telnet to the host specified by %%% <code>HostNameOrIpAddress</code>, use the interface functions in -%%% <code>ct</code>, e.g. <code>open(Name), cmd(Name,Cmd), ...</code>.</p> +%%% <code>ct_telnet</code>, e.g. <code>open(Name), cmd(Name,Cmd), ...</code>.</p> %%% %%% <p><code>Name</code> is the name you allocated to the unix host in %%% your <code>require</code> statement. E.g.</p> -%%% <pre> suite() -> [{require,Name,{unix,[telnet,username,password]}}].</pre> +%%% <pre> suite() -> [{require,Name,{unix,[telnet]}}].</pre> %%% <p>or</p> -%%% <pre> ct:require(Name,{unix,[telnet,username,password]}).</pre> +%%% <pre> ct:require(Name,{unix,[telnet]}).</pre> %%% %%% <p>The "keep alive" activity (i.e. that Common Test sends NOP to the server %%% every 10 seconds if the connection is idle) may be enabled or disabled for one @@ -62,20 +62,18 @@ -define(prx,"login: |Password: |\\\$ |> "). %%%----------------------------------------------------------------- -%%% @hidden %%% @spec get_prompt_regexp() -> PromptRegexp %%% PromptRegexp = ct_telnet:prompt_regexp() %%% %%% @doc Callback for ct_telnet.erl. %%% -%%% <p>Return the prompt regexp for telnet connections to the -%%% interwatch instrument.</p> +%%% <p>Return a suitable regexp string that will match common +%%% prompts for users on unix hosts.</p> get_prompt_regexp() -> ?prx. %%%----------------------------------------------------------------- -%%% @hidden %%% @spec connect(ConnName,Ip,Port,Timeout,KeepAlive,Extra) -> %%% {ok,Handle} | {error,Reason} %%% ConnName = ct:target_name() @@ -83,14 +81,15 @@ get_prompt_regexp() -> %%% Port = integer() %%% Timeout = integer() %%% KeepAlive = bool() -%%% Extra = {Username,Password} +%%% Extra = ct:target_name() | {Username,Password} %%% Username = string() %%% Password = string() %%% Handle = ct_telnet:handle() +%%% Reason = term() %%% %%% @doc Callback for ct_telnet.erl. %%% -%%% <p>Setup telnet connection to a UNIX host.</p> +%%% <p>Setup telnet connection to a unix host.</p> connect(ConnName,Ip,Port,Timeout,KeepAlive,Extra) -> case Extra of {Username,Password} -> diff --git a/lib/common_test/test/ct_telnet_SUITE.erl b/lib/common_test/test/ct_telnet_SUITE.erl index f5cff76fd1..84e69c2b54 100644 --- a/lib/common_test/test/ct_telnet_SUITE.erl +++ b/lib/common_test/test/ct_telnet_SUITE.erl @@ -180,14 +180,20 @@ telnet_config(unix_telnet, legacy) -> {ct_conn_log,[]}]; %% LogType same as GroupName telnet_config(unix_telnet, LogType) -> + LogTypeTerm = if LogType == raw -> []; + true -> [{log_type,LogType}] + end, [{unix, ct:get_config(unix)}, {ct_conn_log, - [{ct_telnet,[{log_type,LogType}, - {hosts,[telnet_server_conn1, - telnet_server_conn2, - telnet_server_conn3, - telnet_server_conn4]}]}]}]; + [{ct_telnet, LogTypeTerm ++ + [{hosts,[telnet_server_conn1, + telnet_server_conn2, + telnet_server_conn3, + telnet_server_conn4]}]}]}]; telnet_config(_, LogType) -> + LogTypeTerm = if LogType == raw -> []; + true -> [{log_type,LogType}] + end, [{unix,[{telnet,"localhost"}, {port, ?erl_telnet_server_port}, {username,?erl_telnet_server_user}, @@ -202,11 +208,11 @@ telnet_config(_, LogType) -> [{ct_conn_log,[]}]; true -> [{ct_conn_log, - [{ct_telnet,[{log_type,LogType}, - {hosts,[telnet_server_conn1, - telnet_server_conn2, - telnet_server_conn3, - telnet_server_conn4]}]}]}] + [{ct_telnet, LogTypeTerm ++ + [{hosts,[telnet_server_conn1, + telnet_server_conn2, + telnet_server_conn3, + telnet_server_conn4]}]}]}] end]. %%%----------------------------------------------------------------- diff --git a/lib/compiler/src/cerl.erl b/lib/compiler/src/cerl.erl index ed11c8de4d..54eac20ac4 100644 --- a/lib/compiler/src/cerl.erl +++ b/lib/compiler/src/cerl.erl @@ -133,7 +133,7 @@ ]). -export_type([c_binary/0, c_bitstr/0, c_call/0, c_clause/0, c_cons/0, c_fun/0, - c_literal/0, c_map_pair/0, c_module/0, c_tuple/0, + c_literal/0, c_map/0, c_map_pair/0, c_module/0, c_tuple/0, c_values/0, c_var/0, cerl/0, var_name/0]). -include("core_parse.hrl"). diff --git a/lib/compiler/src/core_lib.erl b/lib/compiler/src/core_lib.erl index 93ec3bbad5..2792fd8fa5 100644 --- a/lib/compiler/src/core_lib.erl +++ b/lib/compiler/src/core_lib.erl @@ -59,7 +59,7 @@ is_lit_bin(Es) -> %% Return the value of LitExpr. -spec literal_value(cerl:c_literal() | cerl:c_binary() | - cerl:c_cons() | cerl:c_tuple()) -> term(). + cerl:c_map() | cerl:c_cons() | cerl:c_tuple()) -> term(). literal_value(#c_literal{val=V}) -> V; literal_value(#c_binary{segments=Es}) -> @@ -67,7 +67,14 @@ literal_value(#c_binary{segments=Es}) -> literal_value(#c_cons{hd=H,tl=T}) -> [literal_value(H)|literal_value(T)]; literal_value(#c_tuple{es=Es}) -> - list_to_tuple(literal_value_list(Es)). + list_to_tuple(literal_value_list(Es)); +literal_value(#c_map{arg=Cm,es=Cmps}) -> + M = literal_value(Cm), + lists:foldl(fun(#c_map_pair{ key=Ck, val=Cv },Mi) -> + K = literal_value(Ck), + V = literal_value(Cv), + maps:put(K,V,Mi) + end, M, Cmps). literal_value_list(Vals) -> [literal_value(V) || V <- Vals]. diff --git a/lib/compiler/src/core_pp.erl b/lib/compiler/src/core_pp.erl index a76327457d..83412ecdd7 100644 --- a/lib/compiler/src/core_pp.erl +++ b/lib/compiler/src/core_pp.erl @@ -120,7 +120,11 @@ format_1(#c_literal{anno=A,val=Bitstring}, Ctxt) when is_bitstring(Bitstring) -> format_1(#c_binary{anno=A,segments=Segs}, Ctxt); format_1(#c_literal{anno=A,val=M},Ctxt) when is_map(M) -> Pairs = maps:to_list(M), - Cpairs = [#c_map_pair{op=#c_literal{val=assoc}, + Op = case Ctxt of + #ctxt{ class = clause } -> exact; + _ -> assoc + end, + Cpairs = [#c_map_pair{op=#c_literal{val=Op}, key=#c_literal{val=V}, val=#c_literal{val=K}} || {K,V} <- Pairs], format_1(#c_map{anno=A,arg=#c_literal{val=#{}},es=Cpairs},Ctxt); diff --git a/lib/compiler/src/sys_core_fold.erl b/lib/compiler/src/sys_core_fold.erl index b7422318b2..ce40213bad 100644 --- a/lib/compiler/src/sys_core_fold.erl +++ b/lib/compiler/src/sys_core_fold.erl @@ -1556,16 +1556,8 @@ map_pair_pattern_list(Ps0, Isub, Osub0) -> {Ps,Osub}. map_pair_pattern(#c_map_pair{op=#c_literal{val=exact},key=K0,val=V0}=Pair,{Isub,Osub0}) -> - {K,Osub1} = case cerl:type(K0) of - binary -> - K1 = eval_binary(K0), - case cerl:type(K1) of - literal -> {K1,Osub0}; - _ -> pattern(K0,Isub,Osub0) - end; - _ -> pattern(K0,Isub,Osub0) - end, - {V,Osub} = pattern(V0,Isub,Osub1), + K = expr(K0, Isub), + {V,Osub} = pattern(V0,Isub,Osub0), {Pair#c_map_pair{key=K,val=V},{Isub,Osub}}. bin_pattern_list(Ps0, Isub, Osub0) -> diff --git a/lib/compiler/src/sys_pre_expand.erl b/lib/compiler/src/sys_pre_expand.erl index 91a46a20fe..761ae8409c 100644 --- a/lib/compiler/src/sys_pre_expand.erl +++ b/lib/compiler/src/sys_pre_expand.erl @@ -232,7 +232,7 @@ pattern({map,Line,Ps}, St0) -> {TPs,St1} = pattern_list(Ps, St0), {{map,Line,TPs},St1}; pattern({map_field_exact,Line,K0,V0}, St0) -> - {K,St1} = pattern(K0, St0), + {K,St1} = expr(K0, St0), {V,St2} = pattern(V0, St1), {{map_field_exact,Line,K,V},St2}; %%pattern({struct,Line,Tag,Ps}, St0) -> diff --git a/lib/compiler/src/v3_core.erl b/lib/compiler/src/v3_core.erl index a548ba2f7c..8c18f6a9f7 100644 --- a/lib/compiler/src/v3_core.erl +++ b/lib/compiler/src/v3_core.erl @@ -1605,26 +1605,17 @@ pattern_alias_map_pair_patterns([Cv1,Cv2|Cvs]) -> pattern_alias_map_pair_patterns([pat_alias(Cv1,Cv2)|Cvs]). pattern_map_pair({map_field_exact,L,K,V}, St) -> - %% FIXME: Better way to construct literals? or missing case - %% {Key,_,_} = expr(K, St), - Key = case K of - {bin,L,Es0} -> - case constant_bin(Es0) of - error -> - %% this will throw a cryptic error message - %% but it is better than nothing - throw(nomatch); - Bin -> - #c_literal{anno=lineno_anno(L,St),val=Bin} - end; + case expr(K,St) of + {#c_literal{}=Key,_,_} -> + #c_map_pair{anno=lineno_anno(L, St), + op=#c_literal{val=exact}, + key=Key, + val=pattern(V, St)}; _ -> - pattern(K,St) - end, - #c_map_pair{anno=lineno_anno(L, St), - op=#c_literal{val=exact}, - key=Key, - val=pattern(V, St)}. - + %% this will throw a cryptic error message + %% but it is better than nothing + throw(nomatch) + end. %% pat_bin([BinElement], State) -> [BinSeg]. diff --git a/lib/compiler/test/map_SUITE.erl b/lib/compiler/test/map_SUITE.erl index cc018e4305..403b7e8405 100644 --- a/lib/compiler/test/map_SUITE.erl +++ b/lib/compiler/test/map_SUITE.erl @@ -113,6 +113,10 @@ t_build_and_match_literals(Config) when is_list(Config) -> M = #{ map_1:=#{ map_2:=#{value_3 := third}, value_2:= second}, value_1:=first} = id(#{ map_1=>#{ map_2=>#{value_3 => third}, value_2=> second}, value_1=>first}), + %% map key + #{ #{} := 42 } = id(#{ #{} => 42 }), + #{ #{ "a" => 3 } := 42 } = id(#{ #{ "a" => 3} => 42 }), + %% nil key #{[]:=ok,1:=2} = id(#{[]=>ok,1=>2}), @@ -123,6 +127,7 @@ t_build_and_match_literals(Config) when is_list(Config) -> {'EXIT',{{badmatch,_},_}} = (catch (#{x:=3} = id(#{y=>3}))), {'EXIT',{{badmatch,_},_}} = (catch (#{x:=3} = id(#{x=>"three"}))), {'EXIT',{badarg,_}} = (catch id(#{<<0:258>> =>"three"})), + {'EXIT',{{badmatch,_},_}} = (catch (#{#{"a"=>42} := 3}=id(#{#{"a"=>3}=>42}))), ok. t_build_and_match_aliasing(Config) when is_list(Config) -> diff --git a/lib/diameter/include/diameter.hrl b/lib/diameter/include/diameter.hrl index 79c4dce541..5a40e42300 100644 --- a/lib/diameter/include/diameter.hrl +++ b/lib/diameter/include/diameter.hrl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2010-2013. All Rights Reserved. +%% Copyright Ericsson AB 2010-2014. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -58,8 +58,8 @@ -record(diameter_header, {version, %% 8-bit unsigned length, %% 24-bit unsigned - cmd_code, %% 8-bit unsigned - application_id, %% 24-bit unsigned + cmd_code, %% 24-bit unsigned + application_id, %% 32-bit unsigned hop_by_hop_id, %% 32-bit unsigned end_to_end_id, %% 32-bit unsigned is_request, %% boolean() R flag diff --git a/lib/diameter/src/info/diameter_dbg.erl b/lib/diameter/src/info/diameter_dbg.erl index 1237007a75..b5b3983afa 100644 --- a/lib/diameter/src/info/diameter_dbg.erl +++ b/lib/diameter/src/info/diameter_dbg.erl @@ -26,7 +26,6 @@ -export([table/1, tables/0, fields/1, - help/0, modules/0, versions/0, version_info/0, @@ -56,9 +55,8 @@ -include_lib("diameter/include/diameter.hrl"). --define(APPLICATION, diameter). --define(INFO, diameter_info). --define(SEP(), ?INFO:sep()). +-define(APP, diameter). +-define(I, diameter_info). -define(LOCAL, [diameter_config, diameter_peer, @@ -70,24 +68,16 @@ -define(VALUES(Rec), tl(tuple_to_list(Rec))). -%%% ---------------------------------------------------------- -%%% # help() -%%% ---------------------------------------------------------- - -help() -> - not_yet_implemented. - -%%% ---------------------------------------------------------- -%%% # table(TableName) -%%% -%%% Input: TableName = diameter table containing record entries. -%%% -%%% Output: Count | undefined -%%% ---------------------------------------------------------- +%% ---------------------------------------------------------- +%% # table(TableName) +%% +%% Pretty-print a diameter table. Returns the number of records +%% printed, or undefined. +%% ---------------------------------------------------------- table(T) when (T == diameter_peer) orelse (T == diameter_reg) -> - ?INFO:format(collect(T), fields(T), fun ?INFO:split/2); + ?I:format(collect(T), fields(T), fun ?I:split/2); table(Table) when is_atom(Table) -> @@ -95,7 +85,7 @@ table(Table) undefined = No -> No; Fields -> - ?INFO:format(Table, Fields, fun split/2) + ?I:format(Table, Fields, fun split/2) end. split([started, name | Fs], [S, N | Vs]) -> @@ -106,9 +96,9 @@ split([[F|FT]|Fs], [Rec|Vs]) -> split([F|Fs], [V|Vs]) -> {F, Fs, V, Vs}. -%%% ---------------------------------------------------------- -%%% # TableName() -%%% ---------------------------------------------------------- +%% ---------------------------------------------------------- +%% # TableName() +%% ---------------------------------------------------------- -define(TABLE(Name), Name() -> table(Name)). @@ -120,16 +110,15 @@ split([F|Fs], [V|Vs]) -> ?TABLE(diameter_service). ?TABLE(diameter_stats). -%%% ---------------------------------------------------------- -%%% # tables() -%%% -%%% Output: Number of records output. -%%% -%%% Description: Pretty-print records in diameter tables from all nodes. -%%% ---------------------------------------------------------- +%% ---------------------------------------------------------- +%% # tables() +%% +%% Pretty-print diameter tables from all nodes. Returns the number of +%% records printed. +%% ---------------------------------------------------------- tables() -> - ?INFO:format(field(?LOCAL), fun split/3, fun collect/1). + ?I:format(field(?LOCAL), fun split/3, fun collect/1). field(Tables) -> lists:map(fun(T) -> {T, fields(T)} end, lists:sort(Tables)). @@ -137,66 +126,66 @@ field(Tables) -> split(_, Fs, Vs) -> split(Fs, Vs). -%%% ---------------------------------------------------------- -%%% # modules() -%%% ---------------------------------------------------------- +%% ---------------------------------------------------------- +%% # modules() +%% ---------------------------------------------------------- modules() -> - Path = filename:join([appdir(), atom_to_list(?APPLICATION) ++ ".app"]), - {ok, [{application, ?APPLICATION, Attrs}]} = file:consult(Path), + Path = filename:join([appdir(), atom_to_list(?APP) ++ ".app"]), + {ok, [{application, ?APP, Attrs}]} = file:consult(Path), {modules, Mods} = lists:keyfind(modules, 1, Attrs), Mods. appdir() -> - [_|_] = code:lib_dir(?APPLICATION, ebin). + [_|_] = code:lib_dir(?APP, ebin). -%%% ---------------------------------------------------------- -%%% # versions() -%%% ---------------------------------------------------------- +%% ---------------------------------------------------------- +%% # versions() +%% ---------------------------------------------------------- versions() -> - ?INFO:versions(modules()). + ?I:versions(modules()). -%%% ---------------------------------------------------------- -%%% # versions() -%%% ---------------------------------------------------------- +%% ---------------------------------------------------------- +%% # versions() +%% ---------------------------------------------------------- version_info() -> - ?INFO:version_info(modules()). + ?I:version_info(modules()). -%%% ---------------------------------------------------------- -%%% # compiled() -%%% ---------------------------------------------------------- +%% ---------------------------------------------------------- +%% # compiled() +%% ---------------------------------------------------------- compiled() -> - ?INFO:compiled(modules()). + ?I:compiled(modules()). -%%% ---------------------------------------------------------- -%%% procs() -%%% ---------------------------------------------------------- +%% ---------------------------------------------------------- +%% procs() +%% ---------------------------------------------------------- procs() -> - ?INFO:procs(?APPLICATION). + ?I:procs(?APP). -%%% ---------------------------------------------------------- -%%% # latest() -%%% ---------------------------------------------------------- +%% ---------------------------------------------------------- +%% # latest() +%% ---------------------------------------------------------- latest() -> - ?INFO:latest(modules()). + ?I:latest(modules()). -%%% ---------------------------------------------------------- -%%% # nl() -%%% ---------------------------------------------------------- +%% ---------------------------------------------------------- +%% # nl() +%% ---------------------------------------------------------- nl() -> lists:foreach(fun(M) -> abcast = c:nl(M) end, modules()). -%%% ---------------------------------------------------------- -%%% # pp(Bin) -%%% -%%% Description: Pretty-print a message binary. -%%% ---------------------------------------------------------- +%% ---------------------------------------------------------- +%% # pp(Bin) +%% +%% Description: Pretty-print a message binary. +%% ---------------------------------------------------------- %% Network byte order = big endian. @@ -206,7 +195,7 @@ pp(<<Version:8, MsgLength:24, HbHid:32, E2Eid:32, AVPs/binary>>) -> - ?SEP(), + ?I:sep(), ppp(["Version", "Message length", "[Actual length]", @@ -226,7 +215,7 @@ pp(<<Version:8, MsgLength:24, HbHid, E2Eid]), N = avp_loop({AVPs, MsgLength - 20}, 0), - ?SEP(), + ?I:sep(), N; pp(<<_Version:8, MsgLength:24, _/binary>> = Bin) -> @@ -327,23 +316,23 @@ ppp(Fields, Values) -> ppp({Field, Value}) -> io:format(": ~-22s : ~p~n", [Field, Value]). -%%% ---------------------------------------------------------- -%%% # subscriptions() -%%% -%%% Output: list of {SvcName, Pid} -%%% ---------------------------------------------------------- +%% ---------------------------------------------------------- +%% # subscriptions() +%% +%% Returns a list of {SvcName, Pid}. +%% ---------------------------------------------------------- subscriptions() -> diameter_service:subscriptions(). -%%% ---------------------------------------------------------- -%%% # children() -%%% ---------------------------------------------------------- +%% ---------------------------------------------------------- +%% # children() +%% ---------------------------------------------------------- children() -> diameter_sup:tree(). -%%% ---------------------------------------------------------- +%% ---------------------------------------------------------- %% tracer/[12] @@ -429,7 +418,7 @@ peers(Name, Ts) -> mk_peers(Name, [_, {type, connect} | _] = Ts) -> [[Name | mk_peer(Ts)]]; -mk_peers(Name, [R, {type, listen}, O, {accept = A, As}]) -> +mk_peers(Name, [R, {type, listen}, O, {accept = A, As} | _]) -> [[Name | mk_peer([R, {type, A}, O | Ts])] || Ts <- As]. %% This is a bit lame: service_info works to build this list and out %% of something like what we want here and then we take it apart. @@ -484,13 +473,12 @@ fields(diameter_service) -> [started, name, record_info(fields, diameter_service), + watchdogT, peerT, - connT, - share_peers, - use_shared_peers, shared_peers, local_peers, - monitor]; + monitor, + options]; ?FIELDS(diameter_event); ?FIELDS(diameter_uri); diff --git a/lib/observer/test/crashdump_viewer_SUITE.erl b/lib/observer/test/crashdump_viewer_SUITE.erl index f6e7d18f65..e9567c82cb 100644 --- a/lib/observer/test/crashdump_viewer_SUITE.erl +++ b/lib/observer/test/crashdump_viewer_SUITE.erl @@ -301,10 +301,12 @@ wait_for_progress_done() -> %%%----------------------------------------------------------------- %%% General check of what is displayed for a dump browse_file(File) -> - io:format("Browsing file: ~s~n",[File]), + io:format("~nBrowsing file: ~s",[File]), ok = start_backend(File), + io:format(" backend started",[]), + {ok,_GI=#general_info{},_GenTW} = crashdump_viewer:general_info(), {ok,Procs,_ProcsTW} = crashdump_viewer:processes(), {ok,Ports,_PortsTW} = crashdump_viewer:ports(), @@ -321,10 +323,16 @@ browse_file(File) -> {ok,_HashTabs,_HashTabsTW} = crashdump_viewer:hash_tables(), {ok,_IndexTabs,_IndexTabsTW} = crashdump_viewer:index_tables(), + io:format(" info read",[]), + lookat_all_pids(Procs), + io:format(" pids ok",[]), lookat_all_ports(Ports), + io:format(" ports ok",[]), lookat_all_mods(Mods), + io:format(" mods ok",[]), lookat_all_nodes(Nodes), + io:format(" nodes ok",[]), Procs. % used as second arg to special/2 @@ -339,6 +347,7 @@ special(File,Procs) -> [#proc{pid=Pid0}|_Rest] = lists:keysort(#proc.name,Procs), Pid = pid_to_list(Pid0), {ok,ProcDetails=#proc{},[]} = crashdump_viewer:proc_details(Pid), + io:format(" process details ok",[]), #proc{dict=Dict} = ProcDetails, @@ -350,6 +359,7 @@ special(File,Procs) -> ['#CDVBin',SOffset,SSize,SPos] = proplists:get_value(sub_bin,Dict), {ok,<<_:SSize/binary>>} = crashdump_viewer:expand_binary({SOffset,SSize,SPos}), + io:format(" expand binary ok",[]), ['#CDVPid',X1,Y1,Z1] = proplists:get_value(ext_pid,Dict), ChannelStr1 = integer_to_list(X1), @@ -359,22 +369,28 @@ special(File,Procs) -> integer_to_list(Z1) ++ ">", {error,{other_node,ChannelStr1}} = crashdump_viewer:proc_details(ExtPid), + io:format(" process details external ok",[]), ['#CDVPort',X2,Y2] = proplists:get_value(port,Dict), ChannelStr2 = integer_to_list(X2), Port = "#Port<"++ChannelStr2++"."++integer_to_list(Y2)++">", {ok,_PortDetails=#port{},[]} = crashdump_viewer:port(Port), + io:format(" port details ok",[]), ['#CDVPort',X3,Y3] = proplists:get_value(ext_port,Dict), ChannelStr3 = integer_to_list(X3), ExtPort = "#Port<"++ChannelStr3++"."++integer_to_list(Y3)++">", {error,{other_node,ChannelStr3}} = crashdump_viewer:port(ExtPort), + io:format(" port details external ok",[]), {ok,[_Ets=#ets_table{}],[]} = crashdump_viewer:ets_tables(Pid), + io:format(" ets tables ok",[]), {ok,[_Timer=#timer{}],[]} = crashdump_viewer:timers(Pid), + io:format(" timers ok",[]), {ok,Mod1=#loaded_mod{},[]} = crashdump_viewer:loaded_mod_details(atom_to_list(?helper_mod)), + io:format(" modules ok",[]), #loaded_mod{current_size=CS, old_size=OS, old_attrib=A,old_comp_info=C}=Mod1, true = is_integer(CS), @@ -383,6 +399,7 @@ special(File,Procs) -> true = (C=/=undefined), {ok,Mod2=#loaded_mod{},[]} = crashdump_viewer:loaded_mod_details("application"), + io:format(" module details ok",[]), #loaded_mod{old_size="No old code exists", old_attrib=undefined, old_comp_info=undefined}=Mod2, diff --git a/lib/public_key/doc/src/cert_records.xml b/lib/public_key/doc/src/cert_records.xml index 79e5cb219d..397c13b463 100644 --- a/lib/public_key/doc/src/cert_records.xml +++ b/lib/public_key/doc/src/cert_records.xml @@ -5,7 +5,7 @@ <header> <copyright> <year>2008</year> - <year>2013</year> + <year>2014</year> <holder>Ericsson AB, All Rights Reserved</holder> </copyright> <legalnotice> @@ -39,7 +39,7 @@ The intent is to describe the data types and not to specify the meaning of each component for this we refer you to <url href="http://www.ietf.org/rfc/rfc5280.txt">RFC 5280</url> and - <url href="http://www.rsa.com/rsalabs/node.asp?id=2124">PKCS-10</url>. + <url href="http://www.ietf.org/rfc/rfc5967.txt">PKCS-10</url>. </p> <p>Use the following include directive to get access to the diff --git a/lib/public_key/doc/src/part.xml b/lib/public_key/doc/src/part.xml index 51e628aa90..73146c8e2a 100644 --- a/lib/public_key/doc/src/part.xml +++ b/lib/public_key/doc/src/part.xml @@ -5,7 +5,7 @@ <header> <copyright> <year>2008</year> - <year>2013</year> + <year>2014</year> <holder>Ericsson AB, All Rights Reserved</holder> </copyright> <legalnotice> @@ -34,7 +34,7 @@ <p> This application provides an API to public key infrastructure from <url href="http://www.ietf.org/rfc/rfc5280.txt">RFC 5280</url> (X.509 certificates) and public key formats defined by - the <url href="http://www.rsa.com/rsalabs/node.asp?id=2124"> + the <url href="http://en.wikipedia.org/wiki/PKCS"> PKCS-standard</url></p> </description> <xi:include href="introduction.xml"/> diff --git a/lib/public_key/doc/src/public_key.xml b/lib/public_key/doc/src/public_key.xml index fc3479cb64..8e93f562d4 100644 --- a/lib/public_key/doc/src/public_key.xml +++ b/lib/public_key/doc/src/public_key.xml @@ -5,7 +5,7 @@ <header> <copyright> <year>2008</year> - <year>2013</year> + <year>2014</year> <holder>Ericsson AB, All Rights Reserved</holder> </copyright> <legalnotice> @@ -48,12 +48,12 @@ <item>Supports <url href="http://www.ietf.org/rfc/rfc5280.txt">RFC 5280 </url> - Internet X.509 Public Key Infrastructure Certificate and Certificate Revocation List (CRL) Profile </item> - <item>Supports <url href="http://www.rsa.com/rsalabs/node.asp?id=2125"> PKCS-1 </url> - RSA Cryptography Standard </item> + <item>Supports <url href="http://www.ietf.org/rfc/rfc3447.txt"> PKCS-1 </url> - RSA Cryptography Standard </item> <item>Supports <url href="http://csrc.nist.gov/publications/fips/fips186-3/fips_186-3.pdf"> DSS</url>- Digital Signature Standard (DSA - Digital Signature Algorithm)</item> - <item>Supports <url href="http://www.rsa.com/rsalabs/node.asp?id=2126"> PKCS-3 </url> - Diffie-Hellman Key Agreement Standard </item> - <item>Supports <url href="http://www.rsa.com/rsalabs/node.asp?id=2127"> PKCS-5</url> - Password-Based Cryptography Standard </item> - <item>Supports <url href="http://www.rsa.com/rsalabs/node.asp?id=2130"> PKCS-8</url> - Private-Key Information Syntax Standard</item> - <item>Supports <url href="http://www.rsa.com/rsalabs/node.asp?id=2132"> PKCS-10</url> - Certification Request Syntax Standard</item> + <item>Supports <url href="http://www.emc.com/emc-plus/rsa-labs/standards-initiatives/pkcs-3-diffie-hellman-key-agreement-standar.htm"> PKCS-3 </url> - Diffie-Hellman Key Agreement Standard </item> + <item>Supports <url href="http://www.ietf.org/rfc/rfc2898.txt"> PKCS-5</url> - Password-Based Cryptography Standard </item> + <item>Supports <url href="http://www.ietf.org/rfc/rfc5208.txt"> PKCS-8</url> - Private-Key Information Syntax Standard</item> + <item>Supports <url href="http://www.ietf.org/rfc/rfc5967.txt"> PKCS-10</url> - Certification Request Syntax Standard</item> </list> </section> @@ -461,11 +461,14 @@ <p>The fun should be defined as:</p> <code> -fun(OtpCert :: #'OTPCertificate'{}, Event :: {bad_cert, Reason :: atom()} | - {extension, #'Extension'{}}, +fun(OtpCert :: #'OTPCertificate'{}, + Event :: {bad_cert, Reason :: atom()} | + {extension, #'Extension'{}}, InitialUserState :: term()) -> - {valid, UserState :: term()} | {valid_peer, UserState :: term()} | - {fail, Reason :: term()} | {unknown, UserState :: term()}. + {valid, UserState :: term()} | + {valid_peer, UserState :: term()} | + {fail, Reason :: term()} | + {unknown, UserState :: term()}. </code> <p>If the verify callback fun returns {fail, Reason}, the @@ -511,7 +514,8 @@ fun(OtpCert :: #'OTPCertificate'{}, Event :: {bad_cert, Reason :: atom()} | <item> <p>The fun has the following type spec:</p> - <code> fun(#'DistributionPoint'{}, #'CertificateList'{}) -> #'CertificateList'{}</code> + <code> fun(#'DistributionPoint'{}, #'CertificateList'{}) -> + #'CertificateList'{}</code> <p>The fun should use the information in the distribution point to acesses the lates possible version of the CRL. If this fun is not specified @@ -519,6 +523,21 @@ fun(OtpCert :: #'OTPCertificate'{}, Event :: {bad_cert, Reason :: atom()} | </p> <code> fun(_DP, CRL) -> CRL end</code> </item> + + <tag>{issuer_fun, fun()}</tag> + <item> + <p>The fun has the following type spec:</p> + + <code> +fun(#'DistributionPoint'{}, #'CertificateList'{}, + {rdnSequence,[#'AttributeTypeAndValue'{}]}, term()) -> + {ok, #'OTPCertificate'{}, [der_encoded]}</code> + + <p>The fun should return the root certificate and certificate chain + that has signed the CRL. + </p> + <code> fun(DP, CRL, Issuer, UserState) -> {ok, RootCert, CertChain}</code> + </item> </taglist> </desc> </func> diff --git a/lib/sasl/doc/src/appup.xml b/lib/sasl/doc/src/appup.xml index 85fcbed3ba..95f315d269 100644 --- a/lib/sasl/doc/src/appup.xml +++ b/lib/sasl/doc/src/appup.xml @@ -4,7 +4,7 @@ <fileref> <header> <copyright> - <year>1997</year><year>2013</year> + <year>1997</year><year>2014</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -84,6 +84,9 @@ version identifier must be specified as a binary, e.g.</p> <code type="none"><<"2\\.1\\.[0-9]+">></code> <p>will match all versions <c>2.1.x</c>, where x is any number.</p> + <p>Note that the regular expression must match the complete + version string, so the above example will work for for + e.g. <c>2.1.1</c>, but not for <c>2.1.1.1</c></p> </section> <section> @@ -339,7 +342,7 @@ restart_new_emulator version of erts, kernel, stdlib and sasl are used when the emulator restarts. Only one <c>restart_new_emulator</c> instruction is allowed in the relup, and it shall be placed - first. <seealso marker="systools#make_relup/3">systools:make_relup3,4</seealso> + first. <seealso marker="systools#make_relup/3">systools:make_relup/3,4</seealso> will ensure this when the relup is generated. The rest of the relup script is executed after the restart as a part of the boot script.</p> @@ -347,11 +350,25 @@ restart_new_emulator completed. To programatically find out if the upgrade is complete, call <seealso marker="release_handler#which_releases/0"> - release_handler:which_releases</seealso> and check if the + release_handler:which_releases/0,1</seealso> and check if the expected release has status <c>current</c>.</p> <p>The new release must still be made permanent after the upgrade is completed. Otherwise, the old emulator is started in case of an emulator restart.</p> + <warning> + <p>As stated above, the <c>restart_new_emulator</c> + instruction causes the emulator to be restarted with new + versions of <c>erts</c>, <c>kernel</c>, <c>stdlib</c> and + <c>sasl</c>. All other applications, however, will at startup + be running their old versions in this new emulator. In most + cases this is no problem, but every now and then there will be + incompatible changes to the core applications which may cause + trouble in this setting. Such incompatible changes (when + functions are removed) are normally preceded by a deprecation + over two major releases. To make sure your application is not + crashed by an incompatible change, always remove any call to + deprecated functions as soon as possible.</p> + </warning> <pre> restart_emulator </pre> diff --git a/lib/sasl/examples/src/target_system.erl b/lib/sasl/examples/src/target_system.erl index fb9e9aaaaf..a0ae016791 100644 --- a/lib/sasl/examples/src/target_system.erl +++ b/lib/sasl/examples/src/target_system.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2011-2013. All Rights Reserved. +%% Copyright Ericsson AB 2011-2014. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -65,7 +65,7 @@ create(RelFileName,SystoolsOpts) -> [RelFileName, RelFileName]), make_script(RelFileName,SystoolsOpts), - TarFileName = filename:join(Dir,RelFileName ++ ".tar.gz"), + TarFileName = RelFileName ++ ".tar.gz", io:fwrite("Creating tar file ~tp ...~n", [TarFileName]), make_tar(RelFileName,SystoolsOpts), @@ -100,6 +100,12 @@ create(RelFileName,SystoolsOpts) -> copy_file(filename:join([ErtsBinDir, "to_erl"]), filename:join([TmpBinDir, "to_erl"]), [preserve]), + %% This is needed if 'start' script created from 'start.src' shall + %% be used as it points out this directory as log dir for 'run_erl' + TmpLogDir = filename:join([TmpDir, "log"]), + io:fwrite("Creating temporary directory ~tp ...~n", [TmpLogDir]), + ok = file:make_dir(TmpLogDir), + StartErlDataFile = filename:join([TmpDir, "releases", "start_erl.data"]), io:fwrite("Creating ~tp ...~n", [StartErlDataFile]), StartErlData = io_lib:fwrite("~s ~s~n", [ErtsVsn, RelVsn]), @@ -115,6 +121,7 @@ create(RelFileName,SystoolsOpts) -> erl_tar:add(Tar, filename:join(TmpDir,ErtsDir), ErtsDir, []), erl_tar:add(Tar, filename:join(TmpDir,"releases"), "releases", []), erl_tar:add(Tar, filename:join(TmpDir,"lib"), "lib", []), + erl_tar:add(Tar, filename:join(TmpDir,"log"), "log", []), erl_tar:close(Tar), %% file:set_cwd(Cwd), io:fwrite("Removing directory ~tp ...~n",[TmpDir]), @@ -136,6 +143,11 @@ install(RelFileName, RootDir) -> subst_src_scripts(["erl", "start", "start_erl"], ErtsBinDir, BinDir, [{"FINAL_ROOTDIR", RootDir}, {"EMU", "beam"}], [preserve]), + %%! Workaround for pre OTP 17.0: start.src and start_erl.src did + %%! not have correct permissions, so the above 'preserve' option did not help + ok = file:change_mode(filename:join(BinDir,"start"),8#0755), + ok = file:change_mode(filename:join(BinDir,"start_erl"),8#0755), + io:fwrite("Creating the RELEASES file ...\n"), create_RELEASES(RootDir, filename:join([RootDir, "releases", filename:basename(RelFileName)])). diff --git a/lib/sasl/test/release_handler_SUITE.erl b/lib/sasl/test/release_handler_SUITE.erl index ad2a8005b9..1d8bf45289 100644 --- a/lib/sasl/test/release_handler_SUITE.erl +++ b/lib/sasl/test/release_handler_SUITE.erl @@ -667,6 +667,9 @@ release_handler_which_releases(Conf) -> ok. +release_handler_which_releases(cleanup,_Conf) -> + stop_node(node_name(release_handler_which_releases)). + %%----------------------------------------------------------------- %% Ticket: OTP-2740 %% Slogan: vsn not numeric doesn't work so good in release_handling @@ -1365,6 +1368,9 @@ upgrade_supervisor(Conf) when is_list(Conf) -> ok. +upgrade_supervisor(cleanup,_Condf) -> + stop_node(node_name(upgrade_supervisor)). + %% Check that if the supervisor fails, then the upgrade is rolled back %% and an ok error message is returned upgrade_supervisor_fail(Conf) when is_list(Conf) -> @@ -2417,9 +2423,28 @@ check_gg_info(Node,OtherAlive,OtherDead,Synced) -> ?t:format("~ncheck_gg_info failed for ~p: ~p~nwhen GGI was: ~p~n" "and GI was: ~p~n", [Node,E,GGI,GI]), + %% An attempt to find out if it is only a timing issue + %% that makes this fail every now and then: + try_again_check(Node,GGI,GI,1), ?t:fail("check_gg_info failed") end. +try_again_check(_Node,_GGI,_GI,6) -> + ok; +try_again_check(Node,GGI,GI,N) -> + timer:sleep(1000), + case {rpc:call(Node,global_group,info,[]), + rpc:call(Node,global,info,[])} of + {GGI,GI} -> + ?t:format("~nAfter one more sek, GGI and GI are still the same"), + try_again_check(Node,GGI,GI,N+1); + {NewGGI,NewGI} -> + ?t:format("~nAfter one more sek:~nNew GGI: ~p~nNew GI: ~p~n", + [NewGGI,NewGI]), + try_again_check(Node,NewGGI,NewGI,N+1) + end. + + do_check_gg_info(OtherAlive,OtherDead,Synced,GGI,GI) -> {_,gg1} = lists:keyfind(own_group_name,1,GGI), {_,synced} = lists:keyfind(state,1,GGI), @@ -2563,7 +2588,7 @@ start_nodes(Conf,Snames,Tag) -> start_node_unix(Sname,NodeDir) -> Script = filename:join([NodeDir,"bin","start"]), - ?t:format("Starting ~p: ~tp~n", [Sname,Script]), + ?t:format("Starting ~p: ~ts~n", [Sname,Script]), case rh_test_lib:cmd(Script,[],[{"NODENAME",atom_to_list(Sname)}]) of ok -> {ok,node_name(Sname)}; diff --git a/lib/stdlib/doc/src/pg.xml b/lib/stdlib/doc/src/pg.xml index 7cc1b805b4..a3b69884b6 100644 --- a/lib/stdlib/doc/src/pg.xml +++ b/lib/stdlib/doc/src/pg.xml @@ -5,7 +5,7 @@ <header> <copyright> <year>1996</year> - <year>2013</year> + <year>2014</year> <holder>Ericsson AB, All Rights Reserved</holder> </copyright> <legalnotice> @@ -32,6 +32,9 @@ <module>pg</module> <modulesummary>Distributed, Named Process Groups</modulesummary> <description> + <warning> + <p>This module is deprecated and will be removed in Erlang/OTP 18.</p> + </warning> <p>This (experimental) module implements process groups. A process group is a group of processes that can be accessed by a common name. For example, a group named <c>foobar</c> can include a set diff --git a/lib/stdlib/examples/erl_id_trans.erl b/lib/stdlib/examples/erl_id_trans.erl index 5fcb74310e..e71e26e51a 100644 --- a/lib/stdlib/examples/erl_id_trans.erl +++ b/lib/stdlib/examples/erl_id_trans.erl @@ -148,7 +148,7 @@ pattern({map,Line,Ps0}) -> Ps1 = pattern_list(Ps0), {map,Line,Ps1}; pattern({map_field_exact,Line,K,V}) -> - Ke = pattern(K), + Ke = expr(K), Ve = pattern(V), {map_field_exact,Line,Ke,Ve}; %%pattern({struct,Line,Tag,Ps0}) -> diff --git a/lib/stdlib/src/erl_expand_records.erl b/lib/stdlib/src/erl_expand_records.erl index f53c6e1278..57e768ba9d 100644 --- a/lib/stdlib/src/erl_expand_records.erl +++ b/lib/stdlib/src/erl_expand_records.erl @@ -135,10 +135,10 @@ pattern({tuple,Line,Ps}, St0) -> pattern({map,Line,Ps}, St0) -> {TPs,St1} = pattern_list(Ps, St0), {{map,Line,TPs},St1}; -pattern({map_field_exact,Line,Key0,V0}, St0) -> - {Key,St1} = pattern(Key0, St0), +pattern({map_field_exact,Line,K0,V0}, St0) -> + {K,St1} = expr(K0, St0), {V,St2} = pattern(V0, St1), - {{map_field_exact,Line,Key,V},St2}; + {{map_field_exact,Line,K,V},St2}; %%pattern({struct,Line,Tag,Ps}, St0) -> %% {TPs,TPsvs,St1} = pattern_list(Ps, St0), %% {{struct,Line,Tag,TPs},TPsvs,St1}; diff --git a/lib/stdlib/src/erl_lint.erl b/lib/stdlib/src/erl_lint.erl index c4c94fbee4..7c064ce902 100644 --- a/lib/stdlib/src/erl_lint.erl +++ b/lib/stdlib/src/erl_lint.erl @@ -1407,7 +1407,7 @@ pattern({map,_Line,Ps}, Vt, Old, Bvt, St) -> ({map_field_assoc,L,_,_}, {Psvt,Bvt0,St0}) -> {Psvt,Bvt0,add_error(L, illegal_pattern, St0)}; ({map_field_exact,L,KP,VP}, {Psvt,Bvt0,St0}) -> - case is_valid_map_key(KP, St0) of + case is_valid_map_key(KP, pattern, St0) of true -> {Pvt,Bvt1,St1} = pattern(VP, Vt, Old, Bvt, St0), {vtmerge_pat(Pvt, Psvt),vtmerge_pat(Bvt0, Bvt1), St1}; @@ -2322,14 +2322,16 @@ is_valid_call(Call) -> %% check for value expression without variables is_valid_map_key(K,St) -> + is_valid_map_key(K,expr,St). +is_valid_map_key(K,Ctx,St) -> case expr(K,[],St) of {[],_} -> - is_valid_map_key_value(K); + is_valid_map_key_value(K,Ctx); {[Var|_],_} -> {false,variable,element(1,Var)} end. -is_valid_map_key_value(K) -> +is_valid_map_key_value(K,Ctx) -> case K of {char,_,_} -> true; {integer,_,_} -> true; @@ -2338,34 +2340,36 @@ is_valid_map_key_value(K) -> {nil,_} -> true; {atom,_,_} -> true; {cons,_,H,T} -> - is_valid_map_key_value(H) andalso - is_valid_map_key_value(T); + is_valid_map_key_value(H,Ctx) andalso + is_valid_map_key_value(T,Ctx); {tuple,_,Es} -> foldl(fun(E,B) -> - B andalso is_valid_map_key_value(E) + B andalso is_valid_map_key_value(E,Ctx) end,true,Es); {map,_,Arg,Ps} -> % only check for value expressions to be valid % invalid map expressions are later checked in % core and kernel - is_valid_map_key_value(Arg) andalso foldl(fun + is_valid_map_key_value(Arg,Ctx) andalso foldl(fun ({Tag,_,Ke,Ve},B) when Tag =:= map_field_assoc; - Tag =:= map_field_exact -> - B andalso is_valid_map_key_value(Ke) - andalso is_valid_map_key_value(Ve) + Tag =:= map_field_exact, Ctx =:= expr -> + B andalso is_valid_map_key_value(Ke,Ctx) + andalso is_valid_map_key_value(Ve,Ctx); + (_,_) -> false end,true,Ps); {map,_,Ps} -> foldl(fun ({Tag,_,Ke,Ve},B) when Tag =:= map_field_assoc; - Tag =:= map_field_exact -> - B andalso is_valid_map_key_value(Ke) - andalso is_valid_map_key_value(Ve) + Tag =:= map_field_exact, Ctx =:= expr -> + B andalso is_valid_map_key_value(Ke,Ctx) + andalso is_valid_map_key_value(Ve,Ctx); + (_,_) -> false end, true, Ps); {record,_,_,Fs} -> foldl(fun ({record_field,_,Ke,Ve},B) -> - B andalso is_valid_map_key_value(Ke) - andalso is_valid_map_key_value(Ve) + B andalso is_valid_map_key_value(Ke,Ctx) + andalso is_valid_map_key_value(Ve,Ctx) end,true,Fs); {bin,_,Es} -> % only check for value expressions to be valid @@ -2373,7 +2377,7 @@ is_valid_map_key_value(K) -> % core and kernel foldl(fun ({bin_element,_,E,_,_},B) -> - B andalso is_valid_map_key_value(E) + B andalso is_valid_map_key_value(E,Ctx) end,true,Es); _ -> false end. diff --git a/lib/stdlib/src/otp_internal.erl b/lib/stdlib/src/otp_internal.erl index 971a2e2baa..c0ee8799c8 100644 --- a/lib/stdlib/src/otp_internal.erl +++ b/lib/stdlib/src/otp_internal.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1999-2013. All Rights Reserved. +%% Copyright Ericsson AB 1999-2014. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -83,18 +83,18 @@ obsolete_1(crypto, sha_init, 0) -> {deprecated, {crypto, hash_init, 1}}; obsolete_1(crypto, md4_update, 2) -> - {deprecated, {crypto, hash_update, 3}}; + {deprecated, {crypto, hash_update, 2}}; obsolete_1(crypto, md5_update, 2) -> - {deprecated, {crypto, hash_update, 3}}; + {deprecated, {crypto, hash_update, 2}}; obsolete_1(crypto, sha_update, 2) -> - {deprecated, {crypto, hash_update, 3}}; + {deprecated, {crypto, hash_update, 2}}; obsolete_1(crypto, md4_final, 1) -> - {deprecated, {crypto, hash_final, 2}}; + {deprecated, {crypto, hash_final, 1}}; obsolete_1(crypto, md5_final, 1) -> - {deprecated, {crypto, hash_final, 2}}; + {deprecated, {crypto, hash_final, 1}}; obsolete_1(crypto, sha_final, 1) -> - {deprecated, {crypto, hash_final, 2}}; + {deprecated, {crypto, hash_final, 1}}; obsolete_1(crypto, md5_mac, 2) -> {deprecated, {crypto, hmac, 3}}; @@ -104,9 +104,9 @@ obsolete_1(crypto, sha_mac, 3) -> {deprecated, {crypto, hmac, 4}}; obsolete_1(crypto, sha_mac_96, 2) -> - {deprecated, {crypto, hmac_n, 3}}; + {deprecated, {crypto, hmac, 4}}; obsolete_1(crypto, md5_mac_96, 2) -> - {deprecated, {crypto, hmac_n, 3}}; + {deprecated, {crypto, hmac, 4}}; obsolete_1(crypto, rsa_sign, 2) -> {deprecated, {crypto, sign, 4}}; @@ -123,9 +123,9 @@ obsolete_1(crypto, dss_sign, 3) -> {deprecated, {crypto, sign, 4}}; obsolete_1(crypto, dss_verify, 3) -> - {deprecated, {crypto, verify, 4}}; + {deprecated, {crypto, verify, 5}}; obsolete_1(crypto, dss_verify, 4) -> - {deprecated, {crypto, verify, 4}}; + {deprecated, {crypto, verify, 5}}; obsolete_1(crypto, mod_exp, 3) -> {deprecated, {crypto, mod_pow, 3}}; @@ -133,7 +133,7 @@ obsolete_1(crypto, mod_exp, 3) -> obsolete_1(crypto, dh_compute_key, 3) -> {deprecated, {crypto, compute_key, 4}}; obsolete_1(crypto, dh_generate_key, 1) -> - {deprecated, {crypto, generate_key, 3}}; + {deprecated, {crypto, generate_key, 2}}; obsolete_1(crypto, dh_generate_key, 2) -> {deprecated, {crypto, generate_key, 3}}; @@ -577,6 +577,8 @@ obsolete_1(asn1rt, utf8_binary_to_list, 1) -> {deprecated,{unicode,characters_to_list,1}}; obsolete_1(asn1rt, utf8_list_to_binary, 1) -> {deprecated,{unicode,characters_to_binary,1}}; +obsolete_1(pg, _, _) -> + {deprecated,"deprecated; will be removed in OTP 18"}; obsolete_1(_, _, _) -> no. diff --git a/lib/stdlib/src/pg.erl b/lib/stdlib/src/pg.erl index ee177e4e0b..a41fd329c2 100644 --- a/lib/stdlib/src/pg.erl +++ b/lib/stdlib/src/pg.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2011. All Rights Reserved. +%% Copyright Ericsson AB 1996-2014. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -17,6 +17,7 @@ %% %CopyrightEnd% %% -module(pg). +-deprecated(module). %% pg provides a process group facility. Messages %% can be multicasted to all members in the group diff --git a/lib/stdlib/test/erl_lint_SUITE.erl b/lib/stdlib/test/erl_lint_SUITE.erl index bb14de333d..d9512c0ef4 100644 --- a/lib/stdlib/test/erl_lint_SUITE.erl +++ b/lib/stdlib/test/erl_lint_SUITE.erl @@ -3406,7 +3406,19 @@ maps(Config) -> {4,erl_lint,illegal_map_key}, {6,erl_lint,illegal_map_key}, {8,erl_lint,illegal_map_key}, - {10,erl_lint,illegal_map_key}],[]}}], + {10,erl_lint,illegal_map_key}],[]}}, + {errors_in_map_keys_pattern, + <<"t(#{ a := 2, + #{} := A, + #{ 3 => 33 } := hi, + #{ 3 := 33 } := hi, + #{ hi => 54, \"hello\" => 45 } := hi, + #{ V => 33 } := hi }) -> + A. + ">>, + [], + {errors,[{4,erl_lint,illegal_map_key}, + {6,erl_lint,{illegal_map_key_variable,'V'}}],[]}}], [] = run(Config, Ts), ok. diff --git a/lib/test_server/doc/src/test_server_ctrl.xml b/lib/test_server/doc/src/test_server_ctrl.xml index f4aae724e0..0cda531716 100644 --- a/lib/test_server/doc/src/test_server_ctrl.xml +++ b/lib/test_server/doc/src/test_server_ctrl.xml @@ -773,11 +773,14 @@ test_server_ctrl:cross_cover_analyse(Level,[{s1,S1LogDir},{s2,S2LogDir}]) <p><c>What = tests_start, Data = {Name,NumCases}</c><br></br> <c>What = loginfo, Data = [{topdir,TestRootDir},{rundir,CurrLogDir}]</c><br></br> <c>What = tests_done, Data = {Ok,Failed,{UserSkipped,AutoSkipped}}</c><br></br> - <c>What = tc_start, Data = {{Mod,Func},TCLogFile}</c><br></br> - <c>What = tc_done, Data = {Mod,Func,Result}</c><br></br> - <c>What = tc_user_skip, Data = {Mod,Func,Comment}</c><br></br> - <c>What = tc_auto_skip, Data = {Mod,Func,Comment}</c><br></br> + <c>What = tc_start, Data = {{Mod,{Func,GroupName}},TCLogFile}</c><br></br> + <c>What = tc_done, Data = {Mod,{Func,GroupName},Result}</c><br></br> + <c>What = tc_user_skip, Data = {Mod,{Func,GroupName},Comment}</c><br></br> + <c>What = tc_auto_skip, Data = {Mod,{Func,GroupName},Comment}</c><br></br> <c>What = framework_error, Data = {{FWMod,FWFunc},Error}</c></p> + <p>Note that for a test case function that doesn't belong to a group, + <c>GroupName</c> has value <c>undefined</c>, otherwise the name of the test + case group.</p> </desc> </func> <func> diff --git a/lib/tools/test/eprof_SUITE.erl b/lib/tools/test/eprof_SUITE.erl index 1227d5b841..04b522de4a 100644 --- a/lib/tools/test/eprof_SUITE.erl +++ b/lib/tools/test/eprof_SUITE.erl @@ -104,7 +104,7 @@ basic(Config) when is_list(Config) -> profiling = eprof:profile([A]), true = exit(A, kill_it), profiling_stopped = eprof:stop_profiling(), - {error,_} = eprof:profile(fun() -> a = b end), + {error,_} = eprof:profile(fun() -> a = id(b) end), %% with mfa @@ -149,8 +149,7 @@ basic_option_1(Config) -> % vanilla {ok, _} = eprof:profile(fun() -> eprof_test:do(10) end, [{set_on_spawn, true}]), - [{_, MfasDo1},{_, MfasLists1}] = eprof:dump(), - Mfas1 = MfasDo1 ++ MfasLists1, + Mfas1 = lists:foldl(fun({_,Mfas},Out) -> Mfas ++ Out end, [], eprof:dump()), {value, {_, {11, _}}} = lists:keysearch({eprof_test,dec,1}, 1, Mfas1), {value, {_, { 1, _}}} = lists:keysearch({eprof_test, go,1}, 1, Mfas1), @@ -159,8 +158,7 @@ basic_option_1(Config) -> {ok, _} = eprof:profile(fun() -> eprof_test:do(10) end, [set_on_spawn]), - [{_, MfasDo2},{_, MfasLists2}] = eprof:dump(), - Mfas2 = MfasDo2 ++ MfasLists2, + Mfas2 = lists:foldl(fun({_,Mfas},Out) -> Mfas ++ Out end, [], eprof:dump()), {value, {_, {11, _}}} = lists:keysearch({eprof_test,dec,1}, 1, Mfas2), {value, {_, { 1, _}}} = lists:keysearch({eprof_test, go,1}, 1, Mfas2), {value, {_, { 9, _}}} = lists:keysearch({lists, split_2,5}, 1, Mfas2), @@ -255,3 +253,5 @@ ensure_eprof_stopped() -> Pid -> stopped=eprof:stop() end. + +id(I) -> I. |