memgraph/tests/unit/database_key_index.cpp
Dominik Gleich 141d9b3bb8 Rework of index api. Remove implicit default value of current_state in graph_db_accessor.
Reviewers: buda, florijan

Reviewed By: buda, florijan

Subscribers: mislav.bradac, pullbot

Differential Revision: https://phabricator.memgraph.io/D392
2017-06-07 10:14:55 +02:00

208 lines
6.4 KiB
C++

#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "data_structures/ptr_int.hpp"
#include "database/graph_db_accessor.hpp"
#include "database/graph_db_datatypes.hpp"
#include "dbms/dbms.hpp"
#include "storage/vertex.hpp"
using testing::UnorderedElementsAreArray;
// Test index does it insert everything uniquely
TEST(LabelsIndex, UniqueInsert) {
KeyIndex<GraphDbTypes::Label, Vertex> index;
Dbms dbms;
auto dba = dbms.active();
tx::Engine engine;
auto t1 = engine.begin();
mvcc::VersionList<Vertex> vlist(*t1);
t1->commit();
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));
t2->commit();
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) {
Dbms dbms;
KeyIndex<GraphDbTypes::Label, Vertex> index;
auto dba = dbms.active();
tx::Engine engine;
auto t1 = engine.begin();
mvcc::VersionList<Vertex> vlist1(*t1);
mvcc::VersionList<Vertex> vlist2(*t1);
t1->engine.advance(
t1->id); // advance command so we can see our inserted version
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);
t1->commit();
auto t2 = engine.begin();
auto r2v1 = vlist1.update(*t2);
auto r2v2 = vlist2.update(*t2);
index.Update(label1, &vlist1, r2v1);
index.Update(label1, &vlist2, r2v2);
t2->commit();
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) {
KeyIndex<GraphDbTypes::Label, Vertex> index;
Dbms dbms;
auto access = dbms.active();
tx::Engine engine;
auto t1 = engine.begin();
mvcc::VersionList<Vertex> vlist1(*t1);
mvcc::VersionList<Vertex> vlist2(*t1);
t1->engine.advance(
t1->id); // advance command so we can see our inserted version
auto r1v1 = vlist1.find(*t1);
auto r1v2 = vlist2.find(*t1);
EXPECT_NE(vlist1.find(*t1), nullptr);
auto label1 = access->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);
t1->commit();
auto t2 = engine.begin();
auto r2v1 = vlist1.update(*t2);
auto r2v2 = vlist2.update(*t2);
index.Update(label1, &vlist1, r2v1);
index.Update(label1, &vlist2, r2v2);
int last_id = t2->id;
t2->commit();
EXPECT_EQ(index.Count(label1), 4);
index.Refresh(last_id, engine);
EXPECT_EQ(index.Count(label1), 4);
index.Refresh(last_id + 1, engine);
EXPECT_EQ(index.Count(label1), 2);
}
// Transaction hasn't ended and so the vertex is not visible.
TEST(LabelsIndexDb, AddGetZeroLabels) {
Dbms dbms;
auto dba = dbms.active();
auto vertex = dba->insert_vertex();
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) {
Dbms dbms;
{
auto dba = dbms.active();
auto vertex1 = dba->insert_vertex();
vertex1.add_label(dba->label("test"));
auto vertex2 = dba->insert_vertex();
vertex2.add_label(dba->label("test2"));
auto vertex3 = dba->insert_vertex();
vertex3.add_label(dba->label("test"));
dba->commit();
} // Finish transaction.
{
auto dba = dbms.active();
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->remove_vertex(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 = dbms.active();
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();
}