gecko-dev/ipc/ipdl/test/cxx/IPDLUnitTests.template.cpp

391 lines
9.6 KiB
C++

//
// 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/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* const
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* const
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(FROM_HERE, NewRunnableFunction(QuitXPCOM));
}
void
DeferredParentShutdown()
{
// ping to DeleteSubprocess
XRE_GetIOMessageLoop()->PostTask(
FROM_HERE,
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(
FROM_HERE, NewRunnableFunction(TryThreadedShutdown));
} else {
// defer "real" shutdown to avoid *Channel::Close() racing with the
// deletion of the subprocess
MessageLoop::current()->PostTask(
FROM_HERE, NewRunnableFunction(DeferredParentShutdown));
}
}
static void
ChildDie()
{
DeleteChildActor();
XRE_ShutdownChildProcess();
}
void
QuitChild()
{
if (gChildThread) { // Threaded-mode test
gParentMessageLoop->PostTask(
FROM_HERE, NewRunnableFunction(ChildCompleted));
} else { // Process-mode test
MessageLoop::current()->PostTask(
FROM_HERE, 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