diff options
| -rwxr-xr-x | indra/llcommon/llsingleton.h | 6 | ||||
| -rwxr-xr-x | indra/llcommon/tests/llsingleton_test.cpp | 205 | 
2 files changed, 167 insertions, 44 deletions
| diff --git a/indra/llcommon/llsingleton.h b/indra/llcommon/llsingleton.h index 253e0b9a6b..6a7f27bed4 100755 --- a/indra/llcommon/llsingleton.h +++ b/indra/llcommon/llsingleton.h @@ -32,8 +32,6 @@  #include <vector>  #include <typeinfo> -// TODO: -// Tests for all this!  class LLSingletonBase: private boost::noncopyable  {  public: @@ -80,8 +78,8 @@ protected:      // Maintain a stack of the LLSingleton subclass instance currently being      // initialized. We use this to notice direct dependencies: we want to know -    // if A requires B. We deduce that if while initializing A, control -    // reaches B::getInstance(). +    // if A requires B. We deduce a dependency if while initializing A, +    // control reaches B::getInstance().      // We want &A to be at the top of that stack during both A::A() and      // A::initSingleton(), since a call to B::getInstance() might occur during      // either. diff --git a/indra/llcommon/tests/llsingleton_test.cpp b/indra/llcommon/tests/llsingleton_test.cpp index bed436283a..a05f650f25 100755 --- a/indra/llcommon/tests/llsingleton_test.cpp +++ b/indra/llcommon/tests/llsingleton_test.cpp @@ -30,46 +30,171 @@  #include "llsingleton.h"  #include "../test/lltut.h" + +// Capture execution sequence by appending to log string. +std::string sLog; + +#define DECLARE_CLASS(CLS)                      \ +struct CLS: public LLSingleton<CLS>             \ +{                                               \ +    static enum dep_flag {                      \ +        DEP_NONE, /* no dependency */           \ +        DEP_CTOR, /* dependency in ctor */      \ +        DEP_INIT  /* dependency in initSingleton */ \ +    } sDepFlag;                                 \ +                                                \ +    CLS();                                      \ +    void initSingleton();                       \ +    void cleanupSingleton();                    \ +    ~CLS();                                     \ +};                                              \ +                                                \ +CLS::dep_flag CLS::sDepFlag = DEP_NONE + +DECLARE_CLASS(A); +DECLARE_CLASS(B); + +#define DEFINE_MEMBERS(CLS, OTHER)              \ +CLS::CLS()                                      \ +{                                               \ +    sLog.append(#CLS);                          \ +    if (sDepFlag == DEP_CTOR)                   \ +    {                                           \ +        (void)OTHER::instance();                \ +    }                                           \ +}                                               \ +                                                \ +void CLS::initSingleton()                       \ +{                                               \ +    sLog.append("i" #CLS);                      \ +    if (sDepFlag == DEP_INIT)                   \ +    {                                           \ +        (void)OTHER::instance();                \ +    }                                           \ +}                                               \ +                                                \ +void CLS::cleanupSingleton()                    \ +{                                               \ +    sLog.append("x" #CLS);                      \ +}                                               \ +                                                \ +CLS::~CLS()                                     \ +{                                               \ +    sLog.append("~" #CLS);                      \ +} + +DEFINE_MEMBERS(A, B) +DEFINE_MEMBERS(B, A) +  namespace tut  { -	struct singleton -	{ -		// We need a class created with the LLSingleton template to test with. -		class LLSingletonTest: public LLSingleton<LLSingletonTest> -		{ - -		}; -	}; - -	typedef test_group<singleton> singleton_t; -	typedef singleton_t::object singleton_object_t; -	tut::singleton_t tut_singleton("LLSingleton"); - -	template<> template<> -	void singleton_object_t::test<1>() -	{ - -	} -	template<> template<> -	void singleton_object_t::test<2>() -	{ -		LLSingletonTest* singleton_test = LLSingletonTest::getInstance(); -		ensure(singleton_test); -	} -	template<> template<> -	void singleton_object_t::test<3>() -	{ -		//Construct the instance -		LLSingletonTest::getInstance(); -		ensure(LLSingletonTest::instanceExists()); - -		//Delete the instance -		LLSingletonTest::deleteSingleton(); -		ensure(!LLSingletonTest::instanceExists()); - -		//Construct it again. -		LLSingletonTest* singleton_test = LLSingletonTest::getInstance(); -		ensure(singleton_test); -		ensure(LLSingletonTest::instanceExists()); -	} +    struct singleton +    { +        // We need a class created with the LLSingleton template to test with. +        class LLSingletonTest: public LLSingleton<LLSingletonTest> +        { + +        }; +    }; + +    typedef test_group<singleton> singleton_t; +    typedef singleton_t::object singleton_object_t; +    tut::singleton_t tut_singleton("LLSingleton"); + +    template<> template<> +    void singleton_object_t::test<1>() +    { + +    } +    template<> template<> +    void singleton_object_t::test<2>() +    { +        LLSingletonTest* singleton_test = LLSingletonTest::getInstance(); +        ensure(singleton_test); +    } + +    template<> template<> +    void singleton_object_t::test<3>() +    { +        //Construct the instance +        LLSingletonTest::getInstance(); +        ensure(LLSingletonTest::instanceExists()); + +        //Delete the instance +        LLSingletonTest::deleteSingleton(); +        ensure(!LLSingletonTest::instanceExists()); + +        //Construct it again. +        LLSingletonTest* singleton_test = LLSingletonTest::getInstance(); +        ensure(singleton_test); +        ensure(LLSingletonTest::instanceExists()); +    } + +#define TESTS(CLS, OTHER, N0, N1, N2, N3)                               \ +    template<> template<>                                               \ +    void singleton_object_t::test<N0>()                                 \ +    {                                                                   \ +        set_test_name("just " #CLS);                                    \ +        CLS::sDepFlag = CLS::DEP_NONE;                                  \ +        OTHER::sDepFlag = OTHER::DEP_NONE;                              \ +        sLog.clear();                                                   \ +                                                                        \ +        (void)CLS::instance();                                          \ +        ensure_equals(sLog, #CLS "i" #CLS);                             \ +        LLSingletonBase::cleanupAll();                                  \ +        ensure_equals(sLog, #CLS "i" #CLS "x" #CLS);                    \ +        LLSingletonBase::deleteAll();                                   \ +        ensure_equals(sLog, #CLS "i" #CLS "x" #CLS "~" #CLS);           \ +    }                                                                   \ +                                                                        \ +    template<> template<>                                               \ +    void singleton_object_t::test<N1>()                                 \ +    {                                                                   \ +        set_test_name(#CLS " ctor depends " #OTHER);                    \ +        CLS::sDepFlag = CLS::DEP_CTOR;                                  \ +        OTHER::sDepFlag = OTHER::DEP_NONE;                              \ +        sLog.clear();                                                   \ +                                                                        \ +        (void)CLS::instance();                                          \ +        ensure_equals(sLog, #CLS #OTHER "i" #OTHER "i" #CLS);           \ +        LLSingletonBase::cleanupAll();                                  \ +        ensure_equals(sLog, #CLS #OTHER "i" #OTHER "i" #CLS "x" #CLS "x" #OTHER); \ +        LLSingletonBase::deleteAll();                                   \ +        ensure_equals(sLog, #CLS #OTHER "i" #OTHER "i" #CLS "x" #CLS "x" #OTHER "~" #CLS "~" #OTHER); \ +    }                                                                   \ +                                                                        \ +    template<> template<>                                               \ +    void singleton_object_t::test<N2>()                                 \ +    {                                                                   \ +        set_test_name(#CLS " init depends " #OTHER);                    \ +        CLS::sDepFlag = CLS::DEP_INIT;                                  \ +        OTHER::sDepFlag = OTHER::DEP_NONE;                              \ +        sLog.clear();                                                   \ +                                                                        \ +        (void)CLS::instance();                                          \ +        ensure_equals(sLog, #CLS "i" #CLS #OTHER "i" #OTHER);           \ +        LLSingletonBase::cleanupAll();                                  \ +        ensure_equals(sLog, #CLS "i" #CLS #OTHER "i" #OTHER "x" #CLS "x" #OTHER); \ +        LLSingletonBase::deleteAll();                                   \ +        ensure_equals(sLog, #CLS "i" #CLS #OTHER "i" #OTHER "x" #CLS "x" #OTHER "~" #CLS "~" #OTHER); \ +    }                                                                   \ +                                                                        \ +    template<> template<>                                               \ +    void singleton_object_t::test<N3>()                                 \ +    {                                                                   \ +        set_test_name(#CLS " circular init");                           \ +        CLS::sDepFlag = CLS::DEP_INIT;                                  \ +        OTHER::sDepFlag = OTHER::DEP_CTOR;                              \ +        sLog.clear();                                                   \ +                                                                        \ +        (void)CLS::instance();                                          \ +        ensure_equals(sLog, #CLS "i" #CLS #OTHER "i" #OTHER);           \ +        LLSingletonBase::cleanupAll();                                  \ +        ensure_equals(sLog, #CLS "i" #CLS #OTHER "i" #OTHER "x" #CLS "x" #OTHER); \ +        LLSingletonBase::deleteAll();                                   \ +        ensure_equals(sLog, #CLS "i" #CLS #OTHER "i" #OTHER "x" #CLS "x" #OTHER "~" #CLS "~" #OTHER); \ +    } + +    TESTS(A, B, 4, 5, 6, 7) +    TESTS(B, A, 8, 9, 10, 11)  } | 
