summaryrefslogtreecommitdiffstats
path: root/storage/src/tests/bucketdb
diff options
context:
space:
mode:
Diffstat (limited to 'storage/src/tests/bucketdb')
-rw-r--r--storage/src/tests/bucketdb/initializertest.cpp12
-rw-r--r--storage/src/tests/bucketdb/lockablemaptest.cpp402
2 files changed, 258 insertions, 156 deletions
diff --git a/storage/src/tests/bucketdb/initializertest.cpp b/storage/src/tests/bucketdb/initializertest.cpp
index 63f990f7cc1..7d3d2c185da 100644
--- a/storage/src/tests/bucketdb/initializertest.cpp
+++ b/storage/src/tests/bucketdb/initializertest.cpp
@@ -139,11 +139,11 @@ typedef std::map<document::BucketId, BucketData> DiskData;
struct BucketInfoLogger {
std::map<PartitionId, DiskData>& map;
- BucketInfoLogger(std::map<PartitionId, DiskData>& m)
+ explicit BucketInfoLogger(std::map<PartitionId, DiskData>& m)
: map(m) {}
StorBucketDatabase::Decision operator()(
- uint64_t revBucket, StorBucketDatabase::Entry& entry)
+ uint64_t revBucket, const StorBucketDatabase::Entry& entry)
{
document::BucketId bucket(
document::BucketId::keyToBucketId(revBucket));
@@ -152,14 +152,14 @@ struct BucketInfoLogger {
DiskData& ddata(map[entry.disk]);
BucketData& bdata(ddata[bucket]);
bdata.info = entry.getBucketInfo();
- return StorBucketDatabase::CONTINUE;
+ return StorBucketDatabase::Decision::CONTINUE;
}
};
std::map<PartitionId, DiskData>
createMapFromBucketDatabase(StorBucketDatabase& db) {
std::map<PartitionId, DiskData> result;
BucketInfoLogger infoLogger(result);
- db.all(infoLogger, "createmap");
+ db.for_each(std::ref(infoLogger), "createmap");
return result;
}
// Create data we want to have in this test
@@ -551,8 +551,8 @@ struct DatabaseInsertCallback : MessageCallback
BucketData d;
StorBucketDatabase::WrappedEntry entry(
_database.get(bid, "DatabaseInsertCallback::onMessage",
- StorBucketDatabase::LOCK_IF_NONEXISTING_AND_NOT_CREATING));
- if (entry.exist()) {
+ StorBucketDatabase::CREATE_IF_NONEXISTING));
+ if (entry.preExisted()) {
_errors << "db entry for " << bid << " already existed";
}
if (i < 5) {
diff --git a/storage/src/tests/bucketdb/lockablemaptest.cpp b/storage/src/tests/bucketdb/lockablemaptest.cpp
index 101b9d014fa..50cde580f55 100644
--- a/storage/src/tests/bucketdb/lockablemaptest.cpp
+++ b/storage/src/tests/bucketdb/lockablemaptest.cpp
@@ -4,8 +4,9 @@
#include <vespa/storage/bucketdb/judymultimap.h>
#include <vespa/storage/bucketdb/judymultimap.hpp>
#include <vespa/storage/bucketdb/lockablemap.hpp>
+#include <vespa/storage/bucketdb/btree_lockable_map.hpp>
#include <vespa/vespalib/gtest/gtest.h>
-#include <boost/operators.hpp>
+#include <gmock/gmock.h>
#include <vespa/log/log.h>
LOG_SETUP(".lockable_map_test");
@@ -13,41 +14,62 @@ LOG_SETUP(".lockable_map_test");
// FIXME these old tests may have the least obvious semantics and worst naming in the entire storage module
using namespace ::testing;
+using document::BucketId;
namespace storage {
namespace {
- struct A : public boost::operators<A> {
- int _val1;
- int _val2;
- int _val3;
- A() : _val1(0), _val2(0), _val3(0) {}
- A(int val1, int val2, int val3)
- : _val1(val1), _val2(val2), _val3(val3) {}
+struct A {
+ int _val1;
+ int _val2;
+ int _val3;
- static bool mayContain(const A&) { return true; }
+ A() : _val1(0), _val2(0), _val3(0) {}
+ A(int val1, int val2, int val3)
+ : _val1(val1), _val2(val2), _val3(val3) {}
- bool operator==(const A& a) const {
- return (_val1 == a._val1 && _val2 == a._val2 && _val3 == a._val3);
- }
- bool operator<(const A& a) const {
- if (_val1 != a._val1) return (_val1 < a._val1);
- if (_val2 != a._val2) return (_val2 < a._val2);
- return (_val3 < a._val3);
- }
- };
+ static bool mayContain(const A&) { return true; }
+ // Make this type smell more like a proper bucket DB value type.
+ constexpr bool verifyLegal() const noexcept { return true; }
+ constexpr bool valid() const noexcept { return true; }
- std::ostream& operator<<(std::ostream& out, const A& a) {
- return out << "A(" << a._val1 << ", " << a._val2 << ", " << a._val3 << ")";
+ bool operator==(const A& a) const noexcept {
+ return (_val1 == a._val1 && _val2 == a._val2 && _val3 == a._val3);
+ }
+ bool operator!=(const A& a) const noexcept {
+ return !(*this == a);
}
+ bool operator<(const A& a) const noexcept {
+ if (_val1 != a._val1) return (_val1 < a._val1);
+ if (_val2 != a._val2) return (_val2 < a._val2);
+ return (_val3 < a._val3);
+ }
+};
+
+std::ostream& operator<<(std::ostream& out, const A& a) {
+ return out << "A(" << a._val1 << ", " << a._val2 << ", " << a._val3 << ")";
+}
- typedef LockableMap<JudyMultiMap<A> > Map;
}
-TEST(LockableMapTest, simple_usage) {
+template <typename MapT>
+struct LockableMapTest : ::testing::Test {
+ using Map = MapT;
+};
+
+using MapTypes = ::testing::Types<LockableMap<JudyMultiMap<A>>, bucketdb::BTreeLockableMap<A>>;
+VESPA_GTEST_TYPED_TEST_SUITE(LockableMapTest, MapTypes);
+
+// Disable warnings emitted by gtest generated files when using typed tests
+#pragma GCC diagnostic push
+#ifndef __clang__
+#pragma GCC diagnostic ignored "-Wsuggest-override"
+#endif
+
+TYPED_TEST(LockableMapTest, simple_usage) {
// Tests insert, erase, size, empty, operator[]
- Map map;
+ TypeParam map;
// Do some insertions
EXPECT_TRUE(map.empty());
bool preExisted;
@@ -57,11 +79,11 @@ TEST(LockableMapTest, simple_usage) {
EXPECT_EQ(false, preExisted);
map.insert(14, A(42, 0, 0), "foo", preExisted);
EXPECT_EQ(false, preExisted);
- EXPECT_EQ((Map::size_type) 3, map.size()) << map.toString();
+ EXPECT_THAT(map, SizeIs(3));
map.insert(11, A(4, 7, 0), "foo", preExisted);
EXPECT_EQ(true, preExisted);
- EXPECT_EQ((Map::size_type) 3, map.size());
+ EXPECT_THAT(map, SizeIs(3));
EXPECT_FALSE(map.empty());
// Access some elements
@@ -71,20 +93,20 @@ TEST(LockableMapTest, simple_usage) {
// Do removes
EXPECT_EQ(map.erase(12, "foo"), 0);
- EXPECT_EQ((Map::size_type) 3, map.size());
+ EXPECT_THAT(map, SizeIs(3));
EXPECT_EQ(map.erase(14, "foo"), 1);
- EXPECT_EQ((Map::size_type) 2, map.size());
+ EXPECT_THAT(map, SizeIs(2));
EXPECT_EQ(map.erase(11, "foo"), 1);
EXPECT_EQ(map.erase(16, "foo"), 1);
- EXPECT_EQ((Map::size_type) 0, map.size());
+ EXPECT_THAT(map, SizeIs(0));
EXPECT_TRUE(map.empty());
}
-TEST(LockableMapTest, comparison) {
- Map map1;
- Map map2;
+TYPED_TEST(LockableMapTest, comparison) {
+ TypeParam map1;
+ TypeParam map2;
bool preExisted;
// Check empty state is correct
@@ -123,154 +145,194 @@ TEST(LockableMapTest, comparison) {
}
namespace {
- struct NonConstProcessor {
- Map::Decision operator()(int key, A& a) {
- (void) key;
- ++a._val2;
- return Map::UPDATE;
+
+template <typename Map>
+struct NonConstProcessor {
+ typename Map::Decision operator()(int key, A& a) {
+ (void) key;
+ ++a._val2;
+ return Map::UPDATE;
+ }
+};
+
+template <typename Map>
+struct EntryProcessor {
+ mutable uint32_t count;
+ mutable std::vector<std::string> log;
+ mutable std::vector<typename Map::Decision> behaviour;
+
+ EntryProcessor();
+ explicit EntryProcessor(const std::vector<typename Map::Decision>& decisions);
+ ~EntryProcessor();
+
+ typename Map::Decision operator()(uint64_t key, A& a) const {
+ std::ostringstream ost;
+ ost << key << " - " << a;
+ log.push_back(ost.str());
+ typename Map::Decision d = Map::CONTINUE;
+ if (behaviour.size() > count) {
+ d = behaviour[count++];
}
- };
- struct EntryProcessor {
- mutable uint32_t count;
- mutable std::vector<std::string> log;
- mutable std::vector<Map::Decision> behaviour;
-
- EntryProcessor();
- EntryProcessor(const std::vector<Map::Decision>& decisions);
- ~EntryProcessor();
-
- Map::Decision operator()(uint64_t key, A& a) const {
- std::ostringstream ost;
- ost << key << " - " << a;
- log.push_back(ost.str());
- Map::Decision d = Map::CONTINUE;
- if (behaviour.size() > count) {
- d = behaviour[count++];
- }
- if (d == Map::UPDATE) {
- ++a._val3;
- }
- return d;
+ if (d == Map::UPDATE) {
+ ++a._val3;
}
+ return d;
+ }
- std::string toString() {
- std::ostringstream ost;
- for (uint32_t i=0; i<log.size(); ++i) {
- ost << log[i] << "\n";
- }
- return ost.str();
+ std::string toString() {
+ std::ostringstream ost;
+ for (uint32_t i=0; i<log.size(); ++i) {
+ ost << log[i] << "\n";
}
- };
-}
+ return ost.str();
+ }
+};
+
+template <typename Map>
+EntryProcessor<Map>::EntryProcessor()
+ : count(0), log(), behaviour() {}
+
+template <typename Map>
+EntryProcessor<Map>::EntryProcessor(const std::vector<typename Map::Decision>& decisions)
+ : count(0), log(), behaviour(decisions) {}
+
+template <typename Map>
+EntryProcessor<Map>::~EntryProcessor() = default;
+
+template <typename Map>
+struct ConstProcessor {
+ mutable std::vector<std::string> log;
+
+ typename Map::Decision operator()(uint64_t key, const A& a) const {
+ std::ostringstream ost;
+ ost << key << " - " << a;
+ log.push_back(ost.str());
+ return Map::CONTINUE;
+ }
-EntryProcessor::EntryProcessor() : count(0), log(), behaviour() {}
-EntryProcessor::EntryProcessor(const std::vector<Map::Decision>& decisions)
- : count(0), log(), behaviour(decisions) {}
-EntryProcessor::~EntryProcessor() = default;
+ std::string toString() {
+ std::ostringstream ost;
+ for (const auto& entry : log) {
+ ost << entry << "\n";
+ }
+ return ost.str();
+ }
+};
+
+}
-TEST(LockableMapTest, iterating) {
- Map map;
+TYPED_TEST(LockableMapTest, iterating) {
+ TypeParam map;
bool preExisted;
map.insert(16, A(1, 2, 3), "foo", preExisted);
map.insert(11, A(4, 6, 0), "foo", preExisted);
map.insert(14, A(42, 0, 0), "foo", preExisted);
- // Test that we can use functor with non-const function
+ // Test that we can use functor with non-const function
{
- NonConstProcessor ncproc;
- map.each(ncproc, "foo"); // Locking both for each element
+ NonConstProcessor<TypeParam> ncproc;
+ map.for_each_mutable(std::ref(ncproc), "foo"); // First round of mutating functor for `all`
EXPECT_EQ(A(4, 7, 0), *map.get(11, "foo"));
EXPECT_EQ(A(42,1, 0), *map.get(14, "foo"));
EXPECT_EQ(A(1, 3, 3), *map.get(16, "foo"));
- map.all(ncproc, "foo"); // And for all
+ map.for_each_mutable(std::ref(ncproc), "foo"); // Once more, with feeling.
EXPECT_EQ(A(4, 8, 0), *map.get(11, "foo"));
EXPECT_EQ(A(42,2, 0), *map.get(14, "foo"));
EXPECT_EQ(A(1, 4, 3), *map.get(16, "foo"));
}
- // Test that we can use const functors directly..
- map.each(EntryProcessor(), "foo");
- // Test iterator bounds
{
- EntryProcessor proc;
- map.each(proc, "foo", 11, 16);
+ ConstProcessor<TypeParam> cproc;
+ map.for_each(std::ref(cproc), "foo");
+ std::string expected("11 - A(4, 8, 0)\n"
+ "14 - A(42, 2, 0)\n"
+ "16 - A(1, 4, 3)\n");
+ EXPECT_EQ(expected, cproc.toString());
+ }
+ // Test that we can use const functors directly..
+ map.for_each(ConstProcessor<TypeParam>(), "foo");
+
+ // Test iterator bounds
+ {
+ EntryProcessor<TypeParam> proc;
+ map.for_each_mutable(std::ref(proc), "foo", 11, 16);
std::string expected("11 - A(4, 8, 0)\n"
"14 - A(42, 2, 0)\n"
"16 - A(1, 4, 3)\n");
EXPECT_EQ(expected, proc.toString());
- EntryProcessor proc2;
- map.each(proc2, "foo", 12, 15);
+ EntryProcessor<TypeParam> proc2;
+ map.for_each_mutable(std::ref(proc2), "foo", 12, 15);
expected = "14 - A(42, 2, 0)\n";
EXPECT_EQ(expected, proc2.toString());
}
// Test that we can abort iterating
{
- std::vector<Map::Decision> decisions;
- decisions.push_back(Map::CONTINUE);
- decisions.push_back(Map::ABORT);
- EntryProcessor proc(decisions);
- map.each(proc, "foo");
+ std::vector<typename TypeParam::Decision> decisions;
+ decisions.push_back(TypeParam::CONTINUE);
+ decisions.push_back(TypeParam::ABORT);
+ EntryProcessor<TypeParam> proc(decisions);
+ map.for_each_mutable(std::ref(proc), "foo");
std::string expected("11 - A(4, 8, 0)\n"
"14 - A(42, 2, 0)\n");
EXPECT_EQ(expected, proc.toString());
}
- // Test that we can remove during iteration
+ // Test that we can remove during iteration
{
- std::vector<Map::Decision> decisions;
- decisions.push_back(Map::CONTINUE);
- decisions.push_back(Map::REMOVE);
- EntryProcessor proc(decisions);
- map.each(proc, "foo");
+ std::vector<typename TypeParam::Decision> decisions;
+ decisions.push_back(TypeParam::CONTINUE);
+ decisions.push_back(TypeParam::REMOVE); // TODO consider removing; not used
+ EntryProcessor<TypeParam> proc(decisions);
+ map.for_each_mutable(std::ref(proc), "foo");
std::string expected("11 - A(4, 8, 0)\n"
"14 - A(42, 2, 0)\n"
"16 - A(1, 4, 3)\n");
EXPECT_EQ(expected, proc.toString());
- EXPECT_EQ((Map::size_type) 2, map.size()) << map.toString();
+ EXPECT_EQ(2u, map.size());
EXPECT_EQ(A(4, 8, 0), *map.get(11, "foo"));
EXPECT_EQ(A(1, 4, 3), *map.get(16, "foo"));
- Map::WrappedEntry entry = map.get(14, "foo");
+ auto entry = map.get(14, "foo");
EXPECT_FALSE(entry.exist());
}
}
-TEST(LockableMapTest, chunked_iteration_is_transparent_across_chunk_sizes) {
- Map map;
+TYPED_TEST(LockableMapTest, chunked_iteration_is_transparent_across_chunk_sizes) {
+ TypeParam map;
bool preExisted;
map.insert(16, A(1, 2, 3), "foo", preExisted);
map.insert(11, A(4, 6, 0), "foo", preExisted);
map.insert(14, A(42, 0, 0), "foo", preExisted);
- NonConstProcessor ncproc; // Increments 2nd value in all entries.
- // chunkedAll with chunk size of 1
- map.chunkedAll(ncproc, "foo", 1us, 1);
+ NonConstProcessor<TypeParam> ncproc; // Increments 2nd value in all entries.
+ // for_each_chunked with chunk size of 1
+ map.for_each_chunked(std::ref(ncproc), "foo", 1us, 1);
EXPECT_EQ(A(4, 7, 0), *map.get(11, "foo"));
EXPECT_EQ(A(42, 1, 0), *map.get(14, "foo"));
EXPECT_EQ(A(1, 3, 3), *map.get(16, "foo"));
- // chunkedAll with chunk size larger than db size
- map.chunkedAll(ncproc, "foo", 1us, 100);
+ // for_each_chunked with chunk size larger than db size
+ map.for_each_chunked(std::ref(ncproc), "foo", 1us, 100);
EXPECT_EQ(A(4, 8, 0), *map.get(11, "foo"));
EXPECT_EQ(A(42, 2, 0), *map.get(14, "foo"));
EXPECT_EQ(A(1, 4, 3), *map.get(16, "foo"));
}
-TEST(LockableMapTest, can_abort_during_chunked_iteration) {
- Map map;
+TYPED_TEST(LockableMapTest, can_abort_during_chunked_iteration) {
+ TypeParam map;
bool preExisted;
map.insert(16, A(1, 2, 3), "foo", preExisted);
map.insert(11, A(4, 6, 0), "foo", preExisted);
map.insert(14, A(42, 0, 0), "foo", preExisted);
- std::vector<Map::Decision> decisions;
- decisions.push_back(Map::CONTINUE);
- decisions.push_back(Map::ABORT);
- EntryProcessor proc(decisions);
- map.chunkedAll(proc, "foo", 1us, 100);
+ std::vector<typename TypeParam::Decision> decisions;
+ decisions.push_back(TypeParam::CONTINUE);
+ decisions.push_back(TypeParam::ABORT);
+ EntryProcessor<TypeParam> proc(decisions);
+ map.for_each_chunked(std::ref(proc), "foo", 1us, 100);
std::string expected("11 - A(4, 6, 0)\n"
"14 - A(42, 0, 0)\n");
EXPECT_EQ(expected, proc.toString());
}
-TEST(LockableMapTest, find_buckets_simple) {
- Map map;
+TYPED_TEST(LockableMapTest, find_buckets_simple) {
+ TypeParam map;
document::BucketId id1(17, 0x0ffff);
id1 = id1.stripUnused();
@@ -293,8 +355,8 @@ TEST(LockableMapTest, find_buckets_simple) {
EXPECT_EQ(A(3,4,5), *results[id3]);
}
-TEST(LockableMapTest, find_buckets) {
- Map map;
+TYPED_TEST(LockableMapTest, find_buckets) {
+ TypeParam map;
document::BucketId id1(16, 0x0ffff);
document::BucketId id2(17, 0x0ffff);
@@ -317,8 +379,8 @@ TEST(LockableMapTest, find_buckets) {
EXPECT_EQ(A(3,4,5), *results[id3.stripUnused()]);
}
-TEST(LockableMapTest, find_buckets_2) { // ticket 3121525
- Map map;
+TYPED_TEST(LockableMapTest, find_buckets_2) { // ticket 3121525
+ TypeParam map;
document::BucketId id1(16, 0x0ffff);
document::BucketId id2(17, 0x0ffff);
@@ -341,8 +403,8 @@ TEST(LockableMapTest, find_buckets_2) { // ticket 3121525
EXPECT_EQ(A(3,4,5), *results[id3.stripUnused()]);
}
-TEST(LockableMapTest, find_buckets_3) { // ticket 3121525
- Map map;
+TYPED_TEST(LockableMapTest, find_buckets_3) { // ticket 3121525
+ TypeParam map;
document::BucketId id1(16, 0x0ffff);
document::BucketId id2(17, 0x0ffff);
@@ -359,8 +421,8 @@ TEST(LockableMapTest, find_buckets_3) { // ticket 3121525
EXPECT_EQ(A(1,2,3), *results[id1.stripUnused()]);
}
-TEST(LockableMapTest, find_buckets_4) { // ticket 3121525
- Map map;
+TYPED_TEST(LockableMapTest, find_buckets_4) { // ticket 3121525
+ TypeParam map;
document::BucketId id1(16, 0x0ffff);
document::BucketId id2(17, 0x0ffff);
@@ -379,8 +441,8 @@ TEST(LockableMapTest, find_buckets_4) { // ticket 3121525
EXPECT_EQ(A(1,2,3), *results[id1.stripUnused()]);
}
-TEST(LockableMapTest, find_buckets_5) { // ticket 3121525
- Map map;
+TYPED_TEST(LockableMapTest, find_buckets_5) { // ticket 3121525
+ TypeParam map;
document::BucketId id1(16, 0x0ffff);
document::BucketId id2(17, 0x0ffff);
@@ -399,8 +461,8 @@ TEST(LockableMapTest, find_buckets_5) { // ticket 3121525
EXPECT_EQ(A(1,2,3), *results[id1.stripUnused()]);
}
-TEST(LockableMapTest, find_no_buckets) {
- Map map;
+TYPED_TEST(LockableMapTest, find_no_buckets) {
+ TypeParam map;
document::BucketId id(16, 0x0ffff);
auto results = map.getAll(id, "foo");
@@ -408,8 +470,8 @@ TEST(LockableMapTest, find_no_buckets) {
EXPECT_EQ(0, results.size());
}
-TEST(LockableMapTest, find_all) {
- Map map;
+TYPED_TEST(LockableMapTest, find_all) {
+ TypeParam map;
document::BucketId id1(16, 0x0aaaa); // contains id2-id7
document::BucketId id2(17, 0x0aaaa); // contains id3-id4
@@ -450,8 +512,8 @@ TEST(LockableMapTest, find_all) {
EXPECT_EQ(A(9,10,11), *results[id9.stripUnused()]); // sub bucket
}
-TEST(LockableMapTest, find_all_2) { // Ticket 3121525
- Map map;
+TYPED_TEST(LockableMapTest, find_all_2) { // Ticket 3121525
+ TypeParam map;
document::BucketId id1(17, 0x00001);
document::BucketId id2(17, 0x10001);
@@ -469,8 +531,8 @@ TEST(LockableMapTest, find_all_2) { // Ticket 3121525
EXPECT_EQ(A(2,3,4), *results[id2.stripUnused()]); // sub bucket
}
-TEST(LockableMapTest, find_all_unused_bit_is_set) { // ticket 2938896
- Map map;
+TYPED_TEST(LockableMapTest, find_all_unused_bit_is_set) { // ticket 2938896
+ TypeParam map;
document::BucketId id1(24, 0x000dc7089);
document::BucketId id2(33, 0x0053c7089);
@@ -493,8 +555,8 @@ TEST(LockableMapTest, find_all_unused_bit_is_set) { // ticket 2938896
EXPECT_EQ(A(3,4,5), *results[id3.stripUnused()]); // sub bucket
}
-TEST(LockableMapTest, find_all_inconsistently_split) { // Ticket 2938896
- Map map;
+TYPED_TEST(LockableMapTest, find_all_inconsistently_split) { // Ticket 2938896
+ TypeParam map;
document::BucketId id1(16, 0x00001); // contains id2-id3
document::BucketId id2(17, 0x00001);
@@ -515,8 +577,8 @@ TEST(LockableMapTest, find_all_inconsistently_split) { // Ticket 2938896
EXPECT_EQ(A(3,4,5), *results[id3.stripUnused()]); // sub bucket
}
-TEST(LockableMapTest, find_all_inconsistently_split_2) { // ticket 3121525
- Map map;
+TYPED_TEST(LockableMapTest, find_all_inconsistently_split_2) { // ticket 3121525
+ TypeParam map;
document::BucketId id1(17, 0x10000);
document::BucketId id2(27, 0x007228034); // contains id3
@@ -538,8 +600,8 @@ TEST(LockableMapTest, find_all_inconsistently_split_2) { // ticket 3121525
EXPECT_EQ(A(3,4,5), *results[id3.stripUnused()]); // most specific match (super bucket)
}
-TEST(LockableMapTest, find_all_inconsistently_split_3) { // ticket 3121525
- Map map;
+TYPED_TEST(LockableMapTest, find_all_inconsistently_split_3) { // ticket 3121525
+ TypeParam map;
document::BucketId id1(16, 0x0ffff); // contains id2
document::BucketId id2(17, 0x0ffff);
@@ -556,8 +618,8 @@ TEST(LockableMapTest, find_all_inconsistently_split_3) { // ticket 3121525
EXPECT_EQ(A(1,2,3), *results[id1.stripUnused()]); // super bucket
}
-TEST(LockableMapTest, find_all_inconsistently_split_4) { // ticket 3121525
- Map map;
+TYPED_TEST(LockableMapTest, find_all_inconsistently_split_4) { // ticket 3121525
+ TypeParam map;
document::BucketId id1(16, 0x0ffff); // contains id2-id3
document::BucketId id2(17, 0x0ffff);
@@ -577,8 +639,8 @@ TEST(LockableMapTest, find_all_inconsistently_split_4) { // ticket 3121525
EXPECT_EQ(A(3,4,5), *results[id3.stripUnused()]); // sub bucket
}
-TEST(LockableMapTest, find_all_inconsistently_split_5) { // ticket 3121525
- Map map;
+TYPED_TEST(LockableMapTest, find_all_inconsistently_split_5) { // ticket 3121525
+ TypeParam map;
document::BucketId id1(16, 0x0ffff); // contains id2-id3
document::BucketId id2(17, 0x0ffff);
@@ -598,8 +660,8 @@ TEST(LockableMapTest, find_all_inconsistently_split_5) { // ticket 3121525
EXPECT_EQ(A(3,4,5), *results[id3.stripUnused()]); // sub bucket
}
-TEST(LockableMapTest, find_all_inconsistently_split_6) {
- Map map;
+TYPED_TEST(LockableMapTest, find_all_inconsistently_split_6) {
+ TypeParam map;
document::BucketId id1(16, 0x0ffff); // contains id2-id3
document::BucketId id2(18, 0x1ffff);
@@ -619,8 +681,8 @@ TEST(LockableMapTest, find_all_inconsistently_split_6) {
EXPECT_EQ(A(3,4,5), *results[id3.stripUnused()]); // sub bucket
}
-TEST(LockableMapTest, find_all_inconsistent_below_16_bits) {
- Map map;
+TYPED_TEST(LockableMapTest, find_all_inconsistent_below_16_bits) {
+ TypeParam map;
document::BucketId id1(1, 0x1); // contains id2-id3
document::BucketId id2(3, 0x1);
@@ -641,24 +703,64 @@ TEST(LockableMapTest, find_all_inconsistent_below_16_bits) {
EXPECT_EQ(A(3,4,5), *results[id3.stripUnused()]); // sub bucket
}
-TEST(LockableMapTest, is_consistent) {
- Map map;
+TYPED_TEST(LockableMapTest, is_consistent) {
+ TypeParam map;
document::BucketId id1(16, 0x00001); // contains id2-id3
document::BucketId id2(17, 0x00001);
bool preExisted;
map.insert(id1.stripUnused().toKey(), A(1,2,3), "foo", preExisted);
{
- Map::WrappedEntry entry(
- map.get(id1.stripUnused().toKey(), "foo", true));
+ auto entry = map.get(id1.stripUnused().toKey(), "foo", true);
EXPECT_TRUE(map.isConsistent(entry));
}
map.insert(id2.stripUnused().toKey(), A(1,2,3), "foo", preExisted);
{
- Map::WrappedEntry entry(
- map.get(id1.stripUnused().toKey(), "foo", true));
+ auto entry = map.get(id1.stripUnused().toKey(), "foo", true);
EXPECT_FALSE(map.isConsistent(entry));
}
}
+TYPED_TEST(LockableMapTest, get_without_auto_create_does_implicitly_not_lock_bucket) {
+ TypeParam map;
+ BucketId id(16, 0x00001);
+
+ auto entry = map.get(id.toKey(), "foo", false);
+ EXPECT_FALSE(entry.exist());
+ EXPECT_FALSE(entry.preExisted());
+ EXPECT_FALSE(entry.locked());
+}
+
+TYPED_TEST(LockableMapTest, get_with_auto_create_returns_default_constructed_entry_if_missing) {
+ TypeParam map;
+ BucketId id(16, 0x00001);
+
+ auto entry = map.get(id.toKey(), "foo", true);
+ EXPECT_TRUE(entry.exist());
+ EXPECT_FALSE(entry.preExisted());
+ EXPECT_TRUE(entry.locked());
+ EXPECT_EQ(*entry, A());
+ *entry = A(1, 2, 3);
+ entry.write(); // Implicit unlock (!)
+
+ // Should now exist
+ entry = map.get(id.toKey(), "foo", true);
+ EXPECT_TRUE(entry.exist());
+ EXPECT_TRUE(entry.preExisted());
+ EXPECT_TRUE(entry.locked());
+ EXPECT_EQ(*entry, A(1, 2, 3));
+}
+
+TYPED_TEST(LockableMapTest, entry_changes_not_visible_if_write_not_invoked_on_guard) {
+ TypeParam map;
+ BucketId id(16, 0x00001);
+ auto entry = map.get(id.toKey(), "foo", true);
+ *entry = A(1, 2, 3);
+ // No write() call on guard
+ entry.unlock();
+
+ entry = map.get(id.toKey(), "foo", true);
+ EXPECT_EQ(*entry, A());
+}
+
} // storage