diff options
Diffstat (limited to 'lib/tools')
66 files changed, 3952 insertions, 5671 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_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 985207a39b..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> @@ -31,6 +31,32 @@ </header> <p>This document describes the changes made to the Tools application.</p> +<section><title>Tools 2.8.3</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + <c>cover:compile_beam/1</c> and + <c>cover:compile_beam_directory/1,2</c> crashed when + trying to compile a beam file without a <c>'file'</c> + attribute. This has been corrected and an error is + returned instead.</p> + <p> + Thanks to Louis-Philippe Gauthier for reporting this bug.</p> + <p> + Own Id: OTP-13200</p> + </item> + <item> + <p>Fix a bit string comprehension bug in Cover. </p> + <p> + Own Id: OTP-13277 Aux Id: PR 856 </p> + </item> + </list> + </section> + +</section> + <section><title>Tools 2.8.2</title> <section><title>Fixed Bugs and Malfunctions</title> 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 cdf09ad502..ce26c83295 100644 --- a/lib/tools/emacs/erlang-skels.el +++ b/lib/tools/emacs/erlang-skels.el @@ -1188,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 466bf139b9..17a156ff00 100644 --- a/lib/tools/emacs/erlang.el +++ b/lib/tools/emacs/erlang.el @@ -7,7 +7,7 @@ ;; %CopyrightBegin% ;; -;; Copyright Ericsson AB 1996-2014. 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. @@ -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" diff --git a/lib/tools/emacs/test.erl.indented b/lib/tools/emacs/test.erl.indented index 1986acadf1..6913068133 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. diff --git a/lib/tools/emacs/test.erl.orig b/lib/tools/emacs/test.erl.orig index 7e8ad23412..621948cbe1 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. 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 366d6bcbd9..69331732bf 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 @@ -1474,7 +1472,7 @@ do_compile_beam(Module,BeamFile0,State) -> {ok,Module,BeamFile}; error -> {error, BeamFile}; - {error,Reason} -> % no abstract code + {error,Reason} -> % no abstract code or no 'file' attribute {error, {Reason, BeamFile}} end; {error,no_beam} -> @@ -1537,32 +1535,11 @@ do_compile_beam1(Module,Beam,UserOptions) -> {error,E}; {raw_abstract_v1,Code} -> Forms0 = epp:interpret_file_attribute(Code), - {Forms,Vars} = transform(Forms0, Module), - - %% We need to recover the source from the compilation - %% info otherwise the newly compiled module will have - %% source pointing to the current directory - SourceInfo = get_source_info(Module, Beam), - - %% Compile and load the result - %% It's necessary to check the result of loading since it may - %% fail, for example if Module resides in a sticky directory - {ok, Module, Binary} = compile:forms(Forms, SourceInfo ++ UserOptions), - case code:load_binary(Module, ?TAG, Binary) of - {module, Module} -> - - %% Store info about all function clauses in database - InitInfo = lists:reverse(Vars#vars.init_info), - ets:insert(?COVER_CLAUSE_TABLE, {Module, InitInfo}), - - %% Store binary code so it can be loaded on remote nodes - ets:insert(?BINARY_TABLE, {Module, Binary}), - - {ok, Module}; - - _Error -> - do_clear(Module), - error + case find_main_filename(Forms0) of + {ok,MainFile} -> + do_compile_beam2(Module,Beam,UserOptions,Forms0,MainFile); + Error -> + Error end; {_VSN,_Code} -> %% Wrong version of abstract code. Just report that there @@ -1579,6 +1556,35 @@ get_abstract_code(Module, Beam) -> Error -> Error end. +do_compile_beam2(Module,Beam,UserOptions,Forms0,MainFile) -> + {Forms,Vars} = transform(Forms0, Module, MainFile), + + %% We need to recover the source from the compilation + %% info otherwise the newly compiled module will have + %% source pointing to the current directory + SourceInfo = get_source_info(Module, Beam), + + %% Compile and load the result + %% It's necessary to check the result of loading since it may + %% fail, for example if Module resides in a sticky directory + {ok, Module, Binary} = compile:forms(Forms, SourceInfo ++ UserOptions), + case code:load_binary(Module, ?TAG, Binary) of + {module, Module} -> + + %% Store info about all function clauses in database + InitInfo = lists:reverse(Vars#vars.init_info), + ets:insert(?COVER_CLAUSE_TABLE, {Module, InitInfo}), + + %% Store binary code so it can be loaded on remote nodes + ets:insert(?BINARY_TABLE, {Module, Binary}), + + {ok, Module}; + + _Error -> + do_clear(Module), + error + end. + get_source_info(Module, Beam) -> Compile = get_compile_info(Module, Beam), case lists:keyfind(source, 1, Compile) of @@ -1601,8 +1607,7 @@ get_compile_info(Module, Beam) -> [] end. -transform(Code, Module) -> - MainFile=find_main_filename(Code), +transform(Code, Module, MainFile) -> Vars0 = #vars{module=Module}, {ok,MungedForms,Vars} = transform_2(Code,[],Vars0,MainFile,on), {MungedForms,Vars}. @@ -1610,9 +1615,12 @@ transform(Code, Module) -> %% Helpfunction which returns the first found file-attribute, which can %% be interpreted as the name of the main erlang source file. find_main_filename([{attribute,_,file,{MainFile,_}}|_]) -> - MainFile; + {ok,MainFile}; find_main_filename([_|Rest]) -> - find_main_filename(Rest). + find_main_filename(Rest); +find_main_filename([]) -> + {error, no_file_attribute}. + transform_2([Form0|Forms],MungedForms,Vars,MainFile,Switch) -> Form = expand(Form0), @@ -1994,9 +2002,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,?BLOCK1(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) -> 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/cprof.erl b/lib/tools/src/cprof.erl index 0240f876bc..f6d68f0bf8 100644 --- a/lib/tools/src/cprof.erl +++ b/lib/tools/src/cprof.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2002-2009. 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. @@ -114,6 +114,7 @@ analyse(Limit) when is_integer(Limit) -> analyse(M) when is_atom(M) -> analyse(M, 1). +-dialyzer({no_improper_lists, analyse/2}). analyse(M, Limit) when is_atom(M), is_integer(Limit) -> L0 = [begin MFA = {M,F,A}, diff --git a/lib/tools/src/eprof.erl b/lib/tools/src/eprof.erl index 0357e46a50..07e995993b 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. diff --git a/lib/tools/src/fprof.erl b/lib/tools/src/fprof.erl index 7c6fab0b75..f9da748fef 100644 --- a/lib/tools/src/fprof.erl +++ b/lib/tools/src/fprof.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2001-2013. 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. @@ -1567,13 +1567,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) -> @@ -2014,8 +2021,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. @@ -2251,6 +2260,8 @@ do_analyse(Table, Analyse) -> ?dbg(5, "do_analyse_1(_, _) ->~p~n", [Result]), Result. +-dialyzer({no_improper_lists, do_analyse_1/2}). + do_analyse_1(Table, #analyse{group_leader = GroupLeader, dest = Io, @@ -2624,6 +2635,8 @@ funcstat_pd(Pid, Func1, Func0, Clocks) -> funcstat_sort_r(FuncstatList, Element) -> funcstat_sort_r_1(FuncstatList, Element, []). +-dialyzer({no_improper_lists, funcstat_sort_r_1/3}). + funcstat_sort_r_1([], _, R) -> postsort_r(lists:sort(R)); funcstat_sort_r_1([#funcstat{callers_sum = #clocks{} = Clocks, @@ -2646,6 +2659,8 @@ funcstat_sort_r_1([#funcstat{callers_sum = #clocks{} = Clocks, clocks_sort_r(L, E) -> clocks_sort_r_1(L, E, []). +-dialyzer({no_improper_lists, clocks_sort_r_1/3}). + clocks_sort_r_1([], _, R) -> postsort_r(lists:sort(R)); clocks_sort_r_1([#clocks{} = C | L], E, R) -> 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 e8b3d242e4..78407a651a 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. @@ -94,12 +94,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, { @@ -757,7 +757,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; @@ -933,7 +933,6 @@ strings(Strings) -> strings(Strings, []). strings([], Out) -> Out; strings([{space, N, S} | Ss], Out) -> strings(Ss, Out ++ term2string(term2string("~~~ws", [N]), [S])); strings([{left, N, S} | Ss], Out) -> strings(Ss, Out ++ term2string(term2string(" ~~s~~~ws", [N]), [S,""])); -strings([{format, Format, S} | Ss], Out) -> strings(Ss, Out ++ term2string(Format, [S])); strings([S|Ss], Out) -> strings(Ss, Out ++ term2string("~ts", [S])). 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/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..70eb107781 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. 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/src/xref_utils.erl b/lib/tools/src/xref_utils.erl index 438ec93962..f69aa70244 100644 --- a/lib/tools/src/xref_utils.erl +++ b/lib/tools/src/xref_utils.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2000-2014. 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. @@ -245,6 +245,8 @@ select_last_application_version(AppVs) -> TL = to_external(partition(1, relation(AppVs))), [last(keysort(2, L)) || L <- TL]. +-record(scan, {collected = [], errors = [], seen = [], unreadable = []}). + %% scan_directory(Directory, Recurse, Collect, Watch) -> %% {Collected, Errors, Seen, Unreadable} %% @@ -261,8 +263,9 @@ select_last_application_version(AppVs) -> %% Unreadable. %% scan_directory(File, Recurse, Collect, Watch) -> - Init = [[] | {[],[],[]}], - [L | {E,J,U}] = find_files_dir(File, Recurse, Collect, Watch, Init), + Init = #scan{}, + S = find_files_dir(File, Recurse, Collect, Watch, Init), + #scan{collected = L, errors = E, seen = J, unreadable = U} = S, {reverse(L), reverse(E), reverse(J), reverse(U)}. %% {Dir, Basename} | false @@ -576,8 +579,7 @@ find_files_dir(Dir, Recurse, Collect, Watch, L) -> {ok, Files} -> find_files(sort(Files), Dir, Recurse, Collect, Watch, L); {error, Error} -> - [B | {E,J,U}] = L, - [B | {[file_error(Dir, Error)|E],J,U}] + L#scan{errors = [file_error(Dir, Error)|L#scan.errors]} end. find_files([F | Fs], Dir, Recurse, Collect, Watch, L) -> @@ -588,22 +590,23 @@ find_files([F | Fs], Dir, Recurse, Collect, Watch, L) -> {ok, {_, directory, _, _}} -> L; Info -> - [B | EJU = {E,J,U}] = L, + #scan{collected = B, errors = E, + seen = J, unreadable = U} = L, Ext = filename:extension(File), C = member(Ext, Collect), case C of true -> case Info of {ok, {_, file, readable, _}} -> - [[{Dir,F} | B] | EJU]; + L#scan{collected = [{Dir,F} | B]}; {ok, {_, file, unreadable, _}} -> - [B | {E,J,[File|U]}]; + L#scan{unreadable = [File|U]}; Error -> - [B | {[Error|E],J,U}] + L#scan{errors = [Error|E]} end; false -> case member(Ext, Watch) of - true -> [B | {E,[File|J],U}]; + true -> L#scan{seen = [File|J]}; false -> L end end 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 25c9317608..b4c9264b30 100644 --- a/lib/tools/test/cover_SUITE.erl +++ b/lib/tools/test/cover_SUITE.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. @@ -19,81 +19,47 @@ %% -module(cover_SUITE). --export([all/0, init_per_testcase/2, end_per_testcase/2, - suite/0,groups/0,init_per_suite/1, end_per_suite/1, - init_per_group/2,end_per_group/2]). +-compile(export_all). --export([coverage/1, coverage_analysis/1, - start/1, compile/1, analyse/1, misc/1, stop/1, - distribution/1, reconnect/1, die_and_reconnect/1, - dont_reconnect_after_stop/1, stop_node_after_disconnect/1, - export_import/1, - otp_5031/1, eif/1, otp_5305/1, otp_5418/1, otp_6115/1, otp_7095/1, - otp_8188/1, otp_8270/1, otp_8273/1, otp_8340/1, - otp_10979_hanging_node/1, compile_beam_opts/1, eep37/1, - analyse_no_beam/1, line_0/1]). +-include_lib("common_test/include/ct.hrl"). --export([do_coverage/1]). - --export([distribution_performance/1]). - --include_lib("test_server/include/test_server.hrl"). - -%%---------------------------------------------------------------------- -%% The following directory structure is assumed: -%% cwd __________________________________________ -%% | \ \ \ \ \ \ \ -%% a b cc d f d1 compile_beam_____ otp_6115 -%% | \ \ \ \ \ \ \ -%% e crypt v w x d f1 f2 -%% | -%% y -%%---------------------------------------------------------------------- - -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], + 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. @@ -101,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. @@ -113,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(), @@ -126,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. @@ -146,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), @@ -156,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) -> @@ -249,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(), @@ -381,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), @@ -403,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 @@ -429,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()), @@ -626,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()), @@ -655,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]), @@ -668,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()), @@ -696,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]), @@ -711,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()), @@ -741,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]), @@ -756,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), @@ -770,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), + {CT,_CA} = timer:tc(CFun), + % erlang:display(_CA), erlang:display({compile,CT}), {SNT,_} = timer:tc(fun() -> {ok,[N1]} = cover:start(nodes()) end), @@ -787,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), + {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), @@ -819,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], @@ -830,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,_,_,_) -> @@ -850,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]), @@ -872,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). @@ -1017,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 @@ -1059,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). @@ -1177,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]). @@ -1269,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,2},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). @@ -1305,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: @@ -1319,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" @@ -1365,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" @@ -1412,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" @@ -1437,204 +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 - - ?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 - " <<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 - " :(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) -> @@ -1647,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), @@ -1690,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), @@ -1733,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), @@ -1746,6 +1661,63 @@ line_0(Config) -> ok. +%% OTP-13200: Return error instead of crashing when trying to compile +%% a beam which has no 'file' attribute. +compile_beam_no_file(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"]), + TT = do_scan(Str), + Forms = [ begin {ok,Y} = erl_parse:parse_form(X),Y end || X <- TT ], + {ok,_,Bin} = compile:forms(Forms,[debug_info]), + BeamFile = filename:join(Dir,"nofile.beam"), + ok = file:write_file(BeamFile,Bin), + {error,{no_file_attribute,BeamFile}} = cover:compile_beam(nofile), + [{error,{no_file_attribute,BeamFile}}] = cover:compile_beam_directory(Dir), + ok. + +do_scan([]) -> + []; +do_scan(Str) -> + {done,{ok,T,_},C} = erl_scan:tokens([],Str,0), + [ T | do_scan(C) ]. + +%% PR 856. Fix a bc bug. +otp_13277(Config) -> + Test = <<"-module(t). + -export([t/0]). + + pad(A, L) -> + P = << <<\"#\">> || _ <- lists:seq(1, L) >>, + <<A/binary, P/binary>>. + + t() -> + pad(<<\"hi\">>, 2). + ">>, + 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------------------------------------------------------------ @@ -1761,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 @@ -1773,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 @@ -1796,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), @@ -1818,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) -> @@ -1830,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/cc.erl b/lib/tools/test/cover_SUITE_data/cc.erl index 587bdbe493..7eb165ef8a 100644 --- a/lib/tools/test/cover_SUITE_data/cc.erl +++ b/lib/tools/test/cover_SUITE_data/cc.erl @@ -1,88 +1,17 @@ -module(cc). --export([epp/1, epp/2, dbg/1, dbg/2, cvr/1, cvr/2]). --export([p/2, pp/2]). +-compile(export_all). -%% epp(Module) - Creates Module.epp which contains all forms of Module -%% as obtained by using epp. -%% -%% dbg(Module) - Creates Module.dbg which contains all forms of Module -%% as obtained by using beam_lib:chunks/2. -%% -%% cvr(Module) - Creates Module.cvr which contains all forms of Module -%% as obtained by using cover:transform/3. -%% +%% This is a dummy module used only for cover compiling. The content +%% of this module has no meaning for the test. -epp(Module) -> - epp(Module, p). -epp(Module, P) -> - File = atom_to_list(Module)++".erl", - {ok,Cwd} = file:get_cwd(), - {ok, Fd1} = epp:open(File, [Cwd], []), - {ok, Fd2} = file:open(atom_to_list(Module)++".epp", write), +foo() -> + T = erlang:time(), + spawn(fun() -> bar(T) end). - epp(Fd1, Fd2, P), - - epp:close(Fd1), - file:close(Fd2), - ok. - -epp(Fd1, Fd2, P) -> - case epp:parse_erl_form(Fd1) of - {ok, {attribute,Line,Attr,Data}} -> - epp(Fd1, Fd2, P); - {ok, Form} when P==p -> - io:format(Fd2, "~p.~n", [Form]), - epp(Fd1, Fd2, P); - {ok, Form} when P==pp -> - io:format(Fd2, "~p.~n", [erl_pp:form(Form)]), - epp(Fd1, Fd2, P); - {eof, Line} -> - ok - end. - -cvr(Module) -> - cvr(Module, p). -cvr(Module, P) -> - case beam_lib:chunks(Module, [abstract_code]) of - {ok, {Module, [{abstract_code, no_abstract_code}]}} -> - {error, {no_debug_info,Module}}; - {ok, {Module, [{abstract_code, {Vsn, Forms}}]}} -> - Vars = {vars,Module,Vsn, [], - undefined, undefined, undefined, undefined, undefined, - undefined, - false}, - {ok, TForms, _Vars2} = cover:transform(Forms, [], Vars), - File = atom_to_list(Module)++".cvr", - apply(?MODULE, P, [File, TForms]); - Error -> - Error +bar(T) -> + receive + X -> + T1 = erlang:time(), + io:format("received ~p at ~p. Last time: ~p~n",[X,T1,T]), + bar(T1) end. - -dbg(Module) -> - dbg(Module, p). -dbg(Module, P) -> - case beam_lib:chunks(Module, [abstract_code]) of - {ok, {Module, [{abstract_code, no_abstract_code}]}} -> - {error, {no_debug_info,Module}}; - {ok, {Module, [{abstract_code, {Vsn, Forms}}]}} -> - File = atom_to_list(Module)++".dbg", - apply(?MODULE, P, [File, Forms]); - Error -> - Error - end. - -p(File, Forms) -> - {ok, Fd} = file:open(File, write), - lists:foreach(fun(Form) -> - io:format(Fd, "~p.~n", [Form]) - end, - Forms), - file:close(Fd). - -pp(File, Forms) -> - {ok, Fd} = file:open(File, write), - lists:foreach(fun(Form) -> - io:format(Fd, "~s", [erl_pp:form(Form)]) - end, - Forms), - file:close(Fd). 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..e18d384b52 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,48 +925,48 @@ 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)}]), 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; @@ -1040,10 +974,10 @@ handle_trace({trace_ts,Pid,gc_end,_,TS},P) -> ?dbg("~p",[{{gc_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; @@ -1051,27 +985,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 +1041,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 +1060,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 +1071,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 +1093,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 +1165,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. - - diff --git a/lib/tools/vsn.mk b/lib/tools/vsn.mk index 3efe89d9f9..70564f05c6 100644 --- a/lib/tools/vsn.mk +++ b/lib/tools/vsn.mk @@ -1 +1 @@ -TOOLS_VSN = 2.8.2 +TOOLS_VSN = 2.8.3 |