| // Copyright 2021 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/fidl.cpp.wire.interop.test/cpp/fidl.h> |
| #include <lib/async-loop/cpp/loop.h> |
| #include <lib/fidl/cpp/client.h> |
| #include <lib/stdcompat/string_view.h> |
| #include <zircon/assert.h> |
| |
| #include <vector> |
| |
| #include <zxtest/zxtest.h> |
| |
| namespace { |
| |
| class WireTestBase : public fidl::WireServer<fidl_cpp_wire_interop_test::Interop> { |
| void RoundTrip(RoundTripRequestView request, RoundTripCompleter::Sync& completer) override { |
| ZX_PANIC("Unreachable"); |
| } |
| void TryRoundTrip(TryRoundTripRequestView request, |
| TryRoundTripCompleter::Sync& completer) override { |
| ZX_PANIC("Unreachable"); |
| } |
| void OneWay(OneWayRequestView request, OneWayCompleter::Sync& completer) override { |
| ZX_PANIC("Unreachable"); |
| } |
| }; |
| |
| class MockData { |
| public: |
| // Helpers to build mock domain objects and test that they are equal to expected. |
| static fidl_cpp_wire_interop_test::Node MakeNaturalFile(); |
| static fidl_cpp_wire_interop_test::wire::Node MakeWireFile(fidl::AnyArena& arena); |
| static void CheckNaturalFile(const fidl_cpp_wire_interop_test::Node& node); |
| static void CheckWireFile(const fidl_cpp_wire_interop_test::wire::Node& node); |
| |
| static fidl_cpp_wire_interop_test::Node MakeNaturalDir(); |
| static fidl_cpp_wire_interop_test::wire::Node MakeWireDir(fidl::AnyArena& arena); |
| static void CheckNaturalDir(const fidl_cpp_wire_interop_test::Node& node); |
| static void CheckWireDir(const fidl_cpp_wire_interop_test::wire::Node& node); |
| |
| private: |
| const static char kFileName[9]; |
| static std::vector<uint8_t> kFileContent; |
| static const char kDirName[8]; |
| }; |
| |
| const char MockData::kFileName[9] = "foo file"; |
| std::vector<uint8_t> MockData::kFileContent = {1, 2, 3}; |
| const char MockData::kDirName[8] = "bar dir"; |
| |
| fidl_cpp_wire_interop_test::Node MockData::MakeNaturalFile() { |
| fidl_cpp_wire_interop_test::Node node; |
| node.name() = kFileName; |
| node.kind() = fidl_cpp_wire_interop_test::Kind::WithFile({{.content = kFileContent}}); |
| return node; |
| } |
| |
| fidl_cpp_wire_interop_test::wire::Node MockData::MakeWireFile(fidl::AnyArena& arena) { |
| auto kind = fidl_cpp_wire_interop_test::wire::Kind::WithFile(arena); |
| kind.file().content = fidl::VectorView<uint8_t>::FromExternal(kFileContent); |
| |
| return fidl_cpp_wire_interop_test::wire::Node::Builder(arena).name(kFileName).kind(kind).Build(); |
| } |
| |
| void MockData::CheckNaturalFile(const fidl_cpp_wire_interop_test::Node& node) { |
| ASSERT_TRUE(node.name().has_value()); |
| EXPECT_EQ(kFileName, node.name()); |
| ASSERT_TRUE(node.kind().has_value()); |
| EXPECT_EQ(fidl_cpp_wire_interop_test::Kind::Tag::kFile, node.kind()->Which()); |
| EXPECT_EQ(kFileContent, node.kind()->file()->content()); |
| } |
| |
| void MockData::CheckWireFile(const fidl_cpp_wire_interop_test::wire::Node& node) { |
| ASSERT_TRUE(node.has_name()); |
| EXPECT_EQ(fidl::StringView{kFileName}.get(), node.name().get()); |
| ASSERT_TRUE(node.has_kind()); |
| EXPECT_EQ(fidl_cpp_wire_interop_test::wire::Kind::Tag::kFile, node.kind().Which()); |
| std::vector<uint8_t> content(node.kind().file().content.begin(), |
| node.kind().file().content.end()); |
| EXPECT_EQ(kFileContent, content); |
| } |
| |
| fidl_cpp_wire_interop_test::Node MockData::MakeNaturalDir() { |
| fidl_cpp_wire_interop_test::Node node; |
| node.name() = kDirName; |
| |
| fidl_cpp_wire_interop_test::Node child = MakeNaturalFile(); |
| fidl_cpp_wire_interop_test::Directory directory; |
| directory.children() = std::make_unique<fidl_cpp_wire_interop_test::Children>(); |
| directory.children()->elements().emplace_back(std::move(child)); |
| node.kind() = fidl_cpp_wire_interop_test::Kind::WithDirectory(std::move(directory)); |
| return node; |
| } |
| |
| fidl_cpp_wire_interop_test::wire::Node MockData::MakeWireDir(fidl::AnyArena& arena) { |
| auto node = fidl_cpp_wire_interop_test::wire::Node::Builder(arena) |
| .name(kDirName) |
| .kind(fidl_cpp_wire_interop_test::wire::Kind::WithDirectory(arena)) |
| .Build(); |
| |
| fidl::ObjectView<fidl_cpp_wire_interop_test::wire::Children>& children = |
| node.kind().directory().children; |
| children.Allocate(arena); |
| children->elements.Allocate(arena, 1); |
| children->elements[0] = MakeWireFile(arena); |
| return node; |
| } |
| |
| void MockData::CheckNaturalDir(const fidl_cpp_wire_interop_test::Node& node) { |
| ASSERT_TRUE(node.name().has_value()); |
| EXPECT_EQ(kDirName, node.name()); |
| ASSERT_TRUE(node.kind().has_value()); |
| ASSERT_EQ(fidl_cpp_wire_interop_test::Kind::Tag::kDirectory, node.kind()->Which()); |
| |
| const fidl_cpp_wire_interop_test::Directory& dir = node.kind()->directory().value(); |
| EXPECT_EQ(1, dir.children()->elements().size()); |
| const fidl_cpp_wire_interop_test::Node& child = dir.children()->elements()[0]; |
| CheckNaturalFile(child); |
| } |
| |
| void MockData::CheckWireDir(const fidl_cpp_wire_interop_test::wire::Node& node) { |
| EXPECT_TRUE(node.has_name()); |
| EXPECT_EQ(fidl::StringView{kDirName}.get(), node.name().get()); |
| EXPECT_TRUE(node.has_kind()); |
| EXPECT_EQ(fidl_cpp_wire_interop_test::wire::Kind::Tag::kDirectory, node.kind().Which()); |
| const fidl_cpp_wire_interop_test::wire::Directory& dir = node.kind().directory(); |
| EXPECT_EQ(1, dir.children->elements.count()); |
| const fidl_cpp_wire_interop_test::wire::Node& child = dir.children->elements[0]; |
| CheckWireFile(child); |
| } |
| |
| // Test fixture to simplify creating endpoints and a unified client to talk to |
| // a wire domain object server. |
| class UnifiedClientToWireServerBase : public zxtest::Test, public MockData { |
| public: |
| UnifiedClientToWireServerBase() : loop_(&kAsyncLoopConfigNeverAttachToThread) {} |
| |
| void SetUp() final { |
| zx::status client_end = |
| fidl::CreateEndpoints<fidl_cpp_wire_interop_test::Interop>(&server_end_); |
| ASSERT_OK(client_end.status_value()); |
| client_.Bind(std::move(*client_end), loop_.dispatcher(), GetEventHandler()); |
| } |
| |
| virtual fidl::AsyncEventHandler<fidl_cpp_wire_interop_test::Interop>* GetEventHandler() = 0; |
| |
| async::Loop& loop() { return loop_; } |
| fidl::ServerEnd<fidl_cpp_wire_interop_test::Interop>& server_end() { return server_end_; } |
| fidl::Client<fidl_cpp_wire_interop_test::Interop>& client() { return client_; } |
| |
| private: |
| async::Loop loop_; |
| fidl::ServerEnd<fidl_cpp_wire_interop_test::Interop> server_end_; |
| fidl::Client<fidl_cpp_wire_interop_test::Interop> client_; |
| }; |
| |
| // Test fixture that does not care about events (besides the fact that there |
| // should not be any errors). |
| class UnifiedClientToWireServer : public UnifiedClientToWireServerBase { |
| private: |
| fidl::AsyncEventHandler<fidl_cpp_wire_interop_test::Interop>* GetEventHandler() final { |
| return &event_handler_; |
| } |
| |
| class FailOnClientError : public fidl::AsyncEventHandler<fidl_cpp_wire_interop_test::Interop> { |
| // We should not observe any terminal error from the client during these tests. |
| void on_fidl_error(fidl::UnbindInfo info) final { |
| ADD_FATAL_FAILURE("Detected client error during test: %s", info.FormatDescription().c_str()); |
| } |
| }; |
| |
| FailOnClientError event_handler_; |
| }; |
| |
| // Test round-tripping a file node. |
| TEST_F(UnifiedClientToWireServer, RoundTrip) { |
| class Server : public WireTestBase { |
| public: |
| void RoundTrip(RoundTripRequestView request, RoundTripCompleter::Sync& completer) final { |
| CheckWireFile(request->node); |
| num_calls++; |
| completer.Reply(request->node); |
| } |
| |
| int num_calls = 0; |
| }; |
| Server server; |
| fidl::BindServer(loop().dispatcher(), std::move(server_end()), &server); |
| |
| { |
| // Test with natural domain objects. |
| auto node = MakeNaturalFile(); |
| fidl_cpp_wire_interop_test::InteropRoundTripRequest request{std::move(node)}; |
| bool got_response = false; |
| client() |
| ->RoundTrip(std::move(request)) |
| .ThenExactlyOnce([&](fidl::Result<fidl_cpp_wire_interop_test::Interop::RoundTrip>& result) { |
| ASSERT_TRUE(result.is_ok()); |
| CheckNaturalFile(result->node()); |
| got_response = true; |
| }); |
| ASSERT_OK(loop().RunUntilIdle()); |
| EXPECT_EQ(1, server.num_calls); |
| EXPECT_TRUE(got_response); |
| } |
| |
| { |
| // Test with wire domain objects. |
| fidl::Arena arena; |
| auto node = MakeWireFile(arena); |
| bool got_response = false; |
| client().wire()->RoundTrip(node).ThenExactlyOnce( |
| [&](fidl::WireUnownedResult<fidl_cpp_wire_interop_test::Interop::RoundTrip>& result) { |
| if (!result.ok()) { |
| FAIL("RoundTrip failed: %s", result.error().FormatDescription().c_str()); |
| return; |
| } |
| auto* response = result.Unwrap(); |
| CheckWireFile(response->node); |
| got_response = true; |
| }); |
| ASSERT_OK(loop().RunUntilIdle()); |
| EXPECT_EQ(2, server.num_calls); |
| EXPECT_TRUE(got_response); |
| } |
| } |
| |
| // Test round-tripping a directory node with error syntax. |
| TEST_F(UnifiedClientToWireServer, TryRoundTrip) { |
| class Server : public WireTestBase { |
| public: |
| void TryRoundTrip(TryRoundTripRequestView request, |
| TryRoundTripCompleter::Sync& completer) final { |
| CheckWireDir(request->node); |
| num_calls++; |
| if (reply_with_error) { |
| completer.ReplyError(ZX_ERR_INVALID_ARGS); |
| } else { |
| completer.ReplySuccess(request->node); |
| } |
| } |
| |
| bool reply_with_error = false; |
| int num_calls = 0; |
| }; |
| Server server; |
| fidl::BindServer(loop().dispatcher(), std::move(server_end()), &server); |
| |
| { |
| // Test with natural domain objects, success case. |
| auto node = MakeNaturalDir(); |
| fidl_cpp_wire_interop_test::InteropTryRoundTripRequest request{std::move(node)}; |
| bool got_response = false; |
| client() |
| ->TryRoundTrip(std::move(request)) |
| .ThenExactlyOnce( |
| [&](fidl::Result<fidl_cpp_wire_interop_test::Interop::TryRoundTrip>& result) { |
| ASSERT_TRUE(result.is_ok()); |
| fidl_cpp_wire_interop_test::InteropTryRoundTripResponse payload = |
| std::move(result.value()); |
| fidl_cpp_wire_interop_test::Node node = payload.node(); |
| CheckNaturalDir(node); |
| got_response = true; |
| }); |
| ASSERT_OK(loop().RunUntilIdle()); |
| EXPECT_EQ(1, server.num_calls); |
| EXPECT_TRUE(got_response); |
| } |
| |
| { |
| // Test with wire domain objects, success case. |
| fidl::Arena arena; |
| auto node = MakeWireDir(arena); |
| bool got_response = false; |
| client().wire()->TryRoundTrip(node).ThenExactlyOnce( |
| [&](fidl::WireUnownedResult<fidl_cpp_wire_interop_test::Interop::TryRoundTrip>& result) { |
| if (!result.ok()) { |
| FAIL("TryRoundTrip failed: %s", result.error().FormatDescription().c_str()); |
| return; |
| } |
| auto* response = result.Unwrap(); |
| ASSERT_TRUE(response->result.is_response()); |
| CheckWireDir(response->result.response().node); |
| got_response = true; |
| }); |
| ASSERT_OK(loop().RunUntilIdle()); |
| EXPECT_EQ(2, server.num_calls); |
| EXPECT_TRUE(got_response); |
| } |
| |
| server.reply_with_error = true; |
| |
| { |
| // Test with natural domain objects, error case. |
| auto node = MakeNaturalDir(); |
| fidl_cpp_wire_interop_test::InteropTryRoundTripRequest request{std::move(node)}; |
| bool got_response = false; |
| client() |
| ->TryRoundTrip(std::move(request)) |
| .ThenExactlyOnce( |
| [&](fidl::Result<fidl_cpp_wire_interop_test::Interop::TryRoundTrip>& result) { |
| ASSERT_FALSE(result.is_ok()); |
| ASSERT_TRUE(result.is_error()); |
| fidl::AnyErrorIn<fidl_cpp_wire_interop_test::Interop::TryRoundTrip> error = |
| result.error_value(); |
| ASSERT_TRUE(error.is_application_error()); |
| EXPECT_STATUS(ZX_ERR_INVALID_ARGS, error.application_error()); |
| got_response = true; |
| }); |
| ASSERT_OK(loop().RunUntilIdle()); |
| EXPECT_EQ(3, server.num_calls); |
| EXPECT_TRUE(got_response); |
| } |
| |
| { |
| // Test with wire domain objects, error case. |
| fidl::Arena arena; |
| auto node = MakeWireDir(arena); |
| bool got_response = false; |
| client().wire()->TryRoundTrip(node).ThenExactlyOnce( |
| [&](fidl::WireUnownedResult<fidl_cpp_wire_interop_test::Interop::TryRoundTrip>& result) { |
| if (!result.ok()) { |
| FAIL("TryRoundTrip failed: %s", result.error().FormatDescription().c_str()); |
| return; |
| } |
| auto* response = result.Unwrap(); |
| ASSERT_TRUE(response->result.is_err()); |
| EXPECT_STATUS(ZX_ERR_INVALID_ARGS, response->result.err()); |
| got_response = true; |
| }); |
| ASSERT_OK(loop().RunUntilIdle()); |
| EXPECT_EQ(4, server.num_calls); |
| EXPECT_TRUE(got_response); |
| } |
| } |
| |
| // Test sending a one way call. |
| TEST_F(UnifiedClientToWireServer, OneWay) { |
| class Server : public WireTestBase { |
| public: |
| void OneWay(OneWayRequestView request, OneWayCompleter::Sync& completer) override { |
| CheckWireFile(request->node); |
| num_calls++; |
| } |
| |
| int num_calls = 0; |
| }; |
| Server server; |
| fidl::BindServer(loop().dispatcher(), std::move(server_end()), &server); |
| { |
| // Test with natural domain objects. |
| fitx::result<fidl::Error> result = client()->OneWay({MakeNaturalFile()}); |
| ASSERT_TRUE(result.is_ok()); |
| ASSERT_OK(loop().RunUntilIdle()); |
| EXPECT_EQ(1, server.num_calls); |
| } |
| { |
| // Test with wire domain objects. |
| fidl::Arena arena; |
| fidl::Status status = client().wire()->OneWay(MakeWireFile(arena)); |
| ASSERT_TRUE(status.ok()); |
| ASSERT_OK(loop().RunUntilIdle()); |
| EXPECT_EQ(2, server.num_calls); |
| } |
| } |
| |
| // Test fixture that checks events. |
| class UnifiedClientToWireServerWithEventHandler : public UnifiedClientToWireServerBase { |
| public: |
| int num_events() const { return event_handler_.num_events(); } |
| |
| private: |
| class ExpectOnNodeEvent : public fidl::AsyncEventHandler<fidl_cpp_wire_interop_test::Interop> { |
| public: |
| int num_events() const { return num_events_; } |
| |
| private: |
| // We should not observe any terminal error from the client during these tests. |
| void on_fidl_error(fidl::UnbindInfo info) final { |
| ADD_FATAL_FAILURE("Detected client error during test: %s", info.FormatDescription().c_str()); |
| } |
| |
| void OnNode(fidl::Event<fidl_cpp_wire_interop_test::Interop::OnNode>& event) final { |
| CheckNaturalDir(event.node()); |
| num_events_++; |
| } |
| |
| int num_events_ = 0; |
| }; |
| |
| fidl::AsyncEventHandler<fidl_cpp_wire_interop_test::Interop>* GetEventHandler() final { |
| return &event_handler_; |
| } |
| |
| ExpectOnNodeEvent event_handler_; |
| }; |
| |
| TEST_F(UnifiedClientToWireServerWithEventHandler, OnNode) { |
| class Server : public WireTestBase {}; |
| Server server; |
| auto binding = fidl::BindServer(loop().dispatcher(), std::move(server_end()), &server); |
| |
| EXPECT_EQ(0, num_events()); |
| |
| // Send an event. |
| fidl::Arena arena; |
| auto node = MakeWireDir(arena); |
| fidl::Status status = fidl::WireSendEvent(binding)->OnNode(node); |
| ASSERT_OK(status.status()); |
| |
| // Test receiving natural domain objects. |
| ASSERT_OK(loop().RunUntilIdle()); |
| EXPECT_EQ(1, num_events()); |
| } |
| |
| class NaturalTestBase : public fidl::Server<fidl_cpp_wire_interop_test::Interop> { |
| void RoundTrip(RoundTripRequest& request, RoundTripCompleter::Sync& completer) override { |
| ZX_PANIC("Unreachable"); |
| } |
| void TryRoundTrip(TryRoundTripRequest& request, TryRoundTripCompleter::Sync& completer) override { |
| ZX_PANIC("Unreachable"); |
| } |
| void OneWay(OneWayRequest& request, OneWayCompleter::Sync& completer) override { |
| ZX_PANIC("Unreachable"); |
| } |
| }; |
| |
| // Test fixture to simplify creating endpoints and a wire client to talk to |
| // a natural server. |
| class WireClientToNaturalServerBase : public zxtest::Test, public MockData { |
| public: |
| WireClientToNaturalServerBase() : loop_(&kAsyncLoopConfigNeverAttachToThread) {} |
| |
| void SetUp() final { |
| zx::status client_end = |
| fidl::CreateEndpoints<fidl_cpp_wire_interop_test::Interop>(&server_end_); |
| ASSERT_OK(client_end.status_value()); |
| client_.Bind(std::move(*client_end), loop_.dispatcher(), GetEventHandler()); |
| } |
| |
| template <typename ServerImpl> |
| static auto CheckErrorsWhenUnbound() { |
| return [](ServerImpl* impl, fidl::UnbindInfo info, |
| fidl::ServerEnd<fidl_cpp_wire_interop_test::Interop> server_end) { |
| if (info.is_user_initiated()) |
| return; |
| if (info.is_dispatcher_shutdown()) |
| return; |
| if (info.is_peer_closed()) |
| return; |
| |
| ADD_FATAL_FAILURE("Detected server error during test: %s", info.FormatDescription().c_str()); |
| }; |
| } |
| |
| virtual fidl::WireAsyncEventHandler<fidl_cpp_wire_interop_test::Interop>* GetEventHandler() = 0; |
| |
| async::Loop& loop() { return loop_; } |
| fidl::ServerEnd<fidl_cpp_wire_interop_test::Interop>& server_end() { return server_end_; } |
| fidl::WireClient<fidl_cpp_wire_interop_test::Interop>& client() { return client_; } |
| |
| private: |
| async::Loop loop_; |
| fidl::ServerEnd<fidl_cpp_wire_interop_test::Interop> server_end_; |
| fidl::WireClient<fidl_cpp_wire_interop_test::Interop> client_; |
| }; |
| |
| // Test fixture that does not care about events (besides the fact that there |
| // should not be any errors). |
| class WireClientToNaturalServer : public WireClientToNaturalServerBase { |
| private: |
| fidl::WireAsyncEventHandler<fidl_cpp_wire_interop_test::Interop>* GetEventHandler() final { |
| return &event_handler_; |
| } |
| |
| class FailOnClientError |
| : public fidl::WireAsyncEventHandler<fidl_cpp_wire_interop_test::Interop> { |
| // We should not observe any terminal error from the client during these tests. |
| void on_fidl_error(fidl::UnbindInfo info) final { |
| ADD_FATAL_FAILURE("Detected client error during test: %s", info.FormatDescription().c_str()); |
| } |
| }; |
| |
| FailOnClientError event_handler_; |
| }; |
| |
| // Test round-tripping a file node. |
| TEST_F(WireClientToNaturalServer, RoundTrip) { |
| class Server : public NaturalTestBase { |
| public: |
| void RoundTrip(RoundTripRequest& request, RoundTripCompleter::Sync& completer) final { |
| CheckNaturalFile(request.node()); |
| num_calls++; |
| completer.Reply(std::move(request.node())); |
| } |
| |
| int num_calls = 0; |
| }; |
| Server server; |
| fidl::BindServer(loop().dispatcher(), std::move(server_end()), &server, |
| CheckErrorsWhenUnbound<Server>()); |
| |
| fidl::Arena arena; |
| auto node = MakeWireFile(arena); |
| bool got_response = false; |
| client()->RoundTrip(node).ThenExactlyOnce( |
| [&](fidl::WireUnownedResult<fidl_cpp_wire_interop_test::Interop::RoundTrip>& result) { |
| if (!result.ok()) { |
| FAIL("RoundTrip failed: %s", result.error().FormatDescription().c_str()); |
| return; |
| } |
| auto* response = result.Unwrap(); |
| CheckWireFile(response->node); |
| got_response = true; |
| }); |
| ASSERT_OK(loop().RunUntilIdle()); |
| EXPECT_EQ(1, server.num_calls); |
| EXPECT_TRUE(got_response); |
| } |
| |
| // Test round-tripping a directory node with error syntax. |
| TEST_F(WireClientToNaturalServer, TryRoundTrip) { |
| class Server : public NaturalTestBase { |
| public: |
| void TryRoundTrip(TryRoundTripRequest& request, TryRoundTripCompleter::Sync& completer) final { |
| CheckNaturalDir(request.node()); |
| num_calls++; |
| // TODO(fxbug.dev/91363): ReplySuccess/ReplyError. |
| if (reply_with_error) { |
| completer.Reply(fitx::error(ZX_ERR_INVALID_ARGS)); |
| } else { |
| completer.Reply(fitx::ok(std::move(request.node()))); |
| } |
| } |
| |
| bool reply_with_error = false; |
| int num_calls = 0; |
| }; |
| Server server; |
| fidl::BindServer(loop().dispatcher(), std::move(server_end()), &server, |
| CheckErrorsWhenUnbound<Server>()); |
| |
| { |
| // Test success case. |
| fidl::Arena arena; |
| auto node = MakeWireDir(arena); |
| bool got_response = false; |
| client()->TryRoundTrip(node).ThenExactlyOnce( |
| [&](fidl::WireUnownedResult<fidl_cpp_wire_interop_test::Interop::TryRoundTrip>& result) { |
| if (!result.ok()) { |
| FAIL("TryRoundTrip failed: %s", result.error().FormatDescription().c_str()); |
| return; |
| } |
| auto* response = result.Unwrap(); |
| ASSERT_TRUE(response->result.is_response()); |
| CheckWireDir(response->result.response().node); |
| got_response = true; |
| }); |
| ASSERT_OK(loop().RunUntilIdle()); |
| EXPECT_EQ(1, server.num_calls); |
| EXPECT_TRUE(got_response); |
| } |
| |
| server.reply_with_error = true; |
| |
| { |
| // Test error case. |
| fidl::Arena arena; |
| auto node = MakeWireDir(arena); |
| bool got_response = false; |
| client()->TryRoundTrip(node).ThenExactlyOnce( |
| [&](fidl::WireUnownedResult<fidl_cpp_wire_interop_test::Interop::TryRoundTrip>& result) { |
| if (!result.ok()) { |
| FAIL("TryRoundTrip failed: %s", result.error().FormatDescription().c_str()); |
| return; |
| } |
| auto* response = result.Unwrap(); |
| ASSERT_TRUE(response->result.is_err()); |
| EXPECT_STATUS(ZX_ERR_INVALID_ARGS, response->result.err()); |
| got_response = true; |
| }); |
| ASSERT_OK(loop().RunUntilIdle()); |
| EXPECT_EQ(2, server.num_calls); |
| EXPECT_TRUE(got_response); |
| } |
| } |
| |
| // Test receiving a one way call. |
| TEST_F(WireClientToNaturalServer, OneWay) { |
| class Server : public NaturalTestBase { |
| public: |
| void OneWay(OneWayRequest& request, OneWayCompleter::Sync& completer) override { |
| CheckNaturalFile(request.node()); |
| num_calls++; |
| } |
| |
| int num_calls = 0; |
| }; |
| Server server; |
| fidl::BindServer(loop().dispatcher(), std::move(server_end()), &server, |
| CheckErrorsWhenUnbound<Server>()); |
| |
| fidl::Arena arena; |
| fidl::Status status = client()->OneWay(MakeWireFile(arena)); |
| ASSERT_TRUE(status.ok()); |
| ASSERT_OK(loop().RunUntilIdle()); |
| EXPECT_EQ(1, server.num_calls); |
| } |
| |
| // Test fixture that checks events. |
| class WireClientToNaturalServerWithEventHandler : public WireClientToNaturalServerBase { |
| public: |
| int num_events() const { return event_handler_.num_events(); } |
| |
| private: |
| class ExpectOnNodeEvent |
| : public fidl::WireAsyncEventHandler<fidl_cpp_wire_interop_test::Interop> { |
| public: |
| int num_events() const { return num_events_; } |
| |
| private: |
| // We should not observe any terminal error from the client during these tests. |
| void on_fidl_error(fidl::UnbindInfo info) final { |
| ADD_FATAL_FAILURE("Detected client error during test: %s", info.FormatDescription().c_str()); |
| } |
| |
| void OnNode(fidl::WireEvent<fidl_cpp_wire_interop_test::Interop::OnNode>* event) final { |
| CheckWireDir(event->node); |
| num_events_++; |
| } |
| |
| int num_events_ = 0; |
| }; |
| |
| fidl::WireAsyncEventHandler<fidl_cpp_wire_interop_test::Interop>* GetEventHandler() final { |
| return &event_handler_; |
| } |
| |
| ExpectOnNodeEvent event_handler_; |
| }; |
| |
| // Test sending an event over a |fidl::ServerEnd|. |
| TEST_F(WireClientToNaturalServerWithEventHandler, SendOnNodeEventOverServerEnd) { |
| EXPECT_EQ(0, num_events()); |
| |
| // Test sending the event with natural types. |
| { |
| fidl_cpp_wire_interop_test::Node node = MakeNaturalDir(); |
| fitx::result result = fidl::SendEvent(server_end())->OnNode(node); |
| EXPECT_TRUE(result.is_ok(), "%s", result.error_value().FormatDescription().c_str()); |
| EXPECT_OK(loop().RunUntilIdle()); |
| EXPECT_EQ(1, num_events()); |
| } |
| |
| // Test sending the event with wire types. |
| { |
| fidl::Arena arena; |
| fidl_cpp_wire_interop_test::wire::Node node = MakeWireDir(arena); |
| fidl::Status status = fidl::WireSendEvent(server_end())->OnNode(node); |
| EXPECT_OK(status.status()); |
| EXPECT_OK(loop().RunUntilIdle()); |
| EXPECT_EQ(2, num_events()); |
| } |
| } |
| |
| // Test sending an event over a |fidl::ServerBindingRef|. |
| TEST_F(WireClientToNaturalServerWithEventHandler, SendOnNodeEventOverServerBindingRef) { |
| EXPECT_EQ(0, num_events()); |
| |
| class Server : public NaturalTestBase {}; |
| Server server; |
| fidl::ServerBindingRef binding_ref = |
| fidl::BindServer(loop().dispatcher(), std::move(server_end()), &server); |
| |
| // Test sending the event with natural types. |
| { |
| fidl_cpp_wire_interop_test::Node node = MakeNaturalDir(); |
| fitx::result result = fidl::SendEvent(binding_ref)->OnNode(node); |
| EXPECT_TRUE(result.is_ok(), "%s", result.error_value().FormatDescription().c_str()); |
| EXPECT_OK(loop().RunUntilIdle()); |
| EXPECT_EQ(1, num_events()); |
| } |
| |
| // Test sending the event with wire types. |
| { |
| fidl::Arena arena; |
| fidl_cpp_wire_interop_test::wire::Node node = MakeWireDir(arena); |
| fidl::Status status = fidl::WireSendEvent(binding_ref)->OnNode(node); |
| EXPECT_OK(status.status()); |
| EXPECT_OK(loop().RunUntilIdle()); |
| EXPECT_EQ(2, num_events()); |
| } |
| } |
| |
| } // namespace |