summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRaimo Niskanen <raimo@erlang.org>2020-05-11 09:27:05 +0200
committerRaimo Niskanen <raimo@erlang.org>2020-05-11 09:27:05 +0200
commit9639877ea11d6a32ca6e46410b8a48db245b72d8 (patch)
treed7f7cdeb9164d97f86150c77f570e8a8a7f93ac2
parent7c5c500bcb401175b6b431ed1a3b548801a39e9c (diff)
parent7358e4caf143532cbbcc250f00753fe76c5580a0 (diff)
downloaderlang-9639877ea11d6a32ca6e46410b8a48db245b72d8.tar.gz
Merge branch 'raimo/test-case-cuddling'
* raimo/test-case-cuddling: Plug resource leaks for failing test cases
-rw-r--r--lib/stdlib/test/gen_statem_SUITE.erl126
-rw-r--r--lib/stdlib/test/gen_statem_SUITE_data/oc_statem.erl18
2 files changed, 98 insertions, 46 deletions
diff --git a/lib/stdlib/test/gen_statem_SUITE.erl b/lib/stdlib/test/gen_statem_SUITE.erl
index 1bde1b3d74..f40dce5d7a 100644
--- a/lib/stdlib/test/gen_statem_SUITE.erl
+++ b/lib/stdlib/test/gen_statem_SUITE.erl
@@ -453,19 +453,24 @@ stop7(Config) ->
stop8(Config) ->
Node = gen_statem_stop8,
{ok,NodeName} = ct_slave:start(Node),
- Dir = filename:dirname(code:which(?MODULE)),
- rpc:call(NodeName, code, add_path, [Dir]),
- {ok,Pid} =
- rpc:call(
- NodeName, gen_statem,start,
- [?MODULE,start_arg(Config, []),[]]),
- ok = gen_statem:stop(Pid),
- false = rpc:call(NodeName, erlang, is_process_alive, [Pid]),
- noproc =
- ?EXPECT_FAILURE(gen_statem:stop(Pid), Reason1),
- {ok,NodeName} = ct_slave:stop(Node),
+ Statem =
+ try
+ Dir = filename:dirname(code:which(?MODULE)),
+ rpc:block_call(NodeName, code, add_path, [Dir]),
+ {ok,Pid} =
+ rpc:block_call(
+ NodeName, gen_statem,start,
+ [?MODULE,start_arg(Config, []),[]]),
+ ok = gen_statem:stop(Pid),
+ false = rpc:block_call(NodeName, erlang, is_process_alive, [Pid]),
+ noproc =
+ ?EXPECT_FAILURE(gen_statem:stop(Pid), Reason1),
+ Pid
+ after
+ {ok,NodeName} = ct_slave:stop(Node)
+ end,
{{nodedown,NodeName},{sys,terminate,_}} =
- ?EXPECT_FAILURE(gen_statem:stop(Pid), Reason2),
+ ?EXPECT_FAILURE(gen_statem:stop(Statem), Reason2),
ok.
%% Registered name on remote node
@@ -474,21 +479,26 @@ stop9(Config) ->
LocalSTM = {local,Name},
Node = gen_statem__stop9,
{ok,NodeName} = ct_slave:start(Node),
- STM = {Name,NodeName},
- Dir = filename:dirname(code:which(?MODULE)),
- rpc:call(NodeName, code, add_path, [Dir]),
- {ok,Pid} =
- rpc:call(
- NodeName, gen_statem, start,
- [LocalSTM,?MODULE,start_arg(Config, []),[]]),
- ok = gen_statem:stop(STM),
- undefined = rpc:call(NodeName,erlang,whereis,[Name]),
- false = rpc:call(NodeName,erlang,is_process_alive,[Pid]),
- noproc =
- ?EXPECT_FAILURE(gen_statem:stop(STM), Reason1),
- {ok,NodeName} = ct_slave:stop(Node),
+ Statem =
+ try
+ STM = {Name,NodeName},
+ Dir = filename:dirname(code:which(?MODULE)),
+ rpc:block_call(NodeName, code, add_path, [Dir]),
+ {ok,Pid} =
+ rpc:block_call(
+ NodeName, gen_statem, start,
+ [LocalSTM,?MODULE,start_arg(Config, []),[]]),
+ ok = gen_statem:stop(STM),
+ undefined = rpc:block_call(NodeName,erlang,whereis,[Name]),
+ false = rpc:block_call(NodeName,erlang,is_process_alive,[Pid]),
+ noproc =
+ ?EXPECT_FAILURE(gen_statem:stop(STM), Reason1),
+ STM
+ after
+ {ok,NodeName} = ct_slave:stop(Node)
+ end,
{{nodedown,NodeName},{sys,terminate,_}} =
- ?EXPECT_FAILURE(gen_statem:stop(STM), Reason2),
+ ?EXPECT_FAILURE(gen_statem:stop(Statem), Reason2),
ok.
%% Globally registered name on remote node
@@ -496,18 +506,21 @@ stop10(Config) ->
Node = gen_statem_stop10,
STM = {global,to_stop},
{ok,NodeName} = ct_slave:start(Node),
- Dir = filename:dirname(code:which(?MODULE)),
- rpc:call(NodeName,code,add_path,[Dir]),
- {ok,Pid} =
- rpc:call(
- NodeName, gen_statem, start,
- [STM,?MODULE,start_arg(Config, []),[]]),
- global:sync(),
- ok = gen_statem:stop(STM),
- false = rpc:call(NodeName, erlang, is_process_alive, [Pid]),
- noproc =
- ?EXPECT_FAILURE(gen_statem:stop(STM), Reason1),
- {ok,NodeName} = ct_slave:stop(Node),
+ try
+ Dir = filename:dirname(code:which(?MODULE)),
+ rpc:block_call(NodeName,code,add_path,[Dir]),
+ {ok,Pid} =
+ rpc:block_call(
+ NodeName, gen_statem, start,
+ [STM,?MODULE,start_arg(Config, []),[]]),
+ global:sync(),
+ ok = gen_statem:stop(STM),
+ false = rpc:block_call(NodeName, erlang, is_process_alive, [Pid]),
+ noproc =
+ ?EXPECT_FAILURE(gen_statem:stop(STM), Reason1)
+ after
+ {ok,NodeName} = ct_slave:stop(Node)
+ end,
noproc =
?EXPECT_FAILURE(gen_statem:stop(STM), Reason2),
ok.
@@ -2340,13 +2353,13 @@ init(stop_shutdown) ->
{stop,shutdown};
init(sleep) ->
?t:sleep(1000),
- {ok,idle,data};
+ init_sup({ok,idle,data});
init(hiber) ->
- {ok,hiber_idle,[]};
+ init_sup({ok,hiber_idle,[]});
init(hiber_now) ->
- {ok,hiber_idle,[],[hibernate]};
+ init_sup({ok,hiber_idle,[],[hibernate]});
init({data, Data}) ->
- {ok,idle,Data};
+ init_sup({ok,idle,Data});
init({callback_mode,CallbackMode,Arg}) ->
ets:new(?MODULE, [named_table,private]),
ets:insert(?MODULE, {callback_mode,CallbackMode}),
@@ -2356,14 +2369,35 @@ init({map_statem,#{init := Init}=Machine,Modes}) ->
ets:insert(?MODULE, {callback_mode,[handle_event_function|Modes]}),
case Init() of
{ok,State,Data,Ops} ->
- {ok,State,[Data|Machine],Ops};
+ init_sup({ok,State,[Data|Machine],Ops});
{ok,State,Data} ->
- {ok,State,[Data|Machine]};
+ init_sup({ok,State,[Data|Machine]});
Other ->
- Other
+ init_sup(Other)
end;
init([]) ->
- {ok,idle,data}.
+ init_sup({ok,idle,data}).
+
+%% Supervise state machine parent i.e the test case, and if it dies
+%% (fails due to some reason), kill the state machine,
+%% just to not leak resources (process, name, ETS table, etc...)
+%%
+init_sup(Result) ->
+ Parent = gen:get_parent(),
+ Statem = self(),
+ _Supervisor =
+ spawn(
+ fun () ->
+ StatemRef = monitor(process, Statem),
+ ParentRef = monitor(process, Parent),
+ receive
+ {'DOWN', StatemRef, _, _, Reason} ->
+ exit(Reason);
+ {'DOWN', ParentRef, _, _, _} ->
+ exit(Statem, kill)
+ end
+ end),
+ Result.
callback_mode() ->
try ets:lookup(?MODULE, callback_mode) of
diff --git a/lib/stdlib/test/gen_statem_SUITE_data/oc_statem.erl b/lib/stdlib/test/gen_statem_SUITE_data/oc_statem.erl
index 1bcd08867f..1de7de527b 100644
--- a/lib/stdlib/test/gen_statem_SUITE_data/oc_statem.erl
+++ b/lib/stdlib/test/gen_statem_SUITE_data/oc_statem.erl
@@ -31,6 +31,24 @@ start(Opts) ->
gen_statem:start({local, ?MODULE}, ?MODULE, [], Opts).
init([]) ->
+ %% Supervise state machine parent i.e the test case, and if it dies
+ %% (fails due to some reason), kill the state machine,
+ %% just to not leak resources (process, name, ETS table, etc...)
+ %%
+ Parent = gen:get_parent(),
+ Statem = self(),
+ _Supervisor =
+ spawn(
+ fun () ->
+ StatemRef = monitor(process, Statem),
+ ParentRef = monitor(process, Parent),
+ receive
+ {'DOWN', StatemRef, _, _, Reason} ->
+ exit(Reason);
+ {'DOWN', ParentRef, _, _, _} ->
+ exit(Statem, kill)
+ end
+ end),
{ok, start, #{}}.
callback_mode() ->