| // 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 |