| // 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 "src/storage/blobfs/allocator/extent-reserver.h" |
| |
| #include <bitmap/rle-bitmap.h> |
| #include <gtest/gtest.h> |
| |
| #include "src/storage/blobfs/allocator/node-reserver.h" |
| |
| namespace blobfs { |
| namespace { |
| |
| // Test simple cases of reserving a single extent |
| TEST(ExtentReserverTest, Reserve) { |
| ExtentReserver reserver; |
| BlockOffsetType start_block = 0; |
| BlockCountType block_count = 1; |
| Extent extent(start_block, block_count); |
| |
| // The ReservedExtent constructor should reserve the extent. |
| // The destructor should release the extent. |
| { |
| ReservedExtent reserved_extent = reserver.Reserve(extent); |
| EXPECT_EQ(block_count, reserver.ReservedBlockCount()); |
| } |
| EXPECT_EQ(0u, reserver.ReservedBlockCount()); |
| } |
| |
| TEST(ExtentReserverTest, ReserveReset) { |
| ExtentReserver reserver; |
| BlockOffsetType start_block = 0; |
| BlockCountType block_count = 1; |
| Extent extent(start_block, block_count); |
| |
| // The ReservedExtent constructor should reserve the extent. |
| // Reset should release the extent. |
| { |
| ReservedExtent reserved_extent = reserver.Reserve(extent); |
| EXPECT_EQ(block_count, reserver.ReservedBlockCount()); |
| reserved_extent.Reset(); |
| EXPECT_EQ(0u, reserver.ReservedBlockCount()); |
| } |
| EXPECT_EQ(0u, reserver.ReservedBlockCount()); |
| } |
| |
| // Test the constructors of the reserved extent. |
| TEST(ExtentReserverTest, Constructor) { |
| ExtentReserver reserver; |
| BlockOffsetType start_block = 0; |
| BlockCountType block_count = 1; |
| Extent extent(start_block, block_count); |
| |
| // Test reservation via the constructor. |
| { |
| ReservedExtent reserved_extent = reserver.Reserve(extent); |
| EXPECT_EQ(extent.Start(), reserved_extent.extent().Start()); |
| EXPECT_EQ(extent.Length(), reserved_extent.extent().Length()); |
| EXPECT_EQ(block_count, reserver.ReservedBlockCount()); |
| } |
| EXPECT_EQ(0u, reserver.ReservedBlockCount()); |
| } |
| |
| TEST(ExtentReserverTest, MoveConstructor) { |
| ExtentReserver reserver; |
| BlockOffsetType start_block = 0; |
| BlockCountType block_count = 1; |
| Extent extent(start_block, block_count); |
| |
| // Test reservation via move constructor. |
| { |
| ReservedExtent source_extent = reserver.Reserve(extent); |
| EXPECT_EQ(1u, reserver.ReservedBlockCount()); |
| EXPECT_EQ(extent.Start(), source_extent.extent().Start()); |
| EXPECT_EQ(extent.Length(), source_extent.extent().Length()); |
| |
| ReservedExtent dest_extent(std::move(source_extent)); |
| EXPECT_EQ(1u, reserver.ReservedBlockCount()); |
| EXPECT_EQ(extent.Start(), dest_extent.extent().Start()); |
| EXPECT_EQ(extent.Length(), dest_extent.extent().Length()); |
| } |
| EXPECT_EQ(0u, reserver.ReservedBlockCount()); |
| } |
| |
| TEST(ExtentReserverTest, MoveAssignment) { |
| ExtentReserver reserver; |
| BlockOffsetType start_block = 0; |
| BlockCountType block_count = 1; |
| Extent extent(start_block, block_count); |
| |
| // Test reservation via the move assignment operator. |
| { |
| ReservedExtent source_extent = reserver.Reserve(extent); |
| EXPECT_EQ(1u, reserver.ReservedBlockCount()); |
| EXPECT_EQ(extent.Start(), source_extent.extent().Start()); |
| EXPECT_EQ(extent.Length(), source_extent.extent().Length()); |
| |
| ReservedExtent dest_extent = std::move(source_extent); |
| EXPECT_EQ(1u, reserver.ReservedBlockCount()); |
| EXPECT_EQ(extent.Start(), dest_extent.extent().Start()); |
| EXPECT_EQ(extent.Length(), dest_extent.extent().Length()); |
| } |
| } |
| |
| // Test splitting of extents. |
| TEST(ExtentReserverTest, Split) { |
| ExtentReserver reserver; |
| uint64_t start_block = 0; |
| BlockCountType block_count = 10; |
| Extent extent{start_block, block_count}; |
| |
| EXPECT_EQ(0u, reserver.ReservedBlockCount()); |
| ReservedExtent reserved_extent = reserver.Reserve(extent); |
| EXPECT_EQ(10u, reserver.ReservedBlockCount()); |
| |
| { |
| const BlockCountType split_point = 5; |
| ReservedExtent latter(reserved_extent.SplitAt(split_point)); |
| // After splitting, no reservations actually change. |
| EXPECT_EQ(10u, reserver.ReservedBlockCount()); |
| |
| // Verify the split extents contain the expected values. |
| EXPECT_EQ(extent.Start(), reserved_extent.extent().Start()); |
| EXPECT_EQ(split_point, reserved_extent.extent().Length()); |
| |
| EXPECT_EQ(extent.Start() + split_point, latter.extent().Start()); |
| EXPECT_EQ(block_count - split_point, latter.extent().Length()); |
| } |
| |
| // When the latter half of the reservation goes out of scope, the reservations |
| // are cleaned up too. |
| EXPECT_EQ(5u, reserver.ReservedBlockCount()); |
| } |
| |
| } // namespace |
| } // namespace blobfs |