1: %% 2: %% %CopyrightBegin% 3: %% 4: %% Copyright Ericsson AB 1996-2011. All Rights Reserved. 5: %% 6: %% The contents of this file are subject to the Erlang Public License, 7: %% Version 1.1, (the "License"); you may not use this file except in 8: %% compliance with the License. You should have received a copy of the 9: %% Erlang Public License along with this software. If not, it can be 10: %% retrieved online at http://www.erlang.org/. 11: %% 12: %% Software distributed under the License is distributed on an "AS IS" 13: %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See 14: %% the License for the specific language governing rights and limitations 15: %% under the License. 16: %% 17: %% %CopyrightEnd% 18: %% 19: -module(supervisor_bridge_SUITE). 20: -export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, 21: init_per_group/2,end_per_group/2,starting/1, 22: mini_terminate/1,mini_die/1,badstart/1, 23: simple_global_supervisor/1]). 24: -export([client/1,init/1,internal_loop_init/1,terminate/2,server9212/0]). 25: 26: -include_lib("test_server/include/test_server.hrl"). 27: -define(bridge_name,supervisor_bridge_SUITE_server). 28: -define(work_bridge_name,work_supervisor_bridge_SUITE_server). 29: 30: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 31: 32: suite() -> [{ct_hooks,[ts_install_cth]}]. 33: 34: all() -> 35: [starting, mini_terminate, mini_die, badstart, simple_global_supervisor]. 36: 37: groups() -> 38: []. 39: 40: init_per_suite(Config) -> 41: Config. 42: 43: end_per_suite(_Config) -> 44: ok. 45: 46: init_per_group(_GroupName, Config) -> 47: Config. 48: 49: end_per_group(_GroupName, Config) -> 50: Config. 51: 52: 53: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 54: 55: starting(suite) -> []; 56: starting(Config) when is_list(Config) -> 57: process_flag(trap_exit,true), 58: 59: ?line ignore = start(1), 60: ?line {error,testing} = start(2), 61: ok. 62: 63: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 64: 65: mini_terminate(suite) -> []; 66: mini_terminate(Config) when is_list(Config) -> 67: miniappl(1), 68: ok. 69: 70: mini_die(suite) -> []; 71: mini_die(Config) when is_list(Config) -> 72: miniappl(2), 73: ok. 74: 75: miniappl(N) -> 76: process_flag(trap_exit,true), 77: ?line {ok,Server} = start(3), 78: ?line Client = spawn_link(?MODULE,client,[N]), 79: ?line Handle = test_server:timetrap(2000), 80: ?line miniappl_loop(Client,Server), 81: ?line test_server:timetrap_cancel(Handle). 82: 83: miniappl_loop([],[]) -> 84: ok; 85: miniappl_loop(Client,Server) -> 86: io:format("Client ~p, Server ~p\n",[Client,Server]), 87: receive 88: {'EXIT',Client,_} -> 89: ?line miniappl_loop([],Server); 90: {'EXIT',Server,killed} -> %% terminate 91: ?line miniappl_loop(Client,[]); 92: {'EXIT',Server,died} -> %% die 93: ?line miniappl_loop(Client,[]); 94: {dying,_Reason} -> 95: ?line miniappl_loop(Client, Server); 96: Other -> 97: ?line exit({failed,Other}) 98: end. 99: 100: %%%%%%%%%%%%%%%%%%%% 101: % Client 102: 103: client(N) -> 104: io:format("Client starting...\n"), 105: ok = public_request(), 106: case N of 107: 1 -> public_kill(); 108: 2 -> ?work_bridge_name ! die 109: end, 110: io:format("Killed server, terminating client...\n"), 111: exit(fine). 112: 113: %%%%%%%%%%%%%%%%%%%% 114: % Non compliant server 115: 116: start(N) -> 117: supervisor_bridge:start_link({local,?bridge_name},?MODULE,N). 118: 119: public_request() -> 120: ?work_bridge_name ! {non_compliant_message,self()}, 121: io:format("Client waiting for answer...\n"), 122: receive 123: non_compliant_answer -> 124: ok 125: end, 126: io:format("Client got answer...\n"). 127: 128: public_kill() -> 129: %% This func knows about supervisor_bridge 130: exit(whereis(?work_bridge_name),kill). 131: 132: init(1) -> 133: ignore; 134: init(2) -> 135: {error,testing}; 136: init(3) -> 137: %% This func knows about supervisor_bridge 138: InternalPid = spawn_link(?MODULE,internal_loop_init,[self()]), 139: receive 140: {InternalPid,init_done} -> 141: {ok,InternalPid,self()} 142: end; 143: init({4,Result}) -> 144: Result. 145: 146: internal_loop_init(Parent) -> 147: register(?work_bridge_name, self()), 148: Parent ! {self(),init_done}, 149: internal_loop({Parent,self()}). 150: 151: internal_loop(State) -> 152: receive 153: {non_compliant_message,From} -> 154: io:format("Got request from ~p\n",[From]), 155: From ! non_compliant_answer, 156: internal_loop(State); 157: die -> 158: exit(died) 159: end. 160: 161: terminate(Reason,{Parent,Worker}) -> 162: %% This func knows about supervisor_bridge 163: io:format("Terminating bridge...\n"), 164: exit(Worker,kill), 165: Parent ! {dying,Reason}, 166: anything; 167: terminate(_Reason, _State) -> 168: any. 169: 170: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 171: 172: badstart(suite) -> []; 173: badstart(doc) -> "Test various bad ways of starting a supervisor bridge."; 174: badstart(Config) when is_list(Config) -> 175: ?line Dog = test_server:timetrap(test_server:minutes(1)), 176: 177: %% Various bad arguments. 178: 179: ?line {'EXIT',_} = 180: (catch supervisor_bridge:start_link({xxx,?bridge_name},?MODULE,1)), 181: ?line {'EXIT',_} = 182: (catch supervisor_bridge:start_link({local,"foo"},?MODULE,1)), 183: ?line {'EXIT',_} = 184: (catch supervisor_bridge:start_link(?bridge_name,?MODULE,1)), 185: ?line [] = test_server:messages_get(), % No messages waiting 186: 187: %% Already started. 188: 189: ?line process_flag(trap_exit, true), 190: ?line {ok,Pid} = 191: supervisor_bridge:start_link({local,?bridge_name},?MODULE,3), 192: ?line {error,{already_started,Pid}} = 193: supervisor_bridge:start_link({local,?bridge_name},?MODULE,3), 194: ?line public_kill(), 195: 196: %% We used to wait 1 ms before retrieving the message queue, 197: %% but that might not always be enough if the machine is overloaded. 198: ?line receive 199: {'EXIT', Pid, killed} -> ok 200: end, 201: ?line test_server:timetrap_cancel(Dog), 202: ok. 203: 204: %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 205: %% OTP-9212. Restart of global supervisor. 206: 207: simple_global_supervisor(suite) -> []; 208: simple_global_supervisor(doc) -> "Globally registered supervisor."; 209: simple_global_supervisor(Config) when is_list(Config) -> 210: ?line Dog = test_server:timetrap({seconds,10}), 211: 212: Child = {child, {?MODULE,server9212,[]}, permanent, 2000, worker, []}, 213: InitResult = {ok, {{one_for_all,3,60}, [Child]}}, 214: {ok, Sup} = 215: supervisor:start_link({local,bridge9212}, ?MODULE, {4,InitResult}), 216: 217: BN_1 = global:whereis_name(?bridge_name), 218: ?line exit(BN_1, kill), 219: timer:sleep(200), 220: BN_2 = global:whereis_name(?bridge_name), 221: ?line true = is_pid(BN_2), 222: ?line true = BN_1 =/= BN_2, 223: 224: ?line process_flag(trap_exit, true), 225: exit(Sup, kill), 226: ?line receive {'EXIT', Sup, killed} -> ok end, 227: ?line test_server:timetrap_cancel(Dog), 228: ok. 229: 230: server9212() -> 231: supervisor_bridge:start_link({global,?bridge_name}, ?MODULE, 3).