File: BigBlobsTest.cpp

package info (click to toggle)
cryfs 1.0.1-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 28,412 kB
  • sloc: cpp: 150,187; asm: 10,493; python: 1,455; javascript: 65; sh: 50; makefile: 17; xml: 7
file content (138 lines) | stat: -rw-r--r-- 5,441 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
#include <gtest/gtest.h>
#include <blockstore/implementations/compressing/CompressingBlockStore.h>
#include <blockstore/implementations/compressing/compressors/RunLengthEncoding.h>
#include <blockstore/implementations/inmemory/InMemoryBlockStore2.h>
#include <blockstore/implementations/low2highlevel/LowToHighLevelBlockStore.h>
#include <cpp-utils/data/DataFixture.h>
#include <cpp-utils/data/Data.h>

#include "blobstore/implementations/onblocks/BlobOnBlocks.h"
#include "blobstore/implementations/onblocks/BlobStoreOnBlocks.h"
#include <cstddef>

using namespace blobstore;
using namespace blobstore::onblocks;
using cpputils::unique_ref;
using cpputils::make_unique_ref;
using cpputils::DataFixture;
using cpputils::Data;
using blockstore::inmemory::InMemoryBlockStore2;
using blockstore::lowtohighlevel::LowToHighLevelBlockStore;
using blockstore::compressing::CompressingBlockStore;
using blockstore::compressing::RunLengthEncoding;

// Test cases, ensuring that big blobs (>4G) work (i.e. testing that we don't use any 32bit variables for blob size, etc.)
class BigBlobsTest : public ::testing::Test {
public:
    static constexpr size_t BLOCKSIZE = 32 * 1024;
    static constexpr uint64_t SMALL_BLOB_SIZE = UINT64_C(1024)*1024*1024*3.95; // 3.95 GB (<4GB)
    static constexpr uint64_t LARGE_BLOB_SIZE = UINT64_C(1024)*1024*1024*4.05; // 4.05 GB (>4GB)

    static constexpr uint64_t max_uint_32 = std::numeric_limits<uint32_t>::max();
    static_assert(SMALL_BLOB_SIZE < max_uint_32, "LARGE_BLOB_SIZE should need 64bit or the test case is mute");
    static_assert(LARGE_BLOB_SIZE > max_uint_32, "LARGE_BLOB_SIZE should need 64bit or the test case is mute");

    unique_ref<BlobStore> blobStore = make_unique_ref<BlobStoreOnBlocks>(make_unique_ref<CompressingBlockStore<RunLengthEncoding>>(make_unique_ref<LowToHighLevelBlockStore>(make_unique_ref<InMemoryBlockStore2>())), BLOCKSIZE);
    unique_ref<Blob> blob = blobStore->create();
};

constexpr size_t BigBlobsTest::BLOCKSIZE;
constexpr uint64_t BigBlobsTest::SMALL_BLOB_SIZE;
constexpr uint64_t BigBlobsTest::LARGE_BLOB_SIZE;

TEST_F(BigBlobsTest, Resize) {
    //These operations are in one test case and not in many small ones, because it takes quite long to create a >4GB blob.

    //Resize to >4GB
    blob->resize(LARGE_BLOB_SIZE);
    EXPECT_EQ(LARGE_BLOB_SIZE, blob->size());

    //Grow while >4GB
    blob->resize(LARGE_BLOB_SIZE + 1024);
    EXPECT_EQ(LARGE_BLOB_SIZE + 1024, blob->size());

    //Shrink while >4GB
    blob->resize(LARGE_BLOB_SIZE);
    EXPECT_EQ(LARGE_BLOB_SIZE, blob->size());

    //Shrink to <4GB
    blob->resize(SMALL_BLOB_SIZE);
    EXPECT_EQ(SMALL_BLOB_SIZE, blob->size());

    //Grow to >4GB
    blob->resize(LARGE_BLOB_SIZE);
    EXPECT_EQ(LARGE_BLOB_SIZE, blob->size());

    //Flush >4GB blob
    blob->flush();

    //Destruct >4GB blob
    auto blockId = blob->blockId();
    cpputils::destruct(std::move(blob));

    //Load >4GB blob
    blob = blobStore->load(blockId).value();

    //Remove >4GB blob
    blobStore->remove(std::move(blob));
}

