From 5db25ede2566578539ed6b0ab728baf63cc1add9 Mon Sep 17 00:00:00 2001 From: Vinnie Falco Date: Thu, 5 Sep 2013 16:59:09 -0700 Subject: [PATCH] Add LoanedObject container example unit test --- .../ripple_app/main/ripple_Application.cpp | 155 ++++++++++++++++++ 1 file changed, 155 insertions(+) diff --git a/modules/ripple_app/main/ripple_Application.cpp b/modules/ripple_app/main/ripple_Application.cpp index c4158229e0..c84bc3152b 100644 --- a/modules/ripple_app/main/ripple_Application.cpp +++ b/modules/ripple_app/main/ripple_Application.cpp @@ -1165,3 +1165,158 @@ Application& getApp () { return *ApplicationImp::getInstance (); } + +//------------------------------------------------------------------------------ + +// Holds a loaned object. The destructor returns it to the source. +template +class LoanedObjectHolder : public SharedObject +{ +public: + class Owner + { + public: + virtual void recoverLoanedObject (Object* object) = 0; + }; + + // The class that loans out the object uses this constructor + LoanedObjectHolder (Owner* owner, Object* object) + : m_owner (owner) + , m_object (object) + { + } + + ~LoanedObjectHolder () + { + m_owner->recoverLoanedObject (m_object); + } + + Object& get () + { + return *m_object; + } + + Object const& get () const + { + return *m_object; + } + +private: + Owner* m_owner; + Object* m_object; +}; + +//------------------------------------------------------------------------------ + +class LoanedObjectTests : public UnitTest +{ +public: + // Meets the LoaningContainer requirements + // + class LoanedObject : public List ::Node + { + public: + void useful () + { + } + }; + + // Requirements: + // Object must be derived from List ::Node + // + template + class LoaningContainer : protected LoanedObjectHolder ::Owner + { + protected: + void recoverLoanedObject (Object* object) + { + m_list.push_front (*object); + } + + public: + typedef Object ValueType; + typedef Object& Reference; + typedef Object* Pointer; + typedef LoanedObjectHolder Holder; + typedef SharedPtr Ptr; + + LoaningContainer () + { + } + + ~LoaningContainer () + { + while (! m_list.empty ()) + delete (&m_list.pop_front ()); + } + + bool empty () const + { + return m_list.empty (); + } + + std::size_t size () const + { + return m_list.size (); + } + + // Donate an object that can be loaned out later + // Ownership is transferred, the object must have been + // allocated via operator new. + // + void donate (Object* object) + { + m_list.push_front (*object); + } + + // Check an object out + Ptr borrow () + { + if (m_list.empty ()) + return Ptr (); + + Object& object (m_list.pop_front ()); + return Ptr (new Holder (this, &object)); + } + + private: + List m_list; + }; + + enum + { + numberAvailable = 5 + }; + + void runTest () + { + beginTestCase ("loan objects"); + + typedef LoaningContainer Container; + + Container items; + + expect (items.size () == 0); + + for (int i = 0; i < numberAvailable; ++i) + items.donate (new LoanedObject); + + expect (items.size () == numberAvailable); + + { + Container::Ptr item (items.borrow()); + + item->get().useful (); + + expect (items.size () == numberAvailable - 1); + } + + expect (items.size () == numberAvailable); + } + + LoanedObjectTests () : UnitTest ("LoanedObject", "ripple", runManual) + { + } +}; + +static LoanedObjectTests loanedObjectTests;