diff options
Diffstat (limited to 'lib/kernel/test/loose_node.erl')
-rw-r--r-- | lib/kernel/test/loose_node.erl | 193 |
1 files changed, 193 insertions, 0 deletions
diff --git a/lib/kernel/test/loose_node.erl b/lib/kernel/test/loose_node.erl new file mode 100644 index 0000000000..ac1ddb8d9a --- /dev/null +++ b/lib/kernel/test/loose_node.erl @@ -0,0 +1,193 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2004-2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% +%% + +%%%------------------------------------------------------------------- +%%% File : loose_node.erl +%%% Author : Rickard Green <[email protected]> +%%% Description : Creation of nodes which are not supervised by +%%% the test_server. Currently needed by init_SUITE +%%% and heart_SUITE (until the test_server can +%%% handle node restart). +%%% +%%% Created : 22 Sep 2004 by Rickard Green <[email protected]> +%%%------------------------------------------------------------------- +-module(loose_node). +-author('[email protected]'). + +%% +%% Exports +%% +-export([start/3, start/2, stop/1]). + +%% +%% Internal exports +%% +-export([loose_node_started/1]). + +%% +%% Exported functions for internal use. +%% + +%% +%% Defines +%% +-define(L2A, list_to_atom). +-define(A2L, atom_to_list). +-define(I2L, integer_to_list). + +%% +%% Exported functions. +%% + +stop(Node) when atom(Node) -> + rpc:cast(Node, erlang, halt, []), + io:format("Stopped loose node ~p~n", [Node]), + ok. + +start(Name, Args) -> + start(Name, Args, -1). + +start(Name, Args, TimeOut) when atom(Name) -> + start(atom_to_list(Name), Args, TimeOut); +start(Name, Args, TimeOut) when list(Name), list(Args), integer(TimeOut) -> + Parent = self(), + Ref = make_ref(), + Starter + = fun () -> + Erl = case init:get_argument(progname) of + {ok,[[Prog]]} -> + Prog; + _ -> + "erl" + end, + RegName = until_success(fun () -> + {A, B, C} = now(), + Reg = + ?L2A(?A2L(?MODULE) + ++ "-" ++ ?I2L(A) + ++ "-" ++ ?I2L(B) + ++ "-" ++ ?I2L(C)), + true = register(Reg, self()), + Reg + end), + NameCmd = case net_kernel:longnames() of + true -> " -name " ++ Name; + false -> " -sname " ++ Name + end, + Cookie = " -setcookie " ++ atom_to_list(auth:get_cookie()), + Pa = " -pa " ++ filename:dirname(code:which(?MODULE)), + ThisNode = node(), + NodeStarted + = " -run " + ++ atom_to_list(?MODULE) + ++ " loose_node_started " + ++ atom_to_list(RegName) + ++ " " + ++ atom_to_list(ThisNode) + ++ " " + ++ integer_to_list(TimeOut), + CrashDump = + " -env ERL_CRASH_DUMP" + ++ " erl_crash.dump.loose_node." + ++ Name, + Cmd = + Erl + ++ " -detached" + ++ NameCmd + ++ Cookie + ++ Pa + ++ NodeStarted + ++ CrashDump + ++ " " + ++ Args, + io:format("Trying to start loose node...~n" + " --> ~p~n", [Cmd]), + Res = case open_port({spawn, Cmd}, []) of + P when port(P) -> + receive + {loose_node_started, + Node, + {RegName, ThisNode}} -> + io:format("Loose node ~p started.~n", + [Node]), + {ok, Node} + after 10000 -> + io:format("Start of loose node ~p " + "timed out.", [Name]), + {error, timeout} + end; + _ -> + io:format("Start of loose node ~p failed.", + [Name]), + {error, open_port_failed} + end, + Parent ! {Ref, Res} + end, + spawn_opt(Starter, [link, {priority, max}]), + receive + {Ref, Result} -> + Result + end. + + +%% +%% Exported functions for internal use. +%% + +loose_node_started([Name, Node, TimeOutSecs]) when list(Name), + list(Node), + list(TimeOutSecs) -> + spawn_opt(fun () -> + process_flag(trap_exit, true), + Proc = {list_to_atom(Name), list_to_atom(Node)}, + Timeout = case catch list_to_integer(TimeOutSecs) of + I when integer(I), I >= 0 -> I*1000; + _ -> infinity + end, + wait_until(fun () -> is_alive() end), + Proc ! {loose_node_started, node(), Proc}, + receive + after Timeout -> + timeout + end, + erlang:halt("Loose node timeout") + end, + [{priority, max}]), + ok. + +%% +%% Internal functions. +%% + +until_success(Fun) -> + case catch Fun() of + {'EXIT', _} -> until_success(Fun); + Res -> Res + end. + +wait_until(Fun) -> + case Fun() of + true -> true; + _ -> + receive + after 100 -> + wait_until(Fun) + end + end. + |