026c796e06
Reviewers: msantl Reviewed By: msantl Subscribers: pullbot Differential Revision: https://phabricator.memgraph.io/D1944
211 lines
6.4 KiB
C++
211 lines
6.4 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, 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, 0);
|
|
mvcc::VersionList<Vertex> vlist2(*t1, 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, 0);
|
|
mvcc::VersionList<Vertex> vlist2(*t1, 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();
|
|
}
|