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.cpp347
1 files changed, 347 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 0000000000..30eea42838
--- /dev/null
+++ b/ipc/ipdl/test/cxx/IPDLUnitTests.template.cpp
@@ -0,0 +1,347 @@
+//
+// 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"
+
+// clang-format off
+//-----------------------------------------------------------------------------
+//===== TEMPLATED =====
+${INCLUDES}
+//-----------------------------------------------------------------------------
+// clang-format on
+
+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,
+
+ // clang-format off
+//-----------------------------------------------------------------------------
+//===== TEMPLATED =====
+${ENUM_VALUES}
+
+ LastTest = ${LAST_ENUM}
+//-----------------------------------------------------------------------------
+//clang-format on
+};
+
+IPDLUnitTestType IPDLUnitTestFromString(const char* const aString) {
+ if (!aString) return static_cast<IPDLUnitTestType>(0);
+// clang-format off
+//-----------------------------------------------------------------------------
+//===== TEMPLATED =====
+${STRING_TO_ENUMS}
+//-----------------------------------------------------------------------------
+ // clang-format on
+ else return static_cast<IPDLUnitTestType>(0);
+}
+
+IPDLUnitTestType IPDLUnitTest() {
+ return IPDLUnitTestFromString(::mozilla::_ipdltest::IPDLUnitTestName());
+}
+
+} // namespace
+
+//-----------------------------------------------------------------------------
+// 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);
+ MOZ_CRASH("can't continue");
+ }
+ gIPDLUnitTestName = testString;
+
+ // Check whether this test is enabled for processes:
+ switch (test) {
+ // clang-format off
+//-----------------------------------------------------------------------------
+//===== TEMPLATED =====
+${PARENT_ENABLED_CASES_PROC}
+//-----------------------------------------------------------------------------
+ // clang-format on
+
+ 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) {
+ // clang-format off
+//-----------------------------------------------------------------------------
+//===== TEMPLATED =====
+${PARENT_MAIN_CASES_PROC}
+//-----------------------------------------------------------------------------
+ // clang-format on
+
+ 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);
+ MOZ_CRASH("can't continue");
+ }
+ gIPDLUnitTestName = testString;
+
+ // Check whether this test is enabled for threads:
+ switch (test) {
+ // clang-format off
+//-----------------------------------------------------------------------------
+//===== TEMPLATED =====
+${PARENT_ENABLED_CASES_THREAD}
+//-----------------------------------------------------------------------------
+ // clang-format on
+
+ 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) {
+ // clang-format off
+//-----------------------------------------------------------------------------
+//===== TEMPLATED =====
+${PARENT_MAIN_CASES_THREAD}
+//-----------------------------------------------------------------------------
+ // clang-format on
+
+ default:
+ fail("not reached");
+ return; // unreached
+ }
+}
+
+void DeleteParentActor() {
+ if (!gParentActor) return;
+
+ switch (IPDLUnitTest()) {
+ // clang-format off
+//-----------------------------------------------------------------------------
+//===== TEMPLATED =====
+${PARENT_DELETE_CASES}
+//-----------------------------------------------------------------------------
+ // clang-format on
+ 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
+ gSubprocess->Destroy();
+ gSubprocess = nullptr;
+ uiLoop->PostTask(NewRunnableFunction("QuitXPCOM", QuitXPCOM));
+}
+
+void DeferredParentShutdown() {
+ // ping to DeleteSubprocess
+ XRE_GetIOMessageLoop()->PostTask(NewRunnableFunction(
+ "DeleteSubprocess", 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", TryThreadedShutdown));
+ } else {
+ // defer "real" shutdown to avoid *Channel::Close() racing with the
+ // deletion of the subprocess
+ MessageLoop::current()->PostTask(
+ NewRunnableFunction("DeferredParentShutdown", DeferredParentShutdown));
+ }
+}
+
+static void ChildDie() {
+ DeleteChildActor();
+ XRE_ShutdownChildProcess();
+}
+
+void QuitChild() {
+ if (gChildThread) { // Threaded-mode test
+ gParentMessageLoop->PostTask(
+ NewRunnableFunction("ChildCompleted", ChildCompleted));
+ } else { // Process-mode test
+ MessageLoop::current()->PostTask(NewRunnableFunction("ChildDie", ChildDie));
+ }
+}
+
+} // namespace _ipdltest
+} // namespace mozilla
+
+//-----------------------------------------------------------------------------
+// child process only
+
+namespace mozilla {
+namespace _ipdltest {
+
+void DeleteChildActor() {
+ if (!gChildActor) return;
+
+ switch (IPDLUnitTest()) {
+ // clang-format off
+//-----------------------------------------------------------------------------
+//===== TEMPLATED =====
+${CHILD_DELETE_CASES}
+//-----------------------------------------------------------------------------
+ // clang-format on
+ default:
+ ::mozilla::_ipdltest::fail("???");
+ }
+}
+
+void IPDLUnitTestChildInit(IPC::Channel* transport, base::ProcessId parentPid,
+ MessageLoop* worker) {
+ switch (IPDLUnitTest()) {
+ // clang-format off
+//-----------------------------------------------------------------------------
+//===== TEMPLATED =====
+${CHILD_INIT_CASES}
+//-----------------------------------------------------------------------------
+ // clang-format on
+
+ default:
+ fail("not reached");
+ return; // unreached
+ }
+}
+
+} // namespace _ipdltest
+} // namespace mozilla