blob: 76ab7c30aaab4de5a4b7a42e58a211b84638cc37 [file] [log] [blame]
// Copyright 2018 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 <bitmap/rle-bitmap.h>
#include <blobfs/extent-reserver.h>
#include <blobfs/node-reserver.h>
#include <unittest/unittest.h>
namespace blobfs {
namespace {
// Test that reserving a node actually changes the node count, and that RAII releases the node.
bool ReserveTest() {
BEGIN_TEST;
NodeReserver reserver;
{
const uint32_t ino = 3;
ReservedNode reserved_node(&reserver, ino);
EXPECT_EQ(1, reserver.ReservedNodeCount());
}
EXPECT_EQ(0, reserver.ReservedNodeCount());
END_TEST;
}
bool ReserveResetTest() {
BEGIN_TEST;
NodeReserver reserver;
{
const uint32_t ino = 3;
ReservedNode reserved_node(&reserver, ino);
EXPECT_EQ(1, reserver.ReservedNodeCount());
reserved_node.Reset();
EXPECT_EQ(0, reserver.ReservedNodeCount());
}
EXPECT_EQ(0, reserver.ReservedNodeCount());
END_TEST;
}
// Test the constructors of the reserved node.
bool ConstructorTest() {
BEGIN_TEST;
NodeReserver reserver;
// Test the constructor.
{
ReservedNode reserved_node(&reserver, 3);
EXPECT_EQ(3, reserved_node.index());
EXPECT_EQ(1, reserver.ReservedNodeCount());
}
EXPECT_EQ(0, reserver.ReservedNodeCount());
END_TEST;
}
bool MoveConstructorTest() {
BEGIN_TEST;
NodeReserver reserver;
// Test the move constructor.
{
ReservedNode reserved_node(&reserver, 3);
EXPECT_EQ(3, reserved_node.index());
EXPECT_EQ(1, reserver.ReservedNodeCount());
ReservedNode dest_node(std::move(reserved_node));
EXPECT_EQ(3, dest_node.index());
EXPECT_EQ(1, reserver.ReservedNodeCount());
}
EXPECT_EQ(0, reserver.ReservedNodeCount());
END_TEST;
}
bool MoveAssignmentTest() {
BEGIN_TEST;
NodeReserver reserver;
// Test the move assignment operator.
{
ReservedNode reserved_node(&reserver, 3);
EXPECT_EQ(3, reserved_node.index());
EXPECT_EQ(1, reserver.ReservedNodeCount());
ReservedNode dest_node = std::move(reserved_node);
EXPECT_EQ(3, dest_node.index());
EXPECT_EQ(1, reserver.ReservedNodeCount());
}
EXPECT_EQ(0, reserver.ReservedNodeCount());
END_TEST;
}
class TestReserver : public NodeReserver {
public:
bool IsReserved(uint32_t ino) const {
return IsNodeReserved(ino);
}
uint32_t LowerBound() const {
return FreeNodeLowerBound();
}
void SetBound(uint32_t ino) {
SetFreeNodeLowerBound(ino);
}
void SetBoundIfSmallest(uint32_t ino) {
SetFreeNodeLowerBoundIfSmallest(ino);
}
};
// Test the protected interface available to subclasses of the node reserver.
bool LowerBoundAutoResetTest() {
BEGIN_TEST;
TestReserver reserver;
// The lower bound should start at zero.
EXPECT_FALSE(reserver.IsReserved(0));
EXPECT_EQ(0, reserver.LowerBound());
// The lower bound won't move unless we manually move it.
ReservedNode node(&reserver, 0);
EXPECT_TRUE(reserver.IsReserved(0));
EXPECT_EQ(0, reserver.LowerBound());
reserver.SetBound(3);
EXPECT_EQ(3, reserver.LowerBound());
// When we release a node with ino = 0, the lower bound moves back.
node.Reset();
EXPECT_EQ(0, reserver.LowerBound());
END_TEST;
}
bool LowerBoundManualResetTest() {
BEGIN_TEST;
TestReserver reserver;
// When we manually release a node (akin to freeing a committed but unreserved
// node), the lower bound moves back.
reserver.SetBound(3);
EXPECT_EQ(3, reserver.LowerBound());
reserver.SetBoundIfSmallest(1);
EXPECT_EQ(1, reserver.LowerBound());
// Releasing a higher index does nothing.
reserver.SetBoundIfSmallest(10);
EXPECT_EQ(1, reserver.LowerBound());
END_TEST;
}
} // namespace
} // namespace blobfs
BEGIN_TEST_CASE(blobfsNodeReserverTests)
RUN_TEST(blobfs::ReserveTest)
RUN_TEST(blobfs::ReserveResetTest)
RUN_TEST(blobfs::ConstructorTest)
RUN_TEST(blobfs::MoveConstructorTest)
RUN_TEST(blobfs::MoveAssignmentTest)
RUN_TEST(blobfs::LowerBoundAutoResetTest)
RUN_TEST(blobfs::LowerBoundManualResetTest)
END_TEST_CASE(blobfsNodeReserverTests);