TestDestroyNested.cpp (3969B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this file, 5 * You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 /* 8 * Test an actor being destroyed during another ActorDestroy. 9 */ 10 11 #include "gtest/gtest.h" 12 13 #include "mozilla/_ipdltest/IPDLUnitTest.h" 14 #include "mozilla/_ipdltest/PTestDestroyNestedChild.h" 15 #include "mozilla/_ipdltest/PTestDestroyNestedParent.h" 16 #include "mozilla/_ipdltest/PTestDestroyNestedSubChild.h" 17 #include "mozilla/_ipdltest/PTestDestroyNestedSubParent.h" 18 19 #include "mozilla/SpinEventLoopUntil.h" 20 21 using namespace mozilla::ipc; 22 23 namespace mozilla::_ipdltest { 24 25 class TestDestroyNestedSubParent : public PTestDestroyNestedSubParent { 26 NS_INLINE_DECL_REFCOUNTING(TestDestroyNestedSubParent, override) 27 28 void ActorDestroy(ActorDestroyReason aReason) override; 29 30 bool mActorDestroyCalled = false; 31 bool mCloseManager = false; 32 33 nsrefcnt GetRefCnt() const { return mRefCnt; } 34 35 private: 36 ~TestDestroyNestedSubParent() = default; 37 }; 38 39 class TestDestroyNestedSubChild : public PTestDestroyNestedSubChild { 40 NS_INLINE_DECL_REFCOUNTING(TestDestroyNestedSubChild, override) 41 private: 42 ~TestDestroyNestedSubChild() = default; 43 }; 44 45 class TestDestroyNestedParent : public PTestDestroyNestedParent { 46 NS_INLINE_DECL_REFCOUNTING(TestDestroyNestedParent, override) 47 48 void ActorDestroy(ActorDestroyReason aReason) override; 49 50 bool mActorDestroyCalled = false; 51 52 private: 53 ~TestDestroyNestedParent() = default; 54 }; 55 56 class TestDestroyNestedChild : public PTestDestroyNestedChild { 57 NS_INLINE_DECL_REFCOUNTING(TestDestroyNestedChild, override) 58 59 already_AddRefed<PTestDestroyNestedSubChild> AllocPTestDestroyNestedSubChild() 60 override { 61 return MakeAndAddRef<TestDestroyNestedSubChild>(); 62 } 63 64 private: 65 ~TestDestroyNestedChild() = default; 66 }; 67 68 void TestDestroyNestedSubParent::ActorDestroy(ActorDestroyReason aReason) { 69 // Destroy our manager from within ActorDestroy() and assert that we don't 70 // re-enter. 71 EXPECT_FALSE(mActorDestroyCalled) << "re-entered ActorDestroy()"; 72 mActorDestroyCalled = true; 73 74 if (mCloseManager) { 75 EXPECT_FALSE( 76 static_cast<TestDestroyNestedParent*>(Manager())->mActorDestroyCalled) 77 << "manager already destroyed"; 78 Manager()->Close(); 79 EXPECT_TRUE( 80 static_cast<TestDestroyNestedParent*>(Manager())->mActorDestroyCalled) 81 << "manager successfully destroyed"; 82 } 83 84 // Make sure we also process any pending events, because we might be spinning 85 // a nested event loop within `ActorDestroy`. 86 NS_ProcessPendingEvents(nullptr); 87 } 88 89 void TestDestroyNestedParent::ActorDestroy(ActorDestroyReason aReason) { 90 // Destroy our manager from within ActorDestroy() and assert that we don't 91 // re-enter. 92 EXPECT_FALSE(mActorDestroyCalled) << "re-entered ActorDestroy()"; 93 mActorDestroyCalled = true; 94 } 95 96 IPDL_TEST(TestDestroyNested) { 97 auto p = MakeRefPtr<TestDestroyNestedSubParent>(); 98 p->mCloseManager = true; 99 auto* rv1 = mActor->SendPTestDestroyNestedSubConstructor(p); 100 ASSERT_EQ(p, rv1) << "can't allocate Sub"; 101 102 bool rv2 = PTestDestroyNestedSubParent::Send__delete__(p); 103 ASSERT_TRUE(rv2) 104 << "Send__delete__ failed"; 105 106 ASSERT_TRUE(mActor->mActorDestroyCalled) 107 << "Parent not destroyed"; 108 ASSERT_TRUE(p->mActorDestroyCalled) 109 << "Sub not destroyed"; 110 111 ASSERT_EQ(p->GetRefCnt(), 1u) << "Outstanding references to Sub remain"; 112 113 // Try to allocate a new actor under the already-destroyed manager, and ensure 114 // that it is destroyed as expected. 115 auto p2 = MakeRefPtr<TestDestroyNestedSubParent>(); 116 auto* rv3 = mActor->SendPTestDestroyNestedSubConstructor(p2); 117 ASSERT_EQ(rv3, nullptr) << "construction succeeded unexpectedly"; 118 119 ASSERT_TRUE(p2->mActorDestroyCalled) 120 << "Sub not destroyed"; 121 } 122 123 } // namespace mozilla::_ipdltest