aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--bootstrap/lib/compiler/ebin/beam_receive.beambin6616 -> 6480 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/epp.beambin27416 -> 27416 bytes
-rw-r--r--bootstrap/lib/stdlib/ebin/lists.beambin29592 -> 29636 bytes
-rw-r--r--erts/emulator/drivers/unix/ttsl_drv.c4
-rw-r--r--lib/common_test/src/ct_logs.erl47
-rw-r--r--lib/common_test/src/ct_telnet.erl7
-rw-r--r--lib/compiler/src/beam_receive.erl92
-rw-r--r--lib/compiler/test/receive_SUITE.erl13
-rw-r--r--lib/compiler/test/receive_SUITE_data/ref_opt/yes_14.S71
-rwxr-xr-xlib/crypto/doc/src/crypto.xml2
-rw-r--r--lib/dialyzer/src/dialyzer_gui.erl5
-rw-r--r--lib/dialyzer/src/dialyzer_gui_wx.erl5
-rw-r--r--lib/et/doc/src/et_desc.xmlsrc2
-rw-r--r--lib/jinterface/test/jinterface_SUITE.erl3
-rw-r--r--lib/jinterface/test/jitu.erl38
-rw-r--r--lib/jinterface/test/nc_SUITE.erl12
-rw-r--r--lib/ssl/src/ssl_connection.erl2
-rw-r--r--lib/ssl/test/ssl_basic_SUITE.erl33
-rw-r--r--lib/ssl/test/ssl_test_lib.erl32
-rw-r--r--lib/stdlib/doc/src/lists.xml25
-rw-r--r--lib/stdlib/src/epp.erl2
-rw-r--r--lib/stdlib/src/lists.erl24
-rw-r--r--lib/stdlib/test/epp_SUITE.erl4
-rw-r--r--lib/stdlib/test/ets_SUITE.erl68
-rw-r--r--lib/stdlib/test/lists_SUITE.erl4
-rw-r--r--lib/test_server/src/test_server_ctrl.erl4
-rw-r--r--lib/test_server/src/test_server_io.erl17
27 files changed, 386 insertions, 130 deletions
diff --git a/bootstrap/lib/compiler/ebin/beam_receive.beam b/bootstrap/lib/compiler/ebin/beam_receive.beam
index afc5eaa333..2f1fcc9fe1 100644
--- a/bootstrap/lib/compiler/ebin/beam_receive.beam
+++ b/bootstrap/lib/compiler/ebin/beam_receive.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/epp.beam b/bootstrap/lib/stdlib/ebin/epp.beam
index 0e3672e3b0..879370ef87 100644
--- a/bootstrap/lib/stdlib/ebin/epp.beam
+++ b/bootstrap/lib/stdlib/ebin/epp.beam
Binary files differ
diff --git a/bootstrap/lib/stdlib/ebin/lists.beam b/bootstrap/lib/stdlib/ebin/lists.beam
index cf189f2ae5..332a2088d0 100644
--- a/bootstrap/lib/stdlib/ebin/lists.beam
+++ b/bootstrap/lib/stdlib/ebin/lists.beam
Binary files differ
diff --git a/erts/emulator/drivers/unix/ttsl_drv.c b/erts/emulator/drivers/unix/ttsl_drv.c
index 8912d148a5..bedb5ef784 100644
--- a/erts/emulator/drivers/unix/ttsl_drv.c
+++ b/erts/emulator/drivers/unix/ttsl_drv.c
@@ -823,7 +823,7 @@ static int del_chars(int n)
r = llen - lpos - l; /* Characters after deleted */
/* Fix up buffer and buffer pointers. */
if (r > 0)
- memcpy(lbuf + lpos, lbuf + pos, r * sizeof(Uint32));
+ memmove(lbuf + lpos, lbuf + pos, r * sizeof(Uint32));
llen -= l;
/* Write out characters after, blank the tail and jump back to lpos. */
write_buf(lbuf + lpos, r);
@@ -842,7 +842,7 @@ static int del_chars(int n)
move_cursor(lpos, lpos-l); /* Move back */
/* Fix up buffer and buffer pointers. */
if (r > 0)
- memcpy(lbuf + pos, lbuf + lpos, r * sizeof(Uint32));
+ memmove(lbuf + pos, lbuf + lpos, r * sizeof(Uint32));
lpos -= l;
llen -= l;
/* Write out characters after, blank the tail and jump back to lpos. */
diff --git a/lib/common_test/src/ct_logs.erl b/lib/common_test/src/ct_logs.erl
index 1f8160ff03..f5355bfefe 100644
--- a/lib/common_test/src/ct_logs.erl
+++ b/lib/common_test/src/ct_logs.erl
@@ -200,12 +200,19 @@ clear_stylesheet(TC) ->
%%%-----------------------------------------------------------------
%%% @spec get_log_dir() -> {ok,Dir} | {error,Reason}
get_log_dir() ->
- call({get_log_dir,false}).
+ get_log_dir(false).
%%%-----------------------------------------------------------------
%%% @spec get_log_dir(ReturnAbsName) -> {ok,Dir} | {error,Reason}
get_log_dir(ReturnAbsName) ->
- call({get_log_dir,ReturnAbsName}).
+ case call({get_log_dir,ReturnAbsName}) of
+ {error,does_not_exist} when ReturnAbsName == true ->
+ {ok,filename:absname(".")};
+ {error,does_not_exist} ->
+ {ok,"."};
+ Result ->
+ Result
+ end.
%%%-----------------------------------------------------------------
%%% make_last_run_index() -> ok
@@ -552,7 +559,6 @@ log_timestamp({MS,S,US}) ->
logger(Parent, Mode, Verbosity) ->
register(?MODULE,self()),
-
%%! Below is a temporary workaround for the limitation of
%%! max one test run per second.
%%! --->
@@ -984,12 +990,11 @@ print_style_error(Fd,StyleSheet,Reason) ->
print_style(Fd,undefined).
close_ctlog(Fd) ->
- io:format(Fd,"\n</pre>\n",[]),
- io:format(Fd,footer(),[]),
+ io:format(Fd, "\n</pre>\n", []),
+ io:format(Fd, [xhtml("<br><br>\n", "<br /><br />\n") | footer()], []),
file:close(Fd).
-
%%%-----------------------------------------------------------------
%%% Make an index page for the last run
make_last_run_index(StartTime) ->
@@ -1043,7 +1048,7 @@ make_last_run_index1(StartTime,IndexName) ->
0, 0, 0, 0, 0, Missing),
%% write current Totals to file, later to be used in all_runs log
write_totals_file(?totals_name,Label,Logs1,Totals),
- Index = [Index0|index_footer()],
+ Index = [Index0|last_run_index_footer()],
case force_write_file(IndexName, unicode:characters_to_binary(Index)) of
ok ->
@@ -1452,17 +1457,30 @@ header1(Title, SubTitle, TableCols) ->
"</center>\n",
SubTitleHTML,"\n"].
-index_footer() ->
- ["</table>\n"
+last_run_index_footer() ->
+ AllRuns = filename:join("../",?all_runs_name),
+ TestIndex = filename:join("../",?index_name),
+ ["</table>\n",
+ xhtml("<br><hr><p>\n", "<br /><hr /><p>\n"),
+ "<a href=\"", uri(AllRuns),
+ "\">Test run history\n</a> | ",
+ "<a href=\"", uri(TestIndex),
+ "\">Top level test index\n</a>\n</p>\n",
"</center>\n" | footer()].
+all_suites_index_footer() ->
+ ["</table>\n",
+ "</center>\n",
+ xhtml("<br><br>\n", "<br /><br />\n") | footer()].
+
all_runs_index_footer() ->
- ["</tbody>\n</table>\n"
- "</center>\n" | footer()].
+ ["</tbody>\n</table>\n",
+ "</center>\n",
+ xhtml("<br><br>\n", "<br /><br />\n") | footer()].
footer() ->
["<center>\n",
- xhtml("<br><br>\n<hr>\n", "<br /><br />\n"),
+ xhtml("<hr>\n", ""),
xhtml("<p><font size=\"-1\">\n", "<div class=\"copyright\">"),
"Copyright &copy; ", year(),
" <a href=\"http://www.erlang.org\">Open Telecom Platform</a>",
@@ -1474,7 +1492,6 @@ footer() ->
"</body>\n"
"</html>\n"].
-
body_tag() ->
CTPath = code:lib_dir(common_test),
TileFile = filename:join(filename:join(CTPath,"priv"),"tile1.jpg"),
@@ -2376,7 +2393,7 @@ make_all_suites_index2(IndexName, AllTestLogDirs) ->
make_all_suites_index3(AllTestLogDirs,
all_suites_index_header(),
0, 0, 0, 0, 0, [], []),
- Index = [Index0|index_footer()],
+ Index = [Index0|all_suites_index_footer()],
case force_write_file(IndexName, unicode:characters_to_binary(Index)) of
ok ->
{ok,TempData};
@@ -2482,7 +2499,7 @@ make_all_suites_ix_temp(AbsIndexName, NewTestData, Label, AllTestLogDirs) ->
Index0 = make_all_suites_ix_temp1(AllTestLogDirs1,
all_suites_index_header(IndexDir),
0, 0, 0, 0, 0),
- Index = [Index0|index_footer()],
+ Index = [Index0|all_suites_index_footer()],
case force_write_file(AbsIndexName, unicode:characters_to_binary(Index)) of
ok ->
ok;
diff --git a/lib/common_test/src/ct_telnet.erl b/lib/common_test/src/ct_telnet.erl
index beb3c1d649..bd74991859 100644
--- a/lib/common_test/src/ct_telnet.erl
+++ b/lib/common_test/src/ct_telnet.erl
@@ -29,7 +29,9 @@
%%% Command timeout = 10 sec (time to wait for a command to return)
%%% Max no of reconnection attempts = 3
%%% Reconnection interval = 5 sek (time to wait in between reconnection attempts)
-%%% Keep alive = true (will send NOP to the server every 10 sec if connection is idle)</pre>
+%%% Keep alive = true (will send NOP to the server every 10 sec if connection is idle)
+%%% Wait for linebreak = true (Will expect answer from server to end with linebreak when
+%%% using ct_telnet:expect)</pre>
%%% <p>These parameters can be altered by the user with the following
%%% configuration term:</p>
%%% <pre>
@@ -37,7 +39,8 @@
%%% {command_timeout,Millisec},
%%% {reconnection_attempts,N},
%%% {reconnection_interval,Millisec},
-%%% {keep_alive,Bool}]}.</pre>
+%%% {keep_alive,Bool},
+%% {wait_for_linebreak, Bool}]}.</pre>
%%% <p><code>Millisec = integer(), N = integer()</code></p>
%%% <p>Enter the <code>telnet_settings</code> term in a configuration
%%% file included in the test and ct_telnet will retrieve the information
diff --git a/lib/compiler/src/beam_receive.erl b/lib/compiler/src/beam_receive.erl
index 3dd5ed182e..97a9188ee7 100644
--- a/lib/compiler/src/beam_receive.erl
+++ b/lib/compiler/src/beam_receive.erl
@@ -151,20 +151,20 @@ opt_recv(Is, Regs, D) ->
opt_recv([{label,L}=Lbl,{loop_rec,{f,Fail},_}=Loop|Is], D, R0, _, Acc) ->
R = regs_kill_not_live(0, R0),
- case regs_to_list(R) of
- [{y,_}=RefReg] ->
- %% We now have the new reference in the Y register RefReg
+ case regs_empty(R) of
+ false ->
+ %% We now have the new reference in Y registers
%% and the current instruction is the beginning of a
%% receive statement. We must now verify that only messages
%% that contain the reference will be matched.
- case opt_ref_used(Is, RefReg, Fail, D) of
+ case opt_ref_used(Is, R, Fail, D) of
false ->
no;
true ->
RecvSet = {recv_set,{f,L}},
{yes,reverse(Acc, [RecvSet,Lbl,Loop|Is]),L}
end;
- [] ->
+ true ->
no
end;
opt_recv([I|Is], D, R0, L0, Acc) ->
@@ -226,9 +226,9 @@ opt_update_regs_bl([{set,Ds,_,_}|Is], Regs0) ->
opt_update_regs_bl(Is, Regs);
opt_update_regs_bl([], Regs) -> Regs.
-%% opt_ref_used([Instruction], RefRegister, FailLabel, LabelIndex) -> true|false
+%% opt_ref_used([Instruction], RefRegs, FailLabel, LabelIndex) -> true|false
%% Return 'true' if it is certain that only messages that contain the same
-%% reference as in RefRegister can be matched out. Otherwise return 'false'.
+%% reference as in RefRegs can be matched out. Otherwise return 'false'.
%%
%% Basically, we follow all possible paths through the receive statement.
%% If all paths are safe, we return 'true'.
@@ -236,7 +236,7 @@ opt_update_regs_bl([], Regs) -> Regs.
%% A branch to FailLabel is safe, because it exits the receive statement
%% and no further message may be matched out.
%%
-%% If a path hits an comparision between RefRegister and part of the message,
+%% If a path hits an comparision between RefRegs and part of the message,
%% that path is safe (any messages that may be matched further down the
%% path is guaranteed to contain the reference).
%%
@@ -245,11 +245,11 @@ opt_update_regs_bl([], Regs) -> Regs.
%% we hit an unrecognized instruction, we also give up and return
%% 'false' (the optimization may be unsafe).
-opt_ref_used(Is, RefReg, Fail, D) ->
+opt_ref_used(Is, RefRegs, Fail, D) ->
Done = gb_sets:singleton(Fail),
Regs = regs_init_x0(),
try
- _ = opt_ref_used_1(Is, RefReg, D, Done, Regs),
+ _ = opt_ref_used_1(Is, RefRegs, D, Done, Regs),
true
catch
throw:not_used ->
@@ -258,37 +258,39 @@ opt_ref_used(Is, RefReg, Fail, D) ->
%% This functions only returns if all paths through the receive
%% statement are safe, and throws an 'not_used' term otherwise.
-opt_ref_used_1([{block,Bl}|Is], RefReg, D, Done, Regs0) ->
+opt_ref_used_1([{block,Bl}|Is], RefRegs, D, Done, Regs0) ->
Regs = opt_ref_used_bl(Bl, Regs0),
- opt_ref_used_1(Is, RefReg, D, Done, Regs);
-opt_ref_used_1([{test,is_eq_exact,{f,Fail},Args}|Is], RefReg, D, Done0, Regs) ->
- Done = opt_ref_used_at(Fail, RefReg, D, Done0, Regs),
- case is_ref_msg_comparison(Args, RefReg, Regs) of
+ opt_ref_used_1(Is, RefRegs, D, Done, Regs);
+opt_ref_used_1([{test,is_eq_exact,{f,Fail},Args}|Is],
+ RefRegs, D, Done0, Regs) ->
+ Done = opt_ref_used_at(Fail, RefRegs, D, Done0, Regs),
+ case is_ref_msg_comparison(Args, RefRegs, Regs) of
false ->
- opt_ref_used_1(Is, RefReg, D, Done, Regs);
+ opt_ref_used_1(Is, RefRegs, D, Done, Regs);
true ->
%% The instructions that follow (Is) can only be executed
- %% if the message contains the same reference as in RefReg.
+ %% if the message contains the same reference as in RefRegs.
Done
end;
-opt_ref_used_1([{test,is_ne_exact,{f,Fail},Args}|Is], RefReg, D, Done0, Regs) ->
- Done = opt_ref_used_1(Is, RefReg, D, Done0, Regs),
- case is_ref_msg_comparison(Args, RefReg, Regs) of
+opt_ref_used_1([{test,is_ne_exact,{f,Fail},Args}|Is],
+ RefRegs, D, Done0, Regs) ->
+ Done = opt_ref_used_1(Is, RefRegs, D, Done0, Regs),
+ case is_ref_msg_comparison(Args, RefRegs, Regs) of
false ->
- opt_ref_used_at(Fail, RefReg, D, Done, Regs);
+ opt_ref_used_at(Fail, RefRegs, D, Done, Regs);
true ->
Done
end;
-opt_ref_used_1([{test,_,{f,Fail},_}|Is], RefReg, D, Done0, Regs) ->
- Done = opt_ref_used_at(Fail, RefReg, D, Done0, Regs),
- opt_ref_used_1(Is, RefReg, D, Done, Regs);
-opt_ref_used_1([{select,_,_,{f,Fail},List}|_], RefReg, D, Done, Regs) ->
+opt_ref_used_1([{test,_,{f,Fail},_}|Is], RefRegs, D, Done0, Regs) ->
+ Done = opt_ref_used_at(Fail, RefRegs, D, Done0, Regs),
+ opt_ref_used_1(Is, RefRegs, D, Done, Regs);
+opt_ref_used_1([{select,_,_,{f,Fail},List}|_], RefRegs, D, Done, Regs) ->
Lbls = [F || {f,F} <- List] ++ [Fail],
- opt_ref_used_in_all(Lbls, RefReg, D, Done, Regs);
-opt_ref_used_1([{label,Lbl}|Is], RefReg, D, Done, Regs) ->
+ opt_ref_used_in_all(Lbls, RefRegs, D, Done, Regs);
+opt_ref_used_1([{label,Lbl}|Is], RefRegs, D, Done, Regs) ->
case gb_sets:is_member(Lbl, Done) of
true -> Done;
- false -> opt_ref_used_1(Is, RefReg, D, Done, Regs)
+ false -> opt_ref_used_1(Is, RefRegs, D, Done, Regs)
end;
opt_ref_used_1([{loop_rec_end,_}|_], _, _, Done, _) ->
Done;
@@ -296,27 +298,25 @@ opt_ref_used_1([_I|_], _RefReg, _D, _Done, _Regs) ->
%% The optimization may be unsafe.
throw(not_used).
-%% is_ref_msg_comparison(Args, RefReg, RegisterSet) -> true|false.
+%% is_ref_msg_comparison(Args, RefRegs, RegisterSet) -> true|false.
%% Return 'true' if Args denotes a comparison between the
%% reference and message or part of the message.
-is_ref_msg_comparison([R,RefReg], RefReg, Regs) ->
- regs_is_member(R, Regs);
-is_ref_msg_comparison([RefReg,R], RefReg, Regs) ->
- regs_is_member(R, Regs);
-is_ref_msg_comparison([_,_], _, _) -> false.
-
-opt_ref_used_in_all([L|Ls], RefReg, D, Done0, Regs) ->
- Done = opt_ref_used_at(L, RefReg, D, Done0, Regs),
- opt_ref_used_in_all(Ls, RefReg, D, Done, Regs);
+is_ref_msg_comparison([R1,R2], RefRegs, Regs) ->
+ (regs_is_member(R2, RefRegs) andalso regs_is_member(R1, Regs)) orelse
+ (regs_is_member(R1, RefRegs) andalso regs_is_member(R2, Regs)).
+
+opt_ref_used_in_all([L|Ls], RefRegs, D, Done0, Regs) ->
+ Done = opt_ref_used_at(L, RefRegs, D, Done0, Regs),
+ opt_ref_used_in_all(Ls, RefRegs, D, Done, Regs);
opt_ref_used_in_all([], _, _, Done, _) -> Done.
-opt_ref_used_at(Fail, RefReg, D, Done0, Regs) ->
+opt_ref_used_at(Fail, RefRegs, D, Done0, Regs) ->
case gb_sets:is_member(Fail, Done0) of
true ->
Done0;
false ->
Is = beam_utils:code_at(Fail, D),
- Done = opt_ref_used_1(Is, RefReg, D, Done0, Regs),
+ Done = opt_ref_used_1(Is, RefRegs, D, Done0, Regs),
gb_sets:add(Fail, Done)
end.
@@ -408,15 +408,3 @@ regs_all_members([], _) -> true.
regs_is_member({x,N}, {Regs,_}) -> Regs band (1 bsl N) =/= 0;
regs_is_member({y,N}, {_,Regs}) -> Regs band (1 bsl N) =/= 0;
regs_is_member(_, _) -> false.
-
-%% regs_to_list(RegisterSet) -> [Register]
-%% Convert the register set to an explicit list of registers.
-regs_to_list({Xregs,Yregs}) ->
- regs_to_list_1(Xregs, 0, x, regs_to_list_1(Yregs, 0, y, [])).
-
-regs_to_list_1(0, _, _, Acc) ->
- Acc;
-regs_to_list_1(Regs, N, Tag, Acc) when (Regs band 1) =:= 1 ->
- regs_to_list_1(Regs bsr 1, N+1, Tag, [{Tag,N}|Acc]);
-regs_to_list_1(Regs, N, Tag, Acc) ->
- regs_to_list_1(Regs bsr 1, N+1, Tag, Acc).
diff --git a/lib/compiler/test/receive_SUITE.erl b/lib/compiler/test/receive_SUITE.erl
index b91f2922fb..e60584d4ab 100644
--- a/lib/compiler/test/receive_SUITE.erl
+++ b/lib/compiler/test/receive_SUITE.erl
@@ -188,7 +188,7 @@ ref_opt(Config) when is_list(Config) ->
ref_opt_1(Config) ->
?line DataDir = ?config(data_dir, Config),
?line PrivDir = ?config(priv_dir, Config),
- ?line Sources = filelib:wildcard(filename:join([DataDir,"ref_opt","*.erl"])),
+ Sources = filelib:wildcard(filename:join([DataDir,"ref_opt","*.{erl,S}"])),
?line test_lib:p_run(fun(Src) ->
do_ref_opt(Src, PrivDir)
end, Sources),
@@ -196,10 +196,15 @@ ref_opt_1(Config) ->
do_ref_opt(Source, PrivDir) ->
try
- {ok,Mod} = c:c(Source, [{outdir,PrivDir}]),
+ Ext = filename:extension(Source),
+ {ok,Mod} = compile:file(Source, [report_errors,report_warnings,
+ {outdir,PrivDir}] ++
+ [from_asm || Ext =:= ".S" ]),
+ Base = filename:rootname(filename:basename(Source), Ext),
+ code:purge(list_to_atom(Base)),
+ BeamFile = filename:join(PrivDir, Base),
+ code:load_abs(BeamFile),
ok = Mod:Mod(),
- Base = filename:rootname(filename:basename(Source), ".erl"),
- BeamFile = filename:join(PrivDir, Base),
{beam_file,Mod,_,_,_,Code} = beam_disasm:file(BeamFile),
case Base of
"no_"++_ ->
diff --git a/lib/compiler/test/receive_SUITE_data/ref_opt/yes_14.S b/lib/compiler/test/receive_SUITE_data/ref_opt/yes_14.S
new file mode 100644
index 0000000000..fd14228135
--- /dev/null
+++ b/lib/compiler/test/receive_SUITE_data/ref_opt/yes_14.S
@@ -0,0 +1,71 @@
+{module, yes_14}. %% version = 0
+
+{exports, [{f,2},{module_info,0},{module_info,1},{yes_14,0}]}.
+
+{attributes, []}.
+
+{labels, 12}.
+
+
+{function, yes_14, 0, 2}.
+ {label,1}.
+ {func_info,{atom,yes_14},{atom,yes_14},0}.
+ {label,2}.
+ {move,{atom,ok},{x,0}}.
+ return.
+
+
+{function, f, 2, 4}.
+ {label,3}.
+ {func_info,{atom,yes_14},{atom,f},2}.
+ {label,4}.
+ {allocate_heap,2,3,2}.
+ {move,{x,0},{y,1}}.
+ {put_tuple,2,{y,0}}.
+ {put,{atom,data}}.
+ {put,{x,1}}.
+ {call_ext,0,{extfunc,erlang,make_ref,0}}. % Ref in [x0]
+ {test_heap,4,1}.
+ {put_tuple,3,{x,1}}.
+ {put,{atom,request}}.
+ {put,{x,0}}.
+ {put,{y,0}}.
+ {move,{x,0},{y,0}}. % Ref in [x0,y0]
+ {move,{y,1},{x,0}}. % Ref in [y0]
+ {kill,{y,1}}.
+ send.
+ {move,{y,0},{x,0}}. % Ref in [x0,y0]
+ {move,{x,0},{y,1}}. % Ref in [x0,y0,y1]
+ {label,5}.
+ {loop_rec,{f,7},{x,0}}. % Ref in [y0,y1]
+ {test,is_tuple,{f,6},[{x,0}]}.
+ {test,test_arity,{f,6},[{x,0},2]}.
+ {get_tuple_element,{x,0},0,{x,1}}.
+ {get_tuple_element,{x,0},1,{x,2}}.
+ {test,is_eq_exact,{f,6},[{x,1},{atom,reply}]}.
+ {test,is_eq_exact,{f,6},[{x,2},{y,1}]}.
+ remove_message.
+ {move,{atom,ok},{x,0}}.
+ {deallocate,2}.
+ return.
+ {label,6}.
+ {loop_rec_end,{f,5}}.
+ {label,7}.
+ {wait,{f,5}}.
+
+
+{function, module_info, 0, 9}.
+ {label,8}.
+ {func_info,{atom,yes_14},{atom,module_info},0}.
+ {label,9}.
+ {move,{atom,yes_14},{x,0}}.
+ {call_ext_only,1,{extfunc,erlang,get_module_info,1}}.
+
+
+{function, module_info, 1, 11}.
+ {label,10}.
+ {func_info,{atom,yes_14},{atom,module_info},1}.
+ {label,11}.
+ {move,{x,0},{x,1}}.
+ {move,{atom,yes_14},{x,0}}.
+ {call_ext_only,2,{extfunc,erlang,get_module_info,2}}.
diff --git a/lib/crypto/doc/src/crypto.xml b/lib/crypto/doc/src/crypto.xml
index 29fc885152..7eca4557d9 100755
--- a/lib/crypto/doc/src/crypto.xml
+++ b/lib/crypto/doc/src/crypto.xml
@@ -1354,7 +1354,7 @@ Mpint() = <![CDATA[<<ByteLen:32/integer-big, Bytes:ByteLen/binary>>]]>
<p>
Computes the SRP session key (shared secret) for the client side (first argument is DerivedKey)
or for the server side (first argument is Verifier). Also used
- as premaster secret by TLS-SRP ciher suites.
+ as premaster secret by TLS-SRP cipher suites.
</p>
</desc>
</func>
diff --git a/lib/dialyzer/src/dialyzer_gui.erl b/lib/dialyzer/src/dialyzer_gui.erl
index ac9844c22c..97e5752577 100644
--- a/lib/dialyzer/src/dialyzer_gui.erl
+++ b/lib/dialyzer/src/dialyzer_gui.erl
@@ -2,7 +2,7 @@
%%------------------------------------------------------------------------
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2006-2012. All Rights Reserved.
+%% Copyright Ericsson AB 2006-2013. 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
@@ -1331,7 +1331,8 @@ build_analysis_record(#gui_state{mode = Mode, menu = Menu, options = Options,
#analysis{defines = Options#options.defines,
include_dirs = Options#options.include_dirs,
plt = InitPlt,
- start_from = StartFrom}.
+ start_from = StartFrom,
+ solvers = Options#options.solvers}.
get_anal_files(#gui_state{chosen_box = ChosenBox}, StartFrom) ->
Files = gs:read(ChosenBox, items),
diff --git a/lib/dialyzer/src/dialyzer_gui_wx.erl b/lib/dialyzer/src/dialyzer_gui_wx.erl
index c6f7c56227..08f31c1e13 100644
--- a/lib/dialyzer/src/dialyzer_gui_wx.erl
+++ b/lib/dialyzer/src/dialyzer_gui_wx.erl
@@ -2,7 +2,7 @@
%%------------------------------------------------------------------------
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2009-2012. All Rights Reserved.
+%% Copyright Ericsson AB 2009-2013. 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
@@ -810,7 +810,8 @@ build_analysis_record(#gui_state{mode = Mode, menu = Menu, options = Options,
#analysis{defines = Options#options.defines,
include_dirs = Options#options.include_dirs,
plt = InitPlt,
- start_from = StartFrom}.
+ start_from = StartFrom,
+ solvers = Options#options.solvers}.
get_anal_files(#gui_state{files_to_analyze = Files}, StartFrom) ->
FilteredMods =
diff --git a/lib/et/doc/src/et_desc.xmlsrc b/lib/et/doc/src/et_desc.xmlsrc
index c02517ae01..36274f6316 100644
--- a/lib/et/doc/src/et_desc.xmlsrc
+++ b/lib/et/doc/src/et_desc.xmlsrc
@@ -150,7 +150,7 @@
NewEvent = #event{}]]></code>
<p>The interface of the filter function is the same as the the
- filter functions for the good old <c>lists:zf/2</c>. If the filter
+ filter functions for the good old <c>lists:filtermap/2</c>. If the filter
returns <c>false</c> it means that the trace data should silently
be dropped. <c>true</c> means that the trace data data already is
an <c>Event Record</c> and that it should be kept as it is.
diff --git a/lib/jinterface/test/jinterface_SUITE.erl b/lib/jinterface/test/jinterface_SUITE.erl
index b438da12d0..de8d611efc 100644
--- a/lib/jinterface/test/jinterface_SUITE.erl
+++ b/lib/jinterface/test/jinterface_SUITE.erl
@@ -180,7 +180,7 @@ init_per_testcase(Case, _Config)
Case =:= kill_mbox_from_erlang ->
{skip, "Not yet implemented"};
init_per_testcase(_Case,Config) ->
- Dog = ?t:timetrap({seconds,10}),
+ Dog = ?t:timetrap({seconds,30}),
[{watch_dog,Dog}|Config].
end_per_testcase(_Case,Config) ->
@@ -188,6 +188,7 @@ end_per_testcase(_Case,Config) ->
undefined -> ok;
Pid -> exit(Pid,kill)
end,
+ jitu:kill_all_jnodes(),
?t:timetrap_cancel(?config(watch_dog,Config)),
ok.
diff --git a/lib/jinterface/test/jitu.erl b/lib/jinterface/test/jitu.erl
index 0e1af0ff22..a029c063bc 100644
--- a/lib/jinterface/test/jitu.erl
+++ b/lib/jinterface/test/jitu.erl
@@ -27,7 +27,10 @@
java/4,
java/5,
init_all/1,
- finish_all/1]).
+ finish_all/1,
+ kill_all_jnodes/0]).
+
+-include("ct.hrl").
%%
%% Lots of stuff here are originating from java_client_erl_server_SUITE.erl
@@ -51,10 +54,33 @@ java(Java, Dir, Class, Args, Props) ->
init_all(Config) when is_list(Config) ->
case find_executable(["java"]) of
false -> {skip,"Found no Java VM"};
- Path -> [{java,Path}|Config]
+ Path ->
+ Pid = spawn(fun() ->
+ ets:new(jitu_tab,[set,named_table,public]),
+ receive stop -> ets:delete(jitu_tab) end
+ end),
+ [{java,Path},{tab_proc,Pid}|Config]
end.
-finish_all(Config) -> Config.
+finish_all(Config) ->
+ kill_all_jnodes(),
+ ?config(tab_proc,Config) ! stop,
+ Config.
+
+kill_all_jnodes() ->
+ Jnodes = ets:tab2list(jitu_tab),
+ [begin
+% ct:pal("Killing OsPid=~w started with ~p",[OsPid,_Cmd]),
+ kill_os_process(os:type(),integer_to_list(OsPid))
+ end || {OsPid,_Cmd} <- Jnodes],
+ ets:delete_all_objects(jitu_tab),
+ ok.
+
+kill_os_process({win32,_},OsPid) ->
+ os:cmd("taskkill /PID " ++ OsPid);
+kill_os_process(_,OsPid) ->
+ os:cmd("kill " ++ OsPid).
+
%%
%% Internal stuff...
@@ -110,6 +136,12 @@ cmd(Cmd) ->
io:format("cmd: ~s~n", [Cmd]),
case catch open_port({spawn,Cmd}, PortOpts) of
Port when is_port(Port) ->
+ case erlang:port_info(Port,os_pid) of
+ {os_pid,OsPid} ->
+ ets:insert(jitu_tab,{OsPid,Cmd});
+ _ ->
+ ok
+ end,
Result = cmd_loop(Port, []),
io:format("cmd res: ~w~n", [Result]),
case Result of
diff --git a/lib/jinterface/test/nc_SUITE.erl b/lib/jinterface/test/nc_SUITE.erl
index 63c78ebdaa..f1493a3cc9 100644
--- a/lib/jinterface/test/nc_SUITE.erl
+++ b/lib/jinterface/test/nc_SUITE.erl
@@ -105,12 +105,13 @@ end_per_suite(Config) ->
init_per_testcase(Case, Config) ->
T = case atom_to_list(Case) of
"unicode"++_ -> 240;
- _ -> 30
+ _ -> 120
end,
WatchDog = test_server:timetrap(test_server:seconds(T)),
[{watchdog, WatchDog}| Config].
end_per_testcase(_Case, Config) ->
+ jitu:kill_all_jnodes(),
WatchDog = ?config(watchdog, Config),
test_server:timetrap_cancel(WatchDog).
@@ -695,15 +696,18 @@ run_server(Server, Config, Action, ExtraArgs) ->
true = register(Name, self()),
JName = make_name(),
spawn_link(fun () ->
+ %% Setting max memory to 256. This is due to
+ %% echo_server sometimes failing with
+ %% OutOfMemoryException one some test machines.
ok = jitu:java(?config(java, Config),
?config(data_dir, Config),
atom_to_list(Server),
[JName,
erlang:get_cookie(),
node(),
- Name]++ExtraArgs
- ),
- %,"-DOtpConnection.trace=3"),
+ Name]++ExtraArgs,
+ " -Xmx256m"),
+ %% " -Xmx256m -DOtpConnection.trace=3"),
Name ! {done, JName}
end),
receive
diff --git a/lib/ssl/src/ssl_connection.erl b/lib/ssl/src/ssl_connection.erl
index 1843377582..fa64915fd0 100644
--- a/lib/ssl/src/ssl_connection.erl
+++ b/lib/ssl/src/ssl_connection.erl
@@ -1547,7 +1547,7 @@ server_hello_done(#state{transport_cb = Transport,
tls_handshake_history = Handshake}.
certify_server(#state{key_algorithm = Algo} = State)
- when Algo == dh_anon; Algo == psk; Algo == dhe_psk ->
+ when Algo == dh_anon; Algo == psk; Algo == dhe_psk; Algo == srp_anon ->
State;
certify_server(#state{transport_cb = Transport,
diff --git a/lib/ssl/test/ssl_basic_SUITE.erl b/lib/ssl/test/ssl_basic_SUITE.erl
index 5cedde5d27..10bbd4d88b 100644
--- a/lib/ssl/test/ssl_basic_SUITE.erl
+++ b/lib/ssl/test/ssl_basic_SUITE.erl
@@ -156,7 +156,10 @@ cipher_tests() ->
anonymous_cipher_suites,
psk_cipher_suites,
psk_with_hint_cipher_suites,
+ psk_anon_cipher_suites,
+ psk_anon_with_hint_cipher_suites,
srp_cipher_suites,
+ srp_anon_cipher_suites,
srp_dsa_cipher_suites,
default_reject_anonymous].
@@ -1594,6 +1597,20 @@ psk_with_hint_cipher_suites(Config) when is_list(Config) ->
Ciphers = ssl_test_lib:psk_suites(),
run_suites(Ciphers, Version, Config, psk_with_hint).
%%-------------------------------------------------------------------
+psk_anon_cipher_suites() ->
+ [{doc, "Test the anonymous PSK ciphersuites WITHOUT server supplied identity hint"}].
+psk_anon_cipher_suites(Config) when is_list(Config) ->
+ Version = ssl_record:protocol_version(ssl_record:highest_protocol_version([])),
+ Ciphers = ssl_test_lib:psk_anon_suites(),
+ run_suites(Ciphers, Version, Config, psk_anon).
+%%-------------------------------------------------------------------
+psk_anon_with_hint_cipher_suites()->
+ [{doc, "Test the anonymous PSK ciphersuites WITH server supplied identity hint"}].
+psk_anon_with_hint_cipher_suites(Config) when is_list(Config) ->
+ Version = ssl_record:protocol_version(ssl_record:highest_protocol_version([])),
+ Ciphers = ssl_test_lib:psk_anon_suites(),
+ run_suites(Ciphers, Version, Config, psk_anon_with_hint).
+%%-------------------------------------------------------------------
srp_cipher_suites()->
[{doc, "Test the SRP ciphersuites"}].
srp_cipher_suites(Config) when is_list(Config) ->
@@ -1601,6 +1618,13 @@ srp_cipher_suites(Config) when is_list(Config) ->
Ciphers = ssl_test_lib:srp_suites(),
run_suites(Ciphers, Version, Config, srp).
%%-------------------------------------------------------------------
+srp_anon_cipher_suites()->
+ [{doc, "Test the anonymous SRP ciphersuites"}].
+srp_anon_cipher_suites(Config) when is_list(Config) ->
+ Version = ssl_record:protocol_version(ssl_record:highest_protocol_version([])),
+ Ciphers = ssl_test_lib:srp_anon_suites(),
+ run_suites(Ciphers, Version, Config, srp_anon).
+%%-------------------------------------------------------------------
srp_dsa_cipher_suites()->
[{doc, "Test the SRP DSA ciphersuites"}].
srp_dsa_cipher_suites(Config) when is_list(Config) ->
@@ -3151,9 +3175,18 @@ run_suites(Ciphers, Version, Config, Type) ->
psk_with_hint ->
{?config(client_psk, Config),
?config(server_psk_hint, Config)};
+ psk_anon ->
+ {?config(client_psk, Config),
+ ?config(server_psk_anon, Config)};
+ psk_anon_with_hint ->
+ {?config(client_psk, Config),
+ ?config(server_psk_anon_hint, Config)};
srp ->
{?config(client_srp, Config),
?config(server_srp, Config)};
+ srp_anon ->
+ {?config(client_srp, Config),
+ ?config(server_srp_anon, Config)};
srp_dsa ->
{?config(client_srp_dsa, Config),
?config(server_srp_dsa, Config)}
diff --git a/lib/ssl/test/ssl_test_lib.erl b/lib/ssl/test/ssl_test_lib.erl
index d655d7659e..e4fedcd118 100644
--- a/lib/ssl/test/ssl_test_lib.erl
+++ b/lib/ssl/test/ssl_test_lib.erl
@@ -339,12 +339,22 @@ cert_options(Config) ->
{psk_identity, "HINT"},
{user_lookup_fun, {fun user_lookup/3, PskSharedSecret}},
{ciphers, psk_suites()}]},
+ {server_psk_anon, [{ssl_imp, new},{reuseaddr, true},
+ {user_lookup_fun, {fun user_lookup/3, PskSharedSecret}},
+ {ciphers, psk_anon_suites()}]},
+ {server_psk_anon_hint, [{ssl_imp, new},{reuseaddr, true},
+ {psk_identity, "HINT"},
+ {user_lookup_fun, {fun user_lookup/3, PskSharedSecret}},
+ {ciphers, psk_anon_suites()}]},
{client_srp, [{ssl_imp, new},{reuseaddr, true},
{srp_identity, {"Test-User", "secret"}}]},
{server_srp, [{ssl_imp, new},{reuseaddr, true},
{certfile, ServerCertFile}, {keyfile, ServerKeyFile},
{user_lookup_fun, {fun user_lookup/3, undefined}},
{ciphers, srp_suites()}]},
+ {server_srp_anon, [{ssl_imp, new},{reuseaddr, true},
+ {user_lookup_fun, {fun user_lookup/3, undefined}},
+ {ciphers, srp_anon_suites()}]},
{server_verification_opts, [{ssl_imp, new},{reuseaddr, true},
{cacertfile, ServerCaCertFile},
{certfile, ServerCertFile}, {keyfile, ServerKeyFile}]},
@@ -711,6 +721,12 @@ anonymous_suites() ->
{dh_anon, aes_256_cbc, sha}].
psk_suites() ->
+ [{rsa_psk, rc4_128, sha},
+ {rsa_psk, '3des_ede_cbc', sha},
+ {rsa_psk, aes_128_cbc, sha},
+ {rsa_psk, aes_256_cbc, sha}].
+
+psk_anon_suites() ->
[{psk, rc4_128, sha},
{psk, '3des_ede_cbc', sha},
{psk, aes_128_cbc, sha},
@@ -718,20 +734,18 @@ psk_suites() ->
{dhe_psk, rc4_128, sha},
{dhe_psk, '3des_ede_cbc', sha},
{dhe_psk, aes_128_cbc, sha},
- {dhe_psk, aes_256_cbc, sha},
- {rsa_psk, rc4_128, sha},
- {rsa_psk, '3des_ede_cbc', sha},
- {rsa_psk, aes_128_cbc, sha},
- {rsa_psk, aes_256_cbc, sha}].
+ {dhe_psk, aes_256_cbc, sha}].
srp_suites() ->
- [{srp_anon, '3des_ede_cbc', sha},
- {srp_rsa, '3des_ede_cbc', sha},
- {srp_anon, aes_128_cbc, sha},
+ [{srp_rsa, '3des_ede_cbc', sha},
{srp_rsa, aes_128_cbc, sha},
- {srp_anon, aes_256_cbc, sha},
{srp_rsa, aes_256_cbc, sha}].
+srp_anon_suites() ->
+ [{srp_anon, '3des_ede_cbc', sha},
+ {srp_anon, aes_128_cbc, sha},
+ {srp_anon, aes_256_cbc, sha}].
+
srp_dss_suites() ->
[{srp_dss, '3des_ede_cbc', sha},
{srp_dss, aes_128_cbc, sha},
diff --git a/lib/stdlib/doc/src/lists.xml b/lib/stdlib/doc/src/lists.xml
index b6c0fa4e05..1aff78f4fc 100644
--- a/lib/stdlib/doc/src/lists.xml
+++ b/lib/stdlib/doc/src/lists.xml
@@ -152,6 +152,31 @@
</desc>
</func>
<func>
+ <name name="filtermap" arity="2"/>
+ <fsummary>Filter and map elements which satisfy a function</fsummary>
+ <desc>
+ <p>Calls <c><anno>Fun</anno>(<anno>Elem</anno>)</c> on successive elements <c>Elem</c>
+ of <c><anno>List1</anno></c>. <c><anno>Fun</anno>/2</c> must return either a boolean
+ or a tuple <c>{true, <anno>Value</anno>}</c>. The function returns the list of elements
+ for which <c><anno>Fun</anno></c> returns a new value, where a value of <c>true</c>
+ is synonymous with <c>{true, <anno>Elem</anno>}</c>.</p>
+ <p>That is, <c>filtermap</c> behaves as if it had been defined as follows:</p>
+ <code type="none">
+filtermap(Fun, List1) ->
+ lists:foldr(fun(Elem, Acc) ->
+ case Fun(Elem) of
+ false -> Acc;
+ true -> [Elem|Acc];
+ {true,Value} -> [Value|Acc]
+ end,
+ end, [], List1).</code>
+ <p>Example:</p>
+ <pre>
+> <input>lists:filtermap(fun(X) -> case X rem 2 of 0 -> {true, X div 2}; _ -> false end end, [1,2,3,4,5]).</input>
+[1,2]</pre>
+ </desc>
+ </func>
+ <func>
<name name="flatlength" arity="1"/>
<fsummary>Length of flattened deep list</fsummary>
<desc>
diff --git a/lib/stdlib/src/epp.erl b/lib/stdlib/src/epp.erl
index e31cd63f69..d1d060ebc8 100644
--- a/lib/stdlib/src/epp.erl
+++ b/lib/stdlib/src/epp.erl
@@ -601,7 +601,7 @@ enter_file2(NewF, Pname, From, St0, AtLocation) ->
%% file will depend on the order of file inclusions in the parent files
Path = [filename:dirname(Pname) | tl(St0#epp.path)],
_ = set_encoding(NewF),
- #epp{file=NewF,location=Loc,name=Pname,delta=0,
+ #epp{file=NewF,location=Loc,name=Pname,name2=Pname,delta=0,
sstk=[St0|St0#epp.sstk],path=Path,macs=Ms}.
enter_file_reply(From, Name, Location, AtLocation) ->
diff --git a/lib/stdlib/src/lists.erl b/lib/stdlib/src/lists.erl
index 961c060019..0c033acd88 100644
--- a/lib/stdlib/src/lists.erl
+++ b/lib/stdlib/src/lists.erl
@@ -36,7 +36,7 @@
-export([merge/3, rmerge/3, sort/2, umerge/3, rumerge/3, usort/2]).
-export([all/2,any/2,map/2,flatmap/2,foldl/3,foldr/3,filter/2,
- partition/2,zf/2,
+ partition/2,zf/2,filtermap/2,
mapfoldl/3,mapfoldr/3,foreach/2,takewhile/2,dropwhile/2,splitwith/2,
split/2]).
@@ -1291,18 +1291,28 @@ partition(Pred, [H | T], As, Bs) ->
partition(Pred, [], As, Bs) when is_function(Pred, 1) ->
{reverse(As), reverse(Bs)}.
--spec zf(fun((T) -> boolean() | {'true', X}), [T]) -> [(T | X)].
+-spec filtermap(Fun, List1) -> List2 when
+ Fun :: fun((Elem) -> boolean() | {'true', Value}),
+ List1 :: [Elem],
+ List2 :: [Elem | Value],
+ Elem :: term(),
+ Value :: term().
-zf(F, [Hd|Tail]) ->
+filtermap(F, [Hd|Tail]) ->
case F(Hd) of
true ->
- [Hd|zf(F, Tail)];
+ [Hd|filtermap(F, Tail)];
{true,Val} ->
- [Val|zf(F, Tail)];
+ [Val|filtermap(F, Tail)];
false ->
- zf(F, Tail)
+ filtermap(F, Tail)
end;
-zf(F, []) when is_function(F, 1) -> [].
+filtermap(F, []) when is_function(F, 1) -> [].
+
+-spec zf(fun((T) -> boolean() | {'true', X}), [T]) -> [(T | X)].
+
+zf(F, L) ->
+ filtermap(F, L).
-spec foreach(Fun, List) -> ok when
Fun :: fun((Elem :: T) -> term()),
diff --git a/lib/stdlib/test/epp_SUITE.erl b/lib/stdlib/test/epp_SUITE.erl
index b2f1aa955a..0cbdf76270 100644
--- a/lib/stdlib/test/epp_SUITE.erl
+++ b/lib/stdlib/test/epp_SUITE.erl
@@ -104,6 +104,8 @@ include_local(suite) ->
include_local(Config) when is_list(Config) ->
?line DataDir = ?config(data_dir, Config),
?line File = filename:join(DataDir, "include_local.erl"),
+ FooHrl = filename:join([DataDir,"include","foo.hrl"]),
+ BarHrl = filename:join([DataDir,"include","bar.hrl"]),
%% include_local.erl includes include/foo.hrl which
%% includes bar.hrl (also in include/) without requiring
%% any additional include path, and overriding any file
@@ -111,6 +113,8 @@ include_local(Config) when is_list(Config) ->
?line {ok, List} = epp:parse_file(File, [DataDir], []),
?line {value, {attribute,_,a,{true,true}}} =
lists:keysearch(a,3,List),
+ [{File,1},{FooHrl,1},{BarHrl,1},{FooHrl,5},{File,5}] =
+ [ FileLine || {attribute,_,file,FileLine} <- List ],
ok.
%%% Here is a little reimplementation of epp:parse_file, which times out
diff --git a/lib/stdlib/test/ets_SUITE.erl b/lib/stdlib/test/ets_SUITE.erl
index af5d5a8f21..bd69019892 100644
--- a/lib/stdlib/test/ets_SUITE.erl
+++ b/lib/stdlib/test/ets_SUITE.erl
@@ -75,6 +75,7 @@
-export([otp_9932/1]).
-export([otp_9423/1]).
-export([otp_10182/1]).
+-export([memory_check_summary/1]).
-export([init_per_testcase/2, end_per_testcase/2]).
%% Convenience for manual testing
@@ -149,7 +150,9 @@ all() ->
give_away, setopts, bad_table, types,
otp_10182,
otp_9932,
- otp_9423].
+ otp_9423,
+
+ memory_check_summary]. % MUST BE LAST
groups() ->
[{new, [],
@@ -185,7 +188,8 @@ init_per_suite(Config) ->
end_per_suite(_Config) ->
stop_spawn_logger(),
- catch erts_debug:set_internal_state(available_internal_state, false).
+ catch erts_debug:set_internal_state(available_internal_state, false),
+ ok.
init_per_group(_GroupName, Config) ->
Config.
@@ -193,6 +197,26 @@ init_per_group(_GroupName, Config) ->
end_per_group(_GroupName, Config) ->
Config.
+%% Test that we did not have "too many" failed verify_etsmem()'s
+%% in the test suite.
+%% verify_etsmem() may give a low number of false positives
+%% as concurrent activities, such as lingering processes
+%% from earlier test suites, may do unrelated ets (de)allocations.
+memory_check_summary(_Config) ->
+ case whereis(ets_test_spawn_logger) of
+ undefined ->
+ ?t:fail("No spawn logger exist");
+ _ ->
+ ets_test_spawn_logger ! {self(), get_failed_memchecks},
+ receive {get_failed_memchecks, FailedMemchecks} -> ok end,
+ io:format("Failed memchecks: ~p\n",[FailedMemchecks]),
+ if FailedMemchecks > 3 ->
+ ct:fail("Too many failed (~p) memchecks", [FailedMemchecks]);
+ true ->
+ ok
+ end
+ end.
+
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -5635,7 +5659,8 @@ verify_etsmem({MemInfo,AllTabs}) ->
io:format("Actual: ~p", [MemInfo2]),
io:format("Changed tables before: ~p\n",[AllTabs -- AllTabs2]),
io:format("Changed tables after: ~p\n", [AllTabs2 -- AllTabs]),
- ?t:fail()
+ ets_test_spawn_logger ! failed_memcheck,
+ {comment, "Failed memory check"}
end.
@@ -5657,10 +5682,10 @@ stop_loopers(Loopers) ->
looper(Fun, State) ->
looper(Fun, Fun(State)).
-spawn_logger(Procs) ->
+spawn_logger(Procs, FailedMemchecks) ->
receive
{new_test_proc, Proc} ->
- spawn_logger([Proc|Procs]);
+ spawn_logger([Proc|Procs], FailedMemchecks);
{sync_test_procs, Kill, From} ->
lists:foreach(fun (Proc) when From == Proc ->
ok;
@@ -5683,7 +5708,14 @@ spawn_logger(Procs) ->
end
end, Procs),
From ! test_procs_synced,
- spawn_logger([From])
+ spawn_logger([From], FailedMemchecks);
+
+ failed_memcheck ->
+ spawn_logger(Procs, FailedMemchecks+1);
+
+ {Pid, get_failed_memchecks} ->
+ Pid ! {get_failed_memchecks, FailedMemchecks},
+ spawn_logger(Procs, FailedMemchecks)
end.
pid_status(Pid) ->
@@ -5699,7 +5731,7 @@ start_spawn_logger() ->
case whereis(ets_test_spawn_logger) of
Pid when is_pid(Pid) -> true;
_ -> register(ets_test_spawn_logger,
- spawn_opt(fun () -> spawn_logger([]) end,
+ spawn_opt(fun () -> spawn_logger([], 0) end,
[{priority, max}]))
end.
@@ -5710,8 +5742,7 @@ start_spawn_logger() ->
stop_spawn_logger() ->
Mon = erlang:monitor(process, ets_test_spawn_logger),
(catch exit(whereis(ets_test_spawn_logger), kill)),
- receive {'DOWN', Mon, _, _, _} -> ok end,
- ok.
+ receive {'DOWN', Mon, _, _, _} -> ok end.
wait_for_test_procs() ->
wait_for_test_procs(false).
@@ -5811,7 +5842,7 @@ spawn_monitor_with_pid(Pid, Fun, N) ->
end) of
Pid ->
{Pid, erlang:monitor(process, Pid)};
- Other ->
+ _Other ->
spawn_monitor_with_pid(Pid,Fun,N-1)
end.
@@ -6117,11 +6148,18 @@ repeat_for_opts(F, OptGenList) ->
repeat_for_opts(F, OptGenList, []).
repeat_for_opts(F, [], Acc) ->
- lists:map(fun(Opts) ->
- OptList = lists:filter(fun(E) -> E =/= void end, Opts),
- io:format("Calling with options ~p\n",[OptList]),
- F(OptList)
- end, Acc);
+ lists:foldl(fun(Opts, RV_Acc) ->
+ OptList = lists:filter(fun(E) -> E =/= void end, Opts),
+ io:format("Calling with options ~p\n",[OptList]),
+ RV = F(OptList),
+ case RV_Acc of
+ {comment,_} -> RV_Acc;
+ _ -> case RV of
+ {comment,_} -> RV;
+ _ -> [RV | RV_Acc]
+ end
+ end
+ end, [], Acc);
repeat_for_opts(F, [OptList | Tail], []) when is_list(OptList) ->
repeat_for_opts(F, Tail, [[Opt] || Opt <- OptList]);
repeat_for_opts(F, [OptList | Tail], AccList) when is_list(OptList) ->
diff --git a/lib/stdlib/test/lists_SUITE.erl b/lib/stdlib/test/lists_SUITE.erl
index b56f0b39d8..cd7210f8ec 100644
--- a/lib/stdlib/test/lists_SUITE.erl
+++ b/lib/stdlib/test/lists_SUITE.erl
@@ -2532,8 +2532,8 @@ otp_5939(Config) when is_list(Config) ->
?line [] = lists:filter(Pred, []),
?line {'EXIT', _} = (catch lists:partition(func, [])),
?line {[],[]} = lists:partition(Pred, []),
- ?line {'EXIT', _} = (catch lists:zf(func, [])),
- ?line [] = lists:zf(Fun1, []),
+ ?line {'EXIT', _} = (catch lists:filtermap(func, [])),
+ ?line [] = lists:filtermap(Fun1, []),
?line {'EXIT', _} = (catch lists:foreach(func, [])),
?line ok = lists:foreach(Fun1, []),
?line {'EXIT', _} = (catch lists:mapfoldl(func, [], [])),
diff --git a/lib/test_server/src/test_server_ctrl.erl b/lib/test_server/src/test_server_ctrl.erl
index 21c10adccb..ffa21d054c 100644
--- a/lib/test_server/src/test_server_ctrl.erl
+++ b/lib/test_server/src/test_server_ctrl.erl
@@ -1183,7 +1183,7 @@ init_tester(Mod, Func, Args, Dir, Name, {_,_,MinLev}=Levels,
"<td>~.3fs</td><td><b>~ts</b></td><td>~w Ok, ~w Failed~ts of ~w</td></tr>\n"
"</tfoot>\n",
[Time,SuccessStr,OkN,FailedN,SkipStr,OkN+FailedN+SkippedN]),
- test_server_io:stop().
+ test_server_io:stop([major,html,unexpected_io]).
report_severe_error(Reason) ->
test_server_sup:framework_call(report, [severe_error,Reason]).
@@ -1588,7 +1588,7 @@ do_test_cases(TopCases, SkipCases,
print(major, "=started ~s",
[lists:flatten(timestamp_get(""))]),
- put(test_server_html_footer, Footer),
+ test_server_io:set_footer(Footer),
run_test_cases(TestSpec, Config, TimetrapData)
end;
diff --git a/lib/test_server/src/test_server_io.erl b/lib/test_server/src/test_server_io.erl
index a979deffc3..73d4468bda 100644
--- a/lib/test_server/src/test_server_io.erl
+++ b/lib/test_server/src/test_server_io.erl
@@ -29,7 +29,7 @@
%%
-module(test_server_io).
--export([start_link/0,stop/0,get_gl/1,set_fd/2,
+-export([start_link/0,stop/1,get_gl/1,set_fd/2,
start_transaction/0,end_transaction/0,
print_buffered/1,print/3,print_unexpected/1,
set_footer/1,set_job_name/1,set_gl_props/1]).
@@ -55,10 +55,10 @@ start_link() ->
Other
end.
-stop() ->
+stop(FilesToClose) ->
OldGL = group_leader(),
group_leader(self(), self()),
- req(stop),
+ req({stop,FilesToClose}),
group_leader(OldGL, self()),
ok.
@@ -213,12 +213,21 @@ handle_call({set_job_name,Name}, _From, St) ->
handle_call({set_gl_props,Props}, _From, #st{shared_gl=Shared}=St) ->
test_server_gl:set_props(Shared, Props),
{reply,ok,St#st{gl_props=Props}};
-handle_call(stop, From, #st{shared_gl=SGL,gls=Gls0}=St0) ->
+handle_call({stop,FdTags}, From, #st{fds=Fds,shared_gl=SGL,gls=Gls0}=St0) ->
St = St0#st{gls=gb_sets:insert(SGL, Gls0),stopping=From},
gc(St),
%% Give the users of the surviving group leaders some
%% time to finish.
erlang:send_after(2000, self(), stop_group_leaders),
+ %% close open log files
+ lists:foreach(fun(Tag) ->
+ case gb_trees:lookup(Tag, Fds) of
+ none ->
+ ok;
+ {value,Fd} ->
+ file:close(Fd)
+ end
+ end, FdTags),
{noreply,St}.
handle_info({'EXIT',Pid,normal}, #st{gls=Gls0,stopping=From}=St) ->