Create dedicated Key class for addressing blocks
This commit is contained in:
parent
868c06a5f1
commit
e7aea38f83
@ -1,6 +1,5 @@
|
|||||||
#include <blockstore/implementations/inmemory/InMemoryBlock.h>
|
#include <blockstore/implementations/inmemory/InMemoryBlock.h>
|
||||||
#include <blockstore/implementations/inmemory/InMemoryBlockStore.h>
|
#include <blockstore/implementations/inmemory/InMemoryBlockStore.h>
|
||||||
#include <blockstore/utils/RandomKeyGenerator.h>
|
|
||||||
|
|
||||||
using std::unique_ptr;
|
using std::unique_ptr;
|
||||||
using std::make_unique;
|
using std::make_unique;
|
||||||
@ -14,21 +13,21 @@ namespace inmemory {
|
|||||||
InMemoryBlockStore::InMemoryBlockStore()
|
InMemoryBlockStore::InMemoryBlockStore()
|
||||||
: _blocks() {}
|
: _blocks() {}
|
||||||
|
|
||||||
unique_ptr<BlockWithKey> InMemoryBlockStore::create(const std::string &key, size_t size) {
|
unique_ptr<Block> InMemoryBlockStore::create(const Key &key, size_t size) {
|
||||||
auto insert_result = _blocks.emplace(key, size);
|
auto insert_result = _blocks.emplace(key.AsString(), size);
|
||||||
|
|
||||||
if (!insert_result.second) {
|
if (!insert_result.second) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Return a copy of the stored InMemoryBlock
|
//Return a copy of the stored InMemoryBlock
|
||||||
return make_unique<BlockWithKey>(key, make_unique<InMemoryBlock>(insert_result.first->second));
|
return make_unique<InMemoryBlock>(insert_result.first->second);
|
||||||
}
|
}
|
||||||
|
|
||||||
unique_ptr<Block> InMemoryBlockStore::load(const string &key) {
|
unique_ptr<Block> InMemoryBlockStore::load(const Key &key) {
|
||||||
//Return a copy of the stored InMemoryBlock
|
//Return a copy of the stored InMemoryBlock
|
||||||
try {
|
try {
|
||||||
return make_unique<InMemoryBlock>(_blocks.at(key));
|
return make_unique<InMemoryBlock>(_blocks.at(key.AsString()));
|
||||||
} catch (const std::out_of_range &e) {
|
} catch (const std::out_of_range &e) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
@ -16,8 +16,8 @@ class InMemoryBlockStore: public BlockStoreWithRandomKeys {
|
|||||||
public:
|
public:
|
||||||
InMemoryBlockStore();
|
InMemoryBlockStore();
|
||||||
|
|
||||||
std::unique_ptr<BlockWithKey> create(const std::string &key, size_t size) override;
|
std::unique_ptr<Block> create(const Key &key, size_t size) override;
|
||||||
std::unique_ptr<Block> load(const std::string &key) override;
|
std::unique_ptr<Block> load(const Key &key) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::map<std::string, InMemoryBlock> _blocks;
|
std::map<std::string, InMemoryBlock> _blocks;
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
#include <blockstore/implementations/ondisk/OnDiskBlock.h>
|
#include <blockstore/implementations/ondisk/OnDiskBlock.h>
|
||||||
#include <blockstore/implementations/ondisk/OnDiskBlockStore.h>
|
#include <blockstore/implementations/ondisk/OnDiskBlockStore.h>
|
||||||
#include <blockstore/utils/RandomKeyGenerator.h>
|
|
||||||
|
|
||||||
using std::unique_ptr;
|
using std::unique_ptr;
|
||||||
using std::make_unique;
|
using std::make_unique;
|
||||||
@ -16,18 +15,18 @@ namespace ondisk {
|
|||||||
OnDiskBlockStore::OnDiskBlockStore(const boost::filesystem::path &rootdir)
|
OnDiskBlockStore::OnDiskBlockStore(const boost::filesystem::path &rootdir)
|
||||||
: _rootdir(rootdir) {}
|
: _rootdir(rootdir) {}
|
||||||
|
|
||||||
unique_ptr<BlockWithKey> OnDiskBlockStore::create(const std::string &key, size_t size) {
|
unique_ptr<Block> OnDiskBlockStore::create(const Key &key, size_t size) {
|
||||||
auto file_path = _rootdir / key;
|
auto file_path = _rootdir / key.AsString();
|
||||||
auto block = OnDiskBlock::CreateOnDisk(file_path, size);
|
auto block = OnDiskBlock::CreateOnDisk(file_path, size);
|
||||||
|
|
||||||
if (!block) {
|
if (!block) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
return make_unique<BlockWithKey>(key, std::move(block));
|
return std::move(block);
|
||||||
}
|
}
|
||||||
|
|
||||||
unique_ptr<Block> OnDiskBlockStore::load(const string &key) {
|
unique_ptr<Block> OnDiskBlockStore::load(const Key &key) {
|
||||||
auto file_path = _rootdir / key;
|
auto file_path = _rootdir / key.AsString();
|
||||||
return OnDiskBlock::LoadFromDisk(file_path);
|
return OnDiskBlock::LoadFromDisk(file_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,8 +16,8 @@ class OnDiskBlockStore: public BlockStoreWithRandomKeys {
|
|||||||
public:
|
public:
|
||||||
OnDiskBlockStore(const boost::filesystem::path &rootdir);
|
OnDiskBlockStore(const boost::filesystem::path &rootdir);
|
||||||
|
|
||||||
std::unique_ptr<BlockWithKey> create(const std::string &key, size_t size) override;
|
std::unique_ptr<Block> create(const Key &key, size_t size) override;
|
||||||
std::unique_ptr<Block> load(const std::string &key) override;
|
std::unique_ptr<Block> load(const Key &key) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const boost::filesystem::path _rootdir;
|
const boost::filesystem::path _rootdir;
|
||||||
|
@ -19,7 +19,7 @@ public:
|
|||||||
virtual BlockWithKey create(size_t size) = 0;
|
virtual BlockWithKey create(size_t size) = 0;
|
||||||
//TODO Use boost::optional (if key doesn't exist)
|
//TODO Use boost::optional (if key doesn't exist)
|
||||||
// Return nullptr if block with this key doesn't exists
|
// Return nullptr if block with this key doesn't exists
|
||||||
virtual std::unique_ptr<Block> load(const std::string &key) = 0;
|
virtual std::unique_ptr<Block> load(const Key &key) = 0;
|
||||||
//TODO Needed for performance? Or is deleting loaded blocks enough?
|
//TODO Needed for performance? Or is deleting loaded blocks enough?
|
||||||
//virtual void remove(const std::string &key) = 0;
|
//virtual void remove(const std::string &key) = 0;
|
||||||
};
|
};
|
||||||
|
@ -1,19 +1,19 @@
|
|||||||
#include <blockstore/interface/helpers/BlockStoreWithRandomKeys.h>
|
#include <blockstore/interface/helpers/BlockStoreWithRandomKeys.h>
|
||||||
#include <blockstore/utils/RandomKeyGenerator.h>
|
|
||||||
|
|
||||||
using namespace blockstore;
|
using namespace blockstore;
|
||||||
|
|
||||||
using std::string;
|
using std::string;
|
||||||
|
|
||||||
BlockWithKey BlockStoreWithRandomKeys::create(size_t size) {
|
BlockWithKey BlockStoreWithRandomKeys::create(size_t size) {
|
||||||
std::unique_ptr<BlockWithKey> result;
|
BlockWithKey result = tryCreate(size);
|
||||||
do {
|
while (!result.block) {
|
||||||
result = create(_generateRandomKey(), size);
|
result = tryCreate(size);
|
||||||
} while (!result);
|
}
|
||||||
|
return result;
|
||||||
return std::move(*result);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
string BlockStoreWithRandomKeys::_generateRandomKey() {
|
BlockWithKey BlockStoreWithRandomKeys::tryCreate(size_t size) {
|
||||||
return RandomKeyGenerator::singleton().create();
|
Key key = Key::CreateRandomKey();
|
||||||
|
return BlockWithKey(key, create(key, size));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,12 +14,12 @@ class BlockStoreWithRandomKeys: public BlockStore {
|
|||||||
public:
|
public:
|
||||||
//TODO Use boost::optional (if key already exists)
|
//TODO Use boost::optional (if key already exists)
|
||||||
// Return nullptr if key already exists
|
// Return nullptr if key already exists
|
||||||
virtual std::unique_ptr<BlockWithKey> create(const std::string &key, size_t size) = 0;
|
virtual std::unique_ptr<Block> create(const Key &key, size_t size) = 0;
|
||||||
|
|
||||||
BlockWithKey create(size_t size) final;
|
BlockWithKey create(size_t size) final;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string _generateRandomKey();
|
BlockWithKey tryCreate(size_t size);
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -5,13 +5,14 @@
|
|||||||
#include <blockstore/interface/Block.h>
|
#include <blockstore/interface/Block.h>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include "fspp/utils/macros.h"
|
#include "fspp/utils/macros.h"
|
||||||
|
#include "Key.h"
|
||||||
|
|
||||||
namespace blockstore {
|
namespace blockstore {
|
||||||
|
|
||||||
struct BlockWithKey {
|
struct BlockWithKey {
|
||||||
BlockWithKey(const std::string &key_, std::unique_ptr<Block> block_): key(key_), block(std::move(block_)) {}
|
BlockWithKey(const Key &key_, std::unique_ptr<Block> block_): key(key_), block(std::move(block_)) {}
|
||||||
|
|
||||||
std::string key;
|
Key key;
|
||||||
std::unique_ptr<Block> block;
|
std::unique_ptr<Block> block;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
add_library(blockstore_utils Data.cpp RandomKeyGenerator.cpp FileDoesntExistException.cpp)
|
add_library(blockstore_utils Data.cpp Key.cpp FileDoesntExistException.cpp)
|
||||||
|
|
||||||
target_link_libraries(blockstore_utils cryptopp)
|
target_link_libraries(blockstore_utils cryptopp)
|
||||||
|
74
src/blockstore/utils/Key.cpp
Normal file
74
src/blockstore/utils/Key.cpp
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
#include <blockstore/utils/Key.h>
|
||||||
|
|
||||||
|
#include <crypto++/hex.h>
|
||||||
|
#include <crypto++/osrng.h>
|
||||||
|
|
||||||
|
using CryptoPP::ArraySource;
|
||||||
|
using CryptoPP::ArraySink;
|
||||||
|
using CryptoPP::StringSink;
|
||||||
|
using CryptoPP::StringSource;
|
||||||
|
using CryptoPP::HexEncoder;
|
||||||
|
using CryptoPP::HexDecoder;
|
||||||
|
using CryptoPP::AutoSeededRandomPool;
|
||||||
|
|
||||||
|
using std::string;
|
||||||
|
|
||||||
|
namespace blockstore {
|
||||||
|
|
||||||
|
constexpr unsigned int Key::KEYLENGTH_BINARY;
|
||||||
|
constexpr unsigned int Key::KEYLENGTH_STRING;
|
||||||
|
|
||||||
|
Key::Key() {
|
||||||
|
}
|
||||||
|
|
||||||
|
Key::~Key() {
|
||||||
|
}
|
||||||
|
|
||||||
|
AutoSeededRandomPool &RandomPool() {
|
||||||
|
static AutoSeededRandomPool singleton;
|
||||||
|
return singleton;
|
||||||
|
}
|
||||||
|
|
||||||
|
Key Key::CreateRandomKey() {
|
||||||
|
Key result;
|
||||||
|
RandomPool().GenerateBlock(result._key, KEYLENGTH_BINARY);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
Key Key::CreateDummyKey() {
|
||||||
|
Key result;
|
||||||
|
std::memset(result._key, 0, KEYLENGTH_BINARY);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
Key Key::FromString(const std::string &key) {
|
||||||
|
assert(key.size() == KEYLENGTH_STRING);
|
||||||
|
Key result;
|
||||||
|
StringSource(key, true,
|
||||||
|
new HexDecoder(new ArraySink(result._key, KEYLENGTH_BINARY))
|
||||||
|
);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
string Key::AsString() const {
|
||||||
|
string result;
|
||||||
|
ArraySource(_key, KEYLENGTH_BINARY, true,
|
||||||
|
new HexEncoder(new StringSink(result))
|
||||||
|
);
|
||||||
|
assert(result.size() == KEYLENGTH_STRING);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
const unsigned char *Key::data() const {
|
||||||
|
return _key;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==(const Key &lhs, const Key &rhs) {
|
||||||
|
return 0 == std::memcmp(lhs.data(), rhs.data(), Key::KEYLENGTH_BINARY);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator!=(const Key &lhs, const Key &rhs) {
|
||||||
|
return !operator==(lhs, rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
37
src/blockstore/utils/Key.h
Normal file
37
src/blockstore/utils/Key.h
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
#pragma once
|
||||||
|
#ifndef BLOCKSTORE_UTILS_KEY_H_
|
||||||
|
#define BLOCKSTORE_UTILS_KEY_H_
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
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").
|
||||||
|
class Key {
|
||||||
|
public:
|
||||||
|
//Non-virtual destructor because we want Key objects to be small
|
||||||
|
~Key();
|
||||||
|
|
||||||
|
static constexpr unsigned int KEYLENGTH_BINARY = 16;
|
||||||
|
static constexpr unsigned int KEYLENGTH_STRING = 2 * KEYLENGTH_BINARY; // Hex encoding
|
||||||
|
|
||||||
|
static Key CreateRandomKey();
|
||||||
|
static Key CreateDummyKey();
|
||||||
|
|
||||||
|
static Key FromString(const std::string &key);
|
||||||
|
std::string AsString() const;
|
||||||
|
|
||||||
|
const unsigned char *data() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
Key();
|
||||||
|
|
||||||
|
unsigned char _key[KEYLENGTH_BINARY];
|
||||||
|
};
|
||||||
|
|
||||||
|
bool operator==(const Key &lhs, const Key &rhs);
|
||||||
|
bool operator!=(const Key &lhs, const Key &rhs);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
@ -1,53 +0,0 @@
|
|||||||
#include <blockstore/utils/RandomKeyGenerator.h>
|
|
||||||
|
|
||||||
using std::string;
|
|
||||||
|
|
||||||
#include <crypto++/hex.h>
|
|
||||||
#include <crypto++/osrng.h>
|
|
||||||
|
|
||||||
using CryptoPP::AutoSeededRandomPool;
|
|
||||||
using CryptoPP::ArraySource;
|
|
||||||
using CryptoPP::StringSink;
|
|
||||||
using CryptoPP::HexEncoder;
|
|
||||||
|
|
||||||
using std::make_unique;
|
|
||||||
|
|
||||||
namespace blockstore {
|
|
||||||
|
|
||||||
constexpr unsigned int RandomKeyGenerator::KEYLENGTH_ENTROPY;
|
|
||||||
constexpr unsigned int RandomKeyGenerator::KEYLENGTH;
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
string encodeKeyToHex(const byte *data);
|
|
||||||
}
|
|
||||||
|
|
||||||
RandomKeyGenerator::RandomKeyGenerator()
|
|
||||||
: _randomPool(make_unique<AutoSeededRandomPool>()) {
|
|
||||||
}
|
|
||||||
|
|
||||||
RandomKeyGenerator::~RandomKeyGenerator() {
|
|
||||||
}
|
|
||||||
|
|
||||||
RandomKeyGenerator &RandomKeyGenerator::singleton() {
|
|
||||||
static RandomKeyGenerator singleton;
|
|
||||||
return singleton;
|
|
||||||
}
|
|
||||||
|
|
||||||
string RandomKeyGenerator::create() {
|
|
||||||
byte key[KEYLENGTH_ENTROPY];
|
|
||||||
_randomPool->GenerateBlock(key, KEYLENGTH_ENTROPY);
|
|
||||||
return encodeKeyToHex(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
string encodeKeyToHex(const byte *data) {
|
|
||||||
string result;
|
|
||||||
ArraySource(data, RandomKeyGenerator::KEYLENGTH_ENTROPY, true,
|
|
||||||
new HexEncoder(new StringSink(result))
|
|
||||||
);
|
|
||||||
assert(result.size() == RandomKeyGenerator::KEYLENGTH);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,37 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#ifndef BLOCKSTORE_UTILS_RANDOMKEYGENERATOR_H_
|
|
||||||
#define BLOCKSTORE_UTILS_RANDOMKEYGENERATOR_H_
|
|
||||||
|
|
||||||
#include "fspp/utils/macros.h"
|
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
namespace CryptoPP {
|
|
||||||
class AutoSeededRandomPool;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace blockstore {
|
|
||||||
|
|
||||||
// Creates random keys for use as block access handles.
|
|
||||||
// A key here is NOT a key for encryption, but a key as used in key->value mappings ("access handle for a block").
|
|
||||||
class RandomKeyGenerator {
|
|
||||||
public:
|
|
||||||
virtual ~RandomKeyGenerator();
|
|
||||||
|
|
||||||
static constexpr unsigned int KEYLENGTH_ENTROPY = 16; // random bytes in the key
|
|
||||||
static constexpr unsigned int KEYLENGTH = KEYLENGTH_ENTROPY * 2;
|
|
||||||
|
|
||||||
static RandomKeyGenerator &singleton();
|
|
||||||
|
|
||||||
std::string create();
|
|
||||||
|
|
||||||
private:
|
|
||||||
RandomKeyGenerator();
|
|
||||||
|
|
||||||
std::unique_ptr<CryptoPP::AutoSeededRandomPool> _randomPool;
|
|
||||||
|
|
||||||
DISALLOW_COPY_AND_ASSIGN(RandomKeyGenerator);
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,5 +1,4 @@
|
|||||||
#include <blockstore/interface/helpers/BlockStoreWithRandomKeys.h>
|
#include <blockstore/interface/helpers/BlockStoreWithRandomKeys.h>
|
||||||
#include <blockstore/utils/RandomKeyGenerator.h>
|
|
||||||
#include <gtest/gtest.h>
|
#include <gtest/gtest.h>
|
||||||
#include <gmock/gmock.h>
|
#include <gmock/gmock.h>
|
||||||
|
|
||||||
@ -17,15 +16,14 @@ using namespace blockstore;
|
|||||||
|
|
||||||
class BlockStoreWithRandomKeysMock: public BlockStoreWithRandomKeys {
|
class BlockStoreWithRandomKeysMock: public BlockStoreWithRandomKeys {
|
||||||
public:
|
public:
|
||||||
unique_ptr<BlockWithKey> create(const std::string &key, size_t size) {
|
unique_ptr<Block> create(const Key &key, size_t size) {
|
||||||
return unique_ptr<BlockWithKey>(do_create(key, size));
|
return unique_ptr<Block>(do_create(key, size));
|
||||||
}
|
}
|
||||||
MOCK_METHOD2(do_create, BlockWithKey*(const std::string &, size_t));
|
MOCK_METHOD2(do_create, Block*(const Key &, size_t));
|
||||||
unique_ptr<Block> load(const string &key) {
|
unique_ptr<Block> load(const Key &key) {
|
||||||
return unique_ptr<Block>(do_load(key));
|
return unique_ptr<Block>(do_load(key));
|
||||||
}
|
}
|
||||||
MOCK_METHOD1(do_load, Block*(const string &));
|
MOCK_METHOD1(do_load, Block*(const Key &));
|
||||||
MOCK_METHOD1(exists, bool(const string &));
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class BlockMock: public Block {
|
class BlockMock: public Block {
|
||||||
@ -43,39 +41,39 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
TEST_F(BlockStoreWithRandomKeysTest, SizeIsPassedThrough0) {
|
TEST_F(BlockStoreWithRandomKeysTest, SizeIsPassedThrough0) {
|
||||||
EXPECT_CALL(blockStoreMock, do_create(_, 0)).WillOnce(Return(new BlockWithKey("", make_unique<BlockMock>())));
|
EXPECT_CALL(blockStoreMock, do_create(_, 0)).WillOnce(Return(new BlockMock));
|
||||||
blockStore.create(0);
|
blockStore.create(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(BlockStoreWithRandomKeysTest, SizeIsPassedThrough1) {
|
TEST_F(BlockStoreWithRandomKeysTest, SizeIsPassedThrough1) {
|
||||||
EXPECT_CALL(blockStoreMock, do_create(_, 1)).WillOnce(Return(new BlockWithKey("", make_unique<BlockMock>())));
|
EXPECT_CALL(blockStoreMock, do_create(_, 1)).WillOnce(Return(new BlockMock));
|
||||||
blockStore.create(1);
|
blockStore.create(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(BlockStoreWithRandomKeysTest, SizeIsPassedThrough1024) {
|
TEST_F(BlockStoreWithRandomKeysTest, SizeIsPassedThrough1024) {
|
||||||
EXPECT_CALL(blockStoreMock, do_create(_, 1024)).WillOnce(Return(new BlockWithKey("", make_unique<BlockMock>())));
|
EXPECT_CALL(blockStoreMock, do_create(_, 1024)).WillOnce(Return(new BlockMock));
|
||||||
blockStore.create(1024);
|
blockStore.create(1024);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(BlockStoreWithRandomKeysTest, KeyHasCorrectSize) {
|
TEST_F(BlockStoreWithRandomKeysTest, KeyHasCorrectSize) {
|
||||||
EXPECT_CALL(blockStoreMock, do_create(_, _)).WillOnce(Invoke([](const string &key, size_t) {
|
EXPECT_CALL(blockStoreMock, do_create(_, _)).WillOnce(Invoke([](const Key &key, size_t) {
|
||||||
EXPECT_EQ(RandomKeyGenerator::KEYLENGTH, key.size());
|
EXPECT_EQ(Key::KEYLENGTH_STRING, key.AsString().size());
|
||||||
return new BlockWithKey("", make_unique<BlockMock>());
|
return new BlockMock;
|
||||||
}));
|
}));
|
||||||
|
|
||||||
blockStore.create(1024);
|
blockStore.create(1024);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(BlockStoreWithRandomKeysTest, TwoBlocksGetDifferentKeys) {
|
TEST_F(BlockStoreWithRandomKeysTest, TwoBlocksGetDifferentKeys) {
|
||||||
string first_key;
|
Key first_key = Key::CreateDummyKey();
|
||||||
EXPECT_CALL(blockStoreMock, do_create(_, _))
|
EXPECT_CALL(blockStoreMock, do_create(_, _))
|
||||||
.WillOnce(Invoke([&first_key](const string &key, size_t) {
|
.WillOnce(Invoke([&first_key](const Key &key, size_t) {
|
||||||
first_key = key;
|
first_key = key;
|
||||||
return new BlockWithKey("", make_unique<BlockMock>());
|
return new BlockMock;
|
||||||
}))
|
}))
|
||||||
.WillOnce(Invoke([&first_key](const string &key, size_t) {
|
.WillOnce(Invoke([&first_key](const Key &key, size_t) {
|
||||||
EXPECT_NE(first_key, key);
|
EXPECT_NE(first_key, key);
|
||||||
return new BlockWithKey("", make_unique<BlockMock>());
|
return new BlockMock;
|
||||||
}));
|
}));
|
||||||
|
|
||||||
blockStore.create(1024);
|
blockStore.create(1024);
|
||||||
@ -83,34 +81,34 @@ TEST_F(BlockStoreWithRandomKeysTest, TwoBlocksGetDifferentKeys) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(BlockStoreWithRandomKeysTest, WillTryADifferentKeyIfKeyAlreadyExists) {
|
TEST_F(BlockStoreWithRandomKeysTest, WillTryADifferentKeyIfKeyAlreadyExists) {
|
||||||
string first_key;
|
Key first_key = Key::CreateDummyKey();
|
||||||
EXPECT_CALL(blockStoreMock, do_create(_, _))
|
EXPECT_CALL(blockStoreMock, do_create(_, _))
|
||||||
.WillOnce(Invoke([&first_key](const string &key, size_t) {
|
.WillOnce(Invoke([&first_key](const Key &key, size_t) {
|
||||||
first_key = key;
|
first_key = key;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}))
|
}))
|
||||||
.WillOnce(Invoke([&first_key](const string &key, size_t) {
|
.WillOnce(Invoke([&first_key](const Key &key, size_t) {
|
||||||
EXPECT_NE(first_key, key);
|
EXPECT_NE(first_key, key);
|
||||||
return new BlockWithKey("", make_unique<BlockMock>());
|
return new BlockMock;
|
||||||
}));
|
}));
|
||||||
|
|
||||||
blockStore.create(1024);
|
blockStore.create(1024);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(BlockStoreWithRandomKeysTest, WillTryADifferentKeyIfKeyAlreadyExistsTwoTimes) {
|
TEST_F(BlockStoreWithRandomKeysTest, WillTryADifferentKeyIfKeyAlreadyExistsTwoTimes) {
|
||||||
string first_key;
|
Key first_key = Key::CreateDummyKey();
|
||||||
EXPECT_CALL(blockStoreMock, do_create(_, _))
|
EXPECT_CALL(blockStoreMock, do_create(_, _))
|
||||||
.WillOnce(Invoke([&first_key](const string &key, size_t) {
|
.WillOnce(Invoke([&first_key](const Key &key, size_t) {
|
||||||
first_key = key;
|
first_key = key;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}))
|
}))
|
||||||
.WillOnce(Invoke([&first_key](const string &key, size_t) {
|
.WillOnce(Invoke([&first_key](const Key &key, size_t) {
|
||||||
first_key = key;
|
first_key = key;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}))
|
}))
|
||||||
.WillOnce(Invoke([&first_key](const string &key, size_t) {
|
.WillOnce(Invoke([&first_key](const Key &key, size_t) {
|
||||||
EXPECT_NE(first_key, key);
|
EXPECT_NE(first_key, key);
|
||||||
return new BlockWithKey("", make_unique<BlockMock>());
|
return new BlockMock;
|
||||||
}));
|
}));
|
||||||
|
|
||||||
blockStore.create(1024);
|
blockStore.create(1024);
|
||||||
|
@ -3,7 +3,6 @@
|
|||||||
#define TEST_BLOCKSTORE_IMPLEMENTATIONS_TESTUTILS_BLOCKSTORETEST_H_
|
#define TEST_BLOCKSTORE_IMPLEMENTATIONS_TESTUTILS_BLOCKSTORETEST_H_
|
||||||
|
|
||||||
#include <blockstore/interface/BlockStore.h>
|
#include <blockstore/interface/BlockStore.h>
|
||||||
#include <blockstore/utils/RandomKeyGenerator.h>
|
|
||||||
#include <test/testutils/DataBlockFixture.h>
|
#include <test/testutils/DataBlockFixture.h>
|
||||||
#include "test/testutils/TempDir.h"
|
#include "test/testutils/TempDir.h"
|
||||||
|
|
||||||
@ -86,7 +85,7 @@ public:
|
|||||||
|
|
||||||
void TestAfterCreate_FlushesWhenDestructed() {
|
void TestAfterCreate_FlushesWhenDestructed() {
|
||||||
DataBlockFixture randomData(size);
|
DataBlockFixture randomData(size);
|
||||||
std::string key;
|
blockstore::Key key = blockstore::Key::CreateDummyKey();
|
||||||
{
|
{
|
||||||
auto block = blockStore->create(size);
|
auto block = blockStore->create(size);
|
||||||
key = block.key;
|
key = block.key;
|
||||||
@ -98,7 +97,7 @@ public:
|
|||||||
|
|
||||||
void TestAfterLoad_FlushesWhenDestructed() {
|
void TestAfterLoad_FlushesWhenDestructed() {
|
||||||
DataBlockFixture randomData(size);
|
DataBlockFixture randomData(size);
|
||||||
std::string key;
|
blockstore::Key key = blockstore::Key::CreateDummyKey();
|
||||||
{
|
{
|
||||||
key = blockStore->create(size).key;
|
key = blockStore->create(size).key;
|
||||||
auto block = blockStore->load(key);
|
auto block = blockStore->load(key);
|
||||||
@ -108,21 +107,15 @@ public:
|
|||||||
EXPECT_BLOCK_DATA_CORRECT(*loaded_block, randomData);
|
EXPECT_BLOCK_DATA_CORRECT(*loaded_block, randomData);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestLoadNonExistingBlockWithDefinitelyValidKey() {
|
void TestLoadNonExistingBlock() {
|
||||||
EXPECT_FALSE(
|
EXPECT_FALSE(
|
||||||
(bool)blockStore->load(blockstore::RandomKeyGenerator::singleton().create())
|
(bool)blockStore->load(blockstore::Key::CreateRandomKey())
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
void TestLoadNonExistingBlockWithMaybeInvalidKey() {
|
|
||||||
EXPECT_FALSE(
|
|
||||||
(bool)blockStore->load("not-existing-key")
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestLoadNonExistingBlockWithEmptyKey() {
|
void TestLoadNonExistingBlockWithEmptyKey() {
|
||||||
EXPECT_FALSE(
|
EXPECT_FALSE(
|
||||||
(bool)blockStore->load("")
|
(bool)blockStore->load(blockstore::Key::CreateDummyKey())
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -137,11 +130,11 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<blockstore::Block> StoreDataToBlockAndLoadIt(const DataBlockFixture &data) {
|
std::unique_ptr<blockstore::Block> StoreDataToBlockAndLoadIt(const DataBlockFixture &data) {
|
||||||
std::string key = StoreDataToBlockAndGetKey(data);
|
blockstore::Key key = StoreDataToBlockAndGetKey(data);
|
||||||
return blockStore->load(key);
|
return blockStore->load(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string StoreDataToBlockAndGetKey(const DataBlockFixture &data) {
|
blockstore::Key StoreDataToBlockAndGetKey(const DataBlockFixture &data) {
|
||||||
auto block = blockStore->create(data.size());
|
auto block = blockStore->create(data.size());
|
||||||
std::memcpy(block.block->data(), data.data(), data.size());
|
std::memcpy(block.block->data(), data.data(), data.size());
|
||||||
return block.key;
|
return block.key;
|
||||||
@ -155,7 +148,7 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<blockstore::Block> CreateBlockAndLoadIt() {
|
std::unique_ptr<blockstore::Block> CreateBlockAndLoadIt() {
|
||||||
std::string key = blockStore->create(size).key;
|
blockstore::Key key = blockStore->create(size).key;
|
||||||
return blockStore->load(key);
|
return blockStore->load(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -194,8 +187,7 @@ TYPED_TEST_P_FOR_ALL_SIZES(AfterCreate_FlushingDoesntChangeBlock);
|
|||||||
TYPED_TEST_P_FOR_ALL_SIZES(AfterLoad_FlushingDoesntChangeBlock);
|
TYPED_TEST_P_FOR_ALL_SIZES(AfterLoad_FlushingDoesntChangeBlock);
|
||||||
TYPED_TEST_P_FOR_ALL_SIZES(AfterCreate_FlushesWhenDestructed);
|
TYPED_TEST_P_FOR_ALL_SIZES(AfterCreate_FlushesWhenDestructed);
|
||||||
TYPED_TEST_P_FOR_ALL_SIZES(AfterLoad_FlushesWhenDestructed);
|
TYPED_TEST_P_FOR_ALL_SIZES(AfterLoad_FlushesWhenDestructed);
|
||||||
TYPED_TEST_P_FOR_ALL_SIZES(LoadNonExistingBlockWithDefinitelyValidKey);
|
TYPED_TEST_P_FOR_ALL_SIZES(LoadNonExistingBlock);
|
||||||
TYPED_TEST_P_FOR_ALL_SIZES(LoadNonExistingBlockWithMaybeInvalidKey);
|
|
||||||
TYPED_TEST_P_FOR_ALL_SIZES(LoadNonExistingBlockWithEmptyKey);
|
TYPED_TEST_P_FOR_ALL_SIZES(LoadNonExistingBlockWithEmptyKey);
|
||||||
|
|
||||||
TYPED_TEST_P(BlockStoreTest, TwoCreatedBlocksHaveDifferentKeys) {
|
TYPED_TEST_P(BlockStoreTest, TwoCreatedBlocksHaveDifferentKeys) {
|
||||||
@ -216,8 +208,7 @@ REGISTER_TYPED_TEST_CASE_P(BlockStoreTest,
|
|||||||
AfterLoad_FlushingDoesntChangeBlock,
|
AfterLoad_FlushingDoesntChangeBlock,
|
||||||
AfterCreate_FlushesWhenDestructed,
|
AfterCreate_FlushesWhenDestructed,
|
||||||
AfterLoad_FlushesWhenDestructed,
|
AfterLoad_FlushesWhenDestructed,
|
||||||
LoadNonExistingBlockWithDefinitelyValidKey,
|
LoadNonExistingBlock,
|
||||||
LoadNonExistingBlockWithMaybeInvalidKey,
|
|
||||||
LoadNonExistingBlockWithEmptyKey,
|
LoadNonExistingBlockWithEmptyKey,
|
||||||
TwoCreatedBlocksHaveDifferentKeys
|
TwoCreatedBlocksHaveDifferentKeys
|
||||||
);
|
);
|
||||||
|
@ -7,7 +7,6 @@
|
|||||||
#include <blockstore/interface/BlockStore.h>
|
#include <blockstore/interface/BlockStore.h>
|
||||||
#include <test/testutils/DataBlockFixture.h>
|
#include <test/testutils/DataBlockFixture.h>
|
||||||
#include "test/testutils/TempDir.h"
|
#include "test/testutils/TempDir.h"
|
||||||
#include "blockstore/utils/RandomKeyGenerator.h"
|
|
||||||
|
|
||||||
class BlockStoreWithRandomKeysTestFixture {
|
class BlockStoreWithRandomKeysTestFixture {
|
||||||
public:
|
public:
|
||||||
@ -22,6 +21,8 @@ public:
|
|||||||
"Given test fixture for instantiating the (type parameterized) BlockStoreWithRandomKeysTest must inherit from BlockStoreWithRandomKeysTestFixture"
|
"Given test fixture for instantiating the (type parameterized) BlockStoreWithRandomKeysTest must inherit from BlockStoreWithRandomKeysTestFixture"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
blockstore::Key key = blockstore::Key::CreateDummyKey();
|
||||||
|
|
||||||
const std::vector<size_t> SIZES = {0, 1, 1024, 4096, 10*1024*1024};
|
const std::vector<size_t> SIZES = {0, 1, 1024, 4096, 10*1024*1024};
|
||||||
|
|
||||||
ConcreteBlockStoreWithRandomKeysTestFixture fixture;
|
ConcreteBlockStoreWithRandomKeysTestFixture fixture;
|
||||||
@ -31,40 +32,40 @@ TYPED_TEST_CASE_P(BlockStoreWithRandomKeysTest);
|
|||||||
|
|
||||||
TYPED_TEST_P(BlockStoreWithRandomKeysTest, CreateTwoBlocksWithSameKeyAndSameSize) {
|
TYPED_TEST_P(BlockStoreWithRandomKeysTest, CreateTwoBlocksWithSameKeyAndSameSize) {
|
||||||
auto blockStore = this->fixture.createBlockStore();
|
auto blockStore = this->fixture.createBlockStore();
|
||||||
auto block = blockStore->create("mykey", 1024);
|
auto block = blockStore->create(this->key, 1024);
|
||||||
auto block2 = blockStore->create("mykey", 1024);
|
auto block2 = blockStore->create(this->key, 1024);
|
||||||
EXPECT_TRUE((bool)block);
|
EXPECT_TRUE((bool)block);
|
||||||
EXPECT_FALSE((bool)block2);
|
EXPECT_FALSE((bool)block2);
|
||||||
}
|
}
|
||||||
|
|
||||||
TYPED_TEST_P(BlockStoreWithRandomKeysTest, CreateTwoBlocksWithSameKeyAndDifferentSize) {
|
TYPED_TEST_P(BlockStoreWithRandomKeysTest, CreateTwoBlocksWithSameKeyAndDifferentSize) {
|
||||||
auto blockStore = this->fixture.createBlockStore();
|
auto blockStore = this->fixture.createBlockStore();
|
||||||
auto block = blockStore->create("mykey", 1024);
|
auto block = blockStore->create(this->key, 1024);
|
||||||
auto block2 = blockStore->create("mykey", 4096);
|
auto block2 = blockStore->create(this->key, 4096);
|
||||||
EXPECT_TRUE((bool)block);
|
EXPECT_TRUE((bool)block);
|
||||||
EXPECT_FALSE((bool)block2);
|
EXPECT_FALSE((bool)block2);
|
||||||
}
|
}
|
||||||
|
|
||||||
TYPED_TEST_P(BlockStoreWithRandomKeysTest, CreateTwoBlocksWithSameKeyAndFirstNullSize) {
|
TYPED_TEST_P(BlockStoreWithRandomKeysTest, CreateTwoBlocksWithSameKeyAndFirstNullSize) {
|
||||||
auto blockStore = this->fixture.createBlockStore();
|
auto blockStore = this->fixture.createBlockStore();
|
||||||
auto block = blockStore->create("mykey", 0);
|
auto block = blockStore->create(this->key, 0);
|
||||||
auto block2 = blockStore->create("mykey", 1024);
|
auto block2 = blockStore->create(this->key, 1024);
|
||||||
EXPECT_TRUE((bool)block);
|
EXPECT_TRUE((bool)block);
|
||||||
EXPECT_FALSE((bool)block2);
|
EXPECT_FALSE((bool)block2);
|
||||||
}
|
}
|
||||||
|
|
||||||
TYPED_TEST_P(BlockStoreWithRandomKeysTest, CreateTwoBlocksWithSameKeyAndSecondNullSize) {
|
TYPED_TEST_P(BlockStoreWithRandomKeysTest, CreateTwoBlocksWithSameKeyAndSecondNullSize) {
|
||||||
auto blockStore = this->fixture.createBlockStore();
|
auto blockStore = this->fixture.createBlockStore();
|
||||||
auto block = blockStore->create("mykey", 1024);
|
auto block = blockStore->create(this->key, 1024);
|
||||||
auto block2 = blockStore->create("mykey", 0);
|
auto block2 = blockStore->create(this->key, 0);
|
||||||
EXPECT_TRUE((bool)block);
|
EXPECT_TRUE((bool)block);
|
||||||
EXPECT_FALSE((bool)block2);
|
EXPECT_FALSE((bool)block2);
|
||||||
}
|
}
|
||||||
|
|
||||||
TYPED_TEST_P(BlockStoreWithRandomKeysTest, CreateTwoBlocksWithSameKeyAndBothNullSize) {
|
TYPED_TEST_P(BlockStoreWithRandomKeysTest, CreateTwoBlocksWithSameKeyAndBothNullSize) {
|
||||||
auto blockStore = this->fixture.createBlockStore();
|
auto blockStore = this->fixture.createBlockStore();
|
||||||
auto block = blockStore->create("mykey", 0);
|
auto block = blockStore->create(this->key, 0);
|
||||||
auto block2 = blockStore->create("mykey", 0);
|
auto block2 = blockStore->create(this->key, 0);
|
||||||
EXPECT_TRUE((bool)block);
|
EXPECT_TRUE((bool)block);
|
||||||
EXPECT_FALSE((bool)block2);
|
EXPECT_FALSE((bool)block2);
|
||||||
}
|
}
|
||||||
|
20
src/test/blockstore/utils/KeyTest.cpp
Normal file
20
src/test/blockstore/utils/KeyTest.cpp
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
#include "gtest/gtest.h"
|
||||||
|
|
||||||
|
#include <blockstore/utils/Key.h>
|
||||||
|
|
||||||
|
using ::testing::Test;
|
||||||
|
|
||||||
|
using std::string;
|
||||||
|
|
||||||
|
using namespace blockstore;
|
||||||
|
|
||||||
|
class KeyTest: public Test {};
|
||||||
|
|
||||||
|
TEST_F(KeyTest, CanGenerateRandomKeysWithoutCrashing) {
|
||||||
|
Key result = Key::CreateRandomKey();
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(KeyTest, CreatedRandomKeysHaveCorrectLength) {
|
||||||
|
auto key = Key::CreateRandomKey();
|
||||||
|
EXPECT_EQ(Key::KEYLENGTH_STRING, key.AsString().size());
|
||||||
|
}
|
@ -1,20 +0,0 @@
|
|||||||
#include <blockstore/utils/RandomKeyGenerator.h>
|
|
||||||
#include "gtest/gtest.h"
|
|
||||||
|
|
||||||
|
|
||||||
using ::testing::Test;
|
|
||||||
|
|
||||||
using std::string;
|
|
||||||
|
|
||||||
using namespace blockstore;
|
|
||||||
|
|
||||||
class RandomKeyGeneratorTest: public Test {};
|
|
||||||
|
|
||||||
TEST_F(RandomKeyGeneratorTest, RunsWithoutCrashes) {
|
|
||||||
string result = RandomKeyGenerator::singleton().create();
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(RandomKeyGeneratorTest, KeySizeIsAsSpecified) {
|
|
||||||
string result = RandomKeyGenerator::singleton().create();
|
|
||||||
EXPECT_EQ(RandomKeyGenerator::KEYLENGTH, result.size());
|
|
||||||
}
|
|
Loading…
x
Reference in New Issue
Block a user