aboutsummaryrefslogtreecommitdiffstats
path: root/lib/kernel/test/loose_node.erl
diff options
context:
space:
mode:
Diffstat (limited to 'lib/kernel/test/loose_node.erl')
-rw-r--r--lib/kernel/test/loose_node.erl193
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.
+