Create dedicated Key class for addressing blocks

This commit is contained in:
Sebastian Messmer 2014-12-09 20:36:32 +01:00
parent 868c06a5f1
commit e7aea38f83
18 changed files with 208 additions and 198 deletions

View File

@ -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;
} }

View File

@ -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;

View File

@ -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);
} }

View File

@ -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;

View File

@ -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;
}; };

View File

@ -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));
} }

View File

@ -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);
}; };
} }

View File

@ -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;
}; };

View File

@ -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)

View 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);
}
}

View 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

View File

@ -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;
}
}
}

View File

@ -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

View File

@ -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);

View File

@ -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
); );

View File

@ -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);
} }

View 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());
}

View File

@ -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());
}