[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 &pem; 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 Unit Test Framework, cause it allows one
to use the Testing tools 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;:
The &pem;: Hello World
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 runtime_error with the message "big trouble" and it's not trapped by any
catch clause? Like in a following example:
The &pem;: standard exception detection
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
``
and define __dynamic_linking__ during program compilation. The same header is required if you want to employ __auto_linking__ feature.
Let's consider an example where function `cpp_main()` had bubbled up a return code of 5:
The &pem;: error return code detection
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]
Configuration
There are two aspects of the &pem; behavior that you can customize at runtime. Customization is performed using
environment variables.
The &pem; configuration environment variablesFlagUsageBOOST_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 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".
The &pem; implementationImplementation
To monitor execution of user supplied function `cpp_main()` the &pem; relies on the Boost.Test's
Execution Monitor. Also the &pem; supplies the function main() to facilitate
uniform error reporting. Following files constitute the &pem; implementation:
boost/test/impl/execution_monitor.ipp
provides Execution Monitor implementation for all supported
configurations.
boost/test/impl/cpp_main.ippsupplies function main() for static library buildboost/test/included/prg_exec_monitor.hppcombines all implementation files into single header to be use as inlined version of componentboost/test/prg_exec_monitor.hpp
contains definitions for main() function for dynamic library build and pragmas for auto-linking feature support.
The &pem; implementation wraps several system headers and is intended to be used as standalone library. While there
exist an alternative variant to include the whole implementation
directly into your program, for the long term usage the preferable solution is to
build library once and reuse it.
The &pem; compilationCompilation
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
built and link with a standalone library or
include the implementation directly into your
program. If you opt to use the library the &pem; header implements the
auto-linking support and following flags can be used to configure
compilation of the &pem; library and your program:
&pem; compilation flagsVariableUsageBOOST_TEST_DYN_LINKDefine this flag to build/use dynamic library.BOOST_TEST_NO_LIBDefine this flag to prevent auto-linking.
Standalone library compilation
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; implementation 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: GNU make (and other make clones) and build systems integrated into IDEs
(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 libs/test/build
directory. The &pem; can be built as either static
or dynamic library.
Static library compilation
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:
bjam-sTOOLS=<your-tool-name>-sBUILD=boost_prg_exec_monitor
Also on Windows you can use the Microsoft Visual Studio .NET project file provided.
Dynamic library compilation
To build the dynamic library [footnote What is meant by the term dynamic library is a dynamically
loaded library, alternatively called a shared library.] you
need to add 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
libs/test/build directory:
bjam-sTOOLS=<your-tool-name>-sBUILD=boost_prg_exec_monitor
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
needs to be defined both during dynamic library
build and during your program compilation.
]
Support of the auto-linking featureAuto-linking support
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
boost/test/prg_exec_monitor.hpp
or header
boost/test/included/prg_exec_monitor.hpp
By default the feature is going to be enabled. To disable it you have to define the flag
.
For more details on the auto-linking feature implementation and configuration you should consult the
appropriate documentation.
Including the &pem; directly into your programDirect include
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
boost/test/included/prg_exec_monitor.hpp
In both variants neither nor
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.
[endsect] [/program execution monitor]