diff options
Diffstat (limited to 'ipc/ipdl/test/gtest/TestDataStructures.cpp')
-rw-r--r-- | ipc/ipdl/test/gtest/TestDataStructures.cpp | 864 |
1 files changed, 864 insertions, 0 deletions
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 |