Boost logo

Boost Users :

Subject: Re: [Boost-users] Boost Unit Testing of DLL's
From: Johan Doré (JDH_at_[hidden])
Date: 2011-05-30 09:23:24


Hi,

 

Based on the answers which clearly stated that it would not work with delay loading the UTF DLL I tried to modify the Boost UTF implementation to get it working.

The code you see below is probably not following the Boost guidelines but it made it possible for us to use the UTF with delay loading of the UTF dll.

 

 

CHANGES APPLIED TO boost_1_46_1\boost\config\auto_link.hpp:

 

//////////////////////////////////////////////////////////

// Original implementation

//////////////////////////////////////////////////////////

#ifdef BOOST_AUTO_LINK_TAGGED

# pragma comment(lib, BOOST_LIB_PREFIX BOOST_STRINGIZE(BOOST_LIB_NAME) BOOST_LIB_THREAD_OPT BOOST_LIB_RT_OPT ".lib")

# ifdef BOOST_LIB_DIAGNOSTIC

# pragma message ("Linking to lib file: " BOOST_LIB_PREFIX BOOST_STRINGIZE(BOOST_LIB_NAME) "-" BOOST_LIB_TOOLSET BOOST_LIB_THREAD_OPT BOOST_LIB_RT_OPT "-" BOOST_LIB_VERSION ".lib")

# endif

#elif defined(BOOST_AUTO_LINK_NOMANGLE)

# pragma comment(lib, BOOST_STRINGIZE(BOOST_LIB_NAME) ".lib")

# ifdef BOOST_LIB_DIAGNOSTIC

# pragma message ("Linking to lib file: " BOOST_STRINGIZE(BOOST_LIB_NAME) ".lib")

# endif

#else

# pragma comment(lib, BOOST_LIB_PREFIX BOOST_STRINGIZE(BOOST_LIB_NAME) "-" BOOST_LIB_TOOLSET BOOST_LIB_THREAD_OPT BOOST_LIB_RT_OPT "-" BOOST_LIB_VERSION ".lib")

# ifdef BOOST_LIB_DIAGNOSTIC

# pragma message ("Linking to lib file: " BOOST_LIB_PREFIX BOOST_STRINGIZE(BOOST_LIB_NAME) "-" BOOST_LIB_TOOLSET BOOST_LIB_THREAD_OPT BOOST_LIB_RT_OPT "-" BOOST_LIB_VERSION ".lib")

# endif

#endif

 

//////////////////////////////////////////////////////////

// Modified implementation

// We need a function which can check if the UTF lib

// functionality can be used this is implemented in the

// new function HasBoostLib

//////////////////////////////////////////////////////////

#ifdef BOOST_AUTO_LINK_TAGGED

# define BOOST_LIB_PATH BOOST_LIB_PREFIX BOOST_STRINGIZE(BOOST_LIB_NAME) BOOST_LIB_THREAD_OPT BOOST_LIB_RT_OPT

#elif defined(BOOST_AUTO_LINK_NOMANGLE)

# define BOOST_LIB_PATH BOOST_STRINGIZE(BOOST_LIB_NAME)

#else

# define BOOST_LIB_PATH BOOST_LIB_PREFIX BOOST_STRINGIZE(BOOST_LIB_NAME) "-" BOOST_LIB_TOOLSET BOOST_LIB_THREAD_OPT BOOST_LIB_RT_OPT "-" BOOST_LIB_VERSION

#endif

 

# pragma comment(lib, BOOST_LIB_PATH ".lib")

# ifdef BOOST_LIB_DIAGNOSTIC

# pragma message ("Linking to lib file: " BOOST_LIB_PATH ".lib")

# endif

 

static bool HasBoostLib()

{

#ifdef BOOST_DYN_LINK

  static bool Available = LoadLibrary(BOOST_LIB_PATH ".dll") != NULL;

      return(Available);

#else

      return(true);

#endif

}

 

 

CHANGES APPLIED TO boost_1_46_1\boost\unit_test.hpp:

 

//////////////////////////////////////////////////////////

// Original implementation

//////////////////////////////////////////////////////////

#include <boost/test/test_tools.hpp>

#include <boost/test/unit_test_suite.hpp>

 

#if !defined(BOOST_ALL_NO_LIB) && !defined(BOOST_TEST_NO_LIB) && \

    !defined(BOOST_TEST_SOURCE) && !defined(BOOST_TEST_INCLUDED)

# define BOOST_LIB_NAME boost_unit_test_framework

 

# if defined(BOOST_ALL_DYN_LINK) || defined(BOOST_TEST_DYN_LINK)

# define BOOST_DYN_LINK

# endif

 

# include <boost/config/auto_link.hpp>

 

#endif // auto-linking disabled

 

//////////////////////////////////////////////////////////

// Modified implementation

// We need to include the auto_link.hpp before headers

// using the HasBoostLib function

//////////////////////////////////////////////////////////

#if !defined(BOOST_ALL_NO_LIB) && !defined(BOOST_TEST_NO_LIB) && \

    !defined(BOOST_TEST_SOURCE) && !defined(BOOST_TEST_INCLUDED)

# define BOOST_LIB_NAME boost_unit_test_framework

 

# if defined(BOOST_ALL_DYN_LINK) || defined(BOOST_TEST_DYN_LINK)

# define BOOST_DYN_LINK

# endif

 

# include <boost/config/auto_link.hpp>

 

#endif // auto-linking disabled

 

#include <boost/test/test_tools.hpp>

#include <boost/test/unit_test_suite.hpp>

 

 

CHANGES APPLIED TO boost_1_46_1\boost\test\utils\trivial_singleton.hpp

 

