Moved Data, FixedSizeData and DataBlockFixture to cpp-utils

This commit is contained in:
Sebastian Messmer 2015-04-25 02:48:41 +02:00
parent 60442a46f0
commit 59bfddc18f
45 changed files with 170 additions and 855 deletions

View File

@ -9,6 +9,7 @@
using std::unique_ptr;
using std::make_unique;
using cpputils::dynamic_pointer_move;
using cpputils::Data;
namespace blockstore {
namespace caching {

View File

@ -14,14 +14,14 @@ public:
CachingBlockStore(std::unique_ptr<BlockStore> baseBlockStore);
Key createKey() override;
std::unique_ptr<Block> tryCreate(const Key &key, Data data) override;
std::unique_ptr<Block> tryCreate(const Key &key, cpputils::Data data) override;
std::unique_ptr<Block> load(const Key &key) override;
void remove(std::unique_ptr<Block> block) override;
uint64_t numBlocks() const override;
void release(std::unique_ptr<Block> block);
std::unique_ptr<Block> tryCreateInBaseStore(const Key &key, Data data);
std::unique_ptr<Block> tryCreateInBaseStore(const Key &key, cpputils::Data data);
void removeFromBaseStore(std::unique_ptr<Block> block);
private:

View File

@ -3,6 +3,7 @@
using std::unique_ptr;
using std::make_unique;
using cpputils::Data;
namespace blockstore {
namespace caching {

View File

@ -3,7 +3,7 @@
#define BLOCKSTORE_IMPLEMENTATIONS_CACHING_NEWBLOCK_H_
#include "../../interface/BlockStore.h"
#include "../../utils/Data.h"
#include <messmer/cpp-utils/data/Data.h>
#include "messmer/cpp-utils/macros.h"
#include <memory>
@ -20,7 +20,7 @@ class CachingBlockStore;
// It only exists in the cache and it is created in the base block store when destructed.
class NewBlock: public Block {
public:
NewBlock(const Key &key, Data data, CachingBlockStore *blockStore);
NewBlock(const Key &key, cpputils::Data data, CachingBlockStore *blockStore);
virtual ~NewBlock();
const void *data() const override;
@ -35,7 +35,7 @@ public:
private:
CachingBlockStore *_blockStore;
Data _data;
cpputils::Data _data;
std::unique_ptr<Block> _baseBlock;
bool _dataChanged;

View File

@ -3,7 +3,7 @@
#define BLOCKSTORE_IMPLEMENTATIONS_ENCRYPTED_ENCRYPTEDBLOCK_H_
#include "../../interface/Block.h"
#include "../../utils/Data.h"
#include <messmer/cpp-utils/data/Data.h>
#include "../../interface/BlockStore.h"
#include "messmer/cpp-utils/macros.h"
@ -21,11 +21,11 @@ template<class Cipher>
class EncryptedBlock: public Block {
public:
BOOST_CONCEPT_ASSERT((CipherConcept<Cipher>));
static std::unique_ptr<EncryptedBlock> TryCreateNew(BlockStore *baseBlockStore, const Key &key, Data data, const typename Cipher::EncryptionKey &encKey);
static std::unique_ptr<EncryptedBlock> TryCreateNew(BlockStore *baseBlockStore, const Key &key, cpputils::Data data, const typename Cipher::EncryptionKey &encKey);
static std::unique_ptr<EncryptedBlock> TryDecrypt(std::unique_ptr<Block> baseBlock, const typename Cipher::EncryptionKey &key);
//TODO Storing key twice (in parent class and in object pointed to). Once would be enough.
EncryptedBlock(std::unique_ptr<Block> baseBlock, const typename Cipher::EncryptionKey &key, Data plaintextData);
EncryptedBlock(std::unique_ptr<Block> baseBlock, const typename Cipher::EncryptionKey &key, cpputils::Data plaintextData);
virtual ~EncryptedBlock();
const void *data() const override;
@ -38,7 +38,7 @@ public:
private:
std::unique_ptr<Block> _baseBlock;
Data _plaintextData;
cpputils::Data _plaintextData;
typename Cipher::EncryptionKey _encKey;
bool _dataChanged;
@ -50,8 +50,8 @@ private:
template<class Cipher>
std::unique_ptr<EncryptedBlock<Cipher>> EncryptedBlock<Cipher>::TryCreateNew(BlockStore *baseBlockStore, const Key &key, Data data, const typename Cipher::EncryptionKey &encKey) {
Data encrypted = Cipher::encrypt((byte*)data.data(), data.size(), encKey);
std::unique_ptr<EncryptedBlock<Cipher>> EncryptedBlock<Cipher>::TryCreateNew(BlockStore *baseBlockStore, const Key &key, cpputils::Data data, const typename Cipher::EncryptionKey &encKey) {
cpputils::Data encrypted = Cipher::encrypt((byte*)data.data(), data.size(), encKey);
auto baseBlock = baseBlockStore->tryCreate(key, std::move(encrypted));
if (baseBlock.get() == nullptr) {
//TODO Test this code branch
@ -64,7 +64,7 @@ std::unique_ptr<EncryptedBlock<Cipher>> EncryptedBlock<Cipher>::TryCreateNew(Blo
template<class Cipher>
std::unique_ptr<EncryptedBlock<Cipher>> EncryptedBlock<Cipher>::TryDecrypt(std::unique_ptr<Block> baseBlock, const typename Cipher::EncryptionKey &encKey) {
//TODO Change BlockStore so we can read their "class Data" objects instead of "void *data()", and then we can change the Cipher interface to take Data objects instead of "byte *" + size
boost::optional<Data> plaintext = Cipher::decrypt((byte*)baseBlock->data(), baseBlock->size(), encKey);
boost::optional<cpputils::Data> plaintext = Cipher::decrypt((byte*)baseBlock->data(), baseBlock->size(), encKey);
if(!plaintext) {
return nullptr;
}
@ -72,7 +72,7 @@ std::unique_ptr<EncryptedBlock<Cipher>> EncryptedBlock<Cipher>::TryDecrypt(std::
}
template<class Cipher>
EncryptedBlock<Cipher>::EncryptedBlock(std::unique_ptr<Block> baseBlock, const typename Cipher::EncryptionKey &encKey, Data plaintextData)
EncryptedBlock<Cipher>::EncryptedBlock(std::unique_ptr<Block> baseBlock, const typename Cipher::EncryptionKey &encKey, cpputils::Data plaintextData)
:Block(baseBlock->key()),
_baseBlock(std::move(baseBlock)),
_plaintextData(std::move(plaintextData)),
@ -111,7 +111,7 @@ size_t EncryptedBlock<Cipher>::size() const {
template<class Cipher>
void EncryptedBlock<Cipher>::_encryptToBaseBlock() {
if (_dataChanged) {
Data encrypted = Cipher::encrypt((byte*)_plaintextData.data(), _plaintextData.size(), _encKey);
cpputils::Data encrypted = Cipher::encrypt((byte*)_plaintextData.data(), _plaintextData.size(), _encKey);
_baseBlock->write(encrypted.data(), 0, encrypted.size());
_dataChanged = false;
}

View File

@ -17,7 +17,7 @@ public:
EncryptedBlockStore(std::unique_ptr<BlockStore> baseBlockStore, const typename Cipher::EncryptionKey &encKey);
Key createKey() override;
std::unique_ptr<Block> tryCreate(const Key &key, Data data) override;
std::unique_ptr<Block> tryCreate(const Key &key, cpputils::Data data) override;
std::unique_ptr<Block> load(const Key &key) override;
void remove(std::unique_ptr<Block> block) override;
uint64_t numBlocks() const override;
@ -42,7 +42,7 @@ Key EncryptedBlockStore<Cipher>::createKey() {
}
template<class Cipher>
std::unique_ptr<Block> EncryptedBlockStore<Cipher>::tryCreate(const Key &key, Data data) {
std::unique_ptr<Block> EncryptedBlockStore<Cipher>::tryCreate(const Key &key, cpputils::Data data) {
return EncryptedBlock<Cipher>::TryCreateNew(_baseBlockStore.get(), key, std::move(data), _encKey);
}

View File

@ -3,6 +3,8 @@
using CryptoPP::CFB_Mode;
using CryptoPP::AES;
using cpputils::Data;
using cpputils::FixedSizeData;
namespace blockstore {
namespace encrypted {

View File

@ -2,8 +2,8 @@
#ifndef MESSMER_BLOCKSTORE_IMPLEMENTATIONS_ENCRYPTED_CIPHERS_AES256_CFB_H_
#define MESSMER_BLOCKSTORE_IMPLEMENTATIONS_ENCRYPTED_CIPHERS_AES256_CFB_H_
#include "../../../utils/FixedSizeData.h"
#include "../../../utils/Data.h"
#include <messmer/cpp-utils/data/FixedSizeData.h>
#include <messmer/cpp-utils/data/Data.h>
#include <cryptopp/cryptopp/aes.h>
#include <boost/optional.hpp>
#include "Cipher.h"
@ -15,7 +15,7 @@ class AES256_CFB {
public:
BOOST_CONCEPT_ASSERT((CipherConcept<AES256_CFB>));
using EncryptionKey = FixedSizeData<32>;
using EncryptionKey = cpputils::FixedSizeData<32>;
static_assert(32 == CryptoPP::AES::MAX_KEYLENGTH, "If AES offered larger keys, we should offer a variant with it");
static constexpr unsigned int ciphertextSize(unsigned int plaintextBlockSize) {
@ -26,8 +26,8 @@ public:
return ciphertextBlockSize - IV_SIZE;
}
static Data encrypt(const byte *plaintext, unsigned int plaintextSize, const EncryptionKey &encKey);
static boost::optional<Data> decrypt(const byte *ciphertext, unsigned int ciphertextSize, const EncryptionKey &encKey);
static cpputils::Data encrypt(const byte *plaintext, unsigned int plaintextSize, const EncryptionKey &encKey);
static boost::optional<cpputils::Data> decrypt(const byte *ciphertext, unsigned int ciphertextSize, const EncryptionKey &encKey);
private:
static constexpr unsigned int IV_SIZE = CryptoPP::AES::BLOCKSIZE;

View File

@ -9,6 +9,8 @@ using CryptoPP::ArraySource;
using CryptoPP::ArraySink;
using CryptoPP::GCM_64K_Tables;
using CryptoPP::HashVerificationFilter;
using cpputils::Data;
using cpputils::FixedSizeData;
namespace blockstore {
namespace encrypted {

View File

@ -2,10 +2,9 @@
#ifndef MESSMER_BLOCKSTORE_IMPLEMENTATIONS_ENCRYPTED_CIPHERS_AES256_GCM_H_
#define MESSMER_BLOCKSTORE_IMPLEMENTATIONS_ENCRYPTED_CIPHERS_AES256_GCM_H_
#include "../../../utils/FixedSizeData.h"
#include "../../../utils/Data.h"
#include <messmer/cpp-utils/data/FixedSizeData.h>
#include <messmer/cpp-utils/data/Data.h>
#include <cryptopp/cryptopp/aes.h>
#include <boost/optional.hpp>
#include "Cipher.h"
namespace blockstore {
@ -15,7 +14,7 @@ class AES256_GCM {
public:
BOOST_CONCEPT_ASSERT((CipherConcept<AES256_GCM>));
using EncryptionKey = FixedSizeData<32>;
using EncryptionKey = cpputils::FixedSizeData<32>;
static_assert(32 == CryptoPP::AES::MAX_KEYLENGTH, "If AES offered larger keys, we should offer a variant with it");
static constexpr unsigned int ciphertextSize(unsigned int plaintextBlockSize) {
@ -26,8 +25,8 @@ public:
return ciphertextBlockSize - IV_SIZE - TAG_SIZE;
}
static Data encrypt(const byte *plaintext, unsigned int plaintextSize, const EncryptionKey &encKey);
static boost::optional<Data> decrypt(const byte *ciphertext, unsigned int ciphertextSize, const EncryptionKey &encKey);
static cpputils::Data encrypt(const byte *plaintext, unsigned int plaintextSize, const EncryptionKey &encKey);
static boost::optional<cpputils::Data> decrypt(const byte *ciphertext, unsigned int ciphertextSize, const EncryptionKey &encKey);
private:
static constexpr unsigned int IV_SIZE = CryptoPP::AES::BLOCKSIZE;

View File

@ -15,8 +15,8 @@ public:
same_type(UINT32_C(0), X::ciphertextSize(UINT32_C(5)));
same_type(UINT32_C(0), X::plaintextSize(UINT32_C(5)));
typename X::EncryptionKey key = X::EncryptionKey::CreateRandom();
same_type(Data(0), X::encrypt((byte*)nullptr, UINT32_C(0), key));
same_type(boost::optional<Data>(Data(0)), X::decrypt((byte*)nullptr, UINT32_C(0), key));
same_type(cpputils::Data(0), X::encrypt((byte*)nullptr, UINT32_C(0), key));
same_type(boost::optional<cpputils::Data>(cpputils::Data(0)), X::decrypt((byte*)nullptr, UINT32_C(0), key));
}
private:

View File

@ -9,6 +9,7 @@ using std::ostream;
using std::ifstream;
using std::ofstream;
using std::ios;
using cpputils::Data;
namespace blockstore {
namespace inmemory {

View File

@ -3,7 +3,7 @@
#define BLOCKSTORE_IMPLEMENTATIONS_INMEMORY_INMEMORYBLOCK_H_
#include "../../interface/Block.h"
#include "../../utils/Data.h"
#include <messmer/cpp-utils/data/Data.h>
namespace blockstore {
namespace inmemory {
@ -11,7 +11,7 @@ class InMemoryBlockStore;
class InMemoryBlock: public Block {
public:
InMemoryBlock(const Key &key, Data size);
InMemoryBlock(const Key &key, cpputils::Data size);
InMemoryBlock(const InMemoryBlock &rhs);
virtual ~InMemoryBlock();
@ -23,7 +23,7 @@ public:
size_t size() const override;
private:
std::shared_ptr<Data> _data;
std::shared_ptr<cpputils::Data> _data;
};
}

View File

@ -9,6 +9,7 @@ using std::mutex;
using std::lock_guard;
using std::piecewise_construct;
using std::make_tuple;
using cpputils::Data;
namespace blockstore {
namespace inmemory {

View File

@ -16,7 +16,7 @@ class InMemoryBlockStore: public BlockStoreWithRandomKeys {
public:
InMemoryBlockStore();
std::unique_ptr<Block> tryCreate(const Key &key, Data data) override;
std::unique_ptr<Block> tryCreate(const Key &key, cpputils::Data data) override;
std::unique_ptr<Block> load(const Key &key) override;
void remove(std::unique_ptr<Block> block) override;
uint64_t numBlocks() const override;

View File

@ -13,6 +13,7 @@ using std::ostream;
using std::ifstream;
using std::ofstream;
using std::ios;
using cpputils::Data;
namespace bf = boost::filesystem;
@ -47,11 +48,15 @@ unique_ptr<OnDiskBlock> OnDiskBlock::LoadFromDisk(const bf::path &rootdir, const
//If it isn't a file, Data::LoadFromFile() would usually also crash. We still need this extra check
//upfront, because Data::LoadFromFile() doesn't crash if we give it the path of a directory
//instead the path of a file.
//TODO Data::LoadFromFile now returns boost::optional. Do we then still need this?
if(!bf::is_regular_file(filepath)) {
return nullptr;
}
Data data = Data::LoadFromFile(filepath);
return unique_ptr<OnDiskBlock>(new OnDiskBlock(key, filepath, std::move(data)));
boost::optional<Data> data = Data::LoadFromFile(filepath);
if (!data) {
return nullptr;
}
return unique_ptr<OnDiskBlock>(new OnDiskBlock(key, filepath, std::move(*data)));
} catch (const FileDoesntExistException &e) {
return nullptr;
}

View File

@ -4,7 +4,7 @@
#include <boost/filesystem/path.hpp>
#include "../../interface/Block.h"
#include "../../utils/Data.h"
#include <messmer/cpp-utils/data/Data.h>
#include <iostream>
#include "messmer/cpp-utils/macros.h"
@ -18,7 +18,7 @@ public:
virtual ~OnDiskBlock();
static std::unique_ptr<OnDiskBlock> LoadFromDisk(const boost::filesystem::path &rootdir, const Key &key);
static std::unique_ptr<OnDiskBlock> CreateOnDisk(const boost::filesystem::path &rootdir, const Key &key, Data data);
static std::unique_ptr<OnDiskBlock> CreateOnDisk(const boost::filesystem::path &rootdir, const Key &key, cpputils::Data data);
static void RemoveFromDisk(const boost::filesystem::path &rootdir, const Key &key);
const void *data() const override;
@ -30,10 +30,10 @@ public:
private:
const boost::filesystem::path _filepath;
Data _data;
cpputils::Data _data;
bool _dataChanged;
OnDiskBlock(const Key &key, const boost::filesystem::path &filepath, Data data);
OnDiskBlock(const Key &key, const boost::filesystem::path &filepath, cpputils::Data data);
void _fillDataWithZeroes();
void _storeToDisk() const;

View File

@ -4,6 +4,7 @@
using std::unique_ptr;
using std::make_unique;
using std::string;
using cpputils::Data;
namespace bf = boost::filesystem;

View File

@ -14,7 +14,7 @@ class OnDiskBlockStore: public BlockStoreWithRandomKeys {
public:
OnDiskBlockStore(const boost::filesystem::path &rootdir);
std::unique_ptr<Block> tryCreate(const Key &key, Data data) override;
std::unique_ptr<Block> tryCreate(const Key &key, cpputils::Data data) override;
std::unique_ptr<Block> load(const Key &key) override;
void remove(std::unique_ptr<Block> block) override;
uint64_t numBlocks() const override;

View File

@ -24,7 +24,7 @@ Key ParallelAccessBlockStore::createKey() {
return _baseBlockStore->createKey();
}
unique_ptr<Block> ParallelAccessBlockStore::tryCreate(const Key &key, Data data) {
unique_ptr<Block> ParallelAccessBlockStore::tryCreate(const Key &key, cpputils::Data data) {
auto block = _baseBlockStore->tryCreate(key, std::move(data));
if (block.get() == nullptr) {
//TODO Test this code branch

View File

@ -15,7 +15,7 @@ public:
ParallelAccessBlockStore(std::unique_ptr<BlockStore> baseBlockStore);
Key createKey() override;
std::unique_ptr<Block> tryCreate(const Key &key, Data data) override;
std::unique_ptr<Block> tryCreate(const Key &key, cpputils::Data data) override;
std::unique_ptr<Block> load(const Key &key) override;
void remove(std::unique_ptr<Block> block) override;
uint64_t numBlocks() const override;

View File

@ -10,6 +10,7 @@ using std::ifstream;
using std::ofstream;
using std::ios;
using std::string;
using cpputils::Data;
namespace blockstore {
namespace testfake {

View File

@ -3,7 +3,7 @@
#define BLOCKSTORE_IMPLEMENTATIONS_INMEMORY_INMEMORYBLOCK_H_
#include "../../interface/Block.h"
#include "../../utils/Data.h"
#include <messmer/cpp-utils/data/Data.h>
#include "messmer/cpp-utils/macros.h"
@ -13,7 +13,7 @@ class FakeBlockStore;
class FakeBlock: public Block {
public:
FakeBlock(FakeBlockStore *store, const Key &key, std::shared_ptr<Data> data, bool dirty);
FakeBlock(FakeBlockStore *store, const Key &key, std::shared_ptr<cpputils::Data> data, bool dirty);
virtual ~FakeBlock();
const void *data() const override;
@ -25,7 +25,7 @@ public:
private:
FakeBlockStore *_store;
std::shared_ptr<Data> _data;
std::shared_ptr<cpputils::Data> _data;
bool _dataChanged;
DISALLOW_COPY_AND_ASSIGN(FakeBlock);

View File

@ -7,6 +7,7 @@ using std::make_shared;
using std::string;
using std::mutex;
using std::lock_guard;
using cpputils::Data;
namespace blockstore {
namespace testfake {

View File

@ -3,7 +3,7 @@
#define BLOCKSTORE_IMPLEMENTATIONS_INMEMORY_INMEMORYBLOCKSTORE_H_
#include "../../interface/helpers/BlockStoreWithRandomKeys.h"
#include "../../utils/Data.h"
#include <messmer/cpp-utils/data/Data.h>
#include "messmer/cpp-utils/macros.h"
#include <mutex>
@ -31,24 +31,24 @@ class FakeBlockStore: public BlockStoreWithRandomKeys {
public:
FakeBlockStore();
std::unique_ptr<Block> tryCreate(const Key &key, Data data) override;
std::unique_ptr<Block> tryCreate(const Key &key, cpputils::Data data) override;
std::unique_ptr<Block> load(const Key &key) override;
void remove(std::unique_ptr<Block> block) override;
uint64_t numBlocks() const override;
void updateData(const Key &key, const Data &data);
void updateData(const Key &key, const cpputils::Data &data);
private:
std::map<std::string, Data> _blocks;
std::map<std::string, cpputils::Data> _blocks;
//This vector keeps a handle of the data regions for all created FakeBlock objects.
//This way, it is ensured that no two created FakeBlock objects will work on the
//same data region. Without this, it could happen that a test case creates a FakeBlock,
//destructs it, creates another one, and the new one gets the same memory region.
//We want to avoid this for the reasons mentioned above (overflow data).
std::vector<std::shared_ptr<Data>> _used_dataregions_for_blocks;
std::vector<std::shared_ptr<cpputils::Data>> _used_dataregions_for_blocks;
std::unique_ptr<Block> makeFakeBlockFromData(const Key &key, const Data &data, bool dirty);
std::unique_ptr<Block> makeFakeBlockFromData(const Key &key, const cpputils::Data &data, bool dirty);
DISALLOW_COPY_AND_ASSIGN(FakeBlockStore);
};

View File

@ -5,7 +5,7 @@
#include "Block.h"
#include <string>
#include <memory>
#include "../utils/Data.h"
#include <messmer/cpp-utils/data/Data.h>
namespace blockstore {
@ -15,14 +15,14 @@ public:
virtual Key createKey() = 0;
//Returns nullptr if key already exists
virtual std::unique_ptr<Block> tryCreate(const Key &key, Data data) = 0;
virtual std::unique_ptr<Block> tryCreate(const Key &key, cpputils::Data data) = 0;
//TODO Use boost::optional (if key doesn't exist)
// Return nullptr if block with this key doesn't exists
virtual std::unique_ptr<Block> load(const Key &key) = 0;
virtual void remove(std::unique_ptr<Block> block) = 0;
virtual uint64_t numBlocks() const = 0;
std::unique_ptr<Block> create(const Data &data) {
std::unique_ptr<Block> create(const cpputils::Data &data) {
std::unique_ptr<Block> block(nullptr);
while(block.get() == nullptr) {
//TODO Copy necessary?

View File

@ -3,13 +3,14 @@
#include "../../../implementations/encrypted/ciphers/AES256_GCM.h"
#include "../../../implementations/encrypted/ciphers/Cipher.h"
#include "../../testutils/DataBlockFixture.h"
#include "../../../utils/Data.h"
#include <messmer/cpp-utils/data/DataBlockFixture.h>
#include <messmer/cpp-utils/data/Data.h>
#include <boost/optional/optional_io.hpp>
using namespace blockstore::encrypted;
using blockstore::Data;
using cpputils::Data;
using cpputils::DataBlockFixture;
template<class Cipher>
class CipherTest: public ::testing::Test {

View File

@ -2,17 +2,17 @@
#include "../../../../implementations/ondisk/OnDiskBlock.h"
#include "google/gtest/gtest.h"
#include "messmer/tempfile/src/TempFile.h"
#include "messmer/tempfile/src/TempDir.h"
#include <messmer/cpp-utils/tempfile/TempFile.h>
#include <messmer/cpp-utils/tempfile/TempDir.h>
using ::testing::Test;
using ::testing::WithParamInterface;
using ::testing::Values;
using tempfile::TempFile;
using tempfile::TempDir;
using std::unique_ptr;
using cpputils::Data;
using cpputils::TempFile;
using cpputils::TempDir;
using namespace blockstore;
using namespace blockstore::ondisk;
@ -63,12 +63,12 @@ public:
INSTANTIATE_TEST_CASE_P(OnDiskBlockCreateSizeTest, OnDiskBlockCreateSizeTest, Values(0, 1, 5, 1024, 10*1024*1024));
TEST_P(OnDiskBlockCreateSizeTest, OnDiskSizeIsCorrect) {
Data fileContent = Data::LoadFromFile(file.path());
Data fileContent = Data::LoadFromFile(file.path()).value();
EXPECT_EQ(GetParam(), fileContent.size());
}
TEST_P(OnDiskBlockCreateSizeTest, OnDiskBlockIsZeroedOut) {
Data fileContent = Data::LoadFromFile(file.path());
Data fileContent = Data::LoadFromFile(file.path()).value();
EXPECT_EQ(0, std::memcmp(ZEROES.data(), fileContent.data(), fileContent.size()));
}

View File

@ -1,19 +1,20 @@
#include "../../../../implementations/ondisk/FileAlreadyExistsException.h"
#include "../../../../implementations/ondisk/OnDiskBlock.h"
#include "../../../testutils/DataBlockFixture.h"
#include <messmer/cpp-utils/data/DataBlockFixture.h>
#include "google/gtest/gtest.h"
#include "messmer/tempfile/src/TempFile.h"
#include "messmer/tempfile/src/TempDir.h"
#include <messmer/cpp-utils/tempfile/TempFile.h>
#include <messmer/cpp-utils/tempfile/TempDir.h>
using ::testing::Test;
using ::testing::WithParamInterface;
using ::testing::Values;
using tempfile::TempFile;
using tempfile::TempDir;
using std::unique_ptr;
using cpputils::Data;
using cpputils::DataBlockFixture;
using cpputils::TempFile;
using cpputils::TempDir;
using namespace blockstore;
using namespace blockstore::ondisk;
@ -60,7 +61,7 @@ public:
}
void EXPECT_STORED_FILE_DATA_CORRECT() {
Data actual = Data::LoadFromFile(file.path());
Data actual = Data::LoadFromFile(file.path()).value();
EXPECT_EQ(randomData.size(), actual.size());
EXPECT_EQ(0, std::memcmp(randomData.data(), actual.data(), randomData.size()));
}

View File

@ -1,23 +1,24 @@
#include "../../../../implementations/ondisk/OnDiskBlock.h"
#include "../../../testutils/DataBlockFixture.h"
#include <messmer/cpp-utils/data/DataBlockFixture.h>
#include "../../../../utils/FileDoesntExistException.h"
#include "google/gtest/gtest.h"
#include "../../../../utils/Data.h"
#include "messmer/tempfile/src/TempFile.h"
#include "messmer/tempfile/src/TempDir.h"
#include <messmer/cpp-utils/data/Data.h>
#include <messmer/cpp-utils/tempfile/TempFile.h>
#include <messmer/cpp-utils/tempfile/TempDir.h>
#include <fstream>
using ::testing::Test;
using ::testing::WithParamInterface;
using ::testing::Values;
using tempfile::TempFile;
using tempfile::TempDir;
using std::ofstream;
using std::unique_ptr;
using std::ios;
using cpputils::Data;
using cpputils::DataBlockFixture;
using cpputils::TempFile;
using cpputils::TempDir;
using namespace blockstore;
using namespace blockstore::ondisk;

View File

@ -1,7 +1,7 @@
#include "../../../interface/helpers/BlockStoreWithRandomKeys.h"
#include "google/gtest/gtest.h"
#include "google/gmock/gmock.h"
#include "../../testutils/DataBlockFixture.h"
#include <messmer/cpp-utils/data/DataBlockFixture.h>
using ::testing::Test;
using ::testing::_;
@ -13,6 +13,8 @@ using ::testing::ByRef;
using std::string;
using std::unique_ptr;
using std::make_unique;
using cpputils::Data;
using cpputils::DataBlockFixture;
using namespace blockstore;

View File

@ -4,8 +4,6 @@
#include "google/gtest/gtest.h"
#include "DataBlockFixture.h"
#include "../../interface/BlockStore.h"
class BlockStoreTestFixture {
@ -28,14 +26,14 @@ TYPED_TEST_CASE_P(BlockStoreTest);
TYPED_TEST_P(BlockStoreTest, TwoCreatedBlocksHaveDifferentKeys) {
auto blockStore = this->fixture.createBlockStore();
auto block1 = blockStore->create(blockstore::Data(1024));
auto block2 = blockStore->create(blockstore::Data(1024));
auto block1 = blockStore->create(cpputils::Data(1024));
auto block2 = blockStore->create(cpputils::Data(1024));
EXPECT_NE(block1->key(), block2->key());
}
TYPED_TEST_P(BlockStoreTest, BlockIsNotLoadableAfterDeleting) {
auto blockStore = this->fixture.createBlockStore();
auto blockkey = blockStore->create(blockstore::Data(1024))->key();
auto blockkey = blockStore->create(cpputils::Data(1024))->key();
auto block = blockStore->load(blockkey);
EXPECT_NE(nullptr, block.get());
blockStore->remove(std::move(block));
@ -49,55 +47,55 @@ TYPED_TEST_P(BlockStoreTest, NumBlocksIsCorrectOnEmptyBlockstore) {
TYPED_TEST_P(BlockStoreTest, NumBlocksIsCorrectAfterAddingOneBlock) {
auto blockStore = this->fixture.createBlockStore();
auto block = blockStore->create(blockstore::Data(1));
auto block = blockStore->create(cpputils::Data(1));
EXPECT_EQ(1, blockStore->numBlocks());
}
TYPED_TEST_P(BlockStoreTest, NumBlocksIsCorrectAfterAddingOneBlock_AfterClosingBlock) {
auto blockStore = this->fixture.createBlockStore();
blockStore->create(blockstore::Data(1));
blockStore->create(cpputils::Data(1));
EXPECT_EQ(1, blockStore->numBlocks());
}
TYPED_TEST_P(BlockStoreTest, NumBlocksIsCorrectAfterRemovingTheLastBlock) {
auto blockStore = this->fixture.createBlockStore();
auto block = blockStore->create(blockstore::Data(1));
auto block = blockStore->create(cpputils::Data(1));
blockStore->remove(std::move(block));
EXPECT_EQ(0, blockStore->numBlocks());
}
TYPED_TEST_P(BlockStoreTest, NumBlocksIsCorrectAfterAddingTwoBlocks) {
auto blockStore = this->fixture.createBlockStore();
auto block1 = blockStore->create(blockstore::Data(1));
auto block2 = blockStore->create(blockstore::Data(0));
auto block1 = blockStore->create(cpputils::Data(1));
auto block2 = blockStore->create(cpputils::Data(0));
EXPECT_EQ(2, blockStore->numBlocks());
}
TYPED_TEST_P(BlockStoreTest, NumBlocksIsCorrectAfterAddingTwoBlocks_AfterClosingFirstBlock) {
auto blockStore = this->fixture.createBlockStore();
blockStore->create(blockstore::Data(1));
auto block2 = blockStore->create(blockstore::Data(0));
blockStore->create(cpputils::Data(1));
auto block2 = blockStore->create(cpputils::Data(0));
EXPECT_EQ(2, blockStore->numBlocks());
}
TYPED_TEST_P(BlockStoreTest, NumBlocksIsCorrectAfterAddingTwoBlocks_AfterClosingSecondBlock) {
auto blockStore = this->fixture.createBlockStore();
auto block1 = blockStore->create(blockstore::Data(1));
blockStore->create(blockstore::Data(0));
auto block1 = blockStore->create(cpputils::Data(1));
blockStore->create(cpputils::Data(0));
EXPECT_EQ(2, blockStore->numBlocks());
}
TYPED_TEST_P(BlockStoreTest, NumBlocksIsCorrectAfterAddingTwoBlocks_AfterClosingBothBlocks) {
auto blockStore = this->fixture.createBlockStore();
blockStore->create(blockstore::Data(1));
blockStore->create(blockstore::Data(0));
blockStore->create(cpputils::Data(1));
blockStore->create(cpputils::Data(0));
EXPECT_EQ(2, blockStore->numBlocks());
}
TYPED_TEST_P(BlockStoreTest, NumBlocksIsCorrectAfterRemovingABlock) {
auto blockStore = this->fixture.createBlockStore();
auto block = blockStore->create(blockstore::Data(1));
blockStore->create(blockstore::Data(1));
auto block = blockStore->create(cpputils::Data(1));
blockStore->create(cpputils::Data(1));
blockStore->remove(std::move(block));
EXPECT_EQ(1, blockStore->numBlocks());
}

View File

@ -13,14 +13,14 @@ public:
: blockStore(std::move(blockStore_)),
testData(testData_),
foregroundData(testData.count), backgroundData(testData.blocksize) {
DataBlockFixture _foregroundData(testData.count);
DataBlockFixture _backgroundData(testData.blocksize);
cpputils::DataBlockFixture _foregroundData(testData.count);
cpputils::DataBlockFixture _backgroundData(testData.blocksize);
std::memcpy(foregroundData.data(), _foregroundData.data(), foregroundData.size());
std::memcpy(backgroundData.data(), _backgroundData.data(), backgroundData.size());
}
void TestWriteAndReadImmediately() {
auto block = blockStore->create(blockstore::Data(testData.blocksize).FillWithZeroes());
auto block = blockStore->create(cpputils::Data(testData.blocksize).FillWithZeroes());
block->write(foregroundData.data(), testData.offset, testData.count);
EXPECT_DATA_READS_AS(foregroundData, *block, testData.offset, testData.count);
@ -36,7 +36,7 @@ public:
}
void TestOverwriteAndRead() {
auto block = blockStore->create(blockstore::Data(testData.blocksize));
auto block = blockStore->create(cpputils::Data(testData.blocksize));
block->write(backgroundData.data(), 0, testData.blocksize);
block->write(foregroundData.data(), testData.offset, testData.count);
EXPECT_DATA_READS_AS(foregroundData, *block, testData.offset, testData.count);
@ -46,30 +46,30 @@ public:
private:
std::unique_ptr<blockstore::BlockStore> blockStore;
DataRange testData;
blockstore::Data foregroundData;
blockstore::Data backgroundData;
cpputils::Data foregroundData;
cpputils::Data backgroundData;
void EXPECT_DATA_EQ(const blockstore::Data &expected, const blockstore::Data &actual) {
void EXPECT_DATA_EQ(const cpputils::Data &expected, const cpputils::Data &actual) {
EXPECT_EQ(expected.size(), actual.size());
EXPECT_EQ(0, std::memcmp(expected.data(), actual.data(), expected.size()));
}
blockstore::Key CreateBlockWriteToItAndReturnKey(const blockstore::Data &to_write) {
auto newblock = blockStore->create(blockstore::Data(testData.blocksize).FillWithZeroes());
blockstore::Key CreateBlockWriteToItAndReturnKey(const cpputils::Data &to_write) {
auto newblock = blockStore->create(cpputils::Data(testData.blocksize).FillWithZeroes());
newblock->write(to_write.data(), testData.offset, testData.count);
return newblock->key();
}
void EXPECT_DATA_READS_AS(const blockstore::Data &expected, const blockstore::Block &block, off_t offset, size_t count) {
blockstore::Data read(count);
void EXPECT_DATA_READS_AS(const cpputils::Data &expected, const blockstore::Block &block, off_t offset, size_t count) {
cpputils::Data read(count);
std::memcpy(read.data(), (uint8_t*)block.data() + offset, count);
EXPECT_DATA_EQ(expected, read);
}
void EXPECT_DATA_READS_AS_OUTSIDE_OF(const blockstore::Data &expected, const blockstore::Block &block, off_t start, size_t count) {
blockstore::Data begin(start);
blockstore::Data end(testData.blocksize - count - start);
void EXPECT_DATA_READS_AS_OUTSIDE_OF(const cpputils::Data &expected, const blockstore::Block &block, off_t start, size_t count) {
cpputils::Data begin(start);
cpputils::Data end(testData.blocksize - count - start);
std::memcpy(begin.data(), expected.data(), start);
std::memcpy(end.data(), (uint8_t*)expected.data()+start+count, end.size());
@ -79,7 +79,7 @@ private:
}
void EXPECT_DATA_IS_ZEROES_OUTSIDE_OF(const blockstore::Block &block, off_t start, size_t count) {
blockstore::Data ZEROES(testData.blocksize);
cpputils::Data ZEROES(testData.blocksize);
ZEROES.FillWithZeroes();
EXPECT_DATA_READS_AS_OUTSIDE_OF(ZEROES, block, start, count);
}

View File

@ -1,6 +1,7 @@
// This file is meant to be included by BlockStoreTest.h only
#include "../../utils/Data.h"
#include <messmer/cpp-utils/data/Data.h>
#include <messmer/cpp-utils/data/DataBlockFixture.h>
class BlockStoreSizeParameterizedTest {
public:
@ -18,8 +19,8 @@ public:
}
void TestCreatedBlockData() {
DataBlockFixture dataFixture(size);
blockstore::Data data(size);
cpputils::DataBlockFixture dataFixture(size);
cpputils::Data data(size);
std::memcpy(data.data(), dataFixture.data(), size);
auto block = blockStore->create(data);
EXPECT_EQ(0, std::memcmp(dataFixture.data(), block->data(), size));
@ -27,8 +28,8 @@ public:
}
void TestLoadingUnchangedBlockData() {
DataBlockFixture dataFixture(size);
blockstore::Data data(size);
cpputils::DataBlockFixture dataFixture(size);
cpputils::Data data(size);
std::memcpy(data.data(), dataFixture.data(), size);
blockstore::Key key = blockStore->create(data)->key();
auto loaded_block = blockStore->load(key);
@ -36,21 +37,21 @@ public:
}
void TestLoadedBlockIsCorrect() {
DataBlockFixture randomData(size);
cpputils::DataBlockFixture randomData(size);
auto loaded_block = StoreDataToBlockAndLoadIt(randomData);
EXPECT_EQ(size, loaded_block->size());
EXPECT_EQ(0, std::memcmp(randomData.data(), loaded_block->data(), size));
}
void TestLoadedBlockIsCorrectWhenLoadedDirectlyAfterFlushing() {
DataBlockFixture randomData(size);
cpputils::DataBlockFixture randomData(size);
auto loaded_block = StoreDataToBlockAndLoadItDirectlyAfterFlushing(randomData);
EXPECT_EQ(size, loaded_block->size());
EXPECT_EQ(0, std::memcmp(randomData.data(), loaded_block->data(), size));
}
void TestAfterCreate_FlushingDoesntChangeBlock() {
DataBlockFixture randomData(size);
cpputils::DataBlockFixture randomData(size);
auto block = CreateBlock();
WriteDataToBlock(block.get(), randomData);
block->flush();
@ -59,7 +60,7 @@ public:
}
void TestAfterLoad_FlushingDoesntChangeBlock() {
DataBlockFixture randomData(size);
cpputils::DataBlockFixture randomData(size);
auto block = CreateBlockAndLoadIt();
WriteDataToBlock(block.get(), randomData);
block->flush();
@ -68,10 +69,10 @@ public:
}
void TestAfterCreate_FlushesWhenDestructed() {
DataBlockFixture randomData(size);
cpputils::DataBlockFixture randomData(size);
blockstore::Key key = key;
{
auto block = blockStore->create(blockstore::Data(size));
auto block = blockStore->create(cpputils::Data(size));
key = block->key();
WriteDataToBlock(block.get(), randomData);
}
@ -80,7 +81,7 @@ public:
}
void TestAfterLoad_FlushesWhenDestructed() {
DataBlockFixture randomData(size);
cpputils::DataBlockFixture randomData(size);
blockstore::Key key = key;
{
key = CreateBlock()->key();
@ -102,25 +103,25 @@ private:
std::unique_ptr<blockstore::BlockStore> blockStore;
size_t size;
blockstore::Data ZEROES(size_t size) {
blockstore::Data ZEROES(size);
cpputils::Data ZEROES(size_t size) {
cpputils::Data ZEROES(size);
ZEROES.FillWithZeroes();
return ZEROES;
}
std::unique_ptr<blockstore::Block> StoreDataToBlockAndLoadIt(const DataBlockFixture &data) {
std::unique_ptr<blockstore::Block> StoreDataToBlockAndLoadIt(const cpputils::DataBlockFixture &data) {
blockstore::Key key = StoreDataToBlockAndGetKey(data);
return blockStore->load(key);
}
blockstore::Key StoreDataToBlockAndGetKey(const DataBlockFixture &dataFixture) {
blockstore::Data data(dataFixture.size());
blockstore::Key StoreDataToBlockAndGetKey(const cpputils::DataBlockFixture &dataFixture) {
cpputils::Data data(dataFixture.size());
std::memcpy(data.data(), dataFixture.data(), dataFixture.size());
return blockStore->create(data)->key();
}
std::unique_ptr<blockstore::Block> StoreDataToBlockAndLoadItDirectlyAfterFlushing(const DataBlockFixture &dataFixture) {
blockstore::Data data(dataFixture.size());
std::unique_ptr<blockstore::Block> StoreDataToBlockAndLoadItDirectlyAfterFlushing(const cpputils::DataBlockFixture &dataFixture) {
cpputils::Data data(dataFixture.size());
std::memcpy(data.data(), dataFixture.data(), dataFixture.size());
auto block = blockStore->create(data);
block->flush();
@ -133,14 +134,14 @@ private:
}
std::unique_ptr<blockstore::Block> CreateBlock() {
return blockStore->create(blockstore::Data(size));
return blockStore->create(cpputils::Data(size));
}
void WriteDataToBlock(blockstore::Block *block, const DataBlockFixture &randomData) {
void WriteDataToBlock(blockstore::Block *block, const cpputils::DataBlockFixture &randomData) {
block->write(randomData.data(), 0, randomData.size());
}
void EXPECT_BLOCK_DATA_CORRECT(const blockstore::Block &block, const DataBlockFixture &randomData) {
void EXPECT_BLOCK_DATA_CORRECT(const blockstore::Block &block, const cpputils::DataBlockFixture &randomData) {
EXPECT_EQ(randomData.size(), block.size());
EXPECT_EQ(0, std::memcmp(randomData.data(), block.data(), randomData.size()));
}

View File

@ -3,7 +3,6 @@
#define TEST_BLOCKSTORE_IMPLEMENTATIONS_TESTUTILS_BLOCKSTOREWITHRANDOMKEYSTEST_H_
#include <google/gtest/gtest.h>
#include "DataBlockFixture.h"
#include "../../interface/BlockStore.h"
@ -31,45 +30,45 @@ TYPED_TEST_CASE_P(BlockStoreWithRandomKeysTest);
TYPED_TEST_P(BlockStoreWithRandomKeysTest, CreateTwoBlocksWithSameKeyAndSameSize) {
auto blockStore = this->fixture.createBlockStore();
auto block = blockStore->tryCreate(this->key, blockstore::Data(1024));
auto block = blockStore->tryCreate(this->key, cpputils::Data(1024));
block->flush();
auto block2 = blockStore->tryCreate(this->key, blockstore::Data(1024));
auto block2 = blockStore->tryCreate(this->key, cpputils::Data(1024));
EXPECT_TRUE((bool)block);
EXPECT_FALSE((bool)block2);
}
TYPED_TEST_P(BlockStoreWithRandomKeysTest, CreateTwoBlocksWithSameKeyAndDifferentSize) {
auto blockStore = this->fixture.createBlockStore();
auto block = blockStore->tryCreate(this->key, blockstore::Data(1024));
auto block = blockStore->tryCreate(this->key, cpputils::Data(1024));
block->flush();
auto block2 = blockStore->tryCreate(this->key, blockstore::Data(4096));
auto block2 = blockStore->tryCreate(this->key, cpputils::Data(4096));
EXPECT_TRUE((bool)block);
EXPECT_FALSE((bool)block2);
}
TYPED_TEST_P(BlockStoreWithRandomKeysTest, CreateTwoBlocksWithSameKeyAndFirstNullSize) {
auto blockStore = this->fixture.createBlockStore();
auto block = blockStore->tryCreate(this->key, blockstore::Data(0));
auto block = blockStore->tryCreate(this->key, cpputils::Data(0));
block->flush();
auto block2 = blockStore->tryCreate(this->key, blockstore::Data(1024));
auto block2 = blockStore->tryCreate(this->key, cpputils::Data(1024));
EXPECT_TRUE((bool)block);
EXPECT_FALSE((bool)block2);
}
TYPED_TEST_P(BlockStoreWithRandomKeysTest, CreateTwoBlocksWithSameKeyAndSecondNullSize) {
auto blockStore = this->fixture.createBlockStore();
auto block = blockStore->tryCreate(this->key, blockstore::Data(1024));
auto block = blockStore->tryCreate(this->key, cpputils::Data(1024));
block->flush();
auto block2 = blockStore->tryCreate(this->key, blockstore::Data(0));
auto block2 = blockStore->tryCreate(this->key, cpputils::Data(0));
EXPECT_TRUE((bool)block);
EXPECT_FALSE((bool)block2);
}
TYPED_TEST_P(BlockStoreWithRandomKeysTest, CreateTwoBlocksWithSameKeyAndBothNullSize) {
auto blockStore = this->fixture.createBlockStore();
auto block = blockStore->tryCreate(this->key, blockstore::Data(0));
auto block = blockStore->tryCreate(this->key, cpputils::Data(0));
block->flush();
auto block2 = blockStore->tryCreate(this->key, blockstore::Data(0));
auto block2 = blockStore->tryCreate(this->key, cpputils::Data(0));
EXPECT_TRUE((bool)block);
EXPECT_FALSE((bool)block2);
}

View File

@ -1,87 +0,0 @@
#include "DataBlockFixture.h"
#include <algorithm>
#include <cstring>
using std::min;
DataBlockFixture::DataBlockFixture(size_t size, long long int IV): _fileData(new char[size]), _size(size) {
fillFileWithRandomData(IV);
}
DataBlockFixture::~DataBlockFixture() {
delete[] _fileData;
}
void DataBlockFixture::fillFileWithRandomData(long long int IV) {
long long int val = IV;
for(size_t i=0; i<_size/sizeof(long long int); ++i) {
//MMIX linear congruential generator
val *= 6364136223846793005L;
val += 1442695040888963407;
reinterpret_cast<long long int*>(_fileData)[i] = val;
}
uint64_t alreadyWritten = (_size/sizeof(long long int))*sizeof(long long int);
val *= 6364136223846793005L;
val += 1442695040888963407;
char *remainingBytes = reinterpret_cast<char*>(&val);
//Fill remaining bytes
for(size_t i=0; i<_size-alreadyWritten; ++i) {
reinterpret_cast<char*>(_fileData)[alreadyWritten + i] = remainingBytes[i];
}
}
const char *DataBlockFixture::data() const {
return _fileData;
}
int DataBlockFixture::read(void *buf, size_t count, off_t offset) {
size_t realCount = min(count, _size - offset);
memcpy(buf, _fileData+offset, realCount);
return realCount;
}
size_t DataBlockFixture::size() const {
return _size;
}
bool DataBlockFixture::fileContentEqual(const char *content, size_t count, off_t offset) {
return 0 == memcmp(content, _fileData + offset, count);
}
DataBlockFixtureWriteable::DataBlockFixtureWriteable(size_t size, long long int IV)
:DataBlockFixture(size, IV), _originalSize(size) {
_originalFileData = new char[size];
memcpy(_originalFileData, _fileData, size);
}
DataBlockFixtureWriteable::~DataBlockFixtureWriteable() {
delete[] _originalFileData;
}
void DataBlockFixtureWriteable::write(const void *buf, size_t count, off_t offset) {
extendFileSizeIfNecessary(count + offset);
memcpy(_fileData+offset, buf, count);
}
void DataBlockFixtureWriteable::extendFileSizeIfNecessary(size_t size) {
if (size > _size) {
extendFileSize(size);
}
}
void DataBlockFixtureWriteable::extendFileSize(size_t size) {
char *newfile = new char[size];
memcpy(newfile, _fileData, _size);
delete[] _fileData;
_fileData = newfile;
_size = size;
}
bool DataBlockFixtureWriteable::sizeUnchanged() {
return _size == _originalSize;
}
bool DataBlockFixtureWriteable::regionUnchanged(off_t offset, size_t count) {
return 0 == memcmp(_fileData+offset, _originalFileData+offset, count);
}

View File

@ -1,47 +0,0 @@
#pragma once
#ifndef TEST_TESTUTILS_DATABLOCKFIXTURE_H_
#define TEST_TESTUTILS_DATABLOCKFIXTURE_H_
#include <cstdio>
class DataBlockFixture {
public:
DataBlockFixture(size_t size, long long int IV = 1);
virtual ~DataBlockFixture();
int read(void *buf, size_t count, off_t offset);
// Return true, iff the given data is equal to the data of the file at the given offset.
bool fileContentEqual(const char *content, size_t count, off_t offset);
const char *data() const;
size_t size() const;
protected:
char *_fileData;
size_t _size;
private:
void fillFileWithRandomData(long long int IV);
};
class DataBlockFixtureWriteable: public DataBlockFixture {
public:
DataBlockFixtureWriteable(size_t size, long long int IV = 1);
virtual ~DataBlockFixtureWriteable();
void write(const void *buf, size_t count, off_t offset);
bool sizeUnchanged();
bool regionUnchanged(off_t offset, size_t count);
private:
void extendFileSizeIfNecessary(size_t size);
void extendFileSize(size_t size);
char *_originalFileData;
size_t _originalSize;
};
#endif

View File

@ -1,5 +1,5 @@
#include "../../implementations/testfake/FakeBlockStore.h"
#include "../testutils/DataBlockFixture.h"
#include <messmer/cpp-utils/data/DataBlockFixture.h>
#include "../../utils/BlockStoreUtils.h"
#include "google/gtest/gtest.h"
@ -11,6 +11,8 @@ using ::testing::Values;
using std::make_unique;
using std::unique_ptr;
using cpputils::Data;
using cpputils::DataBlockFixture;
using namespace blockstore;
using namespace blockstore::utils;

View File

@ -1,170 +0,0 @@
#include "../testutils/DataBlockFixture.h"
#include "../../utils/Data.h"
#include "../../utils/FileDoesntExistException.h"
#include "google/gtest/gtest.h"
#include "messmer/tempfile/src/TempFile.h"
#include <fstream>
using ::testing::Test;
using ::testing::WithParamInterface;
using ::testing::Values;
using tempfile::TempFile;
using std::ifstream;
using std::ofstream;
namespace bf = boost::filesystem;
using namespace blockstore;
class DataTest: public Test {
public:
bool DataIsZeroes(const Data &data) {
for (size_t i = 0; i != data.size(); ++ i) {
if (((char*)data.data())[i] != 0) {
return false;
}
}
return true;
}
void FillData(const DataBlockFixture &fillData, Data *data) {
ASSERT_EQ(fillData.size(), data->size());
std::memcpy(data->data(), fillData.data(), fillData.size());
}
void EXPECT_DATA_CORRECT(const DataBlockFixture &expectedData, const Data &data) {
ASSERT_EQ(expectedData.size(), data.size());
EXPECT_EQ(0, std::memcmp(expectedData.data(), data.data(), expectedData.size()));
}
};
class DataTestWithSizeParam: public DataTest, public WithParamInterface<size_t> {
public:
DataBlockFixture randomData;
DataTestWithSizeParam(): randomData(GetParam()) {}
void FillData(Data *data) {
DataTest::FillData(randomData, data);
}
void StoreData(const bf::path &filepath) {
ofstream file(filepath.c_str(), std::ios::binary | std::ios::trunc);
file.write(randomData.data(), randomData.size());
}
void EXPECT_STORED_FILE_DATA_CORRECT(const bf::path &filepath) {
EXPECT_EQ(randomData.size(), bf::file_size(filepath));
ifstream file(filepath.c_str(), std::ios::binary);
char *read_data = new char[randomData.size()];
file.read(read_data, randomData.size());
EXPECT_EQ(0, std::memcmp(randomData.data(), read_data, randomData.size()));
delete[] read_data;
}
void EXPECT_DATA_CORRECT(const Data &data) {
DataTest::EXPECT_DATA_CORRECT(randomData, data);
}
};
INSTANTIATE_TEST_CASE_P(DataTestWithSizeParam, DataTestWithSizeParam, Values(0, 1, 2, 1024, 4096, 10*1024*1024));
// Working on a large data area without a crash is a good indicator that we
// are actually working on memory that was validly allocated for us.
TEST_P(DataTestWithSizeParam, WriteAndCheck) {
Data data(GetParam());
FillData(&data);
EXPECT_DATA_CORRECT(data);
}
TEST_P(DataTestWithSizeParam, Size) {
Data data(GetParam());
EXPECT_EQ(GetParam(), data.size());
}
TEST_P(DataTestWithSizeParam, CheckStoredFile) {
Data data(GetParam());
FillData(&data);
TempFile file;
data.StoreToFile(file.path());
EXPECT_STORED_FILE_DATA_CORRECT(file.path());
}
TEST_P(DataTestWithSizeParam, CheckLoadedData) {
TempFile file;
StoreData(file.path());
Data data = Data::LoadFromFile(file.path());
EXPECT_DATA_CORRECT(data);
}
TEST_P(DataTestWithSizeParam, StoreDoesntChangeData) {
Data data(GetParam());
FillData(&data);
TempFile file;
data.StoreToFile(file.path());
EXPECT_DATA_CORRECT(data);
}
TEST_P(DataTestWithSizeParam, StoreAndLoad) {
Data data(GetParam());
FillData(&data);
TempFile file;
data.StoreToFile(file.path());
Data loaded_data = Data::LoadFromFile(file.path());
EXPECT_DATA_CORRECT(loaded_data);
}
TEST_P(DataTestWithSizeParam, Copy) {
Data data(GetParam());
FillData(&data);
Data copy = data.copy();
EXPECT_DATA_CORRECT(copy);
}
TEST_F(DataTest, InitializeWithZeroes) {
Data data(10*1024);
data.FillWithZeroes();
EXPECT_TRUE(DataIsZeroes(data));
}
TEST_F(DataTest, FillModifiedDataWithZeroes) {
Data data(10*1024);
DataBlockFixture randomData(10*1024);
FillData(randomData, &data);
EXPECT_FALSE(DataIsZeroes(data));
data.FillWithZeroes();
EXPECT_TRUE(DataIsZeroes(data));
}
//Needs 64bit for representation. This value isn't in the size param list, because the list is also used for read/write checks.
TEST_F(DataTest, LargesizeSize) {
size_t size = 10L*1024*1024*1024;
Data data(size);
EXPECT_EQ(size, data.size());
}
TEST_F(DataTest, LoadingNonexistingFile) {
TempFile file(false); // Pass false to constructor, so the tempfile is not created
EXPECT_THROW(
Data::LoadFromFile(file.path()),
FileDoesntExistException
);
}

View File

@ -1,144 +0,0 @@
#include "../testutils/DataBlockFixture.h"
#include "../../utils/Data.h"
#include "../../utils/Key.h"
#include "google/gtest/gtest.h"
using ::testing::Test;
using ::testing::WithParamInterface;
using ::testing::Values;
using std::string;
using namespace blockstore;
//TODO Test blockstore::FixedSizeData instead of blockstore::Key
class KeyTest: public Test {
public:
const string KEY1_AS_STRING = "1491BB4932A389EE14BC7090AC772972";
const string KEY2_AS_STRING = "272EE5517627CFA147A971A8E6E747E0";
const DataBlockFixture KEY3_AS_BINARY;
const DataBlockFixture KEY4_AS_BINARY;
KeyTest() : KEY3_AS_BINARY(Key::BINARY_LENGTH, 1), KEY4_AS_BINARY(Key::BINARY_LENGTH, 2) {}
void EXPECT_DATA_EQ(const DataBlockFixture &expected, const Data &actual) {
EXPECT_EQ(expected.size(), actual.size());
EXPECT_EQ(0, std::memcmp(expected.data(), actual.data(), expected.size()));
}
};
TEST_F(KeyTest, CanGenerateRandomKeysWithoutCrashing) {
Key result = Key::CreateRandom();
}
TEST_F(KeyTest, CreatedRandomKeysHaveCorrectLength) {
Key key = Key::CreateRandom();
EXPECT_EQ(Key::STRING_LENGTH, key.ToString().size());
}
TEST_F(KeyTest, EqualsTrue) {
Key key1_1 = Key::FromString(KEY1_AS_STRING);
Key key1_2 = Key::FromString(KEY1_AS_STRING);
EXPECT_TRUE(key1_1 == key1_2);
EXPECT_TRUE(key1_2 == key1_1);
}
TEST_F(KeyTest, EqualsFalse) {
Key key1_1 = Key::FromString(KEY1_AS_STRING);
Key key2_1 = Key::FromString(KEY2_AS_STRING);
EXPECT_FALSE(key1_1 == key2_1);
EXPECT_FALSE(key2_1 == key1_1);
}
TEST_F(KeyTest, NotEqualsFalse) {
Key key1_1 = Key::FromString(KEY1_AS_STRING);
Key key1_2 = Key::FromString(KEY1_AS_STRING);
EXPECT_FALSE(key1_1 != key1_2);
EXPECT_FALSE(key1_2 != key1_1);
}
TEST_F(KeyTest, NotEqualsTrue) {
Key key1_1 = Key::FromString(KEY1_AS_STRING);
Key key2_1 = Key::FromString(KEY2_AS_STRING);
EXPECT_TRUE(key1_1 != key2_1);
EXPECT_TRUE(key2_1 != key1_1);
}
class KeyTestWithStringKeyParam: public KeyTest, public WithParamInterface<string> {};
INSTANTIATE_TEST_CASE_P(KeyTestWithStringKeyParam, KeyTestWithStringKeyParam, Values("2898B4B8A13CA63CBE0F0278CCE465DB", "6FFEBAD90C0DAA2B79628F0627CE9841"));
TEST_P(KeyTestWithStringKeyParam, FromAndToString) {
Key key = Key::FromString(GetParam());
EXPECT_EQ(GetParam(), key.ToString());
}
TEST_P(KeyTestWithStringKeyParam, ToAndFromString) {
Key key = Key::FromString(GetParam());
Key key2 = Key::FromString(key.ToString());
EXPECT_EQ(key, key2);
}
class KeyTestWithBinaryKeyParam: public KeyTest, public WithParamInterface<const DataBlockFixture*> {
public:
static const DataBlockFixture VALUE1;
static const DataBlockFixture VALUE2;
};
const DataBlockFixture KeyTestWithBinaryKeyParam::VALUE1(Key::BINARY_LENGTH, 3);
const DataBlockFixture KeyTestWithBinaryKeyParam::VALUE2(Key::BINARY_LENGTH, 4);
INSTANTIATE_TEST_CASE_P(KeyTestWithBinaryKeyParam, KeyTestWithBinaryKeyParam, Values(&KeyTestWithBinaryKeyParam::VALUE1, &KeyTestWithBinaryKeyParam::VALUE2));
TEST_P(KeyTestWithBinaryKeyParam, FromAndToBinary) {
Key key = Key::FromBinary((uint8_t*)GetParam()->data());
Data keydata(Key::BINARY_LENGTH);
key.ToBinary(keydata.data());
EXPECT_DATA_EQ(*GetParam(), keydata);
}
TEST_P(KeyTestWithBinaryKeyParam, ToAndFromBinary) {
Key key = Key::FromBinary((uint8_t*)GetParam()->data());
Data stored(Key::BINARY_LENGTH);
key.ToBinary(stored.data());
Key loaded = Key::FromBinary(stored.data());
EXPECT_EQ(key, loaded);
}
class KeyTestWithKeyParam: public KeyTest, public WithParamInterface<Key> {};
INSTANTIATE_TEST_CASE_P(KeyTestWithKeyParam, KeyTestWithKeyParam, Values(Key::FromString("2898B4B8A13CA63CBE0F0278CCE465DB"), Key::FromString("6FFEBAD90C0DAA2B79628F0627CE9841")));
TEST_P(KeyTestWithKeyParam, CopyConstructor) {
Key copy(GetParam());
EXPECT_EQ(GetParam(), copy);
}
TEST_F(KeyTest, CopyConstructorDoesntChangeSource) {
Key key1 = Key::FromString(KEY1_AS_STRING);
Key key2(key1);
EXPECT_EQ(KEY1_AS_STRING, key1.ToString());
}
TEST_P(KeyTestWithKeyParam, IsEqualAfterAssignment1) {
Key key2 = Key::FromString(KEY2_AS_STRING);
EXPECT_NE(GetParam(), key2);
key2 = GetParam();
EXPECT_EQ(GetParam(), key2);
}
TEST_F(KeyTest, AssignmentDoesntChangeSource) {
Key key1 = Key::FromString(KEY1_AS_STRING);
Key key2 = Key::FromString(KEY2_AS_STRING);
key2 = key1;
EXPECT_EQ(KEY1_AS_STRING, key1.ToString());
}
// This tests that a Key object is very lightweight
// (we will often pass keys around)
TEST_F(KeyTest, KeyIsLightweightObject) {
EXPECT_EQ(Key::BINARY_LENGTH, sizeof(Key));
}

View File

@ -1,10 +1,11 @@
#include "../interface/BlockStore.h"
#include "BlockStoreUtils.h"
#include "Data.h"
#include <messmer/cpp-utils/data/Data.h>
#include <memory>
#include <cassert>
using std::unique_ptr;
using cpputils::Data;
namespace blockstore {
namespace utils {

View File

@ -1,100 +0,0 @@
#include "Data.h"
#include "FileDoesntExistException.h"
#include <stdexcept>
#include <fstream>
using std::istream;
using std::ofstream;
using std::ifstream;
using std::ios;
using std::unique_ptr;
using std::make_unique;
namespace bf = boost::filesystem;
namespace blockstore {
Data::Data(size_t size)
: _size(size), _data(std::malloc(size)) {
if (nullptr == _data) {
throw std::bad_alloc();
}
}
Data::Data(Data &&rhs)
: _size(rhs._size), _data(rhs._data) {
// Make rhs invalid, so the memory doesn't get freed in its destructor.
rhs._data = nullptr;
}
Data::~Data() {
std::free(_data);
_data = nullptr;
}
Data Data::copy() const {
Data copy(_size);
std::memcpy(copy._data, _data, _size);
return copy;
}
void *Data::data() {
return const_cast<void*>(const_cast<const Data*>(this)->data());
}
const void *Data::data() const {
return _data;
}
size_t Data::size() const {
return _size;
}
Data &Data::FillWithZeroes() {
std::memset(_data, 0, _size);
return *this;
}
void Data::StoreToFile(const bf::path &filepath) const {
ofstream file(filepath.c_str(), ios::binary | ios::trunc);
file.write((const char*)_data, _size);
}
Data Data::LoadFromFile(const bf::path &filepath) {
ifstream file(filepath.c_str(), ios::binary);
_assertFileExists(file, filepath);
size_t size = _getStreamSize(file);
Data result(size);
result._readFromStream(file);
return result;
}
void Data::_assertFileExists(const ifstream &file, const bf::path &filepath) {
if (!file.good()) {
throw FileDoesntExistException(filepath);
}
}
size_t Data::_getStreamSize(istream &stream) {
auto current_pos = stream.tellg();
//Retrieve length
stream.seekg(0, stream.end);
auto endpos = stream.tellg();
//Restore old position
stream.seekg(current_pos, stream.beg);
return endpos - current_pos;
}
void Data::_readFromStream(istream &stream) {
stream.read((char*)_data, _size);
}
bool operator==(const Data &lhs, const Data &rhs) {
return lhs.size() == rhs.size() && 0 == memcmp(lhs.data(), rhs.data(), lhs.size());
}
}

View File

@ -1,46 +0,0 @@
#pragma once
#ifndef BLOCKSTORE_IMPLEMENTATIONS_ONDISK_DATA_H_
#define BLOCKSTORE_IMPLEMENTATIONS_ONDISK_DATA_H_
#include <cstdlib>
#include <boost/filesystem/path.hpp>
#include <messmer/cpp-utils/macros.h>
#include <memory>
namespace blockstore {
class Data {
public:
explicit Data(size_t size);
Data(Data &&rhs); // move constructor
virtual ~Data();
Data copy() const;
void *data();
const void *data() const;
size_t size() const;
Data &FillWithZeroes();
void StoreToFile(const boost::filesystem::path &filepath) const;
static Data LoadFromFile(const boost::filesystem::path &filepath);
private:
size_t _size;
void *_data;
static void _assertFileExists(const std::ifstream &file, const boost::filesystem::path &filepath);
static size_t _getStreamSize(std::istream &stream);
void _readFromStream(std::istream &stream);
DISALLOW_COPY_AND_ASSIGN(Data);
};
//TODO Test operator==
bool operator==(const Data &lhs, const Data &rhs);
}
#endif

View File

@ -1,112 +0,0 @@
#pragma once
#ifndef BLOCKSTORE_UTILS_data_H_
#define BLOCKSTORE_UTILS_data_H_
#include <cryptopp/cryptopp/hex.h>
#include <cryptopp/cryptopp/osrng.h>
#include <string>
#include <cstring>
namespace blockstore {
template<unsigned int SIZE>
class FixedSizeData {
public:
//Non-virtual destructor because we want objects to be small
~FixedSizeData() {}
static constexpr unsigned int BINARY_LENGTH = SIZE;
static constexpr unsigned int STRING_LENGTH = 2 * BINARY_LENGTH; // Hex encoding
static FixedSizeData<SIZE> CreateRandom();
static FixedSizeData<SIZE> FromString(const std::string &data);
std::string ToString() const;
static FixedSizeData<SIZE> FromBinary(const void *source);
void ToBinary(void *target) const;
const unsigned char *data() const;
private:
FixedSizeData() {}
static CryptoPP::AutoSeededRandomPool &RandomPool();
unsigned char _data[BINARY_LENGTH];
};
template<unsigned int SIZE> bool operator==(const FixedSizeData<SIZE> &lhs, const FixedSizeData<SIZE> &rhs);
template<unsigned int SIZE> bool operator!=(const FixedSizeData<SIZE> &lhs, const FixedSizeData<SIZE> &rhs);
// ----- Implementation -----
template<unsigned int SIZE> constexpr unsigned int FixedSizeData<SIZE>::BINARY_LENGTH;
template<unsigned int SIZE> constexpr unsigned int FixedSizeData<SIZE>::STRING_LENGTH;
template<unsigned int SIZE>
CryptoPP::AutoSeededRandomPool &FixedSizeData<SIZE>::RandomPool() {
static CryptoPP::AutoSeededRandomPool singleton;
return singleton;
}
template<unsigned int SIZE>
FixedSizeData<SIZE> FixedSizeData<SIZE>::CreateRandom() {
FixedSizeData<SIZE> result;
RandomPool().GenerateBlock(result._data, BINARY_LENGTH);
return result;
}
template<unsigned int SIZE>
FixedSizeData<SIZE> FixedSizeData<SIZE>::FromString(const std::string &data) {
assert(data.size() == STRING_LENGTH);
FixedSizeData<SIZE> result;
CryptoPP::StringSource(data, true,
new CryptoPP::HexDecoder(
new CryptoPP::ArraySink(result._data, BINARY_LENGTH)
)
);
return result;
}
template<unsigned int SIZE>
std::string FixedSizeData<SIZE>::ToString() const {
std::string result;
CryptoPP::ArraySource(_data, BINARY_LENGTH, true,
new CryptoPP::HexEncoder(
new CryptoPP::StringSink(result)
)
);
assert(result.size() == STRING_LENGTH);
return result;
}
template<unsigned int SIZE>
const unsigned char *FixedSizeData<SIZE>::data() const {
return _data;
}
template<unsigned int SIZE>
void FixedSizeData<SIZE>::ToBinary(void *target) const {
std::memcpy(target, _data, BINARY_LENGTH);
}
template<unsigned int SIZE>
FixedSizeData<SIZE> FixedSizeData<SIZE>::FromBinary(const void *source) {
FixedSizeData<SIZE> result;
std::memcpy(result._data, source, BINARY_LENGTH);
return result;
}
template<unsigned int SIZE>
bool operator==(const FixedSizeData<SIZE> &lhs, const FixedSizeData<SIZE> &rhs) {
return 0 == std::memcmp(lhs.data(), rhs.data(), FixedSizeData<SIZE>::BINARY_LENGTH);
}
template<unsigned int SIZE>
bool operator!=(const FixedSizeData<SIZE> &lhs, const FixedSizeData<SIZE> &rhs) {
return !operator==(lhs, rhs);
}
}
#endif

View File

@ -3,12 +3,12 @@
#define BLOCKSTORE_UTILS_KEY_H_
#include <string>
#include "FixedSizeData.h"
#include <messmer/cpp-utils/data/FixedSizeData.h>
namespace blockstore {
// A key here is NOT a key for encryption, but a key as used in key->value mappings ("access handle for a block").
using Key = FixedSizeData<16>;
using Key = cpputils::FixedSizeData<16>;
}