Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 7 May 2015 20:34:30 +0000 (UTC)
From:      Jimmy Olgeni <olgeni@FreeBSD.org>
To:        ports-committers@freebsd.org, svn-ports-all@freebsd.org, svn-ports-head@freebsd.org
Subject:   svn commit: r385668 - in head/lang: erlang erlang-java erlang-runtime17 erlang-runtime17/files erlang-wx erlang/files
Message-ID:  <201505072034.t47KYU9L053577@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: olgeni
Date: Thu May  7 20:34:30 2015
New Revision: 385668
URL: https://svnweb.freebsd.org/changeset/ports/385668

Log:
  Upgrade all Erlang 17 ports to 17.5.3.

Added:
  head/lang/erlang-runtime17/files/patch-otp-17.5.3   (contents, props changed)
  head/lang/erlang/files/patch-otp-17.5.3   (contents, props changed)
Modified:
  head/lang/erlang-java/Makefile
  head/lang/erlang-runtime17/Makefile
  head/lang/erlang-wx/Makefile
  head/lang/erlang/Makefile

Modified: head/lang/erlang-java/Makefile
==============================================================================
--- head/lang/erlang-java/Makefile	Thu May  7 20:31:03 2015	(r385667)
+++ head/lang/erlang-java/Makefile	Thu May  7 20:34:30 2015	(r385668)
@@ -1,7 +1,7 @@
 # $FreeBSD$
 
 PORTNAME=	erlang
-PORTVERSION=	17.5.2
+PORTVERSION=	17.5.3
 CATEGORIES=	lang parallel java
 MASTER_SITES=	http://www.erlang.org/download/:erlangorg		\
 		http://erlang.stacken.kth.se/download/:erlangorg	\
@@ -25,8 +25,7 @@ OPTIONS_DEFINE=	DOCS
 
 ERL_RELEASE=	17.5
 
-USES=		gmake
-USE_AUTOTOOLS=	autoconf:env
+USES=		autoreconf gmake
 GNU_CONFIGURE=	yes
 LDFLAGS+=	-L${LOCALBASE}/lib
 

Modified: head/lang/erlang-runtime17/Makefile
==============================================================================
--- head/lang/erlang-runtime17/Makefile	Thu May  7 20:31:03 2015	(r385667)
+++ head/lang/erlang-runtime17/Makefile	Thu May  7 20:34:30 2015	(r385668)
@@ -2,8 +2,7 @@
 # $FreeBSD$
 
 PORTNAME=	erlang
-PORTVERSION=	17.5.2
-PORTREVISION=	2
+PORTVERSION=	17.5.3
 CATEGORIES=	lang parallel java
 MASTER_SITES=	http://www.erlang.org/download/:erlangorg		\
 		http://erlang.stacken.kth.se/download/:erlangorg	\
@@ -186,6 +185,10 @@ post-install:
 	${TAR} --unlink -xzpf ${DISTDIR}/${DIST_SUBDIR}/${ERLANG_DOCS} \
 		-C ${STAGEDIR}${PREFIX}/lib/${ERLANG_LIB}
 
+	${MV} ${STAGEDIR}${PREFIX}/lib/${ERLANG_LIB}/erts-6.4/* \
+		${STAGEDIR}${PREFIX}/lib/${ERLANG_LIB}/erts-6.4.1
+	${RMDIR} ${STAGEDIR}${PREFIX}/lib/${ERLANG_LIB}/erts-6.4
+
 	${MV} ${STAGEDIR}${PREFIX}/lib/${ERLANG_LIB}/lib/inets-5.10.6/* \
 		${STAGEDIR}${PREFIX}/lib/${ERLANG_LIB}/lib/inets-5.10.7
 	${RMDIR} ${STAGEDIR}${PREFIX}/lib/${ERLANG_LIB}/lib/inets-5.10.6
@@ -194,6 +197,22 @@ post-install:
 		${STAGEDIR}${PREFIX}/lib/${ERLANG_LIB}/lib/ssh-3.2.2
 	${RMDIR} ${STAGEDIR}${PREFIX}/lib/${ERLANG_LIB}/lib/ssh-3.2
 
+	${MV} ${STAGEDIR}${PREFIX}/lib/${ERLANG_LIB}/lib/common_test-1.10/* \
+		${STAGEDIR}${PREFIX}/lib/${ERLANG_LIB}/lib/common_test-1.10.1
+	${RMDIR} ${STAGEDIR}${PREFIX}/lib/${ERLANG_LIB}/lib/common_test-1.10
+
+	${MV} ${STAGEDIR}${PREFIX}/lib/${ERLANG_LIB}/lib/diameter-1.9/* \
+		${STAGEDIR}${PREFIX}/lib/${ERLANG_LIB}/lib/diameter-1.9.1
+	${RMDIR} ${STAGEDIR}${PREFIX}/lib/${ERLANG_LIB}/lib/diameter-1.9
+
+	${MV} ${STAGEDIR}${PREFIX}/lib/${ERLANG_LIB}/lib/snmp-5.1.1/* \
+		${STAGEDIR}${PREFIX}/lib/${ERLANG_LIB}/lib/snmp-5.1.2
+	${RMDIR} ${STAGEDIR}${PREFIX}/lib/${ERLANG_LIB}/lib/snmp-5.1.1
+
+	${MV} ${STAGEDIR}${PREFIX}/lib/${ERLANG_LIB}/lib/test_server-3.8/* \
+		${STAGEDIR}${PREFIX}/lib/${ERLANG_LIB}/lib/test_server-3.8.1 
+	${RMDIR} ${STAGEDIR}${PREFIX}/lib/${ERLANG_LIB}/lib/test_server-3.8
+
 	${INSTALL_DATA} ${WRKSRC}/lib/dialyzer/doc/*.txt \
 		${STAGEDIR}${PREFIX}/lib/${ERLANG_LIB}/lib/dialyzer-*/doc/
 .endif

