Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c4a5576f authored by Akilesh Kailash's avatar Akilesh Kailash
Browse files

libsnapshot: Test batch writes and threaded compression



Test all compression algorithms.

Bug: 254188450
Test: cow_api_test
Change-Id: I977e631402eb2dfaa76205f5d8cb955e6d3bddbb
Signed-off-by: default avatarAkilesh Kailash <akailash@google.com>
parent 4bc81b40
Loading
Loading
Loading
Loading
+144 −0
Original line number Diff line number Diff line
@@ -298,6 +298,150 @@ TEST_F(CowTest, CompressGz) {
    ASSERT_TRUE(iter->Done());
}

class CompressionRWTest : public CowTest, public testing::WithParamInterface<const char*> {};

TEST_P(CompressionRWTest, ThreadedBatchWrites) {
    CowOptions options;
    options.compression = GetParam();
    options.num_compress_threads = 2;

    CowWriter writer(options);

    ASSERT_TRUE(writer.Initialize(cow_->fd));

    std::string xor_data = "This is test data-1. Testing xor";
    xor_data.resize(options.block_size, '\0');
    ASSERT_TRUE(writer.AddXorBlocks(50, xor_data.data(), xor_data.size(), 24, 10));

    std::string data = "This is test data-2. Testing replace ops";
    data.resize(options.block_size * 2048, '\0');
    ASSERT_TRUE(writer.AddRawBlocks(100, data.data(), data.size()));

    std::string data2 = "This is test data-3. Testing replace ops";
    data2.resize(options.block_size * 259, '\0');
    ASSERT_TRUE(writer.AddRawBlocks(6000, data2.data(), data2.size()));

    std::string data3 = "This is test data-4. Testing replace ops";
    data3.resize(options.block_size, '\0');
    ASSERT_TRUE(writer.AddRawBlocks(9000, data3.data(), data3.size()));

    ASSERT_TRUE(writer.Finalize());

    int expected_blocks = (1 + 2048 + 259 + 1);
    ASSERT_EQ(lseek(cow_->fd, 0, SEEK_SET), 0);

    CowReader reader;
    ASSERT_TRUE(reader.Parse(cow_->fd));

    auto iter = reader.GetOpIter();
    ASSERT_NE(iter, nullptr);

    int total_blocks = 0;
    while (!iter->Done()) {
        auto op = &iter->Get();

        if (op->type == kCowXorOp) {
            total_blocks += 1;
            StringSink sink;
            ASSERT_EQ(op->new_block, 50);
            ASSERT_EQ(op->source, 98314);  // 4096 * 24 + 10
            ASSERT_TRUE(reader.ReadData(*op, &sink));
            ASSERT_EQ(sink.stream(), xor_data);
        }

        if (op->type == kCowReplaceOp) {
            total_blocks += 1;
            if (op->new_block == 100) {
                StringSink sink;
                ASSERT_TRUE(reader.ReadData(*op, &sink));
                data.resize(options.block_size);
                ASSERT_EQ(sink.stream(), data);
            }
            if (op->new_block == 6000) {
                StringSink sink;
                ASSERT_TRUE(reader.ReadData(*op, &sink));
                data2.resize(options.block_size);
                ASSERT_EQ(sink.stream(), data2);
            }
            if (op->new_block == 9000) {
                StringSink sink;
                ASSERT_TRUE(reader.ReadData(*op, &sink));
                ASSERT_EQ(sink.stream(), data3);
            }
        }

        iter->Next();
    }

    ASSERT_EQ(total_blocks, expected_blocks);
}

TEST_P(CompressionRWTest, NoBatchWrites) {
    CowOptions options;
    options.compression = GetParam();
    options.num_compress_threads = 1;
    options.cluster_ops = 0;

    CowWriter writer(options);

    ASSERT_TRUE(writer.Initialize(cow_->fd));

    std::string data = "Testing replace ops without batch writes";
    data.resize(options.block_size * 1024, '\0');
    ASSERT_TRUE(writer.AddRawBlocks(50, data.data(), data.size()));

    std::string data2 = "Testing odd blocks without batch writes";
    data2.resize(options.block_size * 111, '\0');
    ASSERT_TRUE(writer.AddRawBlocks(3000, data2.data(), data2.size()));

    std::string data3 = "Testing single 4k block";
    data3.resize(options.block_size, '\0');
    ASSERT_TRUE(writer.AddRawBlocks(5000, data3.data(), data3.size()));

    ASSERT_TRUE(writer.Finalize());

    int expected_blocks = (1024 + 111 + 1);
    ASSERT_EQ(lseek(cow_->fd, 0, SEEK_SET), 0);

    CowReader reader;
    ASSERT_TRUE(reader.Parse(cow_->fd));

    auto iter = reader.GetOpIter();
    ASSERT_NE(iter, nullptr);

    int total_blocks = 0;
    while (!iter->Done()) {
        auto op = &iter->Get();

        if (op->type == kCowReplaceOp) {
            total_blocks += 1;
            if (op->new_block == 50) {
                StringSink sink;
                ASSERT_TRUE(reader.ReadData(*op, &sink));
                data.resize(options.block_size);
                ASSERT_EQ(sink.stream(), data);
            }
            if (op->new_block == 3000) {
                StringSink sink;
                ASSERT_TRUE(reader.ReadData(*op, &sink));
                data2.resize(options.block_size);
                ASSERT_EQ(sink.stream(), data2);
            }
            if (op->new_block == 5000) {
                StringSink sink;
                ASSERT_TRUE(reader.ReadData(*op, &sink));
                ASSERT_EQ(sink.stream(), data3);
            }
        }

        iter->Next();
    }

    ASSERT_EQ(total_blocks, expected_blocks);
}

INSTANTIATE_TEST_SUITE_P(CowApi, CompressionRWTest, testing::Values("none", "gz", "brotli", "lz4"));

TEST_F(CowTest, ClusterCompressGz) {
    CowOptions options;
    options.compression = "gz";