mirror of
https://github.com/boostorg/test.git
synced 2026-02-17 14:12:08 +00:00
450 lines
19 KiB
XML
450 lines
19 KiB
XML
<?xml version="1.0" encoding="utf-8"?>
|
|
<!DOCTYPE part PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "../../../../tools/boostbook/dtd/boostbook.dtd" [
|
|
<!ENTITY utf "<acronym>UTF</acronym>">
|
|
]>
|
|
[#ref_execution_monitor][section The Execution Monitor]
|
|
|
|
<section id="execution-monitor.intro">
|
|
<title/>
|
|
|
|
|
|
Sometimes we need to call a function and make sure that no user or system originated exceptions are being thrown
|
|
by it. Uniform exception reporting is also may be convenient. That's the purpose of the Boost.Test's
|
|
<firstterm>Execution Monitor</firstterm>.
|
|
|
|
The Execution Monitor is a lower-level component of the Boost Test Library. It is the base for implementing all
|
|
other Boost.Test components, but also can be used standalone to get controlled execution of error-prone functions
|
|
with a uniform error notification. The Execution Monitor calls a user-supplied function in a controlled
|
|
environment, relieving users from messy error detection.
|
|
|
|
The Execution Monitor usage is demonstrated in the example exec_mon_example <!-- TO FIX: link to example -->. Additional examples are
|
|
in <xref linkend="pem"/> or <xref linkend="utf"/>.
|
|
|
|
<section id="execution-monitor.design">
|
|
<title>Design Rationale</title>
|
|
|
|
|
|
The Execution Monitor design assumes that it can be used when no (or almost no) memory available. Also the
|
|
Execution Monitor is intended to be portable to as many platforms as possible.
|
|
</section>
|
|
</section>
|
|
|
|
<section id="execution-monitor.compilation">
|
|
<title>The Execution Monitor compilation variants and procedures</title>
|
|
<titleabbrev>Compilation</titleabbrev>
|
|
|
|
<section id="execution-monitor.impl">
|
|
<title>Implementation</title>
|
|
|
|
|
|
The Execution Monitor is implemented in two modules: one header file and one source file.
|
|
|
|
<variablelist>
|
|
<?dbhtml term-separator=": "?>
|
|
<?dbhtml list-presentation="list"?>
|
|
|
|
<varlistentry>
|
|
<term><filename>boost/test/execution_monitor.hpp</filename></term>
|
|
<listitem>
|
|
<simpara>
|
|
defines abstract execution monitor interfaces and implements execution exception.
|
|
</simpara>
|
|
</listitem>
|
|
</varlistentry>
|
|
<varlistentry>
|
|
<term><ulink url="../../../../boost/test/impl/execution_monitor.ipp"><filename>boost/test/impl/execution_monitor.ipp</filename></ulink></term>
|
|
<listitem>
|
|
<simpara>
|
|
provides the Execution Monitor implementation for all supported configurations, including Microsoft structured
|
|
exception based, UNIX signals.
|
|
</simpara>
|
|
</listitem>
|
|
</varlistentry>
|
|
</variablelist>
|
|
|
|
You may use this component in both debug and release modes, but in release mode the Execution Monitor won't
|
|
catch Microsoft C runtime debug events.
|
|
</section>
|
|
|
|
<section id="execution-monitor.lib-compilation">
|
|
<title>Standalone library compilation</title>
|
|
|
|
To compile the Execution Monitor as standalone library compose it using only
|
|
<filename>execution_monitor.cpp</filename> as a source file. Alternatively you can add this file directly to the
|
|
list of source files for your project. Boost Test Library's components include this file as a part of their
|
|
compilation procedure.
|
|
</section>
|
|
|
|
<section id="execution-monitor.direct-include">
|
|
<title>Direct include</title>
|
|
|
|
In some cases you may want to include the source file along with header file into your sources. But be aware that
|
|
to be able to catch all kinds of standard exceptions and to implement signal handling logic this file will bring
|
|
a lot of dependencies.
|
|
</section>
|
|
</section>
|
|
|
|
<section id="execution-monitor.user-guide">
|
|
<title>The Execution Monitor user's guide</title>
|
|
<titleabbrev>User's guide</titleabbrev>
|
|
|
|
The Execution Monitor is designed to solve the problem of executing potentially dangerous function that may result
|
|
in any number of error conditions, in monitored environment that should prevent any undesirable exceptions to
|
|
propagate out of function call and produce consistent result report for all
|
|
<link linkend="execution-monitor.user-guide.monitor-outcomes">outcomes</link>. The Execution Monitor is able to
|
|
produce informative report for all standard C++ exceptions and intrinsic types. All other exceptions are reported as
|
|
unknown. If you prefer different message for your exception class or need to perform any action, the Execution
|
|
Monitor supports <link linkend="execution-monitor.user-guide.errors-reporting">custom exception translators</link>.
|
|
There are several other <link linkend="execution-monitor.user-guide.monitor-params">parameters</link> of the
|
|
monitored environment can be configured by setting appropriate properties of the Execution Monitor.
|
|
|
|
All symbols in the Execution Monitor implementation are located in the namespace boost. To use the Execution
|
|
Monitor you need to:
|
|
|
|
<using-namespace name="boost"/>
|
|
|
|
<orderedlist>
|
|
<listitem>
|
|
<simpara>
|
|
#include <<ulink url="../../../../boost/test/execution_monitor.hpp"><filename>boost/test/execution_monitor.hpp</filename></ulink>>
|
|
</simpara>
|
|
</listitem>
|
|
<listitem>
|
|
<simpara>Make an instance of <classname>execution_monitor</classname></simpara>
|
|
</listitem>
|
|
<listitem>
|
|
<simpara>
|
|
Optionally register custom exception translators for exception classes which require special processing.
|
|
</simpara>
|
|
</listitem>
|
|
</orderedlist>
|
|
|
|
<section id="execution-monitor.user-guide.monitor-outcomes">
|
|
<title>Monitored function execution</title>
|
|
|
|
To start the monitored function, invoke the method <methodname>execution_monitor::execute</methodname> and pass
|
|
the monitored function as an argument. If the call succeeds, the method returns the result code produced by the
|
|
monitored function. If any of the following conditions occur:
|
|
|
|
<itemizedlist>
|
|
<listitem>
|
|
<simpara>Uncaught C++ exception.</simpara>
|
|
</listitem>
|
|
<listitem>
|
|
<simpara>Hardware or software signal, trap, or other exception.</simpara>
|
|
</listitem>
|
|
<listitem>
|
|
<simpara>Timeout reached.</simpara>
|
|
</listitem>
|
|
<listitem>
|
|
<simpara>Debug assert event occurred (under Microsoft Visual C++ or compatible compiler).</simpara>
|
|
</listitem>
|
|
</itemizedlist>
|
|
|
|
<simpara>
|
|
then the method throws the <classname>execution_exception</classname>. The exception contains unique
|
|
<enumname>error_code</enumname> value identifying the error condition and the detailed message that can be used to report
|
|
the error.
|
|
</simpara>
|
|
</section>
|
|
|
|
<section id="execution-monitor.user-guide.monitor-params">
|
|
<title>The execution monitor parameters</title>
|
|
|
|
All parameters are implemented as public read-write properties of class <classname>execution_monitor</classname>.
|
|
|
|
The <firstterm>p_catch_system_errors</firstterm> property is a boolean flag (default value is true) specifying whether
|
|
or not <classname>execution_monitor</classname> should trap system level exceptions (second category in above list).
|
|
Set this property to false, for example, if you wish to force coredump file creation. The Unit Test Framework
|
|
provides a runtime parameter --catch_system_errors=yes to alter the behavior in monitored test cases.
|
|
|
|
|
|
The <firstterm>p_auto_start_dbg</firstterm> property is a boolean flag (default value is false) specifying whether or
|
|
not <classname>execution_monitor</classname> should try to attach debugger in case system error is caught.
|
|
|
|
The <firstterm>p_timeout property</firstterm> is an integer timeout (in seconds) for monitored function execution. Use
|
|
this parameter to monitor code with possible deadlocks or indefinite loops. This feature is only available for some
|
|
operating systems (not yet Microsoft Windows).
|
|
|
|
The <firstterm>p_use_alt_stack</firstterm> property is a boolean flag (default value is false) specifying whether or
|
|
not <classname>execution_monitor</classname> should use an alternative stack for the
|
|
<functionname>sigaction</functionname> based signal catching. When enabled the signals are delivered to the
|
|
<classname>execution_monitor</classname> on a stack different from current execution stack, which is safer in case
|
|
if it is corrupted by monitored function. For more details on alternative stack handling see appropriate
|
|
<ulink url="http://www.opengroup.org/onlinepubs/000095399/functions/sigaltstack.html">manuals</ulink>.
|
|
|
|
The <firstterm>p_detect_fp_exceptions</firstterm> property is a boolean flag (default value is false) specifying
|
|
whether or not <classname>execution_monitor</classname> should install hardware traps for the floating point
|
|
exception on platforms where it's supported.
|
|
|
|
</section>
|
|
|
|
<section id="execution-monitor.user-guide.errors-reporting">
|
|
<title>Errors reporting and translation</title>
|
|
If you need to report an error inside monitored function execution you have to throw an exception. Do not use the
|
|
<classname>execution_exception</classname> - it's not intended to be used for this purpose. The simplest choice is
|
|
to use one of the following C++ types as an exception:
|
|
|
|
<itemizedlist>
|
|
<listitem>
|
|
<simpara>C string.</simpara>
|
|
</listitem>
|
|
<listitem>
|
|
<simpara>std:string.</simpara>
|
|
</listitem>
|
|
<listitem>
|
|
<simpara>any exception class in std::exception hierarchy.</simpara>
|
|
</listitem>
|
|
</itemizedlist>
|
|
|
|
In case if you prefer to use your own exception classes or can't govern what exceptions are generated by monitored
|
|
function and would like to see proper error message in a report, the Execution Monitor allows you to register the
|
|
translator for any exception class. You can register as many independent translators as you like. See
|
|
<classname>execution_monitor</classname> specification for requirements on translator function. Also see below
|
|
for usage example.
|
|
|
|
Finally, if you need to abort the monitored function execution without reporting any errors, you can throw an
|
|
exception <classname>execution_aborted</classname>. As a result the execution is aborted and zero result code
|
|
is produced by the method <methodname>execution_monitor::execute</methodname>.
|
|
|
|
</section>
|
|
|
|
<section id="execution-monitor.user-guide.mem-leaks-detection">
|
|
<title>Memory leaks detection</title>
|
|
|
|
The Execution Monitor provides a limited ability to detect memory leaks during program execution, and to
|
|
break program execution on specific memory allocation order-number (1 - first allocation of memory in program, 2 -
|
|
second and so on). Unfortunately this feature is, at the moment, implemented only for the Microsoft family of
|
|
compilers (and Intel, if it employs Microsoft C Runtime Library). Also it can not be tuned per instance of the
|
|
monitor and is only triggered globally and reported after the whole program execution is done. In a future this
|
|
ought to be improved. An interface is composed from two free functions residing in namespace boost::debug:
|
|
|
|
<!-- TO FIX -->
|
|
<programlisting>void detect_memory_leaks( bool on_off );
|
|
void break_memory_alloc( long mem_alloc_order_num );</programlisting>
|
|
|
|
Use function detect_memory_leaks to switch memory leaks detection on/off. Use break_memory_alloc to break a
|
|
program execution at allocation specified by mem_alloc_order_num argument. The Unit Test Framework
|
|
provides a runtime parameter (--detect_memory_leaks=0 or 1 or N>1, where N is memory allocation number)
|
|
allowing you to manage this feature during monitored unit tests.
|
|
</section>
|
|
</section>
|
|
|
|
<library-reference id="execution-monitor.reference">
|
|
<title>The Execution Monitor reference</title>
|
|
<titleabbrev>Reference</titleabbrev>
|
|
|
|
<header name="boost/test/execution_monitor.hpp">
|
|
<namespace name="boost">
|
|
|
|
<class name="execution_monitor">
|
|
<purpose>
|
|
uniformly detects and reports the occurrence of several types of signals and exceptions, reducing various errors
|
|
to a uniform <classname>execution_exception</classname> that is returned to a caller
|
|
</purpose>
|
|
|
|
<data-member name="p_catch_system_errors">
|
|
<type><classname>unit_test::readwrite_property</classname><bool></type>
|
|
|
|
<!-- TO FIX: init value? -->
|
|
|
|
<!-- TO FIX -->
|
|
<purpose>
|
|
Specifies whether the monitor should try to catch system errors/exceptions that would cause program to crash in
|
|
regular case.
|
|
</purpose>
|
|
</data-member>
|
|
|
|
<data-member name="p_auto_start_dbg">
|
|
<type><classname>unit_test::readwrite_property</classname><bool></type>
|
|
|
|
<!-- TO FIX -->
|
|
<purpose>
|
|
Specifies whether the monitor should try to attach debugger in case of caught system error.
|
|
</purpose>
|
|
</data-member>
|
|
|
|
<data-member name="p_timeout">
|
|
<type><classname>unit_test::readwrite_property</classname><int></type>
|
|
|
|
<!-- TO FIX -->
|
|
<purpose>
|
|
Specifies the seconds that elapse before a timer_error occurs. May be ignored on some platforms.
|
|
</purpose>
|
|
</data-member>
|
|
|
|
<data-member name="p_use_alt_stack">
|
|
<type><classname>unit_test::readwrite_property</classname><int></type>
|
|
|
|
<!-- TO FIX -->
|
|
<purpose>
|
|
Specifies whether the monitor should use alternative stack for the signal catching.
|
|
</purpose>
|
|
</data-member>
|
|
|
|
<data-member name="p_detect_fp_exceptions">
|
|
<type><classname>unit_test::readwrite_property</classname><bool></type>
|
|
|
|
<!-- TO FIX -->
|
|
<purpose>
|
|
Specifies whether or not <classname>execution_monitor</classname> should install hardware traps for the floating
|
|
point exception.
|
|
</purpose>
|
|
</data-member>
|
|
|
|
<constructor>
|
|
<throws><simpara>Nothing.</simpara></throws>
|
|
|
|
<effects><simpara>Constructs <classname>execution_monitor</classname> object.</simpara></effects>
|
|
</constructor>
|
|
|
|
<method-group name="execution">
|
|
<method name="execute">
|
|
<parameter name="F">
|
|
<paramtype><classname>unit_test::callback0</classname><int> const&</paramtype>
|
|
<description>zero arity function to be monitored</description> <!-- TO FIX -->
|
|
</parameter>
|
|
|
|
<type>int</type>
|
|
|
|
<returns><simpara>Value returned by monitored function F call.</simpara></returns>
|
|
|
|
<throws>
|
|
<simpara>
|
|
<classname>execution_exception</classname> on detected uncaught C++ exception, a hardware or software signal,
|
|
trap, or other monitored function F premature failure.
|
|
</simpara>
|
|
</throws>
|
|
|
|
<notes><simpara>method execute doesn't consider it an error for F to return a non-zero value</simpara></notes>
|
|
</method>
|
|
</method-group>
|
|
|
|
<method-group name="registration">
|
|
<method name="register_exception_translator">
|
|
<template>
|
|
<template-type-parameter name="Exception"/>
|
|
<template-type-parameter name="ExceptionTranslator"/><!-- TO FIX: how to specify parameter concept? -->
|
|
</template>
|
|
|
|
<parameter name="tr">
|
|
<paramtype>ExceptionTranslator const&</paramtype>
|
|
</parameter>
|
|
|
|
<parameter name="dummy">
|
|
<paramtype><classname>boost::type</classname><Exception>*</paramtype>
|
|
<default>0</default>
|
|
</parameter>
|
|
|
|
<type>void</type>
|
|
|
|
<throws><simpara>Nothing.</simpara></throws>
|
|
|
|
<purpose>register custom (user supplied) exception translator</purpose> <!-- TO FIX: where it is? -->
|
|
|
|
<effects>
|
|
<simpara>
|
|
Registers translator function tr for an exception of type Exception. Translators get chained, so you can
|
|
register as many as you want. The Exception type needs to be specified explicitly as the member function
|
|
template argument. The translator function gets called when an exception of type Exception is thrown from
|
|
within the monitored function. The translator receives a thrown exception object as its first argument.
|
|
Result value of translator is ignored and no exception is reported if this function exits normally. But you
|
|
can always rethrow the exception or throw a different one.
|
|
</simpara>
|
|
</effects>
|
|
|
|
<!-- TO FIX: extra indent before template result type -->
|
|
</method>
|
|
</method-group>
|
|
</class>
|
|
|
|
<!-- TO FIX: separate page per class -->
|
|
|
|
<class name="execution_exception">
|
|
<enum name="error_code">
|
|
<description>
|
|
<para role="first-line-indented">
|
|
These values are sometimes used as program return codes. The particular values have been chosen to avoid
|
|
conflicts with commonly used program return codes: values < 100 are often user assigned, values > 255 are
|
|
sometimes used to report system errors. Gaps in values allow for orderly expansion.
|
|
</para>
|
|
|
|
<note>
|
|
<simpara>
|
|
Only uncaught C++ exceptions are treated as errors. If the application catches a C++ exception, it will never
|
|
reach the <classname>execution_monitor</classname>.
|
|
</simpara>
|
|
</note>
|
|
|
|
<note>
|
|
<simpara>
|
|
The system errors include <acronym>UNIX</acronym> signals and Windows structured exceptions. They are often
|
|
initiated by hardware traps.
|
|
</simpara>
|
|
</note>
|
|
|
|
<para role="first-line-indented">
|
|
The implementation decides what a fatal_system_exception is and what is just a system_exception. Fatal errors
|
|
are so likely to have corrupted machine state (like a stack overflow or addressing exception) that it is
|
|
unreasonable to continue execution.
|
|
</para>
|
|
</description>
|
|
<enumvalue name="no_error"/>
|
|
<enumvalue name="user_error"/>
|
|
<enumvalue name="cpp_exception_error"/>
|
|
<enumvalue name="system_error"/>
|
|
<enumvalue name="timeout_error"/>
|
|
<enumvalue name="user_fatal_error"/>
|
|
<enumvalue name="system_fatal_error"/>
|
|
</enum>
|
|
|
|
<rationale>
|
|
fear of being out (or nearly out) of memory.
|
|
</rationale>
|
|
|
|
<purpose>
|
|
uniformly reports monitored function execution problems
|
|
</purpose>
|
|
|
|
<description>
|
|
<para role="first-line-indented">
|
|
The class execution_exception is an exception used by the Execution Monitor to report problems detected during
|
|
a monitored function execution. It intentionally does not allocate any memory so as to be safe for use when
|
|
there is a lack of memory.
|
|
</para>
|
|
</description>
|
|
</class>
|
|
|
|
<class name="execution_aborted">
|
|
<purpose>
|
|
This is a trivial default constructible class. Use it to report graceful abortion of a monitored function
|
|
execution.
|
|
</purpose>
|
|
</class>
|
|
|
|
|
|
<class name="system_error">
|
|
<constructor>
|
|
<throws><simpara>Nothing.</simpara></throws>
|
|
|
|
<effects><simpara>Constructs <classname>system_error</classname> object.</simpara></effects>
|
|
</constructor>
|
|
|
|
<data-member name="p_errno">
|
|
<type><classname>unit_test::readonly_property</classname><long></type>
|
|
|
|
<!-- TO FIX -->
|
|
<purpose>
|
|
System errno value at the point of error.
|
|
</purpose>
|
|
</data-member>
|
|
|
|
<purpose>
|
|
This is a default constructible class. Use it to report failure in system call invocation.
|
|
</purpose>
|
|
</class>
|
|
</namespace>
|
|
</header>
|
|
</library-reference>
|
|
</section>
|