diff options
Diffstat (limited to 'ipc/ipdl/test/gtest')
43 files changed, 3248 insertions, 37 deletions
diff --git a/ipc/ipdl/test/gtest/IPDLUnitTest.h b/ipc/ipdl/test/gtest/IPDLUnitTest.h index f4548b508c..e2c44630b7 100644 --- a/ipc/ipdl/test/gtest/IPDLUnitTest.h +++ b/ipc/ipdl/test/gtest/IPDLUnitTest.h @@ -27,52 +27,75 @@ class IPDLTestHelper { virtual void TestBody() = 0; }; -#define IPDL_TEST_CLASS_NAME_(actorname) IPDL_TEST_##actorname +#define IPDL_TEST_CLASS_NAME_(actorname, ...) IPDL_TEST_##actorname##__VA_ARGS__ -#define IPDL_TEST_HEAD_(actorname) \ - class IPDL_TEST_CLASS_NAME_(actorname) \ - : public ::mozilla::_ipdltest::IPDLTestHelper { \ - public: \ - IPDL_TEST_CLASS_NAME_(actorname)() : mActor(new actorname##Parent) {} \ - \ - private: \ - void TestBody() override; \ - const char* GetName() override { return sName; }; \ - actorname##Parent* GetActor() override { return mActor; }; \ - \ - RefPtr<actorname##Parent> mActor; \ - static const char* sName; \ - }; \ - const char* IPDL_TEST_CLASS_NAME_(actorname)::sName = \ - ::mozilla::_ipdltest::RegisterAllocChildActor( \ - #actorname, []() -> ::mozilla::ipc::IToplevelProtocol* { \ - return new actorname##Child; \ +#define IPDL_TEST_HEAD_(actorname, ...) \ + class IPDL_TEST_CLASS_NAME_(actorname, ##__VA_ARGS__) \ + : public ::mozilla::_ipdltest::IPDLTestHelper { \ + public: \ + IPDL_TEST_CLASS_NAME_(actorname, ##__VA_ARGS__) \ + () : mActor(new actorname##Parent) {} \ + \ + private: \ + void TestBody() override; \ + const char* GetName() override { return sName; }; \ + actorname##Parent* GetActor() override { return mActor; }; \ + \ + RefPtr<actorname##Parent> mActor; \ + static const char* sName; \ + }; \ + const char* IPDL_TEST_CLASS_NAME_(actorname, ##__VA_ARGS__)::sName = \ + ::mozilla::_ipdltest::RegisterAllocChildActor( \ + #actorname, []() -> ::mozilla::ipc::IToplevelProtocol* { \ + return new actorname##Child; \ }); -#define IPDL_TEST_DECL_(testgroup, actorname, crossprocess) \ - TEST(testgroup, actorname) \ - { \ - IPDL_TEST_CLASS_NAME_(actorname) test; \ - test.TestWrapper(crossprocess); \ +#define IPDL_TEST_DECL_CROSSPROCESS_(actorname, ...) \ + TEST(IPDLTest_CrossProcess, actorname##__VA_ARGS__) \ + { \ + IPDL_TEST_CLASS_NAME_(actorname, ##__VA_ARGS__) test; \ + test.TestWrapper(true); \ } -#define IPDL_TEST_BODY_SEGUE_(actorname) \ - void IPDL_TEST_CLASS_NAME_(actorname)::TestBody() +#define IPDL_TEST_DECL_CROSSTHREAD_(actorname, ...) \ + TEST(IPDLTest_CrossThread, actorname##__VA_ARGS__) \ + { \ + IPDL_TEST_CLASS_NAME_(actorname, ##__VA_ARGS__) test; \ + test.TestWrapper(false); \ + } + +#define IPDL_TEST_DECL_ANY_(actorname, ...) \ + IPDL_TEST_DECL_CROSSPROCESS_(actorname, ##__VA_ARGS__) \ + IPDL_TEST_DECL_CROSSTHREAD_(actorname, ##__VA_ARGS__) + +#define IPDL_TEST_BODY_SEGUE_(actorname, ...) \ + void IPDL_TEST_CLASS_NAME_(actorname, ##__VA_ARGS__)::TestBody() -// Declare a basic IPDL unit test which will be run in both both cross-thread -// and cross-process configurations. The actor `actorname` will be instantiated -// by default-constructing the parent & child actors in the relevant processes, -// and the test block will be executed, with `mActor` being a pointer to the -// parent actor. The test is asynchronous, and will end when the IPDL connection -// between the created actors is destroyed. +// Declare an IPDL unit test. The `mode` should be set to either `CROSSTHREAD`, +// `CROSSPROCESS`, or `ANY` to run in the selected configuration(s). The actor +// `actorname` will be instantiated by default-constructing the parent & child +// actors in the relevant processes, and the test block will be executed, with +// `mActor` being a pointer to the parent actor. The test is asynchronous, and +// will end when the IPDL connection between the created actors is destroyed. +// `aCrossProcess` will indicate whether the test is running cross-process +// (true) or cross-thread (false). +// +// You can optionally pass a single additional argument which provides a +// `testname`, which will be appended to `actorname` as the full GTest test +// name. It should be of the form usually passed to the `TEST` gtest macro (an +// identifier). // // GTest assertions fired in the child process will be relayed to the parent // process, and should generally function correctly. -#define IPDL_TEST(actorname) \ - IPDL_TEST_HEAD_(actorname) \ - IPDL_TEST_DECL_(IPDLTest_CrossProcess, actorname, true) \ - IPDL_TEST_DECL_(IPDLTest_CrossThread, actorname, false) \ - IPDL_TEST_BODY_SEGUE_(actorname) +#define IPDL_TEST_ON(mode, actorname, ...) \ + IPDL_TEST_HEAD_(actorname, ##__VA_ARGS__) \ + IPDL_TEST_DECL_##mode##_(actorname, ##__VA_ARGS__) \ + IPDL_TEST_BODY_SEGUE_(actorname, ##__VA_ARGS__) + +// Declare an IPDL unit test that will run in both cross-thread and +// cross-process configurations. See the documentation of IPDL_TEST_ON for more +// info. +#define IPDL_TEST(actorname, ...) IPDL_TEST_ON(ANY, actorname, ##__VA_ARGS__) } // namespace mozilla::_ipdltest diff --git a/ipc/ipdl/test/gtest/PTestAsyncReturns.ipdl b/ipc/ipdl/test/gtest/PTestAsyncReturns.ipdl new file mode 100644 index 0000000000..5cae489b4a --- /dev/null +++ b/ipc/ipdl/test/gtest/PTestAsyncReturns.ipdl @@ -0,0 +1,19 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +namespace mozilla { +namespace _ipdltest { + +[ChildProc=any, ChildImpl=virtual, ParentImpl=virtual] +protocol PTestAsyncReturns { +child: + async Ping() returns (bool one); + async NoReturn() returns (bool unused); + +parent: + async Pong() returns (uint32_t param1, uint32_t param2); +}; + +} // namespace mozilla +} // namespace _ipdltest diff --git a/ipc/ipdl/test/gtest/PTestCancel.ipdl b/ipc/ipdl/test/gtest/PTestCancel.ipdl new file mode 100644 index 0000000000..b0af04bae7 --- /dev/null +++ b/ipc/ipdl/test/gtest/PTestCancel.ipdl @@ -0,0 +1,39 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +namespace mozilla { +namespace _ipdltest { + +[NestedUpTo=inside_sync, ChildProc=any, ChildImpl=virtual, ParentImpl=virtual] +sync protocol PTestCancel +{ + // Immediate Cancel: child sync function cancels immediately, both ends check after cancellation. +child: + [Nested=inside_sync] sync ImmediateCancel(); + + + // Nested Cancel: child nested sync function cancels +child: + async StartNestedCancel(); + [Nested=inside_sync] sync NestedCancel(); +parent: + [Nested=inside_sync] sync CallNestedCancel(); + + + // Nested Cancel Parent: parent nested sync function cancels +child: + [Nested=inside_sync] sync StartNestedCancelParent(); +parent: + [Nested=inside_sync] sync NestedCancelParent(); + + +// Common functions to check that sync messages still work. +child: + [Nested=inside_sync] sync CheckChild() returns (uint32_t reply); +parent: + [Nested=inside_sync] sync CheckParent() returns (uint32_t reply); +}; + +} // namespace _ipdltest +} // namespace mozilla diff --git a/ipc/ipdl/test/gtest/PTestDataStructures.ipdl b/ipc/ipdl/test/gtest/PTestDataStructures.ipdl new file mode 100644 index 0000000000..7b2bdd3ced --- /dev/null +++ b/ipc/ipdl/test/gtest/PTestDataStructures.ipdl @@ -0,0 +1,106 @@ +include protocol PTestDataStructuresSub; +include PTestDataStructuresCommon; + +include "mozilla/GfxMessageUtils.h"; + +namespace mozilla { +namespace _ipdltest { + +[ChildProc=any, ChildImpl=virtual, ParentImpl=virtual] +sync protocol PTestDataStructures { + manages PTestDataStructuresSub; + +child: + async PTestDataStructuresSub(int i); + + async Start(); + +parent: + async __delete__(); + + sync TestArrayOfInt(int[] i1) + returns (int[] o1); + + sync TestArrayOfActor(PTestDataStructuresSub[] i1) + returns (PTestDataStructuresSub[] o1); + + sync TestUnion(IntDouble i1, + IntDouble i2) + returns (IntDouble o1, + IntDouble o2); + + sync TestArrayOfUnion(IntDouble[] i1) + returns (IntDouble[] o1); + + sync TestUnionWithArray(IntDoubleArrays i1, + IntDoubleArrays i2, + IntDoubleArrays i3) + returns (IntDoubleArrays o1, + IntDoubleArrays o2, + IntDoubleArrays o3); + + sync TestArrayOfUnionWithArray(IntDoubleArrays[] i1) + returns (IntDoubleArrays[] o1); + + sync TestStructWithActor(ActorWrapper a1) + returns (ActorWrapper o1); + + sync TestUnionWithActors(Actors i1, + Actors i2, + Actors i3) + returns (Actors o1, + Actors o2, + Actors o3); + + sync TestArrayOfUnionWithActors(Actors[] i1) + returns (Actors[] o1); + + sync TestUnions(Unions i1, + Unions i2, + Unions i3, + Unions i4) + returns (Unions o1, + Unions o2, + Unions o3, + Unions o4); + + sync TestArrayOfUnions(Unions[] i1) + returns (Unions[] o1); + + sync TestStruct(SIntDouble i) + returns (SIntDouble o); + + sync TestStructWithArrays(SIntDoubleArrays i) + returns (SIntDoubleArrays o); + + sync TestStructWithActors(SActors i) + returns (SActors o); + + sync TestStructs(Structs i) + returns (Structs o); + + sync TestUnionWithStructs(WithStructs i1, + WithStructs i2, + WithStructs i3, + WithStructs i4, + WithStructs i5) + returns (WithStructs o1, + WithStructs o2, + WithStructs o3, + WithStructs o4, + WithStructs o5); + + sync TestStructWithUnions(WithUnions i) + returns (WithUnions o); + + sync TestUnionWithCxx(Op[] ops); + + // test that the ParamTraits<nsTArray>::Read() workaround for + // nsTArray's incorrect memmove() semantics works properly + // (nsIntRegion isn't memmove()able) + sync TestNsIntRegion(nsIntRegion[] ops); +}; + +} // namespace _ipdltest +} // namespace mozilla + diff --git a/ipc/ipdl/test/gtest/PTestDataStructuresCommon.ipdlh b/ipc/ipdl/test/gtest/PTestDataStructuresCommon.ipdlh new file mode 100644 index 0000000000..36549cc2c6 --- /dev/null +++ b/ipc/ipdl/test/gtest/PTestDataStructuresCommon.ipdlh @@ -0,0 +1,107 @@ +include protocol PTestDataStructuresSub; + +using struct mozilla::null_t from "mozilla/ipc/IPCCore.h"; +using nsIntRegion from "nsRegion.h"; + +namespace mozilla { +namespace _foo { + +union IntDouble { + int; + double; +}; + +struct SIntDouble { + int i; + double d; +}; + +union IntDoubleArrays { + int; + int[]; + double[]; +}; + +struct SIntDoubleArrays { + int i; + int[] ai; + double[] ad; +}; + +struct ActorWrapper { + nullable PTestDataStructuresSub actor; +}; + +union Actors { + int; + int[]; + PTestDataStructuresSub[]; +}; + +struct SActors { + int i; + int[] ai; + PTestDataStructuresSub[] ap; +}; + +union Unions { + int; + int[]; + PTestDataStructuresSub[]; + Actors[]; +}; + +struct Structs { + int i; + int[] ai; + PTestDataStructuresSub[] ap; + SActors[] aa; +}; + +union WithStructs { + int; + int[]; + PTestDataStructuresSub[]; + SActors[]; + Structs[]; +}; + +struct WithUnions { + int i; + int[] ai; + PTestDataStructuresSub[] ap; + Actors[] aa; + Unions[] au; +}; + +struct CommonAttrs { bool dummy; }; +struct FooAttrs { int dummy; }; +struct BarAttrs { float dummy; }; +union SpecificAttrs { + FooAttrs; + BarAttrs; +}; +struct Attrs { + CommonAttrs common; + SpecificAttrs specific; +}; +struct SetAttrs { + PTestDataStructuresSub x; + Attrs attrs; +}; +union Op { null_t; SetAttrs; }; + +struct ShmemStruct { + int i; + Shmem mem; +}; + +union ShmemUnion { + int; + Shmem; +}; + +struct Empty { }; + +} // namespace _foo +} // namespace mozilla diff --git a/ipc/ipdl/test/gtest/PTestDataStructuresSub.ipdl b/ipc/ipdl/test/gtest/PTestDataStructuresSub.ipdl new file mode 100644 index 0000000000..f9f7d69411 --- /dev/null +++ b/ipc/ipdl/test/gtest/PTestDataStructuresSub.ipdl @@ -0,0 +1,15 @@ +include protocol PTestDataStructures; + +namespace mozilla { +namespace _ipdltest { + +[ChildProc=any, ChildImpl=virtual, ParentImpl=virtual] +async protocol PTestDataStructuresSub { + manager PTestDataStructures; + +parent: + async __delete__(); +}; + +} // namespace _ipdltest +} // namespace mozilla diff --git a/ipc/ipdl/test/gtest/PTestDescendant.ipdl b/ipc/ipdl/test/gtest/PTestDescendant.ipdl new file mode 100644 index 0000000000..b8524babab --- /dev/null +++ b/ipc/ipdl/test/gtest/PTestDescendant.ipdl @@ -0,0 +1,22 @@ +include protocol PTestDescendantSub; +include protocol PTestDescendantSubsub; + +namespace mozilla { +namespace _ipdltest { + +[ChildProc=any, ChildImpl=virtual, ParentImpl=virtual] +async protocol PTestDescendant { + manages PTestDescendantSub; +child: + async PTestDescendantSub(nullable PTestDescendantSubsub dummy); + + async Test(PTestDescendantSubsub a); + + async __delete__(); + +parent: + async Ok(PTestDescendantSubsub a); +}; + +} +} diff --git a/ipc/ipdl/test/gtest/PTestDescendantSub.ipdl b/ipc/ipdl/test/gtest/PTestDescendantSub.ipdl new file mode 100644 index 0000000000..dd76801a43 --- /dev/null +++ b/ipc/ipdl/test/gtest/PTestDescendantSub.ipdl @@ -0,0 +1,19 @@ +include protocol PTestDescendant; +include protocol PTestDescendantSubsub; + +namespace mozilla { +namespace _ipdltest { + +[ChildProc=any, ChildImpl=virtual, ParentImpl=virtual] +async protocol PTestDescendantSub { + manager PTestDescendant; + manages PTestDescendantSubsub; + +child: + async __delete__(); + + async PTestDescendantSubsub(); +}; + +} +} diff --git a/ipc/ipdl/test/gtest/PTestDescendantSubsub.ipdl b/ipc/ipdl/test/gtest/PTestDescendantSubsub.ipdl new file mode 100644 index 0000000000..a2fac12d72 --- /dev/null +++ b/ipc/ipdl/test/gtest/PTestDescendantSubsub.ipdl @@ -0,0 +1,14 @@ +include protocol PTestDescendantSub; + +namespace mozilla { +namespace _ipdltest { + +[ChildProc=any, ChildImpl=virtual, ParentImpl=virtual] +async protocol PTestDescendantSubsub { + manager PTestDescendantSub; +child: + async __delete__(); +}; + +} +} diff --git a/ipc/ipdl/test/gtest/PTestEndpointOpens.ipdl b/ipc/ipdl/test/gtest/PTestEndpointOpens.ipdl new file mode 100644 index 0000000000..0ee1759b7f --- /dev/null +++ b/ipc/ipdl/test/gtest/PTestEndpointOpens.ipdl @@ -0,0 +1,22 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +include protocol PTestEndpointOpensOpened; + +namespace mozilla { +namespace _ipdltest { + +[ChildProc=any, ChildImpl=virtual, ParentImpl=virtual] +protocol PTestEndpointOpens { +child: + async Start(); + +parent: + async StartSubprotocol(Endpoint<PTestEndpointOpensOpenedParent> endpoint); + + async __delete__(); +}; + +} // namespace _ipdltest +} // namespace mozilla diff --git a/ipc/ipdl/test/gtest/PTestEndpointOpensOpened.ipdl b/ipc/ipdl/test/gtest/PTestEndpointOpensOpened.ipdl new file mode 100644 index 0000000000..1baa662235 --- /dev/null +++ b/ipc/ipdl/test/gtest/PTestEndpointOpensOpened.ipdl @@ -0,0 +1,22 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +namespace mozilla { +namespace _ipdltest { + +// (Opens protocols can have different semantics than the endpoints +// that opened them) +[ChildProc=any, ChildImpl=virtual, ParentImpl=virtual] +sync protocol PTestEndpointOpensOpened { +child: + async Hi(); + +parent: + async Hello(); + sync HelloSync(); + async __delete__(); +}; + +} // namespace _ipdltest +} // namespace mozilla diff --git a/ipc/ipdl/test/gtest/PTestHangs.ipdl b/ipc/ipdl/test/gtest/PTestHangs.ipdl new file mode 100644 index 0000000000..7df791cee6 --- /dev/null +++ b/ipc/ipdl/test/gtest/PTestHangs.ipdl @@ -0,0 +1,20 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +[MoveOnly] using mozilla::CrossProcessSemaphoreHandle from "mozilla/ipc/CrossProcessSemaphore.h"; + +namespace mozilla { +namespace _ipdltest { + +[ChildProc=any, ChildImpl=virtual, ParentImpl=virtual] +sync protocol PTestHangs { +parent: + sync Hang(uint32_t hangMode, CrossProcessSemaphoreHandle timeout); +child: + async Start(uint32_t hangMode) + returns (bool detectedHang); +}; + +} // namespace _ipdltest +} // namespace mozilla diff --git a/ipc/ipdl/test/gtest/PTestJSON.ipdl b/ipc/ipdl/test/gtest/PTestJSON.ipdl new file mode 100644 index 0000000000..2486e85378 --- /dev/null +++ b/ipc/ipdl/test/gtest/PTestJSON.ipdl @@ -0,0 +1,43 @@ +include protocol PTestJSONHandle; + +using struct mozilla::void_t from "mozilla/ipc/IPCCore.h"; +using struct mozilla::null_t from "mozilla/ipc/IPCCore.h"; + +namespace mozilla { +namespace _ipdltest { + +[Comparable] +struct KeyValue { + nsString key; + JSONVariant value; +}; + +[Comparable] +union JSONVariant { + void_t; + null_t; + bool; + int; + double; + nsString; + PTestJSONHandle; + KeyValue[]; + JSONVariant[]; +}; + +[ChildProc=any, ChildImpl=virtual, ParentImpl=virtual] +sync protocol PTestJSON { + manages PTestJSONHandle; + +child: + async Start(); + +parent: + async PTestJSONHandle(); + sync Test(JSONVariant i) + returns (JSONVariant o); + async __delete__(); +}; + +} // namespace mozilla +} // namespace _ipdltest diff --git a/ipc/ipdl/test/gtest/PTestJSONHandle.ipdl b/ipc/ipdl/test/gtest/PTestJSONHandle.ipdl new file mode 100644 index 0000000000..81bbb913b4 --- /dev/null +++ b/ipc/ipdl/test/gtest/PTestJSONHandle.ipdl @@ -0,0 +1,15 @@ +include protocol PTestJSON; + +namespace mozilla { +namespace _ipdltest { + +[ChildProc=any, ChildImpl=virtual, ParentImpl=virtual] +protocol PTestJSONHandle { + manager PTestJSON; + +child: + async __delete__(); +}; + +} // namespace mozilla +} // namespace _ipdltest diff --git a/ipc/ipdl/test/gtest/PTestManyChildAllocs.ipdl b/ipc/ipdl/test/gtest/PTestManyChildAllocs.ipdl new file mode 100644 index 0000000000..149e5aefab --- /dev/null +++ b/ipc/ipdl/test/gtest/PTestManyChildAllocs.ipdl @@ -0,0 +1,18 @@ +include protocol PTestManyChildAllocsSub; + +namespace mozilla { +namespace _ipdltest { + +[ChildProc=any, ChildImpl=virtual, ParentImpl=virtual] +protocol PTestManyChildAllocs { + manages PTestManyChildAllocsSub; +child: + async Go(); // start allocating + +parent: + async Done(); + async PTestManyChildAllocsSub(); +}; + +} // namespace _ipdltest +} // namespace mozilla diff --git a/ipc/ipdl/test/gtest/PTestManyChildAllocsSub.ipdl b/ipc/ipdl/test/gtest/PTestManyChildAllocsSub.ipdl new file mode 100644 index 0000000000..4a34af2e52 --- /dev/null +++ b/ipc/ipdl/test/gtest/PTestManyChildAllocsSub.ipdl @@ -0,0 +1,18 @@ +include protocol PTestManyChildAllocs; + +namespace mozilla { +namespace _ipdltest { + +[ChildProc=any, ChildImpl=virtual, ParentImpl=virtual] +protocol PTestManyChildAllocsSub { + manager PTestManyChildAllocs; + +child: + async __delete__(); + +parent: + async Hello(); +}; + +} // namespace _ipdltest +} // namespace mozilla diff --git a/ipc/ipdl/test/gtest/PTestMostNested.ipdl b/ipc/ipdl/test/gtest/PTestMostNested.ipdl new file mode 100644 index 0000000000..2c6750137c --- /dev/null +++ b/ipc/ipdl/test/gtest/PTestMostNested.ipdl @@ -0,0 +1,23 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +namespace mozilla { +namespace _ipdltest { + +[ChildProc=any, NestedUpTo=inside_cpow, ChildImpl=virtual, ParentImpl=virtual] +sync protocol PTestMostNested +{ +parent: + [Nested=inside_cpow] async Msg1(); + [Nested=inside_sync] sync Msg2(); + [Nested=inside_cpow] async Msg3(); + [Nested=inside_cpow] sync Msg4(); + +child: + async Start(); + [Nested=inside_sync] sync StartInner(); +}; + +} +} diff --git a/ipc/ipdl/test/gtest/PTestMultiMgrs.ipdl b/ipc/ipdl/test/gtest/PTestMultiMgrs.ipdl new file mode 100644 index 0000000000..80de57459d --- /dev/null +++ b/ipc/ipdl/test/gtest/PTestMultiMgrs.ipdl @@ -0,0 +1,23 @@ +include protocol PTestMultiMgrsLeft; +include protocol PTestMultiMgrsRight; + +namespace mozilla { +namespace _ipdltest { + +[ChildProc=any, ChildImpl=virtual, ParentImpl=virtual] +protocol PTestMultiMgrs { + manages PTestMultiMgrsLeft; + manages PTestMultiMgrsRight; + +parent: + async OK(); + +child: + async PTestMultiMgrsLeft(); + async PTestMultiMgrsRight(); + async Check(); + async __delete__(); +}; + +} // namespace _ipdltest +} // namespace mozilla diff --git a/ipc/ipdl/test/gtest/PTestMultiMgrsBottom.ipdl b/ipc/ipdl/test/gtest/PTestMultiMgrsBottom.ipdl new file mode 100644 index 0000000000..03bbc7f886 --- /dev/null +++ b/ipc/ipdl/test/gtest/PTestMultiMgrsBottom.ipdl @@ -0,0 +1,16 @@ +include protocol PTestMultiMgrsLeft; +include protocol PTestMultiMgrsRight; + +namespace mozilla { +namespace _ipdltest { + +[ChildProc=any, ChildImpl=virtual, ParentImpl=virtual] +protocol PTestMultiMgrsBottom { + manager PTestMultiMgrsLeft or PTestMultiMgrsRight; + +child: + async __delete__(); +}; + +} // namespace _ipdltest +} // namespace mozilla diff --git a/ipc/ipdl/test/gtest/PTestMultiMgrsLeft.ipdl b/ipc/ipdl/test/gtest/PTestMultiMgrsLeft.ipdl new file mode 100644 index 0000000000..ee62fc3487 --- /dev/null +++ b/ipc/ipdl/test/gtest/PTestMultiMgrsLeft.ipdl @@ -0,0 +1,19 @@ +include protocol PTestMultiMgrs; +include protocol PTestMultiMgrsBottom; + +namespace mozilla { +namespace _ipdltest { + +[ChildProc=any, ChildImpl=virtual, ParentImpl=virtual] +protocol PTestMultiMgrsLeft { + manager PTestMultiMgrs; + + manages PTestMultiMgrsBottom; + +child: + async PTestMultiMgrsBottom(); + async __delete__(); +}; + +} // namespace _ipdltest +} // namespace mozilla diff --git a/ipc/ipdl/test/gtest/PTestMultiMgrsRight.ipdl b/ipc/ipdl/test/gtest/PTestMultiMgrsRight.ipdl new file mode 100644 index 0000000000..202f60247e --- /dev/null +++ b/ipc/ipdl/test/gtest/PTestMultiMgrsRight.ipdl @@ -0,0 +1,19 @@ +include protocol PTestMultiMgrs; +include protocol PTestMultiMgrsBottom; + +namespace mozilla { +namespace _ipdltest { + +[ChildProc=any, ChildImpl=virtual, ParentImpl=virtual] +protocol PTestMultiMgrsRight { + manager PTestMultiMgrs; + + manages PTestMultiMgrsBottom; + +child: + async PTestMultiMgrsBottom(); + async __delete__(); +}; + +} // namespace _ipdltest +} // namespace mozilla diff --git a/ipc/ipdl/test/gtest/PTestSelfManage.ipdl b/ipc/ipdl/test/gtest/PTestSelfManage.ipdl new file mode 100644 index 0000000000..e7dc077808 --- /dev/null +++ b/ipc/ipdl/test/gtest/PTestSelfManage.ipdl @@ -0,0 +1,17 @@ +include protocol PTestSelfManageRoot; + +namespace mozilla { +namespace _ipdltest { + +[ChildProc=any, ChildImpl=virtual, ParentImpl=virtual] +protocol PTestSelfManage { + manager PTestSelfManageRoot or PTestSelfManage; + manages PTestSelfManage; + +child: + async PTestSelfManage(); + async __delete__(); +}; + +} // namespace mozilla +} // namespace _ipdltest diff --git a/ipc/ipdl/test/gtest/PTestSelfManageRoot.ipdl b/ipc/ipdl/test/gtest/PTestSelfManageRoot.ipdl new file mode 100644 index 0000000000..37e8218720 --- /dev/null +++ b/ipc/ipdl/test/gtest/PTestSelfManageRoot.ipdl @@ -0,0 +1,16 @@ +include protocol PTestSelfManage; + +namespace mozilla { +namespace _ipdltest { + +[ChildProc=any, ChildImpl=virtual, ParentImpl=virtual] +protocol PTestSelfManageRoot { + manages PTestSelfManage; + +child: + async PTestSelfManage(); + async __delete__(); +}; + +} // namespace mozilla +} // namespace _ipdltest diff --git a/ipc/ipdl/test/gtest/PTestShmem.ipdl b/ipc/ipdl/test/gtest/PTestShmem.ipdl new file mode 100644 index 0000000000..33eeabffdf --- /dev/null +++ b/ipc/ipdl/test/gtest/PTestShmem.ipdl @@ -0,0 +1,15 @@ +namespace mozilla { +namespace _ipdltest { + +[ChildProc=any, ChildImpl=virtual, ParentImpl=virtual] +protocol PTestShmem { +child: + async Give(Shmem mem, Shmem unsafe, uint32_t expectedSize); + +parent: + async Take(Shmem mem, Shmem unsafe, uint32_t expectedSize); + async __delete__(); +}; + +} +} diff --git a/ipc/ipdl/test/gtest/PTestSyncError.ipdl b/ipc/ipdl/test/gtest/PTestSyncError.ipdl new file mode 100644 index 0000000000..e549bde919 --- /dev/null +++ b/ipc/ipdl/test/gtest/PTestSyncError.ipdl @@ -0,0 +1,16 @@ +namespace mozilla { +namespace _ipdltest { + +[ChildProc=any, ChildImpl=virtual, ParentImpl=virtual] +sync protocol PTestSyncError { + +child: + async Start(); + +parent: + sync Error(); + async __delete__(); +}; + +} // namespace mozilla +} // namespace _ipdltest diff --git a/ipc/ipdl/test/gtest/PTestUniquePtrIPC.ipdl b/ipc/ipdl/test/gtest/PTestUniquePtrIPC.ipdl new file mode 100644 index 0000000000..b55d8f19d1 --- /dev/null +++ b/ipc/ipdl/test/gtest/PTestUniquePtrIPC.ipdl @@ -0,0 +1,17 @@ +namespace mozilla { +namespace _ipdltest { + +struct DummyStruct { + int x; +}; + +[ChildProc=any, ChildImpl=virtual, ParentImpl=virtual] +protocol PTestUniquePtrIPC { +child: + async TestMessage(UniquePtr<int> a1, UniquePtr<DummyStruct> a2, + DummyStruct a3, UniquePtr<int> a4); + async TestSendReference(UniquePtr<DummyStruct> a); +}; + +} // namespace _ipdltest +} // namespace mozilla diff --git a/ipc/ipdl/test/gtest/PTestUrgency.ipdl b/ipc/ipdl/test/gtest/PTestUrgency.ipdl new file mode 100644 index 0000000000..ee9b44b543 --- /dev/null +++ b/ipc/ipdl/test/gtest/PTestUrgency.ipdl @@ -0,0 +1,20 @@ +namespace mozilla { +namespace _ipdltest { + +[ChildProc=any, NestedUpTo=inside_cpow, ChildImpl=virtual, ParentImpl=virtual] +sync protocol PTestUrgency +{ +parent: + [Nested=inside_sync] sync Test1() returns (uint32_t result); + async Test2(); + sync Test3() returns (uint32_t result); + sync FinalTest_Begin(); + +child: + async Start(); + [Nested=inside_sync] sync Reply1() returns (uint32_t result); + [Nested=inside_sync] sync Reply2() returns (uint32_t result); +}; + +} // namespace _ipdltest +} // namespace mozilla diff --git a/ipc/ipdl/test/gtest/TestAsyncReturns.cpp b/ipc/ipdl/test/gtest/TestAsyncReturns.cpp new file mode 100644 index 0000000000..960a2954db --- /dev/null +++ b/ipc/ipdl/test/gtest/TestAsyncReturns.cpp @@ -0,0 +1,77 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* + * These tests ensure that async function return values work as expected. + */ + +#include "gtest/gtest.h" + +#include "mozilla/_ipdltest/IPDLUnitTest.h" +#include "mozilla/_ipdltest/PTestAsyncReturnsChild.h" +#include "mozilla/_ipdltest/PTestAsyncReturnsParent.h" + +using namespace mozilla::ipc; + +namespace mozilla::_ipdltest { + +static uint32_t sMagic1 = 0x105b59fb; +static uint32_t sMagic2 = 0x09b6f5e3; + +class TestAsyncReturnsChild : public PTestAsyncReturnsChild { + NS_INLINE_DECL_THREADSAFE_REFCOUNTING(TestAsyncReturnsChild, override) + private: + IPCResult RecvPing(PingResolver&& resolve) final override { + SendPong( + [resolve](const std::tuple<uint32_t, uint32_t>& aParam) { + EXPECT_EQ(std::get<0>(aParam), sMagic1); + EXPECT_EQ(std::get<1>(aParam), sMagic2); + resolve(true); + }, + [](ResponseRejectReason&& aReason) { FAIL() << "sending Pong"; }); + return IPC_OK(); + } + + IPCResult RecvNoReturn(NoReturnResolver&& resolve) final override { + // Not calling `resolve` intentionally + return IPC_OK(); + } + + ~TestAsyncReturnsChild() = default; +}; + +class TestAsyncReturnsParent : public PTestAsyncReturnsParent { + NS_INLINE_DECL_THREADSAFE_REFCOUNTING(TestAsyncReturnsParent, override) + private: + IPCResult RecvPong(PongResolver&& resolve) final override { + resolve(std::tuple<const uint32_t&, const uint32_t&>(sMagic1, sMagic2)); + return IPC_OK(); + } + + ~TestAsyncReturnsParent() = default; +}; + +IPDL_TEST(TestAsyncReturns, NoReturn) { + mActor->SendNoReturn( + [](bool unused) { FAIL() << "resolve handler should not be called"; }, + [=](ResponseRejectReason&& aReason) { + if (aReason != ResponseRejectReason::ResolverDestroyed) { + FAIL() << "reject with wrong reason"; + } + mActor->Close(); + }); +} + +IPDL_TEST(TestAsyncReturns, PingPong) { + mActor->SendPing( + [=](bool one) { + EXPECT_TRUE(one); + mActor->Close(); + }, + [](ResponseRejectReason&& aReason) { FAIL() << "sending Ping"; }); +} + +} // namespace mozilla::_ipdltest diff --git a/ipc/ipdl/test/gtest/TestCancel.cpp b/ipc/ipdl/test/gtest/TestCancel.cpp new file mode 100644 index 0000000000..79f31751dd --- /dev/null +++ b/ipc/ipdl/test/gtest/TestCancel.cpp @@ -0,0 +1,126 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* + * Test that IPC channel transaction cancellation (which applies to nested sync + * messages) works as expected. + */ + +#include "gtest/gtest.h" + +#include "mozilla/_ipdltest/IPDLUnitTest.h" +#include "mozilla/_ipdltest/PTestCancelChild.h" +#include "mozilla/_ipdltest/PTestCancelParent.h" + +using namespace mozilla::ipc; + +namespace mozilla::_ipdltest { + +class TestCancelParent : public PTestCancelParent { + NS_INLINE_DECL_THREADSAFE_REFCOUNTING(TestCancelParent, override) + private: + IPCResult RecvCallNestedCancel() final override { + EXPECT_FALSE(SendNestedCancel()) << "SendNestedCancel should fail"; + EXPECT_EQ(GetIPCChannel()->LastSendError(), + SyncSendError::CancelledAfterSend) + << "SendNestedCancel should be cancelled"; + + return IPC_OK(); + } + + IPCResult RecvNestedCancelParent() final override { + GetIPCChannel()->CancelCurrentTransaction(); + return IPC_OK(); + } + + IPCResult RecvCheckParent(uint32_t* reply) final override { + *reply = 42; + return IPC_OK(); + } + + ~TestCancelParent() = default; +}; + +class TestCancelChild : public PTestCancelChild { + NS_INLINE_DECL_THREADSAFE_REFCOUNTING(TestCancelChild, override) + private: + IPCResult RecvImmediateCancel() final override { + GetIPCChannel()->CancelCurrentTransaction(); + + uint32_t value = 0; + EXPECT_FALSE(SendCheckParent(&value)) << "channel should be closing"; + + return IPC_OK(); + } + + IPCResult RecvStartNestedCancel() final override { + EXPECT_FALSE(SendCallNestedCancel()); + + Close(); + return IPC_OK(); + } + + IPCResult RecvNestedCancel() final override { + GetIPCChannel()->CancelCurrentTransaction(); + + uint32_t value = 0; + EXPECT_TRUE(SendCheckParent(&value)) << "channel should be closing"; + + return IPC_OK(); + } + + IPCResult RecvStartNestedCancelParent() final override { + EXPECT_FALSE(SendNestedCancelParent()) + << "SendNestedCancelParent should fail"; + EXPECT_EQ(GetIPCChannel()->LastSendError(), + SyncSendError::CancelledAfterSend) + << "SendNestedCancelParent should be cancelled"; + + uint32_t value = 0; + EXPECT_FALSE(SendCheckParent(&value)); + + return IPC_OK(); + } + + IPCResult RecvCheckChild(uint32_t* reply) final override { + *reply = 42; + return IPC_OK(); + } + + ~TestCancelChild() = default; +}; + +// Nested sync messages can only be received on the main thread, so threaded +// tests can't be run (the child actor won't be on the main thread). + +IPDL_TEST_ON(CROSSPROCESS, TestCancel, ImmediateCancel) { + EXPECT_FALSE(mActor->SendImmediateCancel()) << "should immediately cancel"; + EXPECT_EQ(mActor->GetIPCChannel()->LastSendError(), + SyncSendError::CancelledAfterSend); + + uint32_t value = 0; + EXPECT_TRUE(mActor->SendCheckChild(&value)); + EXPECT_EQ(value, (uint32_t)42); + + mActor->Close(); +} + +IPDL_TEST_ON(CROSSPROCESS, TestCancel, NestedCancel) { + EXPECT_TRUE(mActor->SendStartNestedCancel()); +} + +IPDL_TEST_ON(CROSSPROCESS, TestCancel, NestedCancelParent) { + EXPECT_FALSE(mActor->SendStartNestedCancelParent()) + << "StartNestedCancelParent should be cancelled"; + + uint32_t value = 0; + EXPECT_TRUE(mActor->SendCheckChild(&value)); + EXPECT_EQ(value, (uint32_t)42); + + mActor->Close(); +} + +} // namespace mozilla::_ipdltest diff --git a/ipc/ipdl/test/gtest/TestDataStructures.cpp b/ipc/ipdl/test/gtest/TestDataStructures.cpp new file mode 100644 index 0000000000..b7f6a7ae95 --- /dev/null +++ b/ipc/ipdl/test/gtest/TestDataStructures.cpp @@ -0,0 +1,864 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* + * Test many combinations of data structures (both in argument and return + * position) to ensure they are transmitted correctly. + */ + +#include "gtest/gtest.h" + +#include "mozilla/_ipdltest/IPDLUnitTest.h" +#include "mozilla/_ipdltest/PTestDataStructuresChild.h" +#include "mozilla/_ipdltest/PTestDataStructuresParent.h" +#include "mozilla/_ipdltest/PTestDataStructuresSubChild.h" +#include "mozilla/_ipdltest/PTestDataStructuresSubParent.h" + +#include "mozilla/Unused.h" + +using namespace mozilla::ipc; + +using RegionArray = nsTArray<nsIntRegion>; + +namespace mozilla::_ipdltest { + +static const uint32_t nactors = 10; + +class TestDataStructuresSubParent : public PTestDataStructuresSubParent { + NS_INLINE_DECL_REFCOUNTING(TestDataStructuresSubParent, override) + + public: + explicit TestDataStructuresSubParent(uint32_t i) : mI(i) {} + uint32_t mI; + + private: + ~TestDataStructuresSubParent() = default; +}; + +class TestDataStructuresSubChild : public PTestDataStructuresSubChild { + NS_INLINE_DECL_REFCOUNTING(TestDataStructuresSubChild, override) + + public: + explicit TestDataStructuresSubChild(uint32_t i) : mI(i) {} + uint32_t mI; + + private: + ~TestDataStructuresSubChild() = default; +}; + +inline static TestDataStructuresSubParent& Cast( + PTestDataStructuresSubParent* a) { + return *static_cast<TestDataStructuresSubParent*>(a); +} + +class TestDataStructuresParent : public PTestDataStructuresParent { + NS_INLINE_DECL_REFCOUNTING(TestDataStructuresParent, override) + + public: + nsTArray<NotNull< + SideVariant<PTestDataStructuresSubParent*, PTestDataStructuresSubChild*>>> + kids; + + private: + IPCResult RecvTestArrayOfInt(nsTArray<int>&& ia, + nsTArray<int>* oa) final override { + EXPECT_EQ(5u, ia.Length()); + for (int i = 0; i < 5; ++i) EXPECT_EQ(i, ia[i]); + + *oa = std::move(ia); + + return IPC_OK(); + } + + IPCResult RecvTestArrayOfActor( + nsTArray<NotNull<PTestDataStructuresSubParent*>>&& i1, + nsTArray<NotNull<PTestDataStructuresSubParent*>>* o1) final override { + EXPECT_EQ(nactors, i1.Length()); + for (uint32_t i = 0; i < i1.Length(); ++i) EXPECT_EQ(i, Cast(i1[i]).mI); + *o1 = std::move(i1); + return IPC_OK(); + } + + IPCResult RecvTestUnion(const IntDouble& i1, const IntDouble& i2, + IntDouble* o1, IntDouble* o2) final override { + EXPECT_EQ(42, i1.get_int()); + EXPECT_EQ(4.0, i2.get_double()); + + *o1 = i1; + *o2 = i2; + + return IPC_OK(); + } + + IPCResult RecvTestArrayOfUnion(nsTArray<IntDouble>&& i1, + nsTArray<IntDouble>* o1) final override { + EXPECT_EQ(4u, i1.Length()); + EXPECT_EQ(1, i1[0].get_int()); + EXPECT_EQ(2.0, i1[1].get_double()); + EXPECT_EQ(3, i1[2].get_int()); + EXPECT_EQ(4.0, i1[3].get_double()); + + *o1 = std::move(i1); + + return IPC_OK(); + } + + IPCResult RecvTestUnionWithArray(const IntDoubleArrays& i1, + const IntDoubleArrays& i2, + const IntDoubleArrays& i3, + IntDoubleArrays* o1, IntDoubleArrays* o2, + IntDoubleArrays* o3) final override { + EXPECT_EQ(42, i1.get_int()); + + const nsTArray<int>& i2a = i2.get_ArrayOfint(); + EXPECT_EQ(3u, i2a.Length()); + EXPECT_EQ(1, i2a[0]); + EXPECT_EQ(2, i2a[1]); + EXPECT_EQ(3, i2a[2]); + + const nsTArray<double>& i3a = i3.get_ArrayOfdouble(); + EXPECT_EQ(3u, i3a.Length()); + EXPECT_EQ(1.0, i3a[0]); + EXPECT_EQ(2.0, i3a[1]); + EXPECT_EQ(3.0, i3a[2]); + + *o1 = i1; + *o2 = i2a; + *o3 = i3a; + + return IPC_OK(); + } + + IPCResult RecvTestArrayOfUnionWithArray( + nsTArray<IntDoubleArrays>&& i1, + nsTArray<IntDoubleArrays>* o1) final override { + EXPECT_EQ(3u, i1.Length()); + + IntDoubleArrays id1(i1[0]); + EXPECT_EQ(42, id1.get_int()); + + nsTArray<int> i2a = i1[1].get_ArrayOfint().Clone(); + EXPECT_EQ(3u, i2a.Length()); + EXPECT_EQ(1, i2a[0]); + EXPECT_EQ(2, i2a[1]); + EXPECT_EQ(3, i2a[2]); + + nsTArray<double> i3a = i1[2].get_ArrayOfdouble().Clone(); + EXPECT_EQ(3u, i3a.Length()); + EXPECT_EQ(1.0, i3a[0]); + EXPECT_EQ(2.0, i3a[1]); + EXPECT_EQ(3.0, i3a[2]); + + o1->AppendElement(id1); + o1->AppendElement(IntDoubleArrays(i2a)); + o1->AppendElement(IntDoubleArrays(i3a)); + + return IPC_OK(); + } + + IPCResult RecvTestStructWithActor(const ActorWrapper& i1, + ActorWrapper* o1) final override { + EXPECT_FALSE(i1.actor().IsChild()) << "child side should be empty"; + + EXPECT_EQ(i1.actor(), kids[0]) + << "should have got back same actor on parent side"; + + o1->actor() = kids[0]; + return IPC_OK(); + } + + IPCResult RecvTestUnionWithActors(const Actors& i1, const Actors& i2, + const Actors& i3, Actors* o1, Actors* o2, + Actors* o3) final override { + EXPECT_EQ(42, i1.get_int()); + + nsTArray<int> i2a = i2.get_ArrayOfint().Clone(); + EXPECT_EQ(3u, i2a.Length()); + EXPECT_EQ(1, i2a[0]); + EXPECT_EQ(2, i2a[1]); + EXPECT_EQ(3, i2a[2]); + + const auto& a = i3.get_ArrayOfPTestDataStructuresSub(); + EXPECT_EQ(a.Length(), kids.Length()); + for (size_t i = 0; i < a.Length(); ++i) { + EXPECT_EQ(a[i], kids[i]); + } + + *o1 = 42; + *o2 = i2a; + *o3 = kids.Clone(); + + return IPC_OK(); + } + + IPCResult RecvTestArrayOfUnionWithActors( + nsTArray<Actors>&& i1, nsTArray<Actors>* o1) final override { + EXPECT_EQ(3u, i1.Length()); + EXPECT_EQ(42, i1[0].get_int()); + + const nsTArray<int>& i2a = i1[1].get_ArrayOfint(); + EXPECT_EQ(3u, i2a.Length()); + EXPECT_EQ(1, i2a[0]); + EXPECT_EQ(2, i2a[1]); + EXPECT_EQ(3, i2a[2]); + + EXPECT_EQ(kids, i1[2].get_ArrayOfPTestDataStructuresSub()); + + *o1 = std::move(i1); + + return IPC_OK(); + } + + IPCResult RecvTestUnions(const Unions& i1, const Unions& i2, const Unions& i3, + const Unions& i4, Unions* o1, Unions* o2, Unions* o3, + Unions* o4) final override { + EXPECT_EQ(42, i1.get_int()); + + const nsTArray<int>& i2a = i2.get_ArrayOfint(); + EXPECT_EQ(3u, i2a.Length()); + EXPECT_EQ(1, i2a[0]); + EXPECT_EQ(2, i2a[1]); + EXPECT_EQ(3, i2a[2]); + + EXPECT_EQ(kids, i3.get_ArrayOfPTestDataStructuresSub()); + + const auto& i4a = + i4.get_ArrayOfActors()[0].get_ArrayOfPTestDataStructuresSub(); + EXPECT_EQ(kids, i4a); + + *o1 = i1; + *o2 = i2; + *o3 = i3; + *o4 = i4; + + return IPC_OK(); + } + + IPCResult RecvTestArrayOfUnions(nsTArray<Unions>&& i1, + nsTArray<Unions>* o1) final override { + EXPECT_EQ(42, i1[0].get_int()); + + const nsTArray<int>& i2a = i1[1].get_ArrayOfint(); + EXPECT_EQ(3u, i2a.Length()); + EXPECT_EQ(1, i2a[0]); + EXPECT_EQ(2, i2a[1]); + EXPECT_EQ(3, i2a[2]); + + EXPECT_EQ(kids, i1[2].get_ArrayOfPTestDataStructuresSub()); + + const auto& i4a = + i1[3].get_ArrayOfActors()[0].get_ArrayOfPTestDataStructuresSub(); + EXPECT_EQ(kids, i4a); + + *o1 = std::move(i1); + + return IPC_OK(); + } + + IPCResult RecvTestStruct(const SIntDouble& i, SIntDouble* o) final override { + EXPECT_EQ(1, i.i()); + EXPECT_EQ(2.0, i.d()); + *o = i; + return IPC_OK(); + } + + IPCResult RecvTestStructWithArrays(const SIntDoubleArrays& i, + SIntDoubleArrays* o) final override { + nsTArray<int> ai; + ai.AppendElement(1); + ai.AppendElement(2); + ai.AppendElement(3); + + nsTArray<double> ad; + ad.AppendElement(.5); + ad.AppendElement(1.0); + ad.AppendElement(2.0); + + EXPECT_EQ(42, i.i()); + EXPECT_EQ(ai, i.ai()); + EXPECT_EQ(ad, i.ad()); + + *o = i; + + return IPC_OK(); + } + + IPCResult RecvTestStructWithActors(const SActors& i, + SActors* o) final override { + nsTArray<int> ai; + ai.AppendElement(1); + ai.AppendElement(2); + ai.AppendElement(3); + + EXPECT_EQ(42, i.i()); + EXPECT_EQ(ai, i.ai()); + EXPECT_EQ(kids, i.ap()); + + *o = i; + + return IPC_OK(); + } + + IPCResult RecvTestStructs(const Structs& i, Structs* o) final override { + nsTArray<int> ai; + ai.AppendElement(1); + ai.AppendElement(2); + ai.AppendElement(3); + + EXPECT_EQ(42, i.i()); + EXPECT_EQ(ai, i.ai()); + EXPECT_EQ(kids, i.ap()); + + const SActors& ia = i.aa()[0]; + EXPECT_EQ(42, ia.i()); + EXPECT_EQ(ai, ia.ai()); + EXPECT_EQ(kids, ia.ap()); + + *o = i; + + return IPC_OK(); + } + + IPCResult RecvTestUnionWithStructs( + const WithStructs& i1, const WithStructs& i2, const WithStructs& i3, + const WithStructs& i4, const WithStructs& i5, WithStructs* o1, + WithStructs* o2, WithStructs* o3, WithStructs* o4, + WithStructs* o5) final override { + nsTArray<int> ai; + ai.AppendElement(1); + ai.AppendElement(2); + ai.AppendElement(3); + + EXPECT_EQ(i1, int(42)); + EXPECT_EQ(i2.get_ArrayOfint(), ai); + EXPECT_EQ(i3.get_ArrayOfPTestDataStructuresSub(), kids); + + const SActors& ia = i4.get_ArrayOfSActors()[0]; + EXPECT_EQ(42, ia.i()); + EXPECT_EQ(ai, ia.ai()); + EXPECT_EQ(kids, ia.ap()); + + const Structs& is = i5.get_ArrayOfStructs()[0]; + EXPECT_EQ(42, is.i()); + EXPECT_EQ(ai, is.ai()); + EXPECT_EQ(kids, is.ap()); + + const SActors& isa = is.aa()[0]; + EXPECT_EQ(42, isa.i()); + EXPECT_EQ(ai, isa.ai()); + EXPECT_EQ(kids, isa.ap()); + + *o1 = i1; + *o2 = i2; + *o3 = i3; + *o4 = i4; + *o5 = i5; + + return IPC_OK(); + } + + IPCResult RecvTestStructWithUnions(const WithUnions& i, + WithUnions* o) final override { + EXPECT_EQ(i.i(), 42); + + nsTArray<int> ai; + ai.AppendElement(1); + ai.AppendElement(2); + ai.AppendElement(3); + EXPECT_EQ(ai, i.ai()); + + EXPECT_EQ(i.ap(), kids); + + EXPECT_EQ(kids, i.aa()[0].get_ArrayOfPTestDataStructuresSub()); + + const nsTArray<Unions>& iau = i.au(); + EXPECT_EQ(iau[0], 42); + EXPECT_EQ(ai, iau[1].get_ArrayOfint()); + EXPECT_EQ(kids, iau[2].get_ArrayOfPTestDataStructuresSub()); + EXPECT_EQ( + kids, + iau[3].get_ArrayOfActors()[0].get_ArrayOfPTestDataStructuresSub()); + + *o = i; + + return IPC_OK(); + } + + IPCResult RecvTestUnionWithCxx(nsTArray<Op>&& sa) final override { + EXPECT_EQ(sa.Length(), (size_t)1); + EXPECT_EQ(Op::TSetAttrs, sa[0].type()); + return IPC_OK(); + } + + IPCResult RecvTestNsIntRegion(RegionArray&& ra) final override { + for (RegionArray::index_type i = 0; i < ra.Length(); ++i) { + // if |ra| has been realloc()d and given a different allocator + // chunk, this loop will nondeterministically crash or iloop. + for (auto iter = ra[i].RectIter(); !iter.Done(); iter.Next()) { + Unused << iter.Get(); + } + } + return IPC_OK(); + } + + ~TestDataStructuresParent() = default; +}; + +class TestDataStructuresChild : public PTestDataStructuresChild { + NS_INLINE_DECL_REFCOUNTING(TestDataStructuresChild, override) + + private: + nsTArray<NotNull< + SideVariant<PTestDataStructuresSubParent*, PTestDataStructuresSubChild*>>> + kids; + nsTArray<NotNull<PTestDataStructuresSubChild*>> kidsDirect; + + already_AddRefed<PTestDataStructuresSubChild> + AllocPTestDataStructuresSubChild(const int& i) final override { + auto child = MakeRefPtr<TestDataStructuresSubChild>(i); + kids.AppendElement(WrapNotNull(child)); + kidsDirect.AppendElement(WrapNotNull(child)); + return child.forget(); + } + + IPCResult RecvStart() final override { + TestArrayOfInt(); + TestArrayOfActor(); + TestUnion(); + TestArrayOfUnion(); + TestUnionWithArray(); + TestArrayOfUnionWithArray(); + TestStructWithActor(); + TestUnionWithActors(); + TestArrayOfUnionWithActors(); + TestUnions(); + TestArrayOfUnions(); + TestStruct(); + TestStructWithArrays(); + TestStructWithActors(); + TestStructs(); + TestUnionWithStructs(); + TestStructWithUnions(); + TestUnionWithCxx(); + TestNsIntRegion(); + + auto actors = kidsDirect.Clone(); + for (auto& actor : actors) { + EXPECT_TRUE(PTestDataStructuresSubChild::Send__delete__(actor)); + } + + Close(); + + return IPC_OK(); + } + + void TestArrayOfInt() { + nsTArray<int> ia; + + for (int i = 0; i < 5; ++i) ia.AppendElement(i); + + nsTArray<int> oa; + EXPECT_TRUE(SendTestArrayOfInt(ia, &oa)); + + EXPECT_EQ(ia, oa); + } + + void TestArrayOfActor() { + nsTArray<NotNull<PTestDataStructuresSubChild*>> oa; + EXPECT_TRUE(SendTestArrayOfActor(kidsDirect, &oa)); + EXPECT_EQ(kidsDirect, oa); + } + + void TestUnion() { + int i1i = 42; + double i2d = 4.0; + IntDouble i1(i1i); + IntDouble i2(i2d); + IntDouble o1, o2; + + SendTestUnion(i1, i2, &o1, &o2); + + EXPECT_EQ(i1i, o1.get_int()); + EXPECT_EQ(i2d, o2.get_double()); + } + + void TestArrayOfUnion() { + nsTArray<IntDouble> i1; + i1.AppendElement(IntDouble(int(1))); + i1.AppendElement(IntDouble(2.0)); + i1.AppendElement(IntDouble(int(3))); + i1.AppendElement(IntDouble(4.0)); + + nsTArray<IntDouble> o1; + EXPECT_TRUE(SendTestArrayOfUnion(i1, &o1)); + + // TODO Union::operator==() + EXPECT_EQ(i1.Length(), o1.Length()); + EXPECT_EQ(1, o1[0].get_int()); + EXPECT_EQ(2.0, o1[1].get_double()); + EXPECT_EQ(3, o1[2].get_int()); + EXPECT_EQ(4.0, o1[3].get_double()); + } + + void TestUnionWithArray() { + IntDoubleArrays i1(int(42)); + nsTArray<int> i2; + i2.AppendElement(1); + i2.AppendElement(2); + i2.AppendElement(3); + nsTArray<double> i3; + i3.AppendElement(1.0); + i3.AppendElement(2.0); + i3.AppendElement(3.0); + + IntDoubleArrays o1, o2, o3; + EXPECT_TRUE(SendTestUnionWithArray(i1, IntDoubleArrays(i2), + IntDoubleArrays(i3), &o1, &o2, &o3)); + + EXPECT_EQ(42, o1.get_int()); + EXPECT_EQ(i2, o2.get_ArrayOfint()); + EXPECT_EQ(i3, o3.get_ArrayOfdouble()); + } + + void TestArrayOfUnionWithArray() { + IntDoubleArrays id1(int(42)); + nsTArray<int> id2; + id2.AppendElement(1); + id2.AppendElement(2); + id2.AppendElement(3); + nsTArray<double> id3; + id3.AppendElement(1.0); + id3.AppendElement(2.0); + id3.AppendElement(3.0); + + nsTArray<IntDoubleArrays> i1; + i1.AppendElement(id1); + i1.AppendElement(IntDoubleArrays(id2)); + i1.AppendElement(IntDoubleArrays(id3)); + + nsTArray<IntDoubleArrays> o1; + EXPECT_TRUE(SendTestArrayOfUnionWithArray(i1, &o1)); + + EXPECT_EQ(3u, o1.Length()); + IntDoubleArrays od1(o1[0]); + nsTArray<int> od2 = o1[1].get_ArrayOfint().Clone(); + nsTArray<double> od3 = o1[2].get_ArrayOfdouble().Clone(); + + EXPECT_EQ(42, od1.get_int()); + EXPECT_EQ(id2, od2); + EXPECT_EQ(id3, od3); + } + + void TestStructWithActor() { + ActorWrapper iaw(kidsDirect[0]); + + ActorWrapper oaw; + EXPECT_TRUE(SendTestStructWithActor(iaw, &oaw)); + + EXPECT_TRUE(oaw.actor().IsChild()); + EXPECT_EQ(oaw.actor().AsChild(), kidsDirect[0]); + } + + void TestUnionWithActors() { + Actors i1(42); + nsTArray<int> i2a; + i2a.AppendElement(1); + i2a.AppendElement(2); + i2a.AppendElement(3); + + Actors o1, o2, o3; + EXPECT_TRUE( + SendTestUnionWithActors(i1, Actors(i2a), Actors(kids), &o1, &o2, &o3)); + + EXPECT_EQ(42, o1.get_int()); + EXPECT_EQ(i2a, o2.get_ArrayOfint()); + EXPECT_EQ(kids, o3.get_ArrayOfPTestDataStructuresSub()); + } + + void TestArrayOfUnionWithActors() { + Actors i1e(42); + nsTArray<int> i2a; + i2a.AppendElement(1); + i2a.AppendElement(2); + i2a.AppendElement(3); + + nsTArray<Actors> i1; + i1.AppendElement(i1e); + i1.AppendElement(i2a); + i1.AppendElement(kids); + + nsTArray<Actors> o1; + EXPECT_TRUE(SendTestArrayOfUnionWithActors(i1, &o1)); + + EXPECT_EQ(3u, o1.Length()); + EXPECT_EQ(42, o1[0].get_int()); + EXPECT_EQ(i2a, o1[1].get_ArrayOfint()); + EXPECT_EQ(kids, o1[2].get_ArrayOfPTestDataStructuresSub()); + } + + void TestUnions() { + Unions i1(int(42)); + + nsTArray<int> i2a; + i2a.AppendElement(1); + i2a.AppendElement(2); + i2a.AppendElement(3); + + nsTArray<Actors> i4a; + i4a.AppendElement(kids); + + Unions o1, o2, o3, o4; + EXPECT_TRUE(SendTestUnions(i1, Unions(i2a), Unions(kids), Unions(i4a), &o1, + &o2, &o3, &o4)); + + EXPECT_EQ(42, o1.get_int()); + EXPECT_EQ(i2a, o2.get_ArrayOfint()); + EXPECT_EQ(kids, o3.get_ArrayOfPTestDataStructuresSub()); + EXPECT_EQ(kids, + o4.get_ArrayOfActors()[0].get_ArrayOfPTestDataStructuresSub()); + } + + void TestArrayOfUnions() { + Unions i1a(int(42)); + + nsTArray<int> i2a; + i2a.AppendElement(1); + i2a.AppendElement(2); + i2a.AppendElement(3); + + nsTArray<Actors> i4a; + i4a.AppendElement(kids); + + nsTArray<Unions> i1; + i1.AppendElement(i1a); + i1.AppendElement(Unions(i2a)); + i1.AppendElement(Unions(kids)); + i1.AppendElement(Unions(i4a)); + + nsTArray<Unions> o1; + EXPECT_TRUE(SendTestArrayOfUnions(i1, &o1)); + + EXPECT_EQ(4u, o1.Length()); + EXPECT_EQ(42, o1[0].get_int()); + EXPECT_EQ(i2a, o1[1].get_ArrayOfint()); + EXPECT_EQ(kids, o1[2].get_ArrayOfPTestDataStructuresSub()); + EXPECT_EQ(kids, + o1[3].get_ArrayOfActors()[0].get_ArrayOfPTestDataStructuresSub()); + } + + void TestStruct() { + SIntDouble i(1, 2.0); + SIntDouble o; + + EXPECT_TRUE(SendTestStruct(i, &o)); + + EXPECT_EQ(o.i(), 1); + EXPECT_EQ(o.d(), 2.0); + } + + void TestStructWithArrays() { + nsTArray<int> ai; + ai.AppendElement(1); + ai.AppendElement(2); + ai.AppendElement(3); + + nsTArray<double> ad; + ad.AppendElement(.5); + ad.AppendElement(1.0); + ad.AppendElement(2.0); + + SIntDoubleArrays i(42, ai, ad); + SIntDoubleArrays o; + + EXPECT_TRUE(SendTestStructWithArrays(i, &o)); + + EXPECT_EQ(42, o.i()); + EXPECT_EQ(ai, o.ai()); + EXPECT_EQ(ad, o.ad()); + } + + void TestStructWithActors() { + nsTArray<int> ai; + ai.AppendElement(1); + ai.AppendElement(2); + ai.AppendElement(3); + + SActors i; + i.i() = 42; + i.ai() = ai.Clone(); + i.ap() = kids.Clone(); + + SActors o; + EXPECT_TRUE(SendTestStructWithActors(i, &o)); + + EXPECT_EQ(42, o.i()); + EXPECT_EQ(ai, o.ai()); + EXPECT_EQ(kids, o.ap()); + } + + void TestStructs() { + nsTArray<int> ai; + ai.AppendElement(1); + ai.AppendElement(2); + ai.AppendElement(3); + + SActors ia; + ia.i() = 42; + ia.ai() = ai.Clone(); + ia.ap() = kids.Clone(); + nsTArray<SActors> aa; + aa.AppendElement(ia); + + Structs i; + i.i() = 42; + i.ai() = ai.Clone(); + i.ap() = kids.Clone(); + i.aa() = aa.Clone(); + + Structs o; + EXPECT_TRUE(SendTestStructs(i, &o)); + + EXPECT_EQ(42, o.i()); + EXPECT_EQ(ai, o.ai()); + EXPECT_EQ(kids, o.ap()); + + const SActors& os = o.aa()[0]; + EXPECT_EQ(42, os.i()); + EXPECT_EQ(ai, os.ai()); + EXPECT_EQ(kids, os.ap()); + } + + void TestUnionWithStructs() { + nsTArray<int> ai; + ai.AppendElement(1); + ai.AppendElement(2); + ai.AppendElement(3); + + SActors ia; + ia.i() = 42; + ia.ai() = ai.Clone(); + ia.ap() = kids.Clone(); + nsTArray<SActors> iaa; + iaa.AppendElement(ia); + + Structs is; + is.i() = 42; + is.ai() = ai.Clone(); + is.ap() = kids.Clone(); + is.aa() = iaa.Clone(); + nsTArray<Structs> isa; + isa.AppendElement(is); + + WithStructs o1, o2, o3, o4, o5; + EXPECT_TRUE(SendTestUnionWithStructs( + WithStructs(42), WithStructs(ai), WithStructs(kids), WithStructs(iaa), + WithStructs(isa), &o1, &o2, &o3, &o4, &o5)); + + EXPECT_EQ(o1, int(42)); + EXPECT_EQ(o2.get_ArrayOfint(), ai); + EXPECT_EQ(o3.get_ArrayOfPTestDataStructuresSub(), kids); + + const SActors& oa = o4.get_ArrayOfSActors()[0]; + EXPECT_EQ(42, oa.i()); + EXPECT_EQ(ai, oa.ai()); + EXPECT_EQ(kids, oa.ap()); + + const Structs& os = o5.get_ArrayOfStructs()[0]; + EXPECT_EQ(42, os.i()); + EXPECT_EQ(ai, os.ai()); + EXPECT_EQ(kids, os.ap()); + + const SActors& osa = os.aa()[0]; + EXPECT_EQ(42, osa.i()); + EXPECT_EQ(ai, osa.ai()); + EXPECT_EQ(kids, osa.ap()); + } + + void TestStructWithUnions() { + WithUnions i; + + i.i() = 42; + + nsTArray<int> ai; + ai.AppendElement(1); + ai.AppendElement(2); + ai.AppendElement(3); + i.ai() = ai.Clone(); + + i.ap() = kids.Clone(); + + nsTArray<Actors> iaa; + iaa.AppendElement(kids); + i.aa() = iaa.Clone(); + + nsTArray<Unions> iau; + iau.AppendElement(int(42)); + iau.AppendElement(ai); + iau.AppendElement(kids); + iau.AppendElement(iaa); + i.au() = iau.Clone(); + + WithUnions o; + EXPECT_TRUE(SendTestStructWithUnions(i, &o)); + + EXPECT_EQ(42, o.i()); + EXPECT_EQ(o.ai(), ai); + EXPECT_EQ(o.ap(), kids); + + const Actors& oaa = o.aa()[0]; + EXPECT_EQ(oaa.get_ArrayOfPTestDataStructuresSub(), kids); + + const nsTArray<Unions>& oau = o.au(); + EXPECT_EQ(oau[0], 42); + EXPECT_EQ(oau[1].get_ArrayOfint(), ai); + EXPECT_EQ(oau[2].get_ArrayOfPTestDataStructuresSub(), kids); + EXPECT_EQ(oau[3].get_ArrayOfActors()[0].get_ArrayOfPTestDataStructuresSub(), + kids); + } + + void TestUnionWithCxx() { + Attrs attrs; + attrs.common() = CommonAttrs(true); + attrs.specific() = BarAttrs(1.0f); + + nsTArray<Op> ops; + ops.AppendElement(SetAttrs(kids[0], attrs)); + + EXPECT_TRUE(SendTestUnionWithCxx(ops)); + } + + void TestNsIntRegion() { + const int nelements = 1000; + RegionArray ra; + // big enough to hopefully force a realloc to a different chunk of + // memory on the receiving side, if the workaround isn't working + // correctly. But SetCapacity() here because we don't want to + // crash on the sending side. + ra.SetCapacity(nelements); + for (int i = 0; i < nelements; ++i) { + nsIntRegion r; + r.Or(nsIntRect(0, 0, 10, 10), nsIntRect(10, 10, 10, 10)); + ra.AppendElement(r); + } + + EXPECT_TRUE(SendTestNsIntRegion(ra)); + } + + ~TestDataStructuresChild() = default; +}; + +IPDL_TEST(TestDataStructures) { + for (uint32_t i = 0; i < nactors; ++i) { + auto sub = MakeRefPtr<TestDataStructuresSubParent>(i); + EXPECT_TRUE(mActor->SendPTestDataStructuresSubConstructor(sub, i)) + << "can't alloc actor"; + mActor->kids.AppendElement(WrapNotNull(sub)); + } + + EXPECT_TRUE(mActor->SendStart()) << "can't send Start()"; +} + +} // namespace mozilla::_ipdltest diff --git a/ipc/ipdl/test/gtest/TestDescendant.cpp b/ipc/ipdl/test/gtest/TestDescendant.cpp new file mode 100644 index 0000000000..47f619d32a --- /dev/null +++ b/ipc/ipdl/test/gtest/TestDescendant.cpp @@ -0,0 +1,98 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* + * Test multiple levels of descendant managed protocols. + */ + +#include "gtest/gtest.h" + +#include "mozilla/_ipdltest/IPDLUnitTest.h" +#include "mozilla/_ipdltest/PTestDescendantChild.h" +#include "mozilla/_ipdltest/PTestDescendantParent.h" +#include "mozilla/_ipdltest/PTestDescendantSubChild.h" +#include "mozilla/_ipdltest/PTestDescendantSubParent.h" +#include "mozilla/_ipdltest/PTestDescendantSubsubChild.h" +#include "mozilla/_ipdltest/PTestDescendantSubsubParent.h" + +using namespace mozilla::ipc; + +namespace mozilla::_ipdltest { + +class TestDescendantSubsubParent : public PTestDescendantSubsubParent { + NS_INLINE_DECL_REFCOUNTING(TestDescendantSubsubParent, override) + private: + ~TestDescendantSubsubParent() = default; +}; + +class TestDescendantSubsubChild : public PTestDescendantSubsubChild { + NS_INLINE_DECL_REFCOUNTING(TestDescendantSubsubChild, override) + private: + ~TestDescendantSubsubChild() = default; +}; + +class TestDescendantSubParent : public PTestDescendantSubParent { + NS_INLINE_DECL_REFCOUNTING(TestDescendantSubParent, override) + private: + ~TestDescendantSubParent() = default; +}; + +class TestDescendantSubChild : public PTestDescendantSubChild { + NS_INLINE_DECL_REFCOUNTING(TestDescendantSubChild, override) + private: + already_AddRefed<PTestDescendantSubsubChild> AllocPTestDescendantSubsubChild() + final override { + return MakeAndAddRef<TestDescendantSubsubChild>(); + } + + ~TestDescendantSubChild() = default; +}; + +class TestDescendantParent : public PTestDescendantParent { + NS_INLINE_DECL_REFCOUNTING(TestDescendantParent, override) + private: + IPCResult RecvOk(NotNull<PTestDescendantSubsubParent*> a) final override { + EXPECT_TRUE(PTestDescendantSubsubParent::Send__delete__(a)) + << "deleting Subsub"; + + Close(); + + return IPC_OK(); + } + + ~TestDescendantParent() = default; +}; + +class TestDescendantChild : public PTestDescendantChild { + NS_INLINE_DECL_REFCOUNTING(TestDescendantChild, override) + private: + already_AddRefed<PTestDescendantSubChild> AllocPTestDescendantSubChild( + PTestDescendantSubsubChild* dummy) final override { + EXPECT_FALSE(dummy) << "actor supposed to be null"; + return MakeAndAddRef<TestDescendantSubChild>(); + } + + IPCResult RecvTest(NotNull<PTestDescendantSubsubChild*> a) final override { + EXPECT_TRUE(SendOk(a)) << "couldn't send Ok()"; + return IPC_OK(); + } + + ~TestDescendantChild() = default; +}; + +IPDL_TEST(TestDescendant) { + auto p = MakeRefPtr<TestDescendantSubParent>(); + auto* rv1 = mActor->SendPTestDescendantSubConstructor(p, nullptr); + EXPECT_EQ(p, rv1) << "can't allocate Sub"; + + auto pp = MakeRefPtr<TestDescendantSubsubParent>(); + auto* rv2 = p->SendPTestDescendantSubsubConstructor(pp); + EXPECT_EQ(pp, rv2) << "can't allocate Subsub"; + + EXPECT_TRUE(mActor->SendTest(WrapNotNull(pp))) << "can't send Subsub"; +} + +} // namespace mozilla::_ipdltest diff --git a/ipc/ipdl/test/gtest/TestEndpointOpens.cpp b/ipc/ipdl/test/gtest/TestEndpointOpens.cpp new file mode 100644 index 0000000000..50dab06058 --- /dev/null +++ b/ipc/ipdl/test/gtest/TestEndpointOpens.cpp @@ -0,0 +1,159 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* + * Test Endpoint usage. + */ + +#include "gtest/gtest.h" + +#include "mozilla/_ipdltest/IPDLUnitTest.h" +#include "mozilla/_ipdltest/PTestEndpointOpensChild.h" +#include "mozilla/_ipdltest/PTestEndpointOpensParent.h" +#include "mozilla/_ipdltest/PTestEndpointOpensOpenedChild.h" +#include "mozilla/_ipdltest/PTestEndpointOpensOpenedParent.h" + +#include <memory> + +using namespace mozilla::ipc; + +namespace mozilla::_ipdltest { + +class TestEndpointOpensOpenedParent : public PTestEndpointOpensOpenedParent { + NS_INLINE_DECL_THREADSAFE_REFCOUNTING(TestEndpointOpensOpenedParent, override) + private: + IPCResult RecvHello() final override { + EXPECT_FALSE(NS_IsMainThread()); + if (!SendHi()) { + return IPC_TEST_FAIL(this); + } + return IPC_OK(); + } + + IPCResult RecvHelloSync() final override { + EXPECT_FALSE(NS_IsMainThread()); + return IPC_OK(); + } + + void ActorDestroy(ActorDestroyReason why) final override { + EXPECT_FALSE(NS_IsMainThread()); + } + + ~TestEndpointOpensOpenedParent() = default; +}; + +class TestEndpointOpensChild : public PTestEndpointOpensChild { + NS_INLINE_DECL_THREADSAFE_REFCOUNTING(TestEndpointOpensChild, override) + private: + IPCResult RecvStart() final override; + + ~TestEndpointOpensChild() = default; +}; + +class TestEndpointOpensOpenedChild : public PTestEndpointOpensOpenedChild { + NS_INLINE_DECL_THREADSAFE_REFCOUNTING(TestEndpointOpensOpenedChild, override) + + explicit TestEndpointOpensOpenedChild(TestEndpointOpensChild* opensChild) + : mOpensChild(opensChild) {} + + private: + IPCResult RecvHi() final override { + EXPECT_FALSE(NS_IsMainThread()); + + EXPECT_TRUE(SendHelloSync()); + + Close(); + return IPC_OK(); + } + + void ActorDestroy(ActorDestroyReason why) final override { + EXPECT_FALSE(NS_IsMainThread()); + + // Kick off main-thread shutdown. + NS_DispatchToMainThread(NewRunnableMethod("ipc::IToplevelProtocol::Close", + mOpensChild, + &TestEndpointOpensChild::Close)); + } + + ~TestEndpointOpensOpenedChild() = default; + + TestEndpointOpensChild* mOpensChild; +}; + +class TestEndpointOpensParent : public PTestEndpointOpensParent { + NS_INLINE_DECL_THREADSAFE_REFCOUNTING(TestEndpointOpensParent, override) + private: + IPCResult RecvStartSubprotocol( + Endpoint<PTestEndpointOpensOpenedParent>&& endpoint) final override { + nsCOMPtr<nsISerialEventTarget> eventTarget; + auto rv = NS_CreateBackgroundTaskQueue("ParentThread", + getter_AddRefs(eventTarget)); + if (NS_FAILED(rv)) { + ADD_FAILURE() << "creating background task queue for child"; + return IPC_TEST_FAIL(this); + } + + eventTarget->Dispatch(NS_NewRunnableFunction( + "OpenParent", [endpoint{std::move(endpoint)}]() mutable { + EXPECT_FALSE(NS_IsMainThread()); + + // 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. + auto actor = MakeRefPtr<TestEndpointOpensOpenedParent>(); + ASSERT_TRUE(endpoint.Bind(actor)); + })); + + return IPC_OK(); + } + + ~TestEndpointOpensParent() = default; +}; + +IPCResult TestEndpointOpensChild::RecvStart() { + Endpoint<PTestEndpointOpensOpenedParent> parent; + Endpoint<PTestEndpointOpensOpenedChild> child; + nsresult rv; + rv = PTestEndpointOpensOpened::CreateEndpoints( + OtherPidMaybeInvalid(), base::GetCurrentProcId(), &parent, &child); + if (NS_FAILED(rv)) { + ADD_FAILURE() << "opening PTestEndpointOpensOpened"; + return IPC_TEST_FAIL(this); + } + + nsCOMPtr<nsISerialEventTarget> childEventTarget; + rv = NS_CreateBackgroundTaskQueue("ChildThread", + getter_AddRefs(childEventTarget)); + if (NS_FAILED(rv)) { + ADD_FAILURE() << "creating background task queue for child"; + return IPC_TEST_FAIL(this); + } + + auto actor = MakeRefPtr<TestEndpointOpensOpenedChild>(this); + childEventTarget->Dispatch(NS_NewRunnableFunction( + "OpenChild", + [actor{std::move(actor)}, endpoint{std::move(child)}]() mutable { + EXPECT_FALSE(NS_IsMainThread()); + + // 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. + ASSERT_TRUE(endpoint.Bind(actor)); + + // Kick off the unit tests + ASSERT_TRUE(actor->SendHello()); + })); + + EXPECT_TRUE(SendStartSubprotocol(std::move(parent))); + + return IPC_OK(); +} + +IPDL_TEST_ON(CROSSPROCESS, TestEndpointOpens) { + EXPECT_TRUE(mActor->SendStart()); +} + +} // namespace mozilla::_ipdltest diff --git a/ipc/ipdl/test/gtest/TestHangs.cpp b/ipc/ipdl/test/gtest/TestHangs.cpp new file mode 100644 index 0000000000..ddc4a0c7d0 --- /dev/null +++ b/ipc/ipdl/test/gtest/TestHangs.cpp @@ -0,0 +1,133 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* + * Test various cases of behavior when a synchronous method call times out. + */ + +#include "gtest/gtest.h" + +#include "mozilla/_ipdltest/IPDLUnitTest.h" +#include "mozilla/_ipdltest/PTestHangsChild.h" +#include "mozilla/_ipdltest/PTestHangsParent.h" +#include "mozilla/ipc/CrossProcessSemaphore.h" + +using namespace mozilla::ipc; + +namespace mozilla::_ipdltest { + +enum class HangMode : uint32_t { + /// No hang should occur. + None, + /// The synchronous call should time out. + Hang, + /// The synchronous call should time out but the response should still be + /// received + /// (racing with the reply timeout logic). + HangButReceive, + /// The synchronous call should time out but the response should still be + /// received because the child indicates that processing should continue after + /// timeout. + HangPermitted +}; + +class TestHangsChild : public PTestHangsChild { + NS_INLINE_DECL_REFCOUNTING(TestHangsChild, override) + + TestHangsChild() : timeout(CrossProcessSemaphore::Create("timeout", 0)) {} + + private: + IPCResult RecvStart(const uint32_t& hangMode, + StartResolver&& resolve) final override { + // Minimum possible, 2 ms. We want to detect a hang to race with the reply + // coming in, as reliably as possible. After 1ms the wait for a response + // will be retried. + SetReplyTimeoutMs(2); + + this->hangMode = (HangMode)hangMode; + + auto result = SendHang(hangMode, timeout->CloneHandle()); + if (this->hangMode == HangMode::Hang) { + // Only the `Hang` mode should actually fail. + EXPECT_FALSE(result); + } else { + EXPECT_TRUE(result); + } + + resolve(detectedHang); + + return IPC_OK(); + } + + bool ShouldContinueFromReplyTimeout() final override { + timeout->Signal(); + detectedHang = true; + + if (hangMode == HangMode::HangButReceive) { + // Wait until the transaction is complete so that we can still receive the + // result after returning. + while (!GetIPCChannel()->TestOnlyIsTransactionComplete()) { + PR_Sleep(ticksPerSecond / 1000); + } + } + + // Return true if `HangPermitted` mode (allowing the receive loop to + // continue). + return hangMode == HangMode::HangPermitted; + } + + ~TestHangsChild() = default; + + HangMode hangMode = HangMode::None; + uint32_t ticksPerSecond = PR_TicksPerSecond(); + UniquePtr<CrossProcessSemaphore> timeout; + + public: + bool detectedHang = false; +}; + +class TestHangsParent : public PTestHangsParent { + NS_INLINE_DECL_REFCOUNTING(TestHangsParent, override) + + private: + IPCResult RecvHang( + const uint32_t& hangMode, + CrossProcessSemaphoreHandle&& timeout_handle) final override { + UniquePtr<CrossProcessSemaphore> timeout( + CrossProcessSemaphore::Create(std::move(timeout_handle))); + if (hangMode != (uint32_t)HangMode::None) { + // Wait to ensure the child process has called + // ShouldContinueFromReplyTimeout(). + timeout->Wait(); + } + return IPC_OK(); + } + + ~TestHangsParent() = default; +}; + +// We can verify that the Start message callbacks are run with the `Close()` +// calls; without a `Close()`, the test will hang. + +#define TEST_HANGS(mode) \ + IPDL_TEST(TestHangs, mode) { \ + mActor->SendStart( \ + (uint32_t)HangMode::mode, \ + [=](bool detectedHang) { \ + EXPECT_EQ(detectedHang, HangMode::mode != HangMode::None); \ + mActor->Close(); \ + }, \ + [](auto&& reason) { FAIL() << "failed to send start"; }); \ + } + +TEST_HANGS(None) +TEST_HANGS(Hang) +TEST_HANGS(HangButReceive) +TEST_HANGS(HangPermitted) + +#undef TEST_HANGS + +} // namespace mozilla::_ipdltest diff --git a/ipc/ipdl/test/gtest/TestJSON.cpp b/ipc/ipdl/test/gtest/TestJSON.cpp new file mode 100644 index 0000000000..a3f881abda --- /dev/null +++ b/ipc/ipdl/test/gtest/TestJSON.cpp @@ -0,0 +1,157 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* + * Test sending JSON(-like) objects over IPC. + */ + +#include "gtest/gtest.h" + +#include "mozilla/_ipdltest/IPDLUnitTest.h" +#include "mozilla/_ipdltest/PTestJSONChild.h" +#include "mozilla/_ipdltest/PTestJSONParent.h" +#include "mozilla/_ipdltest/PTestJSONHandleChild.h" +#include "mozilla/_ipdltest/PTestJSONHandleParent.h" + +using namespace mozilla::ipc; + +namespace mozilla::_ipdltest { + +static nsString String(const char* const str) { + return NS_ConvertUTF8toUTF16(str); +} + +static void Array123(nsTArray<JSONVariant>& a123) { + a123.AppendElement(1); + a123.AppendElement(2); + a123.AppendElement(3); + + ASSERT_EQ(a123, a123) << "operator== is broken"; +} + +template <class HandleT> +JSONVariant MakeTestVariant(HandleT* handle) { + // In JS syntax: + // + // return [ + // undefined, null, true, 1.25, "test string", + // handle, + // [ 1, 2, 3 ], + // { "undefined" : undefined, + // "null" : null, + // "true" : true, + // "1.25" : 1.25, + // "string" : "string" + // "handle" : handle, + // "array" : [ 1, 2, 3 ] + // } + // ] + // + nsTArray<JSONVariant> outer; + + outer.AppendElement(void_t()); + outer.AppendElement(null_t()); + outer.AppendElement(true); + outer.AppendElement(1.25); + outer.AppendElement(String("test string")); + + outer.AppendElement(handle); + + nsTArray<JSONVariant> tmp; + Array123(tmp); + outer.AppendElement(tmp); + + nsTArray<KeyValue> obj; + obj.AppendElement(KeyValue(String("undefined"), void_t())); + obj.AppendElement(KeyValue(String("null"), null_t())); + obj.AppendElement(KeyValue(String("true"), true)); + obj.AppendElement(KeyValue(String("1.25"), 1.25)); + obj.AppendElement(KeyValue(String("string"), String("value"))); + obj.AppendElement(KeyValue(String("handle"), handle)); + nsTArray<JSONVariant> tmp2; + Array123(tmp2); + obj.AppendElement(KeyValue(String("array"), tmp2)); + + outer.AppendElement(obj); + + EXPECT_EQ(outer, outer) << "operator== is broken"; + + return JSONVariant(outer); +} + +//----------------------------------------------------------------------------- +// parent + +class TestJSONHandleParent : public PTestJSONHandleParent { + NS_INLINE_DECL_REFCOUNTING(TestJSONHandleParent, override) + private: + ~TestJSONHandleParent() = default; +}; + +class TestJSONHandleChild : public PTestJSONHandleChild { + NS_INLINE_DECL_REFCOUNTING(TestJSONHandleChild, override) + private: + ~TestJSONHandleChild() = default; +}; + +class TestJSONParent : public PTestJSONParent { + NS_INLINE_DECL_REFCOUNTING(TestJSONParent, override) + private: + IPCResult RecvTest(const JSONVariant& i, JSONVariant* o) final override { + EXPECT_EQ(i, MakeTestVariant(mKid.get())) << "inparam mangled en route"; + + *o = i; + + EXPECT_EQ(i, *o) << "operator== and/or copy assignment are broken"; + + return IPC_OK(); + } + + already_AddRefed<PTestJSONHandleParent> AllocPTestJSONHandleParent() + final override { + auto handle = MakeRefPtr<TestJSONHandleParent>(); + EXPECT_FALSE(mKid); + mKid = handle; + return handle.forget(); + } + + ~TestJSONParent() = default; + + RefPtr<PTestJSONHandleParent> mKid; +}; + +//----------------------------------------------------------------------------- +// child + +class TestJSONChild : public PTestJSONChild { + NS_INLINE_DECL_REFCOUNTING(TestJSONChild, override) + private: + IPCResult RecvStart() final override { + mKid = MakeRefPtr<TestJSONHandleChild>(); + EXPECT_TRUE(SendPTestJSONHandleConstructor(mKid)) << "sending Handle ctor"; + + JSONVariant i(MakeTestVariant(mKid.get())); + EXPECT_EQ(i, i) << "operator== is broken"; + EXPECT_EQ(i, MakeTestVariant(mKid.get())) << "copy ctor is broken"; + + JSONVariant o; + EXPECT_TRUE(SendTest(i, &o)) << "sending Test"; + + EXPECT_EQ(i, o) << "round-trip mangled input data"; + EXPECT_EQ(o, MakeTestVariant(mKid.get())) << "outparam mangled en route"; + + Close(); + return IPC_OK(); + } + + ~TestJSONChild() = default; + + RefPtr<PTestJSONHandleChild> mKid; +}; + +IPDL_TEST(TestJSON) { EXPECT_TRUE(mActor->SendStart()) << "sending Start"; } + +} // namespace mozilla::_ipdltest diff --git a/ipc/ipdl/test/gtest/TestManyChildAllocs.cpp b/ipc/ipdl/test/gtest/TestManyChildAllocs.cpp new file mode 100644 index 0000000000..2111f4f49f --- /dev/null +++ b/ipc/ipdl/test/gtest/TestManyChildAllocs.cpp @@ -0,0 +1,82 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* + * Test that many child allocations work correctly. + */ + +#include "gtest/gtest.h" + +#include "mozilla/_ipdltest/IPDLUnitTest.h" +#include "mozilla/_ipdltest/PTestManyChildAllocsChild.h" +#include "mozilla/_ipdltest/PTestManyChildAllocsParent.h" +#include "mozilla/_ipdltest/PTestManyChildAllocsSubChild.h" +#include "mozilla/_ipdltest/PTestManyChildAllocsSubParent.h" + +using namespace mozilla::ipc; + +#define NALLOCS 10 + +namespace mozilla::_ipdltest { + +class TestManyChildAllocsSubParent : public PTestManyChildAllocsSubParent { + NS_INLINE_DECL_REFCOUNTING(TestManyChildAllocsSubParent, override) + private: + IPCResult RecvHello() final override { return IPC_OK(); } + + ~TestManyChildAllocsSubParent() = default; +}; + +class TestManyChildAllocsSubChild : public PTestManyChildAllocsSubChild { + NS_INLINE_DECL_REFCOUNTING(TestManyChildAllocsSubChild, override) + private: + ~TestManyChildAllocsSubChild() = default; +}; + +class TestManyChildAllocsParent : public PTestManyChildAllocsParent { + NS_INLINE_DECL_REFCOUNTING(TestManyChildAllocsParent, override) + private: + IPCResult RecvDone() final override { + Close(); + + return IPC_OK(); + } + + already_AddRefed<PTestManyChildAllocsSubParent> + AllocPTestManyChildAllocsSubParent() final override { + return MakeAndAddRef<TestManyChildAllocsSubParent>(); + } + + ~TestManyChildAllocsParent() = default; +}; + +class TestManyChildAllocsChild : public PTestManyChildAllocsChild { + NS_INLINE_DECL_REFCOUNTING(TestManyChildAllocsChild, override) + private: + IPCResult RecvGo() final override { + for (int i = 0; i < NALLOCS; ++i) { + auto child = MakeRefPtr<TestManyChildAllocsSubChild>(); + EXPECT_TRUE(SendPTestManyChildAllocsSubConstructor(child)); + EXPECT_TRUE(child->SendHello()) << "can't send Hello()"; + } + + size_t len = ManagedPTestManyChildAllocsSubChild().Count(); + EXPECT_EQ((size_t)NALLOCS, len) + << "expected " << NALLOCS << " kids, got " << len; + + EXPECT_TRUE(SendDone()) << "can't send Done()"; + + return IPC_OK(); + } + + ~TestManyChildAllocsChild() = default; +}; + +IPDL_TEST(TestManyChildAllocs) { + EXPECT_TRUE(mActor->SendGo()) << "can't send Go()"; +} + +} // namespace mozilla::_ipdltest diff --git a/ipc/ipdl/test/gtest/TestMostNested.cpp b/ipc/ipdl/test/gtest/TestMostNested.cpp new file mode 100644 index 0000000000..d3fb3582c6 --- /dev/null +++ b/ipc/ipdl/test/gtest/TestMostNested.cpp @@ -0,0 +1,88 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * vim: sw=2 ts=4 et : + */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* + * Test nested sync message priorities. + */ + +#include "gtest/gtest.h" + +#include "mozilla/_ipdltest/IPDLUnitTest.h" +#include "mozilla/_ipdltest/PTestMostNestedChild.h" +#include "mozilla/_ipdltest/PTestMostNestedParent.h" + +#if defined(XP_UNIX) +# include <unistd.h> +#else +# include <windows.h> +#endif + +using namespace mozilla::ipc; + +namespace mozilla::_ipdltest { + +class TestMostNestedChild : public PTestMostNestedChild { + NS_INLINE_DECL_REFCOUNTING(TestMostNestedChild, override) + private: + IPCResult RecvStart() final override { + EXPECT_TRUE(SendMsg1()); + EXPECT_TRUE(SendMsg2()); + + Close(); + return IPC_OK(); + } + + IPCResult RecvStartInner() final override { + EXPECT_TRUE(SendMsg3()); + EXPECT_TRUE(SendMsg4()); + + return IPC_OK(); + } + + ~TestMostNestedChild() = default; +}; + +class TestMostNestedParent : public PTestMostNestedParent { + NS_INLINE_DECL_REFCOUNTING(TestMostNestedParent, override) + private: + IPCResult RecvMsg1() final override { + EXPECT_EQ(msg_num, 0); + msg_num = 1; + return IPC_OK(); + } + + IPCResult RecvMsg2() final override { + EXPECT_EQ(msg_num, 1); + msg_num = 2; + + EXPECT_TRUE(SendStartInner()); + + return IPC_OK(); + } + + IPCResult RecvMsg3() final override { + EXPECT_EQ(msg_num, 2); + msg_num = 3; + return IPC_OK(); + } + + IPCResult RecvMsg4() final override { + EXPECT_EQ(msg_num, 3); + msg_num = 4; + return IPC_OK(); + } + + ~TestMostNestedParent() = default; + + int msg_num = 0; +}; + +// Can only run cross-process because nested sync messages have to come from the +// main thread. +IPDL_TEST_ON(CROSSPROCESS, TestMostNested) { EXPECT_TRUE(mActor->SendStart()); } + +} // namespace mozilla::_ipdltest diff --git a/ipc/ipdl/test/gtest/TestMultiMgrs.cpp b/ipc/ipdl/test/gtest/TestMultiMgrs.cpp new file mode 100644 index 0000000000..06dac581f3 --- /dev/null +++ b/ipc/ipdl/test/gtest/TestMultiMgrs.cpp @@ -0,0 +1,202 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* + * Test a chain of managers, ensuring ownership is maintained correctly. + */ + +#include "gtest/gtest.h" + +#include "mozilla/_ipdltest/IPDLUnitTest.h" +#include "mozilla/_ipdltest/PTestMultiMgrsChild.h" +#include "mozilla/_ipdltest/PTestMultiMgrsParent.h" +#include "mozilla/_ipdltest/PTestMultiMgrsLeftChild.h" +#include "mozilla/_ipdltest/PTestMultiMgrsLeftParent.h" +#include "mozilla/_ipdltest/PTestMultiMgrsRightChild.h" +#include "mozilla/_ipdltest/PTestMultiMgrsRightParent.h" +#include "mozilla/_ipdltest/PTestMultiMgrsBottomChild.h" +#include "mozilla/_ipdltest/PTestMultiMgrsBottomParent.h" + +#include <algorithm> + +using namespace mozilla::ipc; + +namespace mozilla::_ipdltest { + +class TestMultiMgrsBottomParent : public PTestMultiMgrsBottomParent { + NS_INLINE_DECL_REFCOUNTING(TestMultiMgrsBottomParent, override) + private: + ~TestMultiMgrsBottomParent() = default; +}; + +class TestMultiMgrsBottomChild : public PTestMultiMgrsBottomChild { + NS_INLINE_DECL_REFCOUNTING(TestMultiMgrsBottomChild, override) + private: + ~TestMultiMgrsBottomChild() = default; +}; + +class TestMultiMgrsChild : public PTestMultiMgrsChild { + NS_INLINE_DECL_REFCOUNTING(TestMultiMgrsChild, override) + public: + PTestMultiMgrsBottomChild* mBottomL = nullptr; + PTestMultiMgrsBottomChild* mBottomR = nullptr; + + private: + already_AddRefed<PTestMultiMgrsLeftChild> AllocPTestMultiMgrsLeftChild() + final override; + + already_AddRefed<PTestMultiMgrsRightChild> AllocPTestMultiMgrsRightChild() + final override; + + IPCResult RecvCheck() final override; + + ~TestMultiMgrsChild() = default; +}; + +class TestMultiMgrsLeftParent : public PTestMultiMgrsLeftParent { + NS_INLINE_DECL_REFCOUNTING(TestMultiMgrsLeftParent, override) + public: + bool HasChild(PTestMultiMgrsBottomParent* c) { + const auto& managed = ManagedPTestMultiMgrsBottomParent(); + return std::find(managed.begin(), managed.end(), c) != managed.end(); + } + + private: + ~TestMultiMgrsLeftParent() = default; +}; + +class TestMultiMgrsLeftChild : public PTestMultiMgrsLeftChild { + NS_INLINE_DECL_REFCOUNTING(TestMultiMgrsLeftChild, override) + public: + bool HasChild(PTestMultiMgrsBottomChild* c) { + const auto& managed = ManagedPTestMultiMgrsBottomChild(); + return std::find(managed.begin(), managed.end(), c) != managed.end(); + } + + private: + already_AddRefed<PTestMultiMgrsBottomChild> AllocPTestMultiMgrsBottomChild() + final override { + return MakeAndAddRef<TestMultiMgrsBottomChild>(); + } + + IPCResult RecvPTestMultiMgrsBottomConstructor( + PTestMultiMgrsBottomChild* actor) final override { + static_cast<TestMultiMgrsChild*>(Manager())->mBottomL = actor; + return IPC_OK(); + } + + ~TestMultiMgrsLeftChild() = default; +}; + +class TestMultiMgrsRightParent : public PTestMultiMgrsRightParent { + NS_INLINE_DECL_REFCOUNTING(TestMultiMgrsRightParent, override) + public: + bool HasChild(PTestMultiMgrsBottomParent* c) { + const auto& managed = ManagedPTestMultiMgrsBottomParent(); + return std::find(managed.begin(), managed.end(), c) != managed.end(); + } + + private: + ~TestMultiMgrsRightParent() = default; +}; + +class TestMultiMgrsRightChild : public PTestMultiMgrsRightChild { + NS_INLINE_DECL_REFCOUNTING(TestMultiMgrsRightChild, override) + public: + bool HasChild(PTestMultiMgrsBottomChild* c) { + const auto& managed = ManagedPTestMultiMgrsBottomChild(); + return std::find(managed.begin(), managed.end(), c) != managed.end(); + } + + private: + already_AddRefed<PTestMultiMgrsBottomChild> AllocPTestMultiMgrsBottomChild() + final override { + return MakeAndAddRef<TestMultiMgrsBottomChild>(); + } + + IPCResult RecvPTestMultiMgrsBottomConstructor( + PTestMultiMgrsBottomChild* actor) final override { + static_cast<TestMultiMgrsChild*>(Manager())->mBottomR = actor; + return IPC_OK(); + } + + ~TestMultiMgrsRightChild() = default; +}; + +class TestMultiMgrsParent : public PTestMultiMgrsParent { + NS_INLINE_DECL_REFCOUNTING(TestMultiMgrsParent, override) + private: + IPCResult RecvOK() final override { + Close(); + return IPC_OK(); + } + + ~TestMultiMgrsParent() = default; +}; + +already_AddRefed<PTestMultiMgrsLeftChild> +TestMultiMgrsChild::AllocPTestMultiMgrsLeftChild() { + return MakeAndAddRef<TestMultiMgrsLeftChild>(); +} + +already_AddRefed<PTestMultiMgrsRightChild> +TestMultiMgrsChild::AllocPTestMultiMgrsRightChild() { + return MakeAndAddRef<TestMultiMgrsRightChild>(); +} + +IPCResult TestMultiMgrsChild::RecvCheck() { + EXPECT_EQ(ManagedPTestMultiMgrsLeftChild().Count(), (uint32_t)1) + << "where's leftie?"; + EXPECT_EQ(ManagedPTestMultiMgrsRightChild().Count(), (uint32_t)1) + << "where's rightie?"; + + TestMultiMgrsLeftChild* leftie = static_cast<TestMultiMgrsLeftChild*>( + LoneManagedOrNullAsserts(ManagedPTestMultiMgrsLeftChild())); + TestMultiMgrsRightChild* rightie = static_cast<TestMultiMgrsRightChild*>( + LoneManagedOrNullAsserts(ManagedPTestMultiMgrsRightChild())); + + EXPECT_TRUE(leftie->HasChild(mBottomL)) + << "leftie didn't have a child it was supposed to!"; + EXPECT_FALSE(leftie->HasChild(mBottomR)) << "leftie had rightie's child!"; + + EXPECT_TRUE(rightie->HasChild(mBottomR)) + << "rightie didn't have a child it was supposed to!"; + EXPECT_FALSE(rightie->HasChild(mBottomL)) << "rightie had leftie's child!"; + + EXPECT_TRUE(SendOK()) << "couldn't send OK()"; + + return IPC_OK(); +} + +IPDL_TEST(TestMultiMgrs) { + auto leftie = MakeRefPtr<TestMultiMgrsLeftParent>(); + EXPECT_TRUE(mActor->SendPTestMultiMgrsLeftConstructor(leftie)) + << "error sending ctor"; + + auto rightie = MakeRefPtr<TestMultiMgrsRightParent>(); + EXPECT_TRUE(mActor->SendPTestMultiMgrsRightConstructor(rightie)) + << "error sending ctor"; + + auto bottomL = MakeRefPtr<TestMultiMgrsBottomParent>(); + EXPECT_TRUE(leftie->SendPTestMultiMgrsBottomConstructor(bottomL)) + << "error sending ctor"; + + auto bottomR = MakeRefPtr<TestMultiMgrsBottomParent>(); + EXPECT_TRUE(rightie->SendPTestMultiMgrsBottomConstructor(bottomR)) + << "error sending ctor"; + + EXPECT_TRUE(leftie->HasChild(bottomL)) + << "leftie didn't have a child it was supposed to!"; + EXPECT_FALSE(leftie->HasChild(bottomR)) << "leftie had rightie's child!"; + + EXPECT_TRUE(rightie->HasChild(bottomR)) + << "rightie didn't have a child it was supposed to!"; + EXPECT_FALSE(rightie->HasChild(bottomL)) << "rightie had rightie's child!"; + + EXPECT_TRUE(mActor->SendCheck()) << "couldn't kick off the child-side check"; +} + +} // namespace mozilla::_ipdltest diff --git a/ipc/ipdl/test/gtest/TestSelfManage.cpp b/ipc/ipdl/test/gtest/TestSelfManage.cpp new file mode 100644 index 0000000000..6dc1c4b7e4 --- /dev/null +++ b/ipc/ipdl/test/gtest/TestSelfManage.cpp @@ -0,0 +1,100 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* + * Test that actors can manage other actors of the same type. + */ + +#include "gtest/gtest.h" + +#include "mozilla/_ipdltest/IPDLUnitTest.h" +#include "mozilla/_ipdltest/PTestSelfManageChild.h" +#include "mozilla/_ipdltest/PTestSelfManageParent.h" +#include "mozilla/_ipdltest/PTestSelfManageRootChild.h" +#include "mozilla/_ipdltest/PTestSelfManageRootParent.h" + +using namespace mozilla::ipc; + +namespace mozilla::_ipdltest { + +class TestSelfManageParent : public PTestSelfManageParent { + NS_INLINE_DECL_REFCOUNTING(TestSelfManageParent, override) + public: + ActorDestroyReason mWhy = ActorDestroyReason(-1); + + private: + void ActorDestroy(ActorDestroyReason why) final override { mWhy = why; } + + ~TestSelfManageParent() = default; +}; + +class TestSelfManageChild : public PTestSelfManageChild { + NS_INLINE_DECL_REFCOUNTING(TestSelfManageChild, override) + private: + already_AddRefed<PTestSelfManageChild> AllocPTestSelfManageChild() + final override { + return MakeAndAddRef<TestSelfManageChild>(); + } + + ~TestSelfManageChild() = default; +}; + +class TestSelfManageRootParent : public PTestSelfManageRootParent { + NS_INLINE_DECL_REFCOUNTING(TestSelfManageRootParent, override) + private: + ~TestSelfManageRootParent() = default; +}; + +class TestSelfManageRootChild : public PTestSelfManageRootChild { + NS_INLINE_DECL_REFCOUNTING(TestSelfManageRootChild, override) + private: + already_AddRefed<PTestSelfManageChild> AllocPTestSelfManageChild() + final override { + return MakeAndAddRef<TestSelfManageChild>(); + } + + ~TestSelfManageRootChild() = default; +}; + +IPDL_TEST(TestSelfManageRoot) { + auto child = MakeRefPtr<TestSelfManageParent>(); + EXPECT_TRUE(mActor->SendPTestSelfManageConstructor(child)); + + EXPECT_EQ(mActor->ManagedPTestSelfManageParent().Count(), 1u); + + { + auto childsChild = MakeRefPtr<TestSelfManageParent>(); + EXPECT_TRUE(child->SendPTestSelfManageConstructor(childsChild)); + + EXPECT_EQ(mActor->ManagedPTestSelfManageParent().Count(), 1u); + EXPECT_EQ(child->ManagedPTestSelfManageParent().Count(), 1u); + + EXPECT_TRUE(PTestSelfManageParent::Send__delete__(childsChild)); + + EXPECT_EQ(childsChild->mWhy, IProtocol::Deletion); + EXPECT_EQ(mActor->ManagedPTestSelfManageParent().Count(), 1u); + EXPECT_EQ(child->ManagedPTestSelfManageParent().Count(), 0u); + } + + { + auto childsChild = MakeRefPtr<TestSelfManageParent>(); + EXPECT_TRUE(child->SendPTestSelfManageConstructor(childsChild)); + + EXPECT_EQ(mActor->ManagedPTestSelfManageParent().Count(), 1u); + EXPECT_EQ(child->ManagedPTestSelfManageParent().Count(), 1u); + + EXPECT_TRUE(PTestSelfManageParent::Send__delete__(child)); + + EXPECT_EQ(child->mWhy, IProtocol::Deletion); + EXPECT_EQ(childsChild->mWhy, IProtocol::AncestorDeletion); + EXPECT_EQ(mActor->ManagedPTestSelfManageParent().Count(), 0u); + EXPECT_EQ(child->ManagedPTestSelfManageParent().Count(), 0u); + } + + mActor->Close(); +} + +} // namespace mozilla::_ipdltest diff --git a/ipc/ipdl/test/gtest/TestShmem.cpp b/ipc/ipdl/test/gtest/TestShmem.cpp new file mode 100644 index 0000000000..e08bcee179 --- /dev/null +++ b/ipc/ipdl/test/gtest/TestShmem.cpp @@ -0,0 +1,122 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* + * Test sending and receiving Shmem values. + */ + +#include "gtest/gtest.h" + +#include "mozilla/_ipdltest/IPDLUnitTest.h" +#include "mozilla/_ipdltest/PTestShmemChild.h" +#include "mozilla/_ipdltest/PTestShmemParent.h" + +using namespace mozilla::ipc; + +namespace mozilla::_ipdltest { + +class TestShmemParent : public PTestShmemParent { + NS_INLINE_DECL_REFCOUNTING(TestShmemParent, override) + private: + IPCResult RecvTake(Shmem&& mem, Shmem&& unsafe, + const uint32_t& expectedSize) final override { + EXPECT_EQ(mem.Size<char>(), expectedSize) + << "expected shmem size " << expectedSize << ", but it has size " + << mem.Size<char>(); + EXPECT_EQ(unsafe.Size<char>(), expectedSize) + << "expected shmem size " << expectedSize << ", but it has size " + << unsafe.Size<char>(); + + EXPECT_FALSE(strcmp(mem.get<char>(), "And yourself!")) + << "expected message was not written"; + EXPECT_FALSE(strcmp(unsafe.get<char>(), "And yourself!")) + << "expected message was not written"; + + EXPECT_TRUE(DeallocShmem(mem)); + EXPECT_TRUE(DeallocShmem(unsafe)); + + Close(); + + return IPC_OK(); + } + + ~TestShmemParent() = default; +}; + +class TestShmemChild : public PTestShmemChild { + NS_INLINE_DECL_REFCOUNTING(TestShmemChild, override) + private: + IPCResult RecvGive(Shmem&& mem, Shmem&& unsafe, + const uint32_t& expectedSize) final override { + EXPECT_EQ(mem.Size<char>(), expectedSize) + << "expected shmem size " << expectedSize << ", but it has size " + << mem.Size<char>(); + EXPECT_EQ(unsafe.Size<char>(), expectedSize) + << "expected shmem size " << expectedSize << ", but it has size " + << unsafe.Size<char>(); + + EXPECT_FALSE(strcmp(mem.get<char>(), "Hello!")) + << "expected message was not written"; + EXPECT_FALSE(strcmp(unsafe.get<char>(), "Hello!")) + << "expected message was not written"; + + char* unsafeptr = unsafe.get<char>(); + + memcpy(mem.get<char>(), "And yourself!", sizeof("And yourself!")); + memcpy(unsafeptr, "And yourself!", sizeof("And yourself!")); + + Shmem unsafecopy = unsafe; + EXPECT_TRUE(SendTake(std::move(mem), std::move(unsafe), expectedSize)); + + // these checks also shouldn't fail in the child + char uc1 = *unsafeptr; + (void)uc1; + char uc2 = *unsafecopy.get<char>(); + (void)uc2; + + return IPC_OK(); + } + + ~TestShmemChild() = default; +}; + +IPDL_TEST(TestShmem) { + Shmem mem; + Shmem unsafe; + + uint32_t size = 12345; + EXPECT_TRUE(mActor->AllocShmem(size, &mem)) << "can't alloc shmem"; + EXPECT_TRUE(mActor->AllocUnsafeShmem(size, &unsafe)) << "can't alloc shmem"; + + EXPECT_EQ(mem.Size<char>(), size) << "shmem is wrong size: expected " << size + << ", got " << mem.Size<char>(); + EXPECT_EQ(unsafe.Size<char>(), size) + << "shmem is wrong size: expected " << size << ", got " + << unsafe.Size<char>(); + + char* ptr = mem.get<char>(); + memcpy(ptr, "Hello!", sizeof("Hello!")); + + char* unsafeptr = unsafe.get<char>(); + memcpy(unsafeptr, "Hello!", sizeof("Hello!")); + + Shmem unsafecopy = unsafe; + EXPECT_TRUE(mActor->SendGive(std::move(mem), std::move(unsafe), size)); + + // uncomment the following line for a (nondeterministic) surprise! + // char c1 = *ptr; (void)c1; + + // uncomment the following line for a deterministic surprise! + // char c2 = *mem.get<char>(); (void)c2; + + // unsafe shmem gets rid of those checks + char uc1 = *unsafeptr; + (void)uc1; + char uc2 = *unsafecopy.get<char>(); + (void)uc2; +} + +} // namespace mozilla::_ipdltest diff --git a/ipc/ipdl/test/gtest/TestSyncError.cpp b/ipc/ipdl/test/gtest/TestSyncError.cpp new file mode 100644 index 0000000000..f7a85598a6 --- /dev/null +++ b/ipc/ipdl/test/gtest/TestSyncError.cpp @@ -0,0 +1,44 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* + * Test what happens when a sync message fails. + */ + +#include "gtest/gtest.h" + +#include "mozilla/_ipdltest/IPDLUnitTest.h" +#include "mozilla/_ipdltest/PTestSyncErrorChild.h" +#include "mozilla/_ipdltest/PTestSyncErrorParent.h" + +using namespace mozilla::ipc; + +namespace mozilla::_ipdltest { + +class TestSyncErrorParent : public PTestSyncErrorParent { + NS_INLINE_DECL_REFCOUNTING(TestSyncErrorParent, override) + private: + IPCResult RecvError() final override { return IPC_TEST_FAIL(this); } + + ~TestSyncErrorParent() = default; +}; + +class TestSyncErrorChild : public PTestSyncErrorChild { + NS_INLINE_DECL_REFCOUNTING(TestSyncErrorChild, override) + private: + IPCResult RecvStart() final override { + EXPECT_FALSE(SendError()) << "Error() should have return false"; + + Close(); + + return IPC_OK(); + } + ~TestSyncErrorChild() = default; +}; + +IPDL_TEST(TestSyncError) { EXPECT_TRUE(mActor->SendStart()); } + +} // namespace mozilla::_ipdltest diff --git a/ipc/ipdl/test/gtest/TestUniquePtrIPC.cpp b/ipc/ipdl/test/gtest/TestUniquePtrIPC.cpp new file mode 100644 index 0000000000..52ca322f8e --- /dev/null +++ b/ipc/ipdl/test/gtest/TestUniquePtrIPC.cpp @@ -0,0 +1,80 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* + * Test UniquePtr IPC arguments. + */ + +#include "gtest/gtest.h" + +#include "mozilla/_ipdltest/IPDLUnitTest.h" +#include "mozilla/_ipdltest/PTestUniquePtrIPCChild.h" +#include "mozilla/_ipdltest/PTestUniquePtrIPCParent.h" + +using namespace mozilla::ipc; + +namespace mozilla::_ipdltest { + +class TestUniquePtrIPCParent : public PTestUniquePtrIPCParent { + NS_INLINE_DECL_REFCOUNTING(TestUniquePtrIPCParent, override) + private: + ~TestUniquePtrIPCParent() = default; +}; + +class TestUniquePtrIPCChild : public PTestUniquePtrIPCChild { + NS_INLINE_DECL_REFCOUNTING(TestUniquePtrIPCChild, override) + private: + IPCResult RecvTestMessage(const UniquePtr<int>& aA1, + const UniquePtr<DummyStruct>& aA2, + const DummyStruct& aA3, + const UniquePtr<int>& aA4) final override { + EXPECT_TRUE(aA1) << "TestMessage received NULL aA1"; + EXPECT_TRUE(aA2) << "TestMessage received NULL aA2"; + EXPECT_FALSE(aA4) + << "TestMessage received non-NULL when expecting NULL aA4"; + + EXPECT_EQ(*aA1, 1); + EXPECT_EQ(aA2->x(), 2); + EXPECT_EQ(aA3.x(), 3); + + return IPC_OK(); + } + + IPCResult RecvTestSendReference( + const UniquePtr<DummyStruct>& aA) final override { + EXPECT_TRUE(aA) << "TestSendReference received NULL item in child"; + EXPECT_EQ(aA->x(), 1); + + Close(); + return IPC_OK(); + } + + ~TestUniquePtrIPCChild() = default; +}; + +IPDL_TEST(TestUniquePtrIPC) { + UniquePtr<int> a1 = MakeUnique<int>(1); + UniquePtr<DummyStruct> a2 = MakeUnique<DummyStruct>(2); + DummyStruct a3(3); + UniquePtr<int> a4; + + EXPECT_TRUE(mActor->SendTestMessage(a1, a2, a3, a4)); + + EXPECT_TRUE(a1) + << "IPC arguments are passed by const reference and shouldn't be moved"; + EXPECT_TRUE(a2) + << "IPC arguments are passed by const reference and shouldn't be moved"; + + EXPECT_FALSE(a4) << "somehow turned null ptr into non-null by sending it"; + + // Pass UniquePtr by reference + UniquePtr<DummyStruct> b = MakeUnique<DummyStruct>(1); + + EXPECT_TRUE(mActor->SendTestSendReference(b)); + EXPECT_TRUE(b) + << "IPC arguments are passed by const reference and shouldn't be moved"; +} + +} // namespace mozilla::_ipdltest diff --git a/ipc/ipdl/test/gtest/TestUrgency.cpp b/ipc/ipdl/test/gtest/TestUrgency.cpp new file mode 100644 index 0000000000..a4f7d0ea3e --- /dev/null +++ b/ipc/ipdl/test/gtest/TestUrgency.cpp @@ -0,0 +1,115 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* + * Test that sync messages preempt other messages in the expected way. + */ + +#include "gtest/gtest.h" + +#include "mozilla/_ipdltest/IPDLUnitTest.h" +#include "mozilla/_ipdltest/PTestUrgencyChild.h" +#include "mozilla/_ipdltest/PTestUrgencyParent.h" + +using namespace mozilla::ipc; + +namespace mozilla::_ipdltest { + +enum { + kFirstTestBegin = 1, + kFirstTestGotReply, + kSecondTestBegin, + kSecondTestGotReply, +}; + +class TestUrgencyParent : public PTestUrgencyParent { + NS_INLINE_DECL_REFCOUNTING(TestUrgencyParent, override) + private: + IPCResult RecvTest1(uint32_t* value) final override { + EXPECT_TRUE(SendReply1(value)); + EXPECT_EQ(*value, (uint32_t)99) << "unexpected value"; + return IPC_OK(); + } + + IPCResult RecvTest2() final override { + uint32_t value; + inreply_ = true; + EXPECT_TRUE(SendReply2(&value)); + inreply_ = false; + EXPECT_EQ(value, (uint32_t)500) << "unexpected value"; + return IPC_OK(); + } + + IPCResult RecvTest3(uint32_t* value) final override { + EXPECT_FALSE(inreply_) << "nested non-urgent on top of urgent message"; + *value = 1000; + return IPC_OK(); + } + + IPCResult RecvFinalTest_Begin() final override { return IPC_OK(); } + + ~TestUrgencyParent() = default; + + bool inreply_ = false; +}; + +class TestUrgencyChild : public PTestUrgencyChild { + NS_INLINE_DECL_REFCOUNTING(TestUrgencyChild, override) + private: + IPCResult RecvStart() final override { + uint32_t result; + + // Send a synchronous message, expect to get an urgent message while + // blocked. + test_ = kFirstTestBegin; + EXPECT_TRUE(SendTest1(&result)); + EXPECT_EQ(result, (uint32_t)99) << "wrong value from SendTest1"; + EXPECT_EQ(test_, kFirstTestGotReply) + << "never received first urgent message"; + + // Initiate the next test by sending an asynchronous message, then becoming + // blocked. This tests that the urgent message is still delivered properly, + // and that the parent does not try to service the sync + test_ = kSecondTestBegin; + EXPECT_TRUE(SendTest2()); + EXPECT_TRUE(SendTest3(&result)); + EXPECT_EQ(test_, kSecondTestGotReply) + << "never received second urgent message"; + EXPECT_EQ(result, (uint32_t)1000) << "wrong value from SendTest3"; + + EXPECT_TRUE(SendFinalTest_Begin()); + + Close(); + + return IPC_OK(); + } + + IPCResult RecvReply1(uint32_t* reply) final override { + EXPECT_EQ(test_, kFirstTestBegin) << "wrong test state in RecvReply1"; + + *reply = 99; + test_ = kFirstTestGotReply; + return IPC_OK(); + } + + IPCResult RecvReply2(uint32_t* reply) final override { + EXPECT_EQ(test_, kSecondTestBegin) << "wrong test state in RecvReply2"; + + *reply = 500; + test_ = kSecondTestGotReply; + return IPC_OK(); + } + + ~TestUrgencyChild() = default; + + uint32_t test_ = 0; +}; + +// Only run cross-process because we need to send nested sync messages (this can +// only be done from the main thread). +IPDL_TEST_ON(CROSSPROCESS, TestUrgency) { EXPECT_TRUE(mActor->SendStart()); } + +} // namespace mozilla::_ipdltest diff --git a/ipc/ipdl/test/gtest/moz.build b/ipc/ipdl/test/gtest/moz.build index 129e366a4b..86fa2eca9e 100644 --- a/ipc/ipdl/test/gtest/moz.build +++ b/ipc/ipdl/test/gtest/moz.build @@ -16,18 +16,59 @@ EXPORTS.mozilla._ipdltest += [ SOURCES += [ "IPDLUnitTest.cpp", + "TestAsyncReturns.cpp", "TestBasic.cpp", + "TestCancel.cpp", "TestCrossProcessSemaphore.cpp", + "TestDataStructures.cpp", + "TestDescendant.cpp", + "TestEndpointOpens.cpp", + "TestHangs.cpp", "TestInduceConnectionError.cpp", + "TestJSON.cpp", + "TestManyChildAllocs.cpp", "TestManyHandles.cpp", + "TestMostNested.cpp", + "TestMultiMgrs.cpp", + "TestSelfManage.cpp", + "TestShmem.cpp", + "TestSyncError.cpp", + "TestUniquePtrIPC.cpp", + "TestUrgency.cpp", ] IPDL_SOURCES += [ "PIPDLUnitTest.ipdl", + "PTestAsyncReturns.ipdl", "PTestBasic.ipdl", + "PTestCancel.ipdl", "PTestCrossProcessSemaphore.ipdl", + "PTestDataStructures.ipdl", + "PTestDataStructuresCommon.ipdlh", + "PTestDataStructuresSub.ipdl", + "PTestDescendant.ipdl", + "PTestDescendantSub.ipdl", + "PTestDescendantSubsub.ipdl", + "PTestEndpointOpens.ipdl", + "PTestEndpointOpensOpened.ipdl", + "PTestHangs.ipdl", "PTestInduceConnectionError.ipdl", + "PTestJSON.ipdl", + "PTestJSONHandle.ipdl", + "PTestManyChildAllocs.ipdl", + "PTestManyChildAllocsSub.ipdl", "PTestManyHandles.ipdl", + "PTestMostNested.ipdl", + "PTestMultiMgrs.ipdl", + "PTestMultiMgrsBottom.ipdl", + "PTestMultiMgrsLeft.ipdl", + "PTestMultiMgrsRight.ipdl", + "PTestSelfManage.ipdl", + "PTestSelfManageRoot.ipdl", + "PTestShmem.ipdl", + "PTestSyncError.ipdl", + "PTestUniquePtrIPC.ipdl", + "PTestUrgency.ipdl", ] include("/ipc/chromium/chromium-config.mozbuild") |