blob: dbf98d2c938a4e58ea94e11e5fa4eb0ad5724392 [file] [log] [blame]
// Copyright 2016 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 <iterator>
#include <fbl/algorithm.h>
#include <fbl/span.h>
#include "src/storage/host_fs_test/fixture.h"
namespace fs_test {
namespace {
struct ExpectedDirectoryEntry {
std::string_view name;
unsigned char d_type; // Same as the d_type entry from struct dirent.
};
void CheckDirectoryContents(const char* dirname, fbl::Span<const ExpectedDirectoryEntry> entries) {
DIR* dir = emu_opendir(dirname);
emu_rewinddir(dir);
std::vector<bool> seen(entries.size());
size_t total_seen = 0;
while (total_seen < entries.size()) {
struct dirent* de = emu_readdir(dir);
ASSERT_NE(de, nullptr) << "Didn't see all expected direntries";
bool found = false;
auto seen_iter = seen.begin();
for (const auto& entry : entries) {
if (entry.name == de->d_name) {
ASSERT_EQ(entry.d_type, de->d_type) << "Saw direntry with unexpected type";
ASSERT_FALSE(*seen_iter) << "Direntry seen twice";
*seen_iter = true;
found = true;
++total_seen;
break;
}
++seen_iter;
}
ASSERT_TRUE(found) << "Saw an unexpected dirent: " << de->d_name;
}
ASSERT_EQ(emu_readdir(dir), nullptr) << "There exists an entry we didn't expect to see";
EXPECT_EQ(emu_closedir(dir), 0);
}
TEST_F(HostFilesystemTest, DirectoryLarge) {
constexpr int kLargePathLength = 128;
const int num_files = 1024;
for (int i = 0; i < num_files; ++i) {
char path[kLargePathLength + 1];
snprintf(path, sizeof(path), "::%0*d", kLargePathLength - 2, i);
int fd = emu_open(path, O_RDWR | O_CREAT | O_EXCL, 0644);
ASSERT_GT(fd, 0);
ASSERT_EQ(emu_close(fd), 0);
}
ASSERT_EQ(RunFsck(), 0);
}
TEST_F(HostFilesystemTest, DirectoryReaddir) {
ASSERT_EQ(emu_mkdir("::a", 0755), 0);
ASSERT_EQ(emu_mkdir("::a", 0755), -1);
ExpectedDirectoryEntry empty_dir[] = {
{".", DT_DIR},
};
ASSERT_NO_FATAL_FAILURE(CheckDirectoryContents("::a", empty_dir));
ASSERT_EQ(emu_mkdir("::a/dir1", 0755), 0);
int fd = emu_open("::a/file1", O_RDWR | O_CREAT | O_EXCL, 0644);
ASSERT_GT(fd, 0);
ASSERT_EQ(emu_close(fd), 0);
fd = emu_open("::a/file2", O_RDWR | O_CREAT | O_EXCL, 0644);
ASSERT_GT(fd, 0);
ASSERT_EQ(emu_close(fd), 0);
ASSERT_EQ(emu_mkdir("::a/dir2", 0755), 0);
ExpectedDirectoryEntry filled_dir[] = {
{".", DT_DIR}, {"dir1", DT_DIR}, {"dir2", DT_DIR}, {"file1", DT_REG}, {"file2", DT_REG},
};
ASSERT_NO_FATAL_FAILURE(CheckDirectoryContents("::a", filled_dir));
ASSERT_EQ(RunFsck(), 0);
}
TEST_F(HostFilesystemTest, ReaddirLarge) {
size_t num_entries = 1000;
ASSERT_EQ(emu_mkdir("::dir", 0755), 0);
for (size_t i = 0; i < num_entries; ++i) {
char dirname[100];
snprintf(dirname, 100, "::dir/%05lu", i);
ASSERT_EQ(emu_mkdir(dirname, 0755), 0);
}
DIR* dir = emu_opendir("::dir");
ASSERT_NE(dir, nullptr);
struct dirent* de;
size_t num_seen = 0;
size_t i = 0;
while ((de = emu_readdir(dir)) != nullptr) {
if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")) {
continue;
}
char dirname[100];
snprintf(dirname, 100, "%05lu", i++);
ASSERT_EQ(strcmp(de->d_name, dirname), 0) << "Unexpected dirent";
++num_seen;
}
ASSERT_EQ(num_seen, num_entries) << "Did not see all expected entries";
ASSERT_EQ(emu_closedir(dir), 0);
ASSERT_EQ(RunFsck(), 0);
}
} // namespace
} // namespace fs_test