TEST_F(BigBlobsTest, GrowByWriting_Crossing4GBBorder) {
    Data fixture = DataFixture::generate(2*(LARGE_BLOB_SIZE-SMALL_BLOB_SIZE));
    blob->write(fixture.data(), SMALL_BLOB_SIZE, fixture.size());

    EXPECT_EQ(LARGE_BLOB_SIZE+(LARGE_BLOB_SIZE-SMALL_BLOB_SIZE), blob->size());

    Data loaded(fixture.size());
    blob->read(loaded.data(), SMALL_BLOB_SIZE, loaded.size());
    EXPECT_EQ(0, std::memcmp(loaded.data(), fixture.data(), loaded.size()));
}

TEST_F(BigBlobsTest, GrowByWriting_Outside4GBBorder_StartingSizeZero) {
    Data fixture = DataFixture::generate(1024);
    blob->write(fixture.data(), LARGE_BLOB_SIZE, fixture.size());

    EXPECT_EQ(LARGE_BLOB_SIZE+1024, blob->size());

    Data loaded(fixture.size());
    blob->read(loaded.data(), LARGE_BLOB_SIZE, loaded.size());
    EXPECT_EQ(0, std::memcmp(loaded.data(), fixture.data(), loaded.size()));
}

TEST_F(BigBlobsTest, GrowByWriting_Outside4GBBorder_StartingSizeOutside4GBBorder) {
    blob->resize(LARGE_BLOB_SIZE);
    Data fixture = DataFixture::generate(1024);
    blob->write(fixture.data(), LARGE_BLOB_SIZE+1024, fixture.size());

    EXPECT_EQ(LARGE_BLOB_SIZE+2048, blob->size());

    Data loaded(fixture.size());
    blob->read(loaded.data(), LARGE_BLOB_SIZE+1024, loaded.size());
    EXPECT_EQ(0, std::memcmp(loaded.data(), fixture.data(), loaded.size()));
}

TEST_F(BigBlobsTest, ReadWriteAfterGrown_Crossing4GBBorder) {
    blob->resize(LARGE_BLOB_SIZE+(LARGE_BLOB_SIZE-SMALL_BLOB_SIZE)+1024);
    Data fixture = DataFixture::generate(2*(LARGE_BLOB_SIZE-SMALL_BLOB_SIZE));
    blob->write(fixture.data(), SMALL_BLOB_SIZE, fixture.size());

    EXPECT_EQ(LARGE_BLOB_SIZE+(LARGE_BLOB_SIZE-SMALL_BLOB_SIZE)+1024, blob->size());

    Data loaded(fixture.size());
    blob->read(loaded.data(), SMALL_BLOB_SIZE, loaded.size());
    EXPECT_EQ(0, std::memcmp(loaded.data(), fixture.data(), loaded.size()));
}

TEST_F(BigBlobsTest, ReadWriteAfterGrown_Outside4GBBorder) {
    blob->resize(LARGE_BLOB_SIZE+2048);
    Data fixture = DataFixture::generate(1024);
    blob->write(fixture.data(), LARGE_BLOB_SIZE, fixture.size());

    EXPECT_EQ(LARGE_BLOB_SIZE+2048, blob->size());

    Data loaded(fixture.size());
    blob->read(loaded.data(), LARGE_BLOB_SIZE, loaded.size());
    EXPECT_EQ(0, std::memcmp(loaded.data(), fixture.data(), loaded.size()));
}

//TODO Test Blob::readAll (only on 64bit systems)