123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281 |
- [/
- / 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]
|