blob: 74f5612fdc18bfbda7386860f9001e22ca401f65 [file] [log] [blame]
// 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 "src/storage/fshost/fshost_integration_test.h"
#include <lib/fdio/vfs.h>
#include <lib/service/llcpp/service.h>
#include <sys/statfs.h>
namespace fshost {
static const char kTestFshostName[] = "test-fshost";
static const char kTestFshostCollection[] = "fshost-collection";
static const char kTestFshostUrl[] = "fuchsia-pkg://fuchsia.com/fshost-tests#meta/test-fshost.cm";
static const fuchsia_component_decl::wire::ChildRef kFshostChildRef{
.name = kTestFshostName, .collection = kTestFshostCollection};
void FshostIntegrationTest::SetUp() {
auto realm_client_end = service::Connect<fuchsia_component::Realm>();
ASSERT_EQ(realm_client_end.status_value(), ZX_OK);
realm_ = fidl::BindSyncClient(std::move(*realm_client_end));
fidl::Arena allocator;
fuchsia_component_decl::wire::CollectionRef collection_ref{.name = kTestFshostCollection};
fuchsia_component_decl::wire::Child child_decl(allocator);
child_decl.set_name(allocator, allocator, kTestFshostName)
.set_url(allocator, allocator, kTestFshostUrl)
.set_startup(fuchsia_component_decl::wire::StartupMode::kLazy);
fuchsia_component::wire::CreateChildArgs child_args;
auto create_res = realm_->CreateChild(collection_ref, child_decl, child_args);
ASSERT_TRUE(create_res.ok() && !create_res->result.is_err());
auto exposed_endpoints = fidl::CreateEndpoints<fuchsia_io::Directory>();
ASSERT_EQ(exposed_endpoints.status_value(), ZX_OK);
auto open_res = realm_->OpenExposedDir(kFshostChildRef, std::move(exposed_endpoints->server));
ASSERT_TRUE(open_res.ok() && !open_res->result.is_err());
exposed_dir_ = fidl::BindSyncClient(std::move(exposed_endpoints->client));
auto watcher_client_end =
service::ConnectAt<fuchsia_fshost::BlockWatcher>(exposed_dir_.client_end());
ASSERT_EQ(watcher_client_end.status_value(), ZX_OK);
block_watcher_ = fidl::BindSyncClient(std::move(*watcher_client_end));
}
void FshostIntegrationTest::TearDown() {
auto destroy_res = realm_->DestroyChild(kFshostChildRef);
ASSERT_TRUE(destroy_res.ok() && !destroy_res->result.is_err());
}
void FshostIntegrationTest::ResetFshost() {
TearDown();
SetUp();
}
void FshostIntegrationTest::PauseWatcher() const {
auto res = block_watcher_->Pause();
ASSERT_EQ(res.status(), ZX_OK);
ASSERT_EQ(res->status, ZX_OK);
}
void FshostIntegrationTest::ResumeWatcher() const {
auto res = block_watcher_->Resume();
ASSERT_EQ(res.status(), ZX_OK);
ASSERT_EQ(res->status, ZX_OK);
}
std::pair<fbl::unique_fd, uint64_t> FshostIntegrationTest::WaitForMount(const std::string& name) {
// The mount point will always exist so we expect open() to work regardless of whether the device
// is actually mounted. We retry until the mount point has the expected filesystem type.
//
// This can be relatively slow on some bots (especially with asan) because it can involve lots of
// complex process launching so use a high retry limit.
constexpr int kMaxRetries = 30;
for (int i = 0; i < kMaxRetries; i++) {
auto root_endpoints = fidl::CreateEndpoints<fuchsia_io::Node>();
EXPECT_EQ(root_endpoints.status_value(), ZX_OK);
auto open_res = exposed_dir()->Open(fuchsia_io::wire::OpenFlags::kRightReadable, 0,
fidl::StringView::FromExternal(name),
std::move(root_endpoints->server));
EXPECT_EQ(open_res.status(), ZX_OK);
if (open_res.status() != ZX_OK)
return std::make_pair(fbl::unique_fd(), 0);
fbl::unique_fd fd;
zx_status_t status =
fdio_fd_create(root_endpoints->client.TakeChannel().release(), fd.reset_and_get_address());
EXPECT_EQ(ZX_OK, status);
if (status != ZX_OK)
return std::make_pair(fbl::unique_fd(), 0);
struct statfs buf;
EXPECT_EQ(fstatfs(fd.get(), &buf), 0) << ": " << strerror(errno);
if (buf.f_type != VFS_TYPE_MEMFS)
return std::make_pair(std::move(fd), buf.f_type);
sleep(1);
}
return std::make_pair(fbl::unique_fd(), 0);
}
} // namespace fshost