#include #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/indexes/label_property_index.hpp" #include "transactions/single_node/engine.hpp" #include "mvcc_gc_common.hpp" using namespace database; class LabelPropertyIndexComplexTest : public ::testing::Test { protected: virtual void SetUp() { auto accessor = db_.Access(); label = accessor.Label("label"); property = accessor.Property("property"); label2 = accessor.Label("label2"); property2 = accessor.Property("property2"); key = new LabelPropertyIndex::Key(label, property); EXPECT_EQ(index.CreateIndex(*key), true); t = engine.Begin(); vlist = new mvcc::VersionList(*t, 0); engine.Advance(t->id_); vertex = vlist->find(*t); ASSERT_NE(vertex, nullptr); vertex->labels_.push_back(label); vertex->properties_.set(property, PropertyValue(0)); EXPECT_EQ(index.Count(*key), 0); } virtual void TearDown() { delete key; delete vlist; } public: GraphDb db_; LabelPropertyIndex index; LabelPropertyIndex::Key *key; tx::Engine engine; tx::Transaction *t{nullptr}; mvcc::VersionList *vlist; Vertex *vertex; storage::Label label; storage::Property property; storage::Label label2; storage::Property property2; }; TEST(LabelPropertyIndex, CreateIndex) { GraphDb db; auto accessor = db.Access(); LabelPropertyIndex::Key key(accessor.Label("test"), accessor.Property("test2")); LabelPropertyIndex index; EXPECT_EQ(index.CreateIndex(key), true); EXPECT_EQ(index.CreateIndex(key), false); } TEST(LabelPropertyIndex, DeleteIndex) { GraphDb db; auto accessor = db.Access(); LabelPropertyIndex::Key key(accessor.Label("test"), accessor.Property("test2")); LabelPropertyIndex index; EXPECT_EQ(index.CreateIndex(key), true); EXPECT_EQ(index.CreateIndex(key), false); index.DeleteIndex(key); EXPECT_EQ(index.CreateIndex(key), true); } TEST(LabelPropertyIndex, IndexExistance) { GraphDb db; auto accessor = db.Access(); LabelPropertyIndex::Key key(accessor.Label("test"), accessor.Property("test2")); LabelPropertyIndex index; EXPECT_EQ(index.CreateIndex(key), true); // Index doesn't exist - and can't be used untill it's been notified as built. EXPECT_EQ(index.IndexExists(key), true); } TEST(LabelPropertyIndex, Count) { GraphDb db; auto accessor = db.Access(); auto label = accessor.Label("label"); auto property = accessor.Property("property"); LabelPropertyIndex::Key key(label, property); LabelPropertyIndex index; EXPECT_EQ(index.CreateIndex(key), true); EXPECT_EQ(index.Count(key), 0); } // Add on label+property to index. TEST_F(LabelPropertyIndexComplexTest, UpdateOnLabelPropertyTrue) { index.UpdateOnLabelProperty(vlist, vertex); EXPECT_EQ(index.Count(*key), 1); } // Try adding on label+property but fail because labels are clear. TEST_F(LabelPropertyIndexComplexTest, UpdateOnLabelPropertyFalse) { vertex->labels_.clear(); index.UpdateOnLabelProperty(vlist, vertex); EXPECT_EQ(index.Count(*key), 0); } // Add on label to index. TEST_F(LabelPropertyIndexComplexTest, UpdateOnLabelTrue) { index.UpdateOnLabel(label, vlist, vertex); EXPECT_EQ(index.Count(*key), 1); } // Try adding on label but fail because label is wrong. TEST_F(LabelPropertyIndexComplexTest, UpdateOnLabelFalse) { index.UpdateOnLabel(label2, vlist, vertex); EXPECT_EQ(index.Count(*key), 0); } // Add on property to index. TEST_F(LabelPropertyIndexComplexTest, UpdateOnPropertyTrue) { index.UpdateOnProperty(property, vlist, vertex); EXPECT_EQ(index.Count(*key), 1); } // Try adding on property but fail because property is wrong. TEST_F(LabelPropertyIndexComplexTest, UpdateOnPropertyFalse) { index.UpdateOnProperty(property2, vlist, vertex); EXPECT_EQ(index.Count(*key), 0); } // Test index does it insert everything uniquely TEST_F(LabelPropertyIndexComplexTest, UniqueInsert) { index.UpdateOnLabelProperty(vlist, vertex); index.UpdateOnLabelProperty(vlist, vertex); EXPECT_EQ(index.Count(*key), 1); } // Check if index filters duplicates. TEST_F(LabelPropertyIndexComplexTest, UniqueFilter) { index.UpdateOnLabelProperty(vlist, vertex); engine.Commit(*t); auto t2 = engine.Begin(); auto vertex2 = vlist->update(*t2); engine.Commit(*t2); index.UpdateOnLabelProperty(vlist, vertex2); EXPECT_EQ(index.Count(*key), 2); auto t3 = engine.Begin(); auto iter = index.GetVlists(*key, *t3, false); EXPECT_EQ(std::distance(iter.begin(), iter.end()), 1); engine.Commit(*t3); } // Remove label and check if index vertex is not returned now. TEST_F(LabelPropertyIndexComplexTest, RemoveLabel) { index.UpdateOnLabelProperty(vlist, vertex); auto iter1 = index.GetVlists(*key, *t, false); EXPECT_EQ(std::distance(iter1.begin(), iter1.end()), 1); vertex->labels_.clear(); auto iter2 = index.GetVlists(*key, *t, false); EXPECT_EQ(std::distance(iter2.begin(), iter2.end()), 0); } // Remove property and check if vertex is not returned now. TEST_F(LabelPropertyIndexComplexTest, RemoveProperty) { index.UpdateOnLabelProperty(vlist, vertex); auto iter1 = index.GetVlists(*key, *t, false); EXPECT_EQ(std::distance(iter1.begin(), iter1.end()), 1); vertex->properties_.clear(); auto iter2 = index.GetVlists(*key, *t, false); EXPECT_EQ(std::distance(iter2.begin(), iter2.end()), 0); } // Refresh with a vertex that looses its labels and properties. TEST_F(LabelPropertyIndexComplexTest, Refresh) { index.UpdateOnLabelProperty(vlist, vertex); engine.Commit(*t); EXPECT_EQ(index.Count(*key), 1); vertex->labels_.clear(); vertex->properties_.clear(); index.Refresh(GcSnapshot(engine, nullptr), engine); auto iter = index.GetVlists(*key, *t, false); EXPECT_EQ(std::distance(iter.begin(), iter.end()), 0); } int main(int argc, char **argv) { ::testing::InitGoogleTest(&argc, argv); return RUN_ALL_TESTS(); }