blob: 32eca93aa874bb0631b9c05ec83d8e4fe0a87ac7 [file] [log] [blame]
// Copyright 2020 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 <lib/async-loop/cpp/loop.h>
#include <lib/async-loop/default.h>
#include <gtest/gtest.h>
#include "src/storage/lib/block_client/cpp/fake_block_device.h"
#include "src/storage/minfs/bcache.h"
#include "src/storage/minfs/directory.h"
#include "src/storage/minfs/file.h"
#include "src/storage/minfs/format.h"
#include "src/storage/minfs/runner.h"
namespace minfs {
namespace {
using block_client::FakeBlockDevice;
TEST(UnlinkTest, PurgedFileHasCorrectMagic) {
async::Loop loop(&kAsyncLoopConfigAttachToCurrentThread);
constexpr uint64_t kBlockCount = 1 << 20;
auto device = std::make_unique<FakeBlockDevice>(kBlockCount, kMinfsBlockSize);
auto bcache_or = Bcache::Create(std::move(device), kBlockCount);
ASSERT_TRUE(bcache_or.is_ok());
ASSERT_TRUE(Mkfs(bcache_or.value().get()).is_ok());
MountOptions options = {};
auto fs_or = Runner::Create(loop.dispatcher(), std::move(bcache_or.value()), options);
ASSERT_TRUE(fs_or.is_ok());
ino_t ino;
uint32_t inode_block;
{
auto root = fs_or->minfs().VnodeGet(kMinfsRootIno);
ASSERT_TRUE(root.is_ok());
zx::result fs_child = root->Create("foo", fs::CreationType::kFile);
ASSERT_TRUE(fs_child.is_ok()) << fs_child.status_string();
auto child = fbl::RefPtr<File>::Downcast(*std::move(fs_child));
ino = child->GetIno();
EXPECT_EQ(child->Close(), ZX_OK);
EXPECT_EQ(root->Unlink("foo", /*must_be_dir=*/false), ZX_OK);
inode_block = fs_or->minfs().Info().ino_block + ino / kMinfsInodesPerBlock;
}
bcache_or = zx::ok(Runner::Destroy(std::move(fs_or.value())));
Inode inodes[kMinfsInodesPerBlock];
EXPECT_TRUE(bcache_or->Readblk(inode_block, &inodes).is_ok());
EXPECT_EQ(inodes[ino % kMinfsInodesPerBlock].magic, kMinfsMagicPurged);
}
TEST(UnlinkTest, UnlinkedDirectoryFailure) {
async::Loop loop(&kAsyncLoopConfigAttachToCurrentThread);
constexpr uint64_t kBlockCount = 1 << 20;
auto device = std::make_unique<FakeBlockDevice>(kBlockCount, kMinfsBlockSize);
auto bcache_or = Bcache::Create(std::move(device), kBlockCount);
ASSERT_TRUE(bcache_or.is_ok());
ASSERT_TRUE(Mkfs(bcache_or.value().get()).is_ok());
MountOptions options = {};
auto fs_or = Runner::Create(loop.dispatcher(), std::move(bcache_or.value()), options);
ASSERT_TRUE(fs_or.is_ok());
{
auto root = fs_or->minfs().VnodeGet(kMinfsRootIno);
ASSERT_TRUE(root.is_ok()) << root.status_string();
zx::result fs_child = root->Create("foo", fs::CreationType::kDirectory);
ASSERT_TRUE(fs_child.is_ok()) << fs_child.status_string();
EXPECT_EQ(root->Unlink("foo", true), ZX_OK);
auto child = fbl::RefPtr<Directory>::Downcast(*std::move(fs_child));
EXPECT_EQ(0ul, child->GetInode()->size);
EXPECT_EQ(child->Unlink("bar", false), ZX_ERR_NOT_FOUND);
EXPECT_EQ(child->Rename(root.value(), "bar", "bar", false, false), ZX_ERR_NOT_FOUND);
fbl::RefPtr<fs::Vnode> unused_child;
EXPECT_EQ(child->Lookup("bar", &unused_child), ZX_ERR_NOT_FOUND);
EXPECT_EQ(child->Close(), ZX_OK);
}
[[maybe_unused]] auto bcache = Runner::Destroy(std::move(fs_or.value()));
}
} // namespace
} // namespace minfs