From dbda1300aee31850ea89c4f76573dda225fed220 Mon Sep 17 00:00:00 2001 From: David Anderson Date: Mon, 7 Aug 2023 14:54:38 -0700 Subject: [PATCH] snapuserd: Factor a base class out of tests. This factors a lighter weight class out of SnapuserdTest, so we can construct tests without needing a HandlerManager/daemon. Bug: 288273605 Test: snapuserd_test Change-Id: Ib33dc593a5b3d3df86853e73f245918ef36fd9fa --- .../user-space-merge/snapuserd_test.cpp | 316 ++++++++++-------- 1 file changed, 168 insertions(+), 148 deletions(-) diff --git a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_test.cpp b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_test.cpp index ae921fd35..9f7a91dae 100644 --- a/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_test.cpp +++ b/fs_mgr/libsnapshot/snapuserd/user-space-merge/snapuserd_test.cpp @@ -56,7 +56,167 @@ using namespace std::chrono_literals; using namespace android::dm; using namespace std; -class SnapuserdTest : public ::testing::Test { +class SnapuserdTestBase : public ::testing::Test { + protected: + void SetUp() override; + void TearDown() override; + void CreateBaseDevice(); + void CreateCowDevice(); + void SetDeviceControlName(); + std::unique_ptr CreateCowDeviceInternal(); + + std::unique_ptr harness_; + size_t size_ = 100_MiB; + int total_base_size_ = 0; + std::string system_device_ctrl_name_; + std::string system_device_name_; + + unique_ptr base_dev_; + unique_fd base_fd_; + + std::unique_ptr cow_system_; + + std::unique_ptr orig_buffer_; +}; + +void SnapuserdTestBase::SetUp() { + harness_ = std::make_unique(); +} + +void SnapuserdTestBase::TearDown() {} + +void SnapuserdTestBase::CreateBaseDevice() { + total_base_size_ = (size_ * 5); + + base_dev_ = harness_->CreateBackingDevice(total_base_size_); + ASSERT_NE(base_dev_, nullptr); + + base_fd_.reset(open(base_dev_->GetPath().c_str(), O_RDWR | O_CLOEXEC)); + ASSERT_GE(base_fd_, 0); + + unique_fd rnd_fd(open("/dev/random", O_RDONLY)); + ASSERT_GE(rnd_fd, 0); + + std::unique_ptr random_buffer = std::make_unique(1_MiB); + + for (size_t j = 0; j < ((total_base_size_) / 1_MiB); j++) { + ASSERT_EQ(ReadFullyAtOffset(rnd_fd, (char*)random_buffer.get(), 1_MiB, 0), true); + ASSERT_EQ(android::base::WriteFully(base_fd_, random_buffer.get(), 1_MiB), true); + } + + ASSERT_EQ(lseek(base_fd_, 0, SEEK_SET), 0); +} + +std::unique_ptr SnapuserdTestBase::CreateCowDeviceInternal() { + std::string path = android::base::GetExecutableDirectory(); + cow_system_ = std::make_unique(path); + + CowOptions options; + options.compression = "gz"; + + unique_fd fd(cow_system_->fd); + cow_system_->fd = -1; + + return CreateCowWriter(kDefaultCowVersion, options, std::move(fd)); +} + +void SnapuserdTestBase::CreateCowDevice() { + unique_fd rnd_fd; + loff_t offset = 0; + + auto writer = CreateCowDeviceInternal(); + ASSERT_NE(writer, nullptr); + + rnd_fd.reset(open("/dev/random", O_RDONLY)); + ASSERT_TRUE(rnd_fd > 0); + + std::unique_ptr random_buffer_1_ = std::make_unique(size_); + + // Fill random data + for (size_t j = 0; j < (size_ / 1_MiB); j++) { + ASSERT_EQ(ReadFullyAtOffset(rnd_fd, (char*)random_buffer_1_.get() + offset, 1_MiB, 0), + true); + + offset += 1_MiB; + } + + size_t num_blocks = size_ / writer->GetBlockSize(); + size_t blk_end_copy = num_blocks * 2; + size_t source_blk = num_blocks - 1; + size_t blk_src_copy = blk_end_copy - 1; + + uint32_t sequence[num_blocks * 2]; + // Sequence for Copy ops + for (int i = 0; i < num_blocks; i++) { + sequence[i] = num_blocks - 1 - i; + } + // Sequence for Xor ops + for (int i = 0; i < num_blocks; i++) { + sequence[num_blocks + i] = 5 * num_blocks - 1 - i; + } + ASSERT_TRUE(writer->AddSequenceData(2 * num_blocks, sequence)); + + size_t x = num_blocks; + while (1) { + ASSERT_TRUE(writer->AddCopy(source_blk, blk_src_copy)); + x -= 1; + if (x == 0) { + break; + } + source_blk -= 1; + blk_src_copy -= 1; + } + + source_blk = num_blocks; + blk_src_copy = blk_end_copy; + + ASSERT_TRUE(writer->AddRawBlocks(source_blk, random_buffer_1_.get(), size_)); + + size_t blk_zero_copy_start = source_blk + num_blocks; + size_t blk_zero_copy_end = blk_zero_copy_start + num_blocks; + + ASSERT_TRUE(writer->AddZeroBlocks(blk_zero_copy_start, num_blocks)); + + size_t blk_random2_replace_start = blk_zero_copy_end; + + ASSERT_TRUE(writer->AddRawBlocks(blk_random2_replace_start, random_buffer_1_.get(), size_)); + + size_t blk_xor_start = blk_random2_replace_start + num_blocks; + size_t xor_offset = BLOCK_SZ / 2; + ASSERT_TRUE(writer->AddXorBlocks(blk_xor_start, random_buffer_1_.get(), size_, num_blocks, + xor_offset)); + + // Flush operations + ASSERT_TRUE(writer->Finalize()); + // Construct the buffer required for validation + orig_buffer_ = std::make_unique(total_base_size_); + std::string zero_buffer(size_, 0); + ASSERT_EQ(android::base::ReadFullyAtOffset(base_fd_, orig_buffer_.get(), size_, size_), true); + memcpy((char*)orig_buffer_.get() + size_, random_buffer_1_.get(), size_); + memcpy((char*)orig_buffer_.get() + (size_ * 2), (void*)zero_buffer.c_str(), size_); + memcpy((char*)orig_buffer_.get() + (size_ * 3), random_buffer_1_.get(), size_); + ASSERT_EQ(android::base::ReadFullyAtOffset(base_fd_, &orig_buffer_.get()[size_ * 4], size_, + size_ + xor_offset), + true); + for (int i = 0; i < size_; i++) { + orig_buffer_.get()[(size_ * 4) + i] = + (uint8_t)(orig_buffer_.get()[(size_ * 4) + i] ^ random_buffer_1_.get()[i]); + } +} + +void SnapuserdTestBase::SetDeviceControlName() { + system_device_name_.clear(); + system_device_ctrl_name_.clear(); + + std::string str(cow_system_->path); + std::size_t found = str.find_last_of("/\\"); + ASSERT_NE(found, std::string::npos); + system_device_name_ = str.substr(found + 1); + + system_device_ctrl_name_ = system_device_name_ + "-ctrl"; +} + +class SnapuserdTest : public SnapuserdTestBase { public: void SetupDefault(); void SetupOrderedOps(); @@ -77,47 +237,38 @@ class SnapuserdTest : public ::testing::Test { protected: void SetUp() override; - void TearDown() override { Shutdown(); } + void TearDown() override; void SetupImpl(); void SimulateDaemonRestart(); - std::unique_ptr CreateCowDeviceInternal(); - void CreateCowDevice(); void CreateCowDeviceOrderedOps(); void CreateCowDeviceOrderedOpsInverted(); void CreateCowDeviceWithCopyOverlap_1(); void CreateCowDeviceWithCopyOverlap_2(); void SetupDaemon(); - void CreateBaseDevice(); void InitCowDevice(); - void SetDeviceControlName(); void InitDaemon(); void CreateUserDevice(); - unique_ptr base_dev_; unique_ptr dmuser_dev_; - std::string system_device_ctrl_name_; - std::string system_device_name_; - - unique_fd base_fd_; - std::unique_ptr cow_system_; - std::unique_ptr orig_buffer_; std::unique_ptr merged_buffer_; std::unique_ptr handlers_; - size_t size_ = 100_MiB; int cow_num_sectors_; - int total_base_size_; - std::unique_ptr harness_; }; void SnapuserdTest::SetUp() { - harness_ = std::make_unique(); + ASSERT_NO_FATAL_FAILURE(SnapuserdTestBase::SetUp()); handlers_ = std::make_unique(); } +void SnapuserdTest::TearDown() { + SnapuserdTestBase::TearDown(); + Shutdown(); +} + void SnapuserdTest::Shutdown() { ASSERT_TRUE(dmuser_dev_->Destroy()); @@ -165,28 +316,6 @@ void SnapuserdTest::SetupDaemon() { ASSERT_NO_FATAL_FAILURE(InitDaemon()); } -void SnapuserdTest::CreateBaseDevice() { - total_base_size_ = (size_ * 5); - - base_dev_ = harness_->CreateBackingDevice(total_base_size_); - ASSERT_NE(base_dev_, nullptr); - - base_fd_.reset(open(base_dev_->GetPath().c_str(), O_RDWR | O_CLOEXEC)); - ASSERT_GE(base_fd_, 0); - - unique_fd rnd_fd(open("/dev/random", O_RDONLY)); - ASSERT_GE(rnd_fd, 0); - - std::unique_ptr random_buffer = std::make_unique(1_MiB); - - for (size_t j = 0; j < ((total_base_size_) / 1_MiB); j++) { - ASSERT_EQ(ReadFullyAtOffset(rnd_fd, (char*)random_buffer.get(), 1_MiB, 0), true); - ASSERT_EQ(android::base::WriteFully(base_fd_, random_buffer.get(), 1_MiB), true); - } - - ASSERT_EQ(lseek(base_fd_, 0, SEEK_SET), 0); -} - void SnapuserdTest::ReadSnapshotDeviceAndValidate() { unique_fd fd(open(dmuser_dev_->GetPath().c_str(), O_RDONLY)); ASSERT_GE(fd, 0); @@ -218,19 +347,6 @@ void SnapuserdTest::ReadSnapshotDeviceAndValidate() { ASSERT_EQ(memcmp(snapuserd_buffer.get(), (char*)orig_buffer_.get() + (size_ * 4), size_), 0); } -std::unique_ptr SnapuserdTest::CreateCowDeviceInternal() { - std::string path = android::base::GetExecutableDirectory(); - cow_system_ = std::make_unique(path); - - CowOptions options; - options.compression = "gz"; - - unique_fd fd(cow_system_->fd); - cow_system_->fd = -1; - - return CreateCowWriter(kDefaultCowVersion, options, std::move(fd)); -} - void SnapuserdTest::CreateCowDeviceWithCopyOverlap_2() { auto writer = CreateCowDeviceInternal(); ASSERT_NE(writer, nullptr); @@ -427,90 +543,6 @@ void SnapuserdTest::CreateCowDeviceOrderedOps() { } } -void SnapuserdTest::CreateCowDevice() { - unique_fd rnd_fd; - loff_t offset = 0; - - auto writer = CreateCowDeviceInternal(); - ASSERT_NE(writer, nullptr); - - rnd_fd.reset(open("/dev/random", O_RDONLY)); - ASSERT_TRUE(rnd_fd > 0); - - std::unique_ptr random_buffer_1_ = std::make_unique(size_); - - // Fill random data - for (size_t j = 0; j < (size_ / 1_MiB); j++) { - ASSERT_EQ(ReadFullyAtOffset(rnd_fd, (char*)random_buffer_1_.get() + offset, 1_MiB, 0), - true); - - offset += 1_MiB; - } - - size_t num_blocks = size_ / writer->GetBlockSize(); - size_t blk_end_copy = num_blocks * 2; - size_t source_blk = num_blocks - 1; - size_t blk_src_copy = blk_end_copy - 1; - - uint32_t sequence[num_blocks * 2]; - // Sequence for Copy ops - for (int i = 0; i < num_blocks; i++) { - sequence[i] = num_blocks - 1 - i; - } - // Sequence for Xor ops - for (int i = 0; i < num_blocks; i++) { - sequence[num_blocks + i] = 5 * num_blocks - 1 - i; - } - ASSERT_TRUE(writer->AddSequenceData(2 * num_blocks, sequence)); - - size_t x = num_blocks; - while (1) { - ASSERT_TRUE(writer->AddCopy(source_blk, blk_src_copy)); - x -= 1; - if (x == 0) { - break; - } - source_blk -= 1; - blk_src_copy -= 1; - } - - source_blk = num_blocks; - blk_src_copy = blk_end_copy; - - ASSERT_TRUE(writer->AddRawBlocks(source_blk, random_buffer_1_.get(), size_)); - - size_t blk_zero_copy_start = source_blk + num_blocks; - size_t blk_zero_copy_end = blk_zero_copy_start + num_blocks; - - ASSERT_TRUE(writer->AddZeroBlocks(blk_zero_copy_start, num_blocks)); - - size_t blk_random2_replace_start = blk_zero_copy_end; - - ASSERT_TRUE(writer->AddRawBlocks(blk_random2_replace_start, random_buffer_1_.get(), size_)); - - size_t blk_xor_start = blk_random2_replace_start + num_blocks; - size_t xor_offset = BLOCK_SZ / 2; - ASSERT_TRUE(writer->AddXorBlocks(blk_xor_start, random_buffer_1_.get(), size_, num_blocks, - xor_offset)); - - // Flush operations - ASSERT_TRUE(writer->Finalize()); - // Construct the buffer required for validation - orig_buffer_ = std::make_unique(total_base_size_); - std::string zero_buffer(size_, 0); - ASSERT_EQ(android::base::ReadFullyAtOffset(base_fd_, orig_buffer_.get(), size_, size_), true); - memcpy((char*)orig_buffer_.get() + size_, random_buffer_1_.get(), size_); - memcpy((char*)orig_buffer_.get() + (size_ * 2), (void*)zero_buffer.c_str(), size_); - memcpy((char*)orig_buffer_.get() + (size_ * 3), random_buffer_1_.get(), size_); - ASSERT_EQ(android::base::ReadFullyAtOffset(base_fd_, &orig_buffer_.get()[size_ * 4], size_, - size_ + xor_offset), - true); - for (int i = 0; i < size_; i++) { - orig_buffer_.get()[(size_ * 4) + i] = - (uint8_t)(orig_buffer_.get()[(size_ * 4) + i] ^ random_buffer_1_.get()[i]); - } -} - void SnapuserdTest::InitCowDevice() { bool use_iouring = true; if (FLAGS_force_config == "iouring_disabled") { @@ -529,18 +561,6 @@ void SnapuserdTest::InitCowDevice() { #endif } -void SnapuserdTest::SetDeviceControlName() { - system_device_name_.clear(); - system_device_ctrl_name_.clear(); - - std::string str(cow_system_->path); - std::size_t found = str.find_last_of("/\\"); - ASSERT_NE(found, std::string::npos); - system_device_name_ = str.substr(found + 1); - - system_device_ctrl_name_ = system_device_name_ + "-ctrl"; -} - void SnapuserdTest::CreateUserDevice() { auto dev_sz = base_dev_->GetSize(); ASSERT_NE(dev_sz, 0);