From 2b112c7fdbaf999400f538d569f801fb5e8e0055 Mon Sep 17 00:00:00 2001 From: Sebastian Messmer Date: Sat, 6 Dec 2014 21:28:03 +0100 Subject: [PATCH] Generalized BlobStoreTest, added more test cases there --- .../implementations/inmemory/InMemoryBlob.cpp | 1 + .../OnDiskBlobTest/OnDiskBlobCreateTest.cpp | 20 +- .../OnDiskBlobTest/OnDiskBlobFlushTest.cpp | 8 + src/test/blobstore/testutils/BlobStoreTest.h | 198 +++++++++++++++--- 4 files changed, 186 insertions(+), 41 deletions(-) diff --git a/src/blobstore/implementations/inmemory/InMemoryBlob.cpp b/src/blobstore/implementations/inmemory/InMemoryBlob.cpp index 9d20b792..5722be4a 100644 --- a/src/blobstore/implementations/inmemory/InMemoryBlob.cpp +++ b/src/blobstore/implementations/inmemory/InMemoryBlob.cpp @@ -17,6 +17,7 @@ namespace inmemory { InMemoryBlob::InMemoryBlob(size_t size) : _data(make_shared(size)) { + _data->FillWithZeroes(); } InMemoryBlob::InMemoryBlob(const InMemoryBlob &rhs) diff --git a/src/test/blobstore/implementations/ondisk/OnDiskBlobTest/OnDiskBlobCreateTest.cpp b/src/test/blobstore/implementations/ondisk/OnDiskBlobTest/OnDiskBlobCreateTest.cpp index c8a2ee98..092fafab 100644 --- a/src/test/blobstore/implementations/ondisk/OnDiskBlobTest/OnDiskBlobCreateTest.cpp +++ b/src/test/blobstore/implementations/ondisk/OnDiskBlobTest/OnDiskBlobCreateTest.cpp @@ -58,15 +58,19 @@ TEST_P(OnDiskBlobCreateSizeTest, OnDiskSizeIsCorrect) { EXPECT_EQ(GetParam(), fileContent.size()); } -TEST_P(OnDiskBlobCreateSizeTest, InMemorySizeIsCorrect) { - EXPECT_EQ(GetParam(), blob->size()); -} - -TEST_P(OnDiskBlobCreateSizeTest, InMemoryBlobIsZeroedOut) { - EXPECT_EQ(0, std::memcmp(ZEROES.data(), blob->data(), blob->size())); -} - TEST_P(OnDiskBlobCreateSizeTest, OnDiskBlobIsZeroedOut) { Data fileContent = Data::LoadFromFile(file.path()); EXPECT_EQ(0, std::memcmp(ZEROES.data(), fileContent.data(), fileContent.size())); } + +// This test is also tested by OnDiskBlobStoreTest, but there the blob is created using the BlobStore interface. +// Here, we create it using OnDiskBlob::CreateOnDisk() +TEST_P(OnDiskBlobCreateSizeTest, InMemorySizeIsCorrect) { + EXPECT_EQ(GetParam(), blob->size()); +} + +// This test is also tested by OnDiskBlobStoreTest, but there the blob is created using the BlobStore interface. +// Here, we create it using OnDiskBlob::CreateOnDisk() +TEST_P(OnDiskBlobCreateSizeTest, InMemoryBlobIsZeroedOut) { + EXPECT_EQ(0, std::memcmp(ZEROES.data(), blob->data(), blob->size())); +} diff --git a/src/test/blobstore/implementations/ondisk/OnDiskBlobTest/OnDiskBlobFlushTest.cpp b/src/test/blobstore/implementations/ondisk/OnDiskBlobTest/OnDiskBlobFlushTest.cpp index b2f9969c..7afa5609 100644 --- a/src/test/blobstore/implementations/ondisk/OnDiskBlobTest/OnDiskBlobFlushTest.cpp +++ b/src/test/blobstore/implementations/ondisk/OnDiskBlobTest/OnDiskBlobFlushTest.cpp @@ -55,6 +55,8 @@ public: }; INSTANTIATE_TEST_CASE_P(OnDiskBlobFlushTest, OnDiskBlobFlushTest, Values((size_t)0, (size_t)1, (size_t)1024, (size_t)4096, (size_t)10*1024*1024)); +// This test is also tested by OnDiskBlobStoreTest, but there the blob is created using the BlobStore interface. +// Here, we create it using OnDiskBlob::CreateOnDisk() TEST_P(OnDiskBlobFlushTest, AfterCreate_FlushingDoesntChangeBlob) { auto blob = CreateBlob(); WriteDataToBlob(blob); @@ -63,6 +65,8 @@ TEST_P(OnDiskBlobFlushTest, AfterCreate_FlushingDoesntChangeBlob) { EXPECT_BLOB_DATA_CORRECT(blob); } +// This test is also tested by OnDiskBlobStoreTest, but there the blob is created using the BlobStore interface. +// Here, we create it using OnDiskBlob::CreateOnDisk() / OnDiskBlob::LoadFromDisk() TEST_P(OnDiskBlobFlushTest, AfterLoad_FlushingDoesntChangeBlob) { auto blob = CreateBlobAndLoadItFromDisk(); WriteDataToBlob(blob); @@ -87,6 +91,8 @@ TEST_P(OnDiskBlobFlushTest, AfterLoad_FlushingWritesCorrectData) { EXPECT_STORED_FILE_DATA_CORRECT(); } +// This test is also tested by OnDiskBlobStoreTest, but there it can only checks blob content by loading it again. +// Here, we check the content on disk. TEST_P(OnDiskBlobFlushTest, AfterCreate_FlushesWhenDestructed) { { auto blob = CreateBlob(); @@ -95,6 +101,8 @@ TEST_P(OnDiskBlobFlushTest, AfterCreate_FlushesWhenDestructed) { EXPECT_STORED_FILE_DATA_CORRECT(); } +// This test is also tested by OnDiskBlobStoreTest, but there it can only checks blob content by loading it again. +// Here, we check the content on disk. TEST_P(OnDiskBlobFlushTest, AfterLoad_FlushesWhenDestructed) { { auto blob = CreateBlobAndLoadItFromDisk(); diff --git a/src/test/blobstore/testutils/BlobStoreTest.h b/src/test/blobstore/testutils/BlobStoreTest.h index 060f9c4e..ff689b11 100644 --- a/src/test/blobstore/testutils/BlobStoreTest.h +++ b/src/test/blobstore/testutils/BlobStoreTest.h @@ -5,6 +5,7 @@ #include "test/testutils/TempDir.h" #include "test/testutils/VirtualTestFile.h" #include "blobstore/interface/BlobStore.h" +#include "blobstore/utils/RandomKeyGenerator.h" class BlobStoreTestFixture { public: @@ -22,67 +23,183 @@ public: const std::vector SIZES = {0, 1, 1024, 4096, 10*1024*1024}; ConcreteBlobStoreTestFixture fixture; +}; - void TestCreateBlobAndCheckSize(size_t size) { - auto blobStore = fixture.createBlobStore(); +template +class BlobStoreSizeParameterizedTest { +public: + BlobStoreSizeParameterizedTest(ConcreateBlobStoreTestFixture &fixture, size_t size_): blobStore(fixture.createBlobStore()), size(size_) {} + + void TestCreatedBlobHasCorrectSize() { auto blob = blobStore->create(size); EXPECT_EQ(size, blob.blob->size()); } - void TestLoadedBlobIsCorrect(size_t size) { - auto blobStore = fixture.createBlobStore(); + void TestLoadingUnchangedBlobHasCorrectSize() { + auto blob = blobStore->create(size); + auto loaded_blob = blobStore->load(blob.key); + EXPECT_EQ(size, loaded_blob->size()); + } + + void TestCreatedBlobIsZeroedOut() { + auto blob = blobStore->create(size); + EXPECT_EQ(0, std::memcmp(ZEROES(size).data(), blob.blob->data(), size)); + } + + void TestLoadingUnchangedBlobIsZeroedOut() { + auto blob = blobStore->create(size); + auto loaded_blob = blobStore->load(blob.key); + EXPECT_EQ(0, std::memcmp(ZEROES(size).data(), loaded_blob->data(), size)); + } + + void TestLoadedBlobIsCorrect() { VirtualTestFile randomData(size); - auto loaded_blob = StoreDataToBlobAndLoadIt(blobStore.get(), randomData); + auto loaded_blob = StoreDataToBlobAndLoadIt(randomData); EXPECT_EQ(size, loaded_blob->size()); EXPECT_EQ(0, std::memcmp(randomData.data(), loaded_blob->data(), size)); } - std::unique_ptr StoreDataToBlobAndLoadIt(blobstore::BlobStore *blobStore, const VirtualTestFile &data) { - std::string key = StoreDataToBlobAndGetKey(blobStore, data); + void TestLoadedBlobIsCorrectWhenLoadedDirectlyAfterFlushing() { + VirtualTestFile randomData(size); + auto loaded_blob = StoreDataToBlobAndLoadItDirectlyAfterFlushing(randomData); + EXPECT_EQ(size, loaded_blob->size()); + EXPECT_EQ(0, std::memcmp(randomData.data(), loaded_blob->data(), size)); + } + + void TestAfterCreate_FlushingDoesntChangeBlob() { + VirtualTestFile randomData(size); + auto blob = CreateBlob(); + WriteDataToBlob(blob.get(), randomData); + blob->flush(); + + EXPECT_BLOB_DATA_CORRECT(*blob, randomData); + } + + void TestAfterLoad_FlushingDoesntChangeBlob() { + VirtualTestFile randomData(size); + auto blob = CreateBlobAndLoadIt(); + WriteDataToBlob(blob.get(), randomData); + blob->flush(); + + EXPECT_BLOB_DATA_CORRECT(*blob, randomData); + } + + void TestAfterCreate_FlushesWhenDestructed() { + VirtualTestFile randomData(size); + std::string key; + { + auto blob = blobStore->create(size); + key = blob.key; + WriteDataToBlob(blob.blob.get(), randomData); + } + auto loaded_blob = blobStore->load(key); + EXPECT_BLOB_DATA_CORRECT(*loaded_blob, randomData); + } + + void TestAfterLoad_FlushesWhenDestructed() { + VirtualTestFile randomData(size); + std::string key; + { + key = blobStore->create(size).key; + auto blob = blobStore->load(key); + WriteDataToBlob(blob.get(), randomData); + } + auto loaded_blob = blobStore->load(key); + EXPECT_BLOB_DATA_CORRECT(*loaded_blob, randomData); + } + + void TestLoadNonExistingBlobWithDefinitelyValidKey() { + //TODO Specify loading error behavior more precise and test for concrete exception (or whatever behavior we choose) + EXPECT_ANY_THROW( + blobStore->load(blobstore::RandomKeyGenerator::singleton().create()); + ); + } + + void TestLoadNonExistingBlobWithMaybeInvalidKey() { + //TODO Specify loading error behavior more precise and test for concrete exception (or whatever behavior we choose) + EXPECT_ANY_THROW( + blobStore->load("not-existing-key"); + ); + } + + void TestLoadNonExistingBlobWithEmptyKey() { + //TODO Specify loading error behavior more precise and test for concrete exception (or whatever behavior we choose) + EXPECT_ANY_THROW( + blobStore->load(""); + ); + } + +private: + std::unique_ptr blobStore; + size_t size; + + blobstore::Data ZEROES(size_t size) { + blobstore::Data ZEROES(size); + ZEROES.FillWithZeroes(); + return ZEROES; + } + + std::unique_ptr StoreDataToBlobAndLoadIt(const VirtualTestFile &data) { + std::string key = StoreDataToBlobAndGetKey(data); return blobStore->load(key); } - std::string StoreDataToBlobAndGetKey(blobstore::BlobStore *blobStore, const VirtualTestFile &data) { + std::string StoreDataToBlobAndGetKey(const VirtualTestFile &data) { auto blob = blobStore->create(data.size()); std::memcpy(blob.blob->data(), data.data(), data.size()); return blob.key; } - void TestLoadedBlobIsCorrectWhenLoadedDirectlyAfterFlushing(size_t size) { - auto blobStore = fixture.createBlobStore(); - VirtualTestFile randomData(size); - auto loaded_blob = StoreDataToBlobAndLoadItDirectlyAfterFlushing(blobStore.get(), randomData); - EXPECT_EQ(size, loaded_blob->size()); - EXPECT_EQ(0, std::memcmp(randomData.data(), loaded_blob->data(), size)); - } - - std::unique_ptr StoreDataToBlobAndLoadItDirectlyAfterFlushing(blobstore::BlobStore *blobStore, const VirtualTestFile &data) { + std::unique_ptr StoreDataToBlobAndLoadItDirectlyAfterFlushing(const VirtualTestFile &data) { auto blob = blobStore->create(data.size()); std::memcpy(blob.blob->data(), data.data(), data.size()); blob.blob->flush(); return blobStore->load(blob.key); } + + std::unique_ptr CreateBlobAndLoadIt() { + std::string key = blobStore->create(size).key; + return blobStore->load(key); + } + + std::unique_ptr CreateBlob() { + return blobStore->create(size).blob; + } + + void WriteDataToBlob(blobstore::Blob *blob, const VirtualTestFile &randomData) { + std::memcpy(blob->data(), randomData.data(), randomData.size()); + } + + void EXPECT_BLOB_DATA_CORRECT(const blobstore::Blob &blob, const VirtualTestFile &randomData) { + EXPECT_EQ(randomData.size(), blob.size()); + EXPECT_EQ(0, std::memcmp(randomData.data(), blob.data(), randomData.size())); + } }; TYPED_TEST_CASE_P(BlobStoreTest); -TYPED_TEST_P(BlobStoreTest, CreateBlobAndCheckSize) { - for (auto size: this->SIZES) { - this->TestCreateBlobAndCheckSize(size); - } -} +#define TYPED_TEST_P_FOR_ALL_SIZES(TestName) \ + TYPED_TEST_P(BlobStoreTest, TestName) { \ + for (auto size: this->SIZES) { \ + BlobStoreSizeParameterizedTest(this->fixture, size) \ + .Test##TestName(); \ + } \ + } \ -TYPED_TEST_P(BlobStoreTest, LoadedBlobIsCorrect) { - for (auto size: this->SIZES) { - this->TestLoadedBlobIsCorrect(size); - } -} -TYPED_TEST_P(BlobStoreTest, LoadedBlobIsCorrectWhenLoadedDirectlyAfterFlushing) { - for (auto size: this->SIZES) { - this->TestLoadedBlobIsCorrectWhenLoadedDirectlyAfterFlushing(size); - } -} +TYPED_TEST_P_FOR_ALL_SIZES(CreatedBlobHasCorrectSize); +TYPED_TEST_P_FOR_ALL_SIZES(LoadingUnchangedBlobHasCorrectSize); +TYPED_TEST_P_FOR_ALL_SIZES(CreatedBlobIsZeroedOut); +TYPED_TEST_P_FOR_ALL_SIZES(LoadingUnchangedBlobIsZeroedOut); +TYPED_TEST_P_FOR_ALL_SIZES(LoadedBlobIsCorrect); +TYPED_TEST_P_FOR_ALL_SIZES(LoadedBlobIsCorrectWhenLoadedDirectlyAfterFlushing); +TYPED_TEST_P_FOR_ALL_SIZES(AfterCreate_FlushingDoesntChangeBlob); +TYPED_TEST_P_FOR_ALL_SIZES(AfterLoad_FlushingDoesntChangeBlob); +TYPED_TEST_P_FOR_ALL_SIZES(AfterCreate_FlushesWhenDestructed); +TYPED_TEST_P_FOR_ALL_SIZES(AfterLoad_FlushesWhenDestructed); +TYPED_TEST_P_FOR_ALL_SIZES(LoadNonExistingBlobWithDefinitelyValidKey); +TYPED_TEST_P_FOR_ALL_SIZES(LoadNonExistingBlobWithMaybeInvalidKey); +TYPED_TEST_P_FOR_ALL_SIZES(LoadNonExistingBlobWithEmptyKey); TYPED_TEST_P(BlobStoreTest, TwoCreatedBlobsHaveDifferentKeys) { auto blobStore = this->fixture.createBlobStore(); @@ -91,7 +208,22 @@ TYPED_TEST_P(BlobStoreTest, TwoCreatedBlobsHaveDifferentKeys) { EXPECT_NE(blob1.key, blob2.key); } -REGISTER_TYPED_TEST_CASE_P(BlobStoreTest, CreateBlobAndCheckSize, LoadedBlobIsCorrect, LoadedBlobIsCorrectWhenLoadedDirectlyAfterFlushing, TwoCreatedBlobsHaveDifferentKeys); +REGISTER_TYPED_TEST_CASE_P(BlobStoreTest, + CreatedBlobHasCorrectSize, + LoadingUnchangedBlobHasCorrectSize, + CreatedBlobIsZeroedOut, + LoadingUnchangedBlobIsZeroedOut, + LoadedBlobIsCorrect, + LoadedBlobIsCorrectWhenLoadedDirectlyAfterFlushing, + AfterCreate_FlushingDoesntChangeBlob, + AfterLoad_FlushingDoesntChangeBlob, + AfterCreate_FlushesWhenDestructed, + AfterLoad_FlushesWhenDestructed, + LoadNonExistingBlobWithDefinitelyValidKey, + LoadNonExistingBlobWithMaybeInvalidKey, + LoadNonExistingBlobWithEmptyKey, + TwoCreatedBlobsHaveDifferentKeys +); #endif