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