diff options
Diffstat (limited to 'lib/kernel/test/global_group_SUITE.erl')
-rw-r--r-- | lib/kernel/test/global_group_SUITE.erl | 1415 |
1 files changed, 1415 insertions, 0 deletions
diff --git a/lib/kernel/test/global_group_SUITE.erl b/lib/kernel/test/global_group_SUITE.erl new file mode 100644 index 0000000000..a8b87390eb --- /dev/null +++ b/lib/kernel/test/global_group_SUITE.erl @@ -0,0 +1,1415 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 1998-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% 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. +%% +%% %CopyrightEnd% +%% + +-module(global_group_SUITE). + +-export([all/1]). +-export([start_gg_proc/1, no_gg_proc/1, no_gg_proc_sync/1, compatible/1, + one_grp/1, one_grp_x/1, two_grp/1, hidden_groups/1, test_exit/1]). +-export([init/1, init/2, init2/2, start_proc/1, start_proc_rereg/1]). + +-export([init_per_testcase/2, fin_per_testcase/2]). + +%-compile(export_all). + +-include("test_server.hrl"). + +-define(NODES, [node()|nodes()]). + +-define(UNTIL(Seq), loop_until_true(fun() -> Seq end)). + +all(suite) -> + [start_gg_proc, no_gg_proc, no_gg_proc_sync, + compatible, one_grp, one_grp_x, two_grp, test_exit, + hidden_groups]. + +-define(TESTCASE, testcase_name). +-define(testcase, ?config(?TESTCASE, Config)). + +init_per_testcase(Case, Config) when atom(Case), list(Config) -> + Dog=?t:timetrap(?t:minutes(5)), + [{?TESTCASE, Case}, {watchdog, Dog}|Config]. + +fin_per_testcase(_Func, Config) -> + Dog=?config(watchdog, Config), + ?t:timetrap_cancel(Dog). + +%%----------------------------------------------------------------- +%% Test suites for global groups. +%% Should be started in a CC view with: +%% erl -sname XXX -rsh ctrsh where XXX not in [cp1 .. cpN] +%%----------------------------------------------------------------- + + +start_gg_proc(suite) -> []; +start_gg_proc(doc) -> ["Check that the global_group processes are started automatically. "]; +start_gg_proc(Config) when list(Config) -> + ?line Dog = test_server:timetrap(test_server:seconds(120)), + + ?line Dir = ?config(priv_dir, Config), + ?line File = filename:join(Dir, "global_group.config"), + ?line {ok, Fd}=file:open(File, write), + [Ncp1,Ncp2,Ncp3] = node_names([cp1, cp2, cp3], Config), + ?line config(Fd, Ncp1, Ncp2, Ncp3, "cpx", "cpy", "cpz", "cpq"), + + ?line Cp1nn = node_at(Ncp1), + ?line Cp2nn = node_at(Ncp2), + ?line Cp3nn = node_at(Ncp3), + + ?line {ok, Cp1} = start_node(Ncp1, Config), + ?line {ok, Cp2} = start_node(Ncp2, Config), + ?line {ok, Cp3} = start_node(Ncp3, Config), + + ?line [] = rpc:call(Cp1, global_group, registered_names, [{node, Cp1nn}]), + ?line [] = rpc:call(Cp2, global_group, registered_names, [{node, Cp2nn}]), + ?line [] = rpc:call(Cp3, global_group, registered_names, [{node, Cp3nn}]), + + % stop the nodes, and make sure names are released. + stop_node(Cp1), + stop_node(Cp2), + stop_node(Cp3), + + ?line ?UNTIL(undefined =:= global:whereis_name(test)), + ?line test_server:timetrap_cancel(Dog), + ok. + + + +no_gg_proc(suite) -> []; +no_gg_proc(doc) -> ["Start a system without global groups. Nodes are not " + "synced at start (sync_nodes_optional is not defined)"]; +no_gg_proc(Config) when list(Config) -> + ?line Dog = test_server:timetrap(test_server:seconds(200)), + + ?line Dir = ?config(priv_dir, Config), + ?line File = filename:join(Dir, "no_global_group.config"), + ?line {ok, Fd} = file:open(File, write), + ?line config_no(Fd), + + ?line NN = node_name(atom_to_list(node())), + ?line Cp1nn = list_to_atom("cp1@" ++ NN), + ?line Cp2nn = list_to_atom("cp2@" ++ NN), + ?line Cp3nn = list_to_atom("cp3@" ++ NN), + ?line Cpxnn = list_to_atom("cpx@" ++ NN), + ?line Cpynn = list_to_atom("cpy@" ++ NN), + ?line Cpznn = list_to_atom("cpz@" ++ NN), + + ?line {ok, Cp1} = start_node_no(cp1, Config), + ?line {ok, Cp2} = start_node_no(cp2, Config), + ?line {ok, Cp3} = start_node_no(cp3, Config), + ?line {ok, Cpx} = start_node_no(cpx, Config), + ?line {ok, Cpy} = start_node_no(cpy, Config), + ?line {ok, Cpz} = start_node_no(cpz, Config), + + %% let the nodes know of each other + ?line pong = rpc:call(Cp1, net_adm, ping, [Cp2nn]), + ?line pong = rpc:call(Cp2, net_adm, ping, [Cp3nn]), + ?line pong = rpc:call(Cp3, net_adm, ping, [Cpxnn]), + ?line pong = rpc:call(Cpx, net_adm, ping, [Cpynn]), + ?line pong = rpc:call(Cpy, net_adm, ping, [Cpznn]), + + ?line wait_for_ready_net(), + + ?line [test_server] = rpc:call(Cp1, global_group, registered_names, [{node, Cp1nn}]), + ?line [test_server] = rpc:call(Cp2, global_group, registered_names, [{node, Cp2nn}]), + ?line [test_server] = rpc:call(Cp3, global_group, registered_names, [{node, Cp3nn}]), + ?line [test_server] = rpc:call(Cp1, global_group, registered_names, [{node, Cpxnn}]), + ?line [test_server] = rpc:call(Cp2, global_group, registered_names, [{node, Cpynn}]), + ?line [test_server] = rpc:call(Cp3, global_group, registered_names, [{node, Cpznn}]), + + + % start a proc and register it + ?line {Pid2, yes} = rpc:call(Cp2, ?MODULE, start_proc, [test2]), + + ?line RegNames = lists:sort([test2,test_server]), + + ?line RegNames = + lists:sort( + rpc:call(Cp1, global_group, registered_names, [{node, Cp1nn}])), + ?line RegNames = + lists:sort( + rpc:call(Cp2, global_group, registered_names, [{node, Cp2nn}])), + ?line RegNames = + lists:sort( + rpc:call(Cp3, global_group, registered_names, [{node, Cp3nn}])), + ?line RegNames = + lists:sort( + rpc:call(Cp1, global_group, registered_names, [{node, Cpxnn}])), + ?line RegNames = + lists:sort( + rpc:call(Cp2, global_group, registered_names, [{node, Cpynn}])), + ?line RegNames = + lists:sort( + rpc:call(Cp3, global_group, registered_names, [{node, Cpznn}])), + + + ?line undefined = rpc:call(Cp3, global_group, global_groups, []), + + ?line Own_nodes_should = [node(), Cp1nn, Cp2nn, Cp3nn, + Cpxnn, Cpynn, Cpznn], + ?line Own_nodes = rpc:call(Cp3, global_group, own_nodes, []), + ?line true = (Own_nodes -- Own_nodes_should) =:= [], + ?line true = (Own_nodes_should -- Own_nodes) =:= [], + + ?line Pid2 = rpc:call(Cp1, global_group, send, [test2, {ping, self()}]), + ?line receive + {pong, Cp2} -> ok + after + 2000 -> test_server:fail(timeout2) + end, + ?line Pid2 = rpc:call(Cp2, global_group, send, [test2, {ping, self()}]), + ?line receive + {pong, Cp2} -> ok + after + 2000 -> test_server:fail(timeout3) + end, + ?line Pid2 = rpc:call(Cpz, global_group, send, [test2, {ping, self()}]), + ?line receive + {pong, Cp2} -> ok + after + 2000 -> test_server:fail(timeout4) + end, + + + % start a proc and register it + ?line {PidX, yes} = rpc:call(Cpx, ?MODULE, start_proc, [test]), + + + %%------------------------------------ + %% Test monitor nodes + %%------------------------------------ + ?line Pid2 = rpc:call(Cp1, global_group, send, [{node, Cp2nn}, test2, monitor]), + ?line PidX = rpc:call(Cpx, global_group, send, [{node, Cpxnn}, test, monitor]), + + + % Kill node Cp1 + ?line Pid2 = + rpc:call(Cp2, global_group, send, [{node, Cp2nn}, test2, {wait_nodedown, Cp1}]), + ?line PidX = + rpc:call(Cpx, global_group, send, [{node, Cpxnn}, test, {wait_nodedown, Cp1}]), + ?line test_server:sleep(100), + ?line stop_node(Cp1), + ?line test_server:sleep(1000), + + ?line ok = assert_loop(Cp2, Cp2nn, test2, Pid2, loop), + ?line ok = assert_loop(Cpx, Cpxnn, test, PidX, loop), + + % Kill node Cpz + ?line Pid2 = + rpc:call(Cp2, global_group, send, [{node, Cp2nn}, test2, {wait_nodedown, Cpz}]), + ?line PidX = + rpc:call(Cpx, global_group, send, [{node, Cpxnn}, test, {wait_nodedown, Cpz}]), + ?line test_server:sleep(100), + ?line stop_node(Cpz), + ?line test_server:sleep(1000), + + ?line ok = assert_loop(Cp2, Cp2nn, test2, Pid2, loop), + ?line ok = assert_loop(Cpx, Cpxnn, test, PidX, loop), + + % Restart node Cp1 + ?line Pid2 = + rpc:call(Cp2, global_group, send, [{node, Cp2nn}, test2, {wait_nodeup, Cp1}]), + ?line PidX = + rpc:call(Cpx, global_group, send, [{node, Cpxnn}, test, {wait_nodeup, Cp1}]), + ?line {ok, Cp1} = start_node_no(cp1, Config), + ?line pong = rpc:call(Cp2, net_adm, ping, [Cp1nn]), + ?line pong = rpc:call(Cpx, net_adm, ping, [Cp1nn]), + ?line wait_for_ready_net(), + + ?line ok = assert_loop(Cp2, Cp2nn, test2, Pid2, loop), + ?line ok = assert_loop(Cpx, Cpxnn, test, PidX, loop), + + % Restart node Cpz + ?line Pid2 = + rpc:call(Cp2, global_group, send, [{node, Cp2nn}, test2, {wait_nodeup, Cpz}]), + ?line PidX = + rpc:call(Cpx, global_group, send, [{node, Cpxnn}, test, {wait_nodeup, Cpz}]), + ?line {ok, Cpz} = start_node_no(cpz, Config), + ?line pong = rpc:call(Cp2, net_adm, ping, [Cpznn]), + ?line pong = rpc:call(Cpx, net_adm, ping, [Cpznn]), + ?line wait_for_ready_net(), + + ?line ok = assert_loop(Cp2, Cp2nn, test2, Pid2, loop), + ?line ok = assert_loop(Cpx, Cpxnn, test, PidX, loop), + + % stop the nodes, and make sure names are released. + stop_node(Cp1), + stop_node(Cp2), + stop_node(Cp3), + stop_node(Cpx), + stop_node(Cpy), + stop_node(Cpz), + + ?line ?UNTIL(undefined =:= global:whereis_name(test)), + ?line test_server:timetrap_cancel(Dog), + ok. + + + + +no_gg_proc_sync(suite) -> []; +no_gg_proc_sync(doc) -> + ["Start a system without global groups, but syncing the nodes by using " + "sync_nodes_optional."]; +no_gg_proc_sync(Config) when list(Config) -> + ?line Dog = test_server:timetrap(test_server:seconds(200)), + + ?line Dir = ?config(priv_dir, Config), + ?line File = filename:join(Dir, "no_global_group_sync.config"), + ?line {ok, Fd} = file:open(File, write), + + [Ncp1,Ncp2,Ncp3,Ncpx,Ncpy,Ncpz] = + node_names([cp1,cp2,cp3,cpx,cpy,cpz], Config), + ?line config_sync(Fd, Ncp1, Ncp2, Ncp3, Ncpx, Ncpy, Ncpz), + + ?line Cp1nn = node_at(Ncp1), + ?line Cp2nn = node_at(Ncp2), + ?line Cp3nn = node_at(Ncp3), + ?line Cpxnn = node_at(Ncpx), + ?line Cpynn = node_at(Ncpy), + ?line Cpznn = node_at(Ncpz), + + ?line {ok, Cp1} = start_node_no2(Ncp1, Config), + ?line {ok, Cp2} = start_node_no2(Ncp2, Config), + ?line {ok, Cp3} = start_node_no2(Ncp3, Config), + ?line {ok, Cpx} = start_node_no2(Ncpx, Config), + ?line {ok, Cpy} = start_node_no2(Ncpy, Config), + ?line {ok, Cpz} = start_node_no2(Ncpz, Config), + + %% let the nodes know of each other + ?line pong = rpc:call(Cp1, net_adm, ping, [Cp2nn]), + ?line pong = rpc:call(Cp2, net_adm, ping, [Cp3nn]), + ?line pong = rpc:call(Cp3, net_adm, ping, [Cpxnn]), + ?line pong = rpc:call(Cpx, net_adm, ping, [Cpynn]), + ?line pong = rpc:call(Cpy, net_adm, ping, [Cpznn]), + + ?line wait_for_ready_net(), + + ?line [test_server] = rpc:call(Cp1, global_group, registered_names, [{node, Cp1nn}]), + ?line [test_server] = rpc:call(Cp2, global_group, registered_names, [{node, Cp2nn}]), + ?line [test_server] = rpc:call(Cp3, global_group, registered_names, [{node, Cp3nn}]), + ?line [test_server] = rpc:call(Cp1, global_group, registered_names, [{node, Cpxnn}]), + ?line [test_server] = rpc:call(Cp2, global_group, registered_names, [{node, Cpynn}]), + ?line [test_server] = rpc:call(Cp3, global_group, registered_names, [{node, Cpznn}]), + + + % start a proc and register it + ?line {Pid2, yes} = rpc:call(Cp2, ?MODULE, start_proc, [test2]), + + ?line RegNames = lists:sort([test2,test_server]), + + ?line RegNames = + lists:sort( + rpc:call(Cp1, global_group, registered_names, [{node, Cp1nn}])), + ?line RegNames = + lists:sort( + rpc:call(Cp2, global_group, registered_names, [{node, Cp2nn}])), + ?line RegNames = + lists:sort( + rpc:call(Cp3, global_group, registered_names, [{node, Cp3nn}])), + ?line RegNames = + lists:sort( + rpc:call(Cp1, global_group, registered_names, [{node, Cpxnn}])), + ?line RegNames = + lists:sort( + rpc:call(Cp2, global_group, registered_names, [{node, Cpynn}])), + ?line RegNames = + lists:sort( + rpc:call(Cp3, global_group, registered_names, [{node, Cpznn}])), + + + ?line undefined = rpc:call(Cp3, global_group, global_groups, []), + + ?line Own_nodes_should = [node(), Cp1nn, Cp2nn, Cp3nn, + Cpxnn, Cpynn, Cpznn], + ?line Own_nodes = rpc:call(Cp3, global_group, own_nodes, []), + ?line true = (Own_nodes -- Own_nodes_should) =:= [], + ?line true = (Own_nodes_should -- Own_nodes) =:= [], + + ?line Pid2 = rpc:call(Cp1, global_group, send, [test2, {ping, self()}]), + ?line receive + {pong, Cp2} -> ok + after + 2000 -> test_server:fail(timeout2) + end, + ?line Pid2 = rpc:call(Cp2, global_group, send, [test2, {ping, self()}]), + ?line receive + {pong, Cp2} -> ok + after + 2000 -> test_server:fail(timeout3) + end, + ?line Pid2 = rpc:call(Cpz, global_group, send, [test2, {ping, self()}]), + ?line receive + {pong, Cp2} -> ok + after + 2000 -> test_server:fail(timeout4) + end, + + + % start a proc and register it + ?line {PidX, yes} = rpc:call(Cpx, ?MODULE, start_proc, [test]), + + + %%------------------------------------ + %% Test monitor nodes + %%------------------------------------ + ?line Pid2 = rpc:call(Cp1, global_group, send, [{node, Cp2nn}, test2, monitor]), + ?line PidX = rpc:call(Cpx, global_group, send, [{node, Cpxnn}, test, monitor]), + + + % Kill node Cp1 + ?line Pid2 = + rpc:call(Cp2, global_group, send, [{node, Cp2nn}, test2, {wait_nodedown, Cp1}]), + ?line PidX = + rpc:call(Cpx, global_group, send, [{node, Cpxnn}, test, {wait_nodedown, Cp1}]), + ?line test_server:sleep(100), + ?line stop_node(Cp1), + ?line test_server:sleep(1000), + + ?line ok = assert_loop(Cp2, Cp2nn, test2, Pid2, loop), + ?line ok = assert_loop(Cpx, Cpxnn, test, PidX, loop), + + % Kill node Cpz + ?line Pid2 = + rpc:call(Cp2, global_group, send, [{node, Cp2nn}, test2, {wait_nodedown, Cpz}]), + ?line PidX = + rpc:call(Cpx, global_group, send, [{node, Cpxnn}, test, {wait_nodedown, Cpz}]), + ?line test_server:sleep(100), + ?line stop_node(Cpz), + ?line test_server:sleep(1000), + + ?line ok = assert_loop(Cp2, Cp2nn, test2, Pid2, loop), + ?line ok = assert_loop(Cpx, Cpxnn, test, PidX, loop), + + % Restart node Cp1 + ?line Pid2 = + rpc:call(Cp2, global_group, send, [{node, Cp2nn}, test2, {wait_nodeup, Cp1}]), + ?line PidX = + rpc:call(Cpx, global_group, send, [{node, Cpxnn}, test, {wait_nodeup, Cp1}]), + ?line {ok, Cp1} = start_node_no2(Ncp1, Config), + ?line pong = rpc:call(Cp2, net_adm, ping, [Cp1nn]), + ?line pong = rpc:call(Cpx, net_adm, ping, [Cp1nn]), + ?line wait_for_ready_net(), + + ?line ok = assert_loop(Cp2, Cp2nn, test2, Pid2, loop), + ?line ok = assert_loop(Cpx, Cpxnn, test, PidX, loop), + + % Restart node Cpz + ?line Pid2 = + rpc:call(Cp2, global_group, send, [{node, Cp2nn}, test2, {wait_nodeup, Cpz}]), + ?line PidX = + rpc:call(Cpx, global_group, send, [{node, Cpxnn}, test, {wait_nodeup, Cpz}]), + ?line {ok, Cpz} = start_node_no2(Ncpz, Config), + ?line pong = rpc:call(Cp2, net_adm, ping, [Cpznn]), + ?line pong = rpc:call(Cpx, net_adm, ping, [Cpznn]), + ?line wait_for_ready_net(), + + ?line ok = assert_loop(Cp2, Cp2nn, test2, Pid2, loop), + ?line ok = assert_loop(Cpx, Cpxnn, test, PidX, loop), + + % stop the nodes, and make sure names are released. + stop_node(Cp1), + stop_node(Cp2), + stop_node(Cp3), + stop_node(Cpx), + stop_node(Cpy), + stop_node(Cpz), + + ?line ?UNTIL(undefined =:= global:whereis_name(test)), + ?line test_server:timetrap_cancel(Dog), + ok. + + + + +compatible(suite) -> []; +compatible(doc) -> + ["Check that a system without global groups is compatible with the old R4 system."]; +compatible(Config) when list(Config) -> + ?line Dog = test_server:timetrap(test_server:seconds(200)), + + ?line Dir = ?config(priv_dir, Config), + ?line File = filename:join(Dir, "global_group_comp.config"), + ?line {ok, Fd} = file:open(File, write), + + [Ncp1,Ncp2,Ncp3,Ncpx,Ncpy,Ncpz] = + node_names([cp1,cp2,cp3,cpx,cpy,cpz], Config), + ?line config_comp(Fd, Ncp1, Ncp2, Ncp3, Ncpx, Ncpy, Ncpz), + + ?line Cp1nn = node_at(Ncp1), + ?line Cp2nn = node_at(Ncp2), + ?line Cp3nn = node_at(Ncp3), + ?line Cpxnn = node_at(Ncpx), + ?line Cpynn = node_at(Ncpy), + ?line Cpznn = node_at(Ncpz), + + ?line {ok, Cp1} = start_node_comp(Ncp1, Config), + ?line {ok, Cp2} = start_node_comp(Ncp2, Config), + ?line {ok, Cp3} = start_node_comp(Ncp3, Config), + ?line {ok, Cpx} = start_node_comp(Ncpx, Config), + ?line {ok, Cpy} = start_node_comp(Ncpy, Config), + ?line {ok, Cpz} = start_node_comp(Ncpz, Config), + + %% let the nodes know of each other + ?line pong = rpc:call(Cp1, net_adm, ping, [Cp2nn]), + ?line pong = rpc:call(Cp2, net_adm, ping, [Cp3nn]), + ?line pong = rpc:call(Cp3, net_adm, ping, [Cpxnn]), + ?line pong = rpc:call(Cpx, net_adm, ping, [Cpynn]), + ?line pong = rpc:call(Cpy, net_adm, ping, [Cpznn]), + + ?line wait_for_ready_net(), + + ?line [test_server] = rpc:call(Cp1, global_group, registered_names, [{node, Cp1nn}]), + ?line [test_server] = rpc:call(Cp2, global_group, registered_names, [{node, Cp2nn}]), + ?line [test_server] = rpc:call(Cp3, global_group, registered_names, [{node, Cp3nn}]), + ?line [test_server] = rpc:call(Cp1, global_group, registered_names, [{node, Cpxnn}]), + ?line [test_server] = rpc:call(Cp2, global_group, registered_names, [{node, Cpynn}]), + ?line [test_server] = rpc:call(Cp3, global_group, registered_names, [{node, Cpznn}]), + + + % start a proc and register it + ?line {Pid2, yes} = rpc:call(Cp2, ?MODULE, start_proc, [test2]), + + ?line RegNames = lists:sort([test2,test_server]), + + ?line RegNames = + lists:sort( + rpc:call(Cp1, global_group, registered_names, [{node, Cp1nn}])), + ?line RegNames = + lists:sort( + rpc:call(Cp2, global_group, registered_names, [{node, Cp2nn}])), + ?line RegNames = + lists:sort( + rpc:call(Cp3, global_group, registered_names, [{node, Cp3nn}])), + ?line RegNames = + lists:sort( + rpc:call(Cp1, global_group, registered_names, [{node, Cpxnn}])), + ?line RegNames = + lists:sort( + rpc:call(Cp2, global_group, registered_names, [{node, Cpynn}])), + ?line RegNames = + lists:sort( + rpc:call(Cp3, global_group, registered_names, [{node, Cpznn}])), + + + ?line undefined = rpc:call(Cp3, global_group, global_groups, []), + + ?line Own_nodes_should = [node(), Cp1nn, Cp2nn, Cp3nn, + Cpxnn, Cpynn, Cpznn], + ?line Own_nodes = rpc:call(Cp3, global_group, own_nodes, []), + ?line true = (Own_nodes -- Own_nodes_should) =:= [], + ?line true = (Own_nodes_should -- Own_nodes) =:= [], + + ?line Pid2 = rpc:call(Cp1, global_group, send, [test2, {ping, self()}]), + ?line receive + {pong, Cp2} -> ok + after + 2000 -> test_server:fail(timeout2) + end, + ?line Pid2 = rpc:call(Cp2, global_group, send, [test2, {ping, self()}]), + ?line receive + {pong, Cp2} -> ok + after + 2000 -> test_server:fail(timeout3) + end, + ?line Pid2 = rpc:call(Cpz, global_group, send, [test2, {ping, self()}]), + ?line receive + {pong, Cp2} -> ok + after + 2000 -> test_server:fail(timeout4) + end, + + + % start a proc and register it + ?line {PidX, yes} = rpc:call(Cpx, ?MODULE, start_proc, [test]), + + + %%------------------------------------ + %% Test monitor nodes + %%------------------------------------ + ?line Pid2 = rpc:call(Cp1, global_group, send, [{node, Cp2nn}, test2, monitor]), + ?line PidX = rpc:call(Cpx, global_group, send, [{node, Cpxnn}, test, monitor]), + + + % Kill node Cp1 + ?line Pid2 = + rpc:call(Cp2, global_group, send, [{node, Cp2nn}, test2, {wait_nodedown, Cp1}]), + ?line PidX = + rpc:call(Cpx, global_group, send, [{node, Cpxnn}, test, {wait_nodedown, Cp1}]), + ?line test_server:sleep(100), + ?line stop_node(Cp1), + ?line test_server:sleep(1000), + + ?line ok = assert_loop(Cp2, Cp2nn, test2, Pid2, loop), + ?line ok = assert_loop(Cpx, Cpxnn, test, PidX, loop), + + % Kill node Cpz + ?line Pid2 = + rpc:call(Cp2, global_group, send, [{node, Cp2nn}, test2, {wait_nodedown, Cpz}]), + ?line PidX = + rpc:call(Cpx, global_group, send, [{node, Cpxnn}, test, {wait_nodedown, Cpz}]), + ?line test_server:sleep(100), + ?line stop_node(Cpz), + ?line test_server:sleep(1000), + + ?line ok = assert_loop(Cp2, Cp2nn, test2, Pid2, loop), + ?line ok = assert_loop(Cpx, Cpxnn, test, PidX, loop), + + % Restart node Cp1 + ?line Pid2 = + rpc:call(Cp2, global_group, send, [{node, Cp2nn}, test2, {wait_nodeup, Cp1}]), + ?line PidX = + rpc:call(Cpx, global_group, send, [{node, Cpxnn}, test, {wait_nodeup, Cp1}]), + ?line {ok, Cp1} = start_node_comp(Ncp1, Config), + ?line pong = rpc:call(Cp2, net_adm, ping, [Cp1nn]), + ?line pong = rpc:call(Cpx, net_adm, ping, [Cp1nn]), + ?line wait_for_ready_net(), + + ?line ok = assert_loop(Cp2, Cp2nn, test2, Pid2, loop), + ?line ok = assert_loop(Cpx, Cpxnn, test, PidX, loop), + + % Restart node Cpz + ?line Pid2 = + rpc:call(Cp2, global_group, send, [{node, Cp2nn}, test2, {wait_nodeup, Cpz}]), + ?line PidX = + rpc:call(Cpx, global_group, send, [{node, Cpxnn}, test, {wait_nodeup, Cpz}]), + ?line {ok, Cpz} = start_node_comp(Ncpz, Config), + ?line pong = rpc:call(Cp2, net_adm, ping, [Cpznn]), + ?line pong = rpc:call(Cpx, net_adm, ping, [Cpznn]), + ?line wait_for_ready_net(), + + ?line ok = assert_loop(Cp2, Cp2nn, test2, Pid2, loop), + ?line ok = assert_loop(Cpx, Cpxnn, test, PidX, loop), + + % stop the nodes, and make sure names are released. + stop_node(Cp1), + stop_node(Cp2), + stop_node(Cp3), + stop_node(Cpx), + stop_node(Cpy), + stop_node(Cpz), + + ?line ?UNTIL(undefined =:= global:whereis_name(test)), + ?line test_server:timetrap_cancel(Dog), + ok. + + + + +one_grp(suite) -> []; +one_grp(doc) -> ["Test a system with only one global group. "]; +one_grp(Config) when list(Config) -> + ?line Dog = test_server:timetrap(test_server:seconds(120)), + + ?line Dir = ?config(priv_dir, Config), + ?line File = filename:join(Dir, "global_group.config"), + ?line {ok, Fd} = file:open(File, write), + [Ncp1,Ncp2,Ncp3] = node_names([cp1, cp2, cp3], Config), + ?line config(Fd, Ncp1, Ncp2, Ncp3, "cpx", "cpy", "cpz", "cpq"), + + ?line {ok, Cp1} = start_node(Ncp1, Config), + ?line {ok, Cp2} = start_node(Ncp2, Config), + ?line {ok, Cp3} = start_node(Ncp3, Config), + + % sleep a while to make the global_group to sync... + test_server:sleep(1000), + + % start a proc and register it + ?line {Pid, yes} = rpc:call(Cp1, ?MODULE, start_proc, [test]), + + % test that it is registered at all nodes + ?line Pid = rpc:call(Cp1, global, whereis_name, [test]), + ?line Pid = rpc:call(Cp2, global, whereis_name, [test]), + ?line Pid = rpc:call(Cp3, global, whereis_name, [test]), + + % try to register the same name + ?line no = rpc:call(Cp1, global, register_name, [test, self()]), + + % let process exit, check that it is unregistered automatically + Pid ! die, + ?line + ?UNTIL(begin + (undefined =:= rpc:call(Cp1, global, whereis_name, [test])) and + (undefined =:= rpc:call(Cp2, global, whereis_name, [test])) and + (undefined =:= rpc:call(Cp3, global, whereis_name, [test])) + end), + + % test re_register + ?line {Pid2, yes} = rpc:call(Cp1, ?MODULE, start_proc, [test]), + ?line Pid2 = rpc:call(Cp3, global, whereis_name, [test]), + Pid3 = rpc:call(Cp3, ?MODULE, start_proc_rereg, [test]), + ?line Pid3 = rpc:call(Cp3, global, whereis_name, [test]), + + % test sending + rpc:call(Cp1, global, send, [test, {ping, self()}]), + receive + {pong, Cp3} -> ok + after + 2000 -> test_server:fail(timeout1) + end, + + rpc:call(Cp3, global, send, [test, {ping, self()}]), + receive + {pong, Cp3} -> ok + after + 2000 -> test_server:fail(timeout2) + end, + + ?line rpc:call(Cp3, global, unregister_name, [test]), + ?line undefined = rpc:call(Cp1, global, whereis_name, [test]), + ?line undefined = rpc:call(Cp2, global, whereis_name, [test]), + ?line undefined = rpc:call(Cp3, global, whereis_name, [test]), + + Pid3 ! die, + ?line ?UNTIL(undefined =:= rpc:call(Cp3, global, whereis_name, [test])), + + % register a proc + ?line {_, yes} = rpc:call(Cp3, ?MODULE, start_proc, [test]), + + % stop the nodes, and make sure names are released. + stop_node(Cp3), + + ?line ?UNTIL(undefined =:= rpc:call(Cp1, global, whereis_name, [test])), + Pid2 ! die, + + stop_node(Cp1), + stop_node(Cp2), + + ?line test_server:timetrap_cancel(Dog), + ok. + + + + + +one_grp_x(suite) -> []; +one_grp_x(doc) -> ["Check a system with only one global group. " + "Start the nodes with different time intervals. "]; +one_grp_x(Config) when list(Config) -> + ?line Dog = test_server:timetrap(test_server:seconds(120)), + + ?line Dir = ?config(priv_dir, Config), + ?line File = filename:join(Dir, "global_group.config"), + ?line {ok, Fd} = file:open(File, write), + [Ncp1,Ncp2,Ncp3] = node_names([cp1, cp2, cp3], Config), + ?line config(Fd, Ncp1, Ncp2, Ncp3, "cpx", "cpy", "cpz", "cpq"), + + ?line {ok, Cp1} = start_node(Ncp1, Config), + % sleep a while to make the global_group to sync... + test_server:sleep(1000), + + % start a proc and register it + ?line {Pid, yes} = rpc:call(Cp1, ?MODULE, start_proc, [test]), + + ?line {ok, Cp2} = start_node(Ncp2, Config), + % sleep a while to make the global_group to sync... + test_server:sleep(1000), + + % test that it is registered at all nodes + ?line Pid = rpc:call(Cp1, global, whereis_name, [test]), + ?line Pid = rpc:call(Cp2, global, whereis_name, [test]), + + ?line {ok, Cp3} = start_node(Ncp3, Config), + % sleep a while to make the global_group to sync... + test_server:sleep(1000), + + ?line Pid = rpc:call(Cp3, global, whereis_name, [test]), + + % try to register the same name + ?line no = rpc:call(Cp1, global, register_name, [test, self()]), + + % let process exit, check that it is unregistered automatically + Pid ! die, + ?line + ?UNTIL(begin + (undefined =:= rpc:call(Cp1, global, whereis_name, [test])) and + (undefined =:= rpc:call(Cp2, global, whereis_name, [test])) and + (undefined =:= rpc:call(Cp3, global, whereis_name, [test])) + end), + + % test re_register + ?line {Pid2, yes} = rpc:call(Cp1, ?MODULE, start_proc, [test]), + ?line Pid2 = rpc:call(Cp3, global, whereis_name, [test]), + + Pid2 ! die, + + stop_node(Cp1), + stop_node(Cp2), + stop_node(Cp3), + + ?line test_server:timetrap_cancel(Dog), + ok. + + + + + + +two_grp(suite) -> []; +two_grp(doc) -> ["Test a two global group system. "]; +two_grp(Config) when list(Config) -> + ?line Dog = test_server:timetrap(test_server:seconds(200)), + + ?line Dir = ?config(priv_dir, Config), + ?line File = filename:join(Dir, "global_group.config"), + ?line {ok, Fd} = file:open(File, write), + + [Ncp1,Ncp2,Ncp3,Ncpx,Ncpy,Ncpz,Ncpq] = + node_names([cp1,cp2,cp3,cpx,cpy,cpz,cpq], Config), + ?line config(Fd, Ncp1, Ncp2, Ncp3, Ncpx, Ncpy, Ncpz, Ncpq), + + ?line Cp1nn = node_at(Ncp1), + ?line Cp2nn = node_at(Ncp2), + ?line Cp3nn = node_at(Ncp3), + ?line Cpxnn = node_at(Ncpx), + ?line Cpynn = node_at(Ncpy), + ?line Cpznn = node_at(Ncpz), + + ?line {ok, Cp1} = start_node(Ncp1, Config), + ?line {ok, Cp2} = start_node(Ncp2, Config), + ?line {ok, Cp3} = start_node(Ncp3, Config), + ?line {ok, Cpx} = start_node(Ncpx, Config), + ?line {ok, Cpy} = start_node(Ncpy, Config), + ?line {ok, Cpz} = start_node(Ncpz, Config), + + %% The groups (cpq not started): + %% [{nc1, [cp1,cp2,cp3]}, {nc2, [cpx,cpy,cpz]}, {nc3, [cpq]}] + + % sleep a while to make the global_groups to sync... + test_server:sleep(1000), + + % check the global group names + ?line {nc1, [nc2, nc3]} = rpc:call(Cp1, global_group, global_groups, []), + ?line {nc1, [nc2, nc3]} = rpc:call(Cp2, global_group, global_groups, []), + ?line {nc1, [nc2, nc3]} = rpc:call(Cp3, global_group, global_groups, []), + ?line {nc2, [nc1, nc3]} = rpc:call(Cpx, global_group, global_groups, []), + ?line {nc2, [nc1, nc3]} = rpc:call(Cpy, global_group, global_groups, []), + ?line {nc2, [nc1, nc3]} = rpc:call(Cpz, global_group, global_groups, []), + + % check the global group nodes + ?line [Cp1nn, Cp2nn, Cp3nn] = rpc:call(Cp1, global_group, own_nodes, []), + ?line [Cp1nn, Cp2nn, Cp3nn] = rpc:call(Cp2, global_group, own_nodes, []), + ?line [Cp1nn, Cp2nn, Cp3nn] = rpc:call(Cp3, global_group, own_nodes, []), + ?line [Cpxnn, Cpynn, Cpznn] = rpc:call(Cpx, global_group, own_nodes, []), + ?line [Cpxnn, Cpynn, Cpznn] = rpc:call(Cpy, global_group, own_nodes, []), + ?line [Cpxnn, Cpynn, Cpznn] = rpc:call(Cpz, global_group, own_nodes, []), + + + % start a proc and register it + ?line {Pid1, yes} = rpc:call(Cp1, ?MODULE, start_proc, [test]), + + ?line Pid1 = rpc:call(Cp1, global_group, send, [test, {io, from_cp1}]), + ?line Pid1 = rpc:call(Cpx, global_group, send, [test, {io, from_cpx}]), + ?line Pid1 = rpc:call(Cp1, global_group, send, [{group,nc1}, test, + {io, from_cp1}]), + ?line [test] = + rpc:call(Cpx, global_group, registered_names, [{node, Cp1nn}]), + ?line [test] = + rpc:call(Cpx, global_group, registered_names, [{group, nc1}]), + ?line [] = rpc:call(Cpx, global_group, registered_names, [{node, Cpxnn}]), + ?line [] = rpc:call(Cpx, global_group, registered_names, [{group, nc2}]), + ?line Pid1 = rpc:call(Cpx, global_group, send, [{group,nc1}, test, + {io, from_cp1}]), + ?line {badarg,{test,{io,from_cpx}}} = + rpc:call(Cp1, global_group, send, [{group,nc2}, test, {io, from_cpx}]), + ?line {badarg,{test,{io,from_cpx}}} = + rpc:call(Cpx, global_group, send, [{group,nc2}, test, {io, from_cpx}]), + + + + % test that it is registered at all nodes + ?line Pid1 = rpc:call(Cp1, global, whereis_name, [test]), + ?line Pid1 = rpc:call(Cp2, global, whereis_name, [test]), + ?line Pid1 = rpc:call(Cp3, global, whereis_name, [test]), + ?line undefined = rpc:call(Cpx, global, whereis_name, [test]), + ?line undefined = rpc:call(Cpy, global, whereis_name, [test]), + ?line undefined = rpc:call(Cpz, global, whereis_name, [test]), + + % start a proc and register it + ?line {PidX, yes} = rpc:call(Cpx, ?MODULE, start_proc, [test]), + + % test that it is registered at all nodes + ?line Pid1 = rpc:call(Cp1, global, whereis_name, [test]), + ?line Pid1 = rpc:call(Cp2, global, whereis_name, [test]), + ?line Pid1 = rpc:call(Cp3, global, whereis_name, [test]), + ?line PidX = rpc:call(Cpx, global, whereis_name, [test]), + ?line PidX = rpc:call(Cpy, global, whereis_name, [test]), + ?line PidX = rpc:call(Cpz, global, whereis_name, [test]), + + Pid1 ! die, + %% If we don't wait for global on other nodes to have updated its + %% tables, 'test' may still be defined at the point when it is + %% tested a few lines below. + ?line + ?UNTIL(begin + Pid = rpc:call(Cp2, global, whereis_name, [test]), + undefined =:= Pid + end), + + % start a proc and register it + ?line {Pid2, yes} = rpc:call(Cp2, ?MODULE, start_proc, [test2]), + + % test that it is registered at all nodes + ?line Pid2 = rpc:call(Cp1, global, whereis_name, [test2]), + ?line Pid2 = rpc:call(Cp2, global, whereis_name, [test2]), + ?line Pid2 = rpc:call(Cp3, global, whereis_name, [test2]), + ?line PidX = rpc:call(Cpx, global, whereis_name, [test]), + ?line PidX = rpc:call(Cpy, global, whereis_name, [test]), + ?line PidX = rpc:call(Cpz, global, whereis_name, [test]), + + ?line undefined = rpc:call(Cp1, global, whereis_name, [test]), + ?line undefined = rpc:call(Cp2, global, whereis_name, [test]), + ?line undefined = rpc:call(Cp3, global, whereis_name, [test]), + ?line undefined = rpc:call(Cpx, global, whereis_name, [test2]), + ?line undefined = rpc:call(Cpy, global, whereis_name, [test2]), + ?line undefined = rpc:call(Cpz, global, whereis_name, [test2]), + + + ?line Pid2 = rpc:call(Cp1, global_group, send, [test2, {ping, self()}]), + receive + {pong, Cp2} -> ok + after + 2000 -> test_server:fail(timeout2) + end, + ?line Pid2 = rpc:call(Cp2, global_group, send, [test2, {ping, self()}]), + receive + {pong, Cp2} -> ok + after + 2000 -> test_server:fail(timeout2) + end, + ?line Pid2 = rpc:call(Cp3, global_group, send, [test2, {ping, self()}]), + receive + {pong, Cp2} -> ok + after + 2000 -> test_server:fail(timeout2) + end, + + ?line PidX = rpc:call(Cpx, global_group, send, [test, {ping, self()}]), + receive + {pong, Cpx} -> ok + after + 2000 -> test_server:fail(timeout2) + end, + ?line PidX = rpc:call(Cpy, global_group, send, [test, {ping, self()}]), + receive + {pong, Cpx} -> ok + after + 2000 -> test_server:fail(timeout2) + end, + ?line PidX = rpc:call(Cpz, global_group, send, [test, {ping, self()}]), + receive + {pong, Cpx} -> ok + after + 2000 -> test_server:fail(timeout2) + end, + + ?line Pid2 = rpc:call(Cpx, global_group, send, [{node, Cp1nn}, test2, + {ping, self()}]), + receive + {pong, Cp2} -> ok + after + 2000 -> test_server:fail(timeout2) + end, + ?line Pid2 = rpc:call(Cpy, global_group, send, [{node, Cp2nn}, test2, + {ping, self()}]), + receive + {pong, Cp2} -> ok + after + 2000 -> test_server:fail(timeout2) + end, + ?line Pid2 = rpc:call(Cpz, global_group, send, [{node, Cp3nn}, test2, + {ping, self()}]), + receive + {pong, Cp2} -> ok + after + 2000 -> test_server:fail(timeout2) + end, + + ?line PidX = rpc:call(Cpx, global_group, send, [{node, Cpznn}, test, + {ping, self()}]), + receive + {pong, Cpx} -> ok + after + 2000 -> test_server:fail(timeout2) + end, + ?line PidX = rpc:call(Cpy, global_group, send, [{node, Cpxnn}, test, + {ping, self()}]), + receive + {pong, Cpx} -> ok + after + 2000 -> test_server:fail(timeout2) + end, + ?line PidX = rpc:call(Cpz, global_group, send, [{node, Cpynn}, test, + {ping, self()}]), + receive + {pong, Cpx} -> ok + after + 2000 -> test_server:fail(timeout2) + end, + + ?line Pid2 = rpc:call(Cpx, global_group, send, [{group, nc1}, test2, + {ping, self()}]), + receive + {pong, Cp2} -> ok + after + 2000 -> test_server:fail(timeout2) + end, + ?line PidX = rpc:call(Cpy, global_group, send, [{group, nc2}, test, + {ping, self()}]), + receive + {pong, Cpx} -> ok + after + 2000 -> test_server:fail(timeout2) + end, + + %%------------------------------------ + %% Test monitor nodes + %%------------------------------------ + ?line Pid2 = + rpc:call(Cp1, global_group, send, [{node, Cp2nn}, test2, monitor]), + ?line PidX = + rpc:call(Cpx, global_group, send, [{node, Cpxnn}, test, monitor]), + + + % Kill node Cp1 + ?line Pid2 = rpc:call(Cp2, global_group, send, [{node, Cp2nn}, test2, + {wait_nodedown, Cp1}]), + ?line PidX = rpc:call(Cpx, global_group, send, [{node, Cpxnn}, test, + {wait_nodedown, Cp1}]), + ?line test_server:sleep(100), + ?line stop_node(Cp1), + ?line test_server:sleep(1000), + + ?line ok = assert_loop(Cp2, Cp2nn, test2, Pid2, loop), + ?line ok = assert_loop(Cpx, Cpxnn, test, PidX, loop_nodedown), + ?line PidX = + rpc:call(Cpx, global_group, send, [{node, Cpxnn}, test, to_loop]), + + % Kill node Cpz + ?line Pid2 = rpc:call(Cp2, global_group, send, [{node, Cp2nn}, test2, + {wait_nodedown, Cpz}]), + ?line PidX = rpc:call(Cpx, global_group, send, [{node, Cpxnn}, test, + {wait_nodedown, Cpz}]), + ?line test_server:sleep(100), + ?line stop_node(Cpz), + ?line test_server:sleep(1000), + + ?line ok = assert_loop(Cp2, Cp2nn, test2, Pid2, loop_nodedown), + ?line ok = assert_loop(Cpx, Cpxnn, test, PidX, loop), + ?line Pid2 = + rpc:call(Cp2, global_group, send, [{node, Cp2nn}, test2, to_loop]), + + % Restart node Cp1 + ?line [Cp1nn, Cp2nn, Cp3nn] = rpc:call(Cp2, global_group, own_nodes, []), + ?line Pid2 = rpc:call(Cp2, global_group, send, [{node, Cp2nn}, test2, + {wait_nodeup, Cp1}]), + ?line PidX = rpc:call(Cpx, global_group, send, [{node, Cpxnn}, test, + {wait_nodeup, Cp1}]), + ?line test_server:sleep(100), + ?line {ok, Cp1} = start_node(Ncp1, Config), + ?line test_server:sleep(5000), + + ?line ok = assert_loop(Cp2, Cp2nn, test2, Pid2, loop), + ?line ok = assert_loop(Cpx, Cpxnn, test, PidX, loop_nodeup), + ?line PidX = + rpc:call(Cpx, global_group, send, [{node, Cpxnn}, test, to_loop]), + + + % Restart node Cpz + ?line Pid2 = rpc:call(Cp2, global_group, send, [{node, Cp2nn}, test2, + {wait_nodeup, Cpz}]), + ?line PidX = rpc:call(Cpx, global_group, send, [{node, Cpxnn}, test, + {wait_nodeup, Cpz}]), + ?line test_server:sleep(100), + ?line {ok, Cpz} = start_node(Ncpz, Config), + ?line test_server:sleep(5000), + + ?line ok = assert_loop(Cp2, Cp2nn, test2, Pid2, loop_nodeup), + ?line ok = assert_loop(Cpx, Cpxnn, test, PidX, loop), + ?line Pid2 = + rpc:call(Cp2, global_group, send, [{node, Cp2nn}, test2, to_loop]), + + + Pid2 ! die, + PidX ! die, + + stop_node(Cp1), + stop_node(Cp2), + stop_node(Cp3), + stop_node(Cpx), + stop_node(Cpy), + stop_node(Cpz), + + ?line test_server:timetrap_cancel(Dog), + ok. + + + +hidden_groups(suite) -> []; +hidden_groups(doc) -> ["Test hidden global groups."]; +hidden_groups(Config) when list(Config) -> + ?line Dog = test_server:timetrap(test_server:seconds(200)), + + ?line Dir = ?config(priv_dir, Config), + ?line File = filename:join(Dir, "global_group.config"), + ?line {ok, Fd} = file:open(File, write), + + [Ncp1,Ncp2,Ncp3,Ncpx,Ncpy,Ncpz,Ncpq] = + node_names([cp1,cp2,cp3,cpx,cpy,cpz,cpq], Config), + ?line config_hidden(Fd, Ncp1, Ncp2, Ncp3, Ncpx, Ncpy, Ncpz, Ncpq), + + ?line {ok, Cp1} = start_node(Ncp1, Config), + ?line {ok, Cp2} = start_node(Ncp2, Config), + ?line {ok, Cp3} = start_node(Ncp3, Config), + ?line {ok, Cpx} = start_node(Ncpx, Config), + ?line {ok, Cpy} = start_node(Ncpy, Config), + ?line {ok, Cpz} = start_node(Ncpz, Config), + ?line {ok, Cpq} = start_node(Ncpq, Config), + + % sleep a while to make the global_groups to sync... + test_server:sleep(1000), + + % check the global group names + ?line {nc1, [nc2, nc3]} = rpc:call(Cp1, global_group, global_groups, []), + ?line {nc1, [nc2, nc3]} = rpc:call(Cp2, global_group, global_groups, []), + ?line {nc1, [nc2, nc3]} = rpc:call(Cp3, global_group, global_groups, []), + ?line {nc2, [nc1, nc3]} = rpc:call(Cpx, global_group, global_groups, []), + ?line {nc2, [nc1, nc3]} = rpc:call(Cpy, global_group, global_groups, []), + ?line {nc2, [nc1, nc3]} = rpc:call(Cpz, global_group, global_groups, []), + + % check the global group nodes + ?line [Cp1, Cp2, Cp3] = rpc:call(Cp1, global_group, own_nodes, []), + ?line [Cp1, Cp2, Cp3] = rpc:call(Cp2, global_group, own_nodes, []), + ?line [Cp1, Cp2, Cp3] = rpc:call(Cp3, global_group, own_nodes, []), + ?line [Cpx, Cpy, Cpz] = rpc:call(Cpx, global_group, own_nodes, []), + ?line [Cpx, Cpy, Cpz] = rpc:call(Cpy, global_group, own_nodes, []), + ?line [Cpx, Cpy, Cpz] = rpc:call(Cpz, global_group, own_nodes, []), + ?line [Cpq] = rpc:call(Cpq, global_group, own_nodes, []), + + % Make some inter group connections + ?line pong = rpc:call(Cp1, net_adm, ping, [Cpx]), + ?line pong = rpc:call(Cpy, net_adm, ping, [Cp2]), + ?line pong = rpc:call(Cp3, net_adm, ping, [Cpx]), + ?line pong = rpc:call(Cpz, net_adm, ping, [Cp3]), + ?line pong = rpc:call(Cpq, net_adm, ping, [Cp1]), + ?line pong = rpc:call(Cpz, net_adm, ping, [Cpq]), + + % Check that no inter group connections are visible + NC1Nodes = lists:sort([Cp1, Cp2, Cp3]), + NC2Nodes = lists:sort([Cpx, Cpy, Cpz]), + ?line NC1Nodes = lists:sort([Cp1|rpc:call(Cp1, erlang, nodes, [])]), + ?line NC1Nodes = lists:sort([Cp2|rpc:call(Cp2, erlang, nodes, [])]), + ?line NC1Nodes = lists:sort([Cp3|rpc:call(Cp3, erlang, nodes, [])]), + ?line NC2Nodes = lists:sort([Cpx|rpc:call(Cpx, erlang, nodes, [])]), + ?line NC2Nodes = lists:sort([Cpy|rpc:call(Cpy, erlang, nodes, [])]), + ?line NC2Nodes = lists:sort([Cpz|rpc:call(Cpz, erlang, nodes, [])]), + NC12Nodes = lists:append(NC1Nodes, NC2Nodes), + ?line false = lists:any(fun(N) -> lists:member(N, NC12Nodes) end, + rpc:call(Cpq, erlang, nodes, [])), + + + stop_node(Cp1), + stop_node(Cp2), + stop_node(Cp3), + stop_node(Cpx), + stop_node(Cpy), + stop_node(Cpz), + stop_node(Cpq), + + ?line test_server:timetrap_cancel(Dog), + ok. + + +test_exit(suite) -> []; +test_exit(doc) -> ["Checks when the search process exits. "]; +test_exit(Config) when list(Config) -> + ?line Dog = test_server:timetrap(test_server:seconds(120)), + + ?line NN = node_name(atom_to_list(node())), + ?line Cp1nn = list_to_atom("cp1@" ++ NN), + + ?line {ok, Cp1} = start_node(cp1, Config), + ?line {ok, Cp2} = start_node(cp2, Config), + ?line {ok, Cp3} = start_node(cp3, Config), + + test_server:sleep(1000), + + ?line {error, illegal_function_call} = + rpc:call(Cp1, global_group, registered_names_test, [{node, Cp1nn}]), + ?line {badarg,_} = + rpc:call(Cp1, global_group, send, [king, "The message"]), + ?line undefined = rpc:call(Cp1, global_group, whereis_name, [king]), + + % stop the nodes, and make sure names are released. + stop_node(Cp1), + stop_node(Cp2), + stop_node(Cp3), + + % sleep to let the nodes die + test_server:sleep(1000), + + ?line test_server:timetrap_cancel(Dog), + ok. + + +start_node(Name, Config) -> + Pa=filename:dirname(code:which(?MODULE)), + Dir=?config(priv_dir, Config), + ConfFile = " -config " ++ filename:join(Dir, "global_group"), + test_server:start_node(Name, slave, [{args, "-pa " ++ Pa ++ ConfFile}]). + +start_node_no(Name, Config) -> + Pa=filename:dirname(code:which(?MODULE)), + Dir=?config(priv_dir, Config), + ConfFile = " -config " ++ filename:join(Dir, "no_global_group"), + test_server:start_node(Name, slave, [{args, "-pa " ++ Pa ++ ConfFile}]). + +start_node_no2(Name, Config) -> + Pa=filename:dirname(code:which(?MODULE)), + Dir=?config(priv_dir, Config), + ConfFile = " -config " ++ filename:join(Dir, "no_global_group_sync"), + test_server:start_node(Name, slave, [{args, "-pa " ++ Pa ++ ConfFile}]). + +start_node_comp(Name, Config) -> + Pa=filename:dirname(code:which(?MODULE)), + Dir=?config(priv_dir, Config), + ConfFile = " -config " ++ filename:join(Dir, "global_group_comp"), + test_server:start_node(Name, slave, [{args, "-pa " ++ Pa ++ ConfFile}]). + +node_names(Names, Config) -> + [node_name(Name, Config) || Name <- Names]. + +node_name(Name, Config) -> + U = "_", + Pid = os:getpid(), + {{Y,M,D}, {H,Min,S}} = calendar:now_to_local_time(now()), + Date = io_lib:format("~4w_~2..0w_~2..0w__~2..0w_~2..0w_~2..0w", + [Y,M,D, H,Min,S]), + L = lists:flatten(Date), + lists:concat([Name,U,?testcase,U,Pid,U,U,L]). + +stop_node(Node) -> + ?t:stop_node(Node). + + +wait_for_ready_net() -> + Nodes = lists:sort(?NODES), + ?UNTIL(begin + lists:all(fun(N) -> Nodes =:= get_known(N) end, Nodes) and + lists:all(fun(N) -> + LNs = rpc:call(N, erlang, nodes, []), + Nodes =:= lists:sort([N | LNs]) + end, Nodes) + end). + +get_known(Node) -> + Known = gen_server:call({global_name_server,Node}, get_known), + lists:sort([Node | Known]). + +config_hidden(Fd, Ncp1, Ncp2, Ncp3, Ncpx, Ncpy, Ncpz, Ncpq) -> + M = from($@, atom_to_list(node())), + io:format(Fd, "[{kernel, [{sync_nodes_optional, ['~s@~s','~s@~s','~s@~s', " + " '~s@~s','~s@~s','~s@~s']}," + "{sync_nodes_timeout, 1000}," + "{global_groups, [{nc1, hidden, ['~s@~s','~s@~s','~s@~s']}, " + "{nc2, hidden, ['~s@~s','~s@~s','~s@~s']}, " + "{nc3, normal, ['~s@~s']}]} ] }]. ~n", + [Ncp1, M, Ncp2, M, Ncp3, M, + Ncpx, M, Ncpy, M, Ncpz, M, + Ncp1, M, Ncp2, M, Ncp3, M, + Ncpx, M, Ncpy, M, Ncpz, M, + Ncpq, M]). + +config(Fd, Ncp1, Ncp2, Ncp3, Ncpx, Ncpy, Ncpz, Ncpq) -> + M = from($@, atom_to_list(node())), + io:format(Fd, "[{kernel, [{sync_nodes_optional, ['~s@~s','~s@~s','~s@~s', " + " '~s@~s','~s@~s','~s@~s']}," + "{sync_nodes_timeout, 1000}," + "{global_groups, [{nc1, ['~s@~s','~s@~s','~s@~s']}, " + " {nc2, ['~s@~s','~s@~s','~s@~s']}, " + "{nc3, ['~s@~s']}]} ] }]. ~n", + [Ncp1, M, Ncp2, M, Ncp3, M, + Ncpx, M, Ncpy, M, Ncpz, M, + Ncp1, M, Ncp2, M, Ncp3, M, + Ncpx, M, Ncpy, M, Ncpz, M, + Ncpq, M]). + +config_no(Fd) -> + io:format(Fd, "[{kernel, [{global_groups, []}]}]. ~n",[]). + +config_sync(Fd, Ncp1, Ncp2, Ncp3, Ncpx, Ncpy, Ncpz) -> + M = from($@, atom_to_list(node())), + io:format(Fd, "[{kernel, [{sync_nodes_optional, ['~s@~s','~s@~s','~s@~s', " + " '~s@~s','~s@~s','~s@~s']}," + "{sync_nodes_timeout, 1000}," + "{global_groups, []} ] }] .~n", + [Ncp1, M, Ncp2, M, Ncp3, M, + Ncpx, M, Ncpy, M, Ncpz, M]). + + +config_comp(Fd, Ncp1, Ncp2, Ncp3, Ncpx, Ncpy, Ncpz) -> + M = from($@, atom_to_list(node())), + io:format(Fd, "[{kernel, [{sync_nodes_optional, ['~s@~s','~s@~s','~s@~s', " + " '~s@~s','~s@~s','~s@~s']}," + "{sync_nodes_timeout, 1000} ] }] .~n", + [Ncp1, M, Ncp2, M, Ncp3, M, + Ncpx, M, Ncpy, M, Ncpz, M]). + +node_at(N) -> + NN = node_name(atom_to_list(node())), + list_to_atom(lists:concat([N, "@", NN])). + +node_name(L) -> + from($@, L). + +from(H, [H | T]) -> T; +from(H, [_ | T]) -> from(H, T); +from(_, []) -> []. + + +start_proc(Name) -> + Pid = spawn(?MODULE, init, [self(), Name]), + receive + {Pid, Res} -> {Pid, Res} + end. + +start_proc_rereg(Name) -> + Pid = spawn(?MODULE, init2, [self(), Name]), + receive + Pid -> Pid + end. + + + + + + + +init(Parent) -> + Parent ! self(), + loop(). + +init(Parent, Name) -> + X = global:register_name(Name, self()), + Parent ! {self(),X}, + loop(). + +init2(Parent, Name) -> + global:re_register_name(Name, self()), + Parent ! self(), + loop(). + +loop() -> + receive + monitor -> + global_group:monitor_nodes(true), + loop(); + stop_monitor -> + global_group:monitor_nodes(false), + loop(); + {wait_nodeup, Node} -> + loop_nodeup(Node); + {wait_nodedown, Node} -> + loop_nodedown(Node); + {io, _Msg} -> + loop(); + {ping, From} -> + From ! {pong, node()}, + loop(); + {del_lock, Id} -> + global:del_lock({Id, self()}), + loop(); + {del_lock, Id, Nodes} -> + global:del_lock({Id, self()}, Nodes), + loop(); + {set_lock, Id, From} -> + Res = global:set_lock({Id, self()}, ?NODES, 1), + From ! Res, + loop(); + {set_lock, Id, From, Nodes} -> + Res = global:set_lock({Id, self()}, Nodes, 1), + From ! Res, + loop(); + {set_lock_loop, Id, From} -> + global:set_lock({Id, self()}, ?NODES), + From ! {got_lock, self()}, + loop(); + {{got_notify, From}, Ref} -> + receive + X when element(1, X) == global_name_conflict -> + From ! {Ref, yes} + after + 0 -> From ! {Ref, no} + end, + loop(); + {which_loop, From} -> + From ! loop, + loop(); + die -> + exit(normal) + end. + + +loop_nodeup(Node) -> + receive + {nodeup, Node} -> + loop(); + to_loop -> + loop(); + {which_loop, From} -> + From ! loop_nodeup, + loop_nodeup(Node); + die -> + exit(normal) + end. + + +loop_nodedown(Node) -> + receive + {nodedown, Node} -> + loop(); + to_loop -> + loop(); + {which_loop, From} -> + From ! loop_nodedown, + loop_nodedown(Node); + die -> + exit(normal) + end. + +assert_loop(Cp, CpName, Name, NamePid, Loop) -> + M = {which_loop, self()}, + NamePid = rpc:call(Cp, global_group, send, [{node, CpName}, Name, M]), + receive + Loop -> + ok; + Other1 -> + test_server:fail(Other1) + after 5000 -> + test_server:fail(timeout) + end. + +loop_until_true(Fun) -> + case Fun() of + true -> + ok; + _ -> + loop_until_true(Fun) + end. + |