diff options
Diffstat (limited to 'ipc/ipdl/test/cxx/TestEndpointBridgeMain.cpp')
-rw-r--r-- | ipc/ipdl/test/cxx/TestEndpointBridgeMain.cpp | 226 |
1 files changed, 226 insertions, 0 deletions
diff --git a/ipc/ipdl/test/cxx/TestEndpointBridgeMain.cpp b/ipc/ipdl/test/cxx/TestEndpointBridgeMain.cpp new file mode 100644 index 0000000000..4a4366f0ba --- /dev/null +++ b/ipc/ipdl/test/cxx/TestEndpointBridgeMain.cpp @@ -0,0 +1,226 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ + +#include "TestEndpointBridgeMain.h" + +#include "base/task.h" +#include "IPDLUnitTests.h" // fail etc. +#include "IPDLUnitTestSubprocess.h" + +using namespace std; + +namespace mozilla { +namespace _ipdltest { + +//----------------------------------------------------------------------------- +// main process +void TestEndpointBridgeMainParent::Main() { + if (!SendStart()) { + fail("sending Start"); + } +} + +mozilla::ipc::IPCResult TestEndpointBridgeMainParent::RecvBridged( + Endpoint<PTestEndpointBridgeMainSubParent>&& endpoint) { + TestEndpointBridgeMainSubParent* a = new TestEndpointBridgeMainSubParent(); + if (!endpoint.Bind(a)) { + fail("Bind failed"); + } + return IPC_OK(); +} + +void TestEndpointBridgeMainParent::ActorDestroy(ActorDestroyReason why) { + if (NormalShutdown != why) { + fail("unexpected destruction!"); + } + passed("ok"); + QuitParent(); +} + +mozilla::ipc::IPCResult TestEndpointBridgeMainSubParent::RecvHello() { + if (!SendHi()) { + return IPC_FAIL_NO_REASON(this); + } + return IPC_OK(); +} + +mozilla::ipc::IPCResult TestEndpointBridgeMainSubParent::RecvHelloSync() { + return IPC_OK(); +} + +mozilla::ipc::IPCResult TestEndpointBridgeMainSubParent::AnswerHelloRpc() { + if (!CallHiRpc()) { + return IPC_FAIL_NO_REASON(this); + } + return IPC_OK(); +} + +void TestEndpointBridgeMainSubParent::ActorDestroy(ActorDestroyReason why) { + if (NormalShutdown != why) { + fail("unexpected destruction!"); + } + + // ActorDestroy() is just a callback from IPDL-generated code, + // which needs the top-level actor (this) to stay alive a little + // longer so other things can be cleaned up. + MessageLoop::current()->PostTask( + do_AddRef(new DeleteTask<TestEndpointBridgeMainSubParent>(this))); +} + +//----------------------------------------------------------------------------- +// sub process --- child of main +TestEndpointBridgeMainChild* gEndpointBridgeMainChild; + +TestEndpointBridgeMainChild::TestEndpointBridgeMainChild() + : mSubprocess(nullptr) { + gEndpointBridgeMainChild = this; +} + +mozilla::ipc::IPCResult TestEndpointBridgeMainChild::RecvStart() { + vector<string> subsubArgs; + subsubArgs.push_back("TestEndpointBridgeSub"); + + mSubprocess = new IPDLUnitTestSubprocess(); + if (!mSubprocess->SyncLaunch(subsubArgs)) { + fail("problem launching subprocess"); + } + + IPC::Channel* transport = mSubprocess->GetChannel(); + if (!transport) { + fail("no transport"); + } + + TestEndpointBridgeSubParent* bsp = new TestEndpointBridgeSubParent(); + bsp->Open(transport, base::GetProcId(mSubprocess->GetChildProcessHandle())); + + bsp->Main(); + return IPC_OK(); +} + +void TestEndpointBridgeMainChild::ActorDestroy(ActorDestroyReason why) { + if (NormalShutdown != why) { + fail("unexpected destruction!"); + } + // NB: this is kosher because QuitChild() joins with the IO thread + mSubprocess->Destroy(); + mSubprocess = nullptr; + QuitChild(); +} + +void TestEndpointBridgeSubParent::Main() { + if (!SendPing()) { + fail("sending Ping"); + } +} + +mozilla::ipc::IPCResult TestEndpointBridgeSubParent::RecvBridgeEm() { + Endpoint<PTestEndpointBridgeMainSubParent> parent; + Endpoint<PTestEndpointBridgeMainSubChild> child; + nsresult rv; + rv = PTestEndpointBridgeMainSub::CreateEndpoints( + gEndpointBridgeMainChild->OtherPid(), OtherPid(), &parent, &child); + if (NS_FAILED(rv)) { + fail("opening PTestEndpointOpensOpened"); + } + + if (!gEndpointBridgeMainChild->SendBridged(std::move(parent))) { + fail("SendBridge failed for parent"); + } + if (!SendBridged(std::move(child))) { + fail("SendBridge failed for child"); + } + + return IPC_OK(); +} + +void TestEndpointBridgeSubParent::ActorDestroy(ActorDestroyReason why) { + if (NormalShutdown != why) { + fail("unexpected destruction!"); + } + gEndpointBridgeMainChild->Close(); + + // ActorDestroy() is just a callback from IPDL-generated code, + // which needs the top-level actor (this) to stay alive a little + // longer so other things can be cleaned up. + MessageLoop::current()->PostTask( + do_AddRef(new DeleteTask<TestEndpointBridgeSubParent>(this))); +} + +//----------------------------------------------------------------------------- +// subsub process --- child of sub + +static TestEndpointBridgeSubChild* gBridgeSubChild; + +TestEndpointBridgeSubChild::TestEndpointBridgeSubChild() { + gBridgeSubChild = this; +} + +mozilla::ipc::IPCResult TestEndpointBridgeSubChild::RecvPing() { + if (!SendBridgeEm()) { + fail("sending BridgeEm"); + } + return IPC_OK(); +} + +mozilla::ipc::IPCResult TestEndpointBridgeSubChild::RecvBridged( + Endpoint<PTestEndpointBridgeMainSubChild>&& endpoint) { + TestEndpointBridgeMainSubChild* a = new TestEndpointBridgeMainSubChild(); + + if (!endpoint.Bind(a)) { + fail("failed to Bind"); + } + + if (!a->SendHello()) { + fail("sending Hello"); + } + + return IPC_OK(); +} + +void TestEndpointBridgeSubChild::ActorDestroy(ActorDestroyReason why) { + if (NormalShutdown != why) { + fail("unexpected destruction!"); + } + QuitChild(); +} + +mozilla::ipc::IPCResult TestEndpointBridgeMainSubChild::RecvHi() { + if (!SendHelloSync()) { + fail("sending HelloSync"); + } + if (!CallHelloRpc()) { + fail("calling HelloRpc"); + } + if (!mGotHi) { + fail("didn't answer HiRpc"); + } + + // Need to close the channel without message-processing frames on + // the C++ stack + MessageLoop::current()->PostTask( + NewNonOwningRunnableMethod("ipc::IToplevelProtocol::Close", this, + &TestEndpointBridgeMainSubChild::Close)); + return IPC_OK(); +} + +mozilla::ipc::IPCResult TestEndpointBridgeMainSubChild::AnswerHiRpc() { + mGotHi = true; // d00d + return IPC_OK(); +} + +void TestEndpointBridgeMainSubChild::ActorDestroy(ActorDestroyReason why) { + if (NormalShutdown != why) { + fail("unexpected destruction!"); + } + + gBridgeSubChild->Close(); + + // ActorDestroy() is just a callback from IPDL-generated code, + // which needs the top-level actor (this) to stay alive a little + // longer so other things can be cleaned up. + MessageLoop::current()->PostTask( + do_AddRef(new DeleteTask<TestEndpointBridgeMainSubChild>(this))); +} + +} // namespace _ipdltest +} // namespace mozilla |