snapuserd: Add unit tests for ReadWorker::ReadAlignedSector.
These tests are for real bugs that were previously not testable. Bug: 288273605 Test: snapuserd_test Change-Id: I9e9af999e4f5f988f4538750eba109f6b2fe448c
This commit is contained in:
parent
0ec9b0eb92
commit
6aec095d68
4 changed files with 119 additions and 2 deletions
|
@ -64,7 +64,7 @@ std::unique_ptr<IBlockServer> TestBlockServerOpener::Open(IBlockServer::Delegate
|
|||
return std::make_unique<TestBlockServer>(queue_, misc_name_);
|
||||
}
|
||||
|
||||
std::shared_ptr<IBlockServerOpener> TestBlockServerFactory::CreateOpener(
|
||||
std::shared_ptr<TestBlockServerOpener> TestBlockServerFactory::CreateTestOpener(
|
||||
const std::string& misc_name) {
|
||||
if (queues_.count(misc_name)) {
|
||||
LOG(ERROR) << "Cannot create opener for " << misc_name << ", already exists";
|
||||
|
@ -75,6 +75,11 @@ std::shared_ptr<IBlockServerOpener> TestBlockServerFactory::CreateOpener(
|
|||
return std::make_shared<TestBlockServerOpener>(queue, misc_name);
|
||||
}
|
||||
|
||||
std::shared_ptr<IBlockServerOpener> TestBlockServerFactory::CreateOpener(
|
||||
const std::string& misc_name) {
|
||||
return CreateTestOpener(misc_name);
|
||||
}
|
||||
|
||||
bool TestBlockServerFactory::DeleteQueue(const std::string& misc_name) {
|
||||
auto iter = queues_.find(misc_name);
|
||||
if (iter == queues_.end()) {
|
||||
|
|
|
@ -68,6 +68,7 @@ class TestBlockServerOpener final : public IBlockServerOpener {
|
|||
class TestBlockServerFactory final : public IBlockServerFactory {
|
||||
public:
|
||||
std::shared_ptr<IBlockServerOpener> CreateOpener(const std::string& misc_name) override;
|
||||
std::shared_ptr<TestBlockServerOpener> CreateTestOpener(const std::string& misc_name);
|
||||
bool DeleteQueue(const std::string& misc_name);
|
||||
|
||||
private:
|
||||
|
|
|
@ -33,9 +33,11 @@ class ReadWorker : public Worker, public IBlockServer::Delegate {
|
|||
bool Run();
|
||||
bool Init() override;
|
||||
void CloseFds() override;
|
||||
bool RequestSectors(uint64_t sector, uint64_t size) override;
|
||||
|
||||
IBlockServer* block_server() const { return block_server_.get(); }
|
||||
|
||||
private:
|
||||
bool RequestSectors(uint64_t sector, uint64_t size) override;
|
||||
bool SendBufferedIo();
|
||||
|
||||
bool ProcessCowOp(const CowOperation* cow_op, void* buffer);
|
||||
|
|
|
@ -39,6 +39,8 @@
|
|||
#include <snapuserd/dm_user_block_server.h>
|
||||
#include <storage_literals/storage_literals.h>
|
||||
#include "handler_manager.h"
|
||||
#include "merge_worker.h"
|
||||
#include "read_worker.h"
|
||||
#include "snapuserd_core.h"
|
||||
#include "testing/dm_user_harness.h"
|
||||
#include "testing/host_harness.h"
|
||||
|
@ -56,6 +58,9 @@ using LoopDevice = android::dm::LoopDevice;
|
|||
using namespace std::chrono_literals;
|
||||
using namespace android::dm;
|
||||
using namespace std;
|
||||
using testing::AssertionFailure;
|
||||
using testing::AssertionResult;
|
||||
using testing::AssertionSuccess;
|
||||
|
||||
class SnapuserdTestBase : public ::testing::Test {
|
||||
protected:
|
||||
|
@ -776,6 +781,110 @@ TEST_F(SnapuserdTest, Snapshot_Merge_Crash_Random_Inverted) {
|
|||
ValidateMerge();
|
||||
}
|
||||
|
||||
class HandlerTest : public SnapuserdTestBase {
|
||||
protected:
|
||||
void SetUp() override;
|
||||
void TearDown() override;
|
||||
|
||||
AssertionResult ReadSectors(sector_t sector, uint64_t size, void* buffer);
|
||||
|
||||
TestBlockServerFactory factory_;
|
||||
std::shared_ptr<TestBlockServerOpener> opener_;
|
||||
std::shared_ptr<SnapshotHandler> handler_;
|
||||
std::unique_ptr<ReadWorker> read_worker_;
|
||||
TestBlockServer* block_server_;
|
||||
std::future<bool> handler_thread_;
|
||||
};
|
||||
|
||||
void HandlerTest::SetUp() {
|
||||
ASSERT_NO_FATAL_FAILURE(SnapuserdTestBase::SetUp());
|
||||
ASSERT_NO_FATAL_FAILURE(CreateBaseDevice());
|
||||
ASSERT_NO_FATAL_FAILURE(CreateCowDevice());
|
||||
ASSERT_NO_FATAL_FAILURE(SetDeviceControlName());
|
||||
|
||||
opener_ = factory_.CreateTestOpener(system_device_ctrl_name_);
|
||||
ASSERT_NE(opener_, nullptr);
|
||||
|
||||
handler_ = std::make_shared<SnapshotHandler>(system_device_ctrl_name_, cow_system_->path,
|
||||
base_dev_->GetPath(), base_dev_->GetPath(),
|
||||
opener_, 1, false, false);
|
||||
ASSERT_TRUE(handler_->InitCowDevice());
|
||||
ASSERT_TRUE(handler_->InitializeWorkers());
|
||||
|
||||
read_worker_ = std::make_unique<ReadWorker>(cow_system_->path, base_dev_->GetPath(),
|
||||
system_device_ctrl_name_, base_dev_->GetPath(),
|
||||
handler_->GetSharedPtr(), opener_);
|
||||
ASSERT_TRUE(read_worker_->Init());
|
||||
block_server_ = static_cast<TestBlockServer*>(read_worker_->block_server());
|
||||
|
||||
handler_thread_ = std::async(std::launch::async, &SnapshotHandler::Start, handler_.get());
|
||||
}
|
||||
|
||||
void HandlerTest::TearDown() {
|
||||
ASSERT_TRUE(factory_.DeleteQueue(system_device_ctrl_name_));
|
||||
ASSERT_TRUE(handler_thread_.get());
|
||||
SnapuserdTestBase::TearDown();
|
||||
}
|
||||
|
||||
AssertionResult HandlerTest::ReadSectors(sector_t sector, uint64_t size, void* buffer) {
|
||||
if (!read_worker_->RequestSectors(sector, size)) {
|
||||
return AssertionFailure() << "request sectors failed";
|
||||
}
|
||||
|
||||
std::string result = std::move(block_server_->sent_io());
|
||||
if (result.size() != size) {
|
||||
return AssertionFailure() << "size mismatch in result, got " << result.size()
|
||||
<< ", expected " << size;
|
||||
}
|
||||
|
||||
memcpy(buffer, result.data(), size);
|
||||
return AssertionSuccess();
|
||||
}
|
||||
|
||||
// This test mirrors ReadSnapshotDeviceAndValidate.
|
||||
TEST_F(HandlerTest, Read) {
|
||||
std::unique_ptr<uint8_t[]> snapuserd_buffer = std::make_unique<uint8_t[]>(size_);
|
||||
|
||||
// COPY
|
||||
loff_t offset = 0;
|
||||
ASSERT_TRUE(ReadSectors(offset / SECTOR_SIZE, size_, snapuserd_buffer.get()));
|
||||
ASSERT_EQ(memcmp(snapuserd_buffer.get(), orig_buffer_.get(), size_), 0);
|
||||
|
||||
// REPLACE
|
||||
offset += size_;
|
||||
ASSERT_TRUE(ReadSectors(offset / SECTOR_SIZE, size_, snapuserd_buffer.get()));
|
||||
ASSERT_EQ(memcmp(snapuserd_buffer.get(), (char*)orig_buffer_.get() + size_, size_), 0);
|
||||
|
||||
// ZERO
|
||||
offset += size_;
|
||||
ASSERT_TRUE(ReadSectors(offset / SECTOR_SIZE, size_, snapuserd_buffer.get()));
|
||||
ASSERT_EQ(memcmp(snapuserd_buffer.get(), (char*)orig_buffer_.get() + (size_ * 2), size_), 0);
|
||||
|
||||
// REPLACE
|
||||
offset += size_;
|
||||
ASSERT_TRUE(ReadSectors(offset / SECTOR_SIZE, size_, snapuserd_buffer.get()));
|
||||
ASSERT_EQ(memcmp(snapuserd_buffer.get(), (char*)orig_buffer_.get() + (size_ * 3), size_), 0);
|
||||
|
||||
// XOR
|
||||
offset += size_;
|
||||
ASSERT_TRUE(ReadSectors(offset / SECTOR_SIZE, size_, snapuserd_buffer.get()));
|
||||
ASSERT_EQ(memcmp(snapuserd_buffer.get(), (char*)orig_buffer_.get() + (size_ * 4), size_), 0);
|
||||
}
|
||||
|
||||
TEST_F(HandlerTest, ReadUnalignedSector) {
|
||||
std::unique_ptr<uint8_t[]> snapuserd_buffer = std::make_unique<uint8_t[]>(BLOCK_SZ);
|
||||
|
||||
ASSERT_TRUE(ReadSectors(1, BLOCK_SZ, snapuserd_buffer.get()));
|
||||
ASSERT_EQ(memcmp(snapuserd_buffer.get(), orig_buffer_.get() + SECTOR_SIZE, BLOCK_SZ), 0);
|
||||
}
|
||||
|
||||
TEST_F(HandlerTest, ReadUnalignedSize) {
|
||||
std::unique_ptr<uint8_t[]> snapuserd_buffer = std::make_unique<uint8_t[]>(SECTOR_SIZE);
|
||||
|
||||
ASSERT_TRUE(ReadSectors(0, SECTOR_SIZE, snapuserd_buffer.get()));
|
||||
ASSERT_EQ(memcmp(snapuserd_buffer.get(), orig_buffer_.get(), SECTOR_SIZE), 0);
|
||||
}
|
||||
|
||||
} // namespace snapshot
|
||||
} // namespace android
|
||||
|
||||
|
|
Loading…
Reference in a new issue