Include bind in ndnboost.
diff --git a/ndnboost/test/impl/test_tools.ipp b/ndnboost/test/impl/test_tools.ipp
new file mode 100644
index 0000000..b47ef81
--- /dev/null
+++ b/ndnboost/test/impl/test_tools.ipp
@@ -0,0 +1,628 @@
+//  (C) Copyright Gennadiy Rozental 2005-2008.
+//  Distributed under the Boost Software License, Version 1.0.
+//  (See accompanying file LICENSE_1_0.txt or copy at
+//  http://www.boost.org/LICENSE_1_0.txt)
+
+//  See http://www.boost.org/libs/test for the library home page.
+//
+//  File        : $RCSfile$
+//
+//  Version     : $Revision: 54633 $
+//
+//  Description : supplies offline implementation for the Test Tools
+// ***************************************************************************
+
+#ifndef BOOST_TEST_TEST_TOOLS_IPP_012205GER
+#define BOOST_TEST_TEST_TOOLS_IPP_012205GER
+
+// Boost.Test
+#include <ndnboost/test/test_tools.hpp>
+#include <ndnboost/test/unit_test_log.hpp>
+#include <ndnboost/test/output_test_stream.hpp>
+#include <ndnboost/test/framework.hpp>
+#include <ndnboost/test/execution_monitor.hpp> // execution_aborted
+#include <ndnboost/test/unit_test_suite_impl.hpp>
+
+// Boost
+#include <ndnboost/config.hpp>
+
+// STL
+#include <fstream>
+#include <string>
+#include <cstring>
+#include <cctype>
+#include <cwchar>
+#include <stdexcept>
+#include <ios>
+
+// !! should we use #include <cstdarg>
+#include <stdarg.h>
+
+#include <ndnboost/test/detail/suppress_warnings.hpp>
+
+//____________________________________________________________________________//
+
+# ifdef BOOST_NO_STDC_NAMESPACE
+namespace std { using ::strcmp; using ::strlen; using ::isprint; }
+#if !defined( BOOST_NO_CWCHAR )
+namespace std { using ::wcscmp; }
+#endif
+# endif
+
+namespace ndnboost {
+
+namespace test_tools {
+
+// ************************************************************************** //
+// **************                print_log_value               ************** //
+// ************************************************************************** //
+
+void
+print_log_value<char>::operator()( std::ostream& ostr, char t )
+{
+    if( (std::isprint)( static_cast<unsigned char>(t) ) )
+        ostr << '\'' << t << '\'';
+    else
+        ostr << std::hex
+#if BOOST_TEST_USE_STD_LOCALE
+        << std::showbase
+#else
+        << "0x"
+#endif
+        << static_cast<int>(t);
+}
+
+//____________________________________________________________________________//
+
+void
+print_log_value<unsigned char>::operator()( std::ostream& ostr, unsigned char t )
+{
+    ostr << std::hex
+        // showbase is only available for new style streams:
+#if BOOST_TEST_USE_STD_LOCALE
+        << std::showbase
+#else
+        << "0x"
+#endif
+        << static_cast<int>(t);
+}
+
+//____________________________________________________________________________//
+
+void
+print_log_value<char const*>::operator()( std::ostream& ostr, char const* t )
+{
+    ostr << ( t ? t : "null string" );
+}
+
+//____________________________________________________________________________//
+
+void
+print_log_value<wchar_t const*>::operator()( std::ostream& ostr, wchar_t const* t )
+{
+    ostr << ( t ? t : L"null string" );
+}
+
+//____________________________________________________________________________//
+
+namespace tt_detail {
+
+// ************************************************************************** //
+// **************            TOOL BOX Implementation           ************** //
+// ************************************************************************** //
+
+using ::ndnboost::unit_test::lazy_ostream;
+
+bool
+check_impl( predicate_result const& pr, lazy_ostream const& check_descr,
+            const_string file_name, std::size_t line_num,
+            tool_level tl, check_type ct,
+            std::size_t num_of_args, ... )
+{
+    using namespace unit_test;
+
+    if( !framework::is_initialized() )
+        throw std::runtime_error( "can't use testing tools before framework is initialized" );
+
+    if( !!pr )
+        tl = PASS;
+
+    log_level    ll;
+    char const*  prefix;
+    char const*  suffix;
+       
+    switch( tl ) {
+    case PASS:
+        ll      = log_successful_tests;
+        prefix  = "check ";
+        suffix  = " passed";
+        break;
+    case WARN:
+        ll      = log_warnings;
+        prefix  = "condition ";
+        suffix  = " is not satisfied";
+        break;
+    case CHECK:
+        ll      = log_all_errors;
+        prefix  = "check ";
+        suffix  = " failed";
+        break;
+    case REQUIRE:
+        ll      = log_fatal_errors;
+        prefix  = "critical check ";
+        suffix  = " failed";
+        break;
+    default:
+        return true;
+    }
+
+    switch( ct ) {
+    case CHECK_PRED:
+        unit_test_log << unit_test::log::begin( file_name, line_num ) 
+                      << ll << prefix << check_descr << suffix;
+        
+        if( !pr.has_empty_message() )
+            unit_test_log << ". " << pr.message();
+        
+        unit_test_log << unit_test::log::end();
+        break;
+
+    case CHECK_MSG:
+        unit_test_log << unit_test::log::begin( file_name, line_num ) << ll;
+        
+        if( tl == PASS )
+            unit_test_log << prefix << "'" << check_descr << "'" << suffix;
+        else
+            unit_test_log << check_descr;
+        
+        if( !pr.has_empty_message() )
+            unit_test_log << ". " << pr.message();
+
+        unit_test_log << unit_test::log::end();
+        break;
+
+    case CHECK_EQUAL: 
+    case CHECK_NE: 
+    case CHECK_LT: 
+    case CHECK_LE: 
+    case CHECK_GT: 
+    case CHECK_GE: {
+        static char const* check_str [] = { " == ", " != ", " < " , " <= ", " > " , " >= " };
+        static char const* rever_str [] = { " != ", " == ", " >= ", " > " , " <= ", " < "  };
+
+        va_list args;
+
+        va_start( args, num_of_args );
+        char const*         arg1_descr  = va_arg( args, char const* );
+        lazy_ostream const* arg1_val    = va_arg( args, lazy_ostream const* );
+        char const*         arg2_descr  = va_arg( args, char const* );
+        lazy_ostream const* arg2_val    = va_arg( args, lazy_ostream const* );
+
+        unit_test_log << unit_test::log::begin( file_name, line_num ) 
+                      << ll << prefix << arg1_descr << check_str[ct-CHECK_EQUAL] << arg2_descr << suffix;
+
+        if( tl != PASS )
+            unit_test_log << " [" << *arg1_val << rever_str[ct-CHECK_EQUAL] << *arg2_val << "]" ;
+
+        va_end( args );
+        
+        if( !pr.has_empty_message() )
+            unit_test_log << ". " << pr.message();
+
+        unit_test_log << unit_test::log::end();
+        break;
+    }
+
+    case CHECK_CLOSE:
+    case CHECK_CLOSE_FRACTION: {
+        va_list args;
+
+        va_start( args, num_of_args );
+        char const*         arg1_descr  = va_arg( args, char const* );
+        lazy_ostream const* arg1_val    = va_arg( args, lazy_ostream const* );
+        char const*         arg2_descr  = va_arg( args, char const* );
+        lazy_ostream const* arg2_val    = va_arg( args, lazy_ostream const* );
+        /* toler_descr = */               va_arg( args, char const* );
+        lazy_ostream const* toler_val   = va_arg( args, lazy_ostream const* );
+
+        unit_test_log << unit_test::log::begin( file_name, line_num ) << ll;
+
+        unit_test_log << "difference{" << pr.message() << (ct == CHECK_CLOSE ? "%" : "")
+                      << "} between " << arg1_descr << "{" << *arg1_val
+                      << "} and "               << arg2_descr << "{" << *arg2_val
+                      << ( tl == PASS ? "} doesn't exceed " : "} exceeds " )
+                      << *toler_val;
+        if( ct == CHECK_CLOSE )
+            unit_test_log << "%";
+
+        va_end( args );
+        
+        unit_test_log << unit_test::log::end();
+        break;
+    }
+    case CHECK_SMALL: {
+        va_list args;
+
+        va_start( args, num_of_args );
+        char const*         arg1_descr  = va_arg( args, char const* );
+        lazy_ostream const* arg1_val    = va_arg( args, lazy_ostream const* );
+        /* toler_descr = */               va_arg( args, char const* );
+        lazy_ostream const* toler_val   = va_arg( args, lazy_ostream const* );
+
+        unit_test_log << unit_test::log::begin( file_name, line_num ) << ll;
+
+        unit_test_log << "absolute value of " << arg1_descr << "{" << *arg1_val << "}" 
+                      << ( tl == PASS ? " doesn't exceed " : " exceeds " )
+                      << *toler_val;
+
+        va_end( args );
+        
+        if( !pr.has_empty_message() )
+            unit_test_log << ". " << pr.message();
+
+        unit_test_log << unit_test::log::end();
+        break;
+    }
+
+    case CHECK_PRED_WITH_ARGS: {
+        unit_test_log << unit_test::log::begin( file_name, line_num ) 
+                      << ll << prefix << check_descr;
+
+        // print predicate call description
+        {
+            va_list args;
+            va_start( args, num_of_args );
+
+            unit_test_log << "( ";
+            for( std::size_t i = 0; i < num_of_args; ++i ) {
+                unit_test_log << va_arg( args, char const* );
+                va_arg( args, lazy_ostream const* ); // skip argument value;
+                
+                if( i != num_of_args-1 )
+                    unit_test_log << ", ";
+            }
+            unit_test_log << " )" << suffix;
+            va_end( args );
+        }
+                        
+        if( tl != PASS ) {
+            va_list args;
+            va_start( args, num_of_args );
+
+            unit_test_log << " for ( ";
+            for( std::size_t i = 0; i < num_of_args; ++i ) {
+                va_arg( args, char const* ); // skip argument description;            
+                unit_test_log << *va_arg( args, lazy_ostream const* );
+                
+                if( i != num_of_args-1 )
+                    unit_test_log << ", ";
+            }
+            unit_test_log << " )";
+            va_end( args );
+        }
+       
+        if( !pr.has_empty_message() )
+            unit_test_log << ". " << pr.message();
+
+        unit_test_log << unit_test::log::end();
+        break;
+    }
+
+    case CHECK_EQUAL_COLL: {
+        va_list args;
+
+        va_start( args, num_of_args );
+        char const* left_begin_descr    = va_arg( args, char const* );
+        char const* left_end_descr      = va_arg( args, char const* );
+        char const* right_begin_descr   = va_arg( args, char const* );
+        char const* right_end_descr     = va_arg( args, char const* );
+
+        unit_test_log << unit_test::log::begin( file_name, line_num ) 
+                      << ll << prefix 
+                      << "{ " << left_begin_descr  << ", " << left_end_descr  << " } == { " 
+                              << right_begin_descr << ", " << right_end_descr << " }"
+                      << suffix;
+
+        va_end( args );
+        
+        if( !pr.has_empty_message() )
+            unit_test_log << ". " << pr.message();
+
+        unit_test_log << unit_test::log::end();
+        break;
+    }
+
+    case CHECK_BITWISE_EQUAL: {
+        va_list args;
+
+        va_start( args, num_of_args );
+        char const* left_descr    = va_arg( args, char const* );
+        char const* right_descr   = va_arg( args, char const* );
+
+        unit_test_log << unit_test::log::begin( file_name, line_num )
+                      << ll << prefix << left_descr  << " =.= " << right_descr << suffix;
+
+        va_end( args );
+        
+        if( !pr.has_empty_message() )
+            unit_test_log << ". " << pr.message();
+
+        unit_test_log << unit_test::log::end();
+        break;
+    }
+    }
+
+    switch( tl ) {
+    case PASS:
+        framework::assertion_result( true );
+        return true;
+
+    case WARN:
+        return false;
+
+    case CHECK:
+        framework::assertion_result( false );
+        return false;
+        
+    case REQUIRE:
+        framework::assertion_result( false );
+
+        framework::test_unit_aborted( framework::current_test_case() );
+
+        throw execution_aborted();
+    }
+
+    return true;
+}
+
+//____________________________________________________________________________//
+
+predicate_result
+equal_impl( char const* left, char const* right )
+{
+    return (left && right) ? std::strcmp( left, right ) == 0 : (left == right);
+}
+
+//____________________________________________________________________________//
+
+#if !defined( BOOST_NO_CWCHAR )
+
+predicate_result
+equal_impl( wchar_t const* left, wchar_t const* right )
+{
+    return (left && right) ? std::wcscmp( left, right ) == 0 : (left == right);
+}
+
+#endif // !defined( BOOST_NO_CWCHAR )
+
+//____________________________________________________________________________//
+
+bool
+is_defined_impl( const_string symbol_name, const_string symbol_value )
+{
+    symbol_value.trim_left( 2 );
+    return symbol_name != symbol_value;
+}
+
+//____________________________________________________________________________//
+
+} // namespace tt_detail
+
+// ************************************************************************** //
+// **************               output_test_stream             ************** //
+// ************************************************************************** //
+
+struct output_test_stream::Impl
+{
+    std::fstream    m_pattern;
+    bool            m_match_or_save;
+    bool            m_text_or_binary;
+    std::string     m_synced_string;
+
+    char            get_char()
+    {
+        char res;
+        do {
+            m_pattern.get( res );
+        } while( m_text_or_binary && res == '\r' && !m_pattern.fail() && !m_pattern.eof() );
+
+        return res;
+    }
+
+    void            check_and_fill( predicate_result& res )
+    {
+        if( !res.p_predicate_value )
+            res.message() << "Output content: \"" << m_synced_string << '\"';
+    }
+};
+
+//____________________________________________________________________________//
+
+output_test_stream::output_test_stream( const_string pattern_file_name, bool match_or_save, bool text_or_binary )
+: m_pimpl( new Impl )
+{
+    if( !pattern_file_name.is_empty() ) {
+        std::ios::openmode m = match_or_save ? std::ios::in : std::ios::out;
+        if( !text_or_binary )
+            m |= std::ios::binary;
+
+        m_pimpl->m_pattern.open( pattern_file_name.begin(), m );
+
+        BOOST_WARN_MESSAGE( m_pimpl->m_pattern.is_open(),
+                             "Can't open pattern file " << pattern_file_name
+                                << " for " << (match_or_save ? "reading" : "writing") );
+    }
+
+    m_pimpl->m_match_or_save    = match_or_save;
+    m_pimpl->m_text_or_binary   = text_or_binary;
+}
+
+//____________________________________________________________________________//
+
+output_test_stream::~output_test_stream()
+{
+    delete m_pimpl;
+}
+
+//____________________________________________________________________________//
+
+predicate_result
+output_test_stream::is_empty( bool flush_stream )
+{
+    sync();
+
+    result_type res( m_pimpl->m_synced_string.empty() );
+
+    m_pimpl->check_and_fill( res );
+
+    if( flush_stream )
+        flush();
+
+    return res;
+}
+
+//____________________________________________________________________________//
+
+predicate_result
+output_test_stream::check_length( std::size_t length_, bool flush_stream )
+{
+    sync();
+
+    result_type res( m_pimpl->m_synced_string.length() == length_ );
+
+    m_pimpl->check_and_fill( res );
+
+    if( flush_stream )
+        flush();
+
+    return res;
+}
+
+//____________________________________________________________________________//
+
+predicate_result
+output_test_stream::is_equal( const_string arg, bool flush_stream )
+{
+    sync();
+
+    result_type res( const_string( m_pimpl->m_synced_string ) == arg );
+
+    m_pimpl->check_and_fill( res );
+
+    if( flush_stream )
+        flush();
+
+    return res;
+}
+
+//____________________________________________________________________________//
+
+predicate_result
+output_test_stream::match_pattern( bool flush_stream )
+{
+    sync();
+
+    result_type result( true );
+
+    if( !m_pimpl->m_pattern.is_open() ) {
+        result = false;
+        result.message() << "Pattern file can't be opened!";
+    }
+    else {
+        if( m_pimpl->m_match_or_save ) {
+            for ( std::string::size_type i = 0; i < m_pimpl->m_synced_string.length(); ++i ) {
+                char c = m_pimpl->get_char();
+
+                result = !m_pimpl->m_pattern.fail() &&
+                         !m_pimpl->m_pattern.eof()  &&
+                         (m_pimpl->m_synced_string[i] == c);
+
+                if( !result ) {
+                    std::string::size_type suffix_size  = (std::min)( m_pimpl->m_synced_string.length() - i,
+                                                                    static_cast<std::string::size_type>(5) );
+
+                    // try to log area around the mismatch
+                    result.message() << "Mismatch at position " << i << '\n'
+                        << "..." << m_pimpl->m_synced_string.substr( i, suffix_size ) << "..." << '\n'
+                        << "..." << c;
+
+                    std::string::size_type counter = suffix_size;
+                    while( --counter ) {
+                        char c = m_pimpl->get_char();
+
+                        if( m_pimpl->m_pattern.fail() || m_pimpl->m_pattern.eof() )
+                            break;
+
+                        result.message() << c;
+                    }
+
+                    result.message() << "...";
+
+                    // skip rest of the bytes. May help for further matching
+                    m_pimpl->m_pattern.ignore( 
+                        static_cast<std::streamsize>( m_pimpl->m_synced_string.length() - i - suffix_size) );
+                    break;
+                }
+            }
+        }
+        else {
+            m_pimpl->m_pattern.write( m_pimpl->m_synced_string.c_str(),
+                                      static_cast<std::streamsize>( m_pimpl->m_synced_string.length() ) );
+            m_pimpl->m_pattern.flush();
+        }
+    }
+
+    if( flush_stream )
+        flush();
+
+    return result;
+}
+
+//____________________________________________________________________________//
+
+void
+output_test_stream::flush()
+{
+    m_pimpl->m_synced_string.erase();
+
+#ifndef BOOST_NO_STRINGSTREAM
+    str( std::string() );
+#else
+    seekp( 0, std::ios::beg );
+#endif
+}
+
+//____________________________________________________________________________//
+
+std::size_t
+output_test_stream::length()
+{
+    sync();
+
+    return m_pimpl->m_synced_string.length();
+}
+
+//____________________________________________________________________________//
+
+void
+output_test_stream::sync()
+{
+#ifdef BOOST_NO_STRINGSTREAM
+    m_pimpl->m_synced_string.assign( str(), pcount() );
+    freeze( false );
+#else
+    m_pimpl->m_synced_string = str();
+#endif
+}
+
+//____________________________________________________________________________//
+
+} // namespace test_tools
+
+} // namespace ndnboost
+
+//____________________________________________________________________________//
+
+#include <ndnboost/test/detail/enable_warnings.hpp>
+
+#endif // BOOST_TEST_TEST_TOOLS_IPP_012205GER