blob: 17fd796e9724f727101cf6f1f06bd107190e8714 [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/async/dispatcher.h>
#include <lib/fidl/cpp/binding_set.h>
#include <lib/sys/cpp/service_directory.h>
#include <lib/vfs/cpp/composed_service_dir.h>
#include <lib/vfs/cpp/service.h>
#include <lib/vfs/cpp/testing/dir_test_util.h>
#include <gtest/gtest.h>
#include <test/placeholders/cpp/fidl.h>
namespace {
using vfs_tests::Dirent;
class EchoImpl : public test::placeholders::Echo {
public:
EchoImpl(std::string ans) : ans_(ans) {}
void EchoString(fidl::StringPtr value, EchoStringCallback callback) override { callback(ans_); }
private:
std::string ans_;
};
class ComposedServiceDirectorySimpleTest : public vfs_tests::DirConnection {
public:
vfs::internal::Directory* GetDirectoryNode() override { return &dir_; }
ComposedServiceDirectorySimpleTest() : loop_(&kAsyncLoopConfigNoAttachToCurrentThread) {
dir_.AddService("echo1", GetFakeService("echo1", loop_.dispatcher()));
dir_.AddService("echo2", GetFakeService("echo2", loop_.dispatcher()));
dir_.AddService("echo3", GetFakeService("echo3", loop_.dispatcher()));
backing_dir_.AddEntry("echo1", GetFakeService("fallback_echo1", loop_.dispatcher()));
backing_dir_.AddEntry("echo4", GetFakeService("fallback_echo4", loop_.dispatcher()));
backing_dir_.AddEntry("echo5", GetFakeService("fallback_echo5", loop_.dispatcher()));
dir_.set_fallback(GetConnection(&backing_dir_));
loop_.StartThread("vfs test thread");
}
fuchsia::io::DirectoryPtr GetConnection(vfs::internal::Directory* dir) {
fuchsia::io::DirectoryPtr ptr;
dir->Serve(fuchsia::io::OpenFlags::RIGHT_READABLE | fuchsia::io::OpenFlags::RIGHT_WRITABLE,
ptr.NewRequest().TakeChannel(), loop_.dispatcher());
return ptr;
}
fuchsia::io::DirectorySyncPtr GetSyncConnection(vfs::internal::Directory* dir) {
fuchsia::io::DirectorySyncPtr ptr;
dir->Serve(fuchsia::io::OpenFlags::RIGHT_READABLE | fuchsia::io::OpenFlags::RIGHT_WRITABLE,
ptr.NewRequest().TakeChannel(), loop_.dispatcher());
return ptr;
}
protected:
vfs::PseudoDir backing_dir_;
vfs::ComposedServiceDir dir_;
std::vector<std::unique_ptr<EchoImpl>> echo_impls_;
fidl::BindingSet<test::placeholders::Echo> bindings_;
async::Loop loop_;
std::unique_ptr<vfs::Service> GetFakeService(const std::string& ans,
async_dispatcher_t* dispatcher) {
auto echo = std::make_unique<EchoImpl>(ans);
auto service = std::make_unique<vfs::Service>(bindings_.GetHandler(echo.get(), dispatcher));
echo_impls_.push_back(std::move(echo));
return service;
}
};
TEST_F(ComposedServiceDirectorySimpleTest, ConnectToServices) {
auto dir_connection = GetConnection(&dir_);
sys::ServiceDirectory service_directory(std::move(dir_connection));
std::string services[] = {"echo1", "echo2", "echo3"};
// connect to services and test
for (auto& s : services) {
test::placeholders::EchoSyncPtr ptr;
service_directory.Connect(s, ptr.NewRequest().TakeChannel());
fidl::StringPtr ans;
ptr->EchoString("hello", &ans);
ASSERT_TRUE(ans.has_value());
EXPECT_EQ(s, ans.value());
}
std::string fallback_services[] = {"echo4", "echo5"};
for (auto& s : fallback_services) {
test::placeholders::EchoSyncPtr ptr;
service_directory.Connect(s, ptr.NewRequest().TakeChannel());
fidl::StringPtr ans;
ptr->EchoString("hello", &ans);
ASSERT_TRUE(ans.has_value());
EXPECT_EQ("fallback_" + s, ans.value());
}
}
TEST_F(ComposedServiceDirectorySimpleTest, ReadDir) {
auto ptr = GetSyncConnection(&dir_);
// Since directory entries "echo4" and "echo5" are in the fallback dir,
// they are incorrectly excluded here due to a bug. See fxbug.dev/55769.
std::vector<Dirent> expected_dirents = {
Dirent::DirentForDot(),
Dirent::DirentForService("echo1"),
Dirent::DirentForService("echo2"),
Dirent::DirentForService("echo3"),
};
AssertReadDirents(ptr, 1024, expected_dirents);
}
} // namespace