ae01c8387c
- section about command line argument filtering for template test cases - many typos fixes - remove reference to bjam
282 lines
12 KiB
Plaintext
282 lines
12 KiB
Plaintext
[/
|
|
/ Copyright (c) 2003 Boost.Test contributors
|
|
/
|
|
/ Distributed under the Boost Software License, Version 1.0. (See accompanying
|
|
/ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
|
/]
|
|
|
|
[/ ##################################################################### ]
|
|
|
|
[section:pem 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* 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
|
|
__UTF__, because it allows one to use the
|
|
[link boost_test.testing_tools 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__:
|
|
|
|
[bt_example example24..Hello World with the Program Execution Monitor..run-fail]
|
|
|
|
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:
|
|
|
|
[bt_example example25..Standard exception detection within the __PEM__..run-fail]
|
|
|
|
[note Note that in both examples above we used [link boost_test.components.section_pem.section_pem_compilation.section_pem_full_include header-only variant]
|
|
of the __PEM__. Alternatively the binaries may be built and linked with
|
|
a [link boost_test.components.section_pem.section_pem_compilation.section_pem_standalone standalone library] (in case of static library we are not required to include any __PEM__ related headers).
|
|
]
|
|
|
|
Let's consider an example where function `cpp_main()` had bubbled up a return code of 5:
|
|
|
|
[bt_example example26..Error return code detection of the __PEM__..run-fail]
|
|
|
|
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]
|
|
[section Runtime 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 [classref boost::execution_monitor execution_monitor] class. If you
|
|
want to prevent the __PEM__ 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".]
|
|
]
|
|
|
|
]
|
|
|
|
[note `BOOST_TEST_CATCH_SYSTEM_ERRORS` is similar to the __UTF__'s
|
|
[link boost_test.utf_reference.rt_param_reference.catch_system `catch_system_error`] command line parameter.]
|
|
|
|
[endsect] [/ configuration]
|
|
|
|
[/ #################################################################################### implementation]
|
|
[#ref_pem_implementation][section Implementation]
|
|
|
|
To monitor execution of user supplied function `cpp_main()` the __PEM__ relies on the Boost.Test's
|
|
[link boost_test.components.execution_monitor Execution Monitor]. Also the __PEM__ supplies the function `main()` to facilitate
|
|
uniform error reporting. Following files constitute the __PEM__ implementation:
|
|
|
|
|
|
[table:pem_implementation_file __PEM__ implementation files
|
|
|
|
[
|
|
[File name]
|
|
[Content]
|
|
]
|
|
[
|
|
[`boost/test/impl/execution_monitor.ipp`]
|
|
[provides __EM__ implementation for all supported configurations]
|
|
]
|
|
[
|
|
[`boost/test/impl/cpp_main.ipp`]
|
|
[supplies function `main()` for static library build]
|
|
]
|
|
[
|
|
[`boost/test/included/prg_exec_monitor.hpp`]
|
|
[combines all implementation files into single header to be use as inlined version of component]
|
|
]
|
|
[
|
|
[`boost/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 [link ref_pem_direct_include include the whole implementation
|
|
directly] into your program, for the long term usage the preferable solution is to
|
|
[link ref_pem_stanlone build library once] and reuse it.
|
|
|
|
|
|
[endsect] [/implementation]
|
|
|
|
[section:section_pem_compilation 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
|
|
|
|
# built and link with a [link ref_pem_stanlone standalone library] or
|
|
# include the implementation [link ref_pem_direct_include 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:
|
|
|
|
[table
|
|
[
|
|
[Variable]
|
|
[Usage]
|
|
]
|
|
[
|
|
[__BOOST_TEST_DYN_LINK__]
|
|
[Define this flag to build/use dynamic library]
|
|
]
|
|
[
|
|
[__BOOST_TEST_NO_LIB__]
|
|
[Define this flag to prevent auto-linking]
|
|
]
|
|
]
|
|
|
|
[#ref_pem_stanlone][section:section_pem_standalone 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__ [link ref_pem_implementation 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 ['IDE]s
|
|
(for example ['Microsoft Visual Studio]). The Boost preferred solution is Boost.Build system that is based on top of
|
|
`b2` 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 [link ref_pem_static static] or [link ref_pem_dynamic dynamic] library.
|
|
|
|
|
|
|
|
[#ref_pem_static][section:section_pem_compilation_static 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:
|
|
|
|
``
|
|
b2 -sTOOLS=<your-tool-name> -sBUILD=boost_prg_exec_monitor
|
|
``
|
|
|
|
Also on Windows you can use the Microsoft Visual Studio .NET project file provided.
|
|
|
|
[endsect] [/ static compilation]
|
|
|
|
[#ref_pem_dynamic][section:section_pem_compilation_dynamic 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 __BOOST_TEST_DYN_LINK__ to the list of macro definitions in the
|
|
``libs/test/build`` directory:
|
|
|
|
``
|
|
b2 -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
|
|
__BOOST_TEST_DYN_LINK__ needs to be defined both during dynamic library
|
|
build and during your program compilation.
|
|
]
|
|
|
|
|
|
[endsect] [/ dynamic compilation]
|
|
[endsect] [/ standalone lib compilation]
|
|
|
|
[#ref_pem_auto_link][section Support of the auto-linking feature]
|
|
|
|
|
|
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
|
|
|
|
``
|
|
#include <boost/test/prg_exec_monitor.hpp>
|
|
``
|
|
or header
|
|
|
|
``
|
|
#include <boost/test/included/prg_exec_monitor.hpp>
|
|
``
|
|
|
|
By default the feature is enabled. To disable it you have to define the flag __BOOST_TEST_NO_LIB__.
|
|
|
|
|
|
[endsect] [/ autolink]
|
|
|
|
[#ref_pem_direct_include][section:section_pem_full_include Including the __PEM__ directly into your program]
|
|
|
|
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
|
|
``
|
|
#include <boost/test/included/prg_exec_monitor.hpp>
|
|
``
|
|
|
|
In both variants neither __BOOST_TEST_DYN_LINK__ nor __BOOST_TEST_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.
|
|
|
|
[endsect] [/ direct include]
|
|
|
|
|
|
[endsect] [/compilation]
|
|
|
|
|
|
|
|
[endsect] [/program execution monitor]
|