From 8c842dccb2fdbbc8042e9531cd1709419a5a6bf6 Mon Sep 17 00:00:00 2001 From: Chris Jones Date: Fri, 3 Jun 2011 13:33:56 -0500 Subject: [PATCH] Bug 564086, part r: Test IPDL |bridge| --- ipc/ipdl/test/cxx/Makefile.in | 5 +- ipc/ipdl/test/cxx/PTestBridgeMain.ipdl | 24 +++ ipc/ipdl/test/cxx/PTestBridgeMainSub.ipdl | 33 +++ ipc/ipdl/test/cxx/PTestBridgeSub.ipdl | 24 +++ ipc/ipdl/test/cxx/TestBridgeMain.cpp | 252 ++++++++++++++++++++++ ipc/ipdl/test/cxx/TestBridgeMain.h | 152 +++++++++++++ ipc/ipdl/test/cxx/ipdl.mk | 3 + 7 files changed, 492 insertions(+), 1 deletion(-) create mode 100644 ipc/ipdl/test/cxx/PTestBridgeMain.ipdl create mode 100644 ipc/ipdl/test/cxx/PTestBridgeMainSub.ipdl create mode 100644 ipc/ipdl/test/cxx/PTestBridgeSub.ipdl create mode 100644 ipc/ipdl/test/cxx/TestBridgeMain.cpp create mode 100644 ipc/ipdl/test/cxx/TestBridgeMain.h diff --git a/ipc/ipdl/test/cxx/Makefile.in b/ipc/ipdl/test/cxx/Makefile.in index ab0d55e704f7..c58cd637ed3e 100644 --- a/ipc/ipdl/test/cxx/Makefile.in +++ b/ipc/ipdl/test/cxx/Makefile.in @@ -59,6 +59,7 @@ EXPORT_LIBRARY = 1 IPDLTESTS = \ TestBlockChild \ + TestBridgeMain \ TestCrashCleanup \ TestDataStructures \ TestDesc \ @@ -89,7 +90,9 @@ ifeq ($(OS_ARCH),Linux) IPDLTESTS += TestSysVShmem endif -EXTRA_PROTOCOLS = +EXTRA_PROTOCOLS = \ + TestBridgeSub \ + $(NULL) IPDLTESTSRCS = $(addsuffix .cpp,$(IPDLTESTS)) IPDLTESTHDRS = $(addprefix $(srcdir)/,$(addsuffix .h,$(IPDLTESTS))) diff --git a/ipc/ipdl/test/cxx/PTestBridgeMain.ipdl b/ipc/ipdl/test/cxx/PTestBridgeMain.ipdl new file mode 100644 index 000000000000..0f576ae63984 --- /dev/null +++ b/ipc/ipdl/test/cxx/PTestBridgeMain.ipdl @@ -0,0 +1,24 @@ +include protocol PTestBridgeSub; + +namespace mozilla { +namespace _ipdltest { + + +protocol PTestBridgeMain { + child spawns PTestBridgeSub; + +child: + Start(); + +parent: + __delete__(); + +state START: + send Start goto DEAD; +state DEAD: + recv __delete__; +}; + + +} // namespace mozilla +} // namespace _ipdltest diff --git a/ipc/ipdl/test/cxx/PTestBridgeMainSub.ipdl b/ipc/ipdl/test/cxx/PTestBridgeMainSub.ipdl new file mode 100644 index 000000000000..99f6bffc62a3 --- /dev/null +++ b/ipc/ipdl/test/cxx/PTestBridgeMainSub.ipdl @@ -0,0 +1,33 @@ +include protocol PTestBridgeMain; +include protocol PTestBridgeSub; + +namespace mozilla { +namespace _ipdltest { + +// (Bridge protocols can have different semantics than the endpoints +// they bridge) +rpc protocol PTestBridgeMainSub { + bridges PTestBridgeMain, PTestBridgeSub; + +child: + Hi(); + rpc HiRpc(); + +parent: + Hello(); + sync HelloSync(); + rpc HelloRpc(); + __delete__(); + +state START: recv Hello goto HI; +state HI: send Hi goto HELLO_SYNC; +state HELLO_SYNC: recv HelloSync goto HELLO_RPC; +state HELLO_RPC: answer HelloRpc goto HI_RPC; +state HI_RPC: call HiRpc goto DEAD; +state DEAD: + recv __delete__; +}; + + +} // namespace mozilla +} // namespace _ipdltest diff --git a/ipc/ipdl/test/cxx/PTestBridgeSub.ipdl b/ipc/ipdl/test/cxx/PTestBridgeSub.ipdl new file mode 100644 index 000000000000..1216fa1c7c60 --- /dev/null +++ b/ipc/ipdl/test/cxx/PTestBridgeSub.ipdl @@ -0,0 +1,24 @@ + +namespace mozilla { +namespace _ipdltest { + + +protocol PTestBridgeSub { +child: + Ping(); + +parent: + BridgeEm(); + __delete__(); + +state START: + send Ping goto BRIDGEEM; +state BRIDGEEM: + recv BridgeEm goto DEAD; +state DEAD: + recv __delete__; +}; + + +} // namespace mozilla +} // namespace _ipdltest diff --git a/ipc/ipdl/test/cxx/TestBridgeMain.cpp b/ipc/ipdl/test/cxx/TestBridgeMain.cpp new file mode 100644 index 000000000000..4a4b737b04ec --- /dev/null +++ b/ipc/ipdl/test/cxx/TestBridgeMain.cpp @@ -0,0 +1,252 @@ +#include "TestBridgeMain.h" + +#include "IPDLUnitTests.h" // fail etc. +#include "IPDLUnitTestSubprocess.h" + +using namespace std; + +template<> +struct RunnableMethodTraits +{ + static void RetainCallee(mozilla::_ipdltest::TestBridgeMainSubChild* obj) { } + static void ReleaseCallee(mozilla::_ipdltest::TestBridgeMainSubChild* obj) { } +}; + +namespace mozilla { +namespace _ipdltest { + + +//----------------------------------------------------------------------------- +// main process +void +TestBridgeMainParent::Main() +{ + if (!SendStart()) + fail("sending Start"); +} + +PTestBridgeMainSubParent* +TestBridgeMainParent::AllocPTestBridgeMainSub(Transport* transport, + ProcessId otherProcess) +{ + ProcessHandle h; + if (!base::OpenProcessHandle(otherProcess, &h)) { + return nsnull; + } + + nsAutoPtr a(new TestBridgeMainSubParent(transport)); + if (!a->Open(transport, h, XRE_GetIOMessageLoop(), AsyncChannel::Parent)) { + return nsnull; + } + 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( + FROM_HERE, + new DeleteTask(this)); + XRE_GetIOMessageLoop()->PostTask( + FROM_HERE, + new DeleteTask(mTransport)); +} + +//----------------------------------------------------------------------------- +// sub process --- child of main +TestBridgeMainChild* gBridgeMainChild; + +TestBridgeMainChild::TestBridgeMainChild() + : mSubprocess(nsnull) +{ + gBridgeMainChild = this; +} + +bool +TestBridgeMainChild::RecvStart() +{ + vector 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, 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( + FROM_HERE, + new DeleteTask(mSubprocess)); + QuitChild(); +} + +void +TestBridgeSubParent::Main() +{ + if (!SendPing()) + fail("sending Ping"); +} + +bool +TestBridgeSubParent::RecvBridgeEm() +{ + if (!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( + FROM_HERE, + new DeleteTask(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::AllocPTestBridgeMainSub(Transport* transport, + ProcessId otherProcess) +{ + ProcessHandle h; + if (!base::OpenProcessHandle(otherProcess, &h)) { + return nsnull; + } + + nsAutoPtr a(new TestBridgeMainSubChild(transport)); + if (!a->Open(transport, h, XRE_GetIOMessageLoop(), AsyncChannel::Child)) { + return nsnull; + } + + 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( + FROM_HERE, + NewRunnableMethod(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( + FROM_HERE, + new DeleteTask(this)); + XRE_GetIOMessageLoop()->PostTask( + FROM_HERE, + new DeleteTask(mTransport)); +} + +} // namespace mozilla +} // namespace _ipdltest diff --git a/ipc/ipdl/test/cxx/TestBridgeMain.h b/ipc/ipdl/test/cxx/TestBridgeMain.h new file mode 100644 index 000000000000..e96192d0284c --- /dev/null +++ b/ipc/ipdl/test/cxx/TestBridgeMain.h @@ -0,0 +1,152 @@ +#ifndef mozilla__ipdltest_TestBridgeMain_h +#define mozilla__ipdltest_TestBridgeMain_h 1 + +#include "mozilla/_ipdltest/IPDLUnitTests.h" + +#include "mozilla/_ipdltest/PTestBridgeMainParent.h" +#include "mozilla/_ipdltest/PTestBridgeMainChild.h" + +#include "mozilla/_ipdltest/PTestBridgeSubParent.h" +#include "mozilla/_ipdltest/PTestBridgeSubChild.h" + +#include "mozilla/_ipdltest/PTestBridgeMainSubParent.h" +#include "mozilla/_ipdltest/PTestBridgeMainSubChild.h" + +namespace mozilla { +namespace _ipdltest { + +//----------------------------------------------------------------------------- +// "Main" process +// +class TestBridgeMainParent : + public PTestBridgeMainParent +{ +public: + TestBridgeMainParent() {} + virtual ~TestBridgeMainParent() {} + + void Main(); + +protected: + NS_OVERRIDE + virtual PTestBridgeMainSubParent* + AllocPTestBridgeMainSub(Transport* transport, + ProcessId otherProcess); + + NS_OVERRIDE + virtual void ActorDestroy(ActorDestroyReason why); +}; + +class TestBridgeMainSubParent : + public PTestBridgeMainSubParent +{ +public: + TestBridgeMainSubParent(Transport* aTransport) + : mTransport(aTransport) + {} + virtual ~TestBridgeMainSubParent() {} + +protected: + NS_OVERRIDE + virtual bool RecvHello(); + NS_OVERRIDE + virtual bool RecvHelloSync(); + NS_OVERRIDE + virtual bool AnswerHelloRpc(); + + NS_OVERRIDE + virtual void ActorDestroy(ActorDestroyReason why); + + Transport* mTransport; +}; + +//----------------------------------------------------------------------------- +// "Sub" process --- child of "main" +// +class TestBridgeSubParent; + +class TestBridgeMainChild : + public PTestBridgeMainChild +{ +public: + TestBridgeMainChild(); + virtual ~TestBridgeMainChild() {} + +protected: + NS_OVERRIDE + virtual bool RecvStart(); + + NS_OVERRIDE + virtual void ActorDestroy(ActorDestroyReason why); + + IPDLUnitTestSubprocess* mSubprocess; +}; + +class TestBridgeSubParent : + public PTestBridgeSubParent +{ +public: + TestBridgeSubParent() {} + virtual ~TestBridgeSubParent() {} + + void Main(); + +protected: + NS_OVERRIDE + virtual bool RecvBridgeEm(); + + NS_OVERRIDE + virtual void ActorDestroy(ActorDestroyReason why); +}; + +//----------------------------------------------------------------------------- +// "Subsub" process --- child of "sub" +// +class TestBridgeSubChild : + public PTestBridgeSubChild +{ +public: + TestBridgeSubChild(); + virtual ~TestBridgeSubChild() {} + +protected: + NS_OVERRIDE + virtual bool RecvPing(); + + NS_OVERRIDE + virtual PTestBridgeMainSubChild* + AllocPTestBridgeMainSub(Transport* transport, + ProcessId otherProcess); + + NS_OVERRIDE + virtual void ActorDestroy(ActorDestroyReason why); +}; + +class TestBridgeMainSubChild : + public PTestBridgeMainSubChild +{ +public: + TestBridgeMainSubChild(Transport* aTransport) + : mGotHi(false) + , mTransport(aTransport) + {} + virtual ~TestBridgeMainSubChild() {} + +protected: + NS_OVERRIDE + virtual bool RecvHi(); + NS_OVERRIDE + virtual bool AnswerHiRpc(); + + NS_OVERRIDE + virtual void ActorDestroy(ActorDestroyReason why); + + bool mGotHi; + Transport* mTransport; +}; + +} // namespace _ipdltest +} // namespace mozilla + + +#endif // ifndef mozilla__ipdltest_TestBridgeMain_h diff --git a/ipc/ipdl/test/cxx/ipdl.mk b/ipc/ipdl/test/cxx/ipdl.mk index 9b828f12a203..bdd2dd8e929c 100644 --- a/ipc/ipdl/test/cxx/ipdl.mk +++ b/ipc/ipdl/test/cxx/ipdl.mk @@ -1,5 +1,8 @@ IPDLSRCS = \ PTestBlockChild.ipdl \ + PTestBridgeMain.ipdl \ + PTestBridgeSub.ipdl \ + PTestBridgeMainSub.ipdl \ PTestCrashCleanup.ipdl \ PTestDataStructures.ipdl \ PTestDataStructuresSub.ipdl \