mirror of
https://github.com/boostorg/test.git
synced 2026-02-17 14:12:08 +00:00
334 lines
14 KiB
Plaintext
334 lines
14 KiB
Plaintext
[section Program Execution Monitor]
|
|
|
|
The components of a C++ program may report user-detected errors in several ways, such as via a return value or
|
|
throwing an exception. System-detected errors such as dereferencing an invalid pointer are reported in other ways,
|
|
totally operating system and compiler dependent.
|
|
|
|
Yet many C++ programs, both production and test, must run in an environment where uniform reporting of errors is
|
|
necessary. For example, converting otherwise uncaught exceptions to non-zero program return codes allows many
|
|
command line, script, or batch environments to continue processing in a controlled manner. Even some
|
|
['GUI] environments benefit from the unification of errors into program return codes.
|
|
|
|
|
|
The Boost.Test Library's ['Program Execution Monitor] (__PEM__ for short) relieves users from messy error
|
|
detection and reporting duties by providing a replacement function `main()` which calls a user-supplied `cpp_main()`
|
|
function within a monitored environment. The supplied `main()` then uniformly detects and reports the occurrence of
|
|
several types of errors, reducing them to a uniform return code which is returned to the host environment.
|
|
|
|
Uniform error reporting is particularly useful for programs running unattended under control of scripts or batch
|
|
files. Some operating systems pop up message boxes if an uncaught exception occurs, and this requires manual
|
|
intervention. By converting such exceptions into non-zero program return codes, the library makes the program a
|
|
better citizen. More uniform reporting of errors isn't a benefit to some programs, particularly programs always
|
|
run by hand of a knowledgeable person. So the __PEM__ wouldn't be worth using in that environment.
|
|
|
|
Uniform error reporting can be also useful in test environments such as the Boost regression tests. Be aware though
|
|
in such case it might be preferable to use the <link linkend="utf">Unit Test Framework</link>, because it allows one
|
|
to use the <link linkend="utf.user-guide.testing-tools">Testing tools</link> and generate more detailed error information.
|
|
|
|
[section Usage]
|
|
|
|
|
|
To facilitate uniform error reporting the __PEM__ supplies function main() as part if it's implementation. To use the
|
|
__PEM__ instead of regular function main your program is required to supply a function cpp_main() with same signature.
|
|
|
|
Here is the traditional ['Hello World] program implemented using the __PEM__:
|
|
|
|
[import examples/example24.cpp]
|
|
[import examples/example24.output]
|
|
[table:id_example24 Hello World with the Program Execution Monitor
|
|
[
|
|
[Code]
|
|
[Output]
|
|
]
|
|
[
|
|
[[example24]]
|
|
[[example24o]]
|
|
]
|
|
]
|
|
|
|
|
|
|
|
It really is that simple - just change the name of your initial function from `main()` to `cpp_main()`. Do make sure
|
|
the `argc` and `argv` parameters are specified (although you don't have to name them if you don't use them).
|
|
|
|
The __PEM__ treats as errors:
|
|
|
|
* Exceptions thrown from `cpp_main()`
|
|
* Non-zero return from `cpp_main()`
|
|
|
|
So what if some function had thrown a `std::runtime_error` with the message "big trouble" and it is not trapped by any
|
|
catch clause? Like in a following example:
|
|
|
|
|
|
[import examples/example25.cpp]
|
|
[import examples/example25.output]
|
|
[table:id_example25 Standard exception detection within the Program Execution Monitor
|
|
[
|
|
[Code]
|
|
[Output]
|
|
]
|
|
[
|
|
[[example25]]
|
|
[[example25o]]
|
|
]
|
|
]
|
|
|
|
[note Note that in both examples above we used single-header variant of the __PEM__. Alternatively we can build and link with
|
|
standalone library. In case of static library we are not required to include any __PEM__ related headers. To use dynamic
|
|
library you are required to include
|
|
|
|
``
|
|
#include <boost/test/prg_exec_monitor.hpp>
|
|
``
|
|
|
|
and define __dynamic_linking__ during program compilation. The same header is required if you want to employ __auto_linking__ feature.
|
|
]
|
|
[warning Move or copy this comment in the compilation part]
|
|
|
|
Let's consider an example where function `cpp_main()` had bubbled up a return code of 5:
|
|
|
|
[import examples/example26.cpp]
|
|
[import examples/example26.output]
|
|
[table:id_example26 Error return code detection of the __PEM__
|
|
[
|
|
[Code]
|
|
[Output]
|
|
]
|
|
[
|
|
[[example26]]
|
|
[[example26o]]
|
|
]
|
|
]
|
|
|
|
The __PEM__ reports errors to both `std::cout` (details) and `std::cerr` (summary). Primary detailed error
|
|
messages appear on standard output stream so that it is properly interlaced with other output, thus aiding error
|
|
analysis. While the final error notification message appears on standard error stream. This increases the
|
|
visibility of error notification if standard output and error streams are directed to different devices or files.
|
|
|
|
The __PEM__'s supplied `main()` will return following result codes:
|
|
|
|
* `boost::exit_success` - no errors
|
|
* `boost::exit_failure` - non-zero and `non-boost::exit_success` return code from `cpp_main()`
|
|
* `boost::exit_exception_failure` - `cpp_main()` throw an exception
|
|
|
|
[endsect] [/ Usage]
|
|
|
|
|
|
|
|
|
|
[section Configuration]
|
|
|
|
There are two aspects of the __PEM__ behavior that you can customize at runtime. Customization is performed using
|
|
environment variables.
|
|
|
|
[table:id_pem_env The __PEM__ configuration environment variables
|
|
[
|
|
[Flag]
|
|
[Usage]
|
|
]
|
|
[
|
|
[`BOOST_TEST_CATCH_SYSTEM_ERRORS`]
|
|
[allows customizing behavior of the __PEM__ in regards of catching system errors. For more details about the
|
|
meaning of this option see the [link ref_execution_monitor Execution Monitor]. If you
|
|
want to prevent the Program Execution Monitor from catching system exception, set the value of this
|
|
variable to "no". The default value is "yes".]
|
|
]
|
|
[
|
|
[`BOOST_PRG_MON_CONFIRM`]
|
|
[allows avoiding success confirmation message. Some users prefer to see a confirmation message in case if program
|
|
successfully executed. While others don't like the clutter or any output is prohibited by organization standards.
|
|
To avoid the message set the value of this variable to "no". The default value is "yes".]
|
|
]
|
|
|
|
]
|
|
|
|
[warning Copy the environment variables into appropriate pages, as for the command line parameters]
|
|
|
|
[endsect] [/ configuration]
|
|
|
|
[section Implementation]
|
|
|
|
To monitor execution of user supplied function `cpp_main()` the __PEM__ relies on the Boost.Test's
|
|
[link ref_execution_monitor Execution Monitor] (['EM] for short). Also the __PEM__ supplies the function `main()` to facilitate
|
|
uniform error reporting. Following files constitute the __PEM__ implementation:
|
|
|
|
<variablelist>
|
|
<?dbhtml list-presentation="list"?>
|
|
|
|
<varlistentry>
|
|
<term><ulink url="../../../../boost/test/impl/execution_monitor.ipp"><filename>boost/test/impl/execution_monitor.ipp</filename></ulink></term>
|
|
<listitem>
|
|
<simpara>
|
|
provides __EM__ implementation for all supported
|
|
configurations.
|
|
</simpara>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry>
|
|
<term><ulink url="../../../../boost/test/impl/cpp_main.ipp"><filename>boost/test/impl/cpp_main.ipp</filename></ulink></term>
|
|
<listitem>
|
|
<simpara>supplies function `main()` for static library build</simpara>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry>
|
|
<term><ulink url="../../../../boost/test/included/prg_exec_monitor.hpp"><filename>boost/test/included/prg_exec_monitor.hpp</filename></ulink></term>
|
|
<listitem>
|
|
<simpara>combines all implementation files into single header to be use as inlined version of component</simpara>
|
|
</listitem>
|
|
</varlistentry>
|
|
|
|
<varlistentry>
|
|
<term><ulink url="../../../../boost/test/prg_exec_monitor.hpp"><filename>boost/test/prg_exec_monitor.hpp</filename></ulink></term>
|
|
<listitem>
|
|
<simpara>
|
|
contains definitions for `main()` function for dynamic library build and pragmas for auto-linking feature support.
|
|
</simpara>
|
|
</listitem>
|
|
</varlistentry>
|
|
</variablelist>
|
|
|
|
|
|
The __PEM__ implementation wraps several system headers and is intended to be used as standalone library. While there
|
|
exist an alternative variant to <link linkend="pem.compilation.direct-include">include the whole implementation
|
|
directly</link> into your program, for the long term usage the preferable solution is to
|
|
<link linkend="pem.compilation.standalone">build library once</link> and reuse it.
|
|
|
|
|
|
[endsect] [/implementation]
|
|
|
|
[section Compilation]
|
|
|
|
In comparison with many other boost libraries, which are completely implemented in header files, compilation and
|
|
linking with the __PEM__ may require additional steps. The __PEM__ presents you with options to either
|
|
<link linkend="pem.compilation.standalone">built and link with a standalone library</link> or
|
|
<link linkend="pem.compilation.direct-include">include the implementation directly</link> into your
|
|
program. If you opt to use the library the __PEM__ header implements the
|
|
<link linkend="pem.compilation.auto-linking">auto-linking support</link> and following flags can be used to configure
|
|
compilation of the __PEM__ library and your program:
|
|
|
|
<table id="pem.compilation.flags">
|
|
<title>__PEM__ compilation flags</title>
|
|
<tgroup cols="2">
|
|
<colspec colname="c1"/>
|
|
<colspec colname="c3"/>
|
|
<thead>
|
|
<row>
|
|
<entry>Variable</entry>
|
|
<entry>Usage</entry>
|
|
</row>
|
|
</thead>
|
|
<tbody>
|
|
<row>
|
|
<entry id="pem.flag.dyn-link">BOOST_TEST_DYN_LINK</entry>
|
|
<entry>Define this flag to build/use dynamic library.</entry>
|
|
</row>
|
|
<row>
|
|
<entry id="pem.flag.no-lib">BOOST_TEST_NO_LIB</entry>
|
|
<entry>Define this flag to prevent auto-linking.</entry>
|
|
</row>
|
|
</tbody>
|
|
</tgroup>
|
|
</table>
|
|
|
|
<section id="pem.compilation.standalone">
|
|
<title>Standalone library compilation</title>
|
|
|
|
If you opted to link your program with the standalone library, you need to build it first. To build a standalone
|
|
library all C++ files (.cpp), that constitute __PEM__ <link linkend="pem.impl">implementation</link> need to be
|
|
listed as source files in your makefile [footnote There are varieties of make systems that can be used. To name
|
|
a few: <acronym>GNU</acronym> make (and other make clones) and build systems integrated into <acronym>IDE</acronym>s
|
|
(for example Microsoft Visual Studio). The Boost preferred solution is Boost.Build system that is based on top of
|
|
bjam tool. Make systems require some kind of configuration file that lists all files that constitute the library
|
|
and all build options. For example the makefile that is used by make, or the Microsoft Visual Studio project file,
|
|
Jamfile is used by Boost.Build. For the sake of simplicity let's call this file the makefile.].
|
|
|
|
|
|
The makefile for use with Boost.Build system is supplied in <filename class="directory">libs/test/build</filename>
|
|
directory. The __PEM__ can be built as either <link linkend="pem.compilation.standalone.static">static</link>
|
|
or <link linkend="pem.compilation.standalone.dynamic">dynamic</link> library.
|
|
|
|
|
|
|
|
<section id="pem.compilation.standalone.static">
|
|
<title>Static library compilation</title>
|
|
|
|
There are no additional build defines or options required to build static library. Using Boost.Build system you
|
|
can build the static library with a following command from libs/test/build directory:
|
|
|
|
<cmdsynopsis>
|
|
<!-- TO FIX -->
|
|
<command>bjam</command>
|
|
<arg>-sTOOLS=<your-tool-name></arg>
|
|
<arg choice="req">-sBUILD=boost_prg_exec_monitor</arg>
|
|
</cmdsynopsis>
|
|
|
|
Also on Windows you can use the Microsoft Visual Studio .NET project file provided.
|
|
|
|
</section>
|
|
|
|
<section id="pem.compilation.standalone.dynamic">
|
|
<title>Dynamic library compilation</title>
|
|
|
|
|
|
To build the dynamic library [footnote What is meant by the term dynamic library is a <firstterm>dynamically
|
|
loaded library</firstterm>, alternatively called a <firstterm>shared library</firstterm>.] you
|
|
need to add <xref linkend="pem.flag.dyn-link" endterm="pem.flag.dyn-link"/> to the list of macro definitions in the
|
|
makefile. Using the Boost.Build system you can build the dynamic library with the following command from
|
|
<filename class="directory">libs/test/build</filename> directory:
|
|
|
|
<cmdsynopsis>
|
|
<!-- TO FIX -->
|
|
<command>bjam</command>
|
|
<arg>-sTOOLS=<your-tool-name></arg>
|
|
<arg choice="req">-sBUILD=boost_prg_exec_monitor</arg>
|
|
</cmdsynopsis>
|
|
|
|
Also on Windows you can use the Microsoft Visual Studio .NET project file provided.
|
|
|
|
[caution
|
|
For your program to successfully link with the dynamic library the flag
|
|
<xref linkend="pem.flag.dyn-link" endterm="pem.flag.dyn-link"/> needs to be defined both during dynamic library
|
|
build and during your program compilation.
|
|
]
|
|
|
|
|
|
</section>
|
|
</section>
|
|
|
|
<section id="pem.compilation.auto-linking">
|
|
<title>Support of the auto-linking feature</title>
|
|
<titleabbrev>Auto-linking support</titleabbrev>
|
|
|
|
For the Microsoft family of compilers the __PEM__ provides an ability to automatically select proper library name
|
|
and add it to the list of objects to be linked with. To employ this feature you required to include either header
|
|
<ulink url="../../../../boost/test/prg_exec_monitor.hpp"><filename>boost/test/prg_exec_monitor.hpp</filename></ulink>
|
|
or header
|
|
<ulink url="../../../../boost/test/included/prg_exec_monitor.hpp"><filename>boost/test/included/prg_exec_monitor.hpp</filename></ulink>
|
|
By default the feature is going to be enabled. To disable it you have to define the flag
|
|
<xref linkend="pem.flag.no-lib" endterm="pem.flag.no-lib"/>.
|
|
|
|
For more details on the auto-linking feature implementation and configuration you should consult the
|
|
<ulink url="under_construction.html">appropriate documentation</ulink>.
|
|
</section>
|
|
|
|
<section id="pem.compilation.direct-include">
|
|
<title>Including the __PEM__ directly into your program</title>
|
|
<titleabbrev>Direct include</titleabbrev>
|
|
|
|
If you prefer to avoid the standalone library compilation you have two alternative usage variants: you can either
|
|
include all files that constitute the static library in your program's makefile or include them as a part of
|
|
your program's source file. To facilitate the later variant the __PEM__ implementation presents the header
|
|
<ulink url="../../../../boost/test/included/prg_exec_monitor.hpp"><filename>boost/test/included/prg_exec_monitor.hpp</filename></ulink>
|
|
In both variants neither <xref linkend="pem.flag.dyn-link" endterm="pem.flag.dyn-link"/> nor
|
|
<xref linkend="pem.flag.no-lib" endterm="pem.flag.no-lib"/> are applicable. This solution may not be the best choice
|
|
in a long run, since it requires the __PEM__ sources recompilation for every program you use it with.
|
|
|
|
|
|
</section>
|
|
[endsect] [/compilation]
|
|
|
|
|
|
|
|
[endsect] [/program execution monitor] |