ipc/ipdl/test/cxx/IPDLUnitTests.template.cpp

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

michael@0 1 //
michael@0 2 // Autogenerated from Python template. Hands off.
michael@0 3 //
michael@0 4
michael@0 5 #include <stdlib.h>
michael@0 6 #include <string.h>
michael@0 7
michael@0 8 #include "IPDLUnitTests.h"
michael@0 9
michael@0 10 #include "base/command_line.h"
michael@0 11 #include "base/string_util.h"
michael@0 12 #include "base/thread.h"
michael@0 13
michael@0 14 #include "nsRegion.h"
michael@0 15
michael@0 16 #include "IPDLUnitTestSubprocess.h"
michael@0 17
michael@0 18 //-----------------------------------------------------------------------------
michael@0 19 //===== TEMPLATED =====
michael@0 20 ${INCLUDES}
michael@0 21 //-----------------------------------------------------------------------------
michael@0 22
michael@0 23 using namespace base;
michael@0 24 using namespace std;
michael@0 25
michael@0 26 namespace mozilla {
michael@0 27 namespace _ipdltest {
michael@0 28
michael@0 29 void* gParentActor;
michael@0 30 IPDLUnitTestSubprocess* gSubprocess;
michael@0 31
michael@0 32 void* gChildActor;
michael@0 33
michael@0 34 // Note: in threaded mode, this will be non-null (for both parent and
michael@0 35 // child, since they share one set of globals).
michael@0 36 Thread* gChildThread;
michael@0 37 MessageLoop *gParentMessageLoop;
michael@0 38 bool gParentDone;
michael@0 39 bool gChildDone;
michael@0 40
michael@0 41 //-----------------------------------------------------------------------------
michael@0 42 // data/functions accessed by both parent and child processes
michael@0 43
michael@0 44 char* gIPDLUnitTestName = nullptr;
michael@0 45
michael@0 46 const char* const
michael@0 47 IPDLUnitTestName()
michael@0 48 {
michael@0 49 if (!gIPDLUnitTestName) {
michael@0 50 #if defined(OS_WIN)
michael@0 51 vector<wstring> args =
michael@0 52 CommandLine::ForCurrentProcess()->GetLooseValues();
michael@0 53 gIPDLUnitTestName = ::strdup(WideToUTF8(args[0]).c_str());
michael@0 54 #elif defined(OS_POSIX)
michael@0 55 vector<string> argv = CommandLine::ForCurrentProcess()->argv();
michael@0 56 gIPDLUnitTestName = ::moz_xstrdup(argv[1].c_str());
michael@0 57 #else
michael@0 58 # error Sorry
michael@0 59 #endif
michael@0 60 }
michael@0 61 return gIPDLUnitTestName;
michael@0 62 }
michael@0 63
michael@0 64 } // namespace _ipdltest
michael@0 65 } // namespace mozilla
michael@0 66
michael@0 67
michael@0 68 namespace {
michael@0 69
michael@0 70 enum IPDLUnitTestType {
michael@0 71 NoneTest = 0,
michael@0 72
michael@0 73 //-----------------------------------------------------------------------------
michael@0 74 //===== TEMPLATED =====
michael@0 75 ${ENUM_VALUES}
michael@0 76
michael@0 77 LastTest = ${LAST_ENUM}
michael@0 78 //-----------------------------------------------------------------------------
michael@0 79 };
michael@0 80
michael@0 81
michael@0 82 IPDLUnitTestType
michael@0 83 IPDLUnitTestFromString(const char* const aString)
michael@0 84 {
michael@0 85 if (!aString)
michael@0 86 return static_cast<IPDLUnitTestType>(0);
michael@0 87 //-----------------------------------------------------------------------------
michael@0 88 //===== TEMPLATED =====
michael@0 89 ${STRING_TO_ENUMS}
michael@0 90 //-----------------------------------------------------------------------------
michael@0 91 else
michael@0 92 return static_cast<IPDLUnitTestType>(0);
michael@0 93 }
michael@0 94
michael@0 95
michael@0 96 const char* const
michael@0 97 IPDLUnitTestToString(IPDLUnitTestType aTest)
michael@0 98 {
michael@0 99 switch (aTest) {
michael@0 100 //-----------------------------------------------------------------------------
michael@0 101 //===== TEMPLATED =====
michael@0 102 ${ENUM_TO_STRINGS}
michael@0 103 //-----------------------------------------------------------------------------
michael@0 104
michael@0 105 default:
michael@0 106 return nullptr;
michael@0 107 }
michael@0 108 }
michael@0 109
michael@0 110
michael@0 111 IPDLUnitTestType
michael@0 112 IPDLUnitTest()
michael@0 113 {
michael@0 114 return IPDLUnitTestFromString(::mozilla::_ipdltest::IPDLUnitTestName());
michael@0 115 }
michael@0 116
michael@0 117
michael@0 118 } // namespace <anon>
michael@0 119
michael@0 120
michael@0 121 //-----------------------------------------------------------------------------
michael@0 122 // parent process only
michael@0 123
michael@0 124 namespace mozilla {
michael@0 125 namespace _ipdltest {
michael@0 126
michael@0 127 void
michael@0 128 DeferredParentShutdown();
michael@0 129
michael@0 130 void
michael@0 131 IPDLUnitTestThreadMain(char *testString);
michael@0 132
michael@0 133 void
michael@0 134 IPDLUnitTestMain(void* aData)
michael@0 135 {
michael@0 136 char* testString = reinterpret_cast<char*>(aData);
michael@0 137
michael@0 138 // Check if we are to run the test using threads instead:
michael@0 139 const char *prefix = "thread:";
michael@0 140 const int prefixLen = strlen(prefix);
michael@0 141 if (!strncmp(testString, prefix, prefixLen)) {
michael@0 142 IPDLUnitTestThreadMain(testString + prefixLen);
michael@0 143 return;
michael@0 144 }
michael@0 145
michael@0 146 IPDLUnitTestType test = IPDLUnitTestFromString(testString);
michael@0 147 if (!test) {
michael@0 148 // use this instead of |fail()| because we don't know what the test is
michael@0 149 fprintf(stderr, MOZ_IPDL_TESTFAIL_LABEL "| %s | unknown unit test %s\n",
michael@0 150 "<--->", testString);
michael@0 151 NS_RUNTIMEABORT("can't continue");
michael@0 152 }
michael@0 153 gIPDLUnitTestName = testString;
michael@0 154
michael@0 155 // Check whether this test is enabled for processes:
michael@0 156 switch (test) {
michael@0 157 //-----------------------------------------------------------------------------
michael@0 158 //===== TEMPLATED =====
michael@0 159 ${PARENT_ENABLED_CASES_PROC}
michael@0 160 //-----------------------------------------------------------------------------
michael@0 161
michael@0 162 default:
michael@0 163 fail("not reached");
michael@0 164 return; // unreached
michael@0 165 }
michael@0 166
michael@0 167 printf(MOZ_IPDL_TESTINFO_LABEL "| running test | %s\n", gIPDLUnitTestName);
michael@0 168
michael@0 169 std::vector<std::string> testCaseArgs;
michael@0 170 testCaseArgs.push_back(testString);
michael@0 171
michael@0 172 gSubprocess = new IPDLUnitTestSubprocess();
michael@0 173 if (!gSubprocess->SyncLaunch(testCaseArgs))
michael@0 174 fail("problem launching subprocess");
michael@0 175
michael@0 176 IPC::Channel* transport = gSubprocess->GetChannel();
michael@0 177 if (!transport)
michael@0 178 fail("no transport");
michael@0 179
michael@0 180 base::ProcessHandle child = gSubprocess->GetChildProcessHandle();
michael@0 181
michael@0 182 switch (test) {
michael@0 183 //-----------------------------------------------------------------------------
michael@0 184 //===== TEMPLATED =====
michael@0 185 ${PARENT_MAIN_CASES_PROC}
michael@0 186 //-----------------------------------------------------------------------------
michael@0 187
michael@0 188 default:
michael@0 189 fail("not reached");
michael@0 190 return; // unreached
michael@0 191 }
michael@0 192 }
michael@0 193
michael@0 194 void
michael@0 195 IPDLUnitTestThreadMain(char *testString)
michael@0 196 {
michael@0 197 IPDLUnitTestType test = IPDLUnitTestFromString(testString);
michael@0 198 if (!test) {
michael@0 199 // use this instead of |fail()| because we don't know what the test is
michael@0 200 fprintf(stderr, MOZ_IPDL_TESTFAIL_LABEL "| %s | unknown unit test %s\n",
michael@0 201 "<--->", testString);
michael@0 202 NS_RUNTIMEABORT("can't continue");
michael@0 203 }
michael@0 204 gIPDLUnitTestName = testString;
michael@0 205
michael@0 206 // Check whether this test is enabled for threads:
michael@0 207 switch (test) {
michael@0 208 //-----------------------------------------------------------------------------
michael@0 209 //===== TEMPLATED =====
michael@0 210 ${PARENT_ENABLED_CASES_THREAD}
michael@0 211 //-----------------------------------------------------------------------------
michael@0 212
michael@0 213 default:
michael@0 214 fail("not reached");
michael@0 215 return; // unreached
michael@0 216 }
michael@0 217
michael@0 218 printf(MOZ_IPDL_TESTINFO_LABEL "| running test | %s\n", gIPDLUnitTestName);
michael@0 219
michael@0 220 std::vector<std::string> testCaseArgs;
michael@0 221 testCaseArgs.push_back(testString);
michael@0 222
michael@0 223 gChildThread = new Thread("ParentThread");
michael@0 224 if (!gChildThread->Start())
michael@0 225 fail("starting parent thread");
michael@0 226
michael@0 227 gParentMessageLoop = MessageLoop::current();
michael@0 228 MessageLoop *childMessageLoop = gChildThread->message_loop();
michael@0 229
michael@0 230 switch (test) {
michael@0 231 //-----------------------------------------------------------------------------
michael@0 232 //===== TEMPLATED =====
michael@0 233 ${PARENT_MAIN_CASES_THREAD}
michael@0 234 //-----------------------------------------------------------------------------
michael@0 235
michael@0 236 default:
michael@0 237 fail("not reached");
michael@0 238 return; // unreached
michael@0 239 }
michael@0 240 }
michael@0 241
michael@0 242 void
michael@0 243 DeleteParentActor()
michael@0 244 {
michael@0 245 if (!gParentActor)
michael@0 246 return;
michael@0 247
michael@0 248 switch (IPDLUnitTest()) {
michael@0 249 //-----------------------------------------------------------------------------
michael@0 250 //===== TEMPLATED =====
michael@0 251 ${PARENT_DELETE_CASES}
michael@0 252 //-----------------------------------------------------------------------------
michael@0 253 default: ::mozilla::_ipdltest::fail("???");
michael@0 254 }
michael@0 255 }
michael@0 256
michael@0 257 void
michael@0 258 QuitXPCOM()
michael@0 259 {
michael@0 260 DeleteParentActor();
michael@0 261
michael@0 262 static NS_DEFINE_CID(kAppShellCID, NS_APPSHELL_CID);
michael@0 263 nsCOMPtr<nsIAppShell> appShell (do_GetService(kAppShellCID));
michael@0 264 appShell->Exit();
michael@0 265 }
michael@0 266
michael@0 267 void
michael@0 268 DeleteSubprocess(MessageLoop* uiLoop)
michael@0 269 {
michael@0 270 // pong to QuitXPCOM
michael@0 271 delete gSubprocess;
michael@0 272 uiLoop->PostTask(FROM_HERE, NewRunnableFunction(QuitXPCOM));
michael@0 273 }
michael@0 274
michael@0 275 void
michael@0 276 DeferredParentShutdown()
michael@0 277 {
michael@0 278 // ping to DeleteSubprocess
michael@0 279 XRE_GetIOMessageLoop()->PostTask(
michael@0 280 FROM_HERE,
michael@0 281 NewRunnableFunction(DeleteSubprocess, MessageLoop::current()));
michael@0 282 }
michael@0 283
michael@0 284 void
michael@0 285 TryThreadedShutdown()
michael@0 286 {
michael@0 287 // Stop if either:
michael@0 288 // - the child has not finished,
michael@0 289 // - the parent has not finished,
michael@0 290 // - or this code has already executed.
michael@0 291 // Remember: this TryThreadedShutdown() task is enqueued
michael@0 292 // by both parent and child (though always on parent's msg loop).
michael@0 293 if (!gChildDone || !gParentDone || !gChildThread)
michael@0 294 return;
michael@0 295
michael@0 296 delete gChildThread;
michael@0 297 gChildThread = 0;
michael@0 298 DeferredParentShutdown();
michael@0 299 }
michael@0 300
michael@0 301 void
michael@0 302 ChildCompleted()
michael@0 303 {
michael@0 304 // Executes on the parent message loop once child has completed.
michael@0 305 gChildDone = true;
michael@0 306 TryThreadedShutdown();
michael@0 307 }
michael@0 308
michael@0 309 void
michael@0 310 QuitParent()
michael@0 311 {
michael@0 312 if (gChildThread) {
michael@0 313 gParentDone = true;
michael@0 314 MessageLoop::current()->PostTask(
michael@0 315 FROM_HERE, NewRunnableFunction(TryThreadedShutdown));
michael@0 316 } else {
michael@0 317 // defer "real" shutdown to avoid *Channel::Close() racing with the
michael@0 318 // deletion of the subprocess
michael@0 319 MessageLoop::current()->PostTask(
michael@0 320 FROM_HERE, NewRunnableFunction(DeferredParentShutdown));
michael@0 321 }
michael@0 322 }
michael@0 323
michael@0 324 void
michael@0 325 QuitChild()
michael@0 326 {
michael@0 327 if (gChildThread) { // Threaded-mode test
michael@0 328 gParentMessageLoop->PostTask(
michael@0 329 FROM_HERE, NewRunnableFunction(ChildCompleted));
michael@0 330 } else { // Process-mode test
michael@0 331 XRE_ShutdownChildProcess();
michael@0 332 }
michael@0 333 }
michael@0 334
michael@0 335 } // namespace _ipdltest
michael@0 336 } // namespace mozilla
michael@0 337
michael@0 338
michael@0 339 //-----------------------------------------------------------------------------
michael@0 340 // child process only
michael@0 341
michael@0 342 namespace mozilla {
michael@0 343 namespace _ipdltest {
michael@0 344
michael@0 345 void
michael@0 346 DeleteChildActor()
michael@0 347 {
michael@0 348 if (!gChildActor)
michael@0 349 return;
michael@0 350
michael@0 351 switch (IPDLUnitTest()) {
michael@0 352 //-----------------------------------------------------------------------------
michael@0 353 //===== TEMPLATED =====
michael@0 354 ${CHILD_DELETE_CASES}
michael@0 355 //-----------------------------------------------------------------------------
michael@0 356 default: ::mozilla::_ipdltest::fail("???");
michael@0 357 }
michael@0 358 }
michael@0 359
michael@0 360 void
michael@0 361 IPDLUnitTestChildInit(IPC::Channel* transport,
michael@0 362 base::ProcessHandle parent,
michael@0 363 MessageLoop* worker)
michael@0 364 {
michael@0 365 if (atexit(DeleteChildActor))
michael@0 366 fail("can't install atexit() handler");
michael@0 367
michael@0 368 switch (IPDLUnitTest()) {
michael@0 369 //-----------------------------------------------------------------------------
michael@0 370 //===== TEMPLATED =====
michael@0 371 ${CHILD_INIT_CASES}
michael@0 372 //-----------------------------------------------------------------------------
michael@0 373
michael@0 374 default:
michael@0 375 fail("not reached");
michael@0 376 return; // unreached
michael@0 377 }
michael@0 378 }
michael@0 379
michael@0 380 } // namespace _ipdltest
michael@0 381 } // namespace mozilla

mercurial