| // Copyright 2020 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include <fidl/llcpptest.handleraii.test/cpp/wire.h> |
| #include <lib/async-loop/cpp/loop.h> |
| #include <lib/async-loop/default.h> |
| #include <lib/async/wait.h> |
| #include <lib/fidl/cpp/wire/arena.h> |
| #include <lib/fidl/cpp/wire/object_view.h> |
| #include <lib/fidl/cpp/wire/server.h> |
| #include <lib/fidl/cpp/wire/vector_view.h> |
| #include <lib/zx/object.h> |
| #include <zircon/errors.h> |
| #include <zircon/fidl.h> |
| #include <zircon/status.h> |
| #include <zircon/syscalls/object.h> |
| |
| #include <cstdint> |
| |
| #include <gtest/gtest.h> |
| #include <src/lib/fidl/llcpp/tests/types_test_utils.h> |
| |
| namespace test = ::llcpptest_handleraii_test; |
| |
| // All the tests in this file check that when a result is freed, all the handles inside the result |
| // are closed. |
| |
| class HandleCloseProviderServer : public fidl::WireServer<test::HandleProvider> { |
| public: |
| void GetHandle(GetHandleCompleter::Sync& completer) override { |
| zx::event e; |
| zx::event::create(0, &e); |
| completer.Reply(std::move(e)); |
| } |
| void GetHandleStruct(GetHandleStructCompleter::Sync& completer) override { |
| test::wire::HandleStruct s; |
| zx::event::create(0, &s.h); |
| completer.Reply(std::move(s)); |
| } |
| void GetHandleStructStruct(GetHandleStructStructCompleter::Sync& completer) override { |
| test::wire::HandleStructStruct s; |
| zx::event::create(0, &s.s.h); |
| completer.Reply(std::move(s)); |
| } |
| void GetMultiFieldStruct(GetMultiFieldStructCompleter::Sync& completer) override { |
| test::wire::MultiFieldStruct s; |
| zx::event::create(0, &s.h1); |
| zx::event::create(0, &s.s.h); |
| zx::event::create(0, &s.h2); |
| completer.Reply(std::move(s)); |
| } |
| void GetMultiArgs(GetMultiArgsCompleter::Sync& completer) override { |
| zx::event h1; |
| zx::event::create(0, &h1); |
| test::wire::HandleStruct s; |
| zx::event::create(0, &s.h); |
| zx::event h2; |
| zx::event::create(0, &h2); |
| completer.Reply(std::move(h1), std::move(s), std::move(h2)); |
| } |
| void GetVectorStruct(GetVectorStructRequestView request, |
| GetVectorStructCompleter::Sync& completer) override { |
| fidl::Arena allocator; |
| fidl::VectorView<test::wire::HandleStruct> v(allocator, request->count); |
| for (auto& s : v) { |
| zx::event::create(0, &s.h); |
| } |
| test::wire::VectorStruct s; |
| s.v = std::move(v); |
| completer.Reply(std::move(s)); |
| } |
| void GetArrayStruct(GetArrayStructCompleter::Sync& completer) override { |
| test::wire::ArrayStruct s; |
| for (size_t i = 0; i < s.a.size(); ++i) { |
| zx::event::create(0, &s.a[i].h); |
| } |
| completer.Reply(std::move(s)); |
| } |
| void GetHandleUnion(GetHandleUnionRequestView request, |
| GetHandleUnionCompleter::Sync& completer) override { |
| test::wire::HandleUnion u; |
| if (request->field == 1) { |
| u = test::wire::HandleUnion::WithH1(zx::event()); |
| zx::event::create(0, &u.h1()); |
| } else if (request->field == 2) { |
| u = test::wire::HandleUnion::WithH2(test::wire::HandleStruct()); |
| zx::event::create(0, &u.h2().h); |
| } |
| completer.Reply(std::move(u)); |
| } |
| void GetHandleUnionStruct(GetHandleUnionStructRequestView request, |
| GetHandleUnionStructCompleter::Sync& completer) override { |
| test::wire::HandleUnionStruct u; |
| if (request->field == 1) { |
| zx::event event; |
| zx::event::create(0, &event); |
| u.u = test::wire::HandleUnion::WithH1(std::move(event)); |
| } else if (request->field == 2) { |
| u.u = test::wire::HandleUnion::WithH2(test::wire::HandleStruct()); |
| zx::event::create(0, &u.u.h2().h); |
| } |
| completer.Reply(std::move(u)); |
| } |
| void GetHandleTable(GetHandleTableRequestView request, |
| GetHandleTableCompleter::Sync& completer) override { |
| fidl::Arena allocator; |
| auto builder = test::wire::HandleTable::Builder(allocator); |
| if ((request->fields & 1) != 0) { |
| zx::event event; |
| zx::event::create(0, &event); |
| builder.h1(std::move(event)); |
| } |
| if ((request->fields & 2) != 0) { |
| test::wire::HandleStruct hs{}; |
| zx::event::create(0, &hs.h); |
| builder.h2(std::move(hs)); |
| } |
| completer.Reply(builder.Build()); |
| } |
| void GetHandleTableStruct(GetHandleTableStructRequestView request, |
| GetHandleTableStructCompleter::Sync& completer) override { |
| fidl::Arena allocator; |
| test::wire::HandleTableStruct reply; |
| auto builder = test::wire::HandleTable::Builder(allocator); |
| if ((request->fields & 1) != 0) { |
| zx::event event; |
| zx::event::create(0, &event); |
| builder.h1(std::move(event)); |
| } |
| if ((request->fields & 2) != 0) { |
| test::wire::HandleStruct hs{}; |
| zx::event::create(0, &hs.h); |
| builder.h2(std::move(hs)); |
| } |
| reply.t = builder.Build(); |
| completer.Reply(std::move(reply)); |
| } |
| void GetOptionalHandleStruct(GetOptionalHandleStructRequestView request, |
| GetOptionalHandleStructCompleter::Sync& completer) override { |
| fidl::Arena allocator; |
| if (request->defined) { |
| fidl::ObjectView<test::wire::HandleStruct> s(allocator); |
| zx::event::create(0, &s->h); |
| completer.Reply(s); |
| } else { |
| completer.Reply(nullptr); |
| } |
| } |
| void GetOptionalHandleUnion(GetOptionalHandleUnionRequestView request, |
| GetOptionalHandleUnionCompleter::Sync& completer) override { |
| fidl::Arena allocator; |
| test::wire::HandleUnion u; |
| if (request->field == 1) { |
| zx::event event; |
| zx::event::create(0, &event); |
| u = test::wire::HandleUnion::WithH1(std::move(event)); |
| } else if (request->field == 2) { |
| u = test::wire::HandleUnion::WithH2(test::wire::HandleStruct()); |
| zx::event::create(0, &u.h2().h); |
| } |
| completer.Reply(std::move(u)); |
| } |
| void GetOptionalHandleUnionStruct( |
| GetOptionalHandleUnionStructRequestView request, |
| GetOptionalHandleUnionStructCompleter::Sync& completer) override { |
| if (request->defined) { |
| fidl::Arena allocator; |
| fidl::ObjectView<test::wire::HandleUnionStruct> u(allocator); |
| if (request->field == 1) { |
| zx::event event; |
| zx::event::create(0, &event); |
| u->u = test::wire::HandleUnion::WithH1(std::move(event)); |
| } else if (request->field == 2) { |
| u->u = test::wire::HandleUnion::WithH2(test::wire::HandleStruct()); |
| zx::event::create(0, &u->u.h2().h); |
| } |
| completer.Reply(u); |
| } else { |
| completer.Reply(nullptr); |
| } |
| } |
| void GetOptionalHandleTableStruct( |
| GetOptionalHandleTableStructRequestView request, |
| GetOptionalHandleTableStructCompleter::Sync& completer) override { |
| if (request->defined) { |
| fidl::Arena allocator; |
| fidl::ObjectView<test::wire::HandleTableStruct> reply(allocator); |
| auto builder = test::wire::HandleTable::Builder(allocator); |
| if ((request->fields & 1) != 0) { |
| zx::event e; |
| zx::event::create(0, &e); |
| builder.h1(std::move(e)); |
| } |
| if ((request->fields & 2) != 0) { |
| test::wire::HandleStruct s; |
| zx::event::create(0, &s.h); |
| builder.h2(std::move(s)); |
| } |
| reply->t = builder.Build(); |
| completer.Reply(reply); |
| } else { |
| completer.Reply(nullptr); |
| } |
| } |
| void GetHandleStructOptionalStruct( |
| GetHandleStructOptionalStructRequestView request, |
| GetHandleStructOptionalStructCompleter::Sync& completer) override { |
| fidl::Arena allocator; |
| test::wire::HandleStructOptionalStruct reply; |
| if (request->defined) { |
| fidl::ObjectView<test::wire::HandleStruct> s(allocator); |
| zx::event::create(0, &s->h); |
| reply.s = s; |
| } |
| completer.Reply(std::move(reply)); |
| } |
| void GetHandleUnionOptionalStruct( |
| GetHandleUnionOptionalStructRequestView request, |
| GetHandleUnionOptionalStructCompleter::Sync& completer) override { |
| fidl::Arena allocator; |
| test::wire::HandleUnionOptionalStruct reply; |
| if (request->defined) { |
| if (request->field == 1) { |
| zx::event event; |
| zx::event::create(0, &event); |
| reply.u = test::wire::HandleUnion::WithH1(std::move(event)); |
| } else if (request->field == 2) { |
| reply.u = test::wire::HandleUnion::WithH2(test::wire::HandleStruct()); |
| zx::event::create(0, &reply.u->h2().h); |
| } |
| } |
| completer.Reply(std::move(reply)); |
| } |
| void GetVectorOfHandle(GetVectorOfHandleRequestView request, |
| GetVectorOfHandleCompleter::Sync& completer) override { |
| fidl::Arena allocator; |
| fidl::VectorView<zx::event> v(allocator, request->count); |
| for (auto& item : v) { |
| zx::event::create(0, &item); |
| } |
| completer.Reply(std::move(v)); |
| } |
| void GetVectorOfVectorOfHandle(GetVectorOfVectorOfHandleRequestView request, |
| GetVectorOfVectorOfHandleCompleter::Sync& completer) override { |
| fidl::Arena allocator; |
| fidl::VectorView<fidl::VectorView<zx::event>> v(allocator, request->count1); |
| for (uint32_t i1 = 0; i1 < request->count1; ++i1) { |
| v[i1].Allocate(allocator, request->count2); |
| for (uint32_t i2 = 0; i2 < request->count2; ++i2) { |
| zx::event::create(0, &v[i1][i2]); |
| } |
| } |
| completer.Reply(std::move(v)); |
| } |
| void GetVectorOfVectorOfVectorOfHandle( |
| GetVectorOfVectorOfVectorOfHandleRequestView request, |
| GetVectorOfVectorOfVectorOfHandleCompleter::Sync& completer) override { |
| fidl::Arena allocator; |
| fidl::VectorView<fidl::VectorView<fidl::VectorView<zx::event>>> v(allocator, request->count1); |
| for (uint32_t i1 = 0; i1 < request->count1; ++i1) { |
| v[i1].Allocate(allocator, request->count2); |
| for (uint32_t i2 = 0; i2 < request->count2; ++i2) { |
| v[i1][i2].Allocate(allocator, request->count3); |
| for (uint32_t i3 = 0; i3 < request->count3; ++i3) { |
| zx::event::create(0, &v[i1][i2][i3]); |
| } |
| } |
| } |
| completer.Reply(std::move(v)); |
| } |
| void GetVectorOfHandleStruct(GetVectorOfHandleStructRequestView request, |
| GetVectorOfHandleStructCompleter::Sync& completer) override { |
| fidl::Arena allocator; |
| fidl::VectorView<test::wire::HandleStruct> v(allocator, request->count); |
| for (auto& item : v) { |
| zx::event::create(0, &item.h); |
| } |
| completer.Reply(std::move(v)); |
| } |
| void GetVectorOfVectorOfHandleStruct( |
| GetVectorOfVectorOfHandleStructRequestView request, |
| GetVectorOfVectorOfHandleStructCompleter::Sync& completer) override { |
| fidl::Arena allocator; |
| fidl::VectorView<fidl::VectorView<test::wire::HandleStruct>> v(allocator, request->count1); |
| for (uint32_t i1 = 0; i1 < request->count1; ++i1) { |
| v[i1].Allocate(allocator, request->count2); |
| for (uint32_t i2 = 0; i2 < request->count2; ++i2) { |
| zx::event::create(0, &v[i1][i2].h); |
| } |
| } |
| completer.Reply(std::move(v)); |
| } |
| void GetVectorOfVectorOfVectorOfHandleStruct( |
| GetVectorOfVectorOfVectorOfHandleStructRequestView request, |
| GetVectorOfVectorOfVectorOfHandleStructCompleter::Sync& completer) override { |
| fidl::Arena allocator; |
| fidl::VectorView<fidl::VectorView<fidl::VectorView<test::wire::HandleStruct>>> v( |
| allocator, request->count1); |
| for (uint32_t i1 = 0; i1 < request->count1; ++i1) { |
| v[i1].Allocate(allocator, request->count2); |
| for (uint32_t i2 = 0; i2 < request->count2; ++i2) { |
| v[i1][i2].Allocate(allocator, request->count3); |
| for (uint32_t i3 = 0; i3 < request->count3; ++i3) { |
| zx::event::create(0, &v[i1][i2][i3].h); |
| } |
| } |
| } |
| completer.Reply(std::move(v)); |
| } |
| void GetArrayOfHandle(GetArrayOfHandleCompleter::Sync& completer) override { |
| fidl::Array<zx::event, 2> a; |
| for (auto& item : a) { |
| zx::event::create(0, &item); |
| } |
| completer.Reply(std::move(a)); |
| } |
| void GetArrayOfArrayOfHandle(GetArrayOfArrayOfHandleCompleter::Sync& completer) override { |
| fidl::Array<fidl::Array<zx::event, 2>, 3> a; |
| for (auto& item1 : a) { |
| for (auto& item2 : item1) { |
| zx::event::create(0, &item2); |
| } |
| } |
| completer.Reply(std::move(a)); |
| } |
| void GetArrayOfArrayOfArrayOfHandle( |
| GetArrayOfArrayOfArrayOfHandleCompleter::Sync& completer) override { |
| fidl::Array<fidl::Array<fidl::Array<zx::event, 2>, 3>, 4> a; |
| for (auto& item1 : a) { |
| for (auto& item2 : item1) { |
| for (auto& item3 : item2) { |
| zx::event::create(0, &item3); |
| } |
| } |
| } |
| completer.Reply(std::move(a)); |
| } |
| void GetArrayOfHandleStruct(GetArrayOfHandleStructCompleter::Sync& completer) override { |
| fidl::Array<test::wire::HandleStruct, 2> a; |
| for (auto& item : a) { |
| zx::event::create(0, &item.h); |
| } |
| completer.Reply(std::move(a)); |
| } |
| void GetArrayOfArrayOfHandleStruct( |
| GetArrayOfArrayOfHandleStructCompleter::Sync& completer) override { |
| fidl::Array<fidl::Array<test::wire::HandleStruct, 2>, 3> a; |
| for (auto& item1 : a) { |
| for (auto& item2 : item1) { |
| zx::event::create(0, &item2.h); |
| } |
| } |
| completer.Reply(std::move(a)); |
| } |
| void GetArrayOfArrayOfArrayOfHandleStruct( |
| GetArrayOfArrayOfArrayOfHandleStructCompleter::Sync& completer) override { |
| fidl::Array<fidl::Array<fidl::Array<test::wire::HandleStruct, 2>, 3>, 4> a; |
| for (auto& item1 : a) { |
| for (auto& item2 : item1) { |
| for (auto& item3 : item2) { |
| zx::event::create(0, &item3.h); |
| } |
| } |
| } |
| completer.Reply(std::move(a)); |
| } |
| void GetMixed1(GetMixed1RequestView request, GetMixed1Completer::Sync& completer) override { |
| fidl::Arena allocator; |
| fidl::Array<fidl::VectorView<zx::event>, 2> a; |
| for (auto& item1 : a) { |
| item1.Allocate(allocator, request->count); |
| for (auto& item2 : item1) { |
| zx::event::create(0, &item2); |
| } |
| } |
| completer.Reply(std::move(a)); |
| } |
| void GetMixed2(GetMixed2RequestView request, GetMixed2Completer::Sync& completer) override { |
| fidl::Arena allocator; |
| fidl::VectorView<fidl::Array<zx::event, 2>> v(allocator, request->count); |
| for (auto& item1 : v) { |
| for (auto& item2 : item1) { |
| zx::event::create(0, &item2); |
| } |
| } |
| completer.Reply(std::move(v)); |
| } |
| }; |
| |
| class HandleCloseTest : public ::testing::Test { |
| protected: |
| virtual void SetUp() { |
| loop_ = std::make_unique<async::Loop>(&kAsyncLoopConfigAttachToCurrentThread); |
| ASSERT_EQ(loop_->StartThread("test_llcpp_handle_server"), ZX_OK); |
| |
| auto endpoints = fidl::Endpoints<test::HandleProvider>::Create(); |
| client_end_ = std::move(endpoints.client); |
| server_ = std::make_unique<HandleCloseProviderServer>(); |
| fidl::BindServer(loop_->dispatcher(), std::move(endpoints.server), server_.get()); |
| } |
| |
| fidl::WireSyncClient<test::HandleProvider> TakeClient() { |
| EXPECT_TRUE(client_end_.is_valid()); |
| return fidl::WireSyncClient<test::HandleProvider>(std::move(client_end_)); |
| } |
| |
| private: |
| std::unique_ptr<async::Loop> loop_; |
| std::unique_ptr<HandleCloseProviderServer> server_; |
| fidl::ClientEnd<test::HandleProvider> client_end_; |
| }; |
| |
| TEST_F(HandleCloseTest, Handle) { |
| llcpp_types_test_utils::HandleChecker checker; |
| auto client = TakeClient(); |
| { |
| auto result = client->GetHandle(); |
| |
| ASSERT_TRUE(result.ok()) << result.error(); |
| |
| checker.AddEvent(result.value().value); |
| } |
| |
| // After the destruction of the result, each handle in dupes should have only one link. |
| checker.CheckEvents(); |
| } |
| |
| TEST_F(HandleCloseTest, HandleStruct) { |
| llcpp_types_test_utils::HandleChecker checker; |
| auto client = TakeClient(); |
| { |
| auto result = client->GetHandleStruct(); |
| |
| ASSERT_TRUE(result.ok()) << result.error(); |
| |
| checker.AddEvent(result.value().value.h); |
| } |
| |
| // After the destruction of the result, each handle in dupes should have only one link. |
| checker.CheckEvents(); |
| } |
| |
| TEST_F(HandleCloseTest, HandleStructStruct) { |
| llcpp_types_test_utils::HandleChecker checker; |
| auto client = TakeClient(); |
| { |
| auto result = client->GetHandleStructStruct(); |
| |
| ASSERT_TRUE(result.ok()) << result.error(); |
| |
| checker.AddEvent(result.value().value.s.h); |
| } |
| |
| // After the destruction of the result, each handle in dupes should have only one link. |
| checker.CheckEvents(); |
| } |
| |
| TEST_F(HandleCloseTest, MultiFieldStruct) { |
| llcpp_types_test_utils::HandleChecker checker; |
| auto client = TakeClient(); |
| { |
| auto result = client->GetMultiFieldStruct(); |
| |
| ASSERT_TRUE(result.ok()) << result.error(); |
| |
| checker.AddEvent(result.value().value.h1); |
| checker.AddEvent(result.value().value.s.h); |
| checker.AddEvent(result.value().value.h2); |
| } |
| |
| // After the destruction of the result, each handle in dupes should have only one link. |
| checker.CheckEvents(); |
| } |
| |
| TEST_F(HandleCloseTest, MultiArgs) { |
| llcpp_types_test_utils::HandleChecker checker; |
| auto client = TakeClient(); |
| { |
| auto result = client->GetMultiArgs(); |
| |
| ASSERT_TRUE(result.ok()) << result.error(); |
| |
| checker.AddEvent(result.value().h1); |
| checker.AddEvent(result.value().s.h); |
| checker.AddEvent(result.value().h2); |
| } |
| |
| // After the destruction of the result, each handle in dupes should have only one link. |
| checker.CheckEvents(); |
| } |
| |
| TEST_F(HandleCloseTest, VectorStruct) { |
| llcpp_types_test_utils::HandleChecker checker; |
| auto client = TakeClient(); |
| { |
| auto result = client->GetVectorStruct(4); |
| |
| ASSERT_TRUE(result.ok()) << result.error(); |
| |
| for (uint32_t i = 0; i < result.value().value.v.size(); ++i) { |
| checker.AddEvent(result.value().value.v[i].h); |
| } |
| } |
| |
| // After the destruction of the result, each handle in dupes should have only one link. |
| checker.CheckEvents(); |
| } |
| |
| TEST_F(HandleCloseTest, ArrayStruct) { |
| llcpp_types_test_utils::HandleChecker checker; |
| auto client = TakeClient(); |
| { |
| auto result = client->GetArrayStruct(); |
| |
| ASSERT_TRUE(result.ok()) << result.error(); |
| |
| for (size_t i = 0; i < result.value().value.a.size(); ++i) { |
| checker.AddEvent(result.value().value.a[i].h); |
| } |
| } |
| |
| // After the destruction of the result, each handle in dupes should have only one link. |
| checker.CheckEvents(); |
| } |
| |
| TEST_F(HandleCloseTest, HandleUnion1) { |
| llcpp_types_test_utils::HandleChecker checker; |
| auto client = TakeClient(); |
| { |
| auto result = client->GetHandleUnion(1); |
| |
| ASSERT_TRUE(result.ok()) << result.error(); |
| |
| ASSERT_TRUE(result.value().value.is_h1()); |
| checker.AddEvent(result.value().value.h1()); |
| } |
| |
| // After the destruction of the result, each handle in dupes should have only one link. |
| checker.CheckEvents(); |
| } |
| |
| TEST_F(HandleCloseTest, HandleUnion2) { |
| llcpp_types_test_utils::HandleChecker checker; |
| auto client = TakeClient(); |
| { |
| auto result = client->GetHandleUnion(2); |
| |
| ASSERT_TRUE(result.ok()) << result.error(); |
| |
| ASSERT_TRUE(result.value().value.is_h2()); |
| checker.AddEvent(result.value().value.h2().h); |
| } |
| |
| // After the destruction of the result, each handle in dupes should have only one link. |
| checker.CheckEvents(); |
| } |
| |
| TEST_F(HandleCloseTest, HandleUnionStruct1) { |
| llcpp_types_test_utils::HandleChecker checker; |
| auto client = TakeClient(); |
| { |
| auto result = client->GetHandleUnionStruct(1); |
| |
| ASSERT_TRUE(result.ok()) << result.error(); |
| |
| ASSERT_TRUE(result.value().value.u.is_h1()); |
| checker.AddEvent(result.value().value.u.h1()); |
| } |
| |
| // After the destruction of the result, each handle in dupes should have only one link. |
| checker.CheckEvents(); |
| } |
| |
| TEST_F(HandleCloseTest, HandleUnionStruct2) { |
| llcpp_types_test_utils::HandleChecker checker; |
| auto client = TakeClient(); |
| { |
| auto result = client->GetHandleUnionStruct(2); |
| |
| ASSERT_TRUE(result.ok()) << result.error(); |
| |
| ASSERT_TRUE(result.value().value.u.is_h2()); |
| checker.AddEvent(result.value().value.u.h2().h); |
| } |
| |
| // After the destruction of the result, each handle in dupes should have only one link. |
| checker.CheckEvents(); |
| } |
| |
| TEST_F(HandleCloseTest, HandleTableNone) { |
| // Only checks that the destructions won't crash. |
| auto client = TakeClient(); |
| { |
| auto result = client->GetHandleTable(0); |
| |
| ASSERT_TRUE(result.ok()) << result.error(); |
| } |
| } |
| |
| TEST_F(HandleCloseTest, HandleTableEvent) { |
| llcpp_types_test_utils::HandleChecker checker; |
| auto client = TakeClient(); |
| { |
| auto result = client->GetHandleTable(1); |
| |
| ASSERT_TRUE(result.ok()) << result.error(); |
| |
| checker.AddEvent(result.value().value.h1()); |
| } |
| |
| // After the destruction of the result, each handle in dupes should have only one link. |
| checker.CheckEvents(); |
| } |
| |
| TEST_F(HandleCloseTest, HandleTableHandleStruct) { |
| llcpp_types_test_utils::HandleChecker checker; |
| auto client = TakeClient(); |
| { |
| auto result = client->GetHandleTable(2); |
| |
| ASSERT_TRUE(result.ok()) << result.error(); |
| |
| checker.AddEvent(result.value().value.h2().h); |
| } |
| |
| // After the destruction of the result, each handle in dupes should have only one link. |
| checker.CheckEvents(); |
| } |
| |
| TEST_F(HandleCloseTest, HandleTableAll) { |
| llcpp_types_test_utils::HandleChecker checker; |
| auto client = TakeClient(); |
| { |
| auto result = client->GetHandleTable(3); |
| |
| ASSERT_TRUE(result.ok()) << result.error(); |
| |
| checker.AddEvent(result.value().value.h1()); |
| checker.AddEvent(result.value().value.h2().h); |
| } |
| |
| // After the destruction of the result, each handle in dupes should have only one link. |
| checker.CheckEvents(); |
| } |
| |
| TEST_F(HandleCloseTest, HandleTableStructNone) { |
| // Only checks that the destructions won't crash. |
| auto client = TakeClient(); |
| { |
| auto result = client->GetHandleTableStruct(0); |
| |
| ASSERT_TRUE(result.ok()) << result.error(); |
| } |
| } |
| |
| TEST_F(HandleCloseTest, HandleTableStructEvent) { |
| llcpp_types_test_utils::HandleChecker checker; |
| auto client = TakeClient(); |
| { |
| auto result = client->GetHandleTableStruct(1); |
| |
| ASSERT_TRUE(result.ok()) << result.error(); |
| |
| checker.AddEvent(result.value().value.t.h1()); |
| } |
| |
| // After the destruction of the result, each handle in dupes should have only one link. |
| checker.CheckEvents(); |
| } |
| |
| TEST_F(HandleCloseTest, HandleTableStructHandleStruct) { |
| llcpp_types_test_utils::HandleChecker checker; |
| auto client = TakeClient(); |
| { |
| auto result = client->GetHandleTableStruct(2); |
| |
| ASSERT_TRUE(result.ok()) << result.error(); |
| |
| checker.AddEvent(result.value().value.t.h2().h); |
| } |
| |
| // After the destruction of the result, each handle in dupes should have only one link. |
| checker.CheckEvents(); |
| } |
| |
| TEST_F(HandleCloseTest, HandleTableStructAll) { |
| llcpp_types_test_utils::HandleChecker checker; |
| auto client = TakeClient(); |
| { |
| auto result = client->GetHandleTableStruct(3); |
| |
| ASSERT_TRUE(result.ok()) << result.error(); |
| |
| checker.AddEvent(result.value().value.t.h1()); |
| checker.AddEvent(result.value().value.t.h2().h); |
| } |
| |
| // After the destruction of the result, each handle in dupes should have only one link. |
| checker.CheckEvents(); |
| } |
| |
| TEST_F(HandleCloseTest, OptionalHandleStructNotDefined) { |
| // Only checks that the destructions won't crash. |
| auto client = TakeClient(); |
| { |
| auto result = client->GetOptionalHandleStruct(false); |
| |
| ASSERT_TRUE(result.ok()) << result.error(); |
| } |
| } |
| |
| TEST_F(HandleCloseTest, OptionalHandleStructDefined) { |
| llcpp_types_test_utils::HandleChecker checker; |
| auto client = TakeClient(); |
| { |
| auto result = client->GetOptionalHandleStruct(true); |
| |
| ASSERT_TRUE(result.ok()) << result.error(); |
| |
| checker.AddEvent(result.value().value->h); |
| } |
| |
| // After the destruction of the result, each handle in dupes should have only one link. |
| checker.CheckEvents(); |
| } |
| |
| TEST_F(HandleCloseTest, OptionalHandleUnionNone) { |
| // Only checks that the destructions won't crash. |
| auto client = TakeClient(); |
| { |
| auto result = client->GetOptionalHandleUnion(0); |
| |
| ASSERT_TRUE(result.ok()) << result.error(); |
| } |
| } |
| |
| TEST_F(HandleCloseTest, OptionalHandleUnion1) { |
| llcpp_types_test_utils::HandleChecker checker; |
| auto client = TakeClient(); |
| { |
| auto result = client->GetOptionalHandleUnion(1); |
| |
| ASSERT_TRUE(result.ok()) << result.error(); |
| |
| ASSERT_TRUE(result.value().value.has_value()); |
| ASSERT_TRUE(result.value().value->is_h1()); |
| checker.AddEvent(result.value().value->h1()); |
| } |
| |
| // After the destruction of the result, each handle in dupes should have only one link. |
| checker.CheckEvents(); |
| } |
| |
| TEST_F(HandleCloseTest, OptionalHandleUnion2) { |
| llcpp_types_test_utils::HandleChecker checker; |
| auto client = TakeClient(); |
| { |
| auto result = client->GetOptionalHandleUnion(2); |
| |
| ASSERT_TRUE(result.ok()) << result.error(); |
| |
| ASSERT_TRUE(result.value().value.has_value()); |
| ASSERT_TRUE(result.value().value->is_h2()); |
| checker.AddEvent(result.value().value->h2().h); |
| } |
| |
| // After the destruction of the result, each handle in dupes should have only one link. |
| checker.CheckEvents(); |
| } |
| |
| TEST_F(HandleCloseTest, OptionalHandleUnionStructNotDefined) { |
| // Only checks that the destructions won't crash. |
| auto client = TakeClient(); |
| { |
| auto result = client->GetOptionalHandleUnionStruct(false, 0); |
| |
| ASSERT_TRUE(result.ok()) << result.error(); |
| } |
| } |
| |
| TEST_F(HandleCloseTest, OptionalHandleUnionStruct1) { |
| llcpp_types_test_utils::HandleChecker checker; |
| auto client = TakeClient(); |
| { |
| auto result = client->GetOptionalHandleUnionStruct(true, 1); |
| |
| ASSERT_TRUE(result.ok()) << result.error(); |
| |
| ASSERT_TRUE(result.value().value->u.is_h1()); |
| checker.AddEvent(result.value().value->u.h1()); |
| } |
| |
| // After the destruction of the result, each handle in dupes should have only one link. |
| checker.CheckEvents(); |
| } |
| |
| TEST_F(HandleCloseTest, OptionalHandleUnionStruct2) { |
| llcpp_types_test_utils::HandleChecker checker; |
| auto client = TakeClient(); |
| { |
| auto result = client->GetOptionalHandleUnionStruct(true, 2); |
| |
| ASSERT_TRUE(result.ok()) << result.error(); |
| |
| ASSERT_TRUE(result.value().value->u.is_h2()); |
| checker.AddEvent(result.value().value->u.h2().h); |
| } |
| |
| // After the destruction of the result, each handle in dupes should have only one link. |
| checker.CheckEvents(); |
| } |
| |
| TEST_F(HandleCloseTest, OptionalHandleTableStructNotDefined) { |
| // Only checks that the destructions won't crash. |
| auto client = TakeClient(); |
| { |
| auto result = client->GetOptionalHandleTableStruct(false, 0); |
| |
| ASSERT_TRUE(result.ok()) << result.error(); |
| } |
| } |
| |
| TEST_F(HandleCloseTest, OptionalHandleTableStructNone) { |
| // Only checks that the destructions won't crash. |
| auto client = TakeClient(); |
| { |
| auto result = client->GetOptionalHandleTableStruct(true, 0); |
| |
| ASSERT_TRUE(result.ok()) << result.error(); |
| } |
| } |
| |
| TEST_F(HandleCloseTest, OptionalHandleTableStructEvent) { |
| llcpp_types_test_utils::HandleChecker checker; |
| auto client = TakeClient(); |
| { |
| auto result = client->GetOptionalHandleTableStruct(true, 1); |
| |
| ASSERT_TRUE(result.ok()) << result.error(); |
| |
| checker.AddEvent(result.value().value->t.h1()); |
| } |
| |
| // After the destruction of the result, each handle in dupes should have only one link. |
| checker.CheckEvents(); |
| } |
| |
| TEST_F(HandleCloseTest, OptionalHandleTableStructHandleStruct) { |
| llcpp_types_test_utils::HandleChecker checker; |
| auto client = TakeClient(); |
| { |
| auto result = client->GetOptionalHandleTableStruct(true, 2); |
| |
| ASSERT_TRUE(result.ok()) << result.error(); |
| |
| checker.AddEvent(result.value().value->t.h2().h); |
| } |
| |
| // After the destruction of the result, each handle in dupes should have only one link. |
| checker.CheckEvents(); |
| } |
| |
| TEST_F(HandleCloseTest, OptionalHandleTableStructAll) { |
| llcpp_types_test_utils::HandleChecker checker; |
| auto client = TakeClient(); |
| { |
| auto result = client->GetOptionalHandleTableStruct(true, 3); |
| |
| ASSERT_TRUE(result.ok()) << result.error(); |
| |
| checker.AddEvent(result.value().value->t.h1()); |
| checker.AddEvent(result.value().value->t.h2().h); |
| } |
| |
| // After the destruction of the result, each handle in dupes should have only one link. |
| checker.CheckEvents(); |
| } |
| |
| TEST_F(HandleCloseTest, HandleStructOptionalStructNotDefined) { |
| // Only checks that the destructions won't crash. |
| auto client = TakeClient(); |
| { |
| auto result = client->GetHandleStructOptionalStruct(false); |
| |
| ASSERT_TRUE(result.ok()) << result.error(); |
| } |
| } |
| |
| TEST_F(HandleCloseTest, HandleStructOptionalStructDefined) { |
| llcpp_types_test_utils::HandleChecker checker; |
| auto client = TakeClient(); |
| { |
| auto result = client->GetHandleStructOptionalStruct(true); |
| |
| ASSERT_TRUE(result.ok()) << result.error(); |
| |
| checker.AddEvent(result.value().value.s->h); |
| } |
| |
| // After the destruction of the result, each handle in dupes should have only one link. |
| checker.CheckEvents(); |
| } |
| |
| TEST_F(HandleCloseTest, HandleUnionOptionalStructNotDefined) { |
| // Only checks that the destructions won't crash. |
| auto client = TakeClient(); |
| { |
| auto result = client->GetHandleUnionOptionalStruct(false, 0); |
| |
| ASSERT_TRUE(result.ok()) << result.error(); |
| } |
| } |
| |
| TEST_F(HandleCloseTest, HandleUnionOptionalStruct1) { |
| llcpp_types_test_utils::HandleChecker checker; |
| auto client = TakeClient(); |
| { |
| auto result = client->GetHandleUnionOptionalStruct(true, 1); |
| |
| ASSERT_TRUE(result.ok()) << result.error(); |
| |
| ASSERT_TRUE(result.value().value.u.has_value()); |
| ASSERT_TRUE(result.value().value.u->is_h1()); |
| checker.AddEvent(result.value().value.u->h1()); |
| } |
| |
| // After the destruction of the result, each handle in dupes should have only one link. |
| checker.CheckEvents(); |
| } |
| |
| TEST_F(HandleCloseTest, HandleUnionOptionalStruct2) { |
| llcpp_types_test_utils::HandleChecker checker; |
| auto client = TakeClient(); |
| { |
| auto result = client->GetHandleUnionOptionalStruct(true, 2); |
| |
| ASSERT_TRUE(result.ok()) << result.error(); |
| |
| ASSERT_TRUE(result.value().value.u.has_value()); |
| ASSERT_TRUE(result.value().value.u->is_h2()); |
| checker.AddEvent(result.value().value.u->h2().h); |
| } |
| |
| // After the destruction of the result, each handle in dupes should have only one link. |
| checker.CheckEvents(); |
| } |
| |
| TEST_F(HandleCloseTest, VectorOfHandle) { |
| constexpr size_t kNumHandle = 5; |
| llcpp_types_test_utils::HandleChecker checker; |
| auto client = TakeClient(); |
| { |
| auto result = client->GetVectorOfHandle(kNumHandle); |
| |
| ASSERT_TRUE(result.ok()) << result.error(); |
| |
| for (uint32_t i = 0; i < result.value().value.size(); ++i) { |
| checker.AddEvent(result.value().value[i]); |
| } |
| } |
| |
| ASSERT_EQ(checker.size(), kNumHandle); |
| // After the destruction of the result, each handle in dupes should have only one link. |
| checker.CheckEvents(); |
| } |
| |
| TEST_F(HandleCloseTest, VectorOfVectorOfHandle) { |
| constexpr size_t kNumVector = 4; |
| constexpr size_t kNumHandle = 5; |
| llcpp_types_test_utils::HandleChecker checker; |
| auto client = TakeClient(); |
| { |
| auto result = client->GetVectorOfVectorOfHandle(kNumVector, kNumHandle); |
| |
| ASSERT_TRUE(result.ok()) << result.error(); |
| |
| for (uint32_t i = 0; i < result.value().value.size(); ++i) { |
| for (uint32_t j = 0; j < result.value().value[i].size(); ++j) { |
| checker.AddEvent(result.value().value[i][j]); |
| } |
| } |
| } |
| |
| ASSERT_EQ(checker.size(), kNumVector * kNumHandle); |
| // After the destruction of the result, each handle in dupes should have only one link. |
| checker.CheckEvents(); |
| } |
| |
| TEST_F(HandleCloseTest, VectorOfVectorOfVectorOfHandle) { |
| constexpr size_t kNumVector1 = 3; |
| constexpr size_t kNumVector2 = 4; |
| constexpr size_t kNumHandle = 5; |
| llcpp_types_test_utils::HandleChecker checker; |
| auto client = TakeClient(); |
| { |
| auto result = client->GetVectorOfVectorOfVectorOfHandle(kNumVector1, kNumVector2, kNumHandle); |
| |
| ASSERT_TRUE(result.ok()) << result.error(); |
| |
| for (uint32_t i = 0; i < result.value().value.size(); ++i) { |
| for (uint32_t j = 0; j < result.value().value[i].size(); ++j) { |
| for (uint32_t k = 0; k < result.value().value[i][j].size(); ++k) { |
| checker.AddEvent(result.value().value[i][j][k]); |
| } |
| } |
| } |
| } |
| |
| ASSERT_EQ(checker.size(), kNumVector1 * kNumVector2 * kNumHandle); |
| // After the destruction of the result, each handle in dupes should have only one link. |
| checker.CheckEvents(); |
| } |
| |
| TEST_F(HandleCloseTest, VectorOfHandleStruct) { |
| constexpr size_t kNumHandle = 5; |
| llcpp_types_test_utils::HandleChecker checker; |
| auto client = TakeClient(); |
| { |
| auto result = client->GetVectorOfHandleStruct(kNumHandle); |
| |
| ASSERT_TRUE(result.ok()) << result.error(); |
| |
| for (uint32_t i = 0; i < result.value().value.size(); ++i) { |
| checker.AddEvent(result.value().value[i].h); |
| } |
| } |
| |
| ASSERT_EQ(checker.size(), kNumHandle); |
| // After the destruction of the result, each handle in dupes should have only one link. |
| checker.CheckEvents(); |
| } |
| |
| TEST_F(HandleCloseTest, VectorOfVectorOfHandleStruct) { |
| constexpr size_t kNumVector = 4; |
| constexpr size_t kNumHandle = 5; |
| llcpp_types_test_utils::HandleChecker checker; |
| auto client = TakeClient(); |
| { |
| auto result = client->GetVectorOfVectorOfHandleStruct(kNumVector, kNumHandle); |
| |
| ASSERT_TRUE(result.ok()) << result.error(); |
| |
| for (uint32_t i = 0; i < result.value().value.size(); ++i) { |
| for (uint32_t j = 0; j < result.value().value[i].size(); ++j) { |
| checker.AddEvent(result.value().value[i][j].h); |
| } |
| } |
| } |
| |
| ASSERT_EQ(checker.size(), kNumVector * kNumHandle); |
| // After the destruction of the result, each handle in dupes should have only one link. |
| checker.CheckEvents(); |
| } |
| |
| TEST_F(HandleCloseTest, VectorOfVectorOfVectorOfHandleStruct) { |
| constexpr size_t kNumVector1 = 3; |
| constexpr size_t kNumVector2 = 4; |
| constexpr size_t kNumHandle = 5; |
| llcpp_types_test_utils::HandleChecker checker; |
| auto client = TakeClient(); |
| { |
| auto result = |
| client->GetVectorOfVectorOfVectorOfHandleStruct(kNumVector1, kNumVector2, kNumHandle); |
| |
| ASSERT_TRUE(result.ok()) << result.error(); |
| |
| for (uint32_t i = 0; i < result.value().value.size(); ++i) { |
| for (uint32_t j = 0; j < result.value().value[i].size(); ++j) { |
| for (uint32_t k = 0; k < result.value().value[i][j].size(); ++k) { |
| checker.AddEvent(result.value().value[i][j][k].h); |
| } |
| } |
| } |
| } |
| |
| ASSERT_EQ(checker.size(), kNumVector1 * kNumVector2 * kNumHandle); |
| // After the destruction of the result, each handle in dupes should have only one link. |
| checker.CheckEvents(); |
| } |
| |
| TEST_F(HandleCloseTest, ArrayOfHandle) { |
| llcpp_types_test_utils::HandleChecker checker; |
| auto client = TakeClient(); |
| { |
| auto result = client->GetArrayOfHandle(); |
| |
| ASSERT_TRUE(result.ok()) << result.error(); |
| |
| for (auto& item : result.value().value) { |
| checker.AddEvent(item); |
| } |
| } |
| |
| // After the destruction of the result, each handle in dupes should have only one link. |
| checker.CheckEvents(); |
| } |
| |
| TEST_F(HandleCloseTest, ArrayOfArrayOfHandle) { |
| llcpp_types_test_utils::HandleChecker checker; |
| auto client = TakeClient(); |
| { |
| auto result = client->GetArrayOfArrayOfHandle(); |
| |
| ASSERT_TRUE(result.ok()) << result.error(); |
| |
| for (auto& item1 : result.value().value) { |
| for (const auto& item2 : item1) { |
| checker.AddEvent(item2); |
| } |
| } |
| } |
| |
| // After the destruction of the result, each handle in dupes should have only one link. |
| checker.CheckEvents(); |
| } |
| |
| TEST_F(HandleCloseTest, ArrayOfArrayOfArrayOfHandle) { |
| llcpp_types_test_utils::HandleChecker checker; |
| auto client = TakeClient(); |
| { |
| auto result = client->GetArrayOfArrayOfArrayOfHandle(); |
| |
| ASSERT_TRUE(result.ok()) << result.error(); |
| |
| for (auto& item1 : result.value().value) { |
| for (const auto& item2 : item1) { |
| for (const auto& item3 : item2) { |
| checker.AddEvent(item3); |
| } |
| } |
| } |
| } |
| |
| // After the destruction of the result, each handle in dupes should have only one link. |
| checker.CheckEvents(); |
| } |
| |
| TEST_F(HandleCloseTest, ArrayOfHandleStruct) { |
| llcpp_types_test_utils::HandleChecker checker; |
| auto client = TakeClient(); |
| { |
| auto result = client->GetArrayOfHandleStruct(); |
| |
| ASSERT_TRUE(result.ok()) << result.error(); |
| |
| for (auto& item : result.value().value) { |
| checker.AddEvent(item.h); |
| } |
| } |
| |
| // After the destruction of the result, each handle in dupes should have only one link. |
| checker.CheckEvents(); |
| } |
| |
| TEST_F(HandleCloseTest, ArrayOfArrayOfHandleStruct) { |
| llcpp_types_test_utils::HandleChecker checker; |
| auto client = TakeClient(); |
| { |
| auto result = client->GetArrayOfArrayOfHandleStruct(); |
| |
| ASSERT_TRUE(result.ok()) << result.error(); |
| |
| for (auto& item1 : result.value().value) { |
| for (const auto& item2 : item1) { |
| checker.AddEvent(item2.h); |
| } |
| } |
| } |
| |
| // After the destruction of the result, each handle in dupes should have only one link. |
| checker.CheckEvents(); |
| } |
| |
| TEST_F(HandleCloseTest, ArrayOfArrayOfArrayOfHandleStruct) { |
| llcpp_types_test_utils::HandleChecker checker; |
| auto client = TakeClient(); |
| { |
| auto result = client->GetArrayOfArrayOfArrayOfHandleStruct(); |
| |
| ASSERT_TRUE(result.ok()) << result.error(); |
| |
| for (auto& item1 : result.value().value) { |
| for (const auto& item2 : item1) { |
| for (const auto& item3 : item2) { |
| checker.AddEvent(item3.h); |
| } |
| } |
| } |
| } |
| |
| // After the destruction of the result, each handle in dupes should have only one link. |
| checker.CheckEvents(); |
| } |
| |
| TEST_F(HandleCloseTest, Mixed1) { |
| constexpr size_t kNumHandle = 5; |
| llcpp_types_test_utils::HandleChecker checker; |
| auto client = TakeClient(); |
| { |
| auto result = client->GetMixed1(kNumHandle); |
| |
| ASSERT_TRUE(result.ok()) << result.error(); |
| |
| for (auto& item1 : result.value().value) { |
| for (const auto& item2 : item1) { |
| checker.AddEvent(item2); |
| } |
| } |
| } |
| |
| ASSERT_EQ(checker.size(), kNumHandle * 2); |
| // After the destruction of the result, each handle in dupes should have only one link. |
| checker.CheckEvents(); |
| } |
| |
| TEST_F(HandleCloseTest, Mixed2) { |
| constexpr size_t kNumHandle = 5; |
| llcpp_types_test_utils::HandleChecker checker; |
| auto client = TakeClient(); |
| { |
| auto result = client->GetMixed2(kNumHandle); |
| |
| ASSERT_TRUE(result.ok()) << result.error(); |
| |
| for (auto& item1 : result.value().value) { |
| for (const auto& item2 : item1) { |
| checker.AddEvent(item2); |
| } |
| } |
| } |
| |
| ASSERT_EQ(checker.size(), kNumHandle * 2); |
| // After the destruction of the result, each handle in dupes should have only one link. |
| checker.CheckEvents(); |
| } |