exception_safety.ipp
来自「Boost provides free peer-reviewed portab」· IPP 代码 · 共 538 行 · 第 1/2 页
IPP
538 行
// (C) Copyright Gennadiy Rozental 2005-2008.// Use, modification, and distribution are subject to the// Boost Software License, Version 1.0. (See accompanying file// http://www.boost.org/LICENSE_1_0.txt)// See http://www.boost.org/libs/test for the library home page.//// File : $RCSfile$//// Version : $Revision: 49312 $//// Description : Facilities to perform exception safety tests// ***************************************************************************#ifndef BOOST_TEST_EXECUTION_SAFETY_IPP_112005GER#define BOOST_TEST_EXECUTION_SAFETY_IPP_112005GER// Boost.Test#include <boost/test/detail/config.hpp>#if BOOST_TEST_SUPPORT_INTERACTION_TESTING#include <boost/test/detail/global_typedef.hpp>#include <boost/test/detail/unit_test_parameters.hpp>#include <boost/test/utils/callback.hpp>#include <boost/test/utils/wrap_stringstream.hpp>#include <boost/test/utils/iterator/token_iterator.hpp>#include <boost/test/interaction_based.hpp>#include <boost/test/test_tools.hpp>#include <boost/test/unit_test_log.hpp>#include <boost/test/framework.hpp>#include <boost/test/test_observer.hpp>#include <boost/test/debug.hpp>#include <boost/test/detail/suppress_warnings.hpp>// Boost#include <boost/lexical_cast.hpp>// STL#include <vector>#include <cstdlib>#include <map>#include <iomanip>#include <cctype>#include <boost/limits.hpp>//____________________________________________________________________________//namespace boost {using namespace ::boost::unit_test; namespace itest {// ************************************************************************** //// ************** execution_path_point ************** //// ************************************************************************** //enum exec_path_point_type { EPP_SCOPE, EPP_EXCEPT, EPP_DECISION, EPP_ALLOC };struct execution_path_point { execution_path_point( exec_path_point_type t, const_string file, std::size_t line_num ) : m_type( t ) , m_file_name( file ) , m_line_num( line_num ) {} exec_path_point_type m_type; const_string m_file_name; std::size_t m_line_num; // Execution path point specific struct decision_data { bool value; unsigned forced_exception_point; }; struct scope_data { unsigned size; char const* name; }; struct except_data { char const* description; }; struct alloc_data { void* ptr; std::size_t size; }; union { struct decision_data m_decision; struct scope_data m_scope; struct except_data m_except; struct alloc_data m_alloc; };};// ************************************************************************** //// ************** exception safety test implementation ************** //// ************************************************************************** //struct exception_safety_tester : itest::manager, test_observer { // helpers types struct unique_exception {}; // Constructor explicit exception_safety_tester( const_string test_name ); ~exception_safety_tester(); // check last run and prepare for next bool next_execution_path(); // memory tracking // manager interface implementation virtual void exception_point( const_string file, std::size_t line_num, const_string description ); virtual bool decision_point( const_string file, std::size_t line_num ); virtual unsigned enter_scope( const_string file, std::size_t line_num, const_string scope_name ); virtual void leave_scope( unsigned enter_scope_point ); virtual void allocated( const_string file, std::size_t line_num, void* p, std::size_t s ); virtual void freed( void* p ); // test observer interface virtual void assertion_result( bool passed ); virtual int priority() { return (std::numeric_limits<int>::max)(); } // we want this observer to run the lastprivate: void failure_point(); void report_error(); typedef std::vector<execution_path_point> exec_path; typedef std::map<void*,unsigned> registry; // Data members bool m_internal_activity; unsigned m_exception_point_counter; unsigned m_forced_exception_point; unsigned m_exec_path_point; exec_path m_execution_path; unsigned m_exec_path_counter; unsigned m_break_exec_path; bool m_invairant_failed; registry m_memory_in_use;};//____________________________________________________________________________//struct activity_guard { bool& m_v; activity_guard( bool& v ) : m_v( v ) { m_v = true; } ~activity_guard() { m_v = false; }};//____________________________________________________________________________//exception_safety_tester::exception_safety_tester( const_string test_name ): m_internal_activity( true ), m_exception_point_counter( 0 ), m_forced_exception_point( 1 ), m_exec_path_point( 0 ), m_exec_path_counter( 1 ), m_break_exec_path( (unsigned)-1 ), m_invairant_failed( false ){ framework::register_observer( *this ); if( !runtime_config::break_exec_path().is_empty() ) { using namespace unit_test; string_token_iterator tit( runtime_config::break_exec_path(), (dropped_delimeters = ":",kept_delimeters = " ") ); const_string test_to_break = *tit; if( test_to_break == test_name ) { ++tit; m_break_exec_path = lexical_cast<unsigned>( *tit ); } } m_internal_activity = false;}//____________________________________________________________________________//exception_safety_tester::~exception_safety_tester(){ m_internal_activity = true; framework::deregister_observer( *this );}//____________________________________________________________________________//boolexception_safety_tester::next_execution_path(){ activity_guard ag( m_internal_activity ); // check memory usage if( m_execution_path.size() > 0 ) { bool errors_detected = m_invairant_failed || (m_memory_in_use.size() != 0); framework::assertion_result( !errors_detected ); if( errors_detected ) report_error(); m_memory_in_use.clear(); } m_exec_path_point = 0; m_exception_point_counter = 0; m_invairant_failed = false; ++m_exec_path_counter; while( m_execution_path.size() > 0 ) { switch( m_execution_path.back().m_type ) { case EPP_SCOPE: case EPP_ALLOC: m_execution_path.pop_back(); break; case EPP_DECISION: if( !m_execution_path.back().m_decision.value ) { m_execution_path.pop_back(); break; } m_execution_path.back().m_decision.value = false; m_forced_exception_point = m_execution_path.back().m_decision.forced_exception_point; return true; case EPP_EXCEPT: m_execution_path.pop_back(); ++m_forced_exception_point; return true; } } BOOST_TEST_MESSAGE( "Total tested " << --m_exec_path_counter << " execution path" ); return false;}//____________________________________________________________________________//voidexception_safety_tester::exception_point( const_string file, std::size_t line_num, const_string description ){ activity_guard ag( m_internal_activity ); if( ++m_exception_point_counter == m_forced_exception_point ) { m_execution_path.push_back( execution_path_point( EPP_EXCEPT, file, line_num ) ); m_execution_path.back().m_except.description = description.begin(); ++m_exec_path_point; failure_point(); }
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?