Separated QueueMapTest.cpp into test groups with their own files each
This commit is contained in:
parent
1ff807e09c
commit
c47434d3b3
513
test/implementations/caching/cache/QueueMapTest.cpp
vendored
513
test/implementations/caching/cache/QueueMapTest.cpp
vendored
@ -1,513 +0,0 @@
|
|||||||
#include <google/gtest/gtest.h>
|
|
||||||
#include <messmer/cpp-utils/macros.h>
|
|
||||||
#include "../../../../implementations/caching/cache/QueueMap.h"
|
|
||||||
#include <memory>
|
|
||||||
#include <boost/optional/optional_io.hpp>
|
|
||||||
|
|
||||||
using ::testing::Test;
|
|
||||||
using std::unique_ptr;
|
|
||||||
using std::make_unique;
|
|
||||||
|
|
||||||
using namespace blockstore::caching;
|
|
||||||
|
|
||||||
// This is a not-default-constructible Key type
|
|
||||||
class MinimalKeyType {
|
|
||||||
public:
|
|
||||||
static int instances;
|
|
||||||
static MinimalKeyType create(int value) {
|
|
||||||
return MinimalKeyType(value);
|
|
||||||
}
|
|
||||||
bool operator==(const MinimalKeyType &rhs) const {
|
|
||||||
return _value == rhs._value;
|
|
||||||
}
|
|
||||||
int value() const {
|
|
||||||
return _value;
|
|
||||||
}
|
|
||||||
MinimalKeyType(const MinimalKeyType &rhs): MinimalKeyType(rhs.value()) {
|
|
||||||
}
|
|
||||||
~MinimalKeyType() {
|
|
||||||
--instances;
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
MinimalKeyType(int value): _value(value) {
|
|
||||||
++instances;
|
|
||||||
}
|
|
||||||
int _value;
|
|
||||||
};
|
|
||||||
int MinimalKeyType::instances = 0;
|
|
||||||
namespace std {
|
|
||||||
template <> struct hash<MinimalKeyType> {
|
|
||||||
size_t operator()(const MinimalKeyType &obj) const {
|
|
||||||
return obj.value();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
// This is a not-default-constructible non-copyable but moveable Value type
|
|
||||||
class MinimalValueType {
|
|
||||||
public:
|
|
||||||
static int instances;
|
|
||||||
static MinimalValueType create(int value) {
|
|
||||||
return MinimalValueType(value);
|
|
||||||
}
|
|
||||||
MinimalValueType(MinimalValueType &&rhs): MinimalValueType(rhs.value()) {
|
|
||||||
rhs._isMoved = true;
|
|
||||||
}
|
|
||||||
~MinimalValueType() {
|
|
||||||
assert(!_isDestructed);
|
|
||||||
--instances;
|
|
||||||
_isDestructed = true;
|
|
||||||
}
|
|
||||||
int value() const {
|
|
||||||
assert(!_isMoved && !_isDestructed);
|
|
||||||
return _value;
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
MinimalValueType(int value): _value(value), _isMoved(false), _isDestructed(false) {
|
|
||||||
++instances;
|
|
||||||
}
|
|
||||||
int _value;
|
|
||||||
bool _isMoved;
|
|
||||||
bool _isDestructed;
|
|
||||||
DISALLOW_COPY_AND_ASSIGN(MinimalValueType);
|
|
||||||
};
|
|
||||||
int MinimalValueType::instances = 0;
|
|
||||||
|
|
||||||
class QueueMapTest: public Test {
|
|
||||||
public:
|
|
||||||
QueueMapTest() {
|
|
||||||
MinimalKeyType::instances = 0;
|
|
||||||
MinimalValueType::instances = 0;
|
|
||||||
_map = make_unique<QueueMap<MinimalKeyType, MinimalValueType>>();
|
|
||||||
}
|
|
||||||
~QueueMapTest() {
|
|
||||||
_map.reset();
|
|
||||||
EXPECT_EQ(0, MinimalKeyType::instances);
|
|
||||||
EXPECT_EQ(0, MinimalValueType::instances);
|
|
||||||
}
|
|
||||||
void push(int key, int value) {
|
|
||||||
_map->push(MinimalKeyType::create(key), MinimalValueType::create(value));
|
|
||||||
}
|
|
||||||
boost::optional<int> pop() {
|
|
||||||
auto elem = _map->pop();
|
|
||||||
if (!elem) {
|
|
||||||
return boost::none;
|
|
||||||
}
|
|
||||||
return elem.value().value();
|
|
||||||
}
|
|
||||||
boost::optional<int> pop(int key) {
|
|
||||||
auto elem = _map->pop(MinimalKeyType::create(key));
|
|
||||||
if (!elem) {
|
|
||||||
return boost::none;
|
|
||||||
}
|
|
||||||
return elem.value().value();
|
|
||||||
}
|
|
||||||
boost::optional<int> peek() {
|
|
||||||
auto elem = _map->peek();
|
|
||||||
if (!elem) {
|
|
||||||
return boost::none;
|
|
||||||
}
|
|
||||||
return elem.value().value();
|
|
||||||
}
|
|
||||||
int size() {
|
|
||||||
return _map->size();
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
unique_ptr<QueueMap<MinimalKeyType, MinimalValueType>> _map;
|
|
||||||
};
|
|
||||||
|
|
||||||
class QueueMapSizeTest: public QueueMapTest {};
|
|
||||||
|
|
||||||
TEST_F(QueueMapSizeTest, Empty) {
|
|
||||||
EXPECT_EQ(0, size());
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(QueueMapSizeTest, AfterPushingOne) {
|
|
||||||
push(2, 3);
|
|
||||||
EXPECT_EQ(1, size());
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(QueueMapSizeTest, AfterPushingTwo) {
|
|
||||||
push(2, 3);
|
|
||||||
push(3, 4);
|
|
||||||
EXPECT_EQ(2, size());
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(QueueMapSizeTest, AfterPushingTwoAndPoppingOldest) {
|
|
||||||
push(2, 3);
|
|
||||||
push(3, 4);
|
|
||||||
pop();
|
|
||||||
EXPECT_EQ(1, size());
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(QueueMapSizeTest, AfterPushingTwoAndPoppingFirst) {
|
|
||||||
push(2, 3);
|
|
||||||
push(3, 4);
|
|
||||||
pop(2);
|
|
||||||
EXPECT_EQ(1, size());
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(QueueMapSizeTest, AfterPushingTwoAndPoppingLast) {
|
|
||||||
push(2, 3);
|
|
||||||
push(3, 4);
|
|
||||||
pop(3);
|
|
||||||
EXPECT_EQ(1, size());
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(QueueMapSizeTest, AfterPushingOnePoppingOne) {
|
|
||||||
push(2, 3);
|
|
||||||
pop();
|
|
||||||
EXPECT_EQ(0, size());
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(QueueMapSizeTest, AfterPushingOnePoppingOnePerKey) {
|
|
||||||
push(2, 3);
|
|
||||||
pop(2);
|
|
||||||
EXPECT_EQ(0, size());
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(QueueMapSizeTest, AfterPushingOnePoppingOnePushingOne) {
|
|
||||||
push(2, 3);
|
|
||||||
pop();
|
|
||||||
push(3, 4);
|
|
||||||
EXPECT_EQ(1, size());
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(QueueMapSizeTest, AfterPushingOnePoppingOnePerKeyPushingOne) {
|
|
||||||
push(2, 3);
|
|
||||||
pop(2);
|
|
||||||
push(3, 4);
|
|
||||||
EXPECT_EQ(1, size());
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(QueueMapSizeTest, AfterPushingOnePoppingOnePushingSame) {
|
|
||||||
push(2, 3);
|
|
||||||
pop();
|
|
||||||
push(2, 3);
|
|
||||||
EXPECT_EQ(1, size());
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(QueueMapSizeTest, AfterPushingOnePoppingOnePerKeyPushingSame) {
|
|
||||||
push(2, 3);
|
|
||||||
pop(2);
|
|
||||||
push(2, 3);
|
|
||||||
EXPECT_EQ(1, size());
|
|
||||||
}
|
|
||||||
|
|
||||||
class QueueMapMemoryLeakTest: public QueueMapTest {
|
|
||||||
public:
|
|
||||||
void EXPECT_NUM_INSTANCES(int num) {
|
|
||||||
EXPECT_EQ(num, MinimalKeyType::instances);
|
|
||||||
EXPECT_EQ(num, MinimalValueType::instances);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
TEST_F(QueueMapMemoryLeakTest, Empty) {
|
|
||||||
EXPECT_NUM_INSTANCES(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(QueueMapMemoryLeakTest, AfterPushingOne) {
|
|
||||||
push(2, 3);
|
|
||||||
EXPECT_NUM_INSTANCES(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(QueueMapMemoryLeakTest, AfterPushingTwo) {
|
|
||||||
push(2, 3);
|
|
||||||
push(3, 4);
|
|
||||||
EXPECT_NUM_INSTANCES(2);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(QueueMapMemoryLeakTest, AfterPushingTwoAndPoppingOldest) {
|
|
||||||
push(2, 3);
|
|
||||||
push(3, 4);
|
|
||||||
pop();
|
|
||||||
EXPECT_NUM_INSTANCES(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(QueueMapMemoryLeakTest, AfterPushingTwoAndPoppingFirst) {
|
|
||||||
push(2, 3);
|
|
||||||
push(3, 4);
|
|
||||||
pop(2);
|
|
||||||
EXPECT_NUM_INSTANCES(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(QueueMapMemoryLeakTest, AfterPushingTwoAndPoppingLast) {
|
|
||||||
push(2, 3);
|
|
||||||
push(3, 4);
|
|
||||||
pop(3);
|
|
||||||
EXPECT_NUM_INSTANCES(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(QueueMapMemoryLeakTest, AfterPushingOnePoppingOne) {
|
|
||||||
push(2, 3);
|
|
||||||
pop();
|
|
||||||
EXPECT_NUM_INSTANCES(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(QueueMapMemoryLeakTest, AfterPushingOnePoppingOnePerKey) {
|
|
||||||
push(2, 3);
|
|
||||||
pop(2);
|
|
||||||
EXPECT_NUM_INSTANCES(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(QueueMapMemoryLeakTest, AfterPushingOnePoppingOnePushingOne) {
|
|
||||||
push(2, 3);
|
|
||||||
pop();
|
|
||||||
push(3, 4);
|
|
||||||
EXPECT_NUM_INSTANCES(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(QueueMapMemoryLeakTest, AfterPushingOnePoppingOnePerKeyPushingOne) {
|
|
||||||
push(2, 3);
|
|
||||||
pop(2);
|
|
||||||
push(3, 4);
|
|
||||||
EXPECT_NUM_INSTANCES(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(QueueMapMemoryLeakTest, AfterPushingOnePoppingOnePushingSame) {
|
|
||||||
push(2, 3);
|
|
||||||
pop();
|
|
||||||
push(2, 3);
|
|
||||||
EXPECT_NUM_INSTANCES(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(QueueMapMemoryLeakTest, AfterPushingOnePoppingOnePerKeyPushingSame) {
|
|
||||||
push(2, 3);
|
|
||||||
pop(2);
|
|
||||||
push(2, 3);
|
|
||||||
EXPECT_NUM_INSTANCES(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
class QueueMapValueTest: public QueueMapTest {};
|
|
||||||
|
|
||||||
TEST_F(QueueMapValueTest, PoppingFromEmpty) {
|
|
||||||
EXPECT_EQ(boost::none, pop());
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(QueueMapValueTest, PoppingFromEmptyPerKey) {
|
|
||||||
EXPECT_EQ(boost::none, pop(2));
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(QueueMapValueTest, PoppingNonexistingPerKey) {
|
|
||||||
push(3, 2);
|
|
||||||
EXPECT_EQ(boost::none, pop(2));
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(QueueMapValueTest, PushingOne) {
|
|
||||||
push(3, 2);
|
|
||||||
EXPECT_EQ(2, pop(3).value());
|
|
||||||
EXPECT_EQ(boost::none, pop());
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(QueueMapValueTest, PushingTwo) {
|
|
||||||
push(2, 3);
|
|
||||||
push(3, 4);
|
|
||||||
EXPECT_EQ(3, pop().value());
|
|
||||||
EXPECT_EQ(4, pop().value());
|
|
||||||
EXPECT_EQ(boost::none, pop());
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(QueueMapValueTest, AfterPushingTwoAndPoppingFirst) {
|
|
||||||
push(2, 3);
|
|
||||||
push(3, 4);
|
|
||||||
pop(2);
|
|
||||||
EXPECT_EQ(boost::none, pop(2));
|
|
||||||
EXPECT_EQ(4, pop(3).value());
|
|
||||||
EXPECT_EQ(boost::none, pop());
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(QueueMapValueTest, AfterPushingTwoAndPoppingLast) {
|
|
||||||
push(2, 3);
|
|
||||||
push(3, 4);
|
|
||||||
pop(3);
|
|
||||||
EXPECT_EQ(boost::none, pop(3));
|
|
||||||
EXPECT_EQ(3, pop(2).value());
|
|
||||||
EXPECT_EQ(boost::none, pop());
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(QueueMapValueTest, AfterPushingOnePoppingOne) {
|
|
||||||
push(2, 3);
|
|
||||||
pop();
|
|
||||||
EXPECT_EQ(boost::none, pop());
|
|
||||||
EXPECT_EQ(boost::none, pop(2));
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(QueueMapValueTest, AfterPushingOnePoppingOnePerKey) {
|
|
||||||
push(2, 3);
|
|
||||||
pop(2);
|
|
||||||
EXPECT_EQ(boost::none, pop());
|
|
||||||
EXPECT_EQ(boost::none, pop(2));
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(QueueMapValueTest, AfterPushingOnePoppingOnePushingOne) {
|
|
||||||
push(2, 3);
|
|
||||||
pop();
|
|
||||||
push(3, 4);
|
|
||||||
EXPECT_EQ(boost::none, pop(2));
|
|
||||||
EXPECT_EQ(4, pop(3).value());
|
|
||||||
EXPECT_EQ(boost::none, pop());
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(QueueMapValueTest, AfterPushingOnePoppingOnePerKeyPushingOne) {
|
|
||||||
push(2, 3);
|
|
||||||
pop(2);
|
|
||||||
push(3, 4);
|
|
||||||
EXPECT_EQ(boost::none, pop(2));
|
|
||||||
EXPECT_EQ(4, pop(3).value());
|
|
||||||
EXPECT_EQ(boost::none, pop());
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(QueueMapValueTest, PushingSomePoppingMiddlePerKey) {
|
|
||||||
push(1, 2);
|
|
||||||
push(2, 3);
|
|
||||||
push(3, 4);
|
|
||||||
push(4, 5);
|
|
||||||
push(5, 6);
|
|
||||||
EXPECT_EQ(3, pop(2).value());
|
|
||||||
EXPECT_EQ(5, pop(4).value());
|
|
||||||
EXPECT_EQ(2, pop().value());
|
|
||||||
EXPECT_EQ(4, pop().value());
|
|
||||||
EXPECT_EQ(6, pop().value());
|
|
||||||
EXPECT_EQ(boost::none, pop());
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(QueueMapValueTest, PushingSomePoppingFirstPerKey) {
|
|
||||||
push(1, 2);
|
|
||||||
push(2, 3);
|
|
||||||
push(3, 4);
|
|
||||||
push(4, 5);
|
|
||||||
push(5, 6);
|
|
||||||
EXPECT_EQ(2, pop(1).value());
|
|
||||||
EXPECT_EQ(3, pop(2).value());
|
|
||||||
EXPECT_EQ(4, pop().value());
|
|
||||||
EXPECT_EQ(5, pop().value());
|
|
||||||
EXPECT_EQ(6, pop().value());
|
|
||||||
EXPECT_EQ(boost::none, pop());
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(QueueMapValueTest, PushingSomePoppingLastPerKey) {
|
|
||||||
push(1, 2);
|
|
||||||
push(2, 3);
|
|
||||||
push(3, 4);
|
|
||||||
push(4, 5);
|
|
||||||
push(5, 6);
|
|
||||||
EXPECT_EQ(6, pop(5).value());
|
|
||||||
EXPECT_EQ(5, pop(4).value());
|
|
||||||
EXPECT_EQ(2, pop().value());
|
|
||||||
EXPECT_EQ(3, pop().value());
|
|
||||||
EXPECT_EQ(4, pop().value());
|
|
||||||
EXPECT_EQ(boost::none, pop());
|
|
||||||
}
|
|
||||||
|
|
||||||
//This test forces the underlying datastructure (std::map or std::unordered_map) to grow and reallocate memory.
|
|
||||||
//So it tests, that QueueMap still works after reallocating memory.
|
|
||||||
TEST_F(QueueMapValueTest, ManyValues) {
|
|
||||||
//Push 1 million entries
|
|
||||||
for (int i = 0; i < 1000000; ++i) {
|
|
||||||
push(i, 2*i);
|
|
||||||
}
|
|
||||||
//pop every other one by key
|
|
||||||
for (int i = 0; i < 1000000; i += 2) {
|
|
||||||
EXPECT_EQ(2*i, pop(i).value());
|
|
||||||
}
|
|
||||||
//pop the rest in queue order
|
|
||||||
for (int i = 1; i < 1000000; i += 2) {
|
|
||||||
EXPECT_EQ(2*i, peek().value());
|
|
||||||
EXPECT_EQ(2*i, pop().value());
|
|
||||||
}
|
|
||||||
EXPECT_EQ(0, size());
|
|
||||||
EXPECT_EQ(boost::none, pop());
|
|
||||||
EXPECT_EQ(boost::none, peek());
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(QueueMapValueTest, PushAlreadyExistingValue) {
|
|
||||||
push(2, 3);
|
|
||||||
EXPECT_ANY_THROW(
|
|
||||||
push(2, 4);
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
class QueueMapPeekTest: public QueueMapTest {};
|
|
||||||
|
|
||||||
TEST_F(QueueMapPeekTest, PoppingFromEmpty) {
|
|
||||||
EXPECT_EQ(boost::none, peek());
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(QueueMapPeekTest, PushingOne) {
|
|
||||||
push(3, 2);
|
|
||||||
EXPECT_EQ(2, peek().value());
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(QueueMapPeekTest, PushingTwo) {
|
|
||||||
push(2, 3);
|
|
||||||
push(3, 4);
|
|
||||||
EXPECT_EQ(3, peek().value());
|
|
||||||
EXPECT_EQ(3, peek().value());
|
|
||||||
EXPECT_EQ(3, pop().value());
|
|
||||||
EXPECT_EQ(4, peek().value());
|
|
||||||
EXPECT_EQ(4, peek().value());
|
|
||||||
EXPECT_EQ(4, pop().value());
|
|
||||||
EXPECT_EQ(boost::none, peek());
|
|
||||||
EXPECT_EQ(boost::none, pop());
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(QueueMapPeekTest, AfterPushingTwoAndPoppingFirst) {
|
|
||||||
push(2, 3);
|
|
||||||
push(3, 4);
|
|
||||||
pop(2);
|
|
||||||
EXPECT_EQ(boost::none, pop(2));
|
|
||||||
EXPECT_EQ(4, peek().value());
|
|
||||||
}
|
|
||||||
|
|
||||||
class CopyableValueType {
|
|
||||||
public:
|
|
||||||
static int numCopyConstructorCalled;
|
|
||||||
CopyableValueType(int value): _value(value) {}
|
|
||||||
CopyableValueType(const CopyableValueType &rhs): CopyableValueType(rhs._value) {
|
|
||||||
++numCopyConstructorCalled;
|
|
||||||
}
|
|
||||||
CopyableValueType(CopyableValueType &&rhs): CopyableValueType(rhs._value) {
|
|
||||||
//Don't increase numCopyConstructorCalled
|
|
||||||
}
|
|
||||||
int value() const {
|
|
||||||
return _value;
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
int _value;
|
|
||||||
};
|
|
||||||
int CopyableValueType::numCopyConstructorCalled = 0;
|
|
||||||
|
|
||||||
//Test that QueueMap uses a move constructor for Value if possible
|
|
||||||
class QueueMapMoveConstructorTest: public Test {
|
|
||||||
public:
|
|
||||||
QueueMapMoveConstructorTest() {
|
|
||||||
CopyableValueType::numCopyConstructorCalled = 0;
|
|
||||||
map = make_unique<QueueMap<MinimalKeyType, CopyableValueType>>();
|
|
||||||
}
|
|
||||||
unique_ptr<QueueMap<MinimalKeyType, CopyableValueType>> map;
|
|
||||||
};
|
|
||||||
|
|
||||||
TEST_F(QueueMapMoveConstructorTest, PushingAndPopping_MoveIntoMap) {
|
|
||||||
map->push(MinimalKeyType::create(0), CopyableValueType(2));
|
|
||||||
CopyableValueType val = map->pop().value();
|
|
||||||
EXPECT_EQ(0, CopyableValueType::numCopyConstructorCalled);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(QueueMapMoveConstructorTest, PushingAndPoppingPerKey_MoveIntoMap) {
|
|
||||||
map->push(MinimalKeyType::create(0), CopyableValueType(2));
|
|
||||||
CopyableValueType val = map->pop(MinimalKeyType::create(0)).value();
|
|
||||||
EXPECT_EQ(0, CopyableValueType::numCopyConstructorCalled);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(QueueMapMoveConstructorTest, PushingAndPopping_CopyIntoMap) {
|
|
||||||
CopyableValueType value(2);
|
|
||||||
map->push(MinimalKeyType::create(0), value);
|
|
||||||
CopyableValueType val = map->pop().value();
|
|
||||||
EXPECT_EQ(1, CopyableValueType::numCopyConstructorCalled);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(QueueMapMoveConstructorTest, PushingAndPoppingPerKey_CopyIntoMap) {
|
|
||||||
CopyableValueType value(2);
|
|
||||||
map->push(MinimalKeyType::create(0), value);
|
|
||||||
CopyableValueType val = map->pop(MinimalKeyType::create(0)).value();
|
|
||||||
EXPECT_EQ(1, CopyableValueType::numCopyConstructorCalled);
|
|
||||||
}
|
|
87
test/implementations/caching/cache/QueueMapTest_MemoryLeak.cpp
vendored
Normal file
87
test/implementations/caching/cache/QueueMapTest_MemoryLeak.cpp
vendored
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
#include "testutils/QueueMapTest.h"
|
||||||
|
|
||||||
|
// Tests that QueueMap calls destructors correctly.
|
||||||
|
// This is needed, because QueueMap does its own memory management.
|
||||||
|
class QueueMapTest_MemoryLeak: public QueueMapTest {
|
||||||
|
public:
|
||||||
|
void EXPECT_NUM_INSTANCES(int num) {
|
||||||
|
EXPECT_EQ(num, MinimalKeyType::instances);
|
||||||
|
EXPECT_EQ(num, MinimalValueType::instances);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST_F(QueueMapTest_MemoryLeak, Empty) {
|
||||||
|
EXPECT_NUM_INSTANCES(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(QueueMapTest_MemoryLeak, AfterPushingOne) {
|
||||||
|
push(2, 3);
|
||||||
|
EXPECT_NUM_INSTANCES(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(QueueMapTest_MemoryLeak, AfterPushingTwo) {
|
||||||
|
push(2, 3);
|
||||||
|
push(3, 4);
|
||||||
|
EXPECT_NUM_INSTANCES(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(QueueMapTest_MemoryLeak, AfterPushingTwoAndPoppingOldest) {
|
||||||
|
push(2, 3);
|
||||||
|
push(3, 4);
|
||||||
|
pop();
|
||||||
|
EXPECT_NUM_INSTANCES(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(QueueMapTest_MemoryLeak, AfterPushingTwoAndPoppingFirst) {
|
||||||
|
push(2, 3);
|
||||||
|
push(3, 4);
|
||||||
|
pop(2);
|
||||||
|
EXPECT_NUM_INSTANCES(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(QueueMapTest_MemoryLeak, AfterPushingTwoAndPoppingLast) {
|
||||||
|
push(2, 3);
|
||||||
|
push(3, 4);
|
||||||
|
pop(3);
|
||||||
|
EXPECT_NUM_INSTANCES(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(QueueMapTest_MemoryLeak, AfterPushingOnePoppingOne) {
|
||||||
|
push(2, 3);
|
||||||
|
pop();
|
||||||
|
EXPECT_NUM_INSTANCES(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(QueueMapTest_MemoryLeak, AfterPushingOnePoppingOnePerKey) {
|
||||||
|
push(2, 3);
|
||||||
|
pop(2);
|
||||||
|
EXPECT_NUM_INSTANCES(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(QueueMapTest_MemoryLeak, AfterPushingOnePoppingOnePushingOne) {
|
||||||
|
push(2, 3);
|
||||||
|
pop();
|
||||||
|
push(3, 4);
|
||||||
|
EXPECT_NUM_INSTANCES(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(QueueMapTest_MemoryLeak, AfterPushingOnePoppingOnePerKeyPushingOne) {
|
||||||
|
push(2, 3);
|
||||||
|
pop(2);
|
||||||
|
push(3, 4);
|
||||||
|
EXPECT_NUM_INSTANCES(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(QueueMapTest_MemoryLeak, AfterPushingOnePoppingOnePushingSame) {
|
||||||
|
push(2, 3);
|
||||||
|
pop();
|
||||||
|
push(2, 3);
|
||||||
|
EXPECT_NUM_INSTANCES(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(QueueMapTest_MemoryLeak, AfterPushingOnePoppingOnePerKeyPushingSame) {
|
||||||
|
push(2, 3);
|
||||||
|
pop(2);
|
||||||
|
push(2, 3);
|
||||||
|
EXPECT_NUM_INSTANCES(1);
|
||||||
|
}
|
64
test/implementations/caching/cache/QueueMapTest_MoveConstructor.cpp
vendored
Normal file
64
test/implementations/caching/cache/QueueMapTest_MoveConstructor.cpp
vendored
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
#include <google/gtest/gtest.h>
|
||||||
|
#include <memory>
|
||||||
|
#include "../../../../implementations/caching/cache/QueueMap.h"
|
||||||
|
#include "testutils/MinimalKeyType.h"
|
||||||
|
|
||||||
|
using namespace blockstore::caching;
|
||||||
|
|
||||||
|
using ::testing::Test;
|
||||||
|
using std::unique_ptr;
|
||||||
|
using std::make_unique;
|
||||||
|
|
||||||
|
class CopyableValueType {
|
||||||
|
public:
|
||||||
|
static int numCopyConstructorCalled;
|
||||||
|
CopyableValueType(int value): _value(value) {}
|
||||||
|
CopyableValueType(const CopyableValueType &rhs): CopyableValueType(rhs._value) {
|
||||||
|
++numCopyConstructorCalled;
|
||||||
|
}
|
||||||
|
CopyableValueType(CopyableValueType &&rhs): CopyableValueType(rhs._value) {
|
||||||
|
//Don't increase numCopyConstructorCalled
|
||||||
|
}
|
||||||
|
int value() const {
|
||||||
|
return _value;
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
int _value;
|
||||||
|
};
|
||||||
|
int CopyableValueType::numCopyConstructorCalled = 0;
|
||||||
|
|
||||||
|
//Test that QueueMap uses a move constructor for Value if possible
|
||||||
|
class QueueMapTest_MoveConstructor: public Test {
|
||||||
|
public:
|
||||||
|
QueueMapTest_MoveConstructor() {
|
||||||
|
CopyableValueType::numCopyConstructorCalled = 0;
|
||||||
|
map = make_unique<QueueMap<MinimalKeyType, CopyableValueType>>();
|
||||||
|
}
|
||||||
|
unique_ptr<QueueMap<MinimalKeyType, CopyableValueType>> map;
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST_F(QueueMapTest_MoveConstructor, PushingAndPopping_MoveIntoMap) {
|
||||||
|
map->push(MinimalKeyType::create(0), CopyableValueType(2));
|
||||||
|
CopyableValueType val = map->pop().value();
|
||||||
|
EXPECT_EQ(0, CopyableValueType::numCopyConstructorCalled);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(QueueMapTest_MoveConstructor, PushingAndPoppingPerKey_MoveIntoMap) {
|
||||||
|
map->push(MinimalKeyType::create(0), CopyableValueType(2));
|
||||||
|
CopyableValueType val = map->pop(MinimalKeyType::create(0)).value();
|
||||||
|
EXPECT_EQ(0, CopyableValueType::numCopyConstructorCalled);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(QueueMapTest_MoveConstructor, PushingAndPopping_CopyIntoMap) {
|
||||||
|
CopyableValueType value(2);
|
||||||
|
map->push(MinimalKeyType::create(0), value);
|
||||||
|
CopyableValueType val = map->pop().value();
|
||||||
|
EXPECT_EQ(1, CopyableValueType::numCopyConstructorCalled);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(QueueMapTest_MoveConstructor, PushingAndPoppingPerKey_CopyIntoMap) {
|
||||||
|
CopyableValueType value(2);
|
||||||
|
map->push(MinimalKeyType::create(0), value);
|
||||||
|
CopyableValueType val = map->pop(MinimalKeyType::create(0)).value();
|
||||||
|
EXPECT_EQ(1, CopyableValueType::numCopyConstructorCalled);
|
||||||
|
}
|
34
test/implementations/caching/cache/QueueMapTest_Peek.cpp
vendored
Normal file
34
test/implementations/caching/cache/QueueMapTest_Peek.cpp
vendored
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
#include "testutils/QueueMapTest.h"
|
||||||
|
#include <boost/optional/optional_io.hpp>
|
||||||
|
|
||||||
|
class QueueMapPeekTest: public QueueMapTest {};
|
||||||
|
|
||||||
|
TEST_F(QueueMapPeekTest, PoppingFromEmpty) {
|
||||||
|
EXPECT_EQ(boost::none, peek());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(QueueMapPeekTest, PushingOne) {
|
||||||
|
push(3, 2);
|
||||||
|
EXPECT_EQ(2, peek().value());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(QueueMapPeekTest, PushingTwo) {
|
||||||
|
push(2, 3);
|
||||||
|
push(3, 4);
|
||||||
|
EXPECT_EQ(3, peek().value());
|
||||||
|
EXPECT_EQ(3, peek().value());
|
||||||
|
EXPECT_EQ(3, pop().value());
|
||||||
|
EXPECT_EQ(4, peek().value());
|
||||||
|
EXPECT_EQ(4, peek().value());
|
||||||
|
EXPECT_EQ(4, pop().value());
|
||||||
|
EXPECT_EQ(boost::none, peek());
|
||||||
|
EXPECT_EQ(boost::none, pop());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(QueueMapPeekTest, AfterPushingTwoAndPoppingFirst) {
|
||||||
|
push(2, 3);
|
||||||
|
push(3, 4);
|
||||||
|
pop(2);
|
||||||
|
EXPECT_EQ(boost::none, pop(2));
|
||||||
|
EXPECT_EQ(4, peek().value());
|
||||||
|
}
|
79
test/implementations/caching/cache/QueueMapTest_Size.cpp
vendored
Normal file
79
test/implementations/caching/cache/QueueMapTest_Size.cpp
vendored
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
#include "testutils/QueueMapTest.h"
|
||||||
|
|
||||||
|
class QueueMapTest_Size: public QueueMapTest {};
|
||||||
|
|
||||||
|
TEST_F(QueueMapTest_Size, Empty) {
|
||||||
|
EXPECT_EQ(0, size());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(QueueMapTest_Size, AfterPushingOne) {
|
||||||
|
push(2, 3);
|
||||||
|
EXPECT_EQ(1, size());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(QueueMapTest_Size, AfterPushingTwo) {
|
||||||
|
push(2, 3);
|
||||||
|
push(3, 4);
|
||||||
|
EXPECT_EQ(2, size());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(QueueMapTest_Size, AfterPushingTwoAndPoppingOldest) {
|
||||||
|
push(2, 3);
|
||||||
|
push(3, 4);
|
||||||
|
pop();
|
||||||
|
EXPECT_EQ(1, size());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(QueueMapTest_Size, AfterPushingTwoAndPoppingFirst) {
|
||||||
|
push(2, 3);
|
||||||
|
push(3, 4);
|
||||||
|
pop(2);
|
||||||
|
EXPECT_EQ(1, size());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(QueueMapTest_Size, AfterPushingTwoAndPoppingLast) {
|
||||||
|
push(2, 3);
|
||||||
|
push(3, 4);
|
||||||
|
pop(3);
|
||||||
|
EXPECT_EQ(1, size());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(QueueMapTest_Size, AfterPushingOnePoppingOne) {
|
||||||
|
push(2, 3);
|
||||||
|
pop();
|
||||||
|
EXPECT_EQ(0, size());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(QueueMapTest_Size, AfterPushingOnePoppingOnePerKey) {
|
||||||
|
push(2, 3);
|
||||||
|
pop(2);
|
||||||
|
EXPECT_EQ(0, size());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(QueueMapTest_Size, AfterPushingOnePoppingOnePushingOne) {
|
||||||
|
push(2, 3);
|
||||||
|
pop();
|
||||||
|
push(3, 4);
|
||||||
|
EXPECT_EQ(1, size());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(QueueMapTest_Size, AfterPushingOnePoppingOnePerKeyPushingOne) {
|
||||||
|
push(2, 3);
|
||||||
|
pop(2);
|
||||||
|
push(3, 4);
|
||||||
|
EXPECT_EQ(1, size());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(QueueMapTest_Size, AfterPushingOnePoppingOnePushingSame) {
|
||||||
|
push(2, 3);
|
||||||
|
pop();
|
||||||
|
push(2, 3);
|
||||||
|
EXPECT_EQ(1, size());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(QueueMapTest_Size, AfterPushingOnePoppingOnePerKeyPushingSame) {
|
||||||
|
push(2, 3);
|
||||||
|
pop(2);
|
||||||
|
push(2, 3);
|
||||||
|
EXPECT_EQ(1, size());
|
||||||
|
}
|
150
test/implementations/caching/cache/QueueMapTest_Values.cpp
vendored
Normal file
150
test/implementations/caching/cache/QueueMapTest_Values.cpp
vendored
Normal file
@ -0,0 +1,150 @@
|
|||||||
|
#include "testutils/QueueMapTest.h"
|
||||||
|
|
||||||
|
class QueueMapTest_Values: public QueueMapTest {};
|
||||||
|
|
||||||
|
TEST_F(QueueMapTest_Values, PoppingFromEmpty) {
|
||||||
|
EXPECT_EQ(boost::none, pop());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(QueueMapTest_Values, PoppingFromEmptyPerKey) {
|
||||||
|
EXPECT_EQ(boost::none, pop(2));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(QueueMapTest_Values, PoppingNonexistingPerKey) {
|
||||||
|
push(3, 2);
|
||||||
|
EXPECT_EQ(boost::none, pop(2));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(QueueMapTest_Values, PushingOne) {
|
||||||
|
push(3, 2);
|
||||||
|
EXPECT_EQ(2, pop(3).value());
|
||||||
|
EXPECT_EQ(boost::none, pop());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(QueueMapTest_Values, PushingTwo) {
|
||||||
|
push(2, 3);
|
||||||
|
push(3, 4);
|
||||||
|
EXPECT_EQ(3, pop().value());
|
||||||
|
EXPECT_EQ(4, pop().value());
|
||||||
|
EXPECT_EQ(boost::none, pop());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(QueueMapTest_Values, AfterPushingTwoAndPoppingFirst) {
|
||||||
|
push(2, 3);
|
||||||
|
push(3, 4);
|
||||||
|
pop(2);
|
||||||
|
EXPECT_EQ(boost::none, pop(2));
|
||||||
|
EXPECT_EQ(4, pop(3).value());
|
||||||
|
EXPECT_EQ(boost::none, pop());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(QueueMapTest_Values, AfterPushingTwoAndPoppingLast) {
|
||||||
|
push(2, 3);
|
||||||
|
push(3, 4);
|
||||||
|
pop(3);
|
||||||
|
EXPECT_EQ(boost::none, pop(3));
|
||||||
|
EXPECT_EQ(3, pop(2).value());
|
||||||
|
EXPECT_EQ(boost::none, pop());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(QueueMapTest_Values, AfterPushingOnePoppingOne) {
|
||||||
|
push(2, 3);
|
||||||
|
pop();
|
||||||
|
EXPECT_EQ(boost::none, pop());
|
||||||
|
EXPECT_EQ(boost::none, pop(2));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(QueueMapTest_Values, AfterPushingOnePoppingOnePerKey) {
|
||||||
|
push(2, 3);
|
||||||
|
pop(2);
|
||||||
|
EXPECT_EQ(boost::none, pop());
|
||||||
|
EXPECT_EQ(boost::none, pop(2));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(QueueMapTest_Values, AfterPushingOnePoppingOnePushingOne) {
|
||||||
|
push(2, 3);
|
||||||
|
pop();
|
||||||
|
push(3, 4);
|
||||||
|
EXPECT_EQ(boost::none, pop(2));
|
||||||
|
EXPECT_EQ(4, pop(3).value());
|
||||||
|
EXPECT_EQ(boost::none, pop());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(QueueMapTest_Values, AfterPushingOnePoppingOnePerKeyPushingOne) {
|
||||||
|
push(2, 3);
|
||||||
|
pop(2);
|
||||||
|
push(3, 4);
|
||||||
|
EXPECT_EQ(boost::none, pop(2));
|
||||||
|
EXPECT_EQ(4, pop(3).value());
|
||||||
|
EXPECT_EQ(boost::none, pop());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(QueueMapTest_Values, PushingSomePoppingMiddlePerKey) {
|
||||||
|
push(1, 2);
|
||||||
|
push(2, 3);
|
||||||
|
push(3, 4);
|
||||||
|
push(4, 5);
|
||||||
|
push(5, 6);
|
||||||
|
EXPECT_EQ(3, pop(2).value());
|
||||||
|
EXPECT_EQ(5, pop(4).value());
|
||||||
|
EXPECT_EQ(2, pop().value());
|
||||||
|
EXPECT_EQ(4, pop().value());
|
||||||
|
EXPECT_EQ(6, pop().value());
|
||||||
|
EXPECT_EQ(boost::none, pop());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(QueueMapTest_Values, PushingSomePoppingFirstPerKey) {
|
||||||
|
push(1, 2);
|
||||||
|
push(2, 3);
|
||||||
|
push(3, 4);
|
||||||
|
push(4, 5);
|
||||||
|
push(5, 6);
|
||||||
|
EXPECT_EQ(2, pop(1).value());
|
||||||
|
EXPECT_EQ(3, pop(2).value());
|
||||||
|
EXPECT_EQ(4, pop().value());
|
||||||
|
EXPECT_EQ(5, pop().value());
|
||||||
|
EXPECT_EQ(6, pop().value());
|
||||||
|
EXPECT_EQ(boost::none, pop());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(QueueMapTest_Values, PushingSomePoppingLastPerKey) {
|
||||||
|
push(1, 2);
|
||||||
|
push(2, 3);
|
||||||
|
push(3, 4);
|
||||||
|
push(4, 5);
|
||||||
|
push(5, 6);
|
||||||
|
EXPECT_EQ(6, pop(5).value());
|
||||||
|
EXPECT_EQ(5, pop(4).value());
|
||||||
|
EXPECT_EQ(2, pop().value());
|
||||||
|
EXPECT_EQ(3, pop().value());
|
||||||
|
EXPECT_EQ(4, pop().value());
|
||||||
|
EXPECT_EQ(boost::none, pop());
|
||||||
|
}
|
||||||
|
|
||||||
|
//This test forces the underlying datastructure (std::map or std::unordered_map) to grow and reallocate memory.
|
||||||
|
//So it tests, that QueueMap still works after reallocating memory.
|
||||||
|
TEST_F(QueueMapTest_Values, ManyValues) {
|
||||||
|
//Push 1 million entries
|
||||||
|
for (int i = 0; i < 1000000; ++i) {
|
||||||
|
push(i, 2*i);
|
||||||
|
}
|
||||||
|
//pop every other one by key
|
||||||
|
for (int i = 0; i < 1000000; i += 2) {
|
||||||
|
EXPECT_EQ(2*i, pop(i).value());
|
||||||
|
}
|
||||||
|
//pop the rest in queue order
|
||||||
|
for (int i = 1; i < 1000000; i += 2) {
|
||||||
|
EXPECT_EQ(2*i, peek().value());
|
||||||
|
EXPECT_EQ(2*i, pop().value());
|
||||||
|
}
|
||||||
|
EXPECT_EQ(0, size());
|
||||||
|
EXPECT_EQ(boost::none, pop());
|
||||||
|
EXPECT_EQ(boost::none, peek());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(QueueMapTest_Values, PushAlreadyExistingValue) {
|
||||||
|
push(2, 3);
|
||||||
|
EXPECT_ANY_THROW(
|
||||||
|
push(2, 4);
|
||||||
|
);
|
||||||
|
}
|
3
test/implementations/caching/cache/testutils/MinimalKeyType.cpp
vendored
Normal file
3
test/implementations/caching/cache/testutils/MinimalKeyType.cpp
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
#include "MinimalKeyType.h"
|
||||||
|
|
||||||
|
int MinimalKeyType::instances = 0;
|
47
test/implementations/caching/cache/testutils/MinimalKeyType.h
vendored
Normal file
47
test/implementations/caching/cache/testutils/MinimalKeyType.h
vendored
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
#pragma once
|
||||||
|
#ifndef BLOCKS_MESSMER_BLOCKSTORE_TEST_IMPLEMENTATIONS_CACHING_CACHE_TESTUTILS_MINIMALKEYTYPE_H_
|
||||||
|
#define BLOCKS_MESSMER_BLOCKSTORE_TEST_IMPLEMENTATIONS_CACHING_CACHE_TESTUTILS_MINIMALKEYTYPE_H_
|
||||||
|
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
|
// This is a not-default-constructible Key type
|
||||||
|
class MinimalKeyType {
|
||||||
|
public:
|
||||||
|
static int instances;
|
||||||
|
|
||||||
|
static MinimalKeyType create(int value) {
|
||||||
|
return MinimalKeyType(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
MinimalKeyType(const MinimalKeyType &rhs): MinimalKeyType(rhs.value()) {
|
||||||
|
}
|
||||||
|
|
||||||
|
~MinimalKeyType() {
|
||||||
|
--instances;
|
||||||
|
}
|
||||||
|
|
||||||
|
int value() const {
|
||||||
|
return _value;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
MinimalKeyType(int value): _value(value) {
|
||||||
|
++instances;
|
||||||
|
}
|
||||||
|
|
||||||
|
int _value;
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace std {
|
||||||
|
template <> struct hash<MinimalKeyType> {
|
||||||
|
size_t operator()(const MinimalKeyType &obj) const {
|
||||||
|
return obj.value();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool operator==(const MinimalKeyType &lhs, const MinimalKeyType &rhs) {
|
||||||
|
return lhs.value() == rhs.value();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
3
test/implementations/caching/cache/testutils/MinimalValueType.cpp
vendored
Normal file
3
test/implementations/caching/cache/testutils/MinimalValueType.cpp
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
#include "MinimalValueType.h"
|
||||||
|
|
||||||
|
int MinimalValueType::instances = 0;
|
44
test/implementations/caching/cache/testutils/MinimalValueType.h
vendored
Normal file
44
test/implementations/caching/cache/testutils/MinimalValueType.h
vendored
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
#pragma once
|
||||||
|
#ifndef BLOCKS_MESSMER_BLOCKSTORE_TEST_IMPLEMENTATIONS_CACHING_CACHE_TESTUTILS_MINIMALVALUETYPE_H_
|
||||||
|
#define BLOCKS_MESSMER_BLOCKSTORE_TEST_IMPLEMENTATIONS_CACHING_CACHE_TESTUTILS_MINIMALVALUETYPE_H_
|
||||||
|
|
||||||
|
#include <messmer/cpp-utils/macros.h>
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
// This is a not-default-constructible non-copyable but moveable Value type
|
||||||
|
class MinimalValueType {
|
||||||
|
public:
|
||||||
|
static int instances;
|
||||||
|
|
||||||
|
static MinimalValueType create(int value) {
|
||||||
|
return MinimalValueType(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
MinimalValueType(MinimalValueType &&rhs): MinimalValueType(rhs.value()) {
|
||||||
|
rhs._isMoved = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
~MinimalValueType() {
|
||||||
|
assert(!_isDestructed);
|
||||||
|
--instances;
|
||||||
|
_isDestructed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int value() const {
|
||||||
|
assert(!_isMoved && !_isDestructed);
|
||||||
|
return _value;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
MinimalValueType(int value): _value(value), _isMoved(false), _isDestructed(false) {
|
||||||
|
++instances;
|
||||||
|
}
|
||||||
|
|
||||||
|
int _value;
|
||||||
|
bool _isMoved;
|
||||||
|
bool _isDestructed;
|
||||||
|
|
||||||
|
DISALLOW_COPY_AND_ASSIGN(MinimalValueType);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
45
test/implementations/caching/cache/testutils/QueueMapTest.cpp
vendored
Normal file
45
test/implementations/caching/cache/testutils/QueueMapTest.cpp
vendored
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
#include "QueueMapTest.h"
|
||||||
|
|
||||||
|
QueueMapTest::QueueMapTest() {
|
||||||
|
MinimalKeyType::instances = 0;
|
||||||
|
MinimalValueType::instances = 0;
|
||||||
|
_map = std::make_unique<blockstore::caching::QueueMap<MinimalKeyType, MinimalValueType>>();
|
||||||
|
}
|
||||||
|
|
||||||
|
QueueMapTest::~QueueMapTest() {
|
||||||
|
_map.reset();
|
||||||
|
EXPECT_EQ(0, MinimalKeyType::instances);
|
||||||
|
EXPECT_EQ(0, MinimalValueType::instances);
|
||||||
|
}
|
||||||
|
|
||||||
|
void QueueMapTest::push(int key, int value) {
|
||||||
|
_map->push(MinimalKeyType::create(key), MinimalValueType::create(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
boost::optional<int> QueueMapTest::pop() {
|
||||||
|
auto elem = _map->pop();
|
||||||
|
if (!elem) {
|
||||||
|
return boost::none;
|
||||||
|
}
|
||||||
|
return elem.value().value();
|
||||||
|
}
|
||||||
|
|
||||||
|
boost::optional<int> QueueMapTest::pop(int key) {
|
||||||
|
auto elem = _map->pop(MinimalKeyType::create(key));
|
||||||
|
if (!elem) {
|
||||||
|
return boost::none;
|
||||||
|
}
|
||||||
|
return elem.value().value();
|
||||||
|
}
|
||||||
|
|
||||||
|
boost::optional<int> QueueMapTest::peek() {
|
||||||
|
auto elem = _map->peek();
|
||||||
|
if (!elem) {
|
||||||
|
return boost::none;
|
||||||
|
}
|
||||||
|
return elem.value().value();
|
||||||
|
}
|
||||||
|
|
||||||
|
int QueueMapTest::size() {
|
||||||
|
return _map->size();
|
||||||
|
}
|
32
test/implementations/caching/cache/testutils/QueueMapTest.h
vendored
Normal file
32
test/implementations/caching/cache/testutils/QueueMapTest.h
vendored
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
#pragma once
|
||||||
|
#ifndef BLOCKS_MESSMER_BLOCKSTORE_TEST_IMPLEMENTATIONS_CACHING_CACHE_TESTUTILS_QUEUEMAPTEST_H_
|
||||||
|
#define BLOCKS_MESSMER_BLOCKSTORE_TEST_IMPLEMENTATIONS_CACHING_CACHE_TESTUTILS_QUEUEMAPTEST_H_
|
||||||
|
|
||||||
|
#include <google/gtest/gtest.h>
|
||||||
|
#include <memory>
|
||||||
|
#include "../../../../../implementations/caching/cache/QueueMap.h"
|
||||||
|
#include "MinimalKeyType.h"
|
||||||
|
#include "MinimalValueType.h"
|
||||||
|
#include <boost/optional.hpp>
|
||||||
|
|
||||||
|
// This class is a parent class for tests on QueueMap.
|
||||||
|
// It offers functions to work with a QueueMap test object which is built using types having only the minimal type requirements.
|
||||||
|
// Furthermore, the class checks that there are no memory leaks left after destructing the QueueMap (by counting leftover instances of Keys/Values).
|
||||||
|
class QueueMapTest: public ::testing::Test {
|
||||||
|
public:
|
||||||
|
QueueMapTest();
|
||||||
|
~QueueMapTest();
|
||||||
|
|
||||||
|
void push(int key, int value);
|
||||||
|
boost::optional<int> pop();
|
||||||
|
boost::optional<int> pop(int key);
|
||||||
|
boost::optional<int> peek();
|
||||||
|
int size();
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::unique_ptr<blockstore::caching::QueueMap<MinimalKeyType, MinimalValueType>> _map;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
Loading…
x
Reference in New Issue
Block a user