summaryrefslogtreecommitdiffstats
path: root/ipc/ipdl/test/cxx/TestOpens.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'ipc/ipdl/test/cxx/TestOpens.cpp')
-rw-r--r--ipc/ipdl/test/cxx/TestOpens.cpp251
1 files changed, 251 insertions, 0 deletions
diff --git a/ipc/ipdl/test/cxx/TestOpens.cpp b/ipc/ipdl/test/cxx/TestOpens.cpp
new file mode 100644
index 000000000..cb1ed00b5
--- /dev/null
+++ b/ipc/ipdl/test/cxx/TestOpens.cpp
@@ -0,0 +1,251 @@
+#include "base/task.h"
+#include "base/thread.h"
+
+#include "TestOpens.h"
+
+#include "IPDLUnitTests.h" // fail etc.
+
+using namespace mozilla::ipc;
+
+using base::ProcessHandle;
+using base::Thread;
+
+namespace mozilla {
+// NB: this is generally bad style, but I am lazy.
+using namespace _ipdltest;
+using namespace _ipdltest2;
+
+static MessageLoop* gMainThread;
+
+static void
+AssertNotMainThread()
+{
+ if (!gMainThread)
+ fail("gMainThread is not initialized");
+ if (MessageLoop::current() == gMainThread)
+ fail("unexpectedly called on the main thread");
+}
+
+//-----------------------------------------------------------------------------
+// parent
+
+// Thread on which TestOpensOpenedParent runs
+static Thread* gParentThread;
+
+void
+TestOpensParent::Main()
+{
+ if (!SendStart())
+ fail("sending Start");
+}
+
+static void
+OpenParent(TestOpensOpenedParent* aParent,
+ Transport* aTransport, base::ProcessId aOtherPid)
+{
+ AssertNotMainThread();
+
+ // Open the actor on the off-main thread to park it there.
+ // Messages will be delivered to this thread's message loop
+ // instead of the main thread's.
+ if (!aParent->Open(aTransport, aOtherPid,
+ XRE_GetIOMessageLoop(), ipc::ParentSide))
+ fail("opening Parent");
+}
+
+PTestOpensOpenedParent*
+TestOpensParent::AllocPTestOpensOpenedParent(Transport* transport,
+ ProcessId otherPid)
+{
+ gMainThread = MessageLoop::current();
+
+ gParentThread = new Thread("ParentThread");
+ if (!gParentThread->Start())
+ fail("starting parent thread");
+
+ TestOpensOpenedParent* a = new TestOpensOpenedParent(transport);
+ gParentThread->message_loop()->PostTask(
+ NewRunnableFunction(OpenParent, a, transport, otherPid));
+
+ return a;
+}
+
+void
+TestOpensParent::ActorDestroy(ActorDestroyReason why)
+{
+ // Stops the thread and joins it
+ delete gParentThread;
+
+ if (NormalShutdown != why)
+ fail("unexpected destruction!");
+ passed("ok");
+ QuitParent();
+}
+
+bool
+TestOpensOpenedParent::RecvHello()
+{
+ AssertNotMainThread();
+ return SendHi();
+}
+
+bool
+TestOpensOpenedParent::RecvHelloSync()
+{
+ AssertNotMainThread();
+ return true;
+}
+
+bool
+TestOpensOpenedParent::AnswerHelloRpc()
+{
+ AssertNotMainThread();
+ return CallHiRpc();
+}
+
+static void
+ShutdownTestOpensOpenedParent(TestOpensOpenedParent* parent,
+ Transport* transport)
+{
+ delete parent;
+}
+
+void
+TestOpensOpenedParent::ActorDestroy(ActorDestroyReason why)
+{
+ AssertNotMainThread();
+
+ 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.
+ gParentThread->message_loop()->PostTask(
+ NewRunnableFunction(ShutdownTestOpensOpenedParent,
+ this, mTransport));
+}
+
+//-----------------------------------------------------------------------------
+// child
+
+static TestOpensChild* gOpensChild;
+// Thread on which TestOpensOpenedChild runs
+static Thread* gChildThread;
+
+TestOpensChild::TestOpensChild()
+{
+ gOpensChild = this;
+}
+
+bool
+TestOpensChild::RecvStart()
+{
+ if (!PTestOpensOpened::Open(this))
+ fail("opening PTestOpensOpened");
+ return true;
+}
+
+static void
+OpenChild(TestOpensOpenedChild* aChild,
+ Transport* aTransport, base::ProcessId aOtherPid)
+{
+ AssertNotMainThread();
+
+ // Open the actor on the off-main thread to park it there.
+ // Messages will be delivered to this thread's message loop
+ // instead of the main thread's.
+ if (!aChild->Open(aTransport, aOtherPid,
+ XRE_GetIOMessageLoop(), ipc::ChildSide))
+ fail("opening Child");
+
+ // Kick off the unit tests
+ if (!aChild->SendHello())
+ fail("sending Hello");
+}
+
+PTestOpensOpenedChild*
+TestOpensChild::AllocPTestOpensOpenedChild(Transport* transport,
+ ProcessId otherPid)
+{
+ gMainThread = MessageLoop::current();
+
+ gChildThread = new Thread("ChildThread");
+ if (!gChildThread->Start())
+ fail("starting child thread");
+
+ TestOpensOpenedChild* a = new TestOpensOpenedChild(transport);
+ gChildThread->message_loop()->PostTask(
+ NewRunnableFunction(OpenChild, a, transport, otherPid));
+
+ return a;
+}
+
+void
+TestOpensChild::ActorDestroy(ActorDestroyReason why)
+{
+ // Stops the thread and joins it
+ delete gChildThread;
+
+ if (NormalShutdown != why)
+ fail("unexpected destruction!");
+ QuitChild();
+}
+
+bool
+TestOpensOpenedChild::RecvHi()
+{
+ AssertNotMainThread();
+
+ 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, &TestOpensOpenedChild::Close));
+ return true;
+}
+
+bool
+TestOpensOpenedChild::AnswerHiRpc()
+{
+ AssertNotMainThread();
+
+ mGotHi = true; // d00d
+ return true;
+}
+
+static void
+ShutdownTestOpensOpenedChild(TestOpensOpenedChild* child,
+ Transport* transport)
+{
+ delete child;
+
+ // Kick off main-thread shutdown.
+ gMainThread->PostTask(
+ NewNonOwningRunnableMethod(gOpensChild, &TestOpensChild::Close));
+}
+
+void
+TestOpensOpenedChild::ActorDestroy(ActorDestroyReason why)
+{
+ AssertNotMainThread();
+
+ 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. Defer shutdown to
+ // let cleanup finish.
+ gChildThread->message_loop()->PostTask(
+ NewRunnableFunction(ShutdownTestOpensOpenedChild,
+ this, mTransport));
+}
+
+} // namespace mozilla