2
0
mirror of https://github.com/boostorg/test.git synced 2026-02-17 14:12:08 +00:00
Files
test/doc/v2/monitor.execution.qbk
2014-02-23 23:10:31 +01:00

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 &lt;<ulink url="../../../../boost/test/execution_monitor.hpp"><filename>boost/test/execution_monitor.hpp</filename></ulink>&gt;
</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>&lt;bool&gt;</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>&lt;bool&gt;</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>&lt;int&gt;</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>&lt;int&gt;</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>&lt;bool&gt;</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>&lt;int&gt; const&amp;</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&amp;</paramtype>
</parameter>
<parameter name="dummy">
<paramtype><classname>boost::type</classname>&lt;Exception&gt;*</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 &lt; 100 are often user assigned, values &gt; 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>&lt;long&gt;</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>