mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-10-05 06:47:31 +09:00
import FIREFOX_52_6_0esr_RELEASE from mozilla-esr52 hg repo
This commit is contained in:
commit
dcd9973243
150858 changed files with 23884658 additions and 0 deletions
32
ipc/ipdl/test/cxx/IPDLUnitTestProcessChild.cpp
Normal file
32
ipc/ipdl/test/cxx/IPDLUnitTestProcessChild.cpp
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
/* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 8 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "mozilla/ipc/IOThreadChild.h"
|
||||
|
||||
#include "IPDLUnitTestProcessChild.h"
|
||||
#include "IPDLUnitTests.h"
|
||||
|
||||
#include "nsRegion.h"
|
||||
|
||||
using mozilla::ipc::IOThreadChild;
|
||||
|
||||
namespace mozilla {
|
||||
namespace _ipdltest {
|
||||
|
||||
bool
|
||||
IPDLUnitTestProcessChild::Init()
|
||||
{
|
||||
IPDLUnitTestChildInit(IOThreadChild::channel(),
|
||||
ParentPid(),
|
||||
IOThreadChild::message_loop());
|
||||
|
||||
if (NS_FAILED(nsRegion::InitStatic()))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace _ipdltest
|
||||
} // namespace mozilla
|
||||
32
ipc/ipdl/test/cxx/IPDLUnitTestProcessChild.h
Normal file
32
ipc/ipdl/test/cxx/IPDLUnitTestProcessChild.h
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
/* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 8 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla__ipdltest_IPDLUnitTestThreadChild_h
|
||||
#define mozilla__ipdltest_IPDLUnitTestThreadChild_h 1
|
||||
|
||||
#include "mozilla/ipc/ProcessChild.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace _ipdltest {
|
||||
|
||||
class IPDLUnitTestProcessChild : public mozilla::ipc::ProcessChild
|
||||
{
|
||||
typedef mozilla::ipc::ProcessChild ProcessChild;
|
||||
|
||||
public:
|
||||
explicit IPDLUnitTestProcessChild(ProcessId aParentPid) :
|
||||
ProcessChild(aParentPid)
|
||||
{ }
|
||||
|
||||
~IPDLUnitTestProcessChild()
|
||||
{ }
|
||||
|
||||
virtual bool Init();
|
||||
};
|
||||
|
||||
} // namespace _ipdltest
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // ifndef mozilla__ipdltest_IPDLUnitTestThreadChild_h
|
||||
23
ipc/ipdl/test/cxx/IPDLUnitTestSubprocess.cpp
Normal file
23
ipc/ipdl/test/cxx/IPDLUnitTestSubprocess.cpp
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
/* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 8 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "IPDLUnitTestSubprocess.h"
|
||||
|
||||
using mozilla::ipc::GeckoChildProcessHost;
|
||||
|
||||
namespace mozilla {
|
||||
namespace _ipdltest {
|
||||
|
||||
IPDLUnitTestSubprocess::IPDLUnitTestSubprocess() :
|
||||
GeckoChildProcessHost(GeckoProcessType_IPDLUnitTest)
|
||||
{
|
||||
}
|
||||
|
||||
IPDLUnitTestSubprocess::~IPDLUnitTestSubprocess()
|
||||
{
|
||||
}
|
||||
|
||||
} // namespace _ipdltest
|
||||
} // namespace mozilla
|
||||
37
ipc/ipdl/test/cxx/IPDLUnitTestSubprocess.h
Normal file
37
ipc/ipdl/test/cxx/IPDLUnitTestSubprocess.h
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
/* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 8 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla__ipdltest_IPDLUnitTestTestSubprocess_h
|
||||
#define mozilla__ipdltest_IPDLUnitTestTestSubprocess_h 1
|
||||
|
||||
|
||||
#include "mozilla/ipc/GeckoChildProcessHost.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace _ipdltest {
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
class IPDLUnitTestSubprocess : public mozilla::ipc::GeckoChildProcessHost
|
||||
{
|
||||
public:
|
||||
IPDLUnitTestSubprocess();
|
||||
~IPDLUnitTestSubprocess();
|
||||
|
||||
/**
|
||||
* Asynchronously launch the plugin process.
|
||||
*/
|
||||
// Could override parent Launch, but don't need to here
|
||||
//bool Launch();
|
||||
|
||||
private:
|
||||
DISALLOW_EVIL_CONSTRUCTORS(IPDLUnitTestSubprocess);
|
||||
};
|
||||
|
||||
|
||||
} // namespace _ipdltest
|
||||
} // namespace mozilla
|
||||
|
||||
|
||||
#endif // ifndef mozilla__ipdltest_IPDLUnitTestTestSubprocess_h
|
||||
44
ipc/ipdl/test/cxx/IPDLUnitTestTypes.h
Normal file
44
ipc/ipdl/test/cxx/IPDLUnitTestTypes.h
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
/* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 8 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla__ipdltest_IPDLUnitTestTypes_h
|
||||
#define mozilla__ipdltest_IPDLUnitTestTypes_h
|
||||
|
||||
#include "mozilla/ipc/ProtocolUtils.h" // ActorDestroyReason
|
||||
|
||||
namespace mozilla {
|
||||
namespace _ipdltest {
|
||||
|
||||
struct DirtyRect
|
||||
{
|
||||
int x; int y; int w; int h;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
namespace IPC {
|
||||
template<>
|
||||
struct ParamTraits<mozilla::_ipdltest::DirtyRect>
|
||||
{
|
||||
typedef mozilla::_ipdltest::DirtyRect paramType;
|
||||
static void Write(Message* aMsg, const paramType& aParam) {
|
||||
WriteParam(aMsg, aParam.x);
|
||||
WriteParam(aMsg, aParam.y);
|
||||
WriteParam(aMsg, aParam.w);
|
||||
WriteParam(aMsg, aParam.h);
|
||||
}
|
||||
static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
|
||||
{
|
||||
return (ReadParam(aMsg, aIter, &aResult->x) &&
|
||||
ReadParam(aMsg, aIter, &aResult->y) &&
|
||||
ReadParam(aMsg, aIter, &aResult->w) &&
|
||||
ReadParam(aMsg, aIter, &aResult->h));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
#endif // ifndef mozilla__ipdltest_IPDLUnitTestTypes_h
|
||||
27
ipc/ipdl/test/cxx/IPDLUnitTestUtils.h
Normal file
27
ipc/ipdl/test/cxx/IPDLUnitTestUtils.h
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
|
||||
#ifndef mozilla__ipdltest_IPDLUnitTestUtils
|
||||
#define mozilla__ipdltest_IPDLUnitTestUtils 1
|
||||
|
||||
namespace mozilla {
|
||||
namespace _ipdltest {
|
||||
|
||||
struct Bad {};
|
||||
|
||||
} // namespace _ipdltest
|
||||
} // namespace mozilla
|
||||
|
||||
namespace IPC {
|
||||
|
||||
template<>
|
||||
struct ParamTraits<mozilla::_ipdltest::Bad>
|
||||
{
|
||||
typedef mozilla::_ipdltest::Bad paramType;
|
||||
|
||||
// Defined in TestActorPunning.cpp.
|
||||
static void Write(Message* aMsg, const paramType& aParam);
|
||||
static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult);
|
||||
};
|
||||
|
||||
} // namespace IPC
|
||||
|
||||
#endif // mozilla__ipdltest_IPDLUnitTestUtils
|
||||
93
ipc/ipdl/test/cxx/IPDLUnitTests.h
Normal file
93
ipc/ipdl/test/cxx/IPDLUnitTests.h
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
/* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 8 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla__ipdltest_IPDLUnitTests_h
|
||||
#define mozilla__ipdltest_IPDLUnitTests_h 1
|
||||
|
||||
#include "base/message_loop.h"
|
||||
#include "base/process.h"
|
||||
#include "chrome/common/ipc_channel.h"
|
||||
|
||||
#include "nsIAppShell.h"
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsDebug.h"
|
||||
#include "nsServiceManagerUtils.h" // do_GetService()
|
||||
#include "nsWidgetsCID.h" // NS_APPSHELL_CID
|
||||
#include "nsXULAppAPI.h"
|
||||
|
||||
|
||||
#define MOZ_IPDL_TESTFAIL_LABEL "TEST-UNEXPECTED-FAIL"
|
||||
#define MOZ_IPDL_TESTPASS_LABEL "TEST-PASS"
|
||||
#define MOZ_IPDL_TESTINFO_LABEL "TEST-INFO"
|
||||
|
||||
|
||||
namespace mozilla {
|
||||
namespace _ipdltest {
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// both processes
|
||||
const char* IPDLUnitTestName();
|
||||
|
||||
// NB: these are named like the similar functions in
|
||||
// xpcom/test/TestHarness.h. The names should nominally be kept in
|
||||
// sync.
|
||||
|
||||
inline void fail(const char* fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
fprintf(stderr, MOZ_IPDL_TESTFAIL_LABEL " | %s | ", IPDLUnitTestName());
|
||||
|
||||
va_start(ap, fmt);
|
||||
vfprintf(stderr, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
fputc('\n', stderr);
|
||||
|
||||
NS_RUNTIMEABORT("failed test");
|
||||
}
|
||||
|
||||
inline void passed(const char* fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
printf(MOZ_IPDL_TESTPASS_LABEL " | %s | ", IPDLUnitTestName());
|
||||
|
||||
va_start(ap, fmt);
|
||||
vprintf(fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
fputc('\n', stdout);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// parent process only
|
||||
|
||||
class IPDLUnitTestSubprocess;
|
||||
|
||||
extern void* gParentActor;
|
||||
extern IPDLUnitTestSubprocess* gSubprocess;
|
||||
|
||||
void IPDLUnitTestMain(void* aData);
|
||||
|
||||
void QuitParent();
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// child process only
|
||||
|
||||
extern void* gChildActor;
|
||||
|
||||
void IPDLUnitTestChildInit(IPC::Channel* transport,
|
||||
base::ProcessId parentPid,
|
||||
MessageLoop* worker);
|
||||
|
||||
void QuitChild();
|
||||
|
||||
} // namespace _ipdltest
|
||||
} // namespace mozilla
|
||||
|
||||
|
||||
#endif // ifndef mozilla__ipdltest_IPDLUnitTests_h
|
||||
390
ipc/ipdl/test/cxx/IPDLUnitTests.template.cpp
Normal file
390
ipc/ipdl/test/cxx/IPDLUnitTests.template.cpp
Normal file
|
|
@ -0,0 +1,390 @@
|
|||
//
|
||||
// Autogenerated from Python template. Hands off.
|
||||
//
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "IPDLUnitTests.h"
|
||||
|
||||
#include "base/command_line.h"
|
||||
#include "base/string_util.h"
|
||||
#include "base/task.h"
|
||||
#include "base/thread.h"
|
||||
|
||||
#include "nsRegion.h"
|
||||
|
||||
#include "IPDLUnitTestSubprocess.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//===== TEMPLATED =====
|
||||
${INCLUDES}
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
using namespace std;
|
||||
|
||||
using base::Thread;
|
||||
|
||||
namespace mozilla {
|
||||
namespace _ipdltest {
|
||||
|
||||
void* gParentActor;
|
||||
IPDLUnitTestSubprocess* gSubprocess;
|
||||
|
||||
void* gChildActor;
|
||||
|
||||
// Note: in threaded mode, this will be non-null (for both parent and
|
||||
// child, since they share one set of globals).
|
||||
Thread* gChildThread;
|
||||
MessageLoop *gParentMessageLoop;
|
||||
bool gParentDone;
|
||||
bool gChildDone;
|
||||
|
||||
void
|
||||
DeleteChildActor();
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// data/functions accessed by both parent and child processes
|
||||
|
||||
char* gIPDLUnitTestName = nullptr;
|
||||
|
||||
const char*
|
||||
IPDLUnitTestName()
|
||||
{
|
||||
if (!gIPDLUnitTestName) {
|
||||
#if defined(OS_WIN)
|
||||
vector<wstring> args =
|
||||
CommandLine::ForCurrentProcess()->GetLooseValues();
|
||||
gIPDLUnitTestName = ::strdup(WideToUTF8(args[0]).c_str());
|
||||
#elif defined(OS_POSIX)
|
||||
vector<string> argv = CommandLine::ForCurrentProcess()->argv();
|
||||
gIPDLUnitTestName = ::moz_xstrdup(argv[1].c_str());
|
||||
#else
|
||||
# error Sorry
|
||||
#endif
|
||||
}
|
||||
return gIPDLUnitTestName;
|
||||
}
|
||||
|
||||
} // namespace _ipdltest
|
||||
} // namespace mozilla
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
enum IPDLUnitTestType {
|
||||
NoneTest = 0,
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//===== TEMPLATED =====
|
||||
${ENUM_VALUES}
|
||||
|
||||
LastTest = ${LAST_ENUM}
|
||||
//-----------------------------------------------------------------------------
|
||||
};
|
||||
|
||||
|
||||
IPDLUnitTestType
|
||||
IPDLUnitTestFromString(const char* const aString)
|
||||
{
|
||||
if (!aString)
|
||||
return static_cast<IPDLUnitTestType>(0);
|
||||
//-----------------------------------------------------------------------------
|
||||
//===== TEMPLATED =====
|
||||
${STRING_TO_ENUMS}
|
||||
//-----------------------------------------------------------------------------
|
||||
else
|
||||
return static_cast<IPDLUnitTestType>(0);
|
||||
}
|
||||
|
||||
|
||||
const char*
|
||||
IPDLUnitTestToString(IPDLUnitTestType aTest)
|
||||
{
|
||||
switch (aTest) {
|
||||
//-----------------------------------------------------------------------------
|
||||
//===== TEMPLATED =====
|
||||
${ENUM_TO_STRINGS}
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
IPDLUnitTestType
|
||||
IPDLUnitTest()
|
||||
{
|
||||
return IPDLUnitTestFromString(::mozilla::_ipdltest::IPDLUnitTestName());
|
||||
}
|
||||
|
||||
|
||||
} // namespace <anon>
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// parent process only
|
||||
|
||||
namespace mozilla {
|
||||
namespace _ipdltest {
|
||||
|
||||
void
|
||||
DeferredParentShutdown();
|
||||
|
||||
void
|
||||
IPDLUnitTestThreadMain(char *testString);
|
||||
|
||||
void
|
||||
IPDLUnitTestMain(void* aData)
|
||||
{
|
||||
char* testString = reinterpret_cast<char*>(aData);
|
||||
|
||||
// Check if we are to run the test using threads instead:
|
||||
const char *prefix = "thread:";
|
||||
const int prefixLen = strlen(prefix);
|
||||
if (!strncmp(testString, prefix, prefixLen)) {
|
||||
IPDLUnitTestThreadMain(testString + prefixLen);
|
||||
return;
|
||||
}
|
||||
|
||||
IPDLUnitTestType test = IPDLUnitTestFromString(testString);
|
||||
if (!test) {
|
||||
// use this instead of |fail()| because we don't know what the test is
|
||||
fprintf(stderr, MOZ_IPDL_TESTFAIL_LABEL "| %s | unknown unit test %s\n",
|
||||
"<--->", testString);
|
||||
NS_RUNTIMEABORT("can't continue");
|
||||
}
|
||||
gIPDLUnitTestName = testString;
|
||||
|
||||
// Check whether this test is enabled for processes:
|
||||
switch (test) {
|
||||
//-----------------------------------------------------------------------------
|
||||
//===== TEMPLATED =====
|
||||
${PARENT_ENABLED_CASES_PROC}
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
default:
|
||||
fail("not reached");
|
||||
return; // unreached
|
||||
}
|
||||
|
||||
printf(MOZ_IPDL_TESTINFO_LABEL "| running test | %s\n", gIPDLUnitTestName);
|
||||
|
||||
std::vector<std::string> testCaseArgs;
|
||||
testCaseArgs.push_back(testString);
|
||||
|
||||
gSubprocess = new IPDLUnitTestSubprocess();
|
||||
if (!gSubprocess->SyncLaunch(testCaseArgs))
|
||||
fail("problem launching subprocess");
|
||||
|
||||
IPC::Channel* transport = gSubprocess->GetChannel();
|
||||
if (!transport)
|
||||
fail("no transport");
|
||||
|
||||
base::ProcessId child = base::GetProcId(gSubprocess->GetChildProcessHandle());
|
||||
|
||||
switch (test) {
|
||||
//-----------------------------------------------------------------------------
|
||||
//===== TEMPLATED =====
|
||||
${PARENT_MAIN_CASES_PROC}
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
default:
|
||||
fail("not reached");
|
||||
return; // unreached
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
IPDLUnitTestThreadMain(char *testString)
|
||||
{
|
||||
IPDLUnitTestType test = IPDLUnitTestFromString(testString);
|
||||
if (!test) {
|
||||
// use this instead of |fail()| because we don't know what the test is
|
||||
fprintf(stderr, MOZ_IPDL_TESTFAIL_LABEL "| %s | unknown unit test %s\n",
|
||||
"<--->", testString);
|
||||
NS_RUNTIMEABORT("can't continue");
|
||||
}
|
||||
gIPDLUnitTestName = testString;
|
||||
|
||||
// Check whether this test is enabled for threads:
|
||||
switch (test) {
|
||||
//-----------------------------------------------------------------------------
|
||||
//===== TEMPLATED =====
|
||||
${PARENT_ENABLED_CASES_THREAD}
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
default:
|
||||
fail("not reached");
|
||||
return; // unreached
|
||||
}
|
||||
|
||||
printf(MOZ_IPDL_TESTINFO_LABEL "| running test | %s\n", gIPDLUnitTestName);
|
||||
|
||||
std::vector<std::string> testCaseArgs;
|
||||
testCaseArgs.push_back(testString);
|
||||
|
||||
gChildThread = new Thread("ParentThread");
|
||||
if (!gChildThread->Start())
|
||||
fail("starting parent thread");
|
||||
|
||||
gParentMessageLoop = MessageLoop::current();
|
||||
MessageLoop *childMessageLoop = gChildThread->message_loop();
|
||||
|
||||
switch (test) {
|
||||
//-----------------------------------------------------------------------------
|
||||
//===== TEMPLATED =====
|
||||
${PARENT_MAIN_CASES_THREAD}
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
default:
|
||||
fail("not reached");
|
||||
return; // unreached
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
DeleteParentActor()
|
||||
{
|
||||
if (!gParentActor)
|
||||
return;
|
||||
|
||||
switch (IPDLUnitTest()) {
|
||||
//-----------------------------------------------------------------------------
|
||||
//===== TEMPLATED =====
|
||||
${PARENT_DELETE_CASES}
|
||||
//-----------------------------------------------------------------------------
|
||||
default: ::mozilla::_ipdltest::fail("???");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
QuitXPCOM()
|
||||
{
|
||||
DeleteParentActor();
|
||||
|
||||
static NS_DEFINE_CID(kAppShellCID, NS_APPSHELL_CID);
|
||||
nsCOMPtr<nsIAppShell> appShell (do_GetService(kAppShellCID));
|
||||
appShell->Exit();
|
||||
}
|
||||
|
||||
void
|
||||
DeleteSubprocess(MessageLoop* uiLoop)
|
||||
{
|
||||
// pong to QuitXPCOM
|
||||
delete gSubprocess;
|
||||
uiLoop->PostTask(NewRunnableFunction(QuitXPCOM));
|
||||
}
|
||||
|
||||
void
|
||||
DeferredParentShutdown()
|
||||
{
|
||||
// ping to DeleteSubprocess
|
||||
XRE_GetIOMessageLoop()->PostTask(
|
||||
NewRunnableFunction(DeleteSubprocess, MessageLoop::current()));
|
||||
}
|
||||
|
||||
void
|
||||
TryThreadedShutdown()
|
||||
{
|
||||
// Stop if either:
|
||||
// - the child has not finished,
|
||||
// - the parent has not finished,
|
||||
// - or this code has already executed.
|
||||
// Remember: this TryThreadedShutdown() task is enqueued
|
||||
// by both parent and child (though always on parent's msg loop).
|
||||
if (!gChildDone || !gParentDone || !gChildThread)
|
||||
return;
|
||||
|
||||
delete gChildThread;
|
||||
gChildThread = 0;
|
||||
DeferredParentShutdown();
|
||||
}
|
||||
|
||||
void
|
||||
ChildCompleted()
|
||||
{
|
||||
// Executes on the parent message loop once child has completed.
|
||||
gChildDone = true;
|
||||
TryThreadedShutdown();
|
||||
}
|
||||
|
||||
void
|
||||
QuitParent()
|
||||
{
|
||||
if (gChildThread) {
|
||||
gParentDone = true;
|
||||
MessageLoop::current()->PostTask(
|
||||
NewRunnableFunction(TryThreadedShutdown));
|
||||
} else {
|
||||
// defer "real" shutdown to avoid *Channel::Close() racing with the
|
||||
// deletion of the subprocess
|
||||
MessageLoop::current()->PostTask(
|
||||
NewRunnableFunction(DeferredParentShutdown));
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ChildDie()
|
||||
{
|
||||
DeleteChildActor();
|
||||
XRE_ShutdownChildProcess();
|
||||
}
|
||||
|
||||
void
|
||||
QuitChild()
|
||||
{
|
||||
if (gChildThread) { // Threaded-mode test
|
||||
gParentMessageLoop->PostTask(
|
||||
NewRunnableFunction(ChildCompleted));
|
||||
} else { // Process-mode test
|
||||
MessageLoop::current()->PostTask(
|
||||
NewRunnableFunction(ChildDie));
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace _ipdltest
|
||||
} // namespace mozilla
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// child process only
|
||||
|
||||
namespace mozilla {
|
||||
namespace _ipdltest {
|
||||
|
||||
void
|
||||
DeleteChildActor()
|
||||
{
|
||||
if (!gChildActor)
|
||||
return;
|
||||
|
||||
switch (IPDLUnitTest()) {
|
||||
//-----------------------------------------------------------------------------
|
||||
//===== TEMPLATED =====
|
||||
${CHILD_DELETE_CASES}
|
||||
//-----------------------------------------------------------------------------
|
||||
default: ::mozilla::_ipdltest::fail("???");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
IPDLUnitTestChildInit(IPC::Channel* transport,
|
||||
base::ProcessId parentPid,
|
||||
MessageLoop* worker)
|
||||
{
|
||||
switch (IPDLUnitTest()) {
|
||||
//-----------------------------------------------------------------------------
|
||||
//===== TEMPLATED =====
|
||||
${CHILD_INIT_CASES}
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
default:
|
||||
fail("not reached");
|
||||
return; // unreached
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace _ipdltest
|
||||
} // namespace mozilla
|
||||
46
ipc/ipdl/test/cxx/Makefile.in
Normal file
46
ipc/ipdl/test/cxx/Makefile.in
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
IPDLTESTSRCS = $(filter Test%,$(CPPSRCS))
|
||||
IPDLTESTS = $(IPDLTESTSRCS:.cpp=)
|
||||
|
||||
EXTRA_PROTOCOLS = \
|
||||
TestBridgeSub \
|
||||
TestEndpointBridgeSub \
|
||||
$(NULL)
|
||||
|
||||
IPDLTESTHDRS = $(addprefix $(srcdir)/,$(addsuffix .h,$(IPDLTESTS)))
|
||||
|
||||
TESTER_TEMPLATE := $(srcdir)/IPDLUnitTests.template.cpp
|
||||
GENTESTER := $(srcdir)/genIPDLUnitTests.py
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
|
||||
IPDLUNITTEST_BIN = $(DEPTH)/dist/bin/ipdlunittest$(BIN_SUFFIX)
|
||||
|
||||
IPDLUnitTests.cpp : Makefile.in moz.build $(GENTESTER) $(TESTER_TEMPLATE) $(IPDLTESTHDRS)
|
||||
$(PYTHON) $(GENTESTER) $(TESTER_TEMPLATE) -t $(IPDLTESTS) -e $(EXTRA_PROTOCOLS) > $@
|
||||
|
||||
check-proc::
|
||||
@$(EXIT_ON_ERROR) \
|
||||
for test in $(IPDLTESTS); do \
|
||||
$(RUN_TEST_PROGRAM) $(IPDLUNITTEST_BIN) $$test ; \
|
||||
done
|
||||
|
||||
check-thread::
|
||||
@$(EXIT_ON_ERROR) \
|
||||
for test in $(IPDLTESTS); do \
|
||||
$(RUN_TEST_PROGRAM) $(IPDLUNITTEST_BIN) thread:$$test ; \
|
||||
done
|
||||
|
||||
check:: check-proc check-thread
|
||||
|
||||
check-valgrind::
|
||||
@$(EXIT_ON_ERROR) \
|
||||
for test in $(IPDLTESTS); do \
|
||||
$(RUN_TEST_PROGRAM) -g -d \
|
||||
valgrind -a '--leak-check=full --trace-children=yes -q' \
|
||||
$(IPDLUNITTEST_BIN) $$test ; \
|
||||
done
|
||||
39
ipc/ipdl/test/cxx/PTestActorPunning.ipdl
Normal file
39
ipc/ipdl/test/cxx/PTestActorPunning.ipdl
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
|
||||
include protocol PTestActorPunningPunned;
|
||||
include protocol PTestActorPunningSub;
|
||||
include "mozilla/_ipdltest/IPDLUnitTestUtils.h";
|
||||
|
||||
using struct mozilla::_ipdltest::Bad from "mozilla/_ipdltest/IPDLUnitTestUtils.h";
|
||||
|
||||
namespace mozilla {
|
||||
namespace _ipdltest {
|
||||
|
||||
protocol PTestActorPunning {
|
||||
manages PTestActorPunningPunned;
|
||||
manages PTestActorPunningSub;
|
||||
|
||||
child:
|
||||
async Start();
|
||||
|
||||
parent:
|
||||
async PTestActorPunningPunned();
|
||||
async PTestActorPunningSub();
|
||||
async Pun(PTestActorPunningSub a, Bad bad);
|
||||
async __delete__();
|
||||
|
||||
|
||||
state PING:
|
||||
send Start goto CONSTRUCTING;
|
||||
|
||||
state CONSTRUCTING:
|
||||
recv PTestActorPunningPunned goto CONSTRUCTING;
|
||||
recv PTestActorPunningSub goto CONSTRUCTING;
|
||||
recv Pun goto DEAD;
|
||||
// We never make it past this transition, --> error.
|
||||
|
||||
state DEAD:
|
||||
recv __delete__;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
} // namespace _ipdltest
|
||||
15
ipc/ipdl/test/cxx/PTestActorPunningPunned.ipdl
Normal file
15
ipc/ipdl/test/cxx/PTestActorPunningPunned.ipdl
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
|
||||
include protocol PTestActorPunning;
|
||||
|
||||
namespace mozilla {
|
||||
namespace _ipdltest {
|
||||
|
||||
protocol PTestActorPunningPunned {
|
||||
manager PTestActorPunning;
|
||||
|
||||
child:
|
||||
async __delete__();
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
} // namespace _ipdltes
|
||||
16
ipc/ipdl/test/cxx/PTestActorPunningSub.ipdl
Normal file
16
ipc/ipdl/test/cxx/PTestActorPunningSub.ipdl
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
|
||||
include protocol PTestActorPunning;
|
||||
|
||||
namespace mozilla {
|
||||
namespace _ipdltest {
|
||||
|
||||
protocol PTestActorPunningSub {
|
||||
manager PTestActorPunning;
|
||||
|
||||
child:
|
||||
async Bad();
|
||||
async __delete__();
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
} // namespace _ipdltes
|
||||
18
ipc/ipdl/test/cxx/PTestBadActor.ipdl
Normal file
18
ipc/ipdl/test/cxx/PTestBadActor.ipdl
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
include protocol PTestBadActorSub;
|
||||
|
||||
namespace mozilla {
|
||||
namespace _ipdltest {
|
||||
|
||||
// Test that a parent sending a reentrant __delete__ message
|
||||
// is not killed if a child's message races with the reply.
|
||||
|
||||
intr protocol PTestBadActor {
|
||||
manages PTestBadActorSub;
|
||||
|
||||
child:
|
||||
async PTestBadActorSub();
|
||||
async __delete__();
|
||||
};
|
||||
|
||||
} // namespace _ipdltest
|
||||
} // namespace mozilla
|
||||
17
ipc/ipdl/test/cxx/PTestBadActorSub.ipdl
Normal file
17
ipc/ipdl/test/cxx/PTestBadActorSub.ipdl
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
include protocol PTestBadActor;
|
||||
|
||||
namespace mozilla {
|
||||
namespace _ipdltest {
|
||||
|
||||
intr protocol PTestBadActorSub {
|
||||
manager PTestBadActor;
|
||||
|
||||
child:
|
||||
intr __delete__();
|
||||
|
||||
parent:
|
||||
async Ping();
|
||||
};
|
||||
|
||||
} // namespace _ipdltest
|
||||
} // namespace mozilla
|
||||
26
ipc/ipdl/test/cxx/PTestBridgeMain.ipdl
Normal file
26
ipc/ipdl/test/cxx/PTestBridgeMain.ipdl
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
include protocol PTestBridgeMainSub;
|
||||
include protocol PTestBridgeSub;
|
||||
|
||||
namespace mozilla {
|
||||
namespace _ipdltest {
|
||||
|
||||
|
||||
protocol PTestBridgeMain {
|
||||
child spawns PTestBridgeSub;
|
||||
child opens PTestBridgeMainSub;
|
||||
|
||||
child:
|
||||
async Start();
|
||||
|
||||
parent:
|
||||
async __delete__();
|
||||
|
||||
state START:
|
||||
send Start goto DEAD;
|
||||
state DEAD:
|
||||
recv __delete__;
|
||||
};
|
||||
|
||||
|
||||
} // namespace mozilla
|
||||
} // namespace _ipdltest
|
||||
33
ipc/ipdl/test/cxx/PTestBridgeMainSub.ipdl
Normal file
33
ipc/ipdl/test/cxx/PTestBridgeMainSub.ipdl
Normal 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)
|
||||
intr protocol PTestBridgeMainSub {
|
||||
bridges PTestBridgeMain, PTestBridgeSub;
|
||||
|
||||
child:
|
||||
async Hi();
|
||||
intr HiRpc();
|
||||
|
||||
parent:
|
||||
async Hello();
|
||||
sync HelloSync();
|
||||
intr HelloRpc();
|
||||
async __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
|
||||
25
ipc/ipdl/test/cxx/PTestBridgeSub.ipdl
Normal file
25
ipc/ipdl/test/cxx/PTestBridgeSub.ipdl
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
include protocol PTestBridgeMainSub;
|
||||
|
||||
namespace mozilla {
|
||||
namespace _ipdltest {
|
||||
|
||||
|
||||
protocol PTestBridgeSub {
|
||||
child:
|
||||
async Ping();
|
||||
|
||||
parent:
|
||||
async BridgeEm();
|
||||
async __delete__();
|
||||
|
||||
state START:
|
||||
send Ping goto BRIDGEEM;
|
||||
state BRIDGEEM:
|
||||
recv BridgeEm goto DEAD;
|
||||
state DEAD:
|
||||
recv __delete__;
|
||||
};
|
||||
|
||||
|
||||
} // namespace mozilla
|
||||
} // namespace _ipdltest
|
||||
36
ipc/ipdl/test/cxx/PTestCancel.ipdl
Normal file
36
ipc/ipdl/test/cxx/PTestCancel.ipdl
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
namespace mozilla {
|
||||
namespace _ipdltest {
|
||||
|
||||
nested(upto inside_sync) sync protocol PTestCancel
|
||||
{
|
||||
// Test1
|
||||
child:
|
||||
nested(inside_sync) sync Test1_1();
|
||||
parent:
|
||||
async Done1();
|
||||
|
||||
// Test2
|
||||
child:
|
||||
async Start2();
|
||||
nested(inside_sync) sync Test2_2();
|
||||
parent:
|
||||
sync Test2_1();
|
||||
|
||||
// Test3
|
||||
child:
|
||||
nested(inside_sync) sync Test3_1();
|
||||
parent:
|
||||
async Start3();
|
||||
nested(inside_sync) sync Test3_2();
|
||||
|
||||
parent:
|
||||
async Done();
|
||||
|
||||
child:
|
||||
nested(inside_sync) sync CheckChild() returns (uint32_t reply);
|
||||
parent:
|
||||
nested(inside_sync) sync CheckParent() returns (uint32_t reply);
|
||||
};
|
||||
|
||||
} // namespace _ipdltest
|
||||
} // namespace mozilla
|
||||
22
ipc/ipdl/test/cxx/PTestCrashCleanup.ipdl
Normal file
22
ipc/ipdl/test/cxx/PTestCrashCleanup.ipdl
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
// See bug 538586: if the top-level protocol's actor is deleted before
|
||||
// the "connection error" notification comes in from the IO thread,
|
||||
// IPDL teardown never occurs, even if Channel::Close() is called
|
||||
// after the error.
|
||||
|
||||
namespace mozilla {
|
||||
namespace _ipdltest {
|
||||
|
||||
// NB: needs to be RPC so that the parent blocks on the child's crash.
|
||||
intr protocol PTestCrashCleanup {
|
||||
child:
|
||||
intr DIEDIEDIE();
|
||||
async __delete__();
|
||||
|
||||
state ALIVE:
|
||||
call DIEDIEDIE goto CRASH;
|
||||
state CRASH:
|
||||
send __delete__;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
132
ipc/ipdl/test/cxx/PTestDataStructures.ipdl
Normal file
132
ipc/ipdl/test/cxx/PTestDataStructures.ipdl
Normal file
|
|
@ -0,0 +1,132 @@
|
|||
include protocol PTestDataStructuresSub;
|
||||
include PTestDataStructuresCommon;
|
||||
|
||||
include "mozilla/GfxMessageUtils.h";
|
||||
|
||||
namespace mozilla {
|
||||
namespace _ipdltest {
|
||||
|
||||
sync protocol PTestDataStructures {
|
||||
manages PTestDataStructuresSub;
|
||||
|
||||
child:
|
||||
async PTestDataStructuresSub(int i);
|
||||
|
||||
async Start();
|
||||
|
||||
parent:
|
||||
async __delete__();
|
||||
|
||||
sync Test1(int[] i1)
|
||||
returns (int[] o1);
|
||||
|
||||
sync Test2(PTestDataStructuresSub[] i1)
|
||||
returns (PTestDataStructuresSub[] o1);
|
||||
|
||||
sync Test3(IntDouble i1,
|
||||
IntDouble i2)
|
||||
returns (IntDouble o1,
|
||||
IntDouble o2);
|
||||
|
||||
sync Test4(IntDouble[] i1)
|
||||
returns (IntDouble[] o1);
|
||||
|
||||
sync Test5(IntDoubleArrays i1,
|
||||
IntDoubleArrays i2,
|
||||
IntDoubleArrays i3)
|
||||
returns (IntDoubleArrays o1,
|
||||
IntDoubleArrays o2,
|
||||
IntDoubleArrays o3);
|
||||
|
||||
sync Test6(IntDoubleArrays[] i1)
|
||||
returns (IntDoubleArrays[] o1);
|
||||
|
||||
sync Test7_0(ActorWrapper a1)
|
||||
returns (ActorWrapper o1);
|
||||
|
||||
sync Test7(Actors i1,
|
||||
Actors i2,
|
||||
Actors i3)
|
||||
returns (Actors o1,
|
||||
Actors o2,
|
||||
Actors o3);
|
||||
|
||||
sync Test8(Actors[] i1)
|
||||
returns (Actors[] o1);
|
||||
|
||||
sync Test9(Unions i1,
|
||||
Unions i2,
|
||||
Unions i3,
|
||||
Unions i4)
|
||||
returns (Unions o1,
|
||||
Unions o2,
|
||||
Unions o3,
|
||||
Unions o4);
|
||||
|
||||
sync Test10(Unions[] i1)
|
||||
returns (Unions[] o1);
|
||||
|
||||
sync Test11(SIntDouble i)
|
||||
returns (SIntDouble o);
|
||||
|
||||
sync Test12(SIntDoubleArrays i)
|
||||
returns (SIntDoubleArrays o);
|
||||
|
||||
sync Test13(SActors i)
|
||||
returns (SActors o);
|
||||
|
||||
sync Test14(Structs i)
|
||||
returns (Structs o);
|
||||
|
||||
sync Test15(WithStructs i1,
|
||||
WithStructs i2,
|
||||
WithStructs i3,
|
||||
WithStructs i4,
|
||||
WithStructs i5)
|
||||
returns (WithStructs o1,
|
||||
WithStructs o2,
|
||||
WithStructs o3,
|
||||
WithStructs o4,
|
||||
WithStructs o5);
|
||||
|
||||
sync Test16(WithUnions i)
|
||||
returns (WithUnions o);
|
||||
|
||||
sync Test17(Op[] ops);
|
||||
|
||||
// test that the ParamTraits<nsTArray>::Read() workaround for
|
||||
// nsTArray's incorrect memmove() semantics works properly
|
||||
// (nsIntRegion isn't memmove()able)
|
||||
sync Test18(nsIntRegion[] ops);
|
||||
|
||||
sync Dummy(ShmemUnion su) returns (ShmemUnion rsu);
|
||||
|
||||
state CONSTRUCTING:
|
||||
send PTestDataStructuresSub goto CONSTRUCTING;
|
||||
send Start goto TEST1;
|
||||
state TEST1: recv Test1 goto TEST2;
|
||||
state TEST2: recv Test2 goto TEST3;
|
||||
state TEST3: recv Test3 goto TEST4;
|
||||
state TEST4: recv Test4 goto TEST5;
|
||||
state TEST5: recv Test5 goto TEST6;
|
||||
state TEST6: recv Test6 goto TEST7;
|
||||
state TEST7: recv Test7 goto TEST8;
|
||||
state TEST8: recv Test8 goto TEST9;
|
||||
state TEST9: recv Test9 goto TEST10;
|
||||
state TEST10: recv Test10 goto TEST11;
|
||||
state TEST11: recv Test11 goto TEST12;
|
||||
state TEST12: recv Test12 goto TEST13;
|
||||
state TEST13: recv Test13 goto TEST14;
|
||||
state TEST14: recv Test14 goto TEST15;
|
||||
state TEST15: recv Test15 goto TEST16;
|
||||
state TEST16: recv Test16 goto TEST17;
|
||||
state TEST17: recv Test17 goto TEST18;
|
||||
state TEST18: recv Test18 goto DEAD;
|
||||
|
||||
state DEAD:
|
||||
recv __delete__;
|
||||
};
|
||||
|
||||
} // namespace _ipdltest
|
||||
} // namespace mozilla
|
||||
|
||||
107
ipc/ipdl/test/cxx/PTestDataStructuresCommon.ipdlh
Normal file
107
ipc/ipdl/test/cxx/PTestDataStructuresCommon.ipdlh
Normal file
|
|
@ -0,0 +1,107 @@
|
|||
include protocol PTestDataStructuresSub;
|
||||
|
||||
using struct mozilla::null_t from "ipc/IPCMessageUtils.h";
|
||||
using nsIntRegion from "nsRegion.h";
|
||||
|
||||
namespace mozilla {
|
||||
namespace _foo {
|
||||
|
||||
union IntDouble {
|
||||
int;
|
||||
double;
|
||||
};
|
||||
|
||||
struct SIntDouble {
|
||||
int i;
|
||||
double d;
|
||||
};
|
||||
|
||||
union IntDoubleArrays {
|
||||
int;
|
||||
int[];
|
||||
double[];
|
||||
};
|
||||
|
||||
struct SIntDoubleArrays {
|
||||
int i;
|
||||
int[] ai;
|
||||
double[] ad;
|
||||
};
|
||||
|
||||
struct ActorWrapper {
|
||||
PTestDataStructuresSub actor;
|
||||
};
|
||||
|
||||
union Actors {
|
||||
int;
|
||||
int[];
|
||||
PTestDataStructuresSub[];
|
||||
};
|
||||
|
||||
struct SActors {
|
||||
int i;
|
||||
int[] ai;
|
||||
PTestDataStructuresSub[] ap;
|
||||
};
|
||||
|
||||
union Unions {
|
||||
int;
|
||||
int[];
|
||||
PTestDataStructuresSub[];
|
||||
Actors[];
|
||||
};
|
||||
|
||||
struct Structs {
|
||||
int i;
|
||||
int[] ai;
|
||||
PTestDataStructuresSub[] ap;
|
||||
SActors[] aa;
|
||||
};
|
||||
|
||||
union WithStructs {
|
||||
int;
|
||||
int[];
|
||||
PTestDataStructuresSub[];
|
||||
SActors[];
|
||||
Structs[];
|
||||
};
|
||||
|
||||
struct WithUnions {
|
||||
int i;
|
||||
int[] ai;
|
||||
PTestDataStructuresSub[] ap;
|
||||
Actors[] aa;
|
||||
Unions[] au;
|
||||
};
|
||||
|
||||
struct CommonAttrs { bool dummy; };
|
||||
struct FooAttrs { int dummy; };
|
||||
struct BarAttrs { float dummy; };
|
||||
union SpecificAttrs {
|
||||
FooAttrs;
|
||||
BarAttrs;
|
||||
};
|
||||
struct Attrs {
|
||||
CommonAttrs common;
|
||||
SpecificAttrs specific;
|
||||
};
|
||||
struct SetAttrs {
|
||||
PTestDataStructuresSub x;
|
||||
Attrs attrs;
|
||||
};
|
||||
union Op { null_t; SetAttrs; };
|
||||
|
||||
struct ShmemStruct {
|
||||
int i;
|
||||
Shmem mem;
|
||||
};
|
||||
|
||||
union ShmemUnion {
|
||||
int;
|
||||
Shmem;
|
||||
};
|
||||
|
||||
struct Empty { };
|
||||
|
||||
} // namespace _foo
|
||||
} // namespace mozilla
|
||||
15
ipc/ipdl/test/cxx/PTestDataStructuresSub.ipdl
Normal file
15
ipc/ipdl/test/cxx/PTestDataStructuresSub.ipdl
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
include PTestDataStructuresCommon;
|
||||
include protocol PTestDataStructures;
|
||||
|
||||
namespace mozilla {
|
||||
namespace _ipdltest {
|
||||
|
||||
sync protocol PTestDataStructuresSub {
|
||||
manager PTestDataStructures;
|
||||
|
||||
parent:
|
||||
sync __delete__();
|
||||
};
|
||||
|
||||
} // namespace _ipdltest
|
||||
} // namespace mozilla
|
||||
21
ipc/ipdl/test/cxx/PTestDemon.ipdl
Normal file
21
ipc/ipdl/test/cxx/PTestDemon.ipdl
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
namespace mozilla {
|
||||
namespace _ipdltest {
|
||||
|
||||
nested(upto inside_cpow) sync protocol PTestDemon
|
||||
{
|
||||
child:
|
||||
async Start();
|
||||
|
||||
both:
|
||||
async AsyncMessage(int n);
|
||||
nested(inside_sync) sync HiPrioSyncMessage();
|
||||
|
||||
parent:
|
||||
sync SyncMessage(int n);
|
||||
|
||||
nested(inside_cpow) async UrgentAsyncMessage(int n);
|
||||
nested(inside_cpow) sync UrgentSyncMessage(int n);
|
||||
};
|
||||
|
||||
} // namespace _ipdltest
|
||||
} // namespace mozilla
|
||||
31
ipc/ipdl/test/cxx/PTestDesc.ipdl
Normal file
31
ipc/ipdl/test/cxx/PTestDesc.ipdl
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
include protocol PTestDescSub;
|
||||
include protocol PTestDescSubsub;
|
||||
|
||||
namespace mozilla {
|
||||
namespace _ipdltest {
|
||||
|
||||
intr protocol PTestDesc {
|
||||
manages PTestDescSub;
|
||||
child:
|
||||
intr PTestDescSub(nullable PTestDescSubsub dummy);
|
||||
|
||||
async Test(PTestDescSubsub a);
|
||||
|
||||
async __delete__();
|
||||
|
||||
parent:
|
||||
async Ok(PTestDescSubsub a);
|
||||
|
||||
|
||||
state CONSTRUCT:
|
||||
call PTestDescSub goto TEST;
|
||||
state TEST:
|
||||
send Test goto ACK;
|
||||
state ACK:
|
||||
recv Ok goto DEAD;
|
||||
state DEAD:
|
||||
send __delete__;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
18
ipc/ipdl/test/cxx/PTestDescSub.ipdl
Normal file
18
ipc/ipdl/test/cxx/PTestDescSub.ipdl
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
include protocol PTestDesc;
|
||||
include protocol PTestDescSubsub;
|
||||
|
||||
namespace mozilla {
|
||||
namespace _ipdltest {
|
||||
|
||||
intr protocol PTestDescSub {
|
||||
manager PTestDesc;
|
||||
manages PTestDescSubsub;
|
||||
|
||||
child:
|
||||
async __delete__();
|
||||
|
||||
intr PTestDescSubsub();
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
15
ipc/ipdl/test/cxx/PTestDescSubsub.ipdl
Normal file
15
ipc/ipdl/test/cxx/PTestDescSubsub.ipdl
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
|
||||
include protocol PTestDescSub;
|
||||
|
||||
namespace mozilla {
|
||||
namespace _ipdltest {
|
||||
|
||||
intr protocol PTestDescSubsub {
|
||||
manager PTestDescSub;
|
||||
|
||||
child:
|
||||
intr __delete__();
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
23
ipc/ipdl/test/cxx/PTestEndpointBridgeMain.ipdl
Normal file
23
ipc/ipdl/test/cxx/PTestEndpointBridgeMain.ipdl
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
|
||||
include protocol PTestEndpointBridgeMainSub;
|
||||
include protocol PTestEndpointBridgeSub;
|
||||
|
||||
namespace mozilla {
|
||||
namespace _ipdltest {
|
||||
|
||||
|
||||
protocol PTestEndpointBridgeMain {
|
||||
child spawns PTestEndpointBridgeSub;
|
||||
|
||||
child:
|
||||
async Start();
|
||||
|
||||
parent:
|
||||
async Bridged(Endpoint<PTestEndpointBridgeMainSubParent> endpoint);
|
||||
};
|
||||
|
||||
|
||||
} // namespace mozilla
|
||||
} // namespace _ipdltest
|
||||
25
ipc/ipdl/test/cxx/PTestEndpointBridgeMainSub.ipdl
Normal file
25
ipc/ipdl/test/cxx/PTestEndpointBridgeMainSub.ipdl
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
|
||||
include protocol PTestEndpointBridgeMain;
|
||||
include protocol PTestEndpointBridgeSub;
|
||||
|
||||
namespace mozilla {
|
||||
namespace _ipdltest {
|
||||
|
||||
// (Bridge protocols can have different semantics than the endpoints
|
||||
// they bridge)
|
||||
intr protocol PTestEndpointBridgeMainSub {
|
||||
child:
|
||||
async Hi();
|
||||
intr HiRpc();
|
||||
|
||||
parent:
|
||||
async Hello();
|
||||
sync HelloSync();
|
||||
intr HelloRpc();
|
||||
};
|
||||
|
||||
|
||||
} // namespace mozilla
|
||||
} // namespace _ipdltest
|
||||
22
ipc/ipdl/test/cxx/PTestEndpointBridgeSub.ipdl
Normal file
22
ipc/ipdl/test/cxx/PTestEndpointBridgeSub.ipdl
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
|
||||
include protocol PTestEndpointBridgeMainSub;
|
||||
|
||||
namespace mozilla {
|
||||
namespace _ipdltest {
|
||||
|
||||
|
||||
protocol PTestEndpointBridgeSub {
|
||||
child:
|
||||
async Ping();
|
||||
|
||||
async Bridged(Endpoint<PTestEndpointBridgeMainSubChild> endpoint);
|
||||
|
||||
parent:
|
||||
async BridgeEm();
|
||||
};
|
||||
|
||||
|
||||
} // namespace mozilla
|
||||
} // namespace _ipdltest
|
||||
19
ipc/ipdl/test/cxx/PTestEndpointOpens.ipdl
Normal file
19
ipc/ipdl/test/cxx/PTestEndpointOpens.ipdl
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
include protocol PTestEndpointOpensOpened;
|
||||
|
||||
namespace mozilla {
|
||||
namespace _ipdltest {
|
||||
|
||||
protocol PTestEndpointOpens {
|
||||
child:
|
||||
async Start();
|
||||
|
||||
parent:
|
||||
async StartSubprotocol(Endpoint<PTestEndpointOpensOpenedParent> endpoint);
|
||||
|
||||
async __delete__();
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
} // namespace _ipdltest
|
||||
30
ipc/ipdl/test/cxx/PTestEndpointOpensOpened.ipdl
Normal file
30
ipc/ipdl/test/cxx/PTestEndpointOpensOpened.ipdl
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
namespace mozilla {
|
||||
namespace _ipdltest2 {
|
||||
|
||||
// (Opens protocols can have different semantics than the endpoints
|
||||
// that opened them)
|
||||
intr protocol PTestEndpointOpensOpened {
|
||||
child:
|
||||
async Hi();
|
||||
intr HiRpc();
|
||||
|
||||
parent:
|
||||
async Hello();
|
||||
sync HelloSync();
|
||||
intr HelloRpc();
|
||||
async __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 _ipdltest2
|
||||
19
ipc/ipdl/test/cxx/PTestFailedCtor.ipdl
Normal file
19
ipc/ipdl/test/cxx/PTestFailedCtor.ipdl
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
include protocol PTestFailedCtorSub;
|
||||
|
||||
namespace mozilla {
|
||||
namespace _ipdltest {
|
||||
|
||||
intr protocol PTestFailedCtor {
|
||||
manages PTestFailedCtorSub;
|
||||
child:
|
||||
intr PTestFailedCtorSub();
|
||||
async __delete__();
|
||||
|
||||
state CONSTRUCT:
|
||||
call PTestFailedCtorSub goto DEAD;
|
||||
state DEAD:
|
||||
send __delete__;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
18
ipc/ipdl/test/cxx/PTestFailedCtorSub.ipdl
Normal file
18
ipc/ipdl/test/cxx/PTestFailedCtorSub.ipdl
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
include protocol PTestFailedCtor;
|
||||
include protocol PTestFailedCtorSubsub;
|
||||
|
||||
namespace mozilla {
|
||||
namespace _ipdltest {
|
||||
|
||||
intr protocol PTestFailedCtorSub {
|
||||
manager PTestFailedCtor;
|
||||
manages PTestFailedCtorSubsub;
|
||||
|
||||
parent:
|
||||
async PTestFailedCtorSubsub();
|
||||
sync Sync();
|
||||
async __delete__();
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
15
ipc/ipdl/test/cxx/PTestFailedCtorSubsub.ipdl
Normal file
15
ipc/ipdl/test/cxx/PTestFailedCtorSubsub.ipdl
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
|
||||
include protocol PTestFailedCtorSub;
|
||||
|
||||
namespace mozilla {
|
||||
namespace _ipdltest {
|
||||
|
||||
intr protocol PTestFailedCtorSubsub {
|
||||
manager PTestFailedCtorSub;
|
||||
|
||||
parent:
|
||||
async __delete__();
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
14
ipc/ipdl/test/cxx/PTestHandle.ipdl
Normal file
14
ipc/ipdl/test/cxx/PTestHandle.ipdl
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
include protocol PTestJSON;
|
||||
|
||||
namespace mozilla {
|
||||
namespace _ipdltest {
|
||||
|
||||
protocol PTestHandle {
|
||||
manager PTestJSON;
|
||||
|
||||
child:
|
||||
async __delete__();
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
} // namespace _ipdltest
|
||||
40
ipc/ipdl/test/cxx/PTestHangs.ipdl
Normal file
40
ipc/ipdl/test/cxx/PTestHangs.ipdl
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
|
||||
namespace mozilla {
|
||||
namespace _ipdltest {
|
||||
|
||||
intr protocol PTestHangs {
|
||||
both:
|
||||
intr StackFrame();
|
||||
|
||||
parent:
|
||||
async Nonce();
|
||||
|
||||
child:
|
||||
async Start();
|
||||
intr Hang();
|
||||
async __delete__();
|
||||
|
||||
|
||||
state START:
|
||||
send Start goto RACE;
|
||||
|
||||
state RACE:
|
||||
recv Nonce goto RACE1;
|
||||
call StackFrame goto RACE2;
|
||||
state RACE1:
|
||||
call StackFrame goto FRAME2;
|
||||
state RACE2:
|
||||
recv Nonce goto FRAME2;
|
||||
|
||||
// So as to test unwinding the RPC stack
|
||||
state FRAME2: answer StackFrame goto FRAME3;
|
||||
state FRAME3: call StackFrame goto FRAME4;
|
||||
state FRAME4: answer StackFrame goto HANG;
|
||||
state HANG: call Hang goto DEATH;
|
||||
|
||||
state DEATH:
|
||||
send __delete__;
|
||||
};
|
||||
|
||||
} // namespace _ipdltest
|
||||
} // namespace mozilla
|
||||
18
ipc/ipdl/test/cxx/PTestHighestPrio.ipdl
Normal file
18
ipc/ipdl/test/cxx/PTestHighestPrio.ipdl
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
namespace mozilla {
|
||||
namespace _ipdltest {
|
||||
|
||||
nested(upto inside_cpow) sync protocol PTestHighestPrio
|
||||
{
|
||||
parent:
|
||||
nested(inside_cpow) async Msg1();
|
||||
nested(inside_sync) sync Msg2();
|
||||
nested(inside_cpow) async Msg3();
|
||||
nested(inside_cpow) sync Msg4();
|
||||
|
||||
child:
|
||||
async Start();
|
||||
nested(inside_sync) sync StartInner();
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
15
ipc/ipdl/test/cxx/PTestIndirectProtocolParam.ipdlh
Normal file
15
ipc/ipdl/test/cxx/PTestIndirectProtocolParam.ipdlh
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
include protocol PTestIndirectProtocolParamSecond;
|
||||
|
||||
namespace mozilla {
|
||||
namespace _ipdltest {
|
||||
|
||||
struct IndirectParamStruct {
|
||||
PTestIndirectProtocolParamSecond actor;
|
||||
};
|
||||
|
||||
union IndirectParamUnion {
|
||||
IndirectParamStruct;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
19
ipc/ipdl/test/cxx/PTestIndirectProtocolParamFirst.ipdl
Normal file
19
ipc/ipdl/test/cxx/PTestIndirectProtocolParamFirst.ipdl
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
include protocol PTestIndirectProtocolParamManage;
|
||||
// FIXME/bug 792908 protocol PTestIndirectProtocolParamSecond is
|
||||
// already included in PTestIndirectProtocolParam.ipdlh
|
||||
include protocol PTestIndirectProtocolParamSecond;
|
||||
include PTestIndirectProtocolParam;
|
||||
|
||||
namespace mozilla {
|
||||
namespace _ipdltest {
|
||||
|
||||
sync protocol PTestIndirectProtocolParamFirst {
|
||||
manager PTestIndirectProtocolParamManage;
|
||||
parent:
|
||||
sync Test(IndirectParamUnion actor);
|
||||
both:
|
||||
async __delete__();
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
17
ipc/ipdl/test/cxx/PTestIndirectProtocolParamManage.ipdl
Normal file
17
ipc/ipdl/test/cxx/PTestIndirectProtocolParamManage.ipdl
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
include protocol PTestIndirectProtocolParamFirst;
|
||||
include protocol PTestIndirectProtocolParamSecond;
|
||||
|
||||
namespace mozilla {
|
||||
namespace _ipdltest {
|
||||
|
||||
sync protocol PTestIndirectProtocolParamManage {
|
||||
manages PTestIndirectProtocolParamFirst;
|
||||
manages PTestIndirectProtocolParamSecond;
|
||||
both:
|
||||
async PTestIndirectProtocolParamFirst();
|
||||
async PTestIndirectProtocolParamSecond();
|
||||
async __delete__();
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
13
ipc/ipdl/test/cxx/PTestIndirectProtocolParamSecond.ipdl
Normal file
13
ipc/ipdl/test/cxx/PTestIndirectProtocolParamSecond.ipdl
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
include protocol PTestIndirectProtocolParamManage;
|
||||
|
||||
namespace mozilla {
|
||||
namespace _ipdltest {
|
||||
|
||||
sync protocol PTestIndirectProtocolParamSecond {
|
||||
manager PTestIndirectProtocolParamManage;
|
||||
both:
|
||||
async __delete__();
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
11
ipc/ipdl/test/cxx/PTestInterruptErrorCleanup.ipdl
Normal file
11
ipc/ipdl/test/cxx/PTestInterruptErrorCleanup.ipdl
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
namespace mozilla {
|
||||
namespace _ipdltest {
|
||||
|
||||
intr protocol PTestInterruptErrorCleanup {
|
||||
child:
|
||||
intr Error();
|
||||
intr __delete__();
|
||||
};
|
||||
|
||||
} // namespace _ipdltest
|
||||
} // namespace mozilla
|
||||
82
ipc/ipdl/test/cxx/PTestInterruptRaces.ipdl
Normal file
82
ipc/ipdl/test/cxx/PTestInterruptRaces.ipdl
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
namespace mozilla {
|
||||
namespace _ipdltest {
|
||||
|
||||
intr protocol PTestInterruptRaces {
|
||||
both:
|
||||
intr Race() returns (bool hasReply);
|
||||
intr StackFrame() returns ();
|
||||
intr StackFrame3() returns ();
|
||||
|
||||
parent:
|
||||
sync StartRace();
|
||||
intr Parent();
|
||||
sync GetAnsweredParent() returns (bool answeredParent);
|
||||
|
||||
child:
|
||||
async Start();
|
||||
async Wakeup();
|
||||
async Wakeup3();
|
||||
intr Child();
|
||||
async __delete__();
|
||||
|
||||
state START:
|
||||
send Start goto TEST1;
|
||||
|
||||
// First test: race while no other messages are on the Interrupt stack
|
||||
state TEST1:
|
||||
recv StartRace goto RACE1;
|
||||
state RACE1:
|
||||
call Race goto DUMMY1_1;
|
||||
answer Race goto DUMMY1_2;
|
||||
state DUMMY1_1:
|
||||
answer Race goto TEST2;
|
||||
state DUMMY1_2:
|
||||
call Race goto TEST2;
|
||||
|
||||
// Second test: race while other messages are on the Interrupt stack
|
||||
state TEST2:
|
||||
call StackFrame goto MORESTACK;
|
||||
state MORESTACK:
|
||||
answer StackFrame goto STARTRACE;
|
||||
state STARTRACE:
|
||||
send Wakeup goto RACE2;
|
||||
state RACE2:
|
||||
call Race goto DUMMY2_1;
|
||||
answer Race goto DUMMY2_2;
|
||||
state DUMMY2_1:
|
||||
answer Race goto TEST3;
|
||||
state DUMMY2_2:
|
||||
call Race goto TEST3;
|
||||
|
||||
// Third test: resolve race using custom policy
|
||||
state TEST3:
|
||||
call StackFrame3 goto MORESTACK3;
|
||||
state MORESTACK3:
|
||||
answer StackFrame3 goto STARTRACE3;
|
||||
state STARTRACE3:
|
||||
send Wakeup3 goto RACE3;
|
||||
state RACE3:
|
||||
call Child goto DUMMY3_1;
|
||||
answer Parent goto DUMMY3_2;
|
||||
state DUMMY3_1:
|
||||
// the parent receives this from the child in this state
|
||||
recv GetAnsweredParent goto CHECK;
|
||||
// this transition is never taken (if the custom race resolution
|
||||
// works correctly)
|
||||
answer Parent goto CHECK;
|
||||
state DUMMY3_2:
|
||||
call Child goto CHECK;
|
||||
state CHECK:
|
||||
// the child sends this from this state
|
||||
recv GetAnsweredParent goto DYING;
|
||||
// because of deferred processing, the parent receives the child's
|
||||
// message here
|
||||
answer Parent goto DYING;
|
||||
|
||||
|
||||
state DYING:
|
||||
send __delete__;
|
||||
};
|
||||
|
||||
} // namespace _ipdltest
|
||||
} // namespace mozilla
|
||||
34
ipc/ipdl/test/cxx/PTestInterruptShutdownRace.ipdl
Normal file
34
ipc/ipdl/test/cxx/PTestInterruptShutdownRace.ipdl
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
namespace mozilla {
|
||||
namespace _ipdltest {
|
||||
|
||||
intr protocol PTestInterruptShutdownRace {
|
||||
parent:
|
||||
sync StartDeath();
|
||||
async Orphan();
|
||||
|
||||
child:
|
||||
async Start();
|
||||
intr Exit();
|
||||
async __delete__();
|
||||
|
||||
state START:
|
||||
send Start goto START_DEATH;
|
||||
|
||||
state START_DEATH:
|
||||
recv StartDeath goto EXITING;
|
||||
|
||||
state EXITING:
|
||||
recv Orphan goto QUITTING1;
|
||||
call Exit goto QUITTING2;
|
||||
|
||||
state QUITTING1:
|
||||
call Exit goto DEAD;
|
||||
state QUITTING2:
|
||||
recv Orphan goto DEAD;
|
||||
|
||||
state DEAD:
|
||||
send __delete__;
|
||||
};
|
||||
|
||||
} // namespace _ipdltest
|
||||
} // namespace mozilla
|
||||
54
ipc/ipdl/test/cxx/PTestJSON.ipdl
Normal file
54
ipc/ipdl/test/cxx/PTestJSON.ipdl
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
include protocol PTestHandle;
|
||||
|
||||
using struct mozilla::void_t from "ipc/IPCMessageUtils.h";
|
||||
using struct mozilla::null_t from "ipc/IPCMessageUtils.h";
|
||||
|
||||
namespace mozilla {
|
||||
namespace _ipdltest {
|
||||
|
||||
union Key {
|
||||
// int;
|
||||
// double;
|
||||
nsString;
|
||||
};
|
||||
|
||||
struct KeyValue {
|
||||
Key key;
|
||||
JSONVariant value;
|
||||
};
|
||||
|
||||
union JSONVariant {
|
||||
void_t;
|
||||
null_t;
|
||||
bool;
|
||||
int;
|
||||
double;
|
||||
nsString;
|
||||
PTestHandle;
|
||||
KeyValue[];
|
||||
JSONVariant[];
|
||||
};
|
||||
|
||||
sync protocol PTestJSON {
|
||||
manages PTestHandle;
|
||||
|
||||
child:
|
||||
async Start();
|
||||
|
||||
parent:
|
||||
async PTestHandle();
|
||||
sync Test(JSONVariant i)
|
||||
returns (JSONVariant o);
|
||||
async __delete__();
|
||||
|
||||
state START:
|
||||
send Start goto TEST;
|
||||
|
||||
state TEST:
|
||||
recv PTestHandle goto TEST;
|
||||
recv Test goto TEST;
|
||||
recv __delete__;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
} // namespace _ipdltest
|
||||
75
ipc/ipdl/test/cxx/PTestLatency.ipdl
Normal file
75
ipc/ipdl/test/cxx/PTestLatency.ipdl
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
|
||||
namespace mozilla {
|
||||
namespace _ipdltest {
|
||||
|
||||
|
||||
intr protocol PTestLatency {
|
||||
|
||||
child:
|
||||
async __delete__();
|
||||
async Ping();
|
||||
async Ping5();
|
||||
intr Rpc();
|
||||
async Spam();
|
||||
intr Synchro();
|
||||
async CompressedSpam(uint32_t seqno) compress;
|
||||
intr Synchro2() returns (uint32_t lastSeqno,
|
||||
uint32_t numMessagesDispatched);
|
||||
|
||||
parent:
|
||||
async Pong();
|
||||
async Pong5();
|
||||
|
||||
state START:
|
||||
// if the timing resolution is too low, abort the test
|
||||
send __delete__;
|
||||
// otherwise, kick off the ping/pong trials
|
||||
send Ping goto PONG;
|
||||
|
||||
// Trial 1: single ping/pong latency
|
||||
state PING:
|
||||
send Ping goto PONG;
|
||||
send Ping5 goto PING4;
|
||||
|
||||
state PONG:
|
||||
recv Pong goto PING;
|
||||
|
||||
// Trial 2: "overlapped" ping/pong latency
|
||||
state PING5:
|
||||
send Ping5 goto PING4;
|
||||
call Rpc goto RPC;
|
||||
|
||||
state PING4: send Ping5 goto PING3;
|
||||
state PING3: send Ping5 goto PING2;
|
||||
state PING2: send Ping5 goto PING1;
|
||||
state PING1: send Ping5 goto PONG1;
|
||||
|
||||
state PONG1: recv Pong5 goto PONG2;
|
||||
state PONG2: recv Pong5 goto PONG3;
|
||||
state PONG3: recv Pong5 goto PONG4;
|
||||
state PONG4: recv Pong5 goto PONG5;
|
||||
state PONG5: recv Pong5 goto PING5;
|
||||
|
||||
// Trial 3: lotsa RPC
|
||||
state RPC:
|
||||
call Rpc goto RPC;
|
||||
send Spam goto SPAM;
|
||||
|
||||
// Trial 4: lots of sequential asyn messages, which tests pipelining
|
||||
state SPAM:
|
||||
send Spam goto SPAM;
|
||||
call Synchro goto COMPRESSED_SPAM;
|
||||
|
||||
// Trial 5: lots of async spam, but compressed to cut down on
|
||||
// dispatch overhead
|
||||
state COMPRESSED_SPAM: // compressed spam, mmm
|
||||
send CompressedSpam goto COMPRESSED_SPAM;
|
||||
call Synchro2 goto DONE;
|
||||
|
||||
state DONE:
|
||||
send __delete__;
|
||||
};
|
||||
|
||||
|
||||
} // namespace mozilla
|
||||
} // namespace _ipdltest
|
||||
19
ipc/ipdl/test/cxx/PTestManyChildAllocs.ipdl
Normal file
19
ipc/ipdl/test/cxx/PTestManyChildAllocs.ipdl
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
include protocol PTestManyChildAllocsSub;
|
||||
|
||||
namespace mozilla {
|
||||
namespace _ipdltest {
|
||||
|
||||
protocol PTestManyChildAllocs {
|
||||
manages PTestManyChildAllocsSub;
|
||||
|
||||
child:
|
||||
async Go(); // start allocating
|
||||
|
||||
parent:
|
||||
async Done();
|
||||
|
||||
async PTestManyChildAllocsSub();
|
||||
};
|
||||
|
||||
} // namespace _ipdltest
|
||||
} // namespace mozilla
|
||||
19
ipc/ipdl/test/cxx/PTestManyChildAllocsSub.ipdl
Normal file
19
ipc/ipdl/test/cxx/PTestManyChildAllocsSub.ipdl
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
include protocol PTestManyChildAllocs;
|
||||
|
||||
namespace mozilla {
|
||||
namespace _ipdltest {
|
||||
|
||||
protocol PTestManyChildAllocsSub {
|
||||
manager PTestManyChildAllocs;
|
||||
|
||||
child:
|
||||
async __delete__();
|
||||
|
||||
parent:
|
||||
async Hello();
|
||||
|
||||
// empty
|
||||
};
|
||||
|
||||
} // namespace _ipdltest
|
||||
} // namespace mozilla
|
||||
34
ipc/ipdl/test/cxx/PTestMultiMgrs.ipdl
Normal file
34
ipc/ipdl/test/cxx/PTestMultiMgrs.ipdl
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
include protocol PTestMultiMgrsLeft;
|
||||
include protocol PTestMultiMgrsRight;
|
||||
|
||||
namespace mozilla {
|
||||
namespace _ipdltest {
|
||||
|
||||
protocol PTestMultiMgrs {
|
||||
manages PTestMultiMgrsLeft;
|
||||
manages PTestMultiMgrsRight;
|
||||
|
||||
parent:
|
||||
async OK();
|
||||
|
||||
child:
|
||||
async PTestMultiMgrsLeft();
|
||||
async PTestMultiMgrsRight();
|
||||
async Check();
|
||||
async __delete__();
|
||||
|
||||
state START:
|
||||
send PTestMultiMgrsLeft goto CONSTRUCT_RIGHT;
|
||||
state CONSTRUCT_RIGHT:
|
||||
send PTestMultiMgrsRight goto CHILD_CHECK;
|
||||
state CHILD_CHECK:
|
||||
send Check goto CHILD_ACK;
|
||||
state CHILD_ACK:
|
||||
recv OK goto DONE;
|
||||
|
||||
state DONE:
|
||||
send __delete__;
|
||||
};
|
||||
|
||||
} // namespace _ipdltest
|
||||
} // namespace mozilla
|
||||
18
ipc/ipdl/test/cxx/PTestMultiMgrsBottom.ipdl
Normal file
18
ipc/ipdl/test/cxx/PTestMultiMgrsBottom.ipdl
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
include protocol PTestMultiMgrsLeft;
|
||||
include protocol PTestMultiMgrsRight;
|
||||
|
||||
namespace mozilla {
|
||||
namespace _ipdltest {
|
||||
|
||||
protocol PTestMultiMgrsBottom {
|
||||
manager PTestMultiMgrsLeft or PTestMultiMgrsRight;
|
||||
|
||||
child:
|
||||
async __delete__();
|
||||
|
||||
state DOA:
|
||||
send __delete__;
|
||||
};
|
||||
|
||||
} // namespace _ipdltest
|
||||
} // namespace mozilla
|
||||
24
ipc/ipdl/test/cxx/PTestMultiMgrsLeft.ipdl
Normal file
24
ipc/ipdl/test/cxx/PTestMultiMgrsLeft.ipdl
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
include protocol PTestMultiMgrs;
|
||||
include protocol PTestMultiMgrsBottom;
|
||||
|
||||
namespace mozilla {
|
||||
namespace _ipdltest {
|
||||
|
||||
protocol PTestMultiMgrsLeft {
|
||||
manager PTestMultiMgrs;
|
||||
|
||||
manages PTestMultiMgrsBottom;
|
||||
|
||||
child:
|
||||
async PTestMultiMgrsBottom();
|
||||
async __delete__();
|
||||
|
||||
state START:
|
||||
send PTestMultiMgrsBottom goto DONE;
|
||||
|
||||
state DONE:
|
||||
send __delete__;
|
||||
};
|
||||
|
||||
} // namespace _ipdltest
|
||||
} // namespace mozilla
|
||||
24
ipc/ipdl/test/cxx/PTestMultiMgrsRight.ipdl
Normal file
24
ipc/ipdl/test/cxx/PTestMultiMgrsRight.ipdl
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
include protocol PTestMultiMgrs;
|
||||
include protocol PTestMultiMgrsBottom;
|
||||
|
||||
namespace mozilla {
|
||||
namespace _ipdltest {
|
||||
|
||||
protocol PTestMultiMgrsRight {
|
||||
manager PTestMultiMgrs;
|
||||
|
||||
manages PTestMultiMgrsBottom;
|
||||
|
||||
child:
|
||||
async PTestMultiMgrsBottom();
|
||||
async __delete__();
|
||||
|
||||
state START:
|
||||
send PTestMultiMgrsBottom goto DONE;
|
||||
|
||||
state DONE:
|
||||
send __delete__;
|
||||
};
|
||||
|
||||
} // namespace _ipdltest
|
||||
} // namespace mozilla
|
||||
34
ipc/ipdl/test/cxx/PTestNestedLoops.ipdl
Normal file
34
ipc/ipdl/test/cxx/PTestNestedLoops.ipdl
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
|
||||
namespace mozilla {
|
||||
namespace _ipdltest {
|
||||
|
||||
|
||||
intr protocol PTestNestedLoops {
|
||||
|
||||
child:
|
||||
async Start();
|
||||
intr R();
|
||||
async __delete__();
|
||||
|
||||
parent:
|
||||
async Nonce();
|
||||
|
||||
|
||||
state START:
|
||||
send Start goto RACE;
|
||||
|
||||
state RACE:
|
||||
recv Nonce goto RACE1;
|
||||
call R goto RACE2;
|
||||
state RACE1:
|
||||
call R goto DEAD;
|
||||
state RACE2:
|
||||
recv Nonce goto DEAD;
|
||||
|
||||
state DEAD:
|
||||
send __delete__;
|
||||
};
|
||||
|
||||
|
||||
} // namespace mozilla
|
||||
} // namespace _ipdltest
|
||||
25
ipc/ipdl/test/cxx/PTestOpens.ipdl
Normal file
25
ipc/ipdl/test/cxx/PTestOpens.ipdl
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
include protocol PTestOpensOpened;
|
||||
|
||||
namespace mozilla {
|
||||
namespace _ipdltest {
|
||||
|
||||
|
||||
protocol PTestOpens {
|
||||
// This channel is opened and parked on a non-main thread
|
||||
child opens PTestOpensOpened;
|
||||
|
||||
child:
|
||||
async Start();
|
||||
|
||||
parent:
|
||||
async __delete__();
|
||||
|
||||
state START:
|
||||
send Start goto DEAD;
|
||||
state DEAD:
|
||||
recv __delete__;
|
||||
};
|
||||
|
||||
|
||||
} // namespace mozilla
|
||||
} // namespace _ipdltest
|
||||
28
ipc/ipdl/test/cxx/PTestOpensOpened.ipdl
Normal file
28
ipc/ipdl/test/cxx/PTestOpensOpened.ipdl
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
namespace mozilla {
|
||||
namespace _ipdltest2 {
|
||||
|
||||
// (Opens protocols can have different semantics than the endpoints
|
||||
// that opened them)
|
||||
intr protocol PTestOpensOpened {
|
||||
child:
|
||||
async Hi();
|
||||
intr HiRpc();
|
||||
|
||||
parent:
|
||||
async Hello();
|
||||
sync HelloSync();
|
||||
intr HelloRpc();
|
||||
async __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 _ipdltest2
|
||||
14
ipc/ipdl/test/cxx/PTestPriority.ipdl
Normal file
14
ipc/ipdl/test/cxx/PTestPriority.ipdl
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
namespace mozilla {
|
||||
namespace _ipdltest {
|
||||
|
||||
sync protocol PTestPriority {
|
||||
parent:
|
||||
prio(high) async Msg1();
|
||||
prio(high) sync Msg2();
|
||||
|
||||
child:
|
||||
prio(high) async Msg3();
|
||||
};
|
||||
|
||||
} // namespace _ipdltest
|
||||
} // namespace mozilla
|
||||
21
ipc/ipdl/test/cxx/PTestRPC.ipdl
Normal file
21
ipc/ipdl/test/cxx/PTestRPC.ipdl
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
namespace mozilla {
|
||||
namespace _ipdltest {
|
||||
|
||||
nested(upto inside_sync) sync protocol PTestRPC
|
||||
{
|
||||
parent:
|
||||
nested(inside_sync) sync Test1_Start() returns (uint32_t result);
|
||||
nested(inside_sync) sync Test1_InnerEvent() returns (uint32_t result);
|
||||
async Test2_Start();
|
||||
nested(inside_sync) sync Test2_OutOfOrder();
|
||||
|
||||
child:
|
||||
async Start();
|
||||
nested(inside_sync) sync Test1_InnerQuery() returns (uint32_t result);
|
||||
nested(inside_sync) sync Test1_NoReenter() returns (uint32_t result);
|
||||
nested(inside_sync) sync Test2_FirstUrgent();
|
||||
nested(inside_sync) sync Test2_SecondUrgent();
|
||||
};
|
||||
|
||||
} // namespace _ipdltest
|
||||
} // namespace mozilla
|
||||
20
ipc/ipdl/test/cxx/PTestRaceDeadlock.ipdl
Normal file
20
ipc/ipdl/test/cxx/PTestRaceDeadlock.ipdl
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
namespace mozilla {
|
||||
namespace _ipdltest {
|
||||
|
||||
intr protocol PTestRaceDeadlock {
|
||||
both:
|
||||
async StartRace();
|
||||
|
||||
parent:
|
||||
intr Lose();
|
||||
|
||||
child:
|
||||
intr Win();
|
||||
intr Rpc();
|
||||
async __delete__();
|
||||
|
||||
/* Tests that race resolution does not cause deadlocks */
|
||||
};
|
||||
|
||||
} // namespace _ipdltest
|
||||
} // namespace mozilla
|
||||
45
ipc/ipdl/test/cxx/PTestRaceDeferral.ipdl
Normal file
45
ipc/ipdl/test/cxx/PTestRaceDeferral.ipdl
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
namespace mozilla {
|
||||
namespace _ipdltest {
|
||||
|
||||
intr protocol PTestRaceDeferral {
|
||||
parent:
|
||||
intr Lose();
|
||||
|
||||
child:
|
||||
async StartRace();
|
||||
intr Win();
|
||||
intr Rpc();
|
||||
async __delete__();
|
||||
|
||||
// Test that messages deferred due to race resolution are
|
||||
// re-considered when the winner makes later RPCs
|
||||
|
||||
// IPDL's type system can't express this protocol because the race
|
||||
// resolution causes state to diverge for multiple steps, so we'll
|
||||
// leave it "stateless"
|
||||
/*
|
||||
state START:
|
||||
send StartRace goto DEFER;
|
||||
state DEFER:
|
||||
call Win goto PARENT;
|
||||
answer Lose goto CHILD;
|
||||
|
||||
state PARENT:
|
||||
// 'Lose' is received here but deferred
|
||||
call Rpc goto PARENT_LOSE;
|
||||
state PARENT_LOSE:
|
||||
// Calling 'Rpc' undefers 'Lose', and it wins the "race" with 'Rpc'
|
||||
answer Lose goto DONE;
|
||||
|
||||
state CHILD:
|
||||
call Win goto CHILD_RPC;
|
||||
state CHILD_RPC:
|
||||
call Rpc goto DONE;
|
||||
|
||||
state DONE:
|
||||
send __delete__;
|
||||
*/
|
||||
};
|
||||
|
||||
} // namespace _ipdltest
|
||||
} // namespace mozilla
|
||||
41
ipc/ipdl/test/cxx/PTestRacyInterruptReplies.ipdl
Normal file
41
ipc/ipdl/test/cxx/PTestRacyInterruptReplies.ipdl
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
namespace mozilla {
|
||||
namespace _ipdltest {
|
||||
|
||||
intr protocol PTestRacyInterruptReplies {
|
||||
child:
|
||||
intr R_() returns (int replyNum);
|
||||
async _A();
|
||||
async ChildTest();
|
||||
async __delete__();
|
||||
|
||||
parent:
|
||||
intr _R() returns (int replyNum);
|
||||
async A_();
|
||||
|
||||
state PARENT_START:
|
||||
call R_ goto PARENT_S1;
|
||||
|
||||
state PARENT_S1:
|
||||
recv A_ goto PARENT_S2;
|
||||
|
||||
state PARENT_S2:
|
||||
call R_ goto CHILD_TEST;
|
||||
|
||||
state CHILD_TEST:
|
||||
send ChildTest goto CHILD_START;
|
||||
|
||||
state CHILD_START:
|
||||
answer _R goto CHILD_S1;
|
||||
|
||||
state CHILD_S1:
|
||||
send _A goto CHILD_S2;
|
||||
|
||||
state CHILD_S2:
|
||||
answer _R goto DYING;
|
||||
|
||||
state DYING:
|
||||
send __delete__;
|
||||
};
|
||||
|
||||
} // namespace _ipdltest
|
||||
} // namespace mozilla
|
||||
21
ipc/ipdl/test/cxx/PTestRacyReentry.ipdl
Normal file
21
ipc/ipdl/test/cxx/PTestRacyReentry.ipdl
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
|
||||
namespace mozilla {
|
||||
namespace _ipdltest {
|
||||
|
||||
|
||||
intr protocol PTestRacyReentry {
|
||||
|
||||
parent:
|
||||
intr E();
|
||||
async __delete__();
|
||||
|
||||
child:
|
||||
async Start();
|
||||
|
||||
async N();
|
||||
intr H();
|
||||
};
|
||||
|
||||
|
||||
} // namespace mozilla
|
||||
} // namespace _ipdltest
|
||||
28
ipc/ipdl/test/cxx/PTestRacyUndefer.ipdl
Normal file
28
ipc/ipdl/test/cxx/PTestRacyUndefer.ipdl
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
|
||||
namespace mozilla {
|
||||
namespace _ipdltest {
|
||||
|
||||
|
||||
intr protocol PTestRacyUndefer {
|
||||
|
||||
child:
|
||||
async Start();
|
||||
|
||||
async AwakenSpam();
|
||||
async AwakenRaceWinTwice();
|
||||
|
||||
intr Race();
|
||||
|
||||
async __delete__();
|
||||
|
||||
parent:
|
||||
|
||||
intr Spam();
|
||||
intr RaceWinTwice();
|
||||
|
||||
async Done();
|
||||
};
|
||||
|
||||
|
||||
} // namespace mozilla
|
||||
} // namespace _ipdltest
|
||||
28
ipc/ipdl/test/cxx/PTestSanity.ipdl
Normal file
28
ipc/ipdl/test/cxx/PTestSanity.ipdl
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
|
||||
namespace mozilla {
|
||||
namespace _ipdltest {
|
||||
|
||||
|
||||
protocol PTestSanity {
|
||||
|
||||
child:
|
||||
async Ping(int zero, float zeroPtFive, int8_t dummy);
|
||||
async __delete__();
|
||||
|
||||
parent:
|
||||
async Pong(int one, float zeroPtTwoFive, uint8_t dummy);
|
||||
|
||||
|
||||
state PING:
|
||||
send Ping goto PONG;
|
||||
|
||||
state PONG:
|
||||
recv Pong goto DEAD;
|
||||
|
||||
state DEAD:
|
||||
send __delete__;
|
||||
};
|
||||
|
||||
|
||||
} // namespace mozilla
|
||||
} // namespace _ipdltest
|
||||
22
ipc/ipdl/test/cxx/PTestSelfManage.ipdl
Normal file
22
ipc/ipdl/test/cxx/PTestSelfManage.ipdl
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
include protocol PTestSelfManageRoot;
|
||||
|
||||
namespace mozilla {
|
||||
namespace _ipdltest {
|
||||
|
||||
|
||||
protocol PTestSelfManage {
|
||||
manager PTestSelfManageRoot or PTestSelfManage;
|
||||
manages PTestSelfManage;
|
||||
|
||||
child:
|
||||
async PTestSelfManage();
|
||||
async __delete__();
|
||||
|
||||
state LIVE:
|
||||
send PTestSelfManage goto LIVE;
|
||||
send __delete__;
|
||||
};
|
||||
|
||||
|
||||
} // namespace mozilla
|
||||
} // namespace _ipdltest
|
||||
23
ipc/ipdl/test/cxx/PTestSelfManageRoot.ipdl
Normal file
23
ipc/ipdl/test/cxx/PTestSelfManageRoot.ipdl
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
include protocol PTestSelfManage;
|
||||
|
||||
namespace mozilla {
|
||||
namespace _ipdltest {
|
||||
|
||||
|
||||
protocol PTestSelfManageRoot {
|
||||
manages PTestSelfManage;
|
||||
|
||||
child:
|
||||
async PTestSelfManage();
|
||||
async __delete__();
|
||||
|
||||
state LIVE:
|
||||
send PTestSelfManage goto DEAD;
|
||||
|
||||
state DEAD:
|
||||
send __delete__;
|
||||
};
|
||||
|
||||
|
||||
} // namespace mozilla
|
||||
} // namespace _ipdltest
|
||||
22
ipc/ipdl/test/cxx/PTestShmem.ipdl
Normal file
22
ipc/ipdl/test/cxx/PTestShmem.ipdl
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
namespace mozilla {
|
||||
namespace _ipdltest {
|
||||
|
||||
protocol PTestShmem {
|
||||
child:
|
||||
async Give(Shmem mem, Shmem unsafe, size_t expectedSize);
|
||||
|
||||
parent:
|
||||
async Take(Shmem mem, Shmem unsafe, size_t expectedSize);
|
||||
async __delete__();
|
||||
|
||||
|
||||
state GIVING:
|
||||
send Give goto TAKING;
|
||||
|
||||
state TAKING:
|
||||
recv Take goto TAKING;
|
||||
recv __delete__;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
37
ipc/ipdl/test/cxx/PTestShutdown.ipdl
Normal file
37
ipc/ipdl/test/cxx/PTestShutdown.ipdl
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
include protocol PTestShutdownSub;
|
||||
|
||||
namespace mozilla {
|
||||
namespace _ipdltest {
|
||||
|
||||
intr protocol PTestShutdown {
|
||||
manages PTestShutdownSub;
|
||||
|
||||
child:
|
||||
async Start();
|
||||
|
||||
parent:
|
||||
// NB: we test deletion and crashing only, not shutdown, because
|
||||
// crashing is the same code path as shutdown, and other IPDL unit
|
||||
// tests check shutdown semantics
|
||||
async PTestShutdownSub(bool expectCrash);
|
||||
|
||||
// Used to synchronize between parent and child, to avoid races
|
||||
// around flushing socket write queues
|
||||
sync Sync();
|
||||
|
||||
async __delete__();
|
||||
|
||||
|
||||
state START:
|
||||
send Start goto TESTING;
|
||||
|
||||
state TESTING:
|
||||
recv PTestShutdownSub goto TESTING;
|
||||
recv Sync goto DYING;
|
||||
|
||||
state DYING:
|
||||
recv __delete__;
|
||||
};
|
||||
|
||||
} // namespace _ipdltest
|
||||
} // namespace mozilla
|
||||
30
ipc/ipdl/test/cxx/PTestShutdownSub.ipdl
Normal file
30
ipc/ipdl/test/cxx/PTestShutdownSub.ipdl
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
include protocol PTestShutdown;
|
||||
include protocol PTestShutdownSubsub;
|
||||
|
||||
namespace mozilla {
|
||||
namespace _ipdltest {
|
||||
|
||||
intr protocol PTestShutdownSub {
|
||||
manager PTestShutdown;
|
||||
manages PTestShutdownSubsub;
|
||||
|
||||
both:
|
||||
intr StackFrame();
|
||||
|
||||
parent:
|
||||
async PTestShutdownSubsub(bool expectParentDeleted);
|
||||
sync __delete__();
|
||||
|
||||
state CREATING:
|
||||
recv PTestShutdownSubsub goto CREATING;
|
||||
answer StackFrame goto DUMMYFRAME;
|
||||
|
||||
state DUMMYFRAME:
|
||||
call StackFrame goto DEAD;
|
||||
|
||||
state DEAD:
|
||||
recv __delete__;
|
||||
};
|
||||
|
||||
} // namespace _ipdltest
|
||||
} // namespace mozilla
|
||||
17
ipc/ipdl/test/cxx/PTestShutdownSubsub.ipdl
Normal file
17
ipc/ipdl/test/cxx/PTestShutdownSubsub.ipdl
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
include protocol PTestShutdownSub;
|
||||
|
||||
namespace mozilla {
|
||||
namespace _ipdltest {
|
||||
|
||||
sync protocol PTestShutdownSubsub {
|
||||
manager PTestShutdownSub;
|
||||
|
||||
parent:
|
||||
sync __delete__();
|
||||
|
||||
state LIVE:
|
||||
recv __delete__;
|
||||
};
|
||||
|
||||
} // namespace _ipdltest
|
||||
} // namespace mozilla
|
||||
56
ipc/ipdl/test/cxx/PTestStackHooks.ipdl
Normal file
56
ipc/ipdl/test/cxx/PTestStackHooks.ipdl
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
|
||||
namespace mozilla {
|
||||
namespace _ipdltest {
|
||||
|
||||
|
||||
intr protocol PTestStackHooks {
|
||||
child:
|
||||
async Start();
|
||||
|
||||
// These tests are more fruitful running child->parent, because
|
||||
// children can send |sync| messages
|
||||
parent:
|
||||
async Async();
|
||||
sync Sync();
|
||||
intr Rpc();
|
||||
|
||||
both:
|
||||
intr StackFrame();
|
||||
|
||||
parent:
|
||||
async __delete__();
|
||||
|
||||
|
||||
state START:
|
||||
send Start goto TEST1;
|
||||
|
||||
state TEST1:
|
||||
recv Async goto TEST2;
|
||||
|
||||
state TEST2:
|
||||
recv Sync goto TEST3;
|
||||
|
||||
state TEST3:
|
||||
answer Rpc goto TEST4;
|
||||
|
||||
state TEST4:
|
||||
answer StackFrame goto TEST4_2;
|
||||
state TEST4_2:
|
||||
call StackFrame goto TEST4_3;
|
||||
state TEST4_3:
|
||||
recv Async goto TEST5;
|
||||
|
||||
state TEST5:
|
||||
answer StackFrame goto TEST5_2;
|
||||
state TEST5_2:
|
||||
call StackFrame goto TEST5_3;
|
||||
state TEST5_3:
|
||||
recv Sync goto DEAD;
|
||||
|
||||
state DEAD:
|
||||
recv __delete__;
|
||||
};
|
||||
|
||||
|
||||
} // namespace mozilla
|
||||
} // namespace _ipdltest
|
||||
28
ipc/ipdl/test/cxx/PTestSyncError.ipdl
Normal file
28
ipc/ipdl/test/cxx/PTestSyncError.ipdl
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
|
||||
namespace mozilla {
|
||||
namespace _ipdltest {
|
||||
|
||||
|
||||
sync protocol PTestSyncError {
|
||||
|
||||
child:
|
||||
async Start();
|
||||
|
||||
parent:
|
||||
sync Error();
|
||||
async __delete__();
|
||||
|
||||
|
||||
state START:
|
||||
send Start goto SYNC_ERROR;
|
||||
|
||||
state SYNC_ERROR:
|
||||
recv Error goto DEAD;
|
||||
|
||||
state DEAD:
|
||||
recv __delete__;
|
||||
};
|
||||
|
||||
|
||||
} // namespace mozilla
|
||||
} // namespace _ipdltest
|
||||
15
ipc/ipdl/test/cxx/PTestSyncHang.ipdl
Normal file
15
ipc/ipdl/test/cxx/PTestSyncHang.ipdl
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
|
||||
namespace mozilla {
|
||||
namespace _ipdltest {
|
||||
|
||||
|
||||
protocol PTestSyncHang {
|
||||
|
||||
child:
|
||||
async __delete__();
|
||||
|
||||
};
|
||||
|
||||
|
||||
} // namespace mozilla
|
||||
} // namespace _ipdltest
|
||||
41
ipc/ipdl/test/cxx/PTestSyncWakeup.ipdl
Normal file
41
ipc/ipdl/test/cxx/PTestSyncWakeup.ipdl
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
namespace mozilla {
|
||||
namespace _ipdltest {
|
||||
|
||||
intr protocol PTestSyncWakeup {
|
||||
both:
|
||||
intr StackFrame();
|
||||
|
||||
child:
|
||||
async Start();
|
||||
async Note1();
|
||||
async Note2();
|
||||
|
||||
parent:
|
||||
sync Sync1();
|
||||
sync Sync2();
|
||||
async __delete__();
|
||||
|
||||
|
||||
state START:
|
||||
send Start goto TEST1;
|
||||
|
||||
state TEST1:
|
||||
recv Sync1 goto TEST1_P2;
|
||||
state TEST1_P2:
|
||||
send Note1 goto TEST2;
|
||||
|
||||
state TEST2:
|
||||
answer StackFrame goto TEST2_P2;
|
||||
state TEST2_P2:
|
||||
call StackFrame goto TEST2_P3;
|
||||
state TEST2_P3:
|
||||
recv Sync2 goto TEST2_P4;
|
||||
state TEST2_P4:
|
||||
send Note2 goto DONE;
|
||||
|
||||
state DONE:
|
||||
recv __delete__;
|
||||
};
|
||||
|
||||
} // namespace _ipdltest
|
||||
} // namespace mozilla
|
||||
19
ipc/ipdl/test/cxx/PTestUrgency.ipdl
Normal file
19
ipc/ipdl/test/cxx/PTestUrgency.ipdl
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
namespace mozilla {
|
||||
namespace _ipdltest {
|
||||
|
||||
nested(upto inside_cpow) sync protocol PTestUrgency
|
||||
{
|
||||
parent:
|
||||
nested(inside_sync) sync Test1() returns (uint32_t result);
|
||||
async Test2();
|
||||
sync Test3() returns (uint32_t result);
|
||||
sync FinalTest_Begin();
|
||||
|
||||
child:
|
||||
async Start();
|
||||
nested(inside_sync) sync Reply1() returns (uint32_t result);
|
||||
nested(inside_sync) sync Reply2() returns (uint32_t result);
|
||||
};
|
||||
|
||||
} // namespace _ipdltest
|
||||
} // namespace mozilla
|
||||
28
ipc/ipdl/test/cxx/PTestUrgentHangs.ipdl
Normal file
28
ipc/ipdl/test/cxx/PTestUrgentHangs.ipdl
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
namespace mozilla {
|
||||
namespace _ipdltest {
|
||||
|
||||
nested(upto inside_cpow) sync protocol PTestUrgentHangs
|
||||
{
|
||||
parent:
|
||||
nested(inside_sync) sync Test1_2();
|
||||
|
||||
nested(inside_sync) sync TestInner();
|
||||
nested(inside_cpow) sync TestInnerUrgent();
|
||||
|
||||
child:
|
||||
nested(inside_sync) sync Test1_1();
|
||||
nested(inside_sync) sync Test1_3();
|
||||
|
||||
nested(inside_sync) sync Test2();
|
||||
|
||||
nested(inside_sync) sync Test3();
|
||||
|
||||
async Test4();
|
||||
nested(inside_sync) sync Test4_1();
|
||||
|
||||
async Test5();
|
||||
nested(inside_sync) sync Test5_1();
|
||||
};
|
||||
|
||||
} // namespace _ipdltest
|
||||
} // namespace mozilla
|
||||
61
ipc/ipdl/test/cxx/README.txt
Normal file
61
ipc/ipdl/test/cxx/README.txt
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
To add a new IPDL C++ unit test, you need to create (at least) the
|
||||
following files (for a test "TestFoo"):
|
||||
|
||||
- PTestFoo.ipdl, specifying the top-level protocol used for the test
|
||||
|
||||
- TestFoo.h, declaring the top-level parent/child actors used for
|
||||
the test
|
||||
|
||||
- TestFoo.cpp, defining the top-level actors
|
||||
|
||||
- (make sure all are in the namespace mozilla::_ipdltest)
|
||||
|
||||
Next
|
||||
|
||||
- add PTestFoo.ipdl to ipdl.mk
|
||||
|
||||
- append TestFoo to the variable IPDLTESTS in Makefile.in
|
||||
|
||||
You must define three methods in your |TestFooParent| class:
|
||||
|
||||
- static methods |bool RunTestInProcesses()| and
|
||||
|bool RunTestInThreads()|. These methods control whether
|
||||
to execute the test using actors in separate processes and
|
||||
threads respectively. Generally, both should return true.
|
||||
|
||||
- an instance method |void Main()|. The test harness wil first
|
||||
initialize the processes or threads, create and open both actors,
|
||||
and then kick off the test using |Main()|. Make sure you define
|
||||
it.
|
||||
|
||||
If your test passes its criteria, please call
|
||||
|MOZ_IPDL_TESTPASS("msg")| and "exit gracefully".
|
||||
|
||||
If your tests fails, please call |MOZ_IPDL_TESTFAIL("msg")| and "exit
|
||||
ungracefully", preferably by abort()ing.
|
||||
|
||||
|
||||
If all goes well, running
|
||||
|
||||
make -C $OBJDIR/ipc/ipdl/test/cxx
|
||||
|
||||
will update the file IPDLUnitTests.cpp (the test launcher), and your
|
||||
new code will be built automatically.
|
||||
|
||||
|
||||
You can launch your new test by invoking one of
|
||||
|
||||
make -C $OBJDIR/ipc/ipdl/test/cxx check-proc (test process-based tests)
|
||||
make -C $OBJDIR/ipc/ipdl/test/cxx check-threads (test thread-based tests)
|
||||
make -C $OBJDIR/ipc/ipdl/test/cxx check (tests both)
|
||||
|
||||
If you want to launch only your test, run
|
||||
|
||||
cd $OBJDIR/dist/bin
|
||||
./run-mozilla.sh ./ipdlunittest TestFoo (test in two processes, if appl.)
|
||||
./run-mozilla.sh ./ipdlunittest thread:TestFoo (test in two threads, if appl.)
|
||||
|
||||
|
||||
For a bare-bones example of adding a test, take a look at
|
||||
PTestSanity.ipdl, TestSanity.h, TestSanity.cpp, and how "TestSanity"
|
||||
is included in ipdl.mk and Makefile.in.
|
||||
128
ipc/ipdl/test/cxx/TestActorPunning.cpp
Normal file
128
ipc/ipdl/test/cxx/TestActorPunning.cpp
Normal file
|
|
@ -0,0 +1,128 @@
|
|||
#include "TestActorPunning.h"
|
||||
|
||||
#include "IPDLUnitTests.h" // fail etc.
|
||||
#include "mozilla/Unused.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace _ipdltest {
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// parent
|
||||
|
||||
void
|
||||
TestActorPunningParent::Main()
|
||||
{
|
||||
if (!SendStart())
|
||||
fail("sending Start");
|
||||
}
|
||||
|
||||
bool
|
||||
TestActorPunningParent::RecvPun(PTestActorPunningSubParent* a, const Bad& bad)
|
||||
{
|
||||
if (a->SendBad())
|
||||
fail("bad!");
|
||||
fail("shouldn't have received this message in the first place");
|
||||
return true;
|
||||
}
|
||||
|
||||
PTestActorPunningPunnedParent*
|
||||
TestActorPunningParent::AllocPTestActorPunningPunnedParent()
|
||||
{
|
||||
return new TestActorPunningPunnedParent();
|
||||
}
|
||||
|
||||
bool
|
||||
TestActorPunningParent::DeallocPTestActorPunningPunnedParent(PTestActorPunningPunnedParent* a)
|
||||
{
|
||||
delete a;
|
||||
return true;
|
||||
}
|
||||
|
||||
PTestActorPunningSubParent*
|
||||
TestActorPunningParent::AllocPTestActorPunningSubParent()
|
||||
{
|
||||
return new TestActorPunningSubParent();
|
||||
}
|
||||
|
||||
bool
|
||||
TestActorPunningParent::DeallocPTestActorPunningSubParent(PTestActorPunningSubParent* a)
|
||||
{
|
||||
delete a;
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// child
|
||||
|
||||
PTestActorPunningPunnedChild*
|
||||
TestActorPunningChild::AllocPTestActorPunningPunnedChild()
|
||||
{
|
||||
return new TestActorPunningPunnedChild();
|
||||
}
|
||||
|
||||
bool
|
||||
TestActorPunningChild::DeallocPTestActorPunningPunnedChild(PTestActorPunningPunnedChild*)
|
||||
{
|
||||
fail("should have died by now");
|
||||
return true;
|
||||
}
|
||||
|
||||
PTestActorPunningSubChild*
|
||||
TestActorPunningChild::AllocPTestActorPunningSubChild()
|
||||
{
|
||||
return new TestActorPunningSubChild();
|
||||
}
|
||||
|
||||
bool
|
||||
TestActorPunningChild::DeallocPTestActorPunningSubChild(PTestActorPunningSubChild*)
|
||||
{
|
||||
fail("should have died by now");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
TestActorPunningChild::RecvStart()
|
||||
{
|
||||
SendPTestActorPunningSubConstructor();
|
||||
SendPTestActorPunningPunnedConstructor();
|
||||
PTestActorPunningSubChild* a = SendPTestActorPunningSubConstructor();
|
||||
// We can't assert whether this succeeds or fails, due to race
|
||||
// conditions.
|
||||
SendPun(a, Bad());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
TestActorPunningSubChild::RecvBad()
|
||||
{
|
||||
fail("things are going really badly right now");
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
} // namespace _ipdltest
|
||||
} // namespace mozilla
|
||||
|
||||
namespace IPC {
|
||||
using namespace mozilla::_ipdltest;
|
||||
using namespace mozilla::ipc;
|
||||
|
||||
/*static*/ void
|
||||
ParamTraits<Bad>::Write(Message* aMsg, const paramType& aParam)
|
||||
{
|
||||
// Skip past the sentinel for the actor as well as the actor.
|
||||
int32_t* ptr = aMsg->GetInt32PtrForTest(2 * sizeof(int32_t));
|
||||
ActorHandle* ah = reinterpret_cast<ActorHandle*>(ptr);
|
||||
if (ah->mId != -3)
|
||||
fail("guessed wrong offset (value is %d, should be -3)", ah->mId);
|
||||
ah->mId = -2;
|
||||
}
|
||||
|
||||
/*static*/ bool
|
||||
ParamTraits<Bad>::Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace IPC
|
||||
|
||||
110
ipc/ipdl/test/cxx/TestActorPunning.h
Normal file
110
ipc/ipdl/test/cxx/TestActorPunning.h
Normal file
|
|
@ -0,0 +1,110 @@
|
|||
#ifndef mozilla__ipdltest_TestActorPunning_h
|
||||
#define mozilla__ipdltest_TestActorPunning_h 1
|
||||
|
||||
#include "mozilla/_ipdltest/IPDLUnitTests.h"
|
||||
|
||||
#include "mozilla/_ipdltest/PTestActorPunningParent.h"
|
||||
#include "mozilla/_ipdltest/PTestActorPunningPunnedParent.h"
|
||||
#include "mozilla/_ipdltest/PTestActorPunningSubParent.h"
|
||||
#include "mozilla/_ipdltest/PTestActorPunningChild.h"
|
||||
#include "mozilla/_ipdltest/PTestActorPunningPunnedChild.h"
|
||||
#include "mozilla/_ipdltest/PTestActorPunningSubChild.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace _ipdltest {
|
||||
|
||||
|
||||
class TestActorPunningParent :
|
||||
public PTestActorPunningParent
|
||||
{
|
||||
public:
|
||||
static bool RunTestInProcesses() { return true; }
|
||||
static bool RunTestInThreads() { return false; }
|
||||
|
||||
void Main();
|
||||
|
||||
protected:
|
||||
PTestActorPunningPunnedParent* AllocPTestActorPunningPunnedParent() override;
|
||||
bool DeallocPTestActorPunningPunnedParent(PTestActorPunningPunnedParent* a) override;
|
||||
|
||||
PTestActorPunningSubParent* AllocPTestActorPunningSubParent() override;
|
||||
bool DeallocPTestActorPunningSubParent(PTestActorPunningSubParent* a) override;
|
||||
|
||||
virtual bool RecvPun(PTestActorPunningSubParent* a, const Bad& bad) override;
|
||||
|
||||
virtual void ActorDestroy(ActorDestroyReason why) override
|
||||
{
|
||||
if (NormalShutdown == why)
|
||||
fail("should have died from error!");
|
||||
passed("ok");
|
||||
QuitParent();
|
||||
}
|
||||
};
|
||||
|
||||
class TestActorPunningPunnedParent :
|
||||
public PTestActorPunningPunnedParent
|
||||
{
|
||||
public:
|
||||
TestActorPunningPunnedParent() {}
|
||||
virtual ~TestActorPunningPunnedParent() {}
|
||||
protected:
|
||||
virtual void ActorDestroy(ActorDestroyReason why) override {}
|
||||
};
|
||||
|
||||
class TestActorPunningSubParent :
|
||||
public PTestActorPunningSubParent
|
||||
{
|
||||
public:
|
||||
TestActorPunningSubParent() {}
|
||||
virtual ~TestActorPunningSubParent() {}
|
||||
protected:
|
||||
virtual void ActorDestroy(ActorDestroyReason why) override {}
|
||||
};
|
||||
|
||||
|
||||
class TestActorPunningChild :
|
||||
public PTestActorPunningChild
|
||||
{
|
||||
public:
|
||||
TestActorPunningChild() {}
|
||||
virtual ~TestActorPunningChild() {}
|
||||
|
||||
protected:
|
||||
PTestActorPunningPunnedChild* AllocPTestActorPunningPunnedChild() override;
|
||||
bool DeallocPTestActorPunningPunnedChild(PTestActorPunningPunnedChild* a) override;
|
||||
|
||||
PTestActorPunningSubChild* AllocPTestActorPunningSubChild() override;
|
||||
bool DeallocPTestActorPunningSubChild(PTestActorPunningSubChild* a) override;
|
||||
|
||||
virtual bool RecvStart() override;
|
||||
|
||||
virtual void ActorDestroy(ActorDestroyReason why) override
|
||||
{
|
||||
fail("should have been killed off!");
|
||||
}
|
||||
};
|
||||
|
||||
class TestActorPunningPunnedChild :
|
||||
public PTestActorPunningPunnedChild
|
||||
{
|
||||
public:
|
||||
TestActorPunningPunnedChild() {}
|
||||
virtual ~TestActorPunningPunnedChild() {}
|
||||
};
|
||||
|
||||
class TestActorPunningSubChild :
|
||||
public PTestActorPunningSubChild
|
||||
{
|
||||
public:
|
||||
TestActorPunningSubChild() {}
|
||||
virtual ~TestActorPunningSubChild() {}
|
||||
|
||||
virtual bool RecvBad() override;
|
||||
};
|
||||
|
||||
|
||||
} // namespace _ipdltest
|
||||
} // namespace mozilla
|
||||
|
||||
|
||||
#endif // ifndef mozilla__ipdltest_TestActorPunning_h
|
||||
51
ipc/ipdl/test/cxx/TestBadActor.cpp
Normal file
51
ipc/ipdl/test/cxx/TestBadActor.cpp
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
#include "TestBadActor.h"
|
||||
#include "IPDLUnitTests.h"
|
||||
#include "mozilla/Unused.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace _ipdltest {
|
||||
|
||||
void
|
||||
TestBadActorParent::Main()
|
||||
{
|
||||
// This test is designed to test a race condition where the child sends us
|
||||
// a message on an actor that we've already destroyed. The child process
|
||||
// should die, and the parent process should not abort.
|
||||
|
||||
PTestBadActorSubParent* child = SendPTestBadActorSubConstructor();
|
||||
if (!child)
|
||||
fail("Sending constructor");
|
||||
|
||||
Unused << child->Call__delete__(child);
|
||||
}
|
||||
|
||||
PTestBadActorSubParent*
|
||||
TestBadActorParent::AllocPTestBadActorSubParent()
|
||||
{
|
||||
return new TestBadActorSubParent();
|
||||
}
|
||||
|
||||
bool
|
||||
TestBadActorSubParent::RecvPing()
|
||||
{
|
||||
fail("Shouldn't have received ping.");
|
||||
return false;
|
||||
}
|
||||
|
||||
PTestBadActorSubChild*
|
||||
TestBadActorChild::AllocPTestBadActorSubChild()
|
||||
{
|
||||
return new TestBadActorSubChild();
|
||||
}
|
||||
|
||||
bool
|
||||
TestBadActorChild::RecvPTestBadActorSubConstructor(PTestBadActorSubChild* actor)
|
||||
{
|
||||
if (!actor->SendPing()) {
|
||||
fail("Couldn't send ping to an actor which supposedly isn't dead yet.");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace _ipdltest
|
||||
} // namespace mozilla
|
||||
91
ipc/ipdl/test/cxx/TestBadActor.h
Normal file
91
ipc/ipdl/test/cxx/TestBadActor.h
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
#ifndef mozilla__ipdltest_TestBadActor_h
|
||||
#define mozilla__ipdltest_TestBadActor_h
|
||||
|
||||
#include "mozilla/_ipdltest/IPDLUnitTests.h"
|
||||
|
||||
#include "mozilla/_ipdltest/PTestBadActorParent.h"
|
||||
#include "mozilla/_ipdltest/PTestBadActorChild.h"
|
||||
|
||||
#include "mozilla/_ipdltest/PTestBadActorSubParent.h"
|
||||
#include "mozilla/_ipdltest/PTestBadActorSubChild.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace _ipdltest {
|
||||
|
||||
class TestBadActorParent
|
||||
: public PTestBadActorParent
|
||||
{
|
||||
public:
|
||||
TestBadActorParent() { }
|
||||
virtual ~TestBadActorParent() { }
|
||||
|
||||
static bool RunTestInProcesses() { return true; }
|
||||
static bool RunTestInThreads() { return false; }
|
||||
|
||||
void Main();
|
||||
|
||||
protected:
|
||||
virtual void ActorDestroy(ActorDestroyReason why) override
|
||||
{
|
||||
if (AbnormalShutdown != why)
|
||||
fail("unexpected destruction");
|
||||
passed("ok");
|
||||
QuitParent();
|
||||
}
|
||||
|
||||
virtual PTestBadActorSubParent*
|
||||
AllocPTestBadActorSubParent();
|
||||
|
||||
virtual bool
|
||||
DeallocPTestBadActorSubParent(PTestBadActorSubParent* actor) {
|
||||
delete actor;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
class TestBadActorSubParent
|
||||
: public PTestBadActorSubParent
|
||||
{
|
||||
public:
|
||||
TestBadActorSubParent() { }
|
||||
virtual ~TestBadActorSubParent() { }
|
||||
|
||||
protected:
|
||||
virtual void ActorDestroy(ActorDestroyReason why) override {}
|
||||
virtual bool RecvPing();
|
||||
};
|
||||
|
||||
class TestBadActorChild
|
||||
: public PTestBadActorChild
|
||||
{
|
||||
public:
|
||||
TestBadActorChild() { }
|
||||
virtual ~TestBadActorChild() { }
|
||||
|
||||
protected:
|
||||
virtual PTestBadActorSubChild*
|
||||
AllocPTestBadActorSubChild();
|
||||
|
||||
virtual bool
|
||||
DeallocPTestBadActorSubChild(PTestBadActorSubChild* actor)
|
||||
{
|
||||
delete actor;
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual bool
|
||||
RecvPTestBadActorSubConstructor(PTestBadActorSubChild* actor);
|
||||
};
|
||||
|
||||
class TestBadActorSubChild
|
||||
: public PTestBadActorSubChild
|
||||
{
|
||||
public:
|
||||
TestBadActorSubChild() { }
|
||||
virtual ~TestBadActorSubChild() { }
|
||||
};
|
||||
|
||||
} // namespace _ipdltest
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla__ipdltest_TestBadActor_h
|
||||
227
ipc/ipdl/test/cxx/TestBridgeMain.cpp
Normal file
227
ipc/ipdl/test/cxx/TestBridgeMain.cpp
Normal file
|
|
@ -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
|
||||
149
ipc/ipdl/test/cxx/TestBridgeMain.h
Normal file
149
ipc/ipdl/test/cxx/TestBridgeMain.h
Normal file
|
|
@ -0,0 +1,149 @@
|
|||
#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() {}
|
||||
|
||||
static bool RunTestInProcesses() { return true; }
|
||||
static bool RunTestInThreads() { return false; }
|
||||
|
||||
void Main();
|
||||
|
||||
protected:
|
||||
virtual PTestBridgeMainSubParent*
|
||||
AllocPTestBridgeMainSubParent(Transport* transport,
|
||||
ProcessId otherProcess) override;
|
||||
|
||||
virtual void ActorDestroy(ActorDestroyReason why) override;
|
||||
};
|
||||
|
||||
class TestBridgeMainSubParent :
|
||||
public PTestBridgeMainSubParent
|
||||
{
|
||||
public:
|
||||
explicit TestBridgeMainSubParent(Transport* aTransport)
|
||||
: mTransport(aTransport)
|
||||
{}
|
||||
virtual ~TestBridgeMainSubParent() {}
|
||||
|
||||
protected:
|
||||
virtual bool RecvHello() override;
|
||||
virtual bool RecvHelloSync() override;
|
||||
virtual bool AnswerHelloRpc() override;
|
||||
|
||||
virtual void ActorDestroy(ActorDestroyReason why) override;
|
||||
|
||||
Transport* mTransport;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// "Sub" process --- child of "main"
|
||||
//
|
||||
class TestBridgeSubParent;
|
||||
|
||||
class TestBridgeMainChild :
|
||||
public PTestBridgeMainChild
|
||||
{
|
||||
public:
|
||||
TestBridgeMainChild();
|
||||
virtual ~TestBridgeMainChild() {}
|
||||
|
||||
protected:
|
||||
virtual bool RecvStart() override;
|
||||
|
||||
virtual PTestBridgeMainSubChild*
|
||||
AllocPTestBridgeMainSubChild(Transport* transport,
|
||||
ProcessId otherProcess) override
|
||||
{
|
||||
// This shouldn't be called. It's just a byproduct of testing that
|
||||
// the right code is generated for a bridged protocol that's also
|
||||
// opened, but we only test bridging here.
|
||||
MOZ_CRASH();
|
||||
}
|
||||
|
||||
virtual void ActorDestroy(ActorDestroyReason why) override;
|
||||
|
||||
IPDLUnitTestSubprocess* mSubprocess;
|
||||
};
|
||||
|
||||
class TestBridgeSubParent :
|
||||
public PTestBridgeSubParent
|
||||
{
|
||||
public:
|
||||
TestBridgeSubParent() {}
|
||||
virtual ~TestBridgeSubParent() {}
|
||||
|
||||
void Main();
|
||||
|
||||
protected:
|
||||
virtual bool RecvBridgeEm() override;
|
||||
|
||||
virtual void ActorDestroy(ActorDestroyReason why) override;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// "Subsub" process --- child of "sub"
|
||||
//
|
||||
class TestBridgeSubChild :
|
||||
public PTestBridgeSubChild
|
||||
{
|
||||
public:
|
||||
TestBridgeSubChild();
|
||||
virtual ~TestBridgeSubChild() {}
|
||||
|
||||
protected:
|
||||
virtual bool RecvPing() override;
|
||||
|
||||
virtual PTestBridgeMainSubChild*
|
||||
AllocPTestBridgeMainSubChild(Transport* transport,
|
||||
ProcessId otherProcess) override;
|
||||
|
||||
virtual void ActorDestroy(ActorDestroyReason why) override;
|
||||
};
|
||||
|
||||
class TestBridgeMainSubChild :
|
||||
public PTestBridgeMainSubChild
|
||||
{
|
||||
public:
|
||||
explicit TestBridgeMainSubChild(Transport* aTransport)
|
||||
: mGotHi(false)
|
||||
, mTransport(aTransport)
|
||||
{}
|
||||
virtual ~TestBridgeMainSubChild() {}
|
||||
|
||||
protected:
|
||||
virtual bool RecvHi() override;
|
||||
virtual bool AnswerHiRpc() override;
|
||||
|
||||
virtual void ActorDestroy(ActorDestroyReason why) override;
|
||||
|
||||
bool mGotHi;
|
||||
Transport* mTransport;
|
||||
};
|
||||
|
||||
} // namespace _ipdltest
|
||||
} // namespace mozilla
|
||||
|
||||
|
||||
#endif // ifndef mozilla__ipdltest_TestBridgeMain_h
|
||||
168
ipc/ipdl/test/cxx/TestCancel.cpp
Normal file
168
ipc/ipdl/test/cxx/TestCancel.cpp
Normal file
|
|
@ -0,0 +1,168 @@
|
|||
#include "TestCancel.h"
|
||||
|
||||
#include "IPDLUnitTests.h" // fail etc.
|
||||
|
||||
namespace mozilla {
|
||||
namespace _ipdltest {
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// parent
|
||||
|
||||
TestCancelParent::TestCancelParent()
|
||||
{
|
||||
MOZ_COUNT_CTOR(TestCancelParent);
|
||||
}
|
||||
|
||||
TestCancelParent::~TestCancelParent()
|
||||
{
|
||||
MOZ_COUNT_DTOR(TestCancelParent);
|
||||
}
|
||||
|
||||
void
|
||||
TestCancelParent::Main()
|
||||
{
|
||||
if (SendTest1_1())
|
||||
fail("sending Test1_1");
|
||||
|
||||
uint32_t value = 0;
|
||||
if (!SendCheckChild(&value))
|
||||
fail("Test1 CheckChild");
|
||||
|
||||
if (value != 12)
|
||||
fail("Test1 CheckChild reply");
|
||||
}
|
||||
|
||||
bool
|
||||
TestCancelParent::RecvDone1()
|
||||
{
|
||||
if (!SendStart2())
|
||||
fail("sending Start2");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
TestCancelParent::RecvTest2_1()
|
||||
{
|
||||
if (SendTest2_2())
|
||||
fail("sending Test2_2");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
TestCancelParent::RecvStart3()
|
||||
{
|
||||
if (SendTest3_1())
|
||||
fail("sending Test3_1");
|
||||
|
||||
uint32_t value = 0;
|
||||
if (!SendCheckChild(&value))
|
||||
fail("Test1 CheckChild");
|
||||
|
||||
if (value != 12)
|
||||
fail("Test1 CheckChild reply");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
TestCancelParent::RecvTest3_2()
|
||||
{
|
||||
GetIPCChannel()->CancelCurrentTransaction();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
TestCancelParent::RecvDone()
|
||||
{
|
||||
MessageLoop::current()->PostTask(
|
||||
NewNonOwningRunnableMethod(this, &TestCancelParent::Close));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
TestCancelParent::RecvCheckParent(uint32_t *reply)
|
||||
{
|
||||
*reply = 12;
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// child
|
||||
|
||||
bool
|
||||
TestCancelChild::RecvTest1_1()
|
||||
{
|
||||
GetIPCChannel()->CancelCurrentTransaction();
|
||||
|
||||
uint32_t value = 0;
|
||||
if (!SendCheckParent(&value))
|
||||
fail("Test1 CheckParent");
|
||||
|
||||
if (value != 12)
|
||||
fail("Test1 CheckParent reply");
|
||||
|
||||
if (!SendDone1())
|
||||
fail("Test1 CheckParent");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
TestCancelChild::RecvStart2()
|
||||
{
|
||||
if (!SendTest2_1())
|
||||
fail("sending Test2_1");
|
||||
|
||||
if (!SendStart3())
|
||||
fail("sending Start3");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
TestCancelChild::RecvTest2_2()
|
||||
{
|
||||
GetIPCChannel()->CancelCurrentTransaction();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
TestCancelChild::RecvTest3_1()
|
||||
{
|
||||
if (SendTest3_2())
|
||||
fail("sending Test3_2");
|
||||
|
||||
uint32_t value = 0;
|
||||
if (!SendCheckParent(&value))
|
||||
fail("Test1 CheckParent");
|
||||
|
||||
if (value != 12)
|
||||
fail("Test1 CheckParent reply");
|
||||
|
||||
if (!SendDone())
|
||||
fail("sending Done");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
TestCancelChild::RecvCheckChild(uint32_t *reply)
|
||||
{
|
||||
*reply = 12;
|
||||
return true;
|
||||
}
|
||||
|
||||
TestCancelChild::TestCancelChild()
|
||||
{
|
||||
MOZ_COUNT_CTOR(TestCancelChild);
|
||||
}
|
||||
|
||||
TestCancelChild::~TestCancelChild()
|
||||
{
|
||||
MOZ_COUNT_DTOR(TestCancelChild);
|
||||
}
|
||||
|
||||
} // namespace _ipdltest
|
||||
} // namespace mozilla
|
||||
66
ipc/ipdl/test/cxx/TestCancel.h
Normal file
66
ipc/ipdl/test/cxx/TestCancel.h
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
#ifndef mozilla__ipdltest_TestCancel_h
|
||||
#define mozilla__ipdltest_TestCancel_h 1
|
||||
|
||||
#include "mozilla/_ipdltest/IPDLUnitTests.h"
|
||||
|
||||
#include "mozilla/_ipdltest/PTestCancelParent.h"
|
||||
#include "mozilla/_ipdltest/PTestCancelChild.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace _ipdltest {
|
||||
|
||||
|
||||
class TestCancelParent :
|
||||
public PTestCancelParent
|
||||
{
|
||||
public:
|
||||
TestCancelParent();
|
||||
virtual ~TestCancelParent();
|
||||
|
||||
static bool RunTestInProcesses() { return true; }
|
||||
static bool RunTestInThreads() { return false; }
|
||||
|
||||
void Main();
|
||||
|
||||
virtual bool RecvDone1() override;
|
||||
virtual bool RecvTest2_1() override;
|
||||
virtual bool RecvStart3() override;
|
||||
virtual bool RecvTest3_2() override;
|
||||
virtual bool RecvDone() override;
|
||||
|
||||
virtual bool RecvCheckParent(uint32_t *reply) override;
|
||||
|
||||
virtual void ActorDestroy(ActorDestroyReason why) override
|
||||
{
|
||||
passed("ok");
|
||||
QuitParent();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class TestCancelChild :
|
||||
public PTestCancelChild
|
||||
{
|
||||
public:
|
||||
TestCancelChild();
|
||||
virtual ~TestCancelChild();
|
||||
|
||||
virtual bool RecvTest1_1() override;
|
||||
virtual bool RecvStart2() override;
|
||||
virtual bool RecvTest2_2() override;
|
||||
virtual bool RecvTest3_1() override;
|
||||
|
||||
virtual bool RecvCheckChild(uint32_t *reply) override;
|
||||
|
||||
virtual void ActorDestroy(ActorDestroyReason why) override
|
||||
{
|
||||
QuitChild();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
} // namespace _ipdltest
|
||||
} // namespace mozilla
|
||||
|
||||
|
||||
#endif // ifndef mozilla__ipdltest_TestCancel_h
|
||||
116
ipc/ipdl/test/cxx/TestCrashCleanup.cpp
Normal file
116
ipc/ipdl/test/cxx/TestCrashCleanup.cpp
Normal file
|
|
@ -0,0 +1,116 @@
|
|||
#include "TestCrashCleanup.h"
|
||||
|
||||
#include "base/task.h"
|
||||
#include "mozilla/CondVar.h"
|
||||
#include "mozilla/Mutex.h"
|
||||
|
||||
#include "IPDLUnitTests.h" // fail etc.
|
||||
#include "IPDLUnitTestSubprocess.h"
|
||||
|
||||
using mozilla::CondVar;
|
||||
using mozilla::Mutex;
|
||||
using mozilla::MutexAutoLock;
|
||||
|
||||
namespace mozilla {
|
||||
namespace _ipdltest {
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// parent
|
||||
|
||||
namespace {
|
||||
|
||||
// NB: this test does its own shutdown, rather than going through
|
||||
// QuitParent(), because it's testing degenerate edge cases
|
||||
|
||||
void DeleteSubprocess(Mutex* mutex, CondVar* cvar)
|
||||
{
|
||||
MutexAutoLock lock(*mutex);
|
||||
|
||||
delete gSubprocess;
|
||||
gSubprocess = nullptr;
|
||||
|
||||
cvar->Notify();
|
||||
}
|
||||
|
||||
void DeleteTheWorld()
|
||||
{
|
||||
delete static_cast<TestCrashCleanupParent*>(gParentActor);
|
||||
gParentActor = nullptr;
|
||||
|
||||
// needs to be synchronous to avoid affecting event ordering on
|
||||
// the main thread
|
||||
Mutex mutex("TestCrashCleanup.DeleteTheWorld.mutex");
|
||||
CondVar cvar(mutex, "TestCrashCleanup.DeleteTheWorld.cvar");
|
||||
|
||||
MutexAutoLock lock(mutex);
|
||||
|
||||
XRE_GetIOMessageLoop()->PostTask(
|
||||
NewRunnableFunction(DeleteSubprocess, &mutex, &cvar));
|
||||
|
||||
cvar.Wait();
|
||||
}
|
||||
|
||||
void Done()
|
||||
{
|
||||
static NS_DEFINE_CID(kAppShellCID, NS_APPSHELL_CID);
|
||||
nsCOMPtr<nsIAppShell> appShell (do_GetService(kAppShellCID));
|
||||
appShell->Exit();
|
||||
|
||||
passed(__FILE__);
|
||||
}
|
||||
|
||||
} // namespace <anon>
|
||||
|
||||
TestCrashCleanupParent::TestCrashCleanupParent() : mCleanedUp(false)
|
||||
{
|
||||
MOZ_COUNT_CTOR(TestCrashCleanupParent);
|
||||
}
|
||||
|
||||
TestCrashCleanupParent::~TestCrashCleanupParent()
|
||||
{
|
||||
MOZ_COUNT_DTOR(TestCrashCleanupParent);
|
||||
|
||||
if (!mCleanedUp)
|
||||
fail("should have been ActorDestroy()d!");
|
||||
}
|
||||
|
||||
void
|
||||
TestCrashCleanupParent::Main()
|
||||
{
|
||||
// NB: has to be enqueued before IO thread's error notification
|
||||
MessageLoop::current()->PostTask(
|
||||
NewRunnableFunction(DeleteTheWorld));
|
||||
|
||||
if (CallDIEDIEDIE())
|
||||
fail("expected an error!");
|
||||
|
||||
Close();
|
||||
|
||||
MessageLoop::current()->PostTask(NewRunnableFunction(Done));
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// child
|
||||
|
||||
TestCrashCleanupChild::TestCrashCleanupChild()
|
||||
{
|
||||
MOZ_COUNT_CTOR(TestCrashCleanupChild);
|
||||
}
|
||||
|
||||
TestCrashCleanupChild::~TestCrashCleanupChild()
|
||||
{
|
||||
MOZ_COUNT_DTOR(TestCrashCleanupChild);
|
||||
}
|
||||
|
||||
bool
|
||||
TestCrashCleanupChild::AnswerDIEDIEDIE()
|
||||
{
|
||||
_exit(0);
|
||||
NS_RUNTIMEABORT("unreached");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
} // namespace _ipdltest
|
||||
} // namespace mozilla
|
||||
58
ipc/ipdl/test/cxx/TestCrashCleanup.h
Normal file
58
ipc/ipdl/test/cxx/TestCrashCleanup.h
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
#ifndef mozilla__ipdltest_TestCrashCleanup_h
|
||||
#define mozilla__ipdltest_TestCrashCleanup_h 1
|
||||
|
||||
#include "mozilla/_ipdltest/IPDLUnitTests.h"
|
||||
|
||||
#include "mozilla/_ipdltest/PTestCrashCleanupParent.h"
|
||||
#include "mozilla/_ipdltest/PTestCrashCleanupChild.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace _ipdltest {
|
||||
|
||||
|
||||
class TestCrashCleanupParent :
|
||||
public PTestCrashCleanupParent
|
||||
{
|
||||
public:
|
||||
TestCrashCleanupParent();
|
||||
virtual ~TestCrashCleanupParent();
|
||||
|
||||
static bool RunTestInProcesses() { return true; }
|
||||
static bool RunTestInThreads() { return false; }
|
||||
|
||||
void Main();
|
||||
|
||||
protected:
|
||||
virtual void ActorDestroy(ActorDestroyReason why) override
|
||||
{
|
||||
if (AbnormalShutdown != why)
|
||||
fail("unexpected destruction!");
|
||||
mCleanedUp = true;
|
||||
}
|
||||
|
||||
bool mCleanedUp;
|
||||
};
|
||||
|
||||
|
||||
class TestCrashCleanupChild :
|
||||
public PTestCrashCleanupChild
|
||||
{
|
||||
public:
|
||||
TestCrashCleanupChild();
|
||||
virtual ~TestCrashCleanupChild();
|
||||
|
||||
protected:
|
||||
virtual bool AnswerDIEDIEDIE() override;
|
||||
|
||||
virtual void ActorDestroy(ActorDestroyReason why) override
|
||||
{
|
||||
fail("should have 'crashed'!");
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
} // namespace _ipdltest
|
||||
} // namespace mozilla
|
||||
|
||||
|
||||
#endif // ifndef mozilla__ipdltest_TestCrashCleanup_h
|
||||
984
ipc/ipdl/test/cxx/TestDataStructures.cpp
Normal file
984
ipc/ipdl/test/cxx/TestDataStructures.cpp
Normal file
|
|
@ -0,0 +1,984 @@
|
|||
#include "TestDataStructures.h"
|
||||
|
||||
#include "mozilla/Unused.h"
|
||||
|
||||
#include "IPDLUnitTests.h" // fail etc.
|
||||
|
||||
typedef InfallibleTArray<nsIntRegion> RegionArray;
|
||||
|
||||
namespace mozilla {
|
||||
namespace _ipdltest {
|
||||
|
||||
static const uint32_t nactors = 10;
|
||||
|
||||
#define test_assert(_cond, _msg) \
|
||||
if (!(_cond)) fail(_msg)
|
||||
|
||||
template<typename T>
|
||||
static void
|
||||
assert_arrays_equal(const InfallibleTArray<T>& a, const InfallibleTArray<T>& b)
|
||||
{
|
||||
test_assert(a == b, "arrays equal");
|
||||
}
|
||||
|
||||
inline static TestDataStructuresSub&
|
||||
Cast(PTestDataStructuresSubParent* a)
|
||||
{
|
||||
return *static_cast<TestDataStructuresSub*>(a);
|
||||
}
|
||||
|
||||
inline static TestDataStructuresSub&
|
||||
Cast(PTestDataStructuresSubChild* a)
|
||||
{
|
||||
return *static_cast<TestDataStructuresSub*>(a);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// parent
|
||||
|
||||
TestDataStructuresParent::TestDataStructuresParent()
|
||||
{
|
||||
MOZ_COUNT_CTOR(TestDataStructuresParent);
|
||||
}
|
||||
|
||||
TestDataStructuresParent::~TestDataStructuresParent()
|
||||
{
|
||||
MOZ_COUNT_DTOR(TestDataStructuresParent);
|
||||
}
|
||||
|
||||
void
|
||||
TestDataStructuresParent::Main()
|
||||
{
|
||||
for (uint32_t i = 0; i < nactors; ++i)
|
||||
if (!SendPTestDataStructuresSubConstructor(i))
|
||||
fail("can't alloc actor");
|
||||
|
||||
if (!SendStart())
|
||||
fail("can't send Start()");
|
||||
}
|
||||
|
||||
bool
|
||||
TestDataStructuresParent::DeallocPTestDataStructuresSubParent(PTestDataStructuresSubParent* actor)
|
||||
{
|
||||
test_assert(Cast(actor).mI == Cast(mKids[0]).mI,
|
||||
"dtor sent to wrong actor");
|
||||
mKids.RemoveElementAt(0);
|
||||
delete actor;
|
||||
if (mKids.Length() > 0)
|
||||
return true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TestDataStructuresParent::RecvTest1(
|
||||
InfallibleTArray<int>&& ia,
|
||||
InfallibleTArray<int>* oa)
|
||||
{
|
||||
test_assert(5 == ia.Length(), "wrong length");
|
||||
for (int i = 0; i < 5; ++i)
|
||||
test_assert(i == ia[i], "wrong value");
|
||||
|
||||
*oa = ia;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TestDataStructuresParent::RecvTest2(
|
||||
InfallibleTArray<PTestDataStructuresSubParent*>&& i1,
|
||||
InfallibleTArray<PTestDataStructuresSubParent*>* o1)
|
||||
{
|
||||
test_assert(nactors == i1.Length(), "wrong #actors");
|
||||
for (uint32_t i = 0; i < i1.Length(); ++i)
|
||||
test_assert(i == Cast(i1[i]).mI, "wrong mI value");
|
||||
*o1 = i1;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TestDataStructuresParent::RecvTest3(
|
||||
const IntDouble& i1,
|
||||
const IntDouble& i2,
|
||||
IntDouble* o1,
|
||||
IntDouble* o2)
|
||||
{
|
||||
test_assert(42 == i1.get_int(), "wrong value");
|
||||
test_assert(4.0 == i2.get_double(), "wrong value");
|
||||
|
||||
*o1 = i1;
|
||||
*o2 = i2;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TestDataStructuresParent::RecvTest4(
|
||||
InfallibleTArray<IntDouble>&& i1,
|
||||
InfallibleTArray<IntDouble>* o1)
|
||||
{
|
||||
test_assert(4 == i1.Length(), "wrong length");
|
||||
test_assert(1 == i1[0].get_int(), "wrong value");
|
||||
test_assert(2.0 == i1[1].get_double(), "wrong value");
|
||||
test_assert(3 == i1[2].get_int(), "wrong value");
|
||||
test_assert(4.0 == i1[3].get_double(), "wrong value");
|
||||
|
||||
*o1 = i1;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TestDataStructuresParent::RecvTest5(
|
||||
const IntDoubleArrays& i1,
|
||||
const IntDoubleArrays& i2,
|
||||
const IntDoubleArrays& i3,
|
||||
IntDoubleArrays* o1,
|
||||
IntDoubleArrays* o2,
|
||||
IntDoubleArrays* o3)
|
||||
{
|
||||
test_assert(42 == i1.get_int(), "wrong value");
|
||||
|
||||
const InfallibleTArray<int>& i2a = i2.get_ArrayOfint();
|
||||
test_assert(3 == i2a.Length(), "wrong length");
|
||||
test_assert(1 == i2a[0], "wrong value");
|
||||
test_assert(2 == i2a[1], "wrong value");
|
||||
test_assert(3 == i2a[2], "wrong value");
|
||||
|
||||
const InfallibleTArray<double>& i3a = i3.get_ArrayOfdouble();
|
||||
test_assert(3 == i3a.Length(), "wrong length");
|
||||
test_assert(1.0 == i3a[0], "wrong value");
|
||||
test_assert(2.0 == i3a[1], "wrong value");
|
||||
test_assert(3.0 == i3a[2], "wrong value");
|
||||
|
||||
*o1 = i1;
|
||||
*o2 = i2a;
|
||||
*o3 = i3a;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
TestDataStructuresParent::RecvTest7_0(const ActorWrapper& i1,
|
||||
ActorWrapper* o1)
|
||||
{
|
||||
if (i1.actorChild() != nullptr)
|
||||
fail("child side actor should always be null");
|
||||
|
||||
if (i1.actorParent() != mKids[0])
|
||||
fail("should have got back same actor on parent side");
|
||||
|
||||
o1->actorParent() = mKids[0];
|
||||
// malicious behavior
|
||||
o1->actorChild() =
|
||||
reinterpret_cast<PTestDataStructuresSubChild*>(uintptr_t(0xdeadbeef));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TestDataStructuresParent::RecvTest6(
|
||||
InfallibleTArray<IntDoubleArrays>&& i1,
|
||||
InfallibleTArray<IntDoubleArrays>* o1)
|
||||
{
|
||||
test_assert(3 == i1.Length(), "wrong length");
|
||||
|
||||
IntDoubleArrays id1(i1[0]);
|
||||
test_assert(42 == id1.get_int(), "wrong value");
|
||||
|
||||
InfallibleTArray<int> i2a(i1[1].get_ArrayOfint());
|
||||
test_assert(3 == i2a.Length(), "wrong length");
|
||||
test_assert(1 == i2a[0], "wrong value");
|
||||
test_assert(2 == i2a[1], "wrong value");
|
||||
test_assert(3 == i2a[2], "wrong value");
|
||||
|
||||
InfallibleTArray<double> i3a(i1[2].get_ArrayOfdouble());
|
||||
test_assert(3 == i3a.Length(), "wrong length");
|
||||
test_assert(1.0 == i3a[0], "wrong value");
|
||||
test_assert(2.0 == i3a[1], "wrong value");
|
||||
test_assert(3.0 == i3a[2], "wrong value");
|
||||
|
||||
o1->AppendElement(id1);
|
||||
o1->AppendElement(IntDoubleArrays(i2a));
|
||||
o1->AppendElement(IntDoubleArrays(i3a));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TestDataStructuresParent::RecvTest7(
|
||||
const Actors& i1,
|
||||
const Actors& i2,
|
||||
const Actors& i3,
|
||||
Actors* o1,
|
||||
Actors* o2,
|
||||
Actors* o3)
|
||||
{
|
||||
test_assert(42 == i1.get_int(), "wrong value");
|
||||
|
||||
InfallibleTArray<int> i2a(i2.get_ArrayOfint());
|
||||
test_assert(3 == i2a.Length(), "wrong length");
|
||||
test_assert(1 == i2a[0], "wrong value");
|
||||
test_assert(2 == i2a[1], "wrong value");
|
||||
test_assert(3 == i2a[2], "wrong value");
|
||||
|
||||
assert_arrays_equal(mKids, i3.get_ArrayOfPTestDataStructuresSubParent());
|
||||
|
||||
*o1 = 42;
|
||||
*o2 = i2a;
|
||||
*o3 = mKids;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TestDataStructuresParent::RecvTest8(
|
||||
InfallibleTArray<Actors>&& i1,
|
||||
InfallibleTArray<Actors>* o1)
|
||||
{
|
||||
test_assert(3 == i1.Length(), "wrong length");
|
||||
test_assert(42 == i1[0].get_int(), "wrong value");
|
||||
|
||||
const InfallibleTArray<int>& i2a = i1[1].get_ArrayOfint();
|
||||
test_assert(3 == i2a.Length(), "wrong length");
|
||||
test_assert(1 == i2a[0], "wrong value");
|
||||
test_assert(2 == i2a[1], "wrong value");
|
||||
test_assert(3 == i2a[2], "wrong value");
|
||||
|
||||
assert_arrays_equal(mKids, i1[2].get_ArrayOfPTestDataStructuresSubParent());
|
||||
|
||||
*o1 = i1;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TestDataStructuresParent::RecvTest9(
|
||||
const Unions& i1,
|
||||
const Unions& i2,
|
||||
const Unions& i3,
|
||||
const Unions& i4,
|
||||
Unions* o1,
|
||||
Unions* o2,
|
||||
Unions* o3,
|
||||
Unions* o4)
|
||||
{
|
||||
test_assert(42 == i1.get_int(), "wrong value");
|
||||
|
||||
const InfallibleTArray<int>& i2a = i2.get_ArrayOfint();
|
||||
test_assert(3 == i2a.Length(), "wrong length");
|
||||
test_assert(1 == i2a[0], "wrong value");
|
||||
test_assert(2 == i2a[1], "wrong value");
|
||||
test_assert(3 == i2a[2], "wrong value");
|
||||
|
||||
assert_arrays_equal(mKids, i3.get_ArrayOfPTestDataStructuresSubParent());
|
||||
|
||||
const InfallibleTArray<PTestDataStructuresSubParent*>& i4a =
|
||||
i4.get_ArrayOfActors()[0].get_ArrayOfPTestDataStructuresSubParent();
|
||||
assert_arrays_equal(mKids, i4a);
|
||||
|
||||
*o1 = i1;
|
||||
*o2 = i2;
|
||||
*o3 = i3;
|
||||
*o4 = i4;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TestDataStructuresParent::RecvTest10(
|
||||
InfallibleTArray<Unions>&& i1,
|
||||
InfallibleTArray<Unions>* o1)
|
||||
{
|
||||
test_assert(42 == i1[0].get_int(), "wrong value");
|
||||
|
||||
const InfallibleTArray<int>& i2a = i1[1].get_ArrayOfint();
|
||||
test_assert(3 == i2a.Length(), "wrong length");
|
||||
test_assert(1 == i2a[0], "wrong value");
|
||||
test_assert(2 == i2a[1], "wrong value");
|
||||
test_assert(3 == i2a[2], "wrong value");
|
||||
|
||||
assert_arrays_equal(mKids, i1[2].get_ArrayOfPTestDataStructuresSubParent());
|
||||
|
||||
const InfallibleTArray<PTestDataStructuresSubParent*>& i4a =
|
||||
i1[3].get_ArrayOfActors()[0].get_ArrayOfPTestDataStructuresSubParent();
|
||||
assert_arrays_equal(mKids, i4a);
|
||||
|
||||
*o1 = i1;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TestDataStructuresParent::RecvTest11(
|
||||
const SIntDouble& i,
|
||||
SIntDouble* o)
|
||||
{
|
||||
test_assert(1 == i.i(), "wrong value");
|
||||
test_assert(2.0 == i.d(), "wrong value");
|
||||
*o = i;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TestDataStructuresParent::RecvTest12(
|
||||
const SIntDoubleArrays& i,
|
||||
SIntDoubleArrays* o)
|
||||
{
|
||||
InfallibleTArray<int> ai;
|
||||
ai.AppendElement(1);
|
||||
ai.AppendElement(2);
|
||||
ai.AppendElement(3);
|
||||
|
||||
InfallibleTArray<double> ad;
|
||||
ad.AppendElement(.5);
|
||||
ad.AppendElement(1.0);
|
||||
ad.AppendElement(2.0);
|
||||
|
||||
test_assert(42 == i.i(), "wrong value");
|
||||
assert_arrays_equal(ai, i.ai());
|
||||
assert_arrays_equal(ad, i.ad());
|
||||
|
||||
*o = i;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TestDataStructuresParent::RecvTest13(
|
||||
const SActors& i,
|
||||
SActors* o)
|
||||
{
|
||||
InfallibleTArray<int> ai;
|
||||
ai.AppendElement(1); ai.AppendElement(2); ai.AppendElement(3);
|
||||
|
||||
test_assert(42 == i.i(), "wrong value");
|
||||
assert_arrays_equal(ai, i.ai());
|
||||
assert_arrays_equal(mKids, i.apParent());
|
||||
|
||||
*o = i;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TestDataStructuresParent::RecvTest14(
|
||||
const Structs& i,
|
||||
Structs* o)
|
||||
{
|
||||
InfallibleTArray<int> ai;
|
||||
ai.AppendElement(1); ai.AppendElement(2); ai.AppendElement(3);
|
||||
|
||||
test_assert(42 == i.i(), "wrong value");
|
||||
assert_arrays_equal(ai, i.ai());
|
||||
assert_arrays_equal(mKids, i.apParent());
|
||||
|
||||
const SActors& ia = i.aa()[0];
|
||||
test_assert(42 == ia.i(), "wrong value");
|
||||
assert_arrays_equal(ai, ia.ai());
|
||||
assert_arrays_equal(mKids, ia.apParent());
|
||||
|
||||
*o = i;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TestDataStructuresParent::RecvTest15(
|
||||
const WithStructs& i1,
|
||||
const WithStructs& i2,
|
||||
const WithStructs& i3,
|
||||
const WithStructs& i4,
|
||||
const WithStructs& i5,
|
||||
WithStructs* o1,
|
||||
WithStructs* o2,
|
||||
WithStructs* o3,
|
||||
WithStructs* o4,
|
||||
WithStructs* o5)
|
||||
{
|
||||
InfallibleTArray<int> ai;
|
||||
ai.AppendElement(1); ai.AppendElement(2); ai.AppendElement(3);
|
||||
|
||||
test_assert(i1 == int(42), "wrong value");
|
||||
assert_arrays_equal(i2.get_ArrayOfint(), ai);
|
||||
assert_arrays_equal(i3.get_ArrayOfPTestDataStructuresSubParent(), mKids);
|
||||
|
||||
const SActors& ia = i4.get_ArrayOfSActors()[0];
|
||||
test_assert(42 == ia.i(), "wrong value");
|
||||
assert_arrays_equal(ai, ia.ai());
|
||||
assert_arrays_equal(mKids, ia.apParent());
|
||||
|
||||
const Structs& is = i5.get_ArrayOfStructs()[0];
|
||||
test_assert(42 == is.i(), "wrong value");
|
||||
assert_arrays_equal(ai, is.ai());
|
||||
assert_arrays_equal(mKids, is.apParent());
|
||||
|
||||
const SActors& isa = is.aa()[0];
|
||||
test_assert(42 == isa.i(), "wrong value");
|
||||
assert_arrays_equal(ai, isa.ai());
|
||||
assert_arrays_equal(mKids, isa.apParent());
|
||||
|
||||
*o1 = i1;
|
||||
*o2 = i2;
|
||||
*o3 = i3;
|
||||
*o4 = i4;
|
||||
*o5 = i5;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TestDataStructuresParent::RecvTest16(
|
||||
const WithUnions& i,
|
||||
WithUnions* o)
|
||||
{
|
||||
test_assert(i.i() == 42, "wrong value");
|
||||
|
||||
InfallibleTArray<int> ai;
|
||||
ai.AppendElement(1); ai.AppendElement(2); ai.AppendElement(3);
|
||||
assert_arrays_equal(ai, i.ai());
|
||||
|
||||
assert_arrays_equal(i.apParent(), mKids);
|
||||
|
||||
assert_arrays_equal(mKids, i.aa()[0].get_ArrayOfPTestDataStructuresSubParent());
|
||||
|
||||
const InfallibleTArray<Unions>& iau = i.au();
|
||||
test_assert(iau[0] == 42, "wrong value");
|
||||
assert_arrays_equal(ai, iau[1].get_ArrayOfint());
|
||||
assert_arrays_equal(mKids, iau[2].get_ArrayOfPTestDataStructuresSubParent());
|
||||
assert_arrays_equal(mKids,
|
||||
iau[3].get_ArrayOfActors()[0]
|
||||
.get_ArrayOfPTestDataStructuresSubParent());
|
||||
|
||||
*o = i;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TestDataStructuresParent::RecvTest17(InfallibleTArray<Op>&& sa)
|
||||
{
|
||||
test_assert(sa.Length() == 1 && Op::TSetAttrs == sa[0].type(),
|
||||
"wrong value");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TestDataStructuresParent::RecvTest18(RegionArray&& ra)
|
||||
{
|
||||
for (RegionArray::index_type i = 0; i < ra.Length(); ++i) {
|
||||
// if |ra| has been realloc()d and given a different allocator
|
||||
// chunk, this loop will nondeterministically crash or iloop.
|
||||
for (auto iter = ra[i].RectIter(); !iter.Done(); iter.Next()) {
|
||||
Unused << iter.Get();
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// child
|
||||
|
||||
TestDataStructuresChild::TestDataStructuresChild()
|
||||
{
|
||||
MOZ_COUNT_CTOR(TestDataStructuresChild);
|
||||
}
|
||||
|
||||
TestDataStructuresChild::~TestDataStructuresChild()
|
||||
{
|
||||
MOZ_COUNT_DTOR(TestDataStructuresChild);
|
||||
}
|
||||
|
||||
bool
|
||||
TestDataStructuresChild::RecvStart()
|
||||
{
|
||||
puts("[TestDataStructuresChild] starting");
|
||||
|
||||
Test1();
|
||||
Test2();
|
||||
Test3();
|
||||
Test4();
|
||||
Test5();
|
||||
Test6();
|
||||
Test7_0();
|
||||
Test7();
|
||||
Test8();
|
||||
Test9();
|
||||
Test10();
|
||||
Test11();
|
||||
Test12();
|
||||
Test13();
|
||||
Test14();
|
||||
Test15();
|
||||
Test16();
|
||||
Test17();
|
||||
if (OtherPid() != base::GetCurrentProcId()) {
|
||||
//FIXME/bug 703317 allocation of nsIntRegion uses a global
|
||||
//region pool which breaks threads
|
||||
Test18();
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < nactors; ++i)
|
||||
if (!PTestDataStructuresSubChild::Send__delete__(mKids[i]))
|
||||
fail("can't send dtor");
|
||||
|
||||
Close();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
TestDataStructuresChild::Test1()
|
||||
{
|
||||
InfallibleTArray<int> ia;
|
||||
|
||||
for (int i = 0; i < 5; ++i)
|
||||
ia.AppendElement(i);
|
||||
|
||||
InfallibleTArray<int> oa;
|
||||
if (!SendTest1(ia, &oa))
|
||||
fail("can't send Test1");
|
||||
|
||||
assert_arrays_equal(ia, oa);
|
||||
|
||||
printf(" passed %s\n", __FUNCTION__);
|
||||
}
|
||||
|
||||
void
|
||||
TestDataStructuresChild::Test2()
|
||||
{
|
||||
InfallibleTArray<PTestDataStructuresSubChild*> oa;
|
||||
if (!SendTest2(mKids, &oa))
|
||||
fail("can't send Test2");
|
||||
assert_arrays_equal(mKids, oa);
|
||||
|
||||
printf(" passed %s\n", __FUNCTION__);
|
||||
}
|
||||
|
||||
void
|
||||
TestDataStructuresChild::Test3()
|
||||
{
|
||||
int i1i = 42;
|
||||
double i2d = 4.0;
|
||||
IntDouble i1(i1i);
|
||||
IntDouble i2(i2d);
|
||||
IntDouble o1, o2;
|
||||
|
||||
SendTest3(i1, i2, &o1, &o2);
|
||||
|
||||
test_assert(i1i == o1.get_int(), "wrong value");
|
||||
test_assert(i2d == o2.get_double(), "wrong value");
|
||||
|
||||
printf(" passed %s\n", __FUNCTION__);
|
||||
}
|
||||
|
||||
void
|
||||
TestDataStructuresChild::Test4()
|
||||
{
|
||||
InfallibleTArray<IntDouble> i1;
|
||||
i1.AppendElement(IntDouble(int(1)));
|
||||
i1.AppendElement(IntDouble(2.0));
|
||||
i1.AppendElement(IntDouble(int(3)));
|
||||
i1.AppendElement(IntDouble(4.0));
|
||||
|
||||
InfallibleTArray<IntDouble> o1;
|
||||
if (!SendTest4(i1, &o1))
|
||||
fail("can't send Test4");
|
||||
|
||||
// TODO Union::operator==()
|
||||
test_assert(i1.Length() == o1.Length(), "wrong length");
|
||||
test_assert(1 == o1[0].get_int(), "wrong value");
|
||||
test_assert(2.0 == o1[1].get_double(), "wrong value");
|
||||
test_assert(3 == o1[2].get_int(), "wrong value");
|
||||
test_assert(4.0 == o1[3].get_double(), "wrong value");
|
||||
|
||||
printf(" passed %s\n", __FUNCTION__);
|
||||
}
|
||||
|
||||
void
|
||||
TestDataStructuresChild::Test5()
|
||||
{
|
||||
IntDoubleArrays i1(int(42));
|
||||
InfallibleTArray<int> i2;
|
||||
i2.AppendElement(1); i2.AppendElement(2); i2.AppendElement(3);
|
||||
InfallibleTArray<double> i3;
|
||||
i3.AppendElement(1.0); i3.AppendElement(2.0); i3.AppendElement(3.0);
|
||||
|
||||
IntDoubleArrays o1, o2, o3;
|
||||
if (!SendTest5(i1, IntDoubleArrays(i2), IntDoubleArrays(i3),
|
||||
&o1, &o2, &o3))
|
||||
fail("can't send Test5");
|
||||
|
||||
test_assert(42 == o1.get_int(), "wrong value");
|
||||
assert_arrays_equal(i2, o2.get_ArrayOfint());
|
||||
assert_arrays_equal(i3, o3.get_ArrayOfdouble());
|
||||
|
||||
printf(" passed %s\n", __FUNCTION__);
|
||||
}
|
||||
|
||||
void
|
||||
TestDataStructuresChild::Test6()
|
||||
{
|
||||
IntDoubleArrays id1(int(42));
|
||||
InfallibleTArray<int> id2;
|
||||
id2.AppendElement(1); id2.AppendElement(2); id2.AppendElement(3);
|
||||
InfallibleTArray<double> id3;
|
||||
id3.AppendElement(1.0); id3.AppendElement(2.0); id3.AppendElement(3.0);
|
||||
|
||||
InfallibleTArray<IntDoubleArrays> i1;
|
||||
i1.AppendElement(id1);
|
||||
i1.AppendElement(IntDoubleArrays(id2));
|
||||
i1.AppendElement(IntDoubleArrays(id3));
|
||||
|
||||
InfallibleTArray<IntDoubleArrays> o1;
|
||||
if (!SendTest6(i1, &o1))
|
||||
fail("can't send Test6");
|
||||
|
||||
test_assert(3 == o1.Length(), "wrong length");
|
||||
IntDoubleArrays od1(o1[0]);
|
||||
InfallibleTArray<int> od2(o1[1].get_ArrayOfint());
|
||||
InfallibleTArray<double> od3(o1[2].get_ArrayOfdouble());
|
||||
|
||||
test_assert(42 == od1.get_int(), "wrong value");
|
||||
assert_arrays_equal(id2, od2);
|
||||
assert_arrays_equal(id3, od3);
|
||||
|
||||
printf(" passed %s\n", __FUNCTION__);
|
||||
}
|
||||
|
||||
void
|
||||
TestDataStructuresChild::Test7_0()
|
||||
{
|
||||
ActorWrapper iaw;
|
||||
if (iaw.actorChild() != nullptr || iaw.actorParent() != nullptr)
|
||||
fail("actor members should be null initially");
|
||||
|
||||
iaw.actorChild() = mKids[0];
|
||||
if (iaw.actorParent() != nullptr)
|
||||
fail("parent should be null on child side after set");
|
||||
|
||||
ActorWrapper oaw;
|
||||
if (!SendTest7_0(iaw, &oaw))
|
||||
fail("sending Test7_0");
|
||||
|
||||
if (oaw.actorParent() != nullptr)
|
||||
fail("parent accessor on actor-struct members should always be null in child");
|
||||
|
||||
if (oaw.actorChild() != mKids[0])
|
||||
fail("should have got back same child-side actor");
|
||||
}
|
||||
|
||||
void
|
||||
TestDataStructuresChild::Test7()
|
||||
{
|
||||
Actors i1(42);
|
||||
InfallibleTArray<int> i2a;
|
||||
i2a.AppendElement(1); i2a.AppendElement(2); i2a.AppendElement(3);
|
||||
|
||||
Actors o1, o2, o3;
|
||||
if (!SendTest7(i1, Actors(i2a), Actors(mKids), &o1, &o2, &o3))
|
||||
fail("can't send Test7");
|
||||
|
||||
test_assert(42 == o1.get_int(), "wrong value");
|
||||
assert_arrays_equal(i2a, o2.get_ArrayOfint());
|
||||
assert_arrays_equal(mKids, o3.get_ArrayOfPTestDataStructuresSubChild());
|
||||
|
||||
printf(" passed %s\n", __FUNCTION__);
|
||||
}
|
||||
|
||||
void
|
||||
TestDataStructuresChild::Test8()
|
||||
{
|
||||
Actors i1e(42);
|
||||
InfallibleTArray<int> i2a;
|
||||
i2a.AppendElement(1); i2a.AppendElement(2); i2a.AppendElement(3);
|
||||
|
||||
InfallibleTArray<Actors> i1;
|
||||
i1.AppendElement(i1e);
|
||||
i1.AppendElement(i2a);
|
||||
i1.AppendElement(mKids);
|
||||
|
||||
InfallibleTArray<Actors> o1;
|
||||
if (!SendTest8(i1, &o1))
|
||||
fail("can't send Test8");
|
||||
|
||||
test_assert(3 == o1.Length(), "wrong length");
|
||||
test_assert(42 == o1[0].get_int(), "wrong value");
|
||||
assert_arrays_equal(i2a, o1[1].get_ArrayOfint());
|
||||
assert_arrays_equal(mKids, o1[2].get_ArrayOfPTestDataStructuresSubChild());
|
||||
|
||||
printf(" passed %s\n", __FUNCTION__);
|
||||
}
|
||||
|
||||
void
|
||||
TestDataStructuresChild::Test9()
|
||||
{
|
||||
Unions i1(int(42));
|
||||
|
||||
InfallibleTArray<int> i2a;
|
||||
i2a.AppendElement(1);
|
||||
i2a.AppendElement(2);
|
||||
i2a.AppendElement(3);
|
||||
|
||||
InfallibleTArray<Actors> i4a;
|
||||
i4a.AppendElement(mKids);
|
||||
|
||||
Unions o1, o2, o3, o4;
|
||||
if (!SendTest9(i1, Unions(i2a), Unions(mKids), Unions(i4a),
|
||||
&o1, &o2, &o3, &o4))
|
||||
fail("can't send Test9");
|
||||
|
||||
test_assert(42 == o1.get_int(), "wrong value");
|
||||
assert_arrays_equal(i2a, o2.get_ArrayOfint());
|
||||
assert_arrays_equal(mKids, o3.get_ArrayOfPTestDataStructuresSubChild());
|
||||
assert_arrays_equal(
|
||||
mKids,
|
||||
o4.get_ArrayOfActors()[0].get_ArrayOfPTestDataStructuresSubChild());
|
||||
|
||||
printf(" passed %s\n", __FUNCTION__);
|
||||
}
|
||||
|
||||
void
|
||||
TestDataStructuresChild::Test10()
|
||||
{
|
||||
Unions i1a(int(42));
|
||||
|
||||
InfallibleTArray<int> i2a;
|
||||
i2a.AppendElement(1);
|
||||
i2a.AppendElement(2);
|
||||
i2a.AppendElement(3);
|
||||
|
||||
InfallibleTArray<Actors> i4a;
|
||||
i4a.AppendElement(mKids);
|
||||
|
||||
InfallibleTArray<Unions> i1;
|
||||
i1.AppendElement(i1a);
|
||||
i1.AppendElement(Unions(i2a));
|
||||
i1.AppendElement(Unions(mKids));
|
||||
i1.AppendElement(Unions(i4a));
|
||||
|
||||
InfallibleTArray<Unions> o1;
|
||||
if (!SendTest10(i1, &o1))
|
||||
fail("can't send Test10");
|
||||
|
||||
test_assert(4 == o1.Length(), "wrong length");
|
||||
test_assert(42 == o1[0].get_int(), "wrong value");
|
||||
assert_arrays_equal(i2a, o1[1].get_ArrayOfint());
|
||||
assert_arrays_equal(mKids, o1[2].get_ArrayOfPTestDataStructuresSubChild());
|
||||
assert_arrays_equal(
|
||||
mKids,
|
||||
o1[3].get_ArrayOfActors()[0].get_ArrayOfPTestDataStructuresSubChild());
|
||||
|
||||
printf(" passed %s\n", __FUNCTION__);
|
||||
}
|
||||
|
||||
void
|
||||
TestDataStructuresChild::Test11()
|
||||
{
|
||||
SIntDouble i(1, 2.0);
|
||||
SIntDouble o;
|
||||
|
||||
if (!SendTest11(i, &o))
|
||||
fail("sending Test11");
|
||||
|
||||
test_assert(1 == o.i() && 2.0 == o.d(), "wrong values");
|
||||
|
||||
printf(" passed %s\n", __FUNCTION__);
|
||||
}
|
||||
|
||||
void
|
||||
TestDataStructuresChild::Test12()
|
||||
{
|
||||
InfallibleTArray<int> ai;
|
||||
ai.AppendElement(1); ai.AppendElement(2); ai.AppendElement(3);
|
||||
|
||||
InfallibleTArray<double> ad;
|
||||
ad.AppendElement(.5); ad.AppendElement(1.0); ad.AppendElement(2.0);
|
||||
|
||||
SIntDoubleArrays i(42, ai, ad);
|
||||
SIntDoubleArrays o;
|
||||
|
||||
if (!SendTest12(i, &o))
|
||||
fail("sending Test12");
|
||||
|
||||
test_assert(42 == o.i(), "wrong value");
|
||||
assert_arrays_equal(ai, o.ai());
|
||||
assert_arrays_equal(ad, o.ad());
|
||||
|
||||
printf(" passed %s\n", __FUNCTION__);
|
||||
}
|
||||
|
||||
void
|
||||
TestDataStructuresChild::Test13()
|
||||
{
|
||||
InfallibleTArray<int> ai;
|
||||
ai.AppendElement(1); ai.AppendElement(2); ai.AppendElement(3);
|
||||
|
||||
SActors i;
|
||||
i.i() = 42;
|
||||
i.ai() = ai;
|
||||
i.apChild() = mKids;
|
||||
|
||||
SActors o;
|
||||
if (!SendTest13(i, &o))
|
||||
fail("can't send Test13");
|
||||
|
||||
test_assert(42 == o.i(), "wrong value");
|
||||
assert_arrays_equal(ai, o.ai());
|
||||
assert_arrays_equal(mKids, o.apChild());
|
||||
|
||||
printf(" passed %s\n", __FUNCTION__);
|
||||
}
|
||||
|
||||
void
|
||||
TestDataStructuresChild::Test14()
|
||||
{
|
||||
InfallibleTArray<int> ai;
|
||||
ai.AppendElement(1); ai.AppendElement(2); ai.AppendElement(3);
|
||||
|
||||
SActors ia;
|
||||
ia.i() = 42;
|
||||
ia.ai() = ai;
|
||||
ia.apChild() = mKids;
|
||||
InfallibleTArray<SActors> aa; aa.AppendElement(ia);
|
||||
|
||||
Structs i;
|
||||
i.i() = 42;
|
||||
i.ai() = ai;
|
||||
i.apChild() = mKids;
|
||||
i.aa() = aa;
|
||||
|
||||
Structs o;
|
||||
if (!SendTest14(i, &o))
|
||||
fail("can't send Test14");
|
||||
|
||||
test_assert(42 == o.i(), "wrong value");
|
||||
assert_arrays_equal(ai, o.ai());
|
||||
assert_arrays_equal(mKids, o.apChild());
|
||||
|
||||
const SActors& os = o.aa()[0];
|
||||
test_assert(42 == os.i(), "wrong value");
|
||||
assert_arrays_equal(ai, os.ai());
|
||||
assert_arrays_equal(mKids, os.apChild());
|
||||
|
||||
printf(" passed %s\n", __FUNCTION__);
|
||||
}
|
||||
|
||||
void
|
||||
TestDataStructuresChild::Test15()
|
||||
{
|
||||
InfallibleTArray<int> ai;
|
||||
ai.AppendElement(1); ai.AppendElement(2); ai.AppendElement(3);
|
||||
|
||||
SActors ia;
|
||||
ia.i() = 42;
|
||||
ia.ai() = ai;
|
||||
ia.apChild() = mKids;
|
||||
InfallibleTArray<SActors> iaa; iaa.AppendElement(ia);
|
||||
|
||||
Structs is;
|
||||
is.i() = 42;
|
||||
is.ai() = ai;
|
||||
is.apChild() = mKids;
|
||||
is.aa() = iaa;
|
||||
InfallibleTArray<Structs> isa; isa.AppendElement(is);
|
||||
|
||||
WithStructs o1, o2, o3, o4, o5;
|
||||
if (!SendTest15(WithStructs(42),
|
||||
WithStructs(ai),
|
||||
WithStructs(mKids),
|
||||
WithStructs(iaa),
|
||||
WithStructs(isa),
|
||||
&o1, &o2, &o3, &o4, &o5))
|
||||
fail("sending Test15");
|
||||
|
||||
test_assert(o1 == int(42), "wrong value");
|
||||
assert_arrays_equal(o2.get_ArrayOfint(), ai);
|
||||
assert_arrays_equal(o3.get_ArrayOfPTestDataStructuresSubChild(), mKids);
|
||||
|
||||
const SActors& oa = o4.get_ArrayOfSActors()[0];
|
||||
test_assert(42 == oa.i(), "wrong value");
|
||||
assert_arrays_equal(ai, oa.ai());
|
||||
assert_arrays_equal(mKids, oa.apChild());
|
||||
|
||||
const Structs& os = o5.get_ArrayOfStructs()[0];
|
||||
test_assert(42 == os.i(), "wrong value");
|
||||
assert_arrays_equal(ai, os.ai());
|
||||
assert_arrays_equal(mKids, os.apChild());
|
||||
|
||||
const SActors& osa = os.aa()[0];
|
||||
test_assert(42 == osa.i(), "wrong value");
|
||||
assert_arrays_equal(ai, osa.ai());
|
||||
assert_arrays_equal(mKids, osa.apChild());
|
||||
|
||||
printf(" passed %s\n", __FUNCTION__);
|
||||
}
|
||||
|
||||
void
|
||||
TestDataStructuresChild::Test16()
|
||||
{
|
||||
WithUnions i;
|
||||
|
||||
i.i() = 42;
|
||||
|
||||
InfallibleTArray<int> ai;
|
||||
ai.AppendElement(1); ai.AppendElement(2); ai.AppendElement(3);
|
||||
i.ai() = ai;
|
||||
|
||||
i.apChild() = mKids;
|
||||
|
||||
InfallibleTArray<Actors> iaa;
|
||||
iaa.AppendElement(mKids);
|
||||
i.aa() = iaa;
|
||||
|
||||
InfallibleTArray<Unions> iau;
|
||||
iau.AppendElement(int(42));
|
||||
iau.AppendElement(ai);
|
||||
iau.AppendElement(mKids);
|
||||
iau.AppendElement(iaa);
|
||||
i.au() = iau;
|
||||
|
||||
WithUnions o;
|
||||
if (!SendTest16(i, &o))
|
||||
fail("sending Test16");
|
||||
|
||||
test_assert(42 == o.i(), "wrong value");
|
||||
assert_arrays_equal(o.ai(), ai);
|
||||
assert_arrays_equal(o.apChild(), mKids);
|
||||
|
||||
const Actors& oaa = o.aa()[0];
|
||||
assert_arrays_equal(oaa.get_ArrayOfPTestDataStructuresSubChild(), mKids);
|
||||
|
||||
const InfallibleTArray<Unions>& oau = o.au();
|
||||
test_assert(oau[0] == 42, "wrong value");
|
||||
assert_arrays_equal(oau[1].get_ArrayOfint(), ai);
|
||||
assert_arrays_equal(oau[2].get_ArrayOfPTestDataStructuresSubChild(),
|
||||
mKids);
|
||||
assert_arrays_equal(oau[3].get_ArrayOfActors()[0]
|
||||
.get_ArrayOfPTestDataStructuresSubChild(),
|
||||
mKids);
|
||||
|
||||
printf(" passed %s\n", __FUNCTION__);
|
||||
}
|
||||
|
||||
void
|
||||
TestDataStructuresChild::Test17()
|
||||
{
|
||||
Attrs attrs;
|
||||
attrs.common() = CommonAttrs(true);
|
||||
attrs.specific() = BarAttrs(1.0f);
|
||||
|
||||
InfallibleTArray<Op> ops;
|
||||
ops.AppendElement(SetAttrs(nullptr, mKids[0], attrs));
|
||||
|
||||
if (!SendTest17(ops))
|
||||
fail("sending Test17");
|
||||
|
||||
printf(" passed %s\n", __FUNCTION__);
|
||||
}
|
||||
|
||||
void
|
||||
TestDataStructuresChild::Test18()
|
||||
{
|
||||
const int nelements = 1000;
|
||||
RegionArray ra;
|
||||
// big enough to hopefully force a realloc to a different chunk of
|
||||
// memory on the receiving side, if the workaround isn't working
|
||||
// correctly. But SetCapacity() here because we don't want to
|
||||
// crash on the sending side.
|
||||
ra.SetCapacity(nelements);
|
||||
for (int i = 0; i < nelements; ++i) {
|
||||
nsIntRegion r;
|
||||
r.Or(nsIntRect(0, 0, 10, 10), nsIntRect(10, 10, 10, 10));
|
||||
ra.AppendElement(r);
|
||||
}
|
||||
|
||||
if (!SendTest18(ra))
|
||||
fail("sending Test18");
|
||||
|
||||
printf(" passed %s\n", __FUNCTION__);
|
||||
}
|
||||
|
||||
} // namespace _ipdltest
|
||||
} // namespace mozilla
|
||||
234
ipc/ipdl/test/cxx/TestDataStructures.h
Normal file
234
ipc/ipdl/test/cxx/TestDataStructures.h
Normal file
|
|
@ -0,0 +1,234 @@
|
|||
#ifndef mozilla__ipdltest_TestDataStructures_h
|
||||
#define mozilla__ipdltest_TestDataStructures_h 1
|
||||
|
||||
#include "mozilla/_ipdltest/IPDLUnitTests.h"
|
||||
|
||||
#include "mozilla/_ipdltest/PTestDataStructuresParent.h"
|
||||
#include "mozilla/_ipdltest/PTestDataStructuresChild.h"
|
||||
|
||||
#include "mozilla/_ipdltest/PTestDataStructuresSubParent.h"
|
||||
#include "mozilla/_ipdltest/PTestDataStructuresSubChild.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace _ipdltest {
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Subprotocol actors
|
||||
|
||||
class TestDataStructuresSub :
|
||||
public PTestDataStructuresSubParent,
|
||||
public PTestDataStructuresSubChild
|
||||
{
|
||||
public:
|
||||
explicit TestDataStructuresSub(uint32_t i) : mI(i)
|
||||
{ }
|
||||
virtual ~TestDataStructuresSub()
|
||||
{ }
|
||||
virtual void ActorDestroy(ActorDestroyReason why) override
|
||||
{
|
||||
if (Deletion != why)
|
||||
fail("unexpected destruction!");
|
||||
}
|
||||
uint32_t mI;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Main actors
|
||||
|
||||
class TestDataStructuresParent :
|
||||
public PTestDataStructuresParent
|
||||
{
|
||||
public:
|
||||
TestDataStructuresParent();
|
||||
virtual ~TestDataStructuresParent();
|
||||
|
||||
static bool RunTestInProcesses() { return true; }
|
||||
static bool RunTestInThreads() { return true; }
|
||||
|
||||
void Main();
|
||||
|
||||
protected:
|
||||
virtual PTestDataStructuresSubParent* AllocPTestDataStructuresSubParent(const int& i) override
|
||||
{
|
||||
PTestDataStructuresSubParent* actor = new TestDataStructuresSub(i);
|
||||
mKids.AppendElement(actor);
|
||||
return actor;
|
||||
}
|
||||
|
||||
virtual bool DeallocPTestDataStructuresSubParent(PTestDataStructuresSubParent* actor) override;
|
||||
|
||||
virtual bool RecvTest1(
|
||||
InfallibleTArray<int>&& i1,
|
||||
InfallibleTArray<int>* o1) override;
|
||||
|
||||
virtual bool RecvTest2(
|
||||
InfallibleTArray<PTestDataStructuresSubParent*>&& i1,
|
||||
InfallibleTArray<PTestDataStructuresSubParent*>* o1) override;
|
||||
|
||||
virtual bool RecvTest3(
|
||||
const IntDouble& i1,
|
||||
const IntDouble& i2,
|
||||
IntDouble* o1,
|
||||
IntDouble* o2) override;
|
||||
|
||||
virtual bool RecvTest4(
|
||||
InfallibleTArray<IntDouble>&& i1,
|
||||
InfallibleTArray<IntDouble>* o1) override;
|
||||
|
||||
virtual bool RecvTest5(
|
||||
const IntDoubleArrays& i1,
|
||||
const IntDoubleArrays& i2,
|
||||
const IntDoubleArrays& i3,
|
||||
IntDoubleArrays* o1,
|
||||
IntDoubleArrays* o2,
|
||||
IntDoubleArrays* o3) override;
|
||||
|
||||
virtual bool RecvTest6(
|
||||
InfallibleTArray<IntDoubleArrays>&& i1,
|
||||
InfallibleTArray<IntDoubleArrays>* o1) override;
|
||||
|
||||
|
||||
virtual bool RecvTest7_0(const ActorWrapper& i1,
|
||||
ActorWrapper* o1) override;
|
||||
|
||||
virtual bool RecvTest7(
|
||||
const Actors& i1,
|
||||
const Actors& i2,
|
||||
const Actors& i3,
|
||||
Actors* o1,
|
||||
Actors* o2,
|
||||
Actors* o3) override;
|
||||
|
||||
virtual bool RecvTest8(
|
||||
InfallibleTArray<Actors>&& i1,
|
||||
InfallibleTArray<Actors>* o1) override;
|
||||
|
||||
virtual bool RecvTest9(
|
||||
const Unions& i1,
|
||||
const Unions& i2,
|
||||
const Unions& i3,
|
||||
const Unions& i4,
|
||||
Unions* o1,
|
||||
Unions* o2,
|
||||
Unions* o3,
|
||||
Unions* o4) override;
|
||||
|
||||
virtual bool RecvTest10(
|
||||
InfallibleTArray<Unions>&& i1,
|
||||
InfallibleTArray<Unions>* o1) override;
|
||||
|
||||
virtual bool RecvTest11(
|
||||
const SIntDouble& i,
|
||||
SIntDouble* o) override;
|
||||
|
||||
virtual bool RecvTest12(
|
||||
const SIntDoubleArrays& i,
|
||||
SIntDoubleArrays* o) override;
|
||||
|
||||
virtual bool RecvTest13(
|
||||
const SActors& i,
|
||||
SActors* o) override;
|
||||
|
||||
virtual bool RecvTest14(
|
||||
const Structs& i,
|
||||
Structs* o) override;
|
||||
|
||||
virtual bool RecvTest15(
|
||||
const WithStructs& i1,
|
||||
const WithStructs& i2,
|
||||
const WithStructs& i3,
|
||||
const WithStructs& i4,
|
||||
const WithStructs& i5,
|
||||
WithStructs* o1,
|
||||
WithStructs* o2,
|
||||
WithStructs* o3,
|
||||
WithStructs* o4,
|
||||
WithStructs* o5) override;
|
||||
|
||||
virtual bool RecvTest16(
|
||||
const WithUnions& i,
|
||||
WithUnions* o) override;
|
||||
|
||||
virtual bool RecvTest17(InfallibleTArray<Op>&& sa) override;
|
||||
|
||||
virtual bool RecvTest18(InfallibleTArray<nsIntRegion>&& ra) override;
|
||||
|
||||
virtual bool RecvDummy(const ShmemUnion& su, ShmemUnion* rsu) override
|
||||
{
|
||||
*rsu = su;
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual void ActorDestroy(ActorDestroyReason why) override
|
||||
{
|
||||
if (NormalShutdown != why)
|
||||
fail("unexpected destruction!");
|
||||
passed("ok");
|
||||
QuitParent();
|
||||
}
|
||||
|
||||
private:
|
||||
InfallibleTArray<PTestDataStructuresSubParent*> mKids;
|
||||
};
|
||||
|
||||
|
||||
class TestDataStructuresChild :
|
||||
public PTestDataStructuresChild
|
||||
{
|
||||
public:
|
||||
TestDataStructuresChild();
|
||||
virtual ~TestDataStructuresChild();
|
||||
|
||||
protected:
|
||||
virtual PTestDataStructuresSubChild* AllocPTestDataStructuresSubChild(const int& i) override
|
||||
{
|
||||
PTestDataStructuresSubChild* actor = new TestDataStructuresSub(i);
|
||||
mKids.AppendElement(actor);
|
||||
return actor;
|
||||
}
|
||||
|
||||
virtual bool DeallocPTestDataStructuresSubChild(PTestDataStructuresSubChild* actor) override
|
||||
{
|
||||
delete actor;
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual bool RecvStart() override;
|
||||
|
||||
virtual void ActorDestroy(ActorDestroyReason why) override
|
||||
{
|
||||
if (NormalShutdown != why)
|
||||
fail("unexpected destruction!");
|
||||
QuitChild();
|
||||
}
|
||||
|
||||
private:
|
||||
void Test1();
|
||||
void Test2();
|
||||
void Test3();
|
||||
void Test4();
|
||||
void Test5();
|
||||
void Test6();
|
||||
void Test7_0();
|
||||
void Test7();
|
||||
void Test8();
|
||||
void Test9();
|
||||
void Test10();
|
||||
void Test11();
|
||||
void Test12();
|
||||
void Test13();
|
||||
void Test14();
|
||||
void Test15();
|
||||
void Test16();
|
||||
void Test17();
|
||||
void Test18();
|
||||
|
||||
InfallibleTArray<PTestDataStructuresSubChild*> mKids;
|
||||
};
|
||||
|
||||
|
||||
} // namespace _ipdltest
|
||||
} // namespace mozilla
|
||||
|
||||
|
||||
#endif // ifndef mozilla__ipdltest_TestDataStructures_h
|
||||
417
ipc/ipdl/test/cxx/TestDemon.cpp
Normal file
417
ipc/ipdl/test/cxx/TestDemon.cpp
Normal file
|
|
@ -0,0 +1,417 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* vim: sw=4 ts=4 et :
|
||||
*/
|
||||
#include "TestDemon.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "IPDLUnitTests.h" // fail etc.
|
||||
#if defined(OS_POSIX)
|
||||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
#else
|
||||
#include <time.h>
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
namespace _ipdltest {
|
||||
|
||||
const int kMaxStackHeight = 4;
|
||||
|
||||
static LazyLogModule sLogModule("demon");
|
||||
|
||||
#define DEMON_LOG(...) MOZ_LOG(sLogModule, LogLevel::Debug, (__VA_ARGS__))
|
||||
|
||||
static int gStackHeight = 0;
|
||||
static bool gFlushStack = false;
|
||||
|
||||
static int
|
||||
Choose(int count)
|
||||
{
|
||||
#if defined(OS_POSIX)
|
||||
return random() % count;
|
||||
#else
|
||||
return rand() % count;
|
||||
#endif
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// parent
|
||||
|
||||
TestDemonParent::TestDemonParent()
|
||||
: mDone(false),
|
||||
mIncoming(),
|
||||
mOutgoing()
|
||||
{
|
||||
MOZ_COUNT_CTOR(TestDemonParent);
|
||||
}
|
||||
|
||||
TestDemonParent::~TestDemonParent()
|
||||
{
|
||||
MOZ_COUNT_DTOR(TestDemonParent);
|
||||
}
|
||||
|
||||
void
|
||||
TestDemonParent::Main()
|
||||
{
|
||||
if (!getenv("MOZ_TEST_IPC_DEMON")) {
|
||||
QuitParent();
|
||||
return;
|
||||
}
|
||||
#if defined(OS_POSIX)
|
||||
srandom(time(nullptr));
|
||||
#else
|
||||
srand(time(nullptr));
|
||||
#endif
|
||||
|
||||
DEMON_LOG("Start demon");
|
||||
|
||||
if (!SendStart())
|
||||
fail("sending Start");
|
||||
|
||||
RunUnlimitedSequence();
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
bool
|
||||
TestDemonParent::ShouldContinueFromReplyTimeout()
|
||||
{
|
||||
return Choose(2) == 0;
|
||||
}
|
||||
|
||||
bool
|
||||
TestDemonParent::ArtificialTimeout()
|
||||
{
|
||||
return Choose(5) == 0;
|
||||
}
|
||||
|
||||
void
|
||||
TestDemonParent::ArtificialSleep()
|
||||
{
|
||||
if (Choose(2) == 0) {
|
||||
// Sleep for anywhere from 0 to 100 milliseconds.
|
||||
unsigned micros = Choose(100) * 1000;
|
||||
#ifdef OS_POSIX
|
||||
usleep(micros);
|
||||
#else
|
||||
Sleep(micros / 1000);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
bool
|
||||
TestDemonParent::RecvAsyncMessage(const int& n)
|
||||
{
|
||||
DEMON_LOG("Start RecvAsync [%d]", n);
|
||||
|
||||
MOZ_ASSERT(n == mIncoming[0]);
|
||||
mIncoming[0]++;
|
||||
|
||||
RunLimitedSequence();
|
||||
|
||||
DEMON_LOG("End RecvAsync [%d]", n);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
TestDemonParent::RecvHiPrioSyncMessage()
|
||||
{
|
||||
DEMON_LOG("Start RecvHiPrioSyncMessage");
|
||||
RunLimitedSequence();
|
||||
DEMON_LOG("End RecvHiPrioSyncMessage");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
TestDemonParent::RecvSyncMessage(const int& n)
|
||||
{
|
||||
DEMON_LOG("Start RecvSync [%d]", n);
|
||||
|
||||
MOZ_ASSERT(n == mIncoming[0]);
|
||||
mIncoming[0]++;
|
||||
|
||||
RunLimitedSequence(ASYNC_ONLY);
|
||||
|
||||
DEMON_LOG("End RecvSync [%d]", n);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
TestDemonParent::RecvUrgentAsyncMessage(const int& n)
|
||||
{
|
||||
DEMON_LOG("Start RecvUrgentAsyncMessage [%d]", n);
|
||||
|
||||
MOZ_ASSERT(n == mIncoming[2]);
|
||||
mIncoming[2]++;
|
||||
|
||||
RunLimitedSequence(ASYNC_ONLY);
|
||||
|
||||
DEMON_LOG("End RecvUrgentAsyncMessage [%d]", n);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
TestDemonParent::RecvUrgentSyncMessage(const int& n)
|
||||
{
|
||||
DEMON_LOG("Start RecvUrgentSyncMessage [%d]", n);
|
||||
|
||||
MOZ_ASSERT(n == mIncoming[2]);
|
||||
mIncoming[2]++;
|
||||
|
||||
RunLimitedSequence(ASYNC_ONLY);
|
||||
|
||||
DEMON_LOG("End RecvUrgentSyncMessage [%d]", n);
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
TestDemonParent::RunUnlimitedSequence()
|
||||
{
|
||||
if (mDone) {
|
||||
return;
|
||||
}
|
||||
|
||||
gFlushStack = false;
|
||||
DoAction();
|
||||
|
||||
MessageLoop::current()->PostTask(NewNonOwningRunnableMethod(this, &TestDemonParent::RunUnlimitedSequence));
|
||||
}
|
||||
|
||||
void
|
||||
TestDemonParent::RunLimitedSequence(int flags)
|
||||
{
|
||||
if (gStackHeight >= kMaxStackHeight) {
|
||||
return;
|
||||
}
|
||||
gStackHeight++;
|
||||
|
||||
int count = Choose(20);
|
||||
for (int i = 0; i < count; i++) {
|
||||
if (!DoAction(flags)) {
|
||||
gFlushStack = true;
|
||||
}
|
||||
if (gFlushStack) {
|
||||
gStackHeight--;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
gStackHeight--;
|
||||
}
|
||||
|
||||
static bool
|
||||
AllowAsync(int outgoing, int incoming)
|
||||
{
|
||||
return incoming >= outgoing - 5;
|
||||
}
|
||||
|
||||
bool
|
||||
TestDemonParent::DoAction(int flags)
|
||||
{
|
||||
if (flags & ASYNC_ONLY) {
|
||||
if (AllowAsync(mOutgoing[0], mIncoming[0])) {
|
||||
DEMON_LOG("SendAsyncMessage [%d]", mOutgoing[0]);
|
||||
return SendAsyncMessage(mOutgoing[0]++);
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
switch (Choose(3)) {
|
||||
case 0:
|
||||
if (AllowAsync(mOutgoing[0], mIncoming[0])) {
|
||||
DEMON_LOG("SendAsyncMessage [%d]", mOutgoing[0]);
|
||||
return SendAsyncMessage(mOutgoing[0]++);
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
|
||||
case 1: {
|
||||
DEMON_LOG("Start SendHiPrioSyncMessage");
|
||||
bool r = SendHiPrioSyncMessage();
|
||||
DEMON_LOG("End SendHiPrioSyncMessage result=%d", r);
|
||||
return r;
|
||||
}
|
||||
|
||||
case 2:
|
||||
DEMON_LOG("Cancel");
|
||||
GetIPCChannel()->CancelCurrentTransaction();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
MOZ_CRASH();
|
||||
return false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// child
|
||||
|
||||
|
||||
TestDemonChild::TestDemonChild()
|
||||
: mIncoming(),
|
||||
mOutgoing()
|
||||
{
|
||||
MOZ_COUNT_CTOR(TestDemonChild);
|
||||
}
|
||||
|
||||
TestDemonChild::~TestDemonChild()
|
||||
{
|
||||
MOZ_COUNT_DTOR(TestDemonChild);
|
||||
}
|
||||
|
||||
bool
|
||||
TestDemonChild::RecvStart()
|
||||
{
|
||||
#ifdef OS_POSIX
|
||||
srandom(time(nullptr));
|
||||
#else
|
||||
srand(time(nullptr));
|
||||
#endif
|
||||
|
||||
DEMON_LOG("RecvStart");
|
||||
|
||||
RunUnlimitedSequence();
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
void
|
||||
TestDemonChild::ArtificialSleep()
|
||||
{
|
||||
if (Choose(2) == 0) {
|
||||
// Sleep for anywhere from 0 to 100 milliseconds.
|
||||
unsigned micros = Choose(100) * 1000;
|
||||
#ifdef OS_POSIX
|
||||
usleep(micros);
|
||||
#else
|
||||
Sleep(micros / 1000);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
bool
|
||||
TestDemonChild::RecvAsyncMessage(const int& n)
|
||||
{
|
||||
DEMON_LOG("Start RecvAsyncMessage [%d]", n);
|
||||
|
||||
MOZ_ASSERT(n == mIncoming[0]);
|
||||
mIncoming[0]++;
|
||||
|
||||
RunLimitedSequence();
|
||||
|
||||
DEMON_LOG("End RecvAsyncMessage [%d]", n);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
TestDemonChild::RecvHiPrioSyncMessage()
|
||||
{
|
||||
DEMON_LOG("Start RecvHiPrioSyncMessage");
|
||||
RunLimitedSequence();
|
||||
DEMON_LOG("End RecvHiPrioSyncMessage");
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
TestDemonChild::RunUnlimitedSequence()
|
||||
{
|
||||
gFlushStack = false;
|
||||
DoAction();
|
||||
|
||||
MessageLoop::current()->PostTask(NewNonOwningRunnableMethod(this, &TestDemonChild::RunUnlimitedSequence));
|
||||
}
|
||||
|
||||
void
|
||||
TestDemonChild::RunLimitedSequence()
|
||||
{
|
||||
if (gStackHeight >= kMaxStackHeight) {
|
||||
return;
|
||||
}
|
||||
gStackHeight++;
|
||||
|
||||
int count = Choose(20);
|
||||
for (int i = 0; i < count; i++) {
|
||||
if (!DoAction()) {
|
||||
gFlushStack = true;
|
||||
}
|
||||
if (gFlushStack) {
|
||||
gStackHeight--;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
gStackHeight--;
|
||||
}
|
||||
|
||||
bool
|
||||
TestDemonChild::DoAction()
|
||||
{
|
||||
switch (Choose(6)) {
|
||||
case 0:
|
||||
if (AllowAsync(mOutgoing[0], mIncoming[0])) {
|
||||
DEMON_LOG("SendAsyncMessage [%d]", mOutgoing[0]);
|
||||
return SendAsyncMessage(mOutgoing[0]++);
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
|
||||
case 1: {
|
||||
DEMON_LOG("Start SendHiPrioSyncMessage");
|
||||
bool r = SendHiPrioSyncMessage();
|
||||
DEMON_LOG("End SendHiPrioSyncMessage result=%d", r);
|
||||
return r;
|
||||
}
|
||||
|
||||
case 2: {
|
||||
DEMON_LOG("Start SendSyncMessage [%d]", mOutgoing[0]);
|
||||
bool r = SendSyncMessage(mOutgoing[0]++);
|
||||
switch (GetIPCChannel()->LastSendError()) {
|
||||
case SyncSendError::PreviousTimeout:
|
||||
case SyncSendError::SendingCPOWWhileDispatchingSync:
|
||||
case SyncSendError::SendingCPOWWhileDispatchingUrgent:
|
||||
case SyncSendError::NotConnectedBeforeSend:
|
||||
case SyncSendError::CancelledBeforeSend:
|
||||
mOutgoing[0]--;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
DEMON_LOG("End SendSyncMessage result=%d", r);
|
||||
return r;
|
||||
}
|
||||
|
||||
case 3:
|
||||
DEMON_LOG("SendUrgentAsyncMessage [%d]", mOutgoing[2]);
|
||||
return SendUrgentAsyncMessage(mOutgoing[2]++);
|
||||
|
||||
case 4: {
|
||||
DEMON_LOG("Start SendUrgentSyncMessage [%d]", mOutgoing[2]);
|
||||
bool r = SendUrgentSyncMessage(mOutgoing[2]++);
|
||||
switch (GetIPCChannel()->LastSendError()) {
|
||||
case SyncSendError::PreviousTimeout:
|
||||
case SyncSendError::SendingCPOWWhileDispatchingSync:
|
||||
case SyncSendError::SendingCPOWWhileDispatchingUrgent:
|
||||
case SyncSendError::NotConnectedBeforeSend:
|
||||
case SyncSendError::CancelledBeforeSend:
|
||||
mOutgoing[2]--;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
DEMON_LOG("End SendUrgentSyncMessage result=%d", r);
|
||||
return r;
|
||||
}
|
||||
|
||||
case 5:
|
||||
DEMON_LOG("Cancel");
|
||||
GetIPCChannel()->CancelCurrentTransaction();
|
||||
return true;
|
||||
}
|
||||
MOZ_CRASH();
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace _ipdltest
|
||||
} // namespace mozilla
|
||||
106
ipc/ipdl/test/cxx/TestDemon.h
Normal file
106
ipc/ipdl/test/cxx/TestDemon.h
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
#ifndef mozilla__ipdltest_TestDemon_h
|
||||
#define mozilla__ipdltest_TestDemon_h 1
|
||||
|
||||
#include "mozilla/_ipdltest/IPDLUnitTests.h"
|
||||
|
||||
#include "mozilla/_ipdltest/PTestDemonParent.h"
|
||||
#include "mozilla/_ipdltest/PTestDemonChild.h"
|
||||
|
||||
using namespace mozilla::ipc;
|
||||
|
||||
namespace mozilla {
|
||||
namespace _ipdltest {
|
||||
|
||||
|
||||
class TestDemonParent :
|
||||
public PTestDemonParent
|
||||
{
|
||||
public:
|
||||
TestDemonParent();
|
||||
virtual ~TestDemonParent();
|
||||
|
||||
static bool RunTestInProcesses() { return true; }
|
||||
static bool RunTestInThreads() { return true; }
|
||||
|
||||
void Main();
|
||||
|
||||
#ifdef DEBUG
|
||||
bool ShouldContinueFromReplyTimeout() override;
|
||||
bool ArtificialTimeout() override;
|
||||
|
||||
bool NeedArtificialSleep() override { return true; }
|
||||
void ArtificialSleep() override;
|
||||
#endif
|
||||
|
||||
bool RecvAsyncMessage(const int& n) override;
|
||||
bool RecvHiPrioSyncMessage() override;
|
||||
|
||||
bool RecvSyncMessage(const int& n) override;
|
||||
bool RecvUrgentAsyncMessage(const int& n) override;
|
||||
bool RecvUrgentSyncMessage(const int& n) override;
|
||||
|
||||
virtual void ActorDestroy(ActorDestroyReason why) override
|
||||
{
|
||||
mDone = true;
|
||||
printf("Parent ActorDestroy\n");
|
||||
passed("ok");
|
||||
QuitParent();
|
||||
}
|
||||
|
||||
private:
|
||||
bool mDone;
|
||||
int mIncoming[3];
|
||||
int mOutgoing[3];
|
||||
|
||||
enum {
|
||||
ASYNC_ONLY = 1,
|
||||
};
|
||||
|
||||
void RunUnlimitedSequence();
|
||||
void RunLimitedSequence(int flags = 0);
|
||||
bool DoAction(int flags = 0);
|
||||
};
|
||||
|
||||
|
||||
class TestDemonChild :
|
||||
public PTestDemonChild
|
||||
{
|
||||
public:
|
||||
TestDemonChild();
|
||||
virtual ~TestDemonChild();
|
||||
|
||||
bool RecvStart() override;
|
||||
|
||||
#ifdef DEBUG
|
||||
bool NeedArtificialSleep() override { return true; }
|
||||
void ArtificialSleep() override;
|
||||
#endif
|
||||
|
||||
bool RecvAsyncMessage(const int& n) override;
|
||||
bool RecvHiPrioSyncMessage() override;
|
||||
|
||||
virtual void ActorDestroy(ActorDestroyReason why) override
|
||||
{
|
||||
_exit(0);
|
||||
}
|
||||
|
||||
virtual void IntentionalCrash() override
|
||||
{
|
||||
_exit(0);
|
||||
}
|
||||
|
||||
private:
|
||||
int mIncoming[3];
|
||||
int mOutgoing[3];
|
||||
|
||||
void RunUnlimitedSequence();
|
||||
void RunLimitedSequence();
|
||||
bool DoAction();
|
||||
};
|
||||
|
||||
|
||||
} // namespace _ipdltest
|
||||
} // namespace mozilla
|
||||
|
||||
|
||||
#endif // ifndef mozilla__ipdltest_TestDemon_h
|
||||
105
ipc/ipdl/test/cxx/TestDesc.cpp
Normal file
105
ipc/ipdl/test/cxx/TestDesc.cpp
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
#include "TestDesc.h"
|
||||
|
||||
#include "IPDLUnitTests.h" // fail etc.
|
||||
|
||||
namespace mozilla {
|
||||
namespace _ipdltest {
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// parent
|
||||
void
|
||||
TestDescParent::Main()
|
||||
{
|
||||
PTestDescSubParent* p = CallPTestDescSubConstructor(0);
|
||||
if (!p)
|
||||
fail("can't allocate Sub");
|
||||
|
||||
PTestDescSubsubParent* pp = p->CallPTestDescSubsubConstructor();
|
||||
if (!pp)
|
||||
fail("can't allocate Subsub");
|
||||
|
||||
if (!SendTest(pp))
|
||||
fail("can't send Subsub");
|
||||
}
|
||||
|
||||
bool
|
||||
TestDescParent::RecvOk(PTestDescSubsubParent* a)
|
||||
{
|
||||
if (!a)
|
||||
fail("didn't receive Subsub");
|
||||
|
||||
if (!PTestDescSubsubParent::Call__delete__(a))
|
||||
fail("deleting Subsub");
|
||||
|
||||
Close();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
PTestDescSubParent*
|
||||
TestDescParent::AllocPTestDescSubParent(PTestDescSubsubParent* dummy) {
|
||||
if (dummy)
|
||||
fail("actor supposed to be null");
|
||||
return new TestDescSubParent();
|
||||
}
|
||||
bool
|
||||
TestDescParent::DeallocPTestDescSubParent(PTestDescSubParent* actor)
|
||||
{
|
||||
delete actor;
|
||||
return true;
|
||||
}
|
||||
|
||||
PTestDescSubsubParent*
|
||||
TestDescSubParent::AllocPTestDescSubsubParent()
|
||||
{
|
||||
return new TestDescSubsubParent();
|
||||
}
|
||||
bool
|
||||
TestDescSubParent::DeallocPTestDescSubsubParent(PTestDescSubsubParent* actor)
|
||||
{
|
||||
delete actor;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// child
|
||||
|
||||
bool
|
||||
TestDescChild::RecvTest(PTestDescSubsubChild* a)
|
||||
{
|
||||
if (!a)
|
||||
fail("didn't receive Subsub");
|
||||
if (!SendOk(a))
|
||||
fail("couldn't send Ok()");
|
||||
return true;
|
||||
}
|
||||
|
||||
PTestDescSubChild*
|
||||
TestDescChild::AllocPTestDescSubChild(PTestDescSubsubChild* dummy) {
|
||||
if (dummy)
|
||||
fail("actor supposed to be null");
|
||||
return new TestDescSubChild();
|
||||
}
|
||||
bool
|
||||
TestDescChild::DeallocPTestDescSubChild(PTestDescSubChild* actor)
|
||||
{
|
||||
delete actor;
|
||||
return true;
|
||||
}
|
||||
|
||||
PTestDescSubsubChild*
|
||||
TestDescSubChild::AllocPTestDescSubsubChild()
|
||||
{
|
||||
return new TestDescSubsubChild();
|
||||
}
|
||||
bool
|
||||
TestDescSubChild::DeallocPTestDescSubsubChild(PTestDescSubsubChild* actor)
|
||||
{
|
||||
delete actor;
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace _ipdltest
|
||||
} // namespace mozilla
|
||||
128
ipc/ipdl/test/cxx/TestDesc.h
Normal file
128
ipc/ipdl/test/cxx/TestDesc.h
Normal file
|
|
@ -0,0 +1,128 @@
|
|||
#ifndef mozilla_ipdltest_TestDesc_h
|
||||
#define mozilla_ipdltest_TestDesc_h
|
||||
|
||||
#include "mozilla/_ipdltest/IPDLUnitTests.h"
|
||||
|
||||
#include "mozilla/_ipdltest/PTestDescParent.h"
|
||||
#include "mozilla/_ipdltest/PTestDescChild.h"
|
||||
|
||||
#include "mozilla/_ipdltest/PTestDescSubParent.h"
|
||||
#include "mozilla/_ipdltest/PTestDescSubChild.h"
|
||||
|
||||
#include "mozilla/_ipdltest/PTestDescSubsubParent.h"
|
||||
#include "mozilla/_ipdltest/PTestDescSubsubChild.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace _ipdltest {
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Top-level
|
||||
//
|
||||
class TestDescParent :
|
||||
public PTestDescParent
|
||||
{
|
||||
public:
|
||||
TestDescParent() { }
|
||||
virtual ~TestDescParent() { }
|
||||
|
||||
static bool RunTestInProcesses() { return true; }
|
||||
static bool RunTestInThreads() { return true; }
|
||||
|
||||
void Main();
|
||||
|
||||
virtual bool RecvOk(PTestDescSubsubParent* a) override;
|
||||
|
||||
protected:
|
||||
virtual PTestDescSubParent* AllocPTestDescSubParent(PTestDescSubsubParent*) override;
|
||||
virtual bool DeallocPTestDescSubParent(PTestDescSubParent* actor) override;
|
||||
|
||||
virtual void ActorDestroy(ActorDestroyReason why) override
|
||||
{
|
||||
if (NormalShutdown != why)
|
||||
fail("unexpected destruction!");
|
||||
passed("ok");
|
||||
QuitParent();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class TestDescChild :
|
||||
public PTestDescChild
|
||||
{
|
||||
public:
|
||||
TestDescChild() { }
|
||||
virtual ~TestDescChild() { }
|
||||
|
||||
protected:
|
||||
virtual PTestDescSubChild* AllocPTestDescSubChild(PTestDescSubsubChild*) override;
|
||||
|
||||
virtual bool DeallocPTestDescSubChild(PTestDescSubChild* actor) override;
|
||||
|
||||
virtual bool RecvTest(PTestDescSubsubChild* a) override;
|
||||
|
||||
virtual void ActorDestroy(ActorDestroyReason why) override
|
||||
{
|
||||
if (NormalShutdown != why)
|
||||
fail("unexpected destruction!");
|
||||
QuitChild();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// First descendent
|
||||
//
|
||||
class TestDescSubParent :
|
||||
public PTestDescSubParent
|
||||
{
|
||||
public:
|
||||
TestDescSubParent() { }
|
||||
virtual ~TestDescSubParent() { }
|
||||
|
||||
protected:
|
||||
virtual void ActorDestroy(ActorDestroyReason why) override {}
|
||||
virtual PTestDescSubsubParent* AllocPTestDescSubsubParent() override;
|
||||
virtual bool DeallocPTestDescSubsubParent(PTestDescSubsubParent* actor) override;
|
||||
};
|
||||
|
||||
|
||||
class TestDescSubChild :
|
||||
public PTestDescSubChild
|
||||
{
|
||||
public:
|
||||
TestDescSubChild() { }
|
||||
virtual ~TestDescSubChild() { }
|
||||
|
||||
protected:
|
||||
virtual PTestDescSubsubChild* AllocPTestDescSubsubChild() override;
|
||||
virtual bool DeallocPTestDescSubsubChild(PTestDescSubsubChild* actor) override;
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Grand-descendent
|
||||
//
|
||||
class TestDescSubsubParent :
|
||||
public PTestDescSubsubParent
|
||||
{
|
||||
public:
|
||||
TestDescSubsubParent() { }
|
||||
virtual ~TestDescSubsubParent() { }
|
||||
|
||||
protected:
|
||||
virtual void ActorDestroy(ActorDestroyReason why) override {}
|
||||
};
|
||||
|
||||
class TestDescSubsubChild :
|
||||
public PTestDescSubsubChild
|
||||
{
|
||||
public:
|
||||
TestDescSubsubChild() { }
|
||||
virtual ~TestDescSubsubChild() { }
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif // ifndef mozilla_ipdltest_TestDesc_h
|
||||
257
ipc/ipdl/test/cxx/TestEndpointBridgeMain.cpp
Normal file
257
ipc/ipdl/test/cxx/TestEndpointBridgeMain.cpp
Normal file
|
|
@ -0,0 +1,257 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
|
||||
#include "TestEndpointBridgeMain.h"
|
||||
|
||||
#include "base/task.h"
|
||||
#include "IPDLUnitTests.h" // fail etc.
|
||||
#include "IPDLUnitTestSubprocess.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace mozilla {
|
||||
namespace _ipdltest {
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// main process
|
||||
void
|
||||
TestEndpointBridgeMainParent::Main()
|
||||
{
|
||||
if (!SendStart()) {
|
||||
fail("sending Start");
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
TestEndpointBridgeMainParent::RecvBridged(Endpoint<PTestEndpointBridgeMainSubParent>&& endpoint)
|
||||
{
|
||||
TestEndpointBridgeMainSubParent* a = new TestEndpointBridgeMainSubParent();
|
||||
if (!endpoint.Bind(a)) {
|
||||
fail("Bind failed");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
TestEndpointBridgeMainParent::ActorDestroy(ActorDestroyReason why)
|
||||
{
|
||||
if (NormalShutdown != why) {
|
||||
fail("unexpected destruction!");
|
||||
}
|
||||
passed("ok");
|
||||
QuitParent();
|
||||
}
|
||||
|
||||
bool
|
||||
TestEndpointBridgeMainSubParent::RecvHello()
|
||||
{
|
||||
return SendHi();
|
||||
}
|
||||
|
||||
bool
|
||||
TestEndpointBridgeMainSubParent::RecvHelloSync()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
TestEndpointBridgeMainSubParent::AnswerHelloRpc()
|
||||
{
|
||||
return CallHiRpc();
|
||||
}
|
||||
|
||||
void
|
||||
TestEndpointBridgeMainSubParent::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<TestEndpointBridgeMainSubParent>(this)));
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// sub process --- child of main
|
||||
TestEndpointBridgeMainChild* gEndpointBridgeMainChild;
|
||||
|
||||
TestEndpointBridgeMainChild::TestEndpointBridgeMainChild()
|
||||
: mSubprocess(nullptr)
|
||||
{
|
||||
gEndpointBridgeMainChild = this;
|
||||
}
|
||||
|
||||
bool
|
||||
TestEndpointBridgeMainChild::RecvStart()
|
||||
{
|
||||
vector<string> subsubArgs;
|
||||
subsubArgs.push_back("TestEndpointBridgeSub");
|
||||
|
||||
mSubprocess = new IPDLUnitTestSubprocess();
|
||||
if (!mSubprocess->SyncLaunch(subsubArgs)) {
|
||||
fail("problem launching subprocess");
|
||||
}
|
||||
|
||||
IPC::Channel* transport = mSubprocess->GetChannel();
|
||||
if (!transport) {
|
||||
fail("no transport");
|
||||
}
|
||||
|
||||
TestEndpointBridgeSubParent* bsp = new TestEndpointBridgeSubParent();
|
||||
bsp->Open(transport, base::GetProcId(mSubprocess->GetChildProcessHandle()));
|
||||
|
||||
bsp->Main();
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
TestEndpointBridgeMainChild::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
|
||||
TestEndpointBridgeSubParent::Main()
|
||||
{
|
||||
if (!SendPing()) {
|
||||
fail("sending Ping");
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
TestEndpointBridgeSubParent::RecvBridgeEm()
|
||||
{
|
||||
Endpoint<PTestEndpointBridgeMainSubParent> parent;
|
||||
Endpoint<PTestEndpointBridgeMainSubChild> child;
|
||||
nsresult rv;
|
||||
rv = PTestEndpointBridgeMainSub::CreateEndpoints(
|
||||
gEndpointBridgeMainChild->OtherPid(), OtherPid(),
|
||||
&parent, &child);
|
||||
if (NS_FAILED(rv)) {
|
||||
fail("opening PTestEndpointOpensOpened");
|
||||
}
|
||||
|
||||
if (!gEndpointBridgeMainChild->SendBridged(mozilla::Move(parent))) {
|
||||
fail("SendBridge failed for parent");
|
||||
}
|
||||
if (!SendBridged(mozilla::Move(child))) {
|
||||
fail("SendBridge failed for child");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
TestEndpointBridgeSubParent::ActorDestroy(ActorDestroyReason why)
|
||||
{
|
||||
if (NormalShutdown != why) {
|
||||
fail("unexpected destruction!");
|
||||
}
|
||||
gEndpointBridgeMainChild->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<TestEndpointBridgeSubParent>(this)));
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// subsub process --- child of sub
|
||||
|
||||
static TestEndpointBridgeSubChild* gBridgeSubChild;
|
||||
|
||||
TestEndpointBridgeSubChild::TestEndpointBridgeSubChild()
|
||||
{
|
||||
gBridgeSubChild = this;
|
||||
}
|
||||
|
||||
bool
|
||||
TestEndpointBridgeSubChild::RecvPing()
|
||||
{
|
||||
if (!SendBridgeEm()) {
|
||||
fail("sending BridgeEm");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
TestEndpointBridgeSubChild::RecvBridged(Endpoint<PTestEndpointBridgeMainSubChild>&& endpoint)
|
||||
{
|
||||
TestEndpointBridgeMainSubChild* a = new TestEndpointBridgeMainSubChild();
|
||||
|
||||
if (!endpoint.Bind(a)) {
|
||||
fail("failed to Bind");
|
||||
}
|
||||
|
||||
if (!a->SendHello()) {
|
||||
fail("sending Hello");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
TestEndpointBridgeSubChild::ActorDestroy(ActorDestroyReason why)
|
||||
{
|
||||
if (NormalShutdown != why) {
|
||||
fail("unexpected destruction!");
|
||||
}
|
||||
QuitChild();
|
||||
}
|
||||
|
||||
bool
|
||||
TestEndpointBridgeMainSubChild::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, &TestEndpointBridgeMainSubChild::Close));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
TestEndpointBridgeMainSubChild::AnswerHiRpc()
|
||||
{
|
||||
mGotHi = true; // d00d
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
TestEndpointBridgeMainSubChild::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<TestEndpointBridgeMainSubChild>(this)));
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
} // namespace _ipdltest
|
||||
133
ipc/ipdl/test/cxx/TestEndpointBridgeMain.h
Normal file
133
ipc/ipdl/test/cxx/TestEndpointBridgeMain.h
Normal file
|
|
@ -0,0 +1,133 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
|
||||
#ifndef mozilla__ipdltest_TestEndpointBridgeMain_h
|
||||
#define mozilla__ipdltest_TestEndpointBridgeMain_h 1
|
||||
|
||||
#include "mozilla/_ipdltest/IPDLUnitTests.h"
|
||||
|
||||
#include "mozilla/_ipdltest/PTestEndpointBridgeMainParent.h"
|
||||
#include "mozilla/_ipdltest/PTestEndpointBridgeMainChild.h"
|
||||
|
||||
#include "mozilla/_ipdltest/PTestEndpointBridgeSubParent.h"
|
||||
#include "mozilla/_ipdltest/PTestEndpointBridgeSubChild.h"
|
||||
|
||||
#include "mozilla/_ipdltest/PTestEndpointBridgeMainSubParent.h"
|
||||
#include "mozilla/_ipdltest/PTestEndpointBridgeMainSubChild.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace _ipdltest {
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// "Main" process
|
||||
//
|
||||
class TestEndpointBridgeMainParent :
|
||||
public PTestEndpointBridgeMainParent
|
||||
{
|
||||
public:
|
||||
TestEndpointBridgeMainParent() {}
|
||||
virtual ~TestEndpointBridgeMainParent() {}
|
||||
|
||||
static bool RunTestInProcesses() { return true; }
|
||||
static bool RunTestInThreads() { return false; }
|
||||
|
||||
void Main();
|
||||
|
||||
protected:
|
||||
bool RecvBridged(mozilla::ipc::Endpoint<PTestEndpointBridgeMainSubParent>&& endpoint) override;
|
||||
|
||||
virtual void ActorDestroy(ActorDestroyReason why) override;
|
||||
};
|
||||
|
||||
class TestEndpointBridgeMainSubParent :
|
||||
public PTestEndpointBridgeMainSubParent
|
||||
{
|
||||
public:
|
||||
explicit TestEndpointBridgeMainSubParent()
|
||||
{}
|
||||
virtual ~TestEndpointBridgeMainSubParent() {}
|
||||
|
||||
protected:
|
||||
virtual bool RecvHello() override;
|
||||
virtual bool RecvHelloSync() override;
|
||||
virtual bool AnswerHelloRpc() override;
|
||||
|
||||
virtual void ActorDestroy(ActorDestroyReason why) override;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// "Sub" process --- child of "main"
|
||||
//
|
||||
class TestEndpointBridgeSubParent;
|
||||
|
||||
class TestEndpointBridgeMainChild :
|
||||
public PTestEndpointBridgeMainChild
|
||||
{
|
||||
public:
|
||||
TestEndpointBridgeMainChild();
|
||||
virtual ~TestEndpointBridgeMainChild() {}
|
||||
|
||||
protected:
|
||||
virtual bool RecvStart() override;
|
||||
|
||||
virtual void ActorDestroy(ActorDestroyReason why) override;
|
||||
|
||||
IPDLUnitTestSubprocess* mSubprocess;
|
||||
};
|
||||
|
||||
class TestEndpointBridgeSubParent :
|
||||
public PTestEndpointBridgeSubParent
|
||||
{
|
||||
public:
|
||||
TestEndpointBridgeSubParent() {}
|
||||
virtual ~TestEndpointBridgeSubParent() {}
|
||||
|
||||
void Main();
|
||||
|
||||
protected:
|
||||
virtual bool RecvBridgeEm() override;
|
||||
|
||||
virtual void ActorDestroy(ActorDestroyReason why) override;
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// "Subsub" process --- child of "sub"
|
||||
//
|
||||
class TestEndpointBridgeSubChild :
|
||||
public PTestEndpointBridgeSubChild
|
||||
{
|
||||
public:
|
||||
TestEndpointBridgeSubChild();
|
||||
virtual ~TestEndpointBridgeSubChild() {}
|
||||
|
||||
protected:
|
||||
virtual bool RecvPing() override;
|
||||
|
||||
bool RecvBridged(Endpoint<PTestEndpointBridgeMainSubChild>&& endpoint) override;
|
||||
|
||||
virtual void ActorDestroy(ActorDestroyReason why) override;
|
||||
};
|
||||
|
||||
class TestEndpointBridgeMainSubChild :
|
||||
public PTestEndpointBridgeMainSubChild
|
||||
{
|
||||
public:
|
||||
explicit TestEndpointBridgeMainSubChild()
|
||||
: mGotHi(false)
|
||||
{}
|
||||
virtual ~TestEndpointBridgeMainSubChild() {}
|
||||
|
||||
protected:
|
||||
virtual bool RecvHi() override;
|
||||
virtual bool AnswerHiRpc() override;
|
||||
|
||||
virtual void ActorDestroy(ActorDestroyReason why) override;
|
||||
|
||||
bool mGotHi;
|
||||
};
|
||||
|
||||
} // namespace _ipdltest
|
||||
} // namespace mozilla
|
||||
|
||||
|
||||
#endif // ifndef mozilla__ipdltest_TestEndpointBridgeMain_h
|
||||
271
ipc/ipdl/test/cxx/TestEndpointOpens.cpp
Normal file
271
ipc/ipdl/test/cxx/TestEndpointOpens.cpp
Normal file
|
|
@ -0,0 +1,271 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
|
||||
#include "base/task.h"
|
||||
#include "base/thread.h"
|
||||
|
||||
#include "TestEndpointOpens.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 TestEndpointOpensOpenedParent runs
|
||||
static Thread* gParentThread;
|
||||
|
||||
void
|
||||
TestEndpointOpensParent::Main()
|
||||
{
|
||||
if (!SendStart()) {
|
||||
fail("sending Start");
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
OpenParent(TestEndpointOpensOpenedParent* aParent,
|
||||
Endpoint<PTestEndpointOpensOpenedParent>&& aEndpoint)
|
||||
{
|
||||
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 (!aEndpoint.Bind(aParent)) {
|
||||
fail("binding Parent");
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
TestEndpointOpensParent::RecvStartSubprotocol(
|
||||
mozilla::ipc::Endpoint<PTestEndpointOpensOpenedParent>&& endpoint)
|
||||
{
|
||||
gMainThread = MessageLoop::current();
|
||||
|
||||
gParentThread = new Thread("ParentThread");
|
||||
if (!gParentThread->Start()) {
|
||||
fail("starting parent thread");
|
||||
}
|
||||
|
||||
TestEndpointOpensOpenedParent* a = new TestEndpointOpensOpenedParent();
|
||||
gParentThread->message_loop()->PostTask(
|
||||
NewRunnableFunction(OpenParent, a, mozilla::Move(endpoint)));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
TestEndpointOpensParent::ActorDestroy(ActorDestroyReason why)
|
||||
{
|
||||
// Stops the thread and joins it
|
||||
delete gParentThread;
|
||||
|
||||
if (NormalShutdown != why) {
|
||||
fail("unexpected destruction A!");
|
||||
}
|
||||
passed("ok");
|
||||
QuitParent();
|
||||
}
|
||||
|
||||
bool
|
||||
TestEndpointOpensOpenedParent::RecvHello()
|
||||
{
|
||||
AssertNotMainThread();
|
||||
return SendHi();
|
||||
}
|
||||
|
||||
bool
|
||||
TestEndpointOpensOpenedParent::RecvHelloSync()
|
||||
{
|
||||
AssertNotMainThread();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
TestEndpointOpensOpenedParent::AnswerHelloRpc()
|
||||
{
|
||||
AssertNotMainThread();
|
||||
return CallHiRpc();
|
||||
}
|
||||
|
||||
static void
|
||||
ShutdownTestEndpointOpensOpenedParent(TestEndpointOpensOpenedParent* parent,
|
||||
Transport* transport)
|
||||
{
|
||||
delete parent;
|
||||
}
|
||||
|
||||
void
|
||||
TestEndpointOpensOpenedParent::ActorDestroy(ActorDestroyReason why)
|
||||
{
|
||||
AssertNotMainThread();
|
||||
|
||||
if (NormalShutdown != why) {
|
||||
fail("unexpected destruction B!");
|
||||
}
|
||||
|
||||
// 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(ShutdownTestEndpointOpensOpenedParent,
|
||||
this, GetTransport()));
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// child
|
||||
|
||||
static TestEndpointOpensChild* gOpensChild;
|
||||
// Thread on which TestEndpointOpensOpenedChild runs
|
||||
static Thread* gChildThread;
|
||||
|
||||
TestEndpointOpensChild::TestEndpointOpensChild()
|
||||
{
|
||||
gOpensChild = this;
|
||||
}
|
||||
|
||||
static void
|
||||
OpenChild(TestEndpointOpensOpenedChild* aChild,
|
||||
Endpoint<PTestEndpointOpensOpenedChild>&& endpoint)
|
||||
{
|
||||
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 (!endpoint.Bind(aChild)) {
|
||||
fail("binding child endpoint");
|
||||
}
|
||||
|
||||
// Kick off the unit tests
|
||||
if (!aChild->SendHello()) {
|
||||
fail("sending Hello");
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
TestEndpointOpensChild::RecvStart()
|
||||
{
|
||||
Endpoint<PTestEndpointOpensOpenedParent> parent;
|
||||
Endpoint<PTestEndpointOpensOpenedChild> child;
|
||||
nsresult rv;
|
||||
rv = PTestEndpointOpensOpened::CreateEndpoints(OtherPid(), base::GetCurrentProcId(),
|
||||
&parent, &child);
|
||||
if (NS_FAILED(rv)) {
|
||||
fail("opening PTestEndpointOpensOpened");
|
||||
}
|
||||
|
||||
gMainThread = MessageLoop::current();
|
||||
|
||||
gChildThread = new Thread("ChildThread");
|
||||
if (!gChildThread->Start()) {
|
||||
fail("starting child thread");
|
||||
}
|
||||
|
||||
TestEndpointOpensOpenedChild* a = new TestEndpointOpensOpenedChild();
|
||||
gChildThread->message_loop()->PostTask(
|
||||
NewRunnableFunction(OpenChild, a, mozilla::Move(child)));
|
||||
|
||||
if (!SendStartSubprotocol(parent)) {
|
||||
fail("send StartSubprotocol");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
TestEndpointOpensChild::ActorDestroy(ActorDestroyReason why)
|
||||
{
|
||||
// Stops the thread and joins it
|
||||
delete gChildThread;
|
||||
|
||||
if (NormalShutdown != why) {
|
||||
fail("unexpected destruction C!");
|
||||
}
|
||||
QuitChild();
|
||||
}
|
||||
|
||||
bool
|
||||
TestEndpointOpensOpenedChild::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, &TestEndpointOpensOpenedChild::Close));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
TestEndpointOpensOpenedChild::AnswerHiRpc()
|
||||
{
|
||||
AssertNotMainThread();
|
||||
|
||||
mGotHi = true; // d00d
|
||||
return true;
|
||||
}
|
||||
|
||||
static void
|
||||
ShutdownTestEndpointOpensOpenedChild(TestEndpointOpensOpenedChild* child,
|
||||
Transport* transport)
|
||||
{
|
||||
delete child;
|
||||
|
||||
// Kick off main-thread shutdown.
|
||||
gMainThread->PostTask(
|
||||
NewNonOwningRunnableMethod(gOpensChild, &TestEndpointOpensChild::Close));
|
||||
}
|
||||
|
||||
void
|
||||
TestEndpointOpensOpenedChild::ActorDestroy(ActorDestroyReason why)
|
||||
{
|
||||
AssertNotMainThread();
|
||||
|
||||
if (NormalShutdown != why) {
|
||||
fail("unexpected destruction D!");
|
||||
}
|
||||
|
||||
// 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(ShutdownTestEndpointOpensOpenedChild,
|
||||
this, GetTransport()));
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
101
ipc/ipdl/test/cxx/TestEndpointOpens.h
Normal file
101
ipc/ipdl/test/cxx/TestEndpointOpens.h
Normal file
|
|
@ -0,0 +1,101 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
|
||||
#ifndef mozilla__ipdltest_TestEndpointOpens_h
|
||||
#define mozilla__ipdltest_TestEndpointOpens_h 1
|
||||
|
||||
#include "mozilla/_ipdltest/IPDLUnitTests.h"
|
||||
|
||||
#include "mozilla/_ipdltest/PTestEndpointOpensParent.h"
|
||||
#include "mozilla/_ipdltest/PTestEndpointOpensChild.h"
|
||||
|
||||
#include "mozilla/_ipdltest2/PTestEndpointOpensOpenedParent.h"
|
||||
#include "mozilla/_ipdltest2/PTestEndpointOpensOpenedChild.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
// parent process
|
||||
|
||||
namespace _ipdltest {
|
||||
|
||||
class TestEndpointOpensParent : public PTestEndpointOpensParent
|
||||
{
|
||||
public:
|
||||
TestEndpointOpensParent() {}
|
||||
virtual ~TestEndpointOpensParent() {}
|
||||
|
||||
static bool RunTestInProcesses() { return true; }
|
||||
static bool RunTestInThreads() { return false; }
|
||||
|
||||
void Main();
|
||||
|
||||
protected:
|
||||
virtual bool RecvStartSubprotocol(mozilla::ipc::Endpoint<PTestEndpointOpensOpenedParent>&& endpoint);
|
||||
|
||||
virtual void ActorDestroy(ActorDestroyReason why) override;
|
||||
};
|
||||
|
||||
} // namespace _ipdltest
|
||||
|
||||
namespace _ipdltest2 {
|
||||
|
||||
class TestEndpointOpensOpenedParent : public PTestEndpointOpensOpenedParent
|
||||
{
|
||||
public:
|
||||
explicit TestEndpointOpensOpenedParent()
|
||||
{}
|
||||
virtual ~TestEndpointOpensOpenedParent() {}
|
||||
|
||||
protected:
|
||||
virtual bool RecvHello() override;
|
||||
virtual bool RecvHelloSync() override;
|
||||
virtual bool AnswerHelloRpc() override;
|
||||
|
||||
virtual void ActorDestroy(ActorDestroyReason why) override;
|
||||
};
|
||||
|
||||
} // namespace _ipdltest2
|
||||
|
||||
// child process
|
||||
|
||||
namespace _ipdltest {
|
||||
|
||||
class TestEndpointOpensChild : public PTestEndpointOpensChild
|
||||
{
|
||||
public:
|
||||
TestEndpointOpensChild();
|
||||
virtual ~TestEndpointOpensChild() {}
|
||||
|
||||
protected:
|
||||
virtual bool RecvStart() override;
|
||||
|
||||
virtual void ActorDestroy(ActorDestroyReason why) override;
|
||||
};
|
||||
|
||||
} // namespace _ipdltest
|
||||
|
||||
namespace _ipdltest2 {
|
||||
|
||||
class TestEndpointOpensOpenedChild : public PTestEndpointOpensOpenedChild
|
||||
{
|
||||
public:
|
||||
explicit TestEndpointOpensOpenedChild()
|
||||
: mGotHi(false)
|
||||
{}
|
||||
virtual ~TestEndpointOpensOpenedChild() {}
|
||||
|
||||
protected:
|
||||
virtual bool RecvHi() override;
|
||||
virtual bool AnswerHiRpc() override;
|
||||
|
||||
virtual void ActorDestroy(ActorDestroyReason why) override;
|
||||
|
||||
bool mGotHi;
|
||||
};
|
||||
|
||||
} // namespace _ipdltest2
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
|
||||
#endif // ifndef mozilla__ipdltest_TestEndpointOpens_h
|
||||
137
ipc/ipdl/test/cxx/TestFailedCtor.cpp
Normal file
137
ipc/ipdl/test/cxx/TestFailedCtor.cpp
Normal file
|
|
@ -0,0 +1,137 @@
|
|||
#include "TestFailedCtor.h"
|
||||
|
||||
#include "IPDLUnitTests.h" // fail etc.
|
||||
|
||||
namespace mozilla {
|
||||
namespace _ipdltest {
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// parent
|
||||
void
|
||||
TestFailedCtorParent::Main()
|
||||
{
|
||||
PTestFailedCtorSubParent* p = CallPTestFailedCtorSubConstructor();
|
||||
if (p)
|
||||
fail("expected ctor to fail");
|
||||
|
||||
Close();
|
||||
}
|
||||
|
||||
PTestFailedCtorSubParent*
|
||||
TestFailedCtorParent::AllocPTestFailedCtorSubParent()
|
||||
{
|
||||
return new TestFailedCtorSubParent();
|
||||
}
|
||||
bool
|
||||
TestFailedCtorParent::DeallocPTestFailedCtorSubParent(PTestFailedCtorSubParent* actor)
|
||||
{
|
||||
delete actor;
|
||||
return true;
|
||||
}
|
||||
|
||||
PTestFailedCtorSubsubParent*
|
||||
TestFailedCtorSubParent::AllocPTestFailedCtorSubsubParent()
|
||||
{
|
||||
TestFailedCtorSubsub* a = new TestFailedCtorSubsub();
|
||||
if (!mOne) {
|
||||
return mOne = a;
|
||||
} else if (!mTwo) {
|
||||
return mTwo = a;
|
||||
} else if (!mThree) {
|
||||
return mThree = a;
|
||||
} else {
|
||||
fail("unexpected Alloc()");
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
bool
|
||||
TestFailedCtorSubParent::DeallocPTestFailedCtorSubsubParent(PTestFailedCtorSubsubParent* actor)
|
||||
{
|
||||
static_cast<TestFailedCtorSubsub*>(actor)->mDealloced = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
TestFailedCtorSubParent::ActorDestroy(ActorDestroyReason why)
|
||||
{
|
||||
|
||||
if (mOne->mWhy != Deletion)
|
||||
fail("Subsub one got wrong ActorDestroyReason");
|
||||
if (mTwo->mWhy != AncestorDeletion)
|
||||
fail("Subsub two got wrong ActorDestroyReason");
|
||||
if (mThree->mWhy != AncestorDeletion)
|
||||
fail("Subsub three got wrong ActorDestroyReason");
|
||||
|
||||
if (FailedConstructor != why)
|
||||
fail("unexpected destruction!");
|
||||
}
|
||||
|
||||
TestFailedCtorSubParent::~TestFailedCtorSubParent()
|
||||
{
|
||||
if (!(mOne->mDealloced && mTwo->mDealloced && mThree->mDealloced))
|
||||
fail("Not all subsubs were Dealloc'd");
|
||||
delete mOne;
|
||||
delete mTwo;
|
||||
delete mThree;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// child
|
||||
|
||||
PTestFailedCtorSubChild*
|
||||
TestFailedCtorChild::AllocPTestFailedCtorSubChild()
|
||||
{
|
||||
return new TestFailedCtorSubChild();
|
||||
}
|
||||
|
||||
bool
|
||||
TestFailedCtorChild::AnswerPTestFailedCtorSubConstructor(PTestFailedCtorSubChild* actor)
|
||||
{
|
||||
PTestFailedCtorSubsubChild* c1 = actor->SendPTestFailedCtorSubsubConstructor();
|
||||
PTestFailedCtorSubsubChild::Send__delete__(c1);
|
||||
|
||||
if (!actor->SendPTestFailedCtorSubsubConstructor() ||
|
||||
!actor->SendPTestFailedCtorSubsubConstructor() ||
|
||||
!actor->SendSync())
|
||||
fail("setting up test");
|
||||
|
||||
// This causes our process to die
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
TestFailedCtorChild::DeallocPTestFailedCtorSubChild(PTestFailedCtorSubChild* actor)
|
||||
{
|
||||
delete actor;
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
TestFailedCtorChild::ProcessingError(Result aCode, const char* aReason)
|
||||
{
|
||||
if (OtherPid() != base::GetCurrentProcId()) // thread-mode
|
||||
_exit(0);
|
||||
}
|
||||
|
||||
PTestFailedCtorSubsubChild*
|
||||
TestFailedCtorSubChild::AllocPTestFailedCtorSubsubChild()
|
||||
{
|
||||
return new TestFailedCtorSubsub();
|
||||
}
|
||||
|
||||
bool
|
||||
TestFailedCtorSubChild::DeallocPTestFailedCtorSubsubChild(PTestFailedCtorSubsubChild* actor)
|
||||
{
|
||||
delete actor;
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
TestFailedCtorSubChild::ActorDestroy(ActorDestroyReason why)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
} // namespace _ipdltest
|
||||
} // namespace mozilla
|
||||
136
ipc/ipdl/test/cxx/TestFailedCtor.h
Normal file
136
ipc/ipdl/test/cxx/TestFailedCtor.h
Normal file
|
|
@ -0,0 +1,136 @@
|
|||
#ifndef mozilla_ipdltest_TestFailedCtor_h
|
||||
#define mozilla_ipdltest_TestFailedCtor_h
|
||||
|
||||
#include "mozilla/_ipdltest/IPDLUnitTests.h"
|
||||
|
||||
#include "mozilla/_ipdltest/PTestFailedCtorParent.h"
|
||||
#include "mozilla/_ipdltest/PTestFailedCtorChild.h"
|
||||
|
||||
#include "mozilla/_ipdltest/PTestFailedCtorSubParent.h"
|
||||
#include "mozilla/_ipdltest/PTestFailedCtorSubChild.h"
|
||||
|
||||
#include "mozilla/_ipdltest/PTestFailedCtorSubsubParent.h"
|
||||
#include "mozilla/_ipdltest/PTestFailedCtorSubsubChild.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace _ipdltest {
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Top-level
|
||||
//
|
||||
class TestFailedCtorParent :
|
||||
public PTestFailedCtorParent
|
||||
{
|
||||
public:
|
||||
TestFailedCtorParent() { }
|
||||
virtual ~TestFailedCtorParent() { }
|
||||
|
||||
static bool RunTestInProcesses() { return true; }
|
||||
|
||||
// FIXME/bug 703322 Disabled because child calls exit() to end
|
||||
// test, not clear how to handle failed ctor in
|
||||
// threaded mode.
|
||||
static bool RunTestInThreads() { return false; }
|
||||
|
||||
void Main();
|
||||
|
||||
protected:
|
||||
virtual PTestFailedCtorSubParent* AllocPTestFailedCtorSubParent() override;
|
||||
virtual bool DeallocPTestFailedCtorSubParent(PTestFailedCtorSubParent* actor) override;
|
||||
|
||||
virtual void ActorDestroy(ActorDestroyReason why) override
|
||||
{
|
||||
if (AbnormalShutdown != why)
|
||||
fail("unexpected destruction!");
|
||||
passed("ok");
|
||||
QuitParent();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class TestFailedCtorChild :
|
||||
public PTestFailedCtorChild
|
||||
{
|
||||
public:
|
||||
TestFailedCtorChild() { }
|
||||
virtual ~TestFailedCtorChild() { }
|
||||
|
||||
protected:
|
||||
virtual PTestFailedCtorSubChild* AllocPTestFailedCtorSubChild() override;
|
||||
|
||||
virtual bool AnswerPTestFailedCtorSubConstructor(PTestFailedCtorSubChild* actor) override;
|
||||
|
||||
virtual bool DeallocPTestFailedCtorSubChild(PTestFailedCtorSubChild* actor) override;
|
||||
|
||||
virtual void ProcessingError(Result aCode, const char* aReason) override;
|
||||
|
||||
virtual void ActorDestroy(ActorDestroyReason why) override
|
||||
{
|
||||
fail("should have _exit()ed");
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// First descendent
|
||||
//
|
||||
class TestFailedCtorSubsub;
|
||||
|
||||
class TestFailedCtorSubParent :
|
||||
public PTestFailedCtorSubParent
|
||||
{
|
||||
public:
|
||||
TestFailedCtorSubParent() : mOne(nullptr), mTwo(nullptr), mThree(nullptr) { }
|
||||
virtual ~TestFailedCtorSubParent();
|
||||
|
||||
protected:
|
||||
virtual PTestFailedCtorSubsubParent* AllocPTestFailedCtorSubsubParent() override;
|
||||
|
||||
virtual bool DeallocPTestFailedCtorSubsubParent(PTestFailedCtorSubsubParent* actor) override;
|
||||
virtual bool RecvSync() override { return true; }
|
||||
|
||||
virtual void ActorDestroy(ActorDestroyReason why) override;
|
||||
|
||||
TestFailedCtorSubsub* mOne;
|
||||
TestFailedCtorSubsub* mTwo;
|
||||
TestFailedCtorSubsub* mThree;
|
||||
};
|
||||
|
||||
|
||||
class TestFailedCtorSubChild :
|
||||
public PTestFailedCtorSubChild
|
||||
{
|
||||
public:
|
||||
TestFailedCtorSubChild() { }
|
||||
virtual ~TestFailedCtorSubChild() { }
|
||||
|
||||
protected:
|
||||
virtual PTestFailedCtorSubsubChild* AllocPTestFailedCtorSubsubChild() override;
|
||||
virtual bool DeallocPTestFailedCtorSubsubChild(PTestFailedCtorSubsubChild* actor) override;
|
||||
|
||||
virtual void ActorDestroy(ActorDestroyReason why) override;
|
||||
};
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Grand-descendent
|
||||
//
|
||||
class TestFailedCtorSubsub :
|
||||
public PTestFailedCtorSubsubParent,
|
||||
public PTestFailedCtorSubsubChild
|
||||
{
|
||||
public:
|
||||
TestFailedCtorSubsub() : mWhy(ActorDestroyReason(-1)), mDealloced(false) {}
|
||||
virtual ~TestFailedCtorSubsub() {}
|
||||
|
||||
virtual void ActorDestroy(ActorDestroyReason why) override { mWhy = why; }
|
||||
|
||||
ActorDestroyReason mWhy;
|
||||
bool mDealloced;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif // ifndef mozilla_ipdltest_TestFailedCtor_h
|
||||
146
ipc/ipdl/test/cxx/TestHangs.cpp
Normal file
146
ipc/ipdl/test/cxx/TestHangs.cpp
Normal file
|
|
@ -0,0 +1,146 @@
|
|||
#include "base/process_util.h"
|
||||
|
||||
#include "TestHangs.h"
|
||||
|
||||
#include "IPDLUnitTests.h" // fail etc.
|
||||
|
||||
using base::KillProcess;
|
||||
|
||||
namespace mozilla {
|
||||
namespace _ipdltest {
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// parent
|
||||
|
||||
TestHangsParent::TestHangsParent() : mDetectedHang(false)
|
||||
{
|
||||
MOZ_COUNT_CTOR(TestHangsParent);
|
||||
}
|
||||
|
||||
TestHangsParent::~TestHangsParent()
|
||||
{
|
||||
MOZ_COUNT_DTOR(TestHangsParent);
|
||||
}
|
||||
|
||||
void
|
||||
TestHangsParent::Main()
|
||||
{
|
||||
// Here we try to set things up to test the following sequence of events:
|
||||
//
|
||||
// - subprocess causes an OnMaybeDequeueOne() task to be posted to
|
||||
// this thread
|
||||
//
|
||||
// - subprocess hangs just long enough for the hang timer to expire
|
||||
//
|
||||
// - hang-kill code in the parent starts running
|
||||
//
|
||||
// - subprocess replies to message while hang code runs
|
||||
//
|
||||
// - reply is processed in OnMaybeDequeueOne() before Close() has
|
||||
// been called or the channel error notification has been posted
|
||||
|
||||
// this tells the subprocess to send us Nonce()
|
||||
if (!SendStart())
|
||||
fail("sending Start");
|
||||
|
||||
// now we sleep here for a while awaiting the Nonce() message from
|
||||
// the child. since we're not blocked on anything, the IO thread
|
||||
// will enqueue an OnMaybeDequeueOne() task to process that
|
||||
// message
|
||||
//
|
||||
// NB: PR_Sleep is exactly what we want, only the current thread
|
||||
// sleeping
|
||||
PR_Sleep(5000);
|
||||
|
||||
// when we call into this, we'll pull the Nonce() message out of
|
||||
// the mPending queue, but that doesn't matter ... the
|
||||
// OnMaybeDequeueOne() event will remain
|
||||
if (CallStackFrame() && mDetectedHang)
|
||||
fail("should have timed out!");
|
||||
|
||||
// the Close() task in the queue will shut us down
|
||||
}
|
||||
|
||||
bool
|
||||
TestHangsParent::ShouldContinueFromReplyTimeout()
|
||||
{
|
||||
mDetectedHang = true;
|
||||
|
||||
// so we've detected a timeout after 2 ms ... now we cheat and
|
||||
// sleep for a long time, to allow the subprocess's reply to come
|
||||
// in
|
||||
|
||||
PR_Sleep(5000);
|
||||
|
||||
// reply should be here; we'll post a task to shut things down.
|
||||
// This must be after OnMaybeDequeueOne() in the event queue.
|
||||
MessageLoop::current()->PostTask(
|
||||
NewNonOwningRunnableMethod(this, &TestHangsParent::CleanUp));
|
||||
|
||||
GetIPCChannel()->CloseWithTimeout();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
TestHangsParent::AnswerStackFrame()
|
||||
{
|
||||
if (PTestHangs::HANG != state()) {
|
||||
if (CallStackFrame())
|
||||
fail("should have timed out!");
|
||||
}
|
||||
else {
|
||||
// minimum possible, 2 ms. We want to detecting a hang to race
|
||||
// with the reply coming in, as reliably as possible
|
||||
SetReplyTimeoutMs(2);
|
||||
|
||||
if (CallHang())
|
||||
fail("should have timed out!");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
TestHangsParent::CleanUp()
|
||||
{
|
||||
ipc::ScopedProcessHandle otherProcessHandle;
|
||||
if (!base::OpenProcessHandle(OtherPid(), &otherProcessHandle.rwget())) {
|
||||
fail("couldn't open child process");
|
||||
} else {
|
||||
if (!KillProcess(otherProcessHandle, 0, false)) {
|
||||
fail("terminating child process");
|
||||
}
|
||||
}
|
||||
Close();
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// child
|
||||
|
||||
TestHangsChild::TestHangsChild()
|
||||
{
|
||||
MOZ_COUNT_CTOR(TestHangsChild);
|
||||
}
|
||||
|
||||
TestHangsChild::~TestHangsChild()
|
||||
{
|
||||
MOZ_COUNT_DTOR(TestHangsChild);
|
||||
}
|
||||
|
||||
bool
|
||||
TestHangsChild::AnswerHang()
|
||||
{
|
||||
puts(" (child process is 'hanging' now)");
|
||||
|
||||
// just sleep until we're reasonably confident the 1ms hang
|
||||
// detector fired in the parent process and it's sleeping in
|
||||
// ShouldContinueFromReplyTimeout()
|
||||
PR_Sleep(1000);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace _ipdltest
|
||||
} // namespace mozilla
|
||||
87
ipc/ipdl/test/cxx/TestHangs.h
Normal file
87
ipc/ipdl/test/cxx/TestHangs.h
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
#ifndef mozilla__ipdltest_TestHangs_h
|
||||
#define mozilla__ipdltest_TestHangs_h 1
|
||||
|
||||
#include "mozilla/_ipdltest/IPDLUnitTests.h"
|
||||
|
||||
#include "mozilla/_ipdltest/PTestHangsParent.h"
|
||||
#include "mozilla/_ipdltest/PTestHangsChild.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace _ipdltest {
|
||||
|
||||
|
||||
class TestHangsParent :
|
||||
public PTestHangsParent
|
||||
{
|
||||
public:
|
||||
TestHangsParent();
|
||||
virtual ~TestHangsParent();
|
||||
|
||||
static bool RunTestInProcesses() { return true; }
|
||||
|
||||
// FIXME/bug 703320 Disabled because parent kills child proc, not
|
||||
// clear how that should work in threads.
|
||||
static bool RunTestInThreads() { return false; }
|
||||
|
||||
void Main();
|
||||
|
||||
protected:
|
||||
virtual bool ShouldContinueFromReplyTimeout() override;
|
||||
|
||||
virtual bool RecvNonce() {
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual bool AnswerStackFrame() override;
|
||||
|
||||
virtual void ActorDestroy(ActorDestroyReason why) override
|
||||
{
|
||||
if (AbnormalShutdown != why)
|
||||
fail("unexpected destruction!");
|
||||
passed("ok");
|
||||
QuitParent();
|
||||
}
|
||||
|
||||
void CleanUp();
|
||||
|
||||
bool mDetectedHang;
|
||||
};
|
||||
|
||||
|
||||
class TestHangsChild :
|
||||
public PTestHangsChild
|
||||
{
|
||||
public:
|
||||
TestHangsChild();
|
||||
virtual ~TestHangsChild();
|
||||
|
||||
protected:
|
||||
virtual bool RecvStart() override {
|
||||
if (!SendNonce())
|
||||
fail("sending Nonce");
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual bool AnswerStackFrame() override
|
||||
{
|
||||
if (CallStackFrame())
|
||||
fail("should have failed");
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual bool AnswerHang() override;
|
||||
|
||||
virtual void ActorDestroy(ActorDestroyReason why) override
|
||||
{
|
||||
if (AbnormalShutdown != why)
|
||||
fail("unexpected destruction!");
|
||||
QuitChild();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
} // namespace _ipdltest
|
||||
} // namespace mozilla
|
||||
|
||||
|
||||
#endif // ifndef mozilla__ipdltest_TestHangs_h
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue