aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--erts/emulator/beam/beam_load.c7
-rw-r--r--erts/emulator/beam/erl_map.c14
-rw-r--r--erts/emulator/beam/ops.tab2
-rw-r--r--erts/emulator/test/beam_SUITE.erl45
-rw-r--r--lib/asn1/test/asn1_SUITE.erl4
-rw-r--r--lib/asn1/test/asn1_test_lib.erl13
-rw-r--r--lib/kernel/src/dist_util.erl26
-rw-r--r--lib/kernel/test/code_SUITE.erl3
-rw-r--r--lib/kernel/test/file_SUITE.erl5
-rw-r--r--lib/kernel/test/file_name_SUITE.erl325
-rw-r--r--lib/kernel/test/gen_sctp_SUITE.erl39
-rw-r--r--lib/kernel/test/gen_tcp_misc_SUITE.erl250
-rw-r--r--lib/kernel/test/heart_SUITE.erl31
-rw-r--r--lib/kernel/test/inet_SUITE.erl24
-rw-r--r--lib/kernel/test/init_SUITE.erl3
-rw-r--r--lib/stdlib/src/otp_internal.erl108
-rw-r--r--lib/stdlib/test/gen_fsm_SUITE.erl10
-rw-r--r--lib/wx/api_gen/wx_gen_erl.erl2
-rw-r--r--lib/wx/api_gen/wxapi.conf2
-rw-r--r--lib/wx/c_src/gen/wxe_funcs.cpp8
-rw-r--r--lib/wx/include/wx.hrl2
-rw-r--r--lib/wx/src/gen/wxListCtrl.erl13
-rw-r--r--lib/wx/src/gen/wxe_debug.hrl2
-rw-r--r--system/doc/design_principles/spec_proc.xml33
24 files changed, 477 insertions, 494 deletions
diff --git a/erts/emulator/beam/beam_load.c b/erts/emulator/beam/beam_load.c
index d3d278fb81..16cbdbffea 100644
--- a/erts/emulator/beam/beam_load.c
+++ b/erts/emulator/beam/beam_load.c
@@ -2735,6 +2735,13 @@ same_label(LoaderState* stp, GenOpArg Target, GenOpArg Label)
}
static int
+is_killed_apply(LoaderState* stp, GenOpArg Reg, GenOpArg Live)
+{
+ return Reg.type == TAG_x && Live.type == TAG_u &&
+ Live.val+2 <= Reg.val;
+}
+
+static int
is_killed(LoaderState* stp, GenOpArg Reg, GenOpArg Live)
{
return Reg.type == TAG_x && Live.type == TAG_u &&
diff --git a/erts/emulator/beam/erl_map.c b/erts/emulator/beam/erl_map.c
index 4b6931f848..6b747256e1 100644
--- a/erts/emulator/beam/erl_map.c
+++ b/erts/emulator/beam/erl_map.c
@@ -196,13 +196,13 @@ erts_maps_get(Eterm key, Eterm map)
return &vs[i];
}
}
- }
-
- for (i = 0; i < n; i++) {
- if (EQ(ks[i], key)) {
- return &vs[i];
- }
- }
+ } else {
+ for (i = 0; i < n; i++) {
+ if (EQ(ks[i], key)) {
+ return &vs[i];
+ }
+ }
+ }
return NULL;
}
ASSERT(is_hashmap(map));
diff --git a/erts/emulator/beam/ops.tab b/erts/emulator/beam/ops.tab
index 9e53b4bfcc..772460c177 100644
--- a/erts/emulator/beam/ops.tab
+++ b/erts/emulator/beam/ops.tab
@@ -303,7 +303,7 @@ move_window5 x x x x x y
# Swap registers.
move R1=x Tmp=x | move R2=xy R1 | move Tmp R2 => swap_temp R1 R2 Tmp
-swap_temp R1 R2 Tmp | line Loc | apply Live | is_killed(Tmp, Live) => \
+swap_temp R1 R2 Tmp | line Loc | apply Live | is_killed_apply(Tmp, Live) => \
swap R1 R2 | line Loc | apply Live
swap_temp R1 R2 Tmp | line Loc | call Live Addr | is_killed(Tmp, Live) => \
diff --git a/erts/emulator/test/beam_SUITE.erl b/erts/emulator/test/beam_SUITE.erl
index 07dfeb6633..f61ab431e9 100644
--- a/erts/emulator/test/beam_SUITE.erl
+++ b/erts/emulator/test/beam_SUITE.erl
@@ -24,9 +24,9 @@
init_per_group/2,end_per_group/2,
packed_registers/1, apply_last/1, apply_last_bif/1,
buildo_mucho/1, heap_sizes/1, big_lists/1, fconv/1,
- select_val/1]).
+ select_val/1, swap_temp_apply/1]).
--export([applied/2]).
+-export([applied/2,swap_temp_applied/1]).
-include_lib("common_test/include/ct.hrl").
@@ -34,7 +34,8 @@ suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
[packed_registers, apply_last, apply_last_bif,
- buildo_mucho, heap_sizes, big_lists, select_val].
+ buildo_mucho, heap_sizes, big_lists, select_val,
+ swap_temp_apply].
groups() ->
[].
@@ -346,3 +347,41 @@ do_select_val(X) ->
Int when is_integer(Int) ->
integer
end.
+
+swap_temp_apply(_Config) ->
+ {swap_temp_applied,42} = do_swap_temp_apply(41),
+ not_an_integer = do_swap_temp_apply(not_an_integer),
+ ok.
+
+do_swap_temp_apply(Msg) ->
+ case swap_temp_apply_function(Msg) of
+ undefined -> Msg;
+ Type ->
+ %% The following sequence:
+ %% move {x,0} {x,2}
+ %% move {y,0} {x,0}
+ %% move {x,2} {y,0}
+ %% apply 1
+ %%
+ %% Would be incorrectly transformed to:
+ %% swap {x,0} {y,0}
+ %% apply 1
+ %%
+ %% ({x,1} is the module, {x,2} the function to be applied).
+ %%
+ %% If the instructions are to be transformed, the correct
+ %% transformation is:
+ %%
+ %% swap_temp {x,0} {y,0} {x,2}
+ %% apply 1
+ Fields = ?MODULE:Type(Msg),
+ {Type,Fields}
+ end.
+
+swap_temp_apply_function(Int) when is_integer(Int) ->
+ swap_temp_applied;
+swap_temp_apply_function(_) ->
+ undefined.
+
+swap_temp_applied(Int) ->
+ Int+1.
diff --git a/lib/asn1/test/asn1_SUITE.erl b/lib/asn1/test/asn1_SUITE.erl
index 77f78b2716..4d5120221d 100644
--- a/lib/asn1/test/asn1_SUITE.erl
+++ b/lib/asn1/test/asn1_SUITE.erl
@@ -202,7 +202,9 @@ init_per_testcase(Func, Config) ->
[{case_dir, CaseDir}|Config].
end_per_testcase(_Func, Config) ->
- code:del_path(proplists:get_value(case_dir, Config)).
+ CaseDir = proplists:get_value(case_dir, Config),
+ asn1_test_lib:rm_dirs([CaseDir]),
+ code:del_path(CaseDir).
%%------------------------------------------------------------------------------
%% Test runners
diff --git a/lib/asn1/test/asn1_test_lib.erl b/lib/asn1/test/asn1_test_lib.erl
index 21f00b0968..b151546140 100644
--- a/lib/asn1/test/asn1_test_lib.erl
+++ b/lib/asn1/test/asn1_test_lib.erl
@@ -21,6 +21,7 @@
-module(asn1_test_lib).
-export([compile/3,compile_all/3,compile_erlang/3,
+ rm_dirs/1,
hex_to_bin/1,
match_value/2,
parallel/0,
@@ -105,6 +106,18 @@ compile_erlang(Mod, Config, Options) ->
{ok, M} = compile:file(filename:join(DataDir, Mod),
[report,{i,CaseDir},{outdir,CaseDir}|Options]).
+rm_dirs([Dir|Dirs]) ->
+ {ok,L0} = file:list_dir(Dir),
+ L = [filename:join(Dir, F) || F <- L0],
+ IsDir = fun(F) -> filelib:is_dir(F) end,
+ {Subdirs,Files} = lists:partition(IsDir, L),
+ _ = [ok = file:delete(F) || F <- Files],
+ rm_dirs(Subdirs),
+ ok = file:del_dir(Dir),
+ rm_dirs(Dirs);
+rm_dirs([]) ->
+ ok.
+
hex_to_bin(S) ->
<< <<(hex2num(C)):4>> || C <- S, C =/= $\s >>.
diff --git a/lib/kernel/src/dist_util.erl b/lib/kernel/src/dist_util.erl
index c9fc26d62c..e3817fcce5 100644
--- a/lib/kernel/src/dist_util.erl
+++ b/lib/kernel/src/dist_util.erl
@@ -196,7 +196,7 @@ check_dflag_xnc(#hs_data{other_node = Node,
error_msg("** ~w: Connection attempt ~s node ~w ~s "
"since it cannot handle extended ~s. "
"**~n", [node(), Dir, Node, How, What]),
- ?shutdown(Node)
+ ?shutdown2(Node, {check_dflag_xnc_failed, What})
end.
@@ -576,13 +576,13 @@ recv_challenge(#hs_data{socket=Socket,other_node=Node,
[Node, Challenge,Version]),
{Flags,Challenge};
_ ->
- ?shutdown(no_node)
+ ?shutdown2(no_node, {recv_challenge_failed, no_node, Ns})
catch
error:badarg ->
- ?shutdown(no_node)
+ ?shutdown2(no_node, {recv_challenge_failed, no_node, Ns})
end;
- _ ->
- ?shutdown(no_node)
+ Other ->
+ ?shutdown2(no_node, {recv_challenge_failed, Other})
end.
@@ -626,10 +626,10 @@ recv_challenge_ack(#hs_data{socket = Socket, f_recv = FRecv,
_ ->
error_msg("** Connection attempt to "
"disallowed node ~w ** ~n", [NodeB]),
- ?shutdown(NodeB)
+ ?shutdown2(NodeB, {recv_challenge_ack_failed, bad_cookie})
end;
- _ ->
- ?shutdown(NodeB)
+ Other ->
+ ?shutdown2(NodeB, {recv_challenge_ack_failed, Other})
end.
recv_status(#hs_data{kernel_pid = Kernel, socket = Socket,
@@ -639,7 +639,7 @@ recv_status(#hs_data{kernel_pid = Kernel, socket = Socket,
Stat = list_to_atom(StrStat),
?debug({dist_util,self(),recv_status, Node, Stat}),
case Stat of
- not_allowed -> ?shutdown(Node);
+ not_allowed -> ?shutdown2(Node, {recv_status_failed, not_allowed});
nok ->
%% wait to be killed by net_kernel
receive
@@ -656,10 +656,10 @@ recv_status(#hs_data{kernel_pid = Kernel, socket = Socket,
end;
_ -> Stat
end;
- _Error ->
+ Error ->
?debug({dist_util,self(),recv_status_error,
- Node, _Error}),
- ?shutdown(Node)
+ Node, Error}),
+ ?shutdown2(Node, {recv_status_failed, Error})
end.
@@ -758,7 +758,7 @@ setup_timer(Pid, Timeout) ->
setup_timer(Pid, Timeout)
after Timeout ->
?trace("Timer expires ~p, ~p~n",[Pid, Timeout]),
- ?shutdown(timer)
+ ?shutdown2(timer, setup_timer_timeout)
end.
reset_timer(Timer) ->
diff --git a/lib/kernel/test/code_SUITE.erl b/lib/kernel/test/code_SUITE.erl
index abea23e854..1b7672d362 100644
--- a/lib/kernel/test/code_SUITE.erl
+++ b/lib/kernel/test/code_SUITE.erl
@@ -1221,6 +1221,9 @@ on_load_embedded_1(Config) ->
case file:make_symlink(OnLoadApp, LinkName) of
{error,enotsup} ->
throw({skip,"Support for symlinks required"});
+ {error,eperm} ->
+ %% On Windows, we may not have permissions to create symlinks.
+ throw({skip,"Support for symlinks required"});
ok -> ok
end,
diff --git a/lib/kernel/test/file_SUITE.erl b/lib/kernel/test/file_SUITE.erl
index 74db2970af..f0d5b4ac12 100644
--- a/lib/kernel/test/file_SUITE.erl
+++ b/lib/kernel/test/file_SUITE.erl
@@ -83,7 +83,7 @@
-export([unicode/1]).
-export([altname/1]).
--export([large_file/0, large_file/1, large_write/1]).
+-export([large_file/0, large_file/1, large_write/0, large_write/1]).
-export([read_line_1/1, read_line_2/1, read_line_3/1,read_line_4/1]).
@@ -3663,6 +3663,9 @@ do_large_file(Name) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+large_write() ->
+ [{timetrap,{minutes,20}}].
+
large_write(Config) when is_list(Config) ->
run_large_file_test(Config,
fun(Name) -> do_large_write(Name) end,
diff --git a/lib/kernel/test/file_name_SUITE.erl b/lib/kernel/test/file_name_SUITE.erl
index be4ef9c394..dcd2cb28a6 100644
--- a/lib/kernel/test/file_name_SUITE.erl
+++ b/lib/kernel/test/file_name_SUITE.erl
@@ -139,7 +139,12 @@ home_dir(Config) when is_list(Config) ->
test_server:stop_node(Node),
ok
after
- os:putenv(SaveOldName,SaveOldValue),
+ case SaveOldValue of
+ false ->
+ os:unsetenv(SaveOldName);
+ _ ->
+ os:putenv(SaveOldName,SaveOldValue)
+ end,
rm_rf(prim_file,NewHome)
end
catch
@@ -185,9 +190,7 @@ normal(Config) when is_list(Config) ->
try
Priv = proplists:get_value(priv_dir, Config),
file:set_cwd(Priv),
- put(file_module,prim_file),
ok = check_normal(prim_file),
- put(file_module,file),
ok = check_normal(file),
%% If all is good, delete dir again (avoid hanging dir on windows)
rm_rf(file,"normal_dir"),
@@ -207,9 +210,7 @@ icky(Config) when is_list(Config) ->
try
Priv = proplists:get_value(priv_dir, Config),
file:set_cwd(Priv),
- put(file_module,prim_file),
ok = check_icky(prim_file),
- put(file_module,file),
ok = check_icky(file),
%% If all is good, delete dir again (avoid hanging dir on windows)
rm_rf(file,"icky_dir"),
@@ -228,12 +229,10 @@ very_icky(Config) when is_list(Config) ->
try
Priv = proplists:get_value(priv_dir, Config),
file:set_cwd(Priv),
- put(file_module,prim_file),
case check_very_icky(prim_file) of
need_unicode_mode ->
{skipped,"VM needs to be started in Unicode filename mode"};
ok ->
- put(file_module,file),
ok = check_very_icky(file),
%% If all is good, delete dir again
%% (avoid hanging dir on windows)
@@ -249,10 +248,12 @@ very_icky(Config) when is_list(Config) ->
check_normal(Mod) ->
{ok,Dir} = Mod:get_cwd(),
try
- make_normal_dir(Mod),
+ NormalDir = make_normal_dir(Mod, "normal_dir"),
+ io:format("Normaldir = ~p\n", [NormalDir]),
+ L1 = lists:sort(list(NormalDir)),
{ok, L0} = Mod:list_dir("."),
+ io:format("L0 = ~p\n", [L0]),
L1 = lists:sort(L0),
- L1 = lists:sort(list(normal_dir())),
{ok,D2} = Mod:get_cwd(),
true = is_list(D2),
case Mod:altname("fil1") of
@@ -262,45 +263,45 @@ check_normal(Mod) ->
ok
end,
[ true = is_list(El) || El <- L1],
- Syms = [ {S,Targ,list_to_binary(get_data(Targ,normal_dir()))}
- || {T,S,Targ} <- normal_dir(), T =:= symlink ],
+ Syms = [ {S,Targ,list_to_binary(get_data(Targ, NormalDir))}
+ || {T,S,Targ} <- NormalDir, T =:= symlink ],
[ {ok, Cont} = Mod:read_file(SymL) || {SymL,_,Cont} <- Syms ],
[ {ok, Targ} = fixlink(Mod:read_link(SymL)) || {SymL,Targ,_} <- Syms ],
- chk_cre_dir(Mod,[{directory,"temp_dir",normal_dir()}]),
+
{ok,BeginAt} = Mod:get_cwd(),
true = is_list(BeginAt),
+ TempDir = "temp_dir",
+ make_normal_dir(Mod, TempDir),
{error,enoent} = Mod:set_cwd("tmp_dir"),
- ok = Mod:set_cwd("temp_dir"),
{ok, NowAt} = Mod:get_cwd(),
true = BeginAt =/= NowAt,
ok = Mod:set_cwd(".."),
{ok,BeginAt} = Mod:get_cwd(),
- rm_r(Mod,"temp_dir"),
+ rm_r(Mod, TempDir),
true = is_list(Dir),
[ true = is_list(FN) || FN <- L0 ],
- case has_links() of
- true ->
- ok = Mod:make_link("fil1","nisse"),
+ case Mod:make_link("fil1","nisse") of
+ ok ->
{ok, <<"fil1">>} = Mod:read_file("nisse"),
{ok, #file_info{type = regular}} = Mod:read_link_info("nisse"),
ok = Mod:delete("nisse"),
{ok, <<"fil1">>} = Mod:read_file("fil1"),
{error,enoent} = Mod:read_file("nisse"),
{error,enoent} = Mod:read_link_info("nisse");
- false ->
+ {error,enotsup} ->
ok
end,
[ begin
{ok, FD} = Mod:open(Name,[read]),
{ok, Content} = Mod:read(FD,1024),
ok = file:close(FD)
- end || {regular,Name,Content} <- normal_dir() ],
+ end || {regular,Name,Content} <- NormalDir ],
[ begin
{ok, FD} = Mod:open(Name,[read,binary]),
BC = list_to_binary(Content),
{ok, BC} = Mod:read(FD,1024),
ok = file:close(FD)
- end || {regular,Name,Content} <- normal_dir() ],
+ end || {regular,Name,Content} <- NormalDir ],
Mod:rename("fil1","tmp_fil1"),
{ok, <<"fil1">>} = Mod:read_file("tmp_fil1"),
{error,enoent} = Mod:read_file("fil1"),
@@ -333,11 +334,11 @@ check_icky(Mod) ->
try
true=(length("åäö") =:= 3),
UniMode = file:native_name_encoding() =/= latin1,
- make_icky_dir(Mod),
+ IckyDir = make_icky_dir(Mod, "icky_dir"),
{ok, L0} = Mod:list_dir_all("."),
L1 = lists:sort(L0),
- io:format("~p~n~p~n~n",[L1,lists:sort(list(icky_dir()))]),
- L1 = lists:sort(convlist(list(icky_dir()))),
+ io:format("~p~n~p~n~n",[L1,lists:sort(list(IckyDir))]),
+ L1 = lists:sort(convlist(list(IckyDir))),
{ok,D2} = Mod:get_cwd(),
true = is_list(D2),
%% Altname only on windows, and there are no non native filenames there
@@ -348,16 +349,16 @@ check_icky(Mod) ->
%% ok
%% end,
[ true = ((is_list(El) or (UniMode and is_binary(El)))) || El <- L1],
- Syms = [ {S,conv(Targ),list_to_binary(get_data(Targ,icky_dir()))}
- || {T,S,Targ} <- icky_dir(), T =:= symlink ],
+ Syms = [ {S,conv(Targ),list_to_binary(get_data(Targ,IckyDir))}
+ || {T,S,Targ} <- IckyDir, T =:= symlink ],
[ {ok, Cont} = Mod:read_file(SymL) || {SymL,_,Cont} <- Syms ],
[ {ok, Targ} = fixlink(Mod:read_link_all(SymL)) ||
{SymL,Targ,_} <- Syms ],
- chk_cre_dir(Mod,[{directory,"åäö_dir",icky_dir()}]),
+
{ok,BeginAt} = Mod:get_cwd(),
true = is_list(BeginAt),
+ _ = make_icky_dir(Mod, "åäö_dir"),
{error,enoent} = Mod:set_cwd("åä_dir"),
- ok = Mod:set_cwd("åäö_dir"),
{ok, NowAt} = Mod:get_cwd(),
true = is_list(NowAt),
true = BeginAt =/= NowAt,
@@ -365,10 +366,11 @@ check_icky(Mod) ->
{ok,BeginAt} = Mod:get_cwd(),
rm_r2(Mod,"åäö_dir"),
{OS,_} = os:type(),
+
%% Check that treat_icky really converts to the same as the OS
case UniMode of
true ->
- chk_cre_dir(Mod,[{directory,"åäö_dir",[]}]),
+ ok = Mod:make_dir("åäö_dir"),
ok = Mod:set_cwd("åäö_dir"),
ok = Mod:write_file(<<"ååå">>,<<"hello">>),
Treated = treat_icky(<<"ååå">>),
@@ -381,17 +383,17 @@ check_icky(Mod) ->
ok
end,
- chk_cre_dir(Mod,[{directory,treat_icky(<<"åäö_dir">>),icky_dir()}]),
+ _ = make_icky_dir(Mod, treat_icky(<<"åäö_dir">>)),
if
UniMode and (OS =/= win32) ->
{error,enoent} = Mod:set_cwd("åäö_dir");
true ->
ok
end,
+ ok = Mod:set_cwd(".."),
{ok,BeginAt} = Mod:get_cwd(),
- case has_links() of
- true ->
- ok = Mod:make_link("fil1","nisseö"),
+ case Mod:make_link("fil1", "nisseö") of
+ ok ->
{ok, <<"fil1">>} = Mod:read_file("nisseö"),
{ok, #file_info{type = regular}} = Mod:read_link_info("nisseö"),
ok = Mod:delete("nisseö"),
@@ -404,20 +406,20 @@ check_icky(Mod) ->
{error,enoent} = Mod:read_link_info("nisseö"),
{error,enoent} = Mod:read_file(treat_icky(<<"nisseö">>)),
{error,enoent} = Mod:read_link_info(treat_icky(<<"nisseö">>));
- false ->
+ {error,enotsup} ->
ok
end,
[ begin
{ok, FD} = Mod:open(Name,[read]),
{ok, Content} = Mod:read(FD,1024),
ok = file:close(FD)
- end || {regular,Name,Content} <- icky_dir() ],
+ end || {regular,Name,Content} <- IckyDir ],
[ begin
{ok, FD} = Mod:open(Name,[read,binary]),
BC = list_to_binary([Content]),
{ok, BC} = Mod:read(FD,1024),
ok = file:close(FD)
- end || {regular,Name,Content} <- icky_dir() ],
+ end || {regular,Name,Content} <- IckyDir ],
Mod:rename("åäö2","åäö_fil1"),
{ok, <<"åäö2">>} = Mod:read_file("åäö_fil1"),
{error,enoent} = Mod:read_file("åäö2"),
@@ -471,33 +473,33 @@ check_very_icky(Mod) ->
true ->
ok
end,
- make_very_icky_dir(Mod),
- {ok, L0} = Mod:list_dir_all("."),
- L1 = lists:sort(L0),
- L1 = lists:sort(convlist(list(very_icky_dir()))),
+ VeryIckyDir = make_very_icky_dir(Mod, "very_icky_dir"),
+ Expected = lists:sort(convlist(list(VeryIckyDir))),
+ {ok, Actual} = Mod:list_dir_all("."),
+ Expected = lists:sort(Actual),
{ok,D2} = Mod:get_cwd(),
true = is_list(D2),
- [ true = ((is_list(El) or is_binary(El))) || El <- L1],
- Syms = [ {S,conv(Targ),list_to_binary(get_data(Targ,very_icky_dir()))}
- || {T,S,Targ} <- very_icky_dir(), T =:= symlink ],
+ [ true = ((is_list(El) or is_binary(El))) || El <- Expected],
+ Syms = [{S,conv(Targ),list_to_binary(get_data(Targ, VeryIckyDir))}
+ || {symlink,S,Targ} <- VeryIckyDir],
[ {ok, Cont} = Mod:read_file(SymL) || {SymL,_,Cont} <- Syms ],
[ {ok, Targ} = fixlink(Mod:read_link_all(SymL)) ||
{SymL,Targ,_} <- Syms ],
- chk_cre_dir(Mod,[{directory,[1088,1079,1091]++"_dir",very_icky_dir()}]),
+
{ok,BeginAt} = Mod:get_cwd(),
+ OtherDir = [1088,1079,1091] ++ "_dir",
true = is_list(BeginAt),
+ make_very_icky_dir(Mod, OtherDir),
{error,enoent} = Mod:set_cwd("åä_dir"),
- ok = Mod:set_cwd([1088,1079,1091]++"_dir"),
{ok, NowAt} = Mod:get_cwd(),
true = is_list(NowAt),
true = BeginAt =/= NowAt,
ok = Mod:set_cwd(".."),
{ok,BeginAt} = Mod:get_cwd(),
- rm_r2(Mod,[1088,1079,1091]++"_dir"),
+ rm_r2(Mod, OtherDir),
- case has_links() of
- true ->
- ok = Mod:make_link("fil1","nisse"++[1088,1079,1091]),
+ case Mod:make_link("fil1","nisse"++[1088,1079,1091]) of
+ ok ->
{ok, <<"fil1">>} =
Mod:read_file("nisse"++[1088,1079,1091]),
{ok, #file_info{type = regular}} =
@@ -513,20 +515,20 @@ check_very_icky(Mod) ->
{error,enoent} = Mod:read_link_info("nisse"++[1088,1079,1091]),
{error,enoent} = Mod:read_file(<<"nisseö">>),
{error,enoent} = Mod:read_link_info(<<"nisseö">>);
- false ->
+ {error,enotsup} ->
ok
end,
[ begin
{ok, FD} = Mod:open(Name,[read]),
{ok, Content} = Mod:read(FD,1024),
ok = file:close(FD)
- end || {regular,Name,Content} <- very_icky_dir() ],
+ end || {regular,Name,Content} <- VeryIckyDir ],
[ begin
{ok, FD} = Mod:open(Name,[read,binary]),
BC = list_to_binary([Content]),
{ok, BC} = Mod:read(FD,1024),
ok = file:close(FD)
- end || {regular,Name,Content} <- very_icky_dir() ],
+ end || {regular,Name,Content} <- VeryIckyDir ],
Mod:rename([956,965,963,954,959,49],
[956,965,963,954,959]++"_fil1"),
{ok, <<"åäö2">>} = Mod:read_file([956,965,963,954,959]++"_fil1"),
@@ -610,90 +612,35 @@ rm_r2(Mod,Dir) ->
{ok, #file_info{type = symlink}} ->
ok = Mod:delete(Dir)
end.
-chk_cre_dir(_,[]) ->
- ok;
-chk_cre_dir(Mod,[{regular,Name,Content}|T]) ->
- %% io:format("~p~n",[Name]),
- ok = Mod:write_file(Name,Content),
- chk_cre_dir(Mod,T);
-chk_cre_dir(Mod,[{link,Name,Target}|T]) ->
- ok = Mod:make_link(Target,Name),
- chk_cre_dir(Mod,T);
-chk_cre_dir(Mod,[{symlink,Name,Target}|T]) ->
- ok = Mod:make_symlink(Target,Name),
- chk_cre_dir(Mod,T);
-chk_cre_dir(Mod,[{directory,Name,Content}|T]) ->
- ok = Mod:make_dir(Name),
- %% io:format("Content = ~p~n",[Content]),
- Content2 = [{Ty,filename:join(Name,N),case Ty of link -> filename:join(Name,C); _ -> C end} || {Ty,N,C} <- Content ],
- %% io:format("Content2 = ~p~n",[Content2]),
- chk_cre_dir(Mod,Content2),
- chk_cre_dir(Mod,T).
-has_links() ->
- case os:type() of
- {win32,_} ->
- case os:version() of
- {N,NN,_} when (N > 5) andalso (NN >= 1) ->
- true;
- _ ->
- false
- end;
- _ ->
- true
- end.
+make_normal_dir(Mod, DirName) ->
+ Dir = [{regular,"fil1","fil1"},
+ {regular,"fil2","fil2"},
+ {hardlink,"fil3","fil2"},
+ {symlink,"fil4","fil2"},
+ {directory,"subdir",
+ [{regular,"subfil1","subfil1"}]}],
+ rm_rf(Mod, DirName),
+ Mod:make_dir(DirName),
+ Mod:set_cwd(DirName),
+ make_dir_contents(Dir, Mod).
-make_normal_dir(Mod) ->
- rm_rf(Mod,"normal_dir"),
- Mod:make_dir("normal_dir"),
- Mod:set_cwd("normal_dir"),
- Mod:write_file("fil1","fil1"),
- Mod:write_file("fil2","fil2"),
- case has_links() of
- true ->
- Mod:make_link("fil2","fil3"),
- Mod:make_symlink("fil2","fil4");
- _ ->
- ok
- end,
- Mod:make_dir("subdir"),
- Mod:write_file(filename:join("subdir","subfil1"),"subfil1"),
- ok.
-
-normal_dir() ->
- [{regular,"fil1","fil1"},
- {regular,"fil2","fil2"}] ++
- case has_links() of
- true ->
- [{regular,"fil3","fil2"},
- {symlink,"fil4","fil2"}];
- false ->
- []
- end ++
- [{directory,"subdir",
- [{regular,"subfil1","subfil1"}]}].
-
-make_icky_dir(Mod) ->
- rm_rf(Mod,"icky_dir"),
- Icky=icky_dir(),
- chk_cre_dir(Mod,[{directory,"icky_dir",linkify([],Icky)}]),
- Mod:set_cwd("icky_dir"),
- ok.
-
-linkify(_Passed,[]) ->
- [];
-linkify(Passed,[{regular,Name,Content}|T]) ->
- Regulars = [ {N,C} || {regular,N,C} <- Passed, N =/= Name ],
- case lists:keysearch(Content,2,Regulars) of
- {value, {Linkto, Content}} ->
- [{link,Name,Linkto} | linkify(Passed,T)];
- _ ->
- [{regular,Name,Content} | linkify([{regular,Name,Content}|Passed],T)]
- end;
-linkify(Passed,[{directory, Name, Content}|T]) ->
- [{directory,Name, linkify(Content,Content)}|linkify(Passed,T)];
-linkify(Passed,[H|T]) ->
- [H|linkify([H|Passed],T)].
+make_icky_dir(Mod, IckyDirName) ->
+ Icky = [{regular,"fil1","fil1"},
+ {regular,"åäö2","åäö2"},
+ {hardlink,"åäö3","åäö2"},
+ {symlink,"åäö4","åäö2"},
+ {regular,treat_icky(<<"åäö5">>),"åäö5"},
+ {symlink,treat_icky(<<"åäö6">>),treat_icky(<<"åäö5">>)},
+ {directory,treat_icky(<<"åäösubdir2">>),
+ [{regular,treat_icky(<<"åäösubfil2">>),"åäösubfil12"},
+ {regular,"åäösubfil3","åäösubfil13"}]},
+ {directory,"åäösubdir",
+ [{regular,"åäösubfil1","åäösubfil1"}]}],
+ rm_rf(Mod, IckyDirName),
+ ok = Mod:make_dir(IckyDirName),
+ ok = Mod:set_cwd(IckyDirName),
+ make_dir_contents(Icky, Mod).
hopeless_darwin() ->
case {os:type(),os:version()} of
@@ -703,58 +650,24 @@ hopeless_darwin() ->
false
end.
-icky_dir() ->
- [{regular,"fil1","fil1"},
- {regular,"åäö2","åäö2"}] ++
- case has_links() of
- true ->
- [{regular,"åäö3","åäö2"},
- {symlink,"åäö4","åäö2"}];
- false ->
- []
- end ++
- [{regular,treat_icky(<<"åäö5">>),"åäö5"}] ++
- case has_links() of
- true ->
- [{symlink,treat_icky(<<"åäö6">>),treat_icky(<<"åäö5">>)}];
- false ->
- []
- end ++
- [{directory,treat_icky(<<"åäösubdir2">>),
- [{regular,treat_icky(<<"åäösubfil2">>),"åäösubfil12"},
- {regular,"åäösubfil3","åäösubfil13"}]},
- {directory,"åäösubdir",
- [{regular,"åäösubfil1","åäösubfil1"}]}].
-
-make_very_icky_dir(Mod) ->
- rm_rf(Mod,"very_icky_dir"),
- Icky=very_icky_dir(),
- chk_cre_dir(Mod,[{directory,"very_icky_dir",linkify([],Icky)}]),
- Mod:set_cwd("very_icky_dir"),
- ok.
-
-very_icky_dir() ->
- [{regular,"fil1","fil1"},
- {regular,[956,965,963,954,959,49],"åäö2"}] ++
- case has_links() of
- true ->
- [{regular,[956,965,963,954,959,50],"åäö2"},
- {symlink,[956,965,963,954,959,51],[956,965,963,954,959,49]}];
- false ->
- []
- end ++
- [{regular,treat_icky(<<"åäö5">>),"åäö5"}] ++
- case has_links() of
- true ->
- [{symlink,treat_icky(<<"åäö6">>),treat_icky(<<"åäö5">>)}];
- false ->
- []
- end ++
- [{directory,treat_icky(<<"åäösubdir2">>),
- [{regular,treat_icky(<<"åäösubfil2">>),"åäösubfil12"},
- {regular,"åäösubfil3","åäösubfil13"}]},
- {directory,[956,965,963,954,959]++"subdir1",
- [{regular,[956,965,963,954,959]++"subfil1","åäösubfil1"}]}].
+make_very_icky_dir(Mod, DirName) ->
+ Desc = [{regular,"fil1","fil1"},
+ {regular,[956,965,963,954,959,49],"åäö2"},
+ {hardlink,[956,965,963,954,959,50],
+ [956,965,963,954,959,49],
+ "åäö2"},
+ {symlink,[956,965,963,954,959,51],[956,965,963,954,959,49]},
+ {regular,treat_icky(<<"åäö5">>),"åäö5"},
+ {symlink,treat_icky(<<"åäö6">>),treat_icky(<<"åäö5">>)},
+ {directory,treat_icky(<<"åäösubdir2">>),
+ [{regular,treat_icky(<<"åäösubfil2">>),"åäösubfil12"},
+ {regular,"åäösubfil3","åäösubfil13"}]},
+ {directory,[956,965,963,954,959]++"subdir1",
+ [{regular,[956,965,963,954,959]++"subfil1","åäösubfil1"}]}],
+ rm_rf(Mod, DirName),
+ ok = Mod:make_dir(DirName),
+ ok = Mod:set_cwd(DirName),
+ make_dir_contents(Desc, Mod).
%% Some OS'es simply do not allow non UTF8 filenames
treat_icky(Bin) ->
@@ -827,6 +740,48 @@ conv(L) ->
end.
+make_dir_contents([{regular,Name,Contents}=H|T], Mod) ->
+ ok = Mod:write_file(Name, Contents),
+ [H|make_dir_contents(T, Mod)];
+make_dir_contents([{hardlink,Target,Name}|T], Mod) ->
+ case Mod:make_link(Name, Target) of
+ ok ->
+ [{regular,Target,Name}|make_dir_contents(T, Mod)];
+ {error,enotsup} ->
+ make_dir_contents(T, Mod)
+ end;
+make_dir_contents([{hardlink,Target,Name,Contents}|T], Mod) ->
+ case Mod:make_link(Name, Target) of
+ ok ->
+ [{regular,Target,Contents}|make_dir_contents(T, Mod)];
+ {error,enotsup} ->
+ make_dir_contents(T, Mod)
+ end;
+make_dir_contents([{symlink,Target,Name}=H|T], Mod) ->
+ case Mod:make_symlink(Name, Target) of
+ ok ->
+ [H|make_dir_contents(T, Mod)];
+ {error,enotsup} ->
+ make_dir_contents(T, Mod);
+ {error,eperm} ->
+ make_dir_contents(T, Mod)
+ end;
+make_dir_contents([{directory,Dir,C0}|T], Mod) ->
+ ok = Mod:make_dir(Dir),
+ C1 = [case Op of
+ Link when Link =:= hardlink; Link =:= symlink ->
+ {Op,filename:join(Dir, Name0),filename:join(Dir, Extra)};
+ _ ->
+ {Op,filename:join(Dir, Name0),Extra}
+ end || {Op,Name0,Extra} <- C0],
+ C2 = make_dir_contents(C1, Mod),
+ C = [{Op,filename:basename(Name0),Extra} ||
+ {Op,Name0,Extra} <- C2],
+ [{directory,Dir,C}|make_dir_contents(T, Mod)];
+make_dir_contents([], _Mod) ->
+ [].
+
+
rand_comp_decomp(Max) ->
N = rand:uniform(Max),
L = [ rand_decomp() || _ <- lists:seq(1,N) ],
diff --git a/lib/kernel/test/gen_sctp_SUITE.erl b/lib/kernel/test/gen_sctp_SUITE.erl
index 8e53da210e..48cd245204 100644
--- a/lib/kernel/test/gen_sctp_SUITE.erl
+++ b/lib/kernel/test/gen_sctp_SUITE.erl
@@ -29,7 +29,8 @@
init_per_group/2,end_per_group/2,
init_per_testcase/2, end_per_testcase/2]).
-export(
- [basic/1,
+ [skip_old_solaris/1,
+ basic/1,
api_open_close/1,api_listen/1,api_connect_init/1,api_opts/1,
xfer_min/1,xfer_active/1,def_sndrcvinfo/1,implicit_inet6/1,
open_multihoming_ipv4_socket/1,
@@ -46,20 +47,28 @@ suite() ->
[{ct_hooks,[ts_install_cth]},
{timetrap,{minutes,1}}].
-all() ->
- [basic, api_open_close, api_listen, api_connect_init,
- api_opts, xfer_min, xfer_active, def_sndrcvinfo, implicit_inet6,
- open_multihoming_ipv4_socket,
- open_unihoming_ipv6_socket,
- open_multihoming_ipv6_socket,
- open_multihoming_ipv4_and_ipv6_socket, active_n,
- basic_stream, xfer_stream_min, peeloff_active_once,
- peeloff_active_true, peeloff_active_n, buffers,
- names_unihoming_ipv4, names_unihoming_ipv6,
- names_multihoming_ipv4, names_multihoming_ipv6].
+all() ->
+ G = case is_old_solaris() of
+ true -> old_solaris;
+ false -> extensive
+ end,
+ [{group,smoke},
+ {group,G}].
groups() ->
- [].
+ [{smoke,[],[basic,basic_stream]},
+ {old_solaris,[],[skip_old_solaris]},
+ {extensive,[],
+ [api_open_close, api_listen, api_connect_init,
+ api_opts, xfer_min, xfer_active, def_sndrcvinfo, implicit_inet6,
+ open_multihoming_ipv4_socket,
+ open_unihoming_ipv6_socket,
+ open_multihoming_ipv6_socket,
+ open_multihoming_ipv4_and_ipv6_socket, active_n,
+ xfer_stream_min, peeloff_active_once,
+ peeloff_active_true, peeloff_active_n, buffers,
+ names_unihoming_ipv4, names_unihoming_ipv6,
+ names_multihoming_ipv4, names_multihoming_ipv6]}].
init_per_suite(_Config) ->
case gen_sctp:open() of
@@ -91,7 +100,11 @@ end_per_testcase(_Func, _Config) ->
-define(LOGVAR(Var), begin io:format(??Var" = ~p~n", [Var]) end).
+is_old_solaris() ->
+ os:type() =:= {unix,sunos} andalso os:version() < {5,12,0}.
+skip_old_solaris(_Config) ->
+ {skip,"Unreliable test cases and/or implementation on old Solaris"}.
%% Hello world.
basic(Config) when is_list(Config) ->
diff --git a/lib/kernel/test/gen_tcp_misc_SUITE.erl b/lib/kernel/test/gen_tcp_misc_SUITE.erl
index 7c3b011eb9..173cf76237 100644
--- a/lib/kernel/test/gen_tcp_misc_SUITE.erl
+++ b/lib/kernel/test/gen_tcp_misc_SUITE.erl
@@ -2320,70 +2320,82 @@ active_once_closed(Config) when is_list(Config) ->
%% Test the send_timeout socket option.
send_timeout(Config) when is_list(Config) ->
+ Dir = filename:dirname(code:which(?MODULE)),
+ {ok,RNode} = test_server:start_node(?UNIQ_NODE_NAME, slave,
+ [{args,"-pa " ++ Dir}]),
+
%% Basic
- BasicFun =
- fun(AutoClose) ->
- {Loop,A,RNode} = setup_timeout_sink(1000, AutoClose),
- {error,timeout} =
- Loop(fun() ->
- Res = gen_tcp:send(A,<<1:10000>>),
- %%erlang:display(Res),
- Res
- end),
- %% Check that the socket is not busy/closed...
- Error = after_send_timeout(AutoClose),
- {error,Error} = gen_tcp:send(A,<<"Hej">>),
- test_server:stop_node(RNode)
- end,
- BasicFun(false),
- BasicFun(true),
- %% Check timeout length
+ send_timeout_basic(false, RNode),
+ send_timeout_basic(true, RNode),
+
+ BinData = <<1:10000>>,
+
+ %% Check timeout length.
Self = self(),
Pid = spawn(fun() ->
- {Loop,A,RNode} = setup_timeout_sink(1000, true),
- {error,timeout} = Loop(fun() ->
- Res = gen_tcp:send(A,<<1:10000>>),
- %%erlang:display(Res),
- Self ! Res,
- Res
- end),
- test_server:stop_node(RNode)
+ A = setup_timeout_sink(RNode, 1000, true),
+ Send = fun() ->
+ Res = gen_tcp:send(A, BinData),
+ Self ! Res,
+ Res
+ end,
+ {error,timeout} = timeout_sink_loop(Send)
end),
Diff = get_max_diff(),
io:format("Max time for send: ~p~n",[Diff]),
true = (Diff > 500) and (Diff < 1500),
- %% Let test_server slave die...
+
+ %% Wait for the process to die.
Mon = erlang:monitor(process, Pid),
receive {'DOWN',Mon,process,Pid,_} -> ok end,
+
%% Check that parallell writers do not hang forever
- ParaFun =
- fun(AutoClose) ->
- {Loop,A,RNode} = setup_timeout_sink(1000, AutoClose),
- SenderFun = fun() ->
- {error,Error} =
- Loop(fun() ->
- gen_tcp:send(A, <<1:10000>>)
- end),
- Self ! {error,Error}
- end,
- spawn_link(SenderFun),
- spawn_link(SenderFun),
- receive
- {error,timeout} -> ok
- after 10000 ->
- exit(timeout)
- end,
- NextErr = after_send_timeout(AutoClose),
- receive
- {error,NextErr} -> ok
- after 10000 ->
- exit(timeout)
- end,
- {error,NextErr} = gen_tcp:send(A,<<"Hej">>),
- test_server:stop_node(RNode)
- end,
- ParaFun(false),
- ParaFun(true),
+ send_timeout_para(false, RNode),
+ send_timeout_para(true, RNode),
+
+ test_server:stop_node(RNode),
+
+ ok.
+
+send_timeout_basic(AutoClose, RNode) ->
+ BinData = <<1:10000>>,
+
+ A = setup_timeout_sink(RNode, 1000, AutoClose),
+ Send = fun() -> gen_tcp:send(A, BinData) end,
+ {error,timeout} = timeout_sink_loop(Send),
+
+ %% Check that the socket is not busy/closed...
+ Error = after_send_timeout(AutoClose),
+ {error,Error} = gen_tcp:send(A, <<"Hej">>),
+ ok.
+
+send_timeout_para(AutoClose, RNode) ->
+ BinData = <<1:10000>>,
+
+ A = setup_timeout_sink(RNode, 1000, AutoClose),
+ Self = self(),
+ SenderFun = fun() ->
+ Send = fun() -> gen_tcp:send(A, BinData) end,
+ {error,Error} = timeout_sink_loop(Send),
+ Self ! {error,Error}
+ end,
+ spawn_link(SenderFun),
+ spawn_link(SenderFun),
+
+ receive
+ {error,timeout} -> ok
+ after 10000 ->
+ exit(timeout)
+ end,
+
+ NextErr = after_send_timeout(AutoClose),
+ receive
+ {error,NextErr} -> ok
+ after 10000 ->
+ exit(timeout)
+ end,
+
+ {error,NextErr} = gen_tcp:send(A, <<"Hej">>),
ok.
mad_sender(S) ->
@@ -2406,31 +2418,33 @@ flush() ->
%% Test the send_timeout socket option for active sockets.
send_timeout_active(Config) when is_list(Config) ->
- %% Basic
- BasicFun =
- fun(AutoClose) ->
- {Loop,A,RNode,C} = setup_active_timeout_sink(1, AutoClose),
- inet:setopts(A, [{active, once}]),
- Mad = spawn_link(RNode,fun() -> mad_sender(C) end),
- {error,timeout} =
- Loop(fun() ->
- receive
- {tcp, _Sock, _Data} ->
- inet:setopts(A, [{active, once}]),
- Res = gen_tcp:send(A,lists:duplicate(1000, $a)),
- Res;
- Err ->
- io:format("sock closed: ~p~n", [Err]),
- Err
- end
- end),
- unlink(Mad),
- exit(Mad,kill),
- test_server:stop_node(RNode)
+ Dir = filename:dirname(code:which(?MODULE)),
+ {ok,RNode} = test_server:start_node(?UNIQ_NODE_NAME, slave,
+ [{args,"-pa " ++ Dir}]),
+ do_send_timeout_active(false, RNode),
+ do_send_timeout_active(true, RNode),
+ test_server:stop_node(RNode),
+ ok.
+
+do_send_timeout_active(AutoClose, RNode) ->
+ {A,C} = setup_active_timeout_sink(RNode, 1, AutoClose),
+ inet:setopts(A, [{active, once}]),
+ Mad = spawn_link(RNode, fun() -> mad_sender(C) end),
+ ListData = lists:duplicate(1000, $a),
+ F = fun() ->
+ receive
+ {tcp, _Sock, _Data} ->
+ inet:setopts(A, [{active, once}]),
+ Res = gen_tcp:send(A, ListData),
+ Res;
+ Err ->
+ io:format("sock closed: ~p~n", [Err]),
+ Err
+ end
end,
- BasicFun(false),
- flush(),
- BasicFun(true),
+ {error,timeout} = timeout_sink_loop(F),
+ unlink(Mad),
+ exit(Mad, kill),
flush(),
ok.
@@ -2475,7 +2489,7 @@ setup_closed_ao() ->
Dir = filename:dirname(code:which(?MODULE)),
{ok,R} = test_server:start_node(?UNIQ_NODE_NAME, slave,
[{args,"-pa " ++ Dir}]),
- Host = list_to_atom(lists:nth(2,string:tokens(atom_to_list(node()),"@"))),
+ Host = get_hostname(node()),
{ok, L} = gen_tcp:listen(0, [{active,false},{packet,2}]),
Fun = fun(F) ->
receive
@@ -2514,11 +2528,8 @@ setup_closed_ao() ->
test_server:stop_node(R),
{Loop,A}.
-setup_timeout_sink(Timeout, AutoClose) ->
- Dir = filename:dirname(code:which(?MODULE)),
- {ok,R} = test_server:start_node(?UNIQ_NODE_NAME, slave,
- [{args,"-pa " ++ Dir}]),
- Host = list_to_atom(lists:nth(2,string:tokens(atom_to_list(node()),"@"))),
+setup_timeout_sink(RNode, Timeout, AutoClose) ->
+ Host = get_hostname(node()),
{ok, L} = gen_tcp:listen(0, [{active,false},{packet,2},
{send_timeout,Timeout},
{send_timeout_close,AutoClose}]),
@@ -2529,7 +2540,7 @@ setup_timeout_sink(Timeout, AutoClose) ->
die -> ok
end
end,
- Pid = rpc:call(R,erlang,spawn,[fun() -> Fun(Fun) end]),
+ Pid = rpc:call(RNode, erlang, spawn, [fun() -> Fun(Fun) end]),
{ok, Port} = inet:port(L),
Remote = fun(Fu) ->
Pid ! {self(), Fu},
@@ -2543,36 +2554,23 @@ setup_timeout_sink(Timeout, AutoClose) ->
{ok,A} = gen_tcp:accept(L),
gen_tcp:send(A,"Hello"),
{ok, "Hello"} = Remote(fun() -> gen_tcp:recv(C,0) end),
- Loop2 = fun(_,_,0) ->
- {failure, timeout};
- (L2,F2,N) ->
- Ret = F2(),
- io:format("~p~n",[Ret]),
- case Ret of
- ok -> receive after 1 -> ok end,
- L2(L2,F2,N-1);
- Other -> Other
- end
- end,
- Loop = fun(F3) -> Loop2(Loop2,F3,1000) end,
- {Loop,A,R}.
-
-setup_active_timeout_sink(Timeout, AutoClose) ->
- Dir = filename:dirname(code:which(?MODULE)),
- {ok,R} = test_server:start_node(?UNIQ_NODE_NAME, slave,
- [{args,"-pa " ++ Dir}]),
- Host = list_to_atom(lists:nth(2,string:tokens(atom_to_list(node()),"@"))),
- {ok, L} = gen_tcp:listen(0, [binary,{active,false},{packet,0},{nodelay, true},{keepalive, true},
- {send_timeout,Timeout},
- {send_timeout_close,AutoClose}]),
+ A.
+
+setup_active_timeout_sink(RNode, Timeout, AutoClose) ->
+ Host = get_hostname(node()),
+ ListenOpts = [binary,{active,false},{packet,0},
+ {nodelay,true},{keepalive,true},
+ {send_timeout,Timeout},{send_timeout_close,AutoClose}],
+ {ok, L} = gen_tcp:listen(0, ListenOpts),
Fun = fun(F) ->
receive
{From,X} when is_function(X) ->
- From ! {self(),X()}, F(F);
+ From ! {self(),X()},
+ F(F);
die -> ok
end
end,
- Pid = rpc:call(R,erlang,spawn,[fun() -> Fun(Fun) end]),
+ Pid = rpc:call(RNode, erlang, spawn, [fun() -> Fun(Fun) end]),
{ok, Port} = inet:port(L),
Remote = fun(Fu) ->
Pid ! {self(), Fu},
@@ -2580,26 +2578,22 @@ setup_active_timeout_sink(Timeout, AutoClose) ->
end
end,
{ok, C} = Remote(fun() ->
- gen_tcp:connect(Host,Port,
- [{active,false}])
+ gen_tcp:connect(Host, Port, [{active,false}])
end),
{ok,A} = gen_tcp:accept(L),
- gen_tcp:send(A,"Hello"),
- {ok, "H"++_} = Remote(fun() -> gen_tcp:recv(C,0) end),
- Loop2 = fun(_,_,0) ->
- {failure, timeout};
- (L2,F2,N) ->
- Ret = F2(),
- io:format("~p~n",[Ret]),
- case Ret of
- ok -> receive after 1 -> ok end,
- L2(L2,F2,N-1);
- Other -> Other
- end
- end,
- Loop = fun(F3) -> Loop2(Loop2,F3,1000) end,
- {Loop,A,R,C}.
+ gen_tcp:send(A, "Hello"),
+ {ok, "H"++_} = Remote(fun() -> gen_tcp:recv(C, 0) end),
+ {A,C}.
+timeout_sink_loop(Action) ->
+ Ret = Action(),
+ case Ret of
+ ok ->
+ receive after 1 -> ok end,
+ timeout_sink_loop(Action);
+ Other ->
+ Other
+ end.
has_superfluous_schedulers() ->
case {erlang:system_info(schedulers),
@@ -3016,3 +3010,7 @@ oct_aloop(S,X,Times) ->
end.
ok({ok,V}) -> V.
+
+get_hostname(Name) ->
+ "@"++Host = lists:dropwhile(fun(C) -> C =/= $@ end, atom_to_list(Name)),
+ Host.
diff --git a/lib/kernel/test/heart_SUITE.erl b/lib/kernel/test/heart_SUITE.erl
index dd6348c610..6ce1ee54e5 100644
--- a/lib/kernel/test/heart_SUITE.erl
+++ b/lib/kernel/test/heart_SUITE.erl
@@ -37,6 +37,11 @@
-define(DEFAULT_TIMEOUT_SECS, 120).
+-define(UNIQ_NODE_NAME,
+ list_to_atom(?MODULE_STRING ++ "__" ++
+ atom_to_list(?FUNCTION_NAME) ++ "_" ++
+ integer_to_list(erlang:unique_integer([positive])))).
+
init_per_testcase(_Func, Config) ->
Config.
@@ -118,7 +123,7 @@ start_check(Type, Name, Envs) ->
{ok, Node}.
start(Config) when is_list(Config) ->
- {ok, Node} = start_check(slave, heart_test),
+ {ok, Node} = start_check(slave, ?UNIQ_NODE_NAME),
rpc:call(Node, init, reboot, []),
receive
{nodedown, Node} -> ok
@@ -143,12 +148,12 @@ start(Config) when is_list(Config) ->
%% Purpose:
%% Check that a node is up and running after a init:restart/0
restart(Config) when is_list(Config) ->
- {ok, Node} = start_check(loose, heart_test),
+ {ok, Node} = start_check(loose, ?UNIQ_NODE_NAME),
rpc:call(Node, init, restart, []),
receive
{nodedown, Node} ->
ok
- after 2000 ->
+ after 5000 ->
ct:fail(node_not_closed)
end,
timer:sleep(5000),
@@ -159,7 +164,7 @@ restart(Config) when is_list(Config) ->
%% Purpose:
%% Check that a node is up and running after a init:reboot/0
reboot(Config) when is_list(Config) ->
- {ok, Node} = start_check(slave, heart_test),
+ {ok, Node} = start_check(slave, ?UNIQ_NODE_NAME),
ok = rpc:call(Node, heart, set_cmd,
[atom_to_list(lib:progname()) ++
@@ -193,7 +198,8 @@ node_start_immediately_after_crash(Config) when is_list(Config) ->
node_start_immediately_after_crash_test(Config) when is_list(Config) ->
- {ok, Node} = start_check(loose, heart_test_imm, [{"ERL_CRASH_DUMP_SECONDS", "0"}]),
+ {ok, Node} = start_check(loose, ?UNIQ_NODE_NAME,
+ [{"ERL_CRASH_DUMP_SECONDS", "0"}]),
ok = rpc:call(Node, heart, set_cmd,
[atom_to_list(lib:progname()) ++
@@ -243,7 +249,8 @@ node_start_soon_after_crash(Config) when is_list(Config) ->
end.
node_start_soon_after_crash_test(Config) when is_list(Config) ->
- {ok, Node} = start_check(loose, heart_test_soon, [{"ERL_CRASH_DUMP_SECONDS", "10"}]),
+ {ok, Node} = start_check(loose, ?UNIQ_NODE_NAME,
+ [{"ERL_CRASH_DUMP_SECONDS", "10"}]),
ok = rpc:call(Node, heart, set_cmd,
[atom_to_list(lib:progname()) ++
@@ -286,7 +293,7 @@ node_check_up_down(Node, Tmo) ->
%% Only tests bad command, correct behaviour is tested in reboot/1.
set_cmd(Config) when is_list(Config) ->
- {ok, Node} = start_check(slave, heart_test),
+ {ok, Node} = start_check(slave, ?UNIQ_NODE_NAME),
Cmd = wrong_atom,
{error, {bad_cmd, Cmd}} = rpc:call(Node, heart, set_cmd, [Cmd]),
Cmd1 = lists:duplicate(2047, $a),
@@ -299,7 +306,7 @@ set_cmd(Config) when is_list(Config) ->
ok.
clear_cmd(Config) when is_list(Config) ->
- {ok, Node} = start_check(slave, heart_test),
+ {ok, Node} = start_check(slave, ?UNIQ_NODE_NAME),
ok = rpc:call(Node, heart, set_cmd,
[atom_to_list(lib:progname()) ++
" -noshell -heart " ++ name(Node) ++ "&"]),
@@ -337,7 +344,7 @@ clear_cmd(Config) when is_list(Config) ->
ok.
get_cmd(Config) when is_list(Config) ->
- {ok, Node} = start_check(slave, heart_test),
+ {ok, Node} = start_check(slave, ?UNIQ_NODE_NAME),
Cmd = "test",
ok = rpc:call(Node, heart, set_cmd, [Cmd]),
{ok, Cmd} = rpc:call(Node, heart, get_cmd, []),
@@ -345,7 +352,7 @@ get_cmd(Config) when is_list(Config) ->
ok.
callback_api(Config) when is_list(Config) ->
- {ok, Node} = start_check(slave, heart_test),
+ {ok, Node} = start_check(slave, ?UNIQ_NODE_NAME),
none = rpc:call(Node, heart, get_callback, []),
M0 = self(),
F0 = ok,
@@ -379,7 +386,7 @@ callback_api(Config) when is_list(Config) ->
ok.
options_api(Config) when is_list(Config) ->
- {ok, Node} = start_check(slave, heart_test),
+ {ok, Node} = start_check(slave, ?UNIQ_NODE_NAME),
none = rpc:call(Node, heart, get_options, []),
M0 = self(),
F0 = ok,
@@ -474,7 +481,7 @@ kill_pid(Config) when is_list(Config) ->
ok = do_kill_pid(Config).
do_kill_pid(_Config) ->
- Name = heart_test,
+ Name = ?UNIQ_NODE_NAME,
Env = [{"HEART_COMMAND", "nickeNyfikenFarEttJobb"}],
{ok,Node} = start_node_run(Name,Env,suicide_by_heart,[]),
ok = wait_for_node(Node,15),
diff --git a/lib/kernel/test/inet_SUITE.erl b/lib/kernel/test/inet_SUITE.erl
index ee10747b0a..38cb02a6ec 100644
--- a/lib/kernel/test/inet_SUITE.erl
+++ b/lib/kernel/test/inet_SUITE.erl
@@ -1075,6 +1075,10 @@ check_ifopts(
#ifopts{addrs=Addrs}=Ifopts) ->
check_ifopts(Opts, Ifopts#ifopts{addrs=[{Addr,Netmask,Broadaddr}|Addrs]});
check_ifopts(
+ [{addr,Addr},{netmask,Netmask},{dstaddr,_}|Opts],
+ #ifopts{addrs=Addrs}=Ifopts) ->
+ check_ifopts(Opts, Ifopts#ifopts{addrs=[{Addr,Netmask}|Addrs]});
+check_ifopts(
[{addr,Addr},{netmask,Netmask}|Opts],
#ifopts{addrs=Addrs}=Ifopts) ->
check_ifopts(Opts, Ifopts#ifopts{addrs=[{Addr,Netmask}|Addrs]});
@@ -1118,9 +1122,13 @@ simple_netns(Config) when is_list(Config) ->
jog_netns_opt(L),
ok = gen_tcp:close(L),
%%
- {ok,S} = gen_sctp:open(),
- jog_netns_opt(S),
- ok = gen_sctp:close(S);
+ case gen_sctp:open() of
+ {ok,S} ->
+ jog_netns_opt(S),
+ ok = gen_sctp:close(S);
+ {error,eprotonosupport} ->
+ ok
+ end;
{error,einval} ->
{skip,"setns() not supported"}
end.
@@ -1134,24 +1142,28 @@ jog_netns_opt(S) ->
ok.
+%% Smoke test netns support.
simple_netns_open(Config) when is_list(Config) ->
+ %% Note: {error,enoent} will be returned if the run-time executable
+ %% has support for netns, but /proc/self/ns/net is missing.
case gen_udp:open(0, [binary,{netns,"/"},inet]) of
{ok,U} ->
ok = gen_udp:close(U);
- {error,E1} when E1 =:= einval; E1 =:= eperm ->
+ {error,E1} when E1 =:= einval; E1 =:= eperm; E1 =:= enoent ->
ok
end,
case gen_tcp:listen(0, [binary,{netns,"/"},inet]) of
{ok,T} ->
ok = gen_tcp:close(T);
- {error,E2} when E2 =:= einval; E2 =:= eperm ->
+ {error,E2} when E2 =:= einval; E2 =:= eperm; E2 =:= enoent ->
ok
end,
try gen_sctp:open(0, [binary,{netns,"/"},inet]) of
{ok,S} ->
ok = gen_sctp:close(S);
{error,E3}
- when E3 =:= einval; E3 =:= eperm; E3 =:= eprotonosupport ->
+ when E3 =:= einval; E3 =:= eperm;
+ E3 =:= enoent; E3 =:= eprotonosupport ->
ok
catch
error:badarg ->
diff --git a/lib/kernel/test/init_SUITE.erl b/lib/kernel/test/init_SUITE.erl
index 0fa97b585c..e85d50bd0c 100644
--- a/lib/kernel/test/init_SUITE.erl
+++ b/lib/kernel/test/init_SUITE.erl
@@ -249,7 +249,8 @@ boot_var(Config) when is_list(Config) ->
{ok, Node} =
start_node(init_test,
"-boot " ++ BootScript ++
- " -boot_var TEST_VAR " ++ TEST_VAR),
+ " -boot_var TEST_VAR \"" ++
+ TEST_VAR ++ "\""),
stop_node(Node),
Res = ok;
_ ->
diff --git a/lib/stdlib/src/otp_internal.erl b/lib/stdlib/src/otp_internal.erl
index 87601ba0f4..052dffdbfd 100644
--- a/lib/stdlib/src/otp_internal.erl
+++ b/lib/stdlib/src/otp_internal.erl
@@ -47,18 +47,6 @@ obsolete(Module, Name, Arity) ->
obsolete_1(net, _, _) ->
{deprecated, "module 'net' obsolete; use 'net_adm'"};
-obsolete_1(erl_internal, builtins, 0) ->
- {deprecated, {erl_internal, bif, 2}};
-
-obsolete_1(erl_eval, seq, 2) ->
- {deprecated, {erl_eval, exprs, 2}};
-obsolete_1(erl_eval, seq, 3) ->
- {deprecated, {erl_eval, exprs, 3}};
-obsolete_1(erl_eval, arg_list, 2) ->
- {deprecated, {erl_eval, expr_list, 2}};
-obsolete_1(erl_eval, arg_list, 3) ->
- {deprecated, {erl_eval, expr_list, 3}};
-
obsolete_1(erlang, hash, 2) ->
{deprecated, {erlang, phash2, 2}};
@@ -387,106 +375,10 @@ obsolete_1(http, cookie_header, 2) -> {removed,{httpc,cookie_header,2},"R15B"
obsolete_1(http, stream_next, 1) -> {removed,{httpc,stream_next,1},"R15B"};
obsolete_1(http, default_profile, 0) -> {removed,{httpc,default_profile,0},"R15B"};
-obsolete_1(httpd, start, 0) -> {removed,{inets,start,[2,3]},"R14B"};
-obsolete_1(httpd, start, 1) -> {removed,{inets,start,[2,3]},"R14B"};
-obsolete_1(httpd, start_link, 0) -> {removed,{inets,start,[2,3]},"R14B"};
-obsolete_1(httpd, start_link, 1) -> {removed,{inets,start,[2,3]},"R14B"};
-obsolete_1(httpd, start_child, 0) -> {removed,{inets,start,[2,3]},"R14B"};
-obsolete_1(httpd, start_child, 1) -> {removed,{inets,start,[2,3]},"R14B"};
-obsolete_1(httpd, stop, 0) -> {removed,{inets,stop,2},"R14B"};
-obsolete_1(httpd, stop, 1) -> {removed,{inets,stop,2},"R14B"};
-obsolete_1(httpd, stop, 2) -> {removed,{inets,stop,2},"R14B"};
-obsolete_1(httpd, stop_child, 0) -> {removed,{inets,stop,2},"R14B"};
-obsolete_1(httpd, stop_child, 1) -> {removed,{inets,stop,2},"R14B"};
-obsolete_1(httpd, stop_child, 2) -> {removed,{inets,stop,2},"R14B"};
-obsolete_1(httpd, restart, 0) -> {removed,{httpd,reload_config,2},"R14B"};
-obsolete_1(httpd, restart, 1) -> {removed,{httpd,reload_config,2},"R14B"};
-obsolete_1(httpd, restart, 2) -> {removed,{httpd,reload_config,2},"R14B"};
-obsolete_1(httpd, block, 0) -> {removed,{httpd,reload_config,2},"R14B"};
-obsolete_1(httpd, block, 1) -> {removed,{httpd,reload_config,2},"R14B"};
-obsolete_1(httpd, block, 2) -> {removed,{httpd,reload_config,2},"R14B"};
-obsolete_1(httpd, block, 3) -> {removed,{httpd,reload_config,2},"R14B"};
-obsolete_1(httpd, block, 4) -> {removed,{httpd,reload_config,2},"R14B"};
-obsolete_1(httpd, unblock, 0) -> {removed,{httpd,reload_config,2},"R14B"};
-obsolete_1(httpd, unblock, 1) -> {removed,{httpd,reload_config,2},"R14B"};
-obsolete_1(httpd, unblock, 2) -> {removed,{httpd,reload_config,2},"R14B"};
-obsolete_1(httpd_util, key1search, 2) -> {removed,{proplists,get_value,2},"R13B"};
-obsolete_1(httpd_util, key1search, 3) -> {removed,{proplists,get_value,3},"R13B"};
-obsolete_1(ftp, open, 3) -> {removed,{inets,start,[2,3]},"R14B"};
-obsolete_1(ftp, force_active, 1) -> {removed,{inets,start,[2,3]},"R14B"};
-
-%% Added in R12B-4.
-obsolete_1(ssh_cm, connect, A) when 1 =< A, A =< 3 ->
- {removed,{ssh,connect,A},"R14B"};
-obsolete_1(ssh_cm, listen, A) when 2 =< A, A =< 4 ->
- {removed,{ssh,daemon,A},"R14B"};
-obsolete_1(ssh_cm, stop_listener, 1) ->
- {removed,{ssh,stop_listener,[1,2]},"R14B"};
-obsolete_1(ssh_cm, session_open, A) when A =:= 2; A =:= 4 ->
- {removed,{ssh_connection,session_channel,A},"R14B"};
-obsolete_1(ssh_cm, direct_tcpip, A) when A =:= 6; A =:= 8 ->
- {removed,{ssh_connection,direct_tcpip,A},"R14B"};
-obsolete_1(ssh_cm, tcpip_forward, 3) ->
- {removed,{ssh_connection,tcpip_forward,3},"R14B"};
-obsolete_1(ssh_cm, cancel_tcpip_forward, 3) ->
- {removed,{ssh_connection,cancel_tcpip_forward,3},"R14B"};
-obsolete_1(ssh_cm, open_pty, A) when A =:= 3; A =:= 7; A =:= 9 ->
- {removed,{ssh_connection,open_pty,A},"R14B"};
-obsolete_1(ssh_cm, setenv, 5) ->
- {removed,{ssh_connection,setenv,5},"R14B"};
-obsolete_1(ssh_cm, shell, 2) ->
- {removed,{ssh_connection,shell,2},"R14B"};
-obsolete_1(ssh_cm, exec, 4) ->
- {removed,{ssh_connection,exec,4},"R14B"};
-obsolete_1(ssh_cm, subsystem, 4) ->
- {removed,{ssh_connection,subsystem,4},"R14B"};
-obsolete_1(ssh_cm, winch, A) when A =:= 4; A =:= 6 ->
- {removed,{ssh_connection,window_change,A},"R14B"};
-obsolete_1(ssh_cm, signal, 3) ->
- {removed,{ssh_connection,signal,3},"R14B"};
-obsolete_1(ssh_cm, attach, A) when A =:= 2; A =:= 3 ->
- {removed,"no longer useful; removed in R14B"};
-obsolete_1(ssh_cm, detach, 2) ->
- {removed,"no longer useful; removed in R14B"};
-obsolete_1(ssh_cm, set_user_ack, 4) ->
- {removed,"no longer useful; removed in R14B"};
-obsolete_1(ssh_cm, adjust_window, 3) ->
- {removed,{ssh_connection,adjust_window,3},"R14B"};
-obsolete_1(ssh_cm, close, 2) ->
- {removed,{ssh_connection,close,2},"R14B"};
-obsolete_1(ssh_cm, stop, 1) ->
- {removed,{ssh,close,1},"R14B"};
-obsolete_1(ssh_cm, send_eof, 2) ->
- {removed,{ssh_connection,send_eof,2},"R14B"};
-obsolete_1(ssh_cm, send, A) when A =:= 3; A =:= 4 ->
- {removed,{ssh_connection,send,A},"R14B"};
-obsolete_1(ssh_cm, send_ack, A) when 3 =< A, A =< 5 ->
- {removed,{ssh_connection,send,[3,4]},"R14B"};
-obsolete_1(ssh_ssh, connect, A) when 1 =< A, A =< 3 ->
- {removed,{ssh,shell,A},"R14B"};
-obsolete_1(ssh_sshd, listen, A) when 0 =< A, A =< 3 ->
- {removed,{ssh,daemon,[1,2,3]},"R14B"};
-obsolete_1(ssh_sshd, stop, 1) ->
- {removed,{ssh,stop_listener,1},"R14B"};
-
%% Added in R13A.
obsolete_1(regexp, _, _) ->
{removed, "removed in R15; use the re module instead"};
-obsolete_1(lists, flat_length, 1) ->
- {removed,{lists,flatlength,1},"R14"};
-
-obsolete_1(ssh_sftp, connect, A) when 1 =< A, A =< 3 ->
- {removed,{ssh_sftp,start_channel,A},"R14B"};
-obsolete_1(ssh_sftp, stop, 1) ->
- {removed,{ssh_sftp,stop_channel,1},"R14B"};
-
-%% Added in R13B01.
-obsolete_1(ssl_pkix, decode_cert_file, A) when A =:= 1; A =:= 2 ->
- {removed,"removed in R14A; use public_key:pem_to_der/1 and public_key:pkix_decode_cert/2 instead"};
-obsolete_1(ssl_pkix, decode_cert, A) when A =:= 1; A =:= 2 ->
- {removed,{public_key,pkix_decode_cert,2},"R14A"};
-
%% Added in R13B04.
obsolete_1(erlang, concat_binary, 1) ->
{removed,{erlang,list_to_binary,1},"R15B"};
diff --git a/lib/stdlib/test/gen_fsm_SUITE.erl b/lib/stdlib/test/gen_fsm_SUITE.erl
index f79a344c4e..e23e747dee 100644
--- a/lib/stdlib/test/gen_fsm_SUITE.erl
+++ b/lib/stdlib/test/gen_fsm_SUITE.erl
@@ -391,6 +391,12 @@ abnormal1(Config) when is_list(Config) ->
delayed = gen_fsm:sync_send_event(my_fsm, {delayed_answer,1}, 100),
{'EXIT',{timeout,_}} =
(catch gen_fsm:sync_send_event(my_fsm, {delayed_answer,10}, 1)),
+ receive
+ Msg ->
+ %% Ignore the delayed answer from the server.
+ io:format("Delayed message: ~p", [Msg])
+ end,
+
[] = get_messages(),
ok.
@@ -971,7 +977,7 @@ init(stop) ->
init(stop_shutdown) ->
{stop, shutdown};
init(sleep) ->
- ct:sleep(1000),
+ timer:sleep(1000),
{ok, idle, data};
init({timeout, T}) ->
{ok, idle, state, T};
@@ -1004,7 +1010,7 @@ idle(_, Data) ->
idle({connect, _Pid}, _From, Data) ->
{reply, accept, wfor_conf, Data};
idle({delayed_answer, T}, _From, Data) ->
- ct:sleep(T),
+ timer:sleep(T),
{reply, delayed, idle, Data};
idle(badreturn, _From, _Data) ->
badreturn;
diff --git a/lib/wx/api_gen/wx_gen_erl.erl b/lib/wx/api_gen/wx_gen_erl.erl
index c28b9238dc..e11d4f725c 100644
--- a/lib/wx/api_gen/wx_gen_erl.erl
+++ b/lib/wx/api_gen/wx_gen_erl.erl
@@ -1089,7 +1089,7 @@ gen_enums_ints() ->
%% open_write("../include/wx.hrl"), opened in gen_event_recs
w("~n%% Hardcoded Records~n", []),
w("-record(wxMouseState, {x :: integer(), y :: integer(),~n"
- " leftDown :: boolean(), middleDown :: boolean, rightDown :: boolean, ~n"
+ " leftDown :: boolean(), middleDown :: boolean(), rightDown :: boolean(), ~n"
" controlDown :: boolean(), shiftDown :: boolean(),~n"
" altDown :: boolean(), metaDown :: boolean(), cmdDown :: boolean()~n"
" }).~n", []),
diff --git a/lib/wx/api_gen/wxapi.conf b/lib/wx/api_gen/wxapi.conf
index b8458e901b..c6a2df29d7 100644
--- a/lib/wx/api_gen/wxapi.conf
+++ b/lib/wx/api_gen/wxapi.conf
@@ -844,7 +844,7 @@
'GetItemSpacing','GetItemState',
'GetItemText','GetItemTextColour',
'GetNextItem','GetSelectedItemCount','GetTextColour','GetTopItem',
- 'GetViewRect',{'HitTest',[{"pSubItem",nowhere}, {"flags", in}]},
+ 'GetViewRect',{'HitTest',[{"pSubItem",out}]},
'InsertColumn','InsertItem',
%%'OnGetItemAttr', 'OnGetItemImage','OnGetItemText',
'RefreshItem','RefreshItems','ScrollList',
diff --git a/lib/wx/c_src/gen/wxe_funcs.cpp b/lib/wx/c_src/gen/wxe_funcs.cpp
index 03b0baf875..059cee59f4 100644
--- a/lib/wx/c_src/gen/wxe_funcs.cpp
+++ b/lib/wx/c_src/gen/wxe_funcs.cpp
@@ -15631,14 +15631,18 @@ case wxListCtrl_GetViewRect: { // wxListCtrl::GetViewRect
break;
}
case wxListCtrl_HitTest: { // wxListCtrl::HitTest
+ int flags;
+ long pSubItem;
wxListCtrl *This = (wxListCtrl *) getPtr(bp,memenv); bp += 4;
int * pointX = (int *) bp; bp += 4;
int * pointY = (int *) bp; bp += 4;
wxPoint point = wxPoint(*pointX,*pointY);
- int * flags = (int *) bp; bp += 4;
if(!This) throw wxe_badarg(0);
- long Result = This->HitTest(point,*flags);
+ long Result = This->HitTest(point,flags,&pSubItem);
rt.addInt(Result);
+ rt.addInt(flags);
+ rt.addInt(pSubItem);
+ rt.addTupleCount(3);
break;
}
case wxListCtrl_InsertColumn_2: { // wxListCtrl::InsertColumn
diff --git a/lib/wx/include/wx.hrl b/lib/wx/include/wx.hrl
index 333ceca50c..44df57898a 100644
--- a/lib/wx/include/wx.hrl
+++ b/lib/wx/include/wx.hrl
@@ -353,7 +353,7 @@
%% Hardcoded Records
-record(wxMouseState, {x :: integer(), y :: integer(),
- leftDown :: boolean(), middleDown :: boolean, rightDown :: boolean,
+ leftDown :: boolean(), middleDown :: boolean(), rightDown :: boolean(),
controlDown :: boolean(), shiftDown :: boolean(),
altDown :: boolean(), metaDown :: boolean(), cmdDown :: boolean()
}).
diff --git a/lib/wx/src/gen/wxListCtrl.erl b/lib/wx/src/gen/wxListCtrl.erl
index 6750931fdb..ed997710c8 100644
--- a/lib/wx/src/gen/wxListCtrl.erl
+++ b/lib/wx/src/gen/wxListCtrl.erl
@@ -38,7 +38,7 @@
getItemData/2,getItemFont/2,getItemPosition/2,getItemRect/2,getItemRect/3,
getItemSpacing/1,getItemState/3,getItemText/2,getItemTextColour/2,
getNextItem/2,getNextItem/3,getSelectedItemCount/1,getTextColour/1,
- getTopItem/1,getViewRect/1,hitTest/3,insertColumn/3,insertColumn/4,
+ getTopItem/1,getViewRect/1,hitTest/2,insertColumn/3,insertColumn/4,
insertItem/2,insertItem/3,insertItem/4,refreshItem/2,refreshItems/3,
scrollList/3,setBackgroundColour/2,setColumn/3,setColumnWidth/3,setImageList/3,
setItem/2,setItem/4,setItem/5,setItemBackgroundColour/3,setItemColumnImage/4,
@@ -516,13 +516,14 @@ getViewRect(#wx_ref{type=ThisT,ref=ThisRef}) ->
<<ThisRef:32/?UI>>).
%% @doc See <a href="http://www.wxwidgets.org/manuals/2.8.12/wx_wxlistctrl.html#wxlistctrlhittest">external documentation</a>.
--spec hitTest(This, Point, Flags) -> integer() when
- This::wxListCtrl(), Point::{X::integer(), Y::integer()}, Flags::integer().
-hitTest(#wx_ref{type=ThisT,ref=ThisRef},{PointX,PointY},Flags)
- when is_integer(PointX),is_integer(PointY),is_integer(Flags) ->
+-spec hitTest(This, Point) -> Result when
+ Result ::{Res ::integer(), Flags::integer(), PSubItem::integer()},
+ This::wxListCtrl(), Point::{X::integer(), Y::integer()}.
+hitTest(#wx_ref{type=ThisT,ref=ThisRef},{PointX,PointY})
+ when is_integer(PointX),is_integer(PointY) ->
?CLASS(ThisT,wxListCtrl),
wxe_util:call(?wxListCtrl_HitTest,
- <<ThisRef:32/?UI,PointX:32/?UI,PointY:32/?UI,Flags:32/?UI>>).
+ <<ThisRef:32/?UI,PointX:32/?UI,PointY:32/?UI>>).
%% @doc See <a href="http://www.wxwidgets.org/manuals/2.8.12/wx_wxlistctrl.html#wxlistctrlinsertcolumn">external documentation</a>.
%% <br /> Also:<br />
diff --git a/lib/wx/src/gen/wxe_debug.hrl b/lib/wx/src/gen/wxe_debug.hrl
index a2462a6fb2..2ec485cd52 100644
--- a/lib/wx/src/gen/wxe_debug.hrl
+++ b/lib/wx/src/gen/wxe_debug.hrl
@@ -1544,7 +1544,7 @@ wxdebug_table() ->
{1695, {wxListCtrl, getTextColour, 0}},
{1696, {wxListCtrl, getTopItem, 0}},
{1697, {wxListCtrl, getViewRect, 0}},
- {1698, {wxListCtrl, hitTest, 2}},
+ {1698, {wxListCtrl, hitTest, 3}},
{1699, {wxListCtrl, insertColumn_2, 2}},
{1700, {wxListCtrl, insertColumn_3, 3}},
{1701, {wxListCtrl, insertItem_1, 1}},
diff --git a/system/doc/design_principles/spec_proc.xml b/system/doc/design_principles/spec_proc.xml
index 3d7a88da3f..5b156ac263 100644
--- a/system/doc/design_principles/spec_proc.xml
+++ b/system/doc/design_principles/spec_proc.xml
@@ -4,7 +4,7 @@
<chapter>
<header>
<copyright>
- <year>1997</year><year>2014</year>
+ <year>1997</year><year>2016</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
@@ -522,9 +522,36 @@ init(Parent, Name, Module) ->
-module(db).
-behaviour(simple_server).
--export([init/0, handle_req/2, terminate/0]).
+-export([init/1, handle_req/2, terminate/0]).
...</code>
+
+ <p>The contracts specified with <c>-callback</c> attributes in
+ behaviour modules can be further refined by adding <c>-spec</c>
+ attributes in callback modules. This can be useful as
+ <c>-callback</c> contracts are usually generic. The same callback
+ module with contracts for the callbacks:</p>
+
+ <code type="none">
+-module(db).
+-behaviour(simple_server).
+
+-export([init/1, handle_req/2, terminate/0]).
+
+-record(state, {field1 :: [atom()], field2 :: integer()}).
+
+-type state() :: #state{}.
+-type request() :: {'store', term(), term()};
+ {'lookup', term()}.
+
+...
+
+-spec handle_req(request(), state()) -> {'ok', term()}.
+
+...</code>
+
+ <p>Each <c>-spec</c> contract is to be a subtype of the respective
+ <c>-callback</c> contract.</p>
+
</section>
</chapter>
-