[Libreoffice-commits] core.git: include/o3tl o3tl/qa

Daniel Robertson danlrobertson89 at gmail.com
Sat Aug 29 15:48:02 PDT 2015


 include/o3tl/cow_wrapper.hxx    |   15 ++++++-
 o3tl/qa/cow_wrapper_clients.cxx |   50 +++++++++++++++++++++++
 o3tl/qa/cow_wrapper_clients.hxx |   56 ++++++++++++++++++++++++++
 o3tl/qa/test-cow_wrapper.cxx    |   84 ++++++++++++++++++++++++++++++++++++++++
 4 files changed, 203 insertions(+), 2 deletions(-)

New commits:
commit 311e77440f11dbe8e49d75b09a4ae0f850ce00c5
Author: Daniel Robertson <danlrobertson89 at gmail.com>
Date:   Thu Aug 27 17:55:55 2015 -0400

    o3tl: add another unit test to cow_wrapper
    
    Add unit tests to cow_wrapper for the move ctor and move assignment.
    
    Change-Id: I82a5886ca7ae110985c7202125699cf95b6466d8
    Reviewed-on: https://gerrit.libreoffice.org/18108
    Reviewed-by: Thorsten Behrens <Thorsten.Behrens at CIB.de>
    Tested-by: Thorsten Behrens <Thorsten.Behrens at CIB.de>

diff --git a/include/o3tl/cow_wrapper.hxx b/include/o3tl/cow_wrapper.hxx
index 3f117a2b..da822b2 100644
--- a/include/o3tl/cow_wrapper.hxx
+++ b/include/o3tl/cow_wrapper.hxx
@@ -113,9 +113,11 @@ class cow_wrapper_client
 public:
     cow_wrapper_client();
     cow_wrapper_client( const cow_wrapper_client& );
+    cow_wrapper_client( cow_wrapper_client&& );
     ~cow_wrapper_client();
 
     cow_wrapper_client& operator=( const cow_wrapper_client& );
+    cow_wrapper_client& operator=( cow_wrapper_client&& );
 
     void modify( int nVal );
     int queryUnmodified() const;
@@ -144,6 +146,10 @@ cow_wrapper_client::cow_wrapper_client( const cow_wrapper_client& rSrc ) :
     maImpl( rSrc.maImpl )
 {
 }
+cow_wrapper_client::cow_wrapper_client( cow_wrapper_client& rSrc ) :
+    maImpl( std::move( rSrc.maImpl ) )
+{
+}
 cow_wrapper_client::~cow_wrapper_client()
 {
 }
@@ -152,6 +158,11 @@ cow_wrapper_client& cow_wrapper_client::operator=( const cow_wrapper_client& rSr
     maImpl = rSrc.maImpl;
     return *this;
 }
+cow_wrapper_client& cow_wrapper_client::operator=( cow_wrapper_client&& rSrc )
+{
+    maImpl = std::move( rSrc.maImpl );
+    return *this;
+}
 void cow_wrapper_client::modify( int nVal )
 {
     maImpl->setValue( nVal );
@@ -272,13 +283,13 @@ int cow_wrapper_client::queryUnmodified() const
         /// true, if not shared with any other cow_wrapper instance
         bool is_unique() const // nothrow
         {
-            return m_pimpl->m_ref_count == 1;
+            return m_pimpl ? m_pimpl->m_ref_count == 1 : true;
         }
 
         /// return number of shared instances (1 for unique object)
         typename MTPolicy::ref_count_t use_count() const // nothrow
         {
-            return m_pimpl->m_ref_count;
+            return m_pimpl ? m_pimpl->m_ref_count : 0;
         }
 
         void swap(cow_wrapper& r) // never throws
diff --git a/o3tl/qa/cow_wrapper_clients.cxx b/o3tl/qa/cow_wrapper_clients.cxx
index d49dd09..3cea257 100644
--- a/o3tl/qa/cow_wrapper_clients.cxx
+++ b/o3tl/qa/cow_wrapper_clients.cxx
@@ -219,6 +219,56 @@ bool cow_wrapper_client4::operator<( const cow_wrapper_client4& rRHS ) const
     return maImpl < rRHS.maImpl;
 }
 
