summaryrefslogtreecommitdiff
path: root/lib/kernel/test
diff options
context:
space:
mode:
Diffstat (limited to 'lib/kernel/test')
-rw-r--r--lib/kernel/test/erl_distribution_SUITE.erl19
-rw-r--r--lib/kernel/test/global_SUITE.erl997
-rw-r--r--lib/kernel/test/pg2_SUITE.erl262
-rw-r--r--lib/kernel/test/rpc_SUITE.erl50
4 files changed, 739 insertions, 589 deletions
diff --git a/lib/kernel/test/erl_distribution_SUITE.erl b/lib/kernel/test/erl_distribution_SUITE.erl
index 6f0064f0fa..2b84a68c52 100644
--- a/lib/kernel/test/erl_distribution_SUITE.erl
+++ b/lib/kernel/test/erl_distribution_SUITE.erl
@@ -121,6 +121,11 @@ tick(Config) when is_list(Config) ->
run_dist_configs(fun tick/2, Config).
tick(DCfg, _Config) ->
+ %%
+ %% This test case use disabled "connect all" so that
+ %% global wont interfere...
+ %%
+
%% First check that the normal case is OK!
[Name1, Name2] = get_nodenames(2, dist_test),
{ok, Node} = start_node(DCfg, Name1),
@@ -148,11 +153,11 @@ tick(DCfg, _Config) ->
%% node doesn't tick the client node within the interval ...
{ok, ServNode} = start_node(DCfg, Name2,
- "-kernel net_ticktime 100"),
+ "-kernel net_ticktime 100 -connect_all false"),
rpc:call(ServNode, erl_distribution_SUITE, tick_serv_test, [Node, node()]),
{ok, Node} = start_node(DCfg, Name1,
- "-kernel net_ticktime 12"),
+ "-kernel net_ticktime 12 -connect_all false"),
rpc:call(Node, erl_distribution_SUITE, tick_cli_test, [ServNode]),
spawn_link(erl_distribution_SUITE, keep_conn, [Node]),
@@ -585,6 +590,10 @@ tick_change(Config) when is_list(Config) ->
run_dist_configs(fun tick_change/2, Config).
tick_change(DCfg, _Config) ->
+ %%
+ %% This test case use disabled "connect all" so that
+ %% global wont interfere...
+ %%
[BN, CN] = get_nodenames(2, tick_change),
DefaultTT = net_kernel:get_net_ticktime(),
unchanged = net_kernel:set_net_ticktime(DefaultTT, 60),
@@ -601,7 +610,7 @@ tick_change(DCfg, _Config) ->
end,
wait_until(fun () -> 10 == net_kernel:get_net_ticktime() end),
- {ok, B} = start_node(DCfg, BN, "-kernel net_ticktime 10"),
+ {ok, B} = start_node(DCfg, BN, "-kernel net_ticktime 10 -connect_all false"),
{ok, C} = start_node(DCfg, CN, "-kernel net_ticktime 10 -hidden"),
OTE = process_flag(trap_exit, true),
@@ -663,7 +672,7 @@ run_tick_change_test(DCfg, B, C, PrevTT, TT) ->
wait_for_nodedowns(Tester, Ref)
end,
- {ok, D} = start_node(DCfg, DN, "-kernel net_ticktime "
+ {ok, D} = start_node(DCfg, DN, "-connect_all false -kernel net_ticktime "
++ integer_to_list(PrevTT)),
NMA = spawn_link(fun () -> MonitorNodes([B, C, D]) end),
@@ -697,7 +706,7 @@ run_tick_change_test(DCfg, B, C, PrevTT, TT) ->
sleep(7),
change_initiated = rpc:call(C,net_kernel,set_net_ticktime,[TT,10]),
- {ok, E} = start_node(DCfg, EN, "-kernel net_ticktime "
+ {ok, E} = start_node(DCfg, EN, "-connect_all false -kernel net_ticktime "
++ integer_to_list(TT)),
NME = spawn_link(E, fun () -> MonitorNodes([node(), B, C, D]) end),
NMA2 = spawn_link(fun () -> MonitorNodes([E]) end),
diff --git a/lib/kernel/test/global_SUITE.erl b/lib/kernel/test/global_SUITE.erl
index 3837a44c64..feae9ba4db 100644
--- a/lib/kernel/test/global_SUITE.erl
+++ b/lib/kernel/test/global_SUITE.erl
@@ -40,7 +40,11 @@
both_known_1/1,
lost_unregister/1,
mass_death/1,
- garbage_messages/1]).
+ garbage_messages/1,
+ ring_line/1,
+ lost_connection/1,
+ lost_connection2/1
+ ]).
-export([global_load/3, lock_global/2, lock_global2/2]).
@@ -77,7 +81,8 @@ all() ->
simple_resolve2, simple_resolve3, leftover_name,
re_register_name, name_exit, external_nodes, many_nodes,
sync_0, global_groups_change, register_1, both_known_1,
- lost_unregister, mass_death, garbage_messages]
+ lost_unregister, mass_death, garbage_messages,
+ lost_connection, lost_connection2]
end.
groups() ->
@@ -217,6 +222,14 @@ lock_global(Parent, Config) ->
%%% to obtain a lock for 'global' on node 3, which would keep the
%%% name registry from ever becoming consistent again.
both_known_1(Config) when is_list(Config) ->
+ case prevent_overlapping_partitions() of
+ true ->
+ {skipped, "Prevent overlapping partitions enabled"};
+ false ->
+ both_known_1_test(Config)
+ end.
+
+both_known_1_test(Config) when is_list(Config) ->
Timeout = 30,
ct:timetrap({seconds,Timeout}),
init_high_level_trace(Timeout),
@@ -299,6 +312,14 @@ both_known_1(Config) when is_list(Config) ->
%% OTP-6428. An unregistered name reappears.
lost_unregister(Config) when is_list(Config) ->
+ case prevent_overlapping_partitions() of
+ true ->
+ {skipped, "Prevent overlapping partitions enabled"};
+ false ->
+ lost_unregister_test(Config)
+ end.
+
+lost_unregister_test(Config) when is_list(Config) ->
Timeout = 30,
ct:timetrap({seconds,Timeout}),
init_high_level_trace(Timeout),
@@ -339,6 +360,120 @@ lost_unregister(Config) when is_list(Config) ->
init_condition(Config),
ok.
+lost_connection(Config) when is_list(Config) ->
+ case prevent_overlapping_partitions() of
+ true ->
+ lost_connection_test(Config);
+ false ->
+ {skipped, "Prevent overlapping partitions disabled"}
+ end.
+
+lost_connection_test(Config) when is_list(Config) ->
+ %% OTP-17843: Registered names could become inconsistent due to
+ %% overlapping partitions. This has been solved by
+ %% global actively disconnecting nodes to prevent
+ %% overlapping partitions.
+ ct:timetrap({seconds, 15}),
+
+ [Cp1, Cp2] = start_nodes([cp1, cp2], peer, Config),
+
+ PartCtrlr = setup_partitions(Config, [[node(), Cp1, Cp2]]),
+
+ wait_for_ready_net(Config),
+
+ {Gurka, yes} = start_proc_basic(gurka),
+
+ check_everywhere([node(), Cp1, Cp2], gurka, Config),
+
+ Gurka = global:whereis_name(gurka),
+
+ erlang:disconnect_node(Cp2), %% lost connection previously causing issues...
+
+ ok = rfcall(
+ PartCtrlr,
+ fun () ->
+ ok = rfcall(
+ Cp2,
+ fun () ->
+ {AltGurka, yes} = start_proc_basic(gurka),
+ AltGurka = global:whereis_name(gurka),
+ ok
+ end),
+ timer:sleep(1000),
+ rpc:cast(Cp2, erlang, halt, []),
+ wait_until(fun () -> not lists:member(Cp2, nodes(hidden)) end)
+ end),
+
+ Reconnected = case lists:member(Cp1, nodes()) of
+ true ->
+ false;
+ false ->
+ erlang:display("reconnecting Cp1"),
+ pong = net_adm:ping(Cp1),
+ timer:sleep(500),
+ true
+ end,
+
+ check_everywhere([node(), Cp1], gurka, Config),
+
+ Gurka = global:whereis_name(gurka),
+
+ ok = global:unregister_name(gurka),
+
+ stop_node(Cp1),
+ stop_partition_controller(PartCtrlr),
+
+ {comment, case Reconnected of
+ true -> "Re-connected Cp1";
+ false -> "No re-connection of Cp1 needed"
+ end}.
+
+lost_connection2(Config) when is_list(Config) ->
+ case prevent_overlapping_partitions() of
+ true ->
+ lost_connection2_test(Config);
+ false ->
+ {skipped, "Prevent overlapping partitions disabled"}
+ end.
+
+lost_connection2_test(Config) when is_list(Config) ->
+ %% OTP-17843: Registered names could become inconsistent due to
+ %% overlapping partitions. This has been solved by
+ %% global actively disconnecting nodes to prevent
+ %% overlapping partitions.
+ ct:timetrap({seconds, 15}),
+
+ [Cp1, Cp2, Cp3, Cp4] = start_nodes([cp1, cp2, cp3, cp4], peer, Config),
+
+ PartCtrlr = setup_partitions(Config, [[node(), Cp1, Cp2, Cp3, Cp4]]),
+
+ wait_for_ready_net(Config),
+
+ {Gurka, yes} = start_proc_basic(gurka),
+
+ check_everywhere([node(), Cp1, Cp2], gurka, Config),
+
+ Gurka = global:whereis_name(gurka),
+
+ disconnect_nodes(PartCtrlr, Cp3, Cp4),
+
+ Nodes = nodes(),
+ true = lists:member(Cp1, Nodes),
+ true = lists:member(Cp2, Nodes),
+ false = lists:member(Cp3, Nodes),
+ false = lists:member(Cp4, Nodes),
+
+ pong = net_adm:ping(Cp3),
+ pong = net_adm:ping(Cp4),
+
+ stop_node(Cp1),
+ stop_node(Cp2),
+ stop_node(Cp3),
+ stop_node(Cp4),
+ stop_partition_controller(PartCtrlr),
+
+ ok.
+
-define(UNTIL_LOOP, 300).
-define(end_tag, 'end at').
@@ -963,12 +1098,9 @@ name_die(Config) when is_list(Config) ->
T1 = node(),
Part1 = [T1],
Part2 = [Cp1],
- rpc_cast(Cp1,
- ?MODULE, part_2_2, [Config,
- Part1,
- Part2,
- []]),
- ?UNTIL(is_ready_partition(Config)),
+
+ PartCtrlr = setup_partitions(Config, [Part1, Part2]),
+
?UNTIL(undefined =:= global:whereis_name(Name)),
yes = global:register_name(Name, Pid),
@@ -986,12 +1118,9 @@ name_die(Config) when is_list(Config) ->
KillFile = filename:join([Dir, "kill.txt"]),
file:delete(KillFile),
erlang:spawn(Cp1, fun() -> kill_pid(Pid2, KillFile, Config) end),
- rpc_cast(Cp1,
- ?MODULE, part_2_2, [Config,
- Part1,
- Part2,
- []]),
- ?UNTIL(is_ready_partition(Config)),
+
+ setup_partitions(PartCtrlr, [Part1, Part2]),
+
?UNTIL(undefined =:= global:whereis_name(Name)),
yes = global:register_name(Name, Pid2),
touch(KillFile, "kill"),
@@ -1001,6 +1130,7 @@ name_die(Config) when is_list(Config) ->
?UNTIL(OrigNames =:= global:registered_names()),
write_high_level_trace(Config),
stop_nodes(Cps),
+ stop_partition_controller(PartCtrlr),
init_condition(Config),
ok.
@@ -1023,16 +1153,26 @@ basic_partition(Config) when is_list(Config) ->
wait_for_ready_net(Config),
%% make cp2 and cp3 connected, partitioned from us and cp1
- rpc_cast(Cp2, ?MODULE, part1, [Config, node(), Cp1, Cp3]),
- ?UNTIL(is_ready_partition(Config)),
+ PCtrlr = setup_partitions(Config, [[node(), Cp1], [Cp2, Cp3]]),
%% start different processes in both partitions
{Pid, yes} = start_proc(test),
+ %% Reach into the other partition via PCtrlr...
+ ok = rfcall(
+ PCtrlr,
+ fun () ->
+ {_, yes} = rpc:call(Cp2, ?MODULE,
+ start_proc, [test2]),
+ {_, yes} = rpc:call(Cp1, ?MODULE,
+ start_proc, [test4]),
+ ok
+ end),
+
%% connect to other partition
pong = net_adm:ping(Cp2),
pong = net_adm:ping(Cp3),
- [Cp1, Cp2, Cp3] = lists:sort(nodes()),
+ wait_until(fun () -> [Cp1, Cp2, Cp3] == lists:sort(nodes()) end),
%% check names
?UNTIL(Pid =:= rpc:call(Cp2, global, whereis_name, [test])),
@@ -1059,6 +1199,7 @@ basic_partition(Config) when is_list(Config) ->
stop_node(Cp1),
stop_node(Cp2),
stop_node(Cp3),
+ stop_node(PCtrlr),
init_condition(Config),
ok.
@@ -1091,12 +1232,23 @@ basic_name_partition(Config) when is_list(Config) ->
%% cp2: register name12
%% cp3: register name03
- rpc_cast(Cp2, ?MODULE, part1_5, [Config, node(), Cp1, Cp3]),
- ?UNTIL(is_ready_partition(Config)),
+ PCtrlr = setup_partitions(Config, [[node(), Cp1], [Cp2, Cp3]]),
%% start different processes in both partitions
{_, yes} = start_proc_basic(name03),
{_, yes} = rpc:call(Cp1, ?MODULE, start_proc_basic, [name12]),
+
+ %% Reach into the other partition via PCtrlr...
+ ok = rfcall(
+ PCtrlr,
+ fun () ->
+ {_, yes} = rpc:call(Cp2, ?MODULE,
+ start_proc_basic, [name12]),
+ {_, yes} = rpc:call(Cp3, ?MODULE,
+ start_proc_basic, [name03]),
+ ok
+ end),
+
ct:sleep(1000),
%% connect to other partition
@@ -1135,6 +1287,7 @@ basic_name_partition(Config) when is_list(Config) ->
stop_node(Cp1),
stop_node(Cp2),
stop_node(Cp3),
+ stop_node(PCtrlr),
init_condition(Config),
ok.
@@ -1160,24 +1313,36 @@ advanced_partition(Config) when is_list(Config) ->
init_condition(Config),
OrigNames = global:registered_names(),
+ Parent = self(),
+
[Cp0, Cp1, Cp2, Cp3, Cp4, Cp5, Cp6]
= start_nodes([cp0, cp1, cp2, cp3, cp4, cp5, cp6], peer, Config),
Nodes = lists:sort([node(), Cp0, Cp1, Cp2, Cp3, Cp4, Cp5, Cp6]),
wait_for_ready_net(Config),
%% make cp3-cp6 connected, partitioned from us and cp0-cp2
- rpc_cast(Cp3, ?MODULE, part2,
- [Config, self(), node(), Cp0, Cp1, Cp2, Cp3, Cp4, Cp5,Cp6]),
- ?UNTIL(is_ready_partition(Config)),
+ PCntrlr = setup_partitions(Config, [[node(), Cp0, Cp1, Cp2], [Cp3, Cp4, Cp5, Cp6]]),
+
+ %% start processes in other partition (via partition controller)...
+ ok = rfcall(PCntrlr,
+ fun () ->
+ rfcall(Cp3,
+ fun () ->
+ start_procs(Parent, Cp4, Cp5, Cp6, Config),
+ ok
+ end)
+ end),
%% start different processes in this partition
start_procs(self(), Cp0, Cp1, Cp2, Config),
%% connect to other partition
pong = net_adm:ping(Cp3),
- pong = net_adm:ping(Cp4),
- pong = net_adm:ping(Cp5),
- pong = net_adm:ping(Cp6),
+
+ wait_until(fun () ->
+ CurrNodes = lists:sort(?NODES),
+ io:format("CurrNodes: ~p~n", [CurrNodes]),
+ Nodes == CurrNodes end),
wait_for_ready_net(Config),
@@ -1240,6 +1405,7 @@ advanced_partition(Config) when is_list(Config) ->
stop_node(Cp4),
stop_node(Cp5),
stop_node(Cp6),
+ stop_node(PCntrlr),
init_condition(Config),
ok.
@@ -1261,16 +1427,44 @@ stress_partition(Config) when is_list(Config) ->
init_condition(Config),
OrigNames = global:registered_names(),
- [Cp0, Cp1, Cp2, Cp3, Cp4, Cp5, Cp6]
- = start_nodes([cp0, cp1, cp2, cp3, cp4, cp5, cp6], peer, Config),
+ Parent = self(),
+
+ [Cp0, Cp1, Cp2, Cp3, Cp4, Cp5, Cp6a, Cp6b]
+ = start_nodes([cp0, cp1, cp2, cp3, cp4, cp5, cp6a, cp6b], peer, Config),
wait_for_ready_net(Config),
%% make cp3-cp5 connected, partitioned from us and cp0-cp2
%% cp6 is alone (single node). cp6 pings cp0 and cp3 in 12 secs...
- rpc_cast(Cp3, ?MODULE, part3,
- [Config, self(), node(), Cp0, Cp1, Cp2, Cp3, Cp4, Cp5,Cp6]),
- ?UNTIL(is_ready_partition(Config)),
+ PCntrlr = setup_partitions(Config, [[node(), Cp0, Cp1, Cp2], [Cp3, Cp4, Cp5, Cp6a], [Cp6b]]),
+
+ %% start processes in other partition (via partition controller)...
+ ok = rfcall(PCntrlr,
+ fun () ->
+ ok = rfcall(Cp3,
+ fun () ->
+ start_procs(Parent, Cp4, Cp5, Cp6a, Config),
+ ok
+ end),
+ ok = rfcall(Cp6b,
+ fun () ->
+ Pid1 = start_proc3(test1),
+ assert_pid(Pid1),
+ Pid2 = start_proc3(test3),
+ assert_pid(Pid2),
+ yes = global:register_name(
+ test1, Pid1),
+ yes = global:register_name(
+ test3, Pid2,
+ fun global:random_notify_name/3),
+ ok
+ end),
+ %% Make Cp5 crash
+ rpc:cast(Cp5, ?MODULE, crash, [12000]),
+ %% Make Cp6b alone
+ rpc:cast(Cp6b, ?MODULE, alone, [Cp0, Cp3]),
+ ok
+ end),
%% start different processes in this partition
start_procs(self(), Cp0, Cp1, Cp2, Config),
@@ -1289,17 +1483,19 @@ stress_partition(Config) when is_list(Config) ->
%% connect to other partition
pong = net_adm:ping(Cp3),
+ pong = net_adm:ping(Cp4),
rpc_cast(Cp2, ?MODULE, crash, [0]),
%% Start new nodes
{ok, Cp7} = start_peer_node(cp7, Config),
{ok, Cp2_2} = start_peer_node(cp2, Config),
- Nodes = lists:sort([node(), Cp0, Cp1, Cp2_2, Cp3, Cp4, Cp6, Cp7, Cp8]),
+ Nodes = lists:sort([node(), Cp0, Cp1, Cp2_2, Cp3, Cp4, Cp6a, Cp6b, Cp7, Cp8]),
put(?nodes_tag, Nodes),
- pong = net_adm:ping(Cp4),
- pong = net_adm:ping(Cp6),
- pong = net_adm:ping(Cp8),
+ %% We don't know how the crashes partitions the net, so
+ %% we cast trough all nodes so we get them all connected
+ %% again...
+ cast_line(Nodes),
wait_for_ready_net(Nodes, Config),
@@ -1332,9 +1528,11 @@ stress_partition(Config) when is_list(Config) ->
stop_node(Cp3),
stop_node(Cp4),
stop_node(Cp5),
- stop_node(Cp6),
+ stop_node(Cp6a),
+ stop_node(Cp6b),
stop_node(Cp7),
stop_node(Cp8),
+ stop_node(PCntrlr),
init_condition(Config),
ok.
@@ -1373,40 +1571,27 @@ ring(Config) when is_list(Config) ->
wait_for_ready_net(Config),
- Time = msec() + 7000,
-
- rpc_cast(Cp0, ?MODULE, single_node, [Time, Cp8, Config]),
- rpc_cast(Cp1, ?MODULE, single_node, [Time, Cp0, Config]),
- rpc_cast(Cp2, ?MODULE, single_node, [Time, Cp1, Config]),
- rpc_cast(Cp3, ?MODULE, single_node, [Time, Cp2, Config]),
- rpc_cast(Cp4, ?MODULE, single_node, [Time, Cp3, Config]),
- rpc_cast(Cp5, ?MODULE, single_node, [Time, Cp4, Config]),
- rpc_cast(Cp6, ?MODULE, single_node, [Time, Cp5, Config]),
- rpc_cast(Cp7, ?MODULE, single_node, [Time, Cp6, Config]),
- rpc_cast(Cp8, ?MODULE, single_node, [Time, Cp7, Config]),
-
- %% sleep to make the partitioned net ready
- sleep(Time - msec()),
-
- pong = net_adm:ping(Cp0),
- pong = net_adm:ping(Cp1),
- pong = net_adm:ping(Cp2),
- pong = net_adm:ping(Cp3),
- pong = net_adm:ping(Cp4),
- pong = net_adm:ping(Cp5),
- pong = net_adm:ping(Cp6),
- pong = net_adm:ping(Cp7),
- pong = net_adm:ping(Cp8),
+ PartCtrlr = setup_partitions(Config,
+ [[node()], [Cp0], [Cp1], [Cp2], [Cp3],
+ [Cp4], [Cp5], [Cp6], [Cp7], [Cp8]]),
+ Time = msec() + 1000,
+
+ ok = rfcall(
+ PartCtrlr,
+ fun () ->
+ rpc:cast(Cp0, ?MODULE, single_node, [Time, Cp8]), % ping ourself!
+ rpc:cast(Cp1, ?MODULE, single_node, [Time, Cp0]),
+ rpc:cast(Cp2, ?MODULE, single_node, [Time, Cp1]),
+ rpc:cast(Cp3, ?MODULE, single_node, [Time, Cp2]),
+ rpc:cast(Cp4, ?MODULE, single_node, [Time, Cp3]),
+ rpc:cast(Cp5, ?MODULE, single_node, [Time, Cp4]),
+ rpc:cast(Cp6, ?MODULE, single_node, [Time, Cp5]),
+ rpc:cast(Cp7, ?MODULE, single_node, [Time, Cp6]),
+ rpc:cast(Cp8, ?MODULE, single_node, [Time, Cp7]),
+ ok
+ end),
pong = net_adm:ping(Cp0),
- pong = net_adm:ping(Cp1),
- pong = net_adm:ping(Cp2),
- pong = net_adm:ping(Cp3),
- pong = net_adm:ping(Cp4),
- pong = net_adm:ping(Cp5),
- pong = net_adm:ping(Cp6),
- pong = net_adm:ping(Cp7),
- pong = net_adm:ping(Cp8),
wait_for_ready_net(Nodes, Config),
@@ -1437,6 +1622,7 @@ ring(Config) when is_list(Config) ->
stop_node(Cp6),
stop_node(Cp7),
stop_node(Cp8),
+ stop_partition_controller(PartCtrlr),
init_condition(Config),
ok.
@@ -1459,31 +1645,24 @@ simple_ring(Config) when is_list(Config) ->
wait_for_ready_net(Config),
- Time = msec() + 5000,
-
- rpc_cast(Cp0, ?MODULE, single_node, [Time, Cp5, Config]),
- rpc_cast(Cp1, ?MODULE, single_node, [Time, Cp0, Config]),
- rpc_cast(Cp2, ?MODULE, single_node, [Time, Cp1, Config]),
- rpc_cast(Cp3, ?MODULE, single_node, [Time, Cp2, Config]),
- rpc_cast(Cp4, ?MODULE, single_node, [Time, Cp3, Config]),
- rpc_cast(Cp5, ?MODULE, single_node, [Time, Cp4, Config]),
-
- %% sleep to make the partitioned net ready
- sleep(Time - msec()),
-
- pong = net_adm:ping(Cp0),
- pong = net_adm:ping(Cp1),
- pong = net_adm:ping(Cp2),
- pong = net_adm:ping(Cp3),
- pong = net_adm:ping(Cp4),
- pong = net_adm:ping(Cp5),
+ PartCtrlr = setup_partitions(Config,
+ [[node()], [Cp0], [Cp1], [Cp2], [Cp3],
+ [Cp4], [Cp5]]),
+ Time = msec() + 1000,
+
+ ok = rfcall(
+ PartCtrlr,
+ fun () ->
+ rpc:cast(Cp0, ?MODULE, single_node, [Time, Cp5]), % ping ourself!
+ rpc:cast(Cp1, ?MODULE, single_node, [Time, Cp0]),
+ rpc:cast(Cp2, ?MODULE, single_node, [Time, Cp1]),
+ rpc:cast(Cp3, ?MODULE, single_node, [Time, Cp2]),
+ rpc:cast(Cp4, ?MODULE, single_node, [Time, Cp3]),
+ rpc:cast(Cp5, ?MODULE, single_node, [Time, Cp4]),
+ ok
+ end),
pong = net_adm:ping(Cp0),
- pong = net_adm:ping(Cp1),
- pong = net_adm:ping(Cp2),
- pong = net_adm:ping(Cp3),
- pong = net_adm:ping(Cp4),
- pong = net_adm:ping(Cp5),
wait_for_ready_net(Nodes, Config),
@@ -1511,6 +1690,7 @@ simple_ring(Config) when is_list(Config) ->
stop_node(Cp3),
stop_node(Cp4),
stop_node(Cp5),
+ stop_partition_controller(PartCtrlr),
init_condition(Config),
ok.
@@ -1531,41 +1711,27 @@ line(Config) when is_list(Config) ->
wait_for_ready_net(Config),
- Time = msec() + 7000,
-
- rpc_cast(Cp0, ?MODULE, single_node,
- [Time, Cp0, Config]), % ping ourself!
- rpc_cast(Cp1, ?MODULE, single_node, [Time, Cp0, Config]),
- rpc_cast(Cp2, ?MODULE, single_node, [Time, Cp1, Config]),
- rpc_cast(Cp3, ?MODULE, single_node, [Time, Cp2, Config]),
- rpc_cast(Cp4, ?MODULE, single_node, [Time, Cp3, Config]),
- rpc_cast(Cp5, ?MODULE, single_node, [Time, Cp4, Config]),
- rpc_cast(Cp6, ?MODULE, single_node, [Time, Cp5, Config]),
- rpc_cast(Cp7, ?MODULE, single_node, [Time, Cp6, Config]),
- rpc_cast(Cp8, ?MODULE, single_node, [Time, Cp7, Config]),
-
- %% Sleep to make the partitioned net ready
- sleep(Time - msec()),
-
- pong = net_adm:ping(Cp0),
- pong = net_adm:ping(Cp1),
- pong = net_adm:ping(Cp2),
- pong = net_adm:ping(Cp3),
- pong = net_adm:ping(Cp4),
- pong = net_adm:ping(Cp5),
- pong = net_adm:ping(Cp6),
- pong = net_adm:ping(Cp7),
- pong = net_adm:ping(Cp8),
+ PartCtrlr = setup_partitions(Config,
+ [[node()], [Cp0], [Cp1], [Cp2], [Cp3],
+ [Cp4], [Cp5], [Cp6], [Cp7], [Cp8]]),
+ ThisNode = node(),
- pong = net_adm:ping(Cp0),
- pong = net_adm:ping(Cp1),
- pong = net_adm:ping(Cp2),
- pong = net_adm:ping(Cp3),
- pong = net_adm:ping(Cp4),
- pong = net_adm:ping(Cp5),
- pong = net_adm:ping(Cp6),
- pong = net_adm:ping(Cp7),
- pong = net_adm:ping(Cp8),
+ Time = msec() + 1000,
+ ok = rfcall(
+ PartCtrlr,
+ fun () ->
+ rpc:cast(Cp0, ?MODULE, single_node, [Time, Cp0]), % ping ourself!
+ rpc:cast(Cp1, ?MODULE, single_node, [Time, Cp0]),
+ rpc:cast(Cp2, ?MODULE, single_node, [Time, Cp1]),
+ rpc:cast(Cp3, ?MODULE, single_node, [Time, Cp2]),
+ rpc:cast(Cp4, ?MODULE, single_node, [Time, Cp3]),
+ rpc:cast(Cp5, ?MODULE, single_node, [Time, Cp4]),
+ rpc:cast(Cp6, ?MODULE, single_node, [Time, Cp5]),
+ rpc:cast(Cp7, ?MODULE, single_node, [Time, Cp6]),
+ rpc:cast(Cp8, ?MODULE, single_node, [Time, Cp7]),
+ rpc:cast(ThisNode, ?MODULE, single_node, [Time, Cp8]),
+ ok
+ end),
wait_for_ready_net(Nodes, Config),
@@ -1596,6 +1762,7 @@ line(Config) when is_list(Config) ->
stop_node(Cp6),
stop_node(Cp7),
stop_node(Cp8),
+ stop_partition_controller(PartCtrlr),
init_condition(Config),
ok.
@@ -1618,32 +1785,24 @@ simple_line(Config) when is_list(Config) ->
wait_for_ready_net(Config),
- Time = msec() + 5000,
-
- rpc_cast(Cp0, ?MODULE, single_node,
- [Time, Cp0, Config]), % ping ourself!
- rpc_cast(Cp1, ?MODULE, single_node, [Time, Cp0, Config]),
- rpc_cast(Cp2, ?MODULE, single_node, [Time, Cp1, Config]),
- rpc_cast(Cp3, ?MODULE, single_node, [Time, Cp2, Config]),
- rpc_cast(Cp4, ?MODULE, single_node, [Time, Cp3, Config]),
- rpc_cast(Cp5, ?MODULE, single_node, [Time, Cp4, Config]),
-
- %% sleep to make the partitioned net ready
- sleep(Time - msec()),
-
- pong = net_adm:ping(Cp0),
- pong = net_adm:ping(Cp1),
- pong = net_adm:ping(Cp2),
- pong = net_adm:ping(Cp3),
- pong = net_adm:ping(Cp4),
- pong = net_adm:ping(Cp5),
+ PartCtrlr = setup_partitions(Config,
+ [[node()], [Cp0], [Cp1], [Cp2], [Cp3],
+ [Cp4], [Cp5]]),
+ ThisNode = node(),
- pong = net_adm:ping(Cp0),
- pong = net_adm:ping(Cp1),
- pong = net_adm:ping(Cp2),
- pong = net_adm:ping(Cp3),
- pong = net_adm:ping(Cp4),
- pong = net_adm:ping(Cp5),
+ Time = msec() + 1000,
+ ok = rfcall(
+ PartCtrlr,
+ fun () ->
+ rpc:cast(Cp0, ?MODULE, single_node, [Time, Cp0]), % ping ourself!
+ rpc:cast(Cp1, ?MODULE, single_node, [Time, Cp0]),
+ rpc:cast(Cp2, ?MODULE, single_node, [Time, Cp1]),
+ rpc:cast(Cp3, ?MODULE, single_node, [Time, Cp2]),
+ rpc:cast(Cp4, ?MODULE, single_node, [Time, Cp3]),
+ rpc:cast(Cp5, ?MODULE, single_node, [Time, Cp4]),
+ rpc:cast(ThisNode, ?MODULE, single_node, [Time, Cp5]),
+ ok
+ end),
wait_for_ready_net(Nodes, Config),
@@ -1671,6 +1830,7 @@ simple_line(Config) when is_list(Config) ->
stop_node(Cp3),
stop_node(Cp4),
stop_node(Cp5),
+ stop_partition_controller(PartCtrlr),
init_condition(Config),
ok.
@@ -1756,9 +1916,9 @@ otp_1849(Config) when is_list(Config) ->
%% Test ticket: Deadlock in global.
otp_3162(Config) when is_list(Config) ->
StartFun = fun() ->
- {ok, Cp1} = start_node(cp1, Config),
- {ok, Cp2} = start_node(cp2, Config),
- {ok, Cp3} = start_node(cp3, Config),
+ {ok, Cp1} = start_node(cp1, peer, Config),
+ {ok, Cp2} = start_node(cp2, peer, Config),
+ {ok, Cp3} = start_node(cp3, peer, Config),
[Cp1, Cp2, Cp3]
end,
do_otp_3162(StartFun, Config).
@@ -1772,6 +1932,10 @@ do_otp_3162(StartFun, Config) ->
wait_for_ready_net(Config),
+ ThisNode = node(),
+
+ PartCntrlr = setup_partitions(Config, [[ThisNode, Cp1, Cp2, Cp3]]),
+
%% start procs on each node
Pid1 = rpc:call(Cp1, ?MODULE, start_proc4, [kalle]),
assert_pid(Pid1),
@@ -1780,40 +1944,22 @@ do_otp_3162(StartFun, Config) ->
Pid3 = rpc:call(Cp3, ?MODULE, start_proc4, [vera]),
assert_pid(Pid3),
- rpc_disconnect_node(Cp1, Cp2, Config),
-
- ?UNTIL
- ([Cp3] =:= lists:sort(rpc:call(Cp1, erlang, nodes, [])) -- [node()]),
-
- ?UNTIL([kalle, vera] =:=
- lists:sort(rpc:call(Cp1, global, registered_names, []))),
- ?UNTIL
- ([Cp3] =:= lists:sort(rpc:call(Cp2, erlang, nodes, [])) -- [node()]),
- ?UNTIL([stina, vera] =:=
- lists:sort(rpc:call(Cp2, global, registered_names, []))),
- ?UNTIL
- ([Cp1, Cp2] =:=
- lists:sort(rpc:call(Cp3, erlang, nodes, [])) -- [node()]),
- ?UNTIL([kalle, stina, vera] =:=
- lists:sort(rpc:call(Cp3, global, registered_names, []))),
-
- pong = rpc:call(Cp2, net_adm, ping, [Cp1]),
-
- ?UNTIL
- ([Cp2, Cp3] =:=
- lists:sort(rpc:call(Cp1, erlang, nodes, [])) -- [node()]),
- ?UNTIL(begin
- NN = lists:sort(rpc:call(Cp1, global, registered_names, [])),
- [kalle, stina, vera] =:= NN
- end),
- ?UNTIL
- ([Cp1, Cp3] =:=
- lists:sort(rpc:call(Cp2, erlang, nodes, [])) -- [node()]),
- ?UNTIL([kalle, stina, vera] =:=
- lists:sort(rpc:call(Cp2, global, registered_names, []))),
- ?UNTIL
- ([Cp1, Cp2] =:=
- lists:sort(rpc:call(Cp3, erlang, nodes, [])) -- [node()]),
+ disconnect_nodes(PartCntrlr, Cp1, Cp2),
+ %% Nowadays we do not know how the net have been partitioned after the
+ %% disconnect, so we cannot perform all the tests this testcase originally
+ %% did. We instead only test the end result is ok after we have reconnected
+ %% all nodes.
+
+ ok = rfcall(PartCntrlr,
+ fun () ->
+ rpc:cast(Cp1, net_kernel, connect_node, [Cp3]),
+ rpc:cast(Cp2, net_kernel, connect_node, [Cp3]),
+ rpc:cast(ThisNode, net_kernel, connect_node, [Cp3]),
+ ok
+ end),
+
+ ?UNTIL(lists:sort([ThisNode, Cp1, Cp2]) =:=
+ lists:sort(rpc:call(Cp3, erlang, nodes, []))),
?UNTIL([kalle, stina, vera] =:=
lists:sort(rpc:call(Cp3, global, registered_names, []))),
@@ -1821,6 +1967,7 @@ do_otp_3162(StartFun, Config) ->
stop_node(Cp1),
stop_node(Cp2),
stop_node(Cp3),
+ stop_partition_controller(PartCntrlr),
init_condition(Config),
ok.
@@ -1949,6 +2096,8 @@ simple_disconnect(Config) when is_list(Config) ->
[Cp1, Cp2] = Cps = start_nodes([n_1, n_2], peer, Config),
wait_for_ready_net(Config),
+ PartCtrlr = start_partition_controller(Config),
+
Nodes = lists:sort([node() | Cps]),
lists:foreach(fun(N) -> rpc:call(N, ?MODULE, start_tracer, []) end,Nodes),
@@ -1962,16 +2111,21 @@ simple_disconnect(Config) when is_list(Config) ->
ct:sleep(100),
%% Disconnect test_server and Cp2.
- true = erlang:disconnect_node(Cp2),
- ct:sleep(500),
+ disconnect_nodes(PartCtrlr, node(), Cp2),
+ %% We might have been disconnected from Cp1 as well. Ensure connected
+ %% to Cp1...
+ pong = net_adm:ping(Cp1),
%% _Pid is registered on Cp1. The exchange of names between Cp2 and
%% test_server sees two identical pids.
pong = net_adm:ping(PingNode),
+
?UNTIL(Cps =:= lists:sort(nodes())),
{_, Trace0} = collect_tracers(Nodes),
Resolvers = [P || {_Node,new_resolver,{pid,P}} <- Trace0],
+ check_everywhere(Nodes, Name, Config),
+ true = undefined /= global:whereis_name(Name),
lists:foreach(fun(P) -> P ! die end, Resolvers),
lists:foreach(fun(P) -> wait_for_exit(P) end, Resolvers),
check_everywhere(Nodes, Name, Config),
@@ -1989,30 +2143,10 @@ simple_disconnect(Config) when is_list(Config) ->
OrigNames = global:registered_names(),
write_high_level_trace(Config),
stop_nodes(Cps),
+ stop_partition_controller(PartCtrlr),
init_condition(Config),
ok.
-%% Not used right now.
-simple_dis(Nodes0, Name, Resolver, Config) ->
- Nodes = [node() | Nodes0],
- NN = lists:zip(Nodes, lists:seq(1, length(Nodes))),
- [{_Node,Other} | Dis] =
- [{N,[N1 || {N1,I1} <- NN, I1 > I + 1]} || {N,I} <- NN],
- lists:foreach(
- fun({Node, DisNodes}) ->
- Args = [Node, DisNodes, Name, Resolver],
- ok = rpc:call(Node, ?MODULE, simple_dis_node, Args)
- end, Dis),
- ok = simple_dis_node(node(), Other, Name, Resolver, Config).
-
-simple_dis_node(_Node, DisNodes, _Name, _Resolver, Config) ->
- lists:foreach(
- fun(OtherNode) -> _ = erlang:disconnect_node(OtherNode) end, DisNodes),
- ?UNTIL(DisNodes -- nodes() =:= DisNodes),
- ok.
-
-
-
%%%-----------------------------------------------------------------
%%% Testing resolve of name. Many combinations with four nodes.
%%%-----------------------------------------------------------------
@@ -2023,7 +2157,8 @@ simple_dis_node(_Node, DisNodes, _Name, _Resolver, Config) ->
n2, % node starting registered process in partition 2
nodes, % nodes expected to exist after ping
n_res, % expected number of resolvers after ping
- config
+ config,
+ ctrlr
}).
-define(RES(F), {F, fun ?MODULE:F/3}).
@@ -2040,6 +2175,8 @@ simple_resolve(Config) when is_list(Config) ->
Nodes = lists:sort([node() | Cps]),
wait_for_ready_net(Config),
+ PartCtrlr = start_partition_controller(Config),
+
lists:foreach(fun(N) ->
rpc:call(N, ?MODULE, start_tracer, [])
end, Nodes),
@@ -2049,7 +2186,8 @@ simple_resolve(Config) when is_list(Config) ->
%% name 'link' remains...
Cf = #cf{link = none, ping = A2, n1 = node(), n2 = A2,
- nodes = [node(), N1, A2, Z2], n_res = 2, config = Config},
+ nodes = [node(), N1, A2, Z2], n_res = 2, config = Config,
+ ctrlr = PartCtrlr},
%% There is no test with a resolver that deletes a pid (like
%% global_exit_name does). The resulting DOWN signal just clears
@@ -2157,6 +2295,7 @@ simple_resolve(Config) when is_list(Config) ->
OrigNames = global:registered_names(),
write_high_level_trace(Config),
stop_nodes(Cps),
+ stop_partition_controller(PartCtrlr),
init_condition(Config),
ok.
@@ -2175,12 +2314,15 @@ simple_resolve2(Config) when is_list(Config) ->
wait_for_ready_net(Config),
Nodes = lists:sort([node() | Cps]),
+ PartCtrlr = start_partition_controller(Config),
+
lists:foreach(fun(N) ->
rpc:call(N, ?MODULE, start_tracer, [])
end, Nodes),
Cf = #cf{link = none, ping = A2, n1 = node(), n2 = A2,
- nodes = [node(), N1, A2, Z2], n_res = 2, config = Config},
+ nodes = [node(), N1, A2, Z2], n_res = 2, config = Config,
+ ctrlr = PartCtrlr},
%% Halt z_2.
res(?RES(halt_second), Cps, Cf#cf{link = N1, n1 = N1, n2 = Z2, ping = A2,
@@ -2193,6 +2335,7 @@ simple_resolve2(Config) when is_list(Config) ->
OrigNames = global:registered_names(),
write_high_level_trace(Config),
stop_nodes(Cps), % Not all nodes may be present, but it works anyway.
+ stop_partition_controller(PartCtrlr),
init_condition(Config),
ok.
@@ -2210,12 +2353,15 @@ simple_resolve3(Config) when is_list(Config) ->
wait_for_ready_net(Config),
Nodes = lists:sort([node() | Cps]),
+ PartCtrlr = start_partition_controller(Config),
+
lists:foreach(fun(N) ->
rpc:call(N, ?MODULE, start_tracer, [])
end, Nodes),
Cf = #cf{link = none, ping = A2, n1 = node(), n2 = A2,
- nodes = [node(), N1, A2, Z2], n_res = 2, config = Config},
+ nodes = [node(), N1, A2, Z2], n_res = 2, config = Config,
+ ctrlr = PartCtrlr},
%% Halt a_2.
res(?RES(halt_second), Cps, Cf#cf{link = node(), n2 = A2,
@@ -2228,13 +2374,14 @@ simple_resolve3(Config) when is_list(Config) ->
OrigNames = global:registered_names(),
write_high_level_trace(Config),
stop_nodes(Cps), % Not all nodes may be present, but it works anyway.
+ stop_partition_controller(PartCtrlr),
init_condition(Config),
ok.
res({Res,Resolver}, [N1, A2, Z2], Cf) ->
%% Note: there are no links anymore, but monitors.
#cf{link = LinkedNode, ping = PingNode, n1 = Res1, n2 = OtherNode,
- nodes = Nodes0, n_res = NRes, config = Config} = Cf,
+ nodes = Nodes0, n_res = NRes, config = Config, ctrlr = PartCtrlr} = Cf,
io:format("~n~nResolver: ~p", [Res]),
io:format(" Registered on partition 1: ~p", [Res1]),
io:format(" Registered on partition 2: ~p", [OtherNode]),
@@ -2252,11 +2399,20 @@ res({Res,Resolver}, [N1, A2, Z2], Cf) ->
%% expected monitors remain between registered processes and the
%% global_name_server.
- rpc_cast(OtherNode,
- ?MODULE,
- part_2_2,
- [Config, Part1, Part2, [{Name, Resolver}]]),
- ?UNTIL(is_ready_partition(Config)),
+ setup_partitions(PartCtrlr, [Part1, Part2]),
+
+ ok = rfcall(PartCtrlr,
+ fun () ->
+ rfcall(OtherNode,
+ fun () ->
+ {Pid2, yes} = start_resolver(Name,
+ Resolver),
+ trace_message({node(), part_2_2,
+ nodes(), {pid2,Pid2}}),
+ ok
+ end)
+ end),
+
{_Pid1, yes} =
rpc:call(Res1, ?MODULE, start_resolver, [Name, Resolver]),
@@ -2319,15 +2475,6 @@ monitored_by_node(Trace, Servers) ->
M <- ML,
lists:member(M, Servers)]).
-%% Runs on a node in Part2
-part_2_2(Config, Part1, Part2, NameResolvers) ->
- make_partition(Config, Part1, Part2),
- lists:foreach
- (fun({Name, Resolver}) ->
- {Pid2, yes} = start_resolver(Name, Resolver),
- trace_message({node(), part_2_2, nodes(), {pid2,Pid2}})
- end, NameResolvers).
-
resolve_first(name, Pid1, _Pid2) ->
Pid1.
@@ -2398,7 +2545,7 @@ mon_by_servers(Proc) ->
{monitored_by, ML} = process_info(Proc, monitored_by),
{monitors_2levels,
lists:append([ML |
- [begin
+ [begin
{monitored_by, MML} = rpc:call(node(M),
erlang,
process_info,
@@ -2433,13 +2580,23 @@ leftover_name(Config) when is_list(Config) ->
Part2 = [A2, Z2],
NoResolver = {no_module, resolve_none},
Resolver = fun contact_a_2/3,
- rpc_cast(A2,
- ?MODULE, part_2_2, [Config,
- Part1,
- Part2,
- [{Name, NoResolver},
- {ResName, Resolver}]]),
- ?UNTIL(is_ready_partition(Config)),
+
+ PartCtrlr = setup_partitions(Config, [Part1, Part2]),
+
+ ok = rfcall(
+ PartCtrlr,
+ fun () ->
+ rfcall(
+ A2,
+ fun () ->
+ lists:foreach(
+ fun({TheName, TheResolver}) ->
+ {Pid2, yes} = start_resolver(TheName, TheResolver),
+ trace_message({node(), part_2_2, nodes(), {pid2,Pid2}})
+ end, [{Name, NoResolver}, {ResName, Resolver}]),
+ ok
+ end)
+ end),
%% resolved_name is resolved to run on a_2, an insert operation is
%% sent to n_1. The resolver function halts a_2, but the nodedown
@@ -2471,6 +2628,7 @@ leftover_name(Config) when is_list(Config) ->
?UNTIL(OrigNames =:= global:registered_names()),
write_high_level_trace(Config),
stop_nodes(Cps),
+ stop_partition_controller(PartCtrlr),
init_condition(Config),
ok.
@@ -2636,9 +2794,22 @@ external_nodes(Config) when is_list(Config) ->
%% Two partitions: [test_server] and [b, c].
%% c registers an external name on b
- rpc_cast(NodeB, ?MODULE, part_ext,
- [Config, node(), NodeC, Name]),
- ?UNTIL(is_ready_partition(Config)),
+
+ PartCtrlr = setup_partitions(Config, [[node()], [NodeB, NodeC]]),
+
+ ok = rfcall(
+ PartCtrlr,
+ fun () ->
+ rfcall(
+ NodeB,
+ fun () ->
+ Pid = spawn(NodeC, fun() -> cnode_proc(NodeB) end),
+ Pid ! {register, self(), Name},
+ receive {Pid, Reply} -> yes = Reply end,
+ rpc:call(NodeC, erlang, register, [Name, Pid]),
+ ok
+ end)
+ end),
pong = net_adm:ping(NodeB),
?UNTIL([NodeB, NodeC] =:= lists:sort(nodes())),
@@ -2702,6 +2873,7 @@ external_nodes(Config) when is_list(Config) ->
?UNTIL(length(get_ext_names()) =:= 1),
stop_node(NodeC),
+ stop_partition_controller(PartCtrlr),
?UNTIL(length(get_ext_names()) =:= 0),
init_condition(Config),
@@ -2710,15 +2882,6 @@ external_nodes(Config) when is_list(Config) ->
get_ext_names() ->
gen_server:call(global_name_server, get_names_ext, infinity).
-%% Runs at B
-part_ext(Config, Main, C, Name) ->
- make_partition(Config, [Main], [node(), C]),
- ThisNode = node(),
- Pid = erlang:spawn(C, fun() -> cnode_proc(ThisNode) end),
- Pid ! {register, self(), Name},
- receive {Pid, Reply} -> yes = Reply end,
- rpc:call(C, erlang, register, [Name, Pid]).
-
cnode_links(Pid) ->
Pid ! {links, self()},
receive
@@ -2776,25 +2939,29 @@ many_nodes(Config) when is_list(Config) ->
Nodes = lists:sort(?NODES),
wait_for_ready_net(Nodes, Config),
- Dir = proplists:get_value(priv_dir, Config),
- GoFile = filename:join([Dir, "go.txt"]),
- file:delete(GoFile),
-
- CpsFiles = [{N, filename:join([Dir, atom_to_list(N)++".node"])} ||
- N <- Cps],
- IsoFun =
- fun({N, File}) ->
- file:delete(File),
- rpc_cast(N, ?MODULE, isolated_node, [File, GoFile, Cps, Config])
- end,
- lists:foreach(IsoFun, CpsFiles),
+ %% All nodes isolated not connected to any other (visible) nodes...
+ Partitions = [[node()] | lists:map(fun (Node) -> [Node] end, Cps)],
+
+ PartCtrlr = setup_partitions(Config, Partitions),
- all_nodes_files(CpsFiles, "isolated", Config),
Time = msec(),
- sync_until(),
- erlang:display(ready_to_go),
- touch(GoFile, "go"),
- all_nodes_files(CpsFiles, "done", Config),
+
+ ok = rfcall(
+ PartCtrlr,
+ fun () ->
+ OkRes = {lists:map(fun (_) -> ok end, Cps), []},
+ OkRes = rfmulticall(
+ Cps,
+ fun () ->
+ lists:foreach(fun(N) ->
+ _ = net_adm:ping(N)
+ end, shuffle(Cps)),
+ ?UNTIL((Cps -- get_known(node())) =:= []),
+ ok
+ end),
+ ok
+ end),
+
Time2 = msec(),
lists:foreach(fun(N) -> pong = net_adm:ping(N) end, Cps),
@@ -2803,12 +2970,10 @@ many_nodes(Config) when is_list(Config) ->
write_high_level_trace(Config), % The test succeeded, but was it slow?
- lists:foreach(fun({_N, File}) -> file:delete(File) end, CpsFiles),
- file:delete(GoFile),
-
?UNTIL(OrigNames =:= global:registered_names()),
write_high_level_trace(Config),
stop_nodes(Cps),
+ stop_partition_controller(PartCtrlr),
init_condition(Config),
Diff = Time2 - Time,
Return = lists:flatten(io_lib:format("~w nodes took ~w ms",
@@ -2831,29 +2996,6 @@ node_rel(From, To) ->
1 -> Last
end} || N <- NodeNumbers].
-isolated_node(File, GoFile, Nodes, Config) ->
- Ns = lists:sort(Nodes),
- exit(erlang:whereis(user), kill),
- touch(File, "start_isolated"),
- NodesList = nodes(),
- append_to_file(File, [{nodes,Nodes},{nodes_list,NodesList}]),
- Replies =
- lists:map(fun(N) -> _ = erlang:disconnect_node(N) end, NodesList),
- append_to_file(File, {replies,Replies}),
- ?UNTIL(begin
- Known = get_known(node()),
- append_to_file(File, {known,Known}),
- Known =:= [node()]
- end),
- touch(File, "isolated"),
- sync_until(File),
- file_contents(GoFile, "go", Config, File),
- touch(File, "got_go"),
- lists:foreach(fun(N) -> _ = net_adm:ping(N) end, shuffle(Nodes)),
- touch(File, "pinged"),
- ?UNTIL((Ns -- get_known(node())) =:= []),
- touch(File, "done").
-
touch(File, List) ->
ok = file:write_file(File, list_to_binary(List)).
@@ -2862,11 +3004,6 @@ append_to_file(File, Term) ->
ok = file:write(Fd, io_lib:format("~p.~n", [Term])),
ok = file:close(Fd).
-all_nodes_files(CpsFiles, ContentsList, Config) ->
- lists:all(fun({_N,File}) ->
- file_contents(File, ContentsList, Config)
- end, CpsFiles).
-
file_contents(File, ContentsList, Config) ->
file_contents(File, ContentsList, Config, no_log_file).
@@ -2890,14 +3027,6 @@ file_contents(File, ContentsList, Config, LogFile) ->
end
end).
-sync_until() ->
- sync_until(no_log_file).
-
-sync_until(LogFile) ->
- Time = ?UNTIL_LOOP - (msec(now()) rem ?UNTIL_LOOP),
- catch append_to_file(LogFile, {sync_until, Time}),
- timer:sleep(Time).
-
shuffle(L) ->
[E || {_, E} <- lists:keysort(1, [{rand:uniform(), E} || E <- L])].
@@ -3378,109 +3507,11 @@ from(_H, []) -> [].
other(A, [A, _B]) -> A;
other(_, [_A, B]) -> B.
-
-%% this one runs at cp2
-part1(Config, Main, Cp1, Cp3) ->
- case catch begin
- make_partition(Config, [Main, Cp1], [node(), Cp3]),
- {_Pid, yes} = start_proc(test2),
- {_Pid2, yes} = start_proc(test4)
- end of
- {_, yes} -> ok; % w("ok", []);
- {'EXIT', _R} ->
- ok
- %% w("global_SUITE line:~w: ~p", [?LINE, _R])
- end.
-
-%% Runs at Cp2
-part1_5(Config, Main, Cp1, Cp3) ->
- case catch begin
- make_partition(Config, [Main, Cp1], [node(), Cp3]),
- {_Pid1, yes} = start_proc_basic(name12),
- {_Pid2, yes} =
- rpc:call(Cp3, ?MODULE, start_proc_basic, [name03])
- end of
- {_, yes} -> ok; % w("ok", []);
- {'EXIT', _R} ->
- ok
- %% w("global_SUITE line:~w: ~p", [?LINE, _R])
- end.
-
w(X,Y) ->
{ok, F} = file:open("cp2.log", [write]),
io:format(F, X, Y),
file:close(F).
-%% this one runs on one node in Part2
-%% The partition is ready when is_ready_partition(Config) returns (true).
-make_partition(Config, Part1, Part2) ->
- Dir = proplists:get_value(priv_dir, Config),
- Ns = [begin
- Name = lists:concat([atom_to_list(N),"_",msec(),".part"]),
- File = filename:join([Dir, Name]),
- file:delete(File),
- rpc_cast(N, ?MODULE, mk_part_node, [File, Part, Config], File),
- {N, File}
- end || Part <- [Part1, Part2], N <- Part],
- all_nodes_files(Ns, "done", Config),
- lists:foreach(fun({_N,File}) -> file:delete(File) end, Ns),
- PartFile = make_partition_file(Config),
- touch(PartFile, "done").
-
-%% The node signals its success by touching a file.
-mk_part_node(File, MyPart0, Config) ->
- touch(File, "start"), % debug
- MyPart = lists:sort(MyPart0),
- ?UNTIL(is_node_in_part(File, MyPart)),
- touch(File, "done").
-
-%% The calls to append_to_file are for debugging.
-is_node_in_part(File, MyPart) ->
- lists:foreach(fun(N) ->
- _ = erlang:disconnect_node(N)
- end, nodes() -- MyPart),
- case {(Known = get_known(node())) =:= MyPart,
- (Nodes = lists:sort([node() | nodes()])) =:= MyPart} of
- {true, true} ->
- %% Make sure the resolvers have been terminated,
- %% otherwise they may pop up and send some message.
- %% (This check is probably unnecessary.)
- case element(5, global:info()) of
- [] ->
- true;
- Rs ->
- erlang:display({is_node_in_part, resolvers, Rs}),
- trace_message({node(), is_node_in_part, Rs}),
- append_to_file(File, {now(), Known, Nodes, Rs}),
- false
- end;
- _ ->
- append_to_file(File, {now(), Known, Nodes}),
- false
- end.
-
-is_ready_partition(Config) ->
- File = make_partition_file(Config),
- file_contents(File, "done", Config),
- file:delete(File),
- true.
-
-make_partition_file(Config) ->
- Dir = proplists:get_value(priv_dir, Config),
- filename:join([Dir, atom_to_list(make_partition_done)]).
-
-%% this one runs at cp3
-part2(Config, Parent, Main, Cp0, Cp1, Cp2, Cp3, Cp4, Cp5, Cp6) ->
- make_partition(Config, [Main, Cp0, Cp1, Cp2], [Cp3, Cp4, Cp5, Cp6]),
- start_procs(Parent, Cp4, Cp5, Cp6, Config).
-
-part3(Config, Parent, Main, Cp0, Cp1, Cp2, Cp3, Cp4, Cp5, Cp6) ->
- make_partition(Config, [Main, Cp0, Cp1, Cp2], [Cp3, Cp4, Cp5, Cp6]),
- start_procs(Parent, Cp4, Cp5, Cp6, Config),
- %% Make Cp6 alone
- rpc_cast(Cp5, ?MODULE, crash, [12000]),
- rpc_cast(Cp6, ?MODULE, alone, [Cp0, Cp3]).
-
start_procs(Parent, N1, N2, N3, Config) ->
S1 = lists:sort([N1, N2, N3]),
?UNTIL(begin
@@ -3575,13 +3606,11 @@ init_proc_basic(Parent, Name) ->
Parent ! {self(),X},
loop().
-single_node(Time, Node, Config) ->
- exit(erlang:whereis(user), kill),
- lists:foreach(fun(N) -> _ = erlang:disconnect_node(N) end, nodes()),
- ?UNTIL(get_known(node()) =:= [node()]),
+single_node(Time, Node) ->
spawn(?MODULE, init_2, []),
- sleep(Time - msec()),
- net_adm:ping(Node).
+ timer:sleep(Time - msec()),
+ _ = net_adm:ping(Node),
+ ok.
init_2() ->
register(single_name, self()),
@@ -3640,8 +3669,6 @@ sreq(Pid, Msg) ->
receive {Ref, X} -> X end.
alone(N1, N2) ->
- lists:foreach(fun(Node) -> true = erlang:disconnect_node(Node) end,
- nodes()),
ct:sleep(12000),
net_adm:ping(N1),
net_adm:ping(N2),
@@ -4173,16 +4200,150 @@ rpc_cast(Node, Module, Function, Args) ->
{_,pong,Node}= {node(),net_adm:ping(Node),Node},
rpc:cast(Node, Module, Function, Args).
-rpc_cast(Node, Module, Function, Args, File) ->
- case net_adm:ping(Node) of
- pong ->
- rpc:cast(Node, Module, Function, Args);
- Else ->
- append_to_file(File, {now(), {rpc_cast, Node, Module, Function,
- Args, Else}})
- %% Maybe we should crash, but it probably doesn't matter.
+global_known(Node) ->
+ gen_server:call({global_name_server, Node}, get_known, infinity).
+
+global_known() ->
+ global_known(node()).
+
+disconnect(Node) ->
+ erlang:disconnect_node(Node),
+ wait_until(fun () -> not lists:member(Node, global_known()) end),
+ ok.
+
+disconnect_nodes(HiddenCtrlNode, NodeA, NodeB) ->
+ Nodes = [node()|nodes()],
+ ok = rfcall(HiddenCtrlNode,
+ fun () ->
+ ok = rfcall(NodeA,
+ fun () ->
+ disconnect(NodeB)
+ end),
+ ok = rfcall(NodeB,
+ fun () ->
+ disconnect(NodeA)
+ end),
+ %% Try to ensure 'lost_connection' messages
+ %% have been handled (see comment in
+ %% create_partitions)...
+ lists:foreach(fun (N) ->
+ _ = global_known(N)
+ end, Nodes),
+ ok
+ end).
+
+create_partitions(PartitionsList) ->
+ AllNodes = lists:sort(lists:flatten(PartitionsList)),
+
+ %% Take down all connections on all nodes...
+ AllOk = {lists:map(fun (_) -> ok end, AllNodes), []},
+ io:format("Disconnecting all nodes from eachother...", []),
+ AllOk = rfmulticall(
+ AllNodes,
+ fun () ->
+ lists:foreach(fun (N) ->
+ erlang:disconnect_node(N)
+ end, nodes()),
+ wait_until(fun () -> [] == global_known() end),
+ ok
+ end, 5000),
+ %% Here we know that all 'lost_connection' messages that will be
+ %% sent by global name servers due to these disconnects have been
+ %% sent, but we don't know that all of them have been received and
+ %% handled. By communicating with all global name servers one more
+ %% time it is very likely that all of them have been received and
+ %% handled (however, not guaranteed). If 'lost_connection' messages
+ %% are received after we begin to set up the partitions, the
+ %% partitions may lose connection with some of its nodes.
+ lists:foreach(fun (N) -> [] = global_known(N) end, AllNodes),
+
+ %% Set up fully connected partitions...
+ io:format("Connecting partitions...", []),
+ lists:foreach(
+ fun (Partition) ->
+ Part = lists:sort(Partition),
+ PartOk = {lists:map(fun (_) -> ok end, Part), []},
+ PartOk = rfmulticall(
+ Part,
+ fun () ->
+ wait_until(
+ fun () ->
+ ConnNodes = Part -- [node()|nodes()],
+ if ConnNodes == [] ->
+ true;
+ true ->
+ lists:foreach(
+ fun (N) ->
+ net_kernel:connect_node(N)
+ end, ConnNodes),
+ false
+ end
+ end),
+ ok
+
+ end, 5000)
+ end, PartitionsList),
+ ok.
+
+setup_partitions(PartCtrlr, PartList) when is_atom(PartCtrlr) ->
+ ok = rfcall(PartCtrlr, fun () -> create_partitions(PartList) end),
+ io:format("Partitions successfully setup:~n", []),
+ lists:foreach(fun (Part) ->
+ io:format("~p~n", [Part])
+ end,
+ PartList),
+ ok;
+setup_partitions(Config, PartList) when is_list(Config) ->
+ PartCtrlr = start_partition_controller(Config),
+ setup_partitions(PartCtrlr, PartList),
+ PartCtrlr.
+
+start_partition_controller(Config) when is_list(Config) ->
+ {ok, PartCtrlr} = start_hidden_node(part_ctrlr, Config),
+ PartCtrlr.
+
+stop_partition_controller(PartCtrlr) ->
+ stop_node(PartCtrlr).
+
+prevent_overlapping_partitions() ->
+ case application:get_env(kernel, prevent_overlapping_partitions) of
+ {ok, true} ->
+ true;
+ _ ->
+ false
+ end.
+
+cast_line([]) ->
+ ok;
+cast_line([N|Ns]) when N == node() ->
+ cast_line(Ns);
+cast_line([N|Ns]) ->
+ rfcast(N, fun () -> cast_line(Ns) end).
+
+wait_until(F) ->
+ case catch F() of
+ true ->
+ ok;
+ _ ->
+ receive after 10 -> ok end,
+ wait_until(F)
end.
+rfcall(Node, Fun) ->
+ rfcall(Node, Fun, infinity).
+
+rfcall(Node, Fun, Timeout) ->
+ rpc:call(Node, erlang, apply, [Fun, []], Timeout).
+
+rfcast(Node, Fun) ->
+ rpc:cast(Node, erlang, apply, [Fun, []]).
+
+rfmulticall(Nodes, Fun) ->
+ rfmulticall(Nodes, Fun, infinity).
+
+rfmulticall(Nodes, Fun, Timeout) ->
+ rpc:multicall(Nodes, erlang, apply, [Fun, []], Timeout).
+
%% The emulator now ensures that the node has been removed from
%% nodes().
rpc_disconnect_node(Node, DisconnectedNode, Config) ->
diff --git a/lib/kernel/test/pg2_SUITE.erl b/lib/kernel/test/pg2_SUITE.erl
index acecd34ead..1241fe586b 100644
--- a/lib/kernel/test/pg2_SUITE.erl
+++ b/lib/kernel/test/pg2_SUITE.erl
@@ -37,8 +37,7 @@
-define(testcase, proplists:get_value(?TESTCASE, Config)).
%% Internal export.
--export([mk_part_node_and_group/3, part2/4,
- mk_part_node/3, part1/5, p_init/3, start_proc/1, sane/0]).
+-export([p_init/3, start_proc/1, sane/0]).
init_per_testcase(Case, Config) ->
[{?TESTCASE, Case}| Config].
@@ -101,9 +100,19 @@ otp_8653(Config) when is_list(Config) ->
wait_for_ready_net(Config),
+ G = pg2_otp_8653,
+
+ {[ok,ok,ok,ok], []}
+ = rfmulticall([node(), A, B, C],
+ fun () ->
+ Pid = spawn(forever()),
+ ok = pg2:create(G),
+ _ = [ok = pg2:join(G, Pid) || _ <- [1,1]],
+ ok
+ end),
+
%% make b and c connected, partitioned from node() and a
- rpc_cast(B, ?MODULE, part2, [Config, node(), A, C]),
- ?UNTIL(is_ready_partition(Config)),
+ PartCtrlr = setup_partitions(Config, [[B, C], [node(), A]]),
%% Connect to the other partition.
pong = net_adm:ping(B),
@@ -112,7 +121,6 @@ otp_8653(Config) when is_list(Config) ->
_ = global:sync(),
[A, B, C] = lists:sort(nodes()),
- G = pg2_otp_8653,
?UNTIL(begin
GA = lists:sort(rpc:call(A, pg2, get_members, [G])),
GB = lists:sort(rpc:call(B, pg2, get_members, [G])),
@@ -125,27 +133,9 @@ otp_8653(Config) when is_list(Config) ->
end),
ok = pg2:delete(G),
stop_nodes([A,B,C]),
+ stop_partition_controller(PartCtrlr),
ok.
-part2(Config, Main, A, C) ->
- Function = mk_part_node_and_group,
- case catch begin
- make_partition(Config, [Main, A], [node(), C], Function)
- end
- of
- ok -> ok
- end.
-
-mk_part_node_and_group(File, MyPart0, Config) ->
- touch(File, "start"), % debug
- MyPart = lists:sort(MyPart0),
- ?UNTIL(is_node_in_part(File, MyPart)),
- G = pg2_otp_8653,
- Pid = spawn(forever()),
- ok = pg2:create(G),
- _ = [ok = pg2:join(G, Pid) || _ <- [1,1]],
- touch(File, "done").
-
%% OTP-8259. Member was not removed after being killed.
otp_8259(Config) when is_list(Config) ->
[A, B, C] = start_nodes([a, b, c], peer, Config),
@@ -162,8 +152,17 @@ otp_8259(Config) when is_list(Config) ->
ok = pg2:join(G, Pid),
%% make b and c connected, partitioned from node() and a
- rpc_cast(B, ?MODULE, part1, [Config, node(), A, C, Name]),
- ?UNTIL(is_ready_partition(Config)),
+ PartCtrlr = setup_partitions(Config, [[B, C], [node(), A]]),
+ ok = rfcall(
+ PartCtrlr,
+ fun () ->
+ rfcall(
+ B,
+ fun () ->
+ {_, yes} = start_proc(Name),
+ ok
+ end)
+ end),
%% Connect to the other partition.
%% The resolver on node b will be called.
@@ -182,16 +181,9 @@ otp_8259(Config) when is_list(Config) ->
ok = pg2:delete(G),
stop_nodes([A,B,C]),
+ stop_partition_controller(PartCtrlr),
ok.
-part1(Config, Main, A, C, Name) ->
- case catch begin
- make_partition(Config, [Main, A], [node(), C]),
- {_Pid, yes} = start_proc(Name)
- end of
- {_, yes} -> ok
- end.
-
start_proc(Name) ->
Pid = spawn(?MODULE, p_init, [self(), Name, node()]),
receive
@@ -585,6 +577,9 @@ collect_nodes(N, Max) ->
[Node | collect_nodes(N+1, Max)]
end.
+start_hidden_node(Name, Config) ->
+ start_node(Name, slave, "-hidden", Config).
+
start_node(Name, How, Config) ->
start_node(Name, How, "", Config).
@@ -619,60 +614,79 @@ node_name(Name, Config) ->
L = lists:flatten(Date),
lists:concat([Name,U,?testcase,U,U,L]).
-%% This one runs on one node in Part2.
-%% The partition is ready when is_ready_partition(Config) returns (true).
-make_partition(Config, Part1, Part2) ->
- make_partition(Config, Part1, Part2, mk_part_node).
-
-make_partition(Config, Part1, Part2, Function) ->
- Dir = proplists:get_value(priv_dir, Config),
- Ns = [begin
- Name = lists:concat([atom_to_list(N),"_",msec(),".part"]),
- File = filename:join([Dir, Name]),
- file:delete(File),
- rpc_cast(N, ?MODULE, Function, [File, Part, Config], File),
- {N, File}
- end || Part <- [Part1, Part2], N <- Part],
- all_nodes_files(Ns, "done", Config),
- lists:foreach(fun({_N,File}) -> file:delete(File) end, Ns),
- PartFile = make_partition_file(Config),
- touch(PartFile, "done").
-
-%% The node signals its success by touching a file.
-mk_part_node(File, MyPart0, Config) ->
- touch(File, "start"), % debug
- MyPart = lists:sort(MyPart0),
- ?UNTIL(is_node_in_part(File, MyPart)),
- touch(File, "done").
-
-%% The calls to append_to_file are for debugging.
-is_node_in_part(File, MyPart) ->
- lists:foreach(fun(N) ->
- _ = erlang:disconnect_node(N)
- end, nodes() -- MyPart),
- case {(Known = get_known(node())) =:= MyPart,
- (Nodes = lists:sort([node() | nodes()])) =:= MyPart} of
- {true, true} ->
- %% Make sure the resolvers have been terminated,
- %% otherwise they may pop up and send some message.
- %% (This check is probably unnecessary.)
- case element(5, global:info()) of
- [] ->
- true;
- Rs ->
- append_to_file(File, {now(), Known, Nodes, Rs}),
- false
- end;
- _ ->
- append_to_file(File, {now(), Known, Nodes}),
- false
- end.
-is_ready_partition(Config) ->
- File = make_partition_file(Config),
- file_contents(File, "done", Config),
- file:delete(File),
- true.
+create_partitions(PartitionsList) ->
+ AllNodes = lists:sort(lists:flatten(PartitionsList)),
+
+ %% Take down all connections on all nodes...
+ AllOk = {lists:map(fun (_) -> ok end, AllNodes), []},
+ io:format("Disconnecting all nodes from eachother...", []),
+ AllOk = rfmulticall(
+ AllNodes,
+ fun () ->
+ lists:foreach(fun (N) ->
+ erlang:disconnect_node(N)
+ end, nodes()),
+ wait_until(fun () -> [] == global_known() end),
+ ok
+ end, 5000),
+ %% Here we know that all 'lost_connection' messages that will be
+ %% sent by global name servers due to these disconnects have been
+ %% sent, but we don't know that all of them have been received and
+ %% handled. By communicating with all global name servers one more
+ %% time it is very likely that all of them have been received and
+ %% handled (however, not guaranteed). If 'lost_connection' messages
+ %% are received after we begin to set up the partitions, the
+ %% partitions may lose connection with some of its nodes.
+ lists:foreach(fun (N) -> [] = global_known(N) end, AllNodes),
+
+ %% Set up fully connected partitions...
+ io:format("Connecting partitions...", []),
+ lists:foreach(
+ fun (Partition) ->
+ Part = lists:sort(Partition),
+ PartOk = {lists:map(fun (_) -> ok end, Part), []},
+ PartOk = rfmulticall(
+ Part,
+ fun () ->
+ wait_until(
+ fun () ->
+ ConnNodes = Part -- [node()|nodes()],
+ if ConnNodes == [] ->
+ true;
+ true ->
+ lists:foreach(
+ fun (N) ->
+ net_kernel:connect_node(N)
+ end, ConnNodes),
+ false
+ end
+ end),
+ ok
+
+ end, 5000)
+ end, PartitionsList),
+ ok.
+
+setup_partitions(PartCtrlr, PartList) when is_atom(PartCtrlr) ->
+ ok = rfcall(PartCtrlr, fun () -> create_partitions(PartList) end),
+ io:format("Partitions successfully setup:~n", []),
+ lists:foreach(fun (Part) ->
+ io:format("~p~n", [Part])
+ end,
+ PartList),
+ ok;
+setup_partitions(Config, PartList) when is_list(Config) ->
+ PartCtrlr = start_partition_controller(Config),
+ setup_partitions(PartCtrlr, PartList),
+ PartCtrlr.
+
+start_partition_controller(Config) when is_list(Config) ->
+ {ok, PartCtrlr} = start_hidden_node(part_ctrlr, Config),
+ PartCtrlr.
+
+stop_partition_controller(PartCtrlr) ->
+ stop_node(PartCtrlr).
wait_for_ready_net(Config) ->
wait_for_ready_net([node()|nodes()], Config).
@@ -688,64 +702,30 @@ wait_for_ready_net(Nodes0, Config) ->
end, Nodes)
end).
-%% To make it less probable that some low-level problem causes
-%% problems, the receiving node is ping:ed.
-rpc_cast(Node, Module, Function, Args) ->
- {_,pong,Node}= {node(),net_adm:ping(Node),Node},
- rpc:cast(Node, Module, Function, Args).
-
-rpc_cast(Node, Module, Function, Args, File) ->
- case net_adm:ping(Node) of
- pong ->
- rpc:cast(Node, Module, Function, Args);
- Else ->
- append_to_file(File, {now(), {rpc_cast, Node, Module, Function,
- Args, Else}})
- %% Maybe we should crash, but it probably doesn't matter.
- end.
-
-touch(File, List) ->
- ok = file:write_file(File, list_to_binary(List)).
+global_known(Node) ->
+ gen_server:call({global_name_server, Node}, get_known, infinity).
-append_to_file(File, Term) ->
- {ok, Fd} = file:open(File, [raw,binary,append]),
- ok = file:write(Fd, io_lib:format("~p.~n", [Term])),
- ok = file:close(Fd).
+global_known() ->
+ global_known(node()).
-all_nodes_files(Files, ContentsList, Config) ->
- lists:all(fun({_N,File}) ->
- file_contents(File, ContentsList, Config)
- end, Files).
+wait_until(F) ->
+ case catch F() of
+ true ->
+ ok;
+ _ ->
+ receive after 10 -> ok end,
+ wait_until(F)
+ end.
-file_contents(File, ContentsList, Config) ->
- file_contents(File, ContentsList, Config, no_log_file).
+rfcall(Node, Fun) ->
+ rfcall(Node, Fun, infinity).
-file_contents(File, ContentsList, Config, LogFile) ->
- Contents = list_to_binary(ContentsList),
- Sz = size(Contents),
- ?UNTIL(begin
- case file:read_file(File) of
- {ok, FileContents}=Reply ->
- case catch split_binary(FileContents, Sz) of
- {Contents,_} ->
- true;
- _ ->
- catch append_to_file(LogFile,
- {File,Contents,Reply}),
- false
- end;
- Reply ->
- catch append_to_file(LogFile, {File, Contents, Reply}),
- false
- end
- end).
+rfcall(Node, Fun, Timeout) ->
+ rpc:call(Node, erlang, apply, [Fun, []], Timeout).
-make_partition_file(Config) ->
- Dir = proplists:get_value(priv_dir, Config),
- filename:join([Dir, atom_to_list(make_partition_done)]).
+rfmulticall(Nodes, Fun) ->
+ rfmulticall(Nodes, Fun, infinity).
-msec() ->
- msec(now()).
+rfmulticall(Nodes, Fun, Timeout) ->
+ rpc:multicall(Nodes, erlang, apply, [Fun, []], Timeout).
-msec(T) ->
- element(1,T)*1000000000 + element(2,T)*1000 + element(3,T) div 1000.
diff --git a/lib/kernel/test/rpc_SUITE.erl b/lib/kernel/test/rpc_SUITE.erl
index a89a7600a2..aea53003cb 100644
--- a/lib/kernel/test/rpc_SUITE.erl
+++ b/lib/kernel/test/rpc_SUITE.erl
@@ -70,13 +70,13 @@ call(Config) when is_list(Config) ->
PA = filename:dirname(code:which(?MODULE)),
%% Note. First part of nodename sets response delay in seconds
{ok, N1} = test_server:start_node('3_rpc_SUITE_call', slave,
- [{args, "-pa " ++ PA}]),
+ [{args, "-connect_all false -pa " ++ PA}]),
{ok, N2} = test_server:start_node('1_rcp_SUITE_call', slave,
- [{args, "-pa " ++ PA}]),
+ [{args, "-connect_all false -pa " ++ PA}]),
{ok, N3} = test_server:start_node('4_rcp_SUITE_call', slave,
- [{args, "-pa " ++ PA}]),
+ [{args, "-connect_all false -pa " ++ PA}]),
{ok, N4} = test_server:start_node('8_rcp_SUITE_call', slave,
- [{args, "-pa " ++ PA}]),
+ [{args, "-connect_all false -pa " ++ PA}]),
ok = io:format("~p~n", [[N1, N2, N3]]),
{hej,_,N1} = rpc:call(N1, ?MODULE, f, []),
{hej,_,N2} = rpc:call(N2, ?MODULE, f, [], 2000),
@@ -95,13 +95,13 @@ block_call(Config) when is_list(Config) ->
PA = filename:dirname(code:which(?MODULE)),
%% Note. First part of nodename sets response delay in seconds
{ok, N1} = test_server:start_node('3_rpc_SUITE_block_call', slave,
- [{args, "-pa " ++ PA}]),
+ [{args, "-connect_all false -pa " ++ PA}]),
{ok, N2} = test_server:start_node('1_rcp_SUITE_block_call', slave,
- [{args, "-pa " ++ PA}]),
+ [{args, "-connect_all false -pa " ++ PA}]),
{ok, N3} = test_server:start_node('4_rcp_SUITE_block_call', slave,
- [{args, "-pa " ++ PA}]),
+ [{args, "-connect_all false -pa " ++ PA}]),
{ok, N4} = test_server:start_node('8_rcp_SUITE_block_call', slave,
- [{args, "-pa " ++ PA}]),
+ [{args, "-connect_all false -pa " ++ PA}]),
ok = io:format("~p~n", [[N1, N2, N3]]),
{hej,_,N1} = rpc:block_call(N1, ?MODULE, f, []),
{hej,_,N2} = rpc:block_call(N2, ?MODULE, f, [], 2000),
@@ -121,9 +121,9 @@ multicall(Config) when is_list(Config) ->
PA = filename:dirname(code:which(?MODULE)),
%% Note. First part of nodename sets response delay in seconds
{ok, N1} = test_server:start_node('3_rpc_SUITE_multicall', slave,
- [{args, "-pa " ++ PA}]),
+ [{args, "-connect_all false -pa " ++ PA}]),
{ok, N2} = test_server:start_node('1_rcp_SUITE_multicall', slave,
- [{args, "-pa " ++ PA}]),
+ [{args, "-connect_all false -pa " ++ PA}]),
ok = io:format("~p~n", [[N1, N2]]),
{[{hej,_,N1},{hej,_,N2}],[]} =
rpc:multicall([N1, N2], ?MODULE, f, []),
@@ -137,13 +137,13 @@ multicall_timeout(Config) when is_list(Config) ->
PA = filename:dirname(code:which(?MODULE)),
%% Note. First part of nodename sets response delay in seconds
{ok, N1} = test_server:start_node('11_rpc_SUITE_multicall', slave,
- [{args, "-pa " ++ PA}]),
+ [{args, "-connect_all false -pa " ++ PA}]),
{ok, N2} = test_server:start_node('8_rpc_SUITE_multicall', slave,
- [{args, "-pa " ++ PA}]),
+ [{args, "-connect_all false -pa " ++ PA}]),
{ok, N3} = test_server:start_node('5_rpc_SUITE_multicall', slave,
- [{args, "-pa " ++ PA}]),
+ [{args, "-connect_all false -pa " ++ PA}]),
{ok, N4} = test_server:start_node('2_rcp_SUITE_multicall', slave,
- [{args, "-pa " ++ PA}]),
+ [{args, "-connect_all false -pa " ++ PA}]),
ok = io:format("~p~n", [[N1, N2]]),
{[{hej,_,N3},{hej,_,N4}],[N1, N2]} =
rpc:multicall([N3, N1, N2, N4], ?MODULE, f, [], 6000),
@@ -159,9 +159,9 @@ multicall_timeout(Config) when is_list(Config) ->
multicall_dies(Config) when is_list(Config) ->
PA = filename:dirname(code:which(?MODULE)),
{ok, N1} = test_server:start_node('rpc_SUITE_multicall_dies_1', slave,
- [{args, "-pa " ++ PA}]),
+ [{args, "-connect_all false -pa " ++ PA}]),
{ok, N2} = test_server:start_node('rcp_SUITE_multicall_dies_2', slave,
- [{args, "-pa " ++ PA}]),
+ [{args, "-connect_all false -pa " ++ PA}]),
Nodes = [N1, N2],
%%
{[{badrpc, {'EXIT', normal}}, {badrpc, {'EXIT', normal}}], []} =
@@ -213,10 +213,10 @@ multicall_node_dies(Config) when is_list(Config) ->
do_multicall_2_nodes_dies(Mod, Func, Args) ->
ok = io:format("~p:~p~p~n", [Mod, Func, Args]),
PA = filename:dirname(code:which(?MODULE)),
- {ok, N1} = test_server:start_node('rpc_SUITE_multicall_node_dies_1', slave,
- [{args, "-pa " ++ PA}]),
- {ok, N2} = test_server:start_node('rcp_SUITE_multicall_node_dies_2', slave,
- [{args, "-pa " ++ PA}]),
+ {ok, N1} = test_server:start_node('rpc_SUITE_multicall_node_dies_1', peer,
+ [{args, "-connect_all false -pa " ++ PA}]),
+ {ok, N2} = test_server:start_node('rcp_SUITE_multicall_node_dies_2', peer,
+ [{args, "-connect_all false -pa " ++ PA}]),
Nodes = [N1, N2],
{[], Nodes} = rpc:multicall(Nodes, Mod, Func, Args),
Msgs = flush([]),
@@ -229,7 +229,7 @@ do_multicall_2_nodes_dies(Mod, Func, Args) ->
called_dies(Config) when is_list(Config) ->
PA = filename:dirname(code:which(?MODULE)),
{ok, N} = test_server:start_node(rpc_SUITE_called_dies, slave,
- [{args, "-pa " ++ PA}]),
+ [{args, "-connect_all false -pa " ++ PA}]),
%%
rep(fun (Tag, Call, Args) ->
{Tag,{badrpc,{'EXIT',normal}}} =
@@ -395,7 +395,7 @@ node_rep(Fun, Name, PA, M, F, A) ->
node_rep_call(Tag, Call, Args, Fun, Name0, PA) ->
Name = list_to_atom(Name0 ++ "_" ++ atom_to_list(Tag)),
{ok, N} = test_server:start_node(Name, slave,
- [{args, "-pa " ++ PA}]),
+ [{args, "-connect_all false -pa " ++ PA}]),
Fun(Call, [N|Args]),
catch test_server:stop_node(N),
ok.
@@ -405,7 +405,7 @@ called_throws(Config) when is_list(Config) ->
PA = filename:dirname(code:which(?MODULE)),
%%
{ok, N} = test_server:start_node(rpc_SUITE_called_throws, slave,
- [{args, "-pa " ++ PA}]),
+ [{args, "-connect_all false -pa " ++ PA}]),
%%
rep(fun (Tag, Call, Args) ->
{Tag,up} =
@@ -424,7 +424,7 @@ called_throws(Config) when is_list(Config) ->
call_benchmark(Config) when is_list(Config) ->
PA = filename:dirname(code:which(?MODULE)),
{ok, Node} = test_server:start_node(rpc_SUITE_call_benchmark, slave,
- [{args, "-pa " ++ PA}]),
+ [{args, "-connect_all false -pa " ++ PA}]),
Iter = case erlang:system_info(modified_timing_level) of
undefined -> 10000;
_ -> 500 %Modified timing - spawn is slower
@@ -452,7 +452,7 @@ do_call_benchmark(Node, I, M) ->
async_call(Config) when is_list(Config) ->
%% Note: First part of nodename sets response delay in seconds.
PA = filename:dirname(code:which(?MODULE)),
- NodeArgs = [{args,"-pa "++ PA}],
+ NodeArgs = [{args,"-connect_all false -pa "++ PA}],
{ok,Node1} = test_server:start_node('1_rpc_SUITE_call', slave, NodeArgs),
{ok,Node2} = test_server:start_node('10_rpc_SUITE_call', slave, NodeArgs),
{ok,Node3} = test_server:start_node('20_rpc_SUITE_call', slave, NodeArgs),