#include #include #include "storage/v2/storage.hpp" // NOLINTNEXTLINE(hicpp-special-member-functions) TEST(StorageV2, Commit) { storage::Storage store; storage::Gid gid = storage::Gid::FromUint(std::numeric_limits::max()); { auto acc = store.Access(); auto vertex = acc.CreateVertex(); gid = vertex.Gid(); ASSERT_FALSE(acc.FindVertex(gid, storage::View::OLD).has_value()); ASSERT_TRUE(acc.FindVertex(gid, storage::View::NEW).has_value()); acc.Commit(); } { auto acc = store.Access(); ASSERT_TRUE(acc.FindVertex(gid, storage::View::OLD).has_value()); ASSERT_TRUE(acc.FindVertex(gid, storage::View::NEW).has_value()); acc.Abort(); } { auto acc = store.Access(); auto vertex = acc.FindVertex(gid, storage::View::NEW); ASSERT_TRUE(vertex); auto res = acc.DeleteVertex(&*vertex); ASSERT_FALSE(res.IsError()); acc.Commit(); } { auto acc = store.Access(); ASSERT_FALSE(acc.FindVertex(gid, storage::View::OLD).has_value()); ASSERT_FALSE(acc.FindVertex(gid, storage::View::NEW).has_value()); acc.Abort(); } } // NOLINTNEXTLINE(hicpp-special-member-functions) TEST(StorageV2, Abort) { storage::Storage store; storage::Gid gid = storage::Gid::FromUint(std::numeric_limits::max()); { auto acc = store.Access(); auto vertex = acc.CreateVertex(); gid = vertex.Gid(); ASSERT_FALSE(acc.FindVertex(gid, storage::View::OLD).has_value()); ASSERT_TRUE(acc.FindVertex(gid, storage::View::NEW).has_value()); acc.Abort(); } { auto acc = store.Access(); ASSERT_FALSE(acc.FindVertex(gid, storage::View::OLD).has_value()); ASSERT_FALSE(acc.FindVertex(gid, storage::View::NEW).has_value()); acc.Abort(); } } // NOLINTNEXTLINE(hicpp-special-member-functions) TEST(StorageV2, AdvanceCommandCommit) { storage::Storage store; storage::Gid gid1 = storage::Gid::FromUint(std::numeric_limits::max()); storage::Gid gid2 = storage::Gid::FromUint(std::numeric_limits::max()); { auto acc = store.Access(); auto vertex1 = acc.CreateVertex(); gid1 = vertex1.Gid(); ASSERT_FALSE(acc.FindVertex(gid1, storage::View::OLD).has_value()); ASSERT_TRUE(acc.FindVertex(gid1, storage::View::NEW).has_value()); acc.AdvanceCommand(); auto vertex2 = acc.CreateVertex(); gid2 = vertex2.Gid(); ASSERT_FALSE(acc.FindVertex(gid2, storage::View::OLD).has_value()); ASSERT_TRUE(acc.FindVertex(gid2, storage::View::NEW).has_value()); ASSERT_TRUE(acc.FindVertex(gid1, storage::View::OLD).has_value()); ASSERT_TRUE(acc.FindVertex(gid1, storage::View::NEW).has_value()); acc.Commit(); } { auto acc = store.Access(); ASSERT_TRUE(acc.FindVertex(gid1, storage::View::OLD).has_value()); ASSERT_TRUE(acc.FindVertex(gid1, storage::View::NEW).has_value()); ASSERT_TRUE(acc.FindVertex(gid2, storage::View::OLD).has_value()); ASSERT_TRUE(acc.FindVertex(gid2, storage::View::NEW).has_value()); acc.Abort(); } } // NOLINTNEXTLINE(hicpp-special-member-functions) TEST(StorageV2, AdvanceCommandAbort) { storage::Storage store; storage::Gid gid1 = storage::Gid::FromUint(std::numeric_limits::max()); storage::Gid gid2 = storage::Gid::FromUint(std::numeric_limits::max()); { auto acc = store.Access(); auto vertex1 = acc.CreateVertex(); gid1 = vertex1.Gid(); ASSERT_FALSE(acc.FindVertex(gid1, storage::View::OLD).has_value()); ASSERT_TRUE(acc.FindVertex(gid1, storage::View::NEW).has_value()); acc.AdvanceCommand(); auto vertex2 = acc.CreateVertex(); gid2 = vertex2.Gid(); ASSERT_FALSE(acc.FindVertex(gid2, storage::View::OLD).has_value()); ASSERT_TRUE(acc.FindVertex(gid2, storage::View::NEW).has_value()); ASSERT_TRUE(acc.FindVertex(gid1, storage::View::OLD).has_value()); ASSERT_TRUE(acc.FindVertex(gid1, storage::View::NEW).has_value()); acc.Abort(); } { auto acc = store.Access(); ASSERT_FALSE(acc.FindVertex(gid1, storage::View::OLD).has_value()); ASSERT_FALSE(acc.FindVertex(gid1, storage::View::NEW).has_value()); ASSERT_FALSE(acc.FindVertex(gid2, storage::View::OLD).has_value()); ASSERT_FALSE(acc.FindVertex(gid2, storage::View::NEW).has_value()); acc.Abort(); } } // NOLINTNEXTLINE(hicpp-special-member-functions) TEST(StorageV2, SnapshotIsolation) { storage::Storage store; auto acc1 = store.Access(); auto acc2 = store.Access(); auto vertex = acc1.CreateVertex(); auto gid = vertex.Gid(); ASSERT_FALSE(acc2.FindVertex(gid, storage::View::OLD).has_value()); ASSERT_FALSE(acc2.FindVertex(gid, storage::View::NEW).has_value()); acc1.Commit(); ASSERT_FALSE(acc2.FindVertex(gid, storage::View::OLD).has_value()); ASSERT_FALSE(acc2.FindVertex(gid, storage::View::NEW).has_value()); acc2.Abort(); auto acc3 = store.Access(); ASSERT_TRUE(acc3.FindVertex(gid, storage::View::OLD).has_value()); ASSERT_TRUE(acc3.FindVertex(gid, storage::View::NEW).has_value()); acc3.Abort(); } // NOLINTNEXTLINE(hicpp-special-member-functions) TEST(StorageV2, AccessorMove) { storage::Storage store; storage::Gid gid = storage::Gid::FromUint(std::numeric_limits::max()); { auto acc = store.Access(); auto vertex = acc.CreateVertex(); gid = vertex.Gid(); ASSERT_FALSE(acc.FindVertex(gid, storage::View::OLD).has_value()); ASSERT_TRUE(acc.FindVertex(gid, storage::View::NEW).has_value()); storage::Storage::Accessor moved(std::move(acc)); ASSERT_FALSE(moved.FindVertex(gid, storage::View::OLD).has_value()); ASSERT_TRUE(moved.FindVertex(gid, storage::View::NEW).has_value()); moved.Commit(); } { auto acc = store.Access(); ASSERT_TRUE(acc.FindVertex(gid, storage::View::OLD).has_value()); ASSERT_TRUE(acc.FindVertex(gid, storage::View::NEW).has_value()); acc.Abort(); } } // NOLINTNEXTLINE(hicpp-special-member-functions) TEST(StorageV2, VertexDeleteCommit) { storage::Storage store; storage::Gid gid = storage::Gid::FromUint(std::numeric_limits::max()); auto acc1 = store.Access(); // read transaction auto acc2 = store.Access(); // write transaction // Create the vertex in transaction 2 { auto vertex = acc2.CreateVertex(); gid = vertex.Gid(); ASSERT_FALSE(acc2.FindVertex(gid, storage::View::OLD).has_value()); ASSERT_TRUE(acc2.FindVertex(gid, storage::View::NEW).has_value()); acc2.Commit(); } auto acc3 = store.Access(); // read transaction auto acc4 = store.Access(); // write transaction // Check whether the vertex exists in transaction 1 ASSERT_FALSE(acc1.FindVertex(gid, storage::View::OLD).has_value()); ASSERT_FALSE(acc1.FindVertex(gid, storage::View::NEW).has_value()); // Check whether the vertex exists in transaction 3 ASSERT_TRUE(acc3.FindVertex(gid, storage::View::OLD).has_value()); ASSERT_TRUE(acc3.FindVertex(gid, storage::View::NEW).has_value()); // Delete the vertex in transaction 4 { auto vertex = acc4.FindVertex(gid, storage::View::NEW); ASSERT_TRUE(vertex); auto res = acc4.DeleteVertex(&*vertex); ASSERT_TRUE(res.IsReturn()); acc4.Commit(); } auto acc5 = store.Access(); // read transaction // Check whether the vertex exists in transaction 1 ASSERT_FALSE(acc1.FindVertex(gid, storage::View::OLD).has_value()); ASSERT_FALSE(acc1.FindVertex(gid, storage::View::NEW).has_value()); // Check whether the vertex exists in transaction 3 ASSERT_TRUE(acc3.FindVertex(gid, storage::View::OLD).has_value()); ASSERT_TRUE(acc3.FindVertex(gid, storage::View::NEW).has_value()); // Check whether the vertex exists in transaction 5 ASSERT_FALSE(acc5.FindVertex(gid, storage::View::OLD).has_value()); ASSERT_FALSE(acc5.FindVertex(gid, storage::View::NEW).has_value()); } // NOLINTNEXTLINE(hicpp-special-member-functions) TEST(StorageV2, VertexDeleteAbort) { storage::Storage store; storage::Gid gid = storage::Gid::FromUint(std::numeric_limits::max()); auto acc1 = store.Access(); // read transaction auto acc2 = store.Access(); // write transaction // Create the vertex in transaction 2 { auto vertex = acc2.CreateVertex(); gid = vertex.Gid(); ASSERT_FALSE(acc2.FindVertex(gid, storage::View::OLD).has_value()); ASSERT_TRUE(acc2.FindVertex(gid, storage::View::NEW).has_value()); acc2.Commit(); } auto acc3 = store.Access(); // read transaction auto acc4 = store.Access(); // write transaction (aborted) // Check whether the vertex exists in transaction 1 ASSERT_FALSE(acc1.FindVertex(gid, storage::View::OLD).has_value()); ASSERT_FALSE(acc1.FindVertex(gid, storage::View::NEW).has_value()); // Check whether the vertex exists in transaction 3 ASSERT_TRUE(acc3.FindVertex(gid, storage::View::OLD).has_value()); ASSERT_TRUE(acc3.FindVertex(gid, storage::View::NEW).has_value()); // Delete the vertex in transaction 4, but abort the transaction { auto vertex = acc4.FindVertex(gid, storage::View::NEW); ASSERT_TRUE(vertex); auto res = acc4.DeleteVertex(&*vertex); ASSERT_TRUE(res.IsReturn()); acc4.Abort(); } auto acc5 = store.Access(); // read transaction auto acc6 = store.Access(); // write transaction // Check whether the vertex exists in transaction 1 ASSERT_FALSE(acc1.FindVertex(gid, storage::View::OLD).has_value()); ASSERT_FALSE(acc1.FindVertex(gid, storage::View::NEW).has_value()); // Check whether the vertex exists in transaction 3 ASSERT_TRUE(acc3.FindVertex(gid, storage::View::OLD).has_value()); ASSERT_TRUE(acc3.FindVertex(gid, storage::View::NEW).has_value()); // Check whether the vertex exists in transaction 5 ASSERT_TRUE(acc5.FindVertex(gid, storage::View::OLD).has_value()); ASSERT_TRUE(acc5.FindVertex(gid, storage::View::NEW).has_value()); // Delete the vertex in transaction 6 { auto vertex = acc6.FindVertex(gid, storage::View::NEW); ASSERT_TRUE(vertex); auto res = acc6.DeleteVertex(&*vertex); ASSERT_TRUE(res.IsReturn()); acc6.Commit(); } auto acc7 = store.Access(); // read transaction // Check whether the vertex exists in transaction 1 ASSERT_FALSE(acc1.FindVertex(gid, storage::View::OLD).has_value()); ASSERT_FALSE(acc1.FindVertex(gid, storage::View::NEW).has_value()); // Check whether the vertex exists in transaction 3 ASSERT_TRUE(acc3.FindVertex(gid, storage::View::OLD).has_value()); ASSERT_TRUE(acc3.FindVertex(gid, storage::View::NEW).has_value()); // Check whether the vertex exists in transaction 5 ASSERT_TRUE(acc5.FindVertex(gid, storage::View::OLD).has_value()); ASSERT_TRUE(acc5.FindVertex(gid, storage::View::NEW).has_value()); // Check whether the vertex exists in transaction 7 ASSERT_FALSE(acc7.FindVertex(gid, storage::View::OLD).has_value()); ASSERT_FALSE(acc7.FindVertex(gid, storage::View::NEW).has_value()); // Commit all accessors acc1.Commit(); acc3.Commit(); acc5.Commit(); acc7.Commit(); } // NOLINTNEXTLINE(hicpp-special-member-functions) TEST(StorageV2, VertexDeleteSerializationError) { storage::Storage store; storage::Gid gid = storage::Gid::FromUint(std::numeric_limits::max()); // Create vertex { auto acc = store.Access(); auto vertex = acc.CreateVertex(); gid = vertex.Gid(); acc.Commit(); } auto acc1 = store.Access(); auto acc2 = store.Access(); // Delete vertex in accessor 1 { auto vertex = acc1.FindVertex(gid, storage::View::OLD); ASSERT_TRUE(vertex); { auto res = acc1.DeleteVertex(&*vertex); ASSERT_TRUE(res.IsReturn()); ASSERT_TRUE(res.GetReturn()); } { auto res = acc1.DeleteVertex(&*vertex); ASSERT_TRUE(res.IsReturn()); ASSERT_FALSE(res.GetReturn()); } } // Delete vertex in accessor 2 { auto vertex = acc2.FindVertex(gid, storage::View::OLD); ASSERT_TRUE(vertex); auto res = acc2.DeleteVertex(&*vertex); ASSERT_TRUE(res.IsError()); ASSERT_EQ(res.GetError(), storage::Error::SERIALIZATION_ERROR); } // Finalize both accessors acc1.Commit(); acc2.Abort(); // Check whether the vertex exists { auto acc = store.Access(); auto vertex = acc.FindVertex(gid, storage::View::OLD); ASSERT_FALSE(vertex); acc.Commit(); } } // NOLINTNEXTLINE(hicpp-special-member-functions) TEST(StorageV2, VertexDeleteSpecialCases) { storage::Storage store; storage::Gid gid1 = storage::Gid::FromUint(std::numeric_limits::max()); storage::Gid gid2 = storage::Gid::FromUint(std::numeric_limits::max()); // Create vertex and delete it in the same transaction, but abort the // transaction { auto acc = store.Access(); auto vertex = acc.CreateVertex(); gid1 = vertex.Gid(); ASSERT_FALSE(acc.FindVertex(gid1, storage::View::OLD).has_value()); ASSERT_TRUE(acc.FindVertex(gid1, storage::View::NEW).has_value()); auto res = acc.DeleteVertex(&vertex); ASSERT_TRUE(res.IsReturn()); ASSERT_TRUE(res.GetReturn()); acc.Abort(); } // Create vertex and delete it in the same transaction { auto acc = store.Access(); auto vertex = acc.CreateVertex(); gid2 = vertex.Gid(); ASSERT_FALSE(acc.FindVertex(gid2, storage::View::OLD).has_value()); ASSERT_TRUE(acc.FindVertex(gid2, storage::View::NEW).has_value()); auto res = acc.DeleteVertex(&vertex); ASSERT_TRUE(res.IsReturn()); ASSERT_TRUE(res.GetReturn()); acc.Commit(); } // Check whether the vertices exist { auto acc = store.Access(); ASSERT_FALSE(acc.FindVertex(gid1, storage::View::OLD).has_value()); ASSERT_FALSE(acc.FindVertex(gid1, storage::View::NEW).has_value()); ASSERT_FALSE(acc.FindVertex(gid2, storage::View::OLD).has_value()); ASSERT_FALSE(acc.FindVertex(gid2, storage::View::NEW).has_value()); acc.Abort(); } } // NOLINTNEXTLINE(hicpp-special-member-functions) TEST(StorageV2, VertexDeleteLabel) { storage::Storage store; storage::Gid gid = storage::Gid::FromUint(std::numeric_limits::max()); // Create the vertex { auto acc = store.Access(); auto vertex = acc.CreateVertex(); gid = vertex.Gid(); ASSERT_FALSE(acc.FindVertex(gid, storage::View::OLD).has_value()); ASSERT_TRUE(acc.FindVertex(gid, storage::View::NEW).has_value()); acc.Commit(); } // Add label, delete the vertex and check the label API (same command) { auto acc = store.Access(); auto vertex = acc.FindVertex(gid, storage::View::NEW); ASSERT_TRUE(vertex); // Check whether label 5 exists ASSERT_FALSE(vertex->HasLabel(5, storage::View::OLD).GetReturn()); ASSERT_FALSE(vertex->HasLabel(5, storage::View::NEW).GetReturn()); ASSERT_EQ(vertex->Labels(storage::View::OLD).GetReturn().size(), 0); ASSERT_EQ(vertex->Labels(storage::View::NEW).GetReturn().size(), 0); // Add label 5 ASSERT_TRUE(vertex->AddLabel(5).GetReturn()); // Check whether label 5 exists ASSERT_FALSE(vertex->HasLabel(5, storage::View::OLD).GetReturn()); ASSERT_TRUE(vertex->HasLabel(5, storage::View::NEW).GetReturn()); ASSERT_EQ(vertex->Labels(storage::View::OLD).GetReturn().size(), 0); { auto labels = vertex->Labels(storage::View::NEW).GetReturn(); ASSERT_EQ(labels.size(), 1); ASSERT_EQ(labels[0], 5); } // Delete the vertex ASSERT_TRUE(acc.DeleteVertex(&*vertex).GetReturn()); // Check whether label 5 exists ASSERT_FALSE(vertex->HasLabel(5, storage::View::OLD).GetReturn()); ASSERT_EQ(vertex->HasLabel(5, storage::View::NEW).GetError(), storage::Error::DELETED_OBJECT); ASSERT_EQ(vertex->Labels(storage::View::OLD).GetReturn().size(), 0); ASSERT_EQ(vertex->Labels(storage::View::NEW).GetError(), storage::Error::DELETED_OBJECT); // Try to add the label { auto ret = vertex->AddLabel(5); ASSERT_TRUE(ret.IsError()); ASSERT_EQ(ret.GetError(), storage::Error::DELETED_OBJECT); } // Try to remove the label { auto ret = vertex->RemoveLabel(5); ASSERT_TRUE(ret.IsError()); ASSERT_EQ(ret.GetError(), storage::Error::DELETED_OBJECT); } acc.Abort(); } // Add label, delete the vertex and check the label API (different command) { auto acc = store.Access(); auto vertex = acc.FindVertex(gid, storage::View::NEW); ASSERT_TRUE(vertex); // Check whether label 5 exists ASSERT_FALSE(vertex->HasLabel(5, storage::View::OLD).GetReturn()); ASSERT_FALSE(vertex->HasLabel(5, storage::View::NEW).GetReturn()); ASSERT_EQ(vertex->Labels(storage::View::OLD).GetReturn().size(), 0); ASSERT_EQ(vertex->Labels(storage::View::NEW).GetReturn().size(), 0); // Add label 5 ASSERT_TRUE(vertex->AddLabel(5).GetReturn()); // Check whether label 5 exists ASSERT_FALSE(vertex->HasLabel(5, storage::View::OLD).GetReturn()); ASSERT_TRUE(vertex->HasLabel(5, storage::View::NEW).GetReturn()); ASSERT_EQ(vertex->Labels(storage::View::OLD).GetReturn().size(), 0); { auto labels = vertex->Labels(storage::View::NEW).GetReturn(); ASSERT_EQ(labels.size(), 1); ASSERT_EQ(labels[0], 5); } // Advance command acc.AdvanceCommand(); // Check whether label 5 exists ASSERT_TRUE(vertex->HasLabel(5, storage::View::OLD).GetReturn()); ASSERT_TRUE(vertex->HasLabel(5, storage::View::NEW).GetReturn()); { auto labels = vertex->Labels(storage::View::OLD).GetReturn(); ASSERT_EQ(labels.size(), 1); ASSERT_EQ(labels[0], 5); } { auto labels = vertex->Labels(storage::View::NEW).GetReturn(); ASSERT_EQ(labels.size(), 1); ASSERT_EQ(labels[0], 5); } // Delete the vertex ASSERT_TRUE(acc.DeleteVertex(&*vertex).GetReturn()); // Check whether label 5 exists ASSERT_TRUE(vertex->HasLabel(5, storage::View::OLD).GetReturn()); ASSERT_EQ(vertex->HasLabel(5, storage::View::NEW).GetError(), storage::Error::DELETED_OBJECT); { auto labels = vertex->Labels(storage::View::OLD).GetReturn(); ASSERT_EQ(labels.size(), 1); ASSERT_EQ(labels[0], 5); } ASSERT_EQ(vertex->Labels(storage::View::NEW).GetError(), storage::Error::DELETED_OBJECT); // Advance command acc.AdvanceCommand(); // Check whether label 5 exists ASSERT_EQ(vertex->HasLabel(5, storage::View::OLD).GetError(), storage::Error::DELETED_OBJECT); ASSERT_EQ(vertex->HasLabel(5, storage::View::NEW).GetError(), storage::Error::DELETED_OBJECT); ASSERT_EQ(vertex->Labels(storage::View::OLD).GetError(), storage::Error::DELETED_OBJECT); ASSERT_EQ(vertex->Labels(storage::View::NEW).GetError(), storage::Error::DELETED_OBJECT); // Try to add the label { auto ret = vertex->AddLabel(5); ASSERT_TRUE(ret.IsError()); ASSERT_EQ(ret.GetError(), storage::Error::DELETED_OBJECT); } // Try to remove the label { auto ret = vertex->RemoveLabel(5); ASSERT_TRUE(ret.IsError()); ASSERT_EQ(ret.GetError(), storage::Error::DELETED_OBJECT); } acc.Abort(); } } // NOLINTNEXTLINE(hicpp-special-member-functions) TEST(StorageV2, VertexDeleteProperty) { storage::Storage store; storage::Gid gid = storage::Gid::FromUint(std::numeric_limits::max()); // Create the vertex { auto acc = store.Access(); auto vertex = acc.CreateVertex(); gid = vertex.Gid(); ASSERT_FALSE(acc.FindVertex(gid, storage::View::OLD).has_value()); ASSERT_TRUE(acc.FindVertex(gid, storage::View::NEW).has_value()); acc.Commit(); } // Set property, delete the vertex and check the property API (same command) { auto acc = store.Access(); auto vertex = acc.FindVertex(gid, storage::View::NEW); ASSERT_TRUE(vertex); // Check whether property 5 exists ASSERT_TRUE( vertex->GetProperty(5, storage::View::OLD).GetReturn().IsNull()); ASSERT_TRUE( vertex->GetProperty(5, storage::View::NEW).GetReturn().IsNull()); ASSERT_EQ(vertex->Properties(storage::View::OLD).GetReturn().size(), 0); ASSERT_EQ(vertex->Properties(storage::View::NEW).GetReturn().size(), 0); // Set property 5 to "nandare" ASSERT_FALSE( vertex->SetProperty(5, storage::PropertyValue("nandare")).GetReturn()); // Check whether property 5 exists ASSERT_TRUE( vertex->GetProperty(5, storage::View::OLD).GetReturn().IsNull()); ASSERT_EQ( vertex->GetProperty(5, storage::View::NEW).GetReturn().ValueString(), "nandare"); ASSERT_EQ(vertex->Properties(storage::View::OLD).GetReturn().size(), 0); { auto properties = vertex->Properties(storage::View::NEW).GetReturn(); ASSERT_EQ(properties.size(), 1); ASSERT_EQ(properties[5].ValueString(), "nandare"); } // Delete the vertex ASSERT_TRUE(acc.DeleteVertex(&*vertex).GetReturn()); // Check whether label 5 exists ASSERT_TRUE( vertex->GetProperty(5, storage::View::OLD).GetReturn().IsNull()); ASSERT_EQ(vertex->GetProperty(5, storage::View::NEW).GetError(), storage::Error::DELETED_OBJECT); ASSERT_EQ(vertex->Properties(storage::View::OLD).GetReturn().size(), 0); ASSERT_EQ(vertex->Properties(storage::View::NEW).GetError(), storage::Error::DELETED_OBJECT); // Try to set the property { auto ret = vertex->SetProperty(5, storage::PropertyValue("haihai")); ASSERT_TRUE(ret.IsError()); ASSERT_EQ(ret.GetError(), storage::Error::DELETED_OBJECT); } acc.Abort(); } // Set property, delete the vertex and check the property API (different // command) { auto acc = store.Access(); auto vertex = acc.FindVertex(gid, storage::View::NEW); ASSERT_TRUE(vertex); // Check whether property 5 exists ASSERT_TRUE( vertex->GetProperty(5, storage::View::OLD).GetReturn().IsNull()); ASSERT_TRUE( vertex->GetProperty(5, storage::View::NEW).GetReturn().IsNull()); ASSERT_EQ(vertex->Properties(storage::View::OLD).GetReturn().size(), 0); ASSERT_EQ(vertex->Properties(storage::View::NEW).GetReturn().size(), 0); // Set property 5 to "nandare" ASSERT_FALSE( vertex->SetProperty(5, storage::PropertyValue("nandare")).GetReturn()); // Check whether property 5 exists ASSERT_TRUE( vertex->GetProperty(5, storage::View::OLD).GetReturn().IsNull()); ASSERT_EQ( vertex->GetProperty(5, storage::View::NEW).GetReturn().ValueString(), "nandare"); ASSERT_EQ(vertex->Properties(storage::View::OLD).GetReturn().size(), 0); { auto properties = vertex->Properties(storage::View::NEW).GetReturn(); ASSERT_EQ(properties.size(), 1); ASSERT_EQ(properties[5].ValueString(), "nandare"); } // Advance command acc.AdvanceCommand(); // Check whether property 5 exists ASSERT_EQ( vertex->GetProperty(5, storage::View::OLD).GetReturn().ValueString(), "nandare"); ASSERT_EQ( vertex->GetProperty(5, storage::View::NEW).GetReturn().ValueString(), "nandare"); { auto properties = vertex->Properties(storage::View::OLD).GetReturn(); ASSERT_EQ(properties.size(), 1); ASSERT_EQ(properties[5].ValueString(), "nandare"); } { auto properties = vertex->Properties(storage::View::NEW).GetReturn(); ASSERT_EQ(properties.size(), 1); ASSERT_EQ(properties[5].ValueString(), "nandare"); } // Delete the vertex ASSERT_TRUE(acc.DeleteVertex(&*vertex).GetReturn()); // Check whether property 5 exists ASSERT_EQ( vertex->GetProperty(5, storage::View::OLD).GetReturn().ValueString(), "nandare"); ASSERT_EQ(vertex->GetProperty(5, storage::View::NEW).GetError(), storage::Error::DELETED_OBJECT); { auto properties = vertex->Properties(storage::View::OLD).GetReturn(); ASSERT_EQ(properties.size(), 1); ASSERT_EQ(properties[5].ValueString(), "nandare"); } ASSERT_EQ(vertex->Properties(storage::View::NEW).GetError(), storage::Error::DELETED_OBJECT); // Advance command acc.AdvanceCommand(); // Check whether property 5 exists ASSERT_EQ(vertex->GetProperty(5, storage::View::OLD).GetError(), storage::Error::DELETED_OBJECT); ASSERT_EQ(vertex->GetProperty(5, storage::View::NEW).GetError(), storage::Error::DELETED_OBJECT); ASSERT_EQ(vertex->Properties(storage::View::OLD).GetError(), storage::Error::DELETED_OBJECT); ASSERT_EQ(vertex->Properties(storage::View::NEW).GetError(), storage::Error::DELETED_OBJECT); // Try to set the property { auto ret = vertex->SetProperty(5, storage::PropertyValue("haihai")); ASSERT_TRUE(ret.IsError()); ASSERT_EQ(ret.GetError(), storage::Error::DELETED_OBJECT); } acc.Abort(); } } // NOLINTNEXTLINE(hicpp-special-member-functions) TEST(StorageV2, VertexLabelCommit) { storage::Storage store; storage::Gid gid = storage::Gid::FromUint(std::numeric_limits::max()); { auto acc = store.Access(); auto vertex = acc.CreateVertex(); gid = vertex.Gid(); ASSERT_FALSE(vertex.HasLabel(5, storage::View::NEW).GetReturn()); ASSERT_EQ(vertex.Labels(storage::View::NEW).GetReturn().size(), 0); { auto res = vertex.AddLabel(5); ASSERT_TRUE(res.IsReturn()); ASSERT_TRUE(res.GetReturn()); } ASSERT_TRUE(vertex.HasLabel(5, storage::View::NEW).GetReturn()); { auto labels = vertex.Labels(storage::View::NEW).GetReturn(); ASSERT_EQ(labels.size(), 1); ASSERT_EQ(labels[0], 5); } { auto res = vertex.AddLabel(5); ASSERT_TRUE(res.IsReturn()); ASSERT_FALSE(res.GetReturn()); } acc.Commit(); } { auto acc = store.Access(); auto vertex = acc.FindVertex(gid, storage::View::OLD); ASSERT_TRUE(vertex); ASSERT_TRUE(vertex->HasLabel(5, storage::View::OLD).GetReturn()); { auto labels = vertex->Labels(storage::View::OLD).GetReturn(); ASSERT_EQ(labels.size(), 1); ASSERT_EQ(labels[0], 5); } ASSERT_TRUE(vertex->HasLabel(5, storage::View::NEW).GetReturn()); { auto labels = vertex->Labels(storage::View::NEW).GetReturn(); ASSERT_EQ(labels.size(), 1); ASSERT_EQ(labels[0], 5); } ASSERT_FALSE(vertex->HasLabel(10, storage::View::OLD).GetReturn()); ASSERT_FALSE(vertex->HasLabel(10, storage::View::NEW).GetReturn()); acc.Abort(); } { auto acc = store.Access(); auto vertex = acc.FindVertex(gid, storage::View::OLD); ASSERT_TRUE(vertex); { auto res = vertex->RemoveLabel(5); ASSERT_TRUE(res.IsReturn()); ASSERT_TRUE(res.GetReturn()); } ASSERT_TRUE(vertex->HasLabel(5, storage::View::OLD).GetReturn()); { auto labels = vertex->Labels(storage::View::OLD).GetReturn(); ASSERT_EQ(labels.size(), 1); ASSERT_EQ(labels[0], 5); } ASSERT_FALSE(vertex->HasLabel(5, storage::View::NEW).GetReturn()); ASSERT_EQ(vertex->Labels(storage::View::NEW).GetReturn().size(), 0); { auto res = vertex->RemoveLabel(5); ASSERT_TRUE(res.IsReturn()); ASSERT_FALSE(res.GetReturn()); } acc.Commit(); } { auto acc = store.Access(); auto vertex = acc.FindVertex(gid, storage::View::OLD); ASSERT_TRUE(vertex); ASSERT_FALSE(vertex->HasLabel(5, storage::View::OLD).GetReturn()); ASSERT_FALSE(vertex->HasLabel(5, storage::View::NEW).GetReturn()); ASSERT_EQ(vertex->Labels(storage::View::OLD).GetReturn().size(), 0); ASSERT_EQ(vertex->Labels(storage::View::NEW).GetReturn().size(), 0); ASSERT_FALSE(vertex->HasLabel(10, storage::View::OLD).GetReturn()); ASSERT_FALSE(vertex->HasLabel(10, storage::View::NEW).GetReturn()); acc.Abort(); } } // NOLINTNEXTLINE(hicpp-special-member-functions) TEST(StorageV2, VertexLabelAbort) { storage::Storage store; storage::Gid gid = storage::Gid::FromUint(std::numeric_limits::max()); // Create the vertex. { auto acc = store.Access(); auto vertex = acc.CreateVertex(); gid = vertex.Gid(); acc.Commit(); } // Add label 5, but abort the transaction. { auto acc = store.Access(); auto vertex = acc.FindVertex(gid, storage::View::OLD); ASSERT_TRUE(vertex); ASSERT_FALSE(vertex->HasLabel(5, storage::View::NEW).GetReturn()); ASSERT_EQ(vertex->Labels(storage::View::NEW).GetReturn().size(), 0); { auto res = vertex->AddLabel(5); ASSERT_TRUE(res.IsReturn()); ASSERT_TRUE(res.GetReturn()); } ASSERT_TRUE(vertex->HasLabel(5, storage::View::NEW).GetReturn()); { auto labels = vertex->Labels(storage::View::NEW).GetReturn(); ASSERT_EQ(labels.size(), 1); ASSERT_EQ(labels[0], 5); } { auto res = vertex->AddLabel(5); ASSERT_TRUE(res.IsReturn()); ASSERT_FALSE(res.GetReturn()); } acc.Abort(); } // Check that label 5 doesn't exist. { auto acc = store.Access(); auto vertex = acc.FindVertex(gid, storage::View::OLD); ASSERT_TRUE(vertex); ASSERT_FALSE(vertex->HasLabel(5, storage::View::OLD).GetReturn()); ASSERT_FALSE(vertex->HasLabel(5, storage::View::NEW).GetReturn()); ASSERT_EQ(vertex->Labels(storage::View::OLD).GetReturn().size(), 0); ASSERT_EQ(vertex->Labels(storage::View::NEW).GetReturn().size(), 0); ASSERT_FALSE(vertex->HasLabel(10, storage::View::OLD).GetReturn()); ASSERT_FALSE(vertex->HasLabel(10, storage::View::NEW).GetReturn()); acc.Abort(); } // Add label 5. { auto acc = store.Access(); auto vertex = acc.FindVertex(gid, storage::View::OLD); ASSERT_TRUE(vertex); ASSERT_FALSE(vertex->HasLabel(5, storage::View::NEW).GetReturn()); ASSERT_EQ(vertex->Labels(storage::View::NEW).GetReturn().size(), 0); { auto res = vertex->AddLabel(5); ASSERT_TRUE(res.IsReturn()); ASSERT_TRUE(res.GetReturn()); } ASSERT_TRUE(vertex->HasLabel(5, storage::View::NEW).GetReturn()); { auto labels = vertex->Labels(storage::View::NEW).GetReturn(); ASSERT_EQ(labels.size(), 1); ASSERT_EQ(labels[0], 5); } { auto res = vertex->AddLabel(5); ASSERT_TRUE(res.IsReturn()); ASSERT_FALSE(res.GetReturn()); } acc.Commit(); } // Check that label 5 exists. { auto acc = store.Access(); auto vertex = acc.FindVertex(gid, storage::View::OLD); ASSERT_TRUE(vertex); ASSERT_TRUE(vertex->HasLabel(5, storage::View::OLD).GetReturn()); { auto labels = vertex->Labels(storage::View::OLD).GetReturn(); ASSERT_EQ(labels.size(), 1); ASSERT_EQ(labels[0], 5); } ASSERT_TRUE(vertex->HasLabel(5, storage::View::NEW).GetReturn()); { auto labels = vertex->Labels(storage::View::NEW).GetReturn(); ASSERT_EQ(labels.size(), 1); ASSERT_EQ(labels[0], 5); } ASSERT_FALSE(vertex->HasLabel(10, storage::View::OLD).GetReturn()); ASSERT_FALSE(vertex->HasLabel(10, storage::View::NEW).GetReturn()); acc.Abort(); } // Remove label 5, but abort the transaction. { auto acc = store.Access(); auto vertex = acc.FindVertex(gid, storage::View::OLD); ASSERT_TRUE(vertex); { auto res = vertex->RemoveLabel(5); ASSERT_TRUE(res.IsReturn()); ASSERT_TRUE(res.GetReturn()); } ASSERT_TRUE(vertex->HasLabel(5, storage::View::OLD).GetReturn()); { auto labels = vertex->Labels(storage::View::OLD).GetReturn(); ASSERT_EQ(labels.size(), 1); ASSERT_EQ(labels[0], 5); } ASSERT_FALSE(vertex->HasLabel(5, storage::View::NEW).GetReturn()); ASSERT_EQ(vertex->Labels(storage::View::NEW).GetReturn().size(), 0); { auto res = vertex->RemoveLabel(5); ASSERT_TRUE(res.IsReturn()); ASSERT_FALSE(res.GetReturn()); } acc.Abort(); } // Check that label 5 exists. { auto acc = store.Access(); auto vertex = acc.FindVertex(gid, storage::View::OLD); ASSERT_TRUE(vertex); ASSERT_TRUE(vertex->HasLabel(5, storage::View::OLD).GetReturn()); { auto labels = vertex->Labels(storage::View::OLD).GetReturn(); ASSERT_EQ(labels.size(), 1); ASSERT_EQ(labels[0], 5); } ASSERT_TRUE(vertex->HasLabel(5, storage::View::NEW).GetReturn()); { auto labels = vertex->Labels(storage::View::NEW).GetReturn(); ASSERT_EQ(labels.size(), 1); ASSERT_EQ(labels[0], 5); } ASSERT_FALSE(vertex->HasLabel(10, storage::View::OLD).GetReturn()); ASSERT_FALSE(vertex->HasLabel(10, storage::View::NEW).GetReturn()); acc.Abort(); } // Remove label 5. { auto acc = store.Access(); auto vertex = acc.FindVertex(gid, storage::View::OLD); ASSERT_TRUE(vertex); { auto res = vertex->RemoveLabel(5); ASSERT_TRUE(res.IsReturn()); ASSERT_TRUE(res.GetReturn()); } ASSERT_TRUE(vertex->HasLabel(5, storage::View::OLD).GetReturn()); { auto labels = vertex->Labels(storage::View::OLD).GetReturn(); ASSERT_EQ(labels.size(), 1); ASSERT_EQ(labels[0], 5); } ASSERT_FALSE(vertex->HasLabel(5, storage::View::NEW).GetReturn()); ASSERT_EQ(vertex->Labels(storage::View::NEW).GetReturn().size(), 0); { auto res = vertex->RemoveLabel(5); ASSERT_TRUE(res.IsReturn()); ASSERT_FALSE(res.GetReturn()); } acc.Commit(); } // Check that label 5 doesn't exist. { auto acc = store.Access(); auto vertex = acc.FindVertex(gid, storage::View::OLD); ASSERT_TRUE(vertex); ASSERT_FALSE(vertex->HasLabel(5, storage::View::OLD).GetReturn()); ASSERT_FALSE(vertex->HasLabel(5, storage::View::NEW).GetReturn()); ASSERT_EQ(vertex->Labels(storage::View::OLD).GetReturn().size(), 0); ASSERT_EQ(vertex->Labels(storage::View::NEW).GetReturn().size(), 0); ASSERT_FALSE(vertex->HasLabel(10, storage::View::OLD).GetReturn()); ASSERT_FALSE(vertex->HasLabel(10, storage::View::NEW).GetReturn()); acc.Abort(); } } // NOLINTNEXTLINE(hicpp-special-member-functions) TEST(StorageV2, VertexLabelSerializationError) { storage::Storage store; storage::Gid gid = storage::Gid::FromUint(std::numeric_limits::max()); { auto acc = store.Access(); auto vertex = acc.CreateVertex(); gid = vertex.Gid(); acc.Commit(); } auto acc1 = store.Access(); auto acc2 = store.Access(); // Add label 1 in accessor 1. { auto vertex = acc1.FindVertex(gid, storage::View::OLD); ASSERT_TRUE(vertex); ASSERT_FALSE(vertex->HasLabel(1, storage::View::OLD).GetReturn()); ASSERT_FALSE(vertex->HasLabel(1, storage::View::NEW).GetReturn()); ASSERT_FALSE(vertex->HasLabel(2, storage::View::OLD).GetReturn()); ASSERT_FALSE(vertex->HasLabel(2, storage::View::NEW).GetReturn()); ASSERT_EQ(vertex->Labels(storage::View::OLD).GetReturn().size(), 0); ASSERT_EQ(vertex->Labels(storage::View::NEW).GetReturn().size(), 0); { auto res = vertex->AddLabel(1); ASSERT_TRUE(res.IsReturn()); ASSERT_TRUE(res.GetReturn()); } ASSERT_FALSE(vertex->HasLabel(1, storage::View::OLD).GetReturn()); ASSERT_TRUE(vertex->HasLabel(1, storage::View::NEW).GetReturn()); ASSERT_FALSE(vertex->HasLabel(2, storage::View::OLD).GetReturn()); ASSERT_FALSE(vertex->HasLabel(2, storage::View::NEW).GetReturn()); ASSERT_EQ(vertex->Labels(storage::View::OLD).GetReturn().size(), 0); { auto labels = vertex->Labels(storage::View::NEW).GetReturn(); ASSERT_EQ(labels.size(), 1); ASSERT_EQ(labels[0], 1); } { auto res = vertex->AddLabel(1); ASSERT_TRUE(res.IsReturn()); ASSERT_FALSE(res.GetReturn()); } } // Add label 2 in accessor 2. { auto vertex = acc2.FindVertex(gid, storage::View::OLD); ASSERT_TRUE(vertex); ASSERT_FALSE(vertex->HasLabel(1, storage::View::OLD).GetReturn()); ASSERT_FALSE(vertex->HasLabel(1, storage::View::NEW).GetReturn()); ASSERT_FALSE(vertex->HasLabel(2, storage::View::OLD).GetReturn()); ASSERT_FALSE(vertex->HasLabel(2, storage::View::NEW).GetReturn()); ASSERT_EQ(vertex->Labels(storage::View::OLD).GetReturn().size(), 0); ASSERT_EQ(vertex->Labels(storage::View::NEW).GetReturn().size(), 0); { auto res = vertex->AddLabel(1); ASSERT_TRUE(res.IsError()); ASSERT_EQ(res.GetError(), storage::Error::SERIALIZATION_ERROR); } } // Finalize both accessors. acc1.Commit(); acc2.Abort(); // Check which labels exist. { auto acc = store.Access(); auto vertex = acc.FindVertex(gid, storage::View::OLD); ASSERT_TRUE(vertex); ASSERT_TRUE(vertex->HasLabel(1, storage::View::OLD).GetReturn()); ASSERT_FALSE(vertex->HasLabel(2, storage::View::OLD).GetReturn()); { auto labels = vertex->Labels(storage::View::OLD).GetReturn(); ASSERT_EQ(labels.size(), 1); ASSERT_EQ(labels[0], 1); } ASSERT_TRUE(vertex->HasLabel(1, storage::View::NEW).GetReturn()); ASSERT_FALSE(vertex->HasLabel(2, storage::View::NEW).GetReturn()); { auto labels = vertex->Labels(storage::View::NEW).GetReturn(); ASSERT_EQ(labels.size(), 1); ASSERT_EQ(labels[0], 1); } acc.Abort(); } } // NOLINTNEXTLINE(hicpp-special-member-functions) TEST(StorageV2, VertexPropertyCommit) { storage::Storage store; storage::Gid gid = storage::Gid::FromUint(std::numeric_limits::max()); { auto acc = store.Access(); auto vertex = acc.CreateVertex(); gid = vertex.Gid(); ASSERT_TRUE(vertex.GetProperty(5, storage::View::NEW).GetReturn().IsNull()); ASSERT_EQ(vertex.Properties(storage::View::NEW).GetReturn().size(), 0); { auto res = vertex.SetProperty(5, storage::PropertyValue("temporary")); ASSERT_TRUE(res.IsReturn()); ASSERT_FALSE(res.GetReturn()); } ASSERT_EQ( vertex.GetProperty(5, storage::View::NEW).GetReturn().ValueString(), "temporary"); { auto properties = vertex.Properties(storage::View::NEW).GetReturn(); ASSERT_EQ(properties.size(), 1); ASSERT_EQ(properties[5].ValueString(), "temporary"); } { auto res = vertex.SetProperty(5, storage::PropertyValue("nandare")); ASSERT_TRUE(res.IsReturn()); ASSERT_TRUE(res.GetReturn()); } ASSERT_EQ( vertex.GetProperty(5, storage::View::NEW).GetReturn().ValueString(), "nandare"); { auto properties = vertex.Properties(storage::View::NEW).GetReturn(); ASSERT_EQ(properties.size(), 1); ASSERT_EQ(properties[5].ValueString(), "nandare"); } acc.Commit(); } { auto acc = store.Access(); auto vertex = acc.FindVertex(gid, storage::View::OLD); ASSERT_TRUE(vertex); ASSERT_EQ( vertex->GetProperty(5, storage::View::OLD).GetReturn().ValueString(), "nandare"); { auto properties = vertex->Properties(storage::View::OLD).GetReturn(); ASSERT_EQ(properties.size(), 1); ASSERT_EQ(properties[5].ValueString(), "nandare"); } ASSERT_EQ( vertex->GetProperty(5, storage::View::NEW).GetReturn().ValueString(), "nandare"); { auto properties = vertex->Properties(storage::View::NEW).GetReturn(); ASSERT_EQ(properties.size(), 1); ASSERT_EQ(properties[5].ValueString(), "nandare"); } ASSERT_TRUE( vertex->GetProperty(10, storage::View::OLD).GetReturn().IsNull()); ASSERT_TRUE( vertex->GetProperty(10, storage::View::NEW).GetReturn().IsNull()); acc.Abort(); } { auto acc = store.Access(); auto vertex = acc.FindVertex(gid, storage::View::OLD); ASSERT_TRUE(vertex); { auto res = vertex->SetProperty(5, storage::PropertyValue()); ASSERT_TRUE(res.IsReturn()); ASSERT_TRUE(res.GetReturn()); } ASSERT_EQ( vertex->GetProperty(5, storage::View::OLD).GetReturn().ValueString(), "nandare"); { auto properties = vertex->Properties(storage::View::OLD).GetReturn(); ASSERT_EQ(properties.size(), 1); ASSERT_EQ(properties[5].ValueString(), "nandare"); } ASSERT_TRUE( vertex->GetProperty(5, storage::View::NEW).GetReturn().IsNull()); ASSERT_EQ(vertex->Properties(storage::View::NEW).GetReturn().size(), 0); { auto res = vertex->SetProperty(5, storage::PropertyValue()); ASSERT_TRUE(res.IsReturn()); ASSERT_FALSE(res.GetReturn()); } acc.Commit(); } { auto acc = store.Access(); auto vertex = acc.FindVertex(gid, storage::View::OLD); ASSERT_TRUE(vertex); ASSERT_TRUE( vertex->GetProperty(5, storage::View::OLD).GetReturn().IsNull()); ASSERT_TRUE( vertex->GetProperty(5, storage::View::NEW).GetReturn().IsNull()); ASSERT_EQ(vertex->Properties(storage::View::OLD).GetReturn().size(), 0); ASSERT_EQ(vertex->Properties(storage::View::NEW).GetReturn().size(), 0); ASSERT_TRUE( vertex->GetProperty(10, storage::View::OLD).GetReturn().IsNull()); ASSERT_TRUE( vertex->GetProperty(10, storage::View::NEW).GetReturn().IsNull()); acc.Abort(); } } // NOLINTNEXTLINE(hicpp-special-member-functions) TEST(StorageV2, VertexPropertyAbort) { storage::Storage store; storage::Gid gid = storage::Gid::FromUint(std::numeric_limits::max()); // Create the vertex. { auto acc = store.Access(); auto vertex = acc.CreateVertex(); gid = vertex.Gid(); acc.Commit(); } // Set property 5 to "nandare", but abort the transaction. { auto acc = store.Access(); auto vertex = acc.FindVertex(gid, storage::View::OLD); ASSERT_TRUE(vertex); ASSERT_TRUE( vertex->GetProperty(5, storage::View::NEW).GetReturn().IsNull()); ASSERT_EQ(vertex->Properties(storage::View::NEW).GetReturn().size(), 0); { auto res = vertex->SetProperty(5, storage::PropertyValue("temporary")); ASSERT_TRUE(res.IsReturn()); ASSERT_FALSE(res.GetReturn()); } ASSERT_EQ( vertex->GetProperty(5, storage::View::NEW).GetReturn().ValueString(), "temporary"); { auto properties = vertex->Properties(storage::View::NEW).GetReturn(); ASSERT_EQ(properties.size(), 1); ASSERT_EQ(properties[5].ValueString(), "temporary"); } { auto res = vertex->SetProperty(5, storage::PropertyValue("nandare")); ASSERT_TRUE(res.IsReturn()); ASSERT_TRUE(res.GetReturn()); } ASSERT_EQ( vertex->GetProperty(5, storage::View::NEW).GetReturn().ValueString(), "nandare"); { auto properties = vertex->Properties(storage::View::NEW).GetReturn(); ASSERT_EQ(properties.size(), 1); ASSERT_EQ(properties[5].ValueString(), "nandare"); } acc.Abort(); } // Check that property 5 is null. { auto acc = store.Access(); auto vertex = acc.FindVertex(gid, storage::View::OLD); ASSERT_TRUE(vertex); ASSERT_TRUE( vertex->GetProperty(5, storage::View::OLD).GetReturn().IsNull()); ASSERT_TRUE( vertex->GetProperty(5, storage::View::NEW).GetReturn().IsNull()); ASSERT_EQ(vertex->Properties(storage::View::OLD).GetReturn().size(), 0); ASSERT_EQ(vertex->Properties(storage::View::NEW).GetReturn().size(), 0); ASSERT_TRUE( vertex->GetProperty(10, storage::View::OLD).GetReturn().IsNull()); ASSERT_TRUE( vertex->GetProperty(10, storage::View::NEW).GetReturn().IsNull()); acc.Abort(); } // Set property 5 to "nandare". { auto acc = store.Access(); auto vertex = acc.FindVertex(gid, storage::View::OLD); ASSERT_TRUE(vertex); ASSERT_TRUE( vertex->GetProperty(5, storage::View::NEW).GetReturn().IsNull()); ASSERT_EQ(vertex->Properties(storage::View::NEW).GetReturn().size(), 0); { auto res = vertex->SetProperty(5, storage::PropertyValue("temporary")); ASSERT_TRUE(res.IsReturn()); ASSERT_FALSE(res.GetReturn()); } ASSERT_EQ( vertex->GetProperty(5, storage::View::NEW).GetReturn().ValueString(), "temporary"); { auto properties = vertex->Properties(storage::View::NEW).GetReturn(); ASSERT_EQ(properties.size(), 1); ASSERT_EQ(properties[5].ValueString(), "temporary"); } { auto res = vertex->SetProperty(5, storage::PropertyValue("nandare")); ASSERT_TRUE(res.IsReturn()); ASSERT_TRUE(res.GetReturn()); } ASSERT_EQ( vertex->GetProperty(5, storage::View::NEW).GetReturn().ValueString(), "nandare"); { auto properties = vertex->Properties(storage::View::NEW).GetReturn(); ASSERT_EQ(properties.size(), 1); ASSERT_EQ(properties[5].ValueString(), "nandare"); } acc.Commit(); } // Check that property 5 is "nandare". { auto acc = store.Access(); auto vertex = acc.FindVertex(gid, storage::View::OLD); ASSERT_TRUE(vertex); ASSERT_EQ( vertex->GetProperty(5, storage::View::OLD).GetReturn().ValueString(), "nandare"); { auto properties = vertex->Properties(storage::View::OLD).GetReturn(); ASSERT_EQ(properties.size(), 1); ASSERT_EQ(properties[5].ValueString(), "nandare"); } ASSERT_EQ( vertex->GetProperty(5, storage::View::NEW).GetReturn().ValueString(), "nandare"); { auto properties = vertex->Properties(storage::View::NEW).GetReturn(); ASSERT_EQ(properties.size(), 1); ASSERT_EQ(properties[5].ValueString(), "nandare"); } ASSERT_TRUE( vertex->GetProperty(10, storage::View::OLD).GetReturn().IsNull()); ASSERT_TRUE( vertex->GetProperty(10, storage::View::NEW).GetReturn().IsNull()); acc.Abort(); } // Set property 5 to null, but abort the transaction. { auto acc = store.Access(); auto vertex = acc.FindVertex(gid, storage::View::OLD); ASSERT_TRUE(vertex); ASSERT_EQ( vertex->GetProperty(5, storage::View::OLD).GetReturn().ValueString(), "nandare"); { auto properties = vertex->Properties(storage::View::OLD).GetReturn(); ASSERT_EQ(properties.size(), 1); ASSERT_EQ(properties[5].ValueString(), "nandare"); } ASSERT_EQ( vertex->GetProperty(5, storage::View::NEW).GetReturn().ValueString(), "nandare"); { auto properties = vertex->Properties(storage::View::NEW).GetReturn(); ASSERT_EQ(properties.size(), 1); ASSERT_EQ(properties[5].ValueString(), "nandare"); } { auto res = vertex->SetProperty(5, storage::PropertyValue()); ASSERT_TRUE(res.IsReturn()); ASSERT_TRUE(res.GetReturn()); } ASSERT_EQ( vertex->GetProperty(5, storage::View::OLD).GetReturn().ValueString(), "nandare"); { auto properties = vertex->Properties(storage::View::OLD).GetReturn(); ASSERT_EQ(properties.size(), 1); ASSERT_EQ(properties[5].ValueString(), "nandare"); } ASSERT_TRUE( vertex->GetProperty(5, storage::View::NEW).GetReturn().IsNull()); ASSERT_EQ(vertex->Properties(storage::View::NEW).GetReturn().size(), 0); acc.Abort(); } // Check that property 5 is "nandare". { auto acc = store.Access(); auto vertex = acc.FindVertex(gid, storage::View::OLD); ASSERT_TRUE(vertex); ASSERT_EQ( vertex->GetProperty(5, storage::View::OLD).GetReturn().ValueString(), "nandare"); { auto properties = vertex->Properties(storage::View::OLD).GetReturn(); ASSERT_EQ(properties.size(), 1); ASSERT_EQ(properties[5].ValueString(), "nandare"); } ASSERT_EQ( vertex->GetProperty(5, storage::View::NEW).GetReturn().ValueString(), "nandare"); { auto properties = vertex->Properties(storage::View::NEW).GetReturn(); ASSERT_EQ(properties.size(), 1); ASSERT_EQ(properties[5].ValueString(), "nandare"); } ASSERT_TRUE( vertex->GetProperty(10, storage::View::OLD).GetReturn().IsNull()); ASSERT_TRUE( vertex->GetProperty(10, storage::View::NEW).GetReturn().IsNull()); acc.Abort(); } // Set property 5 to null. { auto acc = store.Access(); auto vertex = acc.FindVertex(gid, storage::View::OLD); ASSERT_TRUE(vertex); ASSERT_EQ( vertex->GetProperty(5, storage::View::OLD).GetReturn().ValueString(), "nandare"); { auto properties = vertex->Properties(storage::View::OLD).GetReturn(); ASSERT_EQ(properties.size(), 1); ASSERT_EQ(properties[5].ValueString(), "nandare"); } ASSERT_EQ( vertex->GetProperty(5, storage::View::NEW).GetReturn().ValueString(), "nandare"); { auto properties = vertex->Properties(storage::View::NEW).GetReturn(); ASSERT_EQ(properties.size(), 1); ASSERT_EQ(properties[5].ValueString(), "nandare"); } { auto res = vertex->SetProperty(5, storage::PropertyValue()); ASSERT_TRUE(res.IsReturn()); ASSERT_TRUE(res.GetReturn()); } ASSERT_EQ( vertex->GetProperty(5, storage::View::OLD).GetReturn().ValueString(), "nandare"); { auto properties = vertex->Properties(storage::View::OLD).GetReturn(); ASSERT_EQ(properties.size(), 1); ASSERT_EQ(properties[5].ValueString(), "nandare"); } ASSERT_TRUE( vertex->GetProperty(5, storage::View::NEW).GetReturn().IsNull()); ASSERT_EQ(vertex->Properties(storage::View::NEW).GetReturn().size(), 0); acc.Commit(); } // Check that property 5 is null. { auto acc = store.Access(); auto vertex = acc.FindVertex(gid, storage::View::OLD); ASSERT_TRUE(vertex); ASSERT_TRUE( vertex->GetProperty(5, storage::View::OLD).GetReturn().IsNull()); ASSERT_TRUE( vertex->GetProperty(5, storage::View::NEW).GetReturn().IsNull()); ASSERT_EQ(vertex->Properties(storage::View::OLD).GetReturn().size(), 0); ASSERT_EQ(vertex->Properties(storage::View::NEW).GetReturn().size(), 0); ASSERT_TRUE( vertex->GetProperty(10, storage::View::OLD).GetReturn().IsNull()); ASSERT_TRUE( vertex->GetProperty(10, storage::View::NEW).GetReturn().IsNull()); acc.Abort(); } } // NOLINTNEXTLINE(hicpp-special-member-functions) TEST(StorageV2, VertexPropertySerializationError) { storage::Storage store; storage::Gid gid = storage::Gid::FromUint(std::numeric_limits::max()); { auto acc = store.Access(); auto vertex = acc.CreateVertex(); gid = vertex.Gid(); acc.Commit(); } auto acc1 = store.Access(); auto acc2 = store.Access(); // Set property 1 to 123 in accessor 1. { auto vertex = acc1.FindVertex(gid, storage::View::OLD); ASSERT_TRUE(vertex); ASSERT_TRUE( vertex->GetProperty(1, storage::View::OLD).GetReturn().IsNull()); ASSERT_TRUE( vertex->GetProperty(1, storage::View::NEW).GetReturn().IsNull()); ASSERT_TRUE( vertex->GetProperty(2, storage::View::OLD).GetReturn().IsNull()); ASSERT_TRUE( vertex->GetProperty(2, storage::View::NEW).GetReturn().IsNull()); ASSERT_EQ(vertex->Properties(storage::View::OLD).GetReturn().size(), 0); ASSERT_EQ(vertex->Properties(storage::View::NEW).GetReturn().size(), 0); { auto res = vertex->SetProperty(1, storage::PropertyValue(123)); ASSERT_TRUE(res.IsReturn()); ASSERT_FALSE(res.GetReturn()); } ASSERT_TRUE( vertex->GetProperty(1, storage::View::OLD).GetReturn().IsNull()); ASSERT_EQ(vertex->GetProperty(1, storage::View::NEW).GetReturn().ValueInt(), 123); ASSERT_TRUE( vertex->GetProperty(2, storage::View::OLD).GetReturn().IsNull()); ASSERT_TRUE( vertex->GetProperty(2, storage::View::NEW).GetReturn().IsNull()); ASSERT_EQ(vertex->Properties(storage::View::OLD).GetReturn().size(), 0); { auto properties = vertex->Properties(storage::View::NEW).GetReturn(); ASSERT_EQ(properties.size(), 1); ASSERT_EQ(properties[1].ValueInt(), 123); } } // Set property 2 to "nandare" in accessor 2. { auto vertex = acc2.FindVertex(gid, storage::View::OLD); ASSERT_TRUE(vertex); ASSERT_TRUE( vertex->GetProperty(1, storage::View::OLD).GetReturn().IsNull()); ASSERT_TRUE( vertex->GetProperty(1, storage::View::NEW).GetReturn().IsNull()); ASSERT_TRUE( vertex->GetProperty(2, storage::View::OLD).GetReturn().IsNull()); ASSERT_TRUE( vertex->GetProperty(2, storage::View::NEW).GetReturn().IsNull()); ASSERT_EQ(vertex->Properties(storage::View::OLD).GetReturn().size(), 0); ASSERT_EQ(vertex->Properties(storage::View::NEW).GetReturn().size(), 0); { auto res = vertex->SetProperty(2, storage::PropertyValue("nandare")); ASSERT_TRUE(res.IsError()); ASSERT_EQ(res.GetError(), storage::Error::SERIALIZATION_ERROR); } } // Finalize both accessors. acc1.Commit(); acc2.Abort(); // Check which properties exist. { auto acc = store.Access(); auto vertex = acc.FindVertex(gid, storage::View::OLD); ASSERT_TRUE(vertex); ASSERT_EQ(vertex->GetProperty(1, storage::View::OLD).GetReturn().ValueInt(), 123); ASSERT_TRUE( vertex->GetProperty(2, storage::View::OLD).GetReturn().IsNull()); { auto properties = vertex->Properties(storage::View::OLD).GetReturn(); ASSERT_EQ(properties.size(), 1); ASSERT_EQ(properties[1].ValueInt(), 123); } ASSERT_EQ(vertex->GetProperty(1, storage::View::NEW).GetReturn().ValueInt(), 123); ASSERT_TRUE( vertex->GetProperty(2, storage::View::NEW).GetReturn().IsNull()); { auto properties = vertex->Properties(storage::View::NEW).GetReturn(); ASSERT_EQ(properties.size(), 1); ASSERT_EQ(properties[1].ValueInt(), 123); } acc.Abort(); } } // NOLINTNEXTLINE(hicpp-special-member-functions) TEST(StorageV2, VertexLabelPropertyMixed) { storage::Storage store; auto acc = store.Access(); auto vertex = acc.CreateVertex(); // Check whether label 5 and property 5 exist ASSERT_FALSE(vertex.HasLabel(5, storage::View::NEW).GetReturn()); ASSERT_EQ(vertex.Labels(storage::View::NEW).GetReturn().size(), 0); ASSERT_TRUE(vertex.GetProperty(5, storage::View::NEW).GetReturn().IsNull()); ASSERT_EQ(vertex.Properties(storage::View::NEW).GetReturn().size(), 0); // Add label 5 ASSERT_TRUE(vertex.AddLabel(5).GetReturn()); // Check whether label 5 and property 5 exist ASSERT_TRUE(vertex.HasLabel(5, storage::View::NEW).GetReturn()); { auto labels = vertex.Labels(storage::View::NEW).GetReturn(); ASSERT_EQ(labels.size(), 1); ASSERT_EQ(labels[0], 5); } ASSERT_TRUE(vertex.GetProperty(5, storage::View::NEW).GetReturn().IsNull()); ASSERT_EQ(vertex.Properties(storage::View::NEW).GetReturn().size(), 0); // Advance command acc.AdvanceCommand(); // Check whether label 5 and property 5 exist ASSERT_TRUE(vertex.HasLabel(5, storage::View::OLD).GetReturn()); ASSERT_TRUE(vertex.HasLabel(5, storage::View::NEW).GetReturn()); { auto labels = vertex.Labels(storage::View::OLD).GetReturn(); ASSERT_EQ(labels.size(), 1); ASSERT_EQ(labels[0], 5); } { auto labels = vertex.Labels(storage::View::NEW).GetReturn(); ASSERT_EQ(labels.size(), 1); ASSERT_EQ(labels[0], 5); } ASSERT_TRUE(vertex.GetProperty(5, storage::View::OLD).GetReturn().IsNull()); ASSERT_TRUE(vertex.GetProperty(5, storage::View::NEW).GetReturn().IsNull()); ASSERT_EQ(vertex.Properties(storage::View::OLD).GetReturn().size(), 0); ASSERT_EQ(vertex.Properties(storage::View::NEW).GetReturn().size(), 0); // Set property 5 to "nandare" ASSERT_FALSE( vertex.SetProperty(5, storage::PropertyValue("nandare")).GetReturn()); // Check whether label 5 and property 5 exist ASSERT_TRUE(vertex.HasLabel(5, storage::View::OLD).GetReturn()); ASSERT_TRUE(vertex.HasLabel(5, storage::View::NEW).GetReturn()); { auto labels = vertex.Labels(storage::View::OLD).GetReturn(); ASSERT_EQ(labels.size(), 1); ASSERT_EQ(labels[0], 5); } { auto labels = vertex.Labels(storage::View::NEW).GetReturn(); ASSERT_EQ(labels.size(), 1); ASSERT_EQ(labels[0], 5); } ASSERT_TRUE(vertex.GetProperty(5, storage::View::OLD).GetReturn().IsNull()); ASSERT_EQ(vertex.GetProperty(5, storage::View::NEW).GetReturn().ValueString(), "nandare"); ASSERT_EQ(vertex.Properties(storage::View::OLD).GetReturn().size(), 0); { auto properties = vertex.Properties(storage::View::NEW).GetReturn(); ASSERT_EQ(properties.size(), 1); ASSERT_EQ(properties[5].ValueString(), "nandare"); } // Advance command acc.AdvanceCommand(); // Check whether label 5 and property 5 exist ASSERT_TRUE(vertex.HasLabel(5, storage::View::OLD).GetReturn()); ASSERT_TRUE(vertex.HasLabel(5, storage::View::NEW).GetReturn()); { auto labels = vertex.Labels(storage::View::OLD).GetReturn(); ASSERT_EQ(labels.size(), 1); ASSERT_EQ(labels[0], 5); } { auto labels = vertex.Labels(storage::View::NEW).GetReturn(); ASSERT_EQ(labels.size(), 1); ASSERT_EQ(labels[0], 5); } ASSERT_EQ(vertex.GetProperty(5, storage::View::OLD).GetReturn().ValueString(), "nandare"); ASSERT_EQ(vertex.GetProperty(5, storage::View::NEW).GetReturn().ValueString(), "nandare"); { auto properties = vertex.Properties(storage::View::OLD).GetReturn(); ASSERT_EQ(properties.size(), 1); ASSERT_EQ(properties[5].ValueString(), "nandare"); } { auto properties = vertex.Properties(storage::View::NEW).GetReturn(); ASSERT_EQ(properties.size(), 1); ASSERT_EQ(properties[5].ValueString(), "nandare"); } // Set property 5 to "haihai" ASSERT_TRUE( vertex.SetProperty(5, storage::PropertyValue("haihai")).GetReturn()); // Check whether label 5 and property 5 exist ASSERT_TRUE(vertex.HasLabel(5, storage::View::OLD).GetReturn()); ASSERT_TRUE(vertex.HasLabel(5, storage::View::NEW).GetReturn()); { auto labels = vertex.Labels(storage::View::OLD).GetReturn(); ASSERT_EQ(labels.size(), 1); ASSERT_EQ(labels[0], 5); } { auto labels = vertex.Labels(storage::View::NEW).GetReturn(); ASSERT_EQ(labels.size(), 1); ASSERT_EQ(labels[0], 5); } ASSERT_EQ(vertex.GetProperty(5, storage::View::OLD).GetReturn().ValueString(), "nandare"); ASSERT_EQ(vertex.GetProperty(5, storage::View::NEW).GetReturn().ValueString(), "haihai"); { auto properties = vertex.Properties(storage::View::OLD).GetReturn(); ASSERT_EQ(properties.size(), 1); ASSERT_EQ(properties[5].ValueString(), "nandare"); } { auto properties = vertex.Properties(storage::View::NEW).GetReturn(); ASSERT_EQ(properties.size(), 1); ASSERT_EQ(properties[5].ValueString(), "haihai"); } // Advance command acc.AdvanceCommand(); // Check whether label 5 and property 5 exist ASSERT_TRUE(vertex.HasLabel(5, storage::View::OLD).GetReturn()); ASSERT_TRUE(vertex.HasLabel(5, storage::View::NEW).GetReturn()); { auto labels = vertex.Labels(storage::View::OLD).GetReturn(); ASSERT_EQ(labels.size(), 1); ASSERT_EQ(labels[0], 5); } { auto labels = vertex.Labels(storage::View::NEW).GetReturn(); ASSERT_EQ(labels.size(), 1); ASSERT_EQ(labels[0], 5); } ASSERT_EQ(vertex.GetProperty(5, storage::View::OLD).GetReturn().ValueString(), "haihai"); ASSERT_EQ(vertex.GetProperty(5, storage::View::NEW).GetReturn().ValueString(), "haihai"); { auto properties = vertex.Properties(storage::View::OLD).GetReturn(); ASSERT_EQ(properties.size(), 1); ASSERT_EQ(properties[5].ValueString(), "haihai"); } { auto properties = vertex.Properties(storage::View::NEW).GetReturn(); ASSERT_EQ(properties.size(), 1); ASSERT_EQ(properties[5].ValueString(), "haihai"); } // Remove label 5 ASSERT_TRUE(vertex.RemoveLabel(5).GetReturn()); // Check whether label 5 and property 5 exist ASSERT_TRUE(vertex.HasLabel(5, storage::View::OLD).GetReturn()); ASSERT_FALSE(vertex.HasLabel(5, storage::View::NEW).GetReturn()); { auto labels = vertex.Labels(storage::View::OLD).GetReturn(); ASSERT_EQ(labels.size(), 1); ASSERT_EQ(labels[0], 5); } ASSERT_EQ(vertex.Labels(storage::View::NEW).GetReturn().size(), 0); ASSERT_EQ(vertex.GetProperty(5, storage::View::OLD).GetReturn().ValueString(), "haihai"); ASSERT_EQ(vertex.GetProperty(5, storage::View::NEW).GetReturn().ValueString(), "haihai"); { auto properties = vertex.Properties(storage::View::OLD).GetReturn(); ASSERT_EQ(properties.size(), 1); ASSERT_EQ(properties[5].ValueString(), "haihai"); } { auto properties = vertex.Properties(storage::View::NEW).GetReturn(); ASSERT_EQ(properties.size(), 1); ASSERT_EQ(properties[5].ValueString(), "haihai"); } // Advance command acc.AdvanceCommand(); // Check whether label 5 and property 5 exist ASSERT_FALSE(vertex.HasLabel(5, storage::View::OLD).GetReturn()); ASSERT_FALSE(vertex.HasLabel(5, storage::View::NEW).GetReturn()); ASSERT_EQ(vertex.Labels(storage::View::OLD).GetReturn().size(), 0); ASSERT_EQ(vertex.Labels(storage::View::NEW).GetReturn().size(), 0); ASSERT_EQ(vertex.GetProperty(5, storage::View::OLD).GetReturn().ValueString(), "haihai"); ASSERT_EQ(vertex.GetProperty(5, storage::View::NEW).GetReturn().ValueString(), "haihai"); { auto properties = vertex.Properties(storage::View::OLD).GetReturn(); ASSERT_EQ(properties.size(), 1); ASSERT_EQ(properties[5].ValueString(), "haihai"); } { auto properties = vertex.Properties(storage::View::NEW).GetReturn(); ASSERT_EQ(properties.size(), 1); ASSERT_EQ(properties[5].ValueString(), "haihai"); } // Set property 5 to null ASSERT_TRUE(vertex.SetProperty(5, storage::PropertyValue()).GetReturn()); // Check whether label 5 and property 5 exist ASSERT_FALSE(vertex.HasLabel(5, storage::View::OLD).GetReturn()); ASSERT_FALSE(vertex.HasLabel(5, storage::View::NEW).GetReturn()); ASSERT_EQ(vertex.Labels(storage::View::OLD).GetReturn().size(), 0); ASSERT_EQ(vertex.Labels(storage::View::NEW).GetReturn().size(), 0); ASSERT_EQ(vertex.GetProperty(5, storage::View::OLD).GetReturn().ValueString(), "haihai"); ASSERT_TRUE(vertex.GetProperty(5, storage::View::NEW).GetReturn().IsNull()); { auto properties = vertex.Properties(storage::View::OLD).GetReturn(); ASSERT_EQ(properties.size(), 1); ASSERT_EQ(properties[5].ValueString(), "haihai"); } ASSERT_EQ(vertex.Properties(storage::View::NEW).GetReturn().size(), 0); // Advance command acc.AdvanceCommand(); // Check whether label 5 and property 5 exist ASSERT_FALSE(vertex.HasLabel(5, storage::View::OLD).GetReturn()); ASSERT_FALSE(vertex.HasLabel(5, storage::View::NEW).GetReturn()); ASSERT_EQ(vertex.Labels(storage::View::OLD).GetReturn().size(), 0); ASSERT_EQ(vertex.Labels(storage::View::NEW).GetReturn().size(), 0); ASSERT_TRUE(vertex.GetProperty(5, storage::View::NEW).GetReturn().IsNull()); ASSERT_TRUE(vertex.GetProperty(5, storage::View::NEW).GetReturn().IsNull()); ASSERT_EQ(vertex.Properties(storage::View::OLD).GetReturn().size(), 0); ASSERT_EQ(vertex.Properties(storage::View::NEW).GetReturn().size(), 0); acc.Commit(); }