blob: d71b92cb353035d846946a8ac7a9574a7350fee3 [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-async/cpp/bind.h>
#include <lib/sync/completion.h>
#include <zxtest/zxtest.h>
#include "generated/fidl_llcpp_simple.test.h"
namespace {
class Server : public ::llcpp::fidl::test::simple::Simple::Interface {
public:
explicit Server(sync_completion_t* destroyed) : destroyed_(destroyed) {}
Server(Server&& other) = delete;
Server(const Server& other) = delete;
Server& operator=(Server&& other) = delete;
Server& operator=(const Server& other) = delete;
~Server() override { sync_completion_signal(destroyed_); }
void Echo(int32_t request, EchoCompleter::Sync completer) override { completer.Reply(request); }
void Close(CloseCompleter::Sync completer) override { completer.Close(ZX_OK); }
private:
sync_completion_t* destroyed_;
};
TEST(BindTestCase, UniquePtrDestroyOnClientClose) {
sync_completion_t destroyed;
auto server = std::make_unique<Server>(&destroyed);
async::Loop loop(&kAsyncLoopConfigNoAttachToCurrentThread);
zx::channel local, remote;
ASSERT_OK(zx::channel::create(0, &local, &remote));
ASSERT_OK(fidl::Bind(loop.dispatcher(), std::move(remote), std::move(server)));
loop.RunUntilIdle();
ASSERT_FALSE(sync_completion_signaled(&destroyed));
local.reset();
loop.RunUntilIdle();
ASSERT_OK(sync_completion_wait(&destroyed, ZX_TIME_INFINITE));
}
TEST(BindTestCase, UniquePtrDestroyOnServerClose) {
sync_completion_t destroyed;
auto server = std::make_unique<Server>(&destroyed);
async::Loop loop(&kAsyncLoopConfigNoAttachToCurrentThread);
// Launch a thread so we can make a blocking client call
ASSERT_OK(loop.StartThread());
zx::channel local, remote;
ASSERT_OK(zx::channel::create(0, &local, &remote));
ASSERT_OK(fidl::Bind(loop.dispatcher(), std::move(remote), std::move(server)));
ASSERT_FALSE(sync_completion_signaled(&destroyed));
auto result = ::llcpp::fidl::test::simple::Simple::Call::Close(zx::unowned_channel{local});
ASSERT_EQ(result.status(), ZX_ERR_PEER_CLOSED);
// Make sure the other end closed
ASSERT_OK(local.wait_one(ZX_CHANNEL_PEER_CLOSED, zx::time{}, nullptr));
ASSERT_OK(sync_completion_wait(&destroyed, ZX_TIME_INFINITE));
}
TEST(BindTestCase, CallbackDestroyOnClientClose) {
sync_completion_t destroyed;
auto server = std::make_unique<Server>(&destroyed);
async::Loop loop(&kAsyncLoopConfigNoAttachToCurrentThread);
zx::channel local, remote;
ASSERT_OK(zx::channel::create(0, &local, &remote));
fidl::OnChannelClosedFn<Server> cb = [](Server* server) { delete server; };
ASSERT_OK(fidl::Bind(loop.dispatcher(), std::move(remote), server.release(), std::move(cb)));
loop.RunUntilIdle();
ASSERT_FALSE(sync_completion_signaled(&destroyed));
local.reset();
loop.RunUntilIdle();
ASSERT_OK(sync_completion_wait(&destroyed, ZX_TIME_INFINITE));
}
TEST(BindTestCase, CallbackDestroyOnServerClose) {
sync_completion_t destroyed;
auto server = std::make_unique<Server>(&destroyed);
async::Loop loop(&kAsyncLoopConfigNoAttachToCurrentThread);
// Launch a thread so we can make a blocking client call
ASSERT_OK(loop.StartThread());
zx::channel local, remote;
ASSERT_OK(zx::channel::create(0, &local, &remote));
fidl::OnChannelClosedFn<Server> cb = [](Server* server) { delete server; };
ASSERT_OK(fidl::Bind(loop.dispatcher(), std::move(remote), server.release(), std::move(cb)));
ASSERT_FALSE(sync_completion_signaled(&destroyed));
auto result = ::llcpp::fidl::test::simple::Simple::Call::Close(zx::unowned_channel{local});
ASSERT_EQ(result.status(), ZX_ERR_PEER_CLOSED);
ASSERT_OK(sync_completion_wait(&destroyed, ZX_TIME_INFINITE));
// Make sure the other end closed
ASSERT_OK(local.wait_one(ZX_CHANNEL_PEER_CLOSED, zx::time{}, nullptr));
}
} // namespace