+bool BogusRefCountPolicy::s_bShouldIncrement = 0;
+bool BogusRefCountPolicy::s_bShouldDecrement = 0;
+sal_uInt32 BogusRefCountPolicy::s_nEndOfScope = 0;
+
+cow_wrapper_client5::cow_wrapper_client5() :
+    maImpl()
+{
+}
+
+cow_wrapper_client5::cow_wrapper_client5(int nX) :
+    maImpl(nX)
+{
+}
+
+cow_wrapper_client5::cow_wrapper_client5( const cow_wrapper_client5& rSrc ) :
+    maImpl( rSrc.maImpl )
+{
+}
+
+cow_wrapper_client5::cow_wrapper_client5( cow_wrapper_client5&& rSrc ) :
+    maImpl( std::move( rSrc.maImpl ) )
+{
+}
+
+cow_wrapper_client5::~cow_wrapper_client5()
+{
+}
+
+cow_wrapper_client5& cow_wrapper_client5::operator=( const cow_wrapper_client5& rSrc )
+{
+    maImpl = rSrc.maImpl;
+
+    return *this;
+}
+
+cow_wrapper_client5& cow_wrapper_client5::operator=( cow_wrapper_client5&& rSrc )
+{
+    maImpl = std::move( rSrc.maImpl );
+
+    return *this;
+}
+
+bool cow_wrapper_client5::operator==( const cow_wrapper_client5& rSrc ) const {
+    return maImpl == rSrc.maImpl;
+}
+
+bool cow_wrapper_client5::operator!=( const cow_wrapper_client5& rSrc ) const {
+    return maImpl != rSrc.maImpl;
+}
+
 } // namespace o3tltests
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/o3tl/qa/cow_wrapper_clients.hxx b/o3tl/qa/cow_wrapper_clients.hxx
index 30dd5e0..f438c06 100644
--- a/o3tl/qa/cow_wrapper_clients.hxx
+++ b/o3tl/qa/cow_wrapper_clients.hxx
@@ -21,6 +21,7 @@
 #define INCLUDED_O3TL_QA_COW_WRAPPER_CLIENTS_HXX
 
 #include "o3tl/cow_wrapper.hxx"
+#include "cppunit/extensions/HelperMacros.h"
 
 /* Definition of Cow_Wrapper_Clients classes */
 
@@ -139,6 +140,61 @@ private:
     o3tl::cow_wrapper< int > maImpl;
 };
 
+// singleton ref-counting policy used to keep track of when
+// incrementing and decrementing occurs
+struct BogusRefCountPolicy
+{
+    static bool s_bShouldIncrement;
+    static bool s_bShouldDecrement;
+    static sal_uInt32 s_nEndOfScope;
+    typedef sal_uInt32 ref_count_t;
+    static void incrementCount( ref_count_t& rCount ) {
+        if(s_bShouldIncrement)
+        {
+            ++rCount;
+            s_bShouldIncrement = 0;
+        }
+        else
+            CPPUNIT_FAIL("Ref-counting policy incremented when it should not have.");
+    }
+    static bool decrementCount( ref_count_t& rCount ) {
+        if(s_nEndOfScope)
+        {
+            --rCount;
+            --s_nEndOfScope;
+            return true;
+        }
+        if(s_bShouldDecrement)
+        {
+            --rCount;
+            s_bShouldDecrement = 0;
+        }
+        else
+            CPPUNIT_FAIL("Ref-counting policy decremented when it should not have.");
+        return true;
+    }
+};
+
+class cow_wrapper_client5
+{
+public:
+    cow_wrapper_client5();
+    explicit cow_wrapper_client5(int);
+    ~cow_wrapper_client5();
+
+    cow_wrapper_client5( const cow_wrapper_client5& );
+    cow_wrapper_client5( cow_wrapper_client5&& );
+    cow_wrapper_client5& operator=( const cow_wrapper_client5& );
+    cow_wrapper_client5& operator=( cow_wrapper_client5&& );
+
+    sal_uInt32 use_count() const { return maImpl.use_count(); }
+
+    bool operator==( const cow_wrapper_client5& rRHS ) const;
+    bool operator!=( const cow_wrapper_client5& rRHS ) const;
+
+private:
+    o3tl::cow_wrapper< int, BogusRefCountPolicy > maImpl;
+};
 } // namespace o3tltests
 
 #endif // INCLUDED_O3TL_QA_COW_WRAPPER_CLIENTS_HXX
diff --git a/o3tl/qa/test-cow_wrapper.cxx b/o3tl/qa/test-cow_wrapper.cxx
index 82bc2be..7100355 100644
--- a/o3tl/qa/test-cow_wrapper.cxx
+++ b/o3tl/qa/test-cow_wrapper.cxx
@@ -161,6 +161,89 @@ public:
                                !aTestObj1.is_default() );
     }
 
