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/InMemoryBlockStore.h>
|
||||
#include <blockstore/utils/RandomKeyGenerator.h>
|
||||
|
||||
using std::unique_ptr;
|
||||
using std::make_unique;
|
||||
@ -14,21 +13,21 @@ namespace inmemory {
|
||||
InMemoryBlockStore::InMemoryBlockStore()
|
||||
: _blocks() {}
|
||||
|
||||
unique_ptr<BlockWithKey> InMemoryBlockStore::create(const std::string &key, size_t size) {
|
||||
auto insert_result = _blocks.emplace(key, size);
|
||||
unique_ptr<Block> InMemoryBlockStore::create(const Key &key, size_t size) {
|
||||
auto insert_result = _blocks.emplace(key.AsString(), size);
|
||||
|
||||
if (!insert_result.second) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//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
|
||||
try {
|
||||
return make_unique<InMemoryBlock>(_blocks.at(key));
|
||||
return make_unique<InMemoryBlock>(_blocks.at(key.AsString()));
|
||||
} catch (const std::out_of_range &e) {
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -16,8 +16,8 @@ class InMemoryBlockStore: public BlockStoreWithRandomKeys {
|
||||
public:
|
||||
InMemoryBlockStore();
|
||||
|
||||
std::unique_ptr<BlockWithKey> create(const std::string &key, size_t size) override;
|
||||
std::unique_ptr<Block> load(const std::string &key) override;
|
||||
std::unique_ptr<Block> create(const Key &key, size_t size) override;
|
||||
std::unique_ptr<Block> load(const Key &key) override;
|
||||
|
||||
private:
|
||||
std::map<std::string, InMemoryBlock> _blocks;
|
||||
|
@ -1,6 +1,5 @@
|
||||
#include <blockstore/implementations/ondisk/OnDiskBlock.h>
|
||||
#include <blockstore/implementations/ondisk/OnDiskBlockStore.h>
|
||||
#include <blockstore/utils/RandomKeyGenerator.h>
|
||||
|
||||
using std::unique_ptr;
|
||||
using std::make_unique;
|
||||
@ -16,18 +15,18 @@ namespace ondisk {
|
||||
OnDiskBlockStore::OnDiskBlockStore(const boost::filesystem::path &rootdir)
|
||||
: _rootdir(rootdir) {}
|
||||
|
||||
unique_ptr<BlockWithKey> OnDiskBlockStore::create(const std::string &key, size_t size) {
|
||||
auto file_path = _rootdir / key;
|
||||
unique_ptr<Block> OnDiskBlockStore::create(const Key &key, size_t size) {
|
||||
auto file_path = _rootdir / key.AsString();
|
||||
auto block = OnDiskBlock::CreateOnDisk(file_path, size);
|
||||
|
||||
if (!block) {
|
||||
return nullptr;
|
||||
}
|
||||
return make_unique<BlockWithKey>(key, std::move(block));
|
||||
return std::move(block);
|
||||
}
|
||||
|
||||
unique_ptr<Block> OnDiskBlockStore::load(const string &key) {
|
||||
auto file_path = _rootdir / key;
|
||||
unique_ptr<Block> OnDiskBlockStore::load(const Key &key) {
|
||||
auto file_path = _rootdir / key.AsString();
|
||||
return OnDiskBlock::LoadFromDisk(file_path);
|
||||
}
|
||||
|
||||
|
@ -16,8 +16,8 @@ class OnDiskBlockStore: public BlockStoreWithRandomKeys {
|
||||
public:
|
||||
OnDiskBlockStore(const boost::filesystem::path &rootdir);
|
||||
|
||||
std::unique_ptr<BlockWithKey> create(const std::string &key, size_t size) override;
|
||||
std::unique_ptr<Block> load(const std::string &key) override;
|
||||
std::unique_ptr<Block> create(const Key &key, size_t size) override;
|
||||
std::unique_ptr<Block> load(const Key &key) override;
|
||||
|
||||
private:
|
||||
const boost::filesystem::path _rootdir;
|
||||
|
@ -19,7 +19,7 @@ public:
|
||||
virtual BlockWithKey create(size_t size) = 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 std::string &key) = 0;
|
||||
virtual std::unique_ptr<Block> load(const Key &key) = 0;
|
||||
//TODO Needed for performance? Or is deleting loaded blocks enough?
|
||||
//virtual void remove(const std::string &key) = 0;
|
||||
};
|
||||
|
@ -1,19 +1,19 @@
|
||||
#include <blockstore/interface/helpers/BlockStoreWithRandomKeys.h>
|
||||
#include <blockstore/utils/RandomKeyGenerator.h>
|
||||
|
||||
using namespace blockstore;
|
||||
|
||||
using std::string;
|
||||
|
||||
BlockWithKey BlockStoreWithRandomKeys::create(size_t size) {
|
||||
std::unique_ptr<BlockWithKey> result;
|
||||
do {
|
||||
result = create(_generateRandomKey(), size);
|
||||
} while (!result);
|
||||
|
||||
return std::move(*result);
|
||||
BlockWithKey result = tryCreate(size);
|
||||
while (!result.block) {
|
||||
result = tryCreate(size);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
string BlockStoreWithRandomKeys::_generateRandomKey() {
|
||||
return RandomKeyGenerator::singleton().create();
|
||||
BlockWithKey BlockStoreWithRandomKeys::tryCreate(size_t size) {
|
||||
Key key = Key::CreateRandomKey();
|
||||
return BlockWithKey(key, create(key, size));
|
||||
}
|
||||
|
||||
|
@ -14,12 +14,12 @@ class BlockStoreWithRandomKeys: public BlockStore {
|
||||
public:
|
||||
//TODO Use boost::optional (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;
|
||||
|
||||
private:
|
||||
std::string _generateRandomKey();
|
||||
BlockWithKey tryCreate(size_t size);
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -5,13 +5,14 @@
|
||||
#include <blockstore/interface/Block.h>
|
||||
#include <memory>
|
||||
#include "fspp/utils/macros.h"
|
||||
#include "Key.h"
|
||||
|
||||
namespace blockstore {
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
|
@ -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)
|
||||
|
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/utils/RandomKeyGenerator.h>
|
||||
#include <gtest/gtest.h>
|
||||
#include <gmock/gmock.h>
|
||||
|
||||
@ -17,15 +16,14 @@ using namespace blockstore;
|
||||
|
||||
class BlockStoreWithRandomKeysMock: public BlockStoreWithRandomKeys {
|
||||
public:
|
||||
unique_ptr<BlockWithKey> create(const std::string &key, size_t size) {
|
||||
return unique_ptr<BlockWithKey>(do_create(key, size));
|
||||
unique_ptr<Block> create(const Key &key, size_t size) {
|
||||
return unique_ptr<Block>(do_create(key, size));
|
||||
}
|
||||
MOCK_METHOD2(do_create, BlockWithKey*(const std::string &, size_t));
|
||||
unique_ptr<Block> load(const string &key) {
|
||||
MOCK_METHOD2(do_create, Block*(const Key &, size_t));
|
||||
unique_ptr<Block> load(const Key &key) {
|
||||
return unique_ptr<Block>(do_load(key));
|
||||
}
|
||||
MOCK_METHOD1(do_load, Block*(const string &));
|
||||
MOCK_METHOD1(exists, bool(const string &));
|
||||
MOCK_METHOD1(do_load, Block*(const Key &));
|
||||
};
|
||||
|
||||
class BlockMock: public Block {
|
||||
@ -43,39 +41,39 @@ public:
|
||||
};
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
TEST_F(BlockStoreWithRandomKeysTest, KeyHasCorrectSize) {
|
||||
EXPECT_CALL(blockStoreMock, do_create(_, _)).WillOnce(Invoke([](const string &key, size_t) {
|
||||
EXPECT_EQ(RandomKeyGenerator::KEYLENGTH, key.size());
|
||||
return new BlockWithKey("", make_unique<BlockMock>());
|
||||
EXPECT_CALL(blockStoreMock, do_create(_, _)).WillOnce(Invoke([](const Key &key, size_t) {
|
||||
EXPECT_EQ(Key::KEYLENGTH_STRING, key.AsString().size());
|
||||
return new BlockMock;
|
||||
}));
|
||||
|
||||
blockStore.create(1024);
|
||||
}
|
||||
|
||||
TEST_F(BlockStoreWithRandomKeysTest, TwoBlocksGetDifferentKeys) {
|
||||
string first_key;
|
||||
Key first_key = Key::CreateDummyKey();
|
||||
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;
|
||||
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);
|
||||
return new BlockWithKey("", make_unique<BlockMock>());
|
||||
return new BlockMock;
|
||||
}));
|
||||
|
||||
blockStore.create(1024);
|
||||
@ -83,34 +81,34 @@ TEST_F(BlockStoreWithRandomKeysTest, TwoBlocksGetDifferentKeys) {
|
||||
}
|
||||
|
||||
TEST_F(BlockStoreWithRandomKeysTest, WillTryADifferentKeyIfKeyAlreadyExists) {
|
||||
string first_key;
|
||||
Key first_key = Key::CreateDummyKey();
|
||||
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;
|
||||
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);
|
||||
return new BlockWithKey("", make_unique<BlockMock>());
|
||||
return new BlockMock;
|
||||
}));
|
||||
|
||||
blockStore.create(1024);
|
||||
}
|
||||
|
||||
TEST_F(BlockStoreWithRandomKeysTest, WillTryADifferentKeyIfKeyAlreadyExistsTwoTimes) {
|
||||
string first_key;
|
||||
Key first_key = Key::CreateDummyKey();
|
||||
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;
|
||||
return nullptr;
|
||||
}))
|
||||
.WillOnce(Invoke([&first_key](const string &key, size_t) {
|
||||
.WillOnce(Invoke([&first_key](const Key &key, size_t) {
|
||||
first_key = key;
|
||||
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);
|
||||
return new BlockWithKey("", make_unique<BlockMock>());
|
||||
return new BlockMock;
|
||||
}));
|
||||
|
||||
blockStore.create(1024);
|
||||
|
@ -3,7 +3,6 @@
|
||||
#define TEST_BLOCKSTORE_IMPLEMENTATIONS_TESTUTILS_BLOCKSTORETEST_H_
|
||||
|
||||
#include <blockstore/interface/BlockStore.h>
|
||||
#include <blockstore/utils/RandomKeyGenerator.h>
|
||||
#include <test/testutils/DataBlockFixture.h>
|
||||
#include "test/testutils/TempDir.h"
|
||||
|
||||
@ -86,7 +85,7 @@ public:
|
||||
|
||||
void TestAfterCreate_FlushesWhenDestructed() {
|
||||
DataBlockFixture randomData(size);
|
||||
std::string key;
|
||||
blockstore::Key key = blockstore::Key::CreateDummyKey();
|
||||
{
|
||||
auto block = blockStore->create(size);
|
||||
key = block.key;
|
||||
@ -98,7 +97,7 @@ public:
|
||||
|
||||
void TestAfterLoad_FlushesWhenDestructed() {
|
||||
DataBlockFixture randomData(size);
|
||||
std::string key;
|
||||
blockstore::Key key = blockstore::Key::CreateDummyKey();
|
||||
{
|
||||
key = blockStore->create(size).key;
|
||||
auto block = blockStore->load(key);
|
||||
@ -108,21 +107,15 @@ public:
|
||||
EXPECT_BLOCK_DATA_CORRECT(*loaded_block, randomData);
|
||||
}
|
||||
|
||||
void TestLoadNonExistingBlockWithDefinitelyValidKey() {
|
||||
void TestLoadNonExistingBlock() {
|
||||
EXPECT_FALSE(
|
||||
(bool)blockStore->load(blockstore::RandomKeyGenerator::singleton().create())
|
||||
);
|
||||
}
|
||||
|
||||
void TestLoadNonExistingBlockWithMaybeInvalidKey() {
|
||||
EXPECT_FALSE(
|
||||
(bool)blockStore->load("not-existing-key")
|
||||
(bool)blockStore->load(blockstore::Key::CreateRandomKey())
|
||||
);
|
||||
}
|
||||
|
||||
void TestLoadNonExistingBlockWithEmptyKey() {
|
||||
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::string key = StoreDataToBlockAndGetKey(data);
|
||||
blockstore::Key key = StoreDataToBlockAndGetKey(data);
|
||||
return blockStore->load(key);
|
||||
}
|
||||
|
||||
std::string StoreDataToBlockAndGetKey(const DataBlockFixture &data) {
|
||||
blockstore::Key StoreDataToBlockAndGetKey(const DataBlockFixture &data) {
|
||||
auto block = blockStore->create(data.size());
|
||||
std::memcpy(block.block->data(), data.data(), data.size());
|
||||
return block.key;
|
||||
@ -155,7 +148,7 @@ private:
|
||||
}
|
||||
|
||||
std::unique_ptr<blockstore::Block> CreateBlockAndLoadIt() {
|
||||
std::string key = blockStore->create(size).key;
|
||||
blockstore::Key key = blockStore->create(size).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(AfterCreate_FlushesWhenDestructed);
|
||||
TYPED_TEST_P_FOR_ALL_SIZES(AfterLoad_FlushesWhenDestructed);
|
||||
TYPED_TEST_P_FOR_ALL_SIZES(LoadNonExistingBlockWithDefinitelyValidKey);
|
||||
TYPED_TEST_P_FOR_ALL_SIZES(LoadNonExistingBlockWithMaybeInvalidKey);
|
||||
TYPED_TEST_P_FOR_ALL_SIZES(LoadNonExistingBlock);
|
||||
TYPED_TEST_P_FOR_ALL_SIZES(LoadNonExistingBlockWithEmptyKey);
|
||||
|
||||
TYPED_TEST_P(BlockStoreTest, TwoCreatedBlocksHaveDifferentKeys) {
|
||||
@ -216,8 +208,7 @@ REGISTER_TYPED_TEST_CASE_P(BlockStoreTest,
|
||||
AfterLoad_FlushingDoesntChangeBlock,
|
||||
AfterCreate_FlushesWhenDestructed,
|
||||
AfterLoad_FlushesWhenDestructed,
|
||||
LoadNonExistingBlockWithDefinitelyValidKey,
|
||||
LoadNonExistingBlockWithMaybeInvalidKey,
|
||||
LoadNonExistingBlock,
|
||||
LoadNonExistingBlockWithEmptyKey,
|
||||
TwoCreatedBlocksHaveDifferentKeys
|
||||
);
|
||||
|
@ -7,7 +7,6 @@
|
||||
#include <blockstore/interface/BlockStore.h>
|
||||
#include <test/testutils/DataBlockFixture.h>
|
||||
#include "test/testutils/TempDir.h"
|
||||
#include "blockstore/utils/RandomKeyGenerator.h"
|
||||
|
||||
class BlockStoreWithRandomKeysTestFixture {
|
||||
public:
|
||||
@ -22,6 +21,8 @@ public:
|
||||
"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};
|
||||
|
||||
ConcreteBlockStoreWithRandomKeysTestFixture fixture;
|
||||
@ -31,40 +32,40 @@ TYPED_TEST_CASE_P(BlockStoreWithRandomKeysTest);
|
||||
|
||||
TYPED_TEST_P(BlockStoreWithRandomKeysTest, CreateTwoBlocksWithSameKeyAndSameSize) {
|
||||
auto blockStore = this->fixture.createBlockStore();
|
||||
auto block = blockStore->create("mykey", 1024);
|
||||
auto block2 = blockStore->create("mykey", 1024);
|
||||
auto block = blockStore->create(this->key, 1024);
|
||||
auto block2 = blockStore->create(this->key, 1024);
|
||||
EXPECT_TRUE((bool)block);
|
||||
EXPECT_FALSE((bool)block2);
|
||||
}
|
||||
|
||||
TYPED_TEST_P(BlockStoreWithRandomKeysTest, CreateTwoBlocksWithSameKeyAndDifferentSize) {
|
||||
auto blockStore = this->fixture.createBlockStore();
|
||||
auto block = blockStore->create("mykey", 1024);
|
||||
auto block2 = blockStore->create("mykey", 4096);
|
||||
auto block = blockStore->create(this->key, 1024);
|
||||
auto block2 = blockStore->create(this->key, 4096);
|
||||
EXPECT_TRUE((bool)block);
|
||||
EXPECT_FALSE((bool)block2);
|
||||
}
|
||||
|
||||
TYPED_TEST_P(BlockStoreWithRandomKeysTest, CreateTwoBlocksWithSameKeyAndFirstNullSize) {
|
||||
auto blockStore = this->fixture.createBlockStore();
|
||||
auto block = blockStore->create("mykey", 0);
|
||||
auto block2 = blockStore->create("mykey", 1024);
|
||||
auto block = blockStore->create(this->key, 0);
|
||||
auto block2 = blockStore->create(this->key, 1024);
|
||||
EXPECT_TRUE((bool)block);
|
||||
EXPECT_FALSE((bool)block2);
|
||||
}
|
||||
|
||||
TYPED_TEST_P(BlockStoreWithRandomKeysTest, CreateTwoBlocksWithSameKeyAndSecondNullSize) {
|
||||
auto blockStore = this->fixture.createBlockStore();
|
||||
auto block = blockStore->create("mykey", 1024);
|
||||
auto block2 = blockStore->create("mykey", 0);
|
||||
auto block = blockStore->create(this->key, 1024);
|
||||
auto block2 = blockStore->create(this->key, 0);
|
||||
EXPECT_TRUE((bool)block);
|
||||
EXPECT_FALSE((bool)block2);
|
||||
}
|
||||
|
||||
TYPED_TEST_P(BlockStoreWithRandomKeysTest, CreateTwoBlocksWithSameKeyAndBothNullSize) {
|
||||
auto blockStore = this->fixture.createBlockStore();
|
||||
auto block = blockStore->create("mykey", 0);
|
||||
auto block2 = blockStore->create("mykey", 0);
|
||||
auto block = blockStore->create(this->key, 0);
|
||||
auto block2 = blockStore->create(this->key, 0);
|
||||
EXPECT_TRUE((bool)block);
|
||||
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