| // 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 <fuchsia/io/cpp/fidl.h> |
| #include <lib/vfs/cpp/testing/dir_test_util.h> |
| |
| namespace vfs_tests { |
| |
| Dirent Dirent::DirentForDot() { return DirentForDirectory("."); } |
| |
| Dirent Dirent::DirentForDirectory(const std::string& name) { |
| return Dirent(fuchsia::io::INO_UNKNOWN, fuchsia::io::DIRENT_TYPE_DIRECTORY, name); |
| } |
| |
| Dirent Dirent::DirentForFile(const std::string& name) { |
| return Dirent(fuchsia::io::INO_UNKNOWN, fuchsia::io::DIRENT_TYPE_FILE, name); |
| } |
| |
| Dirent Dirent::DirentForService(const std::string& name) { |
| return Dirent(fuchsia::io::INO_UNKNOWN, fuchsia::io::DIRENT_TYPE_SERVICE, name); |
| } |
| |
| std::string Dirent::String() { |
| return "Dirent:\nino: " + std ::to_string(ino_) + "\ntype: " + std ::to_string(type_) + |
| "\nsize: " + std ::to_string(size_) + "\nname: " + name_; |
| } |
| |
| Dirent::Dirent(uint64_t ino, uint8_t type, const std::string& name) |
| : ino_(ino), |
| type_(type), |
| size_(static_cast<uint8_t>(name.length())), |
| name_(name), |
| size_in_bytes_(sizeof(vdirent_t) + size_) { |
| ZX_DEBUG_ASSERT(name.length() <= static_cast<uint64_t>(NAME_MAX)); |
| } |
| |
| void DirConnection::AssertOpen(async_dispatcher_t* dispatcher, uint32_t flags, |
| zx_status_t expected_status, bool test_on_open_event) { |
| fuchsia::io::NodePtr node_ptr; |
| if (test_on_open_event) { |
| flags |= fuchsia::io::OPEN_FLAG_DESCRIBE; |
| } |
| EXPECT_EQ(expected_status, |
| GetDirectoryNode()->Serve(flags, node_ptr.NewRequest().TakeChannel(), dispatcher)); |
| |
| if (test_on_open_event) { |
| bool on_open_called = false; |
| node_ptr.events().OnOpen = [&](zx_status_t status, |
| std::unique_ptr<fuchsia::io::NodeInfo> info) { |
| EXPECT_FALSE(on_open_called); // should be called only once |
| on_open_called = true; |
| EXPECT_EQ(expected_status, status); |
| if (expected_status == ZX_OK) { |
| ASSERT_NE(info.get(), nullptr); |
| EXPECT_TRUE(info->is_directory()); |
| } else { |
| EXPECT_EQ(info.get(), nullptr); |
| } |
| }; |
| |
| RunLoopUntil([&]() { return on_open_called; }, zx::msec(1)); |
| } |
| } |
| |
| void DirConnection::AssertReadDirents(fuchsia::io::DirectorySyncPtr& ptr, uint64_t max_bytes, |
| std::vector<Dirent>& expected_dirents, |
| zx_status_t expected_status) { |
| std::vector<uint8_t> out_dirents; |
| zx_status_t status; |
| ptr->ReadDirents(max_bytes, &status, &out_dirents); |
| ASSERT_EQ(expected_status, status); |
| if (status != ZX_OK) { |
| return; |
| } |
| uint64_t expected_size = 0; |
| for (auto& d : expected_dirents) { |
| expected_size += d.size_in_bytes(); |
| } |
| EXPECT_EQ(expected_size, out_dirents.size()); |
| uint64_t offset = 0; |
| auto data_ptr = out_dirents.data(); |
| for (auto& d : expected_dirents) { |
| SCOPED_TRACE(d.String()); |
| ASSERT_LE(sizeof(vdirent_t), out_dirents.size() - offset); |
| vdirent_t* de = reinterpret_cast<vdirent_t*>(data_ptr + offset); |
| EXPECT_EQ(d.ino(), de->ino); |
| EXPECT_EQ(d.size(), de->size); |
| EXPECT_EQ(d.type(), de->type); |
| ASSERT_LE(d.size_in_bytes(), out_dirents.size() - offset); |
| EXPECT_EQ(d.name(), std::string(de->name, de->size)); |
| |
| offset += sizeof(vdirent_t) + de->size; |
| } |
| } |
| |
| void DirConnection::AssertRewind(fuchsia::io::DirectorySyncPtr& ptr, zx_status_t expected_status) { |
| zx_status_t status; |
| ptr->Rewind(&status); |
| ASSERT_EQ(expected_status, status); |
| } |
| |
| void DirConnection::AssertRead(fuchsia::io::FileSyncPtr& file, int count, |
| const std::string& expected_str, zx_status_t expected_status) { |
| zx_status_t status; |
| std::vector<uint8_t> buffer; |
| file->Read(count, &status, &buffer); |
| ASSERT_EQ(expected_status, status); |
| std::string str(buffer.size(), 0); |
| std::copy(buffer.begin(), buffer.end(), str.begin()); |
| ASSERT_EQ(expected_str, str); |
| } |
| |
| } // namespace vfs_tests |