memgraph/tests/unit/database_key_index.cpp
Teon Banek 7213bec886 Make Gid a full on class wrapper around uint64_t
Summary:
This makes Gid the same as the one in storage/v2. Before they can be
merge into one implementation, we probably want to have a similar
transition for remaining ID types.

Depends on D2346

Reviewers: mferencevic, ipaljak

Reviewed By: mferencevic

Subscribers: pullbot

Differential Revision: https://phabricator.memgraph.io/D2347
2019-09-03 15:14:21 +02:00

211 lines
6.6 KiB
C++

#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "database/single_node/graph_db.hpp"
#include "database/single_node/graph_db_accessor.hpp"
#include "storage/common/types/types.hpp"
#include "storage/single_node/vertex.hpp"
#include "transactions/single_node/engine.hpp"
#include "mvcc_gc_common.hpp"
using testing::UnorderedElementsAreArray;
// Test index does it insert everything uniquely
TEST(LabelsIndex, UniqueInsert) {
database::KeyIndex<storage::Label, Vertex> index;
database::GraphDb db;
auto dba = db.Access();
tx::Engine engine;
auto t1 = engine.Begin();
mvcc::VersionList<Vertex> vlist(*t1, storage::Gid::FromInt(0));
engine.Commit(*t1);
auto t2 = engine.Begin();
vlist.find(*t2)->labels_.push_back(dba.Label("1"));
index.Update(dba.Label("1"), &vlist, vlist.find(*t2));
// Try multiple inserts
index.Update(dba.Label("1"), &vlist, vlist.find(*t2));
vlist.find(*t2)->labels_.push_back(dba.Label("2"));
index.Update(dba.Label("2"), &vlist, vlist.find(*t2));
vlist.find(*t2)->labels_.push_back(dba.Label("3"));
index.Update(dba.Label("3"), &vlist, vlist.find(*t2));
engine.Commit(*t2);
EXPECT_EQ(index.Count(dba.Label("1")), 1);
EXPECT_EQ(index.Count(dba.Label("2")), 1);
EXPECT_EQ(index.Count(dba.Label("3")), 1);
}
// Check if index filters duplicates.
TEST(LabelsIndex, UniqueFilter) {
database::GraphDb db;
database::KeyIndex<storage::Label, Vertex> index;
auto dba = db.Access();
tx::Engine engine;
auto t1 = engine.Begin();
mvcc::VersionList<Vertex> vlist1(*t1, storage::Gid::FromInt(0));
mvcc::VersionList<Vertex> vlist2(*t1, storage::Gid::FromInt(1));
engine.Advance(t1->id_);
auto r1v1 = vlist1.find(*t1);
auto r1v2 = vlist2.find(*t1);
EXPECT_NE(vlist1.find(*t1), nullptr);
auto label1 = dba.Label("1");
vlist1.find(*t1)->labels_.push_back(label1);
vlist2.find(*t1)->labels_.push_back(label1);
index.Update(label1, &vlist1, r1v1);
index.Update(label1, &vlist2, r1v2);
engine.Commit(*t1);
auto t2 = engine.Begin();
auto r2v1 = vlist1.update(*t2);
auto r2v2 = vlist2.update(*t2);
index.Update(label1, &vlist1, r2v1);
index.Update(label1, &vlist2, r2v2);
engine.Commit(*t2);
auto t3 = engine.Begin();
std::vector<mvcc::VersionList<Vertex> *> expected = {&vlist1, &vlist2};
sort(expected.begin(),
expected.end()); // Entries will be sorted by vlist pointers.
int cnt = 0;
for (auto vlist : index.GetVlists(label1, *t3, false)) {
EXPECT_LT(cnt, expected.size());
EXPECT_EQ(vlist, expected[cnt++]);
}
}
// Delete not anymore relevant recods from index.
TEST(LabelsIndex, Refresh) {
database::KeyIndex<storage::Label, Vertex> index;
database::GraphDb db;
auto access = db.Access();
tx::Engine engine;
// add two vertices to database
auto t1 = engine.Begin();
mvcc::VersionList<Vertex> vlist1(*t1, storage::Gid::FromInt(0));
mvcc::VersionList<Vertex> vlist2(*t1, storage::Gid::FromInt(1));
engine.Advance(t1->id_);
auto v1r1 = vlist1.find(*t1);
auto v2r1 = vlist2.find(*t1);
EXPECT_NE(v1r1, nullptr);
EXPECT_NE(v2r1, nullptr);
auto label = access.Label("label");
v1r1->labels_.push_back(label);
v2r1->labels_.push_back(label);
index.Update(label, &vlist1, v1r1);
index.Update(label, &vlist2, v2r1);
engine.Commit(*t1);
auto t2 = engine.Begin();
auto v1r2 = vlist1.update(*t2);
auto v2r2 = vlist2.update(*t2);
index.Update(label, &vlist1, v1r2);
index.Update(label, &vlist2, v2r2);
index.Refresh(GcSnapshot(engine, t2), engine);
EXPECT_EQ(index.Count(label), 4);
engine.Commit(*t2);
EXPECT_EQ(index.Count(label), 4);
index.Refresh(GcSnapshot(engine, nullptr), engine);
EXPECT_EQ(index.Count(label), 2);
}
// Transaction hasn't ended and so the vertex is not visible.
TEST(LabelsIndexDb, AddGetZeroLabels) {
database::GraphDb db;
auto dba = db.Access();
auto vertex = dba.InsertVertex();
vertex.add_label(dba.Label("test"));
auto collection = dba.Vertices(dba.Label("test"), false);
std::vector<VertexAccessor> collection_vector(collection.begin(),
collection.end());
EXPECT_EQ(collection_vector.size(), (size_t)0);
}
// Test label index by adding and removing one vertex, and removing label from
// another, while the third one with an irrelevant label exists.
TEST(LabelsIndexDb, AddGetRemoveLabel) {
database::GraphDb db;
{
auto dba = db.Access();
auto vertex1 = dba.InsertVertex();
vertex1.add_label(dba.Label("test"));
auto vertex2 = dba.InsertVertex();
vertex2.add_label(dba.Label("test2"));
auto vertex3 = dba.InsertVertex();
vertex3.add_label(dba.Label("test"));
dba.Commit();
} // Finish transaction.
{
auto dba = db.Access();
auto filtered = dba.Vertices(dba.Label("test"), false);
std::vector<VertexAccessor> collection(filtered.begin(), filtered.end());
auto vertices = dba.Vertices(false);
std::vector<VertexAccessor> expected_collection;
for (auto vertex : vertices) {
if (vertex.has_label(dba.Label("test"))) {
expected_collection.push_back(vertex);
} else {
EXPECT_TRUE(vertex.has_label(dba.Label("test2")));
}
}
EXPECT_EQ(expected_collection.size(), collection.size());
EXPECT_TRUE(collection[0].has_label(dba.Label("test")));
EXPECT_TRUE(collection[1].has_label(dba.Label("test")));
EXPECT_FALSE(collection[0].has_label(dba.Label("test2")));
EXPECT_FALSE(collection[1].has_label(dba.Label("test2")));
dba.RemoveVertex(collection[0]); // Remove from database and test if
// index won't return it.
// Remove label from the vertex and add new label.
collection[1].remove_label(dba.Label("test"));
collection[1].add_label(dba.Label("test2"));
dba.Commit();
}
{
auto dba = db.Access();
auto filtered = dba.Vertices(dba.Label("test"), false);
std::vector<VertexAccessor> collection(filtered.begin(), filtered.end());
auto vertices = dba.Vertices(false);
std::vector<VertexAccessor> expected_collection;
for (auto vertex : vertices) {
if (vertex.has_label(dba.Label("test"))) {
expected_collection.push_back(vertex);
} else {
EXPECT_TRUE(vertex.has_label(dba.Label("test2")));
}
}
// It should be empty since everything with an old label is either deleted
// or doesn't have that label anymore.
EXPECT_EQ(expected_collection.size(), 0);
EXPECT_EQ(collection.size(), 0);
}
}
// TODO gleich - discuss with Flor the API changes and the tests
int main(int argc, char **argv) {
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}