Bug 564086, part r: Test IPDL |bridge|

This commit is contained in:
Chris Jones 2011-06-03 13:33:56 -05:00
parent 777e4d37f8
commit 8c842dccb2
7 changed files with 492 additions and 1 deletions

View File

@ -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)))

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -0,0 +1,252 @@
#include "TestBridgeMain.h"
#include "IPDLUnitTests.h" // fail etc.
#include "IPDLUnitTestSubprocess.h"
using namespace std;
template<>
struct RunnableMethodTraits<mozilla::_ipdltest::TestBridgeMainSubChild>
{
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<TestBridgeMainSubParent> 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<TestBridgeMainSubParent>(this));
XRE_GetIOMessageLoop()->PostTask(
FROM_HERE,
new DeleteTask<Transport>(mTransport));
}
//-----------------------------------------------------------------------------
// sub process --- child of main
TestBridgeMainChild* gBridgeMainChild;
TestBridgeMainChild::TestBridgeMainChild()
: mSubprocess(nsnull)
{
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, 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<IPDLUnitTestSubprocess>(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<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::AllocPTestBridgeMainSub(Transport* transport,
ProcessId otherProcess)
{
ProcessHandle h;
if (!base::OpenProcessHandle(otherProcess, &h)) {
return nsnull;
}
nsAutoPtr<TestBridgeMainSubChild> 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<TestBridgeMainSubChild>(this));
XRE_GetIOMessageLoop()->PostTask(
FROM_HERE,
new DeleteTask<Transport>(mTransport));
}
} // namespace mozilla
} // namespace _ipdltest

View File

@ -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

View File

@ -1,5 +1,8 @@
IPDLSRCS = \
PTestBlockChild.ipdl \
PTestBridgeMain.ipdl \
PTestBridgeSub.ipdl \
PTestBridgeMainSub.ipdl \
PTestCrashCleanup.ipdl \
PTestDataStructures.ipdl \
PTestDataStructuresSub.ipdl \