ipc/ipdl/test/cxx/TestOpens.cpp

Wed, 31 Dec 2014 13:27:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 13:27:57 +0100
branch
TOR_BUG_3246
changeset 6
8bccb770b82d
permissions
-rw-r--r--

Ignore runtime configuration files generated during quality assurance.

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

mercurial