diff options
Diffstat (limited to 'lib/common_test/src/ct_gen_conn.erl')
| -rw-r--r-- | lib/common_test/src/ct_gen_conn.erl | 174 |
1 files changed, 82 insertions, 92 deletions
diff --git a/lib/common_test/src/ct_gen_conn.erl b/lib/common_test/src/ct_gen_conn.erl index 56082086f6..1ab9946d96 100644 --- a/lib/common_test/src/ct_gen_conn.erl +++ b/lib/common_test/src/ct_gen_conn.erl @@ -1,40 +1,33 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2003-2014. All Rights Reserved. +%% Copyright Ericsson AB 2003-2018. 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/. +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at %% -%% 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. +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. %% %% %CopyrightEnd% %% -%%% @doc Generic connection owner process. +%%% Generic connection owner process. %%% -%%% @type handle() = pid(). A handle for using a connection implemented +%%% -type handle() = pid(). A handle for using a connection implemented %%% with ct_gen_conn.erl. -module(ct_gen_conn). --compile(export_all). - --export([start/4, stop/1, get_conn_pid/1]). +-export([start/4, stop/1, get_conn_pid/1, check_opts/1]). -export([call/2, call/3, return/2, do_within_time/2]). - -%%---------------------------------------------------------------------- -%% Exported types -%%---------------------------------------------------------------------- --export_type([server_id/0, - target_name/0, - key_or_name/0]). +-export([log/3, start_log/1, cont_log/2, cont_log_no_timestamp/2, end_log/0]). -ifdef(debug). -define(dbg,true). @@ -54,20 +47,8 @@ cb_state, ct_util_server}). -%%------------------------------------------------------------------ -%% Type declarations -%%------------------------------------------------------------------ --type server_id() :: atom(). -%% A `ServerId' which exists in a configuration file. --type target_name() :: atom(). -%% A name which is associated to a `server_id()' via a -%% `require' statement or a call to {@link ct:require/2} in the -%% test suite. --type key_or_name() :: server_id() | target_name(). - - %%%----------------------------------------------------------------- -%%% @spec start(Address,InitData,CallbackMod,Opts) -> +%%% -spec start(Address,InitData,CallbackMod,Opts) -> %%% {ok,Handle} | {error,Reason} %%% Name = term() %%% CallbackMod = atom() @@ -77,57 +58,52 @@ %%% Opt = {name,Name} | {use_existing_connection,boolean()} | %%% {reconnect,boolean()} | {forward_messages,boolean()} %%% -%%% @doc Open a connection and start the generic connection owner process. +%%% Open a connection and start the generic connection owner process. %%% -%%% <p>The <code>CallbackMod</code> is a specific callback module for +%%% The CallbackMod is a specific callback module for %%% each type of connection (e.g. telnet, ftp,...). It must export the -%%% function <code>init/3</code> which takes the arguments -%%% <code>Name</code>, <code>Addresse</code>) and -%%% <code>InitData</code> and returna -%%% <code>{ok,ConnectionPid,State}</code> or -%%% <code>{error,Reason}</code>.</p> +%%% function init/3 which takes the arguments +%%% Name, Addresse) and +%%% InitData and returna +%%% {ok,ConnectionPid,State} or +%%% {error,Reason}. %%% -%%% If no name is given, the <code>Name</code> argument in init/3 will -%%% have the value <code>undefined</code>. +%%% If no name is given, the Name argument in init/3 will +%%% have the value undefined. %%% %%% The callback modules must also export -%%% ``` +%%% %%% handle_msg(Msg,From,State) -> {reply,Reply,State} | %%% {noreply,State} | %%% {stop,Reply,State} %%% terminate(ConnectionPid,State) -> term() %%% close(Handle) -> term() -%%% ''' %%% -%%% The <code>close/1</code> callback function is actually a callback +%%% The close/1 callback function is actually a callback %%% for ct_util, for closing registered connections when -%%% ct_util_server is terminated. <code>Handle</code> is the Pid of +%%% ct_util_server is terminated. Handle is the Pid of %%% the ct_gen_conn process. %%% -%%% If option <code>reconnect</code> is <code>true</code>, then the +%%% If option reconnect is true, then the %%% callback must also export -%%% ``` +%%% %%% reconnect(Address,State) -> {ok,ConnectionPid,State} -%%% ''' %%% -%%% If option <code>forward_messages</code> is <ocde>true</code>, then +%%% If option forward_messages is <ocde>true, then %%% the callback must also export -%%% ``` +%%% %%% handle_msg(Msg,State) -> {noreply,State} | {stop,State} -%%% ''' %%% %%% An old interface still exists. This is used by ct_telnet, ct_ftp %%% and ct_ssh. The start function then has an explicit -%%% <code>Name</code> argument, and no <code>Opts</code> argument. The +%%% Name argument, and no Opts argument. The %%% callback must export: %%% -%%% ``` %%% init(Name,Address,InitData) -> {ok,ConnectionPid,State} %%% handle_msg(Msg,State) -> {Reply,State} %%% reconnect(Address,State) -> {ok,ConnectionPid,State} %%% terminate(ConnectionPid,State) -> term() %%% close(Handle) -> term() -%%% ''' %%% start(Address,InitData,CallbackMod,Opts) when is_list(Opts) -> do_start(Address,InitData,CallbackMod,Opts); @@ -135,71 +111,81 @@ start(Name,Address,InitData,CallbackMod) -> do_start(Address,InitData,CallbackMod,[{name,Name},{old,true}]). %%%----------------------------------------------------------------- -%%% @spec stop(Handle) -> ok +%%% -spec stop(Handle) -> ok %%% Handle = handle() %%% -%%% @doc Close the connection and stop the process managing it. +%%% Close the connection and stop the process managing it. stop(Handle) -> call(Handle,stop,5000). %%%----------------------------------------------------------------- -%%% @spec get_conn_pid(Handle) -> ok +%%% -spec get_conn_pid(Handle) -> ok %%% Handle = handle() %%% -%%% @doc Return the connection pid associated with Handle +%%% Return the connection pid associated with Handle get_conn_pid(Handle) -> call(Handle,get_conn_pid). %%%----------------------------------------------------------------- -%%% @spec log(Heading,Format,Args) -> ok +%%% -spec log(Heading,Format,Args) -> ok %%% -%%% @doc Log activities on the current connection (tool-internal use only). -%%% @see ct_logs:log/3 +%%% Log activities on the current connection (tool-internal use only). +%%% See ct_logs:log/3 log(Heading,Format,Args) -> log(log,[Heading,Format,Args]). %%%----------------------------------------------------------------- -%%% @spec start_log(Heading) -> ok +%%% -spec start_log(Heading) -> ok %%% -%%% @doc Log activities on the current connection (tool-internal use only). -%%% @see ct_logs:start_log/1 +%%% Log activities on the current connection (tool-internal use only). +%%% See ct_logs:start_log/1 start_log(Heading) -> log(start_log,[Heading]). %%%----------------------------------------------------------------- -%%% @spec cont_log(Format,Args) -> ok +%%% -spec cont_log(Format,Args) -> ok %%% -%%% @doc Log activities on the current connection (tool-internal use only). -%%% @see ct_logs:cont_log/2 +%%% Log activities on the current connection (tool-internal use only). +%%% See ct_logs:cont_log/2 cont_log(Format,Args) -> log(cont_log,[Format,Args]). %%%----------------------------------------------------------------- -%%% @spec end_log() -> ok +%%% -spec cont_log_no_timestamp(Format,Args) -> ok +%%% +%%% Log activities on the current connection (tool-internal use only). +%%% See ct_logs:cont_log/2 +cont_log_no_timestamp(Format,Args) -> + log(cont_log_no_timestamp,[Format,Args]). + +%%%----------------------------------------------------------------- +%%% -spec end_log() -> ok %%% -%%% @doc Log activities on the current connection (tool-internal use only). -%%% @see ct_logs:end_log/0 +%%% Log activities on the current connection (tool-internal use only). +%%% See ct_logs:end_log/0 end_log() -> log(end_log,[]). %%%----------------------------------------------------------------- -%%% @spec do_within_time(Fun,Timeout) -> FunResult | {error,Reason} +%%% -spec do_within_time(Fun,Timeout) -> FunResult | {error,Reason} %%% Fun = function() %%% Timeout = integer() %%% -%%% @doc Execute a function within a limited time (tool-internal use only). +%%% Execute a function within a limited time (tool-internal use only). %%% -%%% <p>Execute the given <code>Fun</code>, but interrupt if it takes -%%% more than <code>Timeout</code> milliseconds.</p> +%%% Execute the given Fun, but interrupt if it takes +%%% more than Timeout milliseconds. %%% -%%% <p>The execution is also interrupted if the connection is -%%% closed.</p> +%%% The execution is also interrupted if the connection is +%%% closed. do_within_time(Fun,Timeout) -> Self = self(), Silent = get(silent), - TmpPid = spawn_link(fun() -> put(silent,Silent), - R = Fun(), - Self ! {self(),R} + TmpPid = spawn_link(fun() -> + ct_util:mark_process(), + put(silent,Silent), + R = Fun(), + Self ! {self(),R} end), ConnPid = get(conn_pid), receive @@ -258,7 +244,7 @@ do_start(Opts) -> Error; {'DOWN',MRef,process,_,Reason} -> log("ct_gen_conn:start", - "Connection process died: ~p\n", + "Connection process died: ~tp\n", [Reason]), {error,{connection_process_died,Reason}} end. @@ -312,6 +298,7 @@ return({To,Ref},Result) -> init_gen(Parent,Opts) -> process_flag(trap_exit,true), + ct_util:mark_process(), put(silent,false), try (Opts#gen_opts.callback):init(Opts#gen_opts.name, Opts#gen_opts.address, @@ -338,7 +325,7 @@ loop(Opts) -> case Opts#gen_opts.reconnect of true -> log("Connection down!\nOpening new!", - "Reason: ~p\nAddress: ~p\n", + "Reason: ~tp\nAddress: ~tp\n", [Reason,Opts#gen_opts.address]), case reconnect(Opts) of {ok, NewPid, NewState} -> @@ -349,12 +336,12 @@ loop(Opts) -> Error -> ct_util:unregister_connection(self()), log("Reconnect failed. Giving up!", - "Reason: ~p\n", + "Reason: ~tp\n", [Error]) end; false -> ct_util:unregister_connection(self()), - log("Connection closed!","Reason: ~p\n",[Reason]) + log("Connection closed!","Reason: ~tp\n",[Reason]) end; {'EXIT',Pid,Reason} -> case Opts#gen_opts.ct_util_server of @@ -365,8 +352,9 @@ loop(Opts) -> end; {stop, From} -> ct_util:unregister_connection(self()), - (Opts#gen_opts.callback):terminate(Opts#gen_opts.conn_pid, - Opts#gen_opts.cb_state), + ConnPid = Opts#gen_opts.conn_pid, + unlink(ConnPid), + (Opts#gen_opts.callback):terminate(ConnPid,Opts#gen_opts.cb_state), return(From,ok), ok; {{retry,{Error,_Name,CPid,_Msg}}, From} when @@ -403,8 +391,9 @@ loop(Opts) -> loop(Opts#gen_opts{cb_state=NewState}); {stop,Reply,NewState} -> ct_util:unregister_connection(self()), - (Opts#gen_opts.callback):terminate(Opts#gen_opts.conn_pid, - NewState), + ConnPid = Opts#gen_opts.conn_pid, + unlink(ConnPid), + (Opts#gen_opts.callback):terminate(ConnPid,NewState), return(From,Reply) end; Msg when Opts#gen_opts.forward==true -> @@ -414,8 +403,9 @@ loop(Opts) -> loop(Opts#gen_opts{cb_state=NewState}); {stop,NewState} -> ct_util:unregister_connection(self()), - (Opts#gen_opts.callback):terminate(Opts#gen_opts.conn_pid, - NewState) + ConnPid = Opts#gen_opts.conn_pid, + unlink(ConnPid), + (Opts#gen_opts.callback):terminate(ConnPid,NewState) end end. |
