summaryrefslogtreecommitdiffstats
path: root/ipc/ipdl/test/cxx/IPDLUnitTests.template.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'ipc/ipdl/test/cxx/IPDLUnitTests.template.cpp')
-rw-r--r--ipc/ipdl/test/cxx/IPDLUnitTests.template.cpp390
1 files changed, 390 insertions, 0 deletions
diff --git a/ipc/ipdl/test/cxx/IPDLUnitTests.template.cpp b/ipc/ipdl/test/cxx/IPDLUnitTests.template.cpp
new file mode 100644
index 000000000..6a91033bf
--- /dev/null
+++ b/ipc/ipdl/test/cxx/IPDLUnitTests.template.cpp
@@ -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