//////////////////////////////////////////////////////////

// Original implementation

//////////////////////////////////////////////////////////

#define BOOST_TEST_SINGLETON_INST( inst ) \

      namespace { BOOST_JOIN( inst, _t)& inst = BOOST_JOIN( inst, _t)::instance()}

 

//////////////////////////////////////////////////////////

// Modified implementation

// We shall not instantiate the singleton if the lib is

// not available

//////////////////////////////////////////////////////////

#define BOOST_TEST_SINGLETON_INST( inst ) \

      namespace { BOOST_JOIN( inst, _t)& inst = HasBoostLib() ? BOOST_JOIN( inst, _t)::instance() : *(BOOST_JOIN( inst, _t)*)NULL; }

 

 

CHANGES APPLIED TO boost_1_46_1\boost\test\unit_test_suite_impl.hpp

 

//////////////////////////////////////////////////////////

// Original implementation

//////////////////////////////////////////////////////////

inline test_case*

make_test_case( callback0<> const& test_func, const_string tc_name )

{

    return new test_case( ut_detail::normalize_test_case_name( tc_name ), test_func );

}

 

template<typename UserTestCase, typename InstanceType>

inline test_case*

make_test_case( void (UserTestCase::* test_method )(),

                const_string tc_name,

                boost::shared_ptr<InstanceType> user_test_case )

{

    return new test_case( ut_detail::normalize_test_case_name( tc_name ),

                          ut_detail::user_tc_method_invoker<InstanceType,UserTestCase>( user_test_case, test_method ) );

}

 

struct BOOST_TEST_DECL auto_test_unit_registrar

{

    // Constructors

                auto_test_unit_registrar( test_case* tc, counter_t exp_fail );

    explicit auto_test_unit_registrar( const_string ts_name );

    explicit auto_test_unit_registrar( test_unit_generator const& tc_gen );

    explicit auto_test_unit_registrar( int );

 

private:

    static std::list<test_suite*>& curr_ts_store();

};

 

//////////////////////////////////////////////////////////

// Modified implementation

// We shall not instantiate test_case nor

// auto_test_unit_registrar if the Lib is not available

//////////////////////////////////////////////////////////

inline test_case*

make_test_case( callback0<> const& test_func, const_string tc_name )

{

    if(HasBoostLib())

              return new test_case( ut_detail::normalize_test_case_name( tc_name ), test_func );

            return(NULL);

}

 

template<typename UserTestCase, typename InstanceType>

inline test_case*

make_test_case( void (UserTestCase::* test_method )(),

                const_string tc_name,

                boost::shared_ptr<InstanceType> user_test_case )

{

    if(HasBoostLib())

              return new test_case( ut_detail::normalize_test_case_name( tc_name ),

                          ut_detail::user_tc_method_invoker<InstanceType,UserTestCase>( user_test_case, test_method ) );

    return(NULL);

}

 

namespace ut_detail {

 

struct BOOST_TEST_DECL auto_test_unit_registrar

{

    // Constructors

                auto_test_unit_registrar( test_case* tc, counter_t exp_fail );

    explicit auto_test_unit_registrar( const_string ts_name ) ;

    explicit auto_test_unit_registrar( test_unit_generator const& tc_gen );

    explicit auto_test_unit_registrar( int ) ;

 

private:

    static std::list<test_suite*>& curr_ts_store();

};

 

/////////////////////////////////////////////////////////////////////////

// auto_test_unit_registrar implementation which can be instantiated

// even if the Boost UTF DLL is not available.

// Test functionalities will probably crash if the DLL is not available

// but not UTF code will work

/////////////////////////////////////////////////////////////////////////

class CDynamic_auto_test_unit_registrar

{

public:

 

      // Constructors

      CDynamic_auto_test_unit_registrar( test_case* tc, counter_t exp_fail )

      {

            Registrar = HasBoostLib() ? new auto_test_unit_registrar(tc, exp_fail) : NULL;

      };

 

      CDynamic_auto_test_unit_registrar( const_string ts_name )

      {

            Registrar = HasBoostLib() ? new auto_test_unit_registrar(ts_name) : NULL;

      }

 

      CDynamic_auto_test_unit_registrar( test_unit_generator const& tc_gen )

      {

            Registrar = HasBoostLib() ? new auto_test_unit_registrar(tc_gen) : NULL;

      }

 

      CDynamic_auto_test_unit_registrar( int Val)

      {

            Registrar = HasBoostLib() ? new auto_test_unit_registrar(Val) :NULL;

      }

 

      ~CDynamic_auto_test_unit_registrar()

      {

            delete Registrar; Registrar = NULL;

      }

 

private:

 

      auto_test_unit_registrar* Registrar;

};

 

 

CHANGES APPLIED TO boost_1_46_1\boost\test\unit_test_suite.hpp

 

//////////////////////////////////////////////////////////

// Original implementation

//////////////////////////////////////////////////////////

 

#define BOOST_AUTO_TU_REGISTRAR( test_name ) \

static boost::unit_test::ut_detail::auto_test_unit_registrar BOOST_JOIN( BOOST_JOIN( test_name, _registrar ), __LINE__ )

 

//////////////////////////////////////////////////////////

// Modified implementation

// Instantiate the CDynamic_auto_test_unit_registrar

// instead of the auto_test_unit_registrar

//////////////////////////////////////////////////////////

 

#define BOOST_AUTO_TU_REGISTRAR( test_name ) \

static boost::unit_test::ut_detail::CDynamic_auto_test_unit_registrar BOOST_JOIN( BOOST_JOIN( test_name, _registrar ), __LINE__ )

 

 

 

That is all it required to work in our setup.

 

Best regards

 

Johan Doré



Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net