program_execution_monitor.qbk 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281
  1. [/
  2. / Copyright (c) 2003 Boost.Test contributors
  3. /
  4. / Distributed under the Boost Software License, Version 1.0. (See accompanying
  5. / file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  6. /]
  7. [/ ##################################################################### ]
  8. [section:pem Program Execution Monitor]
  9. The components of a C++ program may report user-detected errors in several ways, such as via a return value or
  10. throwing an exception. System-detected errors such as dereferencing an invalid pointer are reported in other ways,
  11. totally operating system and compiler dependent.
  12. Yet many C++ programs, both production and test, must run in an environment where uniform reporting of errors is
  13. necessary. For example, converting otherwise uncaught exceptions to non-zero program return codes allows many
  14. command line, script, or batch environments to continue processing in a controlled manner. Even some
  15. ['GUI] environments benefit from the unification of errors into program return codes.
  16. The Boost.Test Library's *Program Execution Monitor* relieves users from messy error
  17. detection and reporting duties by providing a replacement function `main()` which calls a user-supplied `cpp_main()`
  18. function within a monitored environment. The supplied `main()` then uniformly detects and reports the occurrence of
  19. several types of errors, reducing them to a uniform return code which is returned to the host environment.
  20. Uniform error reporting is particularly useful for programs running unattended under control of scripts or batch
  21. files. Some operating systems pop up message boxes if an uncaught exception occurs, and this requires manual
  22. intervention. By converting such exceptions into non-zero program return codes, the library makes the program a
  23. better citizen. More uniform reporting of errors isn't a benefit to some programs, particularly programs always
  24. run by hand of a knowledgeable person. So the __PEM__ wouldn't be worth using in that environment.
  25. Uniform error reporting can be also useful in test environments such as the Boost
  26. regression tests. Be aware though in such case it might be preferable to use the
  27. __UTF__, because it allows one to use the
  28. [link boost_test.testing_tools testing tools] and generate more detailed
  29. error information.
  30. [section Usage]
  31. To facilitate uniform error reporting the __PEM__ supplies function `main()` as part if it's implementation. To use the
  32. __PEM__ instead of regular function `main` your program is required to supply a function `cpp_main()` with same signature.
  33. Here is the traditional ['Hello World] program implemented using the __PEM__:
  34. [bt_example example24..Hello World with the Program Execution Monitor..run-fail]
  35. It really is that simple - just change the name of your initial function from `main()` to `cpp_main()`. Do make sure
  36. the `argc` and `argv` parameters are specified (although you don't have to name them if you don't use them).
  37. The __PEM__ treats as errors:
  38. * Exceptions thrown from `cpp_main()`
  39. * Non-zero return from `cpp_main()`
  40. So what if some function had thrown a `std::runtime_error` with the message "big trouble" and it is not trapped by any
  41. catch clause? Like in a following example:
  42. [bt_example example25..Standard exception detection within the __PEM__..run-fail]
  43. [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]
  44. of the __PEM__. Alternatively the binaries may be built and linked with
  45. 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).
  46. ]
  47. Let's consider an example where function `cpp_main()` had bubbled up a return code of 5:
  48. [bt_example example26..Error return code detection of the __PEM__..run-fail]
  49. The __PEM__ reports errors to both `std::cout` (details) and `std::cerr` (summary). Primary detailed error
  50. messages appear on standard output stream so that it is properly interlaced with other output, thus aiding error
  51. analysis. While the final error notification message appears on standard error stream. This increases the
  52. visibility of error notification if standard output and error streams are directed to different devices or files.
  53. The __PEM__'s supplied `main()` will return following result codes:
  54. * `boost::exit_success` - no errors
  55. * `boost::exit_failure` - non-zero and `non-boost::exit_success` return code from `cpp_main()`
  56. * `boost::exit_exception_failure` - `cpp_main()` throw an exception
  57. [endsect] [/ Usage]
  58. [/ #################################################################################### configuration]
  59. [section Runtime configuration]
  60. There are two aspects of the __PEM__ behavior that you can customize at runtime. Customization is performed using
  61. environment variables.
  62. [table:id_pem_env The __PEM__ configuration environment variables
  63. [
  64. [Flag]
  65. [Usage]
  66. ]
  67. [
  68. [`BOOST_TEST_CATCH_SYSTEM_ERRORS`]
  69. [allows customizing behavior of the __PEM__ in regards of catching system errors. For more details about the
  70. meaning of this option see the [classref boost::execution_monitor execution_monitor] class. If you
  71. want to prevent the __PEM__ from catching system exception, set the value of this
  72. variable to "no". The default value is "yes".]
  73. ]
  74. [
  75. [`BOOST_PRG_MON_CONFIRM`]
  76. [allows avoiding success confirmation message. Some users prefer to see a confirmation message in case if program
  77. successfully executed. While others don't like the clutter or any output is prohibited by organization standards.
  78. To avoid the message set the value of this variable to "no". The default value is "yes".]
  79. ]
  80. ]
  81. [note `BOOST_TEST_CATCH_SYSTEM_ERRORS` is similar to the __UTF__'s
  82. [link boost_test.utf_reference.rt_param_reference.catch_system `catch_system_error`] command line parameter.]
  83. [endsect] [/ configuration]
  84. [/ #################################################################################### implementation]
  85. [#ref_pem_implementation][section Implementation]
  86. To monitor execution of user supplied function `cpp_main()` the __PEM__ relies on the Boost.Test's
  87. [link boost_test.components.execution_monitor Execution Monitor]. Also the __PEM__ supplies the function `main()` to facilitate
  88. uniform error reporting. Following files constitute the __PEM__ implementation:
  89. [table:pem_implementation_file __PEM__ implementation files
  90. [
  91. [File name]
  92. [Content]
  93. ]
  94. [
  95. [`boost/test/impl/execution_monitor.ipp`]
  96. [provides __EM__ implementation for all supported configurations]
  97. ]
  98. [
  99. [`boost/test/impl/cpp_main.ipp`]
  100. [supplies function `main()` for static library build]
  101. ]
  102. [
  103. [`boost/test/included/prg_exec_monitor.hpp`]
  104. [combines all implementation files into single header to be use as inlined version of component]
  105. ]
  106. [
  107. [`boost/test/prg_exec_monitor.hpp`]
  108. [contains definitions for `main()` function for dynamic library build and pragmas for auto-linking feature support]
  109. ]
  110. ]
  111. The __PEM__ implementation wraps several system headers and is intended to be used as standalone library. While there
  112. exist an alternative variant to [link ref_pem_direct_include include the whole implementation
  113. directly] into your program, for the long term usage the preferable solution is to
  114. [link ref_pem_stanlone build library once] and reuse it.
  115. [endsect] [/implementation]
  116. [section:section_pem_compilation Compilation]
  117. In comparison with many other boost libraries, which are completely implemented in header files, compilation and
  118. linking with the __PEM__ may require additional steps. The __PEM__ presents you with options to either
  119. # built and link with a [link ref_pem_stanlone standalone library] or
  120. # include the implementation [link ref_pem_direct_include directly] into your program.
  121. If you opt to use the library the __PEM__ header implements the
  122. [*auto-linking support] and following flags can be used to configure
  123. compilation of the __PEM__ library and your program:
  124. [table
  125. [
  126. [Variable]
  127. [Usage]
  128. ]
  129. [
  130. [__BOOST_TEST_DYN_LINK__]
  131. [Define this flag to build/use dynamic library]
  132. ]
  133. [
  134. [__BOOST_TEST_NO_LIB__]
  135. [Define this flag to prevent auto-linking]
  136. ]
  137. ]
  138. [#ref_pem_stanlone][section:section_pem_standalone Standalone library compilation]
  139. If you opted to link your program with the standalone library, you need to build it first. To build a standalone
  140. library all C++ files (.cpp), that constitute __PEM__ [link ref_pem_implementation implementation] need to be
  141. listed as source files in your makefile [footnote There are varieties of make systems that can be used. To name
  142. a few: ['GNU] make (and other make clones) and build systems integrated into ['IDE]s
  143. (for example ['Microsoft Visual Studio]). The Boost preferred solution is Boost.Build system that is based on top of
  144. `b2` tool. Make systems require some kind of configuration file that lists all files that constitute the library
  145. and all build options. For example the makefile that is used by make, or the Microsoft Visual Studio project file,
  146. Jamfile is used by Boost.Build. For the sake of simplicity let's call this file the makefile.].
  147. The makefile for use with Boost.Build system is supplied in
  148. ``
  149. libs/test/build
  150. ``
  151. directory. The __PEM__ can be built as either [link ref_pem_static static] or [link ref_pem_dynamic dynamic] library.
  152. [#ref_pem_static][section:section_pem_compilation_static Static library compilation]
  153. There are no additional build defines or options required to build static library. Using Boost.Build system you
  154. can build the static library with a following command from `libs/test/build` directory:
  155. ``
  156. b2 -sTOOLS=<your-tool-name> -sBUILD=boost_prg_exec_monitor
  157. ``
  158. Also on Windows you can use the Microsoft Visual Studio .NET project file provided.
  159. [endsect] [/ static compilation]
  160. [#ref_pem_dynamic][section:section_pem_compilation_dynamic Dynamic library compilation]
  161. To build the dynamic library [footnote What is meant by the term dynamic library is a ['dynamically
  162. loaded library], alternatively called a ['shared library].] you
  163. need to add __BOOST_TEST_DYN_LINK__ to the list of macro definitions in the
  164. ``libs/test/build`` directory:
  165. ``
  166. b2 -sTOOLS=<your-tool-name> -sBUILD=boost_prg_exec_monitor
  167. ``
  168. Also on Windows you can use the Microsoft Visual Studio .NET project file provided.
  169. [caution
  170. For your program to successfully link with the dynamic library the flag
  171. __BOOST_TEST_DYN_LINK__ needs to be defined both during dynamic library
  172. build and during your program compilation.
  173. ]
  174. [endsect] [/ dynamic compilation]
  175. [endsect] [/ standalone lib compilation]
  176. [#ref_pem_auto_link][section Support of the auto-linking feature]
  177. For the Microsoft family of compilers the __PEM__ provides an ability to automatically select proper library name
  178. and add it to the list of objects to be linked with. To employ this feature you required to include either header
  179. ``
  180. #include <boost/test/prg_exec_monitor.hpp>
  181. ``
  182. or header
  183. ``
  184. #include <boost/test/included/prg_exec_monitor.hpp>
  185. ``
  186. By default the feature is enabled. To disable it you have to define the flag __BOOST_TEST_NO_LIB__.
  187. [endsect] [/ autolink]
  188. [#ref_pem_direct_include][section:section_pem_full_include Including the __PEM__ directly into your program]
  189. If you prefer to avoid the standalone library compilation you have two alternative usage variants: you can either
  190. include all files that constitute the static library in your program's makefile or include them as a part of
  191. your program's source file. To facilitate the later variant the __PEM__ implementation presents the header
  192. ``
  193. #include <boost/test/included/prg_exec_monitor.hpp>
  194. ``
  195. In both variants neither __BOOST_TEST_DYN_LINK__ nor __BOOST_TEST_NO_LIB__ are applicable. This solution may not be the best choice
  196. in a long run, since it requires the __PEM__ sources recompilation for every program you use it with.
  197. [endsect] [/ direct include]
  198. [endsect] [/compilation]
  199. [endsect] [/program execution monitor]