diff options
Diffstat (limited to 'lib/tools')
64 files changed, 4172 insertions, 5697 deletions
diff --git a/lib/tools/Makefile b/lib/tools/Makefile index 2699ffab51..e17e9cfd1e 100644 --- a/lib/tools/Makefile +++ b/lib/tools/Makefile @@ -1,7 +1,7 @@ # # %CopyrightBegin% # -# Copyright Ericsson AB 1996-2009. All Rights Reserved. +# Copyright Ericsson AB 1996-2016. All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -24,7 +24,7 @@ include $(ERL_TOP)/make/$(TARGET)/otp.mk # Macros # ---------------------------------------------------- -SUB_DIRECTORIES = c_src src doc/src examples priv emacs +SUB_DIRECTORIES = c_src src doc/src examples emacs include vsn.mk VSN = $(TOOLS_VSN) diff --git a/lib/tools/c_src/Makefile.in b/lib/tools/c_src/Makefile.in index 66bba229f6..cfe91917f8 100644 --- a/lib/tools/c_src/Makefile.in +++ b/lib/tools/c_src/Makefile.in @@ -1,7 +1,7 @@ # # %CopyrightBegin% # -# Copyright Ericsson AB 2009-2012. All Rights Reserved. +# Copyright Ericsson AB 2009-2016. All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -97,11 +97,8 @@ DRIVERS= ifneq ($(strip $(ETHR_LIB_NAME)),) # Need ethread package for emem -ifneq ($(findstring ose,$(TARGET)),ose) -# Do not build on OSE PROGS += $(BIN_DIR)/emem$(TYPEMARKER)@EXEEXT@ endif -endif EMEM_OBJ_DIR=$(OBJ_DIR)/emem CREATE_DIRS += $(EMEM_OBJ_DIR) @@ -152,12 +149,7 @@ ERTS_LIB = $(ERL_TOP/erts/lib_src/obj/$(TARGET)/$(TYPE)/MADE _create_dirs := $(shell mkdir -p $(CREATE_DIRS)) -ifneq ($(findstring ose,$(TARGET)),ose) all: $(PROGS) $(DRIVERS) -else -# Do not build dynamic files on OSE -all: -endif $(ERTS_LIB): $(make_verbose)cd $(ERL_TOP)/erts/lib_src && $(MAKE) $(TYPE) diff --git a/lib/tools/c_src/erl_memory.c b/lib/tools/c_src/erl_memory.c index d3a96884db..13a3fccc6d 100644 --- a/lib/tools/c_src/erl_memory.c +++ b/lib/tools/c_src/erl_memory.c @@ -1,7 +1,7 @@ /* * %CopyrightBegin% * - * Copyright Ericsson AB 2003-2013. All Rights Reserved. + * Copyright Ericsson AB 2003-2016. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/lib/tools/doc/src/Makefile b/lib/tools/doc/src/Makefile index c44c9ef4df..d9c3b0ad2a 100644 --- a/lib/tools/doc/src/Makefile +++ b/lib/tools/doc/src/Makefile @@ -1,7 +1,7 @@ # # %CopyrightBegin% # -# Copyright Ericsson AB 1997-2012. All Rights Reserved. +# Copyright Ericsson AB 1997-2016. All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/lib/tools/doc/src/book.xml b/lib/tools/doc/src/book.xml index 03afa1fc37..38d0408156 100644 --- a/lib/tools/doc/src/book.xml +++ b/lib/tools/doc/src/book.xml @@ -4,7 +4,7 @@ <book xmlns:xi="http://www.w3.org/2001/XInclude"> <header titlestyle="normal"> <copyright> - <year>1997</year><year>2013</year> + <year>1997</year><year>2016</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> diff --git a/lib/tools/doc/src/cover_chapter.xml b/lib/tools/doc/src/cover_chapter.xml index 2f7f8d8083..3847adbe59 100644 --- a/lib/tools/doc/src/cover_chapter.xml +++ b/lib/tools/doc/src/cover_chapter.xml @@ -4,7 +4,7 @@ <chapter> <header> <copyright> - <year>2001</year><year>2013</year> + <year>2001</year><year>2016</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -451,48 +451,5 @@ ok <p>When Cover is stopped, all Cover compiled modules are unloaded.</p> </section> </section> - - <section> - <title>Using the Web Based User Interface to Cover</title> - - <section> - <title>Introduction</title> - <p>To ease the use of Cover there is a web based user interface - to Cover called WebCover. WebCover is designed to be started - and used via WebTool. It is possible to Cover compile Erlang - modules and to generate printable Cover and Call analyses via - the web based user interface.</p> - </section> - - <section> - <title>Start the Web Based User Interface to Cover</title> - <p>To start WebCover you can either start WebTool, point a - browser to the start page of WebTool and start WebCover from - there, or you can use the <c>start_webtool</c> script to start - Webtool, WebCover and a browser. See WebTool documentation for - further information.</p> - <p>Currently WebCover is only compatible - with Internet Explorer and Netscape Navigator 4.0 and higher.</p> - </section> - - <section> - <title>Navigating WebCover</title> - <p>From the menu in the lefthand frame you can select the - <c>Nodes</c>, <c>Compile</c>, <c>Import</c> or <c>Result</c> - page.</p> - <p>From the <c>Nodes</c> page you can add remote nodes to - participate in the coverage analysis. Coverage data from all - involved nodes will then be merged during analysis.</p> - <p>From the <c>Compile</c> page you can Cover compile <c>.erl</c> - or <c>.beam</c> files.</p> - <p>From the <c>Import</c> page you can import coverage data from - a previous analysis. Imported data will then be merged with - the current coverage data. <em>Note</em> that it is only possible to - import files with the extension <c>.coverdata</c>.</p> - <p>From the <c>Result</c> page you can analyse, reset or export - coverage data.</p> - <p>Please follow the instructions on each page.</p> - </section> - </section> </chapter> diff --git a/lib/tools/doc/src/cprof.xml b/lib/tools/doc/src/cprof.xml index d3be276d28..df0acbe617 100644 --- a/lib/tools/doc/src/cprof.xml +++ b/lib/tools/doc/src/cprof.xml @@ -5,7 +5,7 @@ <header> <copyright> <year>2002</year> - <year>2013</year> + <year>2016</year> <holder>Ericsson AB, All Rights Reserved</holder> </copyright> <legalnotice> diff --git a/lib/tools/doc/src/cprof_chapter.xml b/lib/tools/doc/src/cprof_chapter.xml index 0e83dbbfb5..ba1e7432fd 100644 --- a/lib/tools/doc/src/cprof_chapter.xml +++ b/lib/tools/doc/src/cprof_chapter.xml @@ -4,7 +4,7 @@ <chapter> <header> <copyright> - <year>2002</year><year>2013</year> + <year>2002</year><year>2016</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> diff --git a/lib/tools/doc/src/eprof.xml b/lib/tools/doc/src/eprof.xml index 8e37d49c99..f098b7d39e 100644 --- a/lib/tools/doc/src/eprof.xml +++ b/lib/tools/doc/src/eprof.xml @@ -4,7 +4,7 @@ <erlref> <header> <copyright> - <year>1996</year><year>2013</year> + <year>1996</year><year>2016</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> diff --git a/lib/tools/doc/src/erlang_mode.xml b/lib/tools/doc/src/erlang_mode.xml index 4ecb8feadd..00cf5196b4 100644 --- a/lib/tools/doc/src/erlang_mode.xml +++ b/lib/tools/doc/src/erlang_mode.xml @@ -4,7 +4,7 @@ <erlref> <header> <copyright> - <year>2003</year><year>2013</year> + <year>2003</year><year>2016</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -252,6 +252,7 @@ behavior</item> <item>gen_event - skeleton for the OTP gen_event behavior</item> <item>gen_fsm - skeleton for the OTP gen_fsm behavior</item> + <item>gen_statem - skeleton for the OTP gen_statem behavior</item> <item>Library module - skeleton for a module that does not implement a process.</item> <item>Corba callback - skeleton for a Corba callback module.</item> diff --git a/lib/tools/doc/src/erlang_mode_chapter.xml b/lib/tools/doc/src/erlang_mode_chapter.xml index e07e7a8176..b4e30d883b 100644 --- a/lib/tools/doc/src/erlang_mode_chapter.xml +++ b/lib/tools/doc/src/erlang_mode_chapter.xml @@ -4,7 +4,7 @@ <chapter> <header> <copyright> - <year>2003</year><year>2013</year> + <year>2003</year><year>2016</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> diff --git a/lib/tools/doc/src/fprof.xml b/lib/tools/doc/src/fprof.xml index 2dfc77fdfc..4c9e48045e 100644 --- a/lib/tools/doc/src/fprof.xml +++ b/lib/tools/doc/src/fprof.xml @@ -4,7 +4,7 @@ <erlref> <header> <copyright> - <year>2001</year><year>2013</year> + <year>2001</year><year>2016</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> diff --git a/lib/tools/doc/src/fprof_chapter.xml b/lib/tools/doc/src/fprof_chapter.xml index ecd8f385a5..5a2a5ad47c 100644 --- a/lib/tools/doc/src/fprof_chapter.xml +++ b/lib/tools/doc/src/fprof_chapter.xml @@ -4,7 +4,7 @@ <chapter> <header> <copyright> - <year>2001</year><year>2013</year> + <year>2001</year><year>2016</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> diff --git a/lib/tools/doc/src/instrument.xml b/lib/tools/doc/src/instrument.xml index 76583cd03b..bb6f9b6100 100644 --- a/lib/tools/doc/src/instrument.xml +++ b/lib/tools/doc/src/instrument.xml @@ -4,7 +4,7 @@ <erlref> <header> <copyright> - <year>1998</year><year>2013</year> + <year>1998</year><year>2016</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> diff --git a/lib/tools/doc/src/lcnt.xml b/lib/tools/doc/src/lcnt.xml index c381488f85..9c8ce148e9 100644 --- a/lib/tools/doc/src/lcnt.xml +++ b/lib/tools/doc/src/lcnt.xml @@ -5,7 +5,7 @@ <header> <copyright> <year>2009</year> - <year>2013</year> + <year>2016</year> <holder>Ericsson AB, All Rights Reserved</holder> </copyright> <legalnotice> diff --git a/lib/tools/doc/src/lcnt_chapter.xml b/lib/tools/doc/src/lcnt_chapter.xml index 060559c954..6cfdb5cf1b 100644 --- a/lib/tools/doc/src/lcnt_chapter.xml +++ b/lib/tools/doc/src/lcnt_chapter.xml @@ -4,7 +4,7 @@ <chapter> <header> <copyright> - <year>2009</year><year>2013</year> + <year>2009</year><year>2016</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> diff --git a/lib/tools/doc/src/make.xml b/lib/tools/doc/src/make.xml index 5c2e5e5d62..fddf5ebd7b 100644 --- a/lib/tools/doc/src/make.xml +++ b/lib/tools/doc/src/make.xml @@ -5,7 +5,7 @@ <header> <copyright> <year>1996</year> - <year>2013</year> + <year>2016</year> <holder>Ericsson AB, All Rights Reserved</holder> </copyright> <legalnotice> diff --git a/lib/tools/doc/src/notes.xml b/lib/tools/doc/src/notes.xml index c62b0607ee..3a6ac37eef 100644 --- a/lib/tools/doc/src/notes.xml +++ b/lib/tools/doc/src/notes.xml @@ -4,7 +4,7 @@ <chapter> <header> <copyright> - <year>2004</year><year>2013</year> + <year>2004</year><year>2016</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> diff --git a/lib/tools/doc/src/notes_history.xml b/lib/tools/doc/src/notes_history.xml index d19aac4d4e..d955cbde69 100644 --- a/lib/tools/doc/src/notes_history.xml +++ b/lib/tools/doc/src/notes_history.xml @@ -4,7 +4,7 @@ <chapter> <header> <copyright> - <year>2006</year><year>2013</year> + <year>2006</year><year>2016</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> diff --git a/lib/tools/doc/src/part.xml b/lib/tools/doc/src/part.xml index b96586041a..796047fe8d 100644 --- a/lib/tools/doc/src/part.xml +++ b/lib/tools/doc/src/part.xml @@ -4,7 +4,7 @@ <part xmlns:xi="http://www.w3.org/2001/XInclude"> <header> <copyright> - <year>1996</year><year>2013</year> + <year>1996</year><year>2016</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> diff --git a/lib/tools/doc/src/part_notes.xml b/lib/tools/doc/src/part_notes.xml index c990e973a2..c4c6fa4d7d 100644 --- a/lib/tools/doc/src/part_notes.xml +++ b/lib/tools/doc/src/part_notes.xml @@ -4,7 +4,7 @@ <part xmlns:xi="http://www.w3.org/2001/XInclude"> <header> <copyright> - <year>2004</year><year>2013</year> + <year>2004</year><year>2016</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> diff --git a/lib/tools/doc/src/part_notes_history.xml b/lib/tools/doc/src/part_notes_history.xml index dd9c27e872..a34e35fc56 100644 --- a/lib/tools/doc/src/part_notes_history.xml +++ b/lib/tools/doc/src/part_notes_history.xml @@ -5,7 +5,7 @@ <header> <copyright> <year>2006</year> - <year>2013</year> + <year>2016</year> <holder>Ericsson AB, All Rights Reserved</holder> </copyright> <legalnotice> diff --git a/lib/tools/doc/src/ref_man.xml b/lib/tools/doc/src/ref_man.xml index 2d9ca7660a..d2131e7a93 100644 --- a/lib/tools/doc/src/ref_man.xml +++ b/lib/tools/doc/src/ref_man.xml @@ -4,7 +4,7 @@ <application xmlns:xi="http://www.w3.org/2001/XInclude"> <header> <copyright> - <year>1996</year><year>2013</year> + <year>1996</year><year>2016</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> diff --git a/lib/tools/doc/src/tags.xml b/lib/tools/doc/src/tags.xml index b089f0674b..ea0ae5cc4d 100644 --- a/lib/tools/doc/src/tags.xml +++ b/lib/tools/doc/src/tags.xml @@ -5,7 +5,7 @@ <header> <copyright> <year>1998</year> - <year>2013</year> + <year>2016</year> <holder>Ericsson AB, All Rights Reserved</holder> </copyright> <legalnotice> diff --git a/lib/tools/doc/src/xref.xml b/lib/tools/doc/src/xref.xml index ebf9139f06..8c49f3a206 100644 --- a/lib/tools/doc/src/xref.xml +++ b/lib/tools/doc/src/xref.xml @@ -4,7 +4,7 @@ <erlref> <header> <copyright> - <year>2000</year><year>2013</year> + <year>2000</year><year>2016</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> diff --git a/lib/tools/doc/src/xref_chapter.xml b/lib/tools/doc/src/xref_chapter.xml index e7186b9209..8b14e03064 100644 --- a/lib/tools/doc/src/xref_chapter.xml +++ b/lib/tools/doc/src/xref_chapter.xml @@ -4,7 +4,7 @@ <chapter> <header> <copyright> - <year>2000</year><year>2013</year> + <year>2000</year><year>2016</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> diff --git a/lib/tools/emacs/erlang-eunit.el b/lib/tools/emacs/erlang-eunit.el index a3c29c520c..3b85e6680a 100644 --- a/lib/tools/emacs/erlang-eunit.el +++ b/lib/tools/emacs/erlang-eunit.el @@ -1,7 +1,7 @@ ;; ;; %CopyrightBegin% ;; -;; Copyright Ericsson AB 2009-2010. All Rights Reserved. +;; Copyright Ericsson AB 2009-2016. All Rights Reserved. ;; ;; Licensed under the Apache License, Version 2.0 (the "License"); ;; you may not use this file except in compliance with the License. diff --git a/lib/tools/emacs/erlang-skels-old.el b/lib/tools/emacs/erlang-skels-old.el index c271cce3cb..4087bc3013 100644 --- a/lib/tools/emacs/erlang-skels-old.el +++ b/lib/tools/emacs/erlang-skels-old.el @@ -1,7 +1,7 @@ ;; ;; %CopyrightBegin% ;; -;; Copyright Ericsson AB 2010. All Rights Reserved. +;; Copyright Ericsson AB 2010-2016. All Rights Reserved. ;; ;; Licensed under the Apache License, Version 2.0 (the "License"); ;; you may not use this file except in compliance with the License. @@ -816,7 +816,7 @@ Please see the function `tempo-define-template'.") "%% Note: This directive should only be used in test suites." n "-compile(export_all)." n n - "-include_lib(\"test_server/include/test_server.hrl\")." n n + "-include_lib(\"common_test/include/ct.hrl\")." n n (erlang-skel-separator 2) "%% TEST SERVER CALLBACK FUNCTIONS" n diff --git a/lib/tools/emacs/erlang-skels.el b/lib/tools/emacs/erlang-skels.el index 6880ec733c..ce26c83295 100644 --- a/lib/tools/emacs/erlang-skels.el +++ b/lib/tools/emacs/erlang-skels.el @@ -1,7 +1,7 @@ ;; ;; %CopyrightBegin% ;; -;; Copyright Ericsson AB 2010-2014. All Rights Reserved. +;; Copyright Ericsson AB 2010-2016. All Rights Reserved. ;; ;; Licensed under the Apache License, Version 2.0 (the "License"); ;; you may not use this file except in compliance with the License. @@ -56,6 +56,8 @@ erlang-skel-gen-event erlang-skel-header) ("gen_fsm" "gen-fsm" erlang-skel-gen-fsm erlang-skel-header) + ("gen_statem" "gen-statem" + erlang-skel-gen-statem erlang-skel-header) ("wx_object" "wx-object" erlang-skel-wx-object erlang-skel-header) ("Library module" "gen-lib" @@ -858,6 +860,122 @@ Please see the function `tempo-define-template'.") "*The template of a gen_fsm. Please see the function `tempo-define-template'.") +(defvar erlang-skel-gen-statem + '((erlang-skel-include erlang-skel-large-header) + "-behaviour(gen_statem)." n n + + "%% API" n + "-export([start_link/0])." n + n + "%% gen_statem callbacks" n + "-export([init/1, terminate/3, code_change/4])." n + "-export([state_name/3])." n + "-export([handle_event/4])." n + n + "-define(SERVER, ?MODULE)." n + n + "-record(data, {})." n + n + (erlang-skel-double-separator-start 3) + "%%% API" n + (erlang-skel-double-separator-end 3) n + (erlang-skel-separator-start 2) + "%% @doc" n + "%% Creates a gen_statem process which calls Module:init/1 to" n + "%% initialize. To ensure a synchronized start-up procedure, this" n + "%% function does not return until Module:init/1 has returned." n + "%%" n + (erlang-skel-separator-end 2) + "-spec start_link() ->" n> + "{ok, Pid :: pid()} |" n> + "ignore |" n> + "{error, Error :: term()}." n + "start_link() ->" n> + "gen_statem:start_link({local, ?SERVER}, ?MODULE, [], [])." n + n + (erlang-skel-double-separator-start 3) + "%%% gen_statem callbacks" n + (erlang-skel-double-separator-end 3) n + (erlang-skel-separator-start 2) + "%% @private" n + "%% @doc" n + "%% Whenever a gen_statem is started using gen_statem:start/[3,4] or" n + "%% gen_statem:start_link/[3,4], this function is called by the new" n + "%% process to initialize." n + (erlang-skel-separator-end 2) + "-spec init(Args :: term()) -> " n> + "{gen_statem:callback_mode()," n> + "State :: term(), Data :: term()} |" n> + "{gen_statem:callback_mode()," n> + "State :: term(), Data :: term()," n> + "[gen_statem:action()] | gen_statem:action()} |" n> + "ignore |" n> + "{stop, Reason :: term()}." n + "init([]) ->" n> + "{state_functions, state_name, #data{}}." n + n + (erlang-skel-separator-start 2) + "%% @private" n + "%% @doc" n + "%% If the gen_statem runs with CallbackMode =:= state_functions" n + "%% there should be one instance of this function for each possible" n + "%% state name. Whenever a gen_statem receives an event," n + "%% the instance of this function with the same name" n + "%% as the current state name StateName is called to" n + "%% handle the event." n + (erlang-skel-separator-end 2) + "-spec state_name(" n> + "gen_statem:event_type(), Msg :: term()," n> + "Data :: term()) ->" n> + "gen_statem:state_function_result(). " n + "state_name({call,Caller}, _Msg, Data) ->" n> + "{next_state, state_name, Data, [{reply,Caller,ok}]}." n + n + (erlang-skel-separator-start 2) + "%% @private" n + "%% @doc" n + "%% If the gen_statem runs with CallbackMode =:= handle_event_function" n + "%% this function is called for every event a gen_statem receives." n + (erlang-skel-separator-end 2) + "-spec handle_event(" n> + "gen_statem:event_type(), Msg :: term()," n> + "State :: term(), Data :: term()) ->" n> + "gen_statem:handle_event_result(). " n + "handle_event({call,From}, _Msg, State, Data) ->" n> + "{next_state, State, Data, [{reply,From,ok}]}." n + n + (erlang-skel-separator-start 2) + "%% @private" n + "%% @doc" n + "%% This function is called by a gen_statem when it is about to" n + "%% terminate. It should be the opposite of Module:init/1 and do any" n + "%% necessary cleaning up. When it returns, the gen_statem terminates with" n + "%% Reason. The return value is ignored." n + (erlang-skel-separator-end 2) + "-spec terminate(Reason :: term(), State :: term(), Data :: term()) ->" n> + "any()." n + "terminate(_Reason, _State, _Data) ->" n> + "void." n + n + (erlang-skel-separator-start 2) + "%% @private" n + "%% @doc" n + "%% Convert process state when code is changed" n + (erlang-skel-separator-end 2) + "-spec code_change(" n> + "OldVsn :: term() | {down,term()}," n> + "State :: term(), Data :: term(), Extra :: term()) ->" n> + "{ok, NewState :: term(), NewData :: term()}." n + "code_change(_OldVsn, State, Data, _Extra) ->" n> + "{ok, State, Data}." n + n + (erlang-skel-double-separator-start 3) + "%%% Internal functions" n + (erlang-skel-double-separator-end 3) + ) + "*The template of a gen_statem. +Please see the function `tempo-define-template'.") + (defvar erlang-skel-wx-object '((erlang-skel-include erlang-skel-large-header) "-behaviour(wx_object)." n n @@ -1070,7 +1188,7 @@ Please see the function `tempo-define-template'.") "%% Note: This directive should only be used in test suites." n "-compile(export_all)." n n - "-include_lib(\"test_server/include/test_server.hrl\")." n n + "-include_lib(\"common_test/include/ct.hrl\")." n n (erlang-skel-separator-start 2) "%% TEST SERVER CALLBACK FUNCTIONS" n diff --git a/lib/tools/emacs/erlang.el b/lib/tools/emacs/erlang.el index 2972906dcb..aff2c4b2c9 100644 --- a/lib/tools/emacs/erlang.el +++ b/lib/tools/emacs/erlang.el @@ -897,6 +897,7 @@ resulting regexp is surrounded by \\_< and \\_>." "get_module_info" "get_stacktrace" "hash" + "has_prepared_code_on_load" "hibernate" "insert_element" "is_builtin" @@ -1354,7 +1355,7 @@ Lock syntax table. The effect is that `apply' in the atom (funcall (symbol-function 'interactive-p)))) ;;;###autoload -(defun erlang-mode () +(define-derived-mode erlang-mode prog-mode "Erlang" "Major mode for editing Erlang source files in Emacs. It knows about syntax and comment, it can indent code, it is capable of fontifying the source file, the TAGS commands are aware of Erlang @@ -1413,12 +1414,9 @@ and examples of hooks. Other commands: \\{erlang-mode-map}" - (interactive) - (kill-all-local-variables) - (setq major-mode 'erlang-mode) - (setq mode-name "Erlang") + ;; Use our own syntax table function + :syntax-table nil (erlang-syntax-table-init) - (use-local-map erlang-mode-map) (erlang-electric-init) (erlang-menu-init) (erlang-mode-variables) @@ -1433,10 +1431,7 @@ Other commands: (add-hook 'xref-backend-functions #'erlang-etags--xref-backend nil t)) (run-hooks 'erlang-mode-hook) (if (zerop (buffer-size)) - (run-hooks 'erlang-new-file-hook)) - ;; Doesn't exist in Emacs v21.4; required by Emacs v23. - (if (boundp 'after-change-major-mode-hook) - (run-hooks 'after-change-major-mode-hook))) + (run-hooks 'erlang-new-file-hook))) ;;;###autoload (dolist (r '("\\.erl$" "\\.app\\.src$" "\\.escript" @@ -2992,8 +2987,9 @@ Return nil if inside string, t if in a comment." (current-column))) ;; Type and Spec indentation ((eq (car stack-top) '::) - (if (looking-at "}") - ;; Closing record definition with types + (if (looking-at "[},)]") + ;; Closing function spec, record definition with types, + ;; or a comma at the start of the line ;; pop stack and recurse (erlang-calculate-stack-indent indent-point (cons (erlang-pop stack) (cdr state))) diff --git a/lib/tools/emacs/test.erl.indented b/lib/tools/emacs/test.erl.indented index 1986acadf1..7a1ff6a954 100644 --- a/lib/tools/emacs/test.erl.indented +++ b/lib/tools/emacs/test.erl.indented @@ -2,7 +2,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2009-2012. All Rights Reserved. +%% Copyright Ericsson AB 2009-2016. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -70,6 +70,9 @@ foo() -> 234, d}). +-record(record5, { a = 1 :: integer() + , b = foobar :: atom() + }). -define(MACRO_1, macro). -define(MACRO_2(_), macro). @@ -144,6 +147,12 @@ foo() -> -type t25() :: #rec3{f123 :: [t24() | 1|2|3|4|a|b|c|d| nonempty_maybe_improper_list(integer, any())]}. +-type t26() :: #rec4{ a :: integer() + , b :: any() + }. +-type t27() :: { integer() + , atom() + }. -type t99() :: {t2(),t4(),t5(),t6(),t7(),t8(),t10(),t14(), t15(),t20(),t21(), t22(),t25()}. @@ -179,6 +188,10 @@ foo() -> | {'error', {'no_process', term()} | {'no_such_group', term()}}. +-spec add( X :: integer() + , Y :: integer() + ) -> integer(). + -opaque attributes_data() :: [{'column', column()} | {'line', info_line()} | {'text', string()}] | {line(),column()}. diff --git a/lib/tools/emacs/test.erl.orig b/lib/tools/emacs/test.erl.orig index 7e8ad23412..2552c71baf 100644 --- a/lib/tools/emacs/test.erl.orig +++ b/lib/tools/emacs/test.erl.orig @@ -2,7 +2,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2009-2012. All Rights Reserved. +%% Copyright Ericsson AB 2009-2016. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -70,6 +70,9 @@ foo() -> 234, d}). +-record(record5, { a = 1 :: integer() +, b = foobar :: atom() +}). -define(MACRO_1, macro). -define(MACRO_2(_), macro). @@ -144,6 +147,12 @@ nonempty_maybe_improper_list('integer', any())| -type t25() :: #rec3{f123 :: [t24() | 1|2|3|4|a|b|c|d| nonempty_maybe_improper_list(integer, any())]}. +-type t26() :: #rec4{ a :: integer() +, b :: any() +}. +-type t27() :: { integer() +, atom() +}. -type t99() :: {t2(),t4(),t5(),t6(),t7(),t8(),t10(),t14(), t15(),t20(),t21(), t22(),t25()}. @@ -179,6 +188,10 @@ t15(),t20(),t21(), t22(),t25()}. | {'error', {'no_process', term()} | {'no_such_group', term()}}. +-spec add( X :: integer() +, Y :: integer() +) -> integer(). + -opaque attributes_data() :: [{'column', column()} | {'line', info_line()} | {'text', string()}] | {line(),column()}. diff --git a/lib/tools/priv/.gitignore b/lib/tools/priv/.gitignore new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/lib/tools/priv/.gitignore diff --git a/lib/tools/priv/Makefile b/lib/tools/priv/Makefile deleted file mode 100644 index aa4aaa2fc8..0000000000 --- a/lib/tools/priv/Makefile +++ /dev/null @@ -1,69 +0,0 @@ -# ``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 -# -# 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. -# -# The Initial Developer of the Original Code is Ericsson Utvecklings AB. -# Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings -# AB. All Rights Reserved.'' -# -# $Id$ -# -include $(ERL_TOP)/make/target.mk -include $(ERL_TOP)/make/$(TARGET)/otp.mk - -# ---------------------------------------------------- -# Application version -# ---------------------------------------------------- -include ../vsn.mk -VSN = $(TOOLS_VSN) - -# ---------------------------------------------------- -# Release directory specification -# ---------------------------------------------------- -RELSYSDIR = $(RELEASE_PATH)/lib/tools-$(VSN) - -# ---------------------------------------------------- -# Target Specs -# ---------------------------------------------------- - -HTDOCS_FILES = index.html - -TOOL_FILES = cover.tool - -# ---------------------------------------------------- -# FLAGS -# ---------------------------------------------------- -ERL_COMPILE_FLAGS += - -# ---------------------------------------------------- -# Targets -# ---------------------------------------------------- - -debug opt: - -clean: - -docs: - -# ---------------------------------------------------- -# Release Target -# ---------------------------------------------------- -include $(ERL_TOP)/make/otp_release_targets.mk - -release_spec: opt - $(INSTALL_DIR) "$(RELSYSDIR)/priv" - $(INSTALL_DATA) $(HTDOCS_FILES) "$(RELSYSDIR)/priv" - $(INSTALL_DATA) $(TOOL_FILES) "$(RELSYSDIR)/priv" - -release_docs_spec: - - - diff --git a/lib/tools/priv/cover.tool b/lib/tools/priv/cover.tool deleted file mode 100644 index 9e72f89ff4..0000000000 --- a/lib/tools/priv/cover.tool +++ /dev/null @@ -1,2 +0,0 @@ -{version,"1.2"}. -[{config_func,{cover_web,configData,[]}}]. diff --git a/lib/tools/priv/index.html b/lib/tools/priv/index.html deleted file mode 100644 index 6b60ef5d0a..0000000000 --- a/lib/tools/priv/index.html +++ /dev/null @@ -1,10 +0,0 @@ -<HTML> -<HEAD> -<TITLE>Erlang webb tools </TITLE> -</HEAD> -<FRAMESET COLS="250,*"> -<FRAME NAME="menu" SRC="/webcover/erl/cover_web/menu_frame"> -<FRAME NAME="main" SRC="/webcover/erl/cover_web/compile_frame"> -</FRAMESET> -</HTML> - diff --git a/lib/tools/src/Makefile b/lib/tools/src/Makefile index 9fcfb79628..032bd612db 100644 --- a/lib/tools/src/Makefile +++ b/lib/tools/src/Makefile @@ -1,7 +1,7 @@ # # %CopyrightBegin% # -# Copyright Ericsson AB 1996-2013. All Rights Reserved. +# Copyright Ericsson AB 1996-2016. All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -37,7 +37,6 @@ RELSYSDIR = $(RELEASE_PATH)/lib/tools-$(VSN) MODULES= \ cover \ - cover_web \ eprof \ fprof \ cprof \ diff --git a/lib/tools/src/cover.erl b/lib/tools/src/cover.erl index d16ca7f406..92c10cc306 100644 --- a/lib/tools/src/cover.erl +++ b/lib/tools/src/cover.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2001-2015. All Rights Reserved. +%% Copyright Ericsson AB 2001-2016. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -20,9 +20,7 @@ -module(cover). %% -%% This module implements the Erlang coverage tool. The module named -%% cover_web implements a user interface for the coverage tool to run -%% under webtool. +%% This module implements the Erlang coverage tool. %% %% ARCHITECTURE %% The coverage tool consists of one process on each node involved in @@ -575,7 +573,7 @@ call(Request) -> Ref = erlang:monitor(process,?SERVER), receive {'DOWN', Ref, _Type, _Object, noproc} -> erlang:demonitor(Ref), - start(), + {ok,_} = start(), call(Request) after 0 -> ?SERVER ! {self(),Request}, @@ -591,7 +589,9 @@ call(Request) -> end. reply(From, Reply) -> - From ! {?SERVER,Reply}. + From ! {?SERVER,Reply}, + ok. + is_from(From) -> is_pid(From). @@ -617,9 +617,11 @@ remote_call(Node,Request) -> end. remote_reply(Proc,Reply) when is_pid(Proc) -> - Proc ! {?SERVER,Reply}; + Proc ! {?SERVER,Reply}, + ok; remote_reply(MainNode,Reply) -> - {?SERVER,MainNode} ! {?SERVER,Reply}. + {?SERVER,MainNode} ! {?SERVER,Reply}, + ok. %%%---------------------------------------------------------------------- %%% cover_server on main node @@ -629,14 +631,16 @@ init_main(Starter) -> register(?SERVER,self()), %% Having write concurrancy here gives a 40% performance boost %% when collect/1 is called. - ets:new(?COVER_TABLE, [set, public, named_table - ,{write_concurrency, true} - ]), - ets:new(?COVER_CLAUSE_TABLE, [set, public, named_table]), - ets:new(?BINARY_TABLE, [set, public, named_table]), - ets:new(?COLLECTION_TABLE, [set, public, named_table]), - ets:new(?COLLECTION_CLAUSE_TABLE, [set, public, named_table]), - net_kernel:monitor_nodes(true), + ?COVER_TABLE = ets:new(?COVER_TABLE, [set, public, named_table, + {write_concurrency, true}]), + ?COVER_CLAUSE_TABLE = ets:new(?COVER_CLAUSE_TABLE, [set, public, + named_table]), + ?BINARY_TABLE = ets:new(?BINARY_TABLE, [set, public, named_table]), + ?COLLECTION_TABLE = ets:new(?COLLECTION_TABLE, [set, public, + named_table]), + ?COLLECTION_CLAUSE_TABLE = ets:new(?COLLECTION_CLAUSE_TABLE, [set, public, + named_table]), + ok = net_kernel:monitor_nodes(true), Starter ! {?SERVER,started}, main_process_loop(#main_state{}). @@ -674,7 +678,7 @@ main_process_loop(State) -> Imported = do_import_to_table(Fd,File, State#main_state.imported), reply(From, ok), - file:close(Fd), + ok = file:close(Fd), main_process_loop(State#main_state{imported=Imported}); {error,Reason} -> reply(From, {error, {cant_open_file,File,Reason}}), @@ -872,11 +876,12 @@ main_process_loop(State) -> init_remote(Starter,MainNode) -> register(?SERVER,self()), - ets:new(?COVER_TABLE, [set, public, named_table - %% write_concurrency here makes otp_8270 break :( - %,{write_concurrency, true} - ]), - ets:new(?COVER_CLAUSE_TABLE, [set, public, named_table]), + %% write_concurrency here makes otp_8270 break :( + ?COVER_TABLE = ets:new(?COVER_TABLE, [set, public, named_table + %,{write_concurrency, true} + ]), + ?COVER_CLAUSE_TABLE = ets:new(?COVER_CLAUSE_TABLE, [set, public, + named_table]), Starter ! {self(),started}, remote_process_loop(#remote_state{main_node=MainNode}). @@ -909,11 +914,11 @@ remote_process_loop(State) -> '_' -> [M || {M,_} <- State#remote_state.compiled]; _ -> Modules0 end, - spawn(fun() -> - ?SPAWN_DBG(remote_collect, - {Modules, CollectorPid, From}), - do_collect(Modules, CollectorPid, From) - end), + spawn(fun() -> + ?SPAWN_DBG(remote_collect, + {Modules, CollectorPid, From}), + do_collect(Modules, CollectorPid, From) + end), remote_process_loop(State); {remote,stop} -> @@ -954,13 +959,13 @@ remote_process_loop(State) -> end. do_collect(Modules, CollectorPid, From) -> - pmap( - fun(Module) -> - Pattern = {#bump{module=Module, _='_'}, '$1'}, - MatchSpec = [{Pattern,[{'=/=','$1',0}],['$_']}], - Match = ets:select(?COVER_TABLE,MatchSpec,?CHUNK_SIZE), - send_chunks(Match, CollectorPid, []) - end,Modules), + _ = pmap( + fun(Module) -> + Pattern = {#bump{module=Module, _='_'}, '$1'}, + MatchSpec = [{Pattern,[{'=/=','$1',0}],['$_']}], + Match = ets:select(?COVER_TABLE,MatchSpec,?CHUNK_SIZE), + send_chunks(Match, CollectorPid, []) + end,Modules), CollectorPid ! done, remote_reply(From, ok). @@ -996,20 +1001,20 @@ get_downs(Mons) -> end. reload_originals(Compiled) -> - Modules = [M || {M,_} <- Compiled], - pmap(fun do_reload_original/1, Modules). + _ = pmap(fun do_reload_original/1, [M || {M,_} <- Compiled]), + ok. do_reload_original(Module) -> case code:which(Module) of ?TAG -> - code:purge(Module), % remove code marked as 'old' - code:delete(Module), % mark cover compiled code as 'old' + _ = code:purge(Module), % remove code marked as 'old' + _ = code:delete(Module), % mark cover compiled code as 'old' %% Note: original beam code must be loaded before the cover %% compiled code is purged, in order to for references to %% 'fun M:F/A' and %% 'fun F/A' funs to be correct (they %% refer to (M:)F/A in the *latest* version of the module) - code:load_file(Module), % load original code - code:purge(Module); % remove cover compiled code + _ = code:load_file(Module), % load original code + _ = code:purge(Module); % remove cover compiled code _ -> ignore end. @@ -1221,12 +1226,13 @@ remote_reset(Module,Nodes) -> %% Collect data from remote nodes - used for analyse or stop(Node) remote_collect(Modules,Nodes,Stop) -> - pmap(fun(Node) -> - ?SPAWN_DBG(remote_collect, - {Modules, Nodes, Stop}), - do_collection(Node, Modules, Stop) - end, - Nodes). + _ = pmap( + fun(Node) -> + ?SPAWN_DBG(remote_collect, + {Modules, Nodes, Stop}), + do_collection(Node, Modules, Stop) + end, Nodes), + ok. do_collection(Node, Module, Stop) -> CollectorPid = spawn(fun collector_proc/0), @@ -1262,8 +1268,8 @@ insert_in_collection_table([]) -> insert_in_collection_table(Key,Val) -> case ets:member(?COLLECTION_TABLE,Key) of true -> - ets:update_counter(?COLLECTION_TABLE, - Key,Val); + _ = ets:update_counter(?COLLECTION_TABLE, Key,Val), + ok; false -> %% Make sure that there are no race conditions from ets:member case ets:insert_new(?COLLECTION_TABLE,{Key,Val}) of @@ -2004,9 +2010,7 @@ munge_expr({lc,Line,Expr,Qs}, Vars) -> {MungedQs, Vars3} = munge_qualifiers(Qs, Vars2), {{lc,Line,MungedExpr,MungedQs}, Vars3}; munge_expr({bc,Line,Expr,Qs}, Vars) -> - {bin,BLine,[{bin_element,EL,Val,Sz,TSL}|Es]} = Expr, - Expr2 = {bin,BLine,[{bin_element,EL,Val,Sz,TSL}|Es]}, - {MungedExpr,Vars2} = munge_expr(Expr2, Vars), + {MungedExpr,Vars2} = munge_expr(?BLOCK1(Expr), Vars), {MungedQs, Vars3} = munge_qualifiers(Qs, Vars2), {{bc,Line,MungedExpr,MungedQs}, Vars3}; munge_expr({block,Line,Body}, Vars) -> @@ -2425,7 +2429,7 @@ do_analyse_to_file1(Module, OutFile, ErlFile, HTML) -> "<body style='background-color: white;" " color: black'>\n" "<pre>\n"], - file:write(OutFd,Header); + ok = file:write(OutFd,Header); true -> ok end, @@ -2439,7 +2443,7 @@ do_analyse_to_file1(Module, OutFile, ErlFile, HTML) -> string:right(integer_to_list(H), 2, $0), string:right(integer_to_list(Mi), 2, $0), string:right(integer_to_list(S), 2, $0)]), - file:write(OutFd, + ok = file:write(OutFd, ["File generated from ",ErlFile," by COVER ", Timestamp,"\n\n" "**************************************" @@ -2451,14 +2455,13 @@ do_analyse_to_file1(Module, OutFile, ErlFile, HTML) -> CovLines = lists:keysort(1,ets:select(?COLLECTION_TABLE, MS)), print_lines(Module, CovLines, InFd, OutFd, 1, HTML), - if - HTML -> - file:write(OutFd, "</pre>\n</body>\n</html>\n"); + if HTML -> + ok = file:write(OutFd, "</pre>\n</body>\n</html>\n"); true -> ok end, - file:close(OutFd), - file:close(InFd), + ok = file:close(OutFd), + ok = file:close(InFd), {ok, OutFile}; @@ -2476,34 +2479,33 @@ print_lines(Module, CovLines, InFd, OutFd, L, HTML) -> eof -> ignore; {ok,"%"++_=Line} -> %Comment line - not executed. - file:write(OutFd, [tab(),escape_lt_and_gt(Line, HTML)]), + ok = file:write(OutFd, [tab(),escape_lt_and_gt(Line, HTML)]), print_lines(Module, CovLines, InFd, OutFd, L+1, HTML); {ok,RawLine} -> Line = escape_lt_and_gt(RawLine,HTML), case CovLines of [{L,N}|CovLines1] -> %% N = lists:foldl(fun([Ni], Nacc) -> Nacc+Ni end, 0, Ns), - if - N=:=0, HTML=:=true -> - LineNoNL = Line -- "\n", - Str = " 0", - %%Str = string:right("0", 6, 32), - RedLine = ["<font color=red>",Str,fill1(), - LineNoNL,"</font>\n"], - file:write(OutFd, RedLine); - N<1000000 -> - Str = string:right(integer_to_list(N), 6, 32), - file:write(OutFd, [Str,fill1(),Line]); - N<10000000 -> - Str = integer_to_list(N), - file:write(OutFd, [Str,fill2(),Line]); - true -> - Str = integer_to_list(N), - file:write(OutFd, [Str,fill3(),Line]) - end, + if N=:=0, HTML=:=true -> + LineNoNL = Line -- "\n", + Str = " 0", + %%Str = string:right("0", 6, 32), + RedLine = ["<font color=red>",Str,fill1(), + LineNoNL,"</font>\n"], + ok = file:write(OutFd, RedLine); + N < 1000000 -> + Str = string:right(integer_to_list(N), 6, 32), + ok = file:write(OutFd, [Str,fill1(),Line]); + N < 10000000 -> + Str = integer_to_list(N), + ok = file:write(OutFd, [Str,fill2(),Line]); + true -> + Str = integer_to_list(N), + ok = file:write(OutFd, [Str,fill3(),Line]) + end, print_lines(Module, CovLines1, InFd, OutFd, L+1, HTML); _ -> - file:write(OutFd, [tab(),Line]), + ok = file:write(OutFd, [tab(),Line]), print_lines(Module, CovLines, InFd, OutFd, L+1, HTML) end end. @@ -2543,7 +2545,7 @@ do_export(Module, OutFile, From, State) -> {error,{not_cover_compiled,Module}} end end, - file:close(Fd), + ok = file:close(Fd), reply(From, Reply); {error,Reason} -> reply(From, {error, {cant_open_file,OutFile,Reason}}) @@ -2585,10 +2587,9 @@ write(Element,Fd) -> case byte_size(Bin) of Size when Size > 255 -> SizeBin = term_to_binary({'$size',Size}), - file:write(Fd, - <<(byte_size(SizeBin)):8,SizeBin/binary,Bin/binary>>); + ok = file:write(Fd, <<(byte_size(SizeBin)):8,SizeBin/binary,Bin/binary>>); Size -> - file:write(Fd,<<Size:8,Bin/binary>>) + ok = file:write(Fd,<<Size:8,Bin/binary>>) end, ok. diff --git a/lib/tools/src/cover_web.erl b/lib/tools/src/cover_web.erl deleted file mode 100644 index ae8b3f25cf..0000000000 --- a/lib/tools/src/cover_web.erl +++ /dev/null @@ -1,1185 +0,0 @@ -%% -%% %CopyrightBegin% -%% -%% Copyright Ericsson AB 2001-2009. All Rights Reserved. -%% -%% 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 -%% -%% 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% -%% - --module(cover_web). --author('[email protected]'). --behaviour(gen_server). - -%%Export of configuration function --export([configData/0]). -%% External exports --export([init/1, handle_call/3, handle_cast/2, handle_info/2, - terminate/2, code_change/3]). - --export([start_link/0,start/0,stop/0]). --export([menu_frame/2,nodes_frame/2,import_frame/2, - compile_frame/2,result_frame/2]). --export([list_dir/2,compile/2,add_node/2,remove_node/2,result/2, - calls/2,coverage/2,import/2]). - --record(state,{dir}). - --include_lib("kernel/include/file.hrl"). - -%% Timeouts --define(DEFAULT_TIME,10000). --define(MAX_COMPILE_TIME,60000). --define(MAX_ANALYSE_TIME,30000). - -%% Colors --define(INFO_BG_COLOR,"#C0C0EA"). - -%%%---------------------------------------------------------------------- -%%% API - called from erlang shell -%%%---------------------------------------------------------------------- -%% Start webtool and webcover from erlang shell -start() -> - webtool:start(), - webtool:start_tools([],"app=webcover"), - ok. - -%% Stop webtool and webcover from erlang shell -stop() -> - webtool:stop_tools([],"app=webcover"), - webtool:stop(). - - - -%%%---------------------------------------------------------------------- -%%% API - called from webtool -%%%---------------------------------------------------------------------- -start_link() -> - gen_server:start_link({local, webcover_server},cover_web, [], []). - - -nodes_frame(Env,Input)-> - call({nodes_frame,Env,Input}). - -add_node(Env,Input)-> - call({add_node,Env,Input}). - -remove_node(Env,Input)-> - call({remove_node,Env,Input}). - -compile_frame(Env,Input)-> - call({compile_frame,Env,Input}). - -list_dir(Env,Input) -> - call({list_dir,Env,Input}). - -compile(Env,Input)-> - call({compile,Env,Input},?MAX_COMPILE_TIME). - -result_frame(Env,Input)-> - call({result_frame,Env,Input}). - -result(Env,Input) -> - call({result,Env,Input},?MAX_ANALYSE_TIME). - -calls(Env,Input) -> - call({calls,Env,Input}). - -coverage(Env,Input) -> - call({coverage,Env,Input}). - -import_frame(Env,Input)-> - call({import_frame,Env,Input}). - -import(Env,Input)-> - call({import,Env,Input}). - -menu_frame(Env,Input)-> - call({menu_frame,Env,Input}). - -call(Msg) -> - call(Msg,?DEFAULT_TIME). -call(Msg,Time) -> - gen_server:call(webcover_server,Msg,Time). - - - -configData()-> - {webcover,[{web_data,{"WebCover","/webcover"}}, - {alias,{"/webcover",code:priv_dir(tools)}}, - {alias,{erl_alias,"/webcover/erl",[cover_web]}}, - {start,{child,{{local,webcover_server}, - {cover_web,start_link,[]}, - permanent,100,worker,[cover_web]}}} - ]}. - - -%%%---------------------------------------------------------------------- -%%% Callback functions from gen_server -%%%---------------------------------------------------------------------- - -%%---------------------------------------------------------------------- -%% Func: init/1 -%% Returns: {ok, State} | -%% {ok, State, Timeout} | -%% ignore | -%% {stop, Reason} -%%---------------------------------------------------------------------- -init([]) -> - cover:start(), - CS = whereis(cover_server), - link(CS), - GL = spawn_link(fun group_leader_proc/0), - group_leader(GL,CS), - - %% Must trap exists in order to have terminate/2 executed when - %% crashing because of a linked process crash. - process_flag(trap_exit,true), - {ok,Cwd} = file:get_cwd(), - {ok, #state{dir=Cwd}}. - -group_leader_proc() -> - register(cover_group_leader_proc,self()), - group_leader_loop([]). -group_leader_loop(Warnings) -> - receive - {io_request,From,ReplyAs,{put_chars,io_lib,Func,[Format,Args]}} -> - Msg = (catch io_lib:Func(Format,Args)), - From ! {io_reply,ReplyAs,ok}, - case lists:member(Msg,Warnings) of - true -> group_leader_loop(Warnings); - false -> group_leader_loop([Msg|Warnings]) - end; - {io_request,From,ReplyAs,{put_chars,_Encoding,io_lib,Func,[Format,Args]}} -> - Msg = (catch io_lib:Func(Format,Args)), - From ! {io_reply,ReplyAs,ok}, - case lists:member(Msg,Warnings) of - true -> group_leader_loop(Warnings); - false -> group_leader_loop([Msg|Warnings]) - end; - IoReq when element(1,IoReq)=:= io_request -> - group_leader() ! IoReq, - group_leader_loop(Warnings); - {From,get_warnings} -> - Warnings1 = - receive - {io_request,From,ReplyAs, - {put_chars,io_lib,Func,[Format,Args]}} -> - Msg = (catch io_lib:Func(Format,Args)), - From ! {io_reply,ReplyAs,ok}, - case lists:member(Msg,Warnings) of - true -> Warnings; - false -> [Msg|Warnings] - end - after 0 -> - Warnings - end, - From ! {warnings,Warnings1}, - group_leader_loop([]) - end. - -%%---------------------------------------------------------------------- -%% Func: handle_call/3 -%% Returns: {reply, Reply, State} | -%% {reply, Reply, State, Timeout} | -%% {noreply, State} | -%% {noreply, State, Timeout} | -%% {stop, Reason, Reply, State} | (terminate/2 is called) -%% {stop, Reason, State} (terminate/2 is called) -%%---------------------------------------------------------------------- -handle_call({nodes_frame,_Env,_Input},_From,State)-> - {reply,nodes_frame1(),State}; - -handle_call({add_node,_Env,Input},_From,State)-> - {reply,do_add_node(Input),State}; - -handle_call({remove_node,_Env,Input},_From,State)-> - {reply,do_remove_node(Input),State}; - -handle_call({compile_frame,_Env,_Input},_From,State)-> - {reply,compile_frame1(State#state.dir),State}; - -handle_call({list_dir,_Env,Input},_From,State)-> - Dir = get_input_data(Input,"path"), - case filelib:is_dir(Dir) of - true -> - {reply,compile_frame1(Dir),State#state{dir=Dir}}; - false -> - Err = Dir ++ " is not a directory", - {reply,compile_frame1(State#state.dir,Err),State} - end; -handle_call({compile,_Env,Input},_From,State)-> - {reply,do_compile(Input,State#state.dir),State}; - -handle_call({result_frame,_Env,_Input},_From,State)-> - {reply,result_frame1(),State}; - -handle_call({result,_Env,Input},_From,State)-> - {reply,handle_result(Input),State}; - -handle_call({calls,_Env,Input},_From,State)-> - {reply,call_page(Input),State}; - -handle_call({coverage,_Env,Input},_From,State)-> - {reply,coverage_page(Input),State}; - -handle_call({import_frame,_Env,_Input},_From,State)-> - {ok,Cwd} = file:get_cwd(), - {reply,import_frame1(Cwd),State}; - -handle_call({import,_Env,Input},_From,State)-> - {reply,do_import(Input),State}; - -handle_call({menu_frame,_Env,_Input},_From,State)-> - {reply,menu_frame1(),State}; - -handle_call(_Request, _From, State) -> - Reply = bad_request, - {reply, Reply, State}. - - -%%---------------------------------------------------------------------- -%% Func: handle_cast/2 -%% Returns: {noreply, State} | -%% {noreply, State, Timeout} | -%% {stop, Reason, State} (terminate/2 is called) -%%---------------------------------------------------------------------- -handle_cast(_Msg, State) -> - {noreply, State}. - -%%---------------------------------------------------------------------- -%% Func: handle_info/2 -%% Returns: {noreply, State} | -%% {noreply, State, Timeout} | -%% {stop, Reason, State} (terminate/2 is called) -%%---------------------------------------------------------------------- -handle_info({'EXIT',_Pid,Reason}, State) -> - {stop, Reason, State}. - -%%---------------------------------------------------------------------- -%% Func: terminate/2 -%% Purpose: Shutdown the server -%% Returns: any (ignored by gen_server) -%%---------------------------------------------------------------------- -terminate(_Reason, _State) -> - cover:stop(), - ok. - -%%-------------------------------------------------------------------- -%% Func: code_change/3 -%% Purpose: Convert process state when code is changed -%% Returns: {ok, NewState} -%%-------------------------------------------------------------------- -code_change(_OldVsn, State, _Extra) -> - {ok, State}. - -%%%---------------------------------------------------------------------- -%%% Internal functions -%%%---------------------------------------------------------------------- - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% %% -%% The functions that creates the whole pages by collecting all the %% -%% neccessary data for each page. These functions are the public %% -%% interface. %% -%% %% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%---------------------------------------------------------------------- -%% Returns the page to the left frame -%%---------------------------------------------------------------------- -menu_frame1()-> - [header(),html_header(""),menu_body(),html_end()]. - -%%---------------------------------------------------------------------- -%% Creates the page where the user can add and remove nodes -%%---------------------------------------------------------------------- - -nodes_frame1()-> - nodes_frame1([]). -nodes_frame1(Err)-> - [header(),html_header("Add/remove nodes"),nodes_body(Err),html_end()]. - -%%---------------------------------------------------------------------- -%% Creates the page where the user can cover compile modules -%%---------------------------------------------------------------------- - -compile_frame1(Dir)-> - compile_frame1(Dir,[]). -compile_frame1(Dir,Err) -> - [header(),html_header("Cover compile"),compile_body(Dir,Err),html_end()]. - -%%---------------------------------------------------------------------- -%% Creates the page where the user can handle results -%%---------------------------------------------------------------------- - -result_frame1()-> - result_frame1([]). -result_frame1(Err) -> - [header(),html_header("Show cover results"),result_body(Err),html_end()]. - -%%---------------------------------------------------------------------- -%%The beginning of the page that clear the cover information on a cover -%%compiled module -%%---------------------------------------------------------------------- -call_page(Input)-> - [header(),html_header("Code coverage"),call_result(Input),html_end()]. - -coverage_page(Input)-> - [header(),html_header("Code coverage"),coverage_result(Input),html_end()]. - -%%---------------------------------------------------------------------- -%% Creates the page where the user an import files -%%---------------------------------------------------------------------- -import_frame1(Dir) -> - import_frame1(Dir,""). -import_frame1(Dir,Err) -> - [header(),html_header("Import coverdata"),import_body(Dir,Err),html_end()]. - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% %% -%% The functions that build the body of the menu frame %% -%% %% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -menu_body() -> - Nodes = cover:which_nodes(), - Modules = cover:modules(), - Imported = cover:imported(), - ["<A HREF=\"./nodes_frame\" TARGET=\"main\">Nodes</A><BR>\n", - "<A HREF=\"./compile_frame\" TARGET=\"main\">Compile</A><BR>\n", - "<A HREF=\"./import_frame\" TARGET=\"main\">Import</A><BR>\n", - "<A HREF=\"./result_frame\" TARGET=\"main\">Result</A>\n", - "<P><B>Nodes:</B>\n", - "<UL>\n", - lists:map(fun(N) -> "<LI>"++atom_to_list(N)++"</LI>\n" end,[node()|Nodes]), - "</UL>\n", - "<P><B>Compiled modules:</B>\n", - "<UL>\n", - lists:map(fun(M) -> "<LI>"++atom_to_list(M)++"</LI>\n" end,Modules), - "</UL>\n", - "<P><B>Imported files:</B>\n", - "<UL>\n", - "<FONT SIZE=-1>\n", - lists:map(fun(F) -> - Short = filename:basename(F), - "<LI TITLE=\""++F++"\">"++Short++"</LI>\n" end,Imported), - "</FONT>\n", - "</UL>\n"]. - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% %% -%% The functions that build the body of the nodes frame %% -%% %% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -nodes_body(Err) -> - CN = cover:which_nodes(), - Fun = fun(N) -> - NStr = atom_to_list(N), - ["<OPTION VALUE=",NStr, - " onClick=\"node.value=selected_node.value\">",NStr, - "</OPTION>\n"] - end, - AllNodes = lists:append(lists:map(Fun,nodes()--CN)), - CoverNodes = lists:append(lists:map(Fun,CN)), - - [reload_menu_script(Err), - "<H1 ALIGN=center>Nodes</H1>\n", - "<TABLE BORDER=0 WIDTH=600 ALIGN=center>\n", - "<TR><TD BGCOLOR=",?INFO_BG_COLOR," COLSPAN=2>\n", - "<P>You can run cover over several nodes simultaneously. Coverage data\n", - "from all involved nodes will be merged during analysis.\n", - "<P>Select or enter node names to add or remove here.\n", - "</TD></TR>\n", - "<TR><TD COLSPAN=2><BR><BR></TD></TR>\n", - "<FORM ACTION=\"./add_node\" NAME=add_node>\n", - "<TR><TD VALIGN=top>Add node:</TD>\n", - "<TD><INPUT TYPE=text NAME=\"node\" SIZE=40 >", - "<INPUT TYPE=submit\n", - " onClick=\"if(!node.value){node.value=selected_node.value};\" VALUE=Add>" - "<BR><SELECT NAME=selected_node TITLE=\"Select node\">\n", - AllNodes ++ - "</SELECT>\n", - "</TD></TR>\n" - "</FORM>\n", - "<TR><TD COLSPAN=2><BR><BR></TD></TR>\n", - "<FORM ACTION=\"./remove_node\" NAME=remove_node>\n", - "<TR><TD>Remove node:</TD>\n", - "<TD><SELECT NAME=node TITLE=\"Select node\">\n", - CoverNodes ++ - "</SELECT>\n", - "<INPUT TYPE=submit VALUE=Remove>" - "</TD></TR>\n", - "</FORM>", - "</TABLE>"]. - - -do_add_node(Input) -> - NodeStr = get_input_data(Input, "node"), - Node = list_to_atom(NodeStr), - case net_adm:ping(Node) of - pong -> - cover:start(Node), - nodes_frame1(); - pang -> - nodes_frame1("Node \\\'" ++ NodeStr ++ "\\\' is not alive") - end. - -do_remove_node(Input) -> - Node = list_to_atom(get_input_data(Input, "node")), - cover:stop(Node), - nodes_frame1(). - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% % -% The functions that is used when the user wants to compile something % -% % -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -compile_body(Dir,Err) -> - Erls = filelib:wildcard(filename:join(Dir,"*.erl")), - Beams = filelib:wildcard(filename:join(Dir,"*.beam")), - - [reload_menu_script(Err), - "<H1 ALIGN=center>Compile</H1>\n", - "<TABLE WIDTH=600 ALIGN=center BORDER=0>\n", - "<TR><TD COLSPAN=3 BGCOLOR=",?INFO_BG_COLOR,">\n", - "Each module which shall be part of the cover analysis must be prepared\n", - "or 'cover compiled'. On this page you can select .erl files and/or\n", - ".beam files to include in the analysis. If you select a .erl file it\n", - "will first be compiled with the Erlang compiler and then prepared for\n", - "coverage analysis. If you select a .beam file it will be prepared for\n", - "coverage analysis directly.\n", - "</TD></TR>\n", - "<FORM ACTION=\"./list_dir\" NAME=list_dir>\n", - "<TR><TD WIDTH=30% BGCOLOR=",?INFO_BG_COLOR," ROWSPAN=2>\n", - "To list a different directory, enter the directory name here.\n", - "</TD>\n", - "<TH COLSPAN=2><BR>List directory:<BR></TH>\n", - "</TR>\n", - "<TR><TD ALIGN=center COLSPAN=2>\n", - "<INPUT TYPE=text NAME=\"path\" SIZE=40 VALUE=",Dir,">", - "<INPUT TYPE=submit VALUE=Ok>", - "<BR><BR></TD></TR>\n", - "</FORM>\n", - "<FORM ACTION=\"./compile\" NAME=compile_selection>\n", - "<TR><TD BGCOLOR=",?INFO_BG_COLOR," ROWSPAN=2>\n", - "<P>Select one or more .erl or .beam files to prepare for coverage\n" - "analysis, and click the \"Compile\" button.\n", - "<P>To reload the original file after coverage analysis is complete,\n" - "select one or more files and click the \"Uncompile\" button, or\n", - "simply click the \"Uncompile all\" button to reload all originals.\n" - "</TD>\n", - "<TH>.erl files</TH><TH>.beam files</TH></TR>\n", - "<TR><TD ALIGN=center VALIGN=top>\n", - "<SELECT NAME=erl TITLE=\"Select .erl files to compile\" MULTIPLE=true", - " SIZE=15>\n", - list_modules(Erls) ++ - "</SELECT></TD>\n", - "<TD ALIGN=center VALIGN=top>\n", - "<SELECT NAME=beam TITLE=\"Select .beam files to compile\"MULTIPLE=true", - " SIZE=15>\n", - list_modules(Beams) ++ - "</SELECT></TD></TR>\n" - "<TR><TD BGCOLOR=",?INFO_BG_COLOR," ROWSPAN=2>\n", - "Compile options are only needed for .erl files. The options must be\n" - "given e.g. like this: \n" - "<FONT SIZE=-1>[{i,\"/my/path/include\"},{i,\"/other/path/\"}]</FONT>\n" - "</TD>\n", - "<TH COLSPAN=2><BR>Compile options:<BR></TH>\n", - "</TR>\n", - "<TR><TD COLSPAN=2 ALIGN=center>\n", - "<INPUT TYPE=text NAME=\"options\" SIZE=40>\n", - "<INPUT TYPE=hidden NAME=\"action\"></TD></TR>\n", - "<TR><TD></TD><TD ALIGN=center COLSPAN=2>\n", - "<INPUT TYPE=submit onClick=\"action.value=\'compile\';\"VALUE=Compile>", - "<INPUT TYPE=submit onClick=\"action.value=\'uncompile\';\" ", - "VALUE=Uncompile>", - "<INPUT TYPE=submit onClick=\"action.value=\'uncompile_all\';\" ", - "VALUE=\"Uncompile all\">", - "<BR><INPUT TYPE=reset VALUE=\"Reset form\"></TD></TR>\n", - "</FORM>\n", - "</TABLE>\n"]. - -list_modules([File|Files]) -> - Mod = filename:basename(File), - ["<OPTION VALUE=",File," onDblClick=\"action.value=\'compile\';submit();\">", - Mod,"</OPTION>\n" | list_modules(Files)]; -list_modules([]) -> - []. - -do_compile(Input,Dir) -> - {Erls,Beams,Opts,Action} = get_compile_input(parse(Input),[],[]), - Errs = - case Action of - "compile" -> - do_compile(Erls,Beams,Opts,[]); - "uncompile" -> - do_uncompile(Erls++Beams); - "uncompile_all" -> - do_uncompile(cover:modules()) - end, - compile_frame1(Dir,Errs). - -get_compile_input([{"erl",File}|Input],Erl,Beam) -> - get_compile_input(Input,[File|Erl],Beam); -get_compile_input([{"beam",File}|Input],Erl,Beam) -> - get_compile_input(Input,Erl,[File|Beam]); -get_compile_input([{"options",Opts0},{"action",Action}],Erl,Beam) -> - Opts = parse_options(Opts0), - {Erl,Beam,Opts,Action}. - -do_compile([Erl|Erls],Beams,Opts,Errs) -> - case cover:compile_module(Erl,Opts) of - {ok,_} -> - do_compile(Erls,Beams,Opts,Errs); - {error,File} -> - do_compile(Erls,Beams,Opts,["\\n"++File|Errs]) - end; -do_compile([],[Beam|Beams],Opts,Errs) -> - case cover:compile_beam(Beam) of - {ok,_} -> - do_compile([],Beams,Opts,Errs); - {error,{no_abstract_code,File}} -> - do_compile([],Beams,Opts,["\\n"++File++" (no_abstract_code)"|Errs]) - end; -do_compile([],[],_,[]) -> - []; -do_compile([],[],_,Errs) -> - "Compilation failed for the following files:" ++ Errs. - -parse_options(Options)-> - case erl_scan:string(Options ++".") of - {ok,Tokens,_Line} -> - case erl_parse:parse_exprs(Tokens) of - {ok,X}-> - case lists:map(fun erl_parse:normalise/1, X) of - [List] when is_list(List) -> List; - List -> List - end; - _ -> - [] - end; - _ -> - [] - end. - - -do_uncompile(Files) -> - lists:foreach( - fun(File) -> - Module = - if is_atom(File) -> - File; - true -> - ModStr = filename:basename(filename:rootname(File)), - list_to_atom(ModStr) - end, - case code:which(Module) of - cover_compiled -> - code:purge(Module), - case code:load_file(Module) of - {module, Module} -> - ok; - {error, _Reason2} -> - code:delete(Module) - end; - _ -> - ok - end - end, - Files), - []. - - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% % -% The functions that builds the body of the page for coverage analysis% -% % -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -result_body(Err) -> - [reload_menu_script(Err), - "<H1 ALIGN=center>Result</H1>\n", - "<TABLE BORDER=0 WIDTH=600 ALIGN=center>\n", - "<TR><TD BGCOLOR=",?INFO_BG_COLOR,">\n", - "<P>After executing all your tests you can view the result of the\n", - "coverage analysis here. For each module you can\n", - "<DL>\n", - "<DT><B>Analyse to file</B></DT>\n", - "<DD>The source code of the module is shown with the number of calls\n", - "to each line stated in the left margin. Lines which are never called\n", - "are colored red.</DD>\n", - "<DT><B>Analyse coverage</B></DT>\n", - "<DD>Show the number of covered and uncovered lines in the module.</DD>\n", - "<DT><B>Analyse calls</B></DT>\n", - "<DD>Show the number of calls in the module.</DD>\n", - "<DT><B>Reset module</B></DT>\n", - "<DD>Delete all coverage data for the module.</DD>\n", - "<DT><B>Export module</B></DT>\n", - "<DD>Write all coverage data for the module to a file. The data can\n", - "later be imported from the \"Import\" page.</DD>\n", - "</DL>\n", - "<P>You can also reset or export data for all modules with the\n", - "<B>Reset all</B> and <B>Export all</B> actions respectively. For these\n", - "two actions there is no need to select a module.\n", - "<P>Select module and action from the drop down menus below, and click\n", - "the \"Execute\" button.\n", - "</TD></TR>\n", - "<TR><TD><BR><BR>\n", - result_selections(), - "</TD></TR></TABLE>"]. - -result_selections() -> - ModList = filter_modlist(cover:modules()++cover:imported_modules(),[]), - - ["<FORM ACTION=\"./result\" NAME=result_selection>\n", - "<TABLE WIDTH=\"300\" BORDER=0 ALIGN=center>\n", - "<TR><TD ALIGN=left>\n", - "Module:\n", - "<BR><SELECT NAME=module TITLE=\"Select module\">\n", - ModList ++ - "</SELECT>\n", - "</TD>\n", - "<TD ALIGN=left>\n", - "Action:\n", - "<BR><SELECT NAME=action TITLE=\"Select action\">\n", - "<OPTION VALUE=\"analyse_to_file\">Analyse to file</OPTION>\n" - "<OPTION VALUE=\"coverage\">Analyse coverage</OPTION>\n" - "<OPTION VALUE=\"calls\">Analyse calls</OPTION>\n" - "<OPTION VALUE=\"reset\">Reset module</OPTION>\n" - "<OPTION VALUE=\"reset_all\">Reset all</OPTION>\n" - "<OPTION VALUE=\"export\">Export module</OPTION>\n" - "<OPTION VALUE=\"export_all\">Export all</OPTION>\n" - "</SELECT>\n", - "</TD>\n", - "<TD ALIGN=center VALIGN=bottom><INPUT TYPE=submit VALUE=Execute>\n" - "</TD></TR>\n" - "</TABLE>\n", - "</FORM>\n"]. - -filter_modlist([M|Ms],Already) -> - case lists:member(M,Already) of - true -> - filter_modlist(Ms,Already); - false -> - MStr = atom_to_list(M), - ["<OPTION VALUE=",MStr,">",MStr,"</OPTION>\n" | - filter_modlist(Ms,[M|Already])] - end; -filter_modlist([],_Already) -> - []. - - - -handle_result(Input) -> - case parse(Input) of - [{"module",M},{"action",A}] -> - case A of - "analyse_to_file" -> - case cover:analyse_to_file(list_to_atom(M),[html]) of - {ok,File} -> - case file:read_file(File) of - {ok,HTML}-> - file:delete(File), - [header(), - reload_menu_script(""), - binary_to_list(HTML)]; - _ -> - result_frame1("Can not read file" ++ File) - end; - {error,no_source_code_found} -> - result_frame1("No source code found for \\\'" ++ - M ++ "\\\'") - end; - "calls" -> - call_page(Input); - "coverage" -> - coverage_page(Input); - "reset" -> - cover:reset(list_to_atom(M)), - result_frame1("Coverage data for \\\'" ++ M ++ - "\\\' is now reset"); - "reset_all" -> - cover:reset(), - result_frame1("All coverage data is now reset"); - "export" -> - ExportFile = generate_filename(M), - cover:export(ExportFile,list_to_atom(M)), - result_frame1("Coverage data for \\\'" ++ M ++ - "\\\' is now exported to file \\\"" ++ - ExportFile ++ "\\\""); - "export_all" -> - ExportFile = generate_filename("COVER"), - cover:export(ExportFile), - result_frame1( - "All coverage data is now exported to file \\\"" ++ - ExportFile ++ "\\\"") - end; - [{"action",_A}] -> - result_frame1("No module is selected") - end. - -generate_filename(Prefix) -> - {ok,Cwd} = file:get_cwd(), - filename:join(Cwd,Prefix ++ "_" ++ ts() ++ ".coverdata"). - -ts() -> - {{Y,M,D},{H,Min,S}} = calendar:now_to_local_time(erlang:timestamp()), - io_lib:format("~4.4.0w~2.2.0w~2.2.0w-~2.2.0w~2.2.0w~2.2.0w", - [Y,M,D,H,Min,S]). - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% % -% The functions that builds the body of the page that shows the calls % -% % -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -call_result(Input)-> - Mod = list_to_atom(get_input_data(Input, "module")), - case cover:analyse(Mod,calls) of - {error,_}-> - error_body(); - {ok,_} -> - call_result2(Mod,Input) - end. - -call_result2(Mod,Input)-> - Result = - case get_input_data(Input,"what") of - "mod" -> - call_result(mod,Mod); - "func" -> - call_result(func,Mod); - "clause" -> - call_result(clause,Mod); - _-> - call_result(all,Mod) - end, - result_choice("calls",Mod) ++ Result. - -result_choice(Level,Mod)-> - ModStr=atom_to_list(Mod), - [reload_menu_script(""), - "<TABLE WIDTH=100%><TR>\n", - "<TD><A HREF=./",Level,"?module=",ModStr,"&what=all>All Data</A></TD>\n", - "<TD><A HREF=./",Level,"?module=",ModStr,"&what=mod>Module</A></TD>\n", - "<TD><A HREF=./",Level,"?module=",ModStr,"&what=func>Function</A></TD>\n", - "<TD><A HREF=./",Level,"?module=",ModStr,"&what=clause>Clause</A></TD>\n", - "</TR></TABLE><BR>\n"]. - -call_result(Mode,Module)-> - Content = - case Mode of - mod-> - format_cover_call(cover:analyse(Module,calls,module),mod); - func-> - format_cover_call(cover:analyse(Module,calls,function),func); - clause-> - format_cover_call(cover:analyse(Module,calls,clause),clause); - _-> - format_cover_call(cover:analyse(Module,calls,module),mod) ++ - format_cover_call(cover:analyse(Module,calls,function),func)++ - format_cover_call(cover:analyse(Module,calls,clause),clause) - end, - getModDate(Module,date())++"<BR>"++ - "<TABLE WIDTH=\"100%\" BORDER=1>" - ++ Content ++"</TABLE>". - - -format_cover_call({error,_},_)-> - ["<TR><TD>\n", - "<BR><BR><BR><BR>\n", - "<FONT SIZE=5>The selected module is not Cover Compiled</FONT>\n", - "<BR>\n", - "</TD></TR>\n"]; - -format_cover_call({ok,{Mod,Calls}},mod)-> - ["<TR BGCOLOR=\"#8899AA\"><TD COLSPAN=5><B>Module calls</B></TD></TR>\n", - "<TR><TD COLSPAN=4><I>Module</I></TD>", - "<TD ALIGN=\"right\"><I>Number of calls</I></TD></TR>\n", - "<TR><TD COLSPAN=4>" ++ atom_to_list(Mod) ++"</TD>" - "<TD ALIGN=\"right\">" ++ integer_to_list(Calls)++"</TD></TR>\n"]; - -format_cover_call({ok,Calls},func)-> - ["<TR BGCOLOR=\"#8899AA\"><TD COLSPAN=5><B>Function calls</B></TD></TR>\n", - "<TR><TD><I>Module</I></TD><TD><I>Function</I></TD>", - "<TD COLSPAN=2 ALIGN=\"right\"><I>Arity</I></TD>", - "<TD ALIGN=\"right\"><I>Number of calls </I></TD></TR>\n", - lists:append( - lists:map( - fun({{Mod,Func,Arity},Nr_of_calls})-> - ["<TR><TD WIDTH=\"20%\">"++ atom_to_list(Mod)++"</TD>\n", - "<TD WIDTH=\"20%\" >" ++ atom_to_list(Func) ++" </TD>\n", - "<TD COLSPAN=2 WIDTH=\"40%\" ALIGN=\"right\">", - integer_to_list(Arity), - "</TD>\n", - "<TD WIDTH=\"20%\" ALIGN=\"right\">", - integer_to_list(Nr_of_calls), - "</TD></TR>\n"] - end, - Calls))]; - -format_cover_call({ok,Calls},clause)-> - ["<TR BGCOLOR=\"#8899AA\"><TD COLSPAN=5><B>Clause calls</B></TD></TR>\n", - "<TR><TD><I>Module</I></TD><TD><I>Function</I></TD>", - "<TD ALIGN=\"right\"><I>Arity</I></TD>", - "<TD ALIGN=\"right\"><I>Ordinal</I></TD>", - "<TD ALIGN=\"right\"><I>Number of calls</I></TD></TR>\n", - lists:append( - lists:map( - fun({{Mod,Func,Arity,Ord},Nr_of_calls})-> - ["<TR><TD WIDTH=\"20%\" >", atom_to_list(Mod), "</TD>\n", - "<TD WIDTH=\"20%\" >", atom_to_list(Func), "</TD>\n", - "<TD WIDTH=\"20%\" ALIGN=\"right\">", - integer_to_list(Arity), - "</TD>\n", - "<TD WIDTH=\"20%\" ALIGN=\"right\">", - integer_to_list(Ord), - "</TD>\n", - "<TD WIDTH=\"20%\" ALIGN=\"right\">", - integer_to_list(Nr_of_calls), - "</TD></TR>\n"] - end, - Calls))]. - - -error_body()-> - ["<TABLE WIDTH=\"100%\" BORDER=1>\n", - "<TR ALIGN=\"center\">\n", - "<TD>\n", - "<BR><BR><BR><BR><BR><BR>\n", - "<FONT SIZE=5>The selected module is not Cover Compiled</FONT>\n", - "<BR>\n", - "</TD>\n", - "</TR>\n", - "</TABLE>\n"]. - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% % -% The functions that builds the body of the page that shows coverage % -% % -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -coverage_result(Input)-> - Mod = list_to_atom(get_input_data(Input, "module")), - case cover:analyse(Mod,coverage) of - {error,_}-> - error_body(); - {ok,_} -> - coverage_result2(Mod,Input) - end. - -coverage_result2(Mod,Input)-> - Result = - case get_input_data(Input,"what") of - "mod" -> - coverage_result(mod,Mod); - "func" -> - coverage_result(func,Mod); - "clause" -> - coverage_result(clause,Mod); - _-> - coverage_result(all,Mod) - end, - result_choice("coverage",Mod) ++ Result. - -coverage_result(Mode,Module)-> - Content = - case Mode of - mod-> - format_cover_coverage(cover:analyse(Module,coverage,module), - mod); - func-> - format_cover_coverage(cover:analyse(Module,coverage,function), - func); - clause-> - format_cover_coverage(cover:analyse(Module,coverage,clause), - clause); - _-> - format_cover_coverage(cover:analyse(Module,coverage,module), - mod) ++ - format_cover_coverage(cover:analyse(Module,coverage,function), - func)++ - format_cover_coverage(cover:analyse(Module,coverage,clause), - clause) - end, - getModDate(Module,date())++"<BR>"++ - "<TABLE WIDTH=\"100%\" BORDER=1>" - ++ Content ++"</TABLE>". - -getModDate(Module,{Year,Mon,Day})-> - "<TABLE> - <TR> - <TD>Module:</TD> - <TD>" ++ atom_to_list(Module) ++ "</TD> - </TR> - <TR> - <TD>Date:</TD> - <TD>" ++ integer_to_list(Day) ++ "/" ++ - integer_to_list(Mon) ++" - "++ - integer_to_list(Year) ++ - "</TD> - </TR> - </TABLE>". - - -format_cover_coverage({error,_},_)-> - "<TR><TD> - <BR><BR><BR><BR> - <FONT SIZE=5>The selected module is not Cover Compiled</FONT> - <BR> - </TD></TR>"; - - -format_cover_coverage({ok,{Mod,{Cov,Not_cov}}},mod)-> - ["<TR BGCOLOR=\"#8899AA\"><TD COLSPAN=6><B>Module coverage</B></TD></TR>\n", - "<TR><TD COLSPAN=4><I>Module</I></TD>\n", - "<TD ALIGN=\"right\"><I>Covered</I></TD>\n" - "<TD ALIGN=\"RIGHT\" NOWRAP=\"true\"><I>Not Covered</I></TD>\n", - "</TR>\n", - "<TR><TD COLSPAN=4>", atom_to_list(Mod), "</TD>\n" - "<TD ALIGN=\"right\">", integer_to_list(Cov), "</TD>\n" - "<TD ALIGN=\"right\" >", integer_to_list(Not_cov), "</TD></TR>\n"]; - -format_cover_coverage({ok,Cov_res},func)-> - ["<TR BGCOLOR=\"#8899AA\"><TD COLSPAN=6><B>Function coverage</B></TD>\n", - "</TR>\n", - "<TR><TD><I>Module</I></TD><TD><I>Function</I></TD>", - "<TD ALIGN=\"right\"><I>Arity</I></TD>", - "<TD COLSPAN=2 ALIGN=\"right\"><I>Covered</I></TD>", - "<TD ALIGN=\"right\" STYLE=\"white-space:nowrap\"><I>Not Covered</I></TD>", - "</TR>\n", - lists:append( - lists:map( - fun({{Mod,Func,Arity},{Cov,Not_cov}})-> - ["<TR><TD WIDTH=\"20%\" >"++ atom_to_list(Mod) ++" </TD>\n", - "<TD WIDTH=\"20%\" >" ++ atom_to_list(Func) ++"</TD>\n", - "<TD WIDTH=\"40%\" ALIGN=\"right\">", - integer_to_list(Arity), - "</TD>\n", - "<TD WIDTH=\"40%\" ALIGN=\"right\" COLSPAN=2>", - integer_to_list(Cov), - "</TD>\n" - "<TD WIDTH=\"20%\" ALIGN=\"right\">", - integer_to_list(Not_cov), - "</TD></TR>\n"] - end, - Cov_res))]; - -format_cover_coverage({ok,Cov_res},clause)-> - ["<TR BGCOLOR=\"#8899AA\"><TD COLSPAN=6><B>Clause coverage</B></TD></TR>\n", - "<TR><TD><I>Module</I></TD><TD><I>Function</I></TD>\n", - "<TD ALIGN=\"right\"><I>Arity</I></TD>\n", - "<TD ALIGN=\"right\"><I>Ordinal<I></TD>\n", - "<TD ALIGN=\"right\">Covered</TD>\n", - "<TD ALIGN=\"right\" STYLE=\"white-space:nowrap\">Not Covered</TD></TR>\n", - lists:append( - lists:map( - fun({{Mod,Func,Arity,Ord},{Cov,Not_cov}})-> - ["<TR><TD WIDTH=\"20%\" >"++ atom_to_list(Mod) ++"</TD>\n", - "<TD WIDTH=\"20%\" >" ++ atom_to_list(Func) ++" </TD>\n", - "<TD WIDTH=\"20%\" ALIGN=\"right\">", - integer_to_list(Arity), - "</TD>\n" - "<TD WIDTH=\"20%\" ALIGN=\"right\">", - integer_to_list(Ord), - "</TD>\n" - "<TD WIDTH=\"20%\" ALIGN=\"right\">", - integer_to_list(Cov), - "</TD>\n" - "<TD WIDTH=\"20%\" ALIGN=\"right\">", - integer_to_list(Not_cov), - "</TD></TR>\n"] - end, - Cov_res))]. - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% % -% The functions that builds the body of the import page % -% % -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -import_body(Dir,Err) -> - [reload_menu_script(Err), - "<H1 ALIGN=center>Import</H1>\n", - "<TABLE BORDER=0 WIDTH=600 ALIGN=center>\n", - "<TR><TD BGCOLOR=",?INFO_BG_COLOR,">\n", - "<P>You can import coverage data from a previous analysis. If you do so\n", - "the imported data will be merged with the current coverage data.\n", - "<P>You can export data from the current analysis from the \"Result\"\n", - "page.\n", - "<P>Select the file to import here.\n", - "</TD></TR>\n", - "<TR><TD ALIGN=center><BR><BR>\n", - "<FORM NAME=change_import_dir METHOD=post ACTION=\"./import\">\n", - "<B>Change directory:</B><BR>\n", - "<INPUT TYPE=text NAME=\"file\" SIZE=30 VALUE=",Dir,">", - "<INPUT TYPE=hidden NAME=dir VALUE=",Dir,">\n", - "<INPUT TYPE=submit VALUE=Ok><BR>\n", - "</FORM>\n", - browse_import(Dir), - "</TABLE>"]. - -browse_import(Dir) -> - {ok,List} = file:list_dir(Dir), - Sorted = lists:reverse(lists:sort(List)), - {Dirs,Files} = filter_files(Dir,Sorted,[],[]), - ["<FORM NAME=browse_import METHOD=post ACTION=\"./import\">\n" - "<SELECT NAME=file TITLE=\"Select import file\" SIZE=10>\n", - "<OPTION VALUE=\"..\" onDblClick=submit()>../</OPTION>\n", - Dirs, - Files, - "</SELECT>\n", - "<INPUT TYPE=hidden NAME=dir VALUE=",Dir,">\n", - "<BR><INPUT TYPE=submit VALUE=Ok>\n" - "</FORM>\n"]. - -filter_files(Dir,[File|Files],Ds,Fs) -> - case filename:extension(File) of - ".coverdata" -> - Fs1 = ["<OPTION VALUE=",File," onDblClick=submit()>", - File,"</OPTION>\n" | Fs], - filter_files(Dir,Files,Ds,Fs1); - _ -> - FullName = filename:join(Dir,File), - case filelib:is_dir(FullName) of - true -> - Ds1 = ["<OPTION VALUE=",File," onDblClick=submit()>", - File,"/</OPTION>\n" | Ds], - filter_files(Dir,Files,Ds1,Fs); - false -> - filter_files(Dir,Files,Ds,Fs) - end - end; -filter_files(_Dir,[],Ds,Fs) -> - {Ds,Fs}. - - - - -do_import(Input) -> - case parse(Input) of - [{"file",File0},{"dir",Dir}] -> - File = filename:join(Dir,File0), - case filelib:is_dir(File) of - true -> - import_frame1(File); - false -> - case filelib:is_file(File) of - true -> - case cover:import(File) of - ok -> - import_frame1(Dir); - {error,{cant_open_file,ExportFile,_Reason}} -> - import_frame1(Dir, - "Error importing file\\n\\\"" - ++ ExportFile ++ "\\\"") - end; - false -> - import_frame1(Dir, - "Error importing file\\n\\\"" ++ - File ++ "\\\"") - end - end; - [{"dir",Dir}] -> - import_frame1(Dir,"No file is selected") - end. - - - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% % -% Different private helper functions % -% % -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%Create the Header for the page If we now the mimetype use that type %% -%%otherwise use text %% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -header() -> - header("text/html"). -header(MimeType) -> - "Pragma:no-cache\r\n" ++ - "Content-type: " ++ MimeType ++ "\r\n\r\n". - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%%Create the Htmlheader set the title of the page %% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -html_header(Title) -> - "<HTML>\n" ++ - "<HEAD>\n" ++ - "<TITLE>" ++ Title ++ "</TITLE>\n" ++ - "</HEAD>\n" - "<BODY BGCOLOR=\"#FFFFFF\">\n". - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% Close the body- and Html tags %% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -html_end()-> - "</BODY></HTML>". - - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -%% A script which reloads the menu frame and possibly pops up an alert%% -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -reload_menu_script(Err) -> - ["<SCRIPT>\n", - "function reloadMenu()\n", - " {\n", - " parent.menu.document.location.href=\"./menu_frame\";\n", - case Err of - "" -> ""; - _ -> " alert(\""++Err++"\");\n" - end, - case get_warnings() of - [] -> - ""; - Warnings -> - " alert(\""++fix_newline(lists:flatten(Warnings))++"\");\n" - end, - " }\n", - "</SCRIPT>\n", - "<BODY onLoad=reloadMenu() BGCOLOR=\"#FFFFFF\">"]. - -fix_newline([$\n|Rest]) -> - [$\\,$n|fix_newline(Rest)]; -fix_newline([$"|Rest]) -> - [$\\,$"|fix_newline(Rest)]; -fix_newline([Char|Rest]) -> - [Char|fix_newline(Rest)]; -fix_newline([]) -> - []. - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -% Control the input data and return the intresting values or error % -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -get_input_data(Input,Key)-> - case lists:keysearch(Key,1,parse(Input)) of - {value,{Key,Value}} -> - Value; - false -> - undefined - end. - -parse(Input) -> - httpd:parse_query(Input). - - -get_warnings() -> - cover_group_leader_proc ! {self(), get_warnings}, - receive {warnings,Warnings} -> - Warnings - end. diff --git a/lib/tools/src/eprof.erl b/lib/tools/src/eprof.erl index 0357e46a50..3ae899a078 100644 --- a/lib/tools/src/eprof.erl +++ b/lib/tools/src/eprof.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2013. All Rights Reserved. +%% Copyright Ericsson AB 1996-2016. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -74,7 +74,6 @@ start() -> gen_server:start({local, ?MODULE}, ?MODULE, [], []). stop() -> gen_server:call(?MODULE, stop, infinity). - analyze() -> analyze(procs). @@ -112,7 +111,7 @@ profile(Rootset, M, F, A, Pattern) when is_list(Rootset), is_atom(M), is_atom(F) %% Returns when M:F/A has terminated profile(Rootset, M, F, A, Pattern, Options) -> - start(), + ok = start_internal(), gen_server:call(?MODULE, {profile_start, Rootset, Pattern, {M,F,A}, Options}, infinity). dump() -> @@ -127,7 +126,7 @@ start_profiling(Rootset) -> start_profiling(Rootset, Pattern) -> start_profiling(Rootset, Pattern, ?default_options). start_profiling(Rootset, Pattern, Options) -> - start(), + ok = start_internal(), gen_server:call(?MODULE, {profile_start, Rootset, Pattern, undefined, Options}, infinity). stop_profiling() -> @@ -251,9 +250,9 @@ handle_call({logfile, File}, _From, #state{ fd = OldFd } = S) -> {ok, Fd} -> case OldFd of undefined -> ok; - OldFd -> file:close(OldFd) + OldFd -> ok = file:close(OldFd) end, - {reply, ok, S#state{ fd = Fd}}; + {reply, ok, S#state{fd = Fd}}; Error -> {reply, Error, S} end; @@ -521,3 +520,10 @@ format(Fd, Format, Strings) -> divide(_,0) -> 0.0; divide(T,N) -> T/N. + +start_internal() -> + case start() of + {ok, _} -> ok; + {error, {already_started,_}} -> ok; + Error -> Error + end. diff --git a/lib/tools/src/fprof.erl b/lib/tools/src/fprof.erl index c5c24c8eb3..8db23dd151 100644 --- a/lib/tools/src/fprof.erl +++ b/lib/tools/src/fprof.erl @@ -1003,7 +1003,7 @@ handle_req(#analyse{dest = Dest, already_open -> ok; ok -> - file:close(DestPid) + ok = file:close(DestPid) end, State end; @@ -1364,7 +1364,7 @@ tracer_loop(Parent, Handler, State) -> Trace when element(1, Trace) =:= trace_ts -> tracer_loop(Parent, Handler, Handler(Trace, State)); {'EXIT', Parent, Reason} -> - handler(end_of_trace, State), + _ = handler(end_of_trace, State), exit(Reason); _ -> tracer_loop(Parent, Handler, State) @@ -1450,12 +1450,10 @@ end_of_trace(Table, TS) -> Procs = get(), put(table, Table), ?dbg(2, "get() -> ~p~n", [Procs]), - lists:map( - fun ({Pid, _}) when is_pid(Pid) -> - trace_exit(Table, Pid, TS) - end, - Procs), - erase(), + _ = lists:map(fun ({Pid, _}) when is_pid(Pid) -> + trace_exit(Table, Pid, TS) + end, Procs), + _ = erase(), ok. @@ -1567,13 +1565,20 @@ trace_handler({trace_ts, Pid, return_to, {_M, _F, Args} = MFArgs, TS} = Trace, trace_return_to(Table, Pid, Func, TS), TS; %% -%% spawn +%% spawn, only needed (and reliable) prior to 19.0 trace_handler({trace_ts, Pid, spawn, Child, MFArgs, TS} = Trace, Table, _, Dump) -> dump_stack(Dump, get(Pid), Trace), trace_spawn(Table, Child, MFArgs, TS, Pid), TS; %% +%% spawned, added in 19.0 +trace_handler({trace_ts, Pid, spawned, Parent, MFArgs, TS} = Trace, + Table, _, Dump) -> + dump_stack(Dump, get(Pid), Trace), + trace_spawn(Table, Pid, MFArgs, TS, Parent), + TS; +%% %% exit trace_handler({trace_ts, Pid, exit, _Reason, TS} = Trace, Table, _, Dump) -> @@ -1622,15 +1627,24 @@ trace_handler({trace_ts, Pid, in, {_M, _F, Args} = MFArgs, TS} = Trace, TS; %% %% gc_start -trace_handler({trace_ts, Pid, gc_start, _Func, TS} = Trace, - Table, _, Dump) -> +trace_handler({trace_ts, Pid, gc_minor_start, _Func, TS} = Trace, Table, _, Dump) -> dump_stack(Dump, get(Pid), Trace), trace_gc_start(Table, Pid, TS), TS; + +trace_handler({trace_ts, Pid, gc_major_start, _Func, TS} = Trace, Table, _, Dump) -> + dump_stack(Dump, get(Pid), Trace), + trace_gc_start(Table, Pid, TS), + TS; + %% %% gc_end -trace_handler({trace_ts, Pid, gc_end, _Func, TS} = Trace, - Table, _, Dump) -> +trace_handler({trace_ts, Pid, gc_minor_end, _Func, TS} = Trace, Table, _, Dump) -> + dump_stack(Dump, get(Pid), Trace), + trace_gc_end(Table, Pid, TS), + TS; + +trace_handler({trace_ts, Pid, gc_major_end, _Func, TS} = Trace, Table, _, Dump) -> dump_stack(Dump, get(Pid), Trace), trace_gc_end(Table, Pid, TS), TS; @@ -2014,8 +2028,10 @@ trace_spawn(Table, Pid, MFArgs, TS, Parent) -> ets:insert(Table, #proc{id = Pid, parent = Parent, spawned_as = MFArgs}); _ -> - throw({inconsistent_trace_data, ?MODULE, ?LINE, - [Pid, MFArgs, TS, Parent, Stack]}) + %% In 19.0 we get both a spawn and spawned event, + %% however we do not know the order so we just ignore + %% the second event that comes + ok end. @@ -2029,7 +2045,7 @@ trace_exit(Table, Pid, TS) -> [] -> ok; [_ | _] = Stack -> - trace_return_to_int(Table, Pid, undefined, TS, Stack), + _ = trace_return_to_int(Table, Pid, undefined, TS, Stack), ok end, ok. @@ -2155,7 +2171,7 @@ trace_clock(_Table, _Pid, _T, [[{suspend, _}], [{suspend, _}] | _]=_Stack, _Clock) -> ?dbg(9, "trace_clock(Table, ~w, ~w, ~w, ~w)~n", [_Pid, _T, _Stack, _Clock]), - void; + ok; trace_clock(Table, Pid, T, [[{garbage_collect, TS0}], [{suspend, _}]], Clock) -> trace_clock_1(Table, Pid, T, TS0, undefined, garbage_collect, Clock); @@ -2170,7 +2186,7 @@ trace_clock(Table, Pid, T, [[{Func0, TS0}], [{Func1, _} | _] | _], Clock) -> trace_clock(Table, Pid, T, [[{Func0, TS0}]], Clock) -> trace_clock_1(Table, Pid, T, TS0, undefined, Func0, Clock); trace_clock(_, _, _, [], _) -> - void. + ok. trace_clock_1(Table, Pid, _, _, Caller, suspend, #clocks.own) -> clock_add(Table, {Pid, Caller, suspend}, #clocks.own, 0); @@ -2184,7 +2200,7 @@ trace_clock_1(Table, Pid, T, TS, Caller, Func, Clock) -> clock_add(Table, Id, Clock, T) -> ?dbg(1, "clock_add(Table, ~w, ~w, ~w)~n", [Id, Clock, T]), - try ets:update_counter(Table, Id, {Clock, T}) + try ets:update_counter(Table, Id, {Clock, T}), ok catch error:badarg -> ets:insert(Table, #clocks{id = Id}), @@ -2193,7 +2209,7 @@ clock_add(Table, Id, Clock, T) -> true -> ?dbg(0, "Negative counter value ~p ~p ~p ~p~n", [X, Id, Clock, T]) end, - X + ok end. clocks_add(Table, #clocks{id = Id} = Clocks) -> diff --git a/lib/tools/src/instrument.erl b/lib/tools/src/instrument.erl index 34c5ba04cc..055f4a7afb 100644 --- a/lib/tools/src/instrument.erl +++ b/lib/tools/src/instrument.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1998-2009. All Rights Reserved. +%% Copyright Ericsson AB 1998-2016. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. diff --git a/lib/tools/src/lcnt.erl b/lib/tools/src/lcnt.erl index 3a3cebf3ed..23d66b084e 100644 --- a/lib/tools/src/lcnt.erl +++ b/lib/tools/src/lcnt.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2010-2013. All Rights Reserved. +%% Copyright Ericsson AB 2010-2016. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -23,67 +23,57 @@ -author("Björn-Egil Dahlberg"). %% gen_server callbacks --export([ - init/1, - handle_call/3, - handle_cast/2, - handle_info/2, - terminate/2, - code_change/3 - ]). +-export([init/1, + handle_call/3, + handle_cast/2, + handle_info/2, + terminate/2, + code_change/3]). %% start/stop --export([ - start/0, - stop/0 - ]). +-export([start/0, + stop/0]). %% erts_debug:lock_counters api --export([ - rt_collect/0, - rt_collect/1, - rt_clear/0, - rt_clear/1, - rt_opt/1, - rt_opt/2 - ]). +-export([rt_collect/0, + rt_collect/1, + rt_clear/0, + rt_clear/1, + rt_opt/1, + rt_opt/2]). %% gen_server call api --export([ - raw/0, - collect/0, - collect/1, - clear/0, - clear/1, - conflicts/0, - conflicts/1, - locations/0, - locations/1, - inspect/1, - inspect/2, - histogram/1, - histogram/2, - information/0, - swap_pid_keys/0, - % set options - set/1, - set/2, - - load/1, - save/1 - ]). +-export([raw/0, + collect/0, + collect/1, + clear/0, + clear/1, + conflicts/0, + conflicts/1, + locations/0, + locations/1, + inspect/1, + inspect/2, + histogram/1, + histogram/2, + information/0, + swap_pid_keys/0, + % set options + set/1, + set/2, + + load/1, + save/1]). %% convenience --export([ - apply/3, - apply/2, - apply/1, - all_conflicts/0, - all_conflicts/1, - pid/2, pid/3, - port/1, port/2 - ]). +-export([apply/3, + apply/2, + apply/1, + all_conflicts/0, + all_conflicts/1, + pid/2, pid/3, + port/1, port/2]). -define(version, "1.0"). @@ -94,12 +84,12 @@ -record(stats, { file :: atom(), - line :: non_neg_integer(), + line :: non_neg_integer() | 'undefined', tries :: non_neg_integer(), colls :: non_neg_integer(), time :: non_neg_integer(), % us nt :: non_neg_integer(), % #timings collected - hist :: tuple() % histogram + hist :: tuple() | 'undefined' % histogram }). -record(lock, { @@ -135,6 +125,13 @@ start() -> gen_server:start({local, ?MODULE}, ?MODULE, [], []). stop() -> gen_server:call(?MODULE, stop, infinity). init([]) -> {ok, #state{ locks = [], duration = 0 } }. +start_internal() -> + case start() of + {ok,_} -> ok; + {error, {already_started,_}} -> ok; + Error -> Error + end. + %% -------------------------------------------------------------------- %% %% %% API erts_debug:lock_counters @@ -184,7 +181,7 @@ raw() -> call(raw). set(Option, Value) -> call({set, Option, Value}). set({Option, Value}) -> call({set, Option, Value}). save(Filename) -> call({save, Filename}). -load(Filename) -> start(), call({load, Filename}). +load(Filename) -> ok = start_internal(), call({load, Filename}). call(Msg) -> gen_server:call(?MODULE, Msg, infinity). @@ -195,7 +192,7 @@ call(Msg) -> gen_server:call(?MODULE, Msg, infinity). %% -------------------------------------------------------------------- %% apply(M,F,As) when is_atom(M), is_atom(F), is_list(As) -> - lcnt:start(), + ok = start_internal(), Opt = lcnt:rt_opt({copy_save, true}), lcnt:clear(), Res = erlang:apply(M,F,As), @@ -207,7 +204,7 @@ apply(Fun) when is_function(Fun) -> lcnt:apply(Fun, []). apply(Fun, As) when is_function(Fun) -> - lcnt:start(), + ok = start_internal(), Opt = lcnt:rt_opt({copy_save, true}), lcnt:clear(), Res = erlang:apply(Fun, As), @@ -757,7 +754,7 @@ list2lock([F|Fs], Ls) -> stats2stats([]) -> []; stats2stats([Stat|Stats]) -> - Sz = tuple_size(#stats{}), + Sz = record_info(size, stats), [stat2stat(Stat,Sz)|stats2stats(Stats)]. stat2stat(Stat,Sz) when tuple_size(Stat) =:= Sz -> Stat; diff --git a/lib/tools/src/make.erl b/lib/tools/src/make.erl index 5d5a1ef2bd..26378f28a0 100644 --- a/lib/tools/src/make.erl +++ b/lib/tools/src/make.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2013. All Rights Reserved. +%% Copyright Ericsson AB 1996-2016. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -299,10 +299,11 @@ check_includes(File, IncludePath, ObjMTime) -> end. check_includes2(Epp, File, ObjMTime) -> + A1 = erl_anno:new(1), case epp:parse_erl_form(Epp) of - {ok, {attribute, 1, file, {File, 1}}} -> + {ok, {attribute, A1, file, {File, A1}}} -> check_includes2(Epp, File, ObjMTime); - {ok, {attribute, 1, file, {IncFile, 1}}} -> + {ok, {attribute, A1, file, {IncFile, A1}}} -> case file:read_file_info(IncFile) of {ok, #file_info{mtime=MTime}} when MTime>ObjMTime -> epp:close(Epp), diff --git a/lib/tools/src/tags.erl b/lib/tools/src/tags.erl index 2bc1865503..b833d96c19 100644 --- a/lib/tools/src/tags.erl +++ b/lib/tools/src/tags.erl @@ -101,7 +101,7 @@ files(Files, Options) -> case open_out(Options) of {ok, Os} -> files_loop(Files, Os), - close_out(Os), + ok = close_out(Os), ok; _ -> error @@ -169,7 +169,7 @@ filename(Name, Os) -> case file:open(Name, [read]) of {ok, Desc} -> Acc = module(Desc, [], [], {1, 0}), - file:close(Desc), + ok = file:close(Desc), genout(Os, Name, Acc), ok; _ -> diff --git a/lib/tools/src/tools.app.src b/lib/tools/src/tools.app.src index 978b54719c..a00969eabe 100644 --- a/lib/tools/src/tools.app.src +++ b/lib/tools/src/tools.app.src @@ -21,7 +21,6 @@ [{description, "DEVTOOLS CXC 138 16"}, {vsn, "%VSN%"}, {modules, [cover, - cover_web, eprof, fprof, instrument, @@ -36,12 +35,12 @@ xref_utils ] }, - {registered,[webcover_server]}, + {registered, []}, {applications, [kernel, stdlib]}, {env, [{file_util_search_methods,[{"", ""}, {"ebin", "esrc"}, {"ebin", "src"}]} ] }, - {runtime_dependencies, ["webtool-0.8.10","stdlib-2.5","runtime_tools-1.8.14", + {runtime_dependencies, ["stdlib-2.5","runtime_tools-1.8.14", "kernel-3.0","inets-5.10","erts-7.0", "compiler-5.0"]} ] diff --git a/lib/tools/src/tools.appup.src b/lib/tools/src/tools.appup.src index 9eee8df184..fa48fa4219 100644 --- a/lib/tools/src/tools.appup.src +++ b/lib/tools/src/tools.appup.src @@ -1,7 +1,7 @@ %% -*- erlang -*- %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2001-2014. All Rights Reserved. +%% Copyright Ericsson AB 2001-2016. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. diff --git a/lib/tools/src/xref.erl b/lib/tools/src/xref.erl index 64add7afbb..32efa36fa2 100644 --- a/lib/tools/src/xref.erl +++ b/lib/tools/src/xref.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2000-2013. All Rights Reserved. +%% Copyright Ericsson AB 2000-2016. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. diff --git a/lib/tools/src/xref_base.erl b/lib/tools/src/xref_base.erl index 88031f6e77..4322943c59 100644 --- a/lib/tools/src/xref_base.erl +++ b/lib/tools/src/xref_base.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2000-2013. All Rights Reserved. +%% Copyright Ericsson AB 2000-2016. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -696,7 +696,7 @@ do_add_module({Dir, Basename}, AppName, Builtins, Verbose, Warnings, State) -> File = filename:join(Dir, Basename), {ok, M, Bad, NewState} = do_add_module1(Dir, File, AppName, Builtins, Verbose, Warnings, State), - filter(fun({Tag,B}) -> warnings(Warnings, Tag, [[File,B]]) end, Bad), + _ = filter(fun({Tag,B}) -> warnings(Warnings, Tag, [[File,B]]) end, Bad), {ok, M, NewState}. do_add_module1(Dir, File, AppName, Builtins, Verbose, Warnings, State) -> @@ -1727,7 +1727,7 @@ pack(T) -> NT = pack1(T), %% true = T =:= NT, %% io:format("erasing ~p elements...~n", [length(erase())]), - erase(), % wasting heap (and time)... + _ = erase(), % wasting heap (and time)... foreach(fun({K,V}) -> put(K, V) end, PD), NT. diff --git a/lib/tools/src/xref_parser.yrl b/lib/tools/src/xref_parser.yrl index 48602bb120..0711da79e2 100644 --- a/lib/tools/src/xref_parser.yrl +++ b/lib/tools/src/xref_parser.yrl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2000-2010. All Rights Reserved. +%% Copyright Ericsson AB 2000-2016. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. diff --git a/lib/tools/test/Makefile b/lib/tools/test/Makefile index 49b86628b7..84c4e56aff 100644 --- a/lib/tools/test/Makefile +++ b/lib/tools/test/Makefile @@ -1,7 +1,7 @@ # # %CopyrightBegin% # -# Copyright Ericsson AB 1997-2012. All Rights Reserved. +# Copyright Ericsson AB 1997-2016. All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -53,8 +53,7 @@ RELSYSDIR = $(RELEASE_PATH)/tools_test # FLAGS # ---------------------------------------------------- ERL_MAKE_FLAGS += -ERL_COMPILE_FLAGS += -I$(ERL_TOP)/lib/test_server/include \ - -I$(ERL_TOP)/lib/percept/include +ERL_COMPILE_FLAGS += -I$(ERL_TOP)/lib/percept/include EBIN = . diff --git a/lib/tools/test/cover_SUITE.erl b/lib/tools/test/cover_SUITE.erl index 71570a55fa..b4c9264b30 100644 --- a/lib/tools/test/cover_SUITE.erl +++ b/lib/tools/test/cover_SUITE.erl @@ -21,53 +21,45 @@ -compile(export_all). --include_lib("test_server/include/test_server.hrl"). +-include_lib("common_test/include/ct.hrl"). -suite() -> [{ct_hooks,[ts_install_cth]}]. +suite() -> + [{ct_hooks,[ts_install_cth]}]. all() -> NoStartStop = [eif,otp_5305,otp_5418,otp_7095,otp_8273, otp_8340,otp_8188,compile_beam_opts,eep37, - analyse_no_beam, line_0, compile_beam_no_file, - otp_13277], + analyse_no_beam, line_0, compile_beam_no_file, + otp_13277, otp_13289], StartStop = [start, compile, analyse, misc, stop, - distribution, reconnect, die_and_reconnect, - dont_reconnect_after_stop, stop_node_after_disconnect, - export_import, otp_5031, otp_6115, - otp_8270, otp_10979_hanging_node], + distribution, reconnect, die_and_reconnect, + dont_reconnect_after_stop, stop_node_after_disconnect, + export_import, otp_5031, otp_6115, + otp_8270, otp_10979_hanging_node], case whereis(cover_server) of - undefined -> - [coverage,StartStop ++ NoStartStop]; - _pid -> - [coverage|NoStartStop++[coverage_analysis]] + undefined -> + [coverage,StartStop ++ NoStartStop]; + _pid -> + [coverage|NoStartStop++[coverage_analysis]] end. -groups() -> - []. - init_per_suite(Config) -> [{ct_is_running_cover,whereis(cover_server) =/= undefined}|Config]. end_per_suite(_Config) -> ok. -init_per_group(_GroupName, Config) -> - Config. - -end_per_group(_GroupName, Config) -> - Config. - init_per_testcase(TC, Config) when TC =:= misc; - TC =:= compile; - TC =:= analyse; - TC =:= distribution; - TC =:= otp_5031; - TC =:= stop -> + TC =:= compile; + TC =:= analyse; + TC =:= distribution; + TC =:= otp_5031; + TC =:= stop -> case code:which(crypto) of - Path when is_list(Path) -> - init_per_testcase(dummy_tc, Config); - _Else -> - {skip, "No crypto file to test with"} + Path when is_list(Path) -> + init_per_testcase(dummy_tc, Config); + _Else -> + {skip, "No crypto file to test with"} end; init_per_testcase(_TestCase, Config) -> Config. @@ -75,10 +67,10 @@ init_per_testcase(_TestCase, Config) -> end_per_testcase(TestCase, Config) -> NoStop = [start,compile,analyse,misc], DontStop = proplists:get_bool(ct_is_running_cover, Config) orelse - lists:member(TestCase, NoStop), + lists:member(TestCase, NoStop), case DontStop of - true -> ok; - false -> cover:stop() + true -> ok; + false -> cover:stop() end, ok. @@ -87,7 +79,7 @@ coverage(Config) when is_list(Config) -> ?MODULE:do_coverage(Config). do_coverage(Config) -> - Outdir = ?config(priv_dir, Config), + Outdir = proplists:get_value(priv_dir, Config), ExportFile = filename:join(Outdir, "export"), ok = cover:export(ExportFile, ?MODULE), {error,{already_started,_}} = cover:start(), @@ -100,16 +92,16 @@ do_coverage(Config) -> %% Cover escaping of '&' in HTML files. case proplists:get_bool(ct_is_running_cover, Config) of - false -> - %% Cover server was implicitly started when this module - %% was cover-compiled. We must stop the cover server, but - %% we must ensure that this module is not on the call - %% stack when it is unloaded. Therefore, the call that - %% follows MUST be tail-recursive. - cover:stop(); - true -> - %% Cover server was started by common_test; don't stop it. - ok + false -> + %% Cover server was implicitly started when this module + %% was cover-compiled. We must stop the cover server, but + %% we must ensure that this module is not on the call + %% stack when it is unloaded. Therefore, the call that + %% follows MUST be tail-recursive. + cover:stop(); + true -> + %% Cover server was started by common_test; don't stop it. + ok end. %% This test case will only be run when common_test is running cover. @@ -120,7 +112,7 @@ coverage_analysis(Config) when is_list(Config) -> io:format("~p\n", [Analysis2]), {ok,_Analysis3} = cover:analyze(?MODULE, calls, line), - Outdir = ?config(priv_dir, Config), + Outdir = proplists:get_value(priv_dir, Config), Outfile = filename:join(Outdir, ?MODULE), {ok,Outfile} = cover:analyze_to_file(?MODULE, Outfile), @@ -130,92 +122,90 @@ coverage_analysis(Config) when is_list(Config) -> {ok,Outfile} = cover:analyze_to_file(?MODULE, Outfile, [html]), ok. -start(suite) -> []; start(Config) when is_list(Config) -> - ?line ok = file:set_cwd(?config(data_dir, Config)), + ok = file:set_cwd(proplists:get_value(data_dir, Config)), - ?line Files = lsfiles(), - ?line remove(files(Files, ".out")), + Files = lsfiles(), + remove(files(Files, ".out")), - ?line {ok, Pid} = cover:start(), - ?line {error, {already_started, Pid}} = cover:start(). + {ok, Pid} = cover:start(), + {error, {already_started, Pid}} = cover:start(). -compile(suite) -> []; compile(Config) when is_list(Config) -> - ?line ok = file:set_cwd(?config(data_dir, Config)), + ok = file:set_cwd(proplists:get_value(data_dir, Config)), - ?line Result1 = cover:compile_directory(), - ?line SortedResult = lists:sort(Result1), - ?line {ok, CWD} = file:get_cwd(), - ?line Result2 = cover:compile_directory(CWD), - ?line SortedResult = lists:sort(Result2), - ?line [{error,DFile},{ok,a},{ok,b},{ok,cc},{ok,f}] = SortedResult, - ?line [{ok,e}] = cover:compile_directory("d1"), - ?line {error,enoent} = cover:compile_directory("d2"), + Result1 = cover:compile_directory(), + SortedResult = lists:sort(Result1), + {ok, CWD} = file:get_cwd(), + Result2 = cover:compile_directory(CWD), + SortedResult = lists:sort(Result2), + [{error,DFile},{ok,a},{ok,b},{ok,cc},{ok,f}] = SortedResult, + [{ok,e}] = cover:compile_directory("d1"), + {error,enoent} = cover:compile_directory("d2"), [] = cover:compile([]), Result21 = cover:compile([a,b,"cc.erl",d,"f"]), SortedResult21 = lists:sort(Result21), [{error,DFile},{ok,a},{ok,b},{ok,cc},{ok,f}] = SortedResult21, - ?line {ok,a} = cover:compile(a), - ?line {ok,b} = compile:file(b), - ?line code:purge(b), - ?line {module,b} = code:load_file(b), - ?line {ok,d} = cover:compile("d.erl", [{d,'AGE',42}]), - ?line {error,_BBFile} = cover:compile(bb), + {ok,a} = cover:compile(a), + {ok,b} = compile:file(b), + code:purge(b), + {module,b} = code:load_file(b), + {ok,d} = cover:compile("d.erl", [{d,'AGE',42}]), + {error,_BBFile} = cover:compile(bb), - ?line StdlibDir = code:lib_dir(stdlib), - ?line Lists = filename:join([StdlibDir, "src", "lists.erl"]), - ?line {error, Lists} = cover:compile(Lists), + StdlibDir = code:lib_dir(stdlib), + Lists = filename:join([StdlibDir, "src", "lists.erl"]), + {error, Lists} = cover:compile(Lists), %% For compiling beam: using dummy files v,w,x,y and z - ?line file:set_cwd("compile_beam"), - ?line {ok,_} = compile:file(v,[debug_info,report]), - ?line {ok,_} = compile:file(w,[debug_info,report]), - ?line {ok,_} = compile:file(x), - ?line {ok,_} = compile:file("d/y",[debug_info,{outdir,"d"},report]), - ?line Key = "A Krypto Key", + file:set_cwd("compile_beam"), + {ok,_} = compile:file(v,[debug_info,report]), + {ok,_} = compile:file(w,[debug_info,report]), + {ok,_} = compile:file(x), + {ok,_} = compile:file("d/y",[debug_info,{outdir,"d"},report]), + Key = "A Krypto Key", CryptoWorks = crypto_works(), case CryptoWorks of - false -> - {ok,_} = compile:file(crypt, [debug_info,report]), - {ok,crypt} = cover:compile_beam("crypt.beam"); - true -> - {ok,_} = compile:file(crypt, [{debug_info_key,Key},report]), - {error,{encrypted_abstract_code,_}} = - cover:compile_beam("crypt.beam"), - ok = beam_lib:crypto_key_fun(simple_crypto_fun(Key)), - {ok,crypt} = cover:compile_beam("crypt.beam") + false -> + {ok,_} = compile:file(crypt, [debug_info,report]), + {ok,crypt} = cover:compile_beam("crypt.beam"); + true -> + {ok,_} = compile:file(crypt, [{debug_info_key,Key},report]), + {error,{encrypted_abstract_code,_}} = + cover:compile_beam("crypt.beam"), + ok = beam_lib:crypto_key_fun(simple_crypto_fun(Key)), + {ok,crypt} = cover:compile_beam("crypt.beam") end, - Path = filename:join([?config(data_dir, Config), "compile_beam", "v.erl"]), - ?line {ok,v} = cover:compile_beam(v), + Path = filename:join([proplists:get_value(data_dir, Config), "compile_beam", "v.erl"]), + {ok,v} = cover:compile_beam(v), {source,Path} = lists:keyfind(source, 1, v:module_info(compile)), - ?line {ok,w} = cover:compile_beam("w.beam"), - ?line {error,{no_abstract_code,"./x.beam"}} = cover:compile_beam(x), - ?line {error,{already_cover_compiled,no_beam_found,a}}=cover:compile_beam(a), - ?line {error,non_existing} = cover:compile_beam(z), - ?line [{ok,y}] = cover:compile_beam_directory("d"), - ?line Result3 = lists:sort(cover:compile_beam_directory()), - ?line [{error,{no_abstract_code,XBeam}},{ok,crypt},{ok,v},{ok,w}] = Result3, - ?line {error,enoent} = cover:compile_beam_directory("d2"), + {ok,w} = cover:compile_beam("w.beam"), + {error,{no_abstract_code,"./x.beam"}} = cover:compile_beam(x), + {error,{already_cover_compiled,no_beam_found,a}}=cover:compile_beam(a), + {error,non_existing} = cover:compile_beam(z), + [{ok,y}] = cover:compile_beam_directory("d"), + Result3 = lists:sort(cover:compile_beam_directory()), + [{error,{no_abstract_code,XBeam}},{ok,crypt},{ok,v},{ok,w}] = Result3, + {error,enoent} = cover:compile_beam_directory("d2"), [] = cover:compile_beam([]), Result31 = cover:compile_beam([crypt,"v.beam",w,"x"]), SortedResult31 = lists:sort(Result31), [{error,{no_abstract_code,XBeam}},{ok,crypt},{ok,v},{ok,w}] = SortedResult31, - ?line decompile([v,w,y]), - ?line Files = lsfiles(), - ?line remove(files(Files, ".beam")). + decompile([v,w,y]), + Files = lsfiles(), + remove(files(Files, ".beam")). crypto_works() -> try crypto:start() of - {error,{already_started,crypto}} -> true; - ok -> true + {error,{already_started,crypto}} -> true; + ok -> true catch - error:_ -> - false + error:_ -> + false end. simple_crypto_fun(Key) -> @@ -223,90 +213,89 @@ simple_crypto_fun(Key) -> ({debug_info, des3_cbc, crypt, _}) -> Key end. -analyse(suite) -> []; analyse(Config) when is_list(Config) -> - ?line ok = file:set_cwd(?config(data_dir, Config)), + ok = file:set_cwd(proplists:get_value(data_dir, Config)), - ?line done = a:start(5), + done = a:start(5), {ok, {a,{17,2}}=ACovMod} = cover:analyse(a, coverage, module), {ok, [{{a,exit_kalle,0},{1,0}}, - {{a,loop,3},{5,1}}, - {{a,pong,1},{1,0}}, - {{a,start,1},{6,0}}, - {{a,stop,1},{0,1}}, - {{a,trycatch,1},{4,0}}]=ACovFunc} = - cover:analyse(a, coverage, function), + {{a,loop,3},{5,1}}, + {{a,pong,1},{1,0}}, + {{a,start,1},{6,0}}, + {{a,stop,1},{0,1}}, + {{a,trycatch,1},{4,0}}]=ACovFunc} = + cover:analyse(a, coverage, function), {ok, [{{a,exit_kalle,0,1},{1,0}}, - {{a,loop,3,1},{3,1}}, - {{a,loop,3,2},{2,0}}, - {{a,pong,1,1},{1,0}}, - {{a,start,1,1},{6,0}}, - {{a,stop,1,1},{0,1}}, - {{a,trycatch,1,1},{4,0}}]=ACovClause} = - cover:analyse(a, coverage, clause), - ?line {ok, [{{a,9},{1,0}}, - {{a,10},{1,0}}, - {{a,11},{1,0}}, - {{a,13},{1,0}}, - {{a,14},{1,0}}, - {{a,15},{1,0}}, - {{a,21},{0,1}}, - {{a,26},{1,0}}, - {{a,31},{1,0}}, - {{a,32},{1,0}}, - {{a,34},{1,0}}, - {{a,36},{0,1}}, - {{a,39},{1,0}}, - {{a,40},{1,0}}, - {{a,44},{1,0}}, - {{a,47},{1,0}}, - {{a,49},{1,0}}, - {{a,51},{1,0}}, - {{a,55},{1,0}}]=ACovLine} = cover:analyse(a, coverage, line), + {{a,loop,3,1},{3,1}}, + {{a,loop,3,2},{2,0}}, + {{a,pong,1,1},{1,0}}, + {{a,start,1,1},{6,0}}, + {{a,stop,1,1},{0,1}}, + {{a,trycatch,1,1},{4,0}}]=ACovClause} = + cover:analyse(a, coverage, clause), + {ok, [{{a,9},{1,0}}, + {{a,10},{1,0}}, + {{a,11},{1,0}}, + {{a,13},{1,0}}, + {{a,14},{1,0}}, + {{a,15},{1,0}}, + {{a,21},{0,1}}, + {{a,26},{1,0}}, + {{a,31},{1,0}}, + {{a,32},{1,0}}, + {{a,34},{1,0}}, + {{a,36},{0,1}}, + {{a,39},{1,0}}, + {{a,40},{1,0}}, + {{a,44},{1,0}}, + {{a,47},{1,0}}, + {{a,49},{1,0}}, + {{a,51},{1,0}}, + {{a,55},{1,0}}]=ACovLine} = cover:analyse(a, coverage, line), {ok, {a,15}=ACallsMod} = cover:analyse(a, calls, module), {ok, [{{a,exit_kalle,0},1}, - {{a,loop,3},6}, - {{a,pong,1},5}, - {{a,start,1},1}, - {{a,stop,1},0}, - {{a,trycatch,1},2}]=ACallsFunc} = cover:analyse(a, calls, function), + {{a,loop,3},6}, + {{a,pong,1},5}, + {{a,start,1},1}, + {{a,stop,1},0}, + {{a,trycatch,1},2}]=ACallsFunc} = cover:analyse(a, calls, function), {ok, [{{a,exit_kalle,0,1},1}, - {{a,loop,3,1},5}, - {{a,loop,3,2},1}, - {{a,pong,1,1},5}, - {{a,start,1,1},1}, - {{a,stop,1,1},0}, - {{a,trycatch,1,1},2}]=ACallsClause} = cover:analyse(a, calls, clause), - ?line {ok, [{{a,9},1}, - {{a,10},1}, - {{a,11},1}, - {{a,13},1}, - {{a,14},1}, - {{a,15},1}, - {{a,21},0}, - {{a,26},5}, - {{a,31},5}, - {{a,32},5}, - {{a,34},5}, - {{a,36},0}, - {{a,39},1}, - {{a,40},1}, - {{a,44},2}, - {{a,47},1}, - {{a,49},1}, - {{a,51},2}, - {{a,55},1}]=ACallsLine} = cover:analyse(a, calls, line), + {{a,loop,3,1},5}, + {{a,loop,3,2},1}, + {{a,pong,1,1},5}, + {{a,start,1,1},1}, + {{a,stop,1,1},0}, + {{a,trycatch,1,1},2}]=ACallsClause} = cover:analyse(a, calls, clause), + {ok, [{{a,9},1}, + {{a,10},1}, + {{a,11},1}, + {{a,13},1}, + {{a,14},1}, + {{a,15},1}, + {{a,21},0}, + {{a,26},5}, + {{a,31},5}, + {{a,32},5}, + {{a,34},5}, + {{a,36},0}, + {{a,39},1}, + {{a,40},1}, + {{a,44},2}, + {{a,47},1}, + {{a,49},1}, + {{a,51},2}, + {{a,55},1}]=ACallsLine} = cover:analyse(a, calls, line), {ok,ACovFunc} = cover:analyse(a), {ok,ACovMod} = cover:analyse(a, module), {ok,ACallsFunc} = cover:analyse(a, calls), - ?line {ok, "a.COVER.out"} = cover:analyse_to_file(a), - ?line {ok, "e.COVER.out"} = cover:analyse_to_file(e), - ?line {ok, "a.COVER.html"} = cover:analyse_to_file(a,[html]), - ?line {ok, "e.COVER.html"} = cover:analyse_to_file(e,[html]), + {ok, "a.COVER.out"} = cover:analyse_to_file(a), + {ok, "e.COVER.out"} = cover:analyse_to_file(e), + {ok, "a.COVER.html"} = cover:analyse_to_file(a,[html]), + {ok, "e.COVER.html"} = cover:analyse_to_file(e,[html]), %% Analyse all modules Modules = cover:modules(), @@ -355,7 +344,7 @@ analyse(Config) when is_list(Config) -> {result,CovClause1,[]} = cover:analyse(Modules,coverage,clause), true = lists:sort(CovClause) == lists:sort(CovClause1), - + {result,CovLine1,[]} = cover:analyse(Modules,coverage,line), true = lists:sort(CovLine) == lists:sort(CovLine1), @@ -377,18 +366,18 @@ analyse(Config) when is_list(Config) -> true = lists:sort(AllToFileHtml) == lists:sort(AllToFileHtml1), %% analyse_to_file of file which is compiled from beam - ?line {ok,f} = compile:file(f,[debug_info]), - ?line code:purge(f), - ?line {module,f} = code:load_file(f), - ?line {ok,f} = cover:compile_beam(f), - ?line f:f2(), - ?line {ok, "f.COVER.out"} = cover:analyse_to_file(f), + {ok,f} = compile:file(f,[debug_info]), + code:purge(f), + {module,f} = code:load_file(f), + {ok,f} = cover:compile_beam(f), + f:f2(), + {ok, "f.COVER.out"} = cover:analyse_to_file(f), %% Source code can be found via source - ?line {ok,v} = compile:file("compile_beam/v",[debug_info]), - ?line code:purge(v), - ?line {module,v} = code:load_file(v), - ?line {ok,v} = cover:compile_beam(v), + {ok,v} = compile:file("compile_beam/v",[debug_info]), + code:purge(v), + {module,v} = code:load_file(v), + {ok,v} = cover:compile_beam(v), {ok,"v.COVER.out"} = cover:analyse_to_file(v), %% Source code cannot be found @@ -403,163 +392,161 @@ analyse(Config) when is_list(Config) -> code:purge(z), code:delete(z), - ?line {error,{not_cover_compiled,b}} = cover:analyse(b), - ?line {error,{not_cover_compiled,g}} = cover:analyse(g), + {error,{not_cover_compiled,b}} = cover:analyse(b), + {error,{not_cover_compiled,g}} = cover:analyse(g), {result,[],[{not_cover_compiled,b}]} = cover:analyse([b]), - ?line {error,{not_cover_compiled,b}} = cover:analyse_to_file(b), + {error,{not_cover_compiled,b}} = cover:analyse_to_file(b), {error,{not_cover_compiled,g}} = cover:analyse_to_file(g), {result,[],[{not_cover_compiled,g}]} = cover:analyse_to_file([g]). -misc(suite) -> []; misc(Config) when is_list(Config) -> - ?line ok = file:set_cwd(?config(data_dir, Config)), + ok = file:set_cwd(proplists:get_value(data_dir, Config)), - ?line [a,cc,crypt,d,e,f,v] = lists:sort(cover:modules()), + [a,cc,crypt,d,e,f,v] = lists:sort(cover:modules()), - ?line {ok,cc} = compile:file(cc), - ?line code:purge(cc), - ?line {module,cc} = code:load_file(cc), - ?line [a,crypt,d,e,f,v] = lists:sort(cover:modules()), + {ok,cc} = compile:file(cc), + code:purge(cc), + {module,cc} = code:load_file(cc), + [a,crypt,d,e,f,v] = lists:sort(cover:modules()), - ?line {file, _File} = cover:is_compiled(a), - ?line false = cover:is_compiled(b), - ?line false = cover:is_compiled(g), + {file, _File} = cover:is_compiled(a), + false = cover:is_compiled(b), + false = cover:is_compiled(g), - ?line ok = cover:reset(a), - ?line {ok, {a,{0,19}}} = cover:analyse(a, module), - ?line ok = cover:reset(). + ok = cover:reset(a), + {ok, {a,{0,19}}} = cover:analyse(a, module), + ok = cover:reset(). -stop(suite) -> []; stop(Config) when is_list(Config) -> - ?line ok = file:set_cwd(?config(data_dir, Config)), - - ?line cover_compiled = code:which(a), - ?line {ok,d} = compile:file(d, [{d,'AGE',42}]), - ?line code:purge(d), - ?line {module,d} = code:load_file(d), - ?line ok = cover:stop(), - ?line Beam = code:which(a), - ?line true = is_unloaded(Beam), - - ?line Files = lsfiles(), - ?line remove(files(Files, ".out")), - ?line remove(files(Files, ".html")), - ?line remove(files(Files, ".beam")). - -distribution(suite) -> []; + ok = file:set_cwd(proplists:get_value(data_dir, Config)), + + cover_compiled = code:which(a), + {ok,d} = compile:file(d, [{d,'AGE',42}]), + code:purge(d), + {module,d} = code:load_file(d), + ok = cover:stop(), + Beam = code:which(a), + true = is_unloaded(Beam), + + Files = lsfiles(), + remove(files(Files, ".out")), + remove(files(Files, ".html")), + remove(files(Files, ".beam")). + distribution(Config) when is_list(Config) -> - ?line DataDir = ?config(data_dir, Config), - ?line ok = file:set_cwd(DataDir), + DataDir = proplists:get_value(data_dir, Config), + ok = file:set_cwd(DataDir), - ?line {ok,N1} = ?t:start_node(cover_SUITE_distribution1,slave,[]), - ?line {ok,N2} = ?t:start_node(cover_SUITE_distribution2,slave,[]), - ?line {ok,N3} = ?t:start_node(cover_SUITE_distribution3,slave,[]), - ?line {ok,N4} = ?t:start_node(cover_SUITE_distribution4,slave,[]), + {ok,N1} = test_server:start_node(cover_SUITE_distribution1,slave,[]), + {ok,N2} = test_server:start_node(cover_SUITE_distribution2,slave,[]), + {ok,N3} = test_server:start_node(cover_SUITE_distribution3,slave,[]), + {ok,N4} = test_server:start_node(cover_SUITE_distribution4,slave,[]), %% Check that an already compiled module is loaded on new nodes - ?line {ok,f} = cover:compile(f), - ?line {ok,[_,_,_,_]} = cover:start(nodes()), - ?line cover_compiled = code:which(f), - ?line cover_compiled = rpc:call(N1,code,which,[f]), - ?line cover_compiled = rpc:call(N2,code,which,[f]), - ?line cover_compiled = rpc:call(N3,code,which,[f]), - ?line cover_compiled = rpc:call(N4,code,which,[f]), + {ok,f} = cover:compile(f), + {ok,[_,_,_,_]} = cover:start(nodes()), + cover_compiled = code:which(f), + cover_compiled = rpc:call(N1,code,which,[f]), + cover_compiled = rpc:call(N2,code,which,[f]), + cover_compiled = rpc:call(N3,code,which,[f]), + cover_compiled = rpc:call(N4,code,which,[f]), %% Check that a node cannot be started twice - ?line {ok,[]} = cover:start(N2), + {ok,[]} = cover:start(N2), %% Check that the current node (i.e. the main node) is not started with %% start/1 and not stopped with stop/1 - ?line {ok,[]} = cover:start(node()), - ?line ok = cover:stop(node()), - ?line true = is_pid(whereis(cover_server)), + {ok,[]} = cover:start(node()), + ok = cover:stop(node()), + true = is_pid(whereis(cover_server)), %% Check that a new compiled module is loaded on all existing nodes - ?line compile:file("compile_beam/v",[debug_info]), - ?line {ok,v} = cover:compile_beam(v), - ?line cover_compiled = code:which(v), - ?line cover_compiled = rpc:call(N1,code,which,[v]), - ?line cover_compiled = rpc:call(N2,code,which,[v]), - ?line cover_compiled = rpc:call(N3,code,which,[v]), - ?line cover_compiled = rpc:call(N4,code,which,[v]), - + compile:file("compile_beam/v",[debug_info]), + {ok,v} = cover:compile_beam(v), + cover_compiled = code:which(v), + cover_compiled = rpc:call(N1,code,which,[v]), + cover_compiled = rpc:call(N2,code,which,[v]), + cover_compiled = rpc:call(N3,code,which,[v]), + cover_compiled = rpc:call(N4,code,which,[v]), + %% this is lost when the node is killed - ?line rpc:call(N3,f,f2,[]), - ?line rpc:call(N3,erlang,halt,[]), + rpc:call(N3,f,f2,[]), + rpc:call(N3,erlang,halt,[]), %% this should be visible in analyse - ?line rpc:call(N1,f,f1,[]), + rpc:call(N1,f,f1,[]), %% Check that data is collected from remote node when stopped - ?line ok = cover:stop(N1), - ?line N1Beam = rpc:call(N1,code,which,[f]), - ?line true = is_unloaded(N1Beam), - ?line check_f_calls(1,0), + ok = cover:stop(N1), + N1Beam = rpc:call(N1,code,which,[f]), + true = is_unloaded(N1Beam), + check_f_calls(1,0), %% Call f:f1() again on another node and check that number of calls is %% accumulated. - ?line f:f1(), - ?line check_f_calls(2,0), - + f:f1(), + check_f_calls(2,0), + %% Check that reset works on all nodes - ?line f:f1(), - ?line rpc:call(N2,f,f1,[]), - ?line ok = cover:reset(f), - ?line check_f_calls(0,0), - + f:f1(), + rpc:call(N2,f,f1,[]), + ok = cover:reset(f), + check_f_calls(0,0), + %% Check that data is collected from all nodes - ?line rpc:call(N2,f,f1,[]), - ?line f:f2(), - ?line check_f_calls(1,1), + rpc:call(N2,f,f1,[]), + f:f2(), + check_f_calls(1,1), %% Check that same data is not fetched again (i.e. that analyse does %% reset on the remote node(s)) - ?line check_f_calls(1,1), + check_f_calls(1,1), %% Another checn that data is not fetched twice, i.e. when flushed %% then analyse should not add the same data again. - ?line rpc:call(N4,f,f2,[]), - ?line ok = cover:flush(N4), - ?line check_f_calls(1,2), + rpc:call(N4,f,f2,[]), + ok = cover:flush(N4), + check_f_calls(1,2), %% Check that flush collects data so calls are not lost if node is killed - ?line rpc:call(N4,f,f2,[]), - ?line ok = cover:flush(N4), - ?line rpc:call(N4,erlang,halt,[]), - ?line check_f_calls(1,3), + rpc:call(N4,f,f2,[]), + ok = cover:flush(N4), + rpc:call(N4,erlang,halt,[]), + check_f_calls(1,3), %% Check that stop() unloads on all nodes - ?line ok = cover:stop(), - ?line timer:sleep(100), %% Give nodes time to unload on slow machines. - ?line LocalBeam = code:which(f), - ?line N2Beam = rpc:call(N2,code,which,[f]), - ?line true = is_unloaded(LocalBeam), - ?line true = is_unloaded(N2Beam), + ok = cover:stop(), + timer:sleep(100), %% Give nodes time to unload on slow machines. + LocalBeam = code:which(f), + N2Beam = rpc:call(N2,code,which,[f]), + true = is_unloaded(LocalBeam), + true = is_unloaded(N2Beam), %% Check that cover_server on remote node does not die if main node dies - ?line {ok,[N1]} = cover:start(N1), - ?line true = is_pid(N1Server = rpc:call(N1,erlang,whereis,[cover_server])), - ?line exit(whereis(cover_server),kill), - ?line timer:sleep(100), - ?line N1Server = rpc:call(N1,erlang,whereis,[cover_server]), + {ok,[N1]} = cover:start(N1), + true = is_pid(N1Server = rpc:call(N1,erlang,whereis,[cover_server])), + exit(whereis(cover_server),kill), + timer:sleep(100), + N1Server = rpc:call(N1,erlang,whereis,[cover_server]), %% Cleanup - ?line Files = lsfiles(), - ?line remove(files(Files, ".beam")), - ?line ?t:stop_node(N1), - ?line ?t:stop_node(N2). + Files = lsfiles(), + remove(files(Files, ".beam")), + test_server:stop_node(N1), + test_server:stop_node(N2). %% Test that a lost node is reconnected reconnect(Config) -> - DataDir = ?config(data_dir, Config), + DataDir = proplists:get_value(data_dir, Config), ok = file:set_cwd(DataDir), {ok,a} = compile:file(a), {ok,b} = compile:file(b), {ok,f} = compile:file(f), - {ok,N1} = ?t:start_node(cover_SUITE_reconnect,peer, - [{args," -pa " ++ DataDir},{start_cover,false}]), + {ok,N1} = test_server:start_node(cover_SUITE_reconnect,peer, + [{args," -pa " ++ DataDir}, + {start_cover,false}]), {ok,a} = cover:compile(a), {ok,f} = cover:compile(f), {ok,[N1]} = cover:start(nodes()), @@ -600,19 +587,20 @@ reconnect(Config) -> check_f_calls(2,1), cover:stop(), - ?t:stop_node(N1), + test_server:stop_node(N1), ok. %% Test that a lost node is reconnected - also if it has been dead die_and_reconnect(Config) -> - DataDir = ?config(data_dir, Config), + DataDir = proplists:get_value(data_dir, Config), ok = file:set_cwd(DataDir), {ok,f} = compile:file(f), NodeName = cover_SUITE_die_and_reconnect, - {ok,N1} = ?t:start_node(NodeName,peer, - [{args," -pa " ++ DataDir},{start_cover,false}]), + {ok,N1} = test_server:start_node(NodeName,peer, + [{args," -pa " ++ DataDir}, + {start_cover,false}]), %% {ok,a} = cover:compile(a), {ok,f} = cover:compile(f), {ok,[N1]} = cover:start(nodes()), @@ -629,8 +617,9 @@ die_and_reconnect(Config) -> check_f_calls(1,0), % only the first call - before the flush %% Restart the node and check that cover reconnects - {ok,N1} = ?t:start_node(NodeName,peer, - [{args," -pa " ++ DataDir},{start_cover,false}]), + {ok,N1} = test_server:start_node(NodeName,peer, + [{args," -pa " ++ DataDir}, + {start_cover,false}]), timer:sleep(100), [N1] = cover:which_nodes(), % we are reconnected cover_compiled = rpc:call(N1,code,which,[f]), @@ -642,20 +631,21 @@ die_and_reconnect(Config) -> check_f_calls(2,0), cover:stop(), - ?t:stop_node(N1), + test_server:stop_node(N1), ok. %% Test that a stopped node is not marked as lost, i.e. that it is not %% reconnected if it is restarted (OTP-10638) dont_reconnect_after_stop(Config) -> - DataDir = ?config(data_dir, Config), + DataDir = proplists:get_value(data_dir, Config), ok = file:set_cwd(DataDir), {ok,f} = compile:file(f), NodeName = cover_SUITE_dont_reconnect_after_stop, - {ok,N1} = ?t:start_node(NodeName,peer, - [{args," -pa " ++ DataDir},{start_cover,false}]), + {ok,N1} = test_server:start_node(NodeName,peer, + [{args," -pa " ++ DataDir}, + {start_cover,false}]), {ok,f} = cover:compile(f), {ok,[N1]} = cover:start(nodes()), @@ -670,8 +660,9 @@ dont_reconnect_after_stop(Config) -> check_f_calls(1,0), %% Restart the node and check that cover does not reconnect - {ok,N1} = ?t:start_node(NodeName,peer, - [{args," -pa " ++ DataDir},{start_cover,false}]), + {ok,N1} = test_server:start_node(NodeName,peer, + [{args," -pa " ++ DataDir}, + {start_cover,false}]), timer:sleep(300), cover_which_nodes([]), Beam = rpc:call(N1,code,which,[f]), @@ -685,20 +676,21 @@ dont_reconnect_after_stop(Config) -> check_f_calls(1,0), cover:stop(), - ?t:stop_node(N1), + test_server:stop_node(N1), ok. %% Test that a node which is stopped while it is marked as lost is not %% reconnected if it is restarted (OTP-10638) stop_node_after_disconnect(Config) -> - DataDir = ?config(data_dir, Config), + DataDir = proplists:get_value(data_dir, Config), ok = file:set_cwd(DataDir), {ok,f} = compile:file(f), NodeName = cover_SUITE_stop_node_after_disconnect, - {ok,N1} = ?t:start_node(NodeName,peer, - [{args," -pa " ++ DataDir},{start_cover,false}]), + {ok,N1} = test_server:start_node(NodeName,peer, + [{args," -pa " ++ DataDir}, + {start_cover,false}]), {ok,f} = cover:compile(f), {ok,[N1]} = cover:start(nodes()), @@ -715,8 +707,9 @@ stop_node_after_disconnect(Config) -> cover:stop(N1), %% Restart the node and check that cover does not reconnect - {ok,N1} = ?t:start_node(NodeName,peer, - [{args," -pa " ++ DataDir},{start_cover,false}]), + {ok,N1} = test_server:start_node(NodeName,peer, + [{args," -pa " ++ DataDir}, + {start_cover,false}]), timer:sleep(300), cover_which_nodes([]), Beam = rpc:call(N1,code,which,[f]), @@ -730,11 +723,11 @@ stop_node_after_disconnect(Config) -> check_f_calls(1,0), cover:stop(), - ?t:stop_node(N1), + test_server:stop_node(N1), ok. distribution_performance(Config) -> - PrivDir = ?config(priv_dir,Config), + PrivDir = proplists:get_value(priv_dir,Config), Dir = filename:join(PrivDir,"distribution_performance"), AllFiles = filename:join(Dir,"*"), ok = filelib:ensure_dir(AllFiles), @@ -744,16 +737,16 @@ distribution_performance(Config) -> C = 10, % and each function of C clauses Mods = generate_modules(M,F,C,Dir), -% ?t:break(""), + % test_server:break(""), NodeName = cover_SUITE_distribution_performance, - {ok,N1} = ?t:start_node(NodeName,peer,[{start_cover,false}]), + {ok,N1} = test_server:start_node(NodeName,peer,[{start_cover,false}]), %% CFun = fun() -> %% [{ok,_} = cover:compile_beam(Mod) || Mod <- Mods] %% end, CFun = fun() -> cover:compile_beam(Mods) end, {CT,_CA} = timer:tc(CFun), -% erlang:display(_CA), + % erlang:display(_CA), erlang:display({compile,CT}), {SNT,_} = timer:tc(fun() -> {ok,[N1]} = cover:start(nodes()) end), @@ -761,27 +754,27 @@ distribution_performance(Config) -> [1 = rpc:call(N1,Mod,f1,[1]) || Mod <- Mods], -% Fun = fun() -> [cover:analyse(Mod,calls,function) || Mod<-Mods] end, -% Fun = fun() -> analyse_all(Mods,calls,function) end, -% Fun = fun() -> cover:analyse('_',calls,function) end, + % Fun = fun() -> [cover:analyse(Mod,calls,function) || Mod<-Mods] end, + % Fun = fun() -> analyse_all(Mods,calls,function) end, + % Fun = fun() -> cover:analyse('_',calls,function) end, Fun = fun() -> cover:analyse(Mods,calls,function) end, -% Fun = fun() -> [begin cover:analyse_to_file(Mod,[html]) end || Mod<-Mods] end, -% Fun = fun() -> analyse_all_to_file(Mods,[html]) end, -% Fun = fun() -> cover:analyse_to_file(Mods,[html]) end, -% Fun = fun() -> cover:analyse_to_file([html]) end, + % Fun = fun() -> [begin cover:analyse_to_file(Mod,[html]) end || Mod<-Mods] end, + % Fun = fun() -> analyse_all_to_file(Mods,[html]) end, + % Fun = fun() -> cover:analyse_to_file(Mods,[html]) end, + % Fun = fun() -> cover:analyse_to_file([html]) end, -% Fun = fun() -> cover:reset() end, + % Fun = fun() -> cover:reset() end, {AT,_A} = timer:tc(Fun), erlang:display({analyse,AT}), -% erlang:display(lists:sort([X || X={_MFA,N} <- lists:append([L || {ok,L}<-A]), N=/=0])), + % erlang:display(lists:sort([X || X={_MFA,N} <- lists:append([L || {ok,L}<-A]), N=/=0])), %% fprof:apply(Fun, [],[{procs,[whereis(cover_server)]}]), %% fprof:profile(), %% fprof:analyse(dest,[]), - {SNT2,_} = timer:tc(fun() -> ?t:stop_node(N1) end), + {SNT2,_} = timer:tc(fun() -> test_server:stop_node(N1) end), erlang:display({stop_node,SNT2}), code:del_path(Dir), @@ -793,10 +786,10 @@ distribution_performance(Config) -> %% Run analysis in parallel analyse_all(Mods,Analysis,Level) -> Pids = [begin - Pid = spawn(fun() -> - {ok,A} = cover:analyse(Mod,Analysis,Level), - exit(A) - end), + Pid = spawn(fun() -> + {ok,A} = cover:analyse(Mod,Analysis,Level), + exit(A) + end), erlang:monitor(process,Pid), Pid end || Mod <- Mods], @@ -804,18 +797,18 @@ analyse_all(Mods,Analysis,Level) -> analyse_all_to_file(Mods,Opts) -> Pids = [begin - Pid = cover:async_analyse_to_file(Mod,Opts), - erlang:monitor(process,Pid), - Pid - end || Mod <- Mods], + Pid = cover:async_analyse_to_file(Mod,Opts), + erlang:monitor(process,Pid), + Pid + end || Mod <- Mods], get_downs(Pids,[]). get_downs([],Acc) -> Acc; get_downs(Pids,Acc) -> receive - {'DOWN', _Ref, _Type, Pid, A} -> - get_downs(lists:delete(Pid,Pids),[A|Acc]) + {'DOWN', _Ref, _Type, Pid, A} -> + get_downs(lists:delete(Pid,Pids),[A|Acc]) end. generate_modules(0,_,_,_) -> @@ -824,8 +817,8 @@ generate_modules(M,F,C,Dir) -> ModStr = "m" ++ integer_to_list(M), Mod = list_to_atom(ModStr), Src = ["-module(",ModStr,").\n" - "-compile(export_all).\n" | - generate_functions(F,C)], + "-compile(export_all).\n" | + generate_functions(F,C)], Erl = filename:join(Dir,ModStr++".erl"), ok = file:write_file(Erl,Src), {ok,Mod} = compile:file(Erl,[{outdir,Dir},debug_info,report]), @@ -846,143 +839,133 @@ generate_clauses(C,Func) -> generate_clauses(C-1,Func)]. -export_import(suite) -> []; export_import(Config) when is_list(Config) -> - ?line DataDir = ?config(data_dir, Config), - ?line ok = file:set_cwd(DataDir), - ?line PortCount = length(erlang:ports()), + DataDir = proplists:get_value(data_dir, Config), + ok = file:set_cwd(DataDir), + PortCount = length(erlang:ports()), %% Export one module - ?line {ok,f} = cover:compile(f), - ?line f:f1(), + {ok,f} = cover:compile(f), + f:f1(), %% check that no info is written about where data comes from when no %% files are imported - ?line ?t:capture_start(), - ?line check_f_calls(1,0), - ?line [] = ?t:capture_get(), - ?line ?t:capture_stop(), - ?line ok = cover:export("f_exported",f), - ?line check_f_calls(1,0), - ?line ok = cover:stop(), - + test_server:capture_start(), + check_f_calls(1,0), + [] = test_server:capture_get(), + test_server:capture_stop(), + ok = cover:export("f_exported",f), + check_f_calls(1,0), + ok = cover:stop(), + %% Check that same data exists after import and that info is written about %% data comming from imported file - ?line ok = cover:import("f_exported"), - ?line ?t:capture_start(), - ?line check_f_calls(1,0), - ?line [Text1] = ?t:capture_get(), - ?line "Analysis includes data from imported files"++_ = lists:flatten(Text1), - ?line ?t:capture_stop(), + ok = cover:import("f_exported"), + test_server:capture_start(), + check_f_calls(1,0), + [Text1] = test_server:capture_get(), + "Analysis includes data from imported files"++_ = lists:flatten(Text1), + test_server:capture_stop(), %% Export all modules - ?line {ok,a} = cover:compile(a), - ?line ?t:capture_start(), - ?line ok = cover:export("all_exported"), - ?line [] = ?t:capture_get(), -% ?line "Export includes data from imported files"++_ = lists:flatten(Text2), - ?line ?t:capture_stop(), - ?line ok = cover:stop(), - ?line ok = cover:import("all_exported"), - ?line check_f_calls(1,0), + {ok,a} = cover:compile(a), + test_server:capture_start(), + ok = cover:export("all_exported"), + [] = test_server:capture_get(), + % "Export includes data from imported files"++_ = lists:flatten(Text2), + test_server:capture_stop(), + ok = cover:stop(), + ok = cover:import("all_exported"), + check_f_calls(1,0), %% Check that data is reset when module is compiled again, and that %% warning is written when data is deleted for imported module. - ?line ?t:capture_start(), - ?line {ok,f} = cover:compile(f), - ?line timer:sleep(10), % capture needs some time - ?line [Text3] = ?t:capture_get(), - ?line "WARNING: Deleting data for module f imported from" ++ _ = - lists:flatten(Text3), - ?line ?t:capture_stop(), - ?line check_f_calls(0,0), - + test_server:capture_start(), + {ok,f} = cover:compile(f), + timer:sleep(10), % capture needs some time + [Text3] = test_server:capture_get(), + "WARNING: Deleting data for module f imported from" ++ _ = lists:flatten(Text3), + test_server:capture_stop(), + check_f_calls(0,0), + %% Check that data is summed up when first compiled and then imported %% The module which has been compiled (f) is loaded from the file %% all_exported again (since it has been reset during cover compiling), %% but the other module (a) is not loaded since it is already loaded - ?line f:f1(), - ?line f:f2(), - ?line ok = cover:import("f_exported"), - ?line ?t:capture_start(), - ?line ok = cover:import("all_exported"), - ?line [Text4] = ?t:capture_get(), % a is not loaded again - ?line "WARNING: Module a already imported from " ++ _ = lists:flatten(Text4), - ?line ?t:capture_stop(), - ?line check_f_calls(3,1), + f:f1(), + f:f2(), + ok = cover:import("f_exported"), + test_server:capture_start(), + ok = cover:import("all_exported"), + [Text4] = test_server:capture_get(), % a is not loaded again + "WARNING: Module a already imported from " ++ _ = lists:flatten(Text4), + test_server:capture_stop(), + check_f_calls(3,1), %% Check that warning is written when same file is imported twice, %% and that data is not imported again - ?line ?t:capture_start(), - ?line ok = cover:import("all_exported"), - ?line [Text5,Text6] = ?t:capture_get(), - ?line "WARNING: Module f already imported from " ++ _ = lists:flatten(Text5), - ?line "WARNING: Module a already imported from " ++ _ = lists:flatten(Text6), - ?line ?t:capture_stop(), - ?line check_f_calls(3,1), + test_server:capture_start(), + ok = cover:import("all_exported"), + [Text5,Text6] = test_server:capture_get(), + "WARNING: Module f already imported from " ++ _ = lists:flatten(Text5), + "WARNING: Module a already imported from " ++ _ = lists:flatten(Text6), + test_server:capture_stop(), + check_f_calls(3,1), %% Check that reset removes all data and that the file which has been %% reset can be imported again with no warning - ?line cover:reset(f), - ?line check_f_calls(0,0), - ?line ?t:capture_start(), - ?line ok = cover:import("all_exported"), - ?line [Text7] = ?t:capture_get(), % warning only on mod a - ?line "WARNING: Module a already imported from " ++ _ = lists:flatten(Text7), - ?line ?t:capture_stop(), - ?line check_f_calls(1,0), + cover:reset(f), + check_f_calls(0,0), + test_server:capture_start(), + ok = cover:import("all_exported"), + [Text7] = test_server:capture_get(), % warning only on mod a + "WARNING: Module a already imported from " ++ _ = lists:flatten(Text7), + test_server:capture_stop(), + check_f_calls(1,0), %% same as above - only reset all - ?line cover:reset(), - ?line check_f_calls(0,0), - ?line ?t:capture_start(), - ?line ok = cover:import("all_exported"), - ?line [] = ?t:capture_get(), % no warnings - ?line ?t:capture_stop(), - ?line check_f_calls(1,0), + cover:reset(), + check_f_calls(0,0), + test_server:capture_start(), + ok = cover:import("all_exported"), + [] = test_server:capture_get(), % no warnings + test_server:capture_stop(), + check_f_calls(1,0), %% Check no raw files are left open - ?line PortCount = length(erlang:ports()), + PortCount = length(erlang:ports()), %% Cleanup - ?line ok = cover:stop(), - ?line Files = lsfiles(), - ?line remove(["f_exported","all_exported"|files(Files, ".beam")]). + ok = cover:stop(), + Files = lsfiles(), + remove(["f_exported","all_exported"|files(Files, ".beam")]). -otp_5031(suite) -> []; otp_5031(Config) when is_list(Config) -> + ct:timetrap({seconds, 10}), - Dog = ?t:timetrap(?t:seconds(10)), - - {ok,N1} = ?t:start_node(cover_SUITE_otp_5031,slave,[]), - ?line {ok,[N1]} = cover:start(N1), - ?line {error,not_main_node} = rpc:call(N1,cover,modules,[]), - ?line cover:stop(), - ?t:stop_node(N1), - - ?t:timetrap_cancel(Dog), + {ok,N1} = test_server:start_node(cover_SUITE_otp_5031,slave,[]), + {ok,[N1]} = cover:start(N1), + {error,not_main_node} = rpc:call(N1,cover,modules,[]), + cover:stop(), + test_server:stop_node(N1), ok. -eif(doc) -> - ["Test the \'Exclude Included Functions\' functionality"]; -eif(suite) -> - []; +%% Test the \'Exclude Included Functions\' functionality eif(Config) when is_list(Config) -> - ?line ok = file:set_cwd(filename:join(?config(data_dir, Config), - "included_functions")), - ?line {ok, cover_inc} = compile:file(cover_inc,[debug_info]), - ?line {ok, cover_inc} = cover:compile_beam(cover_inc), + ok = file:set_cwd(filename:join(proplists:get_value(data_dir, Config), + "included_functions")), + {ok, cover_inc} = compile:file(cover_inc,[debug_info]), + {ok, cover_inc} = cover:compile_beam(cover_inc), %% This function will cause an included function to be executed. %% The analysis should only show the lines that actually exist %% in cover_inc.beam - not the ones from the included file. - ?line cover_inc:func(), - ?line {ok, [_, _]} = cover:analyse(cover_inc, line), + cover_inc:func(), + {ok, [_, _]} = cover:analyse(cover_inc, line), ok. - -otp_5305(suite) -> []; + otp_5305(Config) when is_list(Config) -> - ?line ok = file:set_cwd(?config(priv_dir, Config)), + ok = file:set_cwd(proplists:get_value(priv_dir, Config)), File = "t.erl", Test = <<"-module(t). @@ -991,35 +974,32 @@ otp_5305(Config) when is_list(Config) -> t() -> ets:fun2ms(fun(X) -> X end). ">>, - ?line ok = file:write_file(File, Test), - ?line {ok, t} = cover:compile(File), - ?line ok = file:delete(File), - + ok = file:write_file(File, Test), + {ok, t} = cover:compile(File), + ok = file:delete(File), ok. -otp_5418(suite) -> []; otp_5418(Config) when is_list(Config) -> - ?line ok = file:set_cwd(?config(priv_dir, Config)), + ok = file:set_cwd(proplists:get_value(priv_dir, Config)), File = "t.erl", Test = <<"-module(t). ">>, - ?line ok = file:write_file(File, Test), - ?line {ok, t} = cover:compile(File), - ?line {ok,{t,{0,0}}} = cover:analyse(t, module), - ?line ok = file:delete(File), - + ok = file:write_file(File, Test), + {ok, t} = cover:compile(File), + {ok,{t,{0,0}}} = cover:analyse(t, module), + ok = file:delete(File), ok. otp_6115(Config) when is_list(Config) -> - ?line {ok, CWD} = file:get_cwd(), - ?line Dir = filename:join(?config(data_dir, Config), otp_6115), - ?line ok = file:set_cwd(Dir), - ?line {ok, f1} = compile:file(f1, [debug_info]), - ?line {ok, f2} = compile:file(f2, [debug_info]), + {ok, CWD} = file:get_cwd(), + Dir = filename:join(proplists:get_value(data_dir, Config), otp_6115), + ok = file:set_cwd(Dir), + {ok, f1} = compile:file(f1, [debug_info]), + {ok, f2} = compile:file(f2, [debug_info]), %% Cover compile f1, but not f2 - ?line {ok, f1} = cover:compile(f1), + {ok, f1} = cover:compile(f1), %% If f1 is cover compiled, a process P is started with a %% reference to the fun created in start_fail/0, and cover:stop() is @@ -1033,39 +1013,37 @@ otp_6115(Config) when is_list(Config) -> Pid2 = f1:start_b(), %% Now stop cover - ?line cover:stop(), - + cover:stop(), + %% Ensure that f1 is loaded (and not cover compiled), and that %% both Pid1 and Pid2 are dead. case code:which(f1) of - Beam when is_list(Beam) -> - ok; - Other -> - ?line ?t:fail({"f1 is not reloaded", Other}) + Beam when is_list(Beam) -> + ok; + Other -> + ct:fail({"f1 is not reloaded", Other}) end, case process_info(Pid1) of - undefined -> - ok; - _PI1 -> - RefToOldP1 = erlang:check_process_code(Pid1, f1), - ?t:fail({"Pid1 still alive", RefToOldP1}) + undefined -> + ok; + _PI1 -> + RefToOldP1 = erlang:check_process_code(Pid1, f1), + ct:fail({"Pid1 still alive", RefToOldP1}) end, case process_info(Pid2) of - undefined -> - ok; - _PI2 -> - RefToOldP2 = erlang:check_process_code(Pid1, f2), - ?t:fail({"Pid2 still alive", RefToOldP2}) + undefined -> + ok; + _PI2 -> + RefToOldP2 = erlang:check_process_code(Pid1, f2), + ct:fail({"Pid2 still alive", RefToOldP2}) end, - ?line file:set_cwd(CWD), + file:set_cwd(CWD), ok. -otp_7095(doc) -> - ["andalso/orelse"]; -otp_7095(suite) -> []; +%% andalso/orelse otp_7095(Config) when is_list(Config) -> - ?line ok = file:set_cwd(?config(priv_dir, Config)), + ok = file:set_cwd(proplists:get_value(priv_dir, Config)), File = "t.erl", Test = <<"-module(t). @@ -1151,90 +1129,84 @@ otp_7095(Config) when is_list(Config) -> add_one(T) -> put(T, get(T) + 1). % 82 ">>, - ?line ok = file:write_file(File, Test), - ?line {ok, t} = cover:compile(File), - ?line ok = t:t(), - ?line {ok,[{{t,4},1},{{t,5},1},{{t,6},1},{{t,7},1},{{t,8},1},{{t,9},1}, - {{t,10},1},{{t,11},1},{{t,12},1},{{t,13},1},{{t,14},1}, - {{t,15},1},{{t,16},1},{{t,17},1}, - {{t,20},1},{{t,22},0}, - {{t,25},1},{{t,27},1}, - {{t,30},1},{{t,32},1}, - {{t,35},1},{{t,37},0}, - {{t,40},1},{{t,42},1},{{t,44},1}, - {{t,47},1},{{t,48},1}, - {{t,51},1},{{t,53},1},{{t,55},0}, - {{t,58},1},{{t,60},1},{{t,62},1},{{t,64},0}, - {{t,67},1},{{t,69},1},{{t,71},1},{{t,74},1}, - {{t,76},0},{{t,78},1}, - {{t,82},2}]} = cover:analyse(t, calls, line), - ?line ok = file:delete(File), - + ok = file:write_file(File, Test), + {ok, t} = cover:compile(File), + ok = t:t(), + {ok,[{{t,4},1},{{t,5},1},{{t,6},1},{{t,7},1},{{t,8},1},{{t,9},1}, + {{t,10},1},{{t,11},1},{{t,12},1},{{t,13},1},{{t,14},1}, + {{t,15},1},{{t,16},1},{{t,17},1}, + {{t,20},1},{{t,22},0}, + {{t,25},1},{{t,27},1}, + {{t,30},1},{{t,32},1}, + {{t,35},1},{{t,37},0}, + {{t,40},1},{{t,42},1},{{t,44},1}, + {{t,47},1},{{t,48},1}, + {{t,51},1},{{t,53},1},{{t,55},0}, + {{t,58},1},{{t,60},1},{{t,62},1},{{t,64},0}, + {{t,67},1},{{t,69},1},{{t,71},1},{{t,74},1}, + {{t,76},0},{{t,78},1}, + {{t,82},2}]} = cover:analyse(t, calls, line), + ok = file:delete(File), ok. -otp_8270(doc) -> - ["OTP-8270. Bug."]; -otp_8270(suite) -> []; +%% OTP-8270. Bug. otp_8270(Config) when is_list(Config) -> - ?line DataDir = ?config(data_dir, Config), - ?line ok = file:set_cwd(DataDir), + DataDir = proplists:get_value(data_dir, Config), + ok = file:set_cwd(DataDir), - ?line PrivDir = ?config(priv_dir, Config), + PrivDir = proplists:get_value(priv_dir, Config), As = [{args," -pa " ++ PrivDir}], - ?line {ok,N1} = ?t:start_node(cover_n1,slave,As), - ?line {ok,N2} = ?t:start_node(cover_n2,slave,As), - ?line {ok,N3} = ?t:start_node(cover_n3,slave,As), - + {ok,N1} = test_server:start_node(cover_n1,slave,As), + {ok,N2} = test_server:start_node(cover_n2,slave,As), + {ok,N3} = test_server:start_node(cover_n3,slave,As), + timer:sleep(500), {ok,[_,_,_]} = cover:start(nodes()), - Test = << - "-module(m).\n" - "-compile(export_all).\n" - "t() -> t(0).\n" - "l() ->\n" - " catch ets:tab2list(cover_internal_data_table).\n" - "t(Sz) ->\n" - " case ets:info(cover_internal_data_table, size) of\n" - " Sz ->\n" - " m:t(Sz); % Not a local call! Newly loaded code is entered.\n" - " NSz ->\n" - " % error_logger:info_msg(\"~p: ~p ~p change~n L1 ~p~n\", \n" - " % [node(), Sz, NSz, l()]),\n" - " m:t(NSz)\n" - " end.\n">>, - ?line _File = c_mod(m, Test, Config), + Test = <<"-module(m).\n" + "-compile(export_all).\n" + "t() -> t(0).\n" + "l() ->\n" + " catch ets:tab2list(cover_internal_data_table).\n" + "t(Sz) ->\n" + " case ets:info(cover_internal_data_table, size) of\n" + " Sz ->\n" + " m:t(Sz); % Not a local call! Newly loaded code is entered.\n" + " NSz ->\n" + " % error_logger:info_msg(\"~p: ~p ~p change~n L1 ~p~n\", \n" + " % [node(), Sz, NSz, l()]),\n" + " m:t(NSz)\n" + " end.\n">>, + _File = c_mod(m, Test, Config), Fun = fun m:t/0, - ?line Pid1 = spawn(Fun), - ?line Pid2 = spawn(N1, Fun), - ?line Pid3 = spawn(N2, Fun), - ?line Pid4 = spawn(N3, Fun), + Pid1 = spawn(Fun), + Pid2 = spawn(N1, Fun), + Pid3 = spawn(N2, Fun), + Pid4 = spawn(N3, Fun), - ?line {ok, m} = cover:compile_beam(m), + {ok, m} = cover:compile_beam(m), timer:sleep(1000), - ?line Info = erlang:process_info(Pid1), - ?line N1_info = rpc:call(N1, erlang, process_info, [Pid2]), - ?line N2_info = rpc:call(N2, erlang, process_info, [Pid3]), - ?line N3_info = rpc:call(N3, erlang, process_info, [Pid4]), + Info = erlang:process_info(Pid1), + N1_info = rpc:call(N1, erlang, process_info, [Pid2]), + N2_info = rpc:call(N2, erlang, process_info, [Pid3]), + N3_info = rpc:call(N3, erlang, process_info, [Pid4]), - ?line true = is_list(Info), - ?line {N1,true} = {N1,is_list(N1_info)}, - ?line {N2,true} = {N2,is_list(N2_info)}, - ?line {N3,true} = {N3,is_list(N3_info)}, + true = is_list(Info), + {N1,true} = {N1,is_list(N1_info)}, + {N2,true} = {N2,is_list(N2_info)}, + {N3,true} = {N3,is_list(N3_info)}, exit(Pid1,kill), - ?line ?t:stop_node(N1), - ?line ?t:stop_node(N2), - ?line ?t:stop_node(N3), + test_server:stop_node(N1), + test_server:stop_node(N2), + test_server:stop_node(N3), ok. -otp_8273(doc) -> - ["OTP-8273. Bug."]; -otp_8273(suite) -> []; +%% OTP-8273. Bug. otp_8273(Config) when is_list(Config) -> Test = <<"-module(t). -export([t/0]). @@ -1243,27 +1215,22 @@ otp_8273(Config) when is_list(Config) -> bar = false orelse bar, ok. ">>, - ?line File = cc_mod(t, Test, Config), - ?line ok = t:t(), - ?line ok = file:delete(File), + File = cc_mod(t, Test, Config), + ok = t:t(), + ok = file:delete(File), ok. -otp_8340(doc) -> - ["OTP-8340. Bug."]; -otp_8340(suite) -> []; +%% OTP-8340. Bug. otp_8340(Config) when is_list(Config) -> - ?line [{{t,1},1},{{t,4},1}] = - analyse_expr(<<"<< \n" - " <<3:2, \n" - " SeqId:62>> \n" - " || SeqId <- [64] >>">>, Config), - + [{{t,1},1},{{t,2},1},{{t,4},1}] = + analyse_expr(<<"<< \n" + " <<3:2, \n" + " SeqId:62>> \n" + " || SeqId <- [64] >>">>, Config), ok. -otp_8188(doc) -> - ["Clauses on the same line."]; -otp_8188(suite) -> []; +%% Clauses on the same line. otp_8188(Config) when is_list(Config) -> %% This example covers the bug report: Test = <<"-module(t). @@ -1279,10 +1246,10 @@ otp_8188(Config) when is_list(Config) -> _Res = ?FOOBAR(X). ">>, - ?line File = cc_mod(t, Test, Config), - ?line false = t:test(nok), - ?line {ok,[{{t,11},1},{{t,12},1}]} = cover:analyse(t, calls, line), - ?line ok = file:delete(File), + File = cc_mod(t, Test, Config), + false = t:test(nok), + {ok,[{{t,11},1},{{t,12},1}]} = cover:analyse(t, calls, line), + ok = file:delete(File), %% Bit string comprehensions are now traversed; %% the handling of list comprehensions has been improved: @@ -1293,39 +1260,39 @@ otp_8188(Config) when is_list(Config) -> ok. bug_8188(Cf) -> - ?line [{{t,1},1},{{t,2},1},{{t,3},1}] = - analyse_expr(<<"A = 3,\n" % 1 - " case A of\n" % 1 - " 2 -> two; 3 -> three end, A + 2">>, % 1 - Cf), - - ?line [{{t,1},1}, - {{t,2},0}, - {{t,3},1}, - {{t,4},1}, - {{t,5},1}, - {{t,6},0}, - {{t,7},1}, - {{t,9},2}] = - analyse_expr(<<"case two() of\n" % 1 - " 1 -> 2;\n" % 0 - " _ -> begin 3 end\n" % 1 - " +\n" % 1 - " begin 4 end end, case two() of\n" % 1 - " 1 -> a;\n" % 0 - " 2 -> b; 3 -> c\n" % 1 - " end.\n" - "two() -> 2">>, Cf), % 2 - - ?line [{{t,1},1}, {{t,2},1}, {{t,3},1}, - {{t,4},1}, {{t,5},1}, {{t,6},0}] = - analyse_expr(<<" self() ! 1,\n" - " receive \n" - " X=1 -> a;\n" - " X=2 -> b end, case X of \n" - " 1 -> a;\n" - " 2 -> b\n" - " end">>, Cf), + [{{t,1},1},{{t,2},1},{{t,3},1}] = + analyse_expr(<<"A = 3,\n" % 1 + " case A of\n" % 1 + " 2 -> two; 3 -> three end, A + 2">>, % 1 + Cf), + + [{{t,1},1}, + {{t,2},0}, + {{t,3},1}, + {{t,4},1}, + {{t,5},1}, + {{t,6},0}, + {{t,7},1}, + {{t,9},2}] = + analyse_expr(<<"case two() of\n" % 1 + " 1 -> 2;\n" % 0 + " _ -> begin 3 end\n" % 1 + " +\n" % 1 + " begin 4 end end, case two() of\n" % 1 + " 1 -> a;\n" % 0 + " 2 -> b; 3 -> c\n" % 1 + " end.\n" + "two() -> 2">>, Cf), % 2 + + [{{t,1},1}, {{t,2},1}, {{t,3},1}, + {{t,4},1}, {{t,5},1}, {{t,6},0}] = + analyse_expr(<<" self() ! 1,\n" + " receive \n" + " X=1 -> a;\n" + " X=2 -> b end, case X of \n" + " 1 -> a;\n" + " 2 -> b\n" + " end">>, Cf), T0 = <<"t1(X) ->\n " "case X of\n" @@ -1339,42 +1306,42 @@ bug_8188(Cf) -> " end">>, T1 = [<<"a = t1(1). ">>,T0], - ?line [{{t,1},1}, {{t,2},1}, {{t,3},1}, {{t,4},0}, - {{t,5},0}, {{t,6},1}, {{t,7},1}, {{t,8},0}, {{t,9},0}] = - analyse_expr(T1, Cf), + [{{t,1},1}, {{t,2},1}, {{t,3},1}, {{t,4},0}, + {{t,5},0}, {{t,6},1}, {{t,7},1}, {{t,8},0}, {{t,9},0}] = + analyse_expr(T1, Cf), T2 = [<<"b = t1(2). ">>,T0], - ?line [{{t,1},1}, {{t,2},1}, {{t,3},0}, {{t,4},1}, - {{t,5},0}, {{t,6},1}, {{t,7},0}, {{t,8},1}, {{t,9},0}] = - analyse_expr(T2, Cf), + [{{t,1},1}, {{t,2},1}, {{t,3},0}, {{t,4},1}, + {{t,5},0}, {{t,6},1}, {{t,7},0}, {{t,8},1}, {{t,9},0}] = + analyse_expr(T2, Cf), T3 = [<<"c = t1(3). ">>,T0], - ?line [{{t,1},1}, {{t,2},1}, {{t,3},0}, {{t,4},1}, - {{t,5},1}, {{t,6},1}, {{t,7},0}, {{t,8},1}, {{t,9},0}] = - analyse_expr(T3, Cf), + [{{t,1},1}, {{t,2},1}, {{t,3},0}, {{t,4},1}, + {{t,5},1}, {{t,6},1}, {{t,7},0}, {{t,8},1}, {{t,9},0}] = + analyse_expr(T3, Cf), T4 = [<<"d = t1(4). ">>,T0], - ?line [{{t,1},1}, {{t,2},1}, {{t,3},0}, {{t,4},0}, - {{t,5},0}, {{t,6},1}, {{t,7},0}, {{t,8},0}, {{t,9},1}] = - analyse_expr(T4, Cf), - - ?line [{{t,1},1},{{t,2},1},{{t,3},1},{{t,4},1},{{t,5},1}] = - analyse_expr( - <<"2 = x3(1). " - "x3(X) ->\n" - " case X of \n" - " 1 -> case X of\n" - " 1 -> a, Y = 2;\n" - " 2 -> b, Y = 3 end, Y; 2 -> Y = 4 end, Y">>, Cf), - - ?line [{{t,1},1},{{t,2},1},{{t,3},1},{{t,4},1}] = - analyse_expr( - <<"1 = x4(1). " - "x4(X) ->\n" - " case X of\n" - " 1 -> case X of\n" - " 1 -> Y = 1 end, case X of 1 -> Y = 1 end, Y end">>, - Cf), + [{{t,1},1}, {{t,2},1}, {{t,3},0}, {{t,4},0}, + {{t,5},0}, {{t,6},1}, {{t,7},0}, {{t,8},0}, {{t,9},1}] = + analyse_expr(T4, Cf), + + [{{t,1},1},{{t,2},1},{{t,3},1},{{t,4},1},{{t,5},1}] = + analyse_expr( + <<"2 = x3(1). " + "x3(X) ->\n" + " case X of \n" + " 1 -> case X of\n" + " 1 -> a, Y = 2;\n" + " 2 -> b, Y = 3 end, Y; 2 -> Y = 4 end, Y">>, Cf), + + [{{t,1},1},{{t,2},1},{{t,3},1},{{t,4},1}] = + analyse_expr( + <<"1 = x4(1). " + "x4(X) ->\n" + " case X of\n" + " 1 -> case X of\n" + " 1 -> Y = 1 end, case X of 1 -> Y = 1 end, Y end">>, + Cf), T10 = <<"t1(X) ->\n" "if\n" @@ -1386,19 +1353,16 @@ bug_8188(Cf) -> " 2 -> b; 3 -> c\n" " end">>, T11 = [<<"a = t1(1). ">>,T10], - ?line [{{t,1},1}, {{t,2},1}, {{t,3},1}, {{t,4},1}, - {{t,5},1}, {{t,6},1}, {{t,7},1}, {{t,8},0}] = - analyse_expr(T11, Cf), + [{{t,1},1}, {{t,2},1}, {{t,3},1}, {{t,4},1}, + {{t,5},1}, {{t,6},1}, {{t,7},1}, {{t,8},0}] = analyse_expr(T11, Cf), T12 = [<<"b = t1(2). ">>,T10], - ?line [{{t,1},1}, {{t,2},1}, {{t,3},0}, {{t,4},1}, - {{t,5},0}, {{t,6},1}, {{t,7},0}, {{t,8},1}] = - analyse_expr(T12, Cf), + [{{t,1},1}, {{t,2},1}, {{t,3},0}, {{t,4},1}, + {{t,5},0}, {{t,6},1}, {{t,7},0}, {{t,8},1}] = analyse_expr(T12, Cf), T13 = [<<"c = t1(3). ">>,T10], - ?line [{{t,1},1}, {{t,2},1}, {{t,3},0}, {{t,4},1}, - {{t,5},0}, {{t,6},1}, {{t,7},0}, {{t,8},1}] = - analyse_expr(T13, Cf), + [{{t,1},1}, {{t,2},1}, {{t,3},0}, {{t,4},1}, + {{t,5},0}, {{t,6},1}, {{t,7},0}, {{t,8},1}] = analyse_expr(T13, Cf), T20 = <<"t1(X) ->\n" "case X of\n" @@ -1411,206 +1375,185 @@ bug_8188(Cf) -> " end">>, T21 = [<<"a = t1(1). ">>,T20], - ?line [{{t,1},1}, {{t,2},1}, {{t,3},1}, {{t,4},0}, - {{t,5},0}, {{t,6},1}, {{t,7},1}, {{t,8},0}] = - analyse_expr(T21, Cf), + [{{t,1},1}, {{t,2},1}, {{t,3},1}, {{t,4},0}, + {{t,5},0}, {{t,6},1}, {{t,7},1}, {{t,8},0}] = analyse_expr(T21, Cf), T22 = [<<"b = t1(2). ">>,T20], - ?line [{{t,1},1}, {{t,2},1}, {{t,3},0}, {{t,4},1}, - {{t,5},0}, {{t,6},1}, {{t,7},0}, {{t,8},1}] = - analyse_expr(T22, Cf), + [{{t,1},1}, {{t,2},1}, {{t,3},0}, {{t,4},1}, + {{t,5},0}, {{t,6},1}, {{t,7},0}, {{t,8},1}] = analyse_expr(T22, Cf), T23 = [<<"c = t1(3). ">>,T20], - ?line [{{t,1},1}, {{t,2},1}, {{t,3},0}, {{t,4},1}, - {{t,5},0}, {{t,6},1}, {{t,7},0}, {{t,8},1}] = - analyse_expr(T23, Cf), + [{{t,1},1}, {{t,2},1}, {{t,3},0}, {{t,4},1}, + {{t,5},0}, {{t,6},1}, {{t,7},0}, {{t,8},1}] = analyse_expr(T23, Cf), T30 = << - "t1(X) ->\n" - "case X of\n" - " 1 -> a;\n" - " 2 -> b; 3 -> case X of 1 -> a; 2 -> b; 3 -> c end end, case X of\n" - " 1 -> a;\n" - " 2 -> b; 3 -> c\n" - " end\n">>, + "t1(X) ->\n" + "case X of\n" + " 1 -> a;\n" + " 2 -> b; 3 -> case X of 1 -> a; 2 -> b; 3 -> c end end, case X of\n" + " 1 -> a;\n" + " 2 -> b; 3 -> c\n" + " end\n">>, T31 = [<<"a = t1(1). ">>,T30], - ?line [{{t,1},1}, {{t,2},1}, {{t,3},1}, - {{t,4},1}, {{t,5},1}, {{t,6},0}] = - analyse_expr(T31, Cf), + [{{t,1},1}, {{t,2},1}, {{t,3},1}, + {{t,4},1}, {{t,5},1}, {{t,6},0}] = analyse_expr(T31, Cf), T32 = [<<"b = t1(2). ">>,T30], - ?line [{{t,1},1}, {{t,2},1}, {{t,3},0}, - {{t,4},1}, {{t,5},0}, {{t,6},1}] = - analyse_expr(T32, Cf), + [{{t,1},1}, {{t,2},1}, {{t,3},0}, + {{t,4},1}, {{t,5},0}, {{t,6},1}] = analyse_expr(T32, Cf), T33 = [<<"c = t1(3). ">>,T30], - ?line [{{t,1},1}, {{t,2},1}, {{t,3},0}, - {{t,4},1}, {{t,5},0}, {{t,6},1}] = - analyse_expr(T33, Cf), + [{{t,1},1}, {{t,2},1}, {{t,3},0}, + {{t,4},1}, {{t,5},0}, {{t,6},1}] = analyse_expr(T33, Cf), %% 'try' now traverses the body as a body... - ?line [{{t,1},1},{{t,2},1},{{t,3},1},{{t,4},0},{{t,6},1}] = - analyse_expr(<<"try \n" - " B = 2, \n" - " C = erlang:error(foo), \n" - " {B,C} \n" - "catch _:_ -> \n" - " foo \n" - "end">>, Cf), + [{{t,1},1},{{t,2},1},{{t,3},1},{{t,4},0},{{t,6},1}] = + analyse_expr(<<"try \n" + " B = 2, \n" + " C = erlang:error(foo), \n" + " {B,C} \n" + "catch _:_ -> \n" + " foo \n" + "end">>, Cf), %% receive after: - ?line [{{t,1},1},{{t,2},0},{{t,3},1}] = - analyse_expr(<<"receive \n" - " X=1 -> a; \n" - " X=2 -> b after begin 10 end -> X=3 end">>, Cf), - ?line [{{t,1},1},{{t,2},0},{{t,3},1}] = - analyse_expr(<<"receive \n" - " X=1 -> a; \n" - " X=2 -> b after 10 -> begin X=3 end end">>, Cf), + [{{t,1},1},{{t,2},0},{{t,3},1}] = + analyse_expr(<<"receive \n" + " X=1 -> a; \n" + " X=2 -> b after begin 10 end -> X=3 end">>, Cf), + [{{t,1},1},{{t,2},0},{{t,3},1}] = + analyse_expr(<<"receive \n" + " X=1 -> a; \n" + " X=2 -> b after 10 -> begin X=3 end end">>, Cf), ok. comprehension_8188(Cf) -> - ?line [{{t,1},1}] = - analyse_expr(<<"[begin X end || X <- [1,2,3], X > 1]">>, Cf), - ?line [{{t,1},1},{{t,2},1}] = - analyse_expr(<<"[begin X end || \n" - " X <- [1,2,3], X > 1]">>, Cf), - ?line [{{t,1},1},{{t,2},1},{{t,3},3}] = - analyse_expr(<<"[begin X end || \n " - " X <- [1,2,3], \n " - " X > 1]">>, Cf), - ?line [{{t,1},1},{{t,3},1},{{t,4},3}] = - analyse_expr(<<"[begin X end || \n " - " X <- \n " - " [1,2,3], \n " - " X > 1]">>, Cf), - ?line [{{t,1},1},{{t,2},2}] = - analyse_expr(<<"[ \n " - " X || X <- [1,2,3], X > 1]">>, Cf), - ?line [{{t,1},1},{{t,2},2},{{t,3},3}] = - analyse_expr(<<"[ \n" - " X || X <- [1,2,3], \n" - " X > 1]">>, Cf), - ?line [{{t,1},1},{{t,2},1},{{t,3},2}] = - analyse_expr(<<"[ \n " - " X || X <- [1,2,3], X > 1, \n" - " X > 2]">>, Cf), - - ?line [{{t,1},1}, - {{t,3},2}, - {{t,5},1}, - {{t,7},1}, - {{t,8},0}, - {{t,12},3}, - {{t,15},2}, - {{t,17},2}, - {{t,18},1}] = - analyse_expr(<<"[ \n" % 1 - " begin\n" - " X * 2\n" % 2 - " end ||\n" - " X <- [1,\n" % 1 - " case two() of\n" - " 2 -> 2;\n" % 1 - " _ -> two\n" % 0 - " end,\n" - " 3],\n" - " begin\n" - " math:sqrt(X) > 1.0\n" % 3 - " end,\n" - " begin\n" - " true\n" % 2 - " end,\n" - " true]. \n" % 2 - " two() -> 2">>, Cf), % 1 - - ?line [{{t,1},1}, - {{t,2},2}, - {{t,3},1}, - {{t,5},1}, - {{t,6},0}, - {{t,9},3}, - {{t,10},2}, - {{t,11},2}, - {{t,12},1}] = - analyse_expr(<<"[ \n" - " X * 2 || \n" % 2 - " X <- [1,\n" % 1 - " case two() of\n" - " 2 -> 2;\n" % 1 - " _ -> two\n" % 0 - " end,\n" - " 3],\n" - " math:sqrt(X) > 1.0,\n" % 3 - " true,\n" % 2 - " true]. \n" % 2 - " two() -> 2">>, Cf), % 1 - - %% The template cannot have a counter since it is not allowed to - %% be a block. - ?line [{{t,1},1}, - %% {{t,2},2}, - {{t,3},1}, - {{t,4},1}, - {{t,5},0}, - {{t,8},1}, - {{t,9},0}, - {{t,12},3}, - {{t,13},2}, - {{t,14},2}] = - analyse_expr(<<"<< \n" % 1 - " << (X*2) >> || \n" % 2 (now: 0) - " <<X>> <= << (case two() of\n" - " 2 -> 1;\n" % 1 - " _ -> 2\n" % 0 - " end)/integer,\n" - " (case two() of \n" - " 2 -> 2;\n" % 1 - " _ -> two\n" % 0 - " end)/integer,\n" - " 3 >>, \n" - " math:sqrt(X) > 1.0,\n" % 3 - " true >>.\n" % 2 - "two() -> 2">>, Cf), - - ?line [{{t,1},1}, - %% {{t,2},4}, - {{t,4},1}, - {{t,6},1}, - {{t,7},0}, - {{t,10},3}, - {{t,11},2}, - {{t,12},4}, - {{t,13},1}] = - analyse_expr(<<"<< \n" % 1 - " << (2)\n" % 4 (now: 0) - " :(8) >> || \n" - " <<X>> <= << 1,\n" % 1 - " (case two() of \n" - " 2 -> 2;\n" % 1 - " _ -> two\n" % 0 - " end)/integer,\n" - " 3 >>, \n" - " math:sqrt(X) > 1.0,\n" % 3 - " <<_>> <= << 1, 2 >>,\n" % 2 - " true >>.\n" % 4 - "two() -> 2">>, Cf), % 1 - + [{{t,1},1}] = analyse_expr(<<"[begin X end || X <- [1,2,3], X > 1]">>, Cf), + [{{t,1},1},{{t,2},1}] = analyse_expr(<<"[begin X end || \n" + " X <- [1,2,3], X > 1]">>, Cf), + [{{t,1},1},{{t,2},1},{{t,3},3}] = analyse_expr(<<"[begin X end || \n " + " X <- [1,2,3], \n " + " X > 1]">>, Cf), + [{{t,1},1},{{t,3},1},{{t,4},3}] = analyse_expr(<<"[begin X end || \n " + " X <- \n " + " [1,2,3], \n " + " X > 1]">>, Cf), + [{{t,1},1},{{t,2},2}] = analyse_expr(<<"[ \n " + " X || X <- [1,2,3], X > 1]">>, Cf), + [{{t,1},1},{{t,2},2},{{t,3},3}] = analyse_expr(<<"[ \n" + " X || X <- [1,2,3], \n" + " X > 1]">>, Cf), + [{{t,1},1},{{t,2},1},{{t,3},2}] = analyse_expr(<<"[ \n " + " X || X <- [1,2,3], X > 1, \n" + " X > 2]">>, Cf), + + [{{t,1},1}, + {{t,3},2}, + {{t,5},1}, + {{t,7},1}, + {{t,8},0}, + {{t,12},3}, + {{t,15},2}, + {{t,17},2}, + {{t,18},1}] = analyse_expr(<<"[ \n" % 1 + " begin\n" + " X * 2\n" % 2 + " end ||\n" + " X <- [1,\n" % 1 + " case two() of\n" + " 2 -> 2;\n" % 1 + " _ -> two\n" % 0 + " end,\n" + " 3],\n" + " begin\n" + " math:sqrt(X) > 1.0\n" % 3 + " end,\n" + " begin\n" + " true\n" % 2 + " end,\n" + " true]. \n" % 2 + " two() -> 2">>, Cf), % 1 + + [{{t,1},1}, + {{t,2},2}, + {{t,3},1}, + {{t,5},1}, + {{t,6},0}, + {{t,9},3}, + {{t,10},2}, + {{t,11},2}, + {{t,12},1}] = analyse_expr(<<"[ \n" + " X * 2 || \n" % 2 + " X <- [1,\n" % 1 + " case two() of\n" + " 2 -> 2;\n" % 1 + " _ -> two\n" % 0 + " end,\n" + " 3],\n" + " math:sqrt(X) > 1.0,\n" % 3 + " true,\n" % 2 + " true]. \n" % 2 + " two() -> 2">>, Cf), % 1 + + [{{t,1},1}, + {{t,2},2}, + {{t,3},1}, + {{t,4},1}, + {{t,5},0}, + {{t,8},1}, + {{t,9},0}, + {{t,12},3}, + {{t,13},2}, + {{t,14},2}] = analyse_expr(<<"<< \n" % 1 + " << (X*2) >> || \n" % 2 + " <<X>> <= << (case two() of\n" + " 2 -> 1;\n" % 1 + " _ -> 2\n" % 0 + " end)/integer,\n" + " (case two() of \n" + " 2 -> 2;\n" % 1 + " _ -> two\n" % 0 + " end)/integer,\n" + " 3 >>, \n" + " math:sqrt(X) > 1.0,\n" % 3 + " true >>.\n" % 2 + "two() -> 2">>, Cf), + [{{t,1},1}, + {{t,2},4}, + {{t,4},1}, + {{t,6},1}, + {{t,7},0}, + {{t,10},3}, + {{t,11},2}, + {{t,12},4}, + {{t,13},1}] = analyse_expr(<<"<< \n" % 1 + " << (2)\n" % 4 + " :(8) >> || \n" + " <<X>> <= << 1,\n" % 1 + " (case two() of \n" + " 2 -> 2;\n" % 1 + " _ -> two\n" % 0 + " end)/integer,\n" + " 3 >>, \n" + " math:sqrt(X) > 1.0,\n" % 3 + " <<_>> <= << 1, 2 >>,\n" % 2 + " true >>.\n" % 4 + "two() -> 2">>, Cf), % 1 ok. eep37(Config) when is_list(Config) -> [{{t,1},1},{{t,2},1},{{t,4},6},{{t,6},1},{{t,8},1}] = - analyse_expr(<<"begin\n" % 1 - " F =\n" % 1 - " fun Fact(N) when N > 0 ->\n" - " N * Fact(N - 1);\n" % 6 - " Fact(0) ->\n" - " 1\n" % 1 - " end,\n" - " F(6)\n" % 1 - "end\n">>, - Config), + analyse_expr(<<"begin\n" % 1 + " F =\n" % 1 + " fun Fact(N) when N > 0 ->\n" + " N * Fact(N - 1);\n" % 6 + " Fact(0) ->\n" + " 1\n" % 1 + " end,\n" + " F(6)\n" % 1 + "end\n">>, + Config), ok. otp_10979_hanging_node(_Config) -> @@ -1623,42 +1566,40 @@ otp_10979_hanging_node(_Config) -> P2 = processes(), case P2--P1 of - [] -> - ok; - New -> - [io:format("New: ~p, ~p~n",[P,process_info(P)]) || P<-New], - ct:fail(hanging_process) + [] -> + ok; + New -> + [io:format("New: ~p, ~p~n",[P,process_info(P)]) || P<-New], + ct:fail(hanging_process) end, ok. -compile_beam_opts(doc) -> - ["Take compiler options from beam in cover:compile_beam"]; -compile_beam_opts(suite) -> []; +%% Take compiler options from beam in cover:compile_beam compile_beam_opts(Config) when is_list(Config) -> {ok, Cwd} = file:get_cwd(), - ok = file:set_cwd(?config(priv_dir, Config)), - IncDir = filename:join(?config(data_dir, Config), - "included_functions"), - File = filename:join([?config(data_dir, Config), "otp_11439", "t.erl"]), + ok = file:set_cwd(proplists:get_value(priv_dir, Config)), + IncDir = filename:join(proplists:get_value(data_dir, Config), + "included_functions"), + File = filename:join([proplists:get_value(data_dir, Config), "otp_11439", "t.erl"]), %% use all compiler options allowed by cover:filter_options %% i and d don't make sense when compiling from beam though {ok, t} = - compile:file(File, [{i, IncDir}, - {d, 'BOOL'}, - {d, 'MACRO', macro_defined}, - export_all, - debug_info, - return_errors]), + compile:file(File, [{i, IncDir}, + {d, 'BOOL'}, + {d, 'MACRO', macro_defined}, + export_all, + debug_info, + return_errors]), code:purge(t), code:delete(t), Exports = - [{func1,0}, - {macro, 0}, - {exported,0}, - {nonexported,0}, - {module_info,0}, - {module_info,1}], + [{func1,0}, + {macro, 0}, + {exported,0}, + {nonexported,0}, + {module_info,0}, + {module_info,1}], Exports = t:module_info(exports), {ok, t} = cover:compile_beam("t"), Exports = t:module_info(exports), @@ -1666,12 +1607,10 @@ compile_beam_opts(Config) when is_list(Config) -> ok = file:set_cwd(Cwd), ok. -analyse_no_beam(doc) -> - ["Don't crash if beam is not available"]; -analyse_no_beam(suite) -> []; +%% Don't crash if beam is not available analyse_no_beam(Config) when is_list(Config) -> {ok, Cwd} = file:get_cwd(), - ok = file:set_cwd(?config(data_dir, Config)), + ok = file:set_cwd(proplists:get_value(data_dir, Config)), code:purge(t), code:delete(t), @@ -1709,8 +1648,8 @@ analyse_no_beam(Config) when is_list(Config) -> %% file in this situation. The test below tests that this bug is %% corrected. line_0(Config) -> - ok = file:set_cwd(filename:join(?config(data_dir, Config), - "include_eunit_hrl")), + ok = file:set_cwd(filename:join(proplists:get_value(data_dir, Config), + "include_eunit_hrl")), {ok, cover_inc_eunit} = compile:file(cover_inc_eunit,[debug_info]), {ok, cover_inc_eunit} = cover:compile_beam(cover_inc_eunit), {ok, CovOut} = cover:analyse_to_file(cover_inc_eunit), @@ -1725,14 +1664,14 @@ line_0(Config) -> %% OTP-13200: Return error instead of crashing when trying to compile %% a beam which has no 'file' attribute. compile_beam_no_file(Config) -> - PrivDir = ?config(priv_dir,Config), + PrivDir = proplists:get_value(priv_dir,Config), Dir = filename:join(PrivDir,"compile_beam_no_file"), ok = filelib:ensure_dir(filename:join(Dir,"*")), code:add_patha(Dir), Str = lists:concat( - ["-module(nofile).\n" - "-compile(export_all).\n" - "foo() -> ok.\n"]), + ["-module(nofile).\n" + "-compile(export_all).\n" + "foo() -> ok.\n"]), TT = do_scan(Str), Forms = [ begin {ok,Y} = erl_parse:parse_form(X),Y end || X <- TT ], {ok,_,Bin} = compile:forms(Forms,[debug_info]), @@ -1748,8 +1687,7 @@ do_scan(Str) -> {done,{ok,T,_},C} = erl_scan:tokens([],Str,0), [ T | do_scan(C) ]. -otp_13277(doc) -> - ["PR 856. Fix a bc bug."]; +%% PR 856. Fix a bc bug. otp_13277(Config) -> Test = <<"-module(t). -export([t/0]). @@ -1761,9 +1699,24 @@ otp_13277(Config) -> t() -> pad(<<\"hi\">>, 2). ">>, - ?line File = cc_mod(t, Test, Config), - ?line <<"hi##">> = t:t(), - ?line ok = file:delete(File), + File = cc_mod(t, Test, Config), + <<"hi##">> = t:t(), + ok = file:delete(File), + ok. + +%% Test general expressions in a binary comprehension. +otp_13289(Config) -> + Test = <<"-module(t). + -export([t/0]). + + t() -> + << (id(<<I>>)) || I <- [1,2,3] >>. + + id(I) -> I. + ">>, + File = cc_mod(t, Test, Config), + <<1,2,3>> = t:t(), + ok = file:delete(File), ok. %%--Auxiliary------------------------------------------------------------ @@ -1780,7 +1733,7 @@ analyse_expr(Expr, Config) -> cc_mod(M, Binary, Config) -> {ok, Dir} = file:get_cwd(), - PrivDir = ?config(priv_dir, Config), + PrivDir = proplists:get_value(priv_dir, Config), ok = file:set_cwd(PrivDir), File = atom_to_list(M) ++ ".erl", try @@ -1792,7 +1745,7 @@ cc_mod(M, Binary, Config) -> c_mod(M, Binary, Config) -> {ok, Dir} = file:get_cwd(), - PrivDir = ?config(priv_dir, Config), + PrivDir = proplists:get_value(priv_dir, Config), ok = file:set_cwd(PrivDir), File = atom_to_list(M) ++ ".erl", try @@ -1815,12 +1768,12 @@ lsfiles(Dir) -> files(Files, Ext) -> lists:filter(fun(File) -> - case filename:extension(File) of - Ext -> true; - _ -> false - end - end, - Files). + case filename:extension(File) of + Ext -> true; + _ -> false + end + end, + Files). remove([File|Files]) -> ok = file:delete(File), @@ -1837,9 +1790,9 @@ decompile([]) -> is_unloaded(What) -> if - is_list(What) -> true; - What==non_existing -> true; - true -> false + is_list(What) -> true; + What==non_existing -> true; + true -> false end. check_f_calls(F1,F2) -> @@ -1849,18 +1802,18 @@ check_f_calls(F1,F2) -> cover_which_nodes(Expected) -> case cover:which_nodes() of - Expected -> - ok; - Other -> - {Time,ok} = timer:tc(fun Retry() -> - case cover:which_nodes() of - Expected -> ok; - _ -> - ?t:sleep(100), - Retry() - end - end), - io:format("~p ms before cover:which_nodes() returned ~p", - [Time,Expected]), - Expected = Other + Expected -> + ok; + Other -> + {Time,ok} = timer:tc(fun Retry() -> + case cover:which_nodes() of + Expected -> ok; + _ -> + timer:sleep(100), + Retry() + end + end), + io:format("~p ms before cover:which_nodes() returned ~p", + [Time,Expected]), + Expected = Other end. diff --git a/lib/tools/test/cover_SUITE_data/d.erl b/lib/tools/test/cover_SUITE_data/d.erl index 696e27e49b..b1d8ebd62e 100644 --- a/lib/tools/test/cover_SUITE_data/d.erl +++ b/lib/tools/test/cover_SUITE_data/d.erl @@ -6,7 +6,7 @@ size/0]). -export([init/0]). % spawn --record(person, {name, age, location, moved=false}). +-record(person, {name, age :: integer(), location, moved=false :: boolean()}). %%%---------------------------------------------------------------------- %%% User interface functions diff --git a/lib/tools/test/cprof_SUITE.erl b/lib/tools/test/cprof_SUITE.erl index 7b22dea7ed..9cbc27fb17 100644 --- a/lib/tools/test/cprof_SUITE.erl +++ b/lib/tools/test/cprof_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2002-2013. All Rights Reserved. +%% Copyright Ericsson AB 2002-2016. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -42,9 +42,9 @@ -define(config(A,B),config(A,B)). -export([config/2]). -else. --include_lib("test_server/include/test_server.hrl"). +-include_lib("common_test/include/ct.hrl"). -endif. - + -ifdef(debug). -ifdef(STANDALONE). -define(line, erlang:display({?MODULE,?LINE}), ). @@ -56,7 +56,7 @@ -endif. -define(dbgformat(A,B),noop). -endif. - + -ifdef(STANDALONE). config(priv_dir, _) -> "."; @@ -64,69 +64,43 @@ config(data_dir, _) -> "cprof_SUITE_data". -else. %% When run in test server. --export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, - init_per_group/2,end_per_group/2, - init_per_testcase/2, end_per_testcase/2, - not_run/1]). +-export([all/0, suite/0, + init_per_testcase/2, end_per_testcase/2, + not_run/1]). -export([basic/1, on_load/1, modules/1]). - + init_per_testcase(_Case, Config) -> - ?line Dog=test_server:timetrap(test_server:seconds(30)), - [{watchdog, Dog}|Config]. + Config. -end_per_testcase(_Case, Config) -> +end_per_testcase(_Case, _Config) -> erlang:trace_pattern({'_','_','_'}, false, [local,meta,call_count]), erlang:trace_pattern(on_load, false, [local,meta,call_count]), erlang:trace(all, false, [all]), - Dog=?config(watchdog, Config), - test_server:timetrap_cancel(Dog), ok. -suite() -> [{ct_hooks,[ts_install_cth]}]. +suite() -> + [{ct_hooks,[ts_install_cth]}, + {timetrap,{seconds,30}}]. all() -> case test_server:is_native(cprof_SUITE) of - true -> [not_run]; - false -> [basic, on_load, modules] + true -> [not_run]; + false -> [basic, on_load, modules] end. -groups() -> - []. - -init_per_suite(Config) -> - Config. - -end_per_suite(_Config) -> - ok. - -init_per_group(_GroupName, Config) -> - Config. - -end_per_group(_GroupName, Config) -> - Config. - not_run(Config) when is_list(Config) -> {skipped,"Native code"}. -basic(suite) -> - []; -basic(doc) -> - ["Tests basic profiling"]; +%% Tests basic profiling basic(Config) when is_list(Config) -> basic_test(). -on_load(suite) -> - []; -on_load(doc) -> - ["Tests profiling of unloaded module"]; +%% Tests profiling of unloaded module on_load(Config) when is_list(Config) -> on_load_test(Config). -modules(suite) -> - []; -modules(doc) -> - ["Tests profiling of several modules"]; +%% Tests profiling of several modules modules(Config) when is_list(Config) -> modules_test(Config). @@ -137,164 +111,163 @@ modules(Config) when is_list(Config) -> %%% basic_test() -> - ?line M = 1000, + M = 1000, %% - ?line M2 = M*2, - ?line M3 = M*3, - ?line M2__1 = M2 + 1, - ?line M3__1 = M3 + 1, - ?line N = cprof:stop(), + M2 = M*2, + M3 = M*3, + M2__1 = M2 + 1, + M3__1 = M3 + 1, + N = cprof:stop(), %% - ?line 2 = cprof:start(?MODULE, seq_r), - ?line 1 = cprof:start(?MODULE, seq, 3), - ?line L = seq(1, M, fun succ/1), - ?line Lr = seq_r(1, M, fun succ/1), - ?line L = lists:reverse(Lr), + 2 = cprof:start(?MODULE, seq_r), + 1 = cprof:start(?MODULE, seq, 3), + L = seq(1, M, fun succ/1), + Lr = seq_r(1, M, fun succ/1), + L = lists:reverse(Lr), %% - ?line io:format("~p~n~p~n~p~n", - [erlang:trace_info({?MODULE,sec_r,3}, all), - erlang:trace_info({?MODULE,sec_r,4}, all), - erlang:trace_info({?MODULE,sec,3}, all)]), + io:format("~p~n~p~n~p~n", + [erlang:trace_info({?MODULE,sec_r,3}, all), + erlang:trace_info({?MODULE,sec_r,4}, all), + erlang:trace_info({?MODULE,sec,3}, all)]), %% - ?line ModAna1 = {?MODULE,M2__1,[{{?MODULE,seq_r,4},M}, - {{?MODULE,seq,3},M}, - {{?MODULE,seq_r,3},1}]}, - ?line ModAna1 = cprof:analyse(?MODULE,0), - ?line {M2__1, [ModAna1]} = cprof:analyse(), - ?line ModAna1 = cprof:analyse(?MODULE, 1), - ?line {M2__1, [ModAna1]} = cprof:analyse(1), + ModAna1 = {?MODULE,M2__1,[{{?MODULE,seq_r,4},M}, + {{?MODULE,seq,3},M}, + {{?MODULE,seq_r,3},1}]}, + ModAna1 = cprof:analyse(?MODULE,0), + {M2__1, [ModAna1]} = cprof:analyse(), + ModAna1 = cprof:analyse(?MODULE, 1), + {M2__1, [ModAna1]} = cprof:analyse(1), %% - ?line ModAna2 = {?MODULE,M2__1,[{{?MODULE,seq_r,4},M}, - {{?MODULE,seq,3},M}]}, - ?line ModAna2 = cprof:analyse(?MODULE, 2), - ?line {M2__1, [ModAna2]} = cprof:analyse(2), + ModAna2 = {?MODULE,M2__1,[{{?MODULE,seq_r,4},M}, + {{?MODULE,seq,3},M}]}, + ModAna2 = cprof:analyse(?MODULE, 2), + {M2__1, [ModAna2]} = cprof:analyse(2), %% 2 = cprof:pause(?MODULE, seq_r), - ?line L = seq(1, M, fun succ/1), - ?line Lr = seq_r(1, M, fun succ/1), + L = seq(1, M, fun succ/1), + Lr = seq_r(1, M, fun succ/1), %% - ?line ModAna3 = {?MODULE,M3__1,[{{?MODULE,seq,3},M2}, - {{?MODULE,seq_r,4},M}, - {{?MODULE,seq_r,3},1}]}, - ?line ModAna3 = cprof:analyse(?MODULE), + ModAna3 = {?MODULE,M3__1,[{{?MODULE,seq,3},M2}, + {{?MODULE,seq_r,4},M}, + {{?MODULE,seq_r,3},1}]}, + ModAna3 = cprof:analyse(?MODULE), %% - ?line N = cprof:pause(), - ?line L = seq(1, M, fun succ/1), - ?line Lr = seq_r(1, M, fun succ/1), + N = cprof:pause(), + L = seq(1, M, fun succ/1), + Lr = seq_r(1, M, fun succ/1), %% - ?line {M3__1, [ModAna3]} = cprof:analyse(), + {M3__1, [ModAna3]} = cprof:analyse(), %% - ?line N = cprof:restart(), - ?line L = seq(1, M, fun succ/1), - ?line Lr = seq_r(1, M, fun succ/1), + N = cprof:restart(), + L = seq(1, M, fun succ/1), + Lr = seq_r(1, M, fun succ/1), %% - ?line ModAna1 = cprof:analyse(?MODULE), + ModAna1 = cprof:analyse(?MODULE), %% - ?line N = cprof:stop(), - ?line {?MODULE,0,[]} = cprof:analyse(?MODULE), - ?line {0,[]} = cprof:analyse(), + N = cprof:stop(), + {?MODULE,0,[]} = cprof:analyse(?MODULE), + {0,[]} = cprof:analyse(), ok. %% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% on_load_test(Config) -> - ?line Priv = ?config(priv_dir, Config), - ?line Data = ?config(data_dir, Config), - ?line File = filename:join(Data, "cprof_SUITE_test"), - ?line Module = cprof_SUITE_test, - ?line M = 1000, + Priv = proplists:get_value(priv_dir, Config), + Data = proplists:get_value(data_dir, Config), + File = filename:join(Data, "cprof_SUITE_test"), + Module = cprof_SUITE_test, + M = 1000, %% - ?line M2 = M*2, - ?line M2__1 = M2 + 1, - ?line N1 = cprof:start(), + M2 = M*2, + M2__1 = M2 + 1, + N1 = cprof:start(), - ?line {ok,Module} = c:c(File, [{outdir,Priv}]), + {ok,Module} = c:c(File, [{outdir,Priv}]), %% If this system is hipe-enabled, the loader may have called module_info/1 %% when Module was loaded above. Reset the call count to avoid seeing %% the call in the analysis below. - ?line 1 = cprof:restart(Module, module_info, 1), - - ?line L = Module:seq(1, M, fun succ/1), - ?line Lr = Module:seq_r(1, M, fun succ/1), - ?line Lr = lists:reverse(L), - ?line N2 = cprof:pause(), - ?line N3 = cprof:pause(Module), - ?line {Module,M2__1,[{{Module,seq_r,4},M}, - {{Module,seq,3},M}, - {{Module,seq_r,3},1}]} = cprof:analyse(Module), - ?line io:format("~p ~p ~p~n", [N1, N2, N3]), - ?line code:purge(Module), - ?line code:delete(Module), - ?line N4 = N2 - N3, + 1 = cprof:restart(Module, module_info, 1), + + L = Module:seq(1, M, fun succ/1), + Lr = Module:seq_r(1, M, fun succ/1), + Lr = lists:reverse(L), + N2 = cprof:pause(), + N3 = cprof:pause(Module), + {Module,M2__1,[{{Module,seq_r,4},M}, + {{Module,seq,3},M}, + {{Module,seq_r,3},1}]} = cprof:analyse(Module), + io:format("~p ~p ~p~n", [N1, N2, N3]), + code:purge(Module), + code:delete(Module), + N4 = N2 - N3, %% - ?line N4 = cprof:restart(), - ?line {ok,Module} = c:c(File, [{outdir,Priv}]), - ?line L = Module:seq(1, M, fun succ/1), - ?line Lr = Module:seq_r(1, M, fun succ/1), - ?line L = seq(1, M, fun succ/1), - ?line Lr = seq_r(1, M, fun succ/1), - ?line N2 = cprof:pause(), - ?line {Module,0,[]} = cprof:analyse(Module), - ?line M_1 = M - 1, - ?line M4__4 = M*4 - 4, - ?line M10_7 = M*10 - 7, - ?line {?MODULE,M10_7,[{{?MODULE,succ,1},M4__4}, - {{?MODULE,seq_r,4},M}, - {{?MODULE,seq,3},M}, - {{?MODULE,'-on_load_test/1-fun-5-',1},M_1}, - {{?MODULE,'-on_load_test/1-fun-4-',1},M_1}, - {{?MODULE,'-on_load_test/1-fun-3-',1},M_1}, - {{?MODULE,'-on_load_test/1-fun-2-',1},M_1}, - {{?MODULE,seq_r,3},1}]} - = cprof:analyse(?MODULE), - ?line N2 = cprof:stop(), + N4 = cprof:restart(), + {ok,Module} = c:c(File, [{outdir,Priv}]), + L = Module:seq(1, M, fun succ/1), + Lr = Module:seq_r(1, M, fun succ/1), + L = seq(1, M, fun succ/1), + Lr = seq_r(1, M, fun succ/1), + N2 = cprof:pause(), + {Module,0,[]} = cprof:analyse(Module), + M_1 = M - 1, + M4__4 = M*4 - 4, + M10_7 = M*10 - 7, + {?MODULE,M10_7,[{{?MODULE,succ,1},M4__4}, + {{?MODULE,seq_r,4},M}, + {{?MODULE,seq,3},M}, + {{?MODULE,'-on_load_test/1-fun-5-',1},M_1}, + {{?MODULE,'-on_load_test/1-fun-4-',1},M_1}, + {{?MODULE,'-on_load_test/1-fun-3-',1},M_1}, + {{?MODULE,'-on_load_test/1-fun-2-',1},M_1}, + {{?MODULE,seq_r,3},1}]} + = cprof:analyse(?MODULE), + N2 = cprof:stop(), ok. %% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% modules_test(Config) -> - ?line Priv = ?config(priv_dir, Config), - ?line Data = ?config(data_dir, Config), - ?line File = filename:join(Data, "cprof_SUITE_test"), - ?line Module = cprof_SUITE_test, - ?line {ok,Module} = c:c(File, [{outdir,Priv}]), - ?line M = 10, + Priv = proplists:get_value(priv_dir, Config), + Data = proplists:get_value(data_dir, Config), + File = filename:join(Data, "cprof_SUITE_test"), + Module = cprof_SUITE_test, + {ok,Module} = c:c(File, [{outdir,Priv}]), + M = 10, %% - ?line M2 = M*2, - ?line M2__1 = M2 + 1, - ?line erlang:yield(), - ?line N = cprof:start(), - ?line L = Module:seq(1, M, fun succ/1), - ?line Lr = Module:seq_r(1, M, fun succ/1), - ?line L = seq(1, M, fun succ/1), - ?line Lr = seq_r(1, M, fun succ/1), - ?line N = cprof:pause(), - ?line Lr = lists:reverse(L), - ?line M_1 = M - 1, - ?line M4_4 = M*4 - 4, - ?line M10_7 = M*10 - 7, - ?line M2__1 = M*2 + 1, - ?line {Tot,ModList} = cprof:analyse(), - ?line {value,{?MODULE,M10_7,[{{?MODULE,succ,1},M4_4}, - {{?MODULE,seq_r,4},M}, - {{?MODULE,seq,3},M}, - {{?MODULE,'-modules_test/1-fun-3-',1},M_1}, - {{?MODULE,'-modules_test/1-fun-2-',1},M_1}, - {{?MODULE,'-modules_test/1-fun-1-',1},M_1}, - {{?MODULE,'-modules_test/1-fun-0-',1},M_1}, - {{?MODULE,seq_r,3},1}]}} = - lists:keysearch(?MODULE, 1, ModList), - ?line {value,{Module,M2__1,[{{Module,seq_r,4},M}, - {{Module,seq,3},M}, - {{Module,seq_r,3},1}]}} = - lists:keysearch(Module, 1, ModList), - ?line Tot = lists:foldl(fun ({_,C,_}, A) -> C+A end, 0, ModList), - ?line {cprof,_,Prof} = cprof:analyse(cprof), - ?line {value,{{cprof,pause,0},1}} = - lists:keysearch({cprof,pause,0}, 1, Prof), - ?line N = cprof:stop(), + M2 = M*2, + M2__1 = M2 + 1, + erlang:yield(), + N = cprof:start(), + L = Module:seq(1, M, fun succ/1), + Lr = Module:seq_r(1, M, fun succ/1), + L = seq(1, M, fun succ/1), + Lr = seq_r(1, M, fun succ/1), + N = cprof:pause(), + Lr = lists:reverse(L), + M_1 = M - 1, + M4_4 = M*4 - 4, + M10_7 = M*10 - 7, + M2__1 = M*2 + 1, + {Tot,ModList} = cprof:analyse(), + {value,{?MODULE,M10_7,[{{?MODULE,succ,1},M4_4}, + {{?MODULE,seq_r,4},M}, + {{?MODULE,seq,3},M}, + {{?MODULE,'-modules_test/1-fun-3-',1},M_1}, + {{?MODULE,'-modules_test/1-fun-2-',1},M_1}, + {{?MODULE,'-modules_test/1-fun-1-',1},M_1}, + {{?MODULE,'-modules_test/1-fun-0-',1},M_1}, + {{?MODULE,seq_r,3},1}]}} = + lists:keysearch(?MODULE, 1, ModList), + {value,{Module,M2__1,[{{Module,seq_r,4},M}, + {{Module,seq,3},M}, + {{Module,seq_r,3},1}]}} = + lists:keysearch(Module, 1, ModList), + Tot = lists:foldl(fun ({_,C,_}, A) -> C+A end, 0, ModList), + {cprof,_,Prof} = cprof:analyse(cprof), + {value,{{cprof,pause,0},1}} = lists:keysearch({cprof,pause,0}, 1, Prof), + N = cprof:stop(), ok. @@ -303,7 +276,6 @@ modules_test(Config) -> %% Local helpers - %% Stack recursive seq seq(Stop, Stop, Succ) when is_function(Succ) -> [Stop]; @@ -322,6 +294,5 @@ seq_r(Start, Stop, Succ, R) -> seq_r(Succ(Start), Stop, Succ, [Start | R]). - %% Successor succ(X) -> X+1. diff --git a/lib/tools/test/emacs_SUITE.erl b/lib/tools/test/emacs_SUITE.erl index 0c2d077e5d..77a8813db5 100644 --- a/lib/tools/test/emacs_SUITE.erl +++ b/lib/tools/test/emacs_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2005-2013. All Rights Reserved. +%% Copyright Ericsson AB 2005-2016. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. diff --git a/lib/tools/test/emem_SUITE.erl b/lib/tools/test/emem_SUITE.erl index 95cda98558..6dca7f6739 100644 --- a/lib/tools/test/emem_SUITE.erl +++ b/lib/tools/test/emem_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2005-2011. All Rights Reserved. +%% Copyright Ericsson AB 2005-2016. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -19,15 +19,11 @@ %% -module(emem_SUITE). -%%-define(line_trace, 1). - --export([init_per_suite/1, end_per_suite/1, +-export([all/0, suite/0, + init_per_testcase/2, end_per_testcase/2, + init_per_suite/1, end_per_suite/1, receive_and_save_trace/2, send_trace/2]). - --export([all/0, suite/0,groups/0,init_per_group/2,end_per_group/2, - init_per_testcase/2, end_per_testcase/2]). - -export([live_node/1, 'sparc_sunos5.8_32b_emt2.0'/1, 'pc_win2000_32b_emt2.0'/1, @@ -42,10 +38,7 @@ 'sparc_sunos5.8_64b_emt1.0'/1]). -include_lib("kernel/include/file.hrl"). - --include_lib("test_server/include/test_server.hrl"). - --define(DEFAULT_TIMEOUT, ?t:minutes(5)). +-include_lib("common_test/include/ct.hrl"). -define(EMEM_64_32_COMMENT, "64 bit trace; this build of emem can only handle 32 bit traces"). @@ -62,28 +55,19 @@ exit_code}). %% -%% %% Exported suite functions %% -%% -suite() -> [{ct_hooks,[ts_install_cth]}]. +suite() -> + [{ct_hooks,[ts_install_cth]}, + {timetrap,{minutes,5}}]. all() -> - case is_debug_compiled() of - true -> {skip, "Not run when debug compiled"}; - false -> test_cases() + case test_server:is_debug() of + true -> {skip, "Not run when debug compiled"}; + false -> test_cases() end. -groups() -> - []. - -init_per_group(_GroupName, Config) -> - Config. - -end_per_group(_GroupName, Config) -> - Config. - test_cases() -> [live_node, 'sparc_sunos5.8_32b_emt2.0', @@ -99,31 +83,26 @@ test_cases() -> init_per_testcase(Case, Config) when is_list(Config) -> case maybe_skip(Config) of - {skip, _}=Skip -> Skip; + {skip, _}=Skip -> + Skip; ok -> - Dog = ?t:timetrap(?DEFAULT_TIMEOUT), - %% Until emem is completely stable we run these tests in a working %% directory with an ignore_core_files file which will make the %% search for core files ignore cores generated by this suite. - ignore_cores:setup(?MODULE, - Case, - [{watchdog, Dog}, {testcase, Case} | Config]) + ignore_cores:setup(?MODULE, Case, [{testcase, Case}|Config]) end. end_per_testcase(_Case, Config) when is_list(Config) -> ignore_cores:restore(Config), - Dog = ?config(watchdog, Config), - ?t:timetrap_cancel(Dog), ok. maybe_skip(Config) -> - DataDir = ?config(data_dir, Config), + DataDir = proplists:get_value(data_dir, Config), case filelib:is_dir(DataDir) of false -> {skip, "No data directory"}; true -> - case ?config(emem, Config) of + case proplists:get_value(emem, Config) of undefined -> {skip, "emem not found"}; _ -> @@ -159,13 +138,11 @@ end_per_suite(Config) when is_list(Config) -> %% %% -live_node(doc) -> []; -live_node(suite) -> []; live_node(Config) when is_list(Config) -> - ?line {ok, EmuFlag, Port} = start_emem(Config), - ?line Nodename = mk_nodename(Config), - ?line {ok, Node} = start_node(Nodename, EmuFlag), - ?line NP = spawn(Node, + {ok, EmuFlag, Port} = start_emem(Config), + Nodename = mk_nodename(Config), + {ok, Node} = start_node(Nodename, EmuFlag), + NP = spawn(Node, fun () -> receive go -> ok end, I = spawn(fun () -> ignorer end), @@ -187,246 +164,216 @@ live_node(Config) when is_list(Config) -> GC(), GC() end), - ?line MRef = erlang:monitor(process, NP), + MRef = erlang:monitor(process, NP), NP ! go, - ?line receive + receive {'DOWN', MRef, process, NP, Reason} -> - ?line spawn(Node, fun () -> halt(17) end), - ?line normal = Reason + spawn(Node, fun () -> halt(17) end), + normal = Reason end, - ?line Res = get_emem_result(Port), - ?line {ok, Hostname} = inet:gethostname(), - ?line ShortHostname = short_hostname(Hostname), - ?line {true, _} = has_prefix(Nodename, Res#emem_res.nodename), - ?line ShortHostname = short_hostname(Res#emem_res.hostname), - ?line Bits = case erlang:system_info(wordsize) of - 4 -> ?line "32 bits"; - 8 -> ?line "64 bits" + Res = get_emem_result(Port), + {ok, Hostname} = inet:gethostname(), + ShortHostname = short_hostname(Hostname), + {true, _} = has_prefix(Nodename, Res#emem_res.nodename), + ShortHostname = short_hostname(Res#emem_res.hostname), + Bits = case erlang:system_info(wordsize) of + 4 -> "32 bits"; + 8 -> "64 bits" end, - ?line Bits = Res#emem_res.word_size, - ?line "17" = Res#emem_res.exit_code, - ?line emem_comment(Config). + Bits = Res#emem_res.word_size, + "17" = Res#emem_res.exit_code, + emem_comment(Config). -'sparc_sunos5.8_32b_emt2.0'(doc) -> []; -'sparc_sunos5.8_32b_emt2.0'(suite) -> []; 'sparc_sunos5.8_32b_emt2.0'(Config) when is_list(Config) -> - ?line Res = run_emem_on_casefile(Config), - ?line "test_server" = Res#emem_res.nodename, - ?line "gorbag" = Res#emem_res.hostname, - ?line "17074" = Res#emem_res.pid, - ?line "2005-01-14 17:28:37.881980" = Res#emem_res.start_time, - ?line "2.0" = Res#emem_res.trace_version, - ?line "32 bits" = Res#emem_res.word_size, - ?line ["15", - "2665739", "8992", "548986", "16131", "539994", - "4334192", "1", "99", "15", "98", - "0", "0", "49", "0", "49"] = Res#emem_res.last_values, - ?line ["5972061", "9662", - "7987824", "5", - "2375680", "3"] = Res#emem_res.maximum, - ?line "0" = Res#emem_res.exit_code, - ?line emem_comment(Config). - -'pc_win2000_32b_emt2.0'(doc) -> []; -'pc_win2000_32b_emt2.0'(suite) -> []; + Res = run_emem_on_casefile(Config), + "test_server" = Res#emem_res.nodename, + "gorbag" = Res#emem_res.hostname, + "17074" = Res#emem_res.pid, + "2005-01-14 17:28:37.881980" = Res#emem_res.start_time, + "2.0" = Res#emem_res.trace_version, + "32 bits" = Res#emem_res.word_size, + ["15", "2665739", "8992", "548986", "16131", "539994", + "4334192", "1", "99", "15", "98", + "0", "0", "49", "0", "49"] = Res#emem_res.last_values, + ["5972061", "9662", "7987824", "5", + "2375680", "3"] = Res#emem_res.maximum, + "0" = Res#emem_res.exit_code, + emem_comment(Config). + 'pc_win2000_32b_emt2.0'(Config) when is_list(Config) -> - ?line Res = run_emem_on_casefile(Config), - ?line "test_server" = Res#emem_res.nodename, - ?line "E-788FCF5191B54" = Res#emem_res.hostname, - ?line "504" = Res#emem_res.pid, - ?line "2005-01-24 17:27:28.224000" = Res#emem_res.start_time, - ?line "2.0" = Res#emem_res.trace_version, - ?line "32 bits" = Res#emem_res.word_size, - ?line ["11", - "2932575", "8615", "641087", "68924", "632472"] + Res = run_emem_on_casefile(Config), + "test_server" = Res#emem_res.nodename, + "E-788FCF5191B54" = Res#emem_res.hostname, + "504" = Res#emem_res.pid, + "2005-01-24 17:27:28.224000" = Res#emem_res.start_time, + "2.0" = Res#emem_res.trace_version, + "32 bits" = Res#emem_res.word_size, + ["11", "2932575", "8615", "641087", "68924", "632472"] = Res#emem_res.last_values, - ?line ["5434206", "9285"] = Res#emem_res.maximum, - ?line "0" = Res#emem_res.exit_code, - ?line emem_comment(Config). + ["5434206", "9285"] = Res#emem_res.maximum, + "0" = Res#emem_res.exit_code, + emem_comment(Config). -'pc.smp_linux2.2.19pre17_32b_emt2.0'(doc) -> []; -'pc.smp_linux2.2.19pre17_32b_emt2.0'(suite) -> []; 'pc.smp_linux2.2.19pre17_32b_emt2.0'(Config) when is_list(Config) -> - ?line Res = run_emem_on_casefile(Config), - ?line "test_server" = Res#emem_res.nodename, - ?line "four-roses" = Res#emem_res.hostname, - ?line "20689" = Res#emem_res.pid, - ?line "2005-01-20 13:11:26.143077" = Res#emem_res.start_time, - ?line "2.0" = Res#emem_res.trace_version, - ?line "32 bits" = Res#emem_res.word_size, - ?line ["49", - "2901817", "9011", "521610", "10875", "512599", - "5392096", "2", "120", "10", "118", - "0", "0", "59", "0", "59"] = Res#emem_res.last_values, - ?line ["6182918", "9681", - "9062112", "6", - "2322432", "3"] = Res#emem_res.maximum, - ?line "0" = Res#emem_res.exit_code, - ?line emem_comment(Config). - - -'powerpc_darwin7.7.0_32b_emt2.0'(doc) -> []; -'powerpc_darwin7.7.0_32b_emt2.0'(suite) -> []; + Res = run_emem_on_casefile(Config), + "test_server" = Res#emem_res.nodename, + "four-roses" = Res#emem_res.hostname, + "20689" = Res#emem_res.pid, + "2005-01-20 13:11:26.143077" = Res#emem_res.start_time, + "2.0" = Res#emem_res.trace_version, + "32 bits" = Res#emem_res.word_size, + ["49", "2901817", "9011", "521610", "10875", "512599", + "5392096", "2", "120", "10", "118", + "0", "0", "59", "0", "59"] = Res#emem_res.last_values, + ["6182918", "9681", + "9062112", "6", + "2322432", "3"] = Res#emem_res.maximum, + "0" = Res#emem_res.exit_code, + emem_comment(Config). + + 'powerpc_darwin7.7.0_32b_emt2.0'(Config) when is_list(Config) -> - ?line Res = run_emem_on_casefile(Config), - ?line "test_server" = Res#emem_res.nodename, - ?line "grima" = Res#emem_res.hostname, - ?line "13021" = Res#emem_res.pid, - ?line "2005-01-20 15:08:17.568668" = Res#emem_res.start_time, - ?line "2.0" = Res#emem_res.trace_version, - ?line "32 bits" = Res#emem_res.word_size, - ?line ["9", - "2784323", "8641", "531105", "15893", "522464"] + Res = run_emem_on_casefile(Config), + "test_server" = Res#emem_res.nodename, + "grima" = Res#emem_res.hostname, + "13021" = Res#emem_res.pid, + "2005-01-20 15:08:17.568668" = Res#emem_res.start_time, + "2.0" = Res#emem_res.trace_version, + "32 bits" = Res#emem_res.word_size, + ["9", "2784323", "8641", "531105", "15893", "522464"] = Res#emem_res.last_values, - ?line ["6150376", "9311"] = Res#emem_res.maximum, - ?line "0" = Res#emem_res.exit_code, - ?line emem_comment(Config). + ["6150376", "9311"] = Res#emem_res.maximum, + "0" = Res#emem_res.exit_code, + emem_comment(Config). -'alpha_osf1v5.1_64b_emt2.0'(doc) -> []; -'alpha_osf1v5.1_64b_emt2.0'(suite) -> []; 'alpha_osf1v5.1_64b_emt2.0'(Config) when is_list(Config) -> - ?line Res = run_emem_on_casefile(Config), - ?line "test_server" = Res#emem_res.nodename, - ?line "thorin" = Res#emem_res.hostname, - ?line "224630" = Res#emem_res.pid, - ?line "2005-01-20 22:38:01.299632" = Res#emem_res.start_time, - ?line "2.0" = Res#emem_res.trace_version, - ?line "64 bits" = Res#emem_res.word_size, - ?line case Res#emem_res.max_word_size of - "32 bits" -> - ?line emem_comment(Config, ?EMEM_64_32_COMMENT); - "64 bits" -> - ?line ["22", - "6591992", "8625", "516785", "14805", "508160", - "11429184", "5", "127", "254", "122", - "0", "0", "61", "0", "61"] = Res#emem_res.last_values, - ?line ["7041775", "9295", - "11593024", "7", - "2097152", "3"] = Res#emem_res.maximum, - ?line "0" = Res#emem_res.exit_code, - ?line emem_comment(Config) - end. - -'sparc_sunos5.8_64b_emt2.0'(doc) -> []; -'sparc_sunos5.8_64b_emt2.0'(suite) -> []; + Res = run_emem_on_casefile(Config), + "test_server" = Res#emem_res.nodename, + "thorin" = Res#emem_res.hostname, + "224630" = Res#emem_res.pid, + "2005-01-20 22:38:01.299632" = Res#emem_res.start_time, + "2.0" = Res#emem_res.trace_version, + "64 bits" = Res#emem_res.word_size, + case Res#emem_res.max_word_size of + "32 bits" -> + emem_comment(Config, ?EMEM_64_32_COMMENT); + "64 bits" -> + ["22", + "6591992", "8625", "516785", "14805", "508160", + "11429184", "5", "127", "254", "122", + "0", "0", "61", "0", "61"] = Res#emem_res.last_values, + ["7041775", "9295", + "11593024", "7", + "2097152", "3"] = Res#emem_res.maximum, + "0" = Res#emem_res.exit_code, + emem_comment(Config) + end. + 'sparc_sunos5.8_64b_emt2.0'(Config) when is_list(Config) -> - ?line Res = run_emem_on_casefile(Config), - ?line "test_server" = Res#emem_res.nodename, - ?line "gorbag" = Res#emem_res.hostname, - ?line "10907" = Res#emem_res.pid, - ?line "2005-01-20 13:48:34.677068" = Res#emem_res.start_time, - ?line "2.0" = Res#emem_res.trace_version, - ?line "64 bits" = Res#emem_res.word_size, - ?line case Res#emem_res.max_word_size of - "32 bits" -> - ?line emem_comment(Config, ?EMEM_64_32_COMMENT); - "64 bits" -> - ?line ["16", - "5032887", "8657", "530635", "14316", "521978", - "8627140", "5", "139", "19", "134", - "0", "0", "67", "0", "67"] = Res#emem_res.last_values, - ?line ["11695070", "9324", - "16360388", "10", - "4136960", "3"] = Res#emem_res.maximum, - ?line "0" = Res#emem_res.exit_code, - ?line emem_comment(Config) - end. - -'sparc_sunos5.8_32b_emt1.0'(doc) -> []; -'sparc_sunos5.8_32b_emt1.0'(suite) -> []; + Res = run_emem_on_casefile(Config), + "test_server" = Res#emem_res.nodename, + "gorbag" = Res#emem_res.hostname, + "10907" = Res#emem_res.pid, + "2005-01-20 13:48:34.677068" = Res#emem_res.start_time, + "2.0" = Res#emem_res.trace_version, + "64 bits" = Res#emem_res.word_size, + case Res#emem_res.max_word_size of + "32 bits" -> + emem_comment(Config, ?EMEM_64_32_COMMENT); + "64 bits" -> + ["16", + "5032887", "8657", "530635", "14316", "521978", + "8627140", "5", "139", "19", "134", + "0", "0", "67", "0", "67"] = Res#emem_res.last_values, + ["11695070", "9324", + "16360388", "10", + "4136960", "3"] = Res#emem_res.maximum, + "0" = Res#emem_res.exit_code, + emem_comment(Config) + end. + 'sparc_sunos5.8_32b_emt1.0'(Config) when is_list(Config) -> - ?line Res = run_emem_on_casefile(Config), - ?line "" = Res#emem_res.nodename, - ?line "" = Res#emem_res.hostname, - ?line "" = Res#emem_res.pid, - ?line "" = Res#emem_res.start_time, - ?line "1.0" = Res#emem_res.trace_version, - ?line "32 bits" = Res#emem_res.word_size, - ?line ["11", - "2558261", "8643", "560610", "15325", "551967"] + Res = run_emem_on_casefile(Config), + "" = Res#emem_res.nodename, + "" = Res#emem_res.hostname, + "" = Res#emem_res.pid, + "" = Res#emem_res.start_time, + "1.0" = Res#emem_res.trace_version, + "32 bits" = Res#emem_res.word_size, + ["11", "2558261", "8643", "560610", "15325", "551967"] = Res#emem_res.last_values, - ?line ["2791121", "9317"] = Res#emem_res.maximum, - ?line "0" = Res#emem_res.exit_code, - ?line emem_comment(Config). + ["2791121", "9317"] = Res#emem_res.maximum, + "0" = Res#emem_res.exit_code, + emem_comment(Config). -'pc_win2000_32b_emt1.0'(doc) -> []; -'pc_win2000_32b_emt1.0'(suite) -> []; 'pc_win2000_32b_emt1.0'(Config) when is_list(Config) -> - ?line Res = run_emem_on_casefile(Config), - ?line "" = Res#emem_res.nodename, - ?line "" = Res#emem_res.hostname, - ?line "" = Res#emem_res.pid, - ?line "" = Res#emem_res.start_time, - ?line "1.0" = Res#emem_res.trace_version, - ?line "32 bits" = Res#emem_res.word_size, - ?line ["6", - "2965248", "8614", "640897", "68903", "632283"] + Res = run_emem_on_casefile(Config), + "" = Res#emem_res.nodename, + "" = Res#emem_res.hostname, + "" = Res#emem_res.pid, + "" = Res#emem_res.start_time, + "1.0" = Res#emem_res.trace_version, + "32 bits" = Res#emem_res.word_size, + ["6", "2965248", "8614", "640897", "68903", "632283"] = Res#emem_res.last_values, - ?line ["3147090", "9283"] = Res#emem_res.maximum, - ?line "0" = Res#emem_res.exit_code, - ?line emem_comment(Config). + ["3147090", "9283"] = Res#emem_res.maximum, + "0" = Res#emem_res.exit_code, + emem_comment(Config). -'powerpc_darwin7.7.0_32b_emt1.0'(doc) -> []; -'powerpc_darwin7.7.0_32b_emt1.0'(suite) -> []; 'powerpc_darwin7.7.0_32b_emt1.0'(Config) when is_list(Config) -> - ?line Res = run_emem_on_casefile(Config), - ?line "" = Res#emem_res.nodename, - ?line "" = Res#emem_res.hostname, - ?line "" = Res#emem_res.pid, - ?line "" = Res#emem_res.start_time, - ?line "1.0" = Res#emem_res.trace_version, - ?line "32 bits" = Res#emem_res.word_size, - ?line ["8", - "2852991", "8608", "529662", "15875", "521054"] + Res = run_emem_on_casefile(Config), + "" = Res#emem_res.nodename, + "" = Res#emem_res.hostname, + "" = Res#emem_res.pid, + "" = Res#emem_res.start_time, + "1.0" = Res#emem_res.trace_version, + "32 bits" = Res#emem_res.word_size, + ["8", "2852991", "8608", "529662", "15875", "521054"] = Res#emem_res.last_values, - ?line ["3173335", "9278"] = Res#emem_res.maximum, - ?line "0" = Res#emem_res.exit_code, - ?line emem_comment(Config). + ["3173335", "9278"] = Res#emem_res.maximum, + "0" = Res#emem_res.exit_code, + emem_comment(Config). -'alpha_osf1v5.1_64b_emt1.0'(doc) -> []; -'alpha_osf1v5.1_64b_emt1.0'(suite) -> []; 'alpha_osf1v5.1_64b_emt1.0'(Config) when is_list(Config) -> - ?line Res = run_emem_on_casefile(Config), - ?line "" = Res#emem_res.nodename, - ?line "" = Res#emem_res.hostname, - ?line "" = Res#emem_res.pid, - ?line "" = Res#emem_res.start_time, - ?line "1.0" = Res#emem_res.trace_version, - ?line "64 bits" = Res#emem_res.word_size, - ?line case Res#emem_res.max_word_size of - "32 bits" -> - ?line emem_comment(Config, ?EMEM_64_32_COMMENT); - "64 bits" -> - ?line ["22", - "6820094", "8612", "515518", "14812", "506906"] - = Res#emem_res.last_values, - ?line ["7292413", "9282"] = Res#emem_res.maximum, - ?line "0" = Res#emem_res.exit_code, - ?line emem_comment(Config) - end. - -'sparc_sunos5.8_64b_emt1.0'(doc) -> []; -'sparc_sunos5.8_64b_emt1.0'(suite) -> []; + Res = run_emem_on_casefile(Config), + "" = Res#emem_res.nodename, + "" = Res#emem_res.hostname, + "" = Res#emem_res.pid, + "" = Res#emem_res.start_time, + "1.0" = Res#emem_res.trace_version, + "64 bits" = Res#emem_res.word_size, + case Res#emem_res.max_word_size of + "32 bits" -> + emem_comment(Config, ?EMEM_64_32_COMMENT); + "64 bits" -> + ["22", + "6820094", "8612", "515518", "14812", "506906"] + = Res#emem_res.last_values, + ["7292413", "9282"] = Res#emem_res.maximum, + "0" = Res#emem_res.exit_code, + emem_comment(Config) + end. + 'sparc_sunos5.8_64b_emt1.0'(Config) when is_list(Config) -> - ?line Res = run_emem_on_casefile(Config), - ?line "" = Res#emem_res.nodename, - ?line "" = Res#emem_res.hostname, - ?line "" = Res#emem_res.pid, - ?line "" = Res#emem_res.start_time, - ?line "1.0" = Res#emem_res.trace_version, - ?line "64 bits" = Res#emem_res.word_size, - ?line case Res#emem_res.max_word_size of - "32 bits" -> - ?line emem_comment(Config, ?EMEM_64_32_COMMENT); - "64 bits" -> - ?line ["15", - "4965746", "8234", "543940", "14443", "535706"] - = Res#emem_res.last_values, - ?line ["11697645", "8908"] = Res#emem_res.maximum, - ?line "0" = Res#emem_res.exit_code, - ?line emem_comment(Config) - end. + Res = run_emem_on_casefile(Config), + "" = Res#emem_res.nodename, + "" = Res#emem_res.hostname, + "" = Res#emem_res.pid, + "" = Res#emem_res.start_time, + "1.0" = Res#emem_res.trace_version, + "64 bits" = Res#emem_res.word_size, + case Res#emem_res.max_word_size of + "32 bits" -> + emem_comment(Config, ?EMEM_64_32_COMMENT); + "64 bits" -> + ["15", + "4965746", "8234", "543940", "14443", "535706"] + = Res#emem_res.last_values, + ["11697645", "8908"] = Res#emem_res.maximum, + "0" = Res#emem_res.exit_code, + emem_comment(Config) + end. %% %% @@ -444,84 +391,84 @@ receive_and_save_trace(PortNumber, FileName) when is_integer(PortNumber), receive_loop(Socket, File) -> receive - {tcp, Socket, Data} -> - ok = file:write(File, Data), - receive_loop(Socket, File); - {tcp_closed, Socket} -> - file:close(File), - ok; - {tcp_error, Socket, Reason} -> - file:close(File), - {error, Reason} + {tcp, Socket, Data} -> + ok = file:write(File, Data), + receive_loop(Socket, File); + {tcp_closed, Socket} -> + file:close(File), + ok; + {tcp_error, Socket, Reason} -> + file:close(File), + {error, Reason} end. send_trace({Host, PortNumber}, FileName) when is_list(Host), is_integer(PortNumber), is_list(FileName) -> - ?line {ok, F} = file:open(FileName, [read, compressed]), - ?line {ok, S} = gen_tcp:connect(Host, PortNumber, [inet,{packet, 0}]), - ?line send_loop(S, F); + {ok, F} = file:open(FileName, [read, compressed]), + {ok, S} = gen_tcp:connect(Host, PortNumber, [inet,{packet, 0}]), + send_loop(S, F); send_trace(EmuFlag, FileName) when is_list(EmuFlag), is_list(FileName) -> - ?line ["+Mit", IpAddrStr, PortNoStr] = string:tokens(EmuFlag, " :"), - ?line send_trace({IpAddrStr, list_to_integer(PortNoStr)}, FileName). + ["+Mit", IpAddrStr, PortNoStr] = string:tokens(EmuFlag, " :"), + send_trace({IpAddrStr, list_to_integer(PortNoStr)}, FileName). send_loop(Socket, File) -> - ?line case file:read(File, 128) of - {ok, Data} -> - ?line case gen_tcp:send(Socket, Data) of - ok -> ?line send_loop(Socket, File); - Error -> - ?line gen_tcp:close(Socket), - ?line file:close(File), - Error - end; - eof -> - ?line gen_tcp:close(Socket), - ?line file:close(File), - ?line ok; - Error -> - ?line gen_tcp:close(Socket), - ?line file:close(File), - ?line Error - end. + case file:read(File, 128) of + {ok, Data} -> + case gen_tcp:send(Socket, Data) of + ok -> send_loop(Socket, File); + Error -> + gen_tcp:close(Socket), + file:close(File), + Error + end; + eof -> + gen_tcp:close(Socket), + file:close(File), + ok; + Error -> + gen_tcp:close(Socket), + file:close(File), + Error + end. check_emem(Dir, Type) when is_atom(Type) -> - ExeSuffix = case ?t:os_type() of - {win32, _} -> ".exe"; - _ -> "" - end, + ExeSuffix = case os:type() of + {win32, _} -> ".exe"; + _ -> "" + end, TypeSuffix = case Type of - opt -> ""; - _ -> "." ++ atom_to_list(Type) - end, + opt -> ""; + _ -> "." ++ atom_to_list(Type) + end, Emem = "emem" ++ TypeSuffix ++ ExeSuffix, case check_file(filename:join([Dir, Emem])) of - not_found -> ok; - File -> - Comment = case Type of - opt -> ""; - _ -> "[emem " ++ atom_to_list(Type) ++ " compiled]" - end, - throw([{emem, File}, {emem_comment, Comment}]) + not_found -> ok; + File -> + Comment = case Type of + opt -> ""; + _ -> "[emem " ++ atom_to_list(Type) ++ " compiled]" + end, + throw([{emem, File}, {emem_comment, Comment}]) end. check_dir(DirName) -> case file:read_file_info(DirName) of - {ok, #file_info {type = directory, access = A}} when A == read; - A == read_write -> - DirName; - _ -> - not_found + {ok, #file_info {type = directory, access = A}} when A == read; + A == read_write -> + DirName; + _ -> + not_found end. check_file(FileName) -> case file:read_file_info(FileName) of - {ok, #file_info {type = regular, access = A}} when A == read; - A == read_write -> - ?line FileName; - _ -> - ?line not_found + {ok, #file_info {type = regular, access = A}} when A == read; + A == read_write -> + FileName; + _ -> + not_found end. emem_comment(Config) when is_list(Config) -> @@ -529,158 +476,158 @@ emem_comment(Config) when is_list(Config) -> emem_comment(Config, ExtraComment) when is_list(Config), is_list(ExtraComment) -> - case {?config(emem_comment, Config), ExtraComment} of - {"", ""} -> ?line ok; - {"", XC} -> ?line {comment, XC}; - {EmemC, ""} -> ?line {comment, EmemC}; - {EmemC, XC} -> ?line {comment, EmemC ++ " " ++ XC} + case {proplists:get_value(emem_comment, Config), ExtraComment} of + {"", ""} -> ok; + {"", XC} -> {comment, XC}; + {EmemC, ""} -> {comment, EmemC}; + {EmemC, XC} -> {comment, EmemC ++ " " ++ XC} end. run_emem_on_casefile(Config) -> - CaseName = atom_to_list(?config(testcase, Config)), - ?line File = filename:join([?config(data_dir, Config), CaseName ++ ".gz"]), - ?line case check_file(File) of - not_found -> - ?line ?t:fail({error, {filenotfound, File}}); - _ -> - ?line ok - end, - ?line {ok, EmuFlag, Port} = start_emem(Config), - ?line Parent = self(), - ?line Ref = make_ref(), - ?line spawn_link(fun () -> - SRes = send_trace(EmuFlag, File), - Parent ! {Ref, SRes} - end), - ?line Res = get_emem_result(Port), - ?line receive - {Ref, ok} -> - ?line ok; - {Ref, SendError} -> - ?line ?t:format("Send result: ~p~n", [SendError]) - end, - ?line Res. + CaseName = atom_to_list(proplists:get_value(testcase, Config)), + File = filename:join([proplists:get_value(data_dir, Config), CaseName ++ ".gz"]), + case check_file(File) of + not_found -> + ct:fail({error, {filenotfound, File}}); + _ -> + ok + end, + {ok, EmuFlag, Port} = start_emem(Config), + Parent = self(), + Ref = make_ref(), + spawn_link(fun () -> + SRes = send_trace(EmuFlag, File), + Parent ! {Ref, SRes} + end), + Res = get_emem_result(Port), + receive + {Ref, ok} -> + ok; + {Ref, SendError} -> + io:format("Send result: ~p~n", [SendError]) + end, + Res. get_emem_result(Port) -> - ?line {Res, LV} = get_emem_result(Port, {#emem_res{}, []}), - ?line Res#emem_res{last_values = string:tokens(LV, " ")}. + {Res, LV} = get_emem_result(Port, {#emem_res{}, []}), + Res#emem_res{last_values = string:tokens(LV, " ")}. get_emem_result(Port, {_EmemRes, _LastValues} = Res) -> - ?line case get_emem_line(Port) of - eof -> - ?line Res; - Line -> - ?line get_emem_result(Port, parse_emem_line(Line, Res)) - end. + case get_emem_line(Port) of + eof -> + Res; + Line -> + get_emem_result(Port, parse_emem_line(Line, Res)) + end. parse_emem_main_header_footer_line(Line, {ER, LV} = Res) -> %% Header - ?line case has_prefix("> Nodename:", Line) of - {true, NN} -> - ?line throw({ER#emem_res{nodename = strip(NN)}, LV}); - false -> ?line ok - end, - ?line case has_prefix("> Hostname:", Line) of - {true, HN} -> - ?line throw({ER#emem_res{hostname = strip(HN)}, LV}); - false -> ?line ok - end, - ?line case has_prefix("> Pid:", Line) of - {true, P} -> - ?line throw({ER#emem_res{pid = strip(P)}, LV}); - false -> ?line ok - end, - ?line case has_prefix("> Start time (UTC):", Line) of - {true, ST} -> - ?line throw({ER#emem_res{start_time = strip(ST)}, LV}); - false -> ?line ok - end, - ?line case has_prefix("> Actual trace version:", Line) of - {true, TV} -> - ?line throw({ER#emem_res{trace_version = strip(TV)}, LV}); - false -> ?line ok - end, - ?line case has_prefix("> Maximum trace word size:", Line) of - {true, MWS} -> - ?line throw({ER#emem_res{max_word_size = strip(MWS)}, LV}); - false -> ?line ok - end, - ?line case has_prefix("> Actual trace word size:", Line) of - {true, WS} -> - ?line throw({ER#emem_res{word_size = strip(WS)}, LV}); - false -> ?line ok - end, + case has_prefix("> Nodename:", Line) of + {true, NN} -> + throw({ER#emem_res{nodename = strip(NN)}, LV}); + false -> ok + end, + case has_prefix("> Hostname:", Line) of + {true, HN} -> + throw({ER#emem_res{hostname = strip(HN)}, LV}); + false -> ok + end, + case has_prefix("> Pid:", Line) of + {true, P} -> + throw({ER#emem_res{pid = strip(P)}, LV}); + false -> ok + end, + case has_prefix("> Start time (UTC):", Line) of + {true, ST} -> + throw({ER#emem_res{start_time = strip(ST)}, LV}); + false -> ok + end, + case has_prefix("> Actual trace version:", Line) of + {true, TV} -> + throw({ER#emem_res{trace_version = strip(TV)}, LV}); + false -> ok + end, + case has_prefix("> Maximum trace word size:", Line) of + {true, MWS} -> + throw({ER#emem_res{max_word_size = strip(MWS)}, LV}); + false -> ok + end, + case has_prefix("> Actual trace word size:", Line) of + {true, WS} -> + throw({ER#emem_res{word_size = strip(WS)}, LV}); + false -> ok + end, %% Footer - ?line case has_prefix("> Maximum:", Line) of - {true, M} -> - ?line throw({ER#emem_res{maximum = string:tokens(M," ")}, LV}); - false -> ?line ok - end, - ?line case has_prefix("> Emulator exited with code:", Line) of - {true, EC} -> - ?line throw({ER#emem_res{exit_code = strip(EC)}, LV}); - false -> ?line ok - end, - ?line Res. + case has_prefix("> Maximum:", Line) of + {true, M} -> + throw({ER#emem_res{maximum = string:tokens(M," ")}, LV}); + false -> ok + end, + case has_prefix("> Emulator exited with code:", Line) of + {true, EC} -> + throw({ER#emem_res{exit_code = strip(EC)}, LV}); + false -> ok + end, + Res. parse_emem_header_line(_Line, {_ER, _LV} = Res) -> - ?line Res. - + Res. + parse_emem_value_line(Line, {EmemRes, _OldLastValues}) -> - ?line {EmemRes, Line}. + {EmemRes, Line}. parse_emem_line("", Res) -> - ?line Res; + Res; parse_emem_line(Line, Res) -> - ?line [Prefix | _] = Line, + [Prefix | _] = Line, case Prefix of - $> -> ?line catch parse_emem_main_header_footer_line(Line, Res); - $| -> ?line catch parse_emem_header_line(Line, Res); - _ -> ?line catch parse_emem_value_line(Line, Res) + $> -> catch parse_emem_main_header_footer_line(Line, Res); + $| -> catch parse_emem_header_line(Line, Res); + _ -> catch parse_emem_value_line(Line, Res) end. start_emem(Config) when is_list(Config) -> - ?line Emem = ?config(emem, Config), - ?line Cd = case ignore_cores:dir(Config) of - false -> []; - Dir -> [{cd, Dir}] - end, - ?line case open_port({spawn, Emem ++ " -t -n -o -i 1"}, - Cd ++ [{line, 1024}, eof]) of - Port when is_port(Port) -> ?line {ok, read_emu_flag(Port), Port}; - Error -> ?line ?t:fail(Error) - end. + Emem = proplists:get_value(emem, Config), + Cd = case ignore_cores:dir(Config) of + false -> []; + Dir -> [{cd, Dir}] + end, + case open_port({spawn, Emem ++ " -t -n -o -i 1"}, + Cd ++ [{line, 1024}, eof]) of + Port when is_port(Port) -> {ok, read_emu_flag(Port), Port}; + Error -> ct:fail(Error) + end. read_emu_flag(Port) -> - ?line Line = case get_emem_line(Port) of - eof -> ?line ?t:fail(unexpected_end_of_file); - L -> ?line L - end, - ?line case has_prefix("> Emulator command line argument:", Line) of - {true, EmuFlag} -> EmuFlag; - false -> ?line read_emu_flag(Port) - end. + Line = case get_emem_line(Port) of + eof -> ct:fail(unexpected_end_of_file); + L -> L + end, + case has_prefix("> Emulator command line argument:", Line) of + {true, EmuFlag} -> EmuFlag; + false -> read_emu_flag(Port) + end. get_emem_line(Port, Acc) -> - ?line receive - {Port, {data, {eol, Data}}} -> - ?line Res = case Acc of - [] -> ?line Data; - _ -> ?line lists:flatten([Acc|Data]) - end, - ?line ?t:format("~s", [Res]), - ?line Res; - {Port, {data, {noeol, Data}}} -> - ?line get_emem_line(Port, [Acc|Data]); - {Port, eof} -> - ?line port_close(Port), - ?line eof - end. + receive + {Port, {data, {eol, Data}}} -> + Res = case Acc of + [] -> Data; + _ -> lists:flatten([Acc|Data]) + end, + io:format("~s", [Res]), + Res; + {Port, {data, {noeol, Data}}} -> + get_emem_line(Port, [Acc|Data]); + {Port, eof} -> + port_close(Port), + eof + end. get_emem_line(Port) -> - ?line get_emem_line(Port, []). + get_emem_line(Port, []). short_hostname([]) -> []; @@ -697,28 +644,13 @@ has_prefix(_, _) -> false. strip(Str) -> string:strip(Str). - + mk_nodename(Config) -> - {A, B, C} = now(), + Us = erlang:monotonic_time(), atom_to_list(?MODULE) - ++ "-" ++ atom_to_list(?config(testcase, Config)) - ++ "-" ++ integer_to_list(A*1000000000000 + B*1000000 + C). + ++ "-" ++ atom_to_list(proplists:get_value(testcase, Config)) + ++ integer_to_list(Us). start_node(Name, Args) -> - ?line Pa = filename:dirname(code:which(?MODULE)), - ?line ?t:start_node(Name, peer, [{args, Args ++ " -pa " ++ Pa}]). - -% stop_node(Node) -> -% ?t:stop_node(Node). - -is_debug_compiled() -> -is_debug_compiled(erlang:system_info(system_version)). - -is_debug_compiled([$d,$e,$b,$u,$g | _]) -> - true; -is_debug_compiled([ _, _, _, _]) -> - false; -is_debug_compiled([]) -> - false; -is_debug_compiled([_|Rest]) -> - is_debug_compiled(Rest). + Pa = filename:dirname(code:which(?MODULE)), + test_server:start_node(Name, peer, [{args, Args ++ " -pa " ++ Pa}]). diff --git a/lib/tools/test/eprof_SUITE.erl b/lib/tools/test/eprof_SUITE.erl index 5428643667..e908413315 100644 --- a/lib/tools/test/eprof_SUITE.erl +++ b/lib/tools/test/eprof_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2013. All Rights Reserved. +%% Copyright Ericsson AB 1996-2016. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -19,42 +19,25 @@ %% -module(eprof_SUITE). --include_lib("test_server/include/test_server.hrl"). - --export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, - init_per_group/2,end_per_group/2]). +-include_lib("common_test/include/ct.hrl"). +-export([all/0, suite/0]). -export([tiny/1,eed/1,basic/1,basic_option/1]). -suite() -> [{ct_hooks,[ts_install_cth]}]. +suite() -> + [{ct_hooks,[ts_install_cth]}, + {timetrap,{seconds,60}}]. all() -> [basic, basic_option, tiny, eed]. -groups() -> - []. - -init_per_suite(Config) -> - Config. - -end_per_suite(_Config) -> - ok. - -init_per_group(_GroupName, Config) -> - Config. - -end_per_group(_GroupName, Config) -> - Config. - - -basic(suite) -> []; basic(Config) when is_list(Config) -> %% load eprof_test and change directory {ok, OldCurDir} = file:get_cwd(), - Datadir = ?config(data_dir, Config), - Privdir = ?config(priv_dir, Config), + Datadir = proplists:get_value(data_dir, Config), + Privdir = proplists:get_value(priv_dir, Config), {ok,eprof_test} = compile:file(filename:join(Datadir, "eprof_test"), [trace,{outdir, Privdir}]), ok = file:set_cwd(Privdir), @@ -98,9 +81,6 @@ basic(Config) when is_list(Config) -> %% error case - error = eprof:profile([Pid], fun() -> eprof_test:go(10) end), - Pid = whereis(eprof), - error = eprof:profile([Pid], fun() -> eprof_test:go(10) end), A = spawn(fun() -> receive _ -> ok end end), profiling = eprof:profile([A]), true = exit(A, kill_it), @@ -139,8 +119,8 @@ basic_option_1(Config) -> %% load eprof_test and change directory {ok, OldCurDir} = file:get_cwd(), - Datadir = ?config(data_dir, Config), - Privdir = ?config(priv_dir, Config), + Datadir = proplists:get_value(data_dir, Config), + Privdir = proplists:get_value(priv_dir, Config), {ok,eprof_test} = compile:file(filename:join(Datadir, "eprof_test"), [trace,{outdir, Privdir}]), ok = file:set_cwd(Privdir), @@ -178,13 +158,11 @@ basic_option_1(Config) -> stopped = eprof:stop(), ok. -tiny(suite) -> []; tiny(Config) when is_list(Config) -> ensure_eprof_stopped(), {ok, OldCurDir} = file:get_cwd(), - Datadir = ?config(data_dir, Config), - Privdir = ?config(priv_dir, Config), - TTrap=?t:timetrap(60*1000), + Datadir = proplists:get_value(data_dir, Config), + Privdir = proplists:get_value(priv_dir, Config), % (Trace)Compile to priv_dir and make sure the correct version is loaded. {ok,eprof_suite_test} = compile:file(filename:join(Datadir, "eprof_suite_test"), @@ -200,16 +178,14 @@ tiny(Config) when is_list(Config) -> ok = eprof:analyze(total), ok = eprof:log("eprof_SUITE_logfile"), stopped = eprof:stop(), - ?t:timetrap_cancel(TTrap), ok = file:set_cwd(OldCurDir), ok. -eed(suite) -> []; eed(Config) when is_list(Config) -> ensure_eprof_stopped(), - Datadir = ?config(data_dir, Config), - Privdir = ?config(priv_dir, Config), - TTrap=?t:timetrap(5*60*1000), + Datadir = proplists:get_value(data_dir, Config), + Privdir = proplists:get_value(priv_dir, Config), + ct:timetrap({minutes, 5}), %% (Trace)Compile to priv_dir and make sure the correct version is loaded. code:purge(eed), @@ -236,7 +212,6 @@ eed(Config) when is_list(Config) -> ok = eprof:analyze(total), ok = eprof:log("eprof_SUITE_logfile"), stopped = eprof:stop(), - ?t:timetrap_cancel(TTrap), try S = lists:flatten(io_lib:format("~p times slower", [10*(T3-T2)/(T2-T1)])), diff --git a/lib/tools/test/fprof_SUITE.erl b/lib/tools/test/fprof_SUITE.erl index e8f179c630..affb45b7a6 100644 --- a/lib/tools/test/fprof_SUITE.erl +++ b/lib/tools/test/fprof_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2001-2012. All Rights Reserved. +%% Copyright Ericsson AB 2001-2016. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -19,28 +19,23 @@ %% -module(fprof_SUITE). --include_lib("test_server/include/test_server.hrl"). +-include_lib("common_test/include/ct.hrl"). %% Test server framework exports --export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, - init_per_group/2,end_per_group/2, not_run/1]). +-export([all/0, suite/0, not_run/1]). %% Test suites -export([stack_seq/1, tail_seq/1, create_file_slow/1, spawn_simple/1, - imm_tail_seq/1, imm_create_file_slow/1, imm_compile/1, - cpu_create_file_slow/1]). + imm_tail_seq/1, imm_create_file_slow/1, imm_compile/1, + cpu_create_file_slow/1]). %% Other exports -export([create_file_slow/2]). - %% Debug exports -export([parse/1, verify/2]). -export([spawn_simple_test/3]). - --define(line_trace,true). - %-define(debug,true). -ifdef(debug). -define(dbg(Str,Args), io:format(Str,Args)). @@ -49,553 +44,495 @@ -endif. - %%%--------------------------------------------------------------------- %%% Test suites %%%--------------------------------------------------------------------- - -suite() -> [{ct_hooks,[ts_install_cth]}]. +suite() -> + [{ct_hooks,[ts_install_cth]}, + {timetrap,{seconds,60}}]. all() -> case test_server:is_native(fprof_SUITE) of - true -> [not_run]; - false -> - [stack_seq, tail_seq, create_file_slow, spawn_simple, - imm_tail_seq, imm_create_file_slow, imm_compile, - cpu_create_file_slow] + true -> [not_run]; + false -> + [stack_seq, tail_seq, create_file_slow, spawn_simple, + imm_tail_seq, imm_create_file_slow, imm_compile, + cpu_create_file_slow] end. -groups() -> - []. - -init_per_suite(Config) -> - Config. - -end_per_suite(_Config) -> - ok. - -init_per_group(_GroupName, Config) -> - Config. - -end_per_group(_GroupName, Config) -> - Config. - not_run(Config) when is_list(Config) -> {skipped, "Native code"}. %%%--------------------------------------------------------------------- -stack_seq(doc) -> - ["Tests a stack recursive variant of lists:seq/3"]; -stack_seq(suite) -> - []; +%% Tests a stack recursive variant of lists:seq/3 stack_seq(Config) when is_list(Config) -> - ?line Timetrap = ?t:timetrap(?t:seconds(20)), - ?line PrivDir = ?config(priv_dir, Config), - ?line TraceFile = - filename:join(PrivDir, ?MODULE_STRING"_stack_seq.trace"), - ?line AnalysisFile = - filename:join(PrivDir, ?MODULE_STRING"_stack_seq.analysis"), - ?line Start = 1, - ?line Stop = 1000, - ?line Succ = fun (X) -> X + 1 end, - ?line ok = fprof:stop(kill), + PrivDir = proplists:get_value(priv_dir, Config), + TraceFile = filename:join(PrivDir, + ?MODULE_STRING"_stack_seq.trace"), + AnalysisFile = filename:join(PrivDir, + ?MODULE_STRING"_stack_seq.analysis"), + Start = 1, + Stop = 1000, + Succ = fun (X) -> X + 1 end, + ok = fprof:stop(kill), %% - ?line TS0 = erlang:now(), - ?line R0 = fprof:apply(fun seq/3, [Start, Stop, Succ], [{file, TraceFile}]), - ?line TS1 = erlang:now(), - ?line R = seq(Start, Stop, Succ), - ?line TS2 = erlang:now(), - ?line ok = fprof:profile(file, TraceFile), - ?line ok = fprof:analyse(), - ?line ok = fprof:analyse(dest, AnalysisFile), - ?line ok = fprof:stop(), - ?line R = R0, + TS0 = erlang:monotonic_time(), + R0 = fprof:apply(fun seq/3, [Start, Stop, Succ], [{file, TraceFile}]), + TS1 = erlang:monotonic_time(), + R = seq(Start, Stop, Succ), + TS2 = erlang:monotonic_time(), + ok = fprof:profile(file, TraceFile), + ok = fprof:analyse(), + ok = fprof:analyse(dest, AnalysisFile), + ok = fprof:stop(), + R = R0, %% - ?line {ok, [T, P]} = parse(AnalysisFile), - ?line io:format("~p~n~n~p~n", [P, ets:tab2list(T)]), - ?line ok = (catch verify(T, P)), - ?line Proc = pid_to_list(self()), - ?line case P of - [{analysis_options, _}, - [{totals, _, Acc, _}], - [{Proc, _, undefined, _} | _]] -> - ok - end, + {ok, [T, P]} = parse(AnalysisFile), + io:format("~p~n~n~p~n", [P, ets:tab2list(T)]), + ok = (catch verify(T, P)), + Proc = pid_to_list(self()), + case P of + [{analysis_options, _}, + [{totals, _, Acc, _}], + [{Proc, _, undefined, _} | _]] -> + ok + end, %% - ?line check_own_and_acc(TraceFile,AnalysisFile), + check_own_and_acc(TraceFile,AnalysisFile), %% - ?line ets:delete(T), - ?line file:delete(TraceFile), - ?line file:delete(AnalysisFile), - ?line ?t:timetrap_cancel(Timetrap), - ?line Acc1 = ts_sub(TS1, TS0), - ?line Acc2 = ts_sub(TS2, TS1), - ?line io:format("ts:~w, fprof:~w, bare:~w.~n", [Acc, Acc1, Acc2]), - {comment, io_lib:format("~p times slower", [Acc1/Acc2])}. + ets:delete(T), + file:delete(TraceFile), + file:delete(AnalysisFile), + Acc1 = TS1 - TS0, + Acc2 = TS2 - TS1, + io:format("ts:~w, fprof:~w, bare:~w.~n", [Acc, Acc1, Acc2]), + {comment, io_lib:format("~p times slower", [divide(Acc1,Acc2)])}. %%%--------------------------------------------------------------------- -tail_seq(doc) -> - ["Tests a tail recursive variant of lists:seq/3"]; -tail_seq(suite) -> - []; +%% Tests a tail recursive variant of lists:seq/3 tail_seq(Config) when is_list(Config) -> - ?line Timetrap = ?t:timetrap(?t:seconds(10)), - ?line PrivDir = ?config(priv_dir, Config), - ?line TraceFile = - filename:join(PrivDir, ?MODULE_STRING"_tail_seq.trace"), - ?line AnalysisFile = - filename:join(PrivDir, ?MODULE_STRING"_tail_seq.analysis"), - ?line Start = 1, - ?line Stop = 1000, - ?line Succ = fun (X) -> X + 1 end, - ?line ok = fprof:stop(kill), + PrivDir = proplists:get_value(priv_dir, Config), + TraceFile = filename:join(PrivDir, + ?MODULE_STRING"_tail_seq.trace"), + AnalysisFile = filename:join(PrivDir, + ?MODULE_STRING"_tail_seq.analysis"), + Start = 1, + Stop = 1000, + Succ = fun (X) -> X + 1 end, + ok = fprof:stop(kill), %% - ?line TS0 = erlang:now(), - ?line R = seq_r(Start, Stop, Succ), - ?line TS1 = erlang:now(), + TS0 = erlang:monotonic_time(), + R = seq_r(Start, Stop, Succ), + TS1 = erlang:monotonic_time(), %% - ?line R1 = fprof:apply(fun seq_r/3, [Start, Stop, Succ], - [{file, TraceFile}]), - ?line TS2 = erlang:now(), - ?line ok = fprof:profile([{file,TraceFile}]), - ?line ok = fprof:analyse(), - ?line ok = fprof:analyse(dest, AnalysisFile), - ?line ok = fprof:stop(), - ?line R = R1, + R1 = fprof:apply(fun seq_r/3, [Start, Stop, Succ], + [{file, TraceFile}]), + TS2 = erlang:monotonic_time(), + ok = fprof:profile([{file,TraceFile}]), + ok = fprof:analyse(), + ok = fprof:analyse(dest, AnalysisFile), + ok = fprof:stop(), + R = R1, %% - ?line {ok, [T, P]} = parse(AnalysisFile), - ?line io:format("~p~n~n~p~n", [P, ets:tab2list(T)]), - ?line ok = verify(T, P), - ?line Proc = pid_to_list(self()), - ?line case P of - [{analysis_options, _}, - [{totals, _, Acc, _}], - [{Proc, _, undefined, _} | _]] -> - ok - end, + {ok, [T, P]} = parse(AnalysisFile), + io:format("~p~n~n~p~n", [P, ets:tab2list(T)]), + ok = verify(T, P), + Proc = pid_to_list(self()), + case P of + [{analysis_options, _}, + [{totals, _, Acc, _}], + [{Proc, _, undefined, _} | _]] -> + ok + end, %% - ?line check_own_and_acc(TraceFile,AnalysisFile), + check_own_and_acc(TraceFile,AnalysisFile), %% - ?line ets:delete(T), - ?line file:delete(TraceFile), - ?line file:delete(AnalysisFile), - ?line ?t:timetrap_cancel(Timetrap), - ?line Acc1 = ts_sub(TS1, TS0), - ?line Acc2 = ts_sub(TS2, TS1), - ?line io:format("ts:~w, fprof:~w, bare:~w.~n", [Acc, Acc2, Acc1]), - {comment, io_lib:format("~p times slower", [Acc2/Acc1])}. + ets:delete(T), + file:delete(TraceFile), + file:delete(AnalysisFile), + Acc1 = TS1 - TS0, + Acc2 = TS2 - TS1, + io:format("ts:~w, fprof:~w, bare:~w.~n", [Acc, Acc2, Acc1]), + {comment, io_lib:format("~p times slower", [divide(Acc2,Acc1)])}. %%%--------------------------------------------------------------------- %% Tests the create_file_slow benchmark. create_file_slow(Config) -> case test_server:is_native(lists) orelse - test_server:is_native(file) of - true -> - {skip,"Native libs -- tracing does not work"}; - false -> - do_create_file_slow(Config) + test_server:is_native(file) of + true -> + {skip,"Native libs -- tracing does not work"}; + false -> + do_create_file_slow(Config) end. do_create_file_slow(Config) -> - ?line Timetrap = ?t:timetrap(?t:seconds(40)), - ?line PrivDir = ?config(priv_dir, Config), - ?line TraceFile = - filename:join(PrivDir, ?MODULE_STRING"_create_file_slow.trace"), - ?line AnalysisFile = - filename:join(PrivDir, ?MODULE_STRING"_create_file_slow.analysis"), - ?line DataFile = - filename:join(PrivDir, ?MODULE_STRING"_create_file_slow.data"), - ?line ok = fprof:stop(kill), + PrivDir = proplists:get_value(priv_dir, Config), + TraceFile = filename:join(PrivDir, + ?MODULE_STRING"_create_file_slow.trace"), + AnalysisFile = filename:join(PrivDir, + ?MODULE_STRING"_create_file_slow.analysis"), + DataFile = filename:join(PrivDir, + ?MODULE_STRING"_create_file_slow.data"), + ok = fprof:stop(kill), %% - ?line TS0 = erlang:now(), - ?line ok = create_file_slow(DataFile, 1024), - ?line TS1 = erlang:now(), + TS0 = erlang:monotonic_time(), + ok = create_file_slow(DataFile, 1024), + TS1 = erlang:monotonic_time(), %% - ?line ok = file:delete(DataFile), - ?line TS2 = erlang:now(), - ?line ok = fprof:apply(?MODULE, create_file_slow, [DataFile, 1024], - [{file, TraceFile}]), - ?line TS3 = erlang:now(), - ?line ok = fprof:profile(file, TraceFile), - ?line ok = fprof:analyse(), - ?line ok = fprof:analyse(dest, AnalysisFile), - ?line ok = fprof:stop(), + ok = file:delete(DataFile), + TS2 = erlang:monotonic_time(), + ok = fprof:apply(?MODULE, create_file_slow, [DataFile, 1024], + [{file, TraceFile}]), + TS3 = erlang:monotonic_time(), + ok = fprof:profile(file, TraceFile), + ok = fprof:analyse(), + ok = fprof:analyse(dest, AnalysisFile), + ok = fprof:stop(), %% - ?line {ok, [T, P]} = parse(AnalysisFile), - ?line io:format("~p~n~n~p~n", [P, ets:tab2list(T)]), - ?line ok = verify(T, P), - ?line Proc = pid_to_list(self()), - ?line case P of - [{analysis_options, _}, - [{totals, _, Acc, _}], - [{Proc, _, undefined, _} | _]] -> - ok - end, + {ok, [T, P]} = parse(AnalysisFile), + io:format("~p~n~n~p~n", [P, ets:tab2list(T)]), + ok = verify(T, P), + Proc = pid_to_list(self()), + case P of + [{analysis_options, _}, + [{totals, _, Acc, _}], + [{Proc, _, undefined, _} | _]] -> + ok + end, %% - ?line check_own_and_acc(TraceFile,AnalysisFile), + check_own_and_acc(TraceFile,AnalysisFile), %% - ?line ets:delete(T), - ?line file:delete(DataFile), - ?line file:delete(TraceFile), - ?line file:delete(AnalysisFile), - ?line ?t:timetrap_cancel(Timetrap), - ?line Acc1 = ts_sub(TS1, TS0), - ?line Acc3 = ts_sub(TS3, TS2), - ?line io:format("ts:~w, fprof:~w, bare:~w.~n", [Acc, Acc3, Acc1]), - {comment, io_lib:format("~p times slower", [Acc3/Acc1])}. + ets:delete(T), + file:delete(DataFile), + file:delete(TraceFile), + file:delete(AnalysisFile), + Acc1 = TS1 - TS0, + Acc3 = TS3 - TS2, + io:format("ts:~w, fprof:~w, bare:~w.~n", [Acc, Acc3, Acc1]), + {comment, io_lib:format("~p times slower", [divide(Acc3,Acc1)])}. %%%--------------------------------------------------------------------- -spawn_simple(doc) -> - ["Tests process spawn"]; -spawn_simple(suite) -> - []; +%% Tests process spawn spawn_simple(Config) when is_list(Config) -> - ?line Timetrap = ?t:timetrap(?t:seconds(30)), - ?line PrivDir = ?config(priv_dir, Config), - ?line TraceFile = - filename:join(PrivDir, ?MODULE_STRING"_spawn_simple.trace"), - ?line AnalysisFile = - filename:join(PrivDir, ?MODULE_STRING"_spawn_simple.analysis"), - ?line Start = 1, - ?line Stop = 1000, - ?line Succ = fun (X) -> X + 1 end, - ?line ok = fprof:stop(kill), + PrivDir = proplists:get_value(priv_dir, Config), + TraceFile = filename:join(PrivDir, + ?MODULE_STRING"_spawn_simple.trace"), + AnalysisFile = filename:join(PrivDir, + ?MODULE_STRING"_spawn_simple.analysis"), + Start = 1, + Stop = 1000, + Succ = fun (X) -> X + 1 end, + ok = fprof:stop(kill), %% - ?line TS0 = erlang:now(), - ?line {{_, R1}, {_, R2}} = spawn_simple_test(Start, Stop, Succ), - ?line TS1 = erlang:now(), + TS0 = erlang:monotonic_time(), + {{_, R1}, {_, R2}} = spawn_simple_test(Start, Stop, Succ), + TS1 = erlang:monotonic_time(), %% - ?line ok = fprof:trace(start, TraceFile), - ?line {{P1, R3}, {P2, R4}} = spawn_simple_test(Start, Stop, Succ), - ?line ok = fprof:trace(stop), - ?line TS2 = erlang:now(), - ?line ok = fprof:profile(file, TraceFile), - ?line ok = fprof:analyse(), - ?line ok = fprof:analyse(dest, AnalysisFile), - ?line ok = fprof:stop(), - ?line R1 = R3, - ?line R2 = R4, + ok = fprof:trace(start, TraceFile), + {{P1, R3}, {P2, R4}} = spawn_simple_test(Start, Stop, Succ), + ok = fprof:trace(stop), + TS2 = erlang:monotonic_time(), + ok = fprof:profile(file, TraceFile), + ok = fprof:analyse(), + ok = fprof:analyse(dest, AnalysisFile), + ok = fprof:stop(), + R1 = R3, + R2 = R4, %% - ?line {ok, [T, P]} = parse(AnalysisFile), - ?line io:format("~p~n~n~p~n", [P, ets:tab2list(T)]), - ?line ok = verify(T, P), - ?line Proc1 = pid_to_list(P1), - ?line Proc2 = pid_to_list(P2), - ?line Proc0 = pid_to_list(self()), - ?line io:format("~p~n ~p ~p ~p~n", [P, Proc0, Proc1, Proc2]), - ?line [{analysis_options, _}, [{totals, _, Acc, _}] | Procs] = P, - ?line [[{Proc0, _, undefined, _} | _]] = - lists:filter(fun ([Pt | _]) when element(1, Pt) == Proc0 -> true; - (_) -> false - end, Procs), - ?line [[{Proc1, _, undefined, _}, - {spawned_by, Proc0}, - {spawned_as, {erlang, apply, ["#Fun"++_, []]}}, - {initial_calls, [{erlang, apply, 2}, - {?MODULE, '-spawn_simple_test/3-fun-0-', 4}]} - | _]] = - lists:filter(fun ([Pt | _]) when element(1, Pt) == Proc1 -> true; - (_) -> false - end, Procs), - ?line [[{Proc2, _, undefined, _}, - {spawned_by, Proc0}, - {spawned_as, {erlang, apply, ["#Fun"++_, []]}}, - {initial_calls, [{erlang, apply, 2}, - {?MODULE, '-spawn_simple_test/3-fun-1-', 4}]} - | _]] = - lists:filter(fun ([Pt | _]) when element(1, Pt) == Proc2 -> true; - (_) -> false - end, Procs), - ?line 3 = length(Procs), - ?line R1 = lists:reverse(R2), + {ok, [T, P]} = parse(AnalysisFile), + io:format("~p~n~n~p~n", [P, ets:tab2list(T)]), + ok = verify(T, P), + Proc1 = pid_to_list(P1), + Proc2 = pid_to_list(P2), + Proc0 = pid_to_list(self()), + io:format("~p~n ~p ~p ~p~n", [P, Proc0, Proc1, Proc2]), + [{analysis_options, _}, [{totals, _, Acc, _}] | Procs] = P, + [[{Proc0, _, undefined, _} | _]] = lists:filter( + fun ([Pt | _]) when element(1, Pt) == Proc0 -> true; + (_) -> false + end, Procs), + [[{Proc1, _, undefined, _}, + {spawned_by, Proc0}, + {spawned_as, {erlang, apply, ["#Fun"++_, []]}}, + {initial_calls, [{erlang, apply, 2}, + {?MODULE, '-spawn_simple_test/3-fun-0-', 4}]} + | _]] = lists:filter(fun ([Pt | _]) when element(1, Pt) == Proc1 -> true; + (_) -> false + end, Procs), + [[{Proc2, _, undefined, _}, + {spawned_by, Proc0}, + {spawned_as, {erlang, apply, ["#Fun"++_, []]}}, + {initial_calls, [{erlang, apply, 2}, + {?MODULE, '-spawn_simple_test/3-fun-1-', 4}]} + | _]] = lists:filter(fun ([Pt | _]) when element(1, Pt) == Proc2 -> true; + (_) -> false + end, Procs), + 3 = length(Procs), + R1 = lists:reverse(R2), %% - ?line check_own_and_acc(TraceFile,AnalysisFile), + check_own_and_acc(TraceFile,AnalysisFile), %% - ?line ets:delete(T), - ?line file:delete(TraceFile), - ?line file:delete(AnalysisFile), - ?line ?t:timetrap_cancel(Timetrap), - ?line Acc1 = ts_sub(TS1, TS0), - ?line Acc2 = ts_sub(TS2, TS1), - ?line io:format("ts:~w, fprof:~w, bare:~w.~n", [Acc, Acc2, Acc1]), - {comment, io_lib:format("~p times slower", [Acc2/Acc1])}. + ets:delete(T), + file:delete(TraceFile), + file:delete(AnalysisFile), + Acc1 = TS1 - TS0, + Acc2 = TS2 - TS1, + io:format("ts:~w, fprof:~w, bare:~w.~n", [Acc, Acc2, Acc1]), + {comment, io_lib:format("~p times slower", [divide(Acc2,Acc1)])}. spawn_simple_test(Start, Stop, Succ) -> Parent = self(), - Seq = - spawn_link( - fun () -> - Parent ! {self(), seq(Start, Stop, Succ)} - end), - SeqR = - spawn_link( - fun () -> - Parent ! {self(), seq_r(Start, Stop, Succ)} - end), - receive {Seq, SeqResult} -> - receive {SeqR, SeqRResult} -> - {{Seq, SeqResult}, {SeqR, SeqRResult}} - end + Seq = spawn_link(fun() -> + Parent ! {self(), seq(Start, Stop, Succ)} + end), + + SeqR = spawn_link(fun() -> + Parent ! {self(), seq_r(Start, Stop, Succ)} + end), + receive + {Seq, SeqResult} -> + receive + {SeqR, SeqRResult} -> + {{Seq, SeqResult}, {SeqR, SeqRResult}} + end end. %%%--------------------------------------------------------------------- -imm_tail_seq(doc) -> - ["Tests a tail recursive variant of lists:seq/3 ", - "with immediate trace to profile"]; -imm_tail_seq(suite) -> - []; +%% Tests a tail recursive variant of lists:seq/3 +%% with immediate trace to profile imm_tail_seq(Config) when is_list(Config) -> - ?line Timetrap = ?t:timetrap(?t:seconds(10)), - ?line PrivDir = ?config(priv_dir, Config), - ?line AnalysisFile = - filename:join(PrivDir, ?MODULE_STRING"_imm_tail_seq.analysis"), - ?line Start = 1, - ?line Stop = 1000, - ?line Succ = fun (X) -> X + 1 end, - ?line ok = fprof:stop(kill), - ?line catch eprof:stop(), + PrivDir = proplists:get_value(priv_dir, Config), + AnalysisFile = filename:join(PrivDir, + ?MODULE_STRING"_imm_tail_seq.analysis"), + Start = 1, + Stop = 1000, + Succ = fun (X) -> X + 1 end, + ok = fprof:stop(kill), + catch eprof:stop(), %% - ?line TS0 = erlang:now(), - ?line R0 = seq_r(Start, Stop, Succ), - ?line TS1 = erlang:now(), + TS0 = erlang:monotonic_time(), + R0 = seq_r(Start, Stop, Succ), + TS1 = erlang:monotonic_time(), %% - ?line profiling = eprof:start_profiling([self()]), - ?line TS2 = erlang:now(), - ?line R2 = seq_r(Start, Stop, Succ), - ?line TS3 = erlang:now(), - ?line profiling_stopped = eprof:stop_profiling(), - ?line R2 = R0, + profiling = eprof:start_profiling([self()]), + TS2 = erlang:monotonic_time(), + R2 = seq_r(Start, Stop, Succ), + TS3 = erlang:monotonic_time(), + profiling_stopped = eprof:stop_profiling(), + R2 = R0, %% - ?line eprof:analyze(), - ?line stopped = eprof:stop(), + eprof:analyze(), + stopped = eprof:stop(), %% - ?line {ok, Tracer} = fprof:profile(start), - ?line ok = fprof:trace([start, {tracer, Tracer}]), - ?line TS4 = erlang:now(), - ?line R4 = seq_r(Start, Stop, Succ), - ?line TS5 = erlang:now(), - ?line ok = fprof:trace(stop), - ?line ok = fprof:analyse(), - ?line ok = fprof:analyse(dest, AnalysisFile), - ?line ok = fprof:stop(), - ?line R4 = R0, + {ok, Tracer} = fprof:profile(start), + ok = fprof:trace([start, {tracer, Tracer}]), + TS4 = erlang:monotonic_time(), + R4 = seq_r(Start, Stop, Succ), + TS5 = erlang:monotonic_time(), + ok = fprof:trace(stop), + ok = fprof:analyse(), + ok = fprof:analyse(dest, AnalysisFile), + ok = fprof:stop(), + R4 = R0, %% - ?line {ok, [T, P]} = parse(AnalysisFile), - ?line io:format("~p~n~n~p~n", [P, ets:tab2list(T)]), - ?line ok = verify(T, P), - ?line Proc = pid_to_list(self()), - ?line case P of - [{analysis_options, _}, - [{totals, _, Acc, _}], - [{Proc, _, undefined, _} | _]] -> - ok - end, + {ok, [T, P]} = parse(AnalysisFile), + io:format("~p~n~n~p~n", [P, ets:tab2list(T)]), + ok = verify(T, P), + Proc = pid_to_list(self()), + case P of + [{analysis_options, _}, + [{totals, _, Acc, _}], + [{Proc, _, undefined, _} | _]] -> ok + end, %% - ?line ets:delete(T), - ?line file:delete(AnalysisFile), - ?line ?t:timetrap_cancel(Timetrap), - ?line Acc1 = ts_sub(TS1, TS0), - ?line Acc3 = ts_sub(TS3, TS2), - ?line Acc5 = ts_sub(TS5, TS4), - ?line io:format("~p (plain), ~p (eprof), ~p (fprof), ~p (cpu)~n", - [Acc1/1000, Acc3/1000, Acc5/1000, Acc/1000]), + ets:delete(T), + file:delete(AnalysisFile), + Acc1 = TS1 - TS0, + Acc3 = TS3 - TS2, + Acc5 = TS5 - TS4, + io:format("~p (plain), ~p (eprof), ~p (fprof), ~p (cpu)~n", + [Acc1/1000, Acc3/1000, Acc5/1000, Acc/1000]), {comment, io_lib:format("~p/~p (fprof/eprof) times slower", - [Acc5/Acc1, Acc3/Acc1])}. + [divide(Acc5,Acc1), divide(Acc3,Acc1)])}. %%%--------------------------------------------------------------------- -imm_create_file_slow(doc) -> - ["Tests a tail recursive variant of lists:seq/3 ", - "with immediate trace to profile"]; -imm_create_file_slow(suite) -> - []; +%% Tests a tail recursive variant of lists:seq/3 +%% with immediate trace to profile imm_create_file_slow(Config) when is_list(Config) -> - ?line Timetrap = ?t:timetrap(?t:seconds(60)), - ?line PrivDir = ?config(priv_dir, Config), - ?line DataFile = - filename:join(PrivDir, ?MODULE_STRING"_imm_create_file_slow.data"), - ?line AnalysisFile = - filename:join(PrivDir, ?MODULE_STRING"_imm_create_file_slow.analysis"), - ?line ok = fprof:stop(kill), + PrivDir = proplists:get_value(priv_dir, Config), + DataFile = filename:join(PrivDir, + ?MODULE_STRING"_imm_create_file_slow.data"), + AnalysisFile = filename:join(PrivDir, + ?MODULE_STRING"_imm_create_file_slow.analysis"), + ok = fprof:stop(kill), %% - ?line TS0 = erlang:now(), - ?line ok = create_file_slow(DataFile, 1024), - ?line TS1 = erlang:now(), - ?line ok = file:delete(DataFile), + TS0 = erlang:monotonic_time(), + ok = create_file_slow(DataFile, 1024), + TS1 = erlang:monotonic_time(), + ok = file:delete(DataFile), %% - ?line {ok, Tracer} = fprof:profile(start), - ?line TS2 = erlang:now(), - ?line ok = fprof:apply(?MODULE, create_file_slow, [DataFile, 1024], - [{tracer, Tracer}, continue]), - ?line TS3 = erlang:now(), - ?line ok = fprof:profile(stop), - ?line ok = fprof:analyse(), - ?line ok = fprof:analyse(dest, AnalysisFile), - ?line ok = fprof:stop(), + {ok, Tracer} = fprof:profile(start), + TS2 = erlang:monotonic_time(), + ok = fprof:apply(?MODULE, create_file_slow, [DataFile, 1024], + [{tracer, Tracer}, continue]), + TS3 = erlang:monotonic_time(), + ok = fprof:profile(stop), + ok = fprof:analyse(), + ok = fprof:analyse(dest, AnalysisFile), + ok = fprof:stop(), %% - ?line {ok, [T, P]} = parse(AnalysisFile), - ?line io:format("~p~n~n~p~n", [P, ets:tab2list(T)]), - ?line ok = verify(T, P), - ?line Proc = pid_to_list(self()), - ?line case P of - [{analysis_options, _}, - [{totals, _, Acc, _}], - [{Proc, _, undefined, _} | _]] -> - ok - end, + {ok, [T, P]} = parse(AnalysisFile), + io:format("~p~n~n~p~n", [P, ets:tab2list(T)]), + ok = verify(T, P), + Proc = pid_to_list(self()), + case P of + [{analysis_options, _}, + [{totals, _, Acc, _}], + [{Proc, _, undefined, _} | _]] -> + ok + end, %% - ?line ets:delete(T), - ?line file:delete(DataFile), - ?line file:delete(AnalysisFile), - ?line ?t:timetrap_cancel(Timetrap), - ?line Acc1 = ts_sub(TS1, TS0), - ?line Acc3 = ts_sub(TS3, TS2), - ?line io:format("ts:~w, fprof:~w, bare:~w.~n", [Acc, Acc3, Acc1]), - {comment, io_lib:format("~p times slower", [Acc3/Acc1])}. + ets:delete(T), + file:delete(DataFile), + file:delete(AnalysisFile), + Acc1 = TS1 - TS0, + Acc3 = TS3 - TS2, + io:format("ts:~w, fprof:~w, bare:~w.~n", [Acc, Acc3, Acc1]), + {comment, io_lib:format("~p times slower", [divide(Acc3,Acc1)])}. %%%--------------------------------------------------------------------- -imm_compile(doc) -> - ["Tests to compile a small source file ", - "with immediate trace to profile"]; -imm_compile(suite) -> - []; +%% Tests to compile a small source file with immediate trace to profile imm_compile(Config) when is_list(Config) -> - ?line Timetrap = ?t:timetrap(?t:minutes(20)), - ?line DataDir = ?config(data_dir, Config), - ?line SourceFile = filename:join(DataDir, "foo.erl"), - ?line PrivDir = ?config(priv_dir, Config), - ?line AnalysisFile = - filename:join(PrivDir, ?MODULE_STRING"_imm_compile.analysis"), - ?line ok = fprof:stop(kill), - ?line catch eprof:stop(), + ct:timetrap({minutes, 20}), + DataDir = proplists:get_value(data_dir, Config), + SourceFile = filename:join(DataDir, "foo.erl"), + PrivDir = proplists:get_value(priv_dir, Config), + AnalysisFile = filename:join(PrivDir, + ?MODULE_STRING"_imm_compile.analysis"), + ok = fprof:stop(kill), + catch eprof:stop(), %% - ?line {ok, foo, _} = compile:file(SourceFile, [binary]), - ?line TS0 = erlang:now(), - ?line {ok, foo, _} = compile:file(SourceFile, [binary]), - ?line TS1 = erlang:now(), + {ok, foo, _} = compile:file(SourceFile, [binary]), + TS0 = erlang:monotonic_time(), + {ok, foo, _} = compile:file(SourceFile, [binary]), + TS1 = erlang:monotonic_time(), %% - ?line profiling = eprof:start_profiling([self()]), - ?line TS2 = erlang:now(), - ?line {ok, foo, _} = compile:file(SourceFile, [binary]), - ?line TS3 = erlang:now(), - ?line profiling_stopped = eprof:stop_profiling(), + profiling = eprof:start_profiling([self()]), + TS2 = erlang:monotonic_time(), + {ok, foo, _} = compile:file(SourceFile, [binary]), + TS3 = erlang:monotonic_time(), + profiling_stopped = eprof:stop_profiling(), %% - ?line eprof:analyze(), - ?line stopped = eprof:stop(), + eprof:analyze(), + stopped = eprof:stop(), %% - ?line {ok, Tracer} = fprof:profile(start), - ?line ok = fprof:trace([start, {tracer, Tracer}]), - ?line TS4 = erlang:now(), - ?line {ok, foo, _} = compile:file(SourceFile, [binary]), - ?line TS5 = erlang:now(), - ?line ok = fprof:trace(stop), + {ok, Tracer} = fprof:profile(start), + ok = fprof:trace([start, {tracer, Tracer}]), + TS4 = erlang:monotonic_time(), + {ok, foo, _} = compile:file(SourceFile, [binary]), + TS5 = erlang:monotonic_time(), + ok = fprof:trace(stop), %% - ?line io:format("Analysing...~n"), - ?line ok = fprof:analyse(dest, AnalysisFile), - ?line ok = fprof:stop(), + io:format("Analysing...~n"), + ok = fprof:analyse(dest, AnalysisFile), + ok = fprof:stop(), %% - ?line {ok, [T, P]} = parse(AnalysisFile), - ?line io:format("~p~n", [P]), - ?line Acc1 = ts_sub(TS1, TS0), - ?line Acc3 = ts_sub(TS3, TS2), - ?line Acc5 = ts_sub(TS5, TS4), - ?line io:format("Verifying...~n"), - ?line ok = verify(T, P), - ?line case P of - [{analysis_options, _}, - [{totals, _, Acc, _}] | _] -> - ok - end, + {ok, [T, P]} = parse(AnalysisFile), + io:format("~p~n", [P]), + Acc1 = TS1 - TS0, + Acc3 = TS3 - TS2, + Acc5 = TS5 - TS4, + io:format("Verifying...~n"), + ok = verify(T, P), + case P of + [{analysis_options, _}, + [{totals, _, Acc, _}] | _] -> + ok + end, %% - ?line ets:delete(T), - ?line file:delete(AnalysisFile), - ?line ?t:timetrap_cancel(Timetrap), - ?line io:format("~p (plain), ~p (eprof), ~p (fprof), ~p(cpu)~n", - [Acc1/1000, Acc3/1000, Acc5/1000, Acc/1000]), + ets:delete(T), + file:delete(AnalysisFile), + io:format("~p (plain), ~p (eprof), ~p (fprof), ~p(cpu)~n", + [Acc1/1000, Acc3/1000, Acc5/1000, Acc/1000]), {comment, io_lib:format("~p/~p (fprof/eprof) times slower", - [Acc5/Acc1, Acc3/Acc1])}. + [divide(Acc5,Acc1), divide(Acc3,Acc1)])}. %%%--------------------------------------------------------------------- -cpu_create_file_slow(doc) -> - ["Tests the create_file_slow benchmark using cpu_time"]; -cpu_create_file_slow(suite) -> - []; +%% Tests the create_file_slow benchmark using cpu_time cpu_create_file_slow(Config) when is_list(Config) -> - ?line Timetrap = ?t:timetrap(?t:seconds(40)), - ?line PrivDir = ?config(priv_dir, Config), - ?line TraceFile = - filename:join(PrivDir, ?MODULE_STRING"_cpu_create_file_slow.trace"), - ?line AnalysisFile = - filename:join(PrivDir, ?MODULE_STRING"_cpu_create_file_slow.analysis"), - ?line DataFile = - filename:join(PrivDir, ?MODULE_STRING"_cpu_create_file_slow.data"), - ?line ok = fprof:stop(kill), + PrivDir = proplists:get_value(priv_dir, Config), + TraceFile = + filename:join(PrivDir, ?MODULE_STRING"_cpu_create_file_slow.trace"), + AnalysisFile = + filename:join(PrivDir, ?MODULE_STRING"_cpu_create_file_slow.analysis"), + DataFile = + filename:join(PrivDir, ?MODULE_STRING"_cpu_create_file_slow.data"), + ok = fprof:stop(kill), %% - ?line TS0 = erlang:now(), - ?line Result = (catch fprof:apply(?MODULE, create_file_slow, - [DataFile, 1024], - [{file, TraceFile}, cpu_time])), - ?line TS1 = erlang:now(), - ?line TestResult = - case Result of - ok -> - ?line ok = fprof:profile(file, TraceFile), - ?line ok = fprof:analyse(), - ?line ok = fprof:analyse(dest, AnalysisFile), - ?line ok = fprof:stop(), - %% - ?line {ok, [T, P]} = parse(AnalysisFile), - ?line io:format("~p~n~n~p~n", [P, ets:tab2list(T)]), - ?line ok = verify(T, P), - ?line Proc = pid_to_list(self()), - ?line case P of - [{analysis_options, _}, - [{totals, _, Acc, _}], - [{Proc, _, undefined, _} | _]] -> - ok - end, - %% - ?line check_own_and_acc(TraceFile,AnalysisFile), - %% - ?line ets:delete(T), - ?line file:delete(DataFile), - ?line file:delete(TraceFile), - ?line file:delete(AnalysisFile), - ?line Acc1 = ts_sub(TS1, TS0), - ?line io:format("cpu_ts:~w, fprof:~w~n", [Acc, Acc1]), - {comment, io_lib:format("~p% cpu utilization", - [100*Acc/Acc1])}; - {'EXIT', not_supported} -> - case {os:type(), os:version()} of - {{unix, sunos}, {Major, Minor, _}} - when Major >= 5, Minor >= 7 -> - test_server:fail(Result); - _ -> - {skipped, "not_supported"} - end; - _ -> - test_server:fail(Result) - end, - ?line ?t:timetrap_cancel(Timetrap), + TS0 = erlang:monotonic_time(), + Result = (catch fprof:apply(?MODULE, create_file_slow, + [DataFile, 1024], + [{file, TraceFile}, cpu_time])), + TS1 = erlang:monotonic_time(), + TestResult = + case Result of + ok -> + ok = fprof:profile(file, TraceFile), + ok = fprof:analyse(), + ok = fprof:analyse(dest, AnalysisFile), + ok = fprof:stop(), + %% + {ok, [T, P]} = parse(AnalysisFile), + io:format("~p~n~n~p~n", [P, ets:tab2list(T)]), + ok = verify(T, P), + Proc = pid_to_list(self()), + case P of + [{analysis_options, _}, + [{totals, _, Acc, _}], + [{Proc, _, undefined, _} | _]] -> + ok + end, + %% + check_own_and_acc(TraceFile,AnalysisFile), + %% + ets:delete(T), + file:delete(DataFile), + file:delete(TraceFile), + file:delete(AnalysisFile), + Acc1 = TS1 - TS0, + io:format("cpu_ts:~w, fprof:~w~n", [Acc, Acc1]), + {comment, io_lib:format("~p% cpu utilization", [100*divide(Acc,Acc1)])}; + {'EXIT', not_supported} -> + case {os:type(), os:version()} of + {{unix, sunos}, {Major, Minor, _}} + when Major >= 5, Minor >= 7 -> + ct:fail(Result); + _ -> + {skipped, "not_supported"} + end; + _ -> + ct:fail(Result) + end, TestResult. - %%%--------------------------------------------------------------------- %%% Functions to test %%%--------------------------------------------------------------------- @@ -623,14 +560,14 @@ seq_r(Start, Stop, Succ, R) -> create_file_slow(Name, N) when is_integer(N), N >= 0 -> {ok, FD} = - file:open(Name, [raw, write, delayed_write, binary]), + file:open(Name, [raw, write, delayed_write, binary]), if N > 256 -> - ok = file:write(FD, - lists:map(fun (X) -> <<X:32/unsigned>> end, - lists:seq(0, 255))), - ok = create_file_slow(FD, 256, N); + ok = file:write(FD, + lists:map(fun (X) -> <<X:32/unsigned>> end, + lists:seq(0, 255))), + ok = create_file_slow(FD, 256, N); true -> - ok = create_file_slow(FD, 0, N) + ok = create_file_slow(FD, 0, N) end, ok = file:close(FD). @@ -647,46 +584,44 @@ create_file_slow(FD, M, N) -> %%%--------------------------------------------------------------------- - verify(Tab, [{analysis_options, _}, - [{totals, Cnt, Acc, Own} | _] | Processes]) -> + [{totals, Cnt, Acc, Own} | _] | Processes]) -> Processes_1 = - lists:map( - fun ([{Proc, Cnt_P, undefined, Own_P} | _]) -> - case sum_process(Tab, Proc) of - {Proc, Cnt_P, Acc_P, Own_P} = Clocks - when Acc_P >= Own_P -> - Clocks; - Weird -> - throw({error, [?MODULE, ?LINE, Weird]}) - end - end, - Processes), + lists:map( + fun ([{Proc, Cnt_P, undefined, Own_P} | _]) -> + case sum_process(Tab, Proc) of + {Proc, Cnt_P, Acc_P, Own_P} = Clocks + when Acc_P >= Own_P -> + Clocks; + Weird -> + throw({error, [?MODULE, ?LINE, Weird]}) + end + end, + Processes), case lists:foldl( - fun ({_, Cnt_P2, Acc_P2, Own_P2}, - {totals, Cnt_T, Acc_T, Own_T}) -> - {totals, Cnt_P2+Cnt_T, Acc_P2+Acc_T, Own_P2+Own_T} - end, - {totals, 0, 0, 0}, - Processes_1) of - {totals, Cnt, Acc_T, Own} when Acc_T >= Acc -> - ok; - Weird -> - throw({error, [?MODULE, ?LINE, Weird]}) + fun ({_, Cnt_P2, Acc_P2, Own_P2}, + {totals, Cnt_T, Acc_T, Own_T}) -> + {totals, Cnt_P2+Cnt_T, Acc_P2+Acc_T, Own_P2+Own_T} + end, + {totals, 0, 0, 0}, + Processes_1) of + {totals, Cnt, Acc_T, Own} when Acc_T >= Acc -> + ok; + Weird -> + throw({error, [?MODULE, ?LINE, Weird]}) end. - sum_process(Tab, Proc) -> ets_select_fold( Tab, [{{{Proc, '_'}, '_'}, [], ['$_']}], 100, fun ({{P, MFA}, {Callers, {MFA, Cnt, Acc, Own}, Called}}, - {P, Cnt_P, Acc_P, Own_P}) when P == Proc -> - ok = verify_callers(Tab, Proc, MFA, Callers), - ok = verify_called(Tab, Proc, MFA, Called), - {P, Cnt+Cnt_P, Acc+Acc_P, Own+Own_P}; - (Weird, Clocks) -> - throw({error, [?MODULE, ?LINE, Weird, Clocks]}) + {P, Cnt_P, Acc_P, Own_P}) when P == Proc -> + ok = verify_callers(Tab, Proc, MFA, Callers), + ok = verify_called(Tab, Proc, MFA, Called), + {P, Cnt+Cnt_P, Acc+Acc_P, Own+Own_P}; + (Weird, Clocks) -> + throw({error, [?MODULE, ?LINE, Weird, Clocks]}) end, {Proc, 0, 0, 0}). @@ -695,31 +630,31 @@ verify_callers(_, _, _, []) -> verify_callers(Tab, Proc, MFA, [{Caller, Cnt, Acc, Own} | Tail]) -> Id = {Proc, Caller}, case ets:lookup(Tab, Id) of - [{Id, {_, {Caller, _, _, _}, Called}}] -> - case lists:keysearch(MFA, 1, Called) of - {value, {MFA, Cnt, Acc, Own}} -> - verify_callers(Tab, Proc, MFA, Tail); - false -> - throw({error, [?MODULE, ?LINE, MFA, Id]}) - end; - Weird -> - throw({error, [?MODULE, ?LINE, Weird]}) + [{Id, {_, {Caller, _, _, _}, Called}}] -> + case lists:keysearch(MFA, 1, Called) of + {value, {MFA, Cnt, Acc, Own}} -> + verify_callers(Tab, Proc, MFA, Tail); + false -> + throw({error, [?MODULE, ?LINE, MFA, Id]}) + end; + Weird -> + throw({error, [?MODULE, ?LINE, Weird]}) end. - + verify_called(_, _, _, []) -> ok; verify_called(Tab, Proc, MFA, [{Called, Cnt, Acc, Own} | Tail]) -> Id = {Proc, Called}, case ets:lookup(Tab, Id) of - [{Id, {Callers, {Called, _, _, _}, _}}] -> - case lists:keysearch(MFA, 1, Callers) of - {value, {MFA, Cnt, Acc, Own}} -> - verify_called(Tab, Proc, MFA, Tail); - false -> - throw({error, [?MODULE, ?LINE, MFA, Id]}) - end; - Weird -> - throw({error, [?MODULE, ?LINE, Weird]}) + [{Id, {Callers, {Called, _, _, _}, _}}] -> + case lists:keysearch(MFA, 1, Callers) of + {value, {MFA, Cnt, Acc, Own}} -> + verify_called(Tab, Proc, MFA, Tail); + false -> + throw({error, [?MODULE, ?LINE, MFA, Id]}) + end; + Weird -> + throw({error, [?MODULE, ?LINE, Weird]}) end. @@ -729,12 +664,12 @@ verify_called(Tab, Proc, MFA, [{Called, Cnt, Acc, Own} | Tail]) -> %% entries when they are read. parse(Filename) -> case file:open(Filename, [read]) of - {ok, FD} -> - Result = parse_stream(FD), - file:close(FD), - Result; - Error -> - Error + {ok, FD} -> + Result = parse_stream(FD), + file:close(FD), + Result; + Error -> + Error end. parse_stream(FD) -> @@ -743,31 +678,31 @@ parse_stream(FD) -> parse_stream(FD, Tab, R, Proc) -> case catch io:read(FD, '') of - {'EXIT', _} -> - {error, [?MODULE, ?LINE]}; - {ok, Term} -> - case parse_term(Term) of - {ok, {analysis_options, _} = Term_1} - when Proc == void -> - parse_stream(FD, Tab, [Term_1 | R], analysis_options); - {ok, [{totals, _, _, _} | _] = Term_1} - when Proc == analysis_options -> - parse_stream(FD, Tab, [Term_1 | R], totals); - {ok, [{P, _, _, _} | _] = Term_1} -> - parse_stream(FD, Tab, [Term_1 | R], P); - {ok, {_Callers, {MFA, _, _, _}, _Called} = Term_1} - when Proc == totals; is_list(Proc) -> - ets:insert(Tab, {{Proc, MFA}, Term_1}), - parse_stream(FD, Tab, R, Proc); - {ok, Term_1} -> - {error, [?MODULE, ?LINE, Term_1]}; - E -> - E - end; - eof -> - {ok, [Tab, lists:reverse(R)]}; - Error -> - Error + {'EXIT', _} -> + {error, [?MODULE, ?LINE]}; + {ok, Term} -> + case parse_term(Term) of + {ok, {analysis_options, _} = Term_1} + when Proc == void -> + parse_stream(FD, Tab, [Term_1 | R], analysis_options); + {ok, [{totals, _, _, _} | _] = Term_1} + when Proc == analysis_options -> + parse_stream(FD, Tab, [Term_1 | R], totals); + {ok, [{P, _, _, _} | _] = Term_1} -> + parse_stream(FD, Tab, [Term_1 | R], P); + {ok, {_Callers, {MFA, _, _, _}, _Called} = Term_1} + when Proc == totals; is_list(Proc) -> + ets:insert(Tab, {{Proc, MFA}, Term_1}), + parse_stream(FD, Tab, R, Proc); + {ok, Term_1} -> + {error, [?MODULE, ?LINE, Term_1]}; + E -> + E + end; + eof -> + {ok, [Tab, lists:reverse(R)]}; + Error -> + Error end. parse_term({Callers, Func, Called}) @@ -777,10 +712,10 @@ parse_term({Callers, Func, Called}) Called_1 = lists:map(fun parse_clocks/1, Called), Result = {Callers_1, Func_1, Called_1}, case chk_invariant(Result) of - ok -> - {ok, Result}; - Error -> - Error + ok -> + {ok, Result}; + Error -> + Error end; parse_term([{_, _, _, _} = Clocks | Tail]) -> {ok, [parse_clocks(Clocks) | Tail]}; @@ -798,41 +733,41 @@ parse_clocks(Clocks) -> chk_invariant({Callers, {MFA, Cnt, Acc, Own}, Called} = Term) -> {_, Callers_Cnt, Callers_Acc, Callers_Own} = Callers_Sum = sum(Callers), -% {_, Called_Cnt, Called_Acc, Called_Own} = Called_Sum = sum(Called), + % {_, Called_Cnt, Called_Acc, Called_Own} = Called_Sum = sum(Called), case {MFA, - lists:keymember(suspend, 1, Callers), - lists:keymember(garbage_collect, 1, Callers), - Called} of - {suspend, false, _, []} -> - ok; - {suspend, _, _, _} = Weird -> - {error, [?MODULE, ?LINE, Weird, Term]}; - {garbage_collect, false, false, []} -> - ok; - {garbage_collect, false, false, [{suspend, _, _, _}]} -> - ok; - {garbage_collect, _, _, _} = Weird -> - {error, [?MODULE, ?LINE, Weird, Term]}; - {undefined, false, false, _} - when Callers == [], Cnt == 0, Acc == 0, Own == 0 -> - ok; - {undefined, _, _, _} = Weird -> - {error, [?MODULE, ?LINE, Weird, Term]}; - {_, _, _, _} -> - case chk_self_call(Term) of - true when Callers_Cnt /= Cnt; Callers_Acc /= Acc; - Callers_Own /= Own -> - {error, [?MODULE, ?LINE, Callers_Sum, Term]}; -% true when Called_Acc + Own /= Acc -> -% io:format("WARNING: ~p:~p, ~p, ~p.~n", -% [?MODULE, ?LINE, Term, Called_Sum]), -% {error, [?MODULE, ?LINE, Term, Called_Sum]}; -% ok; - true -> - ok; - false -> - {error, [?MODULE, ?LINE, Term]} - end + lists:keymember(suspend, 1, Callers), + lists:keymember(garbage_collect, 1, Callers), + Called} of + {suspend, false, _, []} -> + ok; + {suspend, _, _, _} = Weird -> + {error, [?MODULE, ?LINE, Weird, Term]}; + {garbage_collect, false, false, []} -> + ok; + {garbage_collect, false, false, [{suspend, _, _, _}]} -> + ok; + {garbage_collect, _, _, _} = Weird -> + {error, [?MODULE, ?LINE, Weird, Term]}; + {undefined, false, false, _} + when Callers == [], Cnt == 0, Acc == 0, Own == 0 -> + ok; + {undefined, _, _, _} = Weird -> + {error, [?MODULE, ?LINE, Weird, Term]}; + {_, _, _, _} -> + case chk_self_call(Term) of + true when Callers_Cnt /= Cnt; Callers_Acc /= Acc; + Callers_Own /= Own -> + {error, [?MODULE, ?LINE, Callers_Sum, Term]}; + % true when Called_Acc + Own /= Acc -> + % io:format("WARNING: ~p:~p, ~p, ~p.~n", + % [?MODULE, ?LINE, Term, Called_Sum]), + % {error, [?MODULE, ?LINE, Term, Called_Sum]}; + % ok; + true -> + ok; + false -> + {error, [?MODULE, ?LINE, Term]} + end end. ts_sub({A, B, C}, {A0, B0, C0}) -> @@ -840,28 +775,28 @@ ts_sub({A, B, C}, {A0, B0, C0}) -> sum(Funcs) -> {sum, _Cnt, _Acc, _Own} = - lists:foldl( - fun ({_, C1, A1, O1}, {sum, C2, A2, O2}) -> - {sum, C1+C2, A1+A2, O1+O2} - end, - {sum, 0, 0, 0}, - Funcs). + lists:foldl( + fun ({_, C1, A1, O1}, {sum, C2, A2, O2}) -> + {sum, C1+C2, A1+A2, O1+O2} + end, + {sum, 0, 0, 0}, + Funcs). chk_self_call({Callers, {MFA, _Cnt, _Acc, _Own}, Called}) -> case lists:keysearch(MFA, 1, Callers) of - false -> - true; - {value, {MFA, C, 0, O}} -> - case lists:keysearch(MFA, 1, Called) of - false -> - false; - {value, {MFA, C, 0, O}} -> - true; - {value, _} -> - false - end; - {value, _} -> - false + false -> + true; + {value, {MFA, C, 0, O}} -> + case lists:keysearch(MFA, 1, Called) of + false -> + false; + {value, {MFA, C, 0, O}} -> + true; + {value, _} -> + false + end; + {value, _} -> + false end. @@ -879,9 +814,8 @@ ets_select_fold_1('$end_of_table', _, Acc) -> Acc; ets_select_fold_1({Matches, Continuation}, Fun, Acc) -> ets_select_fold_1(ets:select(Continuation), - Fun, - lists:foldl(Fun, Acc, Matches)). - + Fun, + lists:foldl(Fun, Acc, Matches)). % ets_select_foreach(Table, MatchSpec, Limit, Fun) -> @@ -910,7 +844,7 @@ check_own_and_acc(TraceFile, AnalysisFile) -> check_own_and_acc(TraceFile, AnalysisFile, HandlerFun) -> dbg:trace_client(file,TraceFile,{HandlerFun,{init,self()}}), receive {result,Result} -> - compare(Result,get_own_and_acc_from_analysis(AnalysisFile)) + compare(Result,get_own_and_acc_from_analysis(AnalysisFile)) end. %% handle_trace_traced(Trace, Msg) -> @@ -924,21 +858,21 @@ handle_trace(Trace,{init,Parent}) -> handle_trace({trace_ts,Pid,in,MFA,TS},P) -> ?dbg("~p",[{{in,Pid,MFA},get(Pid)}]), case get(Pid) of - [suspend|[suspend|_]=NewStack] -> - T = ts_sub(TS,get({Pid,last_ts})), - update_acc(Pid,NewStack,T), - put(Pid,NewStack); - [suspend|NewStack] = Stack -> - T = ts_sub(TS,get({Pid,last_ts})), - update_acc(Pid,Stack,T), - put(Pid,NewStack); - [] -> - put(Pid,[MFA]), - insert(Pid,MFA); - undefined -> - put(first_ts,TS), - put(Pid,[MFA]), - insert(Pid,MFA) + [suspend|[suspend|_]=NewStack] -> + T = ts_sub(TS,get({Pid,last_ts})), + update_acc(Pid,NewStack,T), + put(Pid,NewStack); + [suspend|NewStack] = Stack -> + T = ts_sub(TS,get({Pid,last_ts})), + update_acc(Pid,Stack,T), + put(Pid,NewStack); + [] -> + put(Pid,[MFA]), + insert(Pid,MFA); + undefined -> + put(first_ts,TS), + put(Pid,[MFA]), + insert(Pid,MFA) end, put({Pid,last_ts},TS), P; @@ -946,17 +880,17 @@ handle_trace({trace_ts,Pid,out,_MfaOrZero,TS},P) -> ?dbg("~p",[{{out,Pid,_MfaOrZero},get(Pid)}]), T = ts_sub(TS,get({Pid,last_ts})), case get(Pid) of - [suspend|S] = Stack -> - update_acc(Pid,S,T), - put(Pid,[suspend|Stack]); - [MFA|_] = Stack -> - insert(Pid,suspend), - update_own(Pid,MFA,T), - update_acc(Pid,Stack,T), - put(Pid,[suspend|Stack]); - [] -> - insert(Pid,suspend), - put(Pid,[suspend]) + [suspend|S] = Stack -> + update_acc(Pid,S,T), + put(Pid,[suspend|Stack]); + [MFA|_] = Stack -> + insert(Pid,suspend), + update_own(Pid,MFA,T), + update_acc(Pid,Stack,T), + put(Pid,[suspend|Stack]); + [] -> + insert(Pid,suspend), + put(Pid,[suspend]) end, put({Pid,last_ts},TS), P; @@ -964,26 +898,26 @@ handle_trace({trace_ts,Pid,call,MFA,{cp,Caller},TS},P) -> ?dbg("~p",[{{call,Pid,MFA},get(Pid)}]), T = ts_sub(TS,get({Pid,last_ts})), case get(Pid) of - [MFA|_] = Stack -> - %% recursive - update_own(Pid,MFA,T), - update_acc(Pid,Stack,T); - [CallingMFA|_] = Stack when Caller==undefined -> - insert(Pid,MFA), - update_own(Pid,CallingMFA,T), - update_acc(Pid,Stack,T), - put(Pid,[MFA|Stack]); - [] when Caller==undefined -> - insert(Pid,MFA), - insert(Pid,MFA), - put(Pid,[MFA]); - Stack0 -> - Stack = [CallingMFA|_] = insert_caller(Caller,Stack0,[]), - insert(Pid,MFA), - insert(Pid,Caller), - update_own(Pid,CallingMFA,T), - update_acc(Pid,Stack,T), - put(Pid,[MFA|Stack]) + [MFA|_] = Stack -> + %% recursive + update_own(Pid,MFA,T), + update_acc(Pid,Stack,T); + [CallingMFA|_] = Stack when Caller==undefined -> + insert(Pid,MFA), + update_own(Pid,CallingMFA,T), + update_acc(Pid,Stack,T), + put(Pid,[MFA|Stack]); + [] when Caller==undefined -> + insert(Pid,MFA), + insert(Pid,MFA), + put(Pid,[MFA]); + Stack0 -> + Stack = [CallingMFA|_] = insert_caller(Caller,Stack0,[]), + insert(Pid,MFA), + insert(Pid,Caller), + update_own(Pid,CallingMFA,T), + update_acc(Pid,Stack,T), + put(Pid,[MFA|Stack]) end, put({Pid,last_ts},TS), P; @@ -991,59 +925,91 @@ handle_trace({trace_ts,Pid,return_to,MFA,TS},P) -> ?dbg("~p",[{{return_to,Pid,MFA},get(Pid)}]), T = ts_sub(TS,get({Pid,last_ts})), case get(Pid) of - [MFA|_] = Stack -> - %% recursive - update_own(Pid,MFA,T), - update_acc(Pid,Stack,T), - put(Pid,Stack); - [ReturnFromMFA,MFA|RestOfStack] = Stack -> - update_own(Pid,ReturnFromMFA,T), - update_acc(Pid,Stack,T), - put(Pid,[MFA|RestOfStack]); - [ReturnFromMFA|RestOfStack] = Stack -> - update_own(Pid,ReturnFromMFA,T), - update_acc(Pid,Stack,T), - case find_return_to(MFA,RestOfStack) of - [] when MFA==undefined -> - put(Pid,[]); - [] -> - insert(Pid,MFA), - put(Pid,[MFA]); - NewStack -> - put(Pid,NewStack) - end + [MFA|_] = Stack -> + %% recursive + update_own(Pid,MFA,T), + update_acc(Pid,Stack,T), + put(Pid,Stack); + [ReturnFromMFA,MFA|RestOfStack] = Stack -> + update_own(Pid,ReturnFromMFA,T), + update_acc(Pid,Stack,T), + put(Pid,[MFA|RestOfStack]); + [ReturnFromMFA|RestOfStack] = Stack -> + update_own(Pid,ReturnFromMFA,T), + update_acc(Pid,Stack,T), + case find_return_to(MFA,RestOfStack) of + [] when MFA==undefined -> + put(Pid,[]); + [] -> + insert(Pid,MFA), + put(Pid,[MFA]); + NewStack -> + put(Pid,NewStack) + end end, put({Pid,last_ts},TS), P; -handle_trace({trace_ts,Pid,gc_start,_,TS},P) -> - ?dbg("~p",[{{gc_start,Pid},get(Pid)}]), +handle_trace({trace_ts,Pid,gc_minor_start,_,TS},P) -> + ?dbg("~p",[{{gc_minor_start,Pid},get(Pid)}]), case get(Pid) of - [suspend|_] = Stack -> - T = ts_sub(TS,get({Pid,last_ts})), - insert(Pid,garbage_collect), - update_acc(Pid,Stack,T), - put(Pid,[garbage_collect|Stack]); - [CallingMFA|_] = Stack -> - T = ts_sub(TS,get({Pid,last_ts})), - insert(Pid,garbage_collect), - update_own(Pid,CallingMFA,T), - update_acc(Pid,Stack,T), - put(Pid,[garbage_collect|Stack]); - undefined -> - put(first_ts,TS), - put(Pid,[garbage_collect]), - insert(Pid,garbage_collect) + [suspend|_] = Stack -> + T = ts_sub(TS,get({Pid,last_ts})), + insert(Pid,garbage_collect), + update_acc(Pid,Stack,T), + put(Pid,[garbage_collect|Stack]); + [CallingMFA|_] = Stack -> + T = ts_sub(TS,get({Pid,last_ts})), + insert(Pid,garbage_collect), + update_own(Pid,CallingMFA,T), + update_acc(Pid,Stack,T), + put(Pid,[garbage_collect|Stack]); + undefined -> + put(first_ts,TS), + put(Pid,[garbage_collect]), + insert(Pid,garbage_collect) end, put({Pid,last_ts},TS), P; -handle_trace({trace_ts,Pid,gc_end,_,TS},P) -> - ?dbg("~p",[{{gc_end,Pid},get(Pid)}]), +handle_trace({trace_ts,Pid,gc_major_start,_,TS},P) -> + ?dbg("~p",[{{gc_minor_start,Pid},get(Pid)}]), + case get(Pid) of + [suspend|_] = Stack -> + T = ts_sub(TS,get({Pid,last_ts})), + insert(Pid,garbage_collect), + update_acc(Pid,Stack,T), + put(Pid,[garbage_collect|Stack]); + [CallingMFA|_] = Stack -> + T = ts_sub(TS,get({Pid,last_ts})), + insert(Pid,garbage_collect), + update_own(Pid,CallingMFA,T), + update_acc(Pid,Stack,T), + put(Pid,[garbage_collect|Stack]); + undefined -> + put(first_ts,TS), + put(Pid,[garbage_collect]), + insert(Pid,garbage_collect) + end, + put({Pid,last_ts},TS), + P; +handle_trace({trace_ts,Pid,gc_minor_end,_,TS},P) -> + ?dbg("~p",[{{gc_minor_end,Pid},get(Pid)}]), T = ts_sub(TS,get({Pid,last_ts})), case get(Pid) of - [garbage_collect|RestOfStack] = Stack -> - update_own(Pid,garbage_collect,T), - update_acc(Pid,Stack,T), - put(Pid,RestOfStack) + [garbage_collect|RestOfStack] = Stack -> + update_own(Pid,garbage_collect,T), + update_acc(Pid,Stack,T), + put(Pid,RestOfStack) + end, + put({Pid,last_ts},TS), + P; +handle_trace({trace_ts,Pid,gc_major_end,_,TS},P) -> + ?dbg("~p",[{{gc_major_end,Pid},get(Pid)}]), + T = ts_sub(TS,get({Pid,last_ts})), + case get(Pid) of + [garbage_collect|RestOfStack] = Stack -> + update_own(Pid,garbage_collect,T), + update_acc(Pid,Stack,T), + put(Pid,RestOfStack) end, put({Pid,last_ts},TS), P; @@ -1051,27 +1017,45 @@ handle_trace({trace_ts,Pid,spawn,NewPid,{M,F,Args},TS},P) -> MFA = {M,F,length(Args)}, ?dbg("~p",[{{spawn,Pid,NewPid,MFA},get(Pid)}]), T = ts_sub(TS,get({Pid,last_ts})), - put({NewPid,last_ts},TS), - put(NewPid,[suspend,MFA]), - insert(NewPid,suspend), - insert(NewPid,MFA), + case get(NewPid) of + undefined -> + put({NewPid,last_ts},TS), + put(NewPid,[suspend,MFA]), + insert(NewPid,suspend), + insert(NewPid,MFA); + _Else -> + ok + end, case get(Pid) of - [SpawningMFA|_] = Stack -> - update_own(Pid,SpawningMFA,T), - update_acc(Pid,Stack,T) + [SpawningMFA|_] = Stack -> + update_own(Pid,SpawningMFA,T), + update_acc(Pid,Stack,T) end, put({Pid,last_ts},TS), P; +handle_trace({trace_ts,NewPid,spawned,Pid,{M,F,Args},TS},P) -> + MFA = {M,F,length(Args)}, + ?dbg("~p",[{{spawned,NewPid,Pid,MFA},get(NewPid)}]), + case get(NewPid) of + undefined -> + put({NewPid,last_ts},TS), + put(NewPid,[suspend,MFA]), + insert(NewPid,suspend), + insert(NewPid,MFA); + _Else -> + ok + end, + P; handle_trace({trace_ts,Pid,exit,_Reason,TS},P) -> ?dbg("~p",[{{exit,Pid,_Reason},get(Pid)}]), T = ts_sub(TS,get({Pid,last_ts})), case get(Pid) of - [DyingMFA|_] = Stack -> - update_own(Pid,DyingMFA,T), - update_acc(Pid,Stack,T), - put(Pid,[]); - [] -> - ok + [DyingMFA|_] = Stack -> + update_own(Pid,DyingMFA,T), + update_acc(Pid,Stack,T), + put(Pid,[]); + [] -> + ok end, put({Pid,last_ts},TS), P; @@ -1089,6 +1073,7 @@ handle_trace(end_of_trace,P) -> P ! {result,[{totals,TotAcc,TotOwn}|ProcOwns]++Result}, P; handle_trace(Other,_P) -> + ct:log("Got unexpected trace message: ~p",[Other]), exit({unexpected,Other}). find_return_to(MFA,[MFA|_]=Stack) -> @@ -1107,10 +1092,10 @@ insert_caller(MFA,[],Result) -> insert(Pid,MFA) -> case ets:member(fprof_verify_tab,{Pid,MFA}) of - false -> - ets:insert(fprof_verify_tab,{{Pid,MFA},0,0}); - true -> - ok + false -> + ets:insert(fprof_verify_tab,{{Pid,MFA},0,0}); + true -> + ok end. update_own(Pid,MFA,T) -> @@ -1118,11 +1103,11 @@ update_own(Pid,MFA,T) -> update_acc(Pid,[MFA|Rest],T) -> case lists:member(MFA,Rest) of - true -> - %% Only charge one time for recursive functions - ok; - false -> - ets:update_counter(fprof_verify_tab,{Pid,MFA},{2,T}) + true -> + %% Only charge one time for recursive functions + ok; + false -> + ets:update_counter(fprof_verify_tab,{Pid,MFA},{2,T}) end, update_acc(Pid,Rest,T); update_acc(_Pid,[],_T) -> @@ -1140,63 +1125,63 @@ get_last_ts([],Last) -> get_proc_owns([{{Pid,_MFA},_Acc,Own}|Rest],Result,Sum) -> NewResult = - case lists:keysearch(Pid,1,Result) of - {value,{Pid,undefined,PidOwn}} -> - lists:keyreplace(Pid,1,Result,{Pid,undefined,PidOwn+Own}); - false -> - [{Pid,undefined,Own}|Result] + case lists:keysearch(Pid,1,Result) of + {value,{Pid,undefined,PidOwn}} -> + lists:keyreplace(Pid,1,Result,{Pid,undefined,PidOwn+Own}); + false -> + [{Pid,undefined,Own}|Result] end, get_proc_owns(Rest,NewResult,Sum+Own); get_proc_owns([],Result,Sum) -> {Sum,Result}. - + compare([X|Rest],FprofResult) -> FprofResult1 = - case lists:member(X,FprofResult) of - true -> - ?dbg("~p",[X]), - lists:delete(X,FprofResult); - false -> - case lists:keysearch(element(1,X),1,FprofResult) of - {value,Fprof} -> - put(compare_error,true), - io:format("Error: Different values\n" - "Fprof: ~p\n" - "Simulator: ~p",[Fprof,X]), - lists:delete(Fprof,FprofResult); - false -> - put(compare_error,true), - io:format("Error: Missing in fprof: ~p",[X]), - FprofResult - end - end, + case lists:member(X,FprofResult) of + true -> + ?dbg("~p",[X]), + lists:delete(X,FprofResult); + false -> + case lists:keysearch(element(1,X),1,FprofResult) of + {value,Fprof} -> + put(compare_error,true), + io:format("Error: Different values\n" + "Fprof: ~p\n" + "Simulator: ~p",[Fprof,X]), + lists:delete(Fprof,FprofResult); + false -> + put(compare_error,true), + io:format("Error: Missing in fprof: ~p",[X]), + FprofResult + end + end, compare(Rest,FprofResult1); compare([],Rest) -> case {remove_undefined(Rest,[]),get(compare_error)} of - {[],undefined} -> ok; - {Error,_} -> - case Error of - [] -> ok; - _ -> io:format("\nMissing in simulator results:\n~p\n",[Error]) - end, - ?t:fail({error,mismatch_between_simulator_and_fprof}) + {[],undefined} -> ok; + {Error,_} -> + case Error of + [] -> ok; + _ -> io:format("\nMissing in simulator results:\n~p\n",[Error]) + end, + ct:fail({error,mismatch_between_simulator_and_fprof}) end. - + remove_undefined([{{_Pid,undefined},_,_}|Rest],Result) -> remove_undefined(Rest,Result); remove_undefined([X|Rest],Result) -> remove_undefined(Rest,[X|Result]); remove_undefined([],Result) -> Result. - + get_own_and_acc_from_analysis(Log) -> case file:consult(Log) of - {ok,[_Options,[{totals,_,TotAcc,TotOwn}]|Rest]} -> - get_own_and_acc(undefined,Rest, - [{totals,m1000(TotAcc),m1000(TotOwn)}]); - Error -> - exit({error,{cant_open,Log,Error}}) + {ok,[_Options,[{totals,_,TotAcc,TotOwn}]|Rest]} -> + get_own_and_acc(undefined,Rest, + [{totals,m1000(TotAcc),m1000(TotOwn)}]); + Error -> + exit({error,{cant_open,Log,Error}}) end. get_own_and_acc(_,[[{PidStr,_,Acc,Own}|_]|Rest],Result) -> @@ -1212,3 +1197,5 @@ m1000(undefined) -> m1000(X) -> round(X*1000). +divide(_,0) -> inf; +divide(A,B) -> A / B. diff --git a/lib/tools/test/ignore_cores.erl b/lib/tools/test/ignore_cores.erl index 13f34cd10f..25dce346b9 100644 --- a/lib/tools/test/ignore_cores.erl +++ b/lib/tools/test/ignore_cores.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2008-2010. All Rights Reserved. +%% Copyright Ericsson AB 2008-2016. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -28,7 +28,7 @@ -module(ignore_cores). --include_lib("test_server/include/test_server.hrl"). +-include_lib("common_test/include/ct.hrl"). -export([init/1, fini/1, setup/3, setup/4, restore/1, dir/1]). @@ -53,7 +53,7 @@ init(Config) -> fini(Config) -> #ignore_cores{org_cwd = OrgCWD, org_path = OrgPath, - org_pwd_env = OrgPWD} = ?config(ignore_cores, Config), + org_pwd_env = OrgPWD} = proplists:get_value(ignore_cores, Config), ok = file:set_cwd(OrgCWD), true = code:set_path(OrgPath), case OrgPWD of @@ -70,10 +70,10 @@ setup(Suite, Testcase, Config, SetCwd) when is_atom(Suite), is_list(Config) -> #ignore_cores{org_cwd = OrgCWD, org_path = OrgPath, - org_pwd_env = OrgPWD} = ?config(ignore_cores, Config), + org_pwd_env = OrgPWD} = proplists:get_value(ignore_cores, Config), Path = lists:map(fun (".") -> OrgCWD; (Dir) -> Dir end, OrgPath), true = code:set_path(Path), - PrivDir = ?config(priv_dir, Config), + PrivDir = proplists:get_value(priv_dir, Config), IgnDir = filename:join([PrivDir, atom_to_list(Suite) ++ "_" @@ -94,7 +94,7 @@ setup(Suite, Testcase, Config, SetCwd) when is_atom(Suite), end, ok = file:write_file(filename:join([IgnDir, "ignore_core_files"]), <<>>), %% cores are dumped in /cores on MacOS X - CoresDir = case {?t:os_type(), filelib:is_dir("/cores")} of + CoresDir = case {os:type(), filelib:is_dir("/cores")} of {{unix,darwin}, true} -> filelib:fold_files("/cores", "^core.*$", @@ -119,7 +119,7 @@ restore(Config) -> org_path = OrgPath, org_pwd_env = OrgPWD, ign_dir = IgnDir, - cores_dir = CoresDir} = ?config(ignore_cores, Config), + cores_dir = CoresDir} = proplists:get_value(ignore_cores, Config), try case CoresDir of false -> @@ -155,5 +155,5 @@ restore(Config) -> dir(Config) -> - #ignore_cores{ign_dir = Dir} = ?config(ignore_cores, Config), + #ignore_cores{ign_dir = Dir} = proplists:get_value(ignore_cores, Config), Dir. diff --git a/lib/tools/test/instrument_SUITE.erl b/lib/tools/test/instrument_SUITE.erl index 3b981a9303..f37d28c277 100644 --- a/lib/tools/test/instrument_SUITE.erl +++ b/lib/tools/test/instrument_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1998-2011. All Rights Reserved. +%% Copyright Ericsson AB 1998-2016. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -19,133 +19,99 @@ %% -module(instrument_SUITE). --export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, - init_per_group/2,end_per_group/2, - init_per_testcase/2,end_per_testcase/2]). - +-export([all/0, suite/0]). -export(['+Mim true'/1, '+Mis true'/1]). --include_lib("test_server/include/test_server.hrl"). - -init_per_testcase(_Case, Config) -> - ?line Dog=?t:timetrap(10000), - [{watchdog, Dog}|Config]. - -end_per_testcase(_Case, Config) -> - Dog=?config(watchdog, Config), - ?t:timetrap_cancel(Dog), - ok. +-include_lib("common_test/include/ct.hrl"). -suite() -> [{ct_hooks,[ts_install_cth]}]. +suite() -> + [{ct_hooks,[ts_install_cth]}, + {timetrap,{seconds,10}}]. all() -> ['+Mim true', '+Mis true']. -groups() -> - []. - -init_per_suite(Config) -> - Config. - -end_per_suite(_Config) -> - ok. - -init_per_group(_GroupName, Config) -> - Config. - -end_per_group(_GroupName, Config) -> - Config. - -'+Mim true'(doc) -> ["Check that memory data can be read and processed"]; -'+Mim true'(suite) -> []; +%% Check that memory data can be read and processed '+Mim true'(Config) when is_list(Config) -> - ?line Node = start_slave("+Mim true"), - ?line MD = rpc:call(Node, instrument, memory_data, []), - ?line [{total,[{sizes,S1,S2,S3},{blocks,B1,B2,B3}]}] + Node = start_slave("+Mim true"), + MD = rpc:call(Node, instrument, memory_data, []), + [{total,[{sizes,S1,S2,S3},{blocks,B1,B2,B3}]}] = rpc:call(Node, instrument, memory_status, [total]), - ?line stop_slave(Node), - ?line true = S1 =< S2, - ?line true = S2 =< S3, - ?line true = B1 =< B2, - ?line true = B2 =< B3, - ?line MDS = instrument:sort(MD), - ?line {Low, High} = instrument:mem_limits(MDS), - ?line true = Low < High, - ?line {_, AL} = MDS, - ?line SumBlocks = instrument:sum_blocks(MD), - ?line case SumBlocks of - N when is_integer(N) -> - ?line N = lists:foldl(fun ({_,_,Size,_}, Sum) -> - Size+Sum - end, - 0, - AL), - ?line N =< S3; - Other -> - ?line ?t:fail(Other) - end, - ?line lists:foldl( - fun ({TDescr,Addr,Size,Proc}, MinAddr) -> - ?line true = TDescr /= invalid_type, - ?line true = is_integer(TDescr), - ?line true = is_integer(Addr), - ?line true = is_integer(Size), - ?line true = Addr >= MinAddr, - ?line case Proc of - {0, Number, Serial} -> - ?line true = is_integer(Number), - ?line true = is_integer(Serial); - undefined -> - ok; - BadProc -> - ?line ?t:fail({badproc, BadProc}) - end, - ?line NextMinAddr = Addr+Size, - ?line true = NextMinAddr =< High, - ?line NextMinAddr - end, - Low, - AL), - ?line {_, DAL} = instrument:descr(MDS), - ?line lists:foreach( - fun ({TDescr,_,_,Proc}) -> - ?line true = TDescr /= invalid_type, - ?line true = is_atom(TDescr) orelse is_list(TDescr), - ?line true = is_pid(Proc) orelse Proc == undefined - end, - DAL), - ?line ASL = lists:map(fun ({_,A,S,_}) -> {A,S} end, AL), - ?line ASL = lists:map(fun ({_,A,S,_}) -> {A,S} end, DAL), - ?line instrument:holes(MDS), - ?line {comment, - "total status - sum of blocks = " ++ integer_to_list(S1-SumBlocks)}. - -'+Mis true'(doc) -> ["Check that memory data can be read and processed"]; -'+Mis true'(suite) -> []; + stop_slave(Node), + true = S1 =< S2, + true = S2 =< S3, + true = B1 =< B2, + true = B2 =< B3, + MDS = instrument:sort(MD), + {Low, High} = instrument:mem_limits(MDS), + true = Low < High, + {_, AL} = MDS, + SumBlocks = instrument:sum_blocks(MD), + case SumBlocks of + N when is_integer(N) -> + N = lists:foldl(fun ({_,_,Size,_}, Sum) -> + Size+Sum + end, 0, AL), + true = N =< S3; + Other -> + ct:fail(Other) + end, + lists:foldl( + fun ({TDescr,Addr,Size,Proc}, MinAddr) -> + true = TDescr /= invalid_type, + true = is_integer(TDescr), + true = is_integer(Addr), + true = is_integer(Size), + true = Addr >= MinAddr, + case Proc of + {0, Number, Serial} -> + true = is_integer(Number), + true = is_integer(Serial); + undefined -> + ok; + BadProc -> + ct:fail({badproc, BadProc}) + end, + NextMinAddr = Addr+Size, + true = NextMinAddr =< High, + NextMinAddr + end, Low, AL), + {_, DAL} = instrument:descr(MDS), + lists:foreach( + fun ({TDescr,_,_,Proc}) -> + true = TDescr /= invalid_type, + true = is_atom(TDescr) orelse is_list(TDescr), + true = is_pid(Proc) orelse Proc == undefined + end, DAL), + ASL = lists:map(fun ({_,A,S,_}) -> {A,S} end, AL), + ASL = lists:map(fun ({_,A,S,_}) -> {A,S} end, DAL), + instrument:holes(MDS), + {comment, "total status - sum of blocks = " ++ integer_to_list(S1-SumBlocks)}. + +%% Check that memory data can be read and processed '+Mis true'(Config) when is_list(Config) -> - ?line Node = start_slave("+Mis true"), - ?line [{total,[{sizes,S1,S2,S3},{blocks,B1,B2,B3}]}] + Node = start_slave("+Mis true"), + [{total,[{sizes,S1,S2,S3},{blocks,B1,B2,B3}]}] = rpc:call(Node, instrument, memory_status, [total]), - ?line true = S1 =< S2, - ?line true = S2 =< S3, - ?line true = B1 =< B2, - ?line true = B2 =< B3, - ?line true = is_list(rpc:call(Node,instrument,memory_status,[allocators])), - ?line true = is_list(rpc:call(Node,instrument,memory_status,[classes])), - ?line true = is_list(rpc:call(Node,instrument,memory_status,[types])), - ?line ok. + true = S1 =< S2, + true = S2 =< S3, + true = B1 =< B2, + true = B2 =< B3, + true = is_list(rpc:call(Node,instrument,memory_status,[allocators])), + true = is_list(rpc:call(Node,instrument,memory_status,[classes])), + true = is_list(rpc:call(Node,instrument,memory_status,[types])), + ok. start_slave(Args) -> - ?line {A, B, C} = now(), - ?line MicroSecs = A*1000000000000 + B*1000000 + C, - ?line Name = "instr_" ++ integer_to_list(MicroSecs), - ?line Pa = filename:dirname(code:which(?MODULE)), - ?line {ok, Node} = ?t:start_node(list_to_atom(Name), - slave, - [{args, "-pa " ++ Pa ++ " " ++ Args}]), - ?line Node. + MicroSecs = erlang:monotonic_time(), + Name = "instr" ++ integer_to_list(MicroSecs), + Pa = filename:dirname(code:which(?MODULE)), + {ok, Node} = test_server:start_node(list_to_atom(Name), + slave, + [{args, "-pa " ++ Pa ++ " " ++ Args}]), + Node. stop_slave(Node) -> - ?line true = ?t:stop_node(Node). + true = test_server:stop_node(Node). diff --git a/lib/tools/test/lcnt_SUITE.erl b/lib/tools/test/lcnt_SUITE.erl index f3789a4137..d39a5deeab 100644 --- a/lib/tools/test/lcnt_SUITE.erl +++ b/lib/tools/test/lcnt_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2010-2011. All Rights Reserved. +%% Copyright Ericsson AB 2010-2016. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -19,59 +19,39 @@ %% -module(lcnt_SUITE). --include_lib("test_server/include/test_server.hrl"). +-include_lib("common_test/include/ct.hrl"). %% Test server specific exports --export([all/0, suite/0,groups/0,init_per_group/2,end_per_group/2]). --export([init_per_suite/1, end_per_suite/1]). +-export([all/0, suite/0]). -export([init_per_testcase/2, end_per_testcase/2]). %% Test cases --export([ - t_load/1, - t_conflicts/1, - t_locations/1, - t_swap_keys/1 - ]). - -%% Default timetrap timeout (set in init_per_testcase) --define(default_timeout, ?t:minutes(4)). - -init_per_suite(Config) when is_list(Config) -> - Config. - -end_per_suite(Config) when is_list(Config) -> - Config. +-export([t_load/1, + t_conflicts/1, + t_locations/1, + t_swap_keys/1]). init_per_testcase(_Case, Config) -> - Dog = ?t:timetrap(?default_timeout), - [{watchdog,Dog} | Config]. + Config. -end_per_testcase(_Case, Config) -> - Dog = ?config(watchdog, Config), - ?t:timetrap_cancel(Dog), +end_per_testcase(_Case, _Config) -> catch lcnt:stop(), ok. -suite() -> [{ct_hooks,[ts_install_cth]}]. - -all() -> [t_load, t_conflicts, t_locations, t_swap_keys]. - -groups() -> []. - -init_per_group(_GroupName, Config) -> Config. - -end_per_group(_GroupName, Config) -> Config. +suite() -> + [{ct_hooks,[ts_install_cth]}, + {timetrap,{minutes,4}}]. +all() -> + [t_load, t_conflicts, t_locations, t_swap_keys]. %%---------------------------------------------------------------------- %% Tests %%---------------------------------------------------------------------- -t_load(suite) -> []; -t_load(doc) -> ["Load data from file."]; +%% Load data from file. t_load(Config) when is_list(Config) -> - Path = ?config(data_dir, Config), + Path = proplists:get_value(data_dir, Config), Files = [filename:join([Path,"big_bang_40.lcnt"]), filename:join([Path,"ehb_3_3_hist.lcnt"])], ok = t_load_file(Files), @@ -84,10 +64,9 @@ t_load_file([File|Files]) -> ok = lcnt:stop(), t_load_file(Files). -t_conflicts(suite) -> []; -t_conflicts(doc) -> ["API: conflicts"]; +%% API: conflicts t_conflicts(Config) when is_list(Config) -> - Path = ?config(data_dir, Config), + Path = proplists:get_value(data_dir, Config), Files = [filename:join([Path,"big_bang_40.lcnt"]), filename:join([Path,"ehb_3_3_hist.lcnt"])], ok = t_conflicts_file(Files), @@ -118,10 +97,9 @@ test_conflicts_opts([Opt|Opts]) -> ok = lcnt:conflicts(Opt), test_conflicts_opts(Opts). -t_locations(suite) -> []; -t_locations(doc) -> ["API: locations"]; +%% API: locations t_locations(Config) when is_list(Config) -> - Path = ?config(data_dir, Config), + Path = proplists:get_value(data_dir, Config), Files = [filename:join([Path,"big_bang_40.lcnt"]), filename:join([Path,"ehb_3_3_hist.lcnt"])], ok = t_locations_file(Files), @@ -151,10 +129,9 @@ test_locations_opts([Opt|Opts]) -> ok = lcnt:locations(Opt), test_locations_opts(Opts). -t_swap_keys(suite) -> []; -t_swap_keys(doc) -> ["Test interchanging port/process id with class"]; +%% Test interchanging port/process id with class t_swap_keys(Config) when is_list(Config) -> - Path = ?config(data_dir, Config), + Path = proplists:get_value(data_dir, Config), Files = [filename:join([Path,"big_bang_40.lcnt"]), filename:join([Path,"ehb_3_3_hist.lcnt"])], ok = t_swap_keys_file(Files), @@ -169,12 +146,3 @@ t_swap_keys_file([File|Files]) -> ok = lcnt:conflicts(), ok = lcnt:stop(), t_swap_keys_file(Files). - - -%%---------------------------------------------------------------------- -%% Auxiliary tests -%%---------------------------------------------------------------------- - -%%---------------------------------------------------------------------- -%% Auxiliary -%%---------------------------------------------------------------------- diff --git a/lib/tools/test/make_SUITE.erl b/lib/tools/test/make_SUITE.erl index 70bc8502bf..e6284db8b8 100644 --- a/lib/tools/test/make_SUITE.erl +++ b/lib/tools/test/make_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1996-2011. All Rights Reserved. +%% Copyright Ericsson AB 1996-2016. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -20,12 +20,12 @@ -module(make_SUITE). -export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, - init_per_group/2,end_per_group/2, make_all/1, make_files/1]). + init_per_group/2,end_per_group/2, make_all/1, make_files/1]). -export([otp_6057_init/1, - otp_6057_a/1, otp_6057_b/1, otp_6057_c/1, - otp_6057_end/1]). + otp_6057_a/1, otp_6057_b/1, otp_6057_c/1, + otp_6057_end/1]). --include_lib("test_server/include/test_server.hrl"). +-include_lib("common_test/include/ct.hrl"). -include_lib("kernel/include/file.hrl"). @@ -44,7 +44,7 @@ all() -> groups() -> [{otp_6057,[],[otp_6057_a, otp_6057_b, - otp_6057_c]}]. + otp_6057_c]}]. init_per_suite(Config) -> Config. @@ -61,52 +61,50 @@ end_per_group(_GroupName, Config) -> test_files() -> ["test1", "test2", "test3", "test4"]. -make_all(suite) -> []; make_all(Config) when is_list(Config) -> - ?line Current = prepare_data_dir(Config), - ?line up_to_date = make:all(), - ?line ok = ensure_exists(test_files()), - ?line ok = ensure_exists(["test5"],".S"), % Emakefile: [{test5,['S']} - ?line file:set_cwd(Current), - ?line ensure_no_messages(), + Current = prepare_data_dir(Config), + up_to_date = make:all(), + ok = ensure_exists(test_files()), + ok = ensure_exists(["test5"],".S"), % Emakefile: [{test5,['S']} + file:set_cwd(Current), + ensure_no_messages(), ok. -make_files(suite) -> []; make_files(Config) when is_list(Config) -> - ?line Current = prepare_data_dir(Config), + Current = prepare_data_dir(Config), %% Make files that exist. - ?line Files = [test1, test2], - ?line up_to_date = make:files(Files), % ok files - ?line ok = ensure_exists(Files), + Files = [test1, test2], + up_to_date = make:files(Files), % ok files + ok = ensure_exists(Files), - ?line error = make:files([test1,test7]), % non existing file - ?line up_to_date = make:files([test1,test2],[debug_info]), % with option + error = make:files([test1,test7]), % non existing file + up_to_date = make:files([test1,test2],[debug_info]), % with option - ?line file:set_cwd(Current), - ?line ensure_no_messages(), + file:set_cwd(Current), + ensure_no_messages(), ok. %% Moves to the data directory of this suite, clean it from any object %% files (*.jam for a JAM emulator). Returns the previous directory. prepare_data_dir(Config) -> - ?line {ok, Current} = file:get_cwd(), - ?line {value, {data_dir, Dir}} = lists:keysearch(data_dir, 1, Config), - ?line file:set_cwd(Dir), - ?line {ok, Files} = file:list_dir("."), - ?line delete_obj(Files, code:objfile_extension()), - ?line ensure_no_messages(), + {ok, Current} = file:get_cwd(), + {value, {data_dir, Dir}} = lists:keysearch(data_dir, 1, Config), + file:set_cwd(Dir), + {ok, Files} = file:list_dir("."), + delete_obj(Files, code:objfile_extension()), + ensure_no_messages(), Current. delete_obj([File|Rest], ObjExt) -> - ?line case filename:extension(File) of - ObjExt -> file:delete(File); - ".S" -> file:delete(File); - _ -> ok - end, - ?line delete_obj(Rest, ObjExt); + case filename:extension(File) of + ObjExt -> file:delete(File); + ".S" -> file:delete(File); + _ -> ok + end, + delete_obj(Rest, ObjExt); delete_obj([], _) -> ok. @@ -120,26 +118,26 @@ ensure_exists([Name|Rest], ObjExt) when is_atom(Name) -> ensure_exists([atom_to_list(Name)|Rest], ObjExt); ensure_exists([Name|Rest], ObjExt) -> case filelib:is_regular(Name++ObjExt) of - true -> - ensure_exists(Rest, ObjExt); - false -> - Name++ObjExt + true -> + ensure_exists(Rest, ObjExt); + false -> + Name++ObjExt end; ensure_exists([], _) -> ok. otp_6057_init(Config) when is_list(Config) -> - ?line DataDir = ?config(data_dir, Config), - ?line PrivDir = ?config(priv_dir, Config), + DataDir = proplists:get_value(data_dir, Config), + PrivDir = proplists:get_value(priv_dir, Config), %% Create the directories PrivDir/otp_6057/src1, /src2 and /ebin Src1 = filename:join([PrivDir, otp_6057, src1]), Src2 = filename:join([PrivDir, otp_6057, src2]), Ebin = filename:join([PrivDir, otp_6057, ebin]), - ?line ok = file:make_dir(filename:join(PrivDir, otp_6057)), - ?line ok = file:make_dir(Src1), - ?line ok = file:make_dir(Src2), - ?line ok = file:make_dir(Ebin), + ok = file:make_dir(filename:join(PrivDir, otp_6057)), + ok = file:make_dir(Src1), + ok = file:make_dir(Src2), + ok = file:make_dir(Ebin), %% Copy test1.erl and test2.erl to src1, and test3.erl to src2 Test1orig = filename:join(DataDir, "test1.erl"), @@ -148,35 +146,32 @@ otp_6057_init(Config) when is_list(Config) -> Test1 = filename:join(Src1, "test1.erl"), Test2 = filename:join(Src1, "test2.erl"), Test3 = filename:join(Src2, "test3.erl"), - ?line {ok, _} = file:copy(Test1orig, Test1), - ?line {ok, _} = file:copy(Test2orig, Test2), - ?line {ok, _} = file:copy(Test3orig, Test3), + {ok, _} = file:copy(Test1orig, Test1), + {ok, _} = file:copy(Test2orig, Test2), + {ok, _} = file:copy(Test3orig, Test3), %% Create an Emakefile in src1 Emakefile = filename:join(Src1, "Emakefile"), - ?line {ok, Fd} = file:open(Emakefile, write), - ?line ok = io:write(Fd, {["test1.erl","test2","../src2/test3"], - [{outdir,"../ebin"}]}), - ?line ok = io:fwrite(Fd, ".~n", []), - ?line ok = file:close(Fd), + {ok, Fd} = file:open(Emakefile, write), + ok = io:write(Fd, {["test1.erl","test2","../src2/test3"], + [{outdir,"../ebin"}]}), + ok = io:fwrite(Fd, ".~n", []), + ok = file:close(Fd), - ?line ensure_no_messages(), + ensure_no_messages(), Config. -otp_6057_a(suite) -> - []; -otp_6057_a(doc) -> - ["Test that make:all/0, suite/0 looks for object file in correct place"]; +%% Test that make:all/0, suite/0 looks for object file in correct place otp_6057_a(Config) when is_list(Config) -> - ?line PrivDir = ?config(priv_dir, Config), + PrivDir = proplists:get_value(priv_dir, Config), %% Go to src1, saving old CWD - ?line {ok, CWD} = file:get_cwd(), + {ok, CWD} = file:get_cwd(), Src1 = filename:join([PrivDir, otp_6057, src1]), - ?line ok = file:set_cwd(Src1), + ok = file:set_cwd(Src1), %% Call make:all() - ?line up_to_date = make:all(), + up_to_date = make:all(), %% Ensure that all beam files are created in the ebin directory Ebin = filename:join([PrivDir, otp_6057, ebin]), @@ -184,109 +179,103 @@ otp_6057_a(Config) when is_list(Config) -> Test2 = filename:join(Ebin, test2), Test3 = filename:join(Ebin, test3), case ensure_exists([Test1, Test2, Test3]) of - ok -> ok; - Missing -> - ?line ?t:fail({"missing beam file", Missing}) + ok -> ok; + Missing -> + ct:fail({"missing beam file", Missing}) end, %% Check creation date of test1.beam and make sure it is not %% recompiled if make:all() is called again. %% (Sleep a while, if the file is recompiled within a second then %% mtime will be the same). - ?line {ok, FileInfo1} = file:read_file_info(Test1++".beam"), + {ok, FileInfo1} = file:read_file_info(Test1++".beam"), Date1 = FileInfo1#file_info.mtime, - ?t:sleep(?t:seconds(2)), - ?line up_to_date = make:all(), - ?line {ok, FileInfo2} = file:read_file_info(Test1++".beam"), + timer:sleep(2000), + up_to_date = make:all(), + {ok, FileInfo2} = file:read_file_info(Test1++".beam"), case FileInfo2#file_info.mtime of - Date1 -> ok; - _Date2 -> - ?line ?t:fail({"recompiled beam file", Test1++".beam"}) + Date1 -> ok; + _Date2 -> + ct:fail({"recompiled beam file", Test1++".beam"}) end, %% Remove the beam files - ?line ok = - ensure_removed([Test1++".beam",Test2++".beam",Test2++".beam"]), + ok = + ensure_removed([Test1++".beam",Test2++".beam",Test2++".beam"]), %% Return to original CWD - ?line ok = file:set_cwd(CWD), + ok = file:set_cwd(CWD), - ?line ensure_no_messages(), + ensure_no_messages(), ok. -otp_6057_b(suite) -> - []; -otp_6057_b(doc) -> - ["Test that make:files/1 can handle a file in another directory"]; +%% Test that make:files/1 can handle a file in another directory otp_6057_b(Config) when is_list(Config) -> - ?line PrivDir = ?config(priv_dir, Config), + PrivDir = proplists:get_value(priv_dir, Config), %% Go to src1, saving old CWD - ?line {ok, CWD} = file:get_cwd(), + {ok, CWD} = file:get_cwd(), Src1 = filename:join([PrivDir, otp_6057, src1]), - ?line ok = file:set_cwd(Src1), + ok = file:set_cwd(Src1), %% Ensure there is no beam file already Ebin = filename:join([PrivDir, otp_6057, ebin]), Test3 = filename:join(Ebin, "test3"), - ?line ok = ensure_removed([Test3++".beam"]), + ok = ensure_removed([Test3++".beam"]), %% Call make:files/1 - ?line up_to_date = make:files(["../src2/test3"]), - + up_to_date = make:files(["../src2/test3"]), + %% Ensure that the beam file is created in the ebin directory case ensure_exists([Test3]) of - ok -> ok; - Missing -> - ?line ?t:fail({"missing beam file", Missing}) + ok -> ok; + Missing -> + ct:fail({"missing beam file", Missing}) end, %% Remove the beam file - ?line ok = ensure_removed([Test3++".beam"]), + ok = ensure_removed([Test3++".beam"]), %% Return to original CWD - ?line ok = file:set_cwd(CWD), + ok = file:set_cwd(CWD), - ?line ensure_no_messages(), + ensure_no_messages(), ok. -otp_6057_c(suite) -> - []; -otp_6057_c(doc) -> - ["Test that make:files/1 find options in Emakefile if a file is " - "given with the .erl extension there"]; +%% Test that make:files/1 find options in Emakefile if a file is +%% given with the .erl extension there otp_6057_c(Config) when is_list(Config) -> - ?line PrivDir = ?config(priv_dir, Config), + PrivDir = proplists:get_value(priv_dir, Config), %% Go to src1, saving old CWD - ?line {ok, CWD} = file:get_cwd(), + {ok, CWD} = file:get_cwd(), Src1 = filename:join([PrivDir, otp_6057, src1]), - ?line ok = file:set_cwd(Src1), + ok = file:set_cwd(Src1), %% Ensure there are no beam files already Ebin = filename:join([PrivDir, otp_6057, ebin]), Test1 = filename:join(Ebin, "test1"), Test2 = filename:join(Ebin, "test2"), - ?line ok = ensure_removed([Test1++".beam",Test2++".beam"]), + ok = ensure_removed([Test1++".beam",Test2++".beam"]), %% Call make:files/1 - ?line up_to_date = make:files([test1, test2]), - + up_to_date = make:files([test1, test2]), + %% Ensure that the beam files are created in the ebin directory Ebin = filename:join([PrivDir, otp_6057, ebin]), case ensure_exists([Test1, Test2]) of - ok -> ok; - Missing -> - ?line ?t:fail({"missing beam file", Missing}) + ok -> ok; + Missing -> + ct:fail({"missing beam file", Missing}) end, %% Remove the beam files - ?line ok = ensure_removed([Test1++".beam", Test2++".beam"]), + ok = ensure_removed([Test1++".beam", Test2++".beam"]), %% Return to original CWD - ?line ok = file:set_cwd(CWD), + ok = file:set_cwd(CWD), - ?line ensure_no_messages(), + ensure_no_messages(), ok. otp_6057_end(Config) when is_list(Config) -> @@ -303,13 +292,12 @@ ensure_no_messages() -> ensure_no_messages(N) -> receive - Any -> - io:format("Unexpected message: ~p", [Any]), - ensure_no_messages(N+1) + Any -> + io:format("Unexpected message: ~p", [Any]), + ensure_no_messages(N+1) after 0 -> - case N of - 0 -> ok; - N -> ?t:fail() - end + case N of + 0 -> ok; + N -> ct:fail(failed) + end end. - diff --git a/lib/tools/test/tools_SUITE.erl b/lib/tools/test/tools_SUITE.erl index 9403124c96..b50f67a06a 100644 --- a/lib/tools/test/tools_SUITE.erl +++ b/lib/tools/test/tools_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 1997-2011. All Rights Reserved. +%% Copyright Ericsson AB 1997-2016. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -19,60 +19,31 @@ %% -module(tools_SUITE). --include_lib("test_server/include/test_server.hrl"). +-include_lib("common_test/include/ct.hrl"). -%% Default timetrap timeout (set in init_per_testcase). --define(default_timeout, ?t:minutes(1)). -define(application, tools). %% Test server specific exports --export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, - init_per_group/2,end_per_group/2]). --export([init_per_testcase/2, end_per_testcase/2]). +-export([all/0, suite/0]). %% Test cases must be exported. -export([app_test/1, appup_test/1]). -suite() -> [{ct_hooks,[ts_install_cth]}]. +suite() -> + [{ct_hooks,[ts_install_cth]}, + {timetrap,{minutes,1}}]. all() -> [app_test, appup_test]. -groups() -> - []. - -init_per_suite(Config) -> - Config. - -end_per_suite(_Config) -> - ok. - -init_per_group(_GroupName, Config) -> - Config. - -end_per_group(_GroupName, Config) -> - Config. - - -init_per_testcase(_Case, Config) -> - ?line Dog=test_server:timetrap(?default_timeout), - [{watchdog, Dog}|Config]. -end_per_testcase(_Case, Config) -> - Dog=?config(watchdog, Config), - test_server:timetrap_cancel(Dog), - ok. - %%% %%% Test cases starts here. %%% -app_test(doc) -> - ["Test that the .app file does not contain any `basic' errors"]; -app_test(suite) -> - []; +%% Test that the .app file does not contain any `basic' errors app_test(Config) when is_list(Config) -> - ?line ?t:app_test(tools, tolerant). + test_server:app_test(tools, tolerant). %% Test that the .appup file does not contain any `basic' errors appup_test(Config) when is_list(Config) -> - ok = ?t:appup_test(tools). + ok = test_server:appup_test(tools). diff --git a/lib/tools/test/xref_SUITE.erl b/lib/tools/test/xref_SUITE.erl index ad47b31443..ce30fb711a 100644 --- a/lib/tools/test/xref_SUITE.erl +++ b/lib/tools/test/xref_SUITE.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2000-2013. All Rights Reserved. +%% Copyright Ericsson AB 2000-2016. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -30,48 +30,43 @@ -define(privdir, "xref_SUITE_priv"). -define(copydir, "xref_SUITE_priv/datacopy"). -else. --include_lib("test_server/include/test_server.hrl"). +-include_lib("common_test/include/ct.hrl"). -define(format(S, A), ok). --define(datadir, ?config(data_dir, Conf)). --define(privdir, ?config(priv_dir, Conf)). --define(copydir, ?config(copy_dir, Conf)). +-define(datadir, proplists:get_value(data_dir, Conf)). +-define(privdir, proplists:get_value(priv_dir, Conf)). +-define(copydir, proplists:get_value(copy_dir, Conf)). -endif. --export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, - init_per_group/2,end_per_group/2, init/1, fini/1]). +-export([all/0, suite/0, groups/0, + init_per_suite/1, end_per_suite/1]). --export([ - addrem/1, convert/1, intergraph/1, lines/1, loops/1, - no_data/1, modules/1]). +-export([addrem/1, convert/1, intergraph/1, lines/1, loops/1, + no_data/1, modules/1]). --export([ - add/1, default/1, info/1, lib/1, read/1, read2/1, remove/1, - replace/1, update/1, deprecated/1, trycatch/1, +-export([add/1, default/1, info/1, lib/1, read/1, read2/1, remove/1, + replace/1, update/1, deprecated/1, trycatch/1, fun_mfa/1, fun_mfa_r14/1, - fun_mfa_vars/1, qlc/1]). + fun_mfa_vars/1, qlc/1]). --export([ - analyze/1, basic/1, md/1, q/1, variables/1, unused_locals/1]). +-export([analyze/1, basic/1, md/1, q/1, variables/1, unused_locals/1]). --export([ - format_error/1, otp_7423/1, otp_7831/1, otp_10192/1]). +-export([format_error/1, otp_7423/1, otp_7831/1, otp_10192/1]). -import(lists, [append/2, flatten/1, keysearch/3, member/2, sort/1, usort/1]). -import(sofs, [converse/1, from_term/1, intersection/2, is_sofs_set/1, - range/1, relation_to_family/1, set/1, to_external/1, - union/2]). - --export([init_per_testcase/2, end_per_testcase/2]). + range/1, relation_to_family/1, set/1, to_external/1, + union/2]). %% Checks some info counters of a server and some relations that should hold. -export([check_count/1, check_state/1]). -include_lib("kernel/include/file.hrl"). - -include_lib("tools/src/xref.hrl"). -suite() -> [{ct_hooks,[ts_install_cth]}]. +suite() -> + [{ct_hooks,[ts_install_cth]}, + {timetrap,{minutes,2}}]. all() -> [{group, xref}, {group, files}, {group, analyses}, @@ -89,48 +84,24 @@ groups() -> [analyze, basic, md, q, variables, unused_locals]}, {misc, [], [format_error, otp_7423, otp_7831, otp_10192]}]. -init_per_suite(Config) -> - init(Config). - -end_per_suite(_Config) -> - ok. - -init_per_group(_GroupName, Config) -> - Config. - -end_per_group(_GroupName, Config) -> - Config. - -init(Conf) when is_list(Conf) -> +init_per_suite(Conf) when is_list(Conf) -> DataDir = ?datadir, PrivDir = ?privdir, - ?line CopyDir = fname(PrivDir, "datacopy"), - ?line TarFile = fname(PrivDir, "datacopy.tgz"), - ?line {ok, Tar} = erl_tar:open(TarFile, [write, compressed]), - ?line ok = erl_tar:add(Tar, DataDir, CopyDir, [compressed]), - ?line ok = erl_tar:close(Tar), - ?line ok = erl_tar:extract(TarFile, [compressed]), - ?line ok = file:delete(TarFile), - [{copy_dir, CopyDir} | Conf]. - -fini(Conf) when is_list(Conf) -> - %% Nothing. - Conf. - -init_per_testcase(_Case, Config) -> - Dog=?t:timetrap(?t:minutes(2)), - [{watchdog, Dog}|Config]. - -end_per_testcase(_Case, _Config) -> - Dog=?config(watchdog, _Config), - test_server:timetrap_cancel(Dog), + CopyDir = fname(PrivDir, "datacopy"), + TarFile = fname(PrivDir, "datacopy.tgz"), + {ok, Tar} = erl_tar:open(TarFile, [write, compressed]), + ok = erl_tar:add(Tar, DataDir, CopyDir, [compressed]), + ok = erl_tar:close(Tar), + ok = erl_tar:extract(TarFile, [compressed]), + ok = file:delete(TarFile), + [{copy_dir, CopyDir}|Conf]. + +end_per_suite(Conf) when is_list(Conf) -> ok. - %% Seems a bit short... -addrem(suite) -> []; -addrem(doc) -> ["Simple test of removing modules"]; +%% Simple test of removing modules addrem(Conf) when is_list(Conf) -> S0 = new(), @@ -149,8 +120,8 @@ addrem(Conf) when is_list(Conf) -> LCallAt_m1 = [], XCallAt_m1 = [{E1,13}], Info1 = #xref_mod{name = m1, app_name = [a1]}, - ?line S1 = add_module(S0, Info1, DefAt_m1, X_m1, LCallAt_m1, XCallAt_m1, - XC_m1, LC_m1), + S1 = add_module(S0, Info1, DefAt_m1, X_m1, LCallAt_m1, XCallAt_m1, + XC_m1, LC_m1), D2 = {F2,7}, DefAt_m2 = [D2], @@ -161,26 +132,25 @@ addrem(Conf) when is_list(Conf) -> LCallAt_m2 = [], XCallAt_m2 = [{E2,96}], Info2 = #xref_mod{name = m2, app_name = [a2]}, - ?line S2 = add_module(S1, Info2, DefAt_m2, X_m2, LCallAt_m2, XCallAt_m2, - XC_m2, LC_m2), - - ?line S5 = set_up(S2), - - ?line {ok, XMod1, S6} = remove_module(S5, m1), - ?line [a1] = XMod1#xref_mod.app_name, - ?line {ok, XMod2, S6a} = remove_module(S6, m2), - ?line [a2] = XMod2#xref_mod.app_name, - ?line S7 = set_up(S6a), - - ?line AppInfo1 = #xref_app{name = a1, rel_name = [r1]}, - ?line S9 = add_application(S7, AppInfo1), - ?line S10 = set_up(S9), - ?line AppInfo2 = #xref_app{name = a2, rel_name = [r1]}, - ?line _S11 = add_application(S10, AppInfo2), + S2 = add_module(S1, Info2, DefAt_m2, X_m2, LCallAt_m2, XCallAt_m2, + XC_m2, LC_m2), + + S5 = set_up(S2), + + {ok, XMod1, S6} = remove_module(S5, m1), + [a1] = XMod1#xref_mod.app_name, + {ok, XMod2, S6a} = remove_module(S6, m2), + [a2] = XMod2#xref_mod.app_name, + S7 = set_up(S6a), + + AppInfo1 = #xref_app{name = a1, rel_name = [r1]}, + S9 = add_application(S7, AppInfo1), + S10 = set_up(S9), + AppInfo2 = #xref_app{name = a2, rel_name = [r1]}, + _S11 = add_application(S10, AppInfo2), ok. -convert(suite) -> []; -convert(doc) -> ["Coercion of data"]; +%% Coercion of data convert(Conf) when is_list(Conf) -> S0 = new(), @@ -215,8 +185,8 @@ convert(Conf) when is_list(Conf) -> LCallAt_m1 = [], XCallAt_m1 = [{E1,13},{E2,17},{E4,7}], Info1 = #xref_mod{name = m1, app_name = [a1]}, - ?line S1 = add_module(S0, Info1, DefAt_m1, X_m1, LCallAt_m1, XCallAt_m1, - XC_m1, LC_m1), + S1 = add_module(S0, Info1, DefAt_m1, X_m1, LCallAt_m1, XCallAt_m1, + XC_m1, LC_m1), D2 = {F2,7}, D3 = {F3,9}, @@ -229,8 +199,8 @@ convert(Conf) when is_list(Conf) -> LCallAt_m2 = [], XCallAt_m2 = [{E3,96},{E6,12},{UE1,77}], Info2 = #xref_mod{name = m2, app_name = [a2]}, - ?line S2 = add_module(S1, Info2, DefAt_m2, X_m2, LCallAt_m2, XCallAt_m2, - XC_m2, LC_m2), + S2 = add_module(S1, Info2, DefAt_m2, X_m2, LCallAt_m2, XCallAt_m2, + XC_m2, LC_m2), D4 = {F4,6}, D5 = {F5,97}, @@ -242,74 +212,74 @@ convert(Conf) when is_list(Conf) -> LCallAt_m3 = [{E5,19}], XCallAt_m3 = [{UE2,22}], Info3 = #xref_mod{name = m3, app_name = [a3]}, - ?line S3 = add_module(S2, Info3, DefAt_m3, X_m3, LCallAt_m3, XCallAt_m3, - XC_m3, LC_m3), + S3 = add_module(S2, Info3, DefAt_m3, X_m3, LCallAt_m3, XCallAt_m3, + XC_m3, LC_m3), Info4 = #xref_mod{name = m4, app_name = [a2]}, - ?line S4 = add_module(S3, Info4, [], [], [], [], [], []), + S4 = add_module(S3, Info4, [], [], [], [], [], []), AppInfo1 = #xref_app{name = a1, rel_name = [r1]}, - ?line S9 = add_application(S4, AppInfo1), + S9 = add_application(S4, AppInfo1), AppInfo2 = #xref_app{name = a2, rel_name = [r1]}, - ?line S10 = add_application(S9, AppInfo2), + S10 = add_application(S9, AppInfo2), AppInfo3 = #xref_app{name = a3, rel_name = [r2]}, - ?line S11 = add_application(S10, AppInfo3), + S11 = add_application(S10, AppInfo3), RelInfo1 = #xref_rel{name = r1}, - ?line S12 = add_release(S11, RelInfo1), + S12 = add_release(S11, RelInfo1), RelInfo2 = #xref_rel{name = r2}, - ?line S13 = add_release(S12, RelInfo2), + S13 = add_release(S12, RelInfo2), - ?line S = set_up(S13), + S = set_up(S13), - ?line {ok, _} = eval("(Lin)(m1->m1:Mod) * m1->m1", type_error, S), - ?line {ok, _} = eval("(XXL)(Lin)(m1->m1:Mod) * m1->m1", type_error, S), + {ok, _} = eval("(Lin)(m1->m1:Mod) * m1->m1", type_error, S), + {ok, _} = eval("(XXL)(Lin)(m1->m1:Mod) * m1->m1", type_error, S), - ?line AllDefAt = eval("(Lin) M", S), - ?line AllV = eval("(Fun) M", S), - ?line AllCallAt = eval("(XXL)(Lin) E", S), - ?line AllE = eval("E", S), + AllDefAt = eval("(Lin) M", S), + AllV = eval("(Fun) M", S), + AllCallAt = eval("(XXL)(Lin) E", S), + AllE = eval("E", S), - ?line AM = eval("AM", S), - ?line A = eval("A", S), - ?line R = eval("R", S), + AM = eval("AM", S), + A = eval("A", S), + R = eval("R", S), % vertices % general 1 step - ?line {ok, _} = eval("(Fun) (Lin) M", AllV, S), - ?line {ok, _} = eval("(Fun) (Lin) (Lin) M", AllV, S), - ?line {ok, _} = eval(f("(Fun) (Lin) ~p", [[F1, F3]]), [F1,F3], S), - ?line {ok, _} = eval(f("(Mod) ~p", [AllV]), [m1,m17,m2,m3], S), - ?line {ok, _} = eval(f("(Mod) ~p", [[F1,F3,F6]]), [m1,m2], S), - ?line {ok, _} = eval("(App) M", A, S), - ?line {ok, _} = eval(f("(App) ~p", [[m1,m2,m4]]), [a1,a2], S), - ?line {ok, _} = eval(f("(Rel) ~p", [A]), R, S), - ?line {ok, _} = eval(f("(Rel) ~p", [[a1,a2,a2]]), [r1], S), + {ok, _} = eval("(Fun) (Lin) M", AllV, S), + {ok, _} = eval("(Fun) (Lin) (Lin) M", AllV, S), + {ok, _} = eval(f("(Fun) (Lin) ~p", [[F1, F3]]), [F1,F3], S), + {ok, _} = eval(f("(Mod) ~p", [AllV]), [m1,m17,m2,m3], S), + {ok, _} = eval(f("(Mod) ~p", [[F1,F3,F6]]), [m1,m2], S), + {ok, _} = eval("(App) M", A, S), + {ok, _} = eval(f("(App) ~p", [[m1,m2,m4]]), [a1,a2], S), + {ok, _} = eval(f("(Rel) ~p", [A]), R, S), + {ok, _} = eval(f("(Rel) ~p", [[a1,a2,a2]]), [r1], S), % general 2 steps - ?line {ok, _} = eval("(Mod) (Lin) M", [m1,m17,m2,m3], S), - ?line {ok, _} = eval(f("(App) ~p", [AllV]), [a1,a2,a3], S), - ?line {ok, _} = eval("(Rel) M", R, S), + {ok, _} = eval("(Mod) (Lin) M", [m1,m17,m2,m3], S), + {ok, _} = eval(f("(App) ~p", [AllV]), [a1,a2,a3], S), + {ok, _} = eval("(Rel) M", R, S), % general 4 steps - ?line {ok, _} = eval("(Rel) (Lin) M", [r1,r2], S), + {ok, _} = eval("(Rel) (Lin) M", [r1,r2], S), % special 1 step - ?line {ok, _} = eval(f("(Lin) ~p", [AllV]), AllDefAt, S), - ?line {ok, _} = eval(f("(Lin) ~p", [[F1,F3]]), [{F1,12},{F3,9}], S), - ?line {ok, _} = eval("(Fun) M", AllV, S), - ?line {ok, _} = eval(f("(Fun) ~p", [[m1,m2]]), [F1,F2,F3,F6,F7,UF1], S), - ?line {ok, _} = eval(f("(Mod) ~p", [A]), AM, S), - ?line {ok, _} = eval(f("(Mod) ~p", [[a1,a2]]), [m1,m2,m4], S), - ?line {ok, _} = eval(f("(App) ~p", [R]), A, S), - ?line {ok, _} = eval(f("(App) ~p", [[r1]]), [a1,a2], S), + {ok, _} = eval(f("(Lin) ~p", [AllV]), AllDefAt, S), + {ok, _} = eval(f("(Lin) ~p", [[F1,F3]]), [{F1,12},{F3,9}], S), + {ok, _} = eval("(Fun) M", AllV, S), + {ok, _} = eval(f("(Fun) ~p", [[m1,m2]]), [F1,F2,F3,F6,F7,UF1], S), + {ok, _} = eval(f("(Mod) ~p", [A]), AM, S), + {ok, _} = eval(f("(Mod) ~p", [[a1,a2]]), [m1,m2,m4], S), + {ok, _} = eval(f("(App) ~p", [R]), A, S), + {ok, _} = eval(f("(App) ~p", [[r1]]), [a1,a2], S), % special 2 steps - ?line {ok, _} = eval("(Lin) M", AllDefAt, S), - ?line AnalyzedV = eval("(Fun) AM", S), - ?line {ok, _} = eval(f("(Fun) ~p", [A]), AnalyzedV, S), - ?line {ok, _} = eval(f("(Mod) ~p", [R]), AM, S), + {ok, _} = eval("(Lin) M", AllDefAt, S), + AnalyzedV = eval("(Fun) AM", S), + {ok, _} = eval(f("(Fun) ~p", [A]), AnalyzedV, S), + {ok, _} = eval(f("(Mod) ~p", [R]), AM, S), % special 4 steps - ?line AnalyzedAllDefAt = eval("(Lin) AM", S), - ?line {ok, _} = eval("(Lin) R", AnalyzedAllDefAt, S), + AnalyzedAllDefAt = eval("(Lin) AM", S), + {ok, _} = eval("(Lin) R", AnalyzedAllDefAt, S), % edges Ms = [{m1,m2},{m1,m3},{m2,m1},{m2,m3},{m3,m3}], @@ -319,31 +289,30 @@ convert(Conf) when is_list(Conf) -> Rs = [{r1,r1},{r1,r2},{r2,r2}], % general 1 step - ?line {ok, _} = eval("(Fun) (Lin) E", AllE, S), - ?line {ok, _} = eval(f("(Fun)(Lin) ~p", [[E1, E6]]), [E1, E6], S), - ?line {ok, _} = eval("(Mod) E", AllMs, S), - ?line {ok, _} = eval(f("(Mod) ~p", [[E1, E6]]), [{m1,m2},{m2,m3}], S), - ?line {ok, _} = eval(f("(App) ~p", [As]), As, S), - ?line {ok, _} = eval("(App) [m1->m2,m2->m3]", [{a1,a2},{a2,a3}], S), - ?line {ok, _} = eval(f("(Rel) ~p", [As]), Rs, S), - ?line {ok, _} = eval("(Rel) a1->a2", [{r1,r1}], S), + {ok, _} = eval("(Fun) (Lin) E", AllE, S), + {ok, _} = eval(f("(Fun)(Lin) ~p", [[E1, E6]]), [E1, E6], S), + {ok, _} = eval("(Mod) E", AllMs, S), + {ok, _} = eval(f("(Mod) ~p", [[E1, E6]]), [{m1,m2},{m2,m3}], S), + {ok, _} = eval(f("(App) ~p", [As]), As, S), + {ok, _} = eval("(App) [m1->m2,m2->m3]", [{a1,a2},{a2,a3}], S), + {ok, _} = eval(f("(Rel) ~p", [As]), Rs, S), + {ok, _} = eval("(Rel) a1->a2", [{r1,r1}], S), % special 1 step - ?line {ok, _} = eval("(XXL) (Lin) (Fun) E", AllCallAt, S), - ?line {ok, _} = eval("(XXL) (XXL) (Lin) (Fun) E", AllCallAt, S), - - ?line {ok, _} = eval(f("(XXL) (Lin) ~p", [[E1, E6]]), - [{{D1,D3},[13]}, {{D7,D4},[12]}], S), - ?line {ok, _} = eval(f("(Fun) ~p", [AllMs]), AllE, S), - ?line {ok, _} = eval("(Fun) [m1->m2,m2->m3]", [E1,E2,E6], S), - ?line {ok, _} = eval(f("(Mod) ~p", [As]), Ms, S), - ?line {ok, _} = eval("(Mod) [a1->a2,a2->a3]", [{m1,m2},{m2,m3}], S), - ?line {ok, _} = eval(f("(App) ~p", [Rs]), As, S), - ?line {ok, _} = eval("(App) r1->r1", [{a1,a2},{a2,a1}], S), + {ok, _} = eval("(XXL) (Lin) (Fun) E", AllCallAt, S), + {ok, _} = eval("(XXL) (XXL) (Lin) (Fun) E", AllCallAt, S), + + {ok, _} = eval(f("(XXL) (Lin) ~p", [[E1, E6]]), + [{{D1,D3},[13]}, {{D7,D4},[12]}], S), + {ok, _} = eval(f("(Fun) ~p", [AllMs]), AllE, S), + {ok, _} = eval("(Fun) [m1->m2,m2->m3]", [E1,E2,E6], S), + {ok, _} = eval(f("(Mod) ~p", [As]), Ms, S), + {ok, _} = eval("(Mod) [a1->a2,a2->a3]", [{m1,m2},{m2,m3}], S), + {ok, _} = eval(f("(App) ~p", [Rs]), As, S), + {ok, _} = eval("(App) r1->r1", [{a1,a2},{a2,a1}], S), ok. -intergraph(suite) -> []; -intergraph(doc) -> ["Inter Call Graph"]; +%% Inter Call Graph intergraph(Conf) when is_list(Conf) -> S0 = new(), @@ -392,8 +361,8 @@ intergraph(Conf) when is_list(Conf) -> LCallAt_m1 = [{E1,1},{E2,2},{E3,3},{E5,5},{E6,6},{E7,7}], XCallAt_m1 = [{E1,4}], Info1 = #xref_mod{name = m1, app_name = [a1]}, - ?line S1 = add_module(S0, Info1, DefAt_m1, X_m1, LCallAt_m1, XCallAt_m1, - XC_m1, LC_m1), + S1 = add_module(S0, Info1, DefAt_m1, X_m1, LCallAt_m1, XCallAt_m1, + XC_m1, LC_m1), D6 = {F6,6}, D7 = {F7,7}, @@ -409,73 +378,72 @@ intergraph(Conf) when is_list(Conf) -> LCallAt_m2 = [{E8,8},{E9,9},{E11,11},{E12,12},{E13,13},{E14,14}], XCallAt_m2 = [{E10,10},{E15,15}], Info2 = #xref_mod{name = m2, app_name = [a2]}, - ?line S2 = add_module(S1, Info2, DefAt_m2, X_m2, LCallAt_m2, XCallAt_m2, - XC_m2, LC_m2), + S2 = add_module(S1, Info2, DefAt_m2, X_m2, LCallAt_m2, XCallAt_m2, + XC_m2, LC_m2), AppInfo1 = #xref_app{name = a1, rel_name = [r1]}, - ?line S5 = add_application(S2, AppInfo1), + S5 = add_application(S2, AppInfo1), AppInfo2 = #xref_app{name = a2, rel_name = [r1]}, - ?line S6 = add_application(S5, AppInfo2), + S6 = add_application(S5, AppInfo2), RelInfo = #xref_rel{name = r1}, - ?line S7 = add_release(S6, RelInfo), + S7 = add_release(S6, RelInfo), - ?line S = set_up(S7), + S = set_up(S7), - ?line {ok, _} = eval("EE | m1", [E1,E5,E6,E7], S), - ?line {ok, _} = eval("EE | m2", [{F6,F1}], S), - ?line {ok, _} = eval("EE | m2 + EE | m2", [{F6,F1}], S), + {ok, _} = eval("EE | m1", [E1,E5,E6,E7], S), + {ok, _} = eval("EE | m2", [{F6,F1}], S), + {ok, _} = eval("EE | m2 + EE | m2", [{F6,F1}], S), - ?line {ok, _} = eval("(Fun)(Lin)(E | m1)", - to_external(union(set(XC_m1), set(LC_m1))), S), - ?line {ok, _} = eval("(XXL)(ELin) (EE | m1)", - [{{D2,D1},[1,2,4]},{{D4,D2},[5]},{{D5,D4},[6]},{{D4,D5},[7]}], - S), - ?line {ok, _} = eval("(XXL)(ELin)(EE | m2)", [{{D6,D1},[8,11,12]}], S), - ?line {ok, _} = eval("(XXL)(ELin)(ELin)(EE | m2)", - [{{D6,D1},[8,11,12]}], S), + {ok, _} = eval("(Fun)(Lin)(E | m1)", + to_external(union(set(XC_m1), set(LC_m1))), S), + {ok, _} = eval("(XXL)(ELin) (EE | m1)", + [{{D2,D1},[1,2,4]},{{D4,D2},[5]},{{D5,D4},[6]},{{D4,D5},[7]}], + S), + {ok, _} = eval("(XXL)(ELin)(EE | m2)", [{{D6,D1},[8,11,12]}], S), + {ok, _} = eval("(XXL)(ELin)(ELin)(EE | m2)", + [{{D6,D1},[8,11,12]}], S), %% Combining graphs (equal or different): - ?line {ok, _} = eval("(XXL)(ELin)(EE | m2 + EE | m2)", - [{{D6,D1},[8,11,12]}], S), - ?line {ok, _} = eval("(XXL)(ELin)(EE | m2 * EE | m2)", - [{{D6,D1},[8,11,12]}], S), - ?line {ok, _} = eval("(XXL)(ELin)(EE | m2 - EE | m1)", - [{{D6,D1},[8,11,12]}], S), - ?line {ok, _} = eval("(XXL)(ELin)(EE | m2 - E | m2)", - [{{D6,D1},[8,11,12]}], S), - ?line {ok, _} = eval("(XXL)(ELin)(Fun)(ELin)(EE | m2)", - [{{D6,D1},[8,11,12]}], S), - ?line {ok, _} = eval("EE | m1 + E | m1", LC_m1, S), - ?line {ok, _} = eval(f("EE | ~p + E | ~p", [F2, F2]), [E1,E2], S), + {ok, _} = eval("(XXL)(ELin)(EE | m2 + EE | m2)", + [{{D6,D1},[8,11,12]}], S), + {ok, _} = eval("(XXL)(ELin)(EE | m2 * EE | m2)", + [{{D6,D1},[8,11,12]}], S), + {ok, _} = eval("(XXL)(ELin)(EE | m2 - EE | m1)", + [{{D6,D1},[8,11,12]}], S), + {ok, _} = eval("(XXL)(ELin)(EE | m2 - E | m2)", + [{{D6,D1},[8,11,12]}], S), + {ok, _} = eval("(XXL)(ELin)(Fun)(ELin)(EE | m2)", + [{{D6,D1},[8,11,12]}], S), + {ok, _} = eval("EE | m1 + E | m1", LC_m1, S), + {ok, _} = eval(f("EE | ~p + E | ~p", [F2, F2]), [E1,E2], S), %% [1,4] from 'calls' is a subset of [1,2,4] from Inter Call Graph: - ?line {ok, _} = eval(f("(XXL)(Lin) (E | ~p)", [F2]), - [{{D2,D1},[1,4]},{{D2,D3},[2]}], S), - - ?line {ok, _} = eval(f("(XXL)(ELin) (EE | ~p)", [F2]), - [{{D2,D1},[1,2,4]}], S), - ?line {ok, _} = eval(f("(XXL)((ELin)(EE | ~p) + (Lin)(E | ~p))", [F2, F2]), - [{{D2,D1},[1,2,4]},{{D2,D3},[2]}], S), - ?line {ok, _} = - eval(f("(XXL)((ELin) ~p + (Lin) ~p)", [{F2, F1}, {F2, F1}]), - [{{D2,D1},[1,2,4]}], S), - ?line {ok, _} = eval(f("(Fun)(Lin) ~p", [{F2, F1}]), [E1], S), + {ok, _} = eval(f("(XXL)(Lin) (E | ~p)", [F2]), + [{{D2,D1},[1,4]},{{D2,D3},[2]}], S), + + {ok, _} = eval(f("(XXL)(ELin) (EE | ~p)", [F2]), + [{{D2,D1},[1,2,4]}], S), + {ok, _} = eval(f("(XXL)((ELin)(EE | ~p) + (Lin)(E | ~p))", [F2, F2]), + [{{D2,D1},[1,2,4]},{{D2,D3},[2]}], S), + {ok, _} = + eval(f("(XXL)((ELin) ~p + (Lin) ~p)", [{F2, F1}, {F2, F1}]), + [{{D2,D1},[1,2,4]}], S), + {ok, _} = eval(f("(Fun)(Lin) ~p", [{F2, F1}]), [E1], S), %% The external call E4 is included in the reply: - ?line {ok, _} = eval("(XXL)(Lin)(LC | m1)", - [{{D2,D1},[1,4]},{{D2,D3},[2]},{{D3,D1},[3]}, - {{D4,D2},[5]},{{D4,D5},[7]},{{D5,D4},[6]}], S), + {ok, _} = eval("(XXL)(Lin)(LC | m1)", + [{{D2,D1},[1,4]},{{D2,D3},[2]},{{D3,D1},[3]}, + {{D4,D2},[5]},{{D4,D5},[7]},{{D5,D4},[6]}], S), %% The local call E1 is included in the reply: - ?line {ok, _} = eval("(XXL)(Lin)(XC | m1)", [{{D2,D1},[1,4]}], S), + {ok, _} = eval("(XXL)(Lin)(XC | m1)", [{{D2,D1},[1,4]}], S), - ?line {ok, _} = eval(f("(LLin) (E | ~p || ~p) + (XLin) (E | ~p || ~p)", - [F2, F1, F2, F1]), [{E4,[1,4]}], S), + {ok, _} = eval(f("(LLin) (E | ~p || ~p) + (XLin) (E | ~p || ~p)", + [F2, F1, F2, F1]), [{E4,[1,4]}], S), - ?line {ok, _} = eval("# (ELin) E", 6, S), + {ok, _} = eval("# (ELin) E", 6, S), ok. -lines(suite) -> []; -lines(doc) -> ["More test of Inter Call Graph, and regular expressions"]; +%% More test of Inter Call Graph, and regular expressions lines(Conf) when is_list(Conf) -> S0 = new(), @@ -509,8 +477,8 @@ lines(Conf) when is_list(Conf) -> LCallAt_m1 = [{E1,1},{E3,3},{E6,6}], XCallAt_m1 = [{E2,2},{E4,4},{E5,5},{E7,7}], Info1 = #xref_mod{name = m1, app_name = [a1]}, - ?line S1 = add_module(S0, Info1, DefAt_m1, X_m1, LCallAt_m1, XCallAt_m1, - XC_m1, LC_m1), + S1 = add_module(S0, Info1, DefAt_m1, X_m1, LCallAt_m1, XCallAt_m1, + XC_m1, LC_m1), DefAt_m2 = [D4], X_m2 = [F4], @@ -520,81 +488,80 @@ lines(Conf) when is_list(Conf) -> LCallAt_m2 = [], XCallAt_m2 = [], Info2 = #xref_mod{name = m2, app_name = [a2]}, - ?line S2 = add_module(S1, Info2, DefAt_m2, X_m2, LCallAt_m2, XCallAt_m2, - XC_m2, LC_m2), + S2 = add_module(S1, Info2, DefAt_m2, X_m2, LCallAt_m2, XCallAt_m2, + XC_m2, LC_m2), AppInfo1 = #xref_app{name = a1, rel_name = [r1]}, - ?line S5 = add_application(S2, AppInfo1), + S5 = add_application(S2, AppInfo1), AppInfo2 = #xref_app{name = a2, rel_name = [r1]}, - ?line S6 = add_application(S5, AppInfo2), + S6 = add_application(S5, AppInfo2), RelInfo = #xref_rel{name = r1}, - ?line S7 = add_release(S6, RelInfo), - - ?line S = set_up(S7), - - ?line {ok, _} = eval("(XXL) (ELin) (EE | m1)", - [{{D1,D1},[1]},{{D1,D4},[1,4]},{{D3,D1},[3]},{{D3,D4},[3]}, - {{D5,D4},[6]}], S), - ?line {ok, _} = eval("(XXL)(Lin) (E | m1)", - [{{D1,D2},[1]},{{D1,D4},[4]},{{D2,D1},[2]}, - {{D2,D4},[5]},{{D3,D2},[3]},{{D5,D6},[6]},{{D6,D4},[7]}], - S), - ?line {ok, _} = eval("(E | m1) + (EE | m1)", - [E1,E2,E3,E4,E5,E6,E7,{F1,F1},{F3,F1},{F3,F4},{F5,F4}], - S), - ?line {ok, _} = eval("(Lin)(E | m1)", - [{E4,[4]},{E1,[1]},{E2,[2]},{E5,[5]}, - {E3,[3]},{E7,[7]},{E6,[6]}], S), - ?line {ok, _} = eval("(ELin)(EE | m1)", - [{{F1,F1},[1]},{{F1,F4},[1,4]},{{F3,F1},[3]},{{F3,F4},[3]}, - {{F5,F4},[6]}], S), - ?line {ok, _} = eval("(Lin)(E | m1) + (ELin)(EE | m1)", - [{E4,[1,4]},{E1,[1]},{E2,[2]},{E5,[5]}, - {E3,[3]},{E7,[7]},{E6,[6]}, - {{F1,F1},[1]},{{F3,F1},[3]},{{F3,F4},[3]}, - {{F5,F4},[6]}], S), - ?line {ok, _} = eval("(Lin)(E | m1) - (ELin)(EE | m1)", - [{E1,[1]},{E2,[2]},{E5,[5]}, - {E3,[3]},{E7,[7]},{E6,[6]}], S), - ?line {ok, _} = eval("(Lin)(E | m1) * (ELin)(EE | m1)", - [{E4,[4]}], S), - ?line {ok, _} = eval("(XXL)(Lin) (E | m1)", - [{{D1,D4},[4]},{{D1,D2},[1]},{{D2,D1},[2]},{{D2,D4},[5]}, - {{D3,D2},[3]},{{D6,D4},[7]},{{D5,D6},[6]}], S), - ?line {ok, _} = eval("(XXL)(ELin) (EE | m1)", - [{{D1,D1},[1]},{{D1,D4},[1,4]},{{D3,D1},[3]},{{D3,D4},[3]}, - {{D5,D4},[6]}], S), - ?line {ok, _} = eval("(XXL)(Lin)(Fun)(Lin) (E | m1)", - [{{D1,D4},[4]},{{D1,D2},[1]},{{D2,D1},[2]},{{D2,D4},[5]}, - {{D3,D2},[3]},{{D6,D4},[7]},{{D5,D6},[6]}], S), - ?line {ok, _} = eval("(XXL)(ELin)(Fun)(ELin) (EE | m1)", - [{{D1,D1},[1]},{{D1,D4},[1,4]},{{D3,D1},[3]},{{D3,D4},[3]}, - {{D5,D4},[6]}], S), + S7 = add_release(S6, RelInfo), + + S = set_up(S7), + + {ok, _} = eval("(XXL) (ELin) (EE | m1)", + [{{D1,D1},[1]},{{D1,D4},[1,4]},{{D3,D1},[3]},{{D3,D4},[3]}, + {{D5,D4},[6]}], S), + {ok, _} = eval("(XXL)(Lin) (E | m1)", + [{{D1,D2},[1]},{{D1,D4},[4]},{{D2,D1},[2]}, + {{D2,D4},[5]},{{D3,D2},[3]},{{D5,D6},[6]},{{D6,D4},[7]}], + S), + {ok, _} = eval("(E | m1) + (EE | m1)", + [E1,E2,E3,E4,E5,E6,E7,{F1,F1},{F3,F1},{F3,F4},{F5,F4}], + S), + {ok, _} = eval("(Lin)(E | m1)", + [{E4,[4]},{E1,[1]},{E2,[2]},{E5,[5]}, + {E3,[3]},{E7,[7]},{E6,[6]}], S), + {ok, _} = eval("(ELin)(EE | m1)", + [{{F1,F1},[1]},{{F1,F4},[1,4]},{{F3,F1},[3]},{{F3,F4},[3]}, + {{F5,F4},[6]}], S), + {ok, _} = eval("(Lin)(E | m1) + (ELin)(EE | m1)", + [{E4,[1,4]},{E1,[1]},{E2,[2]},{E5,[5]}, + {E3,[3]},{E7,[7]},{E6,[6]}, + {{F1,F1},[1]},{{F3,F1},[3]},{{F3,F4},[3]}, + {{F5,F4},[6]}], S), + {ok, _} = eval("(Lin)(E | m1) - (ELin)(EE | m1)", + [{E1,[1]},{E2,[2]},{E5,[5]}, + {E3,[3]},{E7,[7]},{E6,[6]}], S), + {ok, _} = eval("(Lin)(E | m1) * (ELin)(EE | m1)", + [{E4,[4]}], S), + {ok, _} = eval("(XXL)(Lin) (E | m1)", + [{{D1,D4},[4]},{{D1,D2},[1]},{{D2,D1},[2]},{{D2,D4},[5]}, + {{D3,D2},[3]},{{D6,D4},[7]},{{D5,D6},[6]}], S), + {ok, _} = eval("(XXL)(ELin) (EE | m1)", + [{{D1,D1},[1]},{{D1,D4},[1,4]},{{D3,D1},[3]},{{D3,D4},[3]}, + {{D5,D4},[6]}], S), + {ok, _} = eval("(XXL)(Lin)(Fun)(Lin) (E | m1)", + [{{D1,D4},[4]},{{D1,D2},[1]},{{D2,D1},[2]},{{D2,D4},[5]}, + {{D3,D2},[3]},{{D6,D4},[7]},{{D5,D6},[6]}], S), + {ok, _} = eval("(XXL)(ELin)(Fun)(ELin) (EE | m1)", + [{{D1,D1},[1]},{{D1,D4},[1,4]},{{D3,D1},[3]},{{D3,D4},[3]}, + {{D5,D4},[6]}], S), %% A few tests on regexp. - ?line {ok, _} = eval("\"(foo\":Mod", parse_error, S), - ?line {ok, _} = eval("_Foo:_/_", parse_error, S), - ?line {ok, _} = eval("\".*foo\"", parse_error, S), - ?line {ok, _} = eval("_:_/_:Lin", parse_error, S), - ?line {ok, _} = eval("_:_/_:Mod", parse_error, S), - ?line {ok, _} = eval("_:_/_:App", parse_error, S), - ?line {ok, _} = eval("_:_/_:Rel", parse_error, S), - ?line {ok, _} = eval("m2:_/4", [F4], S), - ?line {ok, _} = eval("m2:_/4:Fun", [F4], S), - ?line {ok, _} = eval("\"m.?\":\"f.*\"/\"6\"", [F6], S), - ?line {ok, _} = eval("_:_/6", [F6], S), - ?line {ok, _} = eval("m1:\"f1\"/_", [F1], S), - ?line {ok, _} = eval("\"m1\":f1/_", [F1], S), - ?line {ok, _} = eval("\"m1\":Mod", [m1], S), - ?line {ok, _} = eval("\"a1\":App", [a1], S), - ?line {ok, _} = eval("\"r1\":Rel", [r1], S), - ?line {ok, _} = eval("_:_/-1", [], S), + {ok, _} = eval("\"(foo\":Mod", parse_error, S), + {ok, _} = eval("_Foo:_/_", parse_error, S), + {ok, _} = eval("\".*foo\"", parse_error, S), + {ok, _} = eval("_:_/_:Lin", parse_error, S), + {ok, _} = eval("_:_/_:Mod", parse_error, S), + {ok, _} = eval("_:_/_:App", parse_error, S), + {ok, _} = eval("_:_/_:Rel", parse_error, S), + {ok, _} = eval("m2:_/4", [F4], S), + {ok, _} = eval("m2:_/4:Fun", [F4], S), + {ok, _} = eval("\"m.?\":\"f.*\"/\"6\"", [F6], S), + {ok, _} = eval("_:_/6", [F6], S), + {ok, _} = eval("m1:\"f1\"/_", [F1], S), + {ok, _} = eval("\"m1\":f1/_", [F1], S), + {ok, _} = eval("\"m1\":Mod", [m1], S), + {ok, _} = eval("\"a1\":App", [a1], S), + {ok, _} = eval("\"r1\":Rel", [r1], S), + {ok, _} = eval("_:_/-1", [], S), ok. -loops(suite) -> []; -loops(doc) -> ["More Inter Call Graph, loops and \"unusual\" cases"]; +%% More Inter Call Graph, loops and "unusual" cases loops(Conf) when is_list(Conf) -> S0 = new(), @@ -627,51 +594,49 @@ loops(Conf) when is_list(Conf) -> LCallAt_m1 = [{E2,2},{E3,3},{E4,4}], XCallAt_m1 = [{E1,1},{E5,5}], Info1 = #xref_mod{name = m1, app_name = [a1]}, - ?line S1 = add_module(S0, Info1, DefAt_m1, X_m1, LCallAt_m1, XCallAt_m1, - XC_m1, LC_m1), + S1 = add_module(S0, Info1, DefAt_m1, X_m1, LCallAt_m1, XCallAt_m1, + XC_m1, LC_m1), - ?line S = set_up(S1), + S = set_up(S1), % Neither F6 nor F7 is included. Perhaps one should change that? - ?line {ok, _} = eval("EE | m1", [E1,E2,{F3,F3}], S), - ?line {ok, _} = eval(f("(XXL)(ELin) (EE | ~p)", [F3]), [{{D3,D3},[3]}], S), + {ok, _} = eval("EE | m1", [E1,E2,{F3,F3}], S), + {ok, _} = eval(f("(XXL)(ELin) (EE | ~p)", [F3]), [{{D3,D3},[3]}], S), - ?line {ok, _} = eval("m1->m1 | m1->m1", type_error, S), - ?line {ok, _} = eval(f("~p | ~p", [F2, F1]), type_error, S), + {ok, _} = eval("m1->m1 | m1->m1", type_error, S), + {ok, _} = eval(f("~p | ~p", [F2, F1]), type_error, S), - ?line {ok, _} = eval(f("range (closure EE | ~p)", [F1]), [F1], S), - ?line {ok, _} = eval(f("domain (closure EE || ~p)", [F3]), [F3], S), + {ok, _} = eval(f("range (closure EE | ~p)", [F1]), [F1], S), + {ok, _} = eval(f("domain (closure EE || ~p)", [F3]), [F3], S), - ?line {ok, _} = eval(f("domain (closure E || ~p)", [F3]), [F3,F4,F5], S), + {ok, _} = eval(f("domain (closure E || ~p)", [F3]), [F3,F4,F5], S), - ?line {ok, _} = eval("components E", [[F1],[F2],[F3,F4,F5]], S), - ?line {ok, _} = eval("components EE", [[F1],[F2],[F3]], S), + {ok, _} = eval("components E", [[F1],[F2],[F3,F4,F5]], S), + {ok, _} = eval("components EE", [[F1],[F2],[F3]], S), ok. -no_data(suite) -> []; -no_data(doc) -> ["Simple tests when there is no data"]; +%% Simple tests when there is no data no_data(Conf) when is_list(Conf) -> S0 = new(), - ?line S1 = set_up(S0), - ?line {ok, _} = eval("M", [], S1), - ?line {ok, _} = eval("A", [], S1), - ?line {ok, _} = eval("R", [], S1), + S1 = set_up(S0), + {ok, _} = eval("M", [], S1), + {ok, _} = eval("A", [], S1), + {ok, _} = eval("R", [], S1), ModInfo = #xref_mod{name = m, app_name = []}, - ?line S2 = add_module(S1, ModInfo, [], [], [], [], [], []), + S2 = add_module(S1, ModInfo, [], [], [], [], [], []), AppInfo = #xref_app{name = a, rel_name = []}, - ?line S3 = add_application(S2, AppInfo), + S3 = add_application(S2, AppInfo), RelInfo = #xref_rel{name = r, dir = ""}, - ?line S4 = add_release(S3, RelInfo), - ?line S5 = set_up(S4), - ?line {ok, _} = eval("M", [m], S5), - ?line {ok, _} = eval("A", [a], S5), - ?line {ok, _} = eval("R", [r], S5), + S4 = add_release(S3, RelInfo), + S5 = set_up(S4), + {ok, _} = eval("M", [m], S5), + {ok, _} = eval("A", [a], S5), + {ok, _} = eval("R", [r], S5), ok. -modules(suite) -> []; -modules(doc) -> ["Modules mode"]; +%% Modules mode modules(Conf) when is_list(Conf) -> CopyDir = ?copydir, Dir = fname(CopyDir, "rel2"), @@ -684,34 +649,33 @@ modules(Conf) when is_list(Conf) -> Xbeam = fname(EB2, "x.beam"), Ybeam = fname(EB1_1, "y.beam"), - ?line {ok, x} = compile:file(X, [debug_info, {outdir,EB2}]), - ?line {ok, y} = compile:file(Y, [debug_info, {outdir,EB1_1}]), - - ?line {ok, S0} = xref_base:new([{xref_mode, modules}]), - ?line {ok, release2, S1} = - xref_base:add_release(S0, Dir, [{name,release2}]), - ?line S = set_up(S1), - ?line {{error, _, {unavailable_analysis, undefined_function_calls}}, _} = - xref_base:analyze(S, undefined_function_calls), - ?line {{error, _, {unavailable_analysis, locals_not_used}}, _} = - xref_base:analyze(S, locals_not_used), - ?line {{error, _, {unavailable_analysis, {call, foo}}}, _} = - xref_base:analyze(S, {call, foo}), - ?line {{error, _, {unavailable_analysis, {use, foo}}}, _} = - xref_base:analyze(S, {use, foo}), - ?line analyze(undefined_functions, [{x,undef,0}], S), - ?line 5 = length(xref_base:info(S)), + {ok, x} = compile:file(X, [debug_info, {outdir,EB2}]), + {ok, y} = compile:file(Y, [debug_info, {outdir,EB1_1}]), + + {ok, S0} = xref_base:new([{xref_mode, modules}]), + {ok, release2, S1} = + xref_base:add_release(S0, Dir, [{name,release2}]), + S = set_up(S1), + {{error, _, {unavailable_analysis, undefined_function_calls}}, _} = + xref_base:analyze(S, undefined_function_calls), + {{error, _, {unavailable_analysis, locals_not_used}}, _} = + xref_base:analyze(S, locals_not_used), + {{error, _, {unavailable_analysis, {call, foo}}}, _} = + xref_base:analyze(S, {call, foo}), + {{error, _, {unavailable_analysis, {use, foo}}}, _} = + xref_base:analyze(S, {use, foo}), + analyze(undefined_functions, [{x,undef,0}], S), + 5 = length(xref_base:info(S)), %% More: all info, conversions. - ?line ok = file:delete(Xbeam), - ?line ok = file:delete(Ybeam), - ?line ok = xref_base:delete(S), + ok = file:delete(Xbeam), + ok = file:delete(Ybeam), + ok = xref_base:delete(S), ok. -add(suite) -> []; -add(doc) -> ["Add modules, applications, releases, directories"]; +%% Add modules, applications, releases, directories add(Conf) when is_list(Conf) -> CopyDir = ?copydir, Dir = fname(CopyDir, "rel2"), @@ -727,116 +691,114 @@ add(Conf) when is_list(Conf) -> Xbeam = fname(EB2, "x.beam"), Ybeam = fname(EB1_1, "y.beam"), - ?line {ok, x} = compile:file(X, [debug_info, {outdir,EB2}]), - ?line {ok, y} = compile:file(Y, [debug_info, {outdir,EB1_1}]), - - ?line case os:type() of - {unix, _} -> - ?line make_udir(UDir), - ?line make_ufile(UFile); - _ -> - true - end, - - ?line {error, _, {invalid_options,[not_an_option] }} = - xref_base:new([not_an_option]), - ?line {error, _, {invalid_options,[{verbose,not_a_value}] }} = - xref_base:new([{verbose,not_a_value}]), - ?line S = new(), - ?line {error, _, {invalid_options,[not_an_option]}} = - xref_base:set_up(S, [not_an_option]), - ?line {error, _, {invalid_options,[{builtins,true},not_an_option]}} = - xref_base:add_directory(S, foo, [{builtins,true},not_an_option]), - ?line {error, _, {invalid_options,[{builtins,not_a_value}]}} = - xref_base:add_directory(S, foo, [{builtins,not_a_value}]), - ?line {error, _, {invalid_filename,{foo,bar}}} = - xref_base:add_directory(S, {foo,bar}, []), - ?line {error, _, {invalid_options,[{builtins,true},not_an_option]}} = - xref_base:add_module(S, foo, [{builtins,true},not_an_option]), - ?line {error, _, {invalid_options,[{builtins,not_a_value}]}} = - xref_base:add_module(S, foo, [{builtins,not_a_value}]), - ?line {error, _, {invalid_filename,{foo,bar}}} = - xref_base:add_module(S, {foo,bar}, []), - ?line {error, _, {invalid_options,[{builtins,true},not_an_option]}} = - xref_base:add_application(S, foo, [{builtins,true},not_an_option]), - ?line {error, _, {invalid_options,[{builtins,not_a_value}]}} = - xref_base:add_application(S, foo, [{builtins,not_a_value}]), - ?line {error, _, {invalid_filename,{foo,bar}}} = - xref_base:add_application(S, {foo,bar}, []), - ?line {error, _, {invalid_options,[not_an_option]}} = - xref_base:add_release(S, foo, [not_an_option]), - ?line {error, _, {invalid_options,[{builtins,not_a_value}]}} = - xref_base:add_release(S, foo, [{builtins,not_a_value}]), - ?line {error, _, {invalid_filename,{foo,bar}}} = - xref_base:add_release(S, {foo,bar}, []), - ?line {ok, S1} = - xref_base:set_default(S, [{verbose,false}, {warnings, false}]), - ?line case os:type() of - {unix, _} -> - ?line {error, _, {file_error, _, _}} = - xref_base:add_release(S, UDir); - _ -> - true - end, - ?line {error, _, {file_error, _, _}} = - xref_base:add_release(S, fname(["/a/b/c/d/e/f","__foo"])), - ?line {ok, release2, S2} = - xref_base:add_release(S1, Dir, [{name,release2}]), - ?line {error, _, {module_clash, {x, _, _}}} = - xref_base:add_module(S2, Xbeam), - ?line {ok, S3} = xref_base:remove_release(S2, release2), - ?line {ok, rel2, S4} = xref_base:add_release(S3, Dir), - ?line {error, _, {release_clash, {rel2, _, _}}} = - xref_base:add_release(S4, Dir), - ?line {ok, S5} = xref_base:remove_release(S4, rel2), + {ok, x} = compile:file(X, [debug_info, {outdir,EB2}]), + {ok, y} = compile:file(Y, [debug_info, {outdir,EB1_1}]), + + case os:type() of + {unix, _} -> + make_udir(UDir), + make_ufile(UFile); + _ -> + true + end, + + {error, _, {invalid_options,[not_an_option] }} = + xref_base:new([not_an_option]), + {error, _, {invalid_options,[{verbose,not_a_value}] }} = + xref_base:new([{verbose,not_a_value}]), + S = new(), + {error, _, {invalid_options,[not_an_option]}} = + xref_base:set_up(S, [not_an_option]), + {error, _, {invalid_options,[{builtins,true},not_an_option]}} = + xref_base:add_directory(S, foo, [{builtins,true},not_an_option]), + {error, _, {invalid_options,[{builtins,not_a_value}]}} = + xref_base:add_directory(S, foo, [{builtins,not_a_value}]), + {error, _, {invalid_filename,{foo,bar}}} = + xref_base:add_directory(S, {foo,bar}, []), + {error, _, {invalid_options,[{builtins,true},not_an_option]}} = + xref_base:add_module(S, foo, [{builtins,true},not_an_option]), + {error, _, {invalid_options,[{builtins,not_a_value}]}} = + xref_base:add_module(S, foo, [{builtins,not_a_value}]), + {error, _, {invalid_filename,{foo,bar}}} = + xref_base:add_module(S, {foo,bar}, []), + {error, _, {invalid_options,[{builtins,true},not_an_option]}} = + xref_base:add_application(S, foo, [{builtins,true},not_an_option]), + {error, _, {invalid_options,[{builtins,not_a_value}]}} = + xref_base:add_application(S, foo, [{builtins,not_a_value}]), + {error, _, {invalid_filename,{foo,bar}}} = + xref_base:add_application(S, {foo,bar}, []), + {error, _, {invalid_options,[not_an_option]}} = + xref_base:add_release(S, foo, [not_an_option]), + {error, _, {invalid_options,[{builtins,not_a_value}]}} = + xref_base:add_release(S, foo, [{builtins,not_a_value}]), + {error, _, {invalid_filename,{foo,bar}}} = + xref_base:add_release(S, {foo,bar}, []), + {ok, S1} = + xref_base:set_default(S, [{verbose,false}, {warnings, false}]), + case os:type() of + {unix, _} -> + {error, _, {file_error, _, _}} = + xref_base:add_release(S, UDir); + _ -> + true + end, + {error, _, {file_error, _, _}} = + xref_base:add_release(S, fname(["/a/b/c/d/e/f","__foo"])), + {ok, release2, S2} = + xref_base:add_release(S1, Dir, [{name,release2}]), + {error, _, {module_clash, {x, _, _}}} = + xref_base:add_module(S2, Xbeam), + {ok, S3} = xref_base:remove_release(S2, release2), + {ok, rel2, S4} = xref_base:add_release(S3, Dir), + {error, _, {release_clash, {rel2, _, _}}} = + xref_base:add_release(S4, Dir), + {ok, S5} = xref_base:remove_release(S4, rel2), %% One unreadable file and one JAM file found (no verification here): - ?line {ok, [], S6} = xref_base:add_directory(S5, fname(CopyDir,"dir"), - [{recurse,true}, {warnings,true}]), - ?line case os:type() of - {unix, _} -> - ?line {error, _, {file_error, _, _}} = - xref_base:add_directory(S6, UDir); - _ -> - true - end, - ?line {ok, app1, S7} = xref_base:add_application(S6, A1_1), - ?line {error, _, {application_clash, {app1, _, _}}} = - xref_base:add_application(S7, A1_1), - ?line {ok, S8} = xref_base:remove_application(S7, app1), - ?line ok = xref_base:delete(S8), - ?line ok = file:delete(Xbeam), - ?line ok = file:delete(Ybeam), - ?line case os:type() of - {unix, _} -> - ?line ok = file:del_dir(UDir), - ?line ok = file:delete(UFile); - _ -> - true - end, + {ok, [], S6} = xref_base:add_directory(S5, fname(CopyDir,"dir"), + [{recurse,true}, {warnings,true}]), + case os:type() of + {unix, _} -> + {error, _, {file_error, _, _}} = + xref_base:add_directory(S6, UDir); + _ -> + true + end, + {ok, app1, S7} = xref_base:add_application(S6, A1_1), + {error, _, {application_clash, {app1, _, _}}} = + xref_base:add_application(S7, A1_1), + {ok, S8} = xref_base:remove_application(S7, app1), + ok = xref_base:delete(S8), + ok = file:delete(Xbeam), + ok = file:delete(Ybeam), + case os:type() of + {unix, _} -> + ok = file:del_dir(UDir), + ok = file:delete(UFile); + _ -> + true + end, ok. -default(suite) -> []; -default(doc) -> ["Default values of options"]; +%% Default values of options default(Conf) when is_list(Conf) -> S = new(), - ?line {error, _, {invalid_options,[not_an_option]}} = - xref_base:set_default(S, not_an_option, true), - ?line {error, _, {invalid_options,[{builtins, not_a_value}]}} = - xref_base:set_default(S, builtins, not_a_value), - ?line {error, _, {invalid_options,[not_an_option]}} = - xref_base:get_default(S, not_an_option), - ?line {error, _, {invalid_options,[not_an_option]}} = - xref_base:set_default(S, [not_an_option]), - - ?line D = xref_base:get_default(S), - ?line [{builtins,false},{recurse,false},{verbose,false},{warnings,true}] = - D, - - ?line ok = xref_base:delete(S), + {error, _, {invalid_options,[not_an_option]}} = + xref_base:set_default(S, not_an_option, true), + {error, _, {invalid_options,[{builtins, not_a_value}]}} = + xref_base:set_default(S, builtins, not_a_value), + {error, _, {invalid_options,[not_an_option]}} = + xref_base:get_default(S, not_an_option), + {error, _, {invalid_options,[not_an_option]}} = + xref_base:set_default(S, [not_an_option]), + + D = xref_base:get_default(S), + [{builtins,false},{recurse,false},{verbose,false},{warnings,true}] = + D, + + ok = xref_base:delete(S), ok. -info(suite) -> []; -info(doc) -> ["The info functions"]; +%% The info functions info(Conf) when is_list(Conf) -> CopyDir = ?copydir, Dir = fname(CopyDir,"rel2"), @@ -850,197 +812,195 @@ info(Conf) when is_list(Conf) -> Xbeam = fname(EB2, "x.beam"), Ybeam = fname(EB1_1, "y.beam"), - ?line {ok, x} = compile:file(X, [debug_info, {outdir,EB2}]), - ?line {ok, y} = compile:file(Y, [debug_info, {outdir,EB1_1}]), - - ?line {ok, _} = start(s), - ?line {error, _, {no_such_info, release}} = xref:info(s, release), - ?line {error, _, {no_such_info, release}} = xref:info(s, release, rel), - ?line {error, _, {no_such_module, mod}} = xref:info(s, modules, mod), - ?line {error, _, {no_such_application, app}} = - xref:info(s, applications, app), - ?line {error, _, {no_such_release, rel}} = xref:info(s, releases, rel), - ?line ok = xref:set_default(s, [{verbose,false}, {warnings, false}]), - ?line {ok, rel2} = xref:add_release(s, Dir), - ?line 9 = length(xref:info(s)), - ?line [{x,_}, {y, _}] = xref:info(s, modules), - ?line [{app1,_}, {app2, _}] = xref:info(s, applications), - ?line [{rel2,_}] = xref:info(s, releases), - ?line [] = xref:info(s, libraries), - ?line [{x,_}] = xref:info(s, modules, x), - ?line [{rel2,_}] = xref:info(s, releases, rel2), - ?line {error, _, {no_such_library, foo}} = xref:info(s, libraries, [foo]), - - ?line {ok, lib1} = - compile:file(fname(LDir,lib1),[debug_info,{outdir,LDir}]), - ?line {ok, lib2} = - compile:file(fname(LDir,lib2),[debug_info,{outdir,LDir}]), - ?line ok = xref:set_library_path(s, [LDir], [{verbose,false}]), - ?line [{lib1,_}, {lib2, _}] = xref:info(s, libraries), - ?line [{lib1,_}, {lib2, _}] = xref:info(s, libraries, [lib1,lib2]), - ?line ok = file:delete(fname(LDir, "lib1.beam")), - ?line ok = file:delete(fname(LDir, "lib2.beam")), - - ?line check_state(s), - - ?line xref:stop(s), - - ?line ok = file:delete(Xbeam), - ?line ok = file:delete(Ybeam), + {ok, x} = compile:file(X, [debug_info, {outdir,EB2}]), + {ok, y} = compile:file(Y, [debug_info, {outdir,EB1_1}]), + + {ok, _} = start(s), + {error, _, {no_such_info, release}} = xref:info(s, release), + {error, _, {no_such_info, release}} = xref:info(s, release, rel), + {error, _, {no_such_module, mod}} = xref:info(s, modules, mod), + {error, _, {no_such_application, app}} = + xref:info(s, applications, app), + {error, _, {no_such_release, rel}} = xref:info(s, releases, rel), + ok = xref:set_default(s, [{verbose,false}, {warnings, false}]), + {ok, rel2} = xref:add_release(s, Dir), + 9 = length(xref:info(s)), + [{x,_}, {y, _}] = xref:info(s, modules), + [{app1,_}, {app2, _}] = xref:info(s, applications), + [{rel2,_}] = xref:info(s, releases), + [] = xref:info(s, libraries), + [{x,_}] = xref:info(s, modules, x), + [{rel2,_}] = xref:info(s, releases, rel2), + {error, _, {no_such_library, foo}} = xref:info(s, libraries, [foo]), + + {ok, lib1} = + compile:file(fname(LDir,lib1),[debug_info,{outdir,LDir}]), + {ok, lib2} = + compile:file(fname(LDir,lib2),[debug_info,{outdir,LDir}]), + ok = xref:set_library_path(s, [LDir], [{verbose,false}]), + [{lib1,_}, {lib2, _}] = xref:info(s, libraries), + [{lib1,_}, {lib2, _}] = xref:info(s, libraries, [lib1,lib2]), + ok = file:delete(fname(LDir, "lib1.beam")), + ok = file:delete(fname(LDir, "lib2.beam")), + + check_state(s), + + xref:stop(s), + + ok = file:delete(Xbeam), + ok = file:delete(Ybeam), ok. -lib(suite) -> []; -lib(doc) -> ["Library modules"]; +%% Library modules lib(Conf) when is_list(Conf) -> CopyDir = ?copydir, Dir = fname(CopyDir,"lib_test"), UDir = fname([CopyDir,"dir","non_existent"]), - ?line {ok, lib1} = compile:file(fname(Dir,lib1),[debug_info,{outdir,Dir}]), - ?line {ok, lib2} = compile:file(fname(Dir,lib2),[debug_info,{outdir,Dir}]), - ?line {ok, lib3} = compile:file(fname(Dir,lib3),[debug_info,{outdir,Dir}]), - ?line {ok, t} = compile:file(fname(Dir,t),[debug_info,{outdir,Dir}]), - - ?line {ok, _} = start(s), - ?line ok = xref:set_default(s, [{verbose,false}, {warnings, false}]), - ?line {ok, t} = xref:add_module(s, fname(Dir,"t.beam")), - ?line {error, _, {invalid_options,[not_an_option]}} = - xref:set_library_path(s, ["foo"], [not_an_option]), - ?line {error, _, {invalid_path,otp}} = xref:set_library_path(s,otp), - ?line {error, _, {invalid_path,[""]}} = xref:set_library_path(s,[""]), - ?line {error, _, {invalid_path,[[$a | $b]]}} = - xref:set_library_path(s,[[$a | $b]]), - ?line {error, _, {invalid_path,[otp]}} = xref:set_library_path(s,[otp]), - ?line {ok, []} = xref:get_library_path(s), - ?line ok = xref:set_library_path(s, [Dir], [{verbose,false}]), - ?line {ok, UnknownFunctions} = xref:q(s, "U"), - ?line [{lib1,unknown,0}, {lib2,local,0}, - {lib2,unknown,0}, {unknown,unknown,0}] - = UnknownFunctions, - ?line {ok, [{lib2,f,0},{lib3,f,0}]} = xref:q(s, "DF"), - ?line {ok, []} = xref:q(s, "DF_1"), - ?line {ok, [{lib2,f,0}]} = xref:q(s, "DF_2"), - ?line {ok, [{lib2,f,0}]} = xref:q(s, "DF_3"), - - ?line {ok, [unknown]} = xref:q(s, "UM"), - ?line {ok, UnknownDefAt} = xref:q(s, "(Lin)U"), - ?line [{{lib1,unknown,0},0},{{lib2,local,0},0}, {{lib2,unknown,0},0}, - {{unknown,unknown,0},0}] = UnknownDefAt, - ?line {ok, LibFuns} = xref:q(s, "X * LM"), - ?line [{lib2,f,0},{lib3,f,0}] = LibFuns, - ?line {ok, LibMods} = xref:q(s, "LM"), - ?line [lib1,lib2,lib3] = LibMods, - ?line {ok, [{{lib2,f,0},0},{{lib3,f,0},0}]} = xref:q(s, "(Lin) (LM * X)"), - ?line {ok, [{{lib1,unknown,0},0}, {{lib2,f,0},0}, {{lib2,local,0},0}, - {{lib2,unknown,0},0}, {{lib3,f,0},0}]} = xref:q(s,"(Lin)LM"), - ?line {ok,[lib1,lib2,lib3,t,unknown]} = xref:q(s,"M"), - ?line {ok,[{lib2,f,0},{lib3,f,0},{t,t,0}]} = xref:q(s,"X * M"), - ?line check_state(s), - - ?line copy_file(fname(Dir, "lib1.erl"), fname(Dir,"lib1.beam")), - ?line ok = xref:set_library_path(s, [Dir]), - ?line {error, _, _} = xref:q(s, "U"), + {ok, lib1} = compile:file(fname(Dir,lib1),[debug_info,{outdir,Dir}]), + {ok, lib2} = compile:file(fname(Dir,lib2),[debug_info,{outdir,Dir}]), + {ok, lib3} = compile:file(fname(Dir,lib3),[debug_info,{outdir,Dir}]), + {ok, t} = compile:file(fname(Dir,t),[debug_info,{outdir,Dir}]), + + {ok, _} = start(s), + ok = xref:set_default(s, [{verbose,false}, {warnings, false}]), + {ok, t} = xref:add_module(s, fname(Dir,"t.beam")), + {error, _, {invalid_options,[not_an_option]}} = + xref:set_library_path(s, ["foo"], [not_an_option]), + {error, _, {invalid_path,otp}} = xref:set_library_path(s,otp), + {error, _, {invalid_path,[""]}} = xref:set_library_path(s,[""]), + {error, _, {invalid_path,[[$a | $b]]}} = + xref:set_library_path(s,[[$a | $b]]), + {error, _, {invalid_path,[otp]}} = xref:set_library_path(s,[otp]), + {ok, []} = xref:get_library_path(s), + ok = xref:set_library_path(s, [Dir], [{verbose,false}]), + {ok, UnknownFunctions} = xref:q(s, "U"), + [{lib1,unknown,0}, {lib2,local,0}, + {lib2,unknown,0}, {unknown,unknown,0}] + = UnknownFunctions, + {ok, [{lib2,f,0},{lib3,f,0}]} = xref:q(s, "DF"), + {ok, []} = xref:q(s, "DF_1"), + {ok, [{lib2,f,0}]} = xref:q(s, "DF_2"), + {ok, [{lib2,f,0}]} = xref:q(s, "DF_3"), + + {ok, [unknown]} = xref:q(s, "UM"), + {ok, UnknownDefAt} = xref:q(s, "(Lin)U"), + [{{lib1,unknown,0},0},{{lib2,local,0},0}, {{lib2,unknown,0},0}, + {{unknown,unknown,0},0}] = UnknownDefAt, + {ok, LibFuns} = xref:q(s, "X * LM"), + [{lib2,f,0},{lib3,f,0}] = LibFuns, + {ok, LibMods} = xref:q(s, "LM"), + [lib1,lib2,lib3] = LibMods, + {ok, [{{lib2,f,0},0},{{lib3,f,0},0}]} = xref:q(s, "(Lin) (LM * X)"), + {ok, [{{lib1,unknown,0},0}, {{lib2,f,0},0}, {{lib2,local,0},0}, + {{lib2,unknown,0},0}, {{lib3,f,0},0}]} = xref:q(s,"(Lin)LM"), + {ok,[lib1,lib2,lib3,t,unknown]} = xref:q(s,"M"), + {ok,[{lib2,f,0},{lib3,f,0},{t,t,0}]} = xref:q(s,"X * M"), + check_state(s), + + copy_file(fname(Dir, "lib1.erl"), fname(Dir,"lib1.beam")), + ok = xref:set_library_path(s, [Dir]), + {error, _, _} = xref:q(s, "U"), %% OTP-3921. AM and LM not always disjoint. - ?line {ok, lib1} = compile:file(fname(Dir,lib1),[debug_info,{outdir,Dir}]), - ?line {ok, lib1} = xref:add_module(s, fname(Dir,"lib1.beam")), - ?line check_state(s), - - ?line {error, _, {file_error, _, _}} = xref:set_library_path(s, [UDir]), - - ?line xref:stop(s), - ?line ok = file:delete(fname(Dir, "lib1.beam")), - ?line ok = file:delete(fname(Dir, "lib2.beam")), - ?line ok = file:delete(fname(Dir, "lib3.beam")), - ?line ok = file:delete(fname(Dir, "t.beam")), - - ?line {ok, cp} = compile:file(fname(Dir,cp),[debug_info,{outdir,Dir}]), - ?line {ok, _} = start(s), - ?line ok = xref:set_default(s, [{verbose,false}, {warnings, false}]), - ?line {ok, cp} = xref:add_module(s, fname(Dir,"cp.beam")), - ?line {ok, [{lists, sort, 1}]} = xref:q(s, "U"), - ?line ok = xref:set_library_path(s, code_path), - ?line {ok, []} = xref:q(s, "U"), - ?line check_state(s), - ?line xref:stop(s), - ?line ok = file:delete(fname(Dir, "cp.beam")), + {ok, lib1} = compile:file(fname(Dir,lib1),[debug_info,{outdir,Dir}]), + {ok, lib1} = xref:add_module(s, fname(Dir,"lib1.beam")), + check_state(s), + + {error, _, {file_error, _, _}} = xref:set_library_path(s, [UDir]), + + xref:stop(s), + ok = file:delete(fname(Dir, "lib1.beam")), + ok = file:delete(fname(Dir, "lib2.beam")), + ok = file:delete(fname(Dir, "lib3.beam")), + ok = file:delete(fname(Dir, "t.beam")), + + {ok, cp} = compile:file(fname(Dir,cp),[debug_info,{outdir,Dir}]), + {ok, _} = start(s), + ok = xref:set_default(s, [{verbose,false}, {warnings, false}]), + {ok, cp} = xref:add_module(s, fname(Dir,"cp.beam")), + {ok, [{lists, sort, 1}]} = xref:q(s, "U"), + ok = xref:set_library_path(s, code_path), + {ok, []} = xref:q(s, "U"), + check_state(s), + xref:stop(s), + ok = file:delete(fname(Dir, "cp.beam")), ok. -read(suite) -> []; -read(doc) -> ["Data read from the Abstract Code"]; +%% Data read from the Abstract Code read(Conf) when is_list(Conf) -> CopyDir = ?copydir, Dir = fname(CopyDir,"read"), File = fname(Dir, "read"), Beam = fname(Dir, "read.beam"), - ?line {ok, read} = compile:file(File, [debug_info,{outdir,Dir}]), - ?line do_read(File, abstract_v2), - ?line copy_file(fname(Dir, "read.beam.v1"), Beam), - ?line do_read(File, abstract_v1), - ?line ok = file:delete(Beam), + {ok, read} = compile:file(File, [debug_info,{outdir,Dir}]), + do_read(File, abstract_v2), + copy_file(fname(Dir, "read.beam.v1"), Beam), + do_read(File, abstract_v1), + ok = file:delete(Beam), ok. do_read(File, Version) -> - ?line {ok, _} = start(s), - ?line ok = xref:set_default(s, [{verbose,false}, {warnings, false}]), - ?line {ok, read} = xref:add_module(s, File), + {ok, _} = start(s), + ok = xref:set_default(s, [{verbose,false}, {warnings, false}]), + {ok, read} = xref:add_module(s, File), - ?line {U, OK, OKB} = read_expected(Version), + {U, OK, OKB} = read_expected(Version), %% {ok, UC} = xref:q(s, "(Lin) UC"), %% RR = to_external(converse(family_to_relation(family(UC)))), %% lists:foreach(fun(X) -> io:format("~w~n", [X]) end, RR), Unres = to_external(relation_to_family(converse(from_term(U)))), - ?line {ok, Unres} = xref:q(s, "(Lin) UC"), + {ok, Unres} = xref:q(s, "(Lin) UC"), %% {ok, EE} = xref:q(s, "(Lin) (E - UC)"), %% AA = to_external(converse(family_to_relation(family(EE)))), %% lists:foreach(fun(X) -> io:format("~w~n", [X]) end, AA), Calls = to_external(relation_to_family(converse(from_term(OK)))), - ?line {ok, Calls} = xref:q(s, "(Lin) (E - UC) "), - - ?line ok = check_state(s), - ?line {ok, UM} = xref:q(s, "UM"), - ?line true = member('$M_EXPR', UM), - - ?line {ok, X} = xref:q(s, "X"), - ?line true = member({read, module_info, 0}, X), - ?line false = member({foo, module_info, 0}, X), - ?line false = member({erlang, module_info, 0}, X), - ?line {ok, Unknowns} = xref:q(s, "U"), - ?line false = member({read, module_info, 0}, Unknowns), - ?line true = member({foo, module_info, 0}, Unknowns), - ?line true = member({erlang, module_info, 0}, Unknowns), - ?line {ok, LC} = xref:q(s, "LC"), - ?line true = member({{read,bi,0},{read,bi,0}}, LC), - - ?line ok = xref:set_library_path(s, add_erts_code_path(fname(code:lib_dir(kernel),ebin))), - ?line io:format("~p~n",[(catch xref:get_library_path(s))]), - ?line {ok, X2} = xref:q(s, "X"), - ?line ok = check_state(s), - ?line true = member({read, module_info, 0}, X2), - ?line false = member({foo, module_info, 0}, X2), - ?line true = member({erlang, module_info, 0}, X2), - ?line {ok, Unknowns2} = xref:q(s, "U"), - ?line false = member({read, module_info, 0}, Unknowns2), - ?line true = member({foo, module_info, 0}, Unknowns2), - ?line false = member({erlang, module_info, 0}, Unknowns2), - - ?line ok = xref:remove_module(s, read), - ?line {ok, read} = xref:add_module(s, File, [{builtins,true}]), + {ok, Calls} = xref:q(s, "(Lin) (E - UC) "), + + ok = check_state(s), + {ok, UM} = xref:q(s, "UM"), + true = member('$M_EXPR', UM), + + {ok, X} = xref:q(s, "X"), + true = member({read, module_info, 0}, X), + false = member({foo, module_info, 0}, X), + false = member({erlang, module_info, 0}, X), + {ok, Unknowns} = xref:q(s, "U"), + false = member({read, module_info, 0}, Unknowns), + true = member({foo, module_info, 0}, Unknowns), + true = member({erlang, module_info, 0}, Unknowns), + {ok, LC} = xref:q(s, "LC"), + true = member({{read,bi,0},{read,bi,0}}, LC), + + ok = xref:set_library_path(s, add_erts_code_path(fname(code:lib_dir(kernel),ebin))), + io:format("~p~n",[(catch xref:get_library_path(s))]), + {ok, X2} = xref:q(s, "X"), + ok = check_state(s), + true = member({read, module_info, 0}, X2), + false = member({foo, module_info, 0}, X2), + true = member({erlang, module_info, 0}, X2), + {ok, Unknowns2} = xref:q(s, "U"), + false = member({read, module_info, 0}, Unknowns2), + true = member({foo, module_info, 0}, Unknowns2), + false = member({erlang, module_info, 0}, Unknowns2), + + ok = xref:remove_module(s, read), + {ok, read} = xref:add_module(s, File, [{builtins,true}]), UnresB = to_external(relation_to_family(converse(from_term(U)))), - ?line {ok, UnresB} = xref:q(s, "(Lin) UC"), + {ok, UnresB} = xref:q(s, "(Lin) UC"), CallsB = to_external(relation_to_family(converse(from_term(OKB)))), - ?line {ok, CallsB} = xref:q(s, "(Lin) (E - UC) "), - ?line ok = check_state(s), - ?line {ok, XU} = xref:q(s, "XU"), - ?line Erl = set([{erlang,length,1},{erlang,integer,1}, - {erlang,binary_to_term,1}]), - ?line [{erlang,binary_to_term,1},{erlang,length,1}] = - to_external(intersection(set(XU), Erl)), - ?line xref:stop(s). + {ok, CallsB} = xref:q(s, "(Lin) (E - UC) "), + ok = check_state(s), + {ok, XU} = xref:q(s, "XU"), + Erl = set([{erlang,length,1},{erlang,integer,1}, + {erlang,binary_to_term,1}]), + [{erlang,binary_to_term,1},{erlang,length,1}] = + to_external(intersection(set(XU), Erl)), + xref:stop(s). %% What is expected when xref_SUITE_data/read/read.erl is added: read_expected(Version) -> @@ -1052,174 +1012,172 @@ read_expected(Version) -> FF = {read,funfuns,0}, U = [{POS1+5,{FF,{dist,'$F_EXPR',0}}}, - {POS1+8,{FF,{dist,'$F_EXPR',0}}}, - {POS2+8,{{read,funfuns,0},{expr,'$F_EXPR',1}}}, - {POS3+4,{FF,{expr,'$F_EXPR',2}}}, - {POS4+2,{FF,{modul,'$F_EXPR',1}}}, - {POS4+4,{FF,{spm,'$F_EXPR',1}}}, - {POS4+6,{FF,{spm,'$F_EXPR',1}}}, - {POS4+8,{FF,{spm,'$F_EXPR',1}}}, - {POS5+1,{FF,{'$M_EXPR','$F_EXPR',0}}}, - {POS5+2,{FF,{'$M_EXPR','$F_EXPR',0}}}, - {POS5+3,{FF,{'$M_EXPR','$F_EXPR',0}}}, - {POS6+1,{FF,{'$M_EXPR','$F_EXPR',0}}}, - {POS6+2,{FF,{'$M_EXPR','$F_EXPR',0}}}, - {POS6+4,{FF,{n,'$F_EXPR',-1}}}, - {POS7+1,{FF,{'$M_EXPR',f,1}}}, - {POS7+2,{FF,{'$M_EXPR',f,1}}}, - {POS8+2,{FF,{hej,'$F_EXPR',1}}}, - {POS8+3,{FF,{t,'$F_EXPR',1}}}, - {POS8+5,{FF,{a,'$F_EXPR',1}}}, - {POS8+7,{FF,{m,'$F_EXPR',1}}}, - {POS9+1,{FF,{'$M_EXPR',f,1}}}, - {POS9+3,{FF,{a,'$F_EXPR',1}}}, - {POS10+1,{FF,{'$M_EXPR',foo,1}}}, - {POS10+2,{FF,{'$M_EXPR','$F_EXPR',1}}}, - {POS10+3,{FF,{'$M_EXPR','$F_EXPR',2}}}, - {POS10+4,{FF,{'$M_EXPR','$F_EXPR',1}}}, - {POS10+5,{FF,{'$M_EXPR',san,1}}}, - {POS10+6,{FF,{'$M_EXPR','$F_EXPR',1}}}, - {POS11+1,{FF,{'$M_EXPR','$F_EXPR',1}}}, - {POS11+2,{FF,{'$M_EXPR','$F_EXPR',-1}}}, - {POS11+3,{FF,{m,f,-1}}}, - {POS11+4,{FF,{m,f,-1}}}, - {POS11+5,{FF,{'$M_EXPR','$F_EXPR',1}}}, - {POS11+6,{FF,{'$M_EXPR','$F_EXPR',1}}}, - {POS12+1,{FF,{'$M_EXPR','$F_EXPR',-1}}}, - {POS12+4,{FF,{'$M_EXPR','$F_EXPR',2}}}, - {POS12+7,{FF,{'$M_EXPR','$F_EXPR',-1}}}, - {POS12+8,{FF,{m4,f4,-1}}}, - {POS13+2,{FF,{debug,'$F_EXPR',0}}}, - {POS13+3,{FF,{'$M_EXPR','$F_EXPR',-1}}}, - {POS14+8,{{read,bi,0},{'$M_EXPR','$F_EXPR',1}}}], + {POS1+8,{FF,{dist,'$F_EXPR',0}}}, + {POS2+8,{{read,funfuns,0},{expr,'$F_EXPR',1}}}, + {POS3+4,{FF,{expr,'$F_EXPR',2}}}, + {POS4+2,{FF,{modul,'$F_EXPR',1}}}, + {POS4+4,{FF,{spm,'$F_EXPR',1}}}, + {POS4+6,{FF,{spm,'$F_EXPR',1}}}, + {POS4+8,{FF,{spm,'$F_EXPR',1}}}, + {POS5+1,{FF,{'$M_EXPR','$F_EXPR',0}}}, + {POS5+2,{FF,{'$M_EXPR','$F_EXPR',0}}}, + {POS5+3,{FF,{'$M_EXPR','$F_EXPR',0}}}, + {POS6+1,{FF,{'$M_EXPR','$F_EXPR',0}}}, + {POS6+2,{FF,{'$M_EXPR','$F_EXPR',0}}}, + {POS6+4,{FF,{n,'$F_EXPR',-1}}}, + {POS7+1,{FF,{'$M_EXPR',f,1}}}, + {POS7+2,{FF,{'$M_EXPR',f,1}}}, + {POS8+2,{FF,{hej,'$F_EXPR',1}}}, + {POS8+3,{FF,{t,'$F_EXPR',1}}}, + {POS8+5,{FF,{a,'$F_EXPR',1}}}, + {POS8+7,{FF,{m,'$F_EXPR',1}}}, + {POS9+1,{FF,{'$M_EXPR',f,1}}}, + {POS9+3,{FF,{a,'$F_EXPR',1}}}, + {POS10+1,{FF,{'$M_EXPR',foo,1}}}, + {POS10+2,{FF,{'$M_EXPR','$F_EXPR',1}}}, + {POS10+3,{FF,{'$M_EXPR','$F_EXPR',2}}}, + {POS10+4,{FF,{'$M_EXPR','$F_EXPR',1}}}, + {POS10+5,{FF,{'$M_EXPR',san,1}}}, + {POS10+6,{FF,{'$M_EXPR','$F_EXPR',1}}}, + {POS11+1,{FF,{'$M_EXPR','$F_EXPR',1}}}, + {POS11+2,{FF,{'$M_EXPR','$F_EXPR',-1}}}, + {POS11+3,{FF,{m,f,-1}}}, + {POS11+4,{FF,{m,f,-1}}}, + {POS11+5,{FF,{'$M_EXPR','$F_EXPR',1}}}, + {POS11+6,{FF,{'$M_EXPR','$F_EXPR',1}}}, + {POS12+1,{FF,{'$M_EXPR','$F_EXPR',-1}}}, + {POS12+4,{FF,{'$M_EXPR','$F_EXPR',2}}}, + {POS12+7,{FF,{'$M_EXPR','$F_EXPR',-1}}}, + {POS12+8,{FF,{m4,f4,-1}}}, + {POS13+2,{FF,{debug,'$F_EXPR',0}}}, + {POS13+3,{FF,{'$M_EXPR','$F_EXPR',-1}}}, + {POS14+8,{{read,bi,0},{'$M_EXPR','$F_EXPR',1}}}], O1 = [{20,{{read,lc,0},{ets,new,0}}}, - {21,{{read,lc,0},{ets,tab2list,1}}}, - {POS1+1,{FF,{erlang,spawn,1}}}, - {POS1+1,{FF,{mod17,fun17,0}}}, - {POS1+2,{FF,{erlang,spawn,1}}}, - {POS1+2,{FF,{read,local,0}}}, - {POS1+3,{FF,{erlang,spawn,1}}}, - {POS1+4,{FF,{dist,func,0}}}, - {POS1+4,{FF,{erlang,spawn,1}}}, - {POS1+5,{FF,{erlang,spawn,1}}}, - {POS1+6,{FF,{erlang,spawn_link,1}}}, - {POS1+6,{FF,{mod17,fun17,0}}}, - {POS1+7,{FF,{dist,func,0}}}, - {POS1+7,{FF,{erlang,spawn_link,1}}}, - {POS1+8,{FF,{erlang,spawn_link,1}}}, - {POS2+1,{FF,{d,f,0}}}, - {POS2+1,{FF,{dist,func,2}}}, - {POS2+1,{FF,{erlang,spawn,2}}}, - {POS2+2,{FF,{dist,func,2}}}, - {POS2+2,{FF,{erlang,spawn,2}}}, - {POS2+2,{FF,{mod42,func,0}}}, - {POS2+3,{FF,{d,f,0}}}, - {POS2+3,{FF,{dist,func,2}}}, - {POS2+3,{FF,{erlang,spawn_link,2}}}, - {POS2+4,{FF,{dist,func,2}}}, - {POS2+4,{FF,{erlang,spawn_link,2}}}, - {POS2+4,{FF,{mod42,func,0}}}, - {POS3+1,{FF,{dist,func,2}}}, - {POS3+3,{FF,{dist,func,2}}}, - {POS4+1,{FF,{erlang,spawn,4}}}, - {POS4+1,{FF,{modul,function,0}}}, - {POS4+2,{FF,{erlang,spawn,4}}}, - {POS4+3,{FF,{dist,func,2}}}, - {POS4+3,{FF,{erlang,spawn,4}}}, - {POS4+3,{FF,{spm,spf,2}}}, - {POS4+4,{FF,{dist,func,2}}}, - {POS4+4,{FF,{erlang,spawn,4}}}, - {POS4+5,{FF,{dist,func,2}}}, - {POS4+5,{FF,{erlang,spawn_link,4}}}, - {POS4+5,{FF,{spm,spf,2}}}, - {POS4+6,{FF,{dist,func,2}}}, - {POS4+6,{FF,{erlang,spawn_link,4}}}, - {POS4+7,{FF,{erlang,spawn_opt,4}}}, - {POS4+7,{FF,{read,bi,0}}}, - {POS4+7,{FF,{spm,spf,2}}}, - {POS4+8,{FF,{erlang,spawn_opt,4}}}, - {POS4+8,{FF,{read,bi,0}}}, - {POS5+1,{FF,{erlang,spawn,1}}}, - {POS5+2,{FF,{erlang,spawn,1}}}, - {POS5+3,{FF,{erlang,spawn_link,1}}}, - {POS6+1,{FF,{erlang,spawn,2}}}, - {POS6+2,{FF,{erlang,spawn_link,2}}}, - {POS7+1,{FF,{erlang,spawn,4}}}, - {POS7+2,{FF,{erlang,spawn_opt,4}}}, - {POS8+1,{FF,{hej,san,1}}}, - {POS8+4,{FF,{a,b,1}}}, - {POS8+4,{FF,{erlang,apply,2}}}, - {POS8+5,{FF,{erlang,apply,2}}}, - {POS8+6,{FF,{erlang,apply,3}}}, - {POS8+6,{FF,{m,f,1}}}, - {POS8+7,{FF,{erlang,apply,3}}}, - {POS9+1,{FF,{erlang,apply,3}}}, - {POS9+1,{FF,{read,bi,0}}}, - {POS9+2,{FF,{a,b,1}}}, - {POS9+2,{FF,{erlang,apply,2}}}, - {POS9+3,{FF,{erlang,apply,2}}}, - {POS9+4,{FF,{erlang,apply,2}}}, - {POS9+4,{FF,{erlang,not_a_function,1}}}, - {POS9+5,{FF,{erlang,apply,3}}}, - {POS9+5,{FF,{mod,func,2}}}, - {POS9+6,{FF,{erlang,apply,1}}}, - {POS9+7,{FF,{erlang,apply,2}}}, - {POS9+7,{FF,{math,add3,1}}}, - {POS9+8,{FF,{q,f,1}}}, - {POS10+4,{FF,{erlang,apply,2}}}, - {POS10+5,{FF,{mod1,fun1,1}}}, - {POS11+1,{FF,{erlang,apply,3}}}, - {POS11+2,{FF,{erlang,apply,3}}}, - {POS11+3,{FF,{erlang,apply,3}}}, - {POS11+4,{FF,{erlang,apply,3}}}, - {POS11+6,{FF,{erlang,apply,2}}}, - {POS12+1,{FF,{erlang,apply,2}}}, - {POS12+4,{FF,{erlang,apply,2}}}, - {POS12+5,{FF,{erlang,apply,3}}}, - {POS12+5,{FF,{m3,f3,2}}}, - {POS12+7,{FF,{erlang,apply,2}}}, - {POS12+8,{FF,{erlang,apply,3}}}, - {POS13+1,{FF,{dm,df,1}}}, - {POS13+6,{{read,bi,0},{foo,module_info,0}}}, - {POS13+7,{{read,bi,0},{read,module_info,0}}}, - {POS13+9,{{read,bi,0},{t,foo,1}}}, - {POS14+11,{{read,bi,0},{erlang,module_info,0}}}, - {POS14+17,{{read,bi,0},{read,bi,0}}}], + {21,{{read,lc,0},{ets,tab2list,1}}}, + {POS1+1,{FF,{erlang,spawn,1}}}, + {POS1+1,{FF,{mod17,fun17,0}}}, + {POS1+2,{FF,{erlang,spawn,1}}}, + {POS1+2,{FF,{read,local,0}}}, + {POS1+3,{FF,{erlang,spawn,1}}}, + {POS1+4,{FF,{dist,func,0}}}, + {POS1+4,{FF,{erlang,spawn,1}}}, + {POS1+5,{FF,{erlang,spawn,1}}}, + {POS1+6,{FF,{erlang,spawn_link,1}}}, + {POS1+6,{FF,{mod17,fun17,0}}}, + {POS1+7,{FF,{dist,func,0}}}, + {POS1+7,{FF,{erlang,spawn_link,1}}}, + {POS1+8,{FF,{erlang,spawn_link,1}}}, + {POS2+1,{FF,{d,f,0}}}, + {POS2+1,{FF,{dist,func,2}}}, + {POS2+1,{FF,{erlang,spawn,2}}}, + {POS2+2,{FF,{dist,func,2}}}, + {POS2+2,{FF,{erlang,spawn,2}}}, + {POS2+2,{FF,{mod42,func,0}}}, + {POS2+3,{FF,{d,f,0}}}, + {POS2+3,{FF,{dist,func,2}}}, + {POS2+3,{FF,{erlang,spawn_link,2}}}, + {POS2+4,{FF,{dist,func,2}}}, + {POS2+4,{FF,{erlang,spawn_link,2}}}, + {POS2+4,{FF,{mod42,func,0}}}, + {POS3+1,{FF,{dist,func,2}}}, + {POS3+3,{FF,{dist,func,2}}}, + {POS4+1,{FF,{erlang,spawn,4}}}, + {POS4+1,{FF,{modul,function,0}}}, + {POS4+2,{FF,{erlang,spawn,4}}}, + {POS4+3,{FF,{dist,func,2}}}, + {POS4+3,{FF,{erlang,spawn,4}}}, + {POS4+3,{FF,{spm,spf,2}}}, + {POS4+4,{FF,{dist,func,2}}}, + {POS4+4,{FF,{erlang,spawn,4}}}, + {POS4+5,{FF,{dist,func,2}}}, + {POS4+5,{FF,{erlang,spawn_link,4}}}, + {POS4+5,{FF,{spm,spf,2}}}, + {POS4+6,{FF,{dist,func,2}}}, + {POS4+6,{FF,{erlang,spawn_link,4}}}, + {POS4+7,{FF,{erlang,spawn_opt,4}}}, + {POS4+7,{FF,{read,bi,0}}}, + {POS4+7,{FF,{spm,spf,2}}}, + {POS4+8,{FF,{erlang,spawn_opt,4}}}, + {POS4+8,{FF,{read,bi,0}}}, + {POS5+1,{FF,{erlang,spawn,1}}}, + {POS5+2,{FF,{erlang,spawn,1}}}, + {POS5+3,{FF,{erlang,spawn_link,1}}}, + {POS6+1,{FF,{erlang,spawn,2}}}, + {POS6+2,{FF,{erlang,spawn_link,2}}}, + {POS7+1,{FF,{erlang,spawn,4}}}, + {POS7+2,{FF,{erlang,spawn_opt,4}}}, + {POS8+1,{FF,{hej,san,1}}}, + {POS8+4,{FF,{a,b,1}}}, + {POS8+4,{FF,{erlang,apply,2}}}, + {POS8+5,{FF,{erlang,apply,2}}}, + {POS8+6,{FF,{m,f,1}}}, + {POS9+1,{FF,{read,bi,0}}}, + {POS9+2,{FF,{a,b,1}}}, + {POS9+2,{FF,{erlang,apply,2}}}, + {POS9+3,{FF,{erlang,apply,2}}}, + {POS9+4,{FF,{erlang,apply,2}}}, + {POS9+4,{FF,{erlang,not_a_function,1}}}, + {POS9+5,{FF,{mod,func,2}}}, + {POS9+6,{FF,{erlang,apply,1}}}, + {POS9+7,{FF,{erlang,apply,2}}}, + {POS9+7,{FF,{math,add3,1}}}, + {POS9+8,{FF,{q,f,1}}}, + {POS10+4,{FF,{erlang,apply,2}}}, + {POS10+5,{FF,{mod1,fun1,1}}}, + {POS11+6,{FF,{erlang,apply,2}}}, + {POS12+1,{FF,{erlang,apply,2}}}, + {POS12+4,{FF,{erlang,apply,2}}}, + {POS12+5,{FF,{m3,f3,2}}}, + {POS12+7,{FF,{erlang,apply,2}}}, + {POS13+1,{FF,{dm,df,1}}}, + {POS13+6,{{read,bi,0},{foo,module_info,0}}}, + {POS13+7,{{read,bi,0},{read,module_info,0}}}, + {POS13+9,{{read,bi,0},{t,foo,1}}}, + {POS14+11,{{read,bi,0},{erlang,module_info,0}}}, + {POS14+17,{{read,bi,0},{read,bi,0}}}], OK = case Version of - abstract_v1 -> - [{POS8+3, {FF,{erlang,apply,3}}}, - {POS10+1, {FF,{erlang,apply,3}}}, - {POS10+6, {FF,{erlang,apply,3}}}] - ++ + abstract_v1 -> [{0,{FF,{read,'$F_EXPR',178}}}, {0,{FF,{modul,'$F_EXPR',179}}}] ++ O1; - _ -> + _ -> [{16,{FF,{read,'$F_EXPR',178}}}, {17,{FF,{modul,'$F_EXPR',179}}}] ++ O1 - end, + end, %% When builtins =:= true: OKB1 = [{POS13+1,{FF,{erts_debug,apply,4}}}, {POS13+2,{FF,{erts_debug,apply,4}}}, {POS13+3,{FF,{erts_debug,apply,4}}}, - {POS1+3, {FF,{erlang,binary_to_term,1}}}, + {POS1+3, {FF,{erlang,binary_to_term,1}}}, {POS3+1, {FF,{erlang,spawn,3}}}, {POS3+2, {FF,{erlang,spawn,3}}}, {POS3+3, {FF,{erlang,spawn_link,3}}}, {POS3+4, {FF,{erlang,spawn_link,3}}}, {POS6+4, {FF,{erlang,spawn,3}}}, + {POS8+6,{FF,{erlang,apply,3}}}, + {POS8+7,{FF,{erlang,apply,3}}}, + {POS9+1,{FF,{erlang,apply,3}}}, + {POS9+5,{FF,{erlang,apply,3}}}, + {POS11+1,{FF,{erlang,apply,3}}}, + {POS11+2,{FF,{erlang,apply,3}}}, + {POS11+3,{FF,{erlang,apply,3}}}, + {POS11+4,{FF,{erlang,apply,3}}}, + {POS12+5,{FF,{erlang,apply,3}}}, + {POS12+8,{FF,{erlang,apply,3}}}, {POS13+5, {{read,bi,0},{erlang,length,1}}}, {POS14+3, {{read,bi,0},{erlang,length,1}}}], %% Operators (OTP-8647): OKB = case Version of abstract_v1 -> - []; + [{POS8+3, {FF,{erlang,apply,3}}}, + {POS10+1, {FF,{erlang,apply,3}}}, + {POS10+6, {FF,{erlang,apply,3}}}]; _ -> [{POS13+16, {{read,bi,0},{erlang,'!',2}}}, {POS13+16, {{read,bi,0},{erlang,'-',1}}}, @@ -1229,18 +1187,17 @@ read_expected(Version) -> {POS15+2, {{read,bi,0},{erlang,'*',2}}}, {POS15+8, {{read,bi,0},{erlang,'/',2}}}] end - ++ [{POS14+19, {{read,bi,0},{erlang,'+',2}}}, - {POS14+21, {{read,bi,0},{erlang,'+',2}}}, - {POS13+16, {{read,bi,0},{erlang,'==',2}}}, - {POS14+15, {{read,bi,0},{erlang,'==',2}}}, - {POS13+5, {{read,bi,0},{erlang,'>',2}}}, - {POS14+3, {{read,bi,0},{erlang,'>',2}}}] - ++ OKB1 ++ OK, + ++ [{POS14+19, {{read,bi,0},{erlang,'+',2}}}, + {POS14+21, {{read,bi,0},{erlang,'+',2}}}, + {POS13+16, {{read,bi,0},{erlang,'==',2}}}, + {POS14+15, {{read,bi,0},{erlang,'==',2}}}, + {POS13+5, {{read,bi,0},{erlang,'>',2}}}, + {POS14+3, {{read,bi,0},{erlang,'>',2}}}] + ++ OKB1 ++ OK, {U, OK, OKB}. -read2(suite) -> []; -read2(doc) -> ["Data read from the Abstract Code (cont)"]; +%% Data read from the Abstract Code (cont) read2(Conf) when is_list(Conf) -> %% Handles the spawn_opt versions added in R9 (OTP-4180). %% Expected augmentations: try/catch, cond. @@ -1250,40 +1207,40 @@ read2(Conf) when is_list(Conf) -> MFile = fname(Dir, "read2"), Beam = fname(Dir, "read2.beam"), Test = <<"-module(read2). - -compile(export_all). - - f() -> - spawn_opt({read2,f}, % POS2 - [f()]), - spawn_opt(fun() -> foo end, [link]), - spawn_opt(f(), - {read2,f}, [{min_heap_size,1000}]), - spawn_opt(f(), - fun() -> f() end, [flopp]), - spawn_opt(f(), - read2, f, [], []); - f() -> - %% Duplicated unresolved calls are ignored: - (f())(foo,bar),(f())(foo,bar). % POS1 + -compile(export_all). + + f() -> + spawn_opt({read2,f}, % POS2 + [f()]), + spawn_opt(fun() -> foo end, [link]), + spawn_opt(f(), + {read2,f}, [{min_heap_size,1000}]), + spawn_opt(f(), + fun() -> f() end, [flopp]), + spawn_opt(f(), + read2, f, [], []); + f() -> + %% Duplicated unresolved calls are ignored: + (f())(foo,bar),(f())(foo,bar). % POS1 ">>, - ?line ok = file:write_file(File, Test), - ?line {ok, read2} = compile:file(File, [debug_info,{outdir,Dir}]), + ok = file:write_file(File, Test), + {ok, read2} = compile:file(File, [debug_info,{outdir,Dir}]), - ?line {ok, _} = xref:start(s), - ?line {ok, read2} = xref:add_module(s, MFile), - ?line {U0, OK0} = read2_expected(), + {ok, _} = xref:start(s), + {ok, read2} = xref:add_module(s, MFile), + {U0, OK0} = read2_expected(), U = to_external(relation_to_family(converse(from_term(U0)))), OK = to_external(relation_to_family(converse(from_term(OK0)))), - ?line {ok, U2} = xref:q(s, "(Lin) UC"), - ?line {ok, OK2} = xref:q(s, "(Lin) (E - UC)"), - ?line true = U =:= U2, - ?line true = OK =:= OK2, - ?line ok = check_state(s), - ?line xref:stop(s), - - ?line ok = file:delete(File), - ?line ok = file:delete(Beam), + {ok, U2} = xref:q(s, "(Lin) UC"), + {ok, OK2} = xref:q(s, "(Lin) (E - UC)"), + true = U =:= U2, + true = OK =:= OK2, + ok = check_state(s), + xref:stop(s), + + ok = file:delete(File), + ok = file:delete(Beam), ok. @@ -1293,36 +1250,34 @@ read2_expected() -> FF = {read2,f,0}, U = [{POS1,{FF,{'$M_EXPR','$F_EXPR',2}}}], OK = [{POS2,{FF,{erlang,spawn_opt,2}}}, - {POS2,{FF,FF}}, - {POS2+1,{FF,FF}}, - {POS2+2,{FF,{erlang,spawn_opt,2}}}, - {POS2+3,{FF,{erlang,spawn_opt,3}}}, - {POS2+3,{FF,FF}}, - {POS2+3,{FF,FF}}, - {POS2+5,{FF,{erlang,spawn_opt,3}}}, - {POS2+5,{FF,FF}}, - {POS2+6,{FF,FF}}, - {POS2+7,{FF,{erlang,spawn_opt,5}}}, - {POS2+7,{FF,FF}}, - {POS2+7,{FF,FF}}, - {POS1,{FF,FF}}], + {POS2,{FF,FF}}, + {POS2+1,{FF,FF}}, + {POS2+2,{FF,{erlang,spawn_opt,2}}}, + {POS2+3,{FF,{erlang,spawn_opt,3}}}, + {POS2+3,{FF,FF}}, + {POS2+3,{FF,FF}}, + {POS2+5,{FF,{erlang,spawn_opt,3}}}, + {POS2+5,{FF,FF}}, + {POS2+6,{FF,FF}}, + {POS2+7,{FF,{erlang,spawn_opt,5}}}, + {POS2+7,{FF,FF}}, + {POS2+7,{FF,FF}}, + {POS1,{FF,FF}}], {U, OK}. -remove(suite) -> []; -remove(doc) -> ["Remove modules, applications, releases"]; +%% Remove modules, applications, releases remove(Conf) when is_list(Conf) -> S = new(), - ?line {error, _, {no_such_module, mod}} = - xref_base:remove_module(S, mod), - ?line {error, _, {no_such_application, app}} = - xref_base:remove_application(S, app), - ?line {error, _, {no_such_release, rel}} = - xref_base:remove_release(S, rel), - ?line ok = xref_base:delete(S), + {error, _, {no_such_module, mod}} = + xref_base:remove_module(S, mod), + {error, _, {no_such_application, app}} = + xref_base:remove_application(S, app), + {error, _, {no_such_release, rel}} = + xref_base:remove_release(S, rel), + ok = xref_base:delete(S), ok. -replace(suite) -> []; -replace(doc) -> ["Replace modules, applications, releases"]; +%% Replace modules, applications, releases replace(Conf) when is_list(Conf) -> CopyDir = ?copydir, Dir = fname(CopyDir,"rel2"), @@ -1336,105 +1291,103 @@ replace(Conf) when is_list(Conf) -> Xbeam = fname(EB1_1, "x.beam"), Ybeam = fname(EB1_1, "y.beam"), - ?line {ok, x} = compile:file(X, [debug_info, {outdir,EB1_0}]), - ?line {ok, x} = compile:file(X, [debug_info, {outdir,EB1_1}]), - ?line {ok, y} = compile:file(Y, [debug_info, {outdir,EB1_1}]), - - ?line {ok, _} = start(s), - ?line {ok, false} = xref:set_default(s, verbose, false), - ?line {ok, true} = xref:set_default(s, warnings, false), - ?line {ok, rel2} = xref:add_release(s, Dir, []), - ?line {error, _, _} = xref:replace_application(s, app1, "no_data"), - ?line {error, _, {no_such_application, app12}} = - xref:replace_application(s, app12, A1_0, []), - ?line {error, _, {invalid_filename,{foo,bar}}} = - xref:replace_application(s, app1, {foo,bar}, []), - ?line {error, _, {invalid_options,[not_an_option]}} = - xref:replace_application(s, foo, bar, [not_an_option]), - ?line {error, _, {invalid_options,[{builtins,not_a_value}]}} = - xref:replace_application(s, foo, bar, [{builtins,not_a_value}]), - ?line {ok, app1} = - xref:replace_application(s, app1, A1_0), - ?line [{_, AppInfo}] = xref:info(s, applications, app1), - ?line {value, {release, [rel2]}} = keysearch(release, 1, AppInfo), - - ?line {error, _, {no_such_module, xx}} = - xref:replace_module(s, xx, Xbeam, []), - ?line {error, _, {invalid_options,[{builtins,true},not_an_option]}} = - xref:replace_module(s, foo, bar,[{builtins,true},not_an_option]), - ?line {error, _, {invalid_options,[{builtins,not_a_value}]}} = - xref:replace_module(s, foo, bar, [{builtins,not_a_value}]), - ?line {error, _, {invalid_filename,{foo,bar}}} = - xref:replace_module(s, x, {foo,bar}), - ?line {ok, x} = xref:replace_module(s, x, Xbeam), - ?line [{x, ModInfo}] = xref:info(s, modules, x), - ?line {value, {application, [app1]}} = - keysearch(application, 1, ModInfo), - - ?line {ok, x} = compile:file(X, [no_debug_info, {outdir,EB1_1}]), - ?line {error, _, {no_debug_info, _}} = xref:replace_module(s, x, Xbeam), - ?line {error, _, {module_mismatch, x,y}} = - xref:replace_module(s, x, Ybeam), - ?line case os:type() of - {unix, _} -> - ?line hide_file(Ybeam), - ?line {error, _, {file_error, _, _}} = - xref:replace_module(s, x, Ybeam); - _ -> - true - end, - ?line ok = xref:remove_module(s, x), - ?line {error, _, {no_debug_info, _}} = xref:add_module(s, Xbeam), + {ok, x} = compile:file(X, [debug_info, {outdir,EB1_0}]), + {ok, x} = compile:file(X, [debug_info, {outdir,EB1_1}]), + {ok, y} = compile:file(Y, [debug_info, {outdir,EB1_1}]), + + {ok, _} = start(s), + {ok, false} = xref:set_default(s, verbose, false), + {ok, true} = xref:set_default(s, warnings, false), + {ok, rel2} = xref:add_release(s, Dir, []), + {error, _, _} = xref:replace_application(s, app1, "no_data"), + {error, _, {no_such_application, app12}} = + xref:replace_application(s, app12, A1_0, []), + {error, _, {invalid_filename,{foo,bar}}} = + xref:replace_application(s, app1, {foo,bar}, []), + {error, _, {invalid_options,[not_an_option]}} = + xref:replace_application(s, foo, bar, [not_an_option]), + {error, _, {invalid_options,[{builtins,not_a_value}]}} = + xref:replace_application(s, foo, bar, [{builtins,not_a_value}]), + {ok, app1} = + xref:replace_application(s, app1, A1_0), + [{_, AppInfo}] = xref:info(s, applications, app1), + {value, {release, [rel2]}} = keysearch(release, 1, AppInfo), + + {error, _, {no_such_module, xx}} = + xref:replace_module(s, xx, Xbeam, []), + {error, _, {invalid_options,[{builtins,true},not_an_option]}} = + xref:replace_module(s, foo, bar,[{builtins,true},not_an_option]), + {error, _, {invalid_options,[{builtins,not_a_value}]}} = + xref:replace_module(s, foo, bar, [{builtins,not_a_value}]), + {error, _, {invalid_filename,{foo,bar}}} = + xref:replace_module(s, x, {foo,bar}), + {ok, x} = xref:replace_module(s, x, Xbeam), + [{x, ModInfo}] = xref:info(s, modules, x), + {value, {application, [app1]}} = + keysearch(application, 1, ModInfo), + + {ok, x} = compile:file(X, [no_debug_info, {outdir,EB1_1}]), + {error, _, {no_debug_info, _}} = xref:replace_module(s, x, Xbeam), + {error, _, {module_mismatch, x,y}} = + xref:replace_module(s, x, Ybeam), + case os:type() of + {unix, _} -> + hide_file(Ybeam), + {error, _, {file_error, _, _}} = + xref:replace_module(s, x, Ybeam); + _ -> + true + end, + ok = xref:remove_module(s, x), + {error, _, {no_debug_info, _}} = xref:add_module(s, Xbeam), %% "app2" is ignored, the old application name is kept - ?line {ok, app1} = xref:replace_application(s, app1, A2), + {ok, app1} = xref:replace_application(s, app1, A2), - ?line xref:stop(s), - ?line ok = file:delete(fname(EB1_0, "x.beam")), - ?line ok = file:delete(Xbeam), - ?line ok = file:delete(Ybeam), + xref:stop(s), + ok = file:delete(fname(EB1_0, "x.beam")), + ok = file:delete(Xbeam), + ok = file:delete(Ybeam), ok. -update(suite) -> []; -update(doc) -> ["The update() function"]; +%% The update() function update(Conf) when is_list(Conf) -> CopyDir = ?copydir, Dir = fname(CopyDir,"update"), Source = fname(Dir, "x.erl"), Beam = fname(Dir, "x.beam"), - ?line copy_file(fname(Dir, "x.erl.1"), Source), - ?line {ok, x} = compile:file(Source, [debug_info, {outdir,Dir}]), - - ?line {ok, _} = start(s), - ?line ok = xref:set_default(s, [{verbose,false}, {warnings, false}]), - ?line {ok, [x]} = xref:add_directory(s, Dir, [{builtins,true}]), - ?line {error, _, {invalid_options,[not_an_option]}} = - xref:update(s, [not_an_option]), - ?line {ok, []} = xref:update(s), - ?line {ok, [{erlang,atom_to_list,1}]} = xref:q(s, "XU"), - - ?line [{x, ModInfo}] = xref:info(s, modules, x), - ?line case keysearch(directory, 1, ModInfo) of - {value, {directory, Dir}} -> ok - end, + copy_file(fname(Dir, "x.erl.1"), Source), + {ok, x} = compile:file(Source, [debug_info, {outdir,Dir}]), + + {ok, _} = start(s), + ok = xref:set_default(s, [{verbose,false}, {warnings, false}]), + {ok, [x]} = xref:add_directory(s, Dir, [{builtins,true}]), + {error, _, {invalid_options,[not_an_option]}} = + xref:update(s, [not_an_option]), + {ok, []} = xref:update(s), + {ok, [{erlang,atom_to_list,1}]} = xref:q(s, "XU"), + + [{x, ModInfo}] = xref:info(s, modules, x), + case keysearch(directory, 1, ModInfo) of + {value, {directory, Dir}} -> ok + end, timer:sleep(2000), % make sure modification time has changed - ?line copy_file(fname(Dir, "x.erl.2"), Source), - ?line {ok, x} = compile:file(Source, [debug_info, {outdir,Dir}]), - ?line {ok, [x]} = xref:update(s, []), - ?line {ok, [{erlang,list_to_atom,1}]} = xref:q(s, "XU"), + copy_file(fname(Dir, "x.erl.2"), Source), + {ok, x} = compile:file(Source, [debug_info, {outdir,Dir}]), + {ok, [x]} = xref:update(s, []), + {ok, [{erlang,list_to_atom,1}]} = xref:q(s, "XU"), timer:sleep(2000), - ?line {ok, x} = compile:file(Source, [no_debug_info,{outdir,Dir}]), - ?line {error, _, {no_debug_info, _}} = xref:update(s), + {ok, x} = compile:file(Source, [no_debug_info,{outdir,Dir}]), + {error, _, {no_debug_info, _}} = xref:update(s), - ?line xref:stop(s), - ?line ok = file:delete(Beam), - ?line ok = file:delete(Source), + xref:stop(s), + ok = file:delete(Beam), + ok = file:delete(Source), ok. -deprecated(suite) -> []; -deprecated(doc) -> ["OTP-4695: Deprecated functions."]; +%% OTP-4695: Deprecated functions. deprecated(Conf) when is_list(Conf) -> Dir = ?copydir, File = fname(Dir, "depr.erl"), @@ -1444,79 +1397,79 @@ deprecated(Conf) when is_list(Conf) -> %% This file has been compiled to ?datadir/depr_r9c.beam %% using the R9C compiler. From R10B and onwards the linter %% checks the 'deprecated' attribute as well. -% Test = <<"-module(depr). + % Test = <<"-module(depr). -% -export([t/0,f/1,bar/2,f/2,g/3]). + % -export([t/0,f/1,bar/2,f/2,g/3]). -% -deprecated([{f,1}, % DF -% {bar,2,eventually}]). % DF_3 -% -deprecated([{f,1,next_major_release}]). % DF_2 (again) -% -deprecated([{frutt,0,next_version}]). % message... -% -deprecated([{f,2,next_major_release}, % DF_2 -% {g,3,next_version}, % DF_1 -% {ignored,10,100}]). % message... -% -deprecated([{does_not_exist,1}]). % message... + % -deprecated([{f,1}, % DF + % {bar,2,eventually}]). % DF_3 + % -deprecated([{f,1,next_major_release}]). % DF_2 (again) + % -deprecated([{frutt,0,next_version}]). % message... + % -deprecated([{f,2,next_major_release}, % DF_2 + % {g,3,next_version}, % DF_1 + % {ignored,10,100}]). % message... + % -deprecated([{does_not_exist,1}]). % message... -% -deprecated(foo). % message... + % -deprecated(foo). % message... -% t() -> -% frutt(1), -% g(1,2, 3), -% ?MODULE:f(10). + % t() -> + % frutt(1), + % g(1,2, 3), + % ?MODULE:f(10). -% f(A) -> -% ?MODULE:f(A,A). + % f(A) -> + % ?MODULE:f(A,A). -% f(X, Y) -> -% ?MODULE:g(X, Y, X). + % f(X, Y) -> + % ?MODULE:g(X, Y, X). -% g(F, G, H) -> -% ?MODULE:bar(F, {G,H}). + % g(F, G, H) -> + % ?MODULE:bar(F, {G,H}). -% bar(_, _) -> -% true. + % bar(_, _) -> + % true. -% frutt(_) -> -% frutt(). + % frutt(_) -> + % frutt(). -% frutt() -> -% true. -% ">>, + % frutt() -> + % true. + % ">>, -% ?line ok = file:write_file(File, Test), -% ?line {ok, depr_r9c} = compile:file(File, [debug_info,{outdir,Dir}]), + % ok = file:write_file(File, Test), + % {ok, depr_r9c} = compile:file(File, [debug_info,{outdir,Dir}]), - ?line {ok, _} = xref:start(s), - ?line {ok, depr_r9c} = xref:add_module(s, MFile_r9c), + {ok, _} = xref:start(s), + {ok, depr_r9c} = xref:add_module(s, MFile_r9c), M9 = depr_r9c, DF_1 = usort([{{M9,f,2},{M9,g,3}}]), DF_2 = usort(DF_1++[{{M9,f,1},{M9,f,2}},{{M9,t,0},{M9,f,1}}]), DF_3 = usort(DF_2++[{{M9,g,3},{M9,bar,2}}]), DF = usort(DF_3++[{{M9,t,0},{M9,f,1}}]), - ?line {ok,DF} = xref:analyze(s, deprecated_function_calls), - ?line {ok,DF_1} = - xref:analyze(s, {deprecated_function_calls,next_version}), - ?line {ok,DF_2} = - xref:analyze(s, {deprecated_function_calls,next_major_release}), - ?line {ok,DF_3} = - xref:analyze(s, {deprecated_function_calls,eventually}), + {ok,DF} = xref:analyze(s, deprecated_function_calls), + {ok,DF_1} = + xref:analyze(s, {deprecated_function_calls,next_version}), + {ok,DF_2} = + xref:analyze(s, {deprecated_function_calls,next_major_release}), + {ok,DF_3} = + xref:analyze(s, {deprecated_function_calls,eventually}), D = to_external(range(from_term(DF))), D_1 = to_external(range(from_term(DF_1))), D_2 = to_external(range(from_term(DF_2))), D_3 = to_external(range(from_term(DF_3))), - ?line {ok,D} = xref:analyze(s, deprecated_functions), - ?line {ok,D_1} = - xref:analyze(s, {deprecated_functions,next_version}), - ?line {ok,D_2} = - xref:analyze(s, {deprecated_functions,next_major_release}), - ?line {ok,D_3} = - xref:analyze(s, {deprecated_functions,eventually}), + {ok,D} = xref:analyze(s, deprecated_functions), + {ok,D_1} = + xref:analyze(s, {deprecated_functions,next_version}), + {ok,D_2} = + xref:analyze(s, {deprecated_functions,next_major_release}), + {ok,D_3} = + xref:analyze(s, {deprecated_functions,eventually}), - ?line ok = check_state(s), - ?line xref:stop(s), + ok = check_state(s), + xref:stop(s), Test2= <<"-module(depr). @@ -1544,11 +1497,11 @@ deprecated(Conf) when is_list(Conf) -> ?MODULE:t(). ">>, - ?line ok = file:write_file(File, Test2), - ?line {ok, depr} = compile:file(File, [debug_info,{outdir,Dir}]), + ok = file:write_file(File, Test2), + {ok, depr} = compile:file(File, [debug_info,{outdir,Dir}]), - ?line {ok, _} = xref:start(s), - ?line {ok, depr} = xref:add_module(s, MFile), + {ok, _} = xref:start(s), + {ok, depr} = xref:add_module(s, MFile), M = depr, DFa_1 = usort([{{M,f,2},{M,g,3}}]), @@ -1556,16 +1509,16 @@ deprecated(Conf) when is_list(Conf) -> DFa_3 = usort(DFa_2++[{{M,bar,2},{M,t,0}},{{M,g,3},{M,bar,2}}]), DFa = DFa_3, - ?line {ok,DFa} = xref:analyze(s, deprecated_function_calls), - ?line {ok,DFa_1} = - xref:analyze(s, {deprecated_function_calls,next_version}), - ?line {ok,DFa_2} = - xref:analyze(s, {deprecated_function_calls,next_major_release}), - ?line {ok,DFa_3} = - xref:analyze(s, {deprecated_function_calls,eventually}), + {ok,DFa} = xref:analyze(s, deprecated_function_calls), + {ok,DFa_1} = + xref:analyze(s, {deprecated_function_calls,next_version}), + {ok,DFa_2} = + xref:analyze(s, {deprecated_function_calls,next_major_release}), + {ok,DFa_3} = + xref:analyze(s, {deprecated_function_calls,eventually}), - ?line ok = check_state(s), - ?line xref:stop(s), + ok = check_state(s), + xref:stop(s), %% All of the module is deprecated. Test3= <<"-module(depr). @@ -1593,35 +1546,34 @@ deprecated(Conf) when is_list(Conf) -> ?MODULE:t(). ">>, - ?line ok = file:write_file(File, Test3), - ?line {ok, depr} = compile:file(File, [debug_info,{outdir,Dir}]), + ok = file:write_file(File, Test3), + {ok, depr} = compile:file(File, [debug_info,{outdir,Dir}]), - ?line {ok, _} = xref:start(s), - ?line {ok, depr} = xref:add_module(s, MFile), + {ok, _} = xref:start(s), + {ok, depr} = xref:add_module(s, MFile), DFb_1 = usort([{{M,f,2},{M,g,3}}]), DFb_2 = usort(DFb_1++[{{M,f,1},{M,f,2}},{{M,t,0},{M,f,1}}]), DFb_3 = DFb_2, DFb = usort(DFb_2++[{{M,bar,2},{M,t,0}},{{M,g,3},{M,bar,2}}]), - ?line {ok,DFb} = xref:analyze(s, deprecated_function_calls), - ?line {ok,DFb_1} = - xref:analyze(s, {deprecated_function_calls,next_version}), - ?line {ok,DFb_2} = - xref:analyze(s, {deprecated_function_calls,next_major_release}), - ?line {ok,DFb_3} = - xref:analyze(s, {deprecated_function_calls,eventually}), + {ok,DFb} = xref:analyze(s, deprecated_function_calls), + {ok,DFb_1} = + xref:analyze(s, {deprecated_function_calls,next_version}), + {ok,DFb_2} = + xref:analyze(s, {deprecated_function_calls,next_major_release}), + {ok,DFb_3} = + xref:analyze(s, {deprecated_function_calls,eventually}), - ?line ok = check_state(s), - ?line xref:stop(s), + ok = check_state(s), + xref:stop(s), - ?line ok = file:delete(File), - ?line ok = file:delete(Beam), + ok = file:delete(File), + ok = file:delete(Beam), ok. -trycatch(suite) -> []; -trycatch(doc) -> ["OTP-5152: try/catch, final (?) version."]; +%% OTP-5152: try/catch, final (?) version. trycatch(Conf) when is_list(Conf) -> Dir = ?copydir, File = fname(Dir, "trycatch.erl"), @@ -1645,11 +1597,11 @@ trycatch(Conf) when is_list(Conf) -> end. ">>, - ?line ok = file:write_file(File, Test), - ?line {ok, trycatch} = compile:file(File, [debug_info,{outdir,Dir}]), + ok = file:write_file(File, Test), + {ok, trycatch} = compile:file(File, [debug_info,{outdir,Dir}]), - ?line {ok, _} = xref:start(s), - ?line {ok, trycatch} = xref:add_module(s, MFile), + {ok, _} = xref:start(s), + {ok, trycatch} = xref:add_module(s, MFile), A = trycatch, {ok,[{{{A,A,0},{bar,bar,0}},[10]}, {{{A,A,0},{bar,foo,0}},[8]}, @@ -1658,18 +1610,17 @@ trycatch(Conf) when is_list(Conf) -> {{{A,A,0},{fini,shed,0}},[15]}, {{{A,A,0},{foo,bar,0}},[7]}, {{{A,A,0},{foo,foo,0}},[9]}]} = - xref:q(s, "(Lin) (E | trycatch:trycatch/0)"), + xref:q(s, "(Lin) (E | trycatch:trycatch/0)"), - ?line ok = check_state(s), - ?line xref:stop(s), + ok = check_state(s), + xref:stop(s), - ?line ok = file:delete(File), - ?line ok = file:delete(Beam), + ok = file:delete(File), + ok = file:delete(Beam), ok. -fun_mfa(suite) -> []; -fun_mfa(doc) -> ["OTP-5653: fun M:F/A."]; +%% OTP-5653: fun M:F/A. fun_mfa(Conf) when is_list(Conf) -> Dir = ?copydir, File = fname(Dir, "fun_mfa.erl"), @@ -1694,42 +1645,42 @@ fun_mfa(Conf) when is_list(Conf) -> fun t3/0(). ">>, - ?line ok = file:write_file(File, Test), + ok = file:write_file(File, Test), A = fun_mfa, - ?line {ok, A} = compile:file(File, [debug_info,{outdir,Dir}]), - ?line {ok, _} = xref:start(s), - ?line {ok, A} = xref:add_module(s, MFile, {warnings,false}), - ?line {ok, [{{{A,t,0},{'$M_EXPR','$F_EXPR',0}},[7]}, - {{{A,t,0},{A,t,0}},[6]}, - {{{A,t1,0},{'$M_EXPR','$F_EXPR',0}},[11]}, - {{{A,t1,0},{A,t,0}},[10]}, - {{{A,t2,0},{A,t,0}},[14]}, - {{{A,t3,0},{fun_mfa,t3,0}},[17]}]} = - xref:q(s, "(Lin) E"), - - ?line ok = check_state(s), - ?line xref:stop(s), - - ?line ok = file:delete(File), - ?line ok = file:delete(Beam), + {ok, A} = compile:file(File, [debug_info,{outdir,Dir}]), + {ok, _} = xref:start(s), + {ok, A} = xref:add_module(s, MFile, {warnings,false}), + {ok, [{{{A,t,0},{'$M_EXPR','$F_EXPR',0}},[7]}, + {{{A,t,0},{A,t,0}},[6]}, + {{{A,t1,0},{'$M_EXPR','$F_EXPR',0}},[11]}, + {{{A,t1,0},{A,t,0}},[10]}, + {{{A,t2,0},{A,t,0}},[14]}, + {{{A,t3,0},{fun_mfa,t3,0}},[17]}]} = + xref:q(s, "(Lin) E"), + + ok = check_state(s), + xref:stop(s), + + ok = file:delete(File), + ok = file:delete(Beam), ok. %% Same as the previous test case, except that we use a BEAM file %% that was compiled by an R14 compiler to test backward compatibility. fun_mfa_r14(Conf) when is_list(Conf) -> - Dir = ?config(data_dir, Conf), + Dir = proplists:get_value(data_dir, Conf), MFile = fname(Dir, "fun_mfa_r14"), A = fun_mfa_r14, {ok, _} = xref:start(s), {ok, A} = xref:add_module(s, MFile, {warnings,false}), {ok, [{{{A,t,0},{'$M_EXPR','$F_EXPR',0}},[7]}, - {{{A,t,0},{A,t,0}},[6]}, - {{{A,t1,0},{'$M_EXPR','$F_EXPR',0}},[11]}, - {{{A,t1,0},{A,t,0}},[10]}, - {{{A,t2,0},{A,t,0}},[14]}, - {{{A,t3,0},{A,t3,0}},[17]}]} = - xref:q(s, "(Lin) E"), + {{{A,t,0},{A,t,0}},[6]}, + {{{A,t1,0},{'$M_EXPR','$F_EXPR',0}},[11]}, + {{{A,t1,0},{A,t,0}},[10]}, + {{{A,t2,0},{A,t,0}},[14]}, + {{{A,t3,0},{A,t3,0}},[17]}]} = + xref:q(s, "(Lin) E"), ok = check_state(s), xref:stop(s), @@ -1777,17 +1728,17 @@ fun_mfa_vars(Conf) when is_list(Conf) -> {ok, _} = xref:start(s), {ok, A} = xref:add_module(s, MFile, {warnings,false}), {ok, [{{{A,t,1},{'$M_EXPR','$F_EXPR',2}},[7]}, - {{{A,t,1},{'$M_EXPR',bar,2}},[6]}, - {{{A,t1,1},{'$M_EXPR','$F_EXPR',1}},[11]}, - {{{A,t1,1},{A,'$F_EXPR',1}},[10]}, - {{{A,t2,3},{'$M_EXPR','$F_EXPR',-1}},[14]}, - {{{A,t2,3},{'$M_EXPR','$F_EXPR',1}},[15]}, - {{{A,t3,1},{'$M_EXPR','$F_EXPR',3}},[19]}, - {{{A,t3,1},{fun_mfa_vars,t,-1}},[18]}, - {{{A,t4,2},{'$M_EXPR','$F_EXPR',3}},[22,23]}, - {{{A,t5,2},{'$M_EXPR','$F_EXPR',0}},[27]}, - {{{A,t5,2},{'$M_EXPR',t,-1}},[26]}]} = - xref:q(s, "(Lin) E"), + {{{A,t,1},{'$M_EXPR',bar,2}},[6]}, + {{{A,t1,1},{'$M_EXPR','$F_EXPR',1}},[11]}, + {{{A,t1,1},{A,'$F_EXPR',1}},[10]}, + {{{A,t2,3},{'$M_EXPR','$F_EXPR',-1}},[14]}, + {{{A,t2,3},{'$M_EXPR','$F_EXPR',1}},[15]}, + {{{A,t3,1},{'$M_EXPR','$F_EXPR',3}},[19]}, + {{{A,t3,1},{fun_mfa_vars,t,-1}},[18]}, + {{{A,t4,2},{'$M_EXPR','$F_EXPR',3}},[22,23]}, + {{{A,t5,2},{'$M_EXPR','$F_EXPR',0}},[27]}, + {{{A,t5,2},{'$M_EXPR',t,-1}},[26]}]} = + xref:q(s, "(Lin) E"), ok = check_state(s), xref:stop(s), @@ -1796,8 +1747,7 @@ fun_mfa_vars(Conf) when is_list(Conf) -> ok = file:delete(Beam), ok. -qlc(suite) -> []; -qlc(doc) -> ["OTP-5195: A bug fix when using qlc:q/1,2."]; +%% OTP-5195: A bug fix when using qlc:q/1,2. qlc(Conf) when is_list(Conf) -> Dir = ?copydir, File = fname(Dir, "qlc.erl"), @@ -1822,32 +1772,31 @@ qlc(Conf) when is_list(Conf) -> ok. ">>, - ?line ok = file:write_file(File, Test), + ok = file:write_file(File, Test), A = qlc, - ?line {ok, A} = compile:file(File, [debug_info,{outdir,Dir}]), - ?line {ok, _} = xref:start(s), - ?line {ok, A} = xref:add_module(s, MFile, {warnings,false}), - ?line {ok, _} = xref:q(s, "(Lin) E"), % is can be loaded + {ok, A} = compile:file(File, [debug_info,{outdir,Dir}]), + {ok, _} = xref:start(s), + {ok, A} = xref:add_module(s, MFile, {warnings,false}), + {ok, _} = xref:q(s, "(Lin) E"), % is can be loaded - ?line ok = check_state(s), - ?line xref:stop(s), + ok = check_state(s), + xref:stop(s), - ?line ok = file:delete(File), - ?line ok = file:delete(Beam), + ok = file:delete(File), + ok = file:delete(Beam), ok. -analyze(suite) -> []; -analyze(doc) -> ["Simple analyses"]; +%% Simple analyses analyze(Conf) when is_list(Conf) -> S0 = new(), - ?line {{error, _, {invalid_options,[not_an_option]}}, _} = - xref_base:analyze(S0, undefined_function_calls, [not_an_option]), - ?line {{error, _, {invalid_query,{q}}}, _} = xref_base:q(S0,{q}), - ?line {{error, _, {unknown_analysis,foo}}, _} = xref_base:analyze(S0, foo), - ?line {{error, _, {unknown_constant,"foo:bar/-1"}}, _} = - xref_base:analyze(S0, {use,{foo,bar,-1}}), + {{error, _, {invalid_options,[not_an_option]}}, _} = + xref_base:analyze(S0, undefined_function_calls, [not_an_option]), + {{error, _, {invalid_query,{q}}}, _} = xref_base:q(S0,{q}), + {{error, _, {unknown_analysis,foo}}, _} = xref_base:analyze(S0, foo), + {{error, _, {unknown_constant,"foo:bar/-1"}}, _} = + xref_base:analyze(S0, {use,{foo,bar,-1}}), CopyDir = ?copydir, Dir = fname(CopyDir,"rel2"), @@ -1860,57 +1809,50 @@ analyze(Conf) when is_list(Conf) -> Xbeam = fname(EB2, "x.beam"), Ybeam = fname(EB1_1, "y.beam"), - ?line {ok, x} = compile:file(X, [debug_info, {outdir,EB2}]), - ?line {ok, y} = compile:file(Y, [debug_info, {outdir,EB1_1}]), - - ?line {ok, rel2, S1} = xref_base:add_release(S0, Dir, [{verbose,false}]), - ?line S = set_up(S1), - - ?line {ok, _} = - analyze(undefined_function_calls, [{{x,xx,0},{x,undef,0}}], S), - ?line {ok, _} = analyze(undefined_functions, [{x,undef,0}], S), - ?line {ok, _} = analyze(locals_not_used, [{x,l,0},{x,l1,0}], S), - ?line {ok, _} = analyze(exports_not_used, [{x,xx,0},{y,t,0}], S), - - ?line {ok, _} = - analyze(deprecated_function_calls, [{{y,t,0},{x,t,0}}], S), - ?line {ok, _} = analyze({deprecated_function_calls,next_version}, [], S), - ?line {ok, _} = - analyze({deprecated_function_calls,next_major_release}, [], S), - ?line {ok, _} = analyze({deprecated_function_calls,eventually}, - [{{y,t,0},{x,t,0}}], S), - ?line {ok, _} = analyze(deprecated_functions, [{x,t,0}], S), - ?line {ok, _} = analyze({deprecated_functions,next_version}, [], S), - ?line {ok, _} = - analyze({deprecated_functions,next_major_release}, [], S), - ?line {ok, _} = analyze({deprecated_functions,eventually}, [{x,t,0}], S), - - ?line {ok, _} = analyze({call, {x,xx,0}}, [{x,undef,0}], S), - ?line {ok, _} = - analyze({call, [{x,xx,0},{x,l,0}]}, [{x,l1,0},{x,undef,0}], S), - ?line {ok, _} = analyze({use, {x,l,0}}, [{x,l1,0}], S), - ?line {ok, _} = - analyze({use, [{x,l,0},{x,l1,0}]}, [{x,l,0},{x,l1,0}], S), - - ?line {ok, _} = analyze({module_call, x}, [x], S), - ?line {ok, _} = analyze({module_call, [x,y]}, [x], S), - ?line {ok, _} = analyze({module_use, x}, [x,y], S), - ?line {ok, _} = analyze({module_use, [x,y]}, [x,y], S), - - ?line {ok, _} = analyze({application_call, app1}, [app2], S), - ?line {ok, _} = analyze({application_call, [app1,app2]}, [app2], S), - ?line {ok, _} = analyze({application_use, app2}, [app1,app2], S), - ?line {ok, _} = analyze({application_use, [app1,app2]}, [app1,app2], S), - - ?line ok = xref_base:delete(S), - ?line ok = file:delete(Xbeam), - ?line ok = file:delete(Ybeam), + {ok, x} = compile:file(X, [debug_info, {outdir,EB2}]), + {ok, y} = compile:file(Y, [debug_info, {outdir,EB1_1}]), + + {ok, rel2, S1} = xref_base:add_release(S0, Dir, [{verbose,false}]), + S = set_up(S1), + + {ok, _} = analyze(undefined_function_calls, [{{x,xx,0},{x,undef,0}}], S), + {ok, _} = analyze(undefined_functions, [{x,undef,0}], S), + {ok, _} = analyze(locals_not_used, [{x,l,0},{x,l1,0}], S), + {ok, _} = analyze(exports_not_used, [{x,xx,0},{y,t,0}], S), + + {ok, _} = analyze(deprecated_function_calls, [{{y,t,0},{x,t,0}}], S), + {ok, _} = analyze({deprecated_function_calls,next_version}, [], S), + {ok, _} = analyze({deprecated_function_calls,next_major_release}, [], S), + {ok, _} = analyze({deprecated_function_calls,eventually}, + [{{y,t,0},{x,t,0}}], S), + {ok, _} = analyze(deprecated_functions, [{x,t,0}], S), + {ok, _} = analyze({deprecated_functions,next_version}, [], S), + {ok, _} = analyze({deprecated_functions,next_major_release}, [], S), + {ok, _} = analyze({deprecated_functions,eventually}, [{x,t,0}], S), + + {ok, _} = analyze({call, {x,xx,0}}, [{x,undef,0}], S), + {ok, _} = analyze({call, [{x,xx,0},{x,l,0}]}, [{x,l1,0},{x,undef,0}], S), + {ok, _} = analyze({use, {x,l,0}}, [{x,l1,0}], S), + {ok, _} = analyze({use, [{x,l,0},{x,l1,0}]}, [{x,l,0},{x,l1,0}], S), + + {ok, _} = analyze({module_call, x}, [x], S), + {ok, _} = analyze({module_call, [x,y]}, [x], S), + {ok, _} = analyze({module_use, x}, [x,y], S), + {ok, _} = analyze({module_use, [x,y]}, [x,y], S), + + {ok, _} = analyze({application_call, app1}, [app2], S), + {ok, _} = analyze({application_call, [app1,app2]}, [app2], S), + {ok, _} = analyze({application_use, app2}, [app1,app2], S), + {ok, _} = analyze({application_use, [app1,app2]}, [app1,app2], S), + + ok = xref_base:delete(S), + ok = file:delete(Xbeam), + ok = file:delete(Ybeam), ok. -basic(suite) -> []; -basic(doc) -> ["Use of operators"]; +%% Use of operators basic(Conf) when is_list(Conf) -> - ?line S0 = new(), + S0 = new(), F1 = {m1,f1,1}, F6 = {m1,f2,6}, % X @@ -1944,8 +1886,8 @@ basic(Conf) when is_list(Conf) -> LCallAt_m1 = [{E7,12}], XCallAt_m1 = [{E1,13},{E2,17},{E4,7}], Info1 = #xref_mod{name = m1, app_name = [a1]}, - ?line S1 = add_module(S0, Info1, DefAt_m1, X_m1, LCallAt_m1, XCallAt_m1, - XC_m1, LC_m1), + S1 = add_module(S0, Info1, DefAt_m1, X_m1, LCallAt_m1, XCallAt_m1, + XC_m1, LC_m1), D2 = {F2,7}, D3 = {F3,9}, @@ -1958,8 +1900,8 @@ basic(Conf) when is_list(Conf) -> LCallAt_m2 = [], XCallAt_m2 = [{E3,96},{E6,12},{UE1,77}], Info2 = #xref_mod{name = m2, app_name = [a2]}, - ?line S2 = add_module(S1, Info2, DefAt_m2, X_m2, LCallAt_m2, XCallAt_m2, - XC_m2, LC_m2), + S2 = add_module(S1, Info2, DefAt_m2, X_m2, LCallAt_m2, XCallAt_m2, + XC_m2, LC_m2), D4 = {F4,6}, D5 = {F5,97}, @@ -1971,186 +1913,185 @@ basic(Conf) when is_list(Conf) -> LCallAt_m3 = [{E5,19}], XCallAt_m3 = [{UE2,22}], Info3 = #xref_mod{name = m3, app_name = [a3]}, - ?line S3 = add_module(S2, Info3, DefAt_m3, X_m3, LCallAt_m3, XCallAt_m3, - XC_m3, LC_m3), + S3 = add_module(S2, Info3, DefAt_m3, X_m3, LCallAt_m3, XCallAt_m3, + XC_m3, LC_m3), Info4 = #xref_mod{name = m4, app_name = [a2]}, - ?line S4 = add_module(S3, Info4, [], [], [], [], [], []), + S4 = add_module(S3, Info4, [], [], [], [], [], []), AppInfo1 = #xref_app{name = a1, rel_name = [r1]}, - ?line S9 = add_application(S4, AppInfo1), + S9 = add_application(S4, AppInfo1), AppInfo2 = #xref_app{name = a2, rel_name = [r1]}, - ?line S10 = add_application(S9, AppInfo2), + S10 = add_application(S9, AppInfo2), AppInfo3 = #xref_app{name = a3, rel_name = [r2]}, - ?line S11 = add_application(S10, AppInfo3), + S11 = add_application(S10, AppInfo3), RelInfo1 = #xref_rel{name = r1}, - ?line S12 = add_release(S11, RelInfo1), + S12 = add_release(S11, RelInfo1), RelInfo2 = #xref_rel{name = r2}, - ?line S13 = add_release(S12, RelInfo2), + S13 = add_release(S12, RelInfo2), - ?line S = set_up(S13), + S = set_up(S13), - ?line {ok, _} = eval("[m1,m2] + m:f/1", unknown_constant, S), - ?line {ok, _} = eval("[m1, m2, m:f/1]", type_mismatch, S), + {ok, _} = eval("[m1,m2] + m:f/1", unknown_constant, S), + {ok, _} = eval("[m1, m2, m:f/1]", type_mismatch, S), - ?line {ok, _} = eval("[m1, m1->m2]", type_mismatch, S), - ?line {ok, _} = eval("components:f/1", unknown_constant, S), - ?line {ok, _} = eval("'of':f/1", unknown_constant, S), - ?line {ok, _} = eval("of:f/1", parse_error, S), - ?line {ok, _} = eval("components", unknown_constant, S), - ?line {ok, _} = eval("[components, of, closure]", parse_error, S), - ?line {ok, _} = eval("[components, 'of', closure]", unknown_constant, S), + {ok, _} = eval("[m1, m1->m2]", type_mismatch, S), + {ok, _} = eval("components:f/1", unknown_constant, S), + {ok, _} = eval("'of':f/1", unknown_constant, S), + {ok, _} = eval("of:f/1", parse_error, S), + {ok, _} = eval("components", unknown_constant, S), + {ok, _} = eval("[components, of, closure]", parse_error, S), + {ok, _} = eval("[components, 'of', closure]", unknown_constant, S), - ?line {ok, _} = eval("[a1->a2,m1->m2]", type_mismatch, S), - ?line {ok, _} = eval("a1->a2,m1->m2", parse_error, S), + {ok, _} = eval("[a1->a2,m1->m2]", type_mismatch, S), + {ok, _} = eval("a1->a2,m1->m2", parse_error, S), - ?line {ok, _} = eval("m1->a1", type_mismatch, S), - ?line {ok, _} = eval("[{m1,f1,1}] : App", parse_error, S), - ?line {ok, _} = eval("[{m1,f1,1}] : Fun", [F1], S), - ?line {ok, _} = eval("range X", type_error, S), - ?line {ok, _} = eval("domain X", type_error, S), - ?line {ok, _} = eval("range M", type_error, S), - ?line {ok, _} = eval("domain M", type_error, S), + {ok, _} = eval("m1->a1", type_mismatch, S), + {ok, _} = eval("[{m1,f1,1}] : App", parse_error, S), + {ok, _} = eval("[{m1,f1,1}] : Fun", [F1], S), + {ok, _} = eval("range X", type_error, S), + {ok, _} = eval("domain X", type_error, S), + {ok, _} = eval("range M", type_error, S), + {ok, _} = eval("domain M", type_error, S), % Misc. - ?line {ok, _} = eval("not_a_prefix_operator m1", parse_error, S), - ?line {ok, _} = eval(f("(Mod) ~p", [[F1,F6,F5]]), [m1,m3], S), - ?line {ok, _} = eval("(Lin) M - (Lin) m1", - [{F2,7},{F3,9},{F7,19},{F4,6},{F5,97},{UF2,0}], S), - ?line {ok, _} = eval(f("(Lin) M * (Lin) ~p", [[F1,F6]]), - [{F1,12},{F6,3}], S), - - ?line {ok, _} = eval(f("X * ~p", [[F1, F2, F3, F4, F5]]), [F3, F4], S), - ?line {ok, _} = eval("X", [F6,F3,F7,F4], S), - ?line {ok, _} = eval("X * AM", [F6,F3,F7,F4], S), - ?line {ok, _} = eval("X * a2", [F3,F7], S), - - ?line {ok, _} = eval("L * r1", [F1,F2], S), - ?line {ok, _} = eval("U", [UF1, UF2], S), - ?line {ok, _} = eval("U * AM", [UF1], S), - ?line {ok, _} = eval("U * UM", [UF2], S), - ?line {ok, _} = eval("XU * [m1, m2]", [F6,F3,F7,UF1], S), - ?line {ok, _} = eval("LU * [m3, m4]", [F5], S), - ?line {ok, _} = eval("UU", [F1,F2], S), - - ?line {ok, _} = eval("XC | m1", [E1,E2,E4], S), - ?line {ok, _} = eval(f("XC | ~p", [F1]), [E1,E4], S), - ?line {ok, _} = eval(f("(XXL) (Lin) (XC | ~p)", [F1]), - [{{D1,D3},[13]},{{D1,D4},[7]}],S), - ?line {ok, _} = eval(f("XC | (~p + ~p)", [F1, F2]), [E1,E4,E3,UE1], S), - ?line {ok, _} = eval(f("(XXL) (Lin) (XC | ~p)", [F1]), - [{{D1,D3},[13]},{{D1,D4},[7]}], S), - ?line {ok, _} = eval("LC | m3", [E5], S), - ?line {ok, _} = eval(f("LC | ~p", [F1]), [E7], S), - ?line {ok, _} = eval(f("LC | (~p + ~p)", [F1, F4]), [E7, E5], S), - ?line {ok, _} = eval("E | m1", [E1,E2,E4,E7], S), - ?line {ok, _} = eval(f("E | ~p", [F1]), [E1,E7,E4], S), - ?line {ok, _} = eval(f("E | (~p + ~p)", [F1, F2]), [E1,E7,E4,E3,UE1], S), - - ?line {ok, _} = eval("XC || m1", [E3,UE2], S), - ?line {ok, _} = eval(f("XC || ~p", [F6]), [E3], S), - ?line {ok, _} = eval(f("XC || (~p + ~p)", [F4, UF2]), [UE1,E4,E6], S), - ?line {ok, _} = eval("LC || m3", [E5], S), - ?line {ok, _} = eval(f("LC || ~p", [F1]), [], S), - ?line {ok, _} = eval(f("LC || ~p", [F6]), [E7], S), - ?line {ok, _} = eval(f("LC || (~p + ~p)", [F5, F6]), [E7,E5], S), - ?line {ok, _} = eval("E || m1", [E3,UE2,E7], S), - ?line {ok, _} = eval(f("E || ~p", [F6]), [E3,E7], S), - ?line {ok, _} = eval(f("E || (~p + ~p)", [F3,F4]), [E1,E4,E6], S), - - ?line {ok, _} = eval(f("~p + ~p", [F1,F2]), [F1,F2], S), - ?line {ok, _} = eval(f("~p * ~p", [m1,[F1,F6,F2]]), [F1,F6], S), - ?line {ok, _} = eval(f("~p * ~p", [F1,F2]), [], S), + {ok, _} = eval("not_a_prefix_operator m1", parse_error, S), + {ok, _} = eval(f("(Mod) ~p", [[F1,F6,F5]]), [m1,m3], S), + {ok, _} = eval("(Lin) M - (Lin) m1", + [{F2,7},{F3,9},{F7,19},{F4,6},{F5,97},{UF2,0}], S), + {ok, _} = eval(f("(Lin) M * (Lin) ~p", [[F1,F6]]), + [{F1,12},{F6,3}], S), + + {ok, _} = eval(f("X * ~p", [[F1, F2, F3, F4, F5]]), [F3, F4], S), + {ok, _} = eval("X", [F6,F3,F7,F4], S), + {ok, _} = eval("X * AM", [F6,F3,F7,F4], S), + {ok, _} = eval("X * a2", [F3,F7], S), + + {ok, _} = eval("L * r1", [F1,F2], S), + {ok, _} = eval("U", [UF1, UF2], S), + {ok, _} = eval("U * AM", [UF1], S), + {ok, _} = eval("U * UM", [UF2], S), + {ok, _} = eval("XU * [m1, m2]", [F6,F3,F7,UF1], S), + {ok, _} = eval("LU * [m3, m4]", [F5], S), + {ok, _} = eval("UU", [F1,F2], S), + + {ok, _} = eval("XC | m1", [E1,E2,E4], S), + {ok, _} = eval(f("XC | ~p", [F1]), [E1,E4], S), + {ok, _} = eval(f("(XXL) (Lin) (XC | ~p)", [F1]), + [{{D1,D3},[13]},{{D1,D4},[7]}],S), + {ok, _} = eval(f("XC | (~p + ~p)", [F1, F2]), [E1,E4,E3,UE1], S), + {ok, _} = eval(f("(XXL) (Lin) (XC | ~p)", [F1]), + [{{D1,D3},[13]},{{D1,D4},[7]}], S), + {ok, _} = eval("LC | m3", [E5], S), + {ok, _} = eval(f("LC | ~p", [F1]), [E7], S), + {ok, _} = eval(f("LC | (~p + ~p)", [F1, F4]), [E7, E5], S), + {ok, _} = eval("E | m1", [E1,E2,E4,E7], S), + {ok, _} = eval(f("E | ~p", [F1]), [E1,E7,E4], S), + {ok, _} = eval(f("E | (~p + ~p)", [F1, F2]), [E1,E7,E4,E3,UE1], S), + + {ok, _} = eval("XC || m1", [E3,UE2], S), + {ok, _} = eval(f("XC || ~p", [F6]), [E3], S), + {ok, _} = eval(f("XC || (~p + ~p)", [F4, UF2]), [UE1,E4,E6], S), + {ok, _} = eval("LC || m3", [E5], S), + {ok, _} = eval(f("LC || ~p", [F1]), [], S), + {ok, _} = eval(f("LC || ~p", [F6]), [E7], S), + {ok, _} = eval(f("LC || (~p + ~p)", [F5, F6]), [E7,E5], S), + {ok, _} = eval("E || m1", [E3,UE2,E7], S), + {ok, _} = eval(f("E || ~p", [F6]), [E3,E7], S), + {ok, _} = eval(f("E || (~p + ~p)", [F3,F4]), [E1,E4,E6], S), + + {ok, _} = eval(f("~p + ~p", [F1,F2]), [F1,F2], S), + {ok, _} = eval(f("~p * ~p", [m1,[F1,F6,F2]]), [F1,F6], S), + {ok, _} = eval(f("~p * ~p", [F1,F2]), [], S), %% range, domain - ?line {ok, _} = eval("range (E || m1)", [F6,UF1], S), - ?line {ok, _} = eval("domain (E || m1)", [F1,F2,F5], S), - ?line {ok, _} = eval(f("E | domain ~p", [[E1, {F2,F4}]]), - [E1,E7,E4,E3,UE1], S), + {ok, _} = eval("range (E || m1)", [F6,UF1], S), + {ok, _} = eval("domain (E || m1)", [F1,F2,F5], S), + {ok, _} = eval(f("E | domain ~p", [[E1, {F2,F4}]]), + [E1,E7,E4,E3,UE1], S), %% components, condensation, use, call - ?line {ok, _} = eval("(Lin) components E", type_error, S), - ?line {ok, _} = eval("components (Lin) E", type_error, S), - ?line {ok, _} = eval("components V", type_error, S), - ?line {ok, _} = eval("components E + components E", type_error, S), - - ?line {ok, _} = eval(f("range (closure E | ~p)", [[F1,F2]]), - [F6,F3,F7,F4,F5,UF1,UF2], S), - ?line {ok, _} = - eval(f("domain (closure E || ~p)", [[UF2,F7]]), [F1,F2,F6], S), - ?line {ok, _} = eval("components E", [], S), - ?line {ok, _} = eval("components (Mod) E", [[m1,m2,m3]], S), - ?line {ok, _} = eval("components closure (Mod) E", [[m1,m2,m3]], S), - ?line {ok, _} = eval("condensation (Mod) E", - [{[m1,m2,m3],[m17]}], S), - ?line {ok, _} = eval("condensation closure (Mod) E", - [{[m1,m2,m3],[m17]}], S), - ?line {ok, _} = eval("condensation closure closure closure (Mod) E", - [{[m1,m2,m3],[m17]}], S), - ?line {ok, _} = eval("weak condensation (Mod) E", - [{[m1,m2,m3],[m1,m2,m3]},{[m1,m2,m3],[m17]},{[m17],[m17]}], S), - ?line {ok, _} = eval("strict condensation (Mod) E", - [{[m1,m2,m3],[m17]}], S), - ?line {ok, _} = eval("range condensation (Mod) E", - [[m17]], S), - ?line {ok, _} = eval("domain condensation (Mod) E", - [[m1,m2,m3]], S), + {ok, _} = eval("(Lin) components E", type_error, S), + {ok, _} = eval("components (Lin) E", type_error, S), + {ok, _} = eval("components V", type_error, S), + {ok, _} = eval("components E + components E", type_error, S), + + {ok, _} = eval(f("range (closure E | ~p)", [[F1,F2]]), + [F6,F3,F7,F4,F5,UF1,UF2], S), + {ok, _} = + eval(f("domain (closure E || ~p)", [[UF2,F7]]), [F1,F2,F6], S), + {ok, _} = eval("components E", [], S), + {ok, _} = eval("components (Mod) E", [[m1,m2,m3]], S), + {ok, _} = eval("components closure (Mod) E", [[m1,m2,m3]], S), + {ok, _} = eval("condensation (Mod) E", + [{[m1,m2,m3],[m17]}], S), + {ok, _} = eval("condensation closure (Mod) E", + [{[m1,m2,m3],[m17]}], S), + {ok, _} = eval("condensation closure closure closure (Mod) E", + [{[m1,m2,m3],[m17]}], S), + {ok, _} = eval("weak condensation (Mod) E", + [{[m1,m2,m3],[m1,m2,m3]},{[m1,m2,m3],[m17]},{[m17],[m17]}], S), + {ok, _} = eval("strict condensation (Mod) E", + [{[m1,m2,m3],[m17]}], S), + {ok, _} = eval("range condensation (Mod) E", + [[m17]], S), + {ok, _} = eval("domain condensation (Mod) E", + [[m1,m2,m3]], S), %% |, ||, ||| - ?line {ok, _} = eval("(Lin) E || V", type_error, S), - ?line {ok, _} = eval("E ||| (Lin) V", type_error, S), - ?line {ok, _} = eval("E ||| m1", [E7], S), - ?line {ok, _} = eval("closure E ||| m1", [E7,{F1,UF1},{F6,UF1}], S), - ?line {ok, _} = eval("closure E ||| [m1,m2]", - [{F1,UF1},{F2,F7},{F1,F7},{F6,UF1},{F2,UF1},{F7,UF1},E7,E1,E2,E3], S), - ?line {ok, _} = eval("AE | a1", [{a1,a1},{a1,a2},{a1,a3}], S), + {ok, _} = eval("(Lin) E || V", type_error, S), + {ok, _} = eval("E ||| (Lin) V", type_error, S), + {ok, _} = eval("E ||| m1", [E7], S), + {ok, _} = eval("closure E ||| m1", [E7,{F1,UF1},{F6,UF1}], S), + {ok, _} = eval("closure E ||| [m1,m2]", + [{F1,UF1},{F2,F7},{F1,F7},{F6,UF1},{F2,UF1},{F7,UF1},E7,E1,E2,E3], S), + {ok, _} = eval("AE | a1", [{a1,a1},{a1,a2},{a1,a3}], S), %% path ('of') - ?line {ok, _} = eval("(Lin) {m1,m2} of E", type_error, S), - ?line {ok, _} = eval("{m1,m2} of (Lin) E", type_error, S), - ?line [m1,m2] = eval("{m1,m2} of {m1,m2}", S), - ?line {ok, _} = eval("{m1,m2} of m1", type_error, S), - ?line {ok, _} = eval("{a3,m1} of ME", type_mismatch, S), - ?line [m1,m1] = eval("{m1} of ME", S), - ?line [m1,m1] = eval("{m1} of closure closure ME", S), - ?line false = eval("{m17} of ME", S), - ?line [m2,m1,m2] = eval("{m2} : Mod of ME", S), - ?line [m1,m2,m17] = eval("{m1, m17} of ME", S), - ?line [m1,m2,m17] = eval("m1 -> m17 of ME", S), - ?line {ok, _} = eval("[m1->m17,m17->m1] of ME", type_error, S), - ?line case eval(f("~p of E", [{F1,F7,UF1}]), S) of - [F1,F6,F7,F4,F5,UF1] -> ok - end, - ?line [a2,a1,a2] = eval("{a2} of AE", S), + {ok, _} = eval("(Lin) {m1,m2} of E", type_error, S), + {ok, _} = eval("{m1,m2} of (Lin) E", type_error, S), + [m1,m2] = eval("{m1,m2} of {m1,m2}", S), + {ok, _} = eval("{m1,m2} of m1", type_error, S), + {ok, _} = eval("{a3,m1} of ME", type_mismatch, S), + [m1,m1] = eval("{m1} of ME", S), + [m1,m1] = eval("{m1} of closure closure ME", S), + false = eval("{m17} of ME", S), + [m2,m1,m2] = eval("{m2} : Mod of ME", S), + [m1,m2,m17] = eval("{m1, m17} of ME", S), + [m1,m2,m17] = eval("m1 -> m17 of ME", S), + {ok, _} = eval("[m1->m17,m17->m1] of ME", type_error, S), + case eval(f("~p of E", [{F1,F7,UF1}]), S) of + [F1,F6,F7,F4,F5,UF1] -> ok + end, + [a2,a1,a2] = eval("{a2} of AE", S), %% weak/strict - ?line {ok, _} = eval("weak {m1,m2}", [{m1,m1},{m1,m2},{m2,m2}], S), - ?line {ok, _} = eval("strict [{m1,m1},{m1,m2},{m2,m2}]", [{m1,m2}], S), - ?line {ok, _} = eval("range weak [{m1,m2}] : Mod", [m1,m2], S), - ?line {ok, _} = eval("domain strict [{m1,m1},{m1,m2},{m2,m2}]", [m1], S), + {ok, _} = eval("weak {m1,m2}", [{m1,m1},{m1,m2},{m2,m2}], S), + {ok, _} = eval("strict [{m1,m1},{m1,m2},{m2,m2}]", [{m1,m2}], S), + {ok, _} = eval("range weak [{m1,m2}] : Mod", [m1,m2], S), + {ok, _} = eval("domain strict [{m1,m1},{m1,m2},{m2,m2}]", [m1], S), %% #, number of - ?line {ok, _} = eval("# [{r1,r2}] : Rel", 1, S), - ?line {ok, _} = eval("# [{a3,a1}] : App", 1, S), - ?line {ok, _} = eval("# AE", 7, S), - ?line {ok, _} = eval("# ME", 8, S), - ?line {ok, _} = eval("# AE + # ME", 15, S), - ?line {ok, _} = eval("# AE * # ME", 56, S), - ?line {ok, _} = eval("# AE - # ME", -1, S), - ?line {ok, _} = eval("# E", 9, S), - ?line {ok, _} = eval("# V", 9, S), - ?line {ok, _} = eval("# (Lin) E", 9, S), - ?line {ok, _} = eval("# (ELin) E", 7, S), - ?line {ok, _} = eval("# closure E", type_error, S), - ?line {ok, _} = eval("# weak {m1,m2}", 3, S), - ?line {ok, _} = eval("#strict condensation (Mod) E", 1, S), - ?line {ok, _} = eval("#components closure (Mod) E", 1, S), - ?line {ok, _} = eval("# range strict condensation (Mod) E", 1, S), + {ok, _} = eval("# [{r1,r2}] : Rel", 1, S), + {ok, _} = eval("# [{a3,a1}] : App", 1, S), + {ok, _} = eval("# AE", 7, S), + {ok, _} = eval("# ME", 8, S), + {ok, _} = eval("# AE + # ME", 15, S), + {ok, _} = eval("# AE * # ME", 56, S), + {ok, _} = eval("# AE - # ME", -1, S), + {ok, _} = eval("# E", 9, S), + {ok, _} = eval("# V", 9, S), + {ok, _} = eval("# (Lin) E", 9, S), + {ok, _} = eval("# (ELin) E", 7, S), + {ok, _} = eval("# closure E", type_error, S), + {ok, _} = eval("# weak {m1,m2}", 3, S), + {ok, _} = eval("#strict condensation (Mod) E", 1, S), + {ok, _} = eval("#components closure (Mod) E", 1, S), + {ok, _} = eval("# range strict condensation (Mod) E", 1, S), ok. -md(suite) -> []; -md(doc) -> ["The xref:m() and xref:d() functions"]; +%% The xref:m() and xref:d() functions md(Conf) when is_list(Conf) -> CopyDir = ?copydir, Dir = fname(CopyDir,"md"), @@ -2159,63 +2100,61 @@ md(Conf) when is_list(Conf) -> Xbeam = fname(Dir, "x__x.beam"), Ybeam = fname(Dir, "y__y.beam"), - ?line {error, _, {invalid_filename,{foo,bar}}} = xref:m({foo,bar}), - ?line {error, _, {invalid_filename,{foo,bar}}} = xref:d({foo,bar}), + {error, _, {invalid_filename,{foo,bar}}} = xref:m({foo,bar}), + {error, _, {invalid_filename,{foo,bar}}} = xref:d({foo,bar}), - ?line {ok, x__x} = compile:file(X, [debug_info, {outdir,Dir}]), - ?line {ok, y__y} = compile:file(Y, [debug_info, {outdir,Dir}]), + {ok, x__x} = compile:file(X, [debug_info, {outdir,Dir}]), + {ok, y__y} = compile:file(Y, [debug_info, {outdir,Dir}]), - ?line {error, _, {no_such_module, foo_bar}} = xref:m(foo_bar), - ?line OldPath = code:get_path(), - ?line true = code:set_path([Dir | OldPath]), - ?line MInfo = xref:m(x__x), - ?line [{{x__x,t,1},{y__y,t,2}}] = info_tag(MInfo, undefined), - ?line [] = info_tag(MInfo, unused), - ?line [] = info_tag(MInfo, deprecated), - ?line DInfo = xref:d(Dir), - ?line [{{x__x,t,1},{y__y,t,2}}] = info_tag(DInfo, undefined), - ?line [{y__y,l,0},{y__y,l1,0}] = info_tag(DInfo, unused), - ?line [] = info_tag(MInfo, deprecated), + {error, _, {no_such_module, foo_bar}} = xref:m(foo_bar), + OldPath = code:get_path(), + true = code:set_path([Dir | OldPath]), + MInfo = xref:m(x__x), + [{{x__x,t,1},{y__y,t,2}}] = info_tag(MInfo, undefined), + [] = info_tag(MInfo, unused), + [] = info_tag(MInfo, deprecated), + DInfo = xref:d(Dir), + [{{x__x,t,1},{y__y,t,2}}] = info_tag(DInfo, undefined), + [{y__y,l,0},{y__y,l1,0}] = info_tag(DInfo, unused), + [] = info_tag(MInfo, deprecated), %% Switch from 'functions' mode to 'modules' mode. - ?line {ok, x__x} = compile:file(X, [no_debug_info, {outdir,Dir}]), - ?line {ok, y__y} = compile:file(Y, [no_debug_info, {outdir,Dir}]), - ?line MInfoMod = xref:m(x__x), - ?line [{y__y,t,2}] = info_tag(MInfoMod, undefined), - ?line [] = info_tag(MInfo, deprecated), - ?line DInfoMod = xref:d(Dir), - ?line [{y__y,t,2}] = info_tag(DInfoMod, undefined), - ?line [] = info_tag(MInfo, deprecated), - - ?line true = code:set_path(OldPath), - ?line ok = file:delete(Xbeam), - ?line ok = file:delete(Ybeam), + {ok, x__x} = compile:file(X, [no_debug_info, {outdir,Dir}]), + {ok, y__y} = compile:file(Y, [no_debug_info, {outdir,Dir}]), + MInfoMod = xref:m(x__x), + [{y__y,t,2}] = info_tag(MInfoMod, undefined), + [] = info_tag(MInfo, deprecated), + DInfoMod = xref:d(Dir), + [{y__y,t,2}] = info_tag(DInfoMod, undefined), + [] = info_tag(MInfo, deprecated), + + true = code:set_path(OldPath), + ok = file:delete(Xbeam), + ok = file:delete(Ybeam), ok. -q(suite) -> []; -q(doc) -> ["User queries"]; +%% User queries q(Conf) when is_list(Conf) -> - ?line S0 = new(), - ?line {ok, _} = eval("'foo", parse_error, S0), - ?line {ok, _} = eval("TT = E, TT = V", variable_reassigned, S0), - ?line {ok, _} = eval("TT = E, TTT", unknown_variable, S0), - ?line {ok, S} = eval("TT := E", [], S0), - ?line {ok, S1} = eval("TT * TT * TT", [], S), - ?line {ok, _S2} = xref_base:forget(S1, 'TT'), + S0 = new(), + {ok, _} = eval("'foo", parse_error, S0), + {ok, _} = eval("TT = E, TT = V", variable_reassigned, S0), + {ok, _} = eval("TT = E, TTT", unknown_variable, S0), + {ok, S} = eval("TT := E", [], S0), + {ok, S1} = eval("TT * TT * TT", [], S), + {ok, _S2} = xref_base:forget(S1, 'TT'), ok. -variables(suite) -> []; -variables(doc) -> ["Setting and getting values of query variables"]; +%% Setting and getting values of query variables variables(Conf) when is_list(Conf) -> - ?line Sa = new(), - ?line {{error, _, {invalid_options,[not_an_option]}}, _} = - xref_base:variables(Sa, [not_an_option]), - ?line {error, _, {not_user_variable,foo}} = xref_base:forget(Sa, foo), - ?line Sa1 = set_up(Sa), - ?line {error, _, {not_user_variable,foo}} = xref_base:forget(Sa1, foo), - ?line ok = xref_base:delete(Sa1), + Sa = new(), + {{error, _, {invalid_options,[not_an_option]}}, _} = + xref_base:variables(Sa, [not_an_option]), + {error, _, {not_user_variable,foo}} = xref_base:forget(Sa, foo), + Sa1 = set_up(Sa), + {error, _, {not_user_variable,foo}} = xref_base:forget(Sa1, foo), + ok = xref_base:delete(Sa1), - ?line S0 = new(), + S0 = new(), F1 = {m1,f1,1}, F2 = {m2,f1,2}, @@ -2234,8 +2173,8 @@ variables(Conf) when is_list(Conf) -> LCallAt_m1 = [], XCallAt_m1 = [{E1,13},{E3,17}], Info1 = #xref_mod{name = m1, app_name = [a1]}, - ?line S1 = add_module(S0, Info1, DefAt_m1, X_m1, LCallAt_m1, XCallAt_m1, - XC_m1, LC_m1), + S1 = add_module(S0, Info1, DefAt_m1, X_m1, LCallAt_m1, XCallAt_m1, + XC_m1, LC_m1), D2 = {F2,7}, DefAt_m2 = [D2], @@ -2246,66 +2185,65 @@ variables(Conf) when is_list(Conf) -> LCallAt_m2 = [], XCallAt_m2 = [{E2,96}], Info2 = #xref_mod{name = m2, app_name = [a2]}, - ?line S2 = add_module(S1, Info2, DefAt_m2, X_m2, LCallAt_m2, XCallAt_m2, - XC_m2, LC_m2), - - ?line S = set_up(S2), - - ?line eval("T1=E, T2=E*T1, T3 = T2*T2, T4=range T3, T5=T3|T4, T5", - [E1,E2,E3], S), - ?line eval("((E*E)*(E*E)) | (range ((E*E)*(E*E)))", - [E1,E2,E3], S), - ?line eval("T1=V*V,T2=T1*V,T3=V*V*V,T3", - [F1,F2,Lib], S), - ?line eval("T1=V*V, T2=V*V, T1*T2", - [F1,F2,Lib], S), - - ?line {ok, S100} = eval("T0 := E", [E1, E2, E3], S), - ?line {ok, S101} = eval("T1 := E | m1", [E1, E3], S100), - ?line {ok, S102} = eval("T2 := E | m2", [E2], S101), - ?line {{ok, [{user, ['T0', 'T1', 'T2']}]}, _} = xref_base:variables(S102), - ?line {ok, S103} = xref_base:forget(S102, 'T0'), - ?line {{ok, [{user, ['T1', 'T2']}]}, S104} = - xref_base:variables(S103, [user]), - ?line {ok, S105} = xref_base:forget(S104), - ?line {{ok, [{user, []}]}, S106} = xref_base:variables(S105), - ?line {{ok, [{predefined,_}]}, S107_0} = - xref_base:variables(S106, [predefined]), - - ?line {ok, S107_1} = - eval("TT := E, TT2 := V, TT1 := TT * TT", [E1,E2,E3], S107_0), - ?line {{ok, [{user, ['TT', 'TT1', 'TT2']}]}, _} = - xref_base:variables(S107_1), - ?line {ok, S107} = xref_base:forget(S107_1), + S2 = add_module(S1, Info2, DefAt_m2, X_m2, LCallAt_m2, XCallAt_m2, + XC_m2, LC_m2), + + S = set_up(S2), + + eval("T1=E, T2=E*T1, T3 = T2*T2, T4=range T3, T5=T3|T4, T5", + [E1,E2,E3], S), + eval("((E*E)*(E*E)) | (range ((E*E)*(E*E)))", + [E1,E2,E3], S), + eval("T1=V*V,T2=T1*V,T3=V*V*V,T3", + [F1,F2,Lib], S), + eval("T1=V*V, T2=V*V, T1*T2", + [F1,F2,Lib], S), + + {ok, S100} = eval("T0 := E", [E1, E2, E3], S), + {ok, S101} = eval("T1 := E | m1", [E1, E3], S100), + {ok, S102} = eval("T2 := E | m2", [E2], S101), + {{ok, [{user, ['T0', 'T1', 'T2']}]}, _} = xref_base:variables(S102), + {ok, S103} = xref_base:forget(S102, 'T0'), + {{ok, [{user, ['T1', 'T2']}]}, S104} = + xref_base:variables(S103, [user]), + {ok, S105} = xref_base:forget(S104), + {{ok, [{user, []}]}, S106} = xref_base:variables(S105), + {{ok, [{predefined,_}]}, S107_0} = + xref_base:variables(S106, [predefined]), + + {ok, S107_1} = + eval("TT := E, TT2 := V, TT1 := TT * TT", [E1,E2,E3], S107_0), + {{ok, [{user, ['TT', 'TT1', 'TT2']}]}, _} = + xref_base:variables(S107_1), + {ok, S107} = xref_base:forget(S107_1), CopyDir = ?copydir, - ?line Dir = fname(CopyDir,"lib_test"), + Dir = fname(CopyDir,"lib_test"), Beam = fname(Dir, "lib1.beam"), - ?line copy_file(fname(Dir, "lib1.erl"), Beam), - ?line {ok, S108} = - xref_base:set_library_path(S107, [Dir], [{verbose,false}]), - ?line {{error, _, _}, _} = xref_base:variables(S108, [{verbose,false}]), - ?line {ok, S109} = xref_base:set_library_path(S108, [], [{verbose,false}]), + copy_file(fname(Dir, "lib1.erl"), Beam), + {ok, S108} = + xref_base:set_library_path(S107, [Dir], [{verbose,false}]), + {{error, _, _}, _} = xref_base:variables(S108, [{verbose,false}]), + {ok, S109} = xref_base:set_library_path(S108, [], [{verbose,false}]), - ?line Tabs = length(ets:all()), + Tabs = length(ets:all()), - ?line {ok, S110} = eval("Eplus := closure E, TT := Eplus", - 'closure()', S109), - ?line {{ok, [{user, ['Eplus','TT']}]}, S111} = xref_base:variables(S110), - ?line {ok, S112} = xref_base:forget(S111, ['TT','Eplus']), - ?line true = Tabs =:= length(ets:all()), + {ok, S110} = eval("Eplus := closure E, TT := Eplus", + 'closure()', S109), + {{ok, [{user, ['Eplus','TT']}]}, S111} = xref_base:variables(S110), + {ok, S112} = xref_base:forget(S111, ['TT','Eplus']), + true = Tabs =:= length(ets:all()), - ?line {ok, NS0} = eval("Eplus := closure E", 'closure()', S112), - ?line {{ok, [{user, ['Eplus']}]}, NS} = xref_base:variables(NS0), - ?line ok = xref_base:delete(NS), - ?line true = Tabs =:= length(ets:all()), + {ok, NS0} = eval("Eplus := closure E", 'closure()', S112), + {{ok, [{user, ['Eplus']}]}, NS} = xref_base:variables(NS0), + ok = xref_base:delete(NS), + true = Tabs =:= length(ets:all()), - ?line ok = file:delete(Beam), + ok = file:delete(Beam), ok. -unused_locals(suite) -> []; -unused_locals(doc) -> ["OTP-5071. Too many unused functions."]; +%% OTP-5071. Too many unused functions. unused_locals(Conf) when is_list(Conf) -> Dir = ?copydir, @@ -2326,8 +2264,8 @@ unused_locals(Conf) when is_list(Conf) -> start(M, F, A) -> spawn(M, F, A). ">>, - ?line ok = file:write_file(File1, Test1), - ?line {ok, a} = compile:file(File1, [debug_info,{outdir,Dir}]), + ok = file:write_file(File1, Test1), + {ok, a} = compile:file(File1, [debug_info,{outdir,Dir}]), File2 = fname(Dir, "b.erl"), MFile2 = fname(Dir, "b"), @@ -2343,123 +2281,109 @@ unused_locals(Conf) when is_list(Conf) -> apply(a, g, [X, Y]). ">>, - ?line ok = file:write_file(File2, Test2), - ?line {ok, b} = compile:file(File2, [debug_info,{outdir,Dir}]), + ok = file:write_file(File2, Test2), + {ok, b} = compile:file(File2, [debug_info,{outdir,Dir}]), - ?line {ok, _} = xref:start(s), - ?line {ok, a} = xref:add_module(s, MFile1), - ?line {ok, b} = xref:add_module(s, MFile2), - ?line {ok, []} = xref:analyse(s, locals_not_used), - ?line ok = check_state(s), - ?line xref:stop(s), + {ok, _} = xref:start(s), + {ok, a} = xref:add_module(s, MFile1), + {ok, b} = xref:add_module(s, MFile2), + {ok, []} = xref:analyse(s, locals_not_used), + ok = check_state(s), + xref:stop(s), - ?line ok = file:delete(File1), - ?line ok = file:delete(Beam1), - ?line ok = file:delete(File2), - ?line ok = file:delete(Beam2), + ok = file:delete(File1), + ok = file:delete(Beam1), + ok = file:delete(File2), + ok = file:delete(Beam2), ok. -format_error(suite) -> []; -format_error(doc) -> ["Format error messages"]; +%% Format error messages format_error(Conf) when is_list(Conf) -> - ?line {ok, _Pid} = start(s), - ?line ok = xref:set_default(s, [{verbose,false}, {warnings, false}]), + {ok, _Pid} = start(s), + ok = xref:set_default(s, [{verbose,false}, {warnings, false}]), %% Parse error messages. - ?line "Invalid regular expression \"add(\"" ++ _ = - fstring(xref:q(s,'"add("')), - ?line 'Invalid operator foo\n' = - fatom(xref:q(s,'foo E')), - ?line 'Invalid wildcard variable \'_Var\' (only \'_\' is allowed)\n' - = fatom(xref:q(s,"module:function/_Var")), - ?line 'Missing type of regular expression ".*"\n' - = fatom(xref:q(s,'".*"')), - ?line 'Type does not match structure of constant: \'M\' : Fun\n' - = fatom(xref:q(s,"'M' : Fun")), - ?line 'Type does not match structure of constant: ".*" : Fun\n' - = fatom(xref:q(s,'".*" : Fun')), - ?line 'Type does not match structure of constant: [m:f/1, m1:f2/3] : App\n' - = fatom(xref:q(s,"[m:f/1,m1:f2/3] : App")), - ?line 'Parse error on line 1: syntax error before: \'-\'\n' = - fatom(xref:q(s,"E + -")), - ?line "Parse error on line 1: unterminated atom starting with 'foo'\n" - = flatten(xref:format_error(xref:q(s,"'foo"))), - ?line 'Parse error at end of string: syntax error before: \n' = - fatom(xref:q(s,"E +")), - ?line 'Parse error on line 1: syntax error before: \'Lin\'\n' = - fatom(xref:q(s,"Lin")), + "Invalid regular expression \"add(\"" ++ _ = fstring(xref:q(s,'"add("')), + 'Invalid operator foo\n' = fatom(xref:q(s,'foo E')), + 'Invalid wildcard variable \'_Var\' (only \'_\' is allowed)\n' + = fatom(xref:q(s,"module:function/_Var")), + 'Missing type of regular expression ".*"\n' + = fatom(xref:q(s,'".*"')), + 'Type does not match structure of constant: \'M\' : Fun\n' + = fatom(xref:q(s,"'M' : Fun")), + 'Type does not match structure of constant: ".*" : Fun\n' + = fatom(xref:q(s,'".*" : Fun')), + 'Type does not match structure of constant: [m:f/1, m1:f2/3] : App\n' + = fatom(xref:q(s,"[m:f/1,m1:f2/3] : App")), + 'Parse error on line 1: syntax error before: \'-\'\n' + = fatom(xref:q(s,"E + -")), + "Parse error on line 1: unterminated atom starting with 'foo'\n" + = flatten(xref:format_error(xref:q(s,"'foo"))), + 'Parse error at end of string: syntax error before: \n' + = fatom(xref:q(s,"E +")), + 'Parse error on line 1: syntax error before: \'Lin\'\n' + = fatom(xref:q(s,"Lin")), %% Other messages - ?line 'Variable \'QQ\' used before set\n' = - fatom(xref:q(s,"QQ")), - ?line 'Unknown constant a\n' = - fatom(xref:q(s,"{a} of E")), + 'Variable \'QQ\' used before set\n' = fatom(xref:q(s,"QQ")), + 'Unknown constant a\n' = fatom(xref:q(s,"{a} of E")), %% Testing xref_parser:t2s/1. - ?line 'Variable assigned more than once: E := E + E\n' = - fatom(xref:q(s,"E:=E + E")), - ?line 'Variable assigned more than once: E = E + E\n' = - fatom(xref:q(s,"E=E + E")), - ?line "Operator applied to argument(s) of different or invalid type(s): " - "E + V * V\n" = - flatten(xref:format_error(xref:q(s,"E + (V * V)"))), - ?line {error,xref_compiler,{type_error,"(V + V) * E"}} = - xref:q(s,"(V + V) * E"), - ?line "Type does not match structure of constant: [m:f/3 -> g:h/17] : " - "App\n" = - flatten(xref:format_error(xref:q(s,"[{{m,f,3},{g,h,17}}] : App"))), - ?line 'Type does not match structure of constant: [m -> f, g -> h] : Fun\n' - = fatom(xref:q(s,"[{m,f},g->h] : Fun")), - ?line 'Type does not match structure of constant: {m, n, o} : Fun\n' = - fatom(xref:q(s,"{m,n,o} : Fun")), - ?line {error,xref_compiler,{type_error,"range (Lin) V"}} = - xref:q(s,"range ((Lin) V)"), - ?line {error,xref_compiler,{type_error,"condensation range E"}} = - xref:q(s,"condensation (range E)"), - ?line {error,xref_compiler,{type_error,"condensation (# E + # V)"}} = - xref:q(s,"condensation (# E + # V)"), - ?line {error,xref_compiler,{type_error,"range (# E + # E)"}} = - xref:q(s,"range (#E + #E)"), - ?line {error,xref_compiler,{type_error,"range (# E)"}} = - xref:q(s,"range #E"), % Hm... - ?line {error,xref_compiler,{type_error,"E + # E"}} = - xref:q(s,"E + #E + #E"), % Hm... - ?line {error,xref_compiler,{type_error,"V * E || V | V"}} = - xref:q(s,"V * (E || V) | V"), - ?line {error,xref_compiler,{type_error,"E || (E | V)"}} = - xref:q(s,"V * E || (E | V)"), - ?line {error,xref_compiler,{type_error,"E * \"m\" : Mod"}} = - xref:q(s,'E * "m" : Mod'), - ?line {error,xref_compiler,{type_error,"E * (\"m\":f/_ + m:\"f\"/3)"}} = - xref:q(s,'E * ("m":f/_ + m:"f"/3)'), - - ?line xref:stop(s), + 'Variable assigned more than once: E := E + E\n' = fatom(xref:q(s,"E:=E + E")), + 'Variable assigned more than once: E = E + E\n' = fatom(xref:q(s,"E=E + E")), + "Operator applied to argument(s) of different or invalid type(s): " + "E + V * V\n" = flatten(xref:format_error(xref:q(s,"E + (V * V)"))), + {error,xref_compiler,{type_error,"(V + V) * E"}} = xref:q(s,"(V + V) * E"), + "Type does not match structure of constant: [m:f/3 -> g:h/17] : " + "App\n" = flatten(xref:format_error(xref:q(s,"[{{m,f,3},{g,h,17}}] : App"))), + 'Type does not match structure of constant: [m -> f, g -> h] : Fun\n' + = fatom(xref:q(s,"[{m,f},g->h] : Fun")), + 'Type does not match structure of constant: {m, n, o} : Fun\n' = + fatom(xref:q(s,"{m,n,o} : Fun")), + {error,xref_compiler,{type_error,"range (Lin) V"}} = + xref:q(s,"range ((Lin) V)"), + {error,xref_compiler,{type_error,"condensation range E"}} = + xref:q(s,"condensation (range E)"), + {error,xref_compiler,{type_error,"condensation (# E + # V)"}} = + xref:q(s,"condensation (# E + # V)"), + {error,xref_compiler,{type_error,"range (# E + # E)"}} = + xref:q(s,"range (#E + #E)"), + {error,xref_compiler,{type_error,"range (# E)"}} = + xref:q(s,"range #E"), % Hm... + {error,xref_compiler,{type_error,"E + # E"}} = + xref:q(s,"E + #E + #E"), % Hm... + {error,xref_compiler,{type_error,"V * E || V | V"}} = + xref:q(s,"V * (E || V) | V"), + {error,xref_compiler,{type_error,"E || (E | V)"}} = + xref:q(s,"V * E || (E | V)"), + {error,xref_compiler,{type_error,"E * \"m\" : Mod"}} = + xref:q(s,'E * "m" : Mod'), + {error,xref_compiler,{type_error,"E * (\"m\":f/_ + m:\"f\"/3)"}} = + xref:q(s,'E * ("m":f/_ + m:"f"/3)'), + + xref:stop(s), ok. -otp_7423(suite) -> []; -otp_7423(doc) -> ["OTP-7423. Xref scanner bug."]; +%% OTP-7423. Xref scanner bug. otp_7423(Conf) when is_list(Conf) -> - ?line {ok, _Pid} = start(s), + {ok, _Pid} = start(s), S = "E | [compiler] : App || [{erlang, size, 1}] : Fun", - ?line {error,xref_compiler,{unknown_constant,"compiler"}} = xref:q(s,S), - ?line xref:stop(s), + {error,xref_compiler,{unknown_constant,"compiler"}} = xref:q(s,S), + xref:stop(s), ok. -otp_7831(suite) -> []; -otp_7831(doc) -> ["OTP-7831. Allow anonymous Xref processes."]; +%% OTP-7831. Allow anonymous Xref processes. otp_7831(Conf) when is_list(Conf) -> - ?line {ok, Pid1} = xref:start([]), - ?line xref:stop(Pid1), - ?line {ok, Pid2} = xref:start([{xref_mode, modules}]), - ?line xref:stop(Pid2), + {ok, Pid1} = xref:start([]), + xref:stop(Pid1), + {ok, Pid2} = xref:start([{xref_mode, modules}]), + xref:stop(Pid2), ok. -otp_10192(suite) -> []; -otp_10192(doc) -> - ["OTP-10192. Allow filenames with character codes greater than 126."]; +%% OTP-10192. Allow filenames with character codes greater than 126. otp_10192(Conf) when is_list(Conf) -> PrivDir = ?privdir, {ok, _Pid} = xref:start(s), @@ -2483,59 +2407,59 @@ fname(Dir, Basename) -> filename:join(Dir, Basename). new() -> - ?line {ok, S} = xref_base:new(), + {ok, S} = xref_base:new(), S. set_up(S) -> - ?line {ok, S1} = xref_base:set_up(S, [{verbose, false}]), + {ok, S1} = xref_base:set_up(S, [{verbose, false}]), S1. eval(Query, E, S) -> ?format("------------------------------~n", []), ?format("Evaluating ~p~n", [Query]), - ?line {Answer, NewState} = xref_base:q(S, Query, [{verbose, false}]), + {Answer, NewState} = xref_base:q(S, Query, [{verbose, false}]), {Reply, Expected} = - case Answer of - {ok, R} when is_list(E) -> - {unsetify(R), sort(E)}; - {ok, R} -> - {unsetify(R), E}; - {error, _Module, Reason} -> - {element(1, Reason), E} - end, + case Answer of + {ok, R} when is_list(E) -> + {unsetify(R), sort(E)}; + {ok, R} -> + {unsetify(R), E}; + {error, _Module, Reason} -> + {element(1, Reason), E} + end, if - Reply =:= Expected -> - ?format("As expected, got ~n~p~n", [Expected]), - {ok, NewState}; - true -> - ?format("Expected ~n~p~nbut got ~n~p~n", [Expected, Reply]), - not_ok + Reply =:= Expected -> + ?format("As expected, got ~n~p~n", [Expected]), + {ok, NewState}; + true -> + ?format("Expected ~n~p~nbut got ~n~p~n", [Expected, Reply]), + not_ok end. analyze(Query, E, S) -> ?format("------------------------------~n", []), ?format("Evaluating ~p~n", [Query]), - ?line {{ok, L}, NewState} = - xref_base:analyze(S, Query, [{verbose, false}]), + {{ok, L}, NewState} = + xref_base:analyze(S, Query, [{verbose, false}]), case {unsetify(L), sort(E)} of - {X,X} -> - ?format("As was expected, got ~n~p~n", [X]), - {ok, NewState}; - {_R,_X} -> - ?format("Expected ~n~p~nbut got ~n~p~n", [_X, _R]), - not_ok + {X,X} -> + ?format("As was expected, got ~n~p~n", [X]), + {ok, NewState}; + {_R,_X} -> + ?format("Expected ~n~p~nbut got ~n~p~n", [_X, _R]), + not_ok end. unsetify(S) -> case is_sofs_set(S) of - true -> to_external(S); - false -> S + true -> to_external(S); + false -> S end. %% Note: assumes S has been set up; the new state is not returned eval(Query, S) -> - ?line {{ok, Answer}, _NewState} = - xref_base:q(S, Query, [{verbose, false}]), + {{ok, Answer}, _NewState} = + xref_base:q(S, Query, [{verbose, false}]), unsetify(Answer). add_module(S, XMod, DefAt, X, LCallAt, XCallAt, XC, LC) -> @@ -2545,159 +2469,159 @@ add_module(S, XMod, DefAt, X, LCallAt, XCallAt, XC, LC) -> Depr = {Depr0,DBad}, Data = {DefAt, LCallAt, XCallAt, LC, XC, X, Attr, Depr}, Unres = [], - ?line {ok, _Module, _Bad, State} = - xref_base:do_add_module(S, XMod, Unres, Data), + {ok, _Module, _Bad, State} = + xref_base:do_add_module(S, XMod, Unres, Data), State. add_application(S, XApp) -> - ?line xref_base:do_add_application(S, XApp). + xref_base:do_add_application(S, XApp). add_release(S, XRel) -> - ?line xref_base:do_add_release(S, XRel). + xref_base:do_add_release(S, XRel). remove_module(S, M) -> - ?line xref_base:do_remove_module(S, M). + xref_base:do_remove_module(S, M). info_tag(Info, Tag) -> {value, {_Tag, Value}} = lists:keysearch(Tag, 1, Info), Value. make_ufile(FileName) -> - ?line ok = file:write_file(FileName, term_to_binary(foo)), - ?line hide_file(FileName). + ok = file:write_file(FileName, term_to_binary(foo)), + hide_file(FileName). make_udir(Dir) -> - ?line ok = file:make_dir(Dir), - ?line hide_file(Dir). + ok = file:make_dir(Dir), + hide_file(Dir). hide_file(FileName) -> - ?line {ok, FileInfo} = file:read_file_info(FileName), - ?line NewFileInfo = FileInfo#file_info{mode = 0}, - ?line ok = file:write_file_info(FileName, NewFileInfo). + {ok, FileInfo} = file:read_file_info(FileName), + NewFileInfo = FileInfo#file_info{mode = 0}, + ok = file:write_file_info(FileName, NewFileInfo). %% Note that S has to be set up before calling this checking function. check_state(S) -> - ?line Info = xref:info(S), + Info = xref:info(S), - ?line modules_mode_check(S, Info), + modules_mode_check(S, Info), case info(Info, mode) of - modules -> - ok; - functions -> - functions_mode_check(S, Info) + modules -> + ok; + functions -> + functions_mode_check(S, Info) end. %% The manual mentions some facts that should always hold. %% Here they are again. functions_mode_check(S, Info) -> %% F = L + X, - ?line {ok, F} = xref:q(S, "F"), - ?line {ok, F} = xref:q(S, "L + X"), + {ok, F} = xref:q(S, "F"), + {ok, F} = xref:q(S, "L + X"), %% V = X + L + B + U, - ?line {ok, V} = xref:q(S, "V"), - ?line {ok, V} = xref:q(S, "X + L + B + U"), + {ok, V} = xref:q(S, "V"), + {ok, V} = xref:q(S, "X + L + B + U"), %% X, L, B and U are disjoint. - ?line {ok, []} = - xref:q(S, "X * L + X * B + X * U + L * B + L * U + B * U"), + {ok, []} = + xref:q(S, "X * L + X * B + X * U + L * B + L * U + B * U"), %% V = UU + XU + LU, - ?line {ok, V} = xref:q(S, "UU + XU + LU"), + {ok, V} = xref:q(S, "UU + XU + LU"), %% E = LC + XC - ?line {ok, E} = xref:q(S, "E"), - ?line {ok, E} = xref:q(S, "LC + XC"), + {ok, E} = xref:q(S, "E"), + {ok, E} = xref:q(S, "LC + XC"), %% U subset of XU, - ?line {ok, []} = xref:q(S, "U - XU"), + {ok, []} = xref:q(S, "U - XU"), %% LU = range LC - ?line {ok, []} = xref:q(S, "(LU - range LC) + (range LC - LU)"), + {ok, []} = xref:q(S, "(LU - range LC) + (range LC - LU)"), %% XU = range XC - ?line {ok, []} = xref:q(S, "(XU - range XC) + (range XC - XU)"), + {ok, []} = xref:q(S, "(XU - range XC) + (range XC - XU)"), %% LU subset F - ?line {ok, []} = xref:q(S, "LU - F"), + {ok, []} = xref:q(S, "LU - F"), %% UU subset F - ?line {ok, []} = xref:q(S, "UU - F"), + {ok, []} = xref:q(S, "UU - F"), %% ME = (Mod) E - ?line {ok, ME} = xref:q(S, "ME"), - ?line {ok, ME} = xref:q(S, "(Mod) E"), + {ok, ME} = xref:q(S, "ME"), + {ok, ME} = xref:q(S, "(Mod) E"), %% AE = (App) E - ?line {ok, AE} = xref:q(S, "AE"), - ?line {ok, AE} = xref:q(S, "(App) E"), + {ok, AE} = xref:q(S, "AE"), + {ok, AE} = xref:q(S, "(App) E"), %% RE = (Rel) E - ?line {ok, RE} = xref:q(S, "RE"), - ?line {ok, RE} = xref:q(S, "(Rel) E"), + {ok, RE} = xref:q(S, "RE"), + {ok, RE} = xref:q(S, "(Rel) E"), %% (Mod) V subset of M - ?line {ok, []} = xref:q(S, "(Mod) V - M"), + {ok, []} = xref:q(S, "(Mod) V - M"), %% range UC subset of U - ?line {ok, []} = xref:q(S, "range UC - U"), + {ok, []} = xref:q(S, "range UC - U"), %% Some checks on the numbers returned by the info functions. - ?line {Resolved, Unresolved} = info(Info, no_calls), - ?line AllCalls = Resolved + Unresolved, - ?line {ok, AllCalls} = xref:q(S, "# (XLin) E + # (LLin) E"), + {Resolved, Unresolved} = info(Info, no_calls), + AllCalls = Resolved + Unresolved, + {ok, AllCalls} = xref:q(S, "# (XLin) E + # (LLin) E"), - ?line {Local, Exported} = info(Info, no_functions), - ?line LX = Local+Exported, - ?line {ok, LXs} = xref:q(S, 'Extra = _:module_info/"(0|1)" + LM, - # (F - Extra)'), - ?line true = LX =:= LXs, + {Local, Exported} = info(Info, no_functions), + LX = Local+Exported, + {ok, LXs} = xref:q(S, 'Extra = _:module_info/"(0|1)" + LM, + # (F - Extra)'), + true = LX =:= LXs, - ?line {LocalCalls, ExternalCalls, UnresCalls} = - info(Info, no_function_calls), - ?line LEU = LocalCalls + ExternalCalls + UnresCalls, - ?line {ok, LEU} = xref:q(S, "# LC + # XC"), + {LocalCalls, ExternalCalls, UnresCalls} = + info(Info, no_function_calls), + LEU = LocalCalls + ExternalCalls + UnresCalls, + {ok, LEU} = xref:q(S, "# LC + # XC"), - ?line InterFunctionCalls = info(Info, no_inter_function_calls), - ?line {ok, InterFunctionCalls} = xref:q(S, "# EE"), + InterFunctionCalls = info(Info, no_inter_function_calls), + {ok, InterFunctionCalls} = xref:q(S, "# EE"), %% And some more checks on counters... - ?line check_count(S), + check_count(S), %% ... and more - ?line {ok, []} = xref:q(S, "LM - X - U - B"), + {ok, []} = xref:q(S, "LM - X - U - B"), ok. modules_mode_check(S, Info) -> %% B subset of XU, - ?line {ok, []} = xref:q(S, "B - XU"), + {ok, []} = xref:q(S, "B - XU"), %% M = AM + LM + UM - ?line {ok, M} = xref:q(S, "M"), - ?line {ok, M} = xref:q(S, "AM + LM + UM"), + {ok, M} = xref:q(S, "M"), + {ok, M} = xref:q(S, "AM + LM + UM"), %% DF is a subset of X U B, etc. - ?line {ok, []} = xref:q(S, "DF - X - B"), - ?line {ok, []} = xref:q(S, "DF_3 - DF"), - ?line {ok, []} = xref:q(S, "DF_2 - DF_3"), - ?line {ok, []} = xref:q(S, "DF_1 - DF_2"), + {ok, []} = xref:q(S, "DF - X - B"), + {ok, []} = xref:q(S, "DF_3 - DF"), + {ok, []} = xref:q(S, "DF_2 - DF_3"), + {ok, []} = xref:q(S, "DF_1 - DF_2"), %% AM, LM and UM are disjoint. - ?line {ok, []} = xref:q(S, "AM * LM + AM * UM + LM * UM"), + {ok, []} = xref:q(S, "AM * LM + AM * UM + LM * UM"), %% (App) M subset of A - ?line {ok, []} = xref:q(S, "(App) M - A"), + {ok, []} = xref:q(S, "(App) M - A"), - ?line AM = info(Info, no_analyzed_modules), - ?line {ok, AM} = xref:q(S, "# AM"), + AM = info(Info, no_analyzed_modules), + {ok, AM} = xref:q(S, "# AM"), - ?line A = info(Info, no_applications), - ?line {ok, A} = xref:q(S, "# A"), + A = info(Info, no_applications), + {ok, A} = xref:q(S, "# A"), - ?line NoR = info(Info, no_releases), - ?line {ok, NoR} = xref:q(S, "# R"), + NoR = info(Info, no_releases), + {ok, NoR} = xref:q(S, "# R"), ok. @@ -2709,7 +2633,7 @@ check_count(S) -> {ok, M} = xref:q(S, 'AM'), {ok, _} = xref:q(S, - "Extra := _:module_info/\"(0|1)\" + LM"), + "Extra := _:module_info/\"(0|1)\" + LM"), %% info/1: {ok, NoR} = xref:q(S, '# R'), @@ -2744,7 +2668,7 @@ check_count(S) -> info_module([M | Ms], S) -> {ok, NoCalls} = per_module("T = (E | ~p : Mod), # (XLin) T + # (LLin) T", - M, S), + M, S), {ok, NoFunCalls} = per_module("# (E | ~p : Mod)", M, S), {ok, NoXCalls} = per_module("# (XC | ~p : Mod)", M, S), {ok, NoLCalls} = per_module("# (LC | ~p : Mod)", M, S), @@ -2784,40 +2708,38 @@ fstring(R) -> flatten(xref:format_error(R)). start(Server) -> - ?line case xref:start(Server) of - {error, {already_started, _Pid}} -> - ?line xref:stop(Server), - ?line xref:start(Server); - R -> R - end. + case xref:start(Server) of + {error, {already_started, _Pid}} -> + xref:stop(Server), + xref:start(Server); + R -> R + end. add_erts_code_path(KernelPath) -> VersionDirs = - filelib:is_dir( - filename:join( - [code:lib_dir(), - lists:flatten( - ["kernel-", - [X || - {kernel,_,X} <- - application_controller:which_applications()]])])), + filelib:is_dir( + filename:join( + [code:lib_dir(), + lists:flatten( + ["kernel-", + [X || + {kernel,_,X} <- + application_controller:which_applications()]])])), case VersionDirs of - true -> - case code:lib_dir(erts) of - String when is_list(String) -> - [KernelPath, fname(String,"ebin")]; - _Other1 -> - [KernelPath] - end; - false -> - % Clearcase? - PrelPath = filename:join([code:lib_dir(),"..","erts","preloaded"]), - case filelib:is_dir(PrelPath) of - true -> - [KernelPath, fname(PrelPath,"ebin")]; - false -> - [KernelPath] - end + true -> + case code:lib_dir(erts) of + String when is_list(String) -> + [KernelPath, fname(String,"ebin")]; + _Other1 -> + [KernelPath] + end; + false -> + % Clearcase? + PrelPath = filename:join([code:lib_dir(),"..","erts","preloaded"]), + case filelib:is_dir(PrelPath) of + true -> + [KernelPath, fname(PrelPath,"ebin")]; + false -> + [KernelPath] + end end. - - |