ipc/ipdl/test/cxx/TestOpens.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

     1 #include "base/thread.h"
     3 #include "TestOpens.h"
     5 #include "IPDLUnitTests.h"      // fail etc.
     7 template<>
     8 struct RunnableMethodTraits<mozilla::_ipdltest::TestOpensChild>
     9 {
    10     static void RetainCallee(mozilla::_ipdltest::TestOpensChild* obj) { }
    11     static void ReleaseCallee(mozilla::_ipdltest::TestOpensChild* obj) { }
    12 };
    14 template<>
    15 struct RunnableMethodTraits<mozilla::_ipdltest2::TestOpensOpenedChild>
    16 {
    17     static void RetainCallee(mozilla::_ipdltest2::TestOpensOpenedChild* obj) { }
    18     static void ReleaseCallee(mozilla::_ipdltest2::TestOpensOpenedChild* obj) { }
    19 };
    21 using namespace base;
    22 using namespace mozilla::ipc;
    24 namespace mozilla {
    25 // NB: this is generally bad style, but I am lazy.
    26 using namespace _ipdltest;
    27 using namespace _ipdltest2;
    29 static MessageLoop* gMainThread;
    31 static void
    32 AssertNotMainThread()
    33 {
    34     if (!gMainThread)
    35         fail("gMainThread is not initialized");
    36     if (MessageLoop::current() == gMainThread)
    37         fail("unexpectedly called on the main thread");
    38 }
    40 //-----------------------------------------------------------------------------
    41 // parent
    43 // Thread on which TestOpensOpenedParent runs
    44 static Thread* gParentThread;
    46 void
    47 TestOpensParent::Main()
    48 {
    49     if (!SendStart())
    50         fail("sending Start");
    51 }
    53 static void
    54 OpenParent(TestOpensOpenedParent* aParent,
    55            Transport* aTransport, ProcessHandle aOtherProcess)
    56 {
    57     AssertNotMainThread();
    59     // Open the actor on the off-main thread to park it there.
    60     // Messages will be delivered to this thread's message loop
    61     // instead of the main thread's.
    62     if (!aParent->Open(aTransport, aOtherProcess,
    63                        XRE_GetIOMessageLoop(), ipc::ParentSide))
    64         fail("opening Parent");
    65 }
    67 PTestOpensOpenedParent*
    68 TestOpensParent::AllocPTestOpensOpenedParent(Transport* transport,
    69                                              ProcessId otherProcess)
    70 {
    71     gMainThread = MessageLoop::current();
    73     ProcessHandle h;
    74     if (!base::OpenProcessHandle(otherProcess, &h)) {
    75         return nullptr;
    76     }
    78     gParentThread = new Thread("ParentThread");
    79     if (!gParentThread->Start())
    80         fail("starting parent thread");
    82     TestOpensOpenedParent* a = new TestOpensOpenedParent(transport);
    83     gParentThread->message_loop()->PostTask(
    84         FROM_HERE,
    85         NewRunnableFunction(OpenParent, a, transport, h));
    87     return a;
    88 }
    90 void
    91 TestOpensParent::ActorDestroy(ActorDestroyReason why)
    92 {
    93     // Stops the thread and joins it
    94     delete gParentThread;
    96     if (NormalShutdown != why)
    97         fail("unexpected destruction!");  
    98     passed("ok");
    99     QuitParent();
   100 }
   102 bool
   103 TestOpensOpenedParent::RecvHello()
   104 {
   105     AssertNotMainThread();
   106     return SendHi();
   107 }
   109 bool
   110 TestOpensOpenedParent::RecvHelloSync()
   111 {
   112     AssertNotMainThread();
   113     return true;
   114 }
   116 bool
   117 TestOpensOpenedParent::AnswerHelloRpc()
   118 {
   119     AssertNotMainThread();
   120     return CallHiRpc();
   121 }
   123 void
   124 TestOpensOpenedParent::ActorDestroy(ActorDestroyReason why)
   125 {
   126     AssertNotMainThread();
   128     if (NormalShutdown != why)
   129         fail("unexpected destruction!");
   131     // ActorDestroy() is just a callback from IPDL-generated code,
   132     // which needs the top-level actor (this) to stay alive a little
   133     // longer so other things can be cleaned up.
   134     MessageLoop::current()->PostTask(
   135         FROM_HERE,
   136         new DeleteTask<TestOpensOpenedParent>(this));
   137     XRE_GetIOMessageLoop()->PostTask(
   138         FROM_HERE,
   139         new DeleteTask<Transport>(mTransport));
   140 }
   142 //-----------------------------------------------------------------------------
   143 // child
   145 static TestOpensChild* gOpensChild;
   146 // Thread on which TestOpensOpenedChild runs
   147 static Thread* gChildThread;
   149 TestOpensChild::TestOpensChild()
   150 {
   151     gOpensChild = this;
   152 }
   154 bool
   155 TestOpensChild::RecvStart()
   156 {
   157     if (!PTestOpensOpened::Open(this))
   158         fail("opening PTestOpensOpened");
   159     return true;
   160 }
   162 static void
   163 OpenChild(TestOpensOpenedChild* aChild,
   164            Transport* aTransport, ProcessHandle aOtherProcess)
   165 {
   166     AssertNotMainThread();
   168     // Open the actor on the off-main thread to park it there.
   169     // Messages will be delivered to this thread's message loop
   170     // instead of the main thread's.
   171     if (!aChild->Open(aTransport, aOtherProcess,
   172                       XRE_GetIOMessageLoop(), ipc::ChildSide))
   173         fail("opening Child");
   175     // Kick off the unit tests
   176     if (!aChild->SendHello())
   177         fail("sending Hello");
   178 }
   180 PTestOpensOpenedChild*
   181 TestOpensChild::AllocPTestOpensOpenedChild(Transport* transport,
   182                                            ProcessId otherProcess)
   183 {
   184     gMainThread = MessageLoop::current();
   186     ProcessHandle h;
   187     if (!base::OpenProcessHandle(otherProcess, &h)) {
   188         return nullptr;
   189     }
   191     gChildThread = new Thread("ChildThread");
   192     if (!gChildThread->Start())
   193         fail("starting child thread");
   195     TestOpensOpenedChild* a = new TestOpensOpenedChild(transport);
   196     gChildThread->message_loop()->PostTask(
   197         FROM_HERE,
   198         NewRunnableFunction(OpenChild, a, transport, h));
   200     return a;
   201 }
   203 void
   204 TestOpensChild::ActorDestroy(ActorDestroyReason why)
   205 {
   206     // Stops the thread and joins it
   207     delete gChildThread;
   209     if (NormalShutdown != why)
   210         fail("unexpected destruction!");
   211     QuitChild();
   212 }
   214 bool
   215 TestOpensOpenedChild::RecvHi()
   216 {
   217     AssertNotMainThread();
   219     if (!SendHelloSync())
   220         fail("sending HelloSync");
   221     if (!CallHelloRpc())
   222         fail("calling HelloRpc");
   223     if (!mGotHi)
   224         fail("didn't answer HiRpc");
   226     // Need to close the channel without message-processing frames on
   227     // the C++ stack
   228     MessageLoop::current()->PostTask(
   229         FROM_HERE,
   230         NewRunnableMethod(this, &TestOpensOpenedChild::Close));
   231     return true;
   232 }
   234 bool
   235 TestOpensOpenedChild::AnswerHiRpc()
   236 {
   237     AssertNotMainThread();
   239     mGotHi = true;              // d00d
   240     return true;
   241 }
   243 static void
   244 ShutdownTestOpensOpenedChild(TestOpensOpenedChild* child,
   245                              Transport* transport)
   246 {
   247     delete child;
   249     // Now delete the transport, which has to happen after the
   250     // top-level actor is deleted.
   251     XRE_GetIOMessageLoop()->PostTask(
   252         FROM_HERE,
   253         new DeleteTask<Transport>(transport));
   255     // Kick off main-thread shutdown.
   256     gMainThread->PostTask(
   257         FROM_HERE,
   258         NewRunnableMethod(gOpensChild, &TestOpensChild::Close));
   259 }
   261 void
   262 TestOpensOpenedChild::ActorDestroy(ActorDestroyReason why)
   263 {
   264     AssertNotMainThread();
   266     if (NormalShutdown != why)
   267         fail("unexpected destruction!");  
   269     // ActorDestroy() is just a callback from IPDL-generated code,
   270     // which needs the top-level actor (this) to stay alive a little
   271     // longer so other things can be cleaned up.  Defer shutdown to
   272     // let cleanup finish.
   273     MessageLoop::current()->PostTask(
   274         FROM_HERE,
   275         NewRunnableFunction(ShutdownTestOpensOpenedChild,
   276                             this, mTransport));
   277 }
   279 } // namespace mozilla

mercurial