mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-01 06:35:42 +00:00
391 lines
9.6 KiB
C++
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
|