From 5f8de423f190bbb79a62f804151bc24824fa32d8 Mon Sep 17 00:00:00 2001 From: "Matt A. Tobin" Date: Fri, 2 Feb 2018 04:16:08 -0500 Subject: Add m-esr52 at 52.6.0 --- ipc/ipdl/test/cxx/TestEndpointOpens.cpp | 271 ++++++++++++++++++++++++++++++++ 1 file changed, 271 insertions(+) create mode 100644 ipc/ipdl/test/cxx/TestEndpointOpens.cpp (limited to 'ipc/ipdl/test/cxx/TestEndpointOpens.cpp') diff --git a/ipc/ipdl/test/cxx/TestEndpointOpens.cpp b/ipc/ipdl/test/cxx/TestEndpointOpens.cpp new file mode 100644 index 0000000000..820273ad77 --- /dev/null +++ b/ipc/ipdl/test/cxx/TestEndpointOpens.cpp @@ -0,0 +1,271 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ + +#include "base/task.h" +#include "base/thread.h" + +#include "TestEndpointOpens.h" + +#include "IPDLUnitTests.h" // fail etc. + +using namespace mozilla::ipc; + +using base::ProcessHandle; +using base::Thread; + +namespace mozilla { +// NB: this is generally bad style, but I am lazy. +using namespace _ipdltest; +using namespace _ipdltest2; + +static MessageLoop* gMainThread; + +static void +AssertNotMainThread() +{ + if (!gMainThread) { + fail("gMainThread is not initialized"); + } + if (MessageLoop::current() == gMainThread) { + fail("unexpectedly called on the main thread"); + } +} + +//----------------------------------------------------------------------------- +// parent + +// Thread on which TestEndpointOpensOpenedParent runs +static Thread* gParentThread; + +void +TestEndpointOpensParent::Main() +{ + if (!SendStart()) { + fail("sending Start"); + } +} + +static void +OpenParent(TestEndpointOpensOpenedParent* aParent, + Endpoint&& aEndpoint) +{ + AssertNotMainThread(); + + // Open the actor on the off-main thread to park it there. + // Messages will be delivered to this thread's message loop + // instead of the main thread's. + if (!aEndpoint.Bind(aParent)) { + fail("binding Parent"); + } +} + +bool +TestEndpointOpensParent::RecvStartSubprotocol( + mozilla::ipc::Endpoint&& endpoint) +{ + gMainThread = MessageLoop::current(); + + gParentThread = new Thread("ParentThread"); + if (!gParentThread->Start()) { + fail("starting parent thread"); + } + + TestEndpointOpensOpenedParent* a = new TestEndpointOpensOpenedParent(); + gParentThread->message_loop()->PostTask( + NewRunnableFunction(OpenParent, a, mozilla::Move(endpoint))); + + return true; +} + +void +TestEndpointOpensParent::ActorDestroy(ActorDestroyReason why) +{ + // Stops the thread and joins it + delete gParentThread; + + if (NormalShutdown != why) { + fail("unexpected destruction A!"); + } + passed("ok"); + QuitParent(); +} + +bool +TestEndpointOpensOpenedParent::RecvHello() +{ + AssertNotMainThread(); + return SendHi(); +} + +bool +TestEndpointOpensOpenedParent::RecvHelloSync() +{ + AssertNotMainThread(); + return true; +} + +bool +TestEndpointOpensOpenedParent::AnswerHelloRpc() +{ + AssertNotMainThread(); + return CallHiRpc(); +} + +static void +ShutdownTestEndpointOpensOpenedParent(TestEndpointOpensOpenedParent* parent, + Transport* transport) +{ + delete parent; +} + +void +TestEndpointOpensOpenedParent::ActorDestroy(ActorDestroyReason why) +{ + AssertNotMainThread(); + + if (NormalShutdown != why) { + fail("unexpected destruction B!"); + } + + // ActorDestroy() is just a callback from IPDL-generated code, + // which needs the top-level actor (this) to stay alive a little + // longer so other things can be cleaned up. + gParentThread->message_loop()->PostTask( + NewRunnableFunction(ShutdownTestEndpointOpensOpenedParent, + this, GetTransport())); +} + +//----------------------------------------------------------------------------- +// child + +static TestEndpointOpensChild* gOpensChild; +// Thread on which TestEndpointOpensOpenedChild runs +static Thread* gChildThread; + +TestEndpointOpensChild::TestEndpointOpensChild() +{ + gOpensChild = this; +} + +static void +OpenChild(TestEndpointOpensOpenedChild* aChild, + Endpoint&& endpoint) +{ + AssertNotMainThread(); + + // Open the actor on the off-main thread to park it there. + // Messages will be delivered to this thread's message loop + // instead of the main thread's. + if (!endpoint.Bind(aChild)) { + fail("binding child endpoint"); + } + + // Kick off the unit tests + if (!aChild->SendHello()) { + fail("sending Hello"); + } +} + +bool +TestEndpointOpensChild::RecvStart() +{ + Endpoint parent; + Endpoint child; + nsresult rv; + rv = PTestEndpointOpensOpened::CreateEndpoints(OtherPid(), base::GetCurrentProcId(), + &parent, &child); + if (NS_FAILED(rv)) { + fail("opening PTestEndpointOpensOpened"); + } + + gMainThread = MessageLoop::current(); + + gChildThread = new Thread("ChildThread"); + if (!gChildThread->Start()) { + fail("starting child thread"); + } + + TestEndpointOpensOpenedChild* a = new TestEndpointOpensOpenedChild(); + gChildThread->message_loop()->PostTask( + NewRunnableFunction(OpenChild, a, mozilla::Move(child))); + + if (!SendStartSubprotocol(parent)) { + fail("send StartSubprotocol"); + } + + return true; +} + +void +TestEndpointOpensChild::ActorDestroy(ActorDestroyReason why) +{ + // Stops the thread and joins it + delete gChildThread; + + if (NormalShutdown != why) { + fail("unexpected destruction C!"); + } + QuitChild(); +} + +bool +TestEndpointOpensOpenedChild::RecvHi() +{ + AssertNotMainThread(); + + if (!SendHelloSync()) { + fail("sending HelloSync"); + } + if (!CallHelloRpc()) { + fail("calling HelloRpc"); + } + if (!mGotHi) { + fail("didn't answer HiRpc"); + } + + // Need to close the channel without message-processing frames on + // the C++ stack + MessageLoop::current()->PostTask( + NewNonOwningRunnableMethod(this, &TestEndpointOpensOpenedChild::Close)); + return true; +} + +bool +TestEndpointOpensOpenedChild::AnswerHiRpc() +{ + AssertNotMainThread(); + + mGotHi = true; // d00d + return true; +} + +static void +ShutdownTestEndpointOpensOpenedChild(TestEndpointOpensOpenedChild* child, + Transport* transport) +{ + delete child; + + // Kick off main-thread shutdown. + gMainThread->PostTask( + NewNonOwningRunnableMethod(gOpensChild, &TestEndpointOpensChild::Close)); +} + +void +TestEndpointOpensOpenedChild::ActorDestroy(ActorDestroyReason why) +{ + AssertNotMainThread(); + + if (NormalShutdown != why) { + fail("unexpected destruction D!"); + } + + // ActorDestroy() is just a callback from IPDL-generated code, + // which needs the top-level actor (this) to stay alive a little + // longer so other things can be cleaned up. Defer shutdown to + // let cleanup finish. + gChildThread->message_loop()->PostTask( + NewRunnableFunction(ShutdownTestEndpointOpensOpenedChild, + this, GetTransport())); +} + +} // namespace mozilla -- cgit v1.2.3