diff options
Diffstat (limited to 'lib/kernel/test')
-rw-r--r-- | lib/kernel/test/erl_distribution_SUITE.erl | 19 | ||||
-rw-r--r-- | lib/kernel/test/global_SUITE.erl | 997 | ||||
-rw-r--r-- | lib/kernel/test/pg2_SUITE.erl | 262 | ||||
-rw-r--r-- | lib/kernel/test/rpc_SUITE.erl | 50 |
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), |