Added: head/lang/erlang-runtime17/files/patch-otp-17.5.3
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/lang/erlang-runtime17/files/patch-otp-17.5.3	Thu May  7 20:34:30 2015	(r385668)
@@ -0,0 +1,3738 @@
+diff --git OTP_VERSION OTP_VERSION
+index 808ab16..f32d20d 100644
+--- OTP_VERSION
++++ OTP_VERSION
+@@ -1 +1 @@
+-17.5.2
++17.5.3
+diff --git erts/doc/src/notes.xml erts/doc/src/notes.xml
+index a2b4ae4..35e6e55 100644
+--- erts/doc/src/notes.xml
++++ erts/doc/src/notes.xml
+@@ -30,6 +30,22 @@
+   </header>
+   <p>This document describes the changes made to the ERTS application.</p>
+ 
++<section><title>Erts 6.4.1</title>
++
++    <section><title>Fixed Bugs and Malfunctions</title>
++      <list>
++        <item>
++          <p>
++	    The VTS mode in Common Test has been modified to use a
++	    private version of the Webtool application (ct_webtool).</p>
++          <p>
++	    Own Id: OTP-12704 Aux Id: OTP-10922 </p>
++        </item>
++      </list>
++    </section>
++
++</section>
++
+ <section><title>Erts 6.4</title>
+ 
+     <section><title>Fixed Bugs and Malfunctions</title>
+diff --git erts/etc/common/ct_run.c erts/etc/common/ct_run.c
+index bb59b93..9e67b94 100644
+--- erts/etc/common/ct_run.c
++++ erts/etc/common/ct_run.c
+@@ -239,7 +239,7 @@ int main(int argc, char** argv)
+      */
+ 
+     if (ct_mode == VTS_MODE) {
+-	PUSH4("-s", "webtool", "script_start", "vts");
++	PUSH4("-s", "ct_webtool", "script_start", "vts");
+ 	if (browser[0] != '\0') PUSH(browser);
+ 	PUSH3("-s", "ct_run", "script_start");
+     }
+diff --git erts/vsn.mk erts/vsn.mk
+index abc9c0b..9e5aa99 100644
+--- erts/vsn.mk
++++ erts/vsn.mk
+@@ -17,7 +17,7 @@
+ # %CopyrightEnd%
+ # 
+ 
+-VSN = 6.4
++VSN = 6.4.1
+ 
+ # Port number 4365 in 4.2
+ # Port number 4366 in 4.3
+diff --git lib/common_test/doc/src/notes.xml lib/common_test/doc/src/notes.xml
+index 822ebf1..472e3b7 100644
+--- lib/common_test/doc/src/notes.xml
++++ lib/common_test/doc/src/notes.xml
+@@ -32,6 +32,66 @@
+     <file>notes.xml</file>
+     </header>
+ 
++<section><title>Common_Test 1.10.1</title>
++
++    <section><title>Fixed Bugs and Malfunctions</title>
++      <list>
++        <item>
++          <p>
++	    A fault in the Common Test logger process, that caused
++	    the application to crash when running on a long name
++	    node, has been corrected.</p>
++          <p>
++	    Own Id: OTP-12643</p>
++        </item>
++        <item>
++          <p>
++	    A 'wait_for_prompt' option in ct_telnet:expect/3 has been
++	    introduced which forces the function to not return until
++	    a prompt string has been received, even if other expect
++	    patterns have already been found.</p>
++          <p>
++	    Own Id: OTP-12688 Aux Id: seq12818 </p>
++        </item>
++        <item>
++          <p>
++	    If the last expression in a test case causes a timetrap
++	    timeout, the stack trace is ignored and not printed to
++	    the test case log file. This happens because the
++	    {Suite,TestCase,Line} info is not available in the stack
++	    trace in this scenario, due to tail call elimination.
++	    Common Test has been modified to handle this situation by
++	    inserting a {Suite,TestCase,last_expr} tuple in the
++	    correct place and printing the stack trace as expected.</p>
++          <p>
++	    Own Id: OTP-12697 Aux Id: seq12848 </p>
++        </item>
++        <item>
++          <p>
++	    Fixed a buffer problem in ct_netconfc which could cause
++	    that some messages where buffered forever.</p>
++          <p>
++	    Own Id: OTP-12698 Aux Id: seq12844 </p>
++        </item>
++        <item>
++          <p>
++	    The VTS mode in Common Test has been modified to use a
++	    private version of the Webtool application (ct_webtool).</p>
++          <p>
++	    Own Id: OTP-12704 Aux Id: OTP-10922 </p>
++        </item>
++        <item>
++          <p>
++	    Add possibility to add user capabilities in
++	    <c>ct_netconfc:hello/3</c>.</p>
++          <p>
++	    Own Id: OTP-12707 Aux Id: seq12846 </p>
++        </item>
++      </list>
++    </section>
++
++</section>
++
+ <section><title>Common_Test 1.10</title>
+ 
+     <section><title>Fixed Bugs and Malfunctions</title>
+diff --git lib/common_test/src/Makefile lib/common_test/src/Makefile
+index 8d74546..449cba6 100644
+--- lib/common_test/src/Makefile
++++ lib/common_test/src/Makefile
+@@ -62,6 +62,8 @@ MODULES= \
+ 	ct_telnet_client \
+ 	ct_make \
+ 	vts \
++	ct_webtool \
++	ct_webtool_sup \
+ 	unix_telnet \
+ 	ct_config \
+ 	ct_config_plain \
+diff --git lib/common_test/src/ct_logs.erl lib/common_test/src/ct_logs.erl
+index dc118ed..fa55a97 100644
+--- lib/common_test/src/ct_logs.erl
++++ lib/common_test/src/ct_logs.erl
+@@ -1908,13 +1908,14 @@ sort_all_runs(Dirs) ->
+ sort_ct_runs(Dirs) ->
+     %% Directory naming: <Prefix>.NodeName.Date_Time[/...]
+     %% Sort on Date_Time string: "YYYY-MM-DD_HH.MM.SS"
+-    lists:sort(fun(Dir1,Dir2) ->
+-		       [_Prefix,_Node1,DateHH1,MM1,SS1] =
+-			   string:tokens(filename:dirname(Dir1),[$.]),
+-		       [_Prefix,_Node2,DateHH2,MM2,SS2] =
+-			   string:tokens(filename:dirname(Dir2),[$.]),
+-		       {DateHH1,MM1,SS1} =< {DateHH2,MM2,SS2}
+-	       end, Dirs).
++    lists:sort(
++      fun(Dir1,Dir2) ->
++	      [SS1,MM1,DateHH1 | _] =
++		  lists:reverse(string:tokens(filename:dirname(Dir1),[$.])),
++	      [SS2,MM2,DateHH2 | _] =
++		  lists:reverse(string:tokens(filename:dirname(Dir2),[$.])),
++	      {DateHH1,MM1,SS1} =< {DateHH2,MM2,SS2}
++      end, Dirs).
+ 
+ dir_diff_all_runs(Dirs, LogCache) ->
+     case LogCache#log_cache.all_runs of
+diff --git lib/common_test/src/ct_netconfc.erl lib/common_test/src/ct_netconfc.erl
+index 85fb1ea..80ffb51 100644
+--- lib/common_test/src/ct_netconfc.erl
++++ lib/common_test/src/ct_netconfc.erl
+@@ -172,6 +172,7 @@
+ 	 only_open/2,
+ 	 hello/1,
+ 	 hello/2,
++	 hello/3,
+ 	 close_session/1,
+ 	 close_session/2,
+ 	 kill_session/2,
+@@ -456,23 +457,35 @@ only_open(KeyOrName, ExtraOpts) ->
+ 
+ %%----------------------------------------------------------------------
+ %% @spec hello(Client) -> Result
+-%% @equiv hello(Client, infinity)
++%% @equiv hello(Client, [], infinity)
+ hello(Client) ->
+-    hello(Client,?DEFAULT_TIMEOUT).
++    hello(Client,[],?DEFAULT_TIMEOUT).
+ 
+ %%----------------------------------------------------------------------
+ -spec hello(Client,Timeout) -> Result when
+       Client :: handle(),
+       Timeout :: timeout(),
+       Result :: ok | {error,error_reason()}.
+-%% @doc Exchange `hello' messages with the server.
+-%%
+-%% Sends a `hello' message to the server and waits for the return.
+-%%
+-%% @end
+-%%----------------------------------------------------------------------
++%% @spec hello(Client, Timeout) -> Result
++%% @equiv hello(Client, [], Timeout)
+ hello(Client,Timeout) ->
+-    call(Client, {hello, Timeout}).
++    hello(Client,[],Timeout).
++
++%%----------------------------------------------------------------------
++-spec hello(Client,Options,Timeout) -> Result when
++      Client :: handle(),
++      Options :: [{capability, [string()]}],
++      Timeout :: timeout(),
++      Result :: ok | {error,error_reason()}.
++%% @doc Exchange `hello' messages with the server.
++%%
++%% Adds optional capabilities and sends a `hello' message to the
++%% server and waits for the return.
++%% @end
++%%----------------------------------------------------------------------
++hello(Client,Options,Timeout) ->
++    call(Client, {hello, Options, Timeout}).
++
+ 
+ %%----------------------------------------------------------------------
+ %% @spec get_session_id(Client) -> Result
+@@ -1040,9 +1053,9 @@ terminate(_, #state{connection=Connection}) ->
+     ok.
+ 
+ %% @private
+-handle_msg({hello,Timeout}, From,
++handle_msg({hello, Options, Timeout}, From,
+ 	   #state{connection=Connection,hello_status=HelloStatus} = State) ->
+-    case do_send(Connection, client_hello()) of
++    case do_send(Connection, client_hello(Options)) of
+ 	ok ->
+ 	    case HelloStatus of
+ 		undefined ->
+@@ -1118,7 +1131,9 @@ handle_msg({Ref,timeout},#state{pending=Pending} = State) ->
+ 	    close_session -> stop;
+ 	    _ -> noreply
+ 	end,
+-    {R,State#state{pending=Pending1}}.
++    %% Halfhearted try to get in correct state, this matches
++    %% the implementation before this patch
++    {R,State#state{pending=Pending1, buff= <<>>}}.
+ 
+ %% @private
+ %% Called by ct_util_server to close registered connections before terminate.
+@@ -1222,10 +1237,14 @@ set_request_timer(T) ->
+ 
+ 
+ %%%-----------------------------------------------------------------
+-client_hello() ->
++client_hello(Options) when is_list(Options) ->
++    UserCaps = [{capability, UserCap} ||
++		   {capability, UserCap} <- Options,
++		   is_list(hd(UserCap))],
+     {hello, ?NETCONF_NAMESPACE_ATTR,
+      [{capabilities,
+-       [{capability,[?NETCONF_BASE_CAP++?NETCONF_BASE_CAP_VSN]}]}]}.
++       [{capability,[?NETCONF_BASE_CAP++?NETCONF_BASE_CAP_VSN]}|
++	UserCaps]}]}.
+ 
+ %%%-----------------------------------------------------------------
+ 
+@@ -1308,72 +1327,54 @@ to_xml_doc(Simple) ->
+ 
+ %%%-----------------------------------------------------------------
+ %%% Parse and handle received XML data
+-handle_data(NewData,#state{connection=Connection,buff=Buff} = State) ->
++handle_data(NewData,#state{connection=Connection,buff=Buff0} = State0) ->
+     log(Connection,recv,NewData),
+-    Data = <<Buff/binary,NewData/binary>>,
+-    case xmerl_sax_parser:stream(<<>>,
+-				 [{continuation_fun,fun sax_cont/1},
+-				  {continuation_state,{Data,Connection,false}},
+-				  {event_fun,fun sax_event/3},
+-				  {event_state,[]}]) of
+-	{ok, Simple, Rest} ->
+-	    decode(Simple,State#state{buff=Rest});
+-	{fatal_error,_Loc,Reason,_EndTags,_EventState} ->
+-	    ?error(Connection#connection.name,[{parse_error,Reason},
+-					       {buffer,Buff},
+-					       {new_data,NewData}]),
+-	    case Reason of
+-		{could_not_fetch_data,Msg} ->
+-		    handle_msg(Msg,State#state{buff = <<>>});
+-		_Other ->
+-		    Pending1 =
+-			case State#state.pending of
+-			    [] ->
+-				[];
+-			    Pending ->
+-				%% Assuming the first request gets the
+-				%% first answer
+-				P=#pending{tref=TRef,caller=Caller} =
+-				    lists:last(Pending),
+-				_ = timer:cancel(TRef),
+-				Reason1 = {failed_to_parse_received_data,Reason},
+-				ct_gen_conn:return(Caller,{error,Reason1}),
+-				lists:delete(P,Pending)
+-			end,
+-		    {noreply,State#state{pending=Pending1,buff = <<>>}}
+-	    end
+-    end.
+-
+-%%%-----------------------------------------------------------------
+-%%% Parsing of XML data
+-%% Contiuation function for the sax parser
+-sax_cont(done) ->
+-    {<<>>,done};
+-sax_cont({Data,Connection,false}) ->
++    Data = append_wo_initial_nl(Buff0,NewData),
+     case binary:split(Data,[?END_TAG],[]) of
+-	[All] ->
+-	    %% No end tag found. Remove what could be a part
+-	    %% of an end tag from the data and save for next
+-	    %% iteration
+-	    SafeSize = size(All)-5,
+-	    <<New:SafeSize/binary,Save:5/binary>> = All,
+-	    {New,{Save,Connection,true}};
+-	[_Msg,_Rest]=Msgs ->
+-	    %% We have at least one full message. Any excess data will
+-	    %% be returned from xmerl_sax_parser:stream/2 in the Rest
+-	    %% parameter.
+-	    {list_to_binary(Msgs),done}
+-    end;
+-sax_cont({Data,Connection,true}) ->
+-    case ssh_receive_data() of
+-	{ok,Bin} ->
+-	    log(Connection,recv,Bin),
+-	    sax_cont({<<Data/binary,Bin/binary>>,Connection,false});
+-	{error,Reason} ->
+-	    throw({could_not_fetch_data,Reason})
++	[_NoEndTagFound] ->
++	    {noreply, State0#state{buff=Data}};
++	[FirstMsg,Buff1] ->
++	    SaxArgs = [{event_fun,fun sax_event/3}, {event_state,[]}],
++	    case xmerl_sax_parser:stream(FirstMsg, SaxArgs) of
++		{ok, Simple, _Thrash} ->
++		    case decode(Simple, State0#state{buff=Buff1}) of
++			{noreply, #state{buff=Buff} = State} when Buff =/= <<>> ->
++			    %% Recurse if we have more data in buffer
++			    handle_data(<<>>, State);
++			Other ->
++			    Other
++		    end;
++		{fatal_error,_Loc,Reason,_EndTags,_EventState} ->
++		    ?error(Connection#connection.name,
++			   [{parse_error,Reason},
++			    {buffer, Buff0},
++			    {new_data,NewData}]),
++		    handle_error(Reason, State0#state{buff= <<>>})
++	    end
+     end.
+ 
++%% xml does not accept a leading nl and some netconf server add a nl after
++%% each ?END_TAG, ignore them
++append_wo_initial_nl(<<>>,NewData) -> NewData;
++append_wo_initial_nl(<<"\n", Data/binary>>, NewData) ->
++    append_wo_initial_nl(Data, NewData);
++append_wo_initial_nl(Data, NewData) ->
++    <<Data/binary, NewData/binary>>.
+ 
++handle_error(Reason, State) ->
++    Pending1 = case State#state.pending of
++		   [] -> [];
++		   Pending ->
++		       %% Assuming the first request gets the
++		       %% first answer
++		       P=#pending{tref=TRef,caller=Caller} =
++			   lists:last(Pending),
++		       _ = timer:cancel(TRef),
++		       Reason1 = {failed_to_parse_received_data,Reason},
++		       ct_gen_conn:return(Caller,{error,Reason1}),
++		       lists:delete(P,Pending)
++	       end,
++    {noreply, State#state{pending=Pending1}}.
+ 
+ %% Event function for the sax parser. It builds a simple XML structure.
+ %% Care is taken to keep namespace attributes and prefixes as in the original XML.
+@@ -1836,16 +1837,6 @@ get_tag([]) ->
+ 
+ %%%-----------------------------------------------------------------
+ %%% SSH stuff
+-ssh_receive_data() ->
+-    receive
+-	{ssh_cm, CM, {data, Ch, _Type, Data}} ->
+-	    ssh_connection:adjust_window(CM,Ch,size(Data)),
+-	    {ok, Data};
+-        {ssh_cm, _CM, {Closed, _Ch}} = X when Closed == closed; Closed == eof ->
+-            {error,X};
+-	{_Ref,timeout} = X ->
+-	    {error,X}
+-    end.
+ 
+ ssh_open(#options{host=Host,timeout=Timeout,port=Port,ssh=SshOpts,name=Name}) ->
+     case ssh:connect(Host, Port,
+diff --git lib/common_test/src/ct_run.erl lib/common_test/src/ct_run.erl
+index 4a12481..be547b4 100644
+--- lib/common_test/src/ct_run.erl
++++ lib/common_test/src/ct_run.erl
+@@ -225,18 +225,24 @@ finish(Tracing, ExitStatus, Args) ->
+     if ExitStatus == interactive_mode ->
+ 	    interactive_mode;
+        true ->
+-	    %% it's possible to tell CT to finish execution with a call
+-	    %% to a different function than the normal halt/1 BIF
+-	    %% (meant to be used mainly for reading the CT exit status)
+-	    case get_start_opt(halt_with,
+-			       fun([HaltMod,HaltFunc]) -> 
+-				       {list_to_atom(HaltMod),
+-					list_to_atom(HaltFunc)} end,
+-			       Args) of
+-		undefined ->
+-		    halt(ExitStatus);
+-		{M,F} ->
+-		    apply(M, F, [ExitStatus])
++	    case get_start_opt(vts, true, Args) of
++		true ->
++		    %% VTS mode, don't halt the node
++		    ok;
++		_ ->
++		    %% it's possible to tell CT to finish execution with a call
++		    %% to a different function than the normal halt/1 BIF
++		    %% (meant to be used mainly for reading the CT exit status)
++		    case get_start_opt(halt_with,
++				       fun([HaltMod,HaltFunc]) -> 
++					       {list_to_atom(HaltMod),
++						list_to_atom(HaltFunc)} end,
++				       Args) of
++			undefined ->
++			    halt(ExitStatus);
++			{M,F} ->
++			    apply(M, F, [ExitStatus])
++		    end
+ 	    end
+     end.
+ 
+@@ -244,7 +250,7 @@ script_start1(Parent, Args) ->
+     %% read general start flags
+     Label = get_start_opt(label, fun([Lbl]) -> Lbl end, Args),
+     Profile = get_start_opt(profile, fun([Prof]) -> Prof end, Args),
+-    Vts = get_start_opt(vts, true, Args),
++    Vts = get_start_opt(vts, true, undefined, Args),
+     Shell = get_start_opt(shell, true, Args),
+     Cover = get_start_opt(cover, fun([CoverFile]) -> ?abs(CoverFile) end, Args),
+     CoverStop = get_start_opt(cover_stop, 
+@@ -330,8 +336,8 @@ script_start1(Parent, Args) ->
+     Stylesheet = get_start_opt(stylesheet,
+ 			       fun([SS]) -> ?abs(SS) end, Args),
+     %% basic_html - used by ct_logs
+-    BasicHtml = case proplists:get_value(basic_html, Args) of
+-		    undefined ->
++    BasicHtml = case {Vts,proplists:get_value(basic_html, Args)} of
++		    {undefined,undefined} ->
+ 			application:set_env(common_test, basic_html, false),
+ 			undefined;
+ 		    _ ->
+@@ -364,9 +370,10 @@ script_start1(Parent, Args) ->
+ 		 scale_timetraps = ScaleTT,
+ 		 create_priv_dir = CreatePrivDir,
+ 		 starter = script},
+-    
++
+     %% check if log files should be refreshed or go on to run tests...
+     Result = run_or_refresh(Opts, Args),
++
+     %% send final results to starting process waiting in script_start/0
+     Parent ! {self(), Result}.
+ 
+@@ -757,21 +764,6 @@ script_start4(Opts = #opts{tests = Tests}, Args) ->
+ %%% @doc Print usage information for <code>ct_run</code>.
+ script_usage() ->
+     io:format("\n\nUsage:\n\n"),
+-    io:format("Run tests in web based GUI:\n\n"
+-	      "\tct_run -vts [-browser Browser]"
+-	      "\n\t[-config ConfigFile1 ConfigFile2 .. ConfigFileN]"
+-	      "\n\t[-decrypt_key Key] | [-decrypt_file KeyFile]"
+-	      "\n\t[-dir TestDir1 TestDir2 .. TestDirN] |"
+-	      "\n\t[-suite Suite [-case Case]]"
+-	      "\n\t[-logopts LogOpt1 LogOpt2 .. LogOptN]"
+-	      "\n\t[-verbosity GenVLvl | [CategoryVLvl1 .. CategoryVLvlN]]"
+-	      "\n\t[-include InclDir1 InclDir2 .. InclDirN]"
+-	      "\n\t[-no_auto_compile]"
+-	      "\n\t[-abort_if_missing_suites]"
+-	      "\n\t[-multiply_timetraps N]"
+-	      "\n\t[-scale_timetraps]"
+-	      "\n\t[-create_priv_dir auto_per_run | auto_per_tc | manual_per_tc]"
+-	      "\n\t[-basic_html]\n\n"),
+     io:format("Run tests from command line:\n\n"
+ 	      "\tct_run [-dir TestDir1 TestDir2 .. TestDirN] |"
+ 	      "\n\t[[-dir TestDir] -suite Suite1 Suite2 .. SuiteN"
+@@ -831,7 +823,22 @@ script_usage() ->
+     io:format("Run CT in interactive mode:\n\n"
+ 	      "\tct_run -shell"
+ 	      "\n\t[-config ConfigFile1 ConfigFile2 .. ConfigFileN]"
+-	      "\n\t[-decrypt_key Key] | [-decrypt_file KeyFile]\n\n").
++	      "\n\t[-decrypt_key Key] | [-decrypt_file KeyFile]\n\n"),
++    io:format("Run tests in web based GUI:\n\n"
++	      "\tct_run -vts [-browser Browser]"
++	      "\n\t[-config ConfigFile1 ConfigFile2 .. ConfigFileN]"
++	      "\n\t[-decrypt_key Key] | [-decrypt_file KeyFile]"
++	      "\n\t[-dir TestDir1 TestDir2 .. TestDirN] |"
++	      "\n\t[-suite Suite [-case Case]]"
++	      "\n\t[-logopts LogOpt1 LogOpt2 .. LogOptN]"
++	      "\n\t[-verbosity GenVLvl | [CategoryVLvl1 .. CategoryVLvlN]]"
++	      "\n\t[-include InclDir1 InclDir2 .. InclDirN]"
++	      "\n\t[-no_auto_compile]"
++	      "\n\t[-abort_if_missing_suites]"
++	      "\n\t[-multiply_timetraps N]"
++	      "\n\t[-scale_timetraps]"
++	      "\n\t[-create_priv_dir auto_per_run | auto_per_tc | manual_per_tc]"
++	      "\n\t[-basic_html]\n\n").
+ 
+ %%%-----------------------------------------------------------------
+ %%% @hidden
+diff --git lib/common_test/src/ct_telnet.erl lib/common_test/src/ct_telnet.erl
+index d906a26..844f537 100644
+--- lib/common_test/src/ct_telnet.erl
++++ lib/common_test/src/ct_telnet.erl
+@@ -486,7 +486,8 @@ expect(Connection,Patterns) ->
+ %%%      Opts = [Opt]
+ %%%      Opt = {idle_timeout,IdleTimeout} | {total_timeout,TotalTimeout} |
+ %%%            repeat | {repeat,N} | sequence | {halt,HaltPatterns} |
+-%%%            ignore_prompt | no_prompt_check
++%%%            ignore_prompt | no_prompt_check | wait_for_prompt |
++%%%            {wait_for_prompt,Prompt}
+ %%%      IdleTimeout = infinity | integer()
+ %%%      TotalTimeout = infinity | integer()
+ %%%      N = integer()
+@@ -499,9 +500,9 @@ expect(Connection,Patterns) ->
+ %%%
+ %%% @doc Get data from telnet and wait for the expected pattern.
+ %%%
+-%%% <p><code>Pattern</code> can be a POSIX regular expression. If more
+-%%% than one pattern is given, the function returns when the first
+-%%% match is found.</p>
++%%% <p><code>Pattern</code> can be a POSIX regular expression. The function
++%%% returns as soon as a pattern has been successfully matched (at least one,
++%%% in the case of multiple patterns).</p>
+ %%%
+ %%% <p><code>RxMatch</code> is a list of matched strings. It looks
+ %%% like this: <code>[FullMatch, SubMatch1, SubMatch2, ...]</code>
+@@ -524,10 +525,13 @@ expect(Connection,Patterns) ->
+ %%% milliseconds, <code>{error,timeout}</code> is returned. The default
+ %%% value is <code>infinity</code> (i.e. no time limit).</p>
+ %%%
+-%%% <p>The function will always return when a prompt is found, unless
+-%%% any of the <code>ignore_prompt</code> or
+-%%% <code>no_prompt_check</code> options are used, in which case it
+-%%% will return when a match is found or after a timeout.</p>
++%%% <p>The function will return when a prompt is received, even if no
++%%% pattern has yet been matched. In this event,
++%%% <code>{error,{prompt,Prompt}}</code> is returned.
++%%% However, this behaviour may be modified with the
++%%% <code>ignore_prompt</code> or <code>no_prompt_check</code> option, which
++%%% tells <code>expect</code> to return only when a match is found or after a
++%%% timeout.</p>
+ %%%
+ %%% <p>If the <code>ignore_prompt</code> option is used,
+ %%% <code>ct_telnet</code> will ignore any prompt found. This option
+@@ -541,6 +545,13 @@ expect(Connection,Patterns) ->
+ %%% is useful if, for instance, the <code>Pattern</code> itself
+ %%% matches the prompt.</p>
+ %%%
++%%% <p>The <code>wait_for_prompt</code> option forces <code>ct_telnet</code>
++%%% to wait until the prompt string has been received before returning
++%%% (even if a pattern has already been matched). This is equal to calling:
++%%% <code>expect(Conn, Patterns++[{prompt,Prompt}], [sequence|Opts])</code>.
++%%% Note that <code>idle_timeout</code> and <code>total_timeout</code>
++%%% may abort the operation of waiting for prompt.</p>
++%%%
+ %%% <p>The <code>repeat</code> option indicates that the pattern(s)
+ %%% shall be matched multiple times. If <code>N</code> is given, the
+ %%% pattern(s) will be matched <code>N</code> times, and the function
+@@ -653,18 +664,21 @@ handle_msg({cmd,Cmd,Opts},State) ->
+     start_gen_log(heading(cmd,State#state.name)),
+     log(State,cmd,"Cmd: ~p",[Cmd]),
+ 
++    %% whatever is in the buffer from previous operations
++    %% will be ignored as we go ahead with this telnet cmd
++
+     debug_cont_gen_log("Throwing Buffer:",[]),
+     debug_log_lines(State#state.buffer),
+ 
+     case {State#state.type,State#state.prompt} of
+-	{ts,_} -> 
++	{ts,_} ->
+ 	    silent_teln_expect(State#state.name,
+ 			       State#state.teln_pid,
+ 			       State#state.buffer,
+ 			       prompt,
+ 			       State#state.prx,
+ 			       [{idle_timeout,2000}]);
+-	{ip,false} -> 
++	{ip,false} ->
+ 	    silent_teln_expect(State#state.name,
+ 			       State#state.teln_pid,
+ 			       State#state.buffer,
+@@ -1029,10 +1043,12 @@ teln_expect(Name,Pid,Data,Pattern0,Prx,Opts) ->
+ 	end,
+ 
+     PromptCheck = get_prompt_check(Opts),
+-    Seq = get_seq(Opts),
+-    Pattern = convert_pattern(Pattern0,Seq),
+ 
+-    {IdleTimeout,TotalTimeout} = get_timeouts(Opts),
++    {WaitForPrompt,Pattern1,Opts1} = wait_for_prompt(Pattern0,Opts),
++
++    Seq = get_seq(Opts1),
++    Pattern2 = convert_pattern(Pattern1,Seq),
++    {IdleTimeout,TotalTimeout} = get_timeouts(Opts1),
+ 
+     EO = #eo{teln_pid=Pid,
+ 	     prx=Prx,
+@@ -1042,9 +1058,16 @@ teln_expect(Name,Pid,Data,Pattern0,Prx,Opts) ->
+ 	     haltpatterns=HaltPatterns,
+ 	     prompt_check=PromptCheck},
+     
+-    case get_repeat(Opts) of
++    case get_repeat(Opts1) of
+ 	false ->
+-	    case teln_expect1(Name,Pid,Data,Pattern,[],EO) of
++	    case teln_expect1(Name,Pid,Data,Pattern2,[],EO) of
++		{ok,Matched,Rest} when WaitForPrompt ->
++		    case lists:reverse(Matched) of
++			[{prompt,_},Matched1] ->
++			    {ok,Matched1,Rest};
++			[{prompt,_}|Matched1] ->
++			    {ok,lists:reverse(Matched1),Rest}
++		    end;
+ 		{ok,Matched,Rest} ->
+ 		    {ok,Matched,Rest};
+ 		{halt,Why,Rest} ->
+@@ -1054,7 +1077,7 @@ teln_expect(Name,Pid,Data,Pattern0,Prx,Opts) ->
+ 	    end;
+ 	N ->
+ 	    EO1 = EO#eo{repeat=N},
+-	    repeat_expect(Name,Pid,Data,Pattern,[],EO1)
++	    repeat_expect(Name,Pid,Data,Pattern2,[],EO1)
+     end.
+ 
+ convert_pattern(Pattern,Seq) 
+@@ -1118,6 +1141,40 @@ get_ignore_prompt(Opts) ->
+ get_prompt_check(Opts) ->
+     not lists:member(no_prompt_check,Opts).
+ 
++wait_for_prompt(Pattern, Opts) ->
++    case lists:member(wait_for_prompt, Opts) of
++	true ->
++	    wait_for_prompt1(prompt, Pattern,
++			     lists:delete(wait_for_prompt,Opts));
++	false ->
++	    case proplists:get_value(wait_for_prompt, Opts) of
++		undefined ->
++		    {false,Pattern,Opts};
++		PromptStr ->
++		    wait_for_prompt1({prompt,PromptStr}, Pattern,
++				     proplists:delete(wait_for_prompt,Opts))
++	    end
++    end.
++
++wait_for_prompt1(Prompt, [Ch|_] = Pattern, Opts) when is_integer(Ch) ->
++    wait_for_prompt2(Prompt, [Pattern], Opts);
++wait_for_prompt1(Prompt, Pattern, Opts) when is_list(Pattern) ->
++    wait_for_prompt2(Prompt, Pattern, Opts);
++wait_for_prompt1(Prompt, Pattern, Opts) ->
++    wait_for_prompt2(Prompt, [Pattern], Opts).
++
++wait_for_prompt2(Prompt, Pattern, Opts) ->
++    Pattern1 = case lists:reverse(Pattern) of
++		   [prompt|_]     -> Pattern;
++		   [{prompt,_}|_] -> Pattern;
++		   _              -> Pattern ++ [Prompt]
++	       end,
++    Opts1 = case lists:member(sequence, Opts) of
++		true ->  Opts;
++		false -> [sequence|Opts]
++	    end,
++    {true,Pattern1,Opts1}.
++
+ %% Repeat either single or sequence. All match results are accumulated
+ %% and returned when a halt condition is fulllfilled.
+ repeat_expect(_Name,_Pid,Rest,_Pattern,Acc,#eo{repeat=0}) ->
+@@ -1210,7 +1267,7 @@ get_data1(Pid) ->
+ %% 1) Single expect.
+ %% First the whole data chunk is searched for a prompt (to avoid doing
+ %% a regexp match for the prompt at each line).
+-%% If we are searching for anyting else, the datachunk is split into
++%% If we are searching for anything else, the datachunk is split into
+ %% lines and each line is matched against each pattern.
+ 
+ %% one_expect: split data chunk at prompts
+@@ -1227,7 +1284,7 @@ one_expect(Name,Pid,Data,Pattern,EO) ->
+ 		    log(name_or_pid(Name,Pid),"PROMPT: ~ts",[PromptType]),
+ 		    {match,{prompt,PromptType},Rest};
+ 		[{prompt,_OtherPromptType}] ->
+-		    %% Only searching for one specific prompt, not thisone
++		    %% Only searching for one specific prompt, not this one
+ 		    log_lines(Name,Pid,UptoPrompt),
+ 		    {nomatch,Rest};
+ 		_ ->
+diff --git lib/common_test/src/ct_webtool.erl lib/common_test/src/ct_webtool.erl
+new file mode 100644
+index 0000000..b67a7c2
+--- /dev/null
++++ lib/common_test/src/ct_webtool.erl
+@@ -0,0 +1,1207 @@
++%%
++%% %CopyrightBegin%
++%%
++%% Copyright Ericsson AB 2001-2010. 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%
++%%
++-module(ct_webtool).
++-behaviour(gen_server).
++
++%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
++%%                                                                    %%
++%% The general idea is:                                               %%
++%%                                                                    %%
++%%                                                                    %%
++%% 1. Scan through the path for *.tool files and find all the web     %%
++%%    based tools. Query each tool for configuration data.            %%
++%% 2. Add Alias for Erlscript and html for each tool to               %%
++%%    the webserver configuration data.                               %%
++%% 3. Start the webserver.                                            %%
++%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
++
++%% API functions
++-export([start/0, start/2, stop/0]).
++
++%% Starting Webtool from a shell script
++-export([script_start/0, script_start/1]).
++
++%% Web api
++-export([started_tools/2, toolbar/2, start_tools/2, stop_tools/2]).
++
++%% API against other tools
++-export([is_localhost/0]).
++
++%% Debug export s
++-export([get_tools1/1]).
++-export([debug/1, stop_debug/0, debug_app/1]).
++
++%% gen_server callbacks
++-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
++	 terminate/2, code_change/3]).
++
++-include_lib("kernel/include/file.hrl").
++-include_lib("stdlib/include/ms_transform.hrl").
++
++-record(state,{priv_dir,app_data,supvis,web_data,started=[]}).
++
++-define(MAX_NUMBER_OF_WEBTOOLS,256).
++-define(DEFAULT_PORT,8888).% must be >1024 or the user must be root on unix
++-define(DEFAULT_ADDR,{127,0,0,1}).
++
++-define(WEBTOOL_ALIAS,{ct_webtool,[{alias,{erl_alias,"/ct_webtool",[ct_webtool]}}]}).
++-define(HEADER,"Pragma:no-cache\r\n Content-type: text/html\r\n\r\n").
++-define(HTML_HEADER,"<HTML>\r\n<HEAD>\r\n<TITLE>WebTool</TITLE>\r\n</HEAD>\r\n<BODY BGCOLOR=\"#FFFFFF\">\r\n").
++-define(HTML_HEADER_RELOAD,"<HTML>\r\n<HEAD>\r\n<TITLE>WebTool
++                             </TITLE>\r\n</HEAD>\r\n
++                             <BODY BGCOLOR=\"#FFFFFF\" onLoad=reloadCompiledList()>\r\n").
++
++-define(HTML_END,"</BODY></HTML>").
++
++-define(SEND_URL_TIMEOUT,5000).
++
++%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
++%%                                                                  %%
++%% For debugging only.                                              %%
++%%                                                                  %%
++%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
++%% Start tracing with
++%% debug(Functions).
++%% Functions = local | global | FunctionList
++%% FunctionList = [Function]
++%% Function = {FunctionName,Arity} | FunctionName |
++%%            {Module, FunctionName, Arity} | {Module,FunctionName}
++debug(F) -> 
++    ttb:tracer(all,[{file,"webtool.trc"}]), % tracing all nodes
++    ttb:p(all,[call,timestamp]),
++    MS = [{'_',[],[{return_trace},{message,{caller}}]}],
++    tp(F,MS),
++    ttb:ctp(?MODULE,stop_debug), % don't want tracing of the stop_debug func
++    ok.
++tp(local,MS) -> % all functions
++    ttb:tpl(?MODULE,MS);
++tp(global,MS) -> % all exported functions
++    ttb:tp(?MODULE,MS);
++tp([{M,F,A}|T],MS) -> % Other module
++    ttb:tpl(M,F,A,MS),
++    tp(T,MS);
++tp([{M,F}|T],MS) when is_atom(F) -> % Other module
++    ttb:tpl(M,F,MS),
++    tp(T,MS);
++tp([{F,A}|T],MS) -> % function/arity
++    ttb:tpl(?MODULE,F,A,MS),
++    tp(T,MS);
++tp([F|T],MS) -> % function
++    ttb:tpl(?MODULE,F,MS),
++    tp(T,MS);
++tp([],_MS) ->
++    ok.
++stop_debug() ->
++    ttb:stop([format]).
++
++debug_app(Mod) ->
++    ttb:tracer(all,[{file,"webtool_app.trc"},{handler,{fun out/4,true}}]),
++    ttb:p(all,[call,timestamp]),
++    MS = [{'_',[],[{return_trace},{message,{caller}}]}],
++    ttb:tp(Mod,MS),
++    ok.
++   
++out(_,{trace_ts,Pid,call,MFA={M,F,A},{W,_,_},TS},_,S) 
++  when W==webtool;W==mod_esi-> 
++    io:format("~w: (~p)~ncall ~s~n", [TS,Pid,ffunc(MFA)]),
++    [{M,F,length(A)}|S];
++out(_,{trace_ts,Pid,return_from,MFA,R,TS},_,[MFA|S]) ->
++    io:format("~w: (~p)~nreturned from ~s -> ~p~n", [TS,Pid,ffunc(MFA),R]),
++    S;
++out(_,_,_,_) ->
++    ok.
++
++%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
++%%                                                                  %%
++%% Functions called via script.                                     %%
++%%                                                                  %%
++%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
++script_start() ->
++    usage(),
++    halt().
++script_start([App]) ->
++    DefaultBrowser = 
++	case os:type() of
++	    {win32,_} -> iexplore;
++	    _ -> firefox
++	end,
++    script_start([App,DefaultBrowser]);
++script_start([App,Browser]) ->
++    io:format("Starting webtool...\n"),
++    start(),
++    AvailableApps = get_applications(),
++    {OSType,_} = os:type(),
++    case lists:keysearch(App,1,AvailableApps) of
++	{value,{App,StartPage}} ->
++	    io:format("Starting ~w...\n",[App]),
++	    start_tools([],"app=" ++ atom_to_list(App)),
++	    PortStr = integer_to_list(get_port()),
++	    Url = case StartPage of
++		      "/" ++ Page -> 
++			  "http://localhost:" ++ PortStr ++ "/" ++ Page;
++		      _ -> 
++			  "http://localhost:" ++ PortStr ++ "/" ++ StartPage
++		  end,
++	    case Browser of 
++		none ->
++		    ok;
++                iexplore when OSType == win32->
++                    io:format("Starting internet explorer...\n"),
++                    {ok,R} = win32reg:open(""),
++		    Key="\\local_machine\\SOFTWARE\\Microsoft\\IE Setup\\Setup",
++                    win32reg:change_key(R,Key),
++                    {ok,Val} = win32reg:value(R,"Path"),
++		    IExplore=filename:join(win32reg:expand(Val),"iexplore.exe"),
++                    os:cmd("\"" ++ IExplore ++ "\" " ++ Url);
++		_ when OSType == win32 ->
++                    io:format("Starting ~w...\n",[Browser]),
++                    os:cmd("\"" ++ atom_to_list(Browser) ++ "\" " ++ Url);
++		B when B==firefox; B==mozilla ->
++		    io:format("Sending URL to ~w...",[Browser]),
++		    BStr = atom_to_list(Browser),
++		    SendCmd = BStr ++ " -raise -remote \'openUrl(" ++ 
++			Url ++ ")\'",
++		    Port = open_port({spawn,SendCmd},[exit_status]),
++		    receive 
++			{Port,{exit_status,0}} -> 
++			    io:format("done\n"),
++			    ok;
++			{Port,{exit_status,_Error}} ->
++			    io:format(" not running, starting ~w...\n",
++				      [Browser]),
++			    os:cmd(BStr ++ " " ++ Url),
++			    ok
++		    after ?SEND_URL_TIMEOUT ->
++			    io:format(" failed, starting ~w...\n",[Browser]),
++			    erlang:port_close(Port),
++			    os:cmd(BStr ++ " " ++ Url)
++		    end;
++		_ ->
++		    io:format("Starting ~w...\n",[Browser]),
++		    os:cmd(atom_to_list(Browser) ++ " " ++ Url)
++	    end,
++	    ok;
++	false ->
++	    stop(),
++	    io:format("\n{error,{unknown_app,~p}}\n",[App]),
++	    halt()
++    end.
++
++usage() ->
++    io:format("Starting webtool...\n"),
++    start(),
++    Apps = lists:map(fun({A,_}) -> A end,get_applications()),
++    io:format(
++      "\nUsage: start_webtool application [ browser ]\n"
++      "\nAvailable applications are: ~p\n"
++      "Default browser is \'iexplore\' (Internet Explorer) on Windows "
++      "or else \'firefox\'\n",
++      [Apps]),
++    stop().
++
++
++get_applications() ->

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201505072034.t47KYU9L053577>