summaryrefslogtreecommitdiff
path: root/src/supervisor2_tests.erl
diff options
context:
space:
mode:
authorTim Watson <tim@rabbitmq.com>2012-09-03 15:31:48 +0100
committerTim Watson <tim@rabbitmq.com>2012-09-03 15:31:48 +0100
commitd43da6ef1a8de96ae08f48bde55b0e38fa6d2e2d (patch)
tree767ded57b62247ff338b4afc64bf35b0e474d1ae /src/supervisor2_tests.erl
parent6934fac0e30d9d9c4f179c38598aaa78a76dced4 (diff)
downloadrabbitmq-server-d43da6ef1a8de96ae08f48bde55b0e38fa6d2e2d.tar.gz
Test that simple_one_for_one_terminate shutdowns no longer deadlock and
handle reporting errors not caught during shutdown (e.g., 'killed' pids)
Diffstat (limited to 'src/supervisor2_tests.erl')
-rw-r--r--src/supervisor2_tests.erl100
1 files changed, 100 insertions, 0 deletions
diff --git a/src/supervisor2_tests.erl b/src/supervisor2_tests.erl
new file mode 100644
index 00000000..c4916791
--- /dev/null
+++ b/src/supervisor2_tests.erl
@@ -0,0 +1,100 @@
+%% The contents of this file are subject to the Mozilla Public License
+%% Version 1.1 (the "License"); you may not use this file except in
+%% compliance with the License. You may obtain a copy of the License at
+%% http://www.mozilla.org/MPL/
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
+%% License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% The Original Code is RabbitMQ.
+%%
+%% The Initial Developer of the Original Code is VMware, Inc.
+%% Copyright (c) 2011-2012 VMware, Inc. All rights reserved.
+%%
+
+-module(supervisor2_tests).
+-behaviour(supervisor2).
+
+-export([test_all/0, start_sup/0, start_link/0, start_child/0]).
+-export([init/1]).
+
+-compile(export_all).
+
+-include_lib("eunit/include/eunit.hrl").
+
+test_all() ->
+ eunit:test(supervisor2, [verbose]).
+
+terminate_simple_children_without_deadlock_test_() ->
+ [{setup, fun init_supervisor/0,
+ {with, [fun ensure_children_are_alive/1,
+ fun shutdown_and_verify_all_children_died/1]}},
+ {setup, fun init_supervisor/0,
+ {with, [fun shutdown_whilst_interleaving_exits_occur/1]}}].
+
+%%
+%% Public (test facing) API
+%%
+
+start_sup() ->
+ supervisor2:start_link({local, ?MODULE}, ?MODULE, []).
+
+start_link() ->
+ Pid = spawn_link(fun loop_infinity/0),
+ {ok, Pid}.
+
+start_child() ->
+ {ok, Pid} = supervisor2:start_child(?MODULE, []),
+ Pid.
+
+%%
+%% supervisor2 callbacks
+%%
+
+init([parent]) ->
+ {ok, {{one_for_one, 0, 1},
+ [{test_sup, {?MODULE, start_sup, []},
+ transient, 5000, supervisor, [?MODULE]}]}};
+init([]) ->
+ {ok, {{simple_one_for_one_terminate, 0, 1},
+ [{test_worker, {?MODULE, start_link, []},
+ temporary, 1000, worker, []}]}}.
+
+%%
+%% Private API
+%%
+
+ensure_children_are_alive({_, ChildPids}) ->
+ ?assertEqual(true,
+ lists:all(fun erlang:is_process_alive/1, ChildPids)).
+
+shutdown_and_verify_all_children_died({Parent, ChildPids}=State) ->
+ ensure_children_are_alive(State),
+ TestSup = erlang:whereis(?MODULE),
+ ?assertEqual(true, erlang:is_process_alive(TestSup)),
+ ?assertMatch(ok, supervisor2:terminate_child(Parent, test_sup)),
+ ?assertMatch([], [P || P <- ChildPids,
+ erlang:is_process_alive(P)]),
+ ?assertEqual(false, erlang:is_process_alive(TestSup)).
+
+shutdown_whilst_interleaving_exits_occur({Parent, ChildPids}=State) ->
+ ensure_children_are_alive(State),
+ TestPid = self(),
+ Ref = erlang:make_ref(),
+ spawn(fun() ->
+ TestPid ! {Ref, supervisor2:terminate_child(Parent, test_sup)}
+ end),
+ [exit(P, kill) || P <- ChildPids],
+ receive {Ref, Res} ->
+ ?assertEqual(ok, Res)
+ end.
+
+init_supervisor() ->
+ {ok, Pid} = supervisor2:start_link(?MODULE, [parent]),
+ {Pid, [start_child() || _ <- lists:seq(1, 100)]}.
+
+loop_infinity() ->
+ loop_infinity().
+