.TH cover 3erl "tools 2.6.7" "Ericsson AB" "Erlang Module Definition"
.SH NAME
cover \- A Coverage Analysis Tool for Erlang
.SH DESCRIPTION
.LP
The module \fIcover\fR\& provides a set of functions for coverage analysis of Erlang programs, counting how many times each \fIexecutable line\fR\& of code is executed when a program is run\&.
.br
An executable line contains an Erlang expression such as a matching or a function call\&. A blank line or a line containing a comment, function head or pattern in a \fIcase\fR\&- or \fIreceive\fR\& statement is not executable\&.
.LP
Coverage analysis can be used to verify test cases, making sure all relevant code is covered, and may also be helpful when looking for bottlenecks in the code\&.
.LP
Before any analysis can take place, the involved modules must be \fICover compiled\fR\&\&. This means that some extra information is added to the module before it is compiled into a binary which then is loaded\&. The source file of the module is not affected and no \fI\&.beam\fR\& file is created\&.
.LP
Each time a function in a Cover compiled module is called, information about the call is added to an internal database of Cover\&. The coverage analysis is performed by examining the contents of the Cover database\&. The output \fIAnswer\fR\& is determined by two parameters, \fILevel\fR\& and \fIAnalysis\fR\&\&.
.RS 2
.TP 2
*
\fILevel = module\fR\&
.RS 2
.LP
\fIAnswer = {Module,Value}\fR\&, where \fIModule\fR\& is the module name\&.
.RE
.LP
.TP 2
*
\fILevel = function\fR\&
.RS 2
.LP
\fIAnswer = [{Function,Value}]\fR\&, one tuple for each function in the module\&. A function is specified by its module name \fIM\fR\&, function name \fIF\fR\& and arity \fIA\fR\& as a tuple \fI{M,F,A}\fR\&\&.
.RE
.LP
.TP 2
*
\fILevel = clause\fR\&
.RS 2
.LP
\fIAnswer = [{Clause,Value}]\fR\&, one tuple for each clause in the module\&. A clause is specified by its module name \fIM\fR\&, function name \fIF\fR\&, arity \fIA\fR\& and position in the function definition \fIC\fR\& as a tuple \fI{M,F,A,C}\fR\&\&.
.RE
.LP
.TP 2
*
\fILevel = line\fR\&
.RS 2
.LP
\fIAnswer = [{Line,Value}]\fR\&, one tuple for each executable line in the module\&. A line is specified by its module name \fIM\fR\& and line number in the source file \fIN\fR\& as a tuple \fI{M,N}\fR\&\&.
.RE
.LP
.TP 2
*
\fIAnalysis = coverage\fR\&
.RS 2
.LP
\fIValue = {Cov,NotCov}\fR\& where \fICov\fR\& is the number of executable lines in the module, function, clause or line that have been executed at least once and \fINotCov\fR\& is the number of executable lines that have not been executed\&.
.RE
.LP
.TP 2
*
\fIAnalysis = calls\fR\&
.RS 2
.LP
\fIValue = Calls\fR\& which is the number of times the module, function, or clause has been called\&. In the case of line level analysis, \fICalls\fR\& is the number of times the line has been executed\&.
.RE
.LP
.RE
.LP
\fIDistribution\fR\&
.LP
Cover can be used in a distributed Erlang system\&. One of the nodes in the system must then be selected as the \fImain node\fR\&, and all Cover commands must be executed from this node\&. The error reason \fInot_main_node\fR\& is returned if an interface function is called on one of the remote nodes\&.
.LP
Use \fIcover:start/1\fR\& and \fIcover:stop/1\fR\& to add or remove nodes\&. The same Cover compiled code will be loaded on each node, and analysis will collect and sum up coverage data results from all nodes\&.
.SH EXPORTS
.LP
.B
start() -> {ok,Pid} | {error,Reason}
.br
.RS
.LP
Types:
.RS 3
Pid = pid()
.br
Reason = {already_started,Pid}
.br
.RE
.RE
.RS
.LP
Starts the Cover server which owns the Cover internal database\&. This function is called automatically by the other functions in the module\&.
.RE
.LP
.B
start(Nodes) -> {ok,StartedNodes} | {error,not_main_node}
.br
.RS
.LP
Types:
.RS 3
Nodes = StartedNodes = [atom()]
.br
.RE
.RE
.RS
.LP
Starts a Cover server on the each of given nodes, and loads all cover compiled modules\&.
.RE
.LP
.B
compile(ModFile) -> Result
.br
.B
compile(ModFile, Options) -> Result
.br
.B
compile_module(ModFile) -> Result
.br
.B
compile_module(ModFile, Options) -> Result
.br
.RS
.LP
Types:
.RS 3
ModFile = Module | File
.br
Module = atom()
.br
File = string()
.br
Options = [Option]
.br
Option = {i,Dir} | {d,Macro} | {d,Macro,Value}
.br
.RS 2
See \fIcompile:file/2\&.\fR\&
.RE
Result = {ok,Module} | {error,File} | {error,not_main_node}
.br
.RE
.RE
.RS
.LP
Compiles a module for Cover analysis\&. The module is given by its module name \fIModule\fR\& or by its file name \fIFile\fR\&\&. The \fI\&.erl\fR\& extension may be omitted\&. If the module is located in another directory, the path has to be specified\&.
.LP
\fIOptions\fR\& is a list of compiler options which defaults to \fI[]\fR\&\&. Only options defining include file directories and macros are passed to \fIcompile:file/2\fR\&, everything else is ignored\&.
.LP
If the module is successfully Cover compiled, the function returns \fI{ok,Module}\fR\&\&. Otherwise the function returns \fI{error,File}\fR\&\&. Errors and warnings are printed as they occur\&.
.LP
Note that the internal database is (re-)initiated during the compilation, meaning any previously collected coverage data for the module will be lost\&.
.RE
.LP
.B
compile_directory() -> [Result] | {error,Reason}
.br
.B
compile_directory(Dir) -> [Result] | {error,Reason}
.br
.B
compile_directory(Dir, Options) -> [Result] | {error,Reason}
.br
.RS
.LP
Types:
.RS 3
Dir = string()
.br
Options = [Option]
.br
.RS 2
See \fIcompile_module/1,2\fR\&
.RE
Result = {ok,Module} | {error,File} | {error,not_main_node}
.br
.RS 2
See \fIcompile_module/1,2\fR\&
.RE
Reason = eacces | enoent
.br
.RE
.RE
.RS
.LP
Compiles all modules (\fI\&.erl\fR\& files) in a directory \fIDir\fR\& for Cover analysis the same way as \fIcompile_module/1,2\fR\& and returns a list with the return values\&.
.LP
\fIDir\fR\& defaults to the current working directory\&.
.LP
The function returns \fI{error,eacces}\fR\& if the directory is not readable or \fI{error,enoent}\fR\& if the directory does not exist\&.
.RE
.LP
.B
compile_beam(ModFile) -> Result
.br
.RS
.LP
Types:
.RS 3
ModFile = Module | BeamFile
.br
Module = atom()
.br
BeamFile = string()
.br
Result = {ok,Module} | {error,BeamFile} | {error,Reason}
.br
Reason = non_existing | {no_abstract_code,BeamFile} | {encrypted_abstract_code,BeamFile} | {already_cover_compiled,no_beam_found,Module} | not_main_node
.br
.RE
.RE
.RS
.LP
Does the same as \fIcompile/1,2\fR\&, but uses an existing \fI\&.beam\fR\& file as base, i\&.e\&. the module is not compiled from source\&. Thus \fIcompile_beam/1\fR\& is faster than \fIcompile/1,2\fR\&\&.
.LP
Note that the existing \fI\&.beam\fR\& file must contain \fIabstract code\fR\&, i\&.e\&. it must have been compiled with the \fIdebug_info\fR\& option\&. If not, the error reason \fI{no_abstract_code,BeamFile}\fR\& is returned\&. If the abstract code is encrypted, and no key is available for decrypting it, the error reason \fI{encrypted_abstract_code,BeamFile} is returned\&.
If only the module name (i\&.e\&. not the full name of the \&.beam\fR\& file) is given to this function, the \fI\&.beam\fR\& file is found by calling \fIcode:which(Module)\fR\&\&. If no \fI\&.beam\fR\& file is found, the error reason \fInon_existing\fR\& is returned\&. If the module is already cover compiled with \fIcompile_beam/1\fR\&, the \fI\&.beam\fR\& file will be picked from the same location as the first time it was compiled\&. If the module is already cover compiled with \fIcompile/1,2\fR\&, there is no way to find the correct \fI\&.beam\fR\& file, so the error reason \fI{already_cover_compiled,no_beam_found,Module}\fR\& is returned\&.
.LP
\fI{error,BeamFile}\fR\& is returned if the compiled code can not be loaded on the node\&.
.RE
.LP
.B
compile_beam_directory() -> [Result] | {error,Reason}
.br
.B
compile_beam_directory(Dir) -> [Result] | {error,Reason}
.br
.RS
.LP
Types:
.RS 3
Dir = string()
.br
Result = See compile_beam/1
.br
Reason = eacces | enoent
.br
.RE
.RE
.RS
.LP
Compiles all modules (\fI\&.beam\fR\& files) in a directory \fIDir\fR\& for Cover analysis the same way as \fIcompile_beam/1\fR\& and returns a list with the return values\&.
.LP
\fIDir\fR\& defaults to the current working directory\&.
.LP
The function returns \fI{error,eacces}\fR\& if the directory is not readable or \fI{error,enoent}\fR\& if the directory does not exist\&.
.RE
.LP
.B
analyse(Module) -> {ok,Answer} | {error,Error}
.br
.B
analyse(Module, Analysis) -> {ok,Answer} | {error,Error}
.br
.B
analyse(Module, Level) -> {ok,Answer} | {error,Error}
.br
.B
analyse(Module, Analysis, Level) -> {ok,Answer} | {error,Error}
.br
.RS
.LP
Types:
.RS 3
Module = atom()
.br
Analysis = coverage | calls
.br
Level = line | clause | function | module
.br
Answer = {Module,Value} | [{Item,Value}]
.br
Item = Line | Clause | Function
.br
Line = {M,N}
.br
Clause = {M,F,A,C}
.br
Function = {M,F,A}
.br
M = F = atom()
.br
N = A = C = integer()
.br
Value = {Cov,NotCov} | Calls
.br
Cov = NotCov = Calls = integer()
.br
Error = {not_cover_compiled,Module} | not_main_node
.br
.RE
.RE
.RS
.LP
Performs analysis of a Cover compiled module \fIModule\fR\&, as specified by \fIAnalysis\fR\& and \fILevel\fR\& (see above), by examining the contents of the internal database\&.
.LP
\fIAnalysis\fR\& defaults to \fIcoverage\fR\& and \fILevel\fR\& defaults to \fIfunction\fR\&\&.
.LP
If \fIModule\fR\& is not Cover compiled, the function returns \fI{error,{not_cover_compiled,Module}}\fR\&\&.
.LP
HINT: It is possible to issue multiple analyse_to_file commands at the same time\&.
.RE
.LP
.B
analyse_to_file(Module) ->
.br
.B
analyse_to_file(Module,Options) ->
.br
.B
analyse_to_file(Module, OutFile) ->
.br
.B
analyse_to_file(Module, OutFile, Options) -> {ok,OutFile} | {error,Error}
.br
.RS
.LP
Types:
.RS 3
Module = atom()
.br
OutFile = string()
.br
Options = [Option]
.br
Option = html
.br
Error = {not_cover_compiled,Module} | {file,File,Reason} | no_source_code_found | not_main_node
.br
File = string()
.br
Reason = term()
.br
.RE
.RE
.RS
.LP
Makes a copy \fIOutFile\fR\& of the source file for a module \fIModule\fR\&, where it for each executable line is specified how many times it has been executed\&.
.LP
The output file \fIOutFile\fR\& defaults to \fIModule\&.COVER\&.out\fR\&, or \fIModule\&.COVER\&.html\fR\& if the option \fIhtml\fR\& was used\&.
.LP
If \fIModule\fR\& is not Cover compiled, the function returns \fI{error,{not_cover_compiled,Module}}\fR\&\&.
.LP
If the source file and/or the output file cannot be opened using \fIfile:open/2\fR\&, the function returns \fI{error,{file,File,Reason}}\fR\& where \fIFile\fR\& is the file name and \fIReason\fR\& is the error reason\&.
.LP
If the module was cover compiled from the \fI\&.beam\fR\& file, i\&.e\&. using \fIcompile_beam/1\fR\& or \fIcompile_beam_directory/0,1\fR\&, it is assumed that the source code can be found in the same directory as the \fI\&.beam\fR\& file, or in \fI\&.\&./src\fR\& relative to that directory\&. If no source code is found, \fI,{error,no_source_code_found}\fR\& is returned\&.
.LP
HINT: It is possible to issue multiple analyse_to_file commands at the same time\&.
.RE
.LP
.B
async_analyse_to_file(Module) ->
.br
.B
async_analyse_to_file(Module,Options) ->
.br
.B
async_analyse_to_file(Module, OutFile) ->
.br
.B
async_analyse_to_file(Module, OutFile, Options) -> pid()
.br
.RS
.LP
Types:
.RS 3
Module = atom()
.br
OutFile = string()
.br
Options = [Option]
.br
Option = html
.br
Error = {not_cover_compiled,Module} | {file,File,Reason} | no_source_code_found | not_main_node
.br
File = string()
.br
Reason = term()
.br
.RE
.RE
.RS
.LP
This function works exactly the same way as \fBanalyse_to_file\fR\& except that it is asynchronous instead of synchronous\&. The spawned process will link with the caller when created\&. If an \fIError\fR\& occurs while doing the cover analysis the process will crash with the same error reason as \fBanalyse_to_file\fR\& would return\&.
.RE
.LP
.B
modules() -> [Module] | {error,not_main_node}
.br
.RS
.LP
Types:
.RS 3
Module = atom()
.br
.RE
.RE
.RS
.LP
Returns a list with all modules that are currently Cover compiled\&.
.RE
.LP
.B
imported_modules() -> [Module] | {error,not_main_node}
.br
.RS
.LP
Types:
.RS 3
Module = atom()
.br
.RE
.RE
.RS
.LP
Returns a list with all modules for which there are imported data\&.
.RE
.LP
.B
imported() -> [File] | {error,not_main_node}
.br
.RS
.LP
Types:
.RS 3
File = string()
.br
.RE
.RE
.RS
.LP
Returns a list with all imported files\&.
.RE
.LP
.B
which_nodes() -> [Node] | {error,not_main_node}
.br
.RS
.LP
Types:
.RS 3
Node = atom()
.br
.RE
.RE
.RS
.LP
Returns a list with all nodes that are part of the coverage analysis\&. Note that the current node is not returned\&. This node is always part of the analysis\&.
.RE
.LP
.B
is_compiled(Module) -> {file,File} | false | {error,not_main_node}
.br
.RS
.LP
Types:
.RS 3
Module = atom()
.br
Beam = string()
.br
.RE
.RE
.RS
.LP
Returns \fI{file,File}\fR\& if the module \fIModule\fR\& is Cover compiled, or \fIfalse\fR\& otherwise\&. \fIFile\fR\& is the \fI\&.erl\fR\& file used by \fIcover:compile_module/1,2\fR\& or the \fI\&.beam\fR\& file used by \fIcompile_beam/1\fR\&\&.
.RE
.LP
.B
reset(Module) ->
.br
.B
reset() -> ok | {error,not_main_node}
.br
.RS
.LP
Types:
.RS 3
Module = atom()
.br
.RE
.RE
.RS
.LP
Resets all coverage data for a Cover compiled module \fIModule\fR\& in the Cover database on all nodes\&. If the argument is omitted, the coverage data will be reset for all modules known by Cover\&.
.LP
If \fIModule\fR\& is not Cover compiled, the function returns \fI{error,{not_cover_compiled,Module}}\fR\&\&.
.RE
.LP
.B
export(ExportFile)
.br
.B
export(ExportFile,Module) -> ok | {error,Reason}
.br
.RS
.LP
Types:
.RS 3
ExportFile = string()
.br
Module = atom()
.br
Reason = {not_cover_compiled,Module} | {cant_open_file,ExportFile,Reason} | not_main_node
.br
.RE
.RE
.RS
.LP
Exports the current coverage data for \fIModule\fR\& to the file \fIExportFile\fR\&\&. It is recommended to name the \fIExportFile\fR\& with the extension \fI\&.coverdata\fR\&, since other filenames can not be read by the web based interface to cover\&.
.LP
If \fIModule\fR\& is not given, data for all Cover compiled or earlier imported modules is exported\&.
.LP
This function is useful if coverage data from different systems is to be merged\&.
.LP
See also \fIcover:import/1\fR\&
.RE
.LP
.B
import(ExportFile) -> ok | {error,Reason}
.br
.RS
.LP
Types:
.RS 3
ExportFile = string()
.br
Reason = {cant_open_file,ExportFile,Reason} | not_main_node
.br
.RE
.RE
.RS
.LP
Imports coverage data from the file \fIExportFile\fR\& created with \fIcover:export/1,2\fR\&\&. Any analysis performed after this will include the imported data\&.
.LP
Note that when compiling a module \fIall existing coverage data is removed\fR\&, including imported data\&. If a module is already compiled when data is imported, the imported data is \fIadded\fR\& to the existing coverage data\&.
.LP
Coverage data from several export files can be imported into one system\&. The coverage data is then added up when analysing\&.
.LP
Coverage data for a module can not be imported from the same file twice unless the module is first reset or compiled\&. The check is based on the filename, so you can easily fool the system by renaming your export file\&.
.LP
See also \fIcover:export/1,2\fR\&
.RE
.LP
.B
stop() -> ok | {error,not_main_node}
.br
.RS
.LP
Stops the Cover server and unloads all Cover compiled code\&.
.RE
.LP
.B
stop(Nodes) -> ok | {error,not_main_node}
.br
.RS
.LP
Types:
.RS 3
Nodes = [atom()]
.br
.RE
.RE
.RS
.LP
Stops the Cover server and unloads all Cover compiled code on the given nodes\&. Data stored in the Cover database on the remote nodes is fetched and stored on the main node\&.
.RE
.SH "SEE ALSO"
.LP
code(3erl), compile(3erl)