|
Boost-Commit : |
Subject: [Boost-commit] svn:boost r74248 - in trunk/boost/test: . impl output
From: gennadiy.rozental_at_[hidden]
Date: 2011-09-06 03:14:10
Author: rogeeff
Date: 2011-09-06 03:14:08 EDT (Tue, 06 Sep 2011)
New Revision: 74248
URL: http://svn.boost.org/trac/boost/changeset/74248
Log:
support for failure context
Text files modified:
trunk/boost/test/framework.hpp | 21 ++++++++
trunk/boost/test/impl/compiler_log_formatter.ipp | 36 +++++++++++++
trunk/boost/test/impl/framework.ipp | 98 +++++++++++++++++++++++++++++++++++++++
trunk/boost/test/impl/test_tools.ipp | 25 ++++++++++
trunk/boost/test/impl/unit_test_log.ipp | 35 +++++++++++++-
trunk/boost/test/impl/xml_log_formatter.ipp | 41 +++++++++++++++
trunk/boost/test/output/compiler_log_formatter.hpp | 7 ++
trunk/boost/test/output/xml_log_formatter.hpp | 8 ++
trunk/boost/test/test_tools.hpp | 24 +++++++++
trunk/boost/test/unit_test_log.hpp | 4 +
trunk/boost/test/unit_test_log_formatter.hpp | 12 ++--
11 files changed, 294 insertions(+), 17 deletions(-)
Modified: trunk/boost/test/framework.hpp
==============================================================================
--- trunk/boost/test/framework.hpp (original)
+++ trunk/boost/test/framework.hpp 2011-09-06 03:14:08 EDT (Tue, 06 Sep 2011)
@@ -20,6 +20,7 @@
#include <boost/test/detail/fwd_decl.hpp>
#include <boost/test/utils/trivial_singleton.hpp>
+
#include <boost/test/detail/suppress_warnings.hpp>
// STL
@@ -61,6 +62,26 @@
BOOST_TEST_DECL void deregister_observer( test_observer& );
BOOST_TEST_DECL void reset_observers();
+// Assertions context support
+struct BOOST_TEST_DECL context_generator {
+ context_generator() : m_curr_frame( 0 ) {}
+
+ // is there any context?
+ bool is_empty() const;
+
+ // give me next frame; empty - last frame
+ const_string next() const;
+
+private:
+ // Data members
+ mutable unsigned m_curr_frame;
+};
+
+BOOST_TEST_DECL int add_context( lazy_ostream const& context_descr, bool sticky );
+BOOST_TEST_DECL void clear_context( int context_id = -1 );
+BOOST_TEST_DECL context_generator get_context();
+
+// Master test suite access
BOOST_TEST_DECL master_test_suite_t& master_test_suite();
// constant access methods
Modified: trunk/boost/test/impl/compiler_log_formatter.ipp
==============================================================================
--- trunk/boost/test/impl/compiler_log_formatter.ipp (original)
+++ trunk/boost/test/impl/compiler_log_formatter.ipp 2011-09-06 03:14:08 EDT (Tue, 06 Sep 2011)
@@ -130,9 +130,10 @@
//____________________________________________________________________________//
void
-compiler_log_formatter::log_exception( std::ostream& output, log_checkpoint_data const& checkpoint_data, execution_exception const& ex )
+compiler_log_formatter::log_exception_start( std::ostream& output, log_checkpoint_data const& checkpoint_data, execution_exception const& ex )
{
execution_exception::location const& loc = ex.where();
+
print_prefix( output, loc.m_file_name, loc.m_line_num );
{
@@ -152,7 +153,13 @@
if( !checkpoint_data.m_message.empty() )
output << ": " << checkpoint_data.m_message;
}
-
+}
+
+//____________________________________________________________________________//
+
+void
+compiler_log_formatter::log_exception_finish( std::ostream& output )
+{
output << std::endl;
}
@@ -216,6 +223,7 @@
{
if( runtime_config::color_output() )
output << setcolor();
+
output << std::endl;
}
@@ -236,6 +244,30 @@
//____________________________________________________________________________//
+void
+compiler_log_formatter::entry_context_start( std::ostream& output )
+{
+ output << "\nFailure occurred in a following context:";
+}
+
+//____________________________________________________________________________//
+
+void
+compiler_log_formatter::entry_context_finish( std::ostream& output )
+{
+ output.flush();
+}
+
+//____________________________________________________________________________//
+
+void
+compiler_log_formatter::log_entry_context( std::ostream& output, const_string context_descr )
+{
+ output << "\n " << context_descr;
+}
+
+//____________________________________________________________________________//
+
} // namespace output
} // namespace unit_test
Modified: trunk/boost/test/impl/framework.ipp
==============================================================================
--- trunk/boost/test/impl/framework.ipp (original)
+++ trunk/boost/test/impl/framework.ipp 2011-09-06 03:14:08 EDT (Tue, 06 Sep 2011)
@@ -117,6 +117,7 @@
, m_next_test_suite_id( MIN_TEST_SUITE_ID )
, m_is_initialized( false )
, m_test_in_progress( false )
+ , m_context_idx( 0 )
{}
~framework_impl() { clear(); }
@@ -134,7 +135,7 @@
delete static_cast<test_case const*>(tu_ptr);
}
}
-
+
void set_tu_id( test_unit& tu, test_unit_id id ) { tu.p_id.value = id; }
// test_tree_visitor interface implementation
@@ -147,9 +148,15 @@
return;
}
+ // setup contexts
+ m_context_idx = 0;
+
+ // notify all observers
BOOST_TEST_FOREACH( test_observer*, to, m_observers )
to->test_unit_start( tc );
+
+ // execute the test case body
boost::timer tc_timer;
test_unit_id bkup = m_curr_test_case;
m_curr_test_case = tc.p_id;
@@ -157,14 +164,21 @@
unsigned long elapsed = static_cast<unsigned long>( tc_timer.elapsed() * 1e6 );
+
+ // notify all observers about abortion
if( unit_test_monitor.is_critical_error( run_result ) ) {
BOOST_TEST_FOREACH( test_observer*, to, m_observers )
to->test_aborted();
}
+ // notify all observers about completion
BOOST_TEST_REVERSE_FOREACH( test_observer*, to, m_observers )
to->test_unit_finish( tc, elapsed );
+ // cleanup leftover context
+ m_context.clear();
+
+ // restore state and abort if necessary
m_curr_test_case = bkup;
if( unit_test_monitor.is_critical_error( run_result ) )
@@ -202,6 +216,18 @@
typedef std::map<test_unit_id,test_unit*> test_unit_store;
typedef std::set<test_observer*,priority_order> observer_store;
+ struct context_frame {
+ context_frame( std::string const& d, int id, bool sticky )
+ : descr( d )
+ , frame_id( id )
+ , is_sticky( sticky )
+ {}
+
+ std::string descr;
+ int frame_id;
+ bool is_sticky;
+ };
+ typedef std::vector<context_frame> context_data;
master_test_suite_t* m_master_test_suite;
test_unit_id m_curr_test_case;
@@ -214,6 +240,8 @@
bool m_test_in_progress;
observer_store m_observers;
+ context_data m_context;
+ int m_context_idx;
};
//____________________________________________________________________________//
@@ -361,6 +389,74 @@
//____________________________________________________________________________//
+int
+add_context( ::boost::unit_test::lazy_ostream const& context_descr, bool sticky )
+{
+ std::stringstream buffer;
+ context_descr( buffer );
+ int res_idx = s_frk_impl().m_context_idx++;
+
+ s_frk_impl().m_context.push_back( framework_impl::context_frame( buffer.str(), res_idx, sticky ) );
+
+ return res_idx;
+}
+
+//____________________________________________________________________________//
+
+struct frame_with_id {
+ explicit frame_with_id( int id ) : m_id( id ) {}
+
+ bool operator()( framework_impl::context_frame const& f )
+ {
+ return f.frame_id == m_id;
+ }
+ int m_id;
+};
+
+void
+clear_context( int frame_id )
+{
+ if( frame_id == -1 ) { // clear all non sticky frames
+ for( int i=s_frk_impl().m_context.size()-1; i>=0; i-- )
+ if( !s_frk_impl().m_context[i].is_sticky )
+ s_frk_impl().m_context.erase( s_frk_impl().m_context.begin()+i );
+ }
+
+ else { // clear specific frame
+ framework_impl::context_data::iterator it =
+ std::find_if( s_frk_impl().m_context.begin(), s_frk_impl().m_context.end(), frame_with_id( frame_id ) );
+
+ if( it != s_frk_impl().m_context.end() ) // really an internal error if this is not true
+ s_frk_impl().m_context.erase( it );
+ }
+}
+
+//____________________________________________________________________________//
+
+context_generator
+get_context()
+{
+ return context_generator();
+}
+
+//____________________________________________________________________________//
+
+bool
+context_generator::is_empty() const
+{
+ return s_frk_impl().m_context.empty();
+}
+
+//____________________________________________________________________________//
+
+const_string
+context_generator::next() const
+{
+ return m_curr_frame < s_frk_impl().m_context.size() ? s_frk_impl().m_context[m_curr_frame++].descr : const_string();
+}
+
+//____________________________________________________________________________//
+
master_test_suite_t&
master_test_suite()
{
Modified: trunk/boost/test/impl/test_tools.ipp
==============================================================================
--- trunk/boost/test/impl/test_tools.ipp (original)
+++ trunk/boost/test/impl/test_tools.ipp 2011-09-06 03:14:08 EDT (Tue, 06 Sep 2011)
@@ -389,6 +389,31 @@
//____________________________________________________________________________//
+// ************************************************************************** //
+// ************** context_frame ************** //
+// ************************************************************************** //
+
+context_frame::context_frame( ::boost::unit_test::lazy_ostream const& context_descr )
+: m_frame_id( unit_test::framework::add_context( context_descr, true ) )
+{
+}
+
+//____________________________________________________________________________//
+
+context_frame::~context_frame()
+{
+ unit_test::framework::clear_context( m_frame_id );
+}
+
+//____________________________________________________________________________//
+
+context_frame::operator bool()
+{
+ return true;
+}
+
+//____________________________________________________________________________//
+
} // namespace tt_detail
// ************************************************************************** //
Modified: trunk/boost/test/impl/unit_test_log.ipp
==============================================================================
--- trunk/boost/test/impl/unit_test_log.ipp (original)
+++ trunk/boost/test/impl/unit_test_log.ipp 2011-09-06 03:14:08 EDT (Tue, 06 Sep 2011)
@@ -20,6 +20,7 @@
#include <boost/test/unit_test_log_formatter.hpp>
#include <boost/test/unit_test_suite_impl.hpp>
#include <boost/test/execution_monitor.hpp>
+#include <boost/test/framework.hpp>
#include <boost/test/detail/unit_test_parameters.hpp>
@@ -235,7 +236,11 @@
if( s_log_impl().m_entry_in_progress )
*this << log::end();
- s_log_impl().m_log_formatter->log_exception( s_log_impl().stream(), s_log_impl().m_checkpoint_data, ex );
+ s_log_impl().m_log_formatter->log_exception_start( s_log_impl().stream(), s_log_impl().m_checkpoint_data, ex );
+
+ log_entry_context();
+
+ s_log_impl().m_log_formatter->log_exception_finish( s_log_impl().stream() );
}
}
@@ -282,10 +287,13 @@
unit_test_log_t&
unit_test_log_t::operator<<( log::end const& )
{
- if( s_log_impl().m_entry_in_progress )
+ if( s_log_impl().m_entry_in_progress ) {
+ log_entry_context();
+
s_log_impl().m_log_formatter->log_entry_finish( s_log_impl().stream() );
- s_log_impl().m_entry_in_progress = false;
+ s_log_impl().m_entry_in_progress = false;
+ }
return *this;
}
@@ -377,6 +385,27 @@
//____________________________________________________________________________//
void
+unit_test_log_t::log_entry_context()
+{
+ framework::context_generator const& context = framework::get_context();
+ if( context.is_empty() )
+ return;
+
+ const_string frame;
+
+ s_log_impl().m_log_formatter->entry_context_start( s_log_impl().stream() );
+
+ while( !(frame=context.next()).is_empty() )
+ s_log_impl().m_log_formatter->log_entry_context( s_log_impl().stream(), frame );
+
+ s_log_impl().m_log_formatter->entry_context_finish( s_log_impl().stream() );
+
+ framework::clear_context();
+}
+
+//____________________________________________________________________________//
+
+void
unit_test_log_t::set_stream( std::ostream& str )
{
if( s_log_impl().m_entry_in_progress )
Modified: trunk/boost/test/impl/xml_log_formatter.ipp
==============================================================================
--- trunk/boost/test/impl/xml_log_formatter.ipp (original)
+++ trunk/boost/test/impl/xml_log_formatter.ipp 2011-09-06 03:14:08 EDT (Tue, 06 Sep 2011)
@@ -110,7 +110,7 @@
//____________________________________________________________________________//
void
-xml_log_formatter::log_exception( std::ostream& ostr, log_checkpoint_data const& checkpoint_data, execution_exception const& ex )
+xml_log_formatter::log_exception_start( std::ostream& ostr, log_checkpoint_data const& checkpoint_data, execution_exception const& ex )
{
execution_exception::location const& loc = ex.where();
@@ -129,7 +129,13 @@
<< cdata() << checkpoint_data.m_message
<< "</LastCheckpoint>";
}
+}
+
+//____________________________________________________________________________//
+void
+xml_log_formatter::log_exception_finish( std::ostream& ostr )
+{
ostr << "</Exception>";
}
@@ -145,6 +151,8 @@
<< BOOST_TEST_L( " file" ) << attr_value() << entry_data.m_file_name
<< BOOST_TEST_L( " line" ) << attr_value() << entry_data.m_line_num
<< BOOST_TEST_L( "><![CDATA[" );
+
+ m_value_closed = false;
}
//____________________________________________________________________________//
@@ -160,13 +168,42 @@
void
xml_log_formatter::log_entry_finish( std::ostream& ostr )
{
- ostr << BOOST_TEST_L( "]]></" ) << m_curr_tag << BOOST_TEST_L( ">" );
+ if( !m_value_closed ) {
+ ostr << BOOST_TEST_L( "]]>" );
+ m_value_closed = true;
+ }
+
+ ostr << BOOST_TEST_L( "</" ) << m_curr_tag << BOOST_TEST_L( ">" );
m_curr_tag.clear();
}
//____________________________________________________________________________//
+void
+xml_log_formatter::entry_context_start( std::ostream& ostr )
+{
+ if( !m_value_closed ) {
+ ostr << BOOST_TEST_L( "]]>" );
+ m_value_closed = true;
+ }
+
+ ostr << BOOST_TEST_L( "<Context>" );
+
+}
+
+void
+xml_log_formatter::entry_context_finish( std::ostream& ostr )
+{
+ ostr << BOOST_TEST_L( "</Context>" );
+}
+
+void
+xml_log_formatter::log_entry_context( std::ostream& ostr, const_string context_descr )
+{
+ ostr << BOOST_TEST_L( "<Frame><![CDATA[" ) << context_descr << BOOST_TEST_L( "]]></Frame>" );
+}
+
} // namespace output
} // namespace unit_test
Modified: trunk/boost/test/output/compiler_log_formatter.hpp
==============================================================================
--- trunk/boost/test/output/compiler_log_formatter.hpp (original)
+++ trunk/boost/test/output/compiler_log_formatter.hpp 2011-09-06 03:14:08 EDT (Tue, 06 Sep 2011)
@@ -44,13 +44,18 @@
void test_unit_finish( std::ostream&, test_unit const& tu, unsigned long elapsed );
void test_unit_skipped( std::ostream&, test_unit const& tu );
- void log_exception( std::ostream&, log_checkpoint_data const&, execution_exception const& ex );
+ void log_exception_start( std::ostream&, log_checkpoint_data const&, execution_exception const& ex );
+ void log_exception_finish( std::ostream& );
void log_entry_start( std::ostream&, log_entry_data const&, log_entry_types let );
void log_entry_value( std::ostream&, const_string value );
void log_entry_value( std::ostream&, lazy_ostream const& value );
void log_entry_finish( std::ostream& );
+ void entry_context_start( std::ostream& );
+ void log_entry_context( std::ostream&, const_string );
+ void entry_context_finish( std::ostream& );
+
protected:
virtual void print_prefix( std::ostream&, const_string file, std::size_t line );
};
Modified: trunk/boost/test/output/xml_log_formatter.hpp
==============================================================================
--- trunk/boost/test/output/xml_log_formatter.hpp (original)
+++ trunk/boost/test/output/xml_log_formatter.hpp 2011-09-06 03:14:08 EDT (Tue, 06 Sep 2011)
@@ -47,16 +47,22 @@
void test_unit_finish( std::ostream&, test_unit const& tu, unsigned long elapsed );
void test_unit_skipped( std::ostream&, test_unit const& tu );
- void log_exception( std::ostream&, log_checkpoint_data const&, execution_exception const& ex );
+ void log_exception_start( std::ostream&, log_checkpoint_data const&, execution_exception const& ex );
+ void log_exception_finish( std::ostream& );
void log_entry_start( std::ostream&, log_entry_data const&, log_entry_types let );
using unit_test_log_formatter::log_entry_value; // bring base class functions into overload set
void log_entry_value( std::ostream&, const_string value );
void log_entry_finish( std::ostream& );
+ void entry_context_start( std::ostream& );
+ void log_entry_context( std::ostream&, const_string );
+ void entry_context_finish( std::ostream& );
+
private:
// Data members
const_string m_curr_tag;
+ bool m_value_closed;
};
} // namespace output
Modified: trunk/boost/test/test_tools.hpp
==============================================================================
--- trunk/boost/test/test_tools.hpp (original)
+++ trunk/boost/test/test_tools.hpp 2011-09-06 03:14:08 EDT (Tue, 06 Sep 2011)
@@ -293,6 +293,16 @@
//____________________________________________________________________________//
+#define BOOST_TEST_INFO( context_descr ) \
+ ::boost::unit_test::framework::add_context( ::boost::unit_test::lazy_ostream::instance() << context_descr, false )
+
+//____________________________________________________________________________//
+
+#define BOOST_TEST_CONTEXT( context_descr ) \
+ if( ::boost::test_tools::tt_detail::context_frame BOOST_JOIN( context_frame_, __LINE__ ) = ::boost::test_tools::tt_detail::context_frame( ::boost::unit_test::lazy_ostream::instance() << context_descr ) )
+
+//____________________________________________________________________________//
+
// ***************************** //
// deprecated interface
@@ -712,6 +722,20 @@
//____________________________________________________________________________//
+// ************************************************************************** //
+// ************** context_frame ************** //
+// ************************************************************************** //
+
+struct BOOST_TEST_DECL context_frame {
+ explicit context_frame( ::boost::unit_test::lazy_ostream const& context_descr );
+ ~context_frame();
+
+ operator bool();
+
+private:
+ int m_frame_id;
+};
+
} // namespace tt_detail
} // namespace test_tools
Modified: trunk/boost/test/unit_test_log.hpp
==============================================================================
--- trunk/boost/test/unit_test_log.hpp (original)
+++ trunk/boost/test/unit_test_log.hpp 2011-09-06 03:14:08 EDT (Tue, 06 Sep 2011)
@@ -126,7 +126,9 @@
ut_detail::entry_value_collector operator()( log_level ); // initiate entry collection
private:
- bool log_entry_start();
+ // Implementation helpers
+ bool log_entry_start();
+ void log_entry_context();
BOOST_TEST_SINGLETON_CONS( unit_test_log_t );
}; // unit_test_log_t
Modified: trunk/boost/test/unit_test_log_formatter.hpp
==============================================================================
--- trunk/boost/test/unit_test_log_formatter.hpp (original)
+++ trunk/boost/test/unit_test_log_formatter.hpp 2011-09-06 03:14:08 EDT (Tue, 06 Sep 2011)
@@ -98,17 +98,17 @@
virtual void test_unit_finish( std::ostream&, test_unit const& tu, unsigned long elapsed ) = 0;
virtual void test_unit_skipped( std::ostream&, test_unit const& ) = 0;
- virtual void log_exception( std::ostream& os, log_checkpoint_data const& cd, execution_exception const& ex )
- {
- // for backward compatibility
- log_exception( os, cd, ex.what() );
- }
- virtual void log_exception( std::ostream&, log_checkpoint_data const&, const_string /* explanation */ ) {}
+ virtual void log_exception_start( std::ostream&, log_checkpoint_data const&, execution_exception const& ex ) = 0;
+ virtual void log_exception_finish( std::ostream& ) = 0;
virtual void log_entry_start( std::ostream&, log_entry_data const&, log_entry_types let ) = 0;
virtual void log_entry_value( std::ostream&, const_string value ) = 0;
virtual void log_entry_value( std::ostream&, lazy_ostream const& value ); // there is a default impl
virtual void log_entry_finish( std::ostream& ) = 0;
+
+ virtual void entry_context_start( std::ostream& ) = 0;
+ virtual void log_entry_context( std::ostream&, const_string ) = 0;
+ virtual void entry_context_finish( std::ostream& ) = 0;
};
} // namespace unit_test
Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk