1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 4 #include "TestEndpointBridgeMain.h" 5 6 #include "base/task.h" 7 #include "IPDLUnitTests.h" // fail etc. 8 #include "IPDLUnitTestSubprocess.h" 9 10 using namespace std; 11 12 namespace mozilla { 13 namespace _ipdltest { 14 15 16 //----------------------------------------------------------------------------- 17 // main process 18 void Main()19TestEndpointBridgeMainParent::Main() 20 { 21 if (!SendStart()) { 22 fail("sending Start"); 23 } 24 } 25 26 bool RecvBridged(Endpoint<PTestEndpointBridgeMainSubParent> && endpoint)27TestEndpointBridgeMainParent::RecvBridged(Endpoint<PTestEndpointBridgeMainSubParent>&& endpoint) 28 { 29 TestEndpointBridgeMainSubParent* a = new TestEndpointBridgeMainSubParent(); 30 if (!endpoint.Bind(a)) { 31 fail("Bind failed"); 32 } 33 return true; 34 } 35 36 void ActorDestroy(ActorDestroyReason why)37TestEndpointBridgeMainParent::ActorDestroy(ActorDestroyReason why) 38 { 39 if (NormalShutdown != why) { 40 fail("unexpected destruction!"); 41 } 42 passed("ok"); 43 QuitParent(); 44 } 45 46 bool RecvHello()47TestEndpointBridgeMainSubParent::RecvHello() 48 { 49 return SendHi(); 50 } 51 52 bool RecvHelloSync()53TestEndpointBridgeMainSubParent::RecvHelloSync() 54 { 55 return true; 56 } 57 58 bool AnswerHelloRpc()59TestEndpointBridgeMainSubParent::AnswerHelloRpc() 60 { 61 return CallHiRpc(); 62 } 63 64 void ActorDestroy(ActorDestroyReason why)65TestEndpointBridgeMainSubParent::ActorDestroy(ActorDestroyReason why) 66 { 67 if (NormalShutdown != why) { 68 fail("unexpected destruction!"); 69 } 70 71 // ActorDestroy() is just a callback from IPDL-generated code, 72 // which needs the top-level actor (this) to stay alive a little 73 // longer so other things can be cleaned up. 74 MessageLoop::current()->PostTask( 75 do_AddRef(new DeleteTask<TestEndpointBridgeMainSubParent>(this))); 76 } 77 78 //----------------------------------------------------------------------------- 79 // sub process --- child of main 80 TestEndpointBridgeMainChild* gEndpointBridgeMainChild; 81 TestEndpointBridgeMainChild()82TestEndpointBridgeMainChild::TestEndpointBridgeMainChild() 83 : mSubprocess(nullptr) 84 { 85 gEndpointBridgeMainChild = this; 86 } 87 88 bool RecvStart()89TestEndpointBridgeMainChild::RecvStart() 90 { 91 vector<string> subsubArgs; 92 subsubArgs.push_back("TestEndpointBridgeSub"); 93 94 mSubprocess = new IPDLUnitTestSubprocess(); 95 if (!mSubprocess->SyncLaunch(subsubArgs)) { 96 fail("problem launching subprocess"); 97 } 98 99 IPC::Channel* transport = mSubprocess->GetChannel(); 100 if (!transport) { 101 fail("no transport"); 102 } 103 104 TestEndpointBridgeSubParent* bsp = new TestEndpointBridgeSubParent(); 105 bsp->Open(transport, base::GetProcId(mSubprocess->GetChildProcessHandle())); 106 107 bsp->Main(); 108 return true; 109 } 110 111 void ActorDestroy(ActorDestroyReason why)112TestEndpointBridgeMainChild::ActorDestroy(ActorDestroyReason why) 113 { 114 if (NormalShutdown != why) { 115 fail("unexpected destruction!"); 116 } 117 // NB: this is kosher because QuitChild() joins with the IO thread 118 XRE_GetIOMessageLoop()->PostTask( 119 do_AddRef(new DeleteTask<IPDLUnitTestSubprocess>(mSubprocess))); 120 QuitChild(); 121 } 122 123 void Main()124TestEndpointBridgeSubParent::Main() 125 { 126 if (!SendPing()) { 127 fail("sending Ping"); 128 } 129 } 130 131 bool RecvBridgeEm()132TestEndpointBridgeSubParent::RecvBridgeEm() 133 { 134 Endpoint<PTestEndpointBridgeMainSubParent> parent; 135 Endpoint<PTestEndpointBridgeMainSubChild> child; 136 nsresult rv; 137 rv = PTestEndpointBridgeMainSub::CreateEndpoints( 138 gEndpointBridgeMainChild->OtherPid(), OtherPid(), 139 &parent, &child); 140 if (NS_FAILED(rv)) { 141 fail("opening PTestEndpointOpensOpened"); 142 } 143 144 if (!gEndpointBridgeMainChild->SendBridged(mozilla::Move(parent))) { 145 fail("SendBridge failed for parent"); 146 } 147 if (!SendBridged(mozilla::Move(child))) { 148 fail("SendBridge failed for child"); 149 } 150 151 return true; 152 } 153 154 void ActorDestroy(ActorDestroyReason why)155TestEndpointBridgeSubParent::ActorDestroy(ActorDestroyReason why) 156 { 157 if (NormalShutdown != why) { 158 fail("unexpected destruction!"); 159 } 160 gEndpointBridgeMainChild->Close(); 161 162 // ActorDestroy() is just a callback from IPDL-generated code, 163 // which needs the top-level actor (this) to stay alive a little 164 // longer so other things can be cleaned up. 165 MessageLoop::current()->PostTask( 166 do_AddRef(new DeleteTask<TestEndpointBridgeSubParent>(this))); 167 } 168 169 //----------------------------------------------------------------------------- 170 // subsub process --- child of sub 171 172 static TestEndpointBridgeSubChild* gBridgeSubChild; 173 TestEndpointBridgeSubChild()174TestEndpointBridgeSubChild::TestEndpointBridgeSubChild() 175 { 176 gBridgeSubChild = this; 177 } 178 179 bool RecvPing()180TestEndpointBridgeSubChild::RecvPing() 181 { 182 if (!SendBridgeEm()) { 183 fail("sending BridgeEm"); 184 } 185 return true; 186 } 187 188 bool RecvBridged(Endpoint<PTestEndpointBridgeMainSubChild> && endpoint)189TestEndpointBridgeSubChild::RecvBridged(Endpoint<PTestEndpointBridgeMainSubChild>&& endpoint) 190 { 191 TestEndpointBridgeMainSubChild* a = new TestEndpointBridgeMainSubChild(); 192 193 if (!endpoint.Bind(a)) { 194 fail("failed to Bind"); 195 } 196 197 if (!a->SendHello()) { 198 fail("sending Hello"); 199 } 200 201 return true; 202 } 203 204 void ActorDestroy(ActorDestroyReason why)205TestEndpointBridgeSubChild::ActorDestroy(ActorDestroyReason why) 206 { 207 if (NormalShutdown != why) { 208 fail("unexpected destruction!"); 209 } 210 QuitChild(); 211 } 212 213 bool RecvHi()214TestEndpointBridgeMainSubChild::RecvHi() 215 { 216 if (!SendHelloSync()) { 217 fail("sending HelloSync"); 218 } 219 if (!CallHelloRpc()) { 220 fail("calling HelloRpc"); 221 } 222 if (!mGotHi) { 223 fail("didn't answer HiRpc"); 224 } 225 226 // Need to close the channel without message-processing frames on 227 // the C++ stack 228 MessageLoop::current()->PostTask( 229 NewNonOwningRunnableMethod(this, &TestEndpointBridgeMainSubChild::Close)); 230 return true; 231 } 232 233 bool AnswerHiRpc()234TestEndpointBridgeMainSubChild::AnswerHiRpc() 235 { 236 mGotHi = true; // d00d 237 return true; 238 } 239 240 void ActorDestroy(ActorDestroyReason why)241TestEndpointBridgeMainSubChild::ActorDestroy(ActorDestroyReason why) 242 { 243 if (NormalShutdown != why) { 244 fail("unexpected destruction!"); 245 } 246 247 gBridgeSubChild->Close(); 248 249 // ActorDestroy() is just a callback from IPDL-generated code, 250 // which needs the top-level actor (this) to stay alive a little 251 // longer so other things can be cleaned up. 252 MessageLoop::current()->PostTask( 253 do_AddRef(new DeleteTask<TestEndpointBridgeMainSubChild>(this))); 254 } 255 256 } // namespace mozilla 257 } // namespace _ipdltest 258