+    void testRefCounting()
+    {
+        // add scope to ensure appropriate number of calls to
+        // the reference counting policy have been made
+        {
+            // if any incrementing/decrementing occurs a failure
+            // will occur
+            cow_wrapper_client5 aTestObj1(1);
+            cow_wrapper_client5 aTestObj2( std::move( aTestObj1 ) );
+            CPPUNIT_ASSERT_MESSAGE("aTestObj2.use_count() == 1",
+                                   aTestObj2.use_count() == 1 );
+
+            // the following should increment
+            BogusRefCountPolicy::s_bShouldIncrement = 1;
+            cow_wrapper_client5 aTestObj3( aTestObj2 );
+            CPPUNIT_ASSERT_MESSAGE("s_bShouldIncrement == 0",
+                                   BogusRefCountPolicy::s_bShouldIncrement == 0 );
+
+            CPPUNIT_ASSERT_MESSAGE("aTestObj3.use_count() == 2",
+                                   aTestObj3.use_count() == 2 );
+            {
+                cow_wrapper_client5 aTestObj4;
+                // the following should decrement the lvalue and then increment the rvalue
+                BogusRefCountPolicy::s_bShouldIncrement = 1;
+                BogusRefCountPolicy::s_bShouldDecrement = 1;
+                aTestObj4 = aTestObj2;
+                CPPUNIT_ASSERT_MESSAGE("s_bShouldIncrement == 0",
+                                       BogusRefCountPolicy::s_bShouldIncrement == 0 );
+                CPPUNIT_ASSERT_MESSAGE("s_bShouldDecrement == 0",
+                                       BogusRefCountPolicy::s_bShouldDecrement == 0 );
+
+                CPPUNIT_ASSERT_MESSAGE("aTestObj2.use_count() == 3",
+                                       aTestObj2.use_count() == 3 );
+                CPPUNIT_ASSERT_MESSAGE("aTestObj3.use_count() == 3",
+                                       aTestObj3.use_count() == 3 );
+                CPPUNIT_ASSERT_MESSAGE("aTestObj4.use_count() == 3",
+                                       aTestObj4.use_count() == 3 );
+                CPPUNIT_ASSERT_MESSAGE("aTestObj2 == aTestObj3",
+                                       aTestObj2 == aTestObj3 );
+                CPPUNIT_ASSERT_MESSAGE("aTestObj3 == aTestObj4",
+                                       aTestObj3 == aTestObj4 );
+                CPPUNIT_ASSERT_MESSAGE("aTestObj2 == aTestObj4",
+                                       aTestObj2 == aTestObj4 );
+
+                // only decrement the lvalue before assignment
+                BogusRefCountPolicy::s_bShouldDecrement = 1;
+                aTestObj4 = cow_wrapper_client5( 4 );
+                CPPUNIT_ASSERT_MESSAGE("s_bShouldIncrement == 0",
+                                       BogusRefCountPolicy::s_bShouldIncrement == 0 );
+
+                // only one call should be made to the ref counting policy's
+                // decrementing function at the end of the scope
+                BogusRefCountPolicy::s_bShouldDecrement = 1;
+            }
+            CPPUNIT_ASSERT_MESSAGE("s_bShouldDecrement == 0",
+                                   BogusRefCountPolicy::s_bShouldDecrement == 0 );
+
+            // self assignment
+            // aTestObj2 is defunct afterwards, one decrement happens
+            BogusRefCountPolicy::s_bShouldDecrement = 1;
+            aTestObj3 = std::move( aTestObj2 );
+            CPPUNIT_ASSERT_MESSAGE("aTestObj2.use_count() == 0",
+                                   aTestObj2.use_count() == 0 );
+            CPPUNIT_ASSERT_MESSAGE("aTestObj3.use_count() == 1",
+                                   aTestObj3.use_count() == 1 );
+
+            cow_wrapper_client5 aTestObj5;
+
+            // only decrement the lvalue before assignment
+            BogusRefCountPolicy::s_bShouldDecrement = 1;
+            aTestObj3 = std::move( aTestObj5 );
+            CPPUNIT_ASSERT_MESSAGE("s_bShouldDecrement == 0",
+                                   BogusRefCountPolicy::s_bShouldDecrement == 0);
+
+            // one call should be made to the ref-counting policy's
+            // decrementing function at the end of the scope. Only
+            // aTestObj3 still holds a valid instance
+            BogusRefCountPolicy::s_nEndOfScope = 1;
+        }
+        CPPUNIT_ASSERT_MESSAGE("s_EndOfScope == 0",
+                               BogusRefCountPolicy::s_nEndOfScope == 0 );
+    }
+
     // Change the following lines only, if you add, remove or rename
     // member functions of the current class,
     // because these macros are need by auto register mechanism.
@@ -168,6 +251,7 @@ public:
     CPPUNIT_TEST_SUITE(cow_wrapper_test);
     CPPUNIT_TEST(testCowWrapper);
     CPPUNIT_TEST(testStaticDefault);
+    CPPUNIT_TEST(testRefCounting);
     CPPUNIT_TEST_SUITE_END();
 };
 


More information about the Libreoffice-commits mailing list