diff --git a/ipc/ipdl/test/cxx/Makefile.in b/ipc/ipdl/test/cxx/Makefile.in index c58cd637ed3e..455251f97b23 100644 --- a/ipc/ipdl/test/cxx/Makefile.in +++ b/ipc/ipdl/test/cxx/Makefile.in @@ -70,6 +70,7 @@ IPDLTESTS = \ TestManyChildAllocs \ TestMultiMgrs \ TestNestedLoops \ + TestOpens \ TestRPCErrorCleanup \ TestRPCRaces \ TestRPCShutdownRace \ diff --git a/ipc/ipdl/test/cxx/PTestOpens.ipdl b/ipc/ipdl/test/cxx/PTestOpens.ipdl new file mode 100644 index 000000000000..d3a7bcafb131 --- /dev/null +++ b/ipc/ipdl/test/cxx/PTestOpens.ipdl @@ -0,0 +1,24 @@ +include protocol PTestOpensOpened; + +namespace mozilla { +namespace _ipdltest { + + +protocol PTestOpens { + child opens PTestOpensOpened; + +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/PTestOpensOpened.ipdl b/ipc/ipdl/test/cxx/PTestOpensOpened.ipdl new file mode 100644 index 000000000000..6a9853ea244d --- /dev/null +++ b/ipc/ipdl/test/cxx/PTestOpensOpened.ipdl @@ -0,0 +1,28 @@ +namespace mozilla { +namespace _ipdltest { + +// (Opens protocols can have different semantics than the endpoints +// that opened them) +rpc protocol PTestOpensOpened { +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/TestOpens.cpp b/ipc/ipdl/test/cxx/TestOpens.cpp new file mode 100644 index 000000000000..1703dffff014 --- /dev/null +++ b/ipc/ipdl/test/cxx/TestOpens.cpp @@ -0,0 +1,176 @@ +#include "TestOpens.h" + +#include "IPDLUnitTests.h" // fail etc. + +template<> +struct RunnableMethodTraits +{ + static void RetainCallee(mozilla::_ipdltest::TestOpensOpenedChild* obj) { } + static void ReleaseCallee(mozilla::_ipdltest::TestOpensOpenedChild* obj) { } +}; + +namespace mozilla { +namespace _ipdltest { + +//----------------------------------------------------------------------------- +// parent + +void +TestOpensParent::Main() +{ + if (!SendStart()) + fail("sending Start"); +} + +PTestOpensOpenedParent* +TestOpensParent::AllocPTestOpensOpened(Transport* transport, + ProcessId otherProcess) +{ + ProcessHandle h; + if (!base::OpenProcessHandle(otherProcess, &h)) { + return nsnull; + } + + nsAutoPtr a(new TestOpensOpenedParent(transport)); + if (!a->Open(transport, h, XRE_GetIOMessageLoop(), AsyncChannel::Parent)) { + return nsnull; + } + return a.forget(); +} + +void +TestOpensParent::ActorDestroy(ActorDestroyReason why) +{ + if (NormalShutdown != why) + fail("unexpected destruction!"); + passed("ok"); + QuitParent(); +} + +bool +TestOpensOpenedParent::RecvHello() +{ + return SendHi(); +} + +bool +TestOpensOpenedParent::RecvHelloSync() +{ + return true; +} + +bool +TestOpensOpenedParent::AnswerHelloRpc() +{ + return CallHiRpc(); +} + +void +TestOpensOpenedParent::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)); +} + +//----------------------------------------------------------------------------- +// child + +static TestOpensChild* gOpensChild; + +TestOpensChild::TestOpensChild() +{ + gOpensChild = this; +} + +bool +TestOpensChild::RecvStart() +{ + if (!PTestOpensOpened::Open(this)) + fail("opening PTestOpensOpened"); + return true; +} + +PTestOpensOpenedChild* +TestOpensChild::AllocPTestOpensOpened(Transport* transport, + ProcessId otherProcess) +{ + ProcessHandle h; + if (!base::OpenProcessHandle(otherProcess, &h)) { + return nsnull; + } + + nsAutoPtr a(new TestOpensOpenedChild(transport)); + if (!a->Open(transport, h, XRE_GetIOMessageLoop(), AsyncChannel::Child)) { + return nsnull; + } + + if (!a->SendHello()) + fail("sending Hello"); + + return a.forget(); +} + +void +TestOpensChild::ActorDestroy(ActorDestroyReason why) +{ + if (NormalShutdown != why) + fail("unexpected destruction!"); + QuitChild(); +} + +bool +TestOpensOpenedChild::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, &TestOpensOpenedChild::Close)); + return true; +} + +bool +TestOpensOpenedChild::AnswerHiRpc() +{ + mGotHi = true; // d00d + return true; +} + +void +TestOpensOpenedChild::ActorDestroy(ActorDestroyReason why) +{ + if (NormalShutdown != why) + fail("unexpected destruction!"); + + gOpensChild->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 _ipdltest +} // namespace mozilla diff --git a/ipc/ipdl/test/cxx/TestOpens.h b/ipc/ipdl/test/cxx/TestOpens.h new file mode 100644 index 000000000000..178ee386f82e --- /dev/null +++ b/ipc/ipdl/test/cxx/TestOpens.h @@ -0,0 +1,104 @@ +#ifndef mozilla__ipdltest_TestOpens_h +#define mozilla__ipdltest_TestOpens_h 1 + +#include "mozilla/_ipdltest/IPDLUnitTests.h" + +#include "mozilla/_ipdltest/PTestOpensParent.h" +#include "mozilla/_ipdltest/PTestOpensChild.h" + +#include "mozilla/_ipdltest/PTestOpensOpenedParent.h" +#include "mozilla/_ipdltest/PTestOpensOpenedChild.h" + +namespace mozilla { +namespace _ipdltest { + +// parent process + +class TestOpensParent : public PTestOpensParent +{ +public: + TestOpensParent() {} + virtual ~TestOpensParent() {} + + void Main(); + +protected: + NS_OVERRIDE + virtual PTestOpensOpenedParent* + AllocPTestOpensOpened(Transport* transport, ProcessId otherProcess); + + NS_OVERRIDE + virtual void ActorDestroy(ActorDestroyReason why); +}; + +class TestOpensOpenedParent : public PTestOpensOpenedParent +{ +public: + TestOpensOpenedParent(Transport* aTransport) + : mTransport(aTransport) + {} + virtual ~TestOpensOpenedParent() {} + +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; +}; + + +// child process + +class TestOpensChild : public PTestOpensChild +{ +public: + TestOpensChild(); + virtual ~TestOpensChild() {} + +protected: + NS_OVERRIDE + virtual bool RecvStart(); + + NS_OVERRIDE + virtual PTestOpensOpenedChild* + AllocPTestOpensOpened(Transport* transport, ProcessId otherProcess); + + NS_OVERRIDE + virtual void ActorDestroy(ActorDestroyReason why); +}; + +class TestOpensOpenedChild : public PTestOpensOpenedChild +{ +public: + TestOpensOpenedChild(Transport* aTransport) + : mGotHi(false) + , mTransport(aTransport) + {} + virtual ~TestOpensOpenedChild() {} + +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_TestOpens_h diff --git a/ipc/ipdl/test/cxx/ipdl.mk b/ipc/ipdl/test/cxx/ipdl.mk index bdd2dd8e929c..2561f40c8df1 100644 --- a/ipc/ipdl/test/cxx/ipdl.mk +++ b/ipc/ipdl/test/cxx/ipdl.mk @@ -23,6 +23,8 @@ IPDLSRCS = \ PTestMultiMgrsRight.ipdl \ PTestMultiMgrsBottom.ipdl \ PTestNestedLoops.ipdl \ + PTestOpens.ipdl \ + PTestOpensOpened.ipdl \ PTestRaceDeferral.ipdl \ PTestRacyReentry.ipdl \ PTestRacyRPCReplies.ipdl \