TestEndpointOpens.cpp (4948B)
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 Endpoint usage. 9 */ 10 11 #include "gtest/gtest.h" 12 13 #include "mozilla/_ipdltest/IPDLUnitTest.h" 14 #include "mozilla/_ipdltest/PTestEndpointOpensChild.h" 15 #include "mozilla/_ipdltest/PTestEndpointOpensParent.h" 16 #include "mozilla/_ipdltest/PTestEndpointOpensOpenedChild.h" 17 #include "mozilla/_ipdltest/PTestEndpointOpensOpenedParent.h" 18 19 using namespace mozilla::ipc; 20 21 namespace mozilla::_ipdltest { 22 23 class TestEndpointOpensOpenedParent : public PTestEndpointOpensOpenedParent { 24 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(TestEndpointOpensOpenedParent, override) 25 private: 26 IPCResult RecvHello() final override { 27 EXPECT_FALSE(NS_IsMainThread()); 28 if (!SendHi()) { 29 return IPC_TEST_FAIL(this); 30 } 31 return IPC_OK(); 32 } 33 34 IPCResult RecvHelloSync() final override { 35 EXPECT_FALSE(NS_IsMainThread()); 36 return IPC_OK(); 37 } 38 39 void ActorDestroy(ActorDestroyReason why) final override { 40 EXPECT_FALSE(NS_IsMainThread()); 41 } 42 43 ~TestEndpointOpensOpenedParent() = default; 44 }; 45 46 class TestEndpointOpensChild : public PTestEndpointOpensChild { 47 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(TestEndpointOpensChild, override) 48 private: 49 IPCResult RecvStart() final override; 50 51 ~TestEndpointOpensChild() = default; 52 }; 53 54 class TestEndpointOpensOpenedChild : public PTestEndpointOpensOpenedChild { 55 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(TestEndpointOpensOpenedChild, override) 56 57 explicit TestEndpointOpensOpenedChild(TestEndpointOpensChild* opensChild) 58 : mOpensChild(opensChild) {} 59 60 private: 61 IPCResult RecvHi() final override { 62 EXPECT_FALSE(NS_IsMainThread()); 63 64 EXPECT_TRUE(SendHelloSync()); 65 66 Close(); 67 return IPC_OK(); 68 } 69 70 void ActorDestroy(ActorDestroyReason why) final override { 71 EXPECT_FALSE(NS_IsMainThread()); 72 73 // Kick off main-thread shutdown. 74 NS_DispatchToMainThread(NewRunnableMethod("ipc::IToplevelProtocol::Close", 75 mOpensChild, 76 &TestEndpointOpensChild::Close)); 77 } 78 79 ~TestEndpointOpensOpenedChild() = default; 80 81 TestEndpointOpensChild* mOpensChild; 82 }; 83 84 class TestEndpointOpensParent : public PTestEndpointOpensParent { 85 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(TestEndpointOpensParent, override) 86 private: 87 IPCResult RecvStartSubprotocol( 88 Endpoint<PTestEndpointOpensOpenedParent>&& endpoint) final override { 89 nsCOMPtr<nsISerialEventTarget> eventTarget; 90 auto rv = NS_CreateBackgroundTaskQueue("ParentThread", 91 getter_AddRefs(eventTarget)); 92 if (NS_FAILED(rv)) { 93 ADD_FAILURE() << "creating background task queue for child"; 94 return IPC_TEST_FAIL(this); 95 } 96 97 eventTarget->Dispatch(NS_NewRunnableFunction( 98 "OpenParent", [endpoint{std::move(endpoint)}]() mutable { 99 EXPECT_FALSE(NS_IsMainThread()); 100 101 // Open the actor on the off-main thread to park it there. 102 // Messages will be delivered to this thread's message loop 103 // instead of the main thread's. 104 auto actor = MakeRefPtr<TestEndpointOpensOpenedParent>(); 105 ASSERT_TRUE(endpoint.Bind(actor)); 106 })); 107 108 return IPC_OK(); 109 } 110 111 ~TestEndpointOpensParent() = default; 112 }; 113 114 IPCResult TestEndpointOpensChild::RecvStart() { 115 Endpoint<PTestEndpointOpensOpenedParent> parent; 116 Endpoint<PTestEndpointOpensOpenedChild> child; 117 nsresult rv; 118 rv = PTestEndpointOpensOpened::CreateEndpoints(&parent, &child); 119 if (NS_FAILED(rv)) { 120 ADD_FAILURE() << "opening PTestEndpointOpensOpened"; 121 return IPC_TEST_FAIL(this); 122 } 123 124 nsCOMPtr<nsISerialEventTarget> childEventTarget; 125 rv = NS_CreateBackgroundTaskQueue("ChildThread", 126 getter_AddRefs(childEventTarget)); 127 if (NS_FAILED(rv)) { 128 ADD_FAILURE() << "creating background task queue for child"; 129 return IPC_TEST_FAIL(this); 130 } 131 132 auto actor = MakeRefPtr<TestEndpointOpensOpenedChild>(this); 133 childEventTarget->Dispatch(NS_NewRunnableFunction( 134 "OpenChild", 135 [actor{std::move(actor)}, endpoint{std::move(child)}]() mutable { 136 EXPECT_FALSE(NS_IsMainThread()); 137 138 // Open the actor on the off-main thread to park it there. 139 // Messages will be delivered to this thread's message loop 140 // instead of the main thread's. 141 ASSERT_TRUE(endpoint.Bind(actor)); 142 143 // Kick off the unit tests 144 ASSERT_TRUE(actor->SendHello()); 145 })); 146 147 EXPECT_TRUE(SendStartSubprotocol(std::move(parent))); 148 149 return IPC_OK(); 150 } 151 152 IPDL_TEST_ON(CROSSPROCESS, TestEndpointOpens) { 153 EXPECT_TRUE(mActor->SendStart()); 154 } 155 156 } // namespace mozilla::_ipdltest