diff options
author | Tim Watson <tim@rabbitmq.com> | 2012-09-03 15:31:48 +0100 |
---|---|---|
committer | Tim Watson <tim@rabbitmq.com> | 2012-09-03 15:31:48 +0100 |
commit | d43da6ef1a8de96ae08f48bde55b0e38fa6d2e2d (patch) | |
tree | 767ded57b62247ff338b4afc64bf35b0e474d1ae /src/supervisor2_tests.erl | |
parent | 6934fac0e30d9d9c4f179c38598aaa78a76dced4 (diff) | |
download | rabbitmq-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.erl | 100 |
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(). + |