summaryrefslogtreecommitdiffstats
path: root/ipc/ipdl/test/cxx/TestBridgeMain.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'ipc/ipdl/test/cxx/TestBridgeMain.cpp')
-rw-r--r--ipc/ipdl/test/cxx/TestBridgeMain.cpp227
1 files changed, 227 insertions, 0 deletions
diff --git a/ipc/ipdl/test/cxx/TestBridgeMain.cpp b/ipc/ipdl/test/cxx/TestBridgeMain.cpp
new file mode 100644
index 000000000..9b1590a46
--- /dev/null
+++ b/ipc/ipdl/test/cxx/TestBridgeMain.cpp
@@ -0,0 +1,227 @@
+#include "TestBridgeMain.h"
+
+#include "base/task.h"
+#include "IPDLUnitTests.h" // fail etc.
+#include "IPDLUnitTestSubprocess.h"
+
+#include "nsAutoPtr.h"
+
+using namespace std;
+
+namespace mozilla {
+namespace _ipdltest {
+
+
+//-----------------------------------------------------------------------------
+// main process
+void
+TestBridgeMainParent::Main()
+{
+ if (!SendStart())
+ fail("sending Start");
+}
+
+PTestBridgeMainSubParent*
+TestBridgeMainParent::AllocPTestBridgeMainSubParent(Transport* transport,
+ ProcessId otherPid)
+{
+ nsAutoPtr<TestBridgeMainSubParent> a(new TestBridgeMainSubParent(transport));
+ if (!a->Open(transport, otherPid, XRE_GetIOMessageLoop(), ipc::ParentSide)) {
+ return nullptr;
+ }
+ return a.forget();
+}
+
+void
+TestBridgeMainParent::ActorDestroy(ActorDestroyReason why)
+{
+ if (NormalShutdown != why)
+ fail("unexpected destruction!");
+ passed("ok");
+ QuitParent();
+}
+
+bool
+TestBridgeMainSubParent::RecvHello()
+{
+ return SendHi();
+}
+
+bool
+TestBridgeMainSubParent::RecvHelloSync()
+{
+ return true;
+}
+
+bool
+TestBridgeMainSubParent::AnswerHelloRpc()
+{
+ return CallHiRpc();
+}
+
+void
+TestBridgeMainSubParent::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<TestBridgeMainSubParent>(this)));
+}
+
+//-----------------------------------------------------------------------------
+// sub process --- child of main
+TestBridgeMainChild* gBridgeMainChild;
+
+TestBridgeMainChild::TestBridgeMainChild()
+ : mSubprocess(nullptr)
+{
+ gBridgeMainChild = this;
+}
+
+bool
+TestBridgeMainChild::RecvStart()
+{
+ vector<string> subsubArgs;
+ subsubArgs.push_back("TestBridgeSub");
+
+ mSubprocess = new IPDLUnitTestSubprocess();
+ if (!mSubprocess->SyncLaunch(subsubArgs))
+ fail("problem launching subprocess");
+
+ IPC::Channel* transport = mSubprocess->GetChannel();
+ if (!transport)
+ fail("no transport");
+
+ TestBridgeSubParent* bsp = new TestBridgeSubParent();
+ bsp->Open(transport, base::GetProcId(mSubprocess->GetChildProcessHandle()));
+
+ bsp->Main();
+ return true;
+}
+
+void
+TestBridgeMainChild::ActorDestroy(ActorDestroyReason why)
+{
+ if (NormalShutdown != why)
+ fail("unexpected destruction!");
+ // NB: this is kosher because QuitChild() joins with the IO thread
+ XRE_GetIOMessageLoop()->PostTask(
+ do_AddRef(new DeleteTask<IPDLUnitTestSubprocess>(mSubprocess)));
+ QuitChild();
+}
+
+void
+TestBridgeSubParent::Main()
+{
+ if (!SendPing())
+ fail("sending Ping");
+}
+
+bool
+TestBridgeSubParent::RecvBridgeEm()
+{
+ if (NS_FAILED(PTestBridgeMainSub::Bridge(gBridgeMainChild, this)))
+ fail("bridging Main and Sub");
+ return true;
+}
+
+void
+TestBridgeSubParent::ActorDestroy(ActorDestroyReason why)
+{
+ if (NormalShutdown != why)
+ fail("unexpected destruction!");
+ gBridgeMainChild->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<TestBridgeSubParent>(this)));
+}
+
+//-----------------------------------------------------------------------------
+// subsub process --- child of sub
+
+static TestBridgeSubChild* gBridgeSubChild;
+
+TestBridgeSubChild::TestBridgeSubChild()
+{
+ gBridgeSubChild = this;
+}
+
+bool
+TestBridgeSubChild::RecvPing()
+{
+ if (!SendBridgeEm())
+ fail("sending BridgeEm");
+ return true;
+}
+
+PTestBridgeMainSubChild*
+TestBridgeSubChild::AllocPTestBridgeMainSubChild(Transport* transport,
+ ProcessId otherPid)
+{
+ nsAutoPtr<TestBridgeMainSubChild> a(new TestBridgeMainSubChild(transport));
+ if (!a->Open(transport, otherPid, XRE_GetIOMessageLoop(), ipc::ChildSide)) {
+ return nullptr;
+ }
+
+ if (!a->SendHello())
+ fail("sending Hello");
+
+ return a.forget();
+}
+
+void
+TestBridgeSubChild::ActorDestroy(ActorDestroyReason why)
+{
+ if (NormalShutdown != why)
+ fail("unexpected destruction!");
+ QuitChild();
+}
+
+bool
+TestBridgeMainSubChild::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(this, &TestBridgeMainSubChild::Close));
+ return true;
+}
+
+bool
+TestBridgeMainSubChild::AnswerHiRpc()
+{
+ mGotHi = true; // d00d
+ return true;
+}
+
+void
+TestBridgeMainSubChild::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<TestBridgeMainSubChild>(this)));
+}
+
+} // namespace mozilla
+} // namespace _ipdltest