blob: 6a932b148b755d3ede7a2b8cae5d07de4e84d2e2 [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 "util.h"
#include <fbl/algorithm.h>
bool check_dir_contents(const char* dirname, expected_dirent_t* edirents, size_t len) {
BEGIN_HELPER;
DIR* dir = emu_opendir(dirname);
emu_rewinddir(dir);
size_t seen = 0;
while (seen != len) {
struct dirent* de = emu_readdir(dir);
ASSERT_NE(de, (void*)0, "Didn't see all expected direntries");
bool found = false;
for (size_t i = 0; i < len; i++) {
if (strcmp(edirents[i].d_name, de->d_name) == 0) {
ASSERT_EQ(edirents[i].d_type, de->d_type, "Saw direntry with unexpected type");
ASSERT_FALSE(edirents[i].seen, "Direntry seen twice");
edirents[i].seen = true;
seen++;
found = true;
break;
}
}
ASSERT_TRUE(found, "Saw an unexpected dirent");
}
ASSERT_EQ(emu_readdir(dir), (void*)0, "There exists an entry we didn't expect to see");
ASSERT_EQ(emu_closedir(dir), 0, "Couldn't close inspected directory");
END_HELPER;
}
#define LARGE_PATH_LENGTH 128
bool TestDirectoryLarge(void) {
BEGIN_TEST;
const int num_files = 1024;
for (int i = 0; i < num_files; i++) {
char path[LARGE_PATH_LENGTH + 1];
snprintf(path, sizeof(path), "::%0*d", LARGE_PATH_LENGTH - 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(run_fsck(), 0);
END_TEST;
}
bool TestDirectoryReaddir(void) {
BEGIN_TEST;
ASSERT_EQ(emu_mkdir("::a", 0755), 0);
ASSERT_EQ(emu_mkdir("::a", 0755), -1);
expected_dirent_t empty_dir[] = {
{false, ".", DT_DIR},
};
ASSERT_TRUE(check_dir_contents("::a", empty_dir, fbl::count_of(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);
expected_dirent_t filled_dir[] = {
{false, ".", DT_DIR},
{false, "dir1", DT_DIR},
{false, "dir2", DT_DIR},
{false, "file1", DT_REG},
{false, "file2", DT_REG},
};
ASSERT_TRUE(check_dir_contents("::a", filled_dir, fbl::count_of(filled_dir)));
ASSERT_EQ(run_fsck(), 0);
END_TEST;
}
bool TestDirectoryReaddirLarge(void) {
BEGIN_TEST;
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_NONNULL(dir);
struct dirent* de;
size_t num_seen = 0;
size_t i = 0;
while ((de = emu_readdir(dir)) != NULL) {
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(run_fsck(), 0);
END_TEST;
}
RUN_MINFS_TESTS(directory_tests,
RUN_TEST_LARGE(TestDirectoryLarge)
RUN_TEST_MEDIUM(TestDirectoryReaddir)
RUN_TEST_MEDIUM(TestDirectoryReaddirLarge)
)