1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/ipc/ipdl/test/cxx/IPDLUnitTests.template.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,381 @@ 1.4 +// 1.5 +// Autogenerated from Python template. Hands off. 1.6 +// 1.7 + 1.8 +#include <stdlib.h> 1.9 +#include <string.h> 1.10 + 1.11 +#include "IPDLUnitTests.h" 1.12 + 1.13 +#include "base/command_line.h" 1.14 +#include "base/string_util.h" 1.15 +#include "base/thread.h" 1.16 + 1.17 +#include "nsRegion.h" 1.18 + 1.19 +#include "IPDLUnitTestSubprocess.h" 1.20 + 1.21 +//----------------------------------------------------------------------------- 1.22 +//===== TEMPLATED ===== 1.23 +${INCLUDES} 1.24 +//----------------------------------------------------------------------------- 1.25 + 1.26 +using namespace base; 1.27 +using namespace std; 1.28 + 1.29 +namespace mozilla { 1.30 +namespace _ipdltest { 1.31 + 1.32 +void* gParentActor; 1.33 +IPDLUnitTestSubprocess* gSubprocess; 1.34 + 1.35 +void* gChildActor; 1.36 + 1.37 +// Note: in threaded mode, this will be non-null (for both parent and 1.38 +// child, since they share one set of globals). 1.39 +Thread* gChildThread; 1.40 +MessageLoop *gParentMessageLoop; 1.41 +bool gParentDone; 1.42 +bool gChildDone; 1.43 + 1.44 +//----------------------------------------------------------------------------- 1.45 +// data/functions accessed by both parent and child processes 1.46 + 1.47 +char* gIPDLUnitTestName = nullptr; 1.48 + 1.49 +const char* const 1.50 +IPDLUnitTestName() 1.51 +{ 1.52 + if (!gIPDLUnitTestName) { 1.53 +#if defined(OS_WIN) 1.54 + vector<wstring> args = 1.55 + CommandLine::ForCurrentProcess()->GetLooseValues(); 1.56 + gIPDLUnitTestName = ::strdup(WideToUTF8(args[0]).c_str()); 1.57 +#elif defined(OS_POSIX) 1.58 + vector<string> argv = CommandLine::ForCurrentProcess()->argv(); 1.59 + gIPDLUnitTestName = ::moz_xstrdup(argv[1].c_str()); 1.60 +#else 1.61 +# error Sorry 1.62 +#endif 1.63 + } 1.64 + return gIPDLUnitTestName; 1.65 +} 1.66 + 1.67 +} // namespace _ipdltest 1.68 +} // namespace mozilla 1.69 + 1.70 + 1.71 +namespace { 1.72 + 1.73 +enum IPDLUnitTestType { 1.74 + NoneTest = 0, 1.75 + 1.76 +//----------------------------------------------------------------------------- 1.77 +//===== TEMPLATED ===== 1.78 +${ENUM_VALUES} 1.79 + 1.80 + LastTest = ${LAST_ENUM} 1.81 +//----------------------------------------------------------------------------- 1.82 +}; 1.83 + 1.84 + 1.85 +IPDLUnitTestType 1.86 +IPDLUnitTestFromString(const char* const aString) 1.87 +{ 1.88 + if (!aString) 1.89 + return static_cast<IPDLUnitTestType>(0); 1.90 +//----------------------------------------------------------------------------- 1.91 +//===== TEMPLATED ===== 1.92 +${STRING_TO_ENUMS} 1.93 +//----------------------------------------------------------------------------- 1.94 + else 1.95 + return static_cast<IPDLUnitTestType>(0); 1.96 +} 1.97 + 1.98 + 1.99 +const char* const 1.100 +IPDLUnitTestToString(IPDLUnitTestType aTest) 1.101 +{ 1.102 + switch (aTest) { 1.103 +//----------------------------------------------------------------------------- 1.104 +//===== TEMPLATED ===== 1.105 +${ENUM_TO_STRINGS} 1.106 +//----------------------------------------------------------------------------- 1.107 + 1.108 + default: 1.109 + return nullptr; 1.110 + } 1.111 +} 1.112 + 1.113 + 1.114 +IPDLUnitTestType 1.115 +IPDLUnitTest() 1.116 +{ 1.117 + return IPDLUnitTestFromString(::mozilla::_ipdltest::IPDLUnitTestName()); 1.118 +} 1.119 + 1.120 + 1.121 +} // namespace <anon> 1.122 + 1.123 + 1.124 +//----------------------------------------------------------------------------- 1.125 +// parent process only 1.126 + 1.127 +namespace mozilla { 1.128 +namespace _ipdltest { 1.129 + 1.130 +void 1.131 +DeferredParentShutdown(); 1.132 + 1.133 +void 1.134 +IPDLUnitTestThreadMain(char *testString); 1.135 + 1.136 +void 1.137 +IPDLUnitTestMain(void* aData) 1.138 +{ 1.139 + char* testString = reinterpret_cast<char*>(aData); 1.140 + 1.141 + // Check if we are to run the test using threads instead: 1.142 + const char *prefix = "thread:"; 1.143 + const int prefixLen = strlen(prefix); 1.144 + if (!strncmp(testString, prefix, prefixLen)) { 1.145 + IPDLUnitTestThreadMain(testString + prefixLen); 1.146 + return; 1.147 + } 1.148 + 1.149 + IPDLUnitTestType test = IPDLUnitTestFromString(testString); 1.150 + if (!test) { 1.151 + // use this instead of |fail()| because we don't know what the test is 1.152 + fprintf(stderr, MOZ_IPDL_TESTFAIL_LABEL "| %s | unknown unit test %s\n", 1.153 + "<--->", testString); 1.154 + NS_RUNTIMEABORT("can't continue"); 1.155 + } 1.156 + gIPDLUnitTestName = testString; 1.157 + 1.158 + // Check whether this test is enabled for processes: 1.159 + switch (test) { 1.160 +//----------------------------------------------------------------------------- 1.161 +//===== TEMPLATED ===== 1.162 +${PARENT_ENABLED_CASES_PROC} 1.163 +//----------------------------------------------------------------------------- 1.164 + 1.165 + default: 1.166 + fail("not reached"); 1.167 + return; // unreached 1.168 + } 1.169 + 1.170 + printf(MOZ_IPDL_TESTINFO_LABEL "| running test | %s\n", gIPDLUnitTestName); 1.171 + 1.172 + std::vector<std::string> testCaseArgs; 1.173 + testCaseArgs.push_back(testString); 1.174 + 1.175 + gSubprocess = new IPDLUnitTestSubprocess(); 1.176 + if (!gSubprocess->SyncLaunch(testCaseArgs)) 1.177 + fail("problem launching subprocess"); 1.178 + 1.179 + IPC::Channel* transport = gSubprocess->GetChannel(); 1.180 + if (!transport) 1.181 + fail("no transport"); 1.182 + 1.183 + base::ProcessHandle child = gSubprocess->GetChildProcessHandle(); 1.184 + 1.185 + switch (test) { 1.186 +//----------------------------------------------------------------------------- 1.187 +//===== TEMPLATED ===== 1.188 +${PARENT_MAIN_CASES_PROC} 1.189 +//----------------------------------------------------------------------------- 1.190 + 1.191 + default: 1.192 + fail("not reached"); 1.193 + return; // unreached 1.194 + } 1.195 +} 1.196 + 1.197 +void 1.198 +IPDLUnitTestThreadMain(char *testString) 1.199 +{ 1.200 + IPDLUnitTestType test = IPDLUnitTestFromString(testString); 1.201 + if (!test) { 1.202 + // use this instead of |fail()| because we don't know what the test is 1.203 + fprintf(stderr, MOZ_IPDL_TESTFAIL_LABEL "| %s | unknown unit test %s\n", 1.204 + "<--->", testString); 1.205 + NS_RUNTIMEABORT("can't continue"); 1.206 + } 1.207 + gIPDLUnitTestName = testString; 1.208 + 1.209 + // Check whether this test is enabled for threads: 1.210 + switch (test) { 1.211 +//----------------------------------------------------------------------------- 1.212 +//===== TEMPLATED ===== 1.213 +${PARENT_ENABLED_CASES_THREAD} 1.214 +//----------------------------------------------------------------------------- 1.215 + 1.216 + default: 1.217 + fail("not reached"); 1.218 + return; // unreached 1.219 + } 1.220 + 1.221 + printf(MOZ_IPDL_TESTINFO_LABEL "| running test | %s\n", gIPDLUnitTestName); 1.222 + 1.223 + std::vector<std::string> testCaseArgs; 1.224 + testCaseArgs.push_back(testString); 1.225 + 1.226 + gChildThread = new Thread("ParentThread"); 1.227 + if (!gChildThread->Start()) 1.228 + fail("starting parent thread"); 1.229 + 1.230 + gParentMessageLoop = MessageLoop::current(); 1.231 + MessageLoop *childMessageLoop = gChildThread->message_loop(); 1.232 + 1.233 + switch (test) { 1.234 +//----------------------------------------------------------------------------- 1.235 +//===== TEMPLATED ===== 1.236 +${PARENT_MAIN_CASES_THREAD} 1.237 +//----------------------------------------------------------------------------- 1.238 + 1.239 + default: 1.240 + fail("not reached"); 1.241 + return; // unreached 1.242 + } 1.243 +} 1.244 + 1.245 +void 1.246 +DeleteParentActor() 1.247 +{ 1.248 + if (!gParentActor) 1.249 + return; 1.250 + 1.251 + switch (IPDLUnitTest()) { 1.252 +//----------------------------------------------------------------------------- 1.253 +//===== TEMPLATED ===== 1.254 +${PARENT_DELETE_CASES} 1.255 +//----------------------------------------------------------------------------- 1.256 + default: ::mozilla::_ipdltest::fail("???"); 1.257 + } 1.258 +} 1.259 + 1.260 +void 1.261 +QuitXPCOM() 1.262 +{ 1.263 + DeleteParentActor(); 1.264 + 1.265 + static NS_DEFINE_CID(kAppShellCID, NS_APPSHELL_CID); 1.266 + nsCOMPtr<nsIAppShell> appShell (do_GetService(kAppShellCID)); 1.267 + appShell->Exit(); 1.268 +} 1.269 + 1.270 +void 1.271 +DeleteSubprocess(MessageLoop* uiLoop) 1.272 +{ 1.273 + // pong to QuitXPCOM 1.274 + delete gSubprocess; 1.275 + uiLoop->PostTask(FROM_HERE, NewRunnableFunction(QuitXPCOM)); 1.276 +} 1.277 + 1.278 +void 1.279 +DeferredParentShutdown() 1.280 +{ 1.281 + // ping to DeleteSubprocess 1.282 + XRE_GetIOMessageLoop()->PostTask( 1.283 + FROM_HERE, 1.284 + NewRunnableFunction(DeleteSubprocess, MessageLoop::current())); 1.285 +} 1.286 + 1.287 +void 1.288 +TryThreadedShutdown() 1.289 +{ 1.290 + // Stop if either: 1.291 + // - the child has not finished, 1.292 + // - the parent has not finished, 1.293 + // - or this code has already executed. 1.294 + // Remember: this TryThreadedShutdown() task is enqueued 1.295 + // by both parent and child (though always on parent's msg loop). 1.296 + if (!gChildDone || !gParentDone || !gChildThread) 1.297 + return; 1.298 + 1.299 + delete gChildThread; 1.300 + gChildThread = 0; 1.301 + DeferredParentShutdown(); 1.302 +} 1.303 + 1.304 +void 1.305 +ChildCompleted() 1.306 +{ 1.307 + // Executes on the parent message loop once child has completed. 1.308 + gChildDone = true; 1.309 + TryThreadedShutdown(); 1.310 +} 1.311 + 1.312 +void 1.313 +QuitParent() 1.314 +{ 1.315 + if (gChildThread) { 1.316 + gParentDone = true; 1.317 + MessageLoop::current()->PostTask( 1.318 + FROM_HERE, NewRunnableFunction(TryThreadedShutdown)); 1.319 + } else { 1.320 + // defer "real" shutdown to avoid *Channel::Close() racing with the 1.321 + // deletion of the subprocess 1.322 + MessageLoop::current()->PostTask( 1.323 + FROM_HERE, NewRunnableFunction(DeferredParentShutdown)); 1.324 + } 1.325 +} 1.326 + 1.327 +void 1.328 +QuitChild() 1.329 +{ 1.330 + if (gChildThread) { // Threaded-mode test 1.331 + gParentMessageLoop->PostTask( 1.332 + FROM_HERE, NewRunnableFunction(ChildCompleted)); 1.333 + } else { // Process-mode test 1.334 + XRE_ShutdownChildProcess(); 1.335 + } 1.336 +} 1.337 + 1.338 +} // namespace _ipdltest 1.339 +} // namespace mozilla 1.340 + 1.341 + 1.342 +//----------------------------------------------------------------------------- 1.343 +// child process only 1.344 + 1.345 +namespace mozilla { 1.346 +namespace _ipdltest { 1.347 + 1.348 +void 1.349 +DeleteChildActor() 1.350 +{ 1.351 + if (!gChildActor) 1.352 + return; 1.353 + 1.354 + switch (IPDLUnitTest()) { 1.355 +//----------------------------------------------------------------------------- 1.356 +//===== TEMPLATED ===== 1.357 +${CHILD_DELETE_CASES} 1.358 +//----------------------------------------------------------------------------- 1.359 + default: ::mozilla::_ipdltest::fail("???"); 1.360 + } 1.361 +} 1.362 + 1.363 +void 1.364 +IPDLUnitTestChildInit(IPC::Channel* transport, 1.365 + base::ProcessHandle parent, 1.366 + MessageLoop* worker) 1.367 +{ 1.368 + if (atexit(DeleteChildActor)) 1.369 + fail("can't install atexit() handler"); 1.370 + 1.371 + switch (IPDLUnitTest()) { 1.372 +//----------------------------------------------------------------------------- 1.373 +//===== TEMPLATED ===== 1.374 +${CHILD_INIT_CASES} 1.375 +//----------------------------------------------------------------------------- 1.376 + 1.377 + default: 1.378 + fail("not reached"); 1.379 + return; // unreached 1.380 + } 1.381 +} 1.382 + 1.383 +} // namespace _ipdltest 1.384 +} // namespace mozilla