blob: 1314aeca991320a9b4d9ae26acc98b9c1160f11d [file] [log] [blame]
// Copyright 2019 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 <lib/async-loop/cpp/loop.h>
#include <lib/async-loop/default.h>
#include <lib/fidl/llcpp/server.h>
#include <lib/fidl/llcpp/server_end.h>
#include <lib/zx/object.h>
#include <zircon/errors.h>
#include <zircon/status.h>
#include <zircon/syscalls/object.h>
#include <gtest/gtest.h>
#include <llcpptest/protocol/test/llcpp/fidl.h>
namespace llcpp_test = ::llcpp::llcpptest::protocol::test;
TEST(ServerEnd, Trivial) {
fidl::ServerEnd<llcpp_test::Frobinator> server_end;
EXPECT_FALSE(server_end.is_valid());
}
TEST(ServerEnd, Control) {
zx::channel h1, h2;
ASSERT_EQ(ZX_OK, zx::channel::create(0, &h1, &h2));
zx_handle_t saved1 = h1.get();
// Test initializing with channel.
fidl::ServerEnd<llcpp_test::Frobinator> server_end(std::move(h1));
EXPECT_TRUE(server_end.is_valid());
EXPECT_EQ(saved1, server_end.channel().get());
// Test move semantics.
fidl::ServerEnd<llcpp_test::Frobinator> server_end_2 = std::move(server_end);
EXPECT_FALSE(server_end.is_valid());
EXPECT_TRUE(server_end_2.is_valid());
EXPECT_EQ(saved1, server_end_2.channel().get());
h1 = server_end_2.TakeChannel();
EXPECT_EQ(saved1, h1.get());
EXPECT_FALSE(server_end_2.is_valid());
zx_handle_t saved2 = h2.get();
server_end.set_channel(std::move(h2));
EXPECT_TRUE(server_end.is_valid());
EXPECT_EQ(saved2, server_end.channel().get());
// Test RAII channel management.
server_end = {};
EXPECT_FALSE(server_end.is_valid());
EXPECT_EQ(ZX_ERR_PEER_CLOSED, h1.write(0, "a", 1, nullptr, 0));
}
TEST(ServerEnd, Close) {
async::Loop loop(&kAsyncLoopConfigNoAttachToCurrentThread);
zx::channel h1, h2;
ASSERT_EQ(ZX_OK, zx::channel::create(0, &h1, &h2));
fidl::UnbindInfo recorded_unbind_info;
fidl::Client<llcpp_test::Frobinator> client(
std::move(h1), loop.dispatcher(), [&recorded_unbind_info](fidl::UnbindInfo unbind_info) {
recorded_unbind_info = unbind_info;
});
fidl::ServerEnd<llcpp_test::Frobinator> server_end(std::move(h2));
EXPECT_TRUE(server_end.is_valid());
constexpr zx_status_t kSysError = ZX_ERR_INVALID_ARGS;
EXPECT_EQ(ZX_OK, server_end.Close(kSysError));
EXPECT_FALSE(server_end.is_valid());
loop.RunUntilIdle();
EXPECT_EQ(fidl::UnbindInfo::Reason::kPeerClosed, recorded_unbind_info.reason);
EXPECT_EQ(kSysError, recorded_unbind_info.status);
}
TEST(ServerEnd, CloseTwice) {
zx::channel h1, h2;
ASSERT_EQ(ZX_OK, zx::channel::create(0, &h1, &h2));
fidl::ServerEnd<llcpp_test::Frobinator> server_end(std::move(h2));
EXPECT_EQ(ZX_OK, server_end.Close(ZX_OK));
ASSERT_DEATH(server_end.Close(ZX_OK), "Cannot close an invalid ServerEnd.");
}