michael@0: /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ michael@0: // vim:cindent:ts=4:et:sw=4: michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include "nsAutoPtr.h" michael@0: #include michael@0: #include "nscore.h" michael@0: #include "mozilla/Attributes.h" michael@0: michael@0: class TestObjectBaseA { michael@0: public: michael@0: // Virtual dtor for deleting through base class pointer michael@0: virtual ~TestObjectBaseA() { } michael@0: int fooA; michael@0: }; michael@0: michael@0: class TestObjectBaseB { michael@0: public: michael@0: // Virtual dtor for deleting through base class pointer michael@0: virtual ~TestObjectBaseB() { } michael@0: int fooB; michael@0: }; michael@0: michael@0: class TestObject : public TestObjectBaseA, public TestObjectBaseB { michael@0: public: michael@0: TestObject() michael@0: { michael@0: printf(" Creating TestObject %p.\n", michael@0: static_cast(this)); michael@0: } michael@0: michael@0: // Virtual dtor for deleting through base class pointer michael@0: virtual ~TestObject() michael@0: { michael@0: printf(" Destroying TestObject %p.\n", michael@0: static_cast(this)); michael@0: } michael@0: }; michael@0: michael@0: class TestRefObjectBaseA { michael@0: public: michael@0: int fooA; michael@0: // Must return |nsrefcnt| to keep |nsDerivedSafe| happy. michael@0: virtual nsrefcnt AddRef() = 0; michael@0: virtual nsrefcnt Release() = 0; michael@0: }; michael@0: michael@0: class TestRefObjectBaseB { michael@0: public: michael@0: int fooB; michael@0: virtual nsrefcnt AddRef() = 0; michael@0: virtual nsrefcnt Release() = 0; michael@0: }; michael@0: michael@0: class TestRefObject MOZ_FINAL : public TestRefObjectBaseA, public TestRefObjectBaseB { michael@0: public: michael@0: TestRefObject() michael@0: : mRefCount(0) michael@0: { michael@0: printf(" Creating TestRefObject %p.\n", michael@0: static_cast(this)); michael@0: } michael@0: michael@0: ~TestRefObject() michael@0: { michael@0: printf(" Destroying TestRefObject %p.\n", michael@0: static_cast(this)); michael@0: } michael@0: michael@0: nsrefcnt AddRef() michael@0: { michael@0: ++mRefCount; michael@0: printf(" AddRef to %d on TestRefObject %p.\n", michael@0: mRefCount, static_cast(this)); michael@0: return mRefCount; michael@0: } michael@0: michael@0: nsrefcnt Release() michael@0: { michael@0: --mRefCount; michael@0: printf(" Release to %d on TestRefObject %p.\n", michael@0: mRefCount, static_cast(this)); michael@0: if (mRefCount == 0) { michael@0: delete const_cast(this); michael@0: return 0; michael@0: } michael@0: return mRefCount; michael@0: } michael@0: michael@0: protected: michael@0: uint32_t mRefCount; michael@0: michael@0: }; michael@0: michael@0: static void CreateTestObject(TestObject **aResult) michael@0: { michael@0: *aResult = new TestObject(); michael@0: } michael@0: michael@0: static void CreateTestRefObject(TestRefObject **aResult) michael@0: { michael@0: (*aResult = new TestRefObject())->AddRef(); michael@0: } michael@0: michael@0: static void DoSomethingWithTestObject(TestObject *aIn) michael@0: { michael@0: printf(" Doing something with |TestObject| %p.\n", michael@0: static_cast(aIn)); michael@0: } michael@0: michael@0: static void DoSomethingWithConstTestObject(const TestObject *aIn) michael@0: { michael@0: printf(" Doing something with |const TestObject| %p.\n", michael@0: static_cast(aIn)); michael@0: } michael@0: michael@0: static void DoSomethingWithTestRefObject(TestRefObject *aIn) michael@0: { michael@0: printf(" Doing something with |TestRefObject| %p.\n", michael@0: static_cast(aIn)); michael@0: } michael@0: michael@0: static void DoSomethingWithConstTestRefObject(const TestRefObject *aIn) michael@0: { michael@0: printf(" Doing something with |const TestRefObject| %p.\n", michael@0: static_cast(aIn)); michael@0: } michael@0: michael@0: static void DoSomethingWithTestObjectBaseB(TestObjectBaseB *aIn) michael@0: { michael@0: printf(" Doing something with |TestObjectBaseB| %p.\n", michael@0: static_cast(aIn)); michael@0: } michael@0: michael@0: static void DoSomethingWithConstTestObjectBaseB(const TestObjectBaseB *aIn) michael@0: { michael@0: printf(" Doing something with |const TestObjectBaseB| %p.\n", michael@0: static_cast(aIn)); michael@0: } michael@0: michael@0: static void DoSomethingWithTestRefObjectBaseB(TestRefObjectBaseB *aIn) michael@0: { michael@0: printf(" Doing something with |TestRefObjectBaseB| %p.\n", michael@0: static_cast(aIn)); michael@0: } michael@0: michael@0: static void DoSomethingWithConstTestRefObjectBaseB(const TestRefObjectBaseB *aIn) michael@0: { michael@0: printf(" Doing something with |const TestRefObjectBaseB| %p.\n", michael@0: static_cast(aIn)); michael@0: } michael@0: michael@0: int main() michael@0: { michael@0: { michael@0: printf("Should create one |TestObject|:\n"); michael@0: nsAutoPtr pobj( new TestObject() ); michael@0: printf("Should destroy one |TestObject|:\n"); michael@0: } michael@0: michael@0: { michael@0: printf("Should create one |TestObject|:\n"); michael@0: nsAutoPtr pobj( new TestObject() ); michael@0: printf("Should create one |TestObject| and then destroy one:\n"); michael@0: pobj = new TestObject(); michael@0: printf("Should destroy one |TestObject|:\n"); michael@0: } michael@0: michael@0: { michael@0: printf("Should create 3 |TestObject|s:\n"); michael@0: nsAutoArrayPtr pobj( new TestObject[3] ); michael@0: printf("Should create 5 |TestObject|s and then destroy 3:\n"); michael@0: pobj = new TestObject[5]; michael@0: printf("Should destroy 5 |TestObject|s:\n"); michael@0: } michael@0: michael@0: { michael@0: printf("Should create and AddRef one |TestRefObject|:\n"); michael@0: nsRefPtr pobj( new TestRefObject() ); michael@0: printf("Should Release and destroy one |TestRefObject|:\n"); michael@0: } michael@0: michael@0: { michael@0: printf("Should create and AddRef one |TestRefObject|:\n"); michael@0: nsRefPtr pobj( new TestRefObject() ); michael@0: printf("Should create and AddRef one |TestRefObject| and then Release and destroy one:\n"); michael@0: pobj = new TestRefObject(); michael@0: printf("Should Release and destroy one |TestRefObject|:\n"); michael@0: } michael@0: michael@0: { michael@0: printf("Should create and AddRef one |TestRefObject|:\n"); michael@0: nsRefPtr p1( new TestRefObject() ); michael@0: printf("Should AddRef one |TestRefObject|:\n"); michael@0: nsRefPtr p2( p1 ); michael@0: printf("Should Release twice and destroy one |TestRefObject|:\n"); michael@0: } michael@0: michael@0: printf("\nTesting equality (with all const-ness combinations):\n"); michael@0: michael@0: { michael@0: nsRefPtr p1( new TestRefObject() ); michael@0: nsRefPtr p2( p1 ); michael@0: printf("equality %s.\n", michael@0: ((p1 == p2) && !(p1 != p2)) ? "OK" : "broken"); michael@0: } michael@0: michael@0: { michael@0: const nsRefPtr p1( new TestRefObject() ); michael@0: nsRefPtr p2( p1 ); michael@0: printf("equality %s.\n", michael@0: ((p1 == p2) && !(p1 != p2)) ? "OK" : "broken"); michael@0: } michael@0: michael@0: { michael@0: nsRefPtr p1( new TestRefObject() ); michael@0: const nsRefPtr p2( p1 ); michael@0: printf("equality %s.\n", michael@0: ((p1 == p2) && !(p1 != p2)) ? "OK" : "broken"); michael@0: } michael@0: michael@0: { michael@0: const nsRefPtr p1( new TestRefObject() ); michael@0: const nsRefPtr p2( p1 ); michael@0: printf("equality %s.\n", michael@0: ((p1 == p2) && !(p1 != p2)) ? "OK" : "broken"); michael@0: } michael@0: michael@0: { michael@0: nsRefPtr p1( new TestRefObject() ); michael@0: TestRefObject * p2 = p1; michael@0: printf("equality %s.\n", michael@0: ((p1 == p2) && !(p1 != p2) && (p2 == p1) && !(p2 != p1)) ? "OK" : "broken"); michael@0: } michael@0: michael@0: { michael@0: const nsRefPtr p1( new TestRefObject() ); michael@0: TestRefObject * p2 = p1; michael@0: printf("equality %s.\n", michael@0: ((p1 == p2) && !(p1 != p2) && (p2 == p1) && !(p2 != p1)) ? "OK" : "broken"); michael@0: } michael@0: michael@0: #if 0 /* MSVC++ 6.0 can't be coaxed to accept this */ michael@0: { michael@0: nsRefPtr p1( new TestRefObject() ); michael@0: TestRefObject * const p2 = p1; michael@0: printf("equality %s.\n", michael@0: ((p1 == p2) && !(p1 != p2) && (p2 == p1) && !(p2 != p1)) ? "OK" : "broken"); michael@0: } michael@0: michael@0: { michael@0: const nsRefPtr p1( new TestRefObject() ); michael@0: TestRefObject * const p2 = p1; michael@0: printf("equality %s.\n", michael@0: ((p1 == p2) && !(p1 != p2) && (p2 == p1) && !(p2 != p1)) ? "OK" : "broken"); michael@0: } michael@0: #endif /* Things that MSVC++ 6.0 can't be coaxed to accept */ michael@0: michael@0: { michael@0: nsRefPtr p1( new TestRefObject() ); michael@0: const TestRefObject * p2 = p1; michael@0: printf("equality %s.\n", michael@0: ((p1 == p2) && !(p1 != p2) && (p2 == p1) && !(p2 != p1)) ? "OK" : "broken"); michael@0: } michael@0: michael@0: { michael@0: const nsRefPtr p1( new TestRefObject() ); michael@0: const TestRefObject * p2 = p1; michael@0: printf("equality %s.\n", michael@0: ((p1 == p2) && !(p1 != p2) && (p2 == p1) && !(p2 != p1)) ? "OK" : "broken"); michael@0: } michael@0: michael@0: { michael@0: nsRefPtr p1( new TestRefObject() ); michael@0: const TestRefObject * const p2 = p1; michael@0: printf("equality %s.\n", michael@0: ((p1 == p2) && !(p1 != p2) && (p2 == p1) && !(p2 != p1)) ? "OK" : "broken"); michael@0: } michael@0: michael@0: { michael@0: const nsRefPtr p1( new TestRefObject() ); michael@0: const TestRefObject * const p2 = p1; michael@0: printf("equality %s.\n", michael@0: ((p1 == p2) && !(p1 != p2) && (p2 == p1) && !(p2 != p1)) ? "OK" : "broken"); michael@0: } michael@0: michael@0: printf("\nTesting getter_Transfers and getter_AddRefs.\n"); michael@0: michael@0: { michael@0: nsAutoPtr ptr; michael@0: printf("Should create one |TestObject|:\n"); michael@0: CreateTestObject(getter_Transfers(ptr)); michael@0: printf("Should destroy one |TestObject|:\n"); michael@0: } michael@0: michael@0: { michael@0: nsRefPtr ptr; michael@0: printf("Should create and AddRef one |TestRefObject|:\n"); michael@0: CreateTestRefObject(getter_AddRefs(ptr)); michael@0: printf("Should Release and destroy one |TestRefObject|:\n"); michael@0: } michael@0: michael@0: printf("\nTesting casts and equality tests.\n"); michael@0: michael@0: if ((void*)(TestObject*)0x1000 == michael@0: (void*)(TestObjectBaseB*)(TestObject*)0x1000) michael@0: printf("\n\nAll these tests are meaningless!\n\n\n"); michael@0: michael@0: { michael@0: nsAutoPtr p1(new TestObject()); michael@0: TestObjectBaseB *p2 = p1; michael@0: printf("equality %s.\n", michael@0: ((static_cast(p1) != static_cast(p2)) && michael@0: (p1 == p2) && !(p1 != p2) && (p2 == p1) && !(p2 != p1)) michael@0: ? "OK" : "broken"); michael@0: } michael@0: michael@0: { michael@0: TestObject *p1 = new TestObject(); michael@0: nsAutoPtr p2(p1); michael@0: printf("equality %s.\n", michael@0: ((static_cast(p1) != static_cast(p2)) && michael@0: (p1 == p2) && !(p1 != p2) && (p2 == p1) && !(p2 != p1)) michael@0: ? "OK" : "broken"); michael@0: } michael@0: michael@0: { michael@0: nsRefPtr p1 = new TestRefObject(); michael@0: // nsCOMPtr requires a |get| for something like this as well michael@0: nsRefPtr p2 = p1.get(); michael@0: printf("equality %s.\n", michael@0: ((static_cast(p1) != static_cast(p2)) && michael@0: (p1 == p2) && !(p1 != p2) && (p2 == p1) && !(p2 != p1)) michael@0: ? "OK" : "broken"); michael@0: } michael@0: michael@0: { michael@0: nsRefPtr p1 = new TestRefObject(); michael@0: TestRefObjectBaseB *p2 = p1; michael@0: printf("equality %s.\n", michael@0: ((static_cast(p1) != static_cast(p2)) && michael@0: (p1 == p2) && !(p1 != p2) && (p2 == p1) && !(p2 != p1)) michael@0: ? "OK" : "broken"); michael@0: } michael@0: michael@0: { michael@0: TestRefObject *p1 = new TestRefObject(); michael@0: nsRefPtr p2 = p1; michael@0: printf("equality %s.\n", michael@0: ((static_cast(p1) != static_cast(p2)) && michael@0: (p1 == p2) && !(p1 != p2) && (p2 == p1) && !(p2 != p1)) michael@0: ? "OK" : "broken"); michael@0: } michael@0: michael@0: printf("\nTesting |forget()|.\n"); michael@0: michael@0: { michael@0: printf("Should create one |TestObject|:\n"); michael@0: nsAutoPtr pobj( new TestObject() ); michael@0: printf("Should do nothing:\n"); michael@0: nsAutoPtr pobj2( pobj.forget() ); michael@0: printf("Should destroy one |TestObject|:\n"); michael@0: } michael@0: michael@0: { michael@0: printf("Should create 3 |TestObject|s:\n"); michael@0: nsAutoArrayPtr pobj( new TestObject[3] ); michael@0: printf("Should do nothing:\n"); michael@0: nsAutoArrayPtr pobj2( pobj.forget() ); michael@0: printf("Should destroy 3 |TestObject|s:\n"); michael@0: } michael@0: michael@0: { michael@0: printf("Should create one |TestRefObject|:\n"); michael@0: nsRefPtr pobj( new TestRefObject() ); michael@0: printf("Should do nothing:\n"); michael@0: nsRefPtr pobj2( pobj.forget() ); michael@0: printf("Should destroy one |TestRefObject|:\n"); michael@0: } michael@0: michael@0: michael@0: printf("\nTesting construction.\n"); michael@0: michael@0: { michael@0: printf("Should create one |TestObject|:\n"); michael@0: nsAutoPtr pobj(new TestObject()); michael@0: printf("Should destroy one |TestObject|:\n"); michael@0: } michael@0: michael@0: { michael@0: printf("Should create 3 |TestObject|s:\n"); michael@0: nsAutoArrayPtr pobj(new TestObject[3]); michael@0: printf("Should destroy 3 |TestObject|s:\n"); michael@0: } michael@0: michael@0: { michael@0: printf("Should create and AddRef one |TestRefObject|:\n"); michael@0: nsRefPtr pobj = new TestRefObject(); michael@0: printf("Should Release and destroy one |TestRefObject|:\n"); michael@0: } michael@0: michael@0: printf("\nTesting calling of functions (including array access and casts).\n"); michael@0: michael@0: { michael@0: printf("Should create one |TestObject|:\n"); michael@0: nsAutoPtr pobj(new TestObject()); michael@0: printf("Should do something with one |TestObject|:\n"); michael@0: DoSomethingWithTestObject(pobj); michael@0: printf("Should do something with one |TestObject|:\n"); michael@0: DoSomethingWithConstTestObject(pobj); michael@0: printf("Should destroy one |TestObject|:\n"); michael@0: } michael@0: michael@0: { michael@0: printf("Should create 3 |TestObject|s:\n"); michael@0: nsAutoArrayPtr pobj(new TestObject[3]); michael@0: printf("Should do something with one |TestObject|:\n"); michael@0: DoSomethingWithTestObject(&pobj[2]); michael@0: printf("Should do something with one |TestObject|:\n"); michael@0: DoSomethingWithConstTestObject(&pobj[1]); michael@0: printf("Should do something with one |TestObject|:\n"); michael@0: DoSomethingWithTestObject(pobj + 2); michael@0: printf("Should do something with one |TestObject|:\n"); michael@0: DoSomethingWithConstTestObject(pobj + 1); michael@0: printf("Should destroy 3 |TestObject|s:\n"); michael@0: } michael@0: michael@0: { michael@0: printf("Should create and AddRef one |TestRefObject|:\n"); michael@0: nsRefPtr pobj = new TestRefObject(); michael@0: printf("Should do something with one |TestRefObject|:\n"); michael@0: DoSomethingWithTestRefObject(pobj); michael@0: printf("Should do something with one |TestRefObject|:\n"); michael@0: DoSomethingWithConstTestRefObject(pobj); michael@0: printf("Should Release and destroy one |TestRefObject|:\n"); michael@0: } michael@0: michael@0: { michael@0: printf("Should create one |TestObject|:\n"); michael@0: nsAutoPtr pobj(new TestObject()); michael@0: printf("Should do something with one |TestObject|:\n"); michael@0: DoSomethingWithTestObjectBaseB(pobj); michael@0: printf("Should do something with one |TestObject|:\n"); michael@0: DoSomethingWithConstTestObjectBaseB(pobj); michael@0: printf("Should destroy one |TestObject|:\n"); michael@0: } michael@0: michael@0: { michael@0: printf("Should create 3 |TestObject|s:\n"); michael@0: nsAutoArrayPtr pobj(new TestObject[3]); michael@0: printf("Should do something with one |TestObject|:\n"); michael@0: DoSomethingWithTestObjectBaseB(&pobj[2]); michael@0: printf("Should do something with one |TestObject|:\n"); michael@0: DoSomethingWithConstTestObjectBaseB(&pobj[1]); michael@0: printf("Should do something with one |TestObject|:\n"); michael@0: DoSomethingWithTestObjectBaseB(pobj + 2); michael@0: printf("Should do something with one |TestObject|:\n"); michael@0: DoSomethingWithConstTestObjectBaseB(pobj + 1); michael@0: printf("Should destroy 3 |TestObject|s:\n"); michael@0: } michael@0: michael@0: { michael@0: printf("Should create and AddRef one |TestRefObject|:\n"); michael@0: nsRefPtr pobj = new TestRefObject(); michael@0: printf("Should do something with one |TestRefObject|:\n"); michael@0: DoSomethingWithTestRefObjectBaseB(pobj); michael@0: printf("Should do something with one |TestRefObject|:\n"); michael@0: DoSomethingWithConstTestRefObjectBaseB(pobj); michael@0: printf("Should Release and destroy one |TestRefObject|:\n"); michael@0: } michael@0: michael@0: { michael@0: printf("Should create one |TestObject|:\n"); michael@0: const nsAutoPtr pobj(new TestObject()); michael@0: printf("Should do something with one |TestObject|:\n"); michael@0: DoSomethingWithTestObject(pobj); michael@0: printf("Should do something with one |TestObject|:\n"); michael@0: DoSomethingWithConstTestObject(pobj); michael@0: printf("Should destroy one |TestObject|:\n"); michael@0: } michael@0: michael@0: { michael@0: printf("Should create 3 |TestObject|s:\n"); michael@0: const nsAutoArrayPtr pobj(new TestObject[3]); michael@0: printf("Should do something with one |TestObject|:\n"); michael@0: DoSomethingWithTestObject(&pobj[2]); michael@0: printf("Should do something with one |TestObject|:\n"); michael@0: DoSomethingWithConstTestObject(&pobj[1]); michael@0: printf("Should do something with one |TestObject|:\n"); michael@0: DoSomethingWithTestObject(pobj + 2); michael@0: printf("Should do something with one |TestObject|:\n"); michael@0: DoSomethingWithConstTestObject(pobj + 1); michael@0: printf("Should destroy 3 |TestObject|s:\n"); michael@0: } michael@0: michael@0: { michael@0: printf("Should create and AddRef one |TestRefObject|:\n"); michael@0: const nsRefPtr pobj = new TestRefObject(); michael@0: printf("Should do something with one |TestRefObject|:\n"); michael@0: DoSomethingWithTestRefObject(pobj); michael@0: printf("Should do something with one |TestRefObject|:\n"); michael@0: DoSomethingWithConstTestRefObject(pobj); michael@0: printf("Should Release and destroy one |TestRefObject|:\n"); michael@0: } michael@0: michael@0: { michael@0: printf("Should create one |TestObject|:\n"); michael@0: const nsAutoPtr pobj(new TestObject()); michael@0: printf("Should do something with one |TestObject|:\n"); michael@0: DoSomethingWithTestObjectBaseB(pobj); michael@0: printf("Should do something with one |TestObject|:\n"); michael@0: DoSomethingWithConstTestObjectBaseB(pobj); michael@0: printf("Should destroy one |TestObject|:\n"); michael@0: } michael@0: michael@0: { michael@0: printf("Should create 3 |TestObject|s:\n"); michael@0: const nsAutoArrayPtr pobj(new TestObject[3]); michael@0: printf("Should do something with one |TestObject|:\n"); michael@0: DoSomethingWithTestObjectBaseB(&pobj[2]); michael@0: printf("Should do something with one |TestObject|:\n"); michael@0: DoSomethingWithConstTestObjectBaseB(&pobj[1]); michael@0: printf("Should do something with one |TestObject|:\n"); michael@0: DoSomethingWithTestObjectBaseB(pobj + 2); michael@0: printf("Should do something with one |TestObject|:\n"); michael@0: DoSomethingWithConstTestObjectBaseB(pobj + 1); michael@0: printf("Should destroy 3 |TestObject|s:\n"); michael@0: } michael@0: michael@0: { michael@0: printf("Should create and AddRef one |TestRefObject|:\n"); michael@0: const nsRefPtr pobj = new TestRefObject(); michael@0: printf("Should do something with one |TestRefObject|:\n"); michael@0: DoSomethingWithTestRefObjectBaseB(pobj); michael@0: printf("Should do something with one |TestRefObject|:\n"); michael@0: DoSomethingWithConstTestRefObjectBaseB(pobj); michael@0: printf("Should Release and destroy one |TestRefObject|:\n"); michael@0: } michael@0: michael@0: return 0; michael@0: }