ipc/ipdl/test/cxx/TestInterruptShutdownRace.cpp

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/ipc/ipdl/test/cxx/TestInterruptShutdownRace.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,144 @@
     1.4 +#include "TestInterruptShutdownRace.h"
     1.5 +
     1.6 +#include "IPDLUnitTests.h"      // fail etc.
     1.7 +#include "IPDLUnitTestSubprocess.h"
     1.8 +
     1.9 +template<>
    1.10 +struct RunnableMethodTraits<mozilla::_ipdltest::TestInterruptShutdownRaceParent>
    1.11 +{
    1.12 +    static void RetainCallee(mozilla::_ipdltest::TestInterruptShutdownRaceParent* obj) { }
    1.13 +    static void ReleaseCallee(mozilla::_ipdltest::TestInterruptShutdownRaceParent* obj) { }
    1.14 +};
    1.15 +
    1.16 +
    1.17 +namespace mozilla {
    1.18 +namespace _ipdltest {
    1.19 +
    1.20 +//-----------------------------------------------------------------------------
    1.21 +// parent
    1.22 +
    1.23 +namespace {
    1.24 +
    1.25 +// NB: this test does its own shutdown, rather than going through
    1.26 +// QuitParent(), because it's testing degenerate edge cases
    1.27 +
    1.28 +void DeleteSubprocess()
    1.29 +{
    1.30 +    delete gSubprocess;
    1.31 +    gSubprocess = nullptr;
    1.32 +}
    1.33 +
    1.34 +void Done()
    1.35 +{
    1.36 +    passed(__FILE__);
    1.37 +    QuitParent();
    1.38 +}
    1.39 +
    1.40 +} // namespace <anon>
    1.41 +
    1.42 +TestInterruptShutdownRaceParent::TestInterruptShutdownRaceParent()
    1.43 +{
    1.44 +    MOZ_COUNT_CTOR(TestInterruptShutdownRaceParent);
    1.45 +}
    1.46 +
    1.47 +TestInterruptShutdownRaceParent::~TestInterruptShutdownRaceParent()
    1.48 +{
    1.49 +    MOZ_COUNT_DTOR(TestInterruptShutdownRaceParent);
    1.50 +}
    1.51 +
    1.52 +void
    1.53 +TestInterruptShutdownRaceParent::Main()
    1.54 +{
    1.55 +    if (!SendStart())
    1.56 +        fail("sending Start");
    1.57 +}
    1.58 +
    1.59 +bool
    1.60 +TestInterruptShutdownRaceParent::RecvStartDeath()
    1.61 +{
    1.62 +    // this will be ordered before the OnMaybeDequeueOne event of
    1.63 +    // Orphan in the queue
    1.64 +    MessageLoop::current()->PostTask(
    1.65 +        FROM_HERE,
    1.66 +        NewRunnableMethod(this,
    1.67 +                          &TestInterruptShutdownRaceParent::StartShuttingDown));
    1.68 +    return true;
    1.69 +}
    1.70 +
    1.71 +void
    1.72 +TestInterruptShutdownRaceParent::StartShuttingDown()
    1.73 +{
    1.74 +    // NB: we sleep here to try and avoid receiving the Orphan message
    1.75 +    // while waiting for the CallExit() reply.  if we fail at that, it
    1.76 +    // will cause the test to pass spuriously, because there won't be
    1.77 +    // an OnMaybeDequeueOne task for Orphan
    1.78 +    PR_Sleep(2000);
    1.79 +
    1.80 +    if (CallExit())
    1.81 +        fail("connection was supposed to be interrupted");
    1.82 +
    1.83 +    Close();
    1.84 +
    1.85 +    delete static_cast<TestInterruptShutdownRaceParent*>(gParentActor);
    1.86 +    gParentActor = nullptr;
    1.87 +
    1.88 +    XRE_GetIOMessageLoop()->PostTask(FROM_HERE,
    1.89 +                                     NewRunnableFunction(DeleteSubprocess));
    1.90 +
    1.91 +    // this is ordered after the OnMaybeDequeueOne event in the queue
    1.92 +    MessageLoop::current()->PostTask(FROM_HERE,
    1.93 +                                     NewRunnableFunction(Done));
    1.94 +
    1.95 +    // |this| has been deleted, be mindful
    1.96 +}
    1.97 +
    1.98 +bool
    1.99 +TestInterruptShutdownRaceParent::RecvOrphan()
   1.100 +{
   1.101 +    // it would be nice to fail() here, but we'll process this message
   1.102 +    // while waiting for the reply CallExit().  The OnMaybeDequeueOne
   1.103 +    // task will still be in the queue, it just wouldn't have had any
   1.104 +    // work to do, if we hadn't deleted ourself
   1.105 +    return true;
   1.106 +}
   1.107 +
   1.108 +//-----------------------------------------------------------------------------
   1.109 +// child
   1.110 +
   1.111 +TestInterruptShutdownRaceChild::TestInterruptShutdownRaceChild()
   1.112 +{
   1.113 +    MOZ_COUNT_CTOR(TestInterruptShutdownRaceChild);
   1.114 +}
   1.115 +
   1.116 +TestInterruptShutdownRaceChild::~TestInterruptShutdownRaceChild()
   1.117 +{
   1.118 +    MOZ_COUNT_DTOR(TestInterruptShutdownRaceChild);
   1.119 +}
   1.120 +
   1.121 +bool
   1.122 +TestInterruptShutdownRaceChild::RecvStart()
   1.123 +{
   1.124 +    if (!SendStartDeath())
   1.125 +        fail("sending StartDeath");
   1.126 +
   1.127 +    // See comment in StartShuttingDown(): we want to send Orphan()
   1.128 +    // while the parent is in its PR_Sleep()
   1.129 +    PR_Sleep(1000);
   1.130 +
   1.131 +    if (!SendOrphan())
   1.132 +        fail("sending Orphan");
   1.133 +
   1.134 +    return true;
   1.135 +}
   1.136 +
   1.137 +bool
   1.138 +TestInterruptShutdownRaceChild::AnswerExit()
   1.139 +{
   1.140 +    _exit(0);
   1.141 +    NS_RUNTIMEABORT("unreached");
   1.142 +    return false;
   1.143 +}
   1.144 +
   1.145 +
   1.146 +} // namespace _ipdltest
   1.147 +} // namespace mozilla

mercurial