#include #include #include #include "database/single_node/graph_db.hpp" #include "database/single_node/graph_db_accessor.hpp" #include "storage/single_node/constraints/unique_label_properties_constraint.hpp" class UniqueLabelPropertiesTest : public ::testing::Test { public: void SetUp() override { auto dba = db_.AccessBlocking(); label_ = dba.Label("label"); property1_ = dba.Property("property1"); property2_ = dba.Property("property2"); property3_ = dba.Property("property3"); constraint_.AddConstraint(label_, {property1_, property2_, property3_}, dba.transaction()); dba.Commit(); } database::GraphDb db_; storage::Label label_; storage::Property property1_; storage::Property property2_; storage::Property property3_; PropertyValue value1_{"value1"}; PropertyValue value2_{"value2"}; PropertyValue value3_{"value3"}; storage::constraints::UniqueLabelPropertiesConstraint constraint_; }; TEST_F(UniqueLabelPropertiesTest, BuildDrop) { { auto dba = db_.Access(); EXPECT_TRUE( constraint_.Exists(label_, {property2_, property1_, property3_})); EXPECT_TRUE( constraint_.Exists(label_, {property1_, property2_, property3_})); EXPECT_FALSE( constraint_.Exists(label_, {property1_, property2_})); dba.Commit(); } { auto dba = db_.AccessBlocking(); constraint_.RemoveConstraint(label_, {property2_, property1_, property3_}); dba.Commit(); } { auto dba = db_.Access(); EXPECT_FALSE( constraint_.Exists(label_, {property2_, property1_, property3_})); EXPECT_FALSE( constraint_.Exists(label_, {property1_, property2_, property3_})); dba.Commit(); } } TEST_F(UniqueLabelPropertiesTest, BuildWithViolation) { auto dba1 = db_.Access(); auto v1 = dba1.InsertVertex(); v1.add_label(label_); v1.PropsSet(property1_, value1_); v1.PropsSet(property2_, value2_); v1.PropsSet(property3_, value3_); auto v2 = dba1.InsertVertex(); v2.add_label(label_); v2.PropsSet(property1_, value1_); v2.PropsSet(property3_, value3_); auto v3 = dba1.InsertVertex(); v3.add_label(label_); v3.PropsSet(property3_, value3_); v3.PropsSet(property1_, value1_); v3.PropsSet(property2_, value2_); dba1.Commit(); auto dba2 = db_.Access(); auto v4 = dba2.FindVertex(v1.gid(), false); auto v5 = dba2.FindVertex(v2.gid(), false); auto v6 = dba2.FindVertex(v3.gid(), false); constraint_.UpdateOnAddLabel(label_, v4, dba2.transaction()); constraint_.UpdateOnAddLabel(label_, v5, dba2.transaction()); EXPECT_THROW(constraint_.UpdateOnAddLabel(label_, v6, dba2.transaction()), database::IndexConstraintViolationException); } TEST_F(UniqueLabelPropertiesTest, InsertInsert) { { auto dba = db_.Access(); auto v = dba.InsertVertex(); v.add_label(label_); constraint_.UpdateOnAddLabel(label_, v, dba.transaction()); v.PropsSet(property2_, value2_); constraint_.UpdateOnAddProperty(property2_, value2_, v, dba.transaction()); v.PropsSet(property1_, value1_); constraint_.UpdateOnAddProperty(property1_, value1_, v, dba.transaction()); v.PropsSet(property3_, value3_); constraint_.UpdateOnAddProperty(property3_, value3_, v, dba.transaction()); dba.Commit(); } { auto dba = db_.Access(); auto v = dba.InsertVertex(); v.add_label(label_); constraint_.UpdateOnAddLabel(label_, v, dba.transaction()); v.PropsSet(property3_, value3_); constraint_.UpdateOnAddProperty(property3_, value3_, v, dba.transaction()); v.PropsSet(property2_, value2_); constraint_.UpdateOnAddProperty(property2_, value2_, v, dba.transaction()); v.PropsSet(property1_, value1_); EXPECT_THROW(constraint_.UpdateOnAddProperty(property1_, value1_, v, dba.transaction()), database::IndexConstraintViolationException); dba.Commit(); } } TEST_F(UniqueLabelPropertiesTest, InsertInsertDiffValues) { { auto dba = db_.Access(); auto v = dba.InsertVertex(); v.add_label(label_); constraint_.UpdateOnAddLabel(label_, v, dba.transaction()); v.PropsSet(property2_, value2_); constraint_.UpdateOnAddProperty(property2_, value2_, v, dba.transaction()); v.PropsSet(property1_, value1_); constraint_.UpdateOnAddProperty(property1_, value1_, v, dba.transaction()); v.PropsSet(property3_, value3_); constraint_.UpdateOnAddProperty(property3_, value3_, v, dba.transaction()); dba.Commit(); } { auto dba = db_.Access(); auto v = dba.InsertVertex(); PropertyValue other3("Some other value 3"); v.PropsSet(property3_, other3); constraint_.UpdateOnAddProperty(property3_, other3, v, dba.transaction()); v.add_label(label_); constraint_.UpdateOnAddLabel(label_, v, dba.transaction()); PropertyValue other2("Some other value 2"); v.PropsSet(property2_, other2); constraint_.UpdateOnAddProperty(property2_, other2, v, dba.transaction()); PropertyValue other1("Some other value 1"); v.PropsSet(property1_, other1); constraint_.UpdateOnAddProperty(property1_, other1, v, dba.transaction()); dba.Commit(); } } TEST_F(UniqueLabelPropertiesTest, InsertAbortInsert) { { auto dba = db_.Access(); auto v = dba.InsertVertex(); v.PropsSet(property1_, value1_); constraint_.UpdateOnAddProperty(property1_, value1_, v, dba.transaction()); v.add_label(label_); constraint_.UpdateOnAddLabel(label_, v, dba.transaction()); v.PropsSet(property2_, value2_); constraint_.UpdateOnAddProperty(property2_, value2_, v, dba.transaction()); v.PropsSet(property3_, value3_); constraint_.UpdateOnAddProperty(property3_, value3_, v, dba.transaction()); dba.Abort(); } { auto dba = db_.Access(); auto v = dba.InsertVertex(); v.PropsSet(property2_, value2_); constraint_.UpdateOnAddProperty(property2_, value2_, v, dba.transaction()); v.PropsSet(property1_, value1_); constraint_.UpdateOnAddProperty(property1_, value1_, v, dba.transaction()); v.PropsSet(property3_, value3_); constraint_.UpdateOnAddProperty(property3_, value3_, v, dba.transaction()); v.add_label(label_); constraint_.UpdateOnAddLabel(label_, v, dba.transaction()); dba.Commit(); } } TEST_F(UniqueLabelPropertiesTest, InsertRemoveAbortInsert) { gid::Gid gid = 0; { auto dba = db_.Access(); auto v = dba.InsertVertex(); v.PropsSet(property2_, value2_); constraint_.UpdateOnAddProperty(property2_, value2_, v, dba.transaction()); v.PropsSet(property1_, value1_); constraint_.UpdateOnAddProperty(property1_, value1_, v, dba.transaction()); v.PropsSet(property3_, value3_); constraint_.UpdateOnAddProperty(property3_, value3_, v, dba.transaction()); v.add_label(label_); constraint_.UpdateOnAddLabel(label_, v, dba.transaction()); dba.Commit(); } { auto dba = db_.Access(); auto v = dba.FindVertex(gid, false); v.PropsErase(property2_); constraint_.UpdateOnRemoveProperty(property2_, value2_, v, dba.transaction()); dba.Abort(); } { auto dba = db_.Access(); auto v = dba.InsertVertex(); v.PropsSet(property1_, value1_); constraint_.UpdateOnAddProperty(property1_, value1_, v, dba.transaction()); v.add_label(label_); constraint_.UpdateOnAddLabel(label_, v, dba.transaction()); v.PropsSet(property2_, value2_); constraint_.UpdateOnAddProperty(property2_, value2_, v, dba.transaction()); v.PropsSet(property3_, value3_); EXPECT_THROW(constraint_.UpdateOnAddProperty(property3_, value3_, v, dba.transaction()), database::IndexConstraintViolationException); } } TEST_F(UniqueLabelPropertiesTest, InsertInsertSameTransaction) { { auto dba = db_.Access(); auto v1 = dba.InsertVertex(); auto v2 = dba.InsertVertex(); v2.add_label(label_); constraint_.UpdateOnAddLabel(label_, v2, dba.transaction()); v1.add_label(label_); constraint_.UpdateOnAddLabel(label_, v1, dba.transaction()); v1.PropsSet(property1_, value1_); constraint_.UpdateOnAddProperty(property1_, value1_, v1, dba.transaction()); v1.PropsSet(property2_, value2_); constraint_.UpdateOnAddProperty(property2_, value2_, v1, dba.transaction()); v2.PropsSet(property2_, value2_); constraint_.UpdateOnAddProperty(property2_, value2_, v2, dba.transaction()); v2.PropsSet(property3_, value3_); constraint_.UpdateOnAddProperty(property3_, value3_, v2, dba.transaction()); v2.PropsSet(property1_, value1_); constraint_.UpdateOnAddProperty(property1_, value1_, v2, dba.transaction()); v1.PropsSet(property3_, value3_); EXPECT_THROW(constraint_.UpdateOnAddProperty(property3_, value3_, v1, dba.transaction()), database::IndexConstraintViolationException); } } TEST_F(UniqueLabelPropertiesTest, InsertInsertReversed) { auto dba1 = db_.Access(); auto dba2 = db_.Access(); auto v1 = dba1.InsertVertex(); auto v2 = dba2.InsertVertex(); v2.add_label(label_); constraint_.UpdateOnAddLabel(label_, v2, dba2.transaction()); v1.add_label(label_); constraint_.UpdateOnAddLabel(label_, v1, dba1.transaction()); v1.PropsSet(property1_, value1_); constraint_.UpdateOnAddProperty(property1_, value1_, v1, dba1.transaction()); v1.PropsSet(property2_, value2_); constraint_.UpdateOnAddProperty(property2_, value2_, v1, dba1.transaction()); v2.PropsSet(property2_, value2_); constraint_.UpdateOnAddProperty(property2_, value2_, v2, dba2.transaction()); v2.PropsSet(property3_, value3_); constraint_.UpdateOnAddProperty(property3_, value3_, v2, dba2.transaction()); v2.PropsSet(property1_, value1_); constraint_.UpdateOnAddProperty(property1_, value1_, v2, dba2.transaction()); v1.PropsSet(property3_, value3_); EXPECT_THROW(constraint_.UpdateOnAddProperty(property3_, value3_, v1, dba1.transaction()), mvcc::SerializationError); } TEST_F(UniqueLabelPropertiesTest, InsertRemoveInsert) { gid::Gid gid = 0; { auto dba = db_.Access(); auto v = dba.InsertVertex(); v.PropsSet(property2_, value2_); constraint_.UpdateOnAddProperty(property2_, value2_, v, dba.transaction()); v.PropsSet(property1_, value1_); constraint_.UpdateOnAddProperty(property1_, value1_, v, dba.transaction()); v.PropsSet(property3_, value3_); constraint_.UpdateOnAddProperty(property3_, value3_, v, dba.transaction()); v.add_label(label_); constraint_.UpdateOnAddLabel(label_, v, dba.transaction()); dba.Commit(); } { auto dba = db_.Access(); auto v = dba.FindVertex(gid, false); v.PropsErase(property2_); constraint_.UpdateOnRemoveProperty(property2_, value2_, v, dba.transaction()); dba.Commit(); } { auto dba = db_.Access(); auto v = dba.InsertVertex(); v.PropsSet(property1_, value1_); constraint_.UpdateOnAddProperty(property1_, value1_, v, dba.transaction()); v.add_label(label_); constraint_.UpdateOnAddLabel(label_, v, dba.transaction()); v.PropsSet(property2_, value2_); constraint_.UpdateOnAddProperty(property2_, value2_, v, dba.transaction()); v.PropsSet(property3_, value3_); constraint_.UpdateOnAddProperty(property3_, value3_, v, dba.transaction()); } } TEST_F(UniqueLabelPropertiesTest, InsertRemoveInsertSameTransaction) { auto dba = db_.Access(); auto v = dba.InsertVertex(); v.PropsSet(property2_, value2_); constraint_.UpdateOnAddProperty(property2_, value2_, v, dba.transaction()); v.PropsSet(property1_, value1_); constraint_.UpdateOnAddProperty(property1_, value1_, v, dba.transaction()); v.PropsSet(property3_, value3_); constraint_.UpdateOnAddProperty(property3_, value3_, v, dba.transaction()); v.add_label(label_); constraint_.UpdateOnAddLabel(label_, v, dba.transaction()); v.PropsErase(property2_); constraint_.UpdateOnRemoveProperty(property2_, value2_, v, dba.transaction()); v.PropsSet(property2_, value2_); constraint_.UpdateOnAddProperty(property2_, value2_, v, dba.transaction()); } TEST_F(UniqueLabelPropertiesTest, InsertDropInsert) { { auto dba = db_.Access(); auto v = dba.InsertVertex(); v.PropsSet(property1_, value1_); constraint_.UpdateOnAddProperty(property1_, value1_, v, dba.transaction()); v.add_label(label_); constraint_.UpdateOnAddLabel(label_, v, dba.transaction()); v.PropsSet(property2_, value2_); constraint_.UpdateOnAddProperty(property2_, value2_, v, dba.transaction()); v.PropsSet(property3_, value3_); constraint_.UpdateOnAddProperty(property3_, value3_, v, dba.transaction()); } { auto dba = db_.AccessBlocking(); constraint_.RemoveConstraint(label_, {property2_, property3_, property1_}); dba.Commit(); } { auto dba = db_.Access(); auto v = dba.InsertVertex(); v.PropsSet(property2_, value2_); constraint_.UpdateOnAddProperty(property2_, value2_, v, dba.transaction()); v.PropsSet(property1_, value1_); constraint_.UpdateOnAddProperty(property1_, value1_, v, dba.transaction()); v.add_label(label_); constraint_.UpdateOnAddLabel(label_, v, dba.transaction()); v.PropsSet(property3_, value3_); constraint_.UpdateOnAddProperty(property3_, value3_, v, dba.transaction()); dba.Commit(); } } int main(int argc, char **argv) { ::testing::InitGoogleTest(&argc, argv); google::InitGoogleLogging(argv[0]); return RUN_ALL_TESTS(); }