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

changeset 0
6474c204b198
     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

mercurial