From 6138d7669044b085af4793412c803dd3f72e36d8 Mon Sep 17 00:00:00 2001 From: Tyler Neely Date: Thu, 3 Nov 2022 14:21:17 +0000 Subject: [PATCH] Remove unit tests for storage v2 --- tests/unit/CMakeLists.txt | 43 - tests/unit/commit_log_v2.cpp | 81 - tests/unit/property_value_v2.cpp | 814 ---- tests/unit/storage_v2.cpp | 2595 ---------- tests/unit/storage_v2_constraints.cpp | 973 ---- tests/unit/storage_v2_decoder_encoder.cpp | 461 -- tests/unit/storage_v2_durability.cpp | 2404 --------- tests/unit/storage_v2_edge.cpp | 5391 --------------------- tests/unit/storage_v2_gc.cpp | 200 - tests/unit/storage_v2_indices.cpp | 832 ---- tests/unit/storage_v2_isolation_level.cpp | 110 - tests/unit/storage_v2_name_id_mapper.cpp | 47 - tests/unit/storage_v2_property_store.cpp | 651 --- tests/unit/storage_v2_replication.cpp | 828 ---- tests/unit/storage_v2_wal_file.cpp | 623 --- 15 files changed, 16053 deletions(-) delete mode 100644 tests/unit/commit_log_v2.cpp delete mode 100644 tests/unit/property_value_v2.cpp delete mode 100644 tests/unit/storage_v2.cpp delete mode 100644 tests/unit/storage_v2_constraints.cpp delete mode 100644 tests/unit/storage_v2_decoder_encoder.cpp delete mode 100644 tests/unit/storage_v2_durability.cpp delete mode 100644 tests/unit/storage_v2_edge.cpp delete mode 100644 tests/unit/storage_v2_gc.cpp delete mode 100644 tests/unit/storage_v2_indices.cpp delete mode 100644 tests/unit/storage_v2_isolation_level.cpp delete mode 100644 tests/unit/storage_v2_name_id_mapper.cpp delete mode 100644 tests/unit/storage_v2_property_store.cpp delete mode 100644 tests/unit/storage_v2_replication.cpp delete mode 100644 tests/unit/storage_v2_wal_file.cpp diff --git a/tests/unit/CMakeLists.txt b/tests/unit/CMakeLists.txt index 52e3a7eef..4a0ee2460 100644 --- a/tests/unit/CMakeLists.txt +++ b/tests/unit/CMakeLists.txt @@ -278,49 +278,6 @@ target_link_libraries(${test_prefix}utils_temporal mg-utils) add_unit_test(utils_histogram.cpp) target_link_libraries(${test_prefix}utils_histogram mg-utils) -# Test mg-storage-v2 -add_unit_test(commit_log_v2.cpp) -target_link_libraries(${test_prefix}commit_log_v2 gflags mg-utils mg-storage-v2) - -add_unit_test(property_value_v2.cpp) -target_link_libraries(${test_prefix}property_value_v2 mg-storage-v2 mg-utils) - -add_unit_test(storage_v2.cpp) -target_link_libraries(${test_prefix}storage_v2 mg-storage-v2 storage_test_utils) - -add_unit_test(storage_v2_constraints.cpp) -target_link_libraries(${test_prefix}storage_v2_constraints mg-storage-v2) - -add_unit_test(storage_v2_decoder_encoder.cpp) -target_link_libraries(${test_prefix}storage_v2_decoder_encoder mg-storage-v2) - -add_unit_test(storage_v2_durability.cpp) -target_link_libraries(${test_prefix}storage_v2_durability mg-storage-v2) - -add_unit_test(storage_v2_edge.cpp) -target_link_libraries(${test_prefix}storage_v2_edge mg-storage-v2) - -add_unit_test(storage_v2_gc.cpp) -target_link_libraries(${test_prefix}storage_v2_gc mg-storage-v2) - -add_unit_test(storage_v2_indices.cpp) -target_link_libraries(${test_prefix}storage_v2_indices mg-storage-v2 mg-utils) - -add_unit_test(storage_v2_name_id_mapper.cpp) -target_link_libraries(${test_prefix}storage_v2_name_id_mapper mg-storage-v2) - -add_unit_test(storage_v2_property_store.cpp) -target_link_libraries(${test_prefix}storage_v2_property_store mg-storage-v2 fmt) - -add_unit_test(storage_v2_wal_file.cpp) -target_link_libraries(${test_prefix}storage_v2_wal_file mg-storage-v2 fmt) - -add_unit_test(storage_v2_replication.cpp) -target_link_libraries(${test_prefix}storage_v2_replication mg-storage-v2 fmt) - -add_unit_test(storage_v2_isolation_level.cpp) -target_link_libraries(${test_prefix}storage_v2_isolation_level mg-storage-v2) - # Test mg-storage-v3 add_library(storage_v3_test_utils storage_v3_test_utils.cpp) target_link_libraries(storage_v3_test_utils mg-storage-v3) diff --git a/tests/unit/commit_log_v2.cpp b/tests/unit/commit_log_v2.cpp deleted file mode 100644 index 5e8413611..000000000 --- a/tests/unit/commit_log_v2.cpp +++ /dev/null @@ -1,81 +0,0 @@ -// Copyright 2022 Memgraph Ltd. -// -// Use of this software is governed by the Business Source License -// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source -// License, and you may not use this file except in compliance with the Business Source License. -// -// As of the Change Date specified in that file, in accordance with -// the Business Source License, use of this software will be governed -// by the Apache License, Version 2.0, included in the file -// licenses/APL.txt. - -#include "storage/v2/commit_log.hpp" - -#include "gtest/gtest.h" - -namespace { -inline constexpr size_t ids_per_block = 8192 * 64; -} // namespace - -TEST(CommitLog, Simple) { - memgraph::storage::CommitLog log; - EXPECT_EQ(log.OldestActive(), 0); - - log.MarkFinished(1); - EXPECT_EQ(log.OldestActive(), 0); - - log.MarkFinished(0); - EXPECT_EQ(log.OldestActive(), 2); -} - -TEST(CommitLog, Fields) { - memgraph::storage::CommitLog log; - - for (uint64_t i = 0; i < 64; ++i) { - log.MarkFinished(i); - EXPECT_EQ(log.OldestActive(), i + 1); - } - - for (uint64_t i = 128; i < 192; ++i) { - log.MarkFinished(i); - EXPECT_EQ(log.OldestActive(), 64); - } - - for (uint64_t i = 64; i < 128; ++i) { - log.MarkFinished(i); - EXPECT_EQ(log.OldestActive(), i < 127 ? i + 1 : 192); - } -} - -TEST(CommitLog, Blocks) { - memgraph::storage::CommitLog log; - - for (uint64_t i = 0; i < ids_per_block; ++i) { - log.MarkFinished(i); - EXPECT_EQ(log.OldestActive(), i + 1); - } - - for (uint64_t i = ids_per_block * 2; i < ids_per_block * 3; ++i) { - log.MarkFinished(i); - EXPECT_EQ(log.OldestActive(), ids_per_block); - } - - for (uint64_t i = ids_per_block; i < ids_per_block; ++i) { - log.MarkFinished(i); - EXPECT_EQ(log.OldestActive(), i < ids_per_block - 1 ? i + 1 : ids_per_block * 3); - } -} - -TEST(CommitLog, TrackAfterInitialId) { - const auto check_marking_ids = [](auto *log, auto current_oldest_active) { - ASSERT_EQ(log->OldestActive(), current_oldest_active); - log->MarkFinished(current_oldest_active); - ++current_oldest_active; - ASSERT_EQ(log->OldestActive(), current_oldest_active); - }; - - for (uint64_t i = 0; i < 2 * ids_per_block; ++i) { - memgraph::storage::CommitLog log{i}; - check_marking_ids(&log, i); - } -} diff --git a/tests/unit/property_value_v2.cpp b/tests/unit/property_value_v2.cpp deleted file mode 100644 index aba322ce7..000000000 --- a/tests/unit/property_value_v2.cpp +++ /dev/null @@ -1,814 +0,0 @@ -// Copyright 2022 Memgraph Ltd. -// -// Use of this software is governed by the Business Source License -// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source -// License, and you may not use this file except in compliance with the Business Source License. -// -// As of the Change Date specified in that file, in accordance with -// the Business Source License, use of this software will be governed -// by the Apache License, Version 2.0, included in the file -// licenses/APL.txt. - -#include - -#include - -#include "storage/v2/property_value.hpp" -#include "storage/v2/temporal.hpp" - -// NOLINTNEXTLINE(hicpp-special-member-functions) -TEST(PropertyValue, Null) { - memgraph::storage::PropertyValue pv; - - ASSERT_EQ(pv.type(), memgraph::storage::PropertyValue::Type::Null); - - ASSERT_TRUE(pv.IsNull()); - ASSERT_FALSE(pv.IsBool()); - ASSERT_FALSE(pv.IsInt()); - ASSERT_FALSE(pv.IsDouble()); - ASSERT_FALSE(pv.IsString()); - ASSERT_FALSE(pv.IsList()); - ASSERT_FALSE(pv.IsMap()); - - ASSERT_THROW(pv.ValueBool(), memgraph::storage::PropertyValueException); - ASSERT_THROW(pv.ValueInt(), memgraph::storage::PropertyValueException); - ASSERT_THROW(pv.ValueDouble(), memgraph::storage::PropertyValueException); - ASSERT_THROW(pv.ValueString(), memgraph::storage::PropertyValueException); - ASSERT_THROW(pv.ValueList(), memgraph::storage::PropertyValueException); - ASSERT_THROW(pv.ValueMap(), memgraph::storage::PropertyValueException); - - const auto &cpv = pv; - - ASSERT_THROW(cpv.ValueBool(), memgraph::storage::PropertyValueException); - ASSERT_THROW(cpv.ValueInt(), memgraph::storage::PropertyValueException); - ASSERT_THROW(cpv.ValueDouble(), memgraph::storage::PropertyValueException); - ASSERT_THROW(cpv.ValueString(), memgraph::storage::PropertyValueException); - ASSERT_THROW(cpv.ValueList(), memgraph::storage::PropertyValueException); - ASSERT_THROW(cpv.ValueMap(), memgraph::storage::PropertyValueException); - - { - std::stringstream ss; - ss << pv.type(); - ASSERT_EQ(ss.str(), "null"); - } - { - std::stringstream ss; - ss << pv; - ASSERT_EQ(ss.str(), "null"); - } -} - -// NOLINTNEXTLINE(hicpp-special-member-functions) -TEST(PropertyValue, Bool) { - memgraph::storage::PropertyValue pv(false); - - ASSERT_EQ(pv.type(), memgraph::storage::PropertyValue::Type::Bool); - - ASSERT_FALSE(pv.IsNull()); - ASSERT_TRUE(pv.IsBool()); - ASSERT_FALSE(pv.IsInt()); - ASSERT_FALSE(pv.IsDouble()); - ASSERT_FALSE(pv.IsString()); - ASSERT_FALSE(pv.IsList()); - ASSERT_FALSE(pv.IsMap()); - - ASSERT_EQ(pv.ValueBool(), false); - ASSERT_THROW(pv.ValueInt(), memgraph::storage::PropertyValueException); - ASSERT_THROW(pv.ValueDouble(), memgraph::storage::PropertyValueException); - ASSERT_THROW(pv.ValueString(), memgraph::storage::PropertyValueException); - ASSERT_THROW(pv.ValueList(), memgraph::storage::PropertyValueException); - ASSERT_THROW(pv.ValueMap(), memgraph::storage::PropertyValueException); - - const auto &cpv = pv; - - ASSERT_EQ(cpv.ValueBool(), false); - ASSERT_THROW(cpv.ValueInt(), memgraph::storage::PropertyValueException); - ASSERT_THROW(cpv.ValueDouble(), memgraph::storage::PropertyValueException); - ASSERT_THROW(cpv.ValueString(), memgraph::storage::PropertyValueException); - ASSERT_THROW(cpv.ValueList(), memgraph::storage::PropertyValueException); - ASSERT_THROW(cpv.ValueMap(), memgraph::storage::PropertyValueException); - - { - std::stringstream ss; - ss << pv.type(); - ASSERT_EQ(ss.str(), "bool"); - } - { - std::stringstream ss; - ss << pv; - ASSERT_EQ(ss.str(), "false"); - } - { - memgraph::storage::PropertyValue pvtrue(true); - std::stringstream ss; - ss << pvtrue; - ASSERT_EQ(ss.str(), "true"); - } -} - -// NOLINTNEXTLINE(hicpp-special-member-functions) -TEST(PropertyValue, Int) { - memgraph::storage::PropertyValue pv(123L); - - ASSERT_EQ(pv.type(), memgraph::storage::PropertyValue::Type::Int); - - ASSERT_FALSE(pv.IsNull()); - ASSERT_FALSE(pv.IsBool()); - ASSERT_TRUE(pv.IsInt()); - ASSERT_FALSE(pv.IsDouble()); - ASSERT_FALSE(pv.IsString()); - ASSERT_FALSE(pv.IsList()); - ASSERT_FALSE(pv.IsMap()); - - ASSERT_THROW(pv.ValueBool(), memgraph::storage::PropertyValueException); - ASSERT_EQ(pv.ValueInt(), 123L); - ASSERT_THROW(pv.ValueDouble(), memgraph::storage::PropertyValueException); - ASSERT_THROW(pv.ValueString(), memgraph::storage::PropertyValueException); - ASSERT_THROW(pv.ValueList(), memgraph::storage::PropertyValueException); - ASSERT_THROW(pv.ValueMap(), memgraph::storage::PropertyValueException); - - const auto &cpv = pv; - - ASSERT_THROW(cpv.ValueBool(), memgraph::storage::PropertyValueException); - ASSERT_EQ(cpv.ValueInt(), 123L); - ASSERT_THROW(cpv.ValueDouble(), memgraph::storage::PropertyValueException); - ASSERT_THROW(cpv.ValueString(), memgraph::storage::PropertyValueException); - ASSERT_THROW(cpv.ValueList(), memgraph::storage::PropertyValueException); - ASSERT_THROW(cpv.ValueMap(), memgraph::storage::PropertyValueException); - - { - std::stringstream ss; - ss << pv.type(); - ASSERT_EQ(ss.str(), "int"); - } - { - std::stringstream ss; - ss << pv; - ASSERT_EQ(ss.str(), "123"); - } - - { - memgraph::storage::PropertyValue pvint(123); - ASSERT_EQ(pvint.type(), memgraph::storage::PropertyValue::Type::Int); - } -} - -// NOLINTNEXTLINE(hicpp-special-member-functions) -TEST(PropertyValue, Double) { - memgraph::storage::PropertyValue pv(123.5); - - ASSERT_EQ(pv.type(), memgraph::storage::PropertyValue::Type::Double); - - ASSERT_FALSE(pv.IsNull()); - ASSERT_FALSE(pv.IsBool()); - ASSERT_FALSE(pv.IsInt()); - ASSERT_TRUE(pv.IsDouble()); - ASSERT_FALSE(pv.IsString()); - ASSERT_FALSE(pv.IsList()); - ASSERT_FALSE(pv.IsMap()); - - ASSERT_THROW(pv.ValueBool(), memgraph::storage::PropertyValueException); - ASSERT_THROW(pv.ValueInt(), memgraph::storage::PropertyValueException); - ASSERT_EQ(pv.ValueDouble(), 123.5); - ASSERT_THROW(pv.ValueString(), memgraph::storage::PropertyValueException); - ASSERT_THROW(pv.ValueList(), memgraph::storage::PropertyValueException); - ASSERT_THROW(pv.ValueMap(), memgraph::storage::PropertyValueException); - - const auto &cpv = pv; - - ASSERT_THROW(cpv.ValueBool(), memgraph::storage::PropertyValueException); - ASSERT_THROW(cpv.ValueInt(), memgraph::storage::PropertyValueException); - ASSERT_EQ(cpv.ValueDouble(), 123.5); - ASSERT_THROW(cpv.ValueString(), memgraph::storage::PropertyValueException); - ASSERT_THROW(cpv.ValueList(), memgraph::storage::PropertyValueException); - ASSERT_THROW(cpv.ValueMap(), memgraph::storage::PropertyValueException); - - { - std::stringstream ss; - ss << pv.type(); - ASSERT_EQ(ss.str(), "double"); - } - { - std::stringstream ss; - ss << pv; - ASSERT_EQ(ss.str(), "123.5"); - } -} - -// NOLINTNEXTLINE(hicpp-special-member-functions) -TEST(PropertyValue, StringCopy) { - std::string str("nandare"); - memgraph::storage::PropertyValue pv(str); - - ASSERT_EQ(str, "nandare"); - - ASSERT_EQ(pv.type(), memgraph::storage::PropertyValue::Type::String); - - ASSERT_FALSE(pv.IsNull()); - ASSERT_FALSE(pv.IsBool()); - ASSERT_FALSE(pv.IsInt()); - ASSERT_FALSE(pv.IsDouble()); - ASSERT_TRUE(pv.IsString()); - ASSERT_FALSE(pv.IsList()); - ASSERT_FALSE(pv.IsMap()); - - ASSERT_THROW(pv.ValueBool(), memgraph::storage::PropertyValueException); - ASSERT_THROW(pv.ValueInt(), memgraph::storage::PropertyValueException); - ASSERT_THROW(pv.ValueDouble(), memgraph::storage::PropertyValueException); - ASSERT_EQ(pv.ValueString(), "nandare"); - ASSERT_THROW(pv.ValueList(), memgraph::storage::PropertyValueException); - ASSERT_THROW(pv.ValueMap(), memgraph::storage::PropertyValueException); - - const auto &cpv = pv; - - ASSERT_THROW(cpv.ValueBool(), memgraph::storage::PropertyValueException); - ASSERT_THROW(cpv.ValueInt(), memgraph::storage::PropertyValueException); - ASSERT_THROW(cpv.ValueDouble(), memgraph::storage::PropertyValueException); - ASSERT_EQ(cpv.ValueString(), "nandare"); - ASSERT_THROW(cpv.ValueList(), memgraph::storage::PropertyValueException); - ASSERT_THROW(cpv.ValueMap(), memgraph::storage::PropertyValueException); - - { - std::stringstream ss; - ss << pv.type(); - ASSERT_EQ(ss.str(), "string"); - } - { - std::stringstream ss; - ss << pv; - ASSERT_EQ(ss.str(), "nandare"); - } -} - -// NOLINTNEXTLINE(hicpp-special-member-functions) -TEST(PropertyValue, StringMove) { - std::string str("nandare"); - memgraph::storage::PropertyValue pv(std::move(str)); - - ASSERT_EQ(str, ""); - - ASSERT_EQ(pv.type(), memgraph::storage::PropertyValue::Type::String); - - ASSERT_FALSE(pv.IsNull()); - ASSERT_FALSE(pv.IsBool()); - ASSERT_FALSE(pv.IsInt()); - ASSERT_FALSE(pv.IsDouble()); - ASSERT_TRUE(pv.IsString()); - ASSERT_FALSE(pv.IsList()); - ASSERT_FALSE(pv.IsMap()); - - ASSERT_THROW(pv.ValueBool(), memgraph::storage::PropertyValueException); - ASSERT_THROW(pv.ValueInt(), memgraph::storage::PropertyValueException); - ASSERT_THROW(pv.ValueDouble(), memgraph::storage::PropertyValueException); - ASSERT_EQ(pv.ValueString(), "nandare"); - ASSERT_THROW(pv.ValueList(), memgraph::storage::PropertyValueException); - ASSERT_THROW(pv.ValueMap(), memgraph::storage::PropertyValueException); - - const auto &cpv = pv; - - ASSERT_THROW(cpv.ValueBool(), memgraph::storage::PropertyValueException); - ASSERT_THROW(cpv.ValueInt(), memgraph::storage::PropertyValueException); - ASSERT_THROW(cpv.ValueDouble(), memgraph::storage::PropertyValueException); - ASSERT_EQ(cpv.ValueString(), "nandare"); - ASSERT_THROW(cpv.ValueList(), memgraph::storage::PropertyValueException); - ASSERT_THROW(cpv.ValueMap(), memgraph::storage::PropertyValueException); - - { - std::stringstream ss; - ss << pv.type(); - ASSERT_EQ(ss.str(), "string"); - } - { - std::stringstream ss; - ss << pv; - ASSERT_EQ(ss.str(), "nandare"); - } -} - -// NOLINTNEXTLINE(hicpp-special-member-functions) -TEST(PropertyValue, ListCopy) { - std::vector vec{memgraph::storage::PropertyValue("nandare"), - memgraph::storage::PropertyValue(123)}; - memgraph::storage::PropertyValue pv(vec); - - ASSERT_EQ(vec.size(), 2); - ASSERT_EQ(vec[0].ValueString(), "nandare"); - ASSERT_EQ(vec[1].ValueInt(), 123); - - ASSERT_EQ(pv.type(), memgraph::storage::PropertyValue::Type::List); - - ASSERT_FALSE(pv.IsNull()); - ASSERT_FALSE(pv.IsBool()); - ASSERT_FALSE(pv.IsInt()); - ASSERT_FALSE(pv.IsDouble()); - ASSERT_FALSE(pv.IsString()); - ASSERT_TRUE(pv.IsList()); - ASSERT_FALSE(pv.IsMap()); - - ASSERT_THROW(pv.ValueBool(), memgraph::storage::PropertyValueException); - ASSERT_THROW(pv.ValueInt(), memgraph::storage::PropertyValueException); - ASSERT_THROW(pv.ValueDouble(), memgraph::storage::PropertyValueException); - ASSERT_THROW(pv.ValueString(), memgraph::storage::PropertyValueException); - { - const auto &ret = pv.ValueList(); - ASSERT_EQ(ret.size(), 2); - ASSERT_EQ(ret[0].ValueString(), "nandare"); - ASSERT_EQ(ret[1].ValueInt(), 123); - } - ASSERT_THROW(pv.ValueMap(), memgraph::storage::PropertyValueException); - - const auto &cpv = pv; - - ASSERT_THROW(cpv.ValueBool(), memgraph::storage::PropertyValueException); - ASSERT_THROW(cpv.ValueInt(), memgraph::storage::PropertyValueException); - ASSERT_THROW(cpv.ValueDouble(), memgraph::storage::PropertyValueException); - ASSERT_THROW(cpv.ValueString(), memgraph::storage::PropertyValueException); - { - const auto &ret = cpv.ValueList(); - ASSERT_EQ(ret.size(), 2); - ASSERT_EQ(ret[0].ValueString(), "nandare"); - ASSERT_EQ(ret[1].ValueInt(), 123); - } - ASSERT_THROW(cpv.ValueMap(), memgraph::storage::PropertyValueException); - - { - std::stringstream ss; - ss << pv.type(); - ASSERT_EQ(ss.str(), "list"); - } - { - std::stringstream ss; - ss << pv; - ASSERT_EQ(ss.str(), "[nandare, 123]"); - } -} - -// NOLINTNEXTLINE(hicpp-special-member-functions) -TEST(PropertyValue, ListMove) { - std::vector vec{memgraph::storage::PropertyValue("nandare"), - memgraph::storage::PropertyValue(123)}; - memgraph::storage::PropertyValue pv(std::move(vec)); - - ASSERT_EQ(vec.size(), 0); - - ASSERT_EQ(pv.type(), memgraph::storage::PropertyValue::Type::List); - - ASSERT_FALSE(pv.IsNull()); - ASSERT_FALSE(pv.IsBool()); - ASSERT_FALSE(pv.IsInt()); - ASSERT_FALSE(pv.IsDouble()); - ASSERT_FALSE(pv.IsString()); - ASSERT_TRUE(pv.IsList()); - ASSERT_FALSE(pv.IsMap()); - - ASSERT_THROW(pv.ValueBool(), memgraph::storage::PropertyValueException); - ASSERT_THROW(pv.ValueInt(), memgraph::storage::PropertyValueException); - ASSERT_THROW(pv.ValueDouble(), memgraph::storage::PropertyValueException); - ASSERT_THROW(pv.ValueString(), memgraph::storage::PropertyValueException); - { - const auto &ret = pv.ValueList(); - ASSERT_EQ(ret.size(), 2); - ASSERT_EQ(ret[0].ValueString(), "nandare"); - ASSERT_EQ(ret[1].ValueInt(), 123); - } - ASSERT_THROW(pv.ValueMap(), memgraph::storage::PropertyValueException); - - const auto &cpv = pv; - - ASSERT_THROW(cpv.ValueBool(), memgraph::storage::PropertyValueException); - ASSERT_THROW(cpv.ValueInt(), memgraph::storage::PropertyValueException); - ASSERT_THROW(cpv.ValueDouble(), memgraph::storage::PropertyValueException); - ASSERT_THROW(cpv.ValueString(), memgraph::storage::PropertyValueException); - { - const auto &ret = cpv.ValueList(); - ASSERT_EQ(ret.size(), 2); - ASSERT_EQ(ret[0].ValueString(), "nandare"); - ASSERT_EQ(ret[1].ValueInt(), 123); - } - ASSERT_THROW(cpv.ValueMap(), memgraph::storage::PropertyValueException); - - { - std::stringstream ss; - ss << pv.type(); - ASSERT_EQ(ss.str(), "list"); - } - { - std::stringstream ss; - ss << pv; - ASSERT_EQ(ss.str(), "[nandare, 123]"); - } -} - -// NOLINTNEXTLINE(hicpp-special-member-functions) -TEST(PropertyValue, MapCopy) { - std::map map{{"nandare", memgraph::storage::PropertyValue(123)}}; - memgraph::storage::PropertyValue pv(map); - - ASSERT_EQ(map.size(), 1); - ASSERT_EQ(map.at("nandare").ValueInt(), 123); - - ASSERT_EQ(pv.type(), memgraph::storage::PropertyValue::Type::Map); - - ASSERT_FALSE(pv.IsNull()); - ASSERT_FALSE(pv.IsBool()); - ASSERT_FALSE(pv.IsInt()); - ASSERT_FALSE(pv.IsDouble()); - ASSERT_FALSE(pv.IsString()); - ASSERT_FALSE(pv.IsList()); - ASSERT_TRUE(pv.IsMap()); - - ASSERT_THROW(pv.ValueBool(), memgraph::storage::PropertyValueException); - ASSERT_THROW(pv.ValueInt(), memgraph::storage::PropertyValueException); - ASSERT_THROW(pv.ValueDouble(), memgraph::storage::PropertyValueException); - ASSERT_THROW(pv.ValueString(), memgraph::storage::PropertyValueException); - ASSERT_THROW(pv.ValueList(), memgraph::storage::PropertyValueException); - { - const auto &ret = pv.ValueMap(); - ASSERT_EQ(ret.size(), 1); - ASSERT_EQ(ret.at("nandare").ValueInt(), 123); - } - - const auto &cpv = pv; - - ASSERT_THROW(cpv.ValueBool(), memgraph::storage::PropertyValueException); - ASSERT_THROW(cpv.ValueInt(), memgraph::storage::PropertyValueException); - ASSERT_THROW(cpv.ValueDouble(), memgraph::storage::PropertyValueException); - ASSERT_THROW(cpv.ValueString(), memgraph::storage::PropertyValueException); - ASSERT_THROW(cpv.ValueList(), memgraph::storage::PropertyValueException); - { - const auto &ret = cpv.ValueMap(); - ASSERT_EQ(ret.size(), 1); - ASSERT_EQ(ret.at("nandare").ValueInt(), 123); - } - - { - std::stringstream ss; - ss << pv.type(); - ASSERT_EQ(ss.str(), "map"); - } - { - std::stringstream ss; - ss << pv; - ASSERT_EQ(ss.str(), "{nandare: 123}"); - } -} - -// NOLINTNEXTLINE(hicpp-special-member-functions) -TEST(PropertyValue, MapMove) { - std::map map{{"nandare", memgraph::storage::PropertyValue(123)}}; - memgraph::storage::PropertyValue pv(std::move(map)); - - ASSERT_EQ(map.size(), 0); - - ASSERT_EQ(pv.type(), memgraph::storage::PropertyValue::Type::Map); - - ASSERT_FALSE(pv.IsNull()); - ASSERT_FALSE(pv.IsBool()); - ASSERT_FALSE(pv.IsInt()); - ASSERT_FALSE(pv.IsDouble()); - ASSERT_FALSE(pv.IsString()); - ASSERT_FALSE(pv.IsList()); - ASSERT_TRUE(pv.IsMap()); - - ASSERT_THROW(pv.ValueBool(), memgraph::storage::PropertyValueException); - ASSERT_THROW(pv.ValueInt(), memgraph::storage::PropertyValueException); - ASSERT_THROW(pv.ValueDouble(), memgraph::storage::PropertyValueException); - ASSERT_THROW(pv.ValueString(), memgraph::storage::PropertyValueException); - ASSERT_THROW(pv.ValueList(), memgraph::storage::PropertyValueException); - { - const auto &ret = pv.ValueMap(); - ASSERT_EQ(ret.size(), 1); - ASSERT_EQ(ret.at("nandare").ValueInt(), 123); - } - - const auto &cpv = pv; - - ASSERT_THROW(cpv.ValueBool(), memgraph::storage::PropertyValueException); - ASSERT_THROW(cpv.ValueInt(), memgraph::storage::PropertyValueException); - ASSERT_THROW(cpv.ValueDouble(), memgraph::storage::PropertyValueException); - ASSERT_THROW(cpv.ValueString(), memgraph::storage::PropertyValueException); - ASSERT_THROW(cpv.ValueList(), memgraph::storage::PropertyValueException); - { - const auto &ret = cpv.ValueMap(); - ASSERT_EQ(ret.size(), 1); - ASSERT_EQ(ret.at("nandare").ValueInt(), 123); - } - - { - std::stringstream ss; - ss << pv.type(); - ASSERT_EQ(ss.str(), "map"); - } - { - std::stringstream ss; - ss << pv; - ASSERT_EQ(ss.str(), "{nandare: 123}"); - } -} - -// NOLINTNEXTLINE(hicpp-special-member-functions) -TEST(PropertyValue, CopyConstructor) { - std::vector vec{memgraph::storage::PropertyValue(true), - memgraph::storage::PropertyValue(123)}; - std::map map{{"nandare", memgraph::storage::PropertyValue(false)}}; - std::vector data{ - memgraph::storage::PropertyValue(), - memgraph::storage::PropertyValue(true), - memgraph::storage::PropertyValue(123), - memgraph::storage::PropertyValue(123.5), - memgraph::storage::PropertyValue("nandare"), - memgraph::storage::PropertyValue(vec), - memgraph::storage::PropertyValue(map), - memgraph::storage::PropertyValue(memgraph::storage::TemporalData(memgraph::storage::TemporalType::Date, 23))}; - - for (const auto &item : data) { - memgraph::storage::PropertyValue pv(item); - ASSERT_EQ(pv.type(), item.type()); - switch (item.type()) { - case memgraph::storage::PropertyValue::Type::Null: - ASSERT_TRUE(pv.IsNull()); - break; - case memgraph::storage::PropertyValue::Type::Bool: - ASSERT_EQ(pv.ValueBool(), item.ValueBool()); - break; - case memgraph::storage::PropertyValue::Type::Int: - ASSERT_EQ(pv.ValueInt(), item.ValueInt()); - break; - case memgraph::storage::PropertyValue::Type::Double: - ASSERT_EQ(pv.ValueDouble(), item.ValueDouble()); - break; - case memgraph::storage::PropertyValue::Type::String: - ASSERT_EQ(pv.ValueString(), item.ValueString()); - break; - case memgraph::storage::PropertyValue::Type::List: - ASSERT_EQ(pv.ValueList(), item.ValueList()); - break; - case memgraph::storage::PropertyValue::Type::Map: - ASSERT_EQ(pv.ValueMap(), item.ValueMap()); - break; - case memgraph::storage::PropertyValue::Type::TemporalData: - ASSERT_EQ(pv.ValueTemporalData(), item.ValueTemporalData()); - } - } -} - -// NOLINTNEXTLINE(hicpp-special-member-functions) -TEST(PropertyValue, MoveConstructor) { - std::vector vec{memgraph::storage::PropertyValue(true), - memgraph::storage::PropertyValue(123)}; - std::map map{{"nandare", memgraph::storage::PropertyValue(false)}}; - std::vector data{ - memgraph::storage::PropertyValue(), - memgraph::storage::PropertyValue(true), - memgraph::storage::PropertyValue(123), - memgraph::storage::PropertyValue(123.5), - memgraph::storage::PropertyValue("nandare"), - memgraph::storage::PropertyValue(vec), - memgraph::storage::PropertyValue(map), - memgraph::storage::PropertyValue(memgraph::storage::TemporalData(memgraph::storage::TemporalType::Date, 23))}; - - for (auto &item : data) { - memgraph::storage::PropertyValue copy(item); - memgraph::storage::PropertyValue pv(std::move(item)); - ASSERT_EQ(item.type(), memgraph::storage::PropertyValue::Type::Null); - ASSERT_EQ(pv.type(), copy.type()); - switch (copy.type()) { - case memgraph::storage::PropertyValue::Type::Null: - ASSERT_TRUE(pv.IsNull()); - break; - case memgraph::storage::PropertyValue::Type::Bool: - ASSERT_EQ(pv.ValueBool(), copy.ValueBool()); - break; - case memgraph::storage::PropertyValue::Type::Int: - ASSERT_EQ(pv.ValueInt(), copy.ValueInt()); - break; - case memgraph::storage::PropertyValue::Type::Double: - ASSERT_EQ(pv.ValueDouble(), copy.ValueDouble()); - break; - case memgraph::storage::PropertyValue::Type::String: - ASSERT_EQ(pv.ValueString(), copy.ValueString()); - break; - case memgraph::storage::PropertyValue::Type::List: - ASSERT_EQ(pv.ValueList(), copy.ValueList()); - break; - case memgraph::storage::PropertyValue::Type::Map: - ASSERT_EQ(pv.ValueMap(), copy.ValueMap()); - break; - case memgraph::storage::PropertyValue::Type::TemporalData: - ASSERT_EQ(pv.ValueTemporalData(), copy.ValueTemporalData()); - break; - } - } -} - -// NOLINTNEXTLINE(hicpp-special-member-functions) -TEST(PropertyValue, CopyAssignment) { - std::vector vec{memgraph::storage::PropertyValue(true), - memgraph::storage::PropertyValue(123)}; - std::map map{{"nandare", memgraph::storage::PropertyValue(false)}}; - std::vector data{ - memgraph::storage::PropertyValue(), - memgraph::storage::PropertyValue(true), - memgraph::storage::PropertyValue(123), - memgraph::storage::PropertyValue(123.5), - memgraph::storage::PropertyValue("nandare"), - memgraph::storage::PropertyValue(vec), - memgraph::storage::PropertyValue(map), - memgraph::storage::PropertyValue(memgraph::storage::TemporalData(memgraph::storage::TemporalType::Date, 23))}; - - for (const auto &item : data) { - memgraph::storage::PropertyValue pv(123); - pv = item; - ASSERT_EQ(pv.type(), item.type()); - switch (item.type()) { - case memgraph::storage::PropertyValue::Type::Null: - ASSERT_TRUE(pv.IsNull()); - break; - case memgraph::storage::PropertyValue::Type::Bool: - ASSERT_EQ(pv.ValueBool(), item.ValueBool()); - break; - case memgraph::storage::PropertyValue::Type::Int: - ASSERT_EQ(pv.ValueInt(), item.ValueInt()); - break; - case memgraph::storage::PropertyValue::Type::Double: - ASSERT_EQ(pv.ValueDouble(), item.ValueDouble()); - break; - case memgraph::storage::PropertyValue::Type::String: - ASSERT_EQ(pv.ValueString(), item.ValueString()); - break; - case memgraph::storage::PropertyValue::Type::List: - ASSERT_EQ(pv.ValueList(), item.ValueList()); - break; - case memgraph::storage::PropertyValue::Type::Map: - ASSERT_EQ(pv.ValueMap(), item.ValueMap()); - break; - case memgraph::storage::PropertyValue::Type::TemporalData: - ASSERT_EQ(pv.ValueTemporalData(), item.ValueTemporalData()); - break; - } - } -} - -// NOLINTNEXTLINE(hicpp-special-member-functions) -TEST(PropertyValue, MoveAssignment) { - std::vector vec{memgraph::storage::PropertyValue(true), - memgraph::storage::PropertyValue(123)}; - std::map map{{"nandare", memgraph::storage::PropertyValue(false)}}; - std::vector data{ - memgraph::storage::PropertyValue(), - memgraph::storage::PropertyValue(true), - memgraph::storage::PropertyValue(123), - memgraph::storage::PropertyValue(123.5), - memgraph::storage::PropertyValue("nandare"), - memgraph::storage::PropertyValue(vec), - memgraph::storage::PropertyValue(map), - memgraph::storage::PropertyValue(memgraph::storage::TemporalData(memgraph::storage::TemporalType::Date, 23))}; - - for (auto &item : data) { - memgraph::storage::PropertyValue copy(item); - memgraph::storage::PropertyValue pv(123); - pv = std::move(item); - ASSERT_EQ(item.type(), memgraph::storage::PropertyValue::Type::Null); - ASSERT_EQ(pv.type(), copy.type()); - switch (copy.type()) { - case memgraph::storage::PropertyValue::Type::Null: - ASSERT_TRUE(pv.IsNull()); - break; - case memgraph::storage::PropertyValue::Type::Bool: - ASSERT_EQ(pv.ValueBool(), copy.ValueBool()); - break; - case memgraph::storage::PropertyValue::Type::Int: - ASSERT_EQ(pv.ValueInt(), copy.ValueInt()); - break; - case memgraph::storage::PropertyValue::Type::Double: - ASSERT_EQ(pv.ValueDouble(), copy.ValueDouble()); - break; - case memgraph::storage::PropertyValue::Type::String: - ASSERT_EQ(pv.ValueString(), copy.ValueString()); - break; - case memgraph::storage::PropertyValue::Type::List: - ASSERT_EQ(pv.ValueList(), copy.ValueList()); - break; - case memgraph::storage::PropertyValue::Type::Map: - ASSERT_EQ(pv.ValueMap(), copy.ValueMap()); - break; - case memgraph::storage::PropertyValue::Type::TemporalData: - ASSERT_EQ(pv.ValueTemporalData(), copy.ValueTemporalData()); - break; - } - } -} - -// NOLINTNEXTLINE(hicpp-special-member-functions) -TEST(PropertyValue, CopyAssignmentSelf) { - memgraph::storage::PropertyValue pv("nandare"); -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wself-assign-overloaded" - pv = pv; -#pragma clang diagnostic pop - ASSERT_EQ(pv.type(), memgraph::storage::PropertyValue::Type::String); - ASSERT_EQ(pv.ValueString(), "nandare"); -} - -// NOLINTNEXTLINE(hicpp-special-member-functions) -TEST(PropertyValue, MoveAssignmentSelf) { - memgraph::storage::PropertyValue pv("nandare"); -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wself-move" - pv = std::move(pv); -#pragma clang diagnostic pop - ASSERT_EQ(pv.type(), memgraph::storage::PropertyValue::Type::String); - ASSERT_EQ(pv.ValueString(), "nandare"); -} - -// NOLINTNEXTLINE(hicpp-special-member-functions) -TEST(PropertyValue, Equal) { - std::vector vec{memgraph::storage::PropertyValue(true), - memgraph::storage::PropertyValue(123)}; - std::map map{{"nandare", memgraph::storage::PropertyValue(false)}}; - std::vector data{ - memgraph::storage::PropertyValue(), memgraph::storage::PropertyValue(true), - memgraph::storage::PropertyValue(123), memgraph::storage::PropertyValue(123.5), - memgraph::storage::PropertyValue("nandare"), memgraph::storage::PropertyValue(vec), - memgraph::storage::PropertyValue(map)}; - for (const auto &item1 : data) { - for (const auto &item2 : data) { - if (item1.type() == item2.type()) { - ASSERT_TRUE(item1 == item2); - } else { - ASSERT_FALSE(item1 == item2); - } - } - } -} - -// NOLINTNEXTLINE(hicpp-special-member-functions) -TEST(PropertyValue, Less) { - std::vector vec{memgraph::storage::PropertyValue(true), - memgraph::storage::PropertyValue(123)}; - std::map map{{"nandare", memgraph::storage::PropertyValue(false)}}; - std::vector data{ - memgraph::storage::PropertyValue(), memgraph::storage::PropertyValue(true), - memgraph::storage::PropertyValue(123), memgraph::storage::PropertyValue(123.5), - memgraph::storage::PropertyValue("nandare"), memgraph::storage::PropertyValue(vec), - memgraph::storage::PropertyValue(map)}; - for (size_t i = 0; i < data.size(); ++i) { - for (size_t j = 0; j < data.size(); ++j) { - auto item1 = data[i]; - auto item2 = data[j]; - if (i < j) { - ASSERT_TRUE(item1 < item2); - } else { - ASSERT_FALSE(item1 < item2); - } - } - } -} - -TEST(PropertyValue, NumeralTypesComparison) { - auto v_int = memgraph::storage::PropertyValue(2); - auto v_double = memgraph::storage::PropertyValue(2.0); - ASSERT_TRUE(v_int.IsInt()); - ASSERT_TRUE(v_double.IsDouble()); - ASSERT_TRUE(v_int == v_double); - ASSERT_FALSE(v_int < v_double); - ASSERT_FALSE(v_double < v_int); -} - -TEST(PropertyValue, NestedNumeralTypesComparison) { - auto v1 = memgraph::storage::PropertyValue( - std::vector{memgraph::storage::PropertyValue(1)}); - auto v2 = memgraph::storage::PropertyValue( - std::vector{memgraph::storage::PropertyValue(1.5)}); - auto v3 = memgraph::storage::PropertyValue( - std::vector{memgraph::storage::PropertyValue(2)}); - - auto v1alt = memgraph::storage::PropertyValue( - std::vector{memgraph::storage::PropertyValue(1.0)}); - auto v3alt = memgraph::storage::PropertyValue( - std::vector{memgraph::storage::PropertyValue(2.0)}); - - ASSERT_TRUE(v1 == v1alt); - ASSERT_TRUE(v3 == v3alt); - - ASSERT_FALSE(v1 == v2); - ASSERT_FALSE(v2 == v1); - ASSERT_FALSE(v2 == v3); - ASSERT_FALSE(v3 == v2); - ASSERT_FALSE(v1 == v3); - ASSERT_FALSE(v3 == v1); - - ASSERT_TRUE(v1 < v2); - ASSERT_TRUE(v2 < v3); - ASSERT_TRUE(v1 < v3); - ASSERT_FALSE(v2 < v1); - ASSERT_FALSE(v3 < v2); - ASSERT_FALSE(v3 < v1); - - ASSERT_TRUE(v1alt < v2); - ASSERT_TRUE(v2 < v3alt); - ASSERT_TRUE(v1alt < v3alt); - ASSERT_FALSE(v2 < v1alt); - ASSERT_FALSE(v3alt < v2); - ASSERT_FALSE(v3 < v1alt); -} diff --git a/tests/unit/storage_v2.cpp b/tests/unit/storage_v2.cpp deleted file mode 100644 index b268ca8f8..000000000 --- a/tests/unit/storage_v2.cpp +++ /dev/null @@ -1,2595 +0,0 @@ -// Copyright 2022 Memgraph Ltd. -// -// Use of this software is governed by the Business Source License -// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source -// License, and you may not use this file except in compliance with the Business Source License. -// -// As of the Change Date specified in that file, in accordance with -// the Business Source License, use of this software will be governed -// by the Apache License, Version 2.0, included in the file -// licenses/APL.txt. - -#include -#include - -#include - -#include "storage/v2/property_value.hpp" -#include "storage/v2/storage.hpp" -#include "storage/v2/vertex_accessor.hpp" -#include "storage_test_utils.hpp" - -using testing::UnorderedElementsAre; - -// NOLINTNEXTLINE(hicpp-special-member-functions) -TEST(StorageV2, Commit) { - memgraph::storage::Storage store; - memgraph::storage::Gid gid = memgraph::storage::Gid::FromUint(std::numeric_limits::max()); - { - auto acc = store.Access(); - auto vertex = acc.CreateVertex(); - gid = vertex.Gid(); - ASSERT_FALSE(acc.FindVertex(gid, memgraph::storage::View::OLD).has_value()); - EXPECT_EQ(CountVertices(acc, memgraph::storage::View::OLD), 0U); - ASSERT_TRUE(acc.FindVertex(gid, memgraph::storage::View::NEW).has_value()); - EXPECT_EQ(CountVertices(acc, memgraph::storage::View::NEW), 1U); - ASSERT_FALSE(acc.Commit().HasError()); - } - { - auto acc = store.Access(); - ASSERT_TRUE(acc.FindVertex(gid, memgraph::storage::View::OLD).has_value()); - EXPECT_EQ(CountVertices(acc, memgraph::storage::View::OLD), 1U); - ASSERT_TRUE(acc.FindVertex(gid, memgraph::storage::View::NEW).has_value()); - EXPECT_EQ(CountVertices(acc, memgraph::storage::View::NEW), 1U); - acc.Abort(); - } - { - auto acc = store.Access(); - auto vertex = acc.FindVertex(gid, memgraph::storage::View::NEW); - ASSERT_TRUE(vertex); - - auto res = acc.DeleteVertex(&*vertex); - ASSERT_FALSE(res.HasError()); - EXPECT_EQ(CountVertices(acc, memgraph::storage::View::OLD), 1U); - EXPECT_EQ(CountVertices(acc, memgraph::storage::View::NEW), 0U); - - acc.AdvanceCommand(); - EXPECT_EQ(CountVertices(acc, memgraph::storage::View::OLD), 0U); - EXPECT_EQ(CountVertices(acc, memgraph::storage::View::NEW), 0U); - - ASSERT_FALSE(acc.Commit().HasError()); - } - { - auto acc = store.Access(); - ASSERT_FALSE(acc.FindVertex(gid, memgraph::storage::View::OLD).has_value()); - EXPECT_EQ(CountVertices(acc, memgraph::storage::View::OLD), 0U); - ASSERT_FALSE(acc.FindVertex(gid, memgraph::storage::View::NEW).has_value()); - EXPECT_EQ(CountVertices(acc, memgraph::storage::View::NEW), 0U); - acc.Abort(); - } -} - -// NOLINTNEXTLINE(hicpp-special-member-functions) -TEST(StorageV2, Abort) { - memgraph::storage::Storage store; - memgraph::storage::Gid gid = memgraph::storage::Gid::FromUint(std::numeric_limits::max()); - { - auto acc = store.Access(); - auto vertex = acc.CreateVertex(); - gid = vertex.Gid(); - ASSERT_FALSE(acc.FindVertex(gid, memgraph::storage::View::OLD).has_value()); - EXPECT_EQ(CountVertices(acc, memgraph::storage::View::OLD), 0U); - ASSERT_TRUE(acc.FindVertex(gid, memgraph::storage::View::NEW).has_value()); - EXPECT_EQ(CountVertices(acc, memgraph::storage::View::NEW), 1U); - acc.Abort(); - } - { - auto acc = store.Access(); - ASSERT_FALSE(acc.FindVertex(gid, memgraph::storage::View::OLD).has_value()); - EXPECT_EQ(CountVertices(acc, memgraph::storage::View::OLD), 0U); - ASSERT_FALSE(acc.FindVertex(gid, memgraph::storage::View::NEW).has_value()); - EXPECT_EQ(CountVertices(acc, memgraph::storage::View::NEW), 0U); - acc.Abort(); - } -} - -// NOLINTNEXTLINE(hicpp-special-member-functions) -TEST(StorageV2, AdvanceCommandCommit) { - memgraph::storage::Storage store; - memgraph::storage::Gid gid1 = memgraph::storage::Gid::FromUint(std::numeric_limits::max()); - memgraph::storage::Gid gid2 = memgraph::storage::Gid::FromUint(std::numeric_limits::max()); - { - auto acc = store.Access(); - - auto vertex1 = acc.CreateVertex(); - gid1 = vertex1.Gid(); - ASSERT_FALSE(acc.FindVertex(gid1, memgraph::storage::View::OLD).has_value()); - EXPECT_EQ(CountVertices(acc, memgraph::storage::View::OLD), 0U); - ASSERT_TRUE(acc.FindVertex(gid1, memgraph::storage::View::NEW).has_value()); - EXPECT_EQ(CountVertices(acc, memgraph::storage::View::NEW), 1U); - - acc.AdvanceCommand(); - - auto vertex2 = acc.CreateVertex(); - gid2 = vertex2.Gid(); - ASSERT_FALSE(acc.FindVertex(gid2, memgraph::storage::View::OLD).has_value()); - EXPECT_EQ(CountVertices(acc, memgraph::storage::View::OLD), 1U); - ASSERT_TRUE(acc.FindVertex(gid2, memgraph::storage::View::NEW).has_value()); - EXPECT_EQ(CountVertices(acc, memgraph::storage::View::NEW), 2U); - - ASSERT_TRUE(acc.FindVertex(gid1, memgraph::storage::View::OLD).has_value()); - ASSERT_TRUE(acc.FindVertex(gid1, memgraph::storage::View::NEW).has_value()); - - ASSERT_FALSE(acc.Commit().HasError()); - } - { - auto acc = store.Access(); - ASSERT_TRUE(acc.FindVertex(gid1, memgraph::storage::View::OLD).has_value()); - ASSERT_TRUE(acc.FindVertex(gid1, memgraph::storage::View::NEW).has_value()); - ASSERT_TRUE(acc.FindVertex(gid2, memgraph::storage::View::OLD).has_value()); - ASSERT_TRUE(acc.FindVertex(gid2, memgraph::storage::View::NEW).has_value()); - EXPECT_EQ(CountVertices(acc, memgraph::storage::View::OLD), 2U); - EXPECT_EQ(CountVertices(acc, memgraph::storage::View::NEW), 2U); - acc.Abort(); - } -} - -// NOLINTNEXTLINE(hicpp-special-member-functions) -TEST(StorageV2, AdvanceCommandAbort) { - memgraph::storage::Storage store; - memgraph::storage::Gid gid1 = memgraph::storage::Gid::FromUint(std::numeric_limits::max()); - memgraph::storage::Gid gid2 = memgraph::storage::Gid::FromUint(std::numeric_limits::max()); - { - auto acc = store.Access(); - - auto vertex1 = acc.CreateVertex(); - gid1 = vertex1.Gid(); - ASSERT_FALSE(acc.FindVertex(gid1, memgraph::storage::View::OLD).has_value()); - EXPECT_EQ(CountVertices(acc, memgraph::storage::View::OLD), 0U); - ASSERT_TRUE(acc.FindVertex(gid1, memgraph::storage::View::NEW).has_value()); - EXPECT_EQ(CountVertices(acc, memgraph::storage::View::NEW), 1U); - - acc.AdvanceCommand(); - - auto vertex2 = acc.CreateVertex(); - gid2 = vertex2.Gid(); - ASSERT_FALSE(acc.FindVertex(gid2, memgraph::storage::View::OLD).has_value()); - EXPECT_EQ(CountVertices(acc, memgraph::storage::View::OLD), 1U); - ASSERT_TRUE(acc.FindVertex(gid2, memgraph::storage::View::NEW).has_value()); - EXPECT_EQ(CountVertices(acc, memgraph::storage::View::NEW), 2U); - - ASSERT_TRUE(acc.FindVertex(gid1, memgraph::storage::View::OLD).has_value()); - ASSERT_TRUE(acc.FindVertex(gid1, memgraph::storage::View::NEW).has_value()); - - acc.Abort(); - } - { - auto acc = store.Access(); - ASSERT_FALSE(acc.FindVertex(gid1, memgraph::storage::View::OLD).has_value()); - ASSERT_FALSE(acc.FindVertex(gid1, memgraph::storage::View::NEW).has_value()); - ASSERT_FALSE(acc.FindVertex(gid2, memgraph::storage::View::OLD).has_value()); - ASSERT_FALSE(acc.FindVertex(gid2, memgraph::storage::View::NEW).has_value()); - EXPECT_EQ(CountVertices(acc, memgraph::storage::View::OLD), 0U); - EXPECT_EQ(CountVertices(acc, memgraph::storage::View::NEW), 0U); - acc.Abort(); - } -} - -// NOLINTNEXTLINE(hicpp-special-member-functions) -TEST(StorageV2, SnapshotIsolation) { - memgraph::storage::Storage store; - - auto acc1 = store.Access(); - auto acc2 = store.Access(); - - auto vertex = acc1.CreateVertex(); - auto gid = vertex.Gid(); - - ASSERT_FALSE(acc2.FindVertex(gid, memgraph::storage::View::OLD).has_value()); - EXPECT_EQ(CountVertices(acc1, memgraph::storage::View::OLD), 0U); - EXPECT_EQ(CountVertices(acc2, memgraph::storage::View::OLD), 0U); - ASSERT_FALSE(acc2.FindVertex(gid, memgraph::storage::View::NEW).has_value()); - EXPECT_EQ(CountVertices(acc1, memgraph::storage::View::NEW), 1U); - EXPECT_EQ(CountVertices(acc2, memgraph::storage::View::NEW), 0U); - - ASSERT_FALSE(acc1.Commit().HasError()); - - ASSERT_FALSE(acc2.FindVertex(gid, memgraph::storage::View::OLD).has_value()); - EXPECT_EQ(CountVertices(acc2, memgraph::storage::View::OLD), 0U); - ASSERT_FALSE(acc2.FindVertex(gid, memgraph::storage::View::NEW).has_value()); - EXPECT_EQ(CountVertices(acc2, memgraph::storage::View::NEW), 0U); - - acc2.Abort(); - - auto acc3 = store.Access(); - ASSERT_TRUE(acc3.FindVertex(gid, memgraph::storage::View::OLD).has_value()); - EXPECT_EQ(CountVertices(acc3, memgraph::storage::View::OLD), 1U); - ASSERT_TRUE(acc3.FindVertex(gid, memgraph::storage::View::NEW).has_value()); - EXPECT_EQ(CountVertices(acc3, memgraph::storage::View::NEW), 1U); - acc3.Abort(); -} - -// NOLINTNEXTLINE(hicpp-special-member-functions) -TEST(StorageV2, AccessorMove) { - memgraph::storage::Storage store; - memgraph::storage::Gid gid = memgraph::storage::Gid::FromUint(std::numeric_limits::max()); - { - auto acc = store.Access(); - auto vertex = acc.CreateVertex(); - gid = vertex.Gid(); - - ASSERT_FALSE(acc.FindVertex(gid, memgraph::storage::View::OLD).has_value()); - EXPECT_EQ(CountVertices(acc, memgraph::storage::View::OLD), 0U); - ASSERT_TRUE(acc.FindVertex(gid, memgraph::storage::View::NEW).has_value()); - EXPECT_EQ(CountVertices(acc, memgraph::storage::View::NEW), 1U); - - memgraph::storage::Storage::Accessor moved(std::move(acc)); - - ASSERT_FALSE(moved.FindVertex(gid, memgraph::storage::View::OLD).has_value()); - EXPECT_EQ(CountVertices(moved, memgraph::storage::View::OLD), 0U); - ASSERT_TRUE(moved.FindVertex(gid, memgraph::storage::View::NEW).has_value()); - EXPECT_EQ(CountVertices(moved, memgraph::storage::View::NEW), 1U); - - ASSERT_FALSE(moved.Commit().HasError()); - } - { - auto acc = store.Access(); - ASSERT_TRUE(acc.FindVertex(gid, memgraph::storage::View::OLD).has_value()); - EXPECT_EQ(CountVertices(acc, memgraph::storage::View::OLD), 1U); - ASSERT_TRUE(acc.FindVertex(gid, memgraph::storage::View::NEW).has_value()); - EXPECT_EQ(CountVertices(acc, memgraph::storage::View::NEW), 1U); - acc.Abort(); - } -} - -// NOLINTNEXTLINE(hicpp-special-member-functions) -TEST(StorageV2, VertexDeleteCommit) { - memgraph::storage::Storage store; - memgraph::storage::Gid gid = memgraph::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, memgraph::storage::View::OLD).has_value()); - EXPECT_EQ(CountVertices(acc2, memgraph::storage::View::OLD), 0U); - ASSERT_TRUE(acc2.FindVertex(gid, memgraph::storage::View::NEW).has_value()); - EXPECT_EQ(CountVertices(acc2, memgraph::storage::View::NEW), 1U); - ASSERT_FALSE(acc2.Commit().HasError()); - } - - 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, memgraph::storage::View::OLD).has_value()); - EXPECT_EQ(CountVertices(acc1, memgraph::storage::View::OLD), 0U); - ASSERT_FALSE(acc1.FindVertex(gid, memgraph::storage::View::NEW).has_value()); - EXPECT_EQ(CountVertices(acc1, memgraph::storage::View::NEW), 0U); - - // Check whether the vertex exists in transaction 3 - ASSERT_TRUE(acc3.FindVertex(gid, memgraph::storage::View::OLD).has_value()); - EXPECT_EQ(CountVertices(acc3, memgraph::storage::View::OLD), 1U); - ASSERT_TRUE(acc3.FindVertex(gid, memgraph::storage::View::NEW).has_value()); - EXPECT_EQ(CountVertices(acc3, memgraph::storage::View::NEW), 1U); - - // Delete the vertex in transaction 4 - { - auto vertex = acc4.FindVertex(gid, memgraph::storage::View::NEW); - ASSERT_TRUE(vertex); - EXPECT_EQ(CountVertices(acc4, memgraph::storage::View::OLD), 1U); - EXPECT_EQ(CountVertices(acc4, memgraph::storage::View::NEW), 1U); - - auto res = acc4.DeleteVertex(&*vertex); - ASSERT_TRUE(res.HasValue()); - EXPECT_EQ(CountVertices(acc4, memgraph::storage::View::OLD), 1U); - EXPECT_EQ(CountVertices(acc4, memgraph::storage::View::NEW), 0U); - - acc4.AdvanceCommand(); - EXPECT_EQ(CountVertices(acc4, memgraph::storage::View::OLD), 0U); - EXPECT_EQ(CountVertices(acc4, memgraph::storage::View::NEW), 0U); - - ASSERT_FALSE(acc4.Commit().HasError()); - } - - auto acc5 = store.Access(); // read transaction - - // Check whether the vertex exists in transaction 1 - ASSERT_FALSE(acc1.FindVertex(gid, memgraph::storage::View::OLD).has_value()); - EXPECT_EQ(CountVertices(acc1, memgraph::storage::View::OLD), 0U); - ASSERT_FALSE(acc1.FindVertex(gid, memgraph::storage::View::NEW).has_value()); - EXPECT_EQ(CountVertices(acc1, memgraph::storage::View::NEW), 0U); - - // Check whether the vertex exists in transaction 3 - ASSERT_TRUE(acc3.FindVertex(gid, memgraph::storage::View::OLD).has_value()); - EXPECT_EQ(CountVertices(acc3, memgraph::storage::View::OLD), 1U); - ASSERT_TRUE(acc3.FindVertex(gid, memgraph::storage::View::NEW).has_value()); - EXPECT_EQ(CountVertices(acc3, memgraph::storage::View::NEW), 1U); - - // Check whether the vertex exists in transaction 5 - ASSERT_FALSE(acc5.FindVertex(gid, memgraph::storage::View::OLD).has_value()); - EXPECT_EQ(CountVertices(acc5, memgraph::storage::View::OLD), 0U); - ASSERT_FALSE(acc5.FindVertex(gid, memgraph::storage::View::NEW).has_value()); - EXPECT_EQ(CountVertices(acc5, memgraph::storage::View::NEW), 0U); -} - -// NOLINTNEXTLINE(hicpp-special-member-functions) -TEST(StorageV2, VertexDeleteAbort) { - memgraph::storage::Storage store; - memgraph::storage::Gid gid = memgraph::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, memgraph::storage::View::OLD).has_value()); - EXPECT_EQ(CountVertices(acc2, memgraph::storage::View::OLD), 0U); - ASSERT_TRUE(acc2.FindVertex(gid, memgraph::storage::View::NEW).has_value()); - EXPECT_EQ(CountVertices(acc2, memgraph::storage::View::NEW), 1U); - ASSERT_FALSE(acc2.Commit().HasError()); - } - - 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, memgraph::storage::View::OLD).has_value()); - EXPECT_EQ(CountVertices(acc1, memgraph::storage::View::OLD), 0U); - ASSERT_FALSE(acc1.FindVertex(gid, memgraph::storage::View::NEW).has_value()); - EXPECT_EQ(CountVertices(acc1, memgraph::storage::View::NEW), 0U); - - // Check whether the vertex exists in transaction 3 - ASSERT_TRUE(acc3.FindVertex(gid, memgraph::storage::View::OLD).has_value()); - EXPECT_EQ(CountVertices(acc3, memgraph::storage::View::OLD), 1U); - ASSERT_TRUE(acc3.FindVertex(gid, memgraph::storage::View::NEW).has_value()); - EXPECT_EQ(CountVertices(acc3, memgraph::storage::View::NEW), 1U); - - // Delete the vertex in transaction 4, but abort the transaction - { - auto vertex = acc4.FindVertex(gid, memgraph::storage::View::NEW); - ASSERT_TRUE(vertex); - EXPECT_EQ(CountVertices(acc4, memgraph::storage::View::OLD), 1U); - EXPECT_EQ(CountVertices(acc4, memgraph::storage::View::NEW), 1U); - - auto res = acc4.DeleteVertex(&*vertex); - ASSERT_TRUE(res.HasValue()); - EXPECT_EQ(CountVertices(acc4, memgraph::storage::View::OLD), 1U); - EXPECT_EQ(CountVertices(acc4, memgraph::storage::View::NEW), 0U); - - acc4.AdvanceCommand(); - EXPECT_EQ(CountVertices(acc4, memgraph::storage::View::OLD), 0U); - EXPECT_EQ(CountVertices(acc4, memgraph::storage::View::NEW), 0U); - - 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, memgraph::storage::View::OLD).has_value()); - EXPECT_EQ(CountVertices(acc1, memgraph::storage::View::OLD), 0U); - ASSERT_FALSE(acc1.FindVertex(gid, memgraph::storage::View::NEW).has_value()); - EXPECT_EQ(CountVertices(acc1, memgraph::storage::View::NEW), 0U); - - // Check whether the vertex exists in transaction 3 - ASSERT_TRUE(acc3.FindVertex(gid, memgraph::storage::View::OLD).has_value()); - EXPECT_EQ(CountVertices(acc3, memgraph::storage::View::OLD), 1U); - ASSERT_TRUE(acc3.FindVertex(gid, memgraph::storage::View::NEW).has_value()); - EXPECT_EQ(CountVertices(acc3, memgraph::storage::View::NEW), 1U); - - // Check whether the vertex exists in transaction 5 - ASSERT_TRUE(acc5.FindVertex(gid, memgraph::storage::View::OLD).has_value()); - EXPECT_EQ(CountVertices(acc5, memgraph::storage::View::OLD), 1U); - ASSERT_TRUE(acc5.FindVertex(gid, memgraph::storage::View::NEW).has_value()); - EXPECT_EQ(CountVertices(acc5, memgraph::storage::View::NEW), 1U); - - // Delete the vertex in transaction 6 - { - auto vertex = acc6.FindVertex(gid, memgraph::storage::View::NEW); - ASSERT_TRUE(vertex); - EXPECT_EQ(CountVertices(acc6, memgraph::storage::View::OLD), 1U); - EXPECT_EQ(CountVertices(acc6, memgraph::storage::View::NEW), 1U); - - auto res = acc6.DeleteVertex(&*vertex); - ASSERT_TRUE(res.HasValue()); - EXPECT_EQ(CountVertices(acc6, memgraph::storage::View::OLD), 1U); - EXPECT_EQ(CountVertices(acc6, memgraph::storage::View::NEW), 0U); - - acc6.AdvanceCommand(); - EXPECT_EQ(CountVertices(acc6, memgraph::storage::View::OLD), 0U); - EXPECT_EQ(CountVertices(acc6, memgraph::storage::View::NEW), 0U); - - ASSERT_FALSE(acc6.Commit().HasError()); - } - - auto acc7 = store.Access(); // read transaction - - // Check whether the vertex exists in transaction 1 - ASSERT_FALSE(acc1.FindVertex(gid, memgraph::storage::View::OLD).has_value()); - EXPECT_EQ(CountVertices(acc1, memgraph::storage::View::OLD), 0U); - ASSERT_FALSE(acc1.FindVertex(gid, memgraph::storage::View::NEW).has_value()); - EXPECT_EQ(CountVertices(acc1, memgraph::storage::View::NEW), 0U); - - // Check whether the vertex exists in transaction 3 - ASSERT_TRUE(acc3.FindVertex(gid, memgraph::storage::View::OLD).has_value()); - EXPECT_EQ(CountVertices(acc3, memgraph::storage::View::OLD), 1U); - ASSERT_TRUE(acc3.FindVertex(gid, memgraph::storage::View::NEW).has_value()); - EXPECT_EQ(CountVertices(acc3, memgraph::storage::View::NEW), 1U); - - // Check whether the vertex exists in transaction 5 - ASSERT_TRUE(acc5.FindVertex(gid, memgraph::storage::View::OLD).has_value()); - EXPECT_EQ(CountVertices(acc5, memgraph::storage::View::OLD), 1U); - ASSERT_TRUE(acc5.FindVertex(gid, memgraph::storage::View::NEW).has_value()); - EXPECT_EQ(CountVertices(acc5, memgraph::storage::View::NEW), 1U); - - // Check whether the vertex exists in transaction 7 - ASSERT_FALSE(acc7.FindVertex(gid, memgraph::storage::View::OLD).has_value()); - EXPECT_EQ(CountVertices(acc7, memgraph::storage::View::OLD), 0U); - ASSERT_FALSE(acc7.FindVertex(gid, memgraph::storage::View::NEW).has_value()); - EXPECT_EQ(CountVertices(acc7, memgraph::storage::View::NEW), 0U); - - // Commit all accessors - ASSERT_FALSE(acc1.Commit().HasError()); - ASSERT_FALSE(acc3.Commit().HasError()); - ASSERT_FALSE(acc5.Commit().HasError()); - ASSERT_FALSE(acc7.Commit().HasError()); -} - -// NOLINTNEXTLINE(hicpp-special-member-functions) -TEST(StorageV2, VertexDeleteSerializationError) { - memgraph::storage::Storage store; - memgraph::storage::Gid gid = memgraph::storage::Gid::FromUint(std::numeric_limits::max()); - - // Create vertex - { - auto acc = store.Access(); - auto vertex = acc.CreateVertex(); - gid = vertex.Gid(); - ASSERT_FALSE(acc.Commit().HasError()); - } - - auto acc1 = store.Access(); - auto acc2 = store.Access(); - - // Delete vertex in accessor 1 - { - auto vertex = acc1.FindVertex(gid, memgraph::storage::View::OLD); - ASSERT_TRUE(vertex); - EXPECT_EQ(CountVertices(acc1, memgraph::storage::View::OLD), 1U); - EXPECT_EQ(CountVertices(acc1, memgraph::storage::View::NEW), 1U); - - { - auto res = acc1.DeleteVertex(&*vertex); - ASSERT_TRUE(res.HasValue()); - ASSERT_TRUE(res.GetValue()); - EXPECT_EQ(CountVertices(acc1, memgraph::storage::View::OLD), 1U); - EXPECT_EQ(CountVertices(acc1, memgraph::storage::View::NEW), 0U); - } - - { - auto res = acc1.DeleteVertex(&*vertex); - ASSERT_TRUE(res.HasValue()); - ASSERT_FALSE(res.GetValue()); - EXPECT_EQ(CountVertices(acc1, memgraph::storage::View::OLD), 1U); - EXPECT_EQ(CountVertices(acc1, memgraph::storage::View::NEW), 0U); - } - - acc1.AdvanceCommand(); - EXPECT_EQ(CountVertices(acc1, memgraph::storage::View::OLD), 0U); - EXPECT_EQ(CountVertices(acc1, memgraph::storage::View::NEW), 0U); - } - - // Delete vertex in accessor 2 - { - auto vertex = acc2.FindVertex(gid, memgraph::storage::View::OLD); - ASSERT_TRUE(vertex); - EXPECT_EQ(CountVertices(acc2, memgraph::storage::View::OLD), 1U); - EXPECT_EQ(CountVertices(acc2, memgraph::storage::View::NEW), 1U); - auto res = acc2.DeleteVertex(&*vertex); - ASSERT_TRUE(res.HasError()); - ASSERT_EQ(res.GetError(), memgraph::storage::Error::SERIALIZATION_ERROR); - EXPECT_EQ(CountVertices(acc2, memgraph::storage::View::OLD), 1U); - EXPECT_EQ(CountVertices(acc2, memgraph::storage::View::NEW), 1U); - acc2.AdvanceCommand(); - EXPECT_EQ(CountVertices(acc2, memgraph::storage::View::OLD), 1U); - EXPECT_EQ(CountVertices(acc2, memgraph::storage::View::NEW), 1U); - } - - // Finalize both accessors - ASSERT_FALSE(acc1.Commit().HasError()); - acc2.Abort(); - - // Check whether the vertex exists - { - auto acc = store.Access(); - auto vertex = acc.FindVertex(gid, memgraph::storage::View::OLD); - ASSERT_FALSE(vertex); - EXPECT_EQ(CountVertices(acc, memgraph::storage::View::OLD), 0U); - EXPECT_EQ(CountVertices(acc, memgraph::storage::View::NEW), 0U); - ASSERT_FALSE(acc.Commit().HasError()); - } -} - -// NOLINTNEXTLINE(hicpp-special-member-functions) -TEST(StorageV2, VertexDeleteSpecialCases) { - memgraph::storage::Storage store; - memgraph::storage::Gid gid1 = memgraph::storage::Gid::FromUint(std::numeric_limits::max()); - memgraph::storage::Gid gid2 = memgraph::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, memgraph::storage::View::OLD).has_value()); - EXPECT_EQ(CountVertices(acc, memgraph::storage::View::OLD), 0U); - ASSERT_TRUE(acc.FindVertex(gid1, memgraph::storage::View::NEW).has_value()); - EXPECT_EQ(CountVertices(acc, memgraph::storage::View::NEW), 1U); - auto res = acc.DeleteVertex(&vertex); - ASSERT_TRUE(res.HasValue()); - ASSERT_TRUE(res.GetValue()); - EXPECT_EQ(CountVertices(acc, memgraph::storage::View::OLD), 0U); - EXPECT_EQ(CountVertices(acc, memgraph::storage::View::NEW), 0U); - acc.AdvanceCommand(); - EXPECT_EQ(CountVertices(acc, memgraph::storage::View::OLD), 0U); - EXPECT_EQ(CountVertices(acc, memgraph::storage::View::NEW), 0U); - 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, memgraph::storage::View::OLD).has_value()); - EXPECT_EQ(CountVertices(acc, memgraph::storage::View::OLD), 0U); - ASSERT_TRUE(acc.FindVertex(gid2, memgraph::storage::View::NEW).has_value()); - EXPECT_EQ(CountVertices(acc, memgraph::storage::View::NEW), 1U); - auto res = acc.DeleteVertex(&vertex); - ASSERT_TRUE(res.HasValue()); - ASSERT_TRUE(res.GetValue()); - EXPECT_EQ(CountVertices(acc, memgraph::storage::View::OLD), 0U); - EXPECT_EQ(CountVertices(acc, memgraph::storage::View::NEW), 0U); - acc.AdvanceCommand(); - EXPECT_EQ(CountVertices(acc, memgraph::storage::View::OLD), 0U); - EXPECT_EQ(CountVertices(acc, memgraph::storage::View::NEW), 0U); - ASSERT_FALSE(acc.Commit().HasError()); - } - - // Check whether the vertices exist - { - auto acc = store.Access(); - ASSERT_FALSE(acc.FindVertex(gid1, memgraph::storage::View::OLD).has_value()); - ASSERT_FALSE(acc.FindVertex(gid1, memgraph::storage::View::NEW).has_value()); - ASSERT_FALSE(acc.FindVertex(gid2, memgraph::storage::View::OLD).has_value()); - ASSERT_FALSE(acc.FindVertex(gid2, memgraph::storage::View::NEW).has_value()); - EXPECT_EQ(CountVertices(acc, memgraph::storage::View::OLD), 0U); - EXPECT_EQ(CountVertices(acc, memgraph::storage::View::NEW), 0U); - acc.Abort(); - } -} - -// NOLINTNEXTLINE(hicpp-special-member-functions) -TEST(StorageV2, VertexDeleteLabel) { - memgraph::storage::Storage store; - memgraph::storage::Gid gid = memgraph::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, memgraph::storage::View::OLD).has_value()); - ASSERT_TRUE(acc.FindVertex(gid, memgraph::storage::View::NEW).has_value()); - ASSERT_FALSE(acc.Commit().HasError()); - } - - // Add label, delete the vertex and check the label API (same command) - { - auto acc = store.Access(); - auto vertex = acc.FindVertex(gid, memgraph::storage::View::NEW); - ASSERT_TRUE(vertex); - - auto label = acc.NameToLabel("label5"); - - // Check whether label 5 exists - ASSERT_FALSE(vertex->HasLabel(label, memgraph::storage::View::OLD).GetValue()); - ASSERT_FALSE(vertex->HasLabel(label, memgraph::storage::View::NEW).GetValue()); - ASSERT_EQ(vertex->Labels(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(vertex->Labels(memgraph::storage::View::NEW)->size(), 0); - - // Add label 5 - ASSERT_TRUE(vertex->AddLabel(label).GetValue()); - - // Check whether label 5 exists - ASSERT_FALSE(vertex->HasLabel(label, memgraph::storage::View::OLD).GetValue()); - ASSERT_TRUE(vertex->HasLabel(label, memgraph::storage::View::NEW).GetValue()); - ASSERT_EQ(vertex->Labels(memgraph::storage::View::OLD)->size(), 0); - { - auto labels = vertex->Labels(memgraph::storage::View::NEW).GetValue(); - ASSERT_EQ(labels.size(), 1); - ASSERT_EQ(labels[0], label); - } - - // Delete the vertex - ASSERT_TRUE(acc.DeleteVertex(&*vertex).GetValue()); - - // Check whether label 5 exists - ASSERT_FALSE(vertex->HasLabel(label, memgraph::storage::View::OLD).GetValue()); - ASSERT_EQ(vertex->HasLabel(label, memgraph::storage::View::NEW).GetError(), - memgraph::storage::Error::DELETED_OBJECT); - ASSERT_EQ(vertex->Labels(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(vertex->Labels(memgraph::storage::View::NEW).GetError(), memgraph::storage::Error::DELETED_OBJECT); - - // Try to add the label - { - auto ret = vertex->AddLabel(label); - ASSERT_TRUE(ret.HasError()); - ASSERT_EQ(ret.GetError(), memgraph::storage::Error::DELETED_OBJECT); - } - - // Try to remove the label - { - auto ret = vertex->RemoveLabel(label); - ASSERT_TRUE(ret.HasError()); - ASSERT_EQ(ret.GetError(), memgraph::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, memgraph::storage::View::NEW); - ASSERT_TRUE(vertex); - - auto label = acc.NameToLabel("label5"); - - // Check whether label 5 exists - ASSERT_FALSE(vertex->HasLabel(label, memgraph::storage::View::OLD).GetValue()); - ASSERT_FALSE(vertex->HasLabel(label, memgraph::storage::View::NEW).GetValue()); - ASSERT_EQ(vertex->Labels(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(vertex->Labels(memgraph::storage::View::NEW)->size(), 0); - - // Add label 5 - ASSERT_TRUE(vertex->AddLabel(label).GetValue()); - - // Check whether label 5 exists - ASSERT_FALSE(vertex->HasLabel(label, memgraph::storage::View::OLD).GetValue()); - ASSERT_TRUE(vertex->HasLabel(label, memgraph::storage::View::NEW).GetValue()); - ASSERT_EQ(vertex->Labels(memgraph::storage::View::OLD)->size(), 0); - { - auto labels = vertex->Labels(memgraph::storage::View::NEW).GetValue(); - ASSERT_EQ(labels.size(), 1); - ASSERT_EQ(labels[0], label); - } - - // Advance command - acc.AdvanceCommand(); - - // Check whether label 5 exists - ASSERT_TRUE(vertex->HasLabel(label, memgraph::storage::View::OLD).GetValue()); - ASSERT_TRUE(vertex->HasLabel(label, memgraph::storage::View::NEW).GetValue()); - { - auto labels = vertex->Labels(memgraph::storage::View::OLD).GetValue(); - ASSERT_EQ(labels.size(), 1); - ASSERT_EQ(labels[0], label); - } - { - auto labels = vertex->Labels(memgraph::storage::View::NEW).GetValue(); - ASSERT_EQ(labels.size(), 1); - ASSERT_EQ(labels[0], label); - } - - // Delete the vertex - ASSERT_TRUE(acc.DeleteVertex(&*vertex).GetValue()); - - // Check whether label 5 exists - ASSERT_TRUE(vertex->HasLabel(label, memgraph::storage::View::OLD).GetValue()); - ASSERT_EQ(vertex->HasLabel(label, memgraph::storage::View::NEW).GetError(), - memgraph::storage::Error::DELETED_OBJECT); - { - auto labels = vertex->Labels(memgraph::storage::View::OLD).GetValue(); - ASSERT_EQ(labels.size(), 1); - ASSERT_EQ(labels[0], label); - } - ASSERT_EQ(vertex->Labels(memgraph::storage::View::NEW).GetError(), memgraph::storage::Error::DELETED_OBJECT); - - // Advance command - acc.AdvanceCommand(); - - // Check whether label 5 exists - ASSERT_EQ(vertex->HasLabel(label, memgraph::storage::View::OLD).GetError(), - memgraph::storage::Error::DELETED_OBJECT); - ASSERT_EQ(vertex->HasLabel(label, memgraph::storage::View::NEW).GetError(), - memgraph::storage::Error::DELETED_OBJECT); - ASSERT_EQ(vertex->Labels(memgraph::storage::View::OLD).GetError(), memgraph::storage::Error::DELETED_OBJECT); - ASSERT_EQ(vertex->Labels(memgraph::storage::View::NEW).GetError(), memgraph::storage::Error::DELETED_OBJECT); - - // Try to add the label - { - auto ret = vertex->AddLabel(label); - ASSERT_TRUE(ret.HasError()); - ASSERT_EQ(ret.GetError(), memgraph::storage::Error::DELETED_OBJECT); - } - - // Try to remove the label - { - auto ret = vertex->RemoveLabel(label); - ASSERT_TRUE(ret.HasError()); - ASSERT_EQ(ret.GetError(), memgraph::storage::Error::DELETED_OBJECT); - } - - acc.Abort(); - } -} - -// NOLINTNEXTLINE(hicpp-special-member-functions) -TEST(StorageV2, VertexDeleteProperty) { - memgraph::storage::Storage store; - memgraph::storage::Gid gid = memgraph::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, memgraph::storage::View::OLD).has_value()); - ASSERT_TRUE(acc.FindVertex(gid, memgraph::storage::View::NEW).has_value()); - ASSERT_FALSE(acc.Commit().HasError()); - } - - // Set property, delete the vertex and check the property API (same command) - { - auto acc = store.Access(); - auto vertex = acc.FindVertex(gid, memgraph::storage::View::NEW); - ASSERT_TRUE(vertex); - - auto property = acc.NameToProperty("property5"); - - // Check whether property 5 exists - ASSERT_TRUE(vertex->GetProperty(property, memgraph::storage::View::OLD)->IsNull()); - ASSERT_TRUE(vertex->GetProperty(property, memgraph::storage::View::NEW)->IsNull()); - ASSERT_EQ(vertex->Properties(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(vertex->Properties(memgraph::storage::View::NEW)->size(), 0); - - // Set property 5 to "nandare" - ASSERT_TRUE(vertex->SetProperty(property, memgraph::storage::PropertyValue("nandare"))->IsNull()); - - // Check whether property 5 exists - ASSERT_TRUE(vertex->GetProperty(property, memgraph::storage::View::OLD)->IsNull()); - ASSERT_EQ(vertex->GetProperty(property, memgraph::storage::View::NEW)->ValueString(), "nandare"); - ASSERT_EQ(vertex->Properties(memgraph::storage::View::OLD)->size(), 0); - { - auto properties = vertex->Properties(memgraph::storage::View::NEW).GetValue(); - ASSERT_EQ(properties.size(), 1); - ASSERT_EQ(properties[property].ValueString(), "nandare"); - } - - // Delete the vertex - ASSERT_TRUE(acc.DeleteVertex(&*vertex).GetValue()); - - // Check whether label 5 exists - ASSERT_TRUE(vertex->GetProperty(property, memgraph::storage::View::OLD)->IsNull()); - ASSERT_EQ(vertex->GetProperty(property, memgraph::storage::View::NEW).GetError(), - memgraph::storage::Error::DELETED_OBJECT); - ASSERT_EQ(vertex->Properties(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(vertex->Properties(memgraph::storage::View::NEW).GetError(), memgraph::storage::Error::DELETED_OBJECT); - - // Try to set the property - { - auto ret = vertex->SetProperty(property, memgraph::storage::PropertyValue("haihai")); - ASSERT_TRUE(ret.HasError()); - ASSERT_EQ(ret.GetError(), memgraph::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, memgraph::storage::View::NEW); - ASSERT_TRUE(vertex); - - auto property = acc.NameToProperty("property5"); - - // Check whether property 5 exists - ASSERT_TRUE(vertex->GetProperty(property, memgraph::storage::View::OLD)->IsNull()); - ASSERT_TRUE(vertex->GetProperty(property, memgraph::storage::View::NEW)->IsNull()); - ASSERT_EQ(vertex->Properties(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(vertex->Properties(memgraph::storage::View::NEW)->size(), 0); - - // Set property 5 to "nandare" - ASSERT_TRUE(vertex->SetProperty(property, memgraph::storage::PropertyValue("nandare"))->IsNull()); - - // Check whether property 5 exists - ASSERT_TRUE(vertex->GetProperty(property, memgraph::storage::View::OLD)->IsNull()); - ASSERT_EQ(vertex->GetProperty(property, memgraph::storage::View::NEW)->ValueString(), "nandare"); - ASSERT_EQ(vertex->Properties(memgraph::storage::View::OLD)->size(), 0); - { - auto properties = vertex->Properties(memgraph::storage::View::NEW).GetValue(); - ASSERT_EQ(properties.size(), 1); - ASSERT_EQ(properties[property].ValueString(), "nandare"); - } - - // Advance command - acc.AdvanceCommand(); - - // Check whether property 5 exists - ASSERT_EQ(vertex->GetProperty(property, memgraph::storage::View::OLD)->ValueString(), "nandare"); - ASSERT_EQ(vertex->GetProperty(property, memgraph::storage::View::NEW)->ValueString(), "nandare"); - { - auto properties = vertex->Properties(memgraph::storage::View::OLD).GetValue(); - ASSERT_EQ(properties.size(), 1); - ASSERT_EQ(properties[property].ValueString(), "nandare"); - } - { - auto properties = vertex->Properties(memgraph::storage::View::NEW).GetValue(); - ASSERT_EQ(properties.size(), 1); - ASSERT_EQ(properties[property].ValueString(), "nandare"); - } - - // Delete the vertex - ASSERT_TRUE(acc.DeleteVertex(&*vertex).GetValue()); - - // Check whether property 5 exists - ASSERT_EQ(vertex->GetProperty(property, memgraph::storage::View::OLD)->ValueString(), "nandare"); - ASSERT_EQ(vertex->GetProperty(property, memgraph::storage::View::NEW).GetError(), - memgraph::storage::Error::DELETED_OBJECT); - { - auto properties = vertex->Properties(memgraph::storage::View::OLD).GetValue(); - ASSERT_EQ(properties.size(), 1); - ASSERT_EQ(properties[property].ValueString(), "nandare"); - } - ASSERT_EQ(vertex->Properties(memgraph::storage::View::NEW).GetError(), memgraph::storage::Error::DELETED_OBJECT); - - // Advance command - acc.AdvanceCommand(); - - // Check whether property 5 exists - ASSERT_EQ(vertex->GetProperty(property, memgraph::storage::View::OLD).GetError(), - memgraph::storage::Error::DELETED_OBJECT); - ASSERT_EQ(vertex->GetProperty(property, memgraph::storage::View::NEW).GetError(), - memgraph::storage::Error::DELETED_OBJECT); - ASSERT_EQ(vertex->Properties(memgraph::storage::View::OLD).GetError(), memgraph::storage::Error::DELETED_OBJECT); - ASSERT_EQ(vertex->Properties(memgraph::storage::View::NEW).GetError(), memgraph::storage::Error::DELETED_OBJECT); - - // Try to set the property - { - auto ret = vertex->SetProperty(property, memgraph::storage::PropertyValue("haihai")); - ASSERT_TRUE(ret.HasError()); - ASSERT_EQ(ret.GetError(), memgraph::storage::Error::DELETED_OBJECT); - } - - acc.Abort(); - } -} - -// NOLINTNEXTLINE(hicpp-special-member-functions) -TEST(StorageV2, VertexLabelCommit) { - memgraph::storage::Storage store; - memgraph::storage::Gid gid = memgraph::storage::Gid::FromUint(std::numeric_limits::max()); - { - auto acc = store.Access(); - auto vertex = acc.CreateVertex(); - gid = vertex.Gid(); - - auto label = acc.NameToLabel("label5"); - - ASSERT_FALSE(vertex.HasLabel(label, memgraph::storage::View::NEW).GetValue()); - ASSERT_EQ(vertex.Labels(memgraph::storage::View::NEW)->size(), 0); - - { - auto res = vertex.AddLabel(label); - ASSERT_TRUE(res.HasValue()); - ASSERT_TRUE(res.GetValue()); - } - - ASSERT_TRUE(vertex.HasLabel(label, memgraph::storage::View::NEW).GetValue()); - { - auto labels = vertex.Labels(memgraph::storage::View::NEW).GetValue(); - ASSERT_EQ(labels.size(), 1); - ASSERT_EQ(labels[0], label); - } - - { - auto res = vertex.AddLabel(label); - ASSERT_TRUE(res.HasValue()); - ASSERT_FALSE(res.GetValue()); - } - - ASSERT_FALSE(acc.Commit().HasError()); - } - { - auto acc = store.Access(); - auto vertex = acc.FindVertex(gid, memgraph::storage::View::OLD); - ASSERT_TRUE(vertex); - - auto label = acc.NameToLabel("label5"); - - ASSERT_TRUE(vertex->HasLabel(label, memgraph::storage::View::OLD).GetValue()); - { - auto labels = vertex->Labels(memgraph::storage::View::OLD).GetValue(); - ASSERT_EQ(labels.size(), 1); - ASSERT_EQ(labels[0], label); - } - - ASSERT_TRUE(vertex->HasLabel(label, memgraph::storage::View::NEW).GetValue()); - { - auto labels = vertex->Labels(memgraph::storage::View::NEW).GetValue(); - ASSERT_EQ(labels.size(), 1); - ASSERT_EQ(labels[0], label); - } - - auto other_label = acc.NameToLabel("other"); - - ASSERT_FALSE(vertex->HasLabel(other_label, memgraph::storage::View::OLD).GetValue()); - ASSERT_FALSE(vertex->HasLabel(other_label, memgraph::storage::View::NEW).GetValue()); - - acc.Abort(); - } - { - auto acc = store.Access(); - auto vertex = acc.FindVertex(gid, memgraph::storage::View::OLD); - ASSERT_TRUE(vertex); - - auto label = acc.NameToLabel("label5"); - - { - auto res = vertex->RemoveLabel(label); - ASSERT_TRUE(res.HasValue()); - ASSERT_TRUE(res.GetValue()); - } - - ASSERT_TRUE(vertex->HasLabel(label, memgraph::storage::View::OLD).GetValue()); - { - auto labels = vertex->Labels(memgraph::storage::View::OLD).GetValue(); - ASSERT_EQ(labels.size(), 1); - ASSERT_EQ(labels[0], label); - } - - ASSERT_FALSE(vertex->HasLabel(label, memgraph::storage::View::NEW).GetValue()); - ASSERT_EQ(vertex->Labels(memgraph::storage::View::NEW)->size(), 0); - - { - auto res = vertex->RemoveLabel(label); - ASSERT_TRUE(res.HasValue()); - ASSERT_FALSE(res.GetValue()); - } - - ASSERT_FALSE(acc.Commit().HasError()); - } - { - auto acc = store.Access(); - auto vertex = acc.FindVertex(gid, memgraph::storage::View::OLD); - ASSERT_TRUE(vertex); - - auto label = acc.NameToLabel("label5"); - - ASSERT_FALSE(vertex->HasLabel(label, memgraph::storage::View::OLD).GetValue()); - ASSERT_FALSE(vertex->HasLabel(label, memgraph::storage::View::NEW).GetValue()); - ASSERT_EQ(vertex->Labels(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(vertex->Labels(memgraph::storage::View::NEW)->size(), 0); - - auto other_label = acc.NameToLabel("other"); - - ASSERT_FALSE(vertex->HasLabel(other_label, memgraph::storage::View::OLD).GetValue()); - ASSERT_FALSE(vertex->HasLabel(other_label, memgraph::storage::View::NEW).GetValue()); - - acc.Abort(); - } -} - -// NOLINTNEXTLINE(hicpp-special-member-functions) -TEST(StorageV2, VertexLabelAbort) { - memgraph::storage::Storage store; - memgraph::storage::Gid gid = memgraph::storage::Gid::FromUint(std::numeric_limits::max()); - - // Create the vertex. - { - auto acc = store.Access(); - auto vertex = acc.CreateVertex(); - gid = vertex.Gid(); - ASSERT_FALSE(acc.Commit().HasError()); - } - - // Add label 5, but abort the transaction. - { - auto acc = store.Access(); - auto vertex = acc.FindVertex(gid, memgraph::storage::View::OLD); - ASSERT_TRUE(vertex); - - auto label = acc.NameToLabel("label5"); - - ASSERT_FALSE(vertex->HasLabel(label, memgraph::storage::View::NEW).GetValue()); - ASSERT_EQ(vertex->Labels(memgraph::storage::View::NEW)->size(), 0); - - { - auto res = vertex->AddLabel(label); - ASSERT_TRUE(res.HasValue()); - ASSERT_TRUE(res.GetValue()); - } - - ASSERT_TRUE(vertex->HasLabel(label, memgraph::storage::View::NEW).GetValue()); - { - auto labels = vertex->Labels(memgraph::storage::View::NEW).GetValue(); - ASSERT_EQ(labels.size(), 1); - ASSERT_EQ(labels[0], label); - } - - { - auto res = vertex->AddLabel(label); - ASSERT_TRUE(res.HasValue()); - ASSERT_FALSE(res.GetValue()); - } - - acc.Abort(); - } - - // Check that label 5 doesn't exist. - { - auto acc = store.Access(); - auto vertex = acc.FindVertex(gid, memgraph::storage::View::OLD); - ASSERT_TRUE(vertex); - - auto label = acc.NameToLabel("label5"); - - ASSERT_FALSE(vertex->HasLabel(label, memgraph::storage::View::OLD).GetValue()); - ASSERT_FALSE(vertex->HasLabel(label, memgraph::storage::View::NEW).GetValue()); - ASSERT_EQ(vertex->Labels(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(vertex->Labels(memgraph::storage::View::NEW)->size(), 0); - - auto other_label = acc.NameToLabel("other"); - - ASSERT_FALSE(vertex->HasLabel(other_label, memgraph::storage::View::OLD).GetValue()); - ASSERT_FALSE(vertex->HasLabel(other_label, memgraph::storage::View::NEW).GetValue()); - - acc.Abort(); - } - - // Add label 5. - { - auto acc = store.Access(); - auto vertex = acc.FindVertex(gid, memgraph::storage::View::OLD); - ASSERT_TRUE(vertex); - - auto label = acc.NameToLabel("label5"); - - ASSERT_FALSE(vertex->HasLabel(label, memgraph::storage::View::NEW).GetValue()); - ASSERT_EQ(vertex->Labels(memgraph::storage::View::NEW)->size(), 0); - - { - auto res = vertex->AddLabel(label); - ASSERT_TRUE(res.HasValue()); - ASSERT_TRUE(res.GetValue()); - } - - ASSERT_TRUE(vertex->HasLabel(label, memgraph::storage::View::NEW).GetValue()); - { - auto labels = vertex->Labels(memgraph::storage::View::NEW).GetValue(); - ASSERT_EQ(labels.size(), 1); - ASSERT_EQ(labels[0], label); - } - - { - auto res = vertex->AddLabel(label); - ASSERT_TRUE(res.HasValue()); - ASSERT_FALSE(res.GetValue()); - } - - ASSERT_FALSE(acc.Commit().HasError()); - } - - // Check that label 5 exists. - { - auto acc = store.Access(); - auto vertex = acc.FindVertex(gid, memgraph::storage::View::OLD); - ASSERT_TRUE(vertex); - - auto label = acc.NameToLabel("label5"); - - ASSERT_TRUE(vertex->HasLabel(label, memgraph::storage::View::OLD).GetValue()); - { - auto labels = vertex->Labels(memgraph::storage::View::OLD).GetValue(); - ASSERT_EQ(labels.size(), 1); - ASSERT_EQ(labels[0], label); - } - - ASSERT_TRUE(vertex->HasLabel(label, memgraph::storage::View::NEW).GetValue()); - { - auto labels = vertex->Labels(memgraph::storage::View::NEW).GetValue(); - ASSERT_EQ(labels.size(), 1); - ASSERT_EQ(labels[0], label); - } - - auto other_label = acc.NameToLabel("other"); - - ASSERT_FALSE(vertex->HasLabel(other_label, memgraph::storage::View::OLD).GetValue()); - ASSERT_FALSE(vertex->HasLabel(other_label, memgraph::storage::View::NEW).GetValue()); - - acc.Abort(); - } - - // Remove label 5, but abort the transaction. - { - auto acc = store.Access(); - auto vertex = acc.FindVertex(gid, memgraph::storage::View::OLD); - ASSERT_TRUE(vertex); - - auto label = acc.NameToLabel("label5"); - - { - auto res = vertex->RemoveLabel(label); - ASSERT_TRUE(res.HasValue()); - ASSERT_TRUE(res.GetValue()); - } - - ASSERT_TRUE(vertex->HasLabel(label, memgraph::storage::View::OLD).GetValue()); - { - auto labels = vertex->Labels(memgraph::storage::View::OLD).GetValue(); - ASSERT_EQ(labels.size(), 1); - ASSERT_EQ(labels[0], label); - } - - ASSERT_FALSE(vertex->HasLabel(label, memgraph::storage::View::NEW).GetValue()); - ASSERT_EQ(vertex->Labels(memgraph::storage::View::NEW)->size(), 0); - - { - auto res = vertex->RemoveLabel(label); - ASSERT_TRUE(res.HasValue()); - ASSERT_FALSE(res.GetValue()); - } - - acc.Abort(); - } - - // Check that label 5 exists. - { - auto acc = store.Access(); - auto vertex = acc.FindVertex(gid, memgraph::storage::View::OLD); - ASSERT_TRUE(vertex); - - auto label = acc.NameToLabel("label5"); - - ASSERT_TRUE(vertex->HasLabel(label, memgraph::storage::View::OLD).GetValue()); - { - auto labels = vertex->Labels(memgraph::storage::View::OLD).GetValue(); - ASSERT_EQ(labels.size(), 1); - ASSERT_EQ(labels[0], label); - } - - ASSERT_TRUE(vertex->HasLabel(label, memgraph::storage::View::NEW).GetValue()); - { - auto labels = vertex->Labels(memgraph::storage::View::NEW).GetValue(); - ASSERT_EQ(labels.size(), 1); - ASSERT_EQ(labels[0], label); - } - - auto other_label = acc.NameToLabel("other"); - - ASSERT_FALSE(vertex->HasLabel(other_label, memgraph::storage::View::OLD).GetValue()); - ASSERT_FALSE(vertex->HasLabel(other_label, memgraph::storage::View::NEW).GetValue()); - - acc.Abort(); - } - - // Remove label 5. - { - auto acc = store.Access(); - auto vertex = acc.FindVertex(gid, memgraph::storage::View::OLD); - ASSERT_TRUE(vertex); - - auto label = acc.NameToLabel("label5"); - - { - auto res = vertex->RemoveLabel(label); - ASSERT_TRUE(res.HasValue()); - ASSERT_TRUE(res.GetValue()); - } - - ASSERT_TRUE(vertex->HasLabel(label, memgraph::storage::View::OLD).GetValue()); - { - auto labels = vertex->Labels(memgraph::storage::View::OLD).GetValue(); - ASSERT_EQ(labels.size(), 1); - ASSERT_EQ(labels[0], label); - } - - ASSERT_FALSE(vertex->HasLabel(label, memgraph::storage::View::NEW).GetValue()); - ASSERT_EQ(vertex->Labels(memgraph::storage::View::NEW)->size(), 0); - - { - auto res = vertex->RemoveLabel(label); - ASSERT_TRUE(res.HasValue()); - ASSERT_FALSE(res.GetValue()); - } - - ASSERT_FALSE(acc.Commit().HasError()); - } - - // Check that label 5 doesn't exist. - { - auto acc = store.Access(); - auto vertex = acc.FindVertex(gid, memgraph::storage::View::OLD); - ASSERT_TRUE(vertex); - - auto label = acc.NameToLabel("label5"); - - ASSERT_FALSE(vertex->HasLabel(label, memgraph::storage::View::OLD).GetValue()); - ASSERT_FALSE(vertex->HasLabel(label, memgraph::storage::View::NEW).GetValue()); - ASSERT_EQ(vertex->Labels(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(vertex->Labels(memgraph::storage::View::NEW)->size(), 0); - - auto other_label = acc.NameToLabel("other"); - - ASSERT_FALSE(vertex->HasLabel(other_label, memgraph::storage::View::OLD).GetValue()); - ASSERT_FALSE(vertex->HasLabel(other_label, memgraph::storage::View::NEW).GetValue()); - - acc.Abort(); - } -} - -// NOLINTNEXTLINE(hicpp-special-member-functions) -TEST(StorageV2, VertexLabelSerializationError) { - memgraph::storage::Storage store; - memgraph::storage::Gid gid = memgraph::storage::Gid::FromUint(std::numeric_limits::max()); - { - auto acc = store.Access(); - auto vertex = acc.CreateVertex(); - gid = vertex.Gid(); - ASSERT_FALSE(acc.Commit().HasError()); - } - - auto acc1 = store.Access(); - auto acc2 = store.Access(); - - // Add label 1 in accessor 1. - { - auto vertex = acc1.FindVertex(gid, memgraph::storage::View::OLD); - ASSERT_TRUE(vertex); - - auto label1 = acc1.NameToLabel("label1"); - auto label2 = acc1.NameToLabel("label2"); - - ASSERT_FALSE(vertex->HasLabel(label1, memgraph::storage::View::OLD).GetValue()); - ASSERT_FALSE(vertex->HasLabel(label1, memgraph::storage::View::NEW).GetValue()); - ASSERT_FALSE(vertex->HasLabel(label2, memgraph::storage::View::OLD).GetValue()); - ASSERT_FALSE(vertex->HasLabel(label2, memgraph::storage::View::NEW).GetValue()); - ASSERT_EQ(vertex->Labels(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(vertex->Labels(memgraph::storage::View::NEW)->size(), 0); - - { - auto res = vertex->AddLabel(label1); - ASSERT_TRUE(res.HasValue()); - ASSERT_TRUE(res.GetValue()); - } - - ASSERT_FALSE(vertex->HasLabel(label1, memgraph::storage::View::OLD).GetValue()); - ASSERT_TRUE(vertex->HasLabel(label1, memgraph::storage::View::NEW).GetValue()); - ASSERT_FALSE(vertex->HasLabel(label2, memgraph::storage::View::OLD).GetValue()); - ASSERT_FALSE(vertex->HasLabel(label2, memgraph::storage::View::NEW).GetValue()); - ASSERT_EQ(vertex->Labels(memgraph::storage::View::OLD)->size(), 0); - { - auto labels = vertex->Labels(memgraph::storage::View::NEW).GetValue(); - ASSERT_EQ(labels.size(), 1); - ASSERT_EQ(labels[0], label1); - } - - { - auto res = vertex->AddLabel(label1); - ASSERT_TRUE(res.HasValue()); - ASSERT_FALSE(res.GetValue()); - } - } - - // Add label 2 in accessor 2. - { - auto vertex = acc2.FindVertex(gid, memgraph::storage::View::OLD); - ASSERT_TRUE(vertex); - - auto label1 = acc2.NameToLabel("label1"); - auto label2 = acc2.NameToLabel("label2"); - - ASSERT_FALSE(vertex->HasLabel(label1, memgraph::storage::View::OLD).GetValue()); - ASSERT_FALSE(vertex->HasLabel(label1, memgraph::storage::View::NEW).GetValue()); - ASSERT_FALSE(vertex->HasLabel(label2, memgraph::storage::View::OLD).GetValue()); - ASSERT_FALSE(vertex->HasLabel(label2, memgraph::storage::View::NEW).GetValue()); - ASSERT_EQ(vertex->Labels(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(vertex->Labels(memgraph::storage::View::NEW)->size(), 0); - - { - auto res = vertex->AddLabel(label1); - ASSERT_TRUE(res.HasError()); - ASSERT_EQ(res.GetError(), memgraph::storage::Error::SERIALIZATION_ERROR); - } - } - - // Finalize both accessors. - ASSERT_FALSE(acc1.Commit().HasError()); - acc2.Abort(); - - // Check which labels exist. - { - auto acc = store.Access(); - auto vertex = acc.FindVertex(gid, memgraph::storage::View::OLD); - ASSERT_TRUE(vertex); - - auto label1 = acc.NameToLabel("label1"); - auto label2 = acc.NameToLabel("label2"); - - ASSERT_TRUE(vertex->HasLabel(label1, memgraph::storage::View::OLD).GetValue()); - ASSERT_FALSE(vertex->HasLabel(label2, memgraph::storage::View::OLD).GetValue()); - { - auto labels = vertex->Labels(memgraph::storage::View::OLD).GetValue(); - ASSERT_EQ(labels.size(), 1); - ASSERT_EQ(labels[0], label1); - } - - ASSERT_TRUE(vertex->HasLabel(label1, memgraph::storage::View::NEW).GetValue()); - ASSERT_FALSE(vertex->HasLabel(label2, memgraph::storage::View::NEW).GetValue()); - { - auto labels = vertex->Labels(memgraph::storage::View::NEW).GetValue(); - ASSERT_EQ(labels.size(), 1); - ASSERT_EQ(labels[0], label1); - } - - acc.Abort(); - } -} - -// NOLINTNEXTLINE(hicpp-special-member-functions) -TEST(StorageV2, VertexPropertyCommit) { - memgraph::storage::Storage store; - memgraph::storage::Gid gid = memgraph::storage::Gid::FromUint(std::numeric_limits::max()); - { - auto acc = store.Access(); - auto vertex = acc.CreateVertex(); - gid = vertex.Gid(); - - auto property = acc.NameToProperty("property5"); - - ASSERT_TRUE(vertex.GetProperty(property, memgraph::storage::View::NEW)->IsNull()); - ASSERT_EQ(vertex.Properties(memgraph::storage::View::NEW)->size(), 0); - - { - auto old_value = vertex.SetProperty(property, memgraph::storage::PropertyValue("temporary")); - ASSERT_TRUE(old_value.HasValue()); - ASSERT_TRUE(old_value->IsNull()); - } - - ASSERT_EQ(vertex.GetProperty(property, memgraph::storage::View::NEW)->ValueString(), "temporary"); - { - auto properties = vertex.Properties(memgraph::storage::View::NEW).GetValue(); - ASSERT_EQ(properties.size(), 1); - ASSERT_EQ(properties[property].ValueString(), "temporary"); - } - - { - auto old_value = vertex.SetProperty(property, memgraph::storage::PropertyValue("nandare")); - ASSERT_TRUE(old_value.HasValue()); - ASSERT_FALSE(old_value->IsNull()); - } - - ASSERT_EQ(vertex.GetProperty(property, memgraph::storage::View::NEW)->ValueString(), "nandare"); - { - auto properties = vertex.Properties(memgraph::storage::View::NEW).GetValue(); - ASSERT_EQ(properties.size(), 1); - ASSERT_EQ(properties[property].ValueString(), "nandare"); - } - - ASSERT_FALSE(acc.Commit().HasError()); - } - { - auto acc = store.Access(); - auto vertex = acc.FindVertex(gid, memgraph::storage::View::OLD); - ASSERT_TRUE(vertex); - - auto property = acc.NameToProperty("property5"); - - ASSERT_EQ(vertex->GetProperty(property, memgraph::storage::View::OLD)->ValueString(), "nandare"); - { - auto properties = vertex->Properties(memgraph::storage::View::OLD).GetValue(); - ASSERT_EQ(properties.size(), 1); - ASSERT_EQ(properties[property].ValueString(), "nandare"); - } - - ASSERT_EQ(vertex->GetProperty(property, memgraph::storage::View::NEW)->ValueString(), "nandare"); - { - auto properties = vertex->Properties(memgraph::storage::View::NEW).GetValue(); - ASSERT_EQ(properties.size(), 1); - ASSERT_EQ(properties[property].ValueString(), "nandare"); - } - - auto other_property = acc.NameToProperty("other"); - - ASSERT_TRUE(vertex->GetProperty(other_property, memgraph::storage::View::OLD)->IsNull()); - ASSERT_TRUE(vertex->GetProperty(other_property, memgraph::storage::View::NEW)->IsNull()); - - acc.Abort(); - } - { - auto acc = store.Access(); - auto vertex = acc.FindVertex(gid, memgraph::storage::View::OLD); - ASSERT_TRUE(vertex); - - auto property = acc.NameToProperty("property5"); - - { - auto old_value = vertex->SetProperty(property, memgraph::storage::PropertyValue()); - ASSERT_TRUE(old_value.HasValue()); - ASSERT_FALSE(old_value->IsNull()); - } - - ASSERT_EQ(vertex->GetProperty(property, memgraph::storage::View::OLD)->ValueString(), "nandare"); - { - auto properties = vertex->Properties(memgraph::storage::View::OLD).GetValue(); - ASSERT_EQ(properties.size(), 1); - ASSERT_EQ(properties[property].ValueString(), "nandare"); - } - - ASSERT_TRUE(vertex->GetProperty(property, memgraph::storage::View::NEW)->IsNull()); - ASSERT_EQ(vertex->Properties(memgraph::storage::View::NEW)->size(), 0); - - { - auto old_value = vertex->SetProperty(property, memgraph::storage::PropertyValue()); - ASSERT_TRUE(old_value.HasValue()); - ASSERT_TRUE(old_value->IsNull()); - } - - ASSERT_FALSE(acc.Commit().HasError()); - } - { - auto acc = store.Access(); - auto vertex = acc.FindVertex(gid, memgraph::storage::View::OLD); - ASSERT_TRUE(vertex); - - auto property = acc.NameToProperty("property5"); - - ASSERT_TRUE(vertex->GetProperty(property, memgraph::storage::View::OLD)->IsNull()); - ASSERT_TRUE(vertex->GetProperty(property, memgraph::storage::View::NEW)->IsNull()); - ASSERT_EQ(vertex->Properties(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(vertex->Properties(memgraph::storage::View::NEW)->size(), 0); - - auto other_property = acc.NameToProperty("other"); - - ASSERT_TRUE(vertex->GetProperty(other_property, memgraph::storage::View::OLD)->IsNull()); - ASSERT_TRUE(vertex->GetProperty(other_property, memgraph::storage::View::NEW)->IsNull()); - - acc.Abort(); - } -} - -// NOLINTNEXTLINE(hicpp-special-member-functions) -TEST(StorageV2, VertexPropertyAbort) { - memgraph::storage::Storage store; - memgraph::storage::Gid gid = memgraph::storage::Gid::FromUint(std::numeric_limits::max()); - - // Create the vertex. - { - auto acc = store.Access(); - auto vertex = acc.CreateVertex(); - gid = vertex.Gid(); - ASSERT_FALSE(acc.Commit().HasError()); - } - - // Set property 5 to "nandare", but abort the transaction. - { - auto acc = store.Access(); - auto vertex = acc.FindVertex(gid, memgraph::storage::View::OLD); - ASSERT_TRUE(vertex); - - auto property = acc.NameToProperty("property5"); - - ASSERT_TRUE(vertex->GetProperty(property, memgraph::storage::View::NEW)->IsNull()); - ASSERT_EQ(vertex->Properties(memgraph::storage::View::NEW)->size(), 0); - - { - auto old_value = vertex->SetProperty(property, memgraph::storage::PropertyValue("temporary")); - ASSERT_TRUE(old_value.HasValue()); - ASSERT_TRUE(old_value->IsNull()); - } - - ASSERT_EQ(vertex->GetProperty(property, memgraph::storage::View::NEW)->ValueString(), "temporary"); - { - auto properties = vertex->Properties(memgraph::storage::View::NEW).GetValue(); - ASSERT_EQ(properties.size(), 1); - ASSERT_EQ(properties[property].ValueString(), "temporary"); - } - - { - auto old_value = vertex->SetProperty(property, memgraph::storage::PropertyValue("nandare")); - ASSERT_TRUE(old_value.HasValue()); - ASSERT_FALSE(old_value->IsNull()); - } - - ASSERT_EQ(vertex->GetProperty(property, memgraph::storage::View::NEW)->ValueString(), "nandare"); - { - auto properties = vertex->Properties(memgraph::storage::View::NEW).GetValue(); - ASSERT_EQ(properties.size(), 1); - ASSERT_EQ(properties[property].ValueString(), "nandare"); - } - - acc.Abort(); - } - - // Check that property 5 is null. - { - auto acc = store.Access(); - auto vertex = acc.FindVertex(gid, memgraph::storage::View::OLD); - ASSERT_TRUE(vertex); - - auto property = acc.NameToProperty("property5"); - - ASSERT_TRUE(vertex->GetProperty(property, memgraph::storage::View::OLD)->IsNull()); - ASSERT_TRUE(vertex->GetProperty(property, memgraph::storage::View::NEW)->IsNull()); - ASSERT_EQ(vertex->Properties(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(vertex->Properties(memgraph::storage::View::NEW)->size(), 0); - - auto other_property = acc.NameToProperty("other"); - - ASSERT_TRUE(vertex->GetProperty(other_property, memgraph::storage::View::OLD)->IsNull()); - ASSERT_TRUE(vertex->GetProperty(other_property, memgraph::storage::View::NEW)->IsNull()); - - acc.Abort(); - } - - // Set property 5 to "nandare". - { - auto acc = store.Access(); - auto vertex = acc.FindVertex(gid, memgraph::storage::View::OLD); - ASSERT_TRUE(vertex); - - auto property = acc.NameToProperty("property5"); - - ASSERT_TRUE(vertex->GetProperty(property, memgraph::storage::View::NEW)->IsNull()); - ASSERT_EQ(vertex->Properties(memgraph::storage::View::NEW)->size(), 0); - - { - auto old_value = vertex->SetProperty(property, memgraph::storage::PropertyValue("temporary")); - ASSERT_TRUE(old_value.HasValue()); - ASSERT_TRUE(old_value->IsNull()); - } - - ASSERT_EQ(vertex->GetProperty(property, memgraph::storage::View::NEW)->ValueString(), "temporary"); - { - auto properties = vertex->Properties(memgraph::storage::View::NEW).GetValue(); - ASSERT_EQ(properties.size(), 1); - ASSERT_EQ(properties[property].ValueString(), "temporary"); - } - - { - auto old_value = vertex->SetProperty(property, memgraph::storage::PropertyValue("nandare")); - ASSERT_TRUE(old_value.HasValue()); - ASSERT_FALSE(old_value->IsNull()); - } - - ASSERT_EQ(vertex->GetProperty(property, memgraph::storage::View::NEW)->ValueString(), "nandare"); - { - auto properties = vertex->Properties(memgraph::storage::View::NEW).GetValue(); - ASSERT_EQ(properties.size(), 1); - ASSERT_EQ(properties[property].ValueString(), "nandare"); - } - - ASSERT_FALSE(acc.Commit().HasError()); - } - - // Check that property 5 is "nandare". - { - auto acc = store.Access(); - auto vertex = acc.FindVertex(gid, memgraph::storage::View::OLD); - ASSERT_TRUE(vertex); - - auto property = acc.NameToProperty("property5"); - - ASSERT_EQ(vertex->GetProperty(property, memgraph::storage::View::OLD)->ValueString(), "nandare"); - { - auto properties = vertex->Properties(memgraph::storage::View::OLD).GetValue(); - ASSERT_EQ(properties.size(), 1); - ASSERT_EQ(properties[property].ValueString(), "nandare"); - } - - ASSERT_EQ(vertex->GetProperty(property, memgraph::storage::View::NEW)->ValueString(), "nandare"); - { - auto properties = vertex->Properties(memgraph::storage::View::NEW).GetValue(); - ASSERT_EQ(properties.size(), 1); - ASSERT_EQ(properties[property].ValueString(), "nandare"); - } - - auto other_property = acc.NameToProperty("other"); - - ASSERT_TRUE(vertex->GetProperty(other_property, memgraph::storage::View::OLD)->IsNull()); - ASSERT_TRUE(vertex->GetProperty(other_property, memgraph::storage::View::NEW)->IsNull()); - - acc.Abort(); - } - - // Set property 5 to null, but abort the transaction. - { - auto acc = store.Access(); - auto vertex = acc.FindVertex(gid, memgraph::storage::View::OLD); - ASSERT_TRUE(vertex); - - auto property = acc.NameToProperty("property5"); - - ASSERT_EQ(vertex->GetProperty(property, memgraph::storage::View::OLD)->ValueString(), "nandare"); - { - auto properties = vertex->Properties(memgraph::storage::View::OLD).GetValue(); - ASSERT_EQ(properties.size(), 1); - ASSERT_EQ(properties[property].ValueString(), "nandare"); - } - - ASSERT_EQ(vertex->GetProperty(property, memgraph::storage::View::NEW)->ValueString(), "nandare"); - { - auto properties = vertex->Properties(memgraph::storage::View::NEW).GetValue(); - ASSERT_EQ(properties.size(), 1); - ASSERT_EQ(properties[property].ValueString(), "nandare"); - } - - { - auto old_value = vertex->SetProperty(property, memgraph::storage::PropertyValue()); - ASSERT_TRUE(old_value.HasValue()); - ASSERT_FALSE(old_value->IsNull()); - } - - ASSERT_EQ(vertex->GetProperty(property, memgraph::storage::View::OLD)->ValueString(), "nandare"); - { - auto properties = vertex->Properties(memgraph::storage::View::OLD).GetValue(); - ASSERT_EQ(properties.size(), 1); - ASSERT_EQ(properties[property].ValueString(), "nandare"); - } - - ASSERT_TRUE(vertex->GetProperty(property, memgraph::storage::View::NEW)->IsNull()); - ASSERT_EQ(vertex->Properties(memgraph::storage::View::NEW)->size(), 0); - - acc.Abort(); - } - - // Check that property 5 is "nandare". - { - auto acc = store.Access(); - auto vertex = acc.FindVertex(gid, memgraph::storage::View::OLD); - ASSERT_TRUE(vertex); - - auto property = acc.NameToProperty("property5"); - - ASSERT_EQ(vertex->GetProperty(property, memgraph::storage::View::OLD)->ValueString(), "nandare"); - { - auto properties = vertex->Properties(memgraph::storage::View::OLD).GetValue(); - ASSERT_EQ(properties.size(), 1); - ASSERT_EQ(properties[property].ValueString(), "nandare"); - } - - ASSERT_EQ(vertex->GetProperty(property, memgraph::storage::View::NEW)->ValueString(), "nandare"); - { - auto properties = vertex->Properties(memgraph::storage::View::NEW).GetValue(); - ASSERT_EQ(properties.size(), 1); - ASSERT_EQ(properties[property].ValueString(), "nandare"); - } - - auto other_property = acc.NameToProperty("other"); - - ASSERT_TRUE(vertex->GetProperty(other_property, memgraph::storage::View::OLD)->IsNull()); - ASSERT_TRUE(vertex->GetProperty(other_property, memgraph::storage::View::NEW)->IsNull()); - - acc.Abort(); - } - - // Set property 5 to null. - { - auto acc = store.Access(); - auto vertex = acc.FindVertex(gid, memgraph::storage::View::OLD); - ASSERT_TRUE(vertex); - - auto property = acc.NameToProperty("property5"); - - ASSERT_EQ(vertex->GetProperty(property, memgraph::storage::View::OLD)->ValueString(), "nandare"); - { - auto properties = vertex->Properties(memgraph::storage::View::OLD).GetValue(); - ASSERT_EQ(properties.size(), 1); - ASSERT_EQ(properties[property].ValueString(), "nandare"); - } - - ASSERT_EQ(vertex->GetProperty(property, memgraph::storage::View::NEW)->ValueString(), "nandare"); - { - auto properties = vertex->Properties(memgraph::storage::View::NEW).GetValue(); - ASSERT_EQ(properties.size(), 1); - ASSERT_EQ(properties[property].ValueString(), "nandare"); - } - - { - auto old_value = vertex->SetProperty(property, memgraph::storage::PropertyValue()); - ASSERT_TRUE(old_value.HasValue()); - ASSERT_FALSE(old_value->IsNull()); - } - - ASSERT_EQ(vertex->GetProperty(property, memgraph::storage::View::OLD)->ValueString(), "nandare"); - { - auto properties = vertex->Properties(memgraph::storage::View::OLD).GetValue(); - ASSERT_EQ(properties.size(), 1); - ASSERT_EQ(properties[property].ValueString(), "nandare"); - } - - ASSERT_TRUE(vertex->GetProperty(property, memgraph::storage::View::NEW)->IsNull()); - ASSERT_EQ(vertex->Properties(memgraph::storage::View::NEW)->size(), 0); - - ASSERT_FALSE(acc.Commit().HasError()); - } - - // Check that property 5 is null. - { - auto acc = store.Access(); - auto vertex = acc.FindVertex(gid, memgraph::storage::View::OLD); - ASSERT_TRUE(vertex); - - auto property = acc.NameToProperty("property5"); - - ASSERT_TRUE(vertex->GetProperty(property, memgraph::storage::View::OLD)->IsNull()); - ASSERT_TRUE(vertex->GetProperty(property, memgraph::storage::View::NEW)->IsNull()); - ASSERT_EQ(vertex->Properties(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(vertex->Properties(memgraph::storage::View::NEW)->size(), 0); - - auto other_property = acc.NameToProperty("other"); - - ASSERT_TRUE(vertex->GetProperty(other_property, memgraph::storage::View::OLD)->IsNull()); - ASSERT_TRUE(vertex->GetProperty(other_property, memgraph::storage::View::NEW)->IsNull()); - - acc.Abort(); - } -} - -// NOLINTNEXTLINE(hicpp-special-member-functions) -TEST(StorageV2, VertexPropertySerializationError) { - memgraph::storage::Storage store; - memgraph::storage::Gid gid = memgraph::storage::Gid::FromUint(std::numeric_limits::max()); - { - auto acc = store.Access(); - auto vertex = acc.CreateVertex(); - gid = vertex.Gid(); - ASSERT_FALSE(acc.Commit().HasError()); - } - - auto acc1 = store.Access(); - auto acc2 = store.Access(); - - // Set property 1 to 123 in accessor 1. - { - auto vertex = acc1.FindVertex(gid, memgraph::storage::View::OLD); - ASSERT_TRUE(vertex); - - auto property1 = acc1.NameToProperty("property1"); - auto property2 = acc1.NameToProperty("property2"); - - ASSERT_TRUE(vertex->GetProperty(property1, memgraph::storage::View::OLD)->IsNull()); - ASSERT_TRUE(vertex->GetProperty(property1, memgraph::storage::View::NEW)->IsNull()); - ASSERT_TRUE(vertex->GetProperty(property2, memgraph::storage::View::OLD)->IsNull()); - ASSERT_TRUE(vertex->GetProperty(property2, memgraph::storage::View::NEW)->IsNull()); - ASSERT_EQ(vertex->Properties(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(vertex->Properties(memgraph::storage::View::NEW)->size(), 0); - - { - auto old_value = vertex->SetProperty(property1, memgraph::storage::PropertyValue(123)); - ASSERT_TRUE(old_value.HasValue()); - ASSERT_TRUE(old_value->IsNull()); - } - - ASSERT_TRUE(vertex->GetProperty(property1, memgraph::storage::View::OLD)->IsNull()); - ASSERT_EQ(vertex->GetProperty(property1, memgraph::storage::View::NEW)->ValueInt(), 123); - ASSERT_TRUE(vertex->GetProperty(property2, memgraph::storage::View::OLD)->IsNull()); - ASSERT_TRUE(vertex->GetProperty(property2, memgraph::storage::View::NEW)->IsNull()); - ASSERT_EQ(vertex->Properties(memgraph::storage::View::OLD)->size(), 0); - { - auto properties = vertex->Properties(memgraph::storage::View::NEW).GetValue(); - ASSERT_EQ(properties.size(), 1); - ASSERT_EQ(properties[property1].ValueInt(), 123); - } - } - - // Set property 2 to "nandare" in accessor 2. - { - auto vertex = acc2.FindVertex(gid, memgraph::storage::View::OLD); - ASSERT_TRUE(vertex); - - auto property1 = acc2.NameToProperty("property1"); - auto property2 = acc2.NameToProperty("property2"); - - ASSERT_TRUE(vertex->GetProperty(property1, memgraph::storage::View::OLD)->IsNull()); - ASSERT_TRUE(vertex->GetProperty(property1, memgraph::storage::View::NEW)->IsNull()); - ASSERT_TRUE(vertex->GetProperty(property2, memgraph::storage::View::OLD)->IsNull()); - ASSERT_TRUE(vertex->GetProperty(property2, memgraph::storage::View::NEW)->IsNull()); - ASSERT_EQ(vertex->Properties(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(vertex->Properties(memgraph::storage::View::NEW)->size(), 0); - - { - auto res = vertex->SetProperty(property2, memgraph::storage::PropertyValue("nandare")); - ASSERT_TRUE(res.HasError()); - ASSERT_EQ(res.GetError(), memgraph::storage::Error::SERIALIZATION_ERROR); - } - } - - // Finalize both accessors. - ASSERT_FALSE(acc1.Commit().HasError()); - acc2.Abort(); - - // Check which properties exist. - { - auto acc = store.Access(); - auto vertex = acc.FindVertex(gid, memgraph::storage::View::OLD); - ASSERT_TRUE(vertex); - - auto property1 = acc.NameToProperty("property1"); - auto property2 = acc.NameToProperty("property2"); - - ASSERT_EQ(vertex->GetProperty(property1, memgraph::storage::View::OLD)->ValueInt(), 123); - ASSERT_TRUE(vertex->GetProperty(property2, memgraph::storage::View::OLD)->IsNull()); - { - auto properties = vertex->Properties(memgraph::storage::View::OLD).GetValue(); - ASSERT_EQ(properties.size(), 1); - ASSERT_EQ(properties[property1].ValueInt(), 123); - } - - ASSERT_EQ(vertex->GetProperty(property1, memgraph::storage::View::NEW)->ValueInt(), 123); - ASSERT_TRUE(vertex->GetProperty(property2, memgraph::storage::View::NEW)->IsNull()); - { - auto properties = vertex->Properties(memgraph::storage::View::NEW).GetValue(); - ASSERT_EQ(properties.size(), 1); - ASSERT_EQ(properties[property1].ValueInt(), 123); - } - - acc.Abort(); - } -} - -// NOLINTNEXTLINE(hicpp-special-member-functions) -TEST(StorageV2, VertexLabelPropertyMixed) { - memgraph::storage::Storage store; - auto acc = store.Access(); - auto vertex = acc.CreateVertex(); - - auto label = acc.NameToLabel("label5"); - auto property = acc.NameToProperty("property5"); - - // Check whether label 5 and property 5 exist - ASSERT_FALSE(vertex.HasLabel(label, memgraph::storage::View::NEW).GetValue()); - ASSERT_EQ(vertex.Labels(memgraph::storage::View::NEW)->size(), 0); - ASSERT_TRUE(vertex.GetProperty(property, memgraph::storage::View::NEW)->IsNull()); - ASSERT_EQ(vertex.Properties(memgraph::storage::View::NEW)->size(), 0); - - // Add label 5 - ASSERT_TRUE(vertex.AddLabel(label).GetValue()); - - // Check whether label 5 and property 5 exist - ASSERT_TRUE(vertex.HasLabel(label, memgraph::storage::View::NEW).GetValue()); - { - auto labels = vertex.Labels(memgraph::storage::View::NEW).GetValue(); - ASSERT_EQ(labels.size(), 1); - ASSERT_EQ(labels[0], label); - } - ASSERT_TRUE(vertex.GetProperty(property, memgraph::storage::View::NEW)->IsNull()); - ASSERT_EQ(vertex.Properties(memgraph::storage::View::NEW)->size(), 0); - - // Advance command - acc.AdvanceCommand(); - - // Check whether label 5 and property 5 exist - ASSERT_TRUE(vertex.HasLabel(label, memgraph::storage::View::OLD).GetValue()); - ASSERT_TRUE(vertex.HasLabel(label, memgraph::storage::View::NEW).GetValue()); - { - auto labels = vertex.Labels(memgraph::storage::View::OLD).GetValue(); - ASSERT_EQ(labels.size(), 1); - ASSERT_EQ(labels[0], label); - } - { - auto labels = vertex.Labels(memgraph::storage::View::NEW).GetValue(); - ASSERT_EQ(labels.size(), 1); - ASSERT_EQ(labels[0], label); - } - ASSERT_TRUE(vertex.GetProperty(property, memgraph::storage::View::OLD)->IsNull()); - ASSERT_TRUE(vertex.GetProperty(property, memgraph::storage::View::NEW)->IsNull()); - ASSERT_EQ(vertex.Properties(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(vertex.Properties(memgraph::storage::View::NEW)->size(), 0); - - // Set property 5 to "nandare" - ASSERT_TRUE(vertex.SetProperty(property, memgraph::storage::PropertyValue("nandare"))->IsNull()); - - // Check whether label 5 and property 5 exist - ASSERT_TRUE(vertex.HasLabel(label, memgraph::storage::View::OLD).GetValue()); - ASSERT_TRUE(vertex.HasLabel(label, memgraph::storage::View::NEW).GetValue()); - { - auto labels = vertex.Labels(memgraph::storage::View::OLD).GetValue(); - ASSERT_EQ(labels.size(), 1); - ASSERT_EQ(labels[0], label); - } - { - auto labels = vertex.Labels(memgraph::storage::View::NEW).GetValue(); - ASSERT_EQ(labels.size(), 1); - ASSERT_EQ(labels[0], label); - } - ASSERT_TRUE(vertex.GetProperty(property, memgraph::storage::View::OLD)->IsNull()); - ASSERT_EQ(vertex.GetProperty(property, memgraph::storage::View::NEW)->ValueString(), "nandare"); - ASSERT_EQ(vertex.Properties(memgraph::storage::View::OLD)->size(), 0); - { - auto properties = vertex.Properties(memgraph::storage::View::NEW).GetValue(); - ASSERT_EQ(properties.size(), 1); - ASSERT_EQ(properties[property].ValueString(), "nandare"); - } - - // Advance command - acc.AdvanceCommand(); - - // Check whether label 5 and property 5 exist - ASSERT_TRUE(vertex.HasLabel(label, memgraph::storage::View::OLD).GetValue()); - ASSERT_TRUE(vertex.HasLabel(label, memgraph::storage::View::NEW).GetValue()); - { - auto labels = vertex.Labels(memgraph::storage::View::OLD).GetValue(); - ASSERT_EQ(labels.size(), 1); - ASSERT_EQ(labels[0], label); - } - { - auto labels = vertex.Labels(memgraph::storage::View::NEW).GetValue(); - ASSERT_EQ(labels.size(), 1); - ASSERT_EQ(labels[0], label); - } - ASSERT_EQ(vertex.GetProperty(property, memgraph::storage::View::OLD)->ValueString(), "nandare"); - ASSERT_EQ(vertex.GetProperty(property, memgraph::storage::View::NEW)->ValueString(), "nandare"); - { - auto properties = vertex.Properties(memgraph::storage::View::OLD).GetValue(); - ASSERT_EQ(properties.size(), 1); - ASSERT_EQ(properties[property].ValueString(), "nandare"); - } - { - auto properties = vertex.Properties(memgraph::storage::View::NEW).GetValue(); - ASSERT_EQ(properties.size(), 1); - ASSERT_EQ(properties[property].ValueString(), "nandare"); - } - - // Set property 5 to "haihai" - ASSERT_FALSE(vertex.SetProperty(property, memgraph::storage::PropertyValue("haihai"))->IsNull()); - - // Check whether label 5 and property 5 exist - ASSERT_TRUE(vertex.HasLabel(label, memgraph::storage::View::OLD).GetValue()); - ASSERT_TRUE(vertex.HasLabel(label, memgraph::storage::View::NEW).GetValue()); - { - auto labels = vertex.Labels(memgraph::storage::View::OLD).GetValue(); - ASSERT_EQ(labels.size(), 1); - ASSERT_EQ(labels[0], label); - } - { - auto labels = vertex.Labels(memgraph::storage::View::NEW).GetValue(); - ASSERT_EQ(labels.size(), 1); - ASSERT_EQ(labels[0], label); - } - ASSERT_EQ(vertex.GetProperty(property, memgraph::storage::View::OLD)->ValueString(), "nandare"); - ASSERT_EQ(vertex.GetProperty(property, memgraph::storage::View::NEW)->ValueString(), "haihai"); - { - auto properties = vertex.Properties(memgraph::storage::View::OLD).GetValue(); - ASSERT_EQ(properties.size(), 1); - ASSERT_EQ(properties[property].ValueString(), "nandare"); - } - { - auto properties = vertex.Properties(memgraph::storage::View::NEW).GetValue(); - ASSERT_EQ(properties.size(), 1); - ASSERT_EQ(properties[property].ValueString(), "haihai"); - } - - // Advance command - acc.AdvanceCommand(); - - // Check whether label 5 and property 5 exist - ASSERT_TRUE(vertex.HasLabel(label, memgraph::storage::View::OLD).GetValue()); - ASSERT_TRUE(vertex.HasLabel(label, memgraph::storage::View::NEW).GetValue()); - { - auto labels = vertex.Labels(memgraph::storage::View::OLD).GetValue(); - ASSERT_EQ(labels.size(), 1); - ASSERT_EQ(labels[0], label); - } - { - auto labels = vertex.Labels(memgraph::storage::View::NEW).GetValue(); - ASSERT_EQ(labels.size(), 1); - ASSERT_EQ(labels[0], label); - } - ASSERT_EQ(vertex.GetProperty(property, memgraph::storage::View::OLD)->ValueString(), "haihai"); - ASSERT_EQ(vertex.GetProperty(property, memgraph::storage::View::NEW)->ValueString(), "haihai"); - { - auto properties = vertex.Properties(memgraph::storage::View::OLD).GetValue(); - ASSERT_EQ(properties.size(), 1); - ASSERT_EQ(properties[property].ValueString(), "haihai"); - } - { - auto properties = vertex.Properties(memgraph::storage::View::NEW).GetValue(); - ASSERT_EQ(properties.size(), 1); - ASSERT_EQ(properties[property].ValueString(), "haihai"); - } - - // Remove label 5 - ASSERT_TRUE(vertex.RemoveLabel(label).GetValue()); - - // Check whether label 5 and property 5 exist - ASSERT_TRUE(vertex.HasLabel(label, memgraph::storage::View::OLD).GetValue()); - ASSERT_FALSE(vertex.HasLabel(label, memgraph::storage::View::NEW).GetValue()); - { - auto labels = vertex.Labels(memgraph::storage::View::OLD).GetValue(); - ASSERT_EQ(labels.size(), 1); - ASSERT_EQ(labels[0], label); - } - ASSERT_EQ(vertex.Labels(memgraph::storage::View::NEW)->size(), 0); - ASSERT_EQ(vertex.GetProperty(property, memgraph::storage::View::OLD)->ValueString(), "haihai"); - ASSERT_EQ(vertex.GetProperty(property, memgraph::storage::View::NEW)->ValueString(), "haihai"); - { - auto properties = vertex.Properties(memgraph::storage::View::OLD).GetValue(); - ASSERT_EQ(properties.size(), 1); - ASSERT_EQ(properties[property].ValueString(), "haihai"); - } - { - auto properties = vertex.Properties(memgraph::storage::View::NEW).GetValue(); - ASSERT_EQ(properties.size(), 1); - ASSERT_EQ(properties[property].ValueString(), "haihai"); - } - - // Advance command - acc.AdvanceCommand(); - - // Check whether label 5 and property 5 exist - ASSERT_FALSE(vertex.HasLabel(label, memgraph::storage::View::OLD).GetValue()); - ASSERT_FALSE(vertex.HasLabel(label, memgraph::storage::View::NEW).GetValue()); - ASSERT_EQ(vertex.Labels(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(vertex.Labels(memgraph::storage::View::NEW)->size(), 0); - ASSERT_EQ(vertex.GetProperty(property, memgraph::storage::View::OLD)->ValueString(), "haihai"); - ASSERT_EQ(vertex.GetProperty(property, memgraph::storage::View::NEW)->ValueString(), "haihai"); - { - auto properties = vertex.Properties(memgraph::storage::View::OLD).GetValue(); - ASSERT_EQ(properties.size(), 1); - ASSERT_EQ(properties[property].ValueString(), "haihai"); - } - { - auto properties = vertex.Properties(memgraph::storage::View::NEW).GetValue(); - ASSERT_EQ(properties.size(), 1); - ASSERT_EQ(properties[property].ValueString(), "haihai"); - } - - // Set property 5 to null - ASSERT_FALSE(vertex.SetProperty(property, memgraph::storage::PropertyValue())->IsNull()); - - // Check whether label 5 and property 5 exist - ASSERT_FALSE(vertex.HasLabel(label, memgraph::storage::View::OLD).GetValue()); - ASSERT_FALSE(vertex.HasLabel(label, memgraph::storage::View::NEW).GetValue()); - ASSERT_EQ(vertex.Labels(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(vertex.Labels(memgraph::storage::View::NEW)->size(), 0); - ASSERT_EQ(vertex.GetProperty(property, memgraph::storage::View::OLD)->ValueString(), "haihai"); - ASSERT_TRUE(vertex.GetProperty(property, memgraph::storage::View::NEW)->IsNull()); - { - auto properties = vertex.Properties(memgraph::storage::View::OLD).GetValue(); - ASSERT_EQ(properties.size(), 1); - ASSERT_EQ(properties[property].ValueString(), "haihai"); - } - ASSERT_EQ(vertex.Properties(memgraph::storage::View::NEW)->size(), 0); - - // Advance command - acc.AdvanceCommand(); - - // Check whether label 5 and property 5 exist - ASSERT_FALSE(vertex.HasLabel(label, memgraph::storage::View::OLD).GetValue()); - ASSERT_FALSE(vertex.HasLabel(label, memgraph::storage::View::NEW).GetValue()); - ASSERT_EQ(vertex.Labels(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(vertex.Labels(memgraph::storage::View::NEW)->size(), 0); - ASSERT_TRUE(vertex.GetProperty(property, memgraph::storage::View::NEW)->IsNull()); - ASSERT_TRUE(vertex.GetProperty(property, memgraph::storage::View::NEW)->IsNull()); - ASSERT_EQ(vertex.Properties(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(vertex.Properties(memgraph::storage::View::NEW)->size(), 0); - - ASSERT_FALSE(acc.Commit().HasError()); -} - -TEST(StorageV2, VertexPropertyClear) { - memgraph::storage::Storage store; - memgraph::storage::Gid gid; - auto property1 = store.NameToProperty("property1"); - auto property2 = store.NameToProperty("property2"); - { - auto acc = store.Access(); - auto vertex = acc.CreateVertex(); - gid = vertex.Gid(); - - auto old_value = vertex.SetProperty(property1, memgraph::storage::PropertyValue("value")); - ASSERT_TRUE(old_value.HasValue()); - ASSERT_TRUE(old_value->IsNull()); - - ASSERT_FALSE(acc.Commit().HasError()); - } - { - auto acc = store.Access(); - auto vertex = acc.FindVertex(gid, memgraph::storage::View::OLD); - ASSERT_TRUE(vertex); - - ASSERT_EQ(vertex->GetProperty(property1, memgraph::storage::View::OLD)->ValueString(), "value"); - ASSERT_TRUE(vertex->GetProperty(property2, memgraph::storage::View::OLD)->IsNull()); - ASSERT_THAT(vertex->Properties(memgraph::storage::View::OLD).GetValue(), - UnorderedElementsAre(std::pair(property1, memgraph::storage::PropertyValue("value")))); - - { - auto old_values = vertex->ClearProperties(); - ASSERT_TRUE(old_values.HasValue()); - ASSERT_FALSE(old_values->empty()); - } - - ASSERT_TRUE(vertex->GetProperty(property1, memgraph::storage::View::NEW)->IsNull()); - ASSERT_TRUE(vertex->GetProperty(property2, memgraph::storage::View::NEW)->IsNull()); - ASSERT_EQ(vertex->Properties(memgraph::storage::View::NEW).GetValue().size(), 0); - - { - auto old_values = vertex->ClearProperties(); - ASSERT_TRUE(old_values.HasValue()); - ASSERT_TRUE(old_values->empty()); - } - - ASSERT_TRUE(vertex->GetProperty(property1, memgraph::storage::View::NEW)->IsNull()); - ASSERT_TRUE(vertex->GetProperty(property2, memgraph::storage::View::NEW)->IsNull()); - ASSERT_EQ(vertex->Properties(memgraph::storage::View::NEW).GetValue().size(), 0); - - acc.Abort(); - } - { - auto acc = store.Access(); - auto vertex = acc.FindVertex(gid, memgraph::storage::View::OLD); - ASSERT_TRUE(vertex); - - auto old_value = vertex->SetProperty(property2, memgraph::storage::PropertyValue(42)); - ASSERT_TRUE(old_value.HasValue()); - ASSERT_TRUE(old_value->IsNull()); - - ASSERT_FALSE(acc.Commit().HasError()); - } - { - auto acc = store.Access(); - auto vertex = acc.FindVertex(gid, memgraph::storage::View::OLD); - ASSERT_TRUE(vertex); - - ASSERT_EQ(vertex->GetProperty(property1, memgraph::storage::View::OLD)->ValueString(), "value"); - ASSERT_EQ(vertex->GetProperty(property2, memgraph::storage::View::OLD)->ValueInt(), 42); - ASSERT_THAT(vertex->Properties(memgraph::storage::View::OLD).GetValue(), - UnorderedElementsAre(std::pair(property1, memgraph::storage::PropertyValue("value")), - std::pair(property2, memgraph::storage::PropertyValue(42)))); - - { - auto old_values = vertex->ClearProperties(); - ASSERT_TRUE(old_values.HasValue()); - ASSERT_FALSE(old_values->empty()); - } - - ASSERT_TRUE(vertex->GetProperty(property1, memgraph::storage::View::NEW)->IsNull()); - ASSERT_TRUE(vertex->GetProperty(property2, memgraph::storage::View::NEW)->IsNull()); - ASSERT_EQ(vertex->Properties(memgraph::storage::View::NEW).GetValue().size(), 0); - - { - auto old_values = vertex->ClearProperties(); - ASSERT_TRUE(old_values.HasValue()); - ASSERT_TRUE(old_values->empty()); - } - - ASSERT_TRUE(vertex->GetProperty(property1, memgraph::storage::View::NEW)->IsNull()); - ASSERT_TRUE(vertex->GetProperty(property2, memgraph::storage::View::NEW)->IsNull()); - ASSERT_EQ(vertex->Properties(memgraph::storage::View::NEW).GetValue().size(), 0); - - ASSERT_FALSE(acc.Commit().HasError()); - } - { - auto acc = store.Access(); - auto vertex = acc.FindVertex(gid, memgraph::storage::View::OLD); - ASSERT_TRUE(vertex); - - ASSERT_TRUE(vertex->GetProperty(property1, memgraph::storage::View::NEW)->IsNull()); - ASSERT_TRUE(vertex->GetProperty(property2, memgraph::storage::View::NEW)->IsNull()); - ASSERT_EQ(vertex->Properties(memgraph::storage::View::NEW).GetValue().size(), 0); - - acc.Abort(); - } -} - -TEST(StorageV2, VertexNonexistentLabelPropertyEdgeAPI) { - memgraph::storage::Storage store; - - auto label = store.NameToLabel("label"); - auto property = store.NameToProperty("property"); - - auto acc = store.Access(); - auto vertex = acc.CreateVertex(); - - // Check state before (OLD view). - ASSERT_EQ(vertex.Labels(memgraph::storage::View::OLD).GetError(), memgraph::storage::Error::NONEXISTENT_OBJECT); - ASSERT_EQ(vertex.HasLabel(label, memgraph::storage::View::OLD).GetError(), - memgraph::storage::Error::NONEXISTENT_OBJECT); - ASSERT_EQ(vertex.Properties(memgraph::storage::View::OLD).GetError(), memgraph::storage::Error::NONEXISTENT_OBJECT); - ASSERT_EQ(vertex.GetProperty(property, memgraph::storage::View::OLD).GetError(), - memgraph::storage::Error::NONEXISTENT_OBJECT); - ASSERT_EQ(vertex.InEdges(memgraph::storage::View::OLD).GetError(), memgraph::storage::Error::NONEXISTENT_OBJECT); - ASSERT_EQ(vertex.OutEdges(memgraph::storage::View::OLD).GetError(), memgraph::storage::Error::NONEXISTENT_OBJECT); - ASSERT_EQ(vertex.InDegree(memgraph::storage::View::OLD).GetError(), memgraph::storage::Error::NONEXISTENT_OBJECT); - ASSERT_EQ(vertex.OutDegree(memgraph::storage::View::OLD).GetError(), memgraph::storage::Error::NONEXISTENT_OBJECT); - - // Check state before (NEW view). - ASSERT_EQ(vertex.Labels(memgraph::storage::View::NEW)->size(), 0); - ASSERT_EQ(*vertex.HasLabel(label, memgraph::storage::View::NEW), false); - ASSERT_EQ(vertex.Properties(memgraph::storage::View::NEW)->size(), 0); - ASSERT_EQ(*vertex.GetProperty(property, memgraph::storage::View::NEW), memgraph::storage::PropertyValue()); - ASSERT_EQ(vertex.InEdges(memgraph::storage::View::NEW)->size(), 0); - ASSERT_EQ(vertex.OutEdges(memgraph::storage::View::NEW)->size(), 0); - ASSERT_EQ(*vertex.InDegree(memgraph::storage::View::NEW), 0); - ASSERT_EQ(*vertex.OutDegree(memgraph::storage::View::NEW), 0); - - // Modify vertex. - ASSERT_TRUE(vertex.AddLabel(label).HasValue()); - ASSERT_TRUE(vertex.SetProperty(property, memgraph::storage::PropertyValue("value")).HasValue()); - ASSERT_TRUE(acc.CreateEdge(&vertex, &vertex, acc.NameToEdgeType("edge")).HasValue()); - - // Check state after (OLD view). - ASSERT_EQ(vertex.Labels(memgraph::storage::View::OLD).GetError(), memgraph::storage::Error::NONEXISTENT_OBJECT); - ASSERT_EQ(vertex.HasLabel(label, memgraph::storage::View::OLD).GetError(), - memgraph::storage::Error::NONEXISTENT_OBJECT); - ASSERT_EQ(vertex.Properties(memgraph::storage::View::OLD).GetError(), memgraph::storage::Error::NONEXISTENT_OBJECT); - ASSERT_EQ(vertex.GetProperty(property, memgraph::storage::View::OLD).GetError(), - memgraph::storage::Error::NONEXISTENT_OBJECT); - ASSERT_EQ(vertex.InEdges(memgraph::storage::View::OLD).GetError(), memgraph::storage::Error::NONEXISTENT_OBJECT); - ASSERT_EQ(vertex.OutEdges(memgraph::storage::View::OLD).GetError(), memgraph::storage::Error::NONEXISTENT_OBJECT); - ASSERT_EQ(vertex.InDegree(memgraph::storage::View::OLD).GetError(), memgraph::storage::Error::NONEXISTENT_OBJECT); - ASSERT_EQ(vertex.OutDegree(memgraph::storage::View::OLD).GetError(), memgraph::storage::Error::NONEXISTENT_OBJECT); - - // Check state after (NEW view). - ASSERT_EQ(vertex.Labels(memgraph::storage::View::NEW)->size(), 1); - ASSERT_EQ(*vertex.HasLabel(label, memgraph::storage::View::NEW), true); - ASSERT_EQ(vertex.Properties(memgraph::storage::View::NEW)->size(), 1); - ASSERT_EQ(*vertex.GetProperty(property, memgraph::storage::View::NEW), memgraph::storage::PropertyValue("value")); - ASSERT_EQ(vertex.InEdges(memgraph::storage::View::NEW)->size(), 1); - ASSERT_EQ(vertex.OutEdges(memgraph::storage::View::NEW)->size(), 1); - ASSERT_EQ(*vertex.InDegree(memgraph::storage::View::NEW), 1); - ASSERT_EQ(*vertex.OutDegree(memgraph::storage::View::NEW), 1); - - ASSERT_FALSE(acc.Commit().HasError()); -} - -TEST(StorageV2, VertexVisibilitySingleTransaction) { - memgraph::storage::Storage store; - - auto acc1 = store.Access(); - auto acc2 = store.Access(); - - auto vertex = acc1.CreateVertex(); - auto gid = vertex.Gid(); - - EXPECT_FALSE(acc1.FindVertex(gid, memgraph::storage::View::OLD)); - EXPECT_TRUE(acc1.FindVertex(gid, memgraph::storage::View::NEW)); - EXPECT_FALSE(acc2.FindVertex(gid, memgraph::storage::View::OLD)); - EXPECT_FALSE(acc2.FindVertex(gid, memgraph::storage::View::NEW)); - - ASSERT_TRUE(vertex.AddLabel(acc1.NameToLabel("label")).HasValue()); - - EXPECT_FALSE(acc1.FindVertex(gid, memgraph::storage::View::OLD)); - EXPECT_TRUE(acc1.FindVertex(gid, memgraph::storage::View::NEW)); - EXPECT_FALSE(acc2.FindVertex(gid, memgraph::storage::View::OLD)); - EXPECT_FALSE(acc2.FindVertex(gid, memgraph::storage::View::NEW)); - - ASSERT_TRUE(vertex.SetProperty(acc1.NameToProperty("meaning"), memgraph::storage::PropertyValue(42)).HasValue()); - - auto acc3 = store.Access(); - - EXPECT_FALSE(acc1.FindVertex(gid, memgraph::storage::View::OLD)); - EXPECT_TRUE(acc1.FindVertex(gid, memgraph::storage::View::NEW)); - EXPECT_FALSE(acc2.FindVertex(gid, memgraph::storage::View::OLD)); - EXPECT_FALSE(acc2.FindVertex(gid, memgraph::storage::View::NEW)); - EXPECT_FALSE(acc3.FindVertex(gid, memgraph::storage::View::OLD)); - EXPECT_FALSE(acc3.FindVertex(gid, memgraph::storage::View::NEW)); - - ASSERT_TRUE(acc1.DeleteVertex(&vertex).HasValue()); - - EXPECT_FALSE(acc1.FindVertex(gid, memgraph::storage::View::OLD)); - EXPECT_FALSE(acc1.FindVertex(gid, memgraph::storage::View::NEW)); - EXPECT_FALSE(acc2.FindVertex(gid, memgraph::storage::View::OLD)); - EXPECT_FALSE(acc2.FindVertex(gid, memgraph::storage::View::NEW)); - EXPECT_FALSE(acc3.FindVertex(gid, memgraph::storage::View::OLD)); - EXPECT_FALSE(acc3.FindVertex(gid, memgraph::storage::View::NEW)); - - acc1.AdvanceCommand(); - acc3.AdvanceCommand(); - - EXPECT_FALSE(acc1.FindVertex(gid, memgraph::storage::View::OLD)); - EXPECT_FALSE(acc1.FindVertex(gid, memgraph::storage::View::NEW)); - EXPECT_FALSE(acc2.FindVertex(gid, memgraph::storage::View::OLD)); - EXPECT_FALSE(acc2.FindVertex(gid, memgraph::storage::View::NEW)); - EXPECT_FALSE(acc3.FindVertex(gid, memgraph::storage::View::OLD)); - EXPECT_FALSE(acc3.FindVertex(gid, memgraph::storage::View::NEW)); - - acc1.Abort(); - acc2.Abort(); - acc3.Abort(); -} - -TEST(StorageV2, VertexVisibilityMultipleTransactions) { - memgraph::storage::Storage store; - memgraph::storage::Gid gid; - - { - auto acc1 = store.Access(); - auto acc2 = store.Access(); - - auto vertex = acc1.CreateVertex(); - gid = vertex.Gid(); - - EXPECT_FALSE(acc1.FindVertex(gid, memgraph::storage::View::OLD)); - EXPECT_TRUE(acc1.FindVertex(gid, memgraph::storage::View::NEW)); - EXPECT_FALSE(acc2.FindVertex(gid, memgraph::storage::View::OLD)); - EXPECT_FALSE(acc2.FindVertex(gid, memgraph::storage::View::NEW)); - - acc2.AdvanceCommand(); - - EXPECT_FALSE(acc1.FindVertex(gid, memgraph::storage::View::OLD)); - EXPECT_TRUE(acc1.FindVertex(gid, memgraph::storage::View::NEW)); - EXPECT_FALSE(acc2.FindVertex(gid, memgraph::storage::View::OLD)); - EXPECT_FALSE(acc2.FindVertex(gid, memgraph::storage::View::NEW)); - - acc1.AdvanceCommand(); - - EXPECT_TRUE(acc1.FindVertex(gid, memgraph::storage::View::OLD)); - EXPECT_TRUE(acc1.FindVertex(gid, memgraph::storage::View::NEW)); - EXPECT_FALSE(acc2.FindVertex(gid, memgraph::storage::View::OLD)); - EXPECT_FALSE(acc2.FindVertex(gid, memgraph::storage::View::NEW)); - - ASSERT_FALSE(acc1.Commit().HasError()); - ASSERT_FALSE(acc2.Commit().HasError()); - } - - { - auto acc1 = store.Access(); - auto acc2 = store.Access(); - - auto vertex = acc1.FindVertex(gid, memgraph::storage::View::OLD); - ASSERT_TRUE(vertex); - - EXPECT_TRUE(acc1.FindVertex(gid, memgraph::storage::View::OLD)); - EXPECT_TRUE(acc1.FindVertex(gid, memgraph::storage::View::NEW)); - EXPECT_TRUE(acc2.FindVertex(gid, memgraph::storage::View::OLD)); - EXPECT_TRUE(acc2.FindVertex(gid, memgraph::storage::View::NEW)); - - ASSERT_TRUE(vertex->AddLabel(acc1.NameToLabel("label")).HasValue()); - - EXPECT_TRUE(acc1.FindVertex(gid, memgraph::storage::View::OLD)); - EXPECT_TRUE(acc1.FindVertex(gid, memgraph::storage::View::NEW)); - EXPECT_TRUE(acc2.FindVertex(gid, memgraph::storage::View::OLD)); - EXPECT_TRUE(acc2.FindVertex(gid, memgraph::storage::View::NEW)); - - acc1.AdvanceCommand(); - - EXPECT_TRUE(acc1.FindVertex(gid, memgraph::storage::View::OLD)); - EXPECT_TRUE(acc1.FindVertex(gid, memgraph::storage::View::NEW)); - EXPECT_TRUE(acc2.FindVertex(gid, memgraph::storage::View::OLD)); - EXPECT_TRUE(acc2.FindVertex(gid, memgraph::storage::View::NEW)); - - acc2.AdvanceCommand(); - - EXPECT_TRUE(acc1.FindVertex(gid, memgraph::storage::View::OLD)); - EXPECT_TRUE(acc1.FindVertex(gid, memgraph::storage::View::NEW)); - EXPECT_TRUE(acc2.FindVertex(gid, memgraph::storage::View::OLD)); - EXPECT_TRUE(acc2.FindVertex(gid, memgraph::storage::View::NEW)); - - ASSERT_TRUE(vertex->SetProperty(acc1.NameToProperty("meaning"), memgraph::storage::PropertyValue(42)).HasValue()); - - auto acc3 = store.Access(); - - EXPECT_TRUE(acc1.FindVertex(gid, memgraph::storage::View::OLD)); - EXPECT_TRUE(acc1.FindVertex(gid, memgraph::storage::View::NEW)); - EXPECT_TRUE(acc2.FindVertex(gid, memgraph::storage::View::OLD)); - EXPECT_TRUE(acc2.FindVertex(gid, memgraph::storage::View::NEW)); - EXPECT_TRUE(acc3.FindVertex(gid, memgraph::storage::View::OLD)); - EXPECT_TRUE(acc3.FindVertex(gid, memgraph::storage::View::NEW)); - - acc1.AdvanceCommand(); - - EXPECT_TRUE(acc1.FindVertex(gid, memgraph::storage::View::OLD)); - EXPECT_TRUE(acc1.FindVertex(gid, memgraph::storage::View::NEW)); - EXPECT_TRUE(acc2.FindVertex(gid, memgraph::storage::View::OLD)); - EXPECT_TRUE(acc2.FindVertex(gid, memgraph::storage::View::NEW)); - EXPECT_TRUE(acc3.FindVertex(gid, memgraph::storage::View::OLD)); - EXPECT_TRUE(acc3.FindVertex(gid, memgraph::storage::View::NEW)); - - acc2.AdvanceCommand(); - - EXPECT_TRUE(acc1.FindVertex(gid, memgraph::storage::View::OLD)); - EXPECT_TRUE(acc1.FindVertex(gid, memgraph::storage::View::NEW)); - EXPECT_TRUE(acc2.FindVertex(gid, memgraph::storage::View::OLD)); - EXPECT_TRUE(acc2.FindVertex(gid, memgraph::storage::View::NEW)); - EXPECT_TRUE(acc3.FindVertex(gid, memgraph::storage::View::OLD)); - EXPECT_TRUE(acc3.FindVertex(gid, memgraph::storage::View::NEW)); - - acc3.AdvanceCommand(); - - EXPECT_TRUE(acc1.FindVertex(gid, memgraph::storage::View::OLD)); - EXPECT_TRUE(acc1.FindVertex(gid, memgraph::storage::View::NEW)); - EXPECT_TRUE(acc2.FindVertex(gid, memgraph::storage::View::OLD)); - EXPECT_TRUE(acc2.FindVertex(gid, memgraph::storage::View::NEW)); - EXPECT_TRUE(acc3.FindVertex(gid, memgraph::storage::View::OLD)); - EXPECT_TRUE(acc3.FindVertex(gid, memgraph::storage::View::NEW)); - - ASSERT_FALSE(acc1.Commit().HasError()); - ASSERT_FALSE(acc2.Commit().HasError()); - ASSERT_FALSE(acc3.Commit().HasError()); - } - - { - auto acc1 = store.Access(); - auto acc2 = store.Access(); - - auto vertex = acc1.FindVertex(gid, memgraph::storage::View::OLD); - ASSERT_TRUE(vertex); - - ASSERT_TRUE(acc1.DeleteVertex(&*vertex).HasValue()); - - auto acc3 = store.Access(); - - EXPECT_TRUE(acc1.FindVertex(gid, memgraph::storage::View::OLD)); - EXPECT_FALSE(acc1.FindVertex(gid, memgraph::storage::View::NEW)); - EXPECT_TRUE(acc2.FindVertex(gid, memgraph::storage::View::OLD)); - EXPECT_TRUE(acc2.FindVertex(gid, memgraph::storage::View::NEW)); - EXPECT_TRUE(acc3.FindVertex(gid, memgraph::storage::View::OLD)); - EXPECT_TRUE(acc3.FindVertex(gid, memgraph::storage::View::NEW)); - - acc2.AdvanceCommand(); - - EXPECT_TRUE(acc1.FindVertex(gid, memgraph::storage::View::OLD)); - EXPECT_FALSE(acc1.FindVertex(gid, memgraph::storage::View::NEW)); - EXPECT_TRUE(acc2.FindVertex(gid, memgraph::storage::View::OLD)); - EXPECT_TRUE(acc2.FindVertex(gid, memgraph::storage::View::NEW)); - EXPECT_TRUE(acc3.FindVertex(gid, memgraph::storage::View::OLD)); - EXPECT_TRUE(acc3.FindVertex(gid, memgraph::storage::View::NEW)); - - acc1.AdvanceCommand(); - - EXPECT_FALSE(acc1.FindVertex(gid, memgraph::storage::View::OLD)); - EXPECT_FALSE(acc1.FindVertex(gid, memgraph::storage::View::NEW)); - EXPECT_TRUE(acc2.FindVertex(gid, memgraph::storage::View::OLD)); - EXPECT_TRUE(acc2.FindVertex(gid, memgraph::storage::View::NEW)); - EXPECT_TRUE(acc3.FindVertex(gid, memgraph::storage::View::OLD)); - EXPECT_TRUE(acc3.FindVertex(gid, memgraph::storage::View::NEW)); - - acc3.AdvanceCommand(); - - EXPECT_FALSE(acc1.FindVertex(gid, memgraph::storage::View::OLD)); - EXPECT_FALSE(acc1.FindVertex(gid, memgraph::storage::View::NEW)); - EXPECT_TRUE(acc2.FindVertex(gid, memgraph::storage::View::OLD)); - EXPECT_TRUE(acc2.FindVertex(gid, memgraph::storage::View::NEW)); - EXPECT_TRUE(acc3.FindVertex(gid, memgraph::storage::View::OLD)); - EXPECT_TRUE(acc3.FindVertex(gid, memgraph::storage::View::NEW)); - - acc1.Abort(); - acc2.Abort(); - acc3.Abort(); - } - - { - auto acc = store.Access(); - - EXPECT_TRUE(acc.FindVertex(gid, memgraph::storage::View::OLD)); - EXPECT_TRUE(acc.FindVertex(gid, memgraph::storage::View::NEW)); - - acc.AdvanceCommand(); - - EXPECT_TRUE(acc.FindVertex(gid, memgraph::storage::View::OLD)); - EXPECT_TRUE(acc.FindVertex(gid, memgraph::storage::View::NEW)); - - acc.Abort(); - } - - { - auto acc1 = store.Access(); - auto acc2 = store.Access(); - - auto vertex = acc1.FindVertex(gid, memgraph::storage::View::OLD); - ASSERT_TRUE(vertex); - - ASSERT_TRUE(acc1.DeleteVertex(&*vertex).HasValue()); - - auto acc3 = store.Access(); - - EXPECT_TRUE(acc1.FindVertex(gid, memgraph::storage::View::OLD)); - EXPECT_FALSE(acc1.FindVertex(gid, memgraph::storage::View::NEW)); - EXPECT_TRUE(acc2.FindVertex(gid, memgraph::storage::View::OLD)); - EXPECT_TRUE(acc2.FindVertex(gid, memgraph::storage::View::NEW)); - EXPECT_TRUE(acc3.FindVertex(gid, memgraph::storage::View::OLD)); - EXPECT_TRUE(acc3.FindVertex(gid, memgraph::storage::View::NEW)); - - acc2.AdvanceCommand(); - - EXPECT_TRUE(acc1.FindVertex(gid, memgraph::storage::View::OLD)); - EXPECT_FALSE(acc1.FindVertex(gid, memgraph::storage::View::NEW)); - EXPECT_TRUE(acc2.FindVertex(gid, memgraph::storage::View::OLD)); - EXPECT_TRUE(acc2.FindVertex(gid, memgraph::storage::View::NEW)); - EXPECT_TRUE(acc3.FindVertex(gid, memgraph::storage::View::OLD)); - EXPECT_TRUE(acc3.FindVertex(gid, memgraph::storage::View::NEW)); - - acc1.AdvanceCommand(); - - EXPECT_FALSE(acc1.FindVertex(gid, memgraph::storage::View::OLD)); - EXPECT_FALSE(acc1.FindVertex(gid, memgraph::storage::View::NEW)); - EXPECT_TRUE(acc2.FindVertex(gid, memgraph::storage::View::OLD)); - EXPECT_TRUE(acc2.FindVertex(gid, memgraph::storage::View::NEW)); - EXPECT_TRUE(acc3.FindVertex(gid, memgraph::storage::View::OLD)); - EXPECT_TRUE(acc3.FindVertex(gid, memgraph::storage::View::NEW)); - - acc3.AdvanceCommand(); - - EXPECT_FALSE(acc1.FindVertex(gid, memgraph::storage::View::OLD)); - EXPECT_FALSE(acc1.FindVertex(gid, memgraph::storage::View::NEW)); - EXPECT_TRUE(acc2.FindVertex(gid, memgraph::storage::View::OLD)); - EXPECT_TRUE(acc2.FindVertex(gid, memgraph::storage::View::NEW)); - EXPECT_TRUE(acc3.FindVertex(gid, memgraph::storage::View::OLD)); - EXPECT_TRUE(acc3.FindVertex(gid, memgraph::storage::View::NEW)); - - ASSERT_FALSE(acc1.Commit().HasError()); - ASSERT_FALSE(acc2.Commit().HasError()); - ASSERT_FALSE(acc3.Commit().HasError()); - } - - { - auto acc = store.Access(); - - EXPECT_FALSE(acc.FindVertex(gid, memgraph::storage::View::OLD)); - EXPECT_FALSE(acc.FindVertex(gid, memgraph::storage::View::NEW)); - - acc.AdvanceCommand(); - - EXPECT_FALSE(acc.FindVertex(gid, memgraph::storage::View::OLD)); - EXPECT_FALSE(acc.FindVertex(gid, memgraph::storage::View::NEW)); - - acc.Abort(); - } -} - -// NOLINTNEXTLINE(hicpp-special-member-functions) -TEST(StorageV2, DeletedVertexAccessor) { - memgraph::storage::Storage store; - - const auto property = store.NameToProperty("property"); - const memgraph::storage::PropertyValue property_value{"property_value"}; - - std::optional gid; - // Create the vertex - { - auto acc = store.Access(); - auto vertex = acc.CreateVertex(); - gid = vertex.Gid(); - ASSERT_FALSE(vertex.SetProperty(property, property_value).HasError()); - ASSERT_FALSE(acc.Commit().HasError()); - } - - auto acc = store.Access(); - auto vertex = acc.FindVertex(*gid, memgraph::storage::View::OLD); - ASSERT_TRUE(vertex); - auto maybe_deleted_vertex = acc.DeleteVertex(&*vertex); - ASSERT_FALSE(maybe_deleted_vertex.HasError()); - - auto deleted_vertex = maybe_deleted_vertex.GetValue(); - ASSERT_TRUE(deleted_vertex); - // you cannot modify deleted vertex - ASSERT_TRUE(deleted_vertex->ClearProperties().HasError()); - - // you can call read only methods - const auto maybe_property = deleted_vertex->GetProperty(property, memgraph::storage::View::OLD); - ASSERT_FALSE(maybe_property.HasError()); - ASSERT_EQ(property_value, *maybe_property); - ASSERT_FALSE(acc.Commit().HasError()); - - { - // you can call read only methods and get valid results even after the - // transaction which deleted the vertex committed, but only if the transaction - // accessor is still alive - const auto maybe_property = deleted_vertex->GetProperty(property, memgraph::storage::View::OLD); - ASSERT_FALSE(maybe_property.HasError()); - ASSERT_EQ(property_value, *maybe_property); - } -} diff --git a/tests/unit/storage_v2_constraints.cpp b/tests/unit/storage_v2_constraints.cpp deleted file mode 100644 index 5c0fde426..000000000 --- a/tests/unit/storage_v2_constraints.cpp +++ /dev/null @@ -1,973 +0,0 @@ -// Copyright 2022 Memgraph Ltd. -// -// Use of this software is governed by the Business Source License -// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source -// License, and you may not use this file except in compliance with the Business Source License. -// -// As of the Change Date specified in that file, in accordance with -// the Business Source License, use of this software will be governed -// by the Apache License, Version 2.0, included in the file -// licenses/APL.txt. - -#include -#include - -#include "storage/v2/storage.hpp" - -// NOLINTNEXTLINE(google-build-using-namespace) -using namespace memgraph::storage; - -using testing::UnorderedElementsAre; - -// NOLINTNEXTLINE(cppcoreguidelines-macro-usage) -#define ASSERT_NO_ERROR(result) ASSERT_FALSE((result).HasError()) - -class ConstraintsTest : public testing::Test { - protected: - ConstraintsTest() - : prop1(storage.NameToProperty("prop1")), - prop2(storage.NameToProperty("prop2")), - label1(storage.NameToLabel("label1")), - label2(storage.NameToLabel("label2")) {} - - Storage storage; - PropertyId prop1; - PropertyId prop2; - LabelId label1; - LabelId label2; -}; - -// NOLINTNEXTLINE(hicpp-special-member-functions) -TEST_F(ConstraintsTest, ExistenceConstraintsCreateAndDrop) { - EXPECT_EQ(storage.ListAllConstraints().existence.size(), 0); - { - auto res = storage.CreateExistenceConstraint(label1, prop1); - EXPECT_TRUE(res.HasValue() && res.GetValue()); - } - EXPECT_THAT(storage.ListAllConstraints().existence, UnorderedElementsAre(std::make_pair(label1, prop1))); - { - auto res = storage.CreateExistenceConstraint(label1, prop1); - EXPECT_TRUE(res.HasValue() && !res.GetValue()); - } - EXPECT_THAT(storage.ListAllConstraints().existence, UnorderedElementsAre(std::make_pair(label1, prop1))); - { - auto res = storage.CreateExistenceConstraint(label2, prop1); - EXPECT_TRUE(res.HasValue() && res.GetValue()); - } - EXPECT_THAT(storage.ListAllConstraints().existence, - UnorderedElementsAre(std::make_pair(label1, prop1), std::make_pair(label2, prop1))); - EXPECT_TRUE(storage.DropExistenceConstraint(label1, prop1)); - EXPECT_FALSE(storage.DropExistenceConstraint(label1, prop1)); - EXPECT_THAT(storage.ListAllConstraints().existence, UnorderedElementsAre(std::make_pair(label2, prop1))); - EXPECT_TRUE(storage.DropExistenceConstraint(label2, prop1)); - EXPECT_FALSE(storage.DropExistenceConstraint(label2, prop2)); - EXPECT_EQ(storage.ListAllConstraints().existence.size(), 0); - { - auto res = storage.CreateExistenceConstraint(label2, prop1); - EXPECT_TRUE(res.HasValue() && res.GetValue()); - } - EXPECT_THAT(storage.ListAllConstraints().existence, UnorderedElementsAre(std::make_pair(label2, prop1))); -} - -// NOLINTNEXTLINE(hicpp-special-member-functions) -TEST_F(ConstraintsTest, ExistenceConstraintsCreateFailure1) { - { - auto acc = storage.Access(); - auto vertex = acc.CreateVertex(); - ASSERT_NO_ERROR(vertex.AddLabel(label1)); - ASSERT_NO_ERROR(acc.Commit()); - } - { - auto res = storage.CreateExistenceConstraint(label1, prop1); - ASSERT_TRUE(res.HasError()); - EXPECT_EQ(res.GetError(), - (ConstraintViolation{ConstraintViolation::Type::EXISTENCE, label1, std::set{prop1}})); - } - { - auto acc = storage.Access(); - for (auto vertex : acc.Vertices(View::OLD)) { - ASSERT_NO_ERROR(acc.DeleteVertex(&vertex)); - } - ASSERT_NO_ERROR(acc.Commit()); - } - { - auto res = storage.CreateExistenceConstraint(label1, prop1); - EXPECT_TRUE(res.HasValue() && res.GetValue()); - } -} - -// NOLINTNEXTLINE(hicpp-special-member-functions) -TEST_F(ConstraintsTest, ExistenceConstraintsCreateFailure2) { - { - auto acc = storage.Access(); - auto vertex = acc.CreateVertex(); - ASSERT_NO_ERROR(vertex.AddLabel(label1)); - ASSERT_NO_ERROR(acc.Commit()); - } - { - auto res = storage.CreateExistenceConstraint(label1, prop1); - ASSERT_TRUE(res.HasError()); - EXPECT_EQ(res.GetError(), - (ConstraintViolation{ConstraintViolation::Type::EXISTENCE, label1, std::set{prop1}})); - } - { - auto acc = storage.Access(); - for (auto vertex : acc.Vertices(View::OLD)) { - ASSERT_NO_ERROR(vertex.SetProperty(prop1, PropertyValue(1))); - } - ASSERT_NO_ERROR(acc.Commit()); - } - { - auto res = storage.CreateExistenceConstraint(label1, prop1); - EXPECT_TRUE(res.HasValue() && res.GetValue()); - } -} - -// NOLINTNEXTLINE(hicpp-special-member-functions) -TEST_F(ConstraintsTest, ExistenceConstraintsViolationOnCommit) { - { - auto res = storage.CreateExistenceConstraint(label1, prop1); - ASSERT_TRUE(res.HasValue() && res.GetValue()); - } - - { - auto acc = storage.Access(); - auto vertex = acc.CreateVertex(); - ASSERT_NO_ERROR(vertex.AddLabel(label1)); - - auto res = acc.Commit(); - ASSERT_TRUE(res.HasError()); - EXPECT_EQ(res.GetError(), - (ConstraintViolation{ConstraintViolation::Type::EXISTENCE, label1, std::set{prop1}})); - } - - { - auto acc = storage.Access(); - auto vertex = acc.CreateVertex(); - ASSERT_NO_ERROR(vertex.AddLabel(label1)); - ASSERT_NO_ERROR(vertex.SetProperty(prop1, PropertyValue(1))); - ASSERT_NO_ERROR(acc.Commit()); - } - - { - auto acc = storage.Access(); - for (auto vertex : acc.Vertices(View::OLD)) { - ASSERT_NO_ERROR(vertex.SetProperty(prop1, PropertyValue())); - } - - auto res = acc.Commit(); - ASSERT_TRUE(res.HasError()); - EXPECT_EQ(res.GetError(), - (ConstraintViolation{ConstraintViolation::Type::EXISTENCE, label1, std::set{prop1}})); - } - - { - auto acc = storage.Access(); - for (auto vertex : acc.Vertices(View::OLD)) { - ASSERT_NO_ERROR(vertex.SetProperty(prop1, PropertyValue())); - } - for (auto vertex : acc.Vertices(View::OLD)) { - ASSERT_NO_ERROR(acc.DeleteVertex(&vertex)); - } - - ASSERT_NO_ERROR(acc.Commit()); - } - - ASSERT_TRUE(storage.DropExistenceConstraint(label1, prop1)); - - { - auto acc = storage.Access(); - auto vertex = acc.CreateVertex(); - ASSERT_NO_ERROR(vertex.AddLabel(label1)); - ASSERT_NO_ERROR(acc.Commit()); - } -} - -// NOLINTNEXTLINE(hicpp-special-member-functions) -TEST_F(ConstraintsTest, UniqueConstraintsCreateAndDropAndList) { - EXPECT_EQ(storage.ListAllConstraints().unique.size(), 0); - { - auto res = storage.CreateUniqueConstraint(label1, {prop1}); - EXPECT_TRUE(res.HasValue()); - EXPECT_EQ(res.GetValue(), UniqueConstraints::CreationStatus::SUCCESS); - } - EXPECT_THAT(storage.ListAllConstraints().unique, - UnorderedElementsAre(std::make_pair(label1, std::set{prop1}))); - { - auto res = storage.CreateUniqueConstraint(label1, {prop1}); - EXPECT_TRUE(res.HasValue()); - EXPECT_EQ(res.GetValue(), UniqueConstraints::CreationStatus::ALREADY_EXISTS); - } - EXPECT_THAT(storage.ListAllConstraints().unique, - UnorderedElementsAre(std::make_pair(label1, std::set{prop1}))); - { - auto res = storage.CreateUniqueConstraint(label2, {prop1}); - EXPECT_TRUE(res.HasValue() && res.GetValue() == UniqueConstraints::CreationStatus::SUCCESS); - ASSERT_EQ(res.GetValue(), UniqueConstraints::CreationStatus::SUCCESS); - } - EXPECT_THAT(storage.ListAllConstraints().unique, - UnorderedElementsAre(std::make_pair(label1, std::set{prop1}), - std::make_pair(label2, std::set{prop1}))); - EXPECT_EQ(storage.DropUniqueConstraint(label1, {prop1}), UniqueConstraints::DeletionStatus::SUCCESS); - EXPECT_EQ(storage.DropUniqueConstraint(label1, {prop1}), UniqueConstraints::DeletionStatus::NOT_FOUND); - EXPECT_THAT(storage.ListAllConstraints().unique, - UnorderedElementsAre(std::make_pair(label2, std::set{prop1}))); - EXPECT_EQ(storage.DropUniqueConstraint(label2, {prop1}), UniqueConstraints::DeletionStatus::SUCCESS); - EXPECT_EQ(storage.DropUniqueConstraint(label2, {prop2}), UniqueConstraints::DeletionStatus::NOT_FOUND); - EXPECT_EQ(storage.ListAllConstraints().unique.size(), 0); - { - auto res = storage.CreateUniqueConstraint(label2, {prop1}); - EXPECT_TRUE(res.HasValue()); - EXPECT_EQ(res.GetValue(), UniqueConstraints::CreationStatus::SUCCESS); - } - EXPECT_THAT(storage.ListAllConstraints().unique, - UnorderedElementsAre(std::make_pair(label2, std::set{prop1}))); -} - -// NOLINTNEXTLINE(hicpp-special-member-functions) -TEST_F(ConstraintsTest, UniqueConstraintsCreateFailure1) { - { - auto acc = storage.Access(); - for (int i = 0; i < 2; ++i) { - auto vertex1 = acc.CreateVertex(); - ASSERT_NO_ERROR(vertex1.AddLabel(label1)); - ASSERT_NO_ERROR(vertex1.SetProperty(prop1, PropertyValue(1))); - } - ASSERT_NO_ERROR(acc.Commit()); - } - - { - auto res = storage.CreateUniqueConstraint(label1, {prop1}); - ASSERT_TRUE(res.HasError()); - EXPECT_EQ(res.GetError(), - (ConstraintViolation{ConstraintViolation::Type::UNIQUE, label1, std::set{prop1}})); - } - - { - auto acc = storage.Access(); - for (auto vertex : acc.Vertices(View::OLD)) { - ASSERT_NO_ERROR(acc.DeleteVertex(&vertex)); - } - ASSERT_NO_ERROR(acc.Commit()); - } - - { - auto res = storage.CreateUniqueConstraint(label1, {prop1}); - ASSERT_TRUE(res.HasValue()); - ASSERT_EQ(res.GetValue(), UniqueConstraints::CreationStatus::SUCCESS); - } -} - -// NOLINTNEXTLINE(hicpp-special-member-functions) -TEST_F(ConstraintsTest, UniqueConstraintsCreateFailure2) { - { - auto acc = storage.Access(); - for (int i = 0; i < 2; ++i) { - auto vertex = acc.CreateVertex(); - ASSERT_NO_ERROR(vertex.AddLabel(label1)); - ASSERT_NO_ERROR(vertex.SetProperty(prop1, PropertyValue(1))); - } - ASSERT_NO_ERROR(acc.Commit()); - } - - { - auto res = storage.CreateUniqueConstraint(label1, {prop1}); - ASSERT_TRUE(res.HasError()); - EXPECT_EQ(res.GetError(), - (ConstraintViolation{ConstraintViolation::Type::UNIQUE, label1, std::set{prop1}})); - } - - { - auto acc = storage.Access(); - int value = 0; - for (auto vertex : acc.Vertices(View::OLD)) { - ASSERT_NO_ERROR(vertex.SetProperty(prop1, PropertyValue(value))); - ++value; - } - ASSERT_NO_ERROR(acc.Commit()); - } - - { - auto res = storage.CreateUniqueConstraint(label1, {prop1}); - ASSERT_TRUE(res.HasValue()); - ASSERT_EQ(res.GetValue(), UniqueConstraints::CreationStatus::SUCCESS); - } -} - -// NOLINTNEXTLINE(hicpp-special-member-functions) -TEST_F(ConstraintsTest, UniqueConstraintsNoViolation1) { - Gid gid1; - Gid gid2; - { - auto acc = storage.Access(); - auto vertex1 = acc.CreateVertex(); - auto vertex2 = acc.CreateVertex(); - gid1 = vertex1.Gid(); - gid2 = vertex2.Gid(); - - ASSERT_NO_ERROR(vertex1.AddLabel(label1)); - ASSERT_NO_ERROR(vertex1.SetProperty(prop1, PropertyValue(1))); - ASSERT_NO_ERROR(acc.Commit()); - } - - { - auto res = storage.CreateUniqueConstraint(label1, {prop1, prop2}); - ASSERT_TRUE(res.HasValue()); - ASSERT_EQ(res.GetValue(), UniqueConstraints::CreationStatus::SUCCESS); - } - - { - auto acc = storage.Access(); - auto vertex1 = acc.FindVertex(gid1, View::OLD); - auto vertex2 = acc.FindVertex(gid2, View::OLD); - - ASSERT_NO_ERROR(vertex1->SetProperty(prop2, PropertyValue(2))); - ASSERT_NO_ERROR(vertex2->AddLabel(label1)); - ASSERT_NO_ERROR(vertex2->SetProperty(prop1, PropertyValue(1))); - ASSERT_NO_ERROR(vertex2->SetProperty(prop2, PropertyValue(3))); - ASSERT_NO_ERROR(acc.Commit()); - } - - { - auto acc = storage.Access(); - auto vertex1 = acc.FindVertex(gid1, View::OLD); - auto vertex2 = acc.FindVertex(gid2, View::OLD); - ASSERT_NO_ERROR(vertex1->SetProperty(prop1, PropertyValue(2))); - ASSERT_NO_ERROR(vertex2->SetProperty(prop1, PropertyValue(1))); - ASSERT_NO_ERROR(acc.Commit()); - } -} - -// NOLINTNEXTLINE(hicpp-special-member-functions) -TEST_F(ConstraintsTest, UniqueConstraintsNoViolation2) { - { - auto res = storage.CreateUniqueConstraint(label1, {prop1}); - ASSERT_TRUE(res.HasValue()); - ASSERT_EQ(res.GetValue(), UniqueConstraints::CreationStatus::SUCCESS); - } - - { - // tx1: B---SP(v1, 1)---SP(v1, 2)---OK-- - // tx2: -B---SP(v2, 2)---SP(v2, 1)---OK- - - auto acc1 = storage.Access(); - auto acc2 = storage.Access(); - auto vertex1 = acc1.CreateVertex(); - auto vertex2 = acc2.CreateVertex(); - - ASSERT_NO_ERROR(vertex1.AddLabel(label1)); - ASSERT_NO_ERROR(vertex1.SetProperty(prop1, PropertyValue(1))); - ASSERT_NO_ERROR(vertex2.AddLabel(label1)); - ASSERT_NO_ERROR(vertex2.SetProperty(prop1, PropertyValue(2))); - - ASSERT_NO_ERROR(vertex1.SetProperty(prop1, PropertyValue(2))); - ASSERT_NO_ERROR(vertex2.SetProperty(prop1, PropertyValue(1))); - - ASSERT_NO_ERROR(acc1.Commit()); - ASSERT_NO_ERROR(acc2.Commit()); - } -} - -// NOLINTNEXTLINE(hicpp-special-member-functions) -TEST_F(ConstraintsTest, UniqueConstraintsNoViolation3) { - { - auto res = storage.CreateUniqueConstraint(label1, {prop1}); - ASSERT_TRUE(res.HasValue()); - ASSERT_EQ(res.GetValue(), UniqueConstraints::CreationStatus::SUCCESS); - } - - { - // tx1: B---SP(v1, 1)---OK---------------------- - // tx2: --------------------B---SP(v1, 2)---OK-- - // tx3: ---------------------B---SP(v2, 1)---OK- - - auto acc1 = storage.Access(); - auto vertex1 = acc1.CreateVertex(); - auto gid = vertex1.Gid(); - - ASSERT_NO_ERROR(vertex1.AddLabel(label1)); - ASSERT_NO_ERROR(vertex1.SetProperty(prop1, PropertyValue(1))); - - ASSERT_NO_ERROR(acc1.Commit()); - - auto acc2 = storage.Access(); - auto acc3 = storage.Access(); - auto vertex2 = acc2.FindVertex(gid, View::NEW); // vertex1 == vertex2 - auto vertex3 = acc3.CreateVertex(); - - ASSERT_NO_ERROR(vertex2->SetProperty(prop1, PropertyValue(2))); - ASSERT_NO_ERROR(vertex3.AddLabel(label1)); - ASSERT_NO_ERROR(vertex3.SetProperty(prop1, PropertyValue(1))); - - ASSERT_NO_ERROR(acc2.Commit()); - ASSERT_NO_ERROR(acc3.Commit()); - } -} - -// NOLINTNEXTLINE(hicpp-special-member-functions) -TEST_F(ConstraintsTest, UniqueConstraintsNoViolation4) { - { - auto res = storage.CreateUniqueConstraint(label1, {prop1}); - ASSERT_TRUE(res.HasValue()); - ASSERT_EQ(res.GetValue(), UniqueConstraints::CreationStatus::SUCCESS); - } - - { - // tx1: B---SP(v1, 1)---OK----------------------- - // tx2: --------------------B---SP(v2, 1)-----OK- - // tx3: ---------------------B---SP(v1, 2)---OK-- - - auto acc1 = storage.Access(); - auto vertex1 = acc1.CreateVertex(); - auto gid = vertex1.Gid(); - - ASSERT_NO_ERROR(vertex1.AddLabel(label1)); - ASSERT_NO_ERROR(vertex1.SetProperty(prop1, PropertyValue(1))); - - ASSERT_NO_ERROR(acc1.Commit()); - - auto acc2 = storage.Access(); - auto acc3 = storage.Access(); - auto vertex2 = acc2.CreateVertex(); - auto vertex3 = acc3.FindVertex(gid, View::NEW); - - ASSERT_NO_ERROR(vertex2.AddLabel(label1)); - ASSERT_NO_ERROR(vertex2.SetProperty(prop1, PropertyValue(1))); - ASSERT_NO_ERROR(vertex3->SetProperty(prop1, PropertyValue(2))); - - ASSERT_NO_ERROR(acc3.Commit()); - ASSERT_NO_ERROR(acc2.Commit()); - } -} - -// NOLINTNEXTLINE(hicpp-special-member-functions) -TEST_F(ConstraintsTest, UniqueConstraintsViolationOnCommit1) { - { - auto res = storage.CreateUniqueConstraint(label1, {prop1}); - ASSERT_TRUE(res.HasValue()); - ASSERT_EQ(res.GetValue(), UniqueConstraints::CreationStatus::SUCCESS); - } - - { - auto acc = storage.Access(); - auto vertex1 = acc.CreateVertex(); - auto vertex2 = acc.CreateVertex(); - ASSERT_NO_ERROR(vertex1.AddLabel(label1)); - ASSERT_NO_ERROR(vertex1.SetProperty(prop1, PropertyValue(1))); - ASSERT_NO_ERROR(vertex2.AddLabel(label1)); - ASSERT_NO_ERROR(vertex2.SetProperty(prop1, PropertyValue(1))); - auto res = acc.Commit(); - ASSERT_TRUE(res.HasError()); - EXPECT_EQ(res.GetError(), - (ConstraintViolation{ConstraintViolation::Type::UNIQUE, label1, std::set{prop1}})); - } -} - -// NOLINTNEXTLINE(hicpp-special-member-functions) -TEST_F(ConstraintsTest, UniqueConstraintsViolationOnCommit2) { - { - auto res = storage.CreateUniqueConstraint(label1, {prop1}); - ASSERT_TRUE(res.HasValue()); - ASSERT_EQ(res.GetValue(), UniqueConstraints::CreationStatus::SUCCESS); - } - - { - // tx1: B---SP(v1, 1)---SP(v2, 2)---OK----------------------- - // tx2: -------------------------------B---SP(v1, 3)---OK---- - // tx3: --------------------------------B---SP(v2, 3)---FAIL- - - auto acc1 = storage.Access(); - auto vertex1 = acc1.CreateVertex(); - auto vertex2 = acc1.CreateVertex(); - auto gid1 = vertex1.Gid(); - auto gid2 = vertex2.Gid(); - - ASSERT_NO_ERROR(vertex1.AddLabel(label1)); - ASSERT_NO_ERROR(vertex1.SetProperty(prop1, PropertyValue(1))); - ASSERT_NO_ERROR(vertex2.AddLabel(label1)); - ASSERT_NO_ERROR(vertex2.SetProperty(prop1, PropertyValue(2))); - - ASSERT_NO_ERROR(acc1.Commit()); - - auto acc2 = storage.Access(); - auto acc3 = storage.Access(); - auto vertex3 = acc2.FindVertex(gid1, View::NEW); // vertex3 == vertex1 - auto vertex4 = acc3.FindVertex(gid2, View::NEW); // vertex4 == vertex2 - - ASSERT_NO_ERROR(vertex3->SetProperty(prop1, PropertyValue(3))); - ASSERT_NO_ERROR(vertex4->SetProperty(prop1, PropertyValue(3))); - - ASSERT_NO_ERROR(acc2.Commit()); - auto res = acc3.Commit(); - ASSERT_TRUE(res.HasError()); - EXPECT_EQ(res.GetError(), - (ConstraintViolation{ConstraintViolation::Type::UNIQUE, label1, std::set{prop1}})); - } -} - -// NOLINTNEXTLINE(hicpp-special-member-functions) -TEST_F(ConstraintsTest, UniqueConstraintsViolationOnCommit3) { - { - auto res = storage.CreateUniqueConstraint(label1, {prop1}); - ASSERT_TRUE(res.HasValue()); - ASSERT_EQ(res.GetValue(), UniqueConstraints::CreationStatus::SUCCESS); - } - - { - // tx1: B---SP(v1, 1)---SP(v2, 2)---OK----------------------- - // tx2: -------------------------------B---SP(v1, 2)---FAIL-- - // tx3: --------------------------------B---SP(v2, 1)---FAIL- - - auto acc1 = storage.Access(); - auto vertex1 = acc1.CreateVertex(); - auto vertex2 = acc1.CreateVertex(); - auto gid1 = vertex1.Gid(); - auto gid2 = vertex2.Gid(); - - ASSERT_NO_ERROR(vertex1.AddLabel(label1)); - ASSERT_NO_ERROR(vertex1.SetProperty(prop1, PropertyValue(1))); - ASSERT_NO_ERROR(vertex2.AddLabel(label1)); - ASSERT_NO_ERROR(vertex2.SetProperty(prop1, PropertyValue(2))); - - ASSERT_NO_ERROR(acc1.Commit()); - - auto acc2 = storage.Access(); - auto acc3 = storage.Access(); - auto vertex3 = acc2.FindVertex(gid1, View::OLD); // vertex3 == vertex1 - auto vertex4 = acc3.FindVertex(gid2, View::OLD); // vertex4 == vertex2 - - // Setting `prop2` shouldn't affect the remaining code. - ASSERT_NO_ERROR(vertex3->SetProperty(prop2, PropertyValue(3))); - ASSERT_NO_ERROR(vertex4->SetProperty(prop2, PropertyValue(3))); - - ASSERT_NO_ERROR(vertex3->SetProperty(prop1, PropertyValue(2))); - ASSERT_NO_ERROR(vertex4->SetProperty(prop1, PropertyValue(1))); - - auto res = acc2.Commit(); - ASSERT_TRUE(res.HasError()); - EXPECT_EQ(res.GetError(), - (ConstraintViolation{ConstraintViolation::Type::UNIQUE, label1, std::set{prop1}})); - res = acc3.Commit(); - ASSERT_TRUE(res.HasError()); - EXPECT_EQ(res.GetError(), - (ConstraintViolation{ConstraintViolation::Type::UNIQUE, label1, std::set{prop1}})); - } -} - -// NOLINTNEXTLINE(hicpp-special-member-functions) -TEST_F(ConstraintsTest, UniqueConstraintsLabelAlteration) { - { - auto res = storage.CreateUniqueConstraint(label1, {prop1}); - ASSERT_TRUE(res.HasValue()); - ASSERT_EQ(res.GetValue(), UniqueConstraints::CreationStatus::SUCCESS); - } - - Gid gid1; - Gid gid2; - { - // B---AL(v2)---SP(v1, 1)---SP(v2, 1)---OK - - auto acc = storage.Access(); - auto vertex1 = acc.CreateVertex(); - auto vertex2 = acc.CreateVertex(); - gid1 = vertex1.Gid(); - gid2 = vertex2.Gid(); - - ASSERT_NO_ERROR(vertex1.AddLabel(label2)); - ASSERT_NO_ERROR(vertex1.SetProperty(prop1, PropertyValue(1))); - ASSERT_NO_ERROR(vertex2.AddLabel(label1)); - ASSERT_NO_ERROR(vertex2.SetProperty(prop1, PropertyValue(1))); - - ASSERT_NO_ERROR(acc.Commit()); - } - - { - // tx1: B---AL(v1)-----OK- - // tx2: -B---RL(v2)---OK-- - - auto acc1 = storage.Access(); - auto acc2 = storage.Access(); - auto vertex1 = acc1.FindVertex(gid1, View::OLD); - auto vertex2 = acc2.FindVertex(gid2, View::OLD); - - ASSERT_NO_ERROR(vertex1->AddLabel(label1)); - ASSERT_NO_ERROR(vertex2->RemoveLabel(label1)); - - // Reapplying labels shouldn't affect the remaining code. - ASSERT_NO_ERROR(vertex1->RemoveLabel(label1)); - ASSERT_NO_ERROR(vertex2->AddLabel(label1)); - ASSERT_NO_ERROR(vertex1->AddLabel(label1)); - ASSERT_NO_ERROR(vertex2->RemoveLabel(label1)); - ASSERT_NO_ERROR(vertex1->RemoveLabel(label2)); - - // Commit the second transaction. - ASSERT_NO_ERROR(acc2.Commit()); - - // Reapplying labels after first commit shouldn't affect the remaining code. - ASSERT_NO_ERROR(vertex1->RemoveLabel(label1)); - ASSERT_NO_ERROR(vertex1->AddLabel(label1)); - - // Commit the first transaction. - ASSERT_NO_ERROR(acc1.Commit()); - } - - { - // B---AL(v2)---FAIL - - auto acc = storage.Access(); - auto vertex2 = acc.FindVertex(gid2, View::OLD); - ASSERT_NO_ERROR(vertex2->AddLabel(label1)); - - auto res = acc.Commit(); - ASSERT_TRUE(res.HasError()); - EXPECT_EQ(res.GetError(), (ConstraintViolation{ConstraintViolation::Type::UNIQUE, label1, std::set{prop1}})); - } - - { - // B---RL(v1)---OK - - auto acc = storage.Access(); - auto vertex1 = acc.FindVertex(gid1, View::OLD); - ASSERT_NO_ERROR(vertex1->RemoveLabel(label1)); - ASSERT_NO_ERROR(acc.Commit()); - } - - { - // tx1: B---AL(v1)-----FAIL - // tx2: -B---AL(v2)---OK--- - - auto acc1 = storage.Access(); - auto acc2 = storage.Access(); - auto vertex1 = acc1.FindVertex(gid1, View::OLD); - auto vertex2 = acc2.FindVertex(gid2, View::OLD); - - ASSERT_NO_ERROR(vertex1->AddLabel(label1)); - ASSERT_NO_ERROR(vertex2->AddLabel(label1)); - - // Reapply everything. - ASSERT_NO_ERROR(vertex1->RemoveLabel(label1)); - ASSERT_NO_ERROR(vertex2->RemoveLabel(label1)); - ASSERT_NO_ERROR(vertex1->AddLabel(label1)); - ASSERT_NO_ERROR(vertex2->AddLabel(label1)); - - ASSERT_NO_ERROR(acc2.Commit()); - - auto res = acc1.Commit(); - ASSERT_TRUE(res.HasError()); - EXPECT_EQ(res.GetError(), (ConstraintViolation{ConstraintViolation::Type::UNIQUE, label1, std::set{prop1}})); - } -} - -// NOLINTNEXTLINE(hicpp-special-member-functions) -TEST_F(ConstraintsTest, UniqueConstraintsPropertySetSize) { - { - // This should fail since unique constraint cannot be created for an empty - // property set. - auto res = storage.CreateUniqueConstraint(label1, {}); - ASSERT_TRUE(res.HasValue()); - ASSERT_EQ(res.GetValue(), UniqueConstraints::CreationStatus::EMPTY_PROPERTIES); - } - - // Removing a constraint with empty property set should also fail. - ASSERT_EQ(storage.DropUniqueConstraint(label1, {}), UniqueConstraints::DeletionStatus::EMPTY_PROPERTIES); - - // Create a set of 33 properties. - std::set properties; - for (int i = 1; i <= 33; ++i) { - properties.insert(storage.NameToProperty("prop" + std::to_string(i))); - } - - { - // This should fail since list of properties exceeds the maximum number of - // properties, which is 32. - auto res = storage.CreateUniqueConstraint(label1, properties); - ASSERT_TRUE(res.HasValue()); - ASSERT_EQ(res.GetValue(), UniqueConstraints::CreationStatus::PROPERTIES_SIZE_LIMIT_EXCEEDED); - } - - // An attempt to delete constraint with too large property set should fail. - ASSERT_EQ(storage.DropUniqueConstraint(label1, properties), - UniqueConstraints::DeletionStatus::PROPERTIES_SIZE_LIMIT_EXCEEDED); - - // Remove one property from the set. - properties.erase(properties.begin()); - - { - // Creating a constraint for 32 properties should succeed. - auto res = storage.CreateUniqueConstraint(label1, properties); - ASSERT_TRUE(res.HasValue()); - ASSERT_EQ(res.GetValue(), UniqueConstraints::CreationStatus::SUCCESS); - } - - EXPECT_THAT(storage.ListAllConstraints().unique, UnorderedElementsAre(std::make_pair(label1, properties))); - - // Removing a constraint with 32 properties should succeed. - ASSERT_EQ(storage.DropUniqueConstraint(label1, properties), UniqueConstraints::DeletionStatus::SUCCESS); - ASSERT_TRUE(storage.ListAllConstraints().unique.empty()); -} - -// NOLINTNEXTLINE(hicpp-special-member-functions) -TEST_F(ConstraintsTest, UniqueConstraintsMultipleProperties) { - { - auto res = storage.CreateUniqueConstraint(label1, {prop1, prop2}); - ASSERT_TRUE(res.HasValue()); - ASSERT_EQ(res.GetValue(), UniqueConstraints::CreationStatus::SUCCESS); - } - - { - // An attempt to create an existing unique constraint. - auto res = storage.CreateUniqueConstraint(label1, {prop2, prop1}); - ASSERT_TRUE(res.HasValue()); - ASSERT_EQ(res.GetValue(), UniqueConstraints::CreationStatus::ALREADY_EXISTS); - } - - Gid gid1; - Gid gid2; - { - auto acc = storage.Access(); - auto vertex1 = acc.CreateVertex(); - auto vertex2 = acc.CreateVertex(); - gid1 = vertex1.Gid(); - gid2 = vertex2.Gid(); - - ASSERT_NO_ERROR(vertex1.AddLabel(label1)); - ASSERT_NO_ERROR(vertex1.SetProperty(prop1, PropertyValue(1))); - ASSERT_NO_ERROR(vertex1.SetProperty(prop2, PropertyValue(2))); - - ASSERT_NO_ERROR(vertex2.AddLabel(label1)); - ASSERT_NO_ERROR(vertex2.SetProperty(prop1, PropertyValue(1))); - ASSERT_NO_ERROR(vertex2.SetProperty(prop2, PropertyValue(3))); - - ASSERT_NO_ERROR(acc.Commit()); - } - - // Try to change property of the second vertex so it becomes the same as the - // first vertex. It should fail. - { - auto acc = storage.Access(); - auto vertex2 = acc.FindVertex(gid2, View::OLD); - ASSERT_NO_ERROR(vertex2->SetProperty(prop2, PropertyValue(2))); - auto res = acc.Commit(); - ASSERT_TRUE(res.HasError()); - EXPECT_EQ(res.GetError(), - (ConstraintViolation{ConstraintViolation::Type::UNIQUE, label1, std::set{prop1, prop2}})); - } - - // Then change the second property of both vertex to null. Property values of - // both vertices should now be equal. However, this operation should succeed - // since null value is treated as non-existing property. - { - auto acc = storage.Access(); - auto vertex1 = acc.FindVertex(gid1, View::OLD); - auto vertex2 = acc.FindVertex(gid2, View::OLD); - ASSERT_NO_ERROR(vertex1->SetProperty(prop2, PropertyValue())); - ASSERT_NO_ERROR(vertex2->SetProperty(prop2, PropertyValue())); - ASSERT_NO_ERROR(acc.Commit()); - } -} - -TEST_F(ConstraintsTest, UniqueConstraintsInsertAbortInsert) { - { - auto res = storage.CreateUniqueConstraint(label1, {prop1, prop2}); - ASSERT_TRUE(res.HasValue()); - ASSERT_EQ(res.GetValue(), UniqueConstraints::CreationStatus::SUCCESS); - } - - { - auto acc = storage.Access(); - auto vertex = acc.CreateVertex(); - ASSERT_NO_ERROR(vertex.AddLabel(label1)); - ASSERT_NO_ERROR(vertex.SetProperty(prop1, PropertyValue(1))); - ASSERT_NO_ERROR(vertex.SetProperty(prop2, PropertyValue(2))); - acc.Abort(); - } - - { - auto acc = storage.Access(); - auto vertex = acc.CreateVertex(); - ASSERT_NO_ERROR(vertex.AddLabel(label1)); - ASSERT_NO_ERROR(vertex.SetProperty(prop2, PropertyValue(2))); - ASSERT_NO_ERROR(vertex.SetProperty(prop1, PropertyValue(1))); - ASSERT_NO_ERROR(acc.Commit()); - } -} - -TEST_F(ConstraintsTest, UniqueConstraintsInsertRemoveInsert) { - { - auto res = storage.CreateUniqueConstraint(label1, {prop1, prop2}); - ASSERT_TRUE(res.HasValue()); - ASSERT_EQ(res.GetValue(), UniqueConstraints::CreationStatus::SUCCESS); - } - - Gid gid; - { - auto acc = storage.Access(); - auto vertex = acc.CreateVertex(); - gid = vertex.Gid(); - ASSERT_NO_ERROR(vertex.AddLabel(label1)); - ASSERT_NO_ERROR(vertex.SetProperty(prop1, PropertyValue(1))); - ASSERT_NO_ERROR(vertex.SetProperty(prop2, PropertyValue(2))); - ASSERT_NO_ERROR(acc.Commit()); - } - - { - auto acc = storage.Access(); - auto vertex = acc.FindVertex(gid, View::OLD); - ASSERT_NO_ERROR(acc.DeleteVertex(&*vertex)); - ASSERT_NO_ERROR(acc.Commit()); - } - - { - auto acc = storage.Access(); - auto vertex = acc.CreateVertex(); - ASSERT_NO_ERROR(vertex.AddLabel(label1)); - ASSERT_NO_ERROR(vertex.SetProperty(prop1, PropertyValue(1))); - ASSERT_NO_ERROR(vertex.SetProperty(prop2, PropertyValue(2))); - ASSERT_NO_ERROR(acc.Commit()); - } -} - -TEST_F(ConstraintsTest, UniqueConstraintsInsertRemoveAbortInsert) { - { - auto res = storage.CreateUniqueConstraint(label1, {prop1, prop2}); - ASSERT_TRUE(res.HasValue()); - ASSERT_EQ(res.GetValue(), UniqueConstraints::CreationStatus::SUCCESS); - } - - Gid gid; - { - auto acc = storage.Access(); - auto vertex = acc.CreateVertex(); - gid = vertex.Gid(); - ASSERT_NO_ERROR(vertex.AddLabel(label1)); - ASSERT_NO_ERROR(vertex.SetProperty(prop1, PropertyValue(2))); - ASSERT_NO_ERROR(vertex.SetProperty(prop2, PropertyValue(1))); - ASSERT_NO_ERROR(acc.Commit()); - } - - { - auto acc = storage.Access(); - auto vertex = acc.FindVertex(gid, View::OLD); - ASSERT_NO_ERROR(acc.DeleteVertex(&*vertex)); - acc.Abort(); - } - - { - auto acc = storage.Access(); - auto vertex = acc.CreateVertex(); - ASSERT_NO_ERROR(vertex.AddLabel(label1)); - ASSERT_NO_ERROR(vertex.SetProperty(prop2, PropertyValue(1))); - ASSERT_NO_ERROR(vertex.SetProperty(prop1, PropertyValue(2))); - - auto res = acc.Commit(); - ASSERT_TRUE(res.HasError()); - EXPECT_EQ(res.GetError(), (ConstraintViolation{ConstraintViolation::Type::UNIQUE, label1, std::set{prop1, prop2}})); - } -} - -TEST_F(ConstraintsTest, UniqueConstraintsDeleteVertexSetProperty) { - { - auto res = storage.CreateUniqueConstraint(label1, {prop1}); - ASSERT_TRUE(res.HasValue()); - ASSERT_EQ(res.GetValue(), UniqueConstraints::CreationStatus::SUCCESS); - } - - Gid gid1; - Gid gid2; - { - auto acc = storage.Access(); - auto vertex1 = acc.CreateVertex(); - auto vertex2 = acc.CreateVertex(); - gid1 = vertex1.Gid(); - gid2 = vertex2.Gid(); - - ASSERT_NO_ERROR(vertex1.AddLabel(label1)); - ASSERT_NO_ERROR(vertex2.AddLabel(label1)); - ASSERT_NO_ERROR(vertex1.SetProperty(prop1, PropertyValue(1))); - ASSERT_NO_ERROR(vertex2.SetProperty(prop1, PropertyValue(2))); - - ASSERT_NO_ERROR(acc.Commit()); - } - - { - auto acc1 = storage.Access(); - auto acc2 = storage.Access(); - auto vertex1 = acc1.FindVertex(gid1, View::OLD); - auto vertex2 = acc2.FindVertex(gid2, View::OLD); - - ASSERT_NO_ERROR(acc2.DeleteVertex(&*vertex2)); - ASSERT_NO_ERROR(vertex1->SetProperty(prop1, PropertyValue(2))); - - auto res = acc1.Commit(); - ASSERT_TRUE(res.HasError()); - EXPECT_EQ(res.GetError(), (ConstraintViolation{ConstraintViolation::Type::UNIQUE, label1, std::set{prop1}})); - - ASSERT_NO_ERROR(acc2.Commit()); - } -} - -TEST_F(ConstraintsTest, UniqueConstraintsInsertDropInsert) { - { - auto res = storage.CreateUniqueConstraint(label1, {prop1, prop2}); - ASSERT_TRUE(res.HasValue()); - ASSERT_EQ(res.GetValue(), UniqueConstraints::CreationStatus::SUCCESS); - } - - { - auto acc = storage.Access(); - auto vertex = acc.CreateVertex(); - ASSERT_NO_ERROR(vertex.AddLabel(label1)); - ASSERT_NO_ERROR(vertex.SetProperty(prop1, PropertyValue(1))); - ASSERT_NO_ERROR(vertex.SetProperty(prop2, PropertyValue(2))); - ASSERT_NO_ERROR(acc.Commit()); - } - - ASSERT_EQ(storage.DropUniqueConstraint(label1, {prop2, prop1}), UniqueConstraints::DeletionStatus::SUCCESS); - - { - auto acc = storage.Access(); - auto vertex = acc.CreateVertex(); - ASSERT_NO_ERROR(vertex.AddLabel(label1)); - ASSERT_NO_ERROR(vertex.SetProperty(prop2, PropertyValue(2))); - ASSERT_NO_ERROR(vertex.SetProperty(prop1, PropertyValue(1))); - ASSERT_NO_ERROR(acc.Commit()); - } -} - -TEST_F(ConstraintsTest, UniqueConstraintsComparePropertyValues) { - // Purpose of this test is to make sure that extracted property values - // are correctly compared. - - { - auto res = storage.CreateUniqueConstraint(label1, {prop1, prop2}); - ASSERT_TRUE(res.HasValue()); - ASSERT_EQ(res.GetValue(), UniqueConstraints::CreationStatus::SUCCESS); - } - - { - auto acc = storage.Access(); - auto vertex = acc.CreateVertex(); - ASSERT_NO_ERROR(vertex.AddLabel(label1)); - ASSERT_NO_ERROR(vertex.SetProperty(prop1, PropertyValue(2))); - ASSERT_NO_ERROR(vertex.SetProperty(prop2, PropertyValue(1))); - ASSERT_NO_ERROR(acc.Commit()); - } - - { - auto acc = storage.Access(); - auto vertex = acc.CreateVertex(); - ASSERT_NO_ERROR(vertex.AddLabel(label1)); - ASSERT_NO_ERROR(vertex.SetProperty(prop1, PropertyValue(1))); - ASSERT_NO_ERROR(vertex.SetProperty(prop2, PropertyValue(2))); - ASSERT_NO_ERROR(acc.Commit()); - } - - { - auto acc = storage.Access(); - auto vertex = acc.CreateVertex(); - ASSERT_NO_ERROR(vertex.AddLabel(label1)); - ASSERT_NO_ERROR(vertex.SetProperty(prop2, PropertyValue(0))); - ASSERT_NO_ERROR(vertex.SetProperty(prop1, PropertyValue(3))); - ASSERT_NO_ERROR(acc.Commit()); - } -} diff --git a/tests/unit/storage_v2_decoder_encoder.cpp b/tests/unit/storage_v2_decoder_encoder.cpp deleted file mode 100644 index 9e2555ebd..000000000 --- a/tests/unit/storage_v2_decoder_encoder.cpp +++ /dev/null @@ -1,461 +0,0 @@ -// Copyright 2022 Memgraph Ltd. -// -// Use of this software is governed by the Business Source License -// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source -// License, and you may not use this file except in compliance with the Business Source License. -// -// As of the Change Date specified in that file, in accordance with -// the Business Source License, use of this software will be governed -// by the Apache License, Version 2.0, included in the file -// licenses/APL.txt. - -#include - -#include -#include - -#include "storage/v2/durability/serialization.hpp" -#include "storage/v2/property_value.hpp" -#include "storage/v2/temporal.hpp" - -static const std::string kTestMagic{"MGtest"}; -static const uint64_t kTestVersion{1}; - -class DecoderEncoderTest : public ::testing::Test { - public: - void SetUp() override { Clear(); } - - void TearDown() override { Clear(); } - - std::filesystem::path storage_file{std::filesystem::temp_directory_path() / - "MG_test_unit_storage_v2_decoder_encoder.bin"}; - - std::filesystem::path alternate_file{std::filesystem::temp_directory_path() / - "MG_test_unit_storage_v2_decoder_encoder_alternate.bin"}; - - private: - void Clear() { - if (std::filesystem::exists(storage_file)) { - std::filesystem::remove(storage_file); - } - if (std::filesystem::exists(alternate_file)) { - std::filesystem::remove(alternate_file); - } - } -}; - -// NOLINTNEXTLINE(hicpp-special-member-functions) -TEST_F(DecoderEncoderTest, ReadMarker) { - { - memgraph::storage::durability::Encoder encoder; - encoder.Initialize(storage_file, kTestMagic, kTestVersion); - for (const auto &item : memgraph::storage::durability::kMarkersAll) { - encoder.WriteMarker(item); - } - { - uint8_t invalid = 1; - encoder.Write(&invalid, sizeof(invalid)); - } - encoder.Finalize(); - } - { - memgraph::storage::durability::Decoder decoder; - auto version = decoder.Initialize(storage_file, kTestMagic); - ASSERT_TRUE(version); - ASSERT_EQ(*version, kTestVersion); - for (const auto &item : memgraph::storage::durability::kMarkersAll) { - auto decoded = decoder.ReadMarker(); - ASSERT_TRUE(decoded); - ASSERT_EQ(*decoded, item); - } - ASSERT_FALSE(decoder.ReadMarker()); - ASSERT_FALSE(decoder.ReadMarker()); - auto pos = decoder.GetPosition(); - ASSERT_TRUE(pos); - ASSERT_EQ(pos, decoder.GetSize()); - } -} - -// NOLINTNEXTLINE(cppcoreguidelines-macro-usage) -#define GENERATE_READ_TEST(name, type, ...) \ - TEST_F(DecoderEncoderTest, Read##name) { \ - std::vector dataset{__VA_ARGS__}; \ - { \ - memgraph::storage::durability::Encoder encoder; \ - encoder.Initialize(storage_file, kTestMagic, kTestVersion); \ - for (const auto &item : dataset) { \ - encoder.Write##name(item); \ - } \ - { \ - uint8_t invalid = 1; \ - encoder.Write(&invalid, sizeof(invalid)); \ - } \ - encoder.Finalize(); \ - } \ - { \ - memgraph::storage::durability::Decoder decoder; \ - auto version = decoder.Initialize(storage_file, kTestMagic); \ - ASSERT_TRUE(version); \ - ASSERT_EQ(*version, kTestVersion); \ - for (const auto &item : dataset) { \ - auto decoded = decoder.Read##name(); \ - ASSERT_TRUE(decoded); \ - ASSERT_EQ(*decoded, item); \ - } \ - ASSERT_FALSE(decoder.Read##name()); \ - ASSERT_FALSE(decoder.Read##name()); \ - auto pos = decoder.GetPosition(); \ - ASSERT_TRUE(pos); \ - ASSERT_EQ(pos, decoder.GetSize()); \ - } \ - } - -// NOLINTNEXTLINE(hicpp-special-member-functions) -GENERATE_READ_TEST(Bool, bool, false, true); - -// NOLINTNEXTLINE(hicpp-special-member-functions) -GENERATE_READ_TEST(Uint, uint64_t, 0, 1, 1000, 123123123, std::numeric_limits::max()); - -// NOLINTNEXTLINE(hicpp-special-member-functions) -GENERATE_READ_TEST(Double, double, 1.123, 3.1415926535, 0, -505.505, std::numeric_limits::infinity(), - -std::numeric_limits::infinity()); - -// NOLINTNEXTLINE(hicpp-special-member-functions) -GENERATE_READ_TEST(String, std::string, "hello", "world", "nandare", "haihaihai", std::string(), - std::string(100000, 'a')); - -// NOLINTNEXTLINE(hicpp-special-member-functions) -GENERATE_READ_TEST( - PropertyValue, memgraph::storage::PropertyValue, memgraph::storage::PropertyValue(), - memgraph::storage::PropertyValue(false), memgraph::storage::PropertyValue(true), - memgraph::storage::PropertyValue(123L), memgraph::storage::PropertyValue(123.5), - memgraph::storage::PropertyValue("nandare"), - memgraph::storage::PropertyValue(std::vector{ - memgraph::storage::PropertyValue("nandare"), memgraph::storage::PropertyValue(123L)}), - memgraph::storage::PropertyValue(std::map{ - {"nandare", memgraph::storage::PropertyValue(123)}}), - memgraph::storage::PropertyValue(memgraph::storage::TemporalData(memgraph::storage::TemporalType::Date, 23))); - -// NOLINTNEXTLINE(cppcoreguidelines-macro-usage) -#define GENERATE_SKIP_TEST(name, type, ...) \ - TEST_F(DecoderEncoderTest, Skip##name) { \ - std::vector dataset{__VA_ARGS__}; \ - { \ - memgraph::storage::durability::Encoder encoder; \ - encoder.Initialize(storage_file, kTestMagic, kTestVersion); \ - for (const auto &item : dataset) { \ - encoder.Write##name(item); \ - } \ - { \ - uint8_t invalid = 1; \ - encoder.Write(&invalid, sizeof(invalid)); \ - } \ - encoder.Finalize(); \ - } \ - { \ - memgraph::storage::durability::Decoder decoder; \ - auto version = decoder.Initialize(storage_file, kTestMagic); \ - ASSERT_TRUE(version); \ - ASSERT_EQ(*version, kTestVersion); \ - for (auto it = dataset.begin(); it != dataset.end(); ++it) { \ - ASSERT_TRUE(decoder.Skip##name()); \ - } \ - ASSERT_FALSE(decoder.Skip##name()); \ - ASSERT_FALSE(decoder.Skip##name()); \ - auto pos = decoder.GetPosition(); \ - ASSERT_TRUE(pos); \ - ASSERT_EQ(pos, decoder.GetSize()); \ - } \ - } - -// NOLINTNEXTLINE(hicpp-special-member-functions) -GENERATE_SKIP_TEST(String, std::string, "hello", "world", "nandare", "haihaihai", std::string(500000, 'a')); - -// NOLINTNEXTLINE(hicpp-special-member-functions) -GENERATE_SKIP_TEST( - PropertyValue, memgraph::storage::PropertyValue, memgraph::storage::PropertyValue(), - memgraph::storage::PropertyValue(false), memgraph::storage::PropertyValue(true), - memgraph::storage::PropertyValue(123L), memgraph::storage::PropertyValue(123.5), - memgraph::storage::PropertyValue("nandare"), - memgraph::storage::PropertyValue(std::vector{ - memgraph::storage::PropertyValue("nandare"), memgraph::storage::PropertyValue(123L)}), - memgraph::storage::PropertyValue(std::map{ - {"nandare", memgraph::storage::PropertyValue(123)}}), - memgraph::storage::PropertyValue(memgraph::storage::TemporalData(memgraph::storage::TemporalType::Date, 23))); - -// NOLINTNEXTLINE(cppcoreguidelines-macro-usage) -#define GENERATE_PARTIAL_READ_TEST(name, value) \ - TEST_F(DecoderEncoderTest, PartialRead##name) { \ - { \ - memgraph::storage::durability::Encoder encoder; \ - encoder.Initialize(storage_file, kTestMagic, kTestVersion); \ - encoder.Write##name(value); \ - encoder.Finalize(); \ - } \ - { \ - memgraph::utils::InputFile ifile; \ - memgraph::utils::OutputFile ofile; \ - ASSERT_TRUE(ifile.Open(storage_file)); \ - ofile.Open(alternate_file, memgraph::utils::OutputFile::Mode::OVERWRITE_EXISTING); \ - auto size = ifile.GetSize(); \ - for (size_t i = 0; i <= size; ++i) { \ - if (i != 0) { \ - uint8_t byte; \ - ASSERT_TRUE(ifile.Read(&byte, sizeof(byte))); \ - ofile.Write(&byte, sizeof(byte)); \ - ofile.Sync(); \ - } \ - memgraph::storage::durability::Decoder decoder; \ - auto version = decoder.Initialize(alternate_file, kTestMagic); \ - if (i < kTestMagic.size() + sizeof(kTestVersion)) { \ - ASSERT_FALSE(version); \ - } else { \ - ASSERT_TRUE(version); \ - ASSERT_EQ(*version, kTestVersion); \ - } \ - if (i != size) { \ - ASSERT_FALSE(decoder.Read##name()); \ - } else { \ - auto decoded = decoder.Read##name(); \ - ASSERT_TRUE(decoded); \ - ASSERT_EQ(*decoded, value); \ - } \ - } \ - } \ - } - -// NOLINTNEXTLINE(hicpp-special-member-functions) -GENERATE_PARTIAL_READ_TEST(Marker, memgraph::storage::durability::Marker::SECTION_VERTEX); - -// NOLINTNEXTLINE(hicpp-special-member-functions) -GENERATE_PARTIAL_READ_TEST(Bool, false); - -// NOLINTNEXTLINE(hicpp-special-member-functions) -GENERATE_PARTIAL_READ_TEST(Uint, 123123123); - -// NOLINTNEXTLINE(hicpp-special-member-functions) -GENERATE_PARTIAL_READ_TEST(Double, 3.1415926535); - -// NOLINTNEXTLINE(hicpp-special-member-functions) -GENERATE_PARTIAL_READ_TEST(String, "nandare"); - -// NOLINTNEXTLINE(hicpp-special-member-functions) -GENERATE_PARTIAL_READ_TEST( - PropertyValue, - memgraph::storage::PropertyValue(std::vector{ - memgraph::storage::PropertyValue(), memgraph::storage::PropertyValue(true), - memgraph::storage::PropertyValue(123L), memgraph::storage::PropertyValue(123.5), - memgraph::storage::PropertyValue("nandare"), - memgraph::storage::PropertyValue{ - std::map{{"haihai", memgraph::storage::PropertyValue()}}}, - memgraph::storage::PropertyValue(memgraph::storage::TemporalData(memgraph::storage::TemporalType::Date, 23))})); - -// NOLINTNEXTLINE(cppcoreguidelines-macro-usage) -#define GENERATE_PARTIAL_SKIP_TEST(name, value) \ - TEST_F(DecoderEncoderTest, PartialSkip##name) { \ - { \ - memgraph::storage::durability::Encoder encoder; \ - encoder.Initialize(storage_file, kTestMagic, kTestVersion); \ - encoder.Write##name(value); \ - encoder.Finalize(); \ - } \ - { \ - memgraph::utils::InputFile ifile; \ - memgraph::utils::OutputFile ofile; \ - ASSERT_TRUE(ifile.Open(storage_file)); \ - ofile.Open(alternate_file, memgraph::utils::OutputFile::Mode::OVERWRITE_EXISTING); \ - auto size = ifile.GetSize(); \ - for (size_t i = 0; i <= size; ++i) { \ - if (i != 0) { \ - uint8_t byte; \ - ASSERT_TRUE(ifile.Read(&byte, sizeof(byte))); \ - ofile.Write(&byte, sizeof(byte)); \ - ofile.Sync(); \ - } \ - memgraph::storage::durability::Decoder decoder; \ - auto version = decoder.Initialize(alternate_file, kTestMagic); \ - if (i < kTestMagic.size() + sizeof(kTestVersion)) { \ - ASSERT_FALSE(version); \ - } else { \ - ASSERT_TRUE(version); \ - ASSERT_EQ(*version, kTestVersion); \ - } \ - if (i != size) { \ - ASSERT_FALSE(decoder.Skip##name()); \ - } else { \ - ASSERT_TRUE(decoder.Skip##name()); \ - } \ - } \ - } \ - } - -// NOLINTNEXTLINE(hicpp-special-member-functions) -GENERATE_PARTIAL_SKIP_TEST(String, "nandare"); - -// NOLINTNEXTLINE(hicpp-special-member-functions) -GENERATE_PARTIAL_SKIP_TEST( - PropertyValue, - memgraph::storage::PropertyValue(std::vector{ - memgraph::storage::PropertyValue(), memgraph::storage::PropertyValue(true), - memgraph::storage::PropertyValue(123L), memgraph::storage::PropertyValue(123.5), - memgraph::storage::PropertyValue("nandare"), - memgraph::storage::PropertyValue{ - std::map{{"haihai", memgraph::storage::PropertyValue()}}}, - memgraph::storage::PropertyValue(memgraph::storage::TemporalData(memgraph::storage::TemporalType::Date, 23))})); - -// NOLINTNEXTLINE(hicpp-special-member-functions) -TEST_F(DecoderEncoderTest, PropertyValueInvalidMarker) { - { - memgraph::storage::durability::Encoder encoder; - encoder.Initialize(storage_file, kTestMagic, kTestVersion); - encoder.WritePropertyValue(memgraph::storage::PropertyValue(123L)); - encoder.Finalize(); - } - { - memgraph::utils::OutputFile file; - file.Open(storage_file, memgraph::utils::OutputFile::Mode::OVERWRITE_EXISTING); - for (auto marker : memgraph::storage::durability::kMarkersAll) { - bool valid_marker; - switch (marker) { - case memgraph::storage::durability::Marker::TYPE_NULL: - case memgraph::storage::durability::Marker::TYPE_BOOL: - case memgraph::storage::durability::Marker::TYPE_INT: - case memgraph::storage::durability::Marker::TYPE_DOUBLE: - case memgraph::storage::durability::Marker::TYPE_STRING: - case memgraph::storage::durability::Marker::TYPE_LIST: - case memgraph::storage::durability::Marker::TYPE_MAP: - case memgraph::storage::durability::Marker::TYPE_TEMPORAL_DATA: - case memgraph::storage::durability::Marker::TYPE_PROPERTY_VALUE: - valid_marker = true; - break; - - case memgraph::storage::durability::Marker::SECTION_VERTEX: - case memgraph::storage::durability::Marker::SECTION_EDGE: - case memgraph::storage::durability::Marker::SECTION_MAPPER: - case memgraph::storage::durability::Marker::SECTION_METADATA: - case memgraph::storage::durability::Marker::SECTION_INDICES: - case memgraph::storage::durability::Marker::SECTION_CONSTRAINTS: - case memgraph::storage::durability::Marker::SECTION_DELTA: - case memgraph::storage::durability::Marker::SECTION_EPOCH_HISTORY: - case memgraph::storage::durability::Marker::SECTION_OFFSETS: - case memgraph::storage::durability::Marker::DELTA_VERTEX_CREATE: - case memgraph::storage::durability::Marker::DELTA_VERTEX_DELETE: - case memgraph::storage::durability::Marker::DELTA_VERTEX_ADD_LABEL: - case memgraph::storage::durability::Marker::DELTA_VERTEX_REMOVE_LABEL: - case memgraph::storage::durability::Marker::DELTA_VERTEX_SET_PROPERTY: - case memgraph::storage::durability::Marker::DELTA_EDGE_CREATE: - case memgraph::storage::durability::Marker::DELTA_EDGE_DELETE: - case memgraph::storage::durability::Marker::DELTA_EDGE_SET_PROPERTY: - case memgraph::storage::durability::Marker::DELTA_TRANSACTION_END: - case memgraph::storage::durability::Marker::DELTA_LABEL_INDEX_CREATE: - case memgraph::storage::durability::Marker::DELTA_LABEL_INDEX_DROP: - case memgraph::storage::durability::Marker::DELTA_LABEL_PROPERTY_INDEX_CREATE: - case memgraph::storage::durability::Marker::DELTA_LABEL_PROPERTY_INDEX_DROP: - case memgraph::storage::durability::Marker::DELTA_EXISTENCE_CONSTRAINT_CREATE: - case memgraph::storage::durability::Marker::DELTA_EXISTENCE_CONSTRAINT_DROP: - case memgraph::storage::durability::Marker::DELTA_UNIQUE_CONSTRAINT_CREATE: - case memgraph::storage::durability::Marker::DELTA_UNIQUE_CONSTRAINT_DROP: - case memgraph::storage::durability::Marker::VALUE_FALSE: - case memgraph::storage::durability::Marker::VALUE_TRUE: - valid_marker = false; - break; - } - // We only run this test with invalid markers. - if (valid_marker) continue; - { - file.SetPosition(memgraph::utils::OutputFile::Position::RELATIVE_TO_END, - -(sizeof(uint64_t) + sizeof(memgraph::storage::durability::Marker))); - auto byte = static_cast(marker); - file.Write(&byte, sizeof(byte)); - file.Sync(); - } - { - memgraph::storage::durability::Decoder decoder; - auto version = decoder.Initialize(storage_file, kTestMagic); - ASSERT_TRUE(version); - ASSERT_EQ(*version, kTestVersion); - ASSERT_FALSE(decoder.SkipPropertyValue()); - } - { - memgraph::storage::durability::Decoder decoder; - auto version = decoder.Initialize(storage_file, kTestMagic); - ASSERT_TRUE(version); - ASSERT_EQ(*version, kTestVersion); - ASSERT_FALSE(decoder.ReadPropertyValue()); - } - } - { - { - file.SetPosition(memgraph::utils::OutputFile::Position::RELATIVE_TO_END, - -(sizeof(uint64_t) + sizeof(memgraph::storage::durability::Marker))); - uint8_t byte = 1; - file.Write(&byte, sizeof(byte)); - file.Sync(); - } - { - memgraph::storage::durability::Decoder decoder; - auto version = decoder.Initialize(storage_file, kTestMagic); - ASSERT_TRUE(version); - ASSERT_EQ(*version, kTestVersion); - ASSERT_FALSE(decoder.SkipPropertyValue()); - } - { - memgraph::storage::durability::Decoder decoder; - auto version = decoder.Initialize(storage_file, kTestMagic); - ASSERT_TRUE(version); - ASSERT_EQ(*version, kTestVersion); - ASSERT_FALSE(decoder.ReadPropertyValue()); - } - } - } -} - -// NOLINTNEXTLINE(hicpp-special-member-functions) -TEST_F(DecoderEncoderTest, DecoderPosition) { - { - memgraph::storage::durability::Encoder encoder; - encoder.Initialize(storage_file, kTestMagic, kTestVersion); - encoder.WriteBool(true); - encoder.Finalize(); - } - { - memgraph::storage::durability::Decoder decoder; - auto version = decoder.Initialize(storage_file, kTestMagic); - ASSERT_TRUE(version); - ASSERT_EQ(*version, kTestVersion); - for (int i = 0; i < 10; ++i) { - ASSERT_TRUE(decoder.SetPosition(kTestMagic.size() + sizeof(kTestVersion))); - auto decoded = decoder.ReadBool(); - ASSERT_TRUE(decoded); - ASSERT_TRUE(*decoded); - auto pos = decoder.GetPosition(); - ASSERT_TRUE(pos); - ASSERT_EQ(pos, decoder.GetSize()); - } - } -} - -// NOLINTNEXTLINE(hicpp-special-member-functions) -TEST_F(DecoderEncoderTest, EncoderPosition) { - { - memgraph::storage::durability::Encoder encoder; - encoder.Initialize(storage_file, kTestMagic, kTestVersion); - encoder.WriteBool(false); - encoder.SetPosition(kTestMagic.size() + sizeof(kTestVersion)); - ASSERT_EQ(encoder.GetPosition(), kTestMagic.size() + sizeof(kTestVersion)); - encoder.WriteBool(true); - encoder.Finalize(); - } - { - memgraph::storage::durability::Decoder decoder; - auto version = decoder.Initialize(storage_file, kTestMagic); - ASSERT_TRUE(version); - ASSERT_EQ(*version, kTestVersion); - auto decoded = decoder.ReadBool(); - ASSERT_TRUE(decoded); - ASSERT_TRUE(*decoded); - auto pos = decoder.GetPosition(); - ASSERT_TRUE(pos); - ASSERT_EQ(pos, decoder.GetSize()); - } -} diff --git a/tests/unit/storage_v2_durability.cpp b/tests/unit/storage_v2_durability.cpp deleted file mode 100644 index fb91ad159..000000000 --- a/tests/unit/storage_v2_durability.cpp +++ /dev/null @@ -1,2404 +0,0 @@ -// Copyright 2022 Memgraph Ltd. -// -// Use of this software is governed by the Business Source License -// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source -// License, and you may not use this file except in compliance with the Business Source License. -// -// As of the Change Date specified in that file, in accordance with -// the Business Source License, use of this software will be governed -// by the Apache License, Version 2.0, included in the file -// licenses/APL.txt. - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include "storage/v2/durability/paths.hpp" -#include "storage/v2/durability/snapshot.hpp" -#include "storage/v2/durability/version.hpp" -#include "storage/v2/storage.hpp" -#include "utils/file.hpp" -#include "utils/logging.hpp" -#include "utils/timer.hpp" - -using testing::Contains; -using testing::UnorderedElementsAre; - -class DurabilityTest : public ::testing::TestWithParam { - protected: - const uint64_t kNumBaseVertices = 1000; - const uint64_t kNumBaseEdges = 10000; - const uint64_t kNumExtendedVertices = 100; - const uint64_t kNumExtendedEdges = 1000; - - // We don't want to flush the WAL while we are doing operations because the - // flushing adds a large overhead that slows down execution. - const uint64_t kFlushWalEvery = (kNumBaseVertices + kNumBaseEdges + kNumExtendedVertices + kNumExtendedEdges) * 2; - - enum class DatasetType { - ONLY_BASE, - ONLY_BASE_WITH_EXTENDED_INDICES_AND_CONSTRAINTS, - ONLY_EXTENDED, - ONLY_EXTENDED_WITH_BASE_INDICES_AND_CONSTRAINTS, - BASE_WITH_EXTENDED, - }; - - public: - DurabilityTest() - : base_vertex_gids_(kNumBaseVertices, memgraph::storage::Gid::FromUint(std::numeric_limits::max())), - base_edge_gids_(kNumBaseEdges, memgraph::storage::Gid::FromUint(std::numeric_limits::max())), - extended_vertex_gids_(kNumExtendedVertices, - memgraph::storage::Gid::FromUint(std::numeric_limits::max())), - extended_edge_gids_(kNumExtendedEdges, memgraph::storage::Gid::FromUint(std::numeric_limits::max())) { - } - - void SetUp() override { Clear(); } - - void TearDown() override { Clear(); } - - void CreateBaseDataset(memgraph::storage::Storage *store, bool properties_on_edges) { - auto label_indexed = store->NameToLabel("base_indexed"); - auto label_unindexed = store->NameToLabel("base_unindexed"); - auto property_id = store->NameToProperty("id"); - auto property_extra = store->NameToProperty("extra"); - auto et1 = store->NameToEdgeType("base_et1"); - auto et2 = store->NameToEdgeType("base_et2"); - - // Create label index. - ASSERT_TRUE(store->CreateIndex(label_unindexed)); - - // Create label+property index. - ASSERT_TRUE(store->CreateIndex(label_indexed, property_id)); - - // Create existence constraint. - ASSERT_FALSE(store->CreateExistenceConstraint(label_unindexed, property_id).HasError()); - - // Create unique constraint. - ASSERT_FALSE(store->CreateUniqueConstraint(label_unindexed, {property_id, property_extra}).HasError()); - - // Create vertices. - for (uint64_t i = 0; i < kNumBaseVertices; ++i) { - auto acc = store->Access(); - auto vertex = acc.CreateVertex(); - base_vertex_gids_[i] = vertex.Gid(); - if (i < kNumBaseVertices / 2) { - ASSERT_TRUE(vertex.AddLabel(label_indexed).HasValue()); - } else { - ASSERT_TRUE(vertex.AddLabel(label_unindexed).HasValue()); - } - if (i < kNumBaseVertices / 3 || i >= kNumBaseVertices / 2) { - ASSERT_TRUE( - vertex.SetProperty(property_id, memgraph::storage::PropertyValue(static_cast(i))).HasValue()); - } - ASSERT_FALSE(acc.Commit().HasError()); - } - - // Create edges. - for (uint64_t i = 0; i < kNumBaseEdges; ++i) { - auto acc = store->Access(); - auto vertex1 = acc.FindVertex(base_vertex_gids_[(i / 2) % kNumBaseVertices], memgraph::storage::View::OLD); - ASSERT_TRUE(vertex1); - auto vertex2 = acc.FindVertex(base_vertex_gids_[(i / 3) % kNumBaseVertices], memgraph::storage::View::OLD); - ASSERT_TRUE(vertex2); - memgraph::storage::EdgeTypeId et; - if (i < kNumBaseEdges / 2) { - et = et1; - } else { - et = et2; - } - auto edge = acc.CreateEdge(&*vertex1, &*vertex2, et); - ASSERT_TRUE(edge.HasValue()); - base_edge_gids_[i] = edge->Gid(); - if (properties_on_edges) { - ASSERT_TRUE( - edge->SetProperty(property_id, memgraph::storage::PropertyValue(static_cast(i))).HasValue()); - } else { - auto ret = edge->SetProperty(property_id, memgraph::storage::PropertyValue(static_cast(i))); - ASSERT_TRUE(ret.HasError()); - ASSERT_EQ(ret.GetError(), memgraph::storage::Error::PROPERTIES_DISABLED); - } - ASSERT_FALSE(acc.Commit().HasError()); - } - } - - void CreateExtendedDataset(memgraph::storage::Storage *store, bool single_transaction = false) { - auto label_indexed = store->NameToLabel("extended_indexed"); - auto label_unused = store->NameToLabel("extended_unused"); - auto property_count = store->NameToProperty("count"); - auto et3 = store->NameToEdgeType("extended_et3"); - auto et4 = store->NameToEdgeType("extended_et4"); - - // Create label index. - ASSERT_TRUE(store->CreateIndex(label_unused)); - - // Create label+property index. - ASSERT_TRUE(store->CreateIndex(label_indexed, property_count)); - - // Create existence constraint. - ASSERT_FALSE(store->CreateExistenceConstraint(label_unused, property_count).HasError()); - - // Create unique constraint. - ASSERT_FALSE(store->CreateUniqueConstraint(label_unused, {property_count}).HasError()); - - // Storage accessor. - std::optional acc; - if (single_transaction) acc.emplace(store->Access()); - - // Create vertices. - for (uint64_t i = 0; i < kNumExtendedVertices; ++i) { - if (!single_transaction) acc.emplace(store->Access()); - auto vertex = acc->CreateVertex(); - extended_vertex_gids_[i] = vertex.Gid(); - if (i < kNumExtendedVertices / 2) { - ASSERT_TRUE(vertex.AddLabel(label_indexed).HasValue()); - } - if (i < kNumExtendedVertices / 3 || i >= kNumExtendedVertices / 2) { - ASSERT_TRUE(vertex.SetProperty(property_count, memgraph::storage::PropertyValue("nandare")).HasValue()); - } - if (!single_transaction) ASSERT_FALSE(acc->Commit().HasError()); - } - - // Create edges. - for (uint64_t i = 0; i < kNumExtendedEdges; ++i) { - if (!single_transaction) acc.emplace(store->Access()); - auto vertex1 = - acc->FindVertex(extended_vertex_gids_[(i / 5) % kNumExtendedVertices], memgraph::storage::View::NEW); - ASSERT_TRUE(vertex1); - auto vertex2 = - acc->FindVertex(extended_vertex_gids_[(i / 6) % kNumExtendedVertices], memgraph::storage::View::NEW); - ASSERT_TRUE(vertex2); - memgraph::storage::EdgeTypeId et; - if (i < kNumExtendedEdges / 4) { - et = et3; - } else { - et = et4; - } - auto edge = acc->CreateEdge(&*vertex1, &*vertex2, et); - ASSERT_TRUE(edge.HasValue()); - extended_edge_gids_[i] = edge->Gid(); - if (!single_transaction) ASSERT_FALSE(acc->Commit().HasError()); - } - - if (single_transaction) ASSERT_FALSE(acc->Commit().HasError()); - } - - void VerifyDataset(memgraph::storage::Storage *store, DatasetType type, bool properties_on_edges, - bool verify_info = true) { - auto base_label_indexed = store->NameToLabel("base_indexed"); - auto base_label_unindexed = store->NameToLabel("base_unindexed"); - auto property_id = store->NameToProperty("id"); - auto property_extra = store->NameToProperty("extra"); - auto et1 = store->NameToEdgeType("base_et1"); - auto et2 = store->NameToEdgeType("base_et2"); - - auto extended_label_indexed = store->NameToLabel("extended_indexed"); - auto extended_label_unused = store->NameToLabel("extended_unused"); - auto property_count = store->NameToProperty("count"); - auto et3 = store->NameToEdgeType("extended_et3"); - auto et4 = store->NameToEdgeType("extended_et4"); - - // Verify indices info. - { - auto info = store->ListAllIndices(); - switch (type) { - case DatasetType::ONLY_BASE: - ASSERT_THAT(info.label, UnorderedElementsAre(base_label_unindexed)); - ASSERT_THAT(info.label_property, UnorderedElementsAre(std::make_pair(base_label_indexed, property_id))); - break; - case DatasetType::ONLY_EXTENDED: - ASSERT_THAT(info.label, UnorderedElementsAre(extended_label_unused)); - ASSERT_THAT(info.label_property, - UnorderedElementsAre(std::make_pair(base_label_indexed, property_id), - std::make_pair(extended_label_indexed, property_count))); - break; - case DatasetType::ONLY_BASE_WITH_EXTENDED_INDICES_AND_CONSTRAINTS: - case DatasetType::ONLY_EXTENDED_WITH_BASE_INDICES_AND_CONSTRAINTS: - case DatasetType::BASE_WITH_EXTENDED: - ASSERT_THAT(info.label, UnorderedElementsAre(base_label_unindexed, extended_label_unused)); - ASSERT_THAT(info.label_property, - UnorderedElementsAre(std::make_pair(base_label_indexed, property_id), - std::make_pair(extended_label_indexed, property_count))); - break; - } - } - - // Verify constraints info. - { - auto info = store->ListAllConstraints(); - switch (type) { - case DatasetType::ONLY_BASE: - ASSERT_THAT(info.existence, UnorderedElementsAre(std::make_pair(base_label_unindexed, property_id))); - ASSERT_THAT(info.unique, UnorderedElementsAre( - std::make_pair(base_label_unindexed, std::set{property_id, property_extra}))); - break; - case DatasetType::ONLY_EXTENDED: - ASSERT_THAT(info.existence, UnorderedElementsAre(std::make_pair(extended_label_unused, property_count))); - ASSERT_THAT(info.unique, - UnorderedElementsAre(std::make_pair(extended_label_unused, std::set{property_count}))); - break; - case DatasetType::ONLY_BASE_WITH_EXTENDED_INDICES_AND_CONSTRAINTS: - case DatasetType::ONLY_EXTENDED_WITH_BASE_INDICES_AND_CONSTRAINTS: - case DatasetType::BASE_WITH_EXTENDED: - ASSERT_THAT(info.existence, UnorderedElementsAre(std::make_pair(base_label_unindexed, property_id), - std::make_pair(extended_label_unused, property_count))); - ASSERT_THAT(info.unique, - UnorderedElementsAre(std::make_pair(base_label_unindexed, std::set{property_id, property_extra}), - std::make_pair(extended_label_unused, std::set{property_count}))); - break; - } - } - - bool have_base_dataset = false; - bool have_extended_dataset = false; - switch (type) { - case DatasetType::ONLY_BASE: - case DatasetType::ONLY_BASE_WITH_EXTENDED_INDICES_AND_CONSTRAINTS: - have_base_dataset = true; - break; - case DatasetType::ONLY_EXTENDED: - case DatasetType::ONLY_EXTENDED_WITH_BASE_INDICES_AND_CONSTRAINTS: - have_extended_dataset = true; - break; - case DatasetType::BASE_WITH_EXTENDED: - have_base_dataset = true; - have_extended_dataset = true; - break; - } - - // Create storage accessor. - auto acc = store->Access(); - - // Verify base dataset. - if (have_base_dataset) { - // Verify vertices. - for (uint64_t i = 0; i < kNumBaseVertices; ++i) { - auto vertex = acc.FindVertex(base_vertex_gids_[i], memgraph::storage::View::OLD); - ASSERT_TRUE(vertex); - auto labels = vertex->Labels(memgraph::storage::View::OLD); - ASSERT_TRUE(labels.HasValue()); - if (i < kNumBaseVertices / 2) { - ASSERT_THAT(*labels, UnorderedElementsAre(base_label_indexed)); - } else { - ASSERT_THAT(*labels, UnorderedElementsAre(base_label_unindexed)); - } - auto properties = vertex->Properties(memgraph::storage::View::OLD); - ASSERT_TRUE(properties.HasValue()); - if (i < kNumBaseVertices / 3 || i >= kNumBaseVertices / 2) { - ASSERT_EQ(properties->size(), 1); - ASSERT_EQ((*properties)[property_id], memgraph::storage::PropertyValue(static_cast(i))); - } else { - ASSERT_EQ(properties->size(), 0); - } - } - - // Verify edges. - for (uint64_t i = 0; i < kNumBaseEdges; ++i) { - auto find_edge = [&](const auto &edges) -> std::optional { - for (const auto &edge : edges) { - if (edge.Gid() == base_edge_gids_[i]) { - return edge; - } - } - return std::nullopt; - }; - - { - auto vertex1 = acc.FindVertex(base_vertex_gids_[(i / 2) % kNumBaseVertices], memgraph::storage::View::OLD); - ASSERT_TRUE(vertex1); - auto out_edges = vertex1->OutEdges(memgraph::storage::View::OLD); - ASSERT_TRUE(out_edges.HasValue()); - auto edge1 = find_edge(*out_edges); - ASSERT_TRUE(edge1); - if (i < kNumBaseEdges / 2) { - ASSERT_EQ(edge1->EdgeType(), et1); - } else { - ASSERT_EQ(edge1->EdgeType(), et2); - } - auto properties = edge1->Properties(memgraph::storage::View::OLD); - ASSERT_TRUE(properties.HasValue()); - if (properties_on_edges) { - ASSERT_EQ(properties->size(), 1); - ASSERT_EQ((*properties)[property_id], memgraph::storage::PropertyValue(static_cast(i))); - } else { - ASSERT_EQ(properties->size(), 0); - } - } - - { - auto vertex2 = acc.FindVertex(base_vertex_gids_[(i / 3) % kNumBaseVertices], memgraph::storage::View::OLD); - ASSERT_TRUE(vertex2); - auto in_edges = vertex2->InEdges(memgraph::storage::View::OLD); - ASSERT_TRUE(in_edges.HasValue()); - auto edge2 = find_edge(*in_edges); - ASSERT_TRUE(edge2); - if (i < kNumBaseEdges / 2) { - ASSERT_EQ(edge2->EdgeType(), et1); - } else { - ASSERT_EQ(edge2->EdgeType(), et2); - } - auto properties = edge2->Properties(memgraph::storage::View::OLD); - ASSERT_TRUE(properties.HasValue()); - if (properties_on_edges) { - ASSERT_EQ(properties->size(), 1); - ASSERT_EQ((*properties)[property_id], memgraph::storage::PropertyValue(static_cast(i))); - } else { - ASSERT_EQ(properties->size(), 0); - } - } - } - - // Verify label indices. - { - std::vector vertices; - vertices.reserve(kNumBaseVertices / 2); - for (auto vertex : acc.Vertices(base_label_unindexed, memgraph::storage::View::OLD)) { - vertices.push_back(vertex); - } - ASSERT_EQ(vertices.size(), kNumBaseVertices / 2); - std::sort(vertices.begin(), vertices.end(), [](const auto &a, const auto &b) { return a.Gid() < b.Gid(); }); - for (uint64_t i = 0; i < kNumBaseVertices / 2; ++i) { - ASSERT_EQ(vertices[i].Gid(), base_vertex_gids_[kNumBaseVertices / 2 + i]); - } - } - - // Verify label+property index. - { - std::vector vertices; - vertices.reserve(kNumBaseVertices / 3); - for (auto vertex : acc.Vertices(base_label_indexed, property_id, memgraph::storage::View::OLD)) { - vertices.push_back(vertex); - } - ASSERT_EQ(vertices.size(), kNumBaseVertices / 3); - std::sort(vertices.begin(), vertices.end(), [](const auto &a, const auto &b) { return a.Gid() < b.Gid(); }); - for (uint64_t i = 0; i < kNumBaseVertices / 3; ++i) { - ASSERT_EQ(vertices[i].Gid(), base_vertex_gids_[i]); - } - } - } else { - // Verify vertices. - for (uint64_t i = 0; i < kNumBaseVertices; ++i) { - auto vertex = acc.FindVertex(base_vertex_gids_[i], memgraph::storage::View::OLD); - ASSERT_FALSE(vertex); - } - - if (type == DatasetType::ONLY_EXTENDED_WITH_BASE_INDICES_AND_CONSTRAINTS) { - // Verify label indices. - { - uint64_t count = 0; - auto iterable = acc.Vertices(base_label_unindexed, memgraph::storage::View::OLD); - for (auto it = iterable.begin(); it != iterable.end(); ++it) { - ++count; - } - ASSERT_EQ(count, 0); - } - - // Verify label+property index. - { - uint64_t count = 0; - auto iterable = acc.Vertices(base_label_indexed, property_id, memgraph::storage::View::OLD); - for (auto it = iterable.begin(); it != iterable.end(); ++it) { - ++count; - } - ASSERT_EQ(count, 0); - } - } - } - - // Verify extended dataset. - if (have_extended_dataset) { - // Verify vertices. - for (uint64_t i = 0; i < kNumExtendedVertices; ++i) { - auto vertex = acc.FindVertex(extended_vertex_gids_[i], memgraph::storage::View::OLD); - ASSERT_TRUE(vertex); - auto labels = vertex->Labels(memgraph::storage::View::OLD); - ASSERT_TRUE(labels.HasValue()); - if (i < kNumExtendedVertices / 2) { - ASSERT_THAT(*labels, UnorderedElementsAre(extended_label_indexed)); - } - auto properties = vertex->Properties(memgraph::storage::View::OLD); - ASSERT_TRUE(properties.HasValue()); - if (i < kNumExtendedVertices / 3 || i >= kNumExtendedVertices / 2) { - ASSERT_EQ(properties->size(), 1); - ASSERT_EQ((*properties)[property_count], memgraph::storage::PropertyValue("nandare")); - } else { - ASSERT_EQ(properties->size(), 0); - } - } - - // Verify edges. - for (uint64_t i = 0; i < kNumExtendedEdges; ++i) { - auto find_edge = [&](const auto &edges) -> std::optional { - for (const auto &edge : edges) { - if (edge.Gid() == extended_edge_gids_[i]) { - return edge; - } - } - return std::nullopt; - }; - - { - auto vertex1 = - acc.FindVertex(extended_vertex_gids_[(i / 5) % kNumExtendedVertices], memgraph::storage::View::OLD); - ASSERT_TRUE(vertex1); - auto out_edges = vertex1->OutEdges(memgraph::storage::View::OLD); - ASSERT_TRUE(out_edges.HasValue()); - auto edge1 = find_edge(*out_edges); - ASSERT_TRUE(edge1); - if (i < kNumExtendedEdges / 4) { - ASSERT_EQ(edge1->EdgeType(), et3); - } else { - ASSERT_EQ(edge1->EdgeType(), et4); - } - auto properties = edge1->Properties(memgraph::storage::View::OLD); - ASSERT_TRUE(properties.HasValue()); - ASSERT_EQ(properties->size(), 0); - } - - { - auto vertex2 = - acc.FindVertex(extended_vertex_gids_[(i / 6) % kNumExtendedVertices], memgraph::storage::View::OLD); - ASSERT_TRUE(vertex2); - auto in_edges = vertex2->InEdges(memgraph::storage::View::OLD); - ASSERT_TRUE(in_edges.HasValue()); - auto edge2 = find_edge(*in_edges); - ASSERT_TRUE(edge2); - if (i < kNumExtendedEdges / 4) { - ASSERT_EQ(edge2->EdgeType(), et3); - } else { - ASSERT_EQ(edge2->EdgeType(), et4); - } - auto properties = edge2->Properties(memgraph::storage::View::OLD); - ASSERT_TRUE(properties.HasValue()); - ASSERT_EQ(properties->size(), 0); - } - } - - // Verify label indices. - { - std::vector vertices; - vertices.reserve(kNumExtendedVertices / 2); - for (auto vertex : acc.Vertices(extended_label_unused, memgraph::storage::View::OLD)) { - vertices.push_back(vertex); - } - ASSERT_EQ(vertices.size(), 0); - } - - // Verify label+property index. - { - std::vector vertices; - vertices.reserve(kNumExtendedVertices / 3); - for (auto vertex : acc.Vertices(extended_label_indexed, property_count, memgraph::storage::View::OLD)) { - vertices.push_back(vertex); - } - ASSERT_EQ(vertices.size(), kNumExtendedVertices / 3); - std::sort(vertices.begin(), vertices.end(), [](const auto &a, const auto &b) { return a.Gid() < b.Gid(); }); - for (uint64_t i = 0; i < kNumExtendedVertices / 3; ++i) { - ASSERT_EQ(vertices[i].Gid(), extended_vertex_gids_[i]); - } - } - } else { - // Verify vertices. - for (uint64_t i = 0; i < kNumExtendedVertices; ++i) { - auto vertex = acc.FindVertex(extended_vertex_gids_[i], memgraph::storage::View::OLD); - ASSERT_FALSE(vertex); - } - - if (type == DatasetType::ONLY_BASE_WITH_EXTENDED_INDICES_AND_CONSTRAINTS) { - // Verify label indices. - { - uint64_t count = 0; - auto iterable = acc.Vertices(extended_label_unused, memgraph::storage::View::OLD); - for (auto it = iterable.begin(); it != iterable.end(); ++it) { - ++count; - } - ASSERT_EQ(count, 0); - } - - // Verify label+property index. - { - uint64_t count = 0; - auto iterable = acc.Vertices(extended_label_indexed, property_count, memgraph::storage::View::OLD); - for (auto it = iterable.begin(); it != iterable.end(); ++it) { - ++count; - } - ASSERT_EQ(count, 0); - } - } - } - - if (verify_info) { - auto info = store->GetInfo(); - if (have_base_dataset) { - if (have_extended_dataset) { - ASSERT_EQ(info.vertex_count, kNumBaseVertices + kNumExtendedVertices); - ASSERT_EQ(info.edge_count, kNumBaseEdges + kNumExtendedEdges); - } else { - ASSERT_EQ(info.vertex_count, kNumBaseVertices); - ASSERT_EQ(info.edge_count, kNumBaseEdges); - } - } else { - if (have_extended_dataset) { - ASSERT_EQ(info.vertex_count, kNumExtendedVertices); - ASSERT_EQ(info.edge_count, kNumExtendedEdges); - } else { - ASSERT_EQ(info.vertex_count, 0); - ASSERT_EQ(info.edge_count, 0); - } - } - } - } - - std::vector GetSnapshotsList() { - return GetFilesList(storage_directory / memgraph::storage::durability::kSnapshotDirectory); - } - - std::vector GetBackupSnapshotsList() { - return GetFilesList(storage_directory / memgraph::storage::durability::kBackupDirectory / - memgraph::storage::durability::kSnapshotDirectory); - } - - std::vector GetWalsList() { - return GetFilesList(storage_directory / memgraph::storage::durability::kWalDirectory); - } - - std::vector GetBackupWalsList() { - return GetFilesList(storage_directory / memgraph::storage::durability::kBackupDirectory / - memgraph::storage::durability::kWalDirectory); - } - - void RestoreBackups() { - { - auto backup_snapshots = GetBackupSnapshotsList(); - for (const auto &item : backup_snapshots) { - std::filesystem::rename( - item, storage_directory / memgraph::storage::durability::kSnapshotDirectory / item.filename()); - } - } - { - auto backup_wals = GetBackupWalsList(); - for (const auto &item : backup_wals) { - std::filesystem::rename(item, - storage_directory / memgraph::storage::durability::kWalDirectory / item.filename()); - } - } - } - - std::filesystem::path storage_directory{std::filesystem::temp_directory_path() / - "MG_test_unit_storage_v2_durability"}; - - private: - std::vector GetFilesList(const std::filesystem::path &path) { - std::vector ret; - std::error_code ec; // For exception suppression. - for (auto &item : std::filesystem::directory_iterator(path, ec)) { - ret.push_back(item.path()); - } - std::sort(ret.begin(), ret.end()); - std::reverse(ret.begin(), ret.end()); - return ret; - } - - void Clear() { - if (!std::filesystem::exists(storage_directory)) return; - std::filesystem::remove_all(storage_directory); - } - - std::vector base_vertex_gids_; - std::vector base_edge_gids_; - std::vector extended_vertex_gids_; - std::vector extended_edge_gids_; -}; - -void DestroySnapshot(const std::filesystem::path &path) { - auto info = memgraph::storage::durability::ReadSnapshotInfo(path); - spdlog::info("Destroying snapshot {}", path); - memgraph::utils::OutputFile file; - file.Open(path, memgraph::utils::OutputFile::Mode::OVERWRITE_EXISTING); - file.SetPosition(memgraph::utils::OutputFile::Position::SET, info.offset_vertices); - auto value = static_cast(memgraph::storage::durability::Marker::TYPE_MAP); - file.Write(&value, sizeof(value)); - file.Sync(); - file.Close(); -} - -void DestroyWalFirstDelta(const std::filesystem::path &path) { - auto info = memgraph::storage::durability::ReadWalInfo(path); - spdlog::info("Destroying WAL {}", path); - memgraph::utils::OutputFile file; - file.Open(path, memgraph::utils::OutputFile::Mode::OVERWRITE_EXISTING); - file.SetPosition(memgraph::utils::OutputFile::Position::SET, info.offset_deltas); - auto value = static_cast(memgraph::storage::durability::Marker::TYPE_MAP); - file.Write(&value, sizeof(value)); - file.Sync(); - file.Close(); -} - -void DestroyWalSuffix(const std::filesystem::path &path) { - auto info = memgraph::storage::durability::ReadWalInfo(path); - spdlog::info("Destroying WAL {}", path); - memgraph::utils::OutputFile file; - file.Open(path, memgraph::utils::OutputFile::Mode::OVERWRITE_EXISTING); - ASSERT_LT(info.offset_deltas, file.SetPosition(memgraph::utils::OutputFile::Position::RELATIVE_TO_END, -100)); - uint8_t value = 0; - for (size_t i = 0; i < 100; ++i) { - file.Write(&value, sizeof(value)); - } - file.Sync(); - file.Close(); -} - -INSTANTIATE_TEST_CASE_P(EdgesWithProperties, DurabilityTest, ::testing::Values(true)); -INSTANTIATE_TEST_CASE_P(EdgesWithoutProperties, DurabilityTest, ::testing::Values(false)); - -// NOLINTNEXTLINE(hicpp-special-member-functions) -TEST_P(DurabilityTest, SnapshotOnExit) { - // Create snapshot. - { - memgraph::storage::Storage store( - {.items = {.properties_on_edges = GetParam()}, - .durability = {.storage_directory = storage_directory, .snapshot_on_exit = true}}); - CreateBaseDataset(&store, GetParam()); - VerifyDataset(&store, DatasetType::ONLY_BASE, GetParam()); - CreateExtendedDataset(&store); - VerifyDataset(&store, DatasetType::BASE_WITH_EXTENDED, GetParam()); - } - - ASSERT_EQ(GetSnapshotsList().size(), 1); - ASSERT_EQ(GetBackupSnapshotsList().size(), 0); - ASSERT_EQ(GetWalsList().size(), 0); - ASSERT_EQ(GetBackupWalsList().size(), 0); - - // Recover snapshot. - memgraph::storage::Storage store( - {.items = {.properties_on_edges = GetParam()}, - .durability = {.storage_directory = storage_directory, .recover_on_startup = true}}); - VerifyDataset(&store, DatasetType::BASE_WITH_EXTENDED, GetParam()); - - // Try to use the storage. - { - auto acc = store.Access(); - auto vertex = acc.CreateVertex(); - auto edge = acc.CreateEdge(&vertex, &vertex, store.NameToEdgeType("et")); - ASSERT_TRUE(edge.HasValue()); - ASSERT_FALSE(acc.Commit().HasError()); - } -} - -// NOLINTNEXTLINE(hicpp-special-member-functions) -TEST_P(DurabilityTest, SnapshotPeriodic) { - // Create snapshot. - { - memgraph::storage::Storage store( - {.items = {.properties_on_edges = GetParam()}, - .durability = {.storage_directory = storage_directory, - .snapshot_wal_mode = memgraph::storage::Config::Durability::SnapshotWalMode::PERIODIC_SNAPSHOT, - .snapshot_interval = std::chrono::milliseconds(2000)}}); - CreateBaseDataset(&store, GetParam()); - std::this_thread::sleep_for(std::chrono::milliseconds(2500)); - } - - ASSERT_GE(GetSnapshotsList().size(), 1); - ASSERT_EQ(GetBackupSnapshotsList().size(), 0); - ASSERT_EQ(GetWalsList().size(), 0); - ASSERT_EQ(GetBackupWalsList().size(), 0); - - // Recover snapshot. - memgraph::storage::Storage store( - {.items = {.properties_on_edges = GetParam()}, - .durability = {.storage_directory = storage_directory, .recover_on_startup = true}}); - VerifyDataset(&store, DatasetType::ONLY_BASE, GetParam()); - - // Try to use the storage. - { - auto acc = store.Access(); - auto vertex = acc.CreateVertex(); - auto edge = acc.CreateEdge(&vertex, &vertex, store.NameToEdgeType("et")); - ASSERT_TRUE(edge.HasValue()); - ASSERT_FALSE(acc.Commit().HasError()); - } -} - -// NOLINTNEXTLINE(hicpp-special-member-functions) -TEST_P(DurabilityTest, SnapshotFallback) { - // Create snapshot. - { - memgraph::storage::Storage store( - {.items = {.properties_on_edges = GetParam()}, - .durability = {.storage_directory = storage_directory, - .snapshot_wal_mode = memgraph::storage::Config::Durability::SnapshotWalMode::PERIODIC_SNAPSHOT, - .snapshot_interval = std::chrono::milliseconds(3000)}}); - CreateBaseDataset(&store, GetParam()); - std::this_thread::sleep_for(std::chrono::milliseconds(3500)); - ASSERT_EQ(GetSnapshotsList().size(), 1); - CreateExtendedDataset(&store); - std::this_thread::sleep_for(std::chrono::milliseconds(3000)); - } - - ASSERT_EQ(GetSnapshotsList().size(), 2); - ASSERT_EQ(GetBackupSnapshotsList().size(), 0); - ASSERT_EQ(GetWalsList().size(), 0); - ASSERT_EQ(GetBackupWalsList().size(), 0); - - // Destroy last snapshot. - { - auto snapshots = GetSnapshotsList(); - ASSERT_EQ(snapshots.size(), 2); - DestroySnapshot(*snapshots.begin()); - } - - // Recover snapshot. - memgraph::storage::Storage store( - {.items = {.properties_on_edges = GetParam()}, - .durability = {.storage_directory = storage_directory, .recover_on_startup = true}}); - VerifyDataset(&store, DatasetType::ONLY_BASE, GetParam()); - - // Try to use the storage. - { - auto acc = store.Access(); - auto vertex = acc.CreateVertex(); - auto edge = acc.CreateEdge(&vertex, &vertex, store.NameToEdgeType("et")); - ASSERT_TRUE(edge.HasValue()); - ASSERT_FALSE(acc.Commit().HasError()); - } -} - -// NOLINTNEXTLINE(hicpp-special-member-functions) -TEST_P(DurabilityTest, SnapshotEverythingCorrupt) { - // Create unrelated snapshot. - { - memgraph::storage::Storage store( - {.items = {.properties_on_edges = GetParam()}, - .durability = {.storage_directory = storage_directory, .snapshot_on_exit = true}}); - auto acc = store.Access(); - for (uint64_t i = 0; i < 1000; ++i) { - acc.CreateVertex(); - } - ASSERT_FALSE(acc.Commit().HasError()); - } - - ASSERT_EQ(GetSnapshotsList().size(), 1); - ASSERT_EQ(GetBackupSnapshotsList().size(), 0); - ASSERT_EQ(GetWalsList().size(), 0); - ASSERT_EQ(GetBackupWalsList().size(), 0); - - // Get unrelated UUID. - std::string unrelated_uuid; - { - auto snapshots = GetSnapshotsList(); - ASSERT_EQ(snapshots.size(), 1); - auto info = memgraph::storage::durability::ReadSnapshotInfo(*snapshots.begin()); - unrelated_uuid = info.uuid; - } - - // Create snapshot. - { - memgraph::storage::Storage store( - {.items = {.properties_on_edges = GetParam()}, - .durability = {.storage_directory = storage_directory, - .snapshot_wal_mode = memgraph::storage::Config::Durability::SnapshotWalMode::PERIODIC_SNAPSHOT, - .snapshot_interval = std::chrono::milliseconds(2000)}}); - CreateBaseDataset(&store, GetParam()); - std::this_thread::sleep_for(std::chrono::milliseconds(2500)); - CreateExtendedDataset(&store); - std::this_thread::sleep_for(std::chrono::milliseconds(2500)); - } - - ASSERT_GE(GetSnapshotsList().size(), 1); - ASSERT_EQ(GetBackupSnapshotsList().size(), 1); - ASSERT_EQ(GetWalsList().size(), 0); - ASSERT_EQ(GetBackupWalsList().size(), 0); - - // Restore unrelated snapshots. - RestoreBackups(); - - ASSERT_GE(GetSnapshotsList().size(), 2); - ASSERT_EQ(GetBackupSnapshotsList().size(), 0); - ASSERT_EQ(GetWalsList().size(), 0); - ASSERT_EQ(GetBackupWalsList().size(), 0); - - // Destroy all current snapshots. - { - auto snapshots = GetSnapshotsList(); - ASSERT_GE(snapshots.size(), 2); - for (const auto &snapshot : snapshots) { - auto info = memgraph::storage::durability::ReadSnapshotInfo(snapshot); - if (info.uuid == unrelated_uuid) { - spdlog::info("Skipping snapshot {}", snapshot); - continue; - } - DestroySnapshot(snapshot); - } - } - - // Recover snapshot. - ASSERT_DEATH( - { - memgraph::storage::Storage store( - {.items = {.properties_on_edges = GetParam()}, - .durability = {.storage_directory = storage_directory, .recover_on_startup = true}}); - }, - ""); -} - -// NOLINTNEXTLINE(hicpp-special-member-functions) -TEST_P(DurabilityTest, SnapshotRetention) { - // Create unrelated snapshot. - { - memgraph::storage::Storage store( - {.items = {.properties_on_edges = GetParam()}, - .durability = {.storage_directory = storage_directory, .snapshot_on_exit = true}}); - auto acc = store.Access(); - for (uint64_t i = 0; i < 1000; ++i) { - acc.CreateVertex(); - } - ASSERT_FALSE(acc.Commit().HasError()); - } - - ASSERT_GE(GetSnapshotsList().size(), 1); - ASSERT_EQ(GetBackupSnapshotsList().size(), 0); - ASSERT_EQ(GetWalsList().size(), 0); - ASSERT_EQ(GetBackupWalsList().size(), 0); - - // Create snapshot. - { - memgraph::storage::Storage store( - {.items = {.properties_on_edges = GetParam()}, - .durability = {.storage_directory = storage_directory, - .snapshot_wal_mode = memgraph::storage::Config::Durability::SnapshotWalMode::PERIODIC_SNAPSHOT, - .snapshot_interval = std::chrono::milliseconds(2000), - .snapshot_retention_count = 3}}); - // Restore unrelated snapshots after the database has been started. - RestoreBackups(); - CreateBaseDataset(&store, GetParam()); - // Allow approximately 5 snapshots to be created. - std::this_thread::sleep_for(std::chrono::milliseconds(10000)); - } - - ASSERT_EQ(GetSnapshotsList().size(), 1 + 3); - ASSERT_EQ(GetBackupSnapshotsList().size(), 0); - ASSERT_EQ(GetWalsList().size(), 0); - ASSERT_EQ(GetBackupWalsList().size(), 0); - - // Verify that exactly 3 snapshots and 1 unrelated snapshot exist. - { - auto snapshots = GetSnapshotsList(); - ASSERT_EQ(snapshots.size(), 1 + 3); - std::string uuid; - for (size_t i = 0; i < snapshots.size(); ++i) { - const auto &path = snapshots[i]; - // This shouldn't throw. - auto info = memgraph::storage::durability::ReadSnapshotInfo(path); - if (i == 0) uuid = info.uuid; - if (i < snapshots.size() - 1) { - ASSERT_EQ(info.uuid, uuid); - } else { - ASSERT_NE(info.uuid, uuid); - } - } - } - - // Recover snapshot. - memgraph::storage::Storage store( - {.items = {.properties_on_edges = GetParam()}, - .durability = {.storage_directory = storage_directory, .recover_on_startup = true}}); - VerifyDataset(&store, DatasetType::ONLY_BASE, GetParam()); - - // Try to use the storage. - { - auto acc = store.Access(); - auto vertex = acc.CreateVertex(); - auto edge = acc.CreateEdge(&vertex, &vertex, store.NameToEdgeType("et")); - ASSERT_TRUE(edge.HasValue()); - ASSERT_FALSE(acc.Commit().HasError()); - } -} - -// NOLINTNEXTLINE(hicpp-special-member-functions) -TEST_P(DurabilityTest, SnapshotMixedUUID) { - // Create snapshot. - { - memgraph::storage::Storage store( - {.items = {.properties_on_edges = GetParam()}, - .durability = {.storage_directory = storage_directory, .snapshot_on_exit = true}}); - CreateBaseDataset(&store, GetParam()); - VerifyDataset(&store, DatasetType::ONLY_BASE, GetParam()); - CreateExtendedDataset(&store); - VerifyDataset(&store, DatasetType::BASE_WITH_EXTENDED, GetParam()); - } - - ASSERT_EQ(GetSnapshotsList().size(), 1); - ASSERT_EQ(GetBackupSnapshotsList().size(), 0); - ASSERT_EQ(GetWalsList().size(), 0); - ASSERT_EQ(GetBackupWalsList().size(), 0); - - // Recover snapshot. - { - memgraph::storage::Storage store( - {.items = {.properties_on_edges = GetParam()}, - .durability = {.storage_directory = storage_directory, .recover_on_startup = true}}); - VerifyDataset(&store, DatasetType::BASE_WITH_EXTENDED, GetParam()); - } - - // Create another snapshot. - { - memgraph::storage::Storage store( - {.items = {.properties_on_edges = GetParam()}, - .durability = {.storage_directory = storage_directory, .snapshot_on_exit = true}}); - CreateBaseDataset(&store, GetParam()); - VerifyDataset(&store, DatasetType::ONLY_BASE, GetParam()); - } - - ASSERT_EQ(GetSnapshotsList().size(), 1); - ASSERT_EQ(GetBackupSnapshotsList().size(), 1); - ASSERT_EQ(GetWalsList().size(), 0); - ASSERT_EQ(GetBackupWalsList().size(), 0); - - // Restore unrelated snapshot. - RestoreBackups(); - - ASSERT_EQ(GetSnapshotsList().size(), 2); - ASSERT_EQ(GetBackupSnapshotsList().size(), 0); - ASSERT_EQ(GetWalsList().size(), 0); - ASSERT_EQ(GetBackupWalsList().size(), 0); - - // Recover snapshot. - memgraph::storage::Storage store( - {.items = {.properties_on_edges = GetParam()}, - .durability = {.storage_directory = storage_directory, .recover_on_startup = true}}); - VerifyDataset(&store, DatasetType::ONLY_BASE, GetParam()); - - // Try to use the storage. - { - auto acc = store.Access(); - auto vertex = acc.CreateVertex(); - auto edge = acc.CreateEdge(&vertex, &vertex, store.NameToEdgeType("et")); - ASSERT_TRUE(edge.HasValue()); - ASSERT_FALSE(acc.Commit().HasError()); - } -} - -// NOLINTNEXTLINE(hicpp-special-member-functions) -TEST_P(DurabilityTest, SnapshotBackup) { - // Create snapshot. - { - memgraph::storage::Storage store( - {.items = {.properties_on_edges = GetParam()}, - .durability = {.storage_directory = storage_directory, .snapshot_on_exit = true}}); - auto acc = store.Access(); - for (uint64_t i = 0; i < 1000; ++i) { - acc.CreateVertex(); - } - ASSERT_FALSE(acc.Commit().HasError()); - } - - ASSERT_EQ(GetSnapshotsList().size(), 1); - ASSERT_EQ(GetBackupSnapshotsList().size(), 0); - ASSERT_EQ(GetWalsList().size(), 0); - ASSERT_EQ(GetBackupWalsList().size(), 0); - - // Start storage without recovery. - { - memgraph::storage::Storage store( - {.items = {.properties_on_edges = GetParam()}, - .durability = {.storage_directory = storage_directory, - .snapshot_wal_mode = memgraph::storage::Config::Durability::SnapshotWalMode::PERIODIC_SNAPSHOT, - .snapshot_interval = std::chrono::minutes(20)}}); - } - - ASSERT_EQ(GetSnapshotsList().size(), 0); - ASSERT_EQ(GetBackupSnapshotsList().size(), 1); - ASSERT_EQ(GetWalsList().size(), 0); - ASSERT_EQ(GetBackupWalsList().size(), 0); -} - -// NOLINTNEXTLINE(hicpp-special-member-functions) -TEST_F(DurabilityTest, SnapshotWithoutPropertiesOnEdgesRecoveryWithPropertiesOnEdges) { - // Create snapshot. - { - memgraph::storage::Storage store( - {.items = {.properties_on_edges = false}, - .durability = {.storage_directory = storage_directory, .snapshot_on_exit = true}}); - CreateBaseDataset(&store, false); - VerifyDataset(&store, DatasetType::ONLY_BASE, false); - CreateExtendedDataset(&store); - VerifyDataset(&store, DatasetType::BASE_WITH_EXTENDED, false); - } - - ASSERT_EQ(GetSnapshotsList().size(), 1); - ASSERT_EQ(GetBackupSnapshotsList().size(), 0); - ASSERT_EQ(GetWalsList().size(), 0); - ASSERT_EQ(GetBackupWalsList().size(), 0); - - // Recover snapshot. - memgraph::storage::Storage store( - {.items = {.properties_on_edges = true}, - .durability = {.storage_directory = storage_directory, .recover_on_startup = true}}); - VerifyDataset(&store, DatasetType::BASE_WITH_EXTENDED, false); - - // Try to use the storage. - { - auto acc = store.Access(); - auto vertex = acc.CreateVertex(); - auto edge = acc.CreateEdge(&vertex, &vertex, store.NameToEdgeType("et")); - ASSERT_TRUE(edge.HasValue()); - ASSERT_FALSE(acc.Commit().HasError()); - } -} - -// NOLINTNEXTLINE(hicpp-special-member-functions) -TEST_F(DurabilityTest, SnapshotWithPropertiesOnEdgesRecoveryWithoutPropertiesOnEdges) { - // Create snapshot. - { - memgraph::storage::Storage store( - {.items = {.properties_on_edges = true}, - .durability = {.storage_directory = storage_directory, .snapshot_on_exit = true}}); - CreateBaseDataset(&store, true); - VerifyDataset(&store, DatasetType::ONLY_BASE, true); - CreateExtendedDataset(&store); - VerifyDataset(&store, DatasetType::BASE_WITH_EXTENDED, true); - } - - ASSERT_EQ(GetSnapshotsList().size(), 1); - ASSERT_EQ(GetBackupSnapshotsList().size(), 0); - ASSERT_EQ(GetWalsList().size(), 0); - ASSERT_EQ(GetBackupWalsList().size(), 0); - - // Recover snapshot. - ASSERT_DEATH( - { - memgraph::storage::Storage store( - {.items = {.properties_on_edges = false}, - .durability = {.storage_directory = storage_directory, .recover_on_startup = true}}); - }, - ""); -} - -// NOLINTNEXTLINE(hicpp-special-member-functions) -TEST_F(DurabilityTest, SnapshotWithPropertiesOnEdgesButUnusedRecoveryWithoutPropertiesOnEdges) { - // Create snapshot. - { - memgraph::storage::Storage store( - {.items = {.properties_on_edges = true}, - .durability = {.storage_directory = storage_directory, .snapshot_on_exit = true}}); - CreateBaseDataset(&store, true); - VerifyDataset(&store, DatasetType::ONLY_BASE, true); - CreateExtendedDataset(&store); - VerifyDataset(&store, DatasetType::BASE_WITH_EXTENDED, true); - // Remove properties from edges. - { - auto acc = store.Access(); - for (auto vertex : acc.Vertices(memgraph::storage::View::OLD)) { - auto in_edges = vertex.InEdges(memgraph::storage::View::OLD); - ASSERT_TRUE(in_edges.HasValue()); - for (auto edge : *in_edges) { - // TODO (mferencevic): Replace with `ClearProperties()` - auto props = edge.Properties(memgraph::storage::View::NEW); - ASSERT_TRUE(props.HasValue()); - for (const auto &prop : *props) { - ASSERT_TRUE(edge.SetProperty(prop.first, memgraph::storage::PropertyValue()).HasValue()); - } - } - auto out_edges = vertex.InEdges(memgraph::storage::View::OLD); - ASSERT_TRUE(out_edges.HasValue()); - for (auto edge : *out_edges) { - // TODO (mferencevic): Replace with `ClearProperties()` - auto props = edge.Properties(memgraph::storage::View::NEW); - ASSERT_TRUE(props.HasValue()); - for (const auto &prop : *props) { - ASSERT_TRUE(edge.SetProperty(prop.first, memgraph::storage::PropertyValue()).HasValue()); - } - } - } - ASSERT_FALSE(acc.Commit().HasError()); - } - } - - ASSERT_EQ(GetSnapshotsList().size(), 1); - ASSERT_EQ(GetBackupSnapshotsList().size(), 0); - ASSERT_EQ(GetWalsList().size(), 0); - ASSERT_EQ(GetBackupWalsList().size(), 0); - - // Recover snapshot. - memgraph::storage::Storage store( - {.items = {.properties_on_edges = false}, - .durability = {.storage_directory = storage_directory, .recover_on_startup = true}}); - VerifyDataset(&store, DatasetType::BASE_WITH_EXTENDED, false); - - // Try to use the storage. - { - auto acc = store.Access(); - auto vertex = acc.CreateVertex(); - auto edge = acc.CreateEdge(&vertex, &vertex, store.NameToEdgeType("et")); - ASSERT_TRUE(edge.HasValue()); - ASSERT_FALSE(acc.Commit().HasError()); - } -} - -// NOLINTNEXTLINE(hicpp-special-member-functions) -TEST_P(DurabilityTest, WalBasic) { - // Create WALs. - { - memgraph::storage::Storage store( - {.items = {.properties_on_edges = GetParam()}, - .durability = { - .storage_directory = storage_directory, - .snapshot_wal_mode = memgraph::storage::Config::Durability::SnapshotWalMode::PERIODIC_SNAPSHOT_WITH_WAL, - .snapshot_interval = std::chrono::minutes(20), - .wal_file_flush_every_n_tx = kFlushWalEvery}}); - CreateBaseDataset(&store, GetParam()); - CreateExtendedDataset(&store); - } - - ASSERT_EQ(GetSnapshotsList().size(), 0); - ASSERT_EQ(GetBackupSnapshotsList().size(), 0); - ASSERT_GE(GetWalsList().size(), 1); - ASSERT_EQ(GetBackupWalsList().size(), 0); - - // Recover WALs. - memgraph::storage::Storage store( - {.items = {.properties_on_edges = GetParam()}, - .durability = {.storage_directory = storage_directory, .recover_on_startup = true}}); - VerifyDataset(&store, DatasetType::BASE_WITH_EXTENDED, GetParam()); - - // Try to use the storage. - { - auto acc = store.Access(); - auto vertex = acc.CreateVertex(); - auto edge = acc.CreateEdge(&vertex, &vertex, store.NameToEdgeType("et")); - ASSERT_TRUE(edge.HasValue()); - ASSERT_FALSE(acc.Commit().HasError()); - } -} - -// NOLINTNEXTLINE(hicpp-special-member-functions) -TEST_P(DurabilityTest, WalBackup) { - // Create WALs. - { - memgraph::storage::Storage store( - {.items = {.properties_on_edges = GetParam()}, - .durability = { - .storage_directory = storage_directory, - .snapshot_wal_mode = memgraph::storage::Config::Durability::SnapshotWalMode::PERIODIC_SNAPSHOT_WITH_WAL, - .snapshot_interval = std::chrono::minutes(20), - .wal_file_size_kibibytes = 1, - .wal_file_flush_every_n_tx = kFlushWalEvery}}); - auto acc = store.Access(); - for (uint64_t i = 0; i < 1000; ++i) { - acc.CreateVertex(); - } - ASSERT_FALSE(acc.Commit().HasError()); - } - - ASSERT_EQ(GetSnapshotsList().size(), 0); - ASSERT_EQ(GetBackupSnapshotsList().size(), 0); - auto num_wals = GetWalsList().size(); - ASSERT_GE(num_wals, 1); - ASSERT_EQ(GetBackupWalsList().size(), 0); - - // Start storage without recovery. - { - memgraph::storage::Storage store( - {.items = {.properties_on_edges = GetParam()}, - .durability = { - .storage_directory = storage_directory, - .snapshot_wal_mode = memgraph::storage::Config::Durability::SnapshotWalMode::PERIODIC_SNAPSHOT_WITH_WAL, - .snapshot_interval = std::chrono::minutes(20)}}); - } - - ASSERT_EQ(GetSnapshotsList().size(), 0); - ASSERT_EQ(GetBackupSnapshotsList().size(), 0); - ASSERT_EQ(GetWalsList().size(), 0); - ASSERT_EQ(GetBackupWalsList().size(), num_wals); -} - -// NOLINTNEXTLINE(hicpp-special-member-functions) -TEST_P(DurabilityTest, WalAppendToExisting) { - // Create WALs. - { - memgraph::storage::Storage store( - {.items = {.properties_on_edges = GetParam()}, - .durability = { - .storage_directory = storage_directory, - .snapshot_wal_mode = memgraph::storage::Config::Durability::SnapshotWalMode::PERIODIC_SNAPSHOT_WITH_WAL, - .snapshot_interval = std::chrono::minutes(20), - .wal_file_flush_every_n_tx = kFlushWalEvery}}); - CreateBaseDataset(&store, GetParam()); - } - - ASSERT_EQ(GetSnapshotsList().size(), 0); - ASSERT_EQ(GetBackupSnapshotsList().size(), 0); - ASSERT_GE(GetWalsList().size(), 1); - ASSERT_EQ(GetBackupWalsList().size(), 0); - - // Recover WALs. - { - memgraph::storage::Storage store( - {.items = {.properties_on_edges = GetParam()}, - .durability = {.storage_directory = storage_directory, .recover_on_startup = true}}); - VerifyDataset(&store, DatasetType::ONLY_BASE, GetParam()); - } - - // Recover WALs and create more WALs. - { - memgraph::storage::Storage store( - {.items = {.properties_on_edges = GetParam()}, - .durability = { - .storage_directory = storage_directory, - .recover_on_startup = true, - .snapshot_wal_mode = memgraph::storage::Config::Durability::SnapshotWalMode::PERIODIC_SNAPSHOT_WITH_WAL, - .snapshot_interval = std::chrono::minutes(20), - .wal_file_flush_every_n_tx = kFlushWalEvery}}); - CreateExtendedDataset(&store); - } - - ASSERT_EQ(GetSnapshotsList().size(), 0); - ASSERT_EQ(GetBackupSnapshotsList().size(), 0); - ASSERT_GE(GetWalsList().size(), 2); - ASSERT_EQ(GetBackupWalsList().size(), 0); - - // Recover WALs. - memgraph::storage::Storage store( - {.items = {.properties_on_edges = GetParam()}, - .durability = {.storage_directory = storage_directory, .recover_on_startup = true}}); - VerifyDataset(&store, DatasetType::BASE_WITH_EXTENDED, GetParam()); - - // Try to use the storage. - { - auto acc = store.Access(); - auto vertex = acc.CreateVertex(); - auto edge = acc.CreateEdge(&vertex, &vertex, store.NameToEdgeType("et")); - ASSERT_TRUE(edge.HasValue()); - ASSERT_FALSE(acc.Commit().HasError()); - } -} - -// NOLINTNEXTLINE(hicpp-special-member-functions) -TEST_P(DurabilityTest, WalCreateInSingleTransaction) { - // NOLINTNEXTLINE(readability-isolate-declaration) - memgraph::storage::Gid gid_v1, gid_v2, gid_e1, gid_v3; - - // Create WALs. - { - memgraph::storage::Storage store( - {.items = {.properties_on_edges = GetParam()}, - .durability = { - .storage_directory = storage_directory, - .snapshot_wal_mode = memgraph::storage::Config::Durability::SnapshotWalMode::PERIODIC_SNAPSHOT_WITH_WAL, - .snapshot_interval = std::chrono::minutes(20), - .wal_file_flush_every_n_tx = kFlushWalEvery}}); - auto acc = store.Access(); - auto v1 = acc.CreateVertex(); - gid_v1 = v1.Gid(); - auto v2 = acc.CreateVertex(); - gid_v2 = v2.Gid(); - auto e1 = acc.CreateEdge(&v1, &v2, store.NameToEdgeType("e1")); - ASSERT_TRUE(e1.HasValue()); - gid_e1 = e1->Gid(); - ASSERT_TRUE(v1.AddLabel(store.NameToLabel("l11")).HasValue()); - ASSERT_TRUE(v1.AddLabel(store.NameToLabel("l12")).HasValue()); - ASSERT_TRUE(v1.AddLabel(store.NameToLabel("l13")).HasValue()); - if (GetParam()) { - ASSERT_TRUE( - e1->SetProperty(store.NameToProperty("test"), memgraph::storage::PropertyValue("nandare")).HasValue()); - } - ASSERT_TRUE(v2.AddLabel(store.NameToLabel("l21")).HasValue()); - ASSERT_TRUE(v2.SetProperty(store.NameToProperty("hello"), memgraph::storage::PropertyValue("world")).HasValue()); - auto v3 = acc.CreateVertex(); - gid_v3 = v3.Gid(); - ASSERT_TRUE(v3.SetProperty(store.NameToProperty("v3"), memgraph::storage::PropertyValue(42)).HasValue()); - ASSERT_FALSE(acc.Commit().HasError()); - } - - ASSERT_EQ(GetSnapshotsList().size(), 0); - ASSERT_EQ(GetBackupSnapshotsList().size(), 0); - ASSERT_GE(GetWalsList().size(), 1); - ASSERT_EQ(GetBackupWalsList().size(), 0); - - // Recover WALs. - memgraph::storage::Storage store( - {.items = {.properties_on_edges = GetParam()}, - .durability = {.storage_directory = storage_directory, .recover_on_startup = true}}); - { - auto indices = store.ListAllIndices(); - ASSERT_EQ(indices.label.size(), 0); - ASSERT_EQ(indices.label_property.size(), 0); - auto constraints = store.ListAllConstraints(); - ASSERT_EQ(constraints.existence.size(), 0); - ASSERT_EQ(constraints.unique.size(), 0); - auto acc = store.Access(); - { - auto v1 = acc.FindVertex(gid_v1, memgraph::storage::View::OLD); - ASSERT_TRUE(v1); - auto labels = v1->Labels(memgraph::storage::View::OLD); - ASSERT_TRUE(labels.HasValue()); - ASSERT_THAT(*labels, - UnorderedElementsAre(store.NameToLabel("l11"), store.NameToLabel("l12"), store.NameToLabel("l13"))); - auto props = v1->Properties(memgraph::storage::View::OLD); - ASSERT_TRUE(props.HasValue()); - ASSERT_EQ(props->size(), 0); - auto in_edges = v1->InEdges(memgraph::storage::View::OLD); - ASSERT_TRUE(in_edges.HasValue()); - ASSERT_EQ(in_edges->size(), 0); - auto out_edges = v1->OutEdges(memgraph::storage::View::OLD); - ASSERT_TRUE(out_edges.HasValue()); - ASSERT_EQ(out_edges->size(), 1); - const auto &edge = (*out_edges)[0]; - ASSERT_EQ(edge.Gid(), gid_e1); - auto edge_props = edge.Properties(memgraph::storage::View::OLD); - ASSERT_TRUE(edge_props.HasValue()); - if (GetParam()) { - ASSERT_THAT(*edge_props, UnorderedElementsAre(std::make_pair(store.NameToProperty("test"), - memgraph::storage::PropertyValue("nandare")))); - } else { - ASSERT_EQ(edge_props->size(), 0); - } - } - { - auto v2 = acc.FindVertex(gid_v2, memgraph::storage::View::OLD); - ASSERT_TRUE(v2); - auto labels = v2->Labels(memgraph::storage::View::OLD); - ASSERT_TRUE(labels.HasValue()); - ASSERT_THAT(*labels, UnorderedElementsAre(store.NameToLabel("l21"))); - auto props = v2->Properties(memgraph::storage::View::OLD); - ASSERT_TRUE(props.HasValue()); - ASSERT_THAT(*props, UnorderedElementsAre(std::make_pair(store.NameToProperty("hello"), - memgraph::storage::PropertyValue("world")))); - auto in_edges = v2->InEdges(memgraph::storage::View::OLD); - ASSERT_TRUE(in_edges.HasValue()); - ASSERT_EQ(in_edges->size(), 1); - const auto &edge = (*in_edges)[0]; - ASSERT_EQ(edge.Gid(), gid_e1); - auto edge_props = edge.Properties(memgraph::storage::View::OLD); - ASSERT_TRUE(edge_props.HasValue()); - if (GetParam()) { - ASSERT_THAT(*edge_props, UnorderedElementsAre(std::make_pair(store.NameToProperty("test"), - memgraph::storage::PropertyValue("nandare")))); - } else { - ASSERT_EQ(edge_props->size(), 0); - } - auto out_edges = v2->OutEdges(memgraph::storage::View::OLD); - ASSERT_TRUE(out_edges.HasValue()); - ASSERT_EQ(out_edges->size(), 0); - } - { - auto v3 = acc.FindVertex(gid_v3, memgraph::storage::View::OLD); - ASSERT_TRUE(v3); - auto labels = v3->Labels(memgraph::storage::View::OLD); - ASSERT_TRUE(labels.HasValue()); - ASSERT_EQ(labels->size(), 0); - auto props = v3->Properties(memgraph::storage::View::OLD); - ASSERT_TRUE(props.HasValue()); - ASSERT_THAT(*props, UnorderedElementsAre( - std::make_pair(store.NameToProperty("v3"), memgraph::storage::PropertyValue(42)))); - auto in_edges = v3->InEdges(memgraph::storage::View::OLD); - ASSERT_TRUE(in_edges.HasValue()); - ASSERT_EQ(in_edges->size(), 0); - auto out_edges = v3->OutEdges(memgraph::storage::View::OLD); - ASSERT_TRUE(out_edges.HasValue()); - ASSERT_EQ(out_edges->size(), 0); - } - } - - // Try to use the storage. - { - auto acc = store.Access(); - auto vertex = acc.CreateVertex(); - auto edge = acc.CreateEdge(&vertex, &vertex, store.NameToEdgeType("et")); - ASSERT_TRUE(edge.HasValue()); - ASSERT_FALSE(acc.Commit().HasError()); - } -} - -// NOLINTNEXTLINE(hicpp-special-member-functions) -TEST_P(DurabilityTest, WalCreateAndRemoveEverything) { - // Create WALs. - { - memgraph::storage::Storage store( - {.items = {.properties_on_edges = GetParam()}, - .durability = { - .storage_directory = storage_directory, - .snapshot_wal_mode = memgraph::storage::Config::Durability::SnapshotWalMode::PERIODIC_SNAPSHOT_WITH_WAL, - .snapshot_interval = std::chrono::minutes(20), - .wal_file_flush_every_n_tx = kFlushWalEvery}}); - CreateBaseDataset(&store, GetParam()); - CreateExtendedDataset(&store); - auto indices = store.ListAllIndices(); - for (const auto &index : indices.label) { - ASSERT_TRUE(store.DropIndex(index)); - } - for (const auto &index : indices.label_property) { - ASSERT_TRUE(store.DropIndex(index.first, index.second)); - } - auto constraints = store.ListAllConstraints(); - for (const auto &constraint : constraints.existence) { - ASSERT_TRUE(store.DropExistenceConstraint(constraint.first, constraint.second)); - } - for (const auto &constraint : constraints.unique) { - ASSERT_EQ(store.DropUniqueConstraint(constraint.first, constraint.second), - memgraph::storage::UniqueConstraints::DeletionStatus::SUCCESS); - } - auto acc = store.Access(); - for (auto vertex : acc.Vertices(memgraph::storage::View::OLD)) { - ASSERT_TRUE(acc.DetachDeleteVertex(&vertex).HasValue()); - } - ASSERT_FALSE(acc.Commit().HasError()); - } - - ASSERT_EQ(GetSnapshotsList().size(), 0); - ASSERT_EQ(GetBackupSnapshotsList().size(), 0); - ASSERT_GE(GetWalsList().size(), 1); - ASSERT_EQ(GetBackupWalsList().size(), 0); - - // Recover WALs. - memgraph::storage::Storage store( - {.items = {.properties_on_edges = GetParam()}, - .durability = {.storage_directory = storage_directory, .recover_on_startup = true}}); - { - auto indices = store.ListAllIndices(); - ASSERT_EQ(indices.label.size(), 0); - ASSERT_EQ(indices.label_property.size(), 0); - auto constraints = store.ListAllConstraints(); - ASSERT_EQ(constraints.existence.size(), 0); - ASSERT_EQ(constraints.unique.size(), 0); - auto acc = store.Access(); - uint64_t count = 0; - auto iterable = acc.Vertices(memgraph::storage::View::OLD); - for (auto it = iterable.begin(); it != iterable.end(); ++it) { - ++count; - } - ASSERT_EQ(count, 0); - } - - // Try to use the storage. - { - auto acc = store.Access(); - auto vertex = acc.CreateVertex(); - auto edge = acc.CreateEdge(&vertex, &vertex, store.NameToEdgeType("et")); - ASSERT_TRUE(edge.HasValue()); - ASSERT_FALSE(acc.Commit().HasError()); - } -} - -// NOLINTNEXTLINE(hicpp-special-member-functions) -TEST_P(DurabilityTest, WalTransactionOrdering) { - // NOLINTNEXTLINE(readability-isolate-declaration) - memgraph::storage::Gid gid1, gid2, gid3; - - // Create WAL. - { - memgraph::storage::Storage store( - {.items = {.properties_on_edges = GetParam()}, - .durability = { - .storage_directory = storage_directory, - .snapshot_wal_mode = memgraph::storage::Config::Durability::SnapshotWalMode::PERIODIC_SNAPSHOT_WITH_WAL, - .snapshot_interval = std::chrono::minutes(20), - .wal_file_size_kibibytes = 100000, - .wal_file_flush_every_n_tx = kFlushWalEvery, - }}); - auto acc1 = store.Access(); - auto acc2 = store.Access(); - - // Create vertex in transaction 2. - { - auto vertex2 = acc2.CreateVertex(); - gid2 = vertex2.Gid(); - ASSERT_TRUE(vertex2.SetProperty(store.NameToProperty("id"), memgraph::storage::PropertyValue(2)).HasValue()); - } - - auto acc3 = store.Access(); - - // Create vertex in transaction 3. - { - auto vertex3 = acc3.CreateVertex(); - gid3 = vertex3.Gid(); - ASSERT_TRUE(vertex3.SetProperty(store.NameToProperty("id"), memgraph::storage::PropertyValue(3)).HasValue()); - } - - // Create vertex in transaction 1. - { - auto vertex1 = acc1.CreateVertex(); - gid1 = vertex1.Gid(); - ASSERT_TRUE(vertex1.SetProperty(store.NameToProperty("id"), memgraph::storage::PropertyValue(1)).HasValue()); - } - - // Commit transaction 3, then 1, then 2. - ASSERT_FALSE(acc3.Commit().HasError()); - ASSERT_FALSE(acc1.Commit().HasError()); - ASSERT_FALSE(acc2.Commit().HasError()); - } - - ASSERT_EQ(GetSnapshotsList().size(), 0); - ASSERT_EQ(GetBackupSnapshotsList().size(), 0); - ASSERT_EQ(GetWalsList().size(), 1); - ASSERT_EQ(GetBackupWalsList().size(), 0); - - // Verify WAL data. - { - auto path = GetWalsList().front(); - auto info = memgraph::storage::durability::ReadWalInfo(path); - memgraph::storage::durability::Decoder wal; - wal.Initialize(path, memgraph::storage::durability::kWalMagic); - wal.SetPosition(info.offset_deltas); - ASSERT_EQ(info.num_deltas, 9); - std::vector> data; - for (uint64_t i = 0; i < info.num_deltas; ++i) { - auto timestamp = memgraph::storage::durability::ReadWalDeltaHeader(&wal); - data.emplace_back(timestamp, memgraph::storage::durability::ReadWalDeltaData(&wal)); - } - // Verify timestamps. - ASSERT_EQ(data[1].first, data[0].first); - ASSERT_EQ(data[2].first, data[1].first); - ASSERT_GT(data[3].first, data[2].first); - ASSERT_EQ(data[4].first, data[3].first); - ASSERT_EQ(data[5].first, data[4].first); - ASSERT_GT(data[6].first, data[5].first); - ASSERT_EQ(data[7].first, data[6].first); - ASSERT_EQ(data[8].first, data[7].first); - // Verify transaction 3. - ASSERT_EQ(data[0].second.type, memgraph::storage::durability::WalDeltaData::Type::VERTEX_CREATE); - ASSERT_EQ(data[0].second.vertex_create_delete.gid, gid3); - ASSERT_EQ(data[1].second.type, memgraph::storage::durability::WalDeltaData::Type::VERTEX_SET_PROPERTY); - ASSERT_EQ(data[1].second.vertex_edge_set_property.gid, gid3); - ASSERT_EQ(data[1].second.vertex_edge_set_property.property, "id"); - ASSERT_EQ(data[1].second.vertex_edge_set_property.value, memgraph::storage::PropertyValue(3)); - ASSERT_EQ(data[2].second.type, memgraph::storage::durability::WalDeltaData::Type::TRANSACTION_END); - // Verify transaction 1. - ASSERT_EQ(data[3].second.type, memgraph::storage::durability::WalDeltaData::Type::VERTEX_CREATE); - ASSERT_EQ(data[3].second.vertex_create_delete.gid, gid1); - ASSERT_EQ(data[4].second.type, memgraph::storage::durability::WalDeltaData::Type::VERTEX_SET_PROPERTY); - ASSERT_EQ(data[4].second.vertex_edge_set_property.gid, gid1); - ASSERT_EQ(data[4].second.vertex_edge_set_property.property, "id"); - ASSERT_EQ(data[4].second.vertex_edge_set_property.value, memgraph::storage::PropertyValue(1)); - ASSERT_EQ(data[5].second.type, memgraph::storage::durability::WalDeltaData::Type::TRANSACTION_END); - // Verify transaction 2. - ASSERT_EQ(data[6].second.type, memgraph::storage::durability::WalDeltaData::Type::VERTEX_CREATE); - ASSERT_EQ(data[6].second.vertex_create_delete.gid, gid2); - ASSERT_EQ(data[7].second.type, memgraph::storage::durability::WalDeltaData::Type::VERTEX_SET_PROPERTY); - ASSERT_EQ(data[7].second.vertex_edge_set_property.gid, gid2); - ASSERT_EQ(data[7].second.vertex_edge_set_property.property, "id"); - ASSERT_EQ(data[7].second.vertex_edge_set_property.value, memgraph::storage::PropertyValue(2)); - ASSERT_EQ(data[8].second.type, memgraph::storage::durability::WalDeltaData::Type::TRANSACTION_END); - } - - // Recover WALs. - memgraph::storage::Storage store( - {.items = {.properties_on_edges = GetParam()}, - .durability = {.storage_directory = storage_directory, .recover_on_startup = true}}); - { - auto acc = store.Access(); - for (auto [gid, id] : std::vector>{{gid1, 1}, {gid2, 2}, {gid3, 3}}) { - auto vertex = acc.FindVertex(gid, memgraph::storage::View::OLD); - ASSERT_TRUE(vertex); - auto labels = vertex->Labels(memgraph::storage::View::OLD); - ASSERT_TRUE(labels.HasValue()); - ASSERT_EQ(labels->size(), 0); - auto props = vertex->Properties(memgraph::storage::View::OLD); - ASSERT_TRUE(props.HasValue()); - ASSERT_EQ(props->size(), 1); - ASSERT_EQ(props->at(store.NameToProperty("id")), memgraph::storage::PropertyValue(id)); - } - } - - // Try to use the storage. - { - auto acc = store.Access(); - auto vertex = acc.CreateVertex(); - auto edge = acc.CreateEdge(&vertex, &vertex, store.NameToEdgeType("et")); - ASSERT_TRUE(edge.HasValue()); - ASSERT_FALSE(acc.Commit().HasError()); - } -} - -// NOLINTNEXTLINE(hicpp-special-member-functions) -TEST_P(DurabilityTest, WalCreateAndRemoveOnlyBaseDataset) { - // Create WALs. - { - memgraph::storage::Storage store( - {.items = {.properties_on_edges = GetParam()}, - .durability = { - .storage_directory = storage_directory, - .snapshot_wal_mode = memgraph::storage::Config::Durability::SnapshotWalMode::PERIODIC_SNAPSHOT_WITH_WAL, - .snapshot_interval = std::chrono::minutes(20), - .wal_file_flush_every_n_tx = kFlushWalEvery}}); - CreateBaseDataset(&store, GetParam()); - CreateExtendedDataset(&store); - auto label_indexed = store.NameToLabel("base_indexed"); - auto label_unindexed = store.NameToLabel("base_unindexed"); - auto acc = store.Access(); - for (auto vertex : acc.Vertices(memgraph::storage::View::OLD)) { - auto has_indexed = vertex.HasLabel(label_indexed, memgraph::storage::View::OLD); - ASSERT_TRUE(has_indexed.HasValue()); - auto has_unindexed = vertex.HasLabel(label_unindexed, memgraph::storage::View::OLD); - if (!*has_indexed && !*has_unindexed) continue; - ASSERT_TRUE(acc.DetachDeleteVertex(&vertex).HasValue()); - } - ASSERT_FALSE(acc.Commit().HasError()); - } - - ASSERT_EQ(GetSnapshotsList().size(), 0); - ASSERT_EQ(GetBackupSnapshotsList().size(), 0); - ASSERT_GE(GetWalsList().size(), 1); - ASSERT_EQ(GetBackupWalsList().size(), 0); - - // Recover WALs. - memgraph::storage::Storage store( - {.items = {.properties_on_edges = GetParam()}, - .durability = {.storage_directory = storage_directory, .recover_on_startup = true}}); - VerifyDataset(&store, DatasetType::ONLY_EXTENDED_WITH_BASE_INDICES_AND_CONSTRAINTS, GetParam()); - - // Try to use the storage. - { - auto acc = store.Access(); - auto vertex = acc.CreateVertex(); - auto edge = acc.CreateEdge(&vertex, &vertex, store.NameToEdgeType("et")); - ASSERT_TRUE(edge.HasValue()); - ASSERT_FALSE(acc.Commit().HasError()); - } -} - -// NOLINTNEXTLINE(hicpp-special-member-functions) -TEST_P(DurabilityTest, WalDeathResilience) { - pid_t pid = fork(); - if (pid == 0) { - // Create WALs. - { - memgraph::storage::Storage store( - {.items = {.properties_on_edges = GetParam()}, - .durability = { - .storage_directory = storage_directory, - .snapshot_wal_mode = memgraph::storage::Config::Durability::SnapshotWalMode::PERIODIC_SNAPSHOT_WITH_WAL, - .snapshot_interval = std::chrono::minutes(20), - .wal_file_flush_every_n_tx = kFlushWalEvery}}); - // Create one million vertices. - for (uint64_t i = 0; i < 1000000; ++i) { - auto acc = store.Access(); - acc.CreateVertex(); - MG_ASSERT(!acc.Commit().HasError(), "Couldn't commit transaction!"); - } - } - } else if (pid > 0) { - // Wait for WALs to be created. - std::this_thread::sleep_for(std::chrono::seconds(2)); - int status; - EXPECT_EQ(waitpid(pid, &status, WNOHANG), 0); - EXPECT_EQ(kill(pid, SIGKILL), 0); - EXPECT_EQ(waitpid(pid, &status, 0), pid); - EXPECT_NE(status, 0); - } else { - LOG_FATAL("Couldn't create process to execute test!"); - } - - ASSERT_EQ(GetSnapshotsList().size(), 0); - ASSERT_EQ(GetBackupSnapshotsList().size(), 0); - ASSERT_GE(GetWalsList().size(), 1); - ASSERT_EQ(GetBackupWalsList().size(), 0); - - // Recover WALs and create more WALs. - const uint64_t kExtraItems = 1000; - uint64_t count = 0; - { - memgraph::storage::Storage store( - {.items = {.properties_on_edges = GetParam()}, - .durability = { - .storage_directory = storage_directory, - .recover_on_startup = true, - .snapshot_wal_mode = memgraph::storage::Config::Durability::SnapshotWalMode::PERIODIC_SNAPSHOT_WITH_WAL, - .snapshot_interval = std::chrono::minutes(20), - .wal_file_flush_every_n_tx = kFlushWalEvery, - }}); - { - auto acc = store.Access(); - auto iterable = acc.Vertices(memgraph::storage::View::OLD); - for (auto it = iterable.begin(); it != iterable.end(); ++it) { - ++count; - } - ASSERT_GT(count, 0); - } - - { - auto acc = store.Access(); - for (uint64_t i = 0; i < kExtraItems; ++i) { - acc.CreateVertex(); - } - ASSERT_FALSE(acc.Commit().HasError()); - } - } - - ASSERT_EQ(GetSnapshotsList().size(), 0); - ASSERT_EQ(GetBackupSnapshotsList().size(), 0); - ASSERT_GE(GetWalsList().size(), 2); - ASSERT_EQ(GetBackupWalsList().size(), 0); - - // Recover WALs. - memgraph::storage::Storage store( - {.items = {.properties_on_edges = GetParam()}, - .durability = {.storage_directory = storage_directory, .recover_on_startup = true}}); - { - uint64_t current = 0; - auto acc = store.Access(); - auto iterable = acc.Vertices(memgraph::storage::View::OLD); - for (auto it = iterable.begin(); it != iterable.end(); ++it) { - ++current; - } - ASSERT_EQ(count + kExtraItems, current); - } - - // Try to use the storage. - { - auto acc = store.Access(); - auto vertex = acc.CreateVertex(); - auto edge = acc.CreateEdge(&vertex, &vertex, store.NameToEdgeType("et")); - ASSERT_TRUE(edge.HasValue()); - ASSERT_FALSE(acc.Commit().HasError()); - } -} - -// NOLINTNEXTLINE(hicpp-special-member-functions) -TEST_P(DurabilityTest, WalMissingSecond) { - // Create unrelated WALs. - { - memgraph::storage::Storage store( - {.items = {.properties_on_edges = GetParam()}, - .durability = { - .storage_directory = storage_directory, - .snapshot_wal_mode = memgraph::storage::Config::Durability::SnapshotWalMode::PERIODIC_SNAPSHOT_WITH_WAL, - .snapshot_interval = std::chrono::minutes(20), - .wal_file_size_kibibytes = 1, - .wal_file_flush_every_n_tx = kFlushWalEvery}}); - auto acc = store.Access(); - for (uint64_t i = 0; i < 1000; ++i) { - acc.CreateVertex(); - } - ASSERT_FALSE(acc.Commit().HasError()); - } - - ASSERT_EQ(GetSnapshotsList().size(), 0); - ASSERT_EQ(GetBackupSnapshotsList().size(), 0); - ASSERT_GE(GetWalsList().size(), 1); - ASSERT_EQ(GetBackupWalsList().size(), 0); - - uint64_t unrelated_wals = GetWalsList().size(); - - // Create WALs. - { - memgraph::storage::Storage store( - {.items = {.properties_on_edges = GetParam()}, - .durability = { - .storage_directory = storage_directory, - .snapshot_wal_mode = memgraph::storage::Config::Durability::SnapshotWalMode::PERIODIC_SNAPSHOT_WITH_WAL, - .snapshot_interval = std::chrono::minutes(20), - .wal_file_size_kibibytes = 1, - .wal_file_flush_every_n_tx = kFlushWalEvery}}); - const uint64_t kNumVertices = 1000; - std::vector gids; - gids.reserve(kNumVertices); - for (uint64_t i = 0; i < kNumVertices; ++i) { - auto acc = store.Access(); - auto vertex = acc.CreateVertex(); - gids.push_back(vertex.Gid()); - ASSERT_FALSE(acc.Commit().HasError()); - } - for (uint64_t i = 0; i < kNumVertices; ++i) { - auto acc = store.Access(); - auto vertex = acc.FindVertex(gids[i], memgraph::storage::View::OLD); - ASSERT_TRUE(vertex); - ASSERT_TRUE(vertex->SetProperty(store.NameToProperty("nandare"), memgraph::storage::PropertyValue("haihaihai!")) - .HasValue()); - ASSERT_FALSE(acc.Commit().HasError()); - } - } - - ASSERT_EQ(GetSnapshotsList().size(), 0); - ASSERT_EQ(GetBackupSnapshotsList().size(), 0); - ASSERT_GE(GetWalsList().size(), 1); - ASSERT_GE(GetBackupWalsList().size(), 1); - - // Restore unrelated WALs. - RestoreBackups(); - - ASSERT_EQ(GetSnapshotsList().size(), 0); - ASSERT_EQ(GetBackupSnapshotsList().size(), 0); - ASSERT_GE(GetWalsList().size(), 2); - ASSERT_EQ(GetBackupWalsList().size(), 0); - - // Remove second WAL. - { - auto wals = GetWalsList(); - ASSERT_GT(wals.size(), unrelated_wals + 2); - const auto &wal_file = wals[wals.size() - unrelated_wals - 2]; - spdlog::info("Deleting WAL file {}", wal_file); - ASSERT_TRUE(std::filesystem::remove(wal_file)); - } - - // Recover WALs. - ASSERT_DEATH( - { - memgraph::storage::Storage store( - {.items = {.properties_on_edges = GetParam()}, - .durability = {.storage_directory = storage_directory, .recover_on_startup = true}}); - }, - ""); -} - -// NOLINTNEXTLINE(hicpp-special-member-functions) -TEST_P(DurabilityTest, WalCorruptSecond) { - // Create unrelated WALs. - { - memgraph::storage::Storage store( - {.items = {.properties_on_edges = GetParam()}, - .durability = { - .storage_directory = storage_directory, - .snapshot_wal_mode = memgraph::storage::Config::Durability::SnapshotWalMode::PERIODIC_SNAPSHOT_WITH_WAL, - .snapshot_interval = std::chrono::minutes(20), - .wal_file_size_kibibytes = 1, - .wal_file_flush_every_n_tx = kFlushWalEvery}}); - auto acc = store.Access(); - for (uint64_t i = 0; i < 1000; ++i) { - acc.CreateVertex(); - } - ASSERT_FALSE(acc.Commit().HasError()); - } - - ASSERT_EQ(GetSnapshotsList().size(), 0); - ASSERT_EQ(GetBackupSnapshotsList().size(), 0); - ASSERT_GE(GetWalsList().size(), 1); - ASSERT_EQ(GetBackupWalsList().size(), 0); - - uint64_t unrelated_wals = GetWalsList().size(); - - // Create WALs. - { - memgraph::storage::Storage store( - {.items = {.properties_on_edges = GetParam()}, - .durability = { - .storage_directory = storage_directory, - .snapshot_wal_mode = memgraph::storage::Config::Durability::SnapshotWalMode::PERIODIC_SNAPSHOT_WITH_WAL, - .snapshot_interval = std::chrono::minutes(20), - .wal_file_size_kibibytes = 1, - .wal_file_flush_every_n_tx = kFlushWalEvery}}); - const uint64_t kNumVertices = 1000; - std::vector gids; - gids.reserve(kNumVertices); - for (uint64_t i = 0; i < kNumVertices; ++i) { - auto acc = store.Access(); - auto vertex = acc.CreateVertex(); - gids.push_back(vertex.Gid()); - ASSERT_FALSE(acc.Commit().HasError()); - } - for (uint64_t i = 0; i < kNumVertices; ++i) { - auto acc = store.Access(); - auto vertex = acc.FindVertex(gids[i], memgraph::storage::View::OLD); - ASSERT_TRUE(vertex); - ASSERT_TRUE(vertex->SetProperty(store.NameToProperty("nandare"), memgraph::storage::PropertyValue("haihaihai!")) - .HasValue()); - ASSERT_FALSE(acc.Commit().HasError()); - } - } - - ASSERT_EQ(GetSnapshotsList().size(), 0); - ASSERT_EQ(GetBackupSnapshotsList().size(), 0); - ASSERT_GE(GetWalsList().size(), 1); - ASSERT_GE(GetBackupWalsList().size(), 1); - - // Restore unrelated WALs. - RestoreBackups(); - - ASSERT_EQ(GetSnapshotsList().size(), 0); - ASSERT_EQ(GetBackupSnapshotsList().size(), 0); - ASSERT_GE(GetWalsList().size(), 2); - ASSERT_EQ(GetBackupWalsList().size(), 0); - - // Destroy second WAL. - { - auto wals = GetWalsList(); - ASSERT_GT(wals.size(), unrelated_wals + 2); - const auto &wal_file = wals[wals.size() - unrelated_wals - 2]; - DestroyWalFirstDelta(wal_file); - } - - // Recover WALs. - ASSERT_DEATH( - { - memgraph::storage::Storage store( - {.items = {.properties_on_edges = GetParam()}, - .durability = {.storage_directory = storage_directory, .recover_on_startup = true}}); - }, - ""); -} - -// NOLINTNEXTLINE(hicpp-special-member-functions) -TEST_P(DurabilityTest, WalCorruptLastTransaction) { - // Create WALs - { - memgraph::storage::Storage store( - {.items = {.properties_on_edges = GetParam()}, - .durability = { - .storage_directory = storage_directory, - .snapshot_wal_mode = memgraph::storage::Config::Durability::SnapshotWalMode::PERIODIC_SNAPSHOT_WITH_WAL, - .snapshot_interval = std::chrono::minutes(20), - .wal_file_size_kibibytes = 1, - .wal_file_flush_every_n_tx = kFlushWalEvery}}); - CreateBaseDataset(&store, GetParam()); - CreateExtendedDataset(&store, /* single_transaction = */ true); - } - - ASSERT_EQ(GetSnapshotsList().size(), 0); - ASSERT_EQ(GetBackupSnapshotsList().size(), 0); - ASSERT_GE(GetWalsList().size(), 2); - ASSERT_EQ(GetBackupWalsList().size(), 0); - - // Destroy last transaction in the latest WAL. - { - auto wals = GetWalsList(); - ASSERT_GE(wals.size(), 2); - const auto &wal_file = wals.front(); - DestroyWalSuffix(wal_file); - } - - // Recover WALs. - memgraph::storage::Storage store( - {.items = {.properties_on_edges = GetParam()}, - .durability = {.storage_directory = storage_directory, .recover_on_startup = true}}); - // The extended dataset shouldn't be recovered because its WAL transaction was - // corrupt. - VerifyDataset(&store, DatasetType::ONLY_BASE_WITH_EXTENDED_INDICES_AND_CONSTRAINTS, GetParam()); - - // Try to use the storage. - { - auto acc = store.Access(); - auto vertex = acc.CreateVertex(); - auto edge = acc.CreateEdge(&vertex, &vertex, store.NameToEdgeType("et")); - ASSERT_TRUE(edge.HasValue()); - ASSERT_FALSE(acc.Commit().HasError()); - } -} - -// NOLINTNEXTLINE(hicpp-special-member-functions) -TEST_P(DurabilityTest, WalAllOperationsInSingleTransaction) { - // Create WALs - { - memgraph::storage::Storage store( - {.items = {.properties_on_edges = GetParam()}, - .durability = { - .storage_directory = storage_directory, - .snapshot_wal_mode = memgraph::storage::Config::Durability::SnapshotWalMode::PERIODIC_SNAPSHOT_WITH_WAL, - .snapshot_interval = std::chrono::minutes(20), - .wal_file_size_kibibytes = 1, - .wal_file_flush_every_n_tx = kFlushWalEvery}}); - auto acc = store.Access(); - auto vertex1 = acc.CreateVertex(); - auto vertex2 = acc.CreateVertex(); - ASSERT_TRUE(vertex1.AddLabel(acc.NameToLabel("nandare")).HasValue()); - ASSERT_TRUE(vertex2.SetProperty(acc.NameToProperty("haihai"), memgraph::storage::PropertyValue(42)).HasValue()); - ASSERT_TRUE(vertex1.RemoveLabel(acc.NameToLabel("nandare")).HasValue()); - auto edge1 = acc.CreateEdge(&vertex1, &vertex2, acc.NameToEdgeType("et1")); - ASSERT_TRUE(edge1.HasValue()); - ASSERT_TRUE(vertex2.SetProperty(acc.NameToProperty("haihai"), memgraph::storage::PropertyValue()).HasValue()); - auto vertex3 = acc.CreateVertex(); - auto edge2 = acc.CreateEdge(&vertex3, &vertex3, acc.NameToEdgeType("et2")); - ASSERT_TRUE(edge2.HasValue()); - if (GetParam()) { - ASSERT_TRUE(edge2->SetProperty(acc.NameToProperty("meaning"), memgraph::storage::PropertyValue(true)).HasValue()); - ASSERT_TRUE( - edge1->SetProperty(acc.NameToProperty("hello"), memgraph::storage::PropertyValue("world")).HasValue()); - ASSERT_TRUE(edge2->SetProperty(acc.NameToProperty("meaning"), memgraph::storage::PropertyValue()).HasValue()); - } - ASSERT_TRUE(vertex3.AddLabel(acc.NameToLabel("test")).HasValue()); - ASSERT_TRUE(vertex3.SetProperty(acc.NameToProperty("nonono"), memgraph::storage::PropertyValue(-1)).HasValue()); - ASSERT_TRUE(vertex3.SetProperty(acc.NameToProperty("nonono"), memgraph::storage::PropertyValue()).HasValue()); - if (GetParam()) { - ASSERT_TRUE(edge1->SetProperty(acc.NameToProperty("hello"), memgraph::storage::PropertyValue()).HasValue()); - } - ASSERT_TRUE(vertex3.RemoveLabel(acc.NameToLabel("test")).HasValue()); - ASSERT_TRUE(acc.DetachDeleteVertex(&vertex1).HasValue()); - ASSERT_TRUE(acc.DeleteEdge(&*edge2).HasValue()); - ASSERT_TRUE(acc.DeleteVertex(&vertex2).HasValue()); - ASSERT_TRUE(acc.DeleteVertex(&vertex3).HasValue()); - ASSERT_FALSE(acc.Commit().HasError()); - } - - ASSERT_EQ(GetSnapshotsList().size(), 0); - ASSERT_EQ(GetBackupSnapshotsList().size(), 0); - ASSERT_GE(GetWalsList().size(), 1); - ASSERT_EQ(GetBackupWalsList().size(), 0); - - // Recover WALs. - memgraph::storage::Storage store( - {.items = {.properties_on_edges = GetParam()}, - .durability = {.storage_directory = storage_directory, .recover_on_startup = true}}); - { - auto acc = store.Access(); - uint64_t count = 0; - auto iterable = acc.Vertices(memgraph::storage::View::OLD); - for (auto it = iterable.begin(); it != iterable.end(); ++it) { - ++count; - } - ASSERT_EQ(count, 0); - } - - // Try to use the storage. - { - auto acc = store.Access(); - auto vertex = acc.CreateVertex(); - auto edge = acc.CreateEdge(&vertex, &vertex, store.NameToEdgeType("et")); - ASSERT_TRUE(edge.HasValue()); - ASSERT_FALSE(acc.Commit().HasError()); - } -} - -// NOLINTNEXTLINE(hicpp-special-member-functions) -TEST_P(DurabilityTest, WalAndSnapshot) { - // Create snapshot and WALs. - { - memgraph::storage::Storage store( - {.items = {.properties_on_edges = GetParam()}, - .durability = { - .storage_directory = storage_directory, - .snapshot_wal_mode = memgraph::storage::Config::Durability::SnapshotWalMode::PERIODIC_SNAPSHOT_WITH_WAL, - .snapshot_interval = std::chrono::milliseconds(2000), - .wal_file_flush_every_n_tx = kFlushWalEvery}}); - CreateBaseDataset(&store, GetParam()); - std::this_thread::sleep_for(std::chrono::milliseconds(2500)); - CreateExtendedDataset(&store); - } - - ASSERT_GE(GetSnapshotsList().size(), 1); - ASSERT_EQ(GetBackupSnapshotsList().size(), 0); - ASSERT_GE(GetWalsList().size(), 1); - ASSERT_EQ(GetBackupWalsList().size(), 0); - - // Recover snapshot and WALs. - memgraph::storage::Storage store( - {.items = {.properties_on_edges = GetParam()}, - .durability = {.storage_directory = storage_directory, .recover_on_startup = true}}); - VerifyDataset(&store, DatasetType::BASE_WITH_EXTENDED, GetParam()); - - // Try to use the storage. - { - auto acc = store.Access(); - auto vertex = acc.CreateVertex(); - auto edge = acc.CreateEdge(&vertex, &vertex, store.NameToEdgeType("et")); - ASSERT_TRUE(edge.HasValue()); - ASSERT_FALSE(acc.Commit().HasError()); - } -} - -// NOLINTNEXTLINE(hicpp-special-member-functions) -TEST_P(DurabilityTest, WalAndSnapshotAppendToExistingSnapshot) { - // Create snapshot. - { - memgraph::storage::Storage store( - {.items = {.properties_on_edges = GetParam()}, - .durability = {.storage_directory = storage_directory, .snapshot_on_exit = true}}); - CreateBaseDataset(&store, GetParam()); - } - - ASSERT_EQ(GetSnapshotsList().size(), 1); - ASSERT_EQ(GetBackupSnapshotsList().size(), 0); - ASSERT_EQ(GetWalsList().size(), 0); - ASSERT_EQ(GetBackupWalsList().size(), 0); - - // Recover snapshot. - { - memgraph::storage::Storage store( - {.items = {.properties_on_edges = GetParam()}, - .durability = {.storage_directory = storage_directory, .recover_on_startup = true}}); - VerifyDataset(&store, DatasetType::ONLY_BASE, GetParam()); - } - - // Recover snapshot and create WALs. - { - memgraph::storage::Storage store( - {.items = {.properties_on_edges = GetParam()}, - .durability = { - .storage_directory = storage_directory, - .recover_on_startup = true, - .snapshot_wal_mode = memgraph::storage::Config::Durability::SnapshotWalMode::PERIODIC_SNAPSHOT_WITH_WAL, - .snapshot_interval = std::chrono::minutes(20), - .wal_file_flush_every_n_tx = kFlushWalEvery}}); - CreateExtendedDataset(&store); - } - - ASSERT_EQ(GetSnapshotsList().size(), 1); - ASSERT_EQ(GetBackupSnapshotsList().size(), 0); - ASSERT_GE(GetWalsList().size(), 1); - ASSERT_EQ(GetBackupWalsList().size(), 0); - - // Recover snapshot and WALs. - memgraph::storage::Storage store( - {.items = {.properties_on_edges = GetParam()}, - .durability = {.storage_directory = storage_directory, .recover_on_startup = true}}); - VerifyDataset(&store, DatasetType::BASE_WITH_EXTENDED, GetParam()); - - // Try to use the storage. - { - auto acc = store.Access(); - auto vertex = acc.CreateVertex(); - auto edge = acc.CreateEdge(&vertex, &vertex, store.NameToEdgeType("et")); - ASSERT_TRUE(edge.HasValue()); - ASSERT_FALSE(acc.Commit().HasError()); - } -} - -// NOLINTNEXTLINE(hicpp-special-member-functions) -TEST_P(DurabilityTest, WalAndSnapshotAppendToExistingSnapshotAndWal) { - // Create snapshot. - { - memgraph::storage::Storage store( - {.items = {.properties_on_edges = GetParam()}, - .durability = {.storage_directory = storage_directory, .snapshot_on_exit = true}}); - CreateBaseDataset(&store, GetParam()); - } - - ASSERT_EQ(GetSnapshotsList().size(), 1); - ASSERT_EQ(GetBackupSnapshotsList().size(), 0); - ASSERT_EQ(GetWalsList().size(), 0); - ASSERT_EQ(GetBackupWalsList().size(), 0); - - // Recover snapshot. - { - memgraph::storage::Storage store( - {.items = {.properties_on_edges = GetParam()}, - .durability = {.storage_directory = storage_directory, .recover_on_startup = true}}); - VerifyDataset(&store, DatasetType::ONLY_BASE, GetParam()); - } - - // Recover snapshot and create WALs. - { - memgraph::storage::Storage store( - {.items = {.properties_on_edges = GetParam()}, - .durability = { - .storage_directory = storage_directory, - .recover_on_startup = true, - .snapshot_wal_mode = memgraph::storage::Config::Durability::SnapshotWalMode::PERIODIC_SNAPSHOT_WITH_WAL, - .snapshot_interval = std::chrono::minutes(20), - .wal_file_flush_every_n_tx = kFlushWalEvery}}); - CreateExtendedDataset(&store); - } - - ASSERT_EQ(GetSnapshotsList().size(), 1); - ASSERT_EQ(GetBackupSnapshotsList().size(), 0); - ASSERT_GE(GetWalsList().size(), 1); - ASSERT_EQ(GetBackupWalsList().size(), 0); - - // Recover snapshot and WALs and create more WALs. - memgraph::storage::Gid vertex_gid; - { - memgraph::storage::Storage store( - {.items = {.properties_on_edges = GetParam()}, - .durability = { - .storage_directory = storage_directory, - .recover_on_startup = true, - .snapshot_wal_mode = memgraph::storage::Config::Durability::SnapshotWalMode::PERIODIC_SNAPSHOT_WITH_WAL, - .snapshot_interval = std::chrono::minutes(20), - .wal_file_flush_every_n_tx = kFlushWalEvery}}); - VerifyDataset(&store, DatasetType::BASE_WITH_EXTENDED, GetParam()); - auto acc = store.Access(); - auto vertex = acc.CreateVertex(); - vertex_gid = vertex.Gid(); - if (GetParam()) { - ASSERT_TRUE(vertex.SetProperty(store.NameToProperty("meaning"), memgraph::storage::PropertyValue(42)).HasValue()); - } - ASSERT_FALSE(acc.Commit().HasError()); - } - - ASSERT_EQ(GetSnapshotsList().size(), 1); - ASSERT_EQ(GetBackupSnapshotsList().size(), 0); - ASSERT_GE(GetWalsList().size(), 2); - ASSERT_EQ(GetBackupWalsList().size(), 0); - - // Recover snapshot and WALs. - memgraph::storage::Storage store( - {.items = {.properties_on_edges = GetParam()}, - .durability = {.storage_directory = storage_directory, .recover_on_startup = true}}); - VerifyDataset(&store, DatasetType::BASE_WITH_EXTENDED, GetParam(), - /* verify_info = */ false); - { - auto acc = store.Access(); - auto vertex = acc.FindVertex(vertex_gid, memgraph::storage::View::OLD); - ASSERT_TRUE(vertex); - auto labels = vertex->Labels(memgraph::storage::View::OLD); - ASSERT_TRUE(labels.HasValue()); - ASSERT_EQ(labels->size(), 0); - auto props = vertex->Properties(memgraph::storage::View::OLD); - ASSERT_TRUE(props.HasValue()); - if (GetParam()) { - ASSERT_THAT(*props, UnorderedElementsAre( - std::make_pair(store.NameToProperty("meaning"), memgraph::storage::PropertyValue(42)))); - } else { - ASSERT_EQ(props->size(), 0); - } - } - - // Try to use the storage. - { - auto acc = store.Access(); - auto vertex = acc.CreateVertex(); - auto edge = acc.CreateEdge(&vertex, &vertex, store.NameToEdgeType("et")); - ASSERT_TRUE(edge.HasValue()); - ASSERT_FALSE(acc.Commit().HasError()); - } -} - -// NOLINTNEXTLINE(hicpp-special-member-functions) -TEST_P(DurabilityTest, WalAndSnapshotWalRetention) { - // Create unrelated WALs. - { - memgraph::storage::Storage store( - {.items = {.properties_on_edges = GetParam()}, - .durability = { - .storage_directory = storage_directory, - .snapshot_wal_mode = memgraph::storage::Config::Durability::SnapshotWalMode::PERIODIC_SNAPSHOT_WITH_WAL, - .snapshot_interval = std::chrono::minutes(20), - .wal_file_size_kibibytes = 1, - .wal_file_flush_every_n_tx = kFlushWalEvery}}); - auto acc = store.Access(); - for (uint64_t i = 0; i < 1000; ++i) { - acc.CreateVertex(); - } - ASSERT_FALSE(acc.Commit().HasError()); - } - - ASSERT_EQ(GetSnapshotsList().size(), 0); - ASSERT_EQ(GetBackupSnapshotsList().size(), 0); - ASSERT_GE(GetWalsList().size(), 1); - ASSERT_EQ(GetBackupWalsList().size(), 0); - - uint64_t unrelated_wals = GetWalsList().size(); - - uint64_t items_created = 0; - - // Create snapshot and WALs. - { - memgraph::storage::Storage store( - {.items = {.properties_on_edges = GetParam()}, - .durability = { - .storage_directory = storage_directory, - .snapshot_wal_mode = memgraph::storage::Config::Durability::SnapshotWalMode::PERIODIC_SNAPSHOT_WITH_WAL, - .snapshot_interval = std::chrono::seconds(2), - .wal_file_size_kibibytes = 1, - .wal_file_flush_every_n_tx = 1}}); - // Restore unrelated snapshots after the database has been started. - RestoreBackups(); - memgraph::utils::Timer timer; - // Allow at least 6 snapshots to be created. - while (timer.Elapsed().count() < 13.0) { - auto acc = store.Access(); - acc.CreateVertex(); - ASSERT_FALSE(acc.Commit().HasError()); - ++items_created; - } - } - - ASSERT_EQ(GetSnapshotsList().size(), 3); - ASSERT_EQ(GetBackupSnapshotsList().size(), 0); - ASSERT_GE(GetWalsList().size(), unrelated_wals + 1); - ASSERT_EQ(GetBackupWalsList().size(), 0); - - auto snapshots = GetSnapshotsList(); - ASSERT_EQ(snapshots.size(), 3); - - for (uint64_t i = 0; i < snapshots.size(); ++i) { - spdlog::info("Recovery attempt {}", i); - - // Recover and verify data. - { - memgraph::storage::Storage store( - {.items = {.properties_on_edges = GetParam()}, - .durability = {.storage_directory = storage_directory, .recover_on_startup = true}}); - auto acc = store.Access(); - for (uint64_t j = 0; j < items_created; ++j) { - auto vertex = acc.FindVertex(memgraph::storage::Gid::FromUint(j), memgraph::storage::View::OLD); - ASSERT_TRUE(vertex); - } - } - - // Destroy current snapshot. - DestroySnapshot(snapshots[i]); - } - - // Recover data after all of the snapshots have been destroyed. The recovery - // shouldn't be possible because the initial WALs are already deleted. - ASSERT_DEATH( - { - memgraph::storage::Storage store( - {.items = {.properties_on_edges = GetParam()}, - .durability = {.storage_directory = storage_directory, .recover_on_startup = true}}); - }, - ""); -} - -// NOLINTNEXTLINE(hicpp-special-member-functions) -TEST_P(DurabilityTest, SnapshotAndWalMixedUUID) { - // Create unrelated snapshot and WALs. - { - memgraph::storage::Storage store( - {.items = {.properties_on_edges = GetParam()}, - .durability = { - .storage_directory = storage_directory, - .snapshot_wal_mode = memgraph::storage::Config::Durability::SnapshotWalMode::PERIODIC_SNAPSHOT_WITH_WAL, - .snapshot_interval = std::chrono::seconds(2)}}); - auto acc = store.Access(); - for (uint64_t i = 0; i < 1000; ++i) { - acc.CreateVertex(); - } - ASSERT_FALSE(acc.Commit().HasError()); - std::this_thread::sleep_for(std::chrono::milliseconds(2500)); - } - - ASSERT_GE(GetSnapshotsList().size(), 1); - ASSERT_EQ(GetBackupSnapshotsList().size(), 0); - ASSERT_GE(GetWalsList().size(), 1); - ASSERT_EQ(GetBackupWalsList().size(), 0); - - // Create snapshot and WALs. - { - memgraph::storage::Storage store( - {.items = {.properties_on_edges = GetParam()}, - .durability = { - .storage_directory = storage_directory, - .snapshot_wal_mode = memgraph::storage::Config::Durability::SnapshotWalMode::PERIODIC_SNAPSHOT_WITH_WAL, - .snapshot_interval = std::chrono::seconds(2)}}); - CreateBaseDataset(&store, GetParam()); - std::this_thread::sleep_for(std::chrono::milliseconds(2500)); - CreateExtendedDataset(&store); - std::this_thread::sleep_for(std::chrono::milliseconds(2500)); - } - - ASSERT_GE(GetSnapshotsList().size(), 1); - ASSERT_GE(GetBackupSnapshotsList().size(), 1); - ASSERT_GE(GetWalsList().size(), 1); - ASSERT_GE(GetBackupWalsList().size(), 1); - - // Restore unrelated snapshots and WALs. - RestoreBackups(); - - ASSERT_GE(GetSnapshotsList().size(), 2); - ASSERT_EQ(GetBackupSnapshotsList().size(), 0); - ASSERT_GE(GetWalsList().size(), 2); - ASSERT_EQ(GetBackupWalsList().size(), 0); - - // Recover snapshot and WALs. - memgraph::storage::Storage store( - {.items = {.properties_on_edges = GetParam()}, - .durability = {.storage_directory = storage_directory, .recover_on_startup = true}}); - VerifyDataset(&store, DatasetType::BASE_WITH_EXTENDED, GetParam()); - - // Try to use the storage. - { - auto acc = store.Access(); - auto vertex = acc.CreateVertex(); - auto edge = acc.CreateEdge(&vertex, &vertex, store.NameToEdgeType("et")); - ASSERT_TRUE(edge.HasValue()); - ASSERT_FALSE(acc.Commit().HasError()); - } -} diff --git a/tests/unit/storage_v2_edge.cpp b/tests/unit/storage_v2_edge.cpp deleted file mode 100644 index 1d62fe35a..000000000 --- a/tests/unit/storage_v2_edge.cpp +++ /dev/null @@ -1,5391 +0,0 @@ -// Copyright 2022 Memgraph Ltd. -// -// Use of this software is governed by the Business Source License -// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source -// License, and you may not use this file except in compliance with the Business Source License. -// -// As of the Change Date specified in that file, in accordance with -// the Business Source License, use of this software will be governed -// by the Apache License, Version 2.0, included in the file -// licenses/APL.txt. - -#include -#include - -#include - -#include "storage/v2/storage.hpp" - -using testing::UnorderedElementsAre; - -class StorageEdgeTest : public ::testing::TestWithParam {}; - -INSTANTIATE_TEST_CASE_P(EdgesWithProperties, StorageEdgeTest, ::testing::Values(true)); -INSTANTIATE_TEST_CASE_P(EdgesWithoutProperties, StorageEdgeTest, ::testing::Values(false)); - -// NOLINTNEXTLINE(hicpp-special-member-functions) -TEST_P(StorageEdgeTest, EdgeCreateFromSmallerCommit) { - memgraph::storage::Storage store({.items = {.properties_on_edges = GetParam()}}); - memgraph::storage::Gid gid_from = memgraph::storage::Gid::FromUint(std::numeric_limits::max()); - memgraph::storage::Gid gid_to = memgraph::storage::Gid::FromUint(std::numeric_limits::max()); - - // Create vertices - { - auto acc = store.Access(); - auto vertex_from = acc.CreateVertex(); - auto vertex_to = acc.CreateVertex(); - gid_from = vertex_from.Gid(); - gid_to = vertex_to.Gid(); - ASSERT_FALSE(acc.Commit().HasError()); - } - - // Create edge - { - auto acc = store.Access(); - auto vertex_from = acc.FindVertex(gid_from, memgraph::storage::View::NEW); - auto vertex_to = acc.FindVertex(gid_to, memgraph::storage::View::NEW); - ASSERT_TRUE(vertex_from); - ASSERT_TRUE(vertex_to); - - auto et = acc.NameToEdgeType("et5"); - - auto res = acc.CreateEdge(&*vertex_from, &*vertex_to, et); - ASSERT_TRUE(res.HasValue()); - auto edge = res.GetValue(); - ASSERT_EQ(edge.EdgeType(), et); - ASSERT_EQ(edge.FromVertex(), *vertex_from); - ASSERT_EQ(edge.ToVertex(), *vertex_to); - - // Check edges without filters - ASSERT_EQ(vertex_from->InEdges(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(*vertex_from->InDegree(memgraph::storage::View::OLD), 0); - ASSERT_EQ(vertex_from->InEdges(memgraph::storage::View::NEW)->size(), 0); - ASSERT_EQ(*vertex_from->InDegree(memgraph::storage::View::NEW), 0); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(*vertex_from->OutDegree(memgraph::storage::View::OLD), 0); - { - auto ret = vertex_from->OutEdges(memgraph::storage::View::NEW); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex_from->OutDegree(memgraph::storage::View::NEW), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et); - ASSERT_EQ(e.FromVertex(), *vertex_from); - ASSERT_EQ(e.ToVertex(), *vertex_to); - } - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(*vertex_to->InDegree(memgraph::storage::View::OLD), 0); - { - auto ret = vertex_to->InEdges(memgraph::storage::View::NEW); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex_to->InDegree(memgraph::storage::View::NEW), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et); - ASSERT_EQ(e.FromVertex(), *vertex_from); - ASSERT_EQ(e.ToVertex(), *vertex_to); - } - ASSERT_EQ(vertex_to->OutEdges(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(*vertex_to->OutDegree(memgraph::storage::View::OLD), 0); - ASSERT_EQ(vertex_to->OutEdges(memgraph::storage::View::NEW)->size(), 0); - ASSERT_EQ(*vertex_to->OutDegree(memgraph::storage::View::NEW), 0); - - auto other_et = acc.NameToEdgeType("other"); - - // Check edges with filters - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::NEW, {other_et})->size(), 0); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::NEW, {et, other_et})->size(), 1); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::NEW, {}, &*vertex_from)->size(), 0); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::NEW, {}, &*vertex_to)->size(), 1); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::NEW, {other_et}, &*vertex_to)->size(), 0); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::NEW, {et, other_et}, &*vertex_to)->size(), 1); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::NEW, {et, other_et}, &*vertex_from)->size(), 0); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::NEW, {other_et})->size(), 0); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::NEW, {et, other_et})->size(), 1); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::NEW, {}, &*vertex_from)->size(), 1); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::NEW, {}, &*vertex_to)->size(), 0); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::NEW, {other_et}, &*vertex_from)->size(), 0); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::NEW, {et, other_et}, &*vertex_from)->size(), 1); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::NEW, {et, other_et}, &*vertex_to)->size(), 0); - - ASSERT_FALSE(acc.Commit().HasError()); - } - - // Check whether the edge exists - { - auto acc = store.Access(); - auto vertex_from = acc.FindVertex(gid_from, memgraph::storage::View::NEW); - auto vertex_to = acc.FindVertex(gid_to, memgraph::storage::View::NEW); - ASSERT_TRUE(vertex_from); - ASSERT_TRUE(vertex_to); - - auto et = acc.NameToEdgeType("et5"); - - // Check edges without filters - ASSERT_EQ(vertex_from->InEdges(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(*vertex_from->InDegree(memgraph::storage::View::OLD), 0); - ASSERT_EQ(vertex_from->InEdges(memgraph::storage::View::NEW)->size(), 0); - ASSERT_EQ(*vertex_from->InDegree(memgraph::storage::View::NEW), 0); - { - auto ret = vertex_from->OutEdges(memgraph::storage::View::OLD); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex_from->OutDegree(memgraph::storage::View::OLD), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et); - ASSERT_EQ(e.FromVertex(), *vertex_from); - ASSERT_EQ(e.ToVertex(), *vertex_to); - } - { - auto ret = vertex_from->OutEdges(memgraph::storage::View::NEW); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex_from->OutDegree(memgraph::storage::View::NEW), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et); - ASSERT_EQ(e.FromVertex(), *vertex_from); - ASSERT_EQ(e.ToVertex(), *vertex_to); - } - { - auto ret = vertex_to->InEdges(memgraph::storage::View::OLD); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex_to->InDegree(memgraph::storage::View::OLD), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et); - ASSERT_EQ(e.FromVertex(), *vertex_from); - ASSERT_EQ(e.ToVertex(), *vertex_to); - } - { - auto ret = vertex_to->InEdges(memgraph::storage::View::NEW); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex_to->InDegree(memgraph::storage::View::NEW), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et); - ASSERT_EQ(e.FromVertex(), *vertex_from); - ASSERT_EQ(e.ToVertex(), *vertex_to); - } - ASSERT_EQ(vertex_to->OutEdges(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(*vertex_to->OutDegree(memgraph::storage::View::OLD), 0); - ASSERT_EQ(vertex_to->OutEdges(memgraph::storage::View::NEW)->size(), 0); - ASSERT_EQ(*vertex_to->OutDegree(memgraph::storage::View::NEW), 0); - - auto other_et = acc.NameToEdgeType("other"); - - // Check edges with filters - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::OLD, {other_et})->size(), 0); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::NEW, {other_et})->size(), 0); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::OLD, {et, other_et})->size(), 1); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::NEW, {et, other_et})->size(), 1); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::OLD, {}, &*vertex_from)->size(), 0); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::NEW, {}, &*vertex_from)->size(), 0); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::OLD, {}, &*vertex_to)->size(), 1); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::NEW, {}, &*vertex_to)->size(), 1); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::OLD, {other_et}, &*vertex_to)->size(), 0); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::NEW, {other_et}, &*vertex_to)->size(), 0); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::OLD, {et, other_et}, &*vertex_to)->size(), 1); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::NEW, {et, other_et}, &*vertex_to)->size(), 1); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::OLD, {et, other_et}, &*vertex_from)->size(), 0); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::NEW, {et, other_et}, &*vertex_from)->size(), 0); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::OLD, {other_et})->size(), 0); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::NEW, {other_et})->size(), 0); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::OLD, {et, other_et})->size(), 1); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::NEW, {et, other_et})->size(), 1); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::OLD, {}, &*vertex_from)->size(), 1); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::NEW, {}, &*vertex_from)->size(), 1); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::OLD, {}, &*vertex_to)->size(), 0); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::NEW, {}, &*vertex_to)->size(), 0); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::OLD, {other_et}, &*vertex_from)->size(), 0); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::NEW, {other_et}, &*vertex_from)->size(), 0); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::OLD, {et, other_et}, &*vertex_from)->size(), 1); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::NEW, {et, other_et}, &*vertex_from)->size(), 1); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::OLD, {et, other_et}, &*vertex_to)->size(), 0); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::NEW, {et, other_et}, &*vertex_to)->size(), 0); - - ASSERT_FALSE(acc.Commit().HasError()); - } -} - -// NOLINTNEXTLINE(hicpp-special-member-functions) -TEST_P(StorageEdgeTest, EdgeCreateFromLargerCommit) { - memgraph::storage::Storage store({.items = {.properties_on_edges = GetParam()}}); - memgraph::storage::Gid gid_from = memgraph::storage::Gid::FromUint(std::numeric_limits::max()); - memgraph::storage::Gid gid_to = memgraph::storage::Gid::FromUint(std::numeric_limits::max()); - - // Create vertices - { - auto acc = store.Access(); - auto vertex_to = acc.CreateVertex(); - auto vertex_from = acc.CreateVertex(); - gid_to = vertex_to.Gid(); - gid_from = vertex_from.Gid(); - ASSERT_FALSE(acc.Commit().HasError()); - } - - // Create edge - { - auto acc = store.Access(); - auto vertex_from = acc.FindVertex(gid_from, memgraph::storage::View::NEW); - auto vertex_to = acc.FindVertex(gid_to, memgraph::storage::View::NEW); - ASSERT_TRUE(vertex_from); - ASSERT_TRUE(vertex_to); - - auto et = acc.NameToEdgeType("et5"); - - auto res = acc.CreateEdge(&*vertex_from, &*vertex_to, et); - ASSERT_TRUE(res.HasValue()); - auto edge = res.GetValue(); - ASSERT_EQ(edge.EdgeType(), et); - ASSERT_EQ(edge.FromVertex(), *vertex_from); - ASSERT_EQ(edge.ToVertex(), *vertex_to); - - // Check edges without filters - ASSERT_EQ(vertex_from->InEdges(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(*vertex_from->InDegree(memgraph::storage::View::OLD), 0); - ASSERT_EQ(vertex_from->InEdges(memgraph::storage::View::NEW)->size(), 0); - ASSERT_EQ(*vertex_from->InDegree(memgraph::storage::View::NEW), 0); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(*vertex_from->OutDegree(memgraph::storage::View::OLD), 0); - { - auto ret = vertex_from->OutEdges(memgraph::storage::View::NEW); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex_from->OutDegree(memgraph::storage::View::NEW), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et); - ASSERT_EQ(e.FromVertex(), *vertex_from); - ASSERT_EQ(e.ToVertex(), *vertex_to); - } - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(*vertex_to->InDegree(memgraph::storage::View::OLD), 0); - { - auto ret = vertex_to->InEdges(memgraph::storage::View::NEW); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex_to->InDegree(memgraph::storage::View::NEW), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et); - ASSERT_EQ(e.FromVertex(), *vertex_from); - ASSERT_EQ(e.ToVertex(), *vertex_to); - } - ASSERT_EQ(vertex_to->OutEdges(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(*vertex_to->OutDegree(memgraph::storage::View::OLD), 0); - ASSERT_EQ(vertex_to->OutEdges(memgraph::storage::View::NEW)->size(), 0); - ASSERT_EQ(*vertex_to->OutDegree(memgraph::storage::View::NEW), 0); - - auto other_et = acc.NameToEdgeType("other"); - - // Check edges with filters - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::NEW, {other_et})->size(), 0); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::NEW, {et, other_et})->size(), 1); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::NEW, {}, &*vertex_to)->size(), 1); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::NEW, {}, &*vertex_from)->size(), 0); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::NEW, {other_et})->size(), 0); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::NEW, {et, other_et})->size(), 1); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::NEW, {}, &*vertex_from)->size(), 1); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::NEW, {}, &*vertex_to)->size(), 0); - - ASSERT_FALSE(acc.Commit().HasError()); - } - - // Check whether the edge exists - { - auto acc = store.Access(); - auto vertex_from = acc.FindVertex(gid_from, memgraph::storage::View::NEW); - auto vertex_to = acc.FindVertex(gid_to, memgraph::storage::View::NEW); - ASSERT_TRUE(vertex_from); - ASSERT_TRUE(vertex_to); - - auto et = acc.NameToEdgeType("et5"); - - // Check edges without filters - ASSERT_EQ(vertex_from->InEdges(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(*vertex_from->InDegree(memgraph::storage::View::OLD), 0); - ASSERT_EQ(vertex_from->InEdges(memgraph::storage::View::NEW)->size(), 0); - ASSERT_EQ(*vertex_from->InDegree(memgraph::storage::View::NEW), 0); - { - auto ret = vertex_from->OutEdges(memgraph::storage::View::OLD); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex_from->OutDegree(memgraph::storage::View::OLD), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et); - ASSERT_EQ(e.FromVertex(), *vertex_from); - ASSERT_EQ(e.ToVertex(), *vertex_to); - } - { - auto ret = vertex_from->OutEdges(memgraph::storage::View::NEW); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex_from->OutDegree(memgraph::storage::View::NEW), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et); - ASSERT_EQ(e.FromVertex(), *vertex_from); - ASSERT_EQ(e.ToVertex(), *vertex_to); - } - { - auto ret = vertex_to->InEdges(memgraph::storage::View::OLD); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex_to->InDegree(memgraph::storage::View::OLD), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et); - ASSERT_EQ(e.FromVertex(), *vertex_from); - ASSERT_EQ(e.ToVertex(), *vertex_to); - } - { - auto ret = vertex_to->InEdges(memgraph::storage::View::NEW); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex_to->InDegree(memgraph::storage::View::NEW), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et); - ASSERT_EQ(e.FromVertex(), *vertex_from); - ASSERT_EQ(e.ToVertex(), *vertex_to); - } - ASSERT_EQ(vertex_to->OutEdges(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(*vertex_to->OutDegree(memgraph::storage::View::OLD), 0); - ASSERT_EQ(vertex_to->OutEdges(memgraph::storage::View::NEW)->size(), 0); - ASSERT_EQ(*vertex_to->OutDegree(memgraph::storage::View::NEW), 0); - - auto other_et = acc.NameToEdgeType("other"); - - // Check edges with filters - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::OLD, {other_et})->size(), 0); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::NEW, {other_et})->size(), 0); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::OLD, {et, other_et})->size(), 1); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::NEW, {et, other_et})->size(), 1); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::OLD, {}, &*vertex_to)->size(), 1); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::NEW, {}, &*vertex_to)->size(), 1); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::OLD, {}, &*vertex_from)->size(), 0); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::NEW, {}, &*vertex_from)->size(), 0); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::OLD, {other_et})->size(), 0); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::NEW, {other_et})->size(), 0); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::OLD, {et, other_et})->size(), 1); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::NEW, {et, other_et})->size(), 1); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::OLD, {}, &*vertex_from)->size(), 1); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::NEW, {}, &*vertex_from)->size(), 1); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::OLD, {}, &*vertex_to)->size(), 0); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::NEW, {}, &*vertex_to)->size(), 0); - - ASSERT_FALSE(acc.Commit().HasError()); - } -} - -// NOLINTNEXTLINE(hicpp-special-member-functions) -TEST_P(StorageEdgeTest, EdgeCreateFromSameCommit) { - memgraph::storage::Storage store({.items = {.properties_on_edges = GetParam()}}); - memgraph::storage::Gid gid_vertex = memgraph::storage::Gid::FromUint(std::numeric_limits::max()); - - // Create vertex - { - auto acc = store.Access(); - auto vertex = acc.CreateVertex(); - gid_vertex = vertex.Gid(); - ASSERT_FALSE(acc.Commit().HasError()); - } - - // Create edge - { - auto acc = store.Access(); - auto vertex = acc.FindVertex(gid_vertex, memgraph::storage::View::NEW); - ASSERT_TRUE(vertex); - - auto et = acc.NameToEdgeType("et5"); - - auto res = acc.CreateEdge(&*vertex, &*vertex, et); - ASSERT_TRUE(res.HasValue()); - auto edge = res.GetValue(); - ASSERT_EQ(edge.EdgeType(), et); - ASSERT_EQ(edge.FromVertex(), *vertex); - ASSERT_EQ(edge.ToVertex(), *vertex); - - // Check edges without filters - ASSERT_EQ(vertex->InEdges(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(*vertex->InDegree(memgraph::storage::View::OLD), 0); - { - auto ret = vertex->InEdges(memgraph::storage::View::NEW); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex->InDegree(memgraph::storage::View::NEW), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et); - ASSERT_EQ(e.FromVertex(), *vertex); - ASSERT_EQ(e.ToVertex(), *vertex); - } - ASSERT_EQ(vertex->OutEdges(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(*vertex->OutDegree(memgraph::storage::View::OLD), 0); - { - auto ret = vertex->OutEdges(memgraph::storage::View::NEW); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex->OutDegree(memgraph::storage::View::NEW), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et); - ASSERT_EQ(e.FromVertex(), *vertex); - ASSERT_EQ(e.ToVertex(), *vertex); - } - - auto other_et = acc.NameToEdgeType("other"); - - // Check edges with filters - ASSERT_EQ(vertex->OutEdges(memgraph::storage::View::NEW, {other_et})->size(), 0); - ASSERT_EQ(vertex->OutEdges(memgraph::storage::View::NEW, {et, other_et})->size(), 1); - ASSERT_EQ(vertex->OutEdges(memgraph::storage::View::NEW, {}, &*vertex)->size(), 1); - ASSERT_EQ(vertex->OutEdges(memgraph::storage::View::NEW, {other_et}, &*vertex)->size(), 0); - ASSERT_EQ(vertex->InEdges(memgraph::storage::View::NEW, {other_et})->size(), 0); - ASSERT_EQ(vertex->InEdges(memgraph::storage::View::NEW, {et, other_et})->size(), 1); - ASSERT_EQ(vertex->InEdges(memgraph::storage::View::NEW, {}, &*vertex)->size(), 1); - ASSERT_EQ(vertex->InEdges(memgraph::storage::View::NEW, {other_et}, &*vertex)->size(), 0); - - ASSERT_FALSE(acc.Commit().HasError()); - } - - // Check whether the edge exists - { - auto acc = store.Access(); - auto vertex = acc.FindVertex(gid_vertex, memgraph::storage::View::NEW); - ASSERT_TRUE(vertex); - - auto et = acc.NameToEdgeType("et5"); - - // Check edges without filters - { - auto ret = vertex->InEdges(memgraph::storage::View::OLD); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex->InDegree(memgraph::storage::View::OLD), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et); - ASSERT_EQ(e.FromVertex(), *vertex); - ASSERT_EQ(e.ToVertex(), *vertex); - } - { - auto ret = vertex->InEdges(memgraph::storage::View::NEW); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex->InDegree(memgraph::storage::View::NEW), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et); - ASSERT_EQ(e.FromVertex(), *vertex); - ASSERT_EQ(e.ToVertex(), *vertex); - } - { - auto ret = vertex->OutEdges(memgraph::storage::View::OLD); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex->OutDegree(memgraph::storage::View::OLD), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et); - ASSERT_EQ(e.FromVertex(), *vertex); - ASSERT_EQ(e.ToVertex(), *vertex); - } - { - auto ret = vertex->OutEdges(memgraph::storage::View::NEW); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex->OutDegree(memgraph::storage::View::NEW), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et); - ASSERT_EQ(e.FromVertex(), *vertex); - ASSERT_EQ(e.ToVertex(), *vertex); - } - - auto other_et = acc.NameToEdgeType("other"); - - // Check edges with filters - ASSERT_EQ(vertex->InEdges(memgraph::storage::View::OLD, {other_et})->size(), 0); - ASSERT_EQ(vertex->InEdges(memgraph::storage::View::NEW, {other_et})->size(), 0); - ASSERT_EQ(vertex->InEdges(memgraph::storage::View::OLD, {et, other_et})->size(), 1); - ASSERT_EQ(vertex->InEdges(memgraph::storage::View::NEW, {et, other_et})->size(), 1); - ASSERT_EQ(vertex->InEdges(memgraph::storage::View::NEW, {}, &*vertex)->size(), 1); - ASSERT_EQ(vertex->InEdges(memgraph::storage::View::NEW, {other_et}, &*vertex)->size(), 0); - ASSERT_EQ(vertex->OutEdges(memgraph::storage::View::OLD, {other_et})->size(), 0); - ASSERT_EQ(vertex->OutEdges(memgraph::storage::View::NEW, {other_et})->size(), 0); - ASSERT_EQ(vertex->OutEdges(memgraph::storage::View::OLD, {et, other_et})->size(), 1); - ASSERT_EQ(vertex->OutEdges(memgraph::storage::View::NEW, {et, other_et})->size(), 1); - ASSERT_EQ(vertex->OutEdges(memgraph::storage::View::NEW, {}, &*vertex)->size(), 1); - ASSERT_EQ(vertex->OutEdges(memgraph::storage::View::NEW, {other_et}, &*vertex)->size(), 0); - - ASSERT_FALSE(acc.Commit().HasError()); - } -} - -// NOLINTNEXTLINE(hicpp-special-member-functions) -TEST_P(StorageEdgeTest, EdgeCreateFromSmallerAbort) { - memgraph::storage::Storage store({.items = {.properties_on_edges = GetParam()}}); - memgraph::storage::Gid gid_from = memgraph::storage::Gid::FromUint(std::numeric_limits::max()); - memgraph::storage::Gid gid_to = memgraph::storage::Gid::FromUint(std::numeric_limits::max()); - - // Create vertices - { - auto acc = store.Access(); - auto vertex_from = acc.CreateVertex(); - auto vertex_to = acc.CreateVertex(); - gid_from = vertex_from.Gid(); - gid_to = vertex_to.Gid(); - ASSERT_FALSE(acc.Commit().HasError()); - } - - // Create edge, but abort the transaction - { - auto acc = store.Access(); - auto vertex_from = acc.FindVertex(gid_from, memgraph::storage::View::NEW); - auto vertex_to = acc.FindVertex(gid_to, memgraph::storage::View::NEW); - ASSERT_TRUE(vertex_from); - ASSERT_TRUE(vertex_to); - - auto et = acc.NameToEdgeType("et5"); - - auto res = acc.CreateEdge(&*vertex_from, &*vertex_to, et); - ASSERT_TRUE(res.HasValue()); - auto edge = res.GetValue(); - ASSERT_EQ(edge.EdgeType(), et); - ASSERT_EQ(edge.FromVertex(), *vertex_from); - ASSERT_EQ(edge.ToVertex(), *vertex_to); - - // Check edges without filters - ASSERT_EQ(vertex_from->InEdges(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(*vertex_from->InDegree(memgraph::storage::View::OLD), 0); - ASSERT_EQ(vertex_from->InEdges(memgraph::storage::View::NEW)->size(), 0); - ASSERT_EQ(*vertex_from->InDegree(memgraph::storage::View::NEW), 0); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(*vertex_from->OutDegree(memgraph::storage::View::OLD), 0); - { - auto ret = vertex_from->OutEdges(memgraph::storage::View::NEW); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex_from->OutDegree(memgraph::storage::View::NEW), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et); - ASSERT_EQ(e.FromVertex(), *vertex_from); - ASSERT_EQ(e.ToVertex(), *vertex_to); - } - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(*vertex_to->InDegree(memgraph::storage::View::OLD), 0); - { - auto ret = vertex_to->InEdges(memgraph::storage::View::NEW); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex_to->InDegree(memgraph::storage::View::NEW), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et); - ASSERT_EQ(e.FromVertex(), *vertex_from); - ASSERT_EQ(e.ToVertex(), *vertex_to); - } - ASSERT_EQ(vertex_to->OutEdges(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(*vertex_to->OutDegree(memgraph::storage::View::OLD), 0); - ASSERT_EQ(vertex_to->OutEdges(memgraph::storage::View::NEW)->size(), 0); - ASSERT_EQ(*vertex_to->OutDegree(memgraph::storage::View::NEW), 0); - - auto other_et = acc.NameToEdgeType("other"); - - // Check edges with filters - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::NEW, {other_et})->size(), 0); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::NEW, {et, other_et})->size(), 1); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::NEW, {}, &*vertex_to)->size(), 1); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::NEW, {}, &*vertex_from)->size(), 0); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::NEW, {other_et})->size(), 0); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::NEW, {et, other_et})->size(), 1); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::NEW, {}, &*vertex_from)->size(), 1); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::NEW, {}, &*vertex_to)->size(), 0); - - acc.Abort(); - } - - // Check whether the edge exists - { - auto acc = store.Access(); - auto vertex_from = acc.FindVertex(gid_from, memgraph::storage::View::NEW); - auto vertex_to = acc.FindVertex(gid_to, memgraph::storage::View::NEW); - ASSERT_TRUE(vertex_from); - ASSERT_TRUE(vertex_to); - - // Check edges without filters - ASSERT_EQ(vertex_from->InEdges(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(*vertex_from->InDegree(memgraph::storage::View::OLD), 0); - ASSERT_EQ(vertex_from->InEdges(memgraph::storage::View::NEW)->size(), 0); - ASSERT_EQ(*vertex_from->InDegree(memgraph::storage::View::NEW), 0); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(*vertex_from->OutDegree(memgraph::storage::View::OLD), 0); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::NEW)->size(), 0); - ASSERT_EQ(*vertex_from->OutDegree(memgraph::storage::View::NEW), 0); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(*vertex_to->InDegree(memgraph::storage::View::OLD), 0); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::NEW)->size(), 0); - ASSERT_EQ(*vertex_to->InDegree(memgraph::storage::View::NEW), 0); - ASSERT_EQ(vertex_to->OutEdges(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(*vertex_to->OutDegree(memgraph::storage::View::OLD), 0); - ASSERT_EQ(vertex_to->OutEdges(memgraph::storage::View::NEW)->size(), 0); - ASSERT_EQ(*vertex_to->OutDegree(memgraph::storage::View::NEW), 0); - - ASSERT_FALSE(acc.Commit().HasError()); - } - - // Create edge - { - auto acc = store.Access(); - auto vertex_from = acc.FindVertex(gid_from, memgraph::storage::View::NEW); - auto vertex_to = acc.FindVertex(gid_to, memgraph::storage::View::NEW); - ASSERT_TRUE(vertex_from); - ASSERT_TRUE(vertex_to); - - auto et = acc.NameToEdgeType("et5"); - - auto res = acc.CreateEdge(&*vertex_from, &*vertex_to, et); - ASSERT_TRUE(res.HasValue()); - auto edge = res.GetValue(); - ASSERT_EQ(edge.EdgeType(), et); - ASSERT_EQ(edge.FromVertex(), *vertex_from); - ASSERT_EQ(edge.ToVertex(), *vertex_to); - - // Check edges without filters - ASSERT_EQ(vertex_from->InEdges(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(*vertex_from->InDegree(memgraph::storage::View::OLD), 0); - ASSERT_EQ(vertex_from->InEdges(memgraph::storage::View::NEW)->size(), 0); - ASSERT_EQ(*vertex_from->InDegree(memgraph::storage::View::NEW), 0); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(*vertex_from->OutDegree(memgraph::storage::View::OLD), 0); - { - auto ret = vertex_from->OutEdges(memgraph::storage::View::NEW); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex_from->OutDegree(memgraph::storage::View::NEW), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et); - ASSERT_EQ(e.FromVertex(), *vertex_from); - ASSERT_EQ(e.ToVertex(), *vertex_to); - } - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(*vertex_to->InDegree(memgraph::storage::View::OLD), 0); - { - auto ret = vertex_to->InEdges(memgraph::storage::View::NEW); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex_to->InDegree(memgraph::storage::View::NEW), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et); - ASSERT_EQ(e.FromVertex(), *vertex_from); - ASSERT_EQ(e.ToVertex(), *vertex_to); - } - ASSERT_EQ(vertex_to->OutEdges(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(*vertex_to->OutDegree(memgraph::storage::View::OLD), 0); - ASSERT_EQ(vertex_to->OutEdges(memgraph::storage::View::NEW)->size(), 0); - ASSERT_EQ(*vertex_to->OutDegree(memgraph::storage::View::NEW), 0); - - auto other_et = acc.NameToEdgeType("other"); - - // Check edges with filters - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::NEW, {other_et})->size(), 0); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::NEW, {et, other_et})->size(), 1); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::NEW, {}, &*vertex_to)->size(), 1); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::NEW, {}, &*vertex_from)->size(), 0); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::NEW, {other_et})->size(), 0); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::NEW, {et, other_et})->size(), 1); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::NEW, {}, &*vertex_from)->size(), 1); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::NEW, {}, &*vertex_to)->size(), 0); - - ASSERT_FALSE(acc.Commit().HasError()); - } - - // Check whether the edge exists - { - auto acc = store.Access(); - auto vertex_from = acc.FindVertex(gid_from, memgraph::storage::View::NEW); - auto vertex_to = acc.FindVertex(gid_to, memgraph::storage::View::NEW); - ASSERT_TRUE(vertex_from); - ASSERT_TRUE(vertex_to); - - auto et = acc.NameToEdgeType("et5"); - - // Check edges without filters - ASSERT_EQ(vertex_from->InEdges(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(*vertex_from->InDegree(memgraph::storage::View::OLD), 0); - ASSERT_EQ(vertex_from->InEdges(memgraph::storage::View::NEW)->size(), 0); - ASSERT_EQ(*vertex_from->InDegree(memgraph::storage::View::NEW), 0); - { - auto ret = vertex_from->OutEdges(memgraph::storage::View::OLD); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex_from->OutDegree(memgraph::storage::View::OLD), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et); - ASSERT_EQ(e.FromVertex(), *vertex_from); - ASSERT_EQ(e.ToVertex(), *vertex_to); - } - { - auto ret = vertex_from->OutEdges(memgraph::storage::View::NEW); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex_from->OutDegree(memgraph::storage::View::NEW), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et); - ASSERT_EQ(e.FromVertex(), *vertex_from); - ASSERT_EQ(e.ToVertex(), *vertex_to); - } - { - auto ret = vertex_to->InEdges(memgraph::storage::View::OLD); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex_to->InDegree(memgraph::storage::View::OLD), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et); - ASSERT_EQ(e.FromVertex(), *vertex_from); - ASSERT_EQ(e.ToVertex(), *vertex_to); - } - { - auto ret = vertex_to->InEdges(memgraph::storage::View::NEW); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex_to->InDegree(memgraph::storage::View::NEW), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et); - ASSERT_EQ(e.FromVertex(), *vertex_from); - ASSERT_EQ(e.ToVertex(), *vertex_to); - } - ASSERT_EQ(vertex_to->OutEdges(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(*vertex_to->OutDegree(memgraph::storage::View::OLD), 0); - ASSERT_EQ(vertex_to->OutEdges(memgraph::storage::View::NEW)->size(), 0); - ASSERT_EQ(*vertex_to->OutDegree(memgraph::storage::View::NEW), 0); - - auto other_et = acc.NameToEdgeType("other"); - - // Check edges with filters - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::OLD, {other_et})->size(), 0); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::NEW, {other_et})->size(), 0); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::OLD, {et, other_et})->size(), 1); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::NEW, {et, other_et})->size(), 1); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::OLD, {}, &*vertex_to)->size(), 1); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::NEW, {}, &*vertex_to)->size(), 1); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::OLD, {}, &*vertex_from)->size(), 0); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::NEW, {}, &*vertex_from)->size(), 0); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::OLD, {other_et})->size(), 0); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::NEW, {other_et})->size(), 0); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::OLD, {et, other_et})->size(), 1); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::NEW, {et, other_et})->size(), 1); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::OLD, {}, &*vertex_from)->size(), 1); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::NEW, {}, &*vertex_from)->size(), 1); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::OLD, {}, &*vertex_to)->size(), 0); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::NEW, {}, &*vertex_to)->size(), 0); - - ASSERT_FALSE(acc.Commit().HasError()); - } -} - -// NOLINTNEXTLINE(hicpp-special-member-functions) -TEST_P(StorageEdgeTest, EdgeCreateFromLargerAbort) { - memgraph::storage::Storage store({.items = {.properties_on_edges = GetParam()}}); - memgraph::storage::Gid gid_from = memgraph::storage::Gid::FromUint(std::numeric_limits::max()); - memgraph::storage::Gid gid_to = memgraph::storage::Gid::FromUint(std::numeric_limits::max()); - - // Create vertices - { - auto acc = store.Access(); - auto vertex_to = acc.CreateVertex(); - auto vertex_from = acc.CreateVertex(); - gid_to = vertex_to.Gid(); - gid_from = vertex_from.Gid(); - ASSERT_FALSE(acc.Commit().HasError()); - } - - // Create edge, but abort the transaction - { - auto acc = store.Access(); - auto vertex_from = acc.FindVertex(gid_from, memgraph::storage::View::NEW); - auto vertex_to = acc.FindVertex(gid_to, memgraph::storage::View::NEW); - ASSERT_TRUE(vertex_from); - ASSERT_TRUE(vertex_to); - - auto et = acc.NameToEdgeType("et5"); - - auto res = acc.CreateEdge(&*vertex_from, &*vertex_to, et); - ASSERT_TRUE(res.HasValue()); - auto edge = res.GetValue(); - ASSERT_EQ(edge.EdgeType(), et); - ASSERT_EQ(edge.FromVertex(), *vertex_from); - ASSERT_EQ(edge.ToVertex(), *vertex_to); - - // Check edges without filters - ASSERT_EQ(vertex_from->InEdges(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(*vertex_from->InDegree(memgraph::storage::View::OLD), 0); - ASSERT_EQ(vertex_from->InEdges(memgraph::storage::View::NEW)->size(), 0); - ASSERT_EQ(*vertex_from->InDegree(memgraph::storage::View::NEW), 0); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(*vertex_from->OutDegree(memgraph::storage::View::OLD), 0); - { - auto ret = vertex_from->OutEdges(memgraph::storage::View::NEW); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex_from->OutDegree(memgraph::storage::View::NEW), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et); - ASSERT_EQ(e.FromVertex(), *vertex_from); - ASSERT_EQ(e.ToVertex(), *vertex_to); - } - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(*vertex_to->InDegree(memgraph::storage::View::OLD), 0); - { - auto ret = vertex_to->InEdges(memgraph::storage::View::NEW); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex_to->InDegree(memgraph::storage::View::NEW), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et); - ASSERT_EQ(e.FromVertex(), *vertex_from); - ASSERT_EQ(e.ToVertex(), *vertex_to); - } - ASSERT_EQ(vertex_to->OutEdges(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(*vertex_to->OutDegree(memgraph::storage::View::OLD), 0); - ASSERT_EQ(vertex_to->OutEdges(memgraph::storage::View::NEW)->size(), 0); - ASSERT_EQ(*vertex_to->OutDegree(memgraph::storage::View::NEW), 0); - - auto other_et = acc.NameToEdgeType("other"); - - // Check edges with filters - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::NEW, {other_et})->size(), 0); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::NEW, {et, other_et})->size(), 1); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::NEW, {}, &*vertex_to)->size(), 1); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::NEW, {}, &*vertex_from)->size(), 0); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::NEW, {other_et})->size(), 0); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::NEW, {et, other_et})->size(), 1); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::NEW, {}, &*vertex_from)->size(), 1); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::NEW, {}, &*vertex_to)->size(), 0); - - acc.Abort(); - } - - // Check whether the edge exists - { - auto acc = store.Access(); - auto vertex_from = acc.FindVertex(gid_from, memgraph::storage::View::NEW); - auto vertex_to = acc.FindVertex(gid_to, memgraph::storage::View::NEW); - ASSERT_TRUE(vertex_from); - ASSERT_TRUE(vertex_to); - - // Check edges without filters - ASSERT_EQ(vertex_from->InEdges(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(*vertex_from->InDegree(memgraph::storage::View::OLD), 0); - ASSERT_EQ(vertex_from->InEdges(memgraph::storage::View::NEW)->size(), 0); - ASSERT_EQ(*vertex_from->InDegree(memgraph::storage::View::NEW), 0); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(*vertex_from->OutDegree(memgraph::storage::View::OLD), 0); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::NEW)->size(), 0); - ASSERT_EQ(*vertex_from->OutDegree(memgraph::storage::View::NEW), 0); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(*vertex_to->InDegree(memgraph::storage::View::OLD), 0); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::NEW)->size(), 0); - ASSERT_EQ(*vertex_to->InDegree(memgraph::storage::View::NEW), 0); - ASSERT_EQ(vertex_to->OutEdges(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(*vertex_to->OutDegree(memgraph::storage::View::OLD), 0); - ASSERT_EQ(vertex_to->OutEdges(memgraph::storage::View::NEW)->size(), 0); - ASSERT_EQ(*vertex_to->OutDegree(memgraph::storage::View::NEW), 0); - - ASSERT_FALSE(acc.Commit().HasError()); - } - - // Create edge - { - auto acc = store.Access(); - auto vertex_from = acc.FindVertex(gid_from, memgraph::storage::View::NEW); - auto vertex_to = acc.FindVertex(gid_to, memgraph::storage::View::NEW); - ASSERT_TRUE(vertex_from); - ASSERT_TRUE(vertex_to); - - auto et = acc.NameToEdgeType("et5"); - - auto res = acc.CreateEdge(&*vertex_from, &*vertex_to, et); - ASSERT_TRUE(res.HasValue()); - auto edge = res.GetValue(); - ASSERT_EQ(edge.EdgeType(), et); - ASSERT_EQ(edge.FromVertex(), *vertex_from); - ASSERT_EQ(edge.ToVertex(), *vertex_to); - - // Check edges without filters - ASSERT_EQ(vertex_from->InEdges(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(*vertex_from->InDegree(memgraph::storage::View::OLD), 0); - ASSERT_EQ(vertex_from->InEdges(memgraph::storage::View::NEW)->size(), 0); - ASSERT_EQ(*vertex_from->InDegree(memgraph::storage::View::NEW), 0); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(*vertex_from->OutDegree(memgraph::storage::View::OLD), 0); - { - auto ret = vertex_from->OutEdges(memgraph::storage::View::NEW); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex_from->OutDegree(memgraph::storage::View::NEW), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et); - ASSERT_EQ(e.FromVertex(), *vertex_from); - ASSERT_EQ(e.ToVertex(), *vertex_to); - } - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(*vertex_to->InDegree(memgraph::storage::View::OLD), 0); - { - auto ret = vertex_to->InEdges(memgraph::storage::View::NEW); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex_to->InDegree(memgraph::storage::View::NEW), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et); - ASSERT_EQ(e.FromVertex(), *vertex_from); - ASSERT_EQ(e.ToVertex(), *vertex_to); - } - ASSERT_EQ(vertex_to->OutEdges(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(*vertex_to->OutDegree(memgraph::storage::View::OLD), 0); - ASSERT_EQ(vertex_to->OutEdges(memgraph::storage::View::NEW)->size(), 0); - ASSERT_EQ(*vertex_to->OutDegree(memgraph::storage::View::NEW), 0); - - auto other_et = acc.NameToEdgeType("other"); - - // Check edges with filters - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::NEW, {other_et})->size(), 0); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::NEW, {et, other_et})->size(), 1); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::NEW, {}, &*vertex_to)->size(), 1); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::NEW, {}, &*vertex_from)->size(), 0); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::NEW, {other_et})->size(), 0); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::NEW, {et, other_et})->size(), 1); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::NEW, {}, &*vertex_from)->size(), 1); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::NEW, {}, &*vertex_to)->size(), 0); - - ASSERT_FALSE(acc.Commit().HasError()); - } - - // Check whether the edge exists - { - auto acc = store.Access(); - auto vertex_from = acc.FindVertex(gid_from, memgraph::storage::View::NEW); - auto vertex_to = acc.FindVertex(gid_to, memgraph::storage::View::NEW); - ASSERT_TRUE(vertex_from); - ASSERT_TRUE(vertex_to); - - auto et = acc.NameToEdgeType("et5"); - - // Check edges without filters - ASSERT_EQ(vertex_from->InEdges(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(*vertex_from->InDegree(memgraph::storage::View::OLD), 0); - ASSERT_EQ(vertex_from->InEdges(memgraph::storage::View::NEW)->size(), 0); - ASSERT_EQ(*vertex_from->InDegree(memgraph::storage::View::NEW), 0); - { - auto ret = vertex_from->OutEdges(memgraph::storage::View::OLD); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex_from->OutDegree(memgraph::storage::View::OLD), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et); - ASSERT_EQ(e.FromVertex(), *vertex_from); - ASSERT_EQ(e.ToVertex(), *vertex_to); - } - { - auto ret = vertex_from->OutEdges(memgraph::storage::View::NEW); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex_from->OutDegree(memgraph::storage::View::NEW), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et); - ASSERT_EQ(e.FromVertex(), *vertex_from); - ASSERT_EQ(e.ToVertex(), *vertex_to); - } - { - auto ret = vertex_to->InEdges(memgraph::storage::View::OLD); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex_to->InDegree(memgraph::storage::View::OLD), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et); - ASSERT_EQ(e.FromVertex(), *vertex_from); - ASSERT_EQ(e.ToVertex(), *vertex_to); - } - { - auto ret = vertex_to->InEdges(memgraph::storage::View::NEW); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex_to->InDegree(memgraph::storage::View::NEW), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et); - ASSERT_EQ(e.FromVertex(), *vertex_from); - ASSERT_EQ(e.ToVertex(), *vertex_to); - } - ASSERT_EQ(vertex_to->OutEdges(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(*vertex_to->OutDegree(memgraph::storage::View::OLD), 0); - ASSERT_EQ(vertex_to->OutEdges(memgraph::storage::View::NEW)->size(), 0); - ASSERT_EQ(*vertex_to->OutDegree(memgraph::storage::View::NEW), 0); - - auto other_et = acc.NameToEdgeType("other"); - - // Check edges with filters - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::OLD, {other_et})->size(), 0); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::NEW, {other_et})->size(), 0); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::OLD, {et, other_et})->size(), 1); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::NEW, {et, other_et})->size(), 1); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::OLD, {}, &*vertex_to)->size(), 1); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::NEW, {}, &*vertex_to)->size(), 1); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::OLD, {}, &*vertex_from)->size(), 0); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::NEW, {}, &*vertex_from)->size(), 0); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::OLD, {other_et})->size(), 0); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::NEW, {other_et})->size(), 0); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::OLD, {et, other_et})->size(), 1); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::NEW, {et, other_et})->size(), 1); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::OLD, {}, &*vertex_from)->size(), 1); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::NEW, {}, &*vertex_from)->size(), 1); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::OLD, {}, &*vertex_to)->size(), 0); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::NEW, {}, &*vertex_to)->size(), 0); - - ASSERT_FALSE(acc.Commit().HasError()); - } -} - -// NOLINTNEXTLINE(hicpp-special-member-functions) -TEST_P(StorageEdgeTest, EdgeCreateFromSameAbort) { - memgraph::storage::Storage store({.items = {.properties_on_edges = GetParam()}}); - memgraph::storage::Gid gid_vertex = memgraph::storage::Gid::FromUint(std::numeric_limits::max()); - - // Create vertex - { - auto acc = store.Access(); - auto vertex = acc.CreateVertex(); - gid_vertex = vertex.Gid(); - ASSERT_FALSE(acc.Commit().HasError()); - } - - // Create edge, but abort the transaction - { - auto acc = store.Access(); - auto vertex = acc.FindVertex(gid_vertex, memgraph::storage::View::NEW); - ASSERT_TRUE(vertex); - - auto et = acc.NameToEdgeType("et5"); - - auto res = acc.CreateEdge(&*vertex, &*vertex, et); - ASSERT_TRUE(res.HasValue()); - auto edge = res.GetValue(); - ASSERT_EQ(edge.EdgeType(), et); - ASSERT_EQ(edge.FromVertex(), *vertex); - ASSERT_EQ(edge.ToVertex(), *vertex); - - // Check edges without filters - ASSERT_EQ(vertex->InEdges(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(*vertex->InDegree(memgraph::storage::View::OLD), 0); - { - auto ret = vertex->InEdges(memgraph::storage::View::NEW); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex->InDegree(memgraph::storage::View::NEW), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et); - ASSERT_EQ(e.FromVertex(), *vertex); - ASSERT_EQ(e.ToVertex(), *vertex); - } - ASSERT_EQ(vertex->OutEdges(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(*vertex->OutDegree(memgraph::storage::View::OLD), 0); - { - auto ret = vertex->OutEdges(memgraph::storage::View::NEW); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex->OutDegree(memgraph::storage::View::NEW), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et); - ASSERT_EQ(e.FromVertex(), *vertex); - ASSERT_EQ(e.ToVertex(), *vertex); - } - - auto other_et = acc.NameToEdgeType("other"); - - // Check edges with filters - ASSERT_EQ(vertex->OutEdges(memgraph::storage::View::NEW, {other_et})->size(), 0); - ASSERT_EQ(vertex->OutEdges(memgraph::storage::View::NEW, {et, other_et})->size(), 1); - ASSERT_EQ(vertex->OutEdges(memgraph::storage::View::NEW, {}, &*vertex)->size(), 1); - ASSERT_EQ(vertex->OutEdges(memgraph::storage::View::NEW, {other_et}, &*vertex)->size(), 0); - ASSERT_EQ(vertex->InEdges(memgraph::storage::View::NEW, {other_et})->size(), 0); - ASSERT_EQ(vertex->InEdges(memgraph::storage::View::NEW, {et, other_et})->size(), 1); - ASSERT_EQ(vertex->InEdges(memgraph::storage::View::NEW, {}, &*vertex)->size(), 1); - ASSERT_EQ(vertex->InEdges(memgraph::storage::View::NEW, {other_et}, &*vertex)->size(), 0); - - acc.Abort(); - } - - // Check whether the edge exists - { - auto acc = store.Access(); - auto vertex = acc.FindVertex(gid_vertex, memgraph::storage::View::NEW); - ASSERT_TRUE(vertex); - - // Check edges without filters - ASSERT_EQ(vertex->InEdges(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(*vertex->InDegree(memgraph::storage::View::OLD), 0); - ASSERT_EQ(vertex->InEdges(memgraph::storage::View::NEW)->size(), 0); - ASSERT_EQ(*vertex->InDegree(memgraph::storage::View::NEW), 0); - ASSERT_EQ(vertex->OutEdges(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(*vertex->OutDegree(memgraph::storage::View::OLD), 0); - ASSERT_EQ(vertex->OutEdges(memgraph::storage::View::NEW)->size(), 0); - ASSERT_EQ(*vertex->OutDegree(memgraph::storage::View::NEW), 0); - - ASSERT_FALSE(acc.Commit().HasError()); - } - - // Create edge - { - auto acc = store.Access(); - auto vertex = acc.FindVertex(gid_vertex, memgraph::storage::View::NEW); - ASSERT_TRUE(vertex); - - auto et = acc.NameToEdgeType("et5"); - - auto res = acc.CreateEdge(&*vertex, &*vertex, et); - ASSERT_TRUE(res.HasValue()); - auto edge = res.GetValue(); - ASSERT_EQ(edge.EdgeType(), et); - ASSERT_EQ(edge.FromVertex(), *vertex); - ASSERT_EQ(edge.ToVertex(), *vertex); - - // Check edges without filters - ASSERT_EQ(vertex->InEdges(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(*vertex->InDegree(memgraph::storage::View::OLD), 0); - { - auto ret = vertex->InEdges(memgraph::storage::View::NEW); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex->InDegree(memgraph::storage::View::NEW), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et); - ASSERT_EQ(e.FromVertex(), *vertex); - ASSERT_EQ(e.ToVertex(), *vertex); - } - ASSERT_EQ(vertex->OutEdges(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(*vertex->OutDegree(memgraph::storage::View::OLD), 0); - { - auto ret = vertex->OutEdges(memgraph::storage::View::NEW); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex->OutDegree(memgraph::storage::View::NEW), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et); - ASSERT_EQ(e.FromVertex(), *vertex); - ASSERT_EQ(e.ToVertex(), *vertex); - } - - auto other_et = acc.NameToEdgeType("other"); - - // Check edges with filters - ASSERT_EQ(vertex->OutEdges(memgraph::storage::View::NEW, {other_et})->size(), 0); - ASSERT_EQ(vertex->OutEdges(memgraph::storage::View::NEW, {et, other_et})->size(), 1); - ASSERT_EQ(vertex->OutEdges(memgraph::storage::View::NEW, {}, &*vertex)->size(), 1); - ASSERT_EQ(vertex->OutEdges(memgraph::storage::View::NEW, {other_et}, &*vertex)->size(), 0); - ASSERT_EQ(vertex->InEdges(memgraph::storage::View::NEW, {other_et})->size(), 0); - ASSERT_EQ(vertex->InEdges(memgraph::storage::View::NEW, {et, other_et})->size(), 1); - ASSERT_EQ(vertex->InEdges(memgraph::storage::View::NEW, {}, &*vertex)->size(), 1); - ASSERT_EQ(vertex->InEdges(memgraph::storage::View::NEW, {other_et}, &*vertex)->size(), 0); - - ASSERT_FALSE(acc.Commit().HasError()); - } - - // Check whether the edge exists - { - auto acc = store.Access(); - auto vertex = acc.FindVertex(gid_vertex, memgraph::storage::View::NEW); - ASSERT_TRUE(vertex); - - auto et = acc.NameToEdgeType("et5"); - - // Check edges without filters - { - auto ret = vertex->InEdges(memgraph::storage::View::OLD); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex->InDegree(memgraph::storage::View::OLD), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et); - ASSERT_EQ(e.FromVertex(), *vertex); - ASSERT_EQ(e.ToVertex(), *vertex); - } - { - auto ret = vertex->InEdges(memgraph::storage::View::NEW); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex->InDegree(memgraph::storage::View::NEW), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et); - ASSERT_EQ(e.FromVertex(), *vertex); - ASSERT_EQ(e.ToVertex(), *vertex); - } - { - auto ret = vertex->OutEdges(memgraph::storage::View::OLD); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex->OutDegree(memgraph::storage::View::OLD), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et); - ASSERT_EQ(e.FromVertex(), *vertex); - ASSERT_EQ(e.ToVertex(), *vertex); - } - { - auto ret = vertex->OutEdges(memgraph::storage::View::NEW); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex->OutDegree(memgraph::storage::View::NEW), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et); - ASSERT_EQ(e.FromVertex(), *vertex); - ASSERT_EQ(e.ToVertex(), *vertex); - } - - auto other_et = acc.NameToEdgeType("other"); - - // Check edges with filters - ASSERT_EQ(vertex->InEdges(memgraph::storage::View::OLD, {other_et})->size(), 0); - ASSERT_EQ(vertex->InEdges(memgraph::storage::View::NEW, {other_et})->size(), 0); - ASSERT_EQ(vertex->InEdges(memgraph::storage::View::OLD, {et, other_et})->size(), 1); - ASSERT_EQ(vertex->InEdges(memgraph::storage::View::NEW, {et, other_et})->size(), 1); - ASSERT_EQ(vertex->InEdges(memgraph::storage::View::OLD, {}, &*vertex)->size(), 1); - ASSERT_EQ(vertex->InEdges(memgraph::storage::View::NEW, {}, &*vertex)->size(), 1); - ASSERT_EQ(vertex->InEdges(memgraph::storage::View::OLD, {other_et}, &*vertex)->size(), 0); - ASSERT_EQ(vertex->InEdges(memgraph::storage::View::NEW, {other_et}, &*vertex)->size(), 0); - ASSERT_EQ(vertex->OutEdges(memgraph::storage::View::OLD, {other_et})->size(), 0); - ASSERT_EQ(vertex->OutEdges(memgraph::storage::View::NEW, {other_et})->size(), 0); - ASSERT_EQ(vertex->OutEdges(memgraph::storage::View::OLD, {et, other_et})->size(), 1); - ASSERT_EQ(vertex->OutEdges(memgraph::storage::View::NEW, {et, other_et})->size(), 1); - ASSERT_EQ(vertex->OutEdges(memgraph::storage::View::OLD, {}, &*vertex)->size(), 1); - ASSERT_EQ(vertex->OutEdges(memgraph::storage::View::NEW, {}, &*vertex)->size(), 1); - ASSERT_EQ(vertex->OutEdges(memgraph::storage::View::OLD, {other_et}, &*vertex)->size(), 0); - ASSERT_EQ(vertex->OutEdges(memgraph::storage::View::NEW, {other_et}, &*vertex)->size(), 0); - - ASSERT_FALSE(acc.Commit().HasError()); - } -} - -// NOLINTNEXTLINE(hicpp-special-member-functions) -TEST_P(StorageEdgeTest, EdgeDeleteFromSmallerCommit) { - memgraph::storage::Storage store({.items = {.properties_on_edges = GetParam()}}); - memgraph::storage::Gid gid_from = memgraph::storage::Gid::FromUint(std::numeric_limits::max()); - memgraph::storage::Gid gid_to = memgraph::storage::Gid::FromUint(std::numeric_limits::max()); - - // Create vertices - { - auto acc = store.Access(); - auto vertex_from = acc.CreateVertex(); - auto vertex_to = acc.CreateVertex(); - gid_from = vertex_from.Gid(); - gid_to = vertex_to.Gid(); - ASSERT_FALSE(acc.Commit().HasError()); - } - - // Create edge - { - auto acc = store.Access(); - auto vertex_from = acc.FindVertex(gid_from, memgraph::storage::View::NEW); - auto vertex_to = acc.FindVertex(gid_to, memgraph::storage::View::NEW); - ASSERT_TRUE(vertex_from); - ASSERT_TRUE(vertex_to); - - auto et = acc.NameToEdgeType("et5"); - - auto res = acc.CreateEdge(&*vertex_from, &*vertex_to, et); - ASSERT_TRUE(res.HasValue()); - auto edge = res.GetValue(); - ASSERT_EQ(edge.EdgeType(), et); - ASSERT_EQ(edge.FromVertex(), *vertex_from); - ASSERT_EQ(edge.ToVertex(), *vertex_to); - - // Check edges without filters - ASSERT_EQ(vertex_from->InEdges(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(*vertex_from->InDegree(memgraph::storage::View::OLD), 0); - ASSERT_EQ(vertex_from->InEdges(memgraph::storage::View::NEW)->size(), 0); - ASSERT_EQ(*vertex_from->InDegree(memgraph::storage::View::NEW), 0); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(*vertex_from->OutDegree(memgraph::storage::View::OLD), 0); - { - auto ret = vertex_from->OutEdges(memgraph::storage::View::NEW); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex_from->OutDegree(memgraph::storage::View::NEW), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et); - ASSERT_EQ(e.FromVertex(), *vertex_from); - ASSERT_EQ(e.ToVertex(), *vertex_to); - } - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(*vertex_to->InDegree(memgraph::storage::View::OLD), 0); - { - auto ret = vertex_to->InEdges(memgraph::storage::View::NEW); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex_to->InDegree(memgraph::storage::View::NEW), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et); - ASSERT_EQ(e.FromVertex(), *vertex_from); - ASSERT_EQ(e.ToVertex(), *vertex_to); - } - ASSERT_EQ(vertex_to->OutEdges(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(*vertex_to->OutDegree(memgraph::storage::View::OLD), 0); - ASSERT_EQ(vertex_to->OutEdges(memgraph::storage::View::NEW)->size(), 0); - ASSERT_EQ(*vertex_to->OutDegree(memgraph::storage::View::NEW), 0); - - auto other_et = acc.NameToEdgeType("other"); - - // Check edges with filters - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::NEW, {other_et})->size(), 0); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::NEW, {et, other_et})->size(), 1); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::NEW, {}, &*vertex_to)->size(), 1); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::NEW, {}, &*vertex_from)->size(), 0); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::NEW, {other_et})->size(), 0); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::NEW, {et, other_et})->size(), 1); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::NEW, {}, &*vertex_from)->size(), 1); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::NEW, {}, &*vertex_to)->size(), 0); - - ASSERT_FALSE(acc.Commit().HasError()); - } - - // Check whether the edge exists - { - auto acc = store.Access(); - auto vertex_from = acc.FindVertex(gid_from, memgraph::storage::View::NEW); - auto vertex_to = acc.FindVertex(gid_to, memgraph::storage::View::NEW); - ASSERT_TRUE(vertex_from); - ASSERT_TRUE(vertex_to); - - auto et = acc.NameToEdgeType("et5"); - - // Check edges without filters - ASSERT_EQ(vertex_from->InEdges(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(*vertex_from->InDegree(memgraph::storage::View::OLD), 0); - ASSERT_EQ(vertex_from->InEdges(memgraph::storage::View::NEW)->size(), 0); - ASSERT_EQ(*vertex_from->InDegree(memgraph::storage::View::NEW), 0); - { - auto ret = vertex_from->OutEdges(memgraph::storage::View::OLD); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex_from->OutDegree(memgraph::storage::View::OLD), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et); - ASSERT_EQ(e.FromVertex(), *vertex_from); - ASSERT_EQ(e.ToVertex(), *vertex_to); - } - { - auto ret = vertex_from->OutEdges(memgraph::storage::View::NEW); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex_from->OutDegree(memgraph::storage::View::NEW), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et); - ASSERT_EQ(e.FromVertex(), *vertex_from); - ASSERT_EQ(e.ToVertex(), *vertex_to); - } - { - auto ret = vertex_to->InEdges(memgraph::storage::View::OLD); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex_to->InDegree(memgraph::storage::View::OLD), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et); - ASSERT_EQ(e.FromVertex(), *vertex_from); - ASSERT_EQ(e.ToVertex(), *vertex_to); - } - { - auto ret = vertex_to->InEdges(memgraph::storage::View::NEW); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex_to->InDegree(memgraph::storage::View::NEW), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et); - ASSERT_EQ(e.FromVertex(), *vertex_from); - ASSERT_EQ(e.ToVertex(), *vertex_to); - } - ASSERT_EQ(vertex_to->OutEdges(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(*vertex_to->OutDegree(memgraph::storage::View::OLD), 0); - ASSERT_EQ(vertex_to->OutEdges(memgraph::storage::View::NEW)->size(), 0); - ASSERT_EQ(*vertex_to->OutDegree(memgraph::storage::View::NEW), 0); - - auto other_et = acc.NameToEdgeType("other"); - - // Check edges with filters - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::OLD, {other_et})->size(), 0); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::NEW, {other_et})->size(), 0); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::OLD, {et, other_et})->size(), 1); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::NEW, {et, other_et})->size(), 1); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::OLD, {}, &*vertex_to)->size(), 1); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::NEW, {}, &*vertex_to)->size(), 1); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::OLD, {}, &*vertex_from)->size(), 0); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::NEW, {}, &*vertex_from)->size(), 0); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::OLD, {other_et})->size(), 0); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::NEW, {other_et})->size(), 0); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::OLD, {et, other_et})->size(), 1); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::NEW, {et, other_et})->size(), 1); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::OLD, {}, &*vertex_from)->size(), 1); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::NEW, {}, &*vertex_from)->size(), 1); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::OLD, {}, &*vertex_to)->size(), 0); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::NEW, {}, &*vertex_to)->size(), 0); - - ASSERT_FALSE(acc.Commit().HasError()); - } - - // Delete edge - { - auto acc = store.Access(); - auto vertex_from = acc.FindVertex(gid_from, memgraph::storage::View::NEW); - auto vertex_to = acc.FindVertex(gid_to, memgraph::storage::View::NEW); - ASSERT_TRUE(vertex_from); - ASSERT_TRUE(vertex_to); - - auto et = acc.NameToEdgeType("et5"); - - auto edge = vertex_from->OutEdges(memgraph::storage::View::NEW).GetValue()[0]; - - auto res = acc.DeleteEdge(&edge); - ASSERT_TRUE(res.HasValue()); - ASSERT_TRUE(res.GetValue()); - - // Check edges without filters - ASSERT_EQ(vertex_from->InEdges(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(*vertex_from->InDegree(memgraph::storage::View::OLD), 0); - ASSERT_EQ(vertex_from->InEdges(memgraph::storage::View::NEW)->size(), 0); - ASSERT_EQ(*vertex_from->InDegree(memgraph::storage::View::NEW), 0); - { - auto ret = vertex_from->OutEdges(memgraph::storage::View::OLD); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex_from->OutDegree(memgraph::storage::View::OLD), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et); - ASSERT_EQ(e.FromVertex(), *vertex_from); - ASSERT_EQ(e.ToVertex(), *vertex_to); - } - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::NEW)->size(), 0); - ASSERT_EQ(*vertex_from->OutDegree(memgraph::storage::View::NEW), 0); - { - auto ret = vertex_to->InEdges(memgraph::storage::View::OLD); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex_to->InDegree(memgraph::storage::View::OLD), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et); - ASSERT_EQ(e.FromVertex(), *vertex_from); - ASSERT_EQ(e.ToVertex(), *vertex_to); - } - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::NEW)->size(), 0); - ASSERT_EQ(*vertex_to->InDegree(memgraph::storage::View::NEW), 0); - ASSERT_EQ(vertex_to->OutEdges(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(*vertex_to->OutDegree(memgraph::storage::View::OLD), 0); - ASSERT_EQ(vertex_to->OutEdges(memgraph::storage::View::NEW)->size(), 0); - ASSERT_EQ(*vertex_to->OutDegree(memgraph::storage::View::NEW), 0); - - auto other_et = acc.NameToEdgeType("other"); - - // Check edges with filters - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::OLD, {other_et})->size(), 0); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::OLD, {et, other_et})->size(), 1); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::OLD, {}, &*vertex_to)->size(), 1); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::OLD, {}, &*vertex_from)->size(), 0); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::OLD, {other_et})->size(), 0); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::OLD, {et, other_et})->size(), 1); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::OLD, {}, &*vertex_from)->size(), 1); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::OLD, {}, &*vertex_to)->size(), 0); - - ASSERT_FALSE(acc.Commit().HasError()); - } - - // Check whether the edge exists - { - auto acc = store.Access(); - auto vertex_from = acc.FindVertex(gid_from, memgraph::storage::View::NEW); - auto vertex_to = acc.FindVertex(gid_to, memgraph::storage::View::NEW); - ASSERT_TRUE(vertex_from); - ASSERT_TRUE(vertex_to); - - // Check edges without filters - ASSERT_EQ(vertex_from->InEdges(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(*vertex_from->InDegree(memgraph::storage::View::OLD), 0); - ASSERT_EQ(vertex_from->InEdges(memgraph::storage::View::NEW)->size(), 0); - ASSERT_EQ(*vertex_from->InDegree(memgraph::storage::View::NEW), 0); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(*vertex_from->OutDegree(memgraph::storage::View::OLD), 0); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::NEW)->size(), 0); - ASSERT_EQ(*vertex_from->OutDegree(memgraph::storage::View::NEW), 0); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(*vertex_to->InDegree(memgraph::storage::View::OLD), 0); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::NEW)->size(), 0); - ASSERT_EQ(*vertex_to->InDegree(memgraph::storage::View::NEW), 0); - ASSERT_EQ(vertex_to->OutEdges(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(*vertex_to->OutDegree(memgraph::storage::View::OLD), 0); - ASSERT_EQ(vertex_to->OutEdges(memgraph::storage::View::NEW)->size(), 0); - ASSERT_EQ(*vertex_to->OutDegree(memgraph::storage::View::NEW), 0); - - ASSERT_FALSE(acc.Commit().HasError()); - } -} - -// NOLINTNEXTLINE(hicpp-special-member-functions) -TEST_P(StorageEdgeTest, EdgeDeleteFromLargerCommit) { - memgraph::storage::Storage store({.items = {.properties_on_edges = GetParam()}}); - memgraph::storage::Gid gid_from = memgraph::storage::Gid::FromUint(std::numeric_limits::max()); - memgraph::storage::Gid gid_to = memgraph::storage::Gid::FromUint(std::numeric_limits::max()); - - // Create vertices - { - auto acc = store.Access(); - auto vertex_to = acc.CreateVertex(); - auto vertex_from = acc.CreateVertex(); - gid_from = vertex_from.Gid(); - gid_to = vertex_to.Gid(); - ASSERT_FALSE(acc.Commit().HasError()); - } - - // Create edge - { - auto acc = store.Access(); - auto vertex_from = acc.FindVertex(gid_from, memgraph::storage::View::NEW); - auto vertex_to = acc.FindVertex(gid_to, memgraph::storage::View::NEW); - ASSERT_TRUE(vertex_from); - ASSERT_TRUE(vertex_to); - - auto et = acc.NameToEdgeType("et5"); - - auto res = acc.CreateEdge(&*vertex_from, &*vertex_to, et); - ASSERT_TRUE(res.HasValue()); - auto edge = res.GetValue(); - ASSERT_EQ(edge.EdgeType(), et); - ASSERT_EQ(edge.FromVertex(), *vertex_from); - ASSERT_EQ(edge.ToVertex(), *vertex_to); - - // Check edges without filters - ASSERT_EQ(vertex_from->InEdges(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(*vertex_from->InDegree(memgraph::storage::View::OLD), 0); - ASSERT_EQ(vertex_from->InEdges(memgraph::storage::View::NEW)->size(), 0); - ASSERT_EQ(*vertex_from->InDegree(memgraph::storage::View::NEW), 0); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(*vertex_from->OutDegree(memgraph::storage::View::OLD), 0); - { - auto ret = vertex_from->OutEdges(memgraph::storage::View::NEW); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex_from->OutDegree(memgraph::storage::View::NEW), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et); - ASSERT_EQ(e.FromVertex(), *vertex_from); - ASSERT_EQ(e.ToVertex(), *vertex_to); - } - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(*vertex_to->InDegree(memgraph::storage::View::OLD), 0); - { - auto ret = vertex_to->InEdges(memgraph::storage::View::NEW); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex_to->InDegree(memgraph::storage::View::NEW), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et); - ASSERT_EQ(e.FromVertex(), *vertex_from); - ASSERT_EQ(e.ToVertex(), *vertex_to); - } - ASSERT_EQ(vertex_to->OutEdges(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(*vertex_to->OutDegree(memgraph::storage::View::OLD), 0); - ASSERT_EQ(vertex_to->OutEdges(memgraph::storage::View::NEW)->size(), 0); - ASSERT_EQ(*vertex_to->OutDegree(memgraph::storage::View::NEW), 0); - - auto other_et = acc.NameToEdgeType("other"); - - // Check edges with filters - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::NEW, {other_et})->size(), 0); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::NEW, {et, other_et})->size(), 1); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::NEW, {}, &*vertex_to)->size(), 1); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::NEW, {}, &*vertex_from)->size(), 0); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::NEW, {other_et})->size(), 0); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::NEW, {et, other_et})->size(), 1); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::NEW, {}, &*vertex_from)->size(), 1); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::NEW, {}, &*vertex_to)->size(), 0); - - ASSERT_FALSE(acc.Commit().HasError()); - } - - // Check whether the edge exists - { - auto acc = store.Access(); - auto vertex_from = acc.FindVertex(gid_from, memgraph::storage::View::NEW); - auto vertex_to = acc.FindVertex(gid_to, memgraph::storage::View::NEW); - ASSERT_TRUE(vertex_from); - ASSERT_TRUE(vertex_to); - - auto et = acc.NameToEdgeType("et5"); - - // Check edges without filters - ASSERT_EQ(vertex_from->InEdges(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(*vertex_from->InDegree(memgraph::storage::View::OLD), 0); - ASSERT_EQ(vertex_from->InEdges(memgraph::storage::View::NEW)->size(), 0); - ASSERT_EQ(*vertex_from->InDegree(memgraph::storage::View::NEW), 0); - { - auto ret = vertex_from->OutEdges(memgraph::storage::View::OLD); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex_from->OutDegree(memgraph::storage::View::OLD), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et); - ASSERT_EQ(e.FromVertex(), *vertex_from); - ASSERT_EQ(e.ToVertex(), *vertex_to); - } - { - auto ret = vertex_from->OutEdges(memgraph::storage::View::NEW); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex_from->OutDegree(memgraph::storage::View::NEW), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et); - ASSERT_EQ(e.FromVertex(), *vertex_from); - ASSERT_EQ(e.ToVertex(), *vertex_to); - } - { - auto ret = vertex_to->InEdges(memgraph::storage::View::OLD); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex_to->InDegree(memgraph::storage::View::OLD), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et); - ASSERT_EQ(e.FromVertex(), *vertex_from); - ASSERT_EQ(e.ToVertex(), *vertex_to); - } - { - auto ret = vertex_to->InEdges(memgraph::storage::View::NEW); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex_to->InDegree(memgraph::storage::View::NEW), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et); - ASSERT_EQ(e.FromVertex(), *vertex_from); - ASSERT_EQ(e.ToVertex(), *vertex_to); - } - ASSERT_EQ(vertex_to->OutEdges(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(*vertex_to->OutDegree(memgraph::storage::View::OLD), 0); - ASSERT_EQ(vertex_to->OutEdges(memgraph::storage::View::NEW)->size(), 0); - ASSERT_EQ(*vertex_to->OutDegree(memgraph::storage::View::NEW), 0); - - auto other_et = acc.NameToEdgeType("other"); - - // Check edges with filters - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::OLD, {other_et})->size(), 0); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::NEW, {other_et})->size(), 0); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::OLD, {et, other_et})->size(), 1); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::NEW, {et, other_et})->size(), 1); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::OLD, {}, &*vertex_to)->size(), 1); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::NEW, {}, &*vertex_to)->size(), 1); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::OLD, {}, &*vertex_from)->size(), 0); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::NEW, {}, &*vertex_from)->size(), 0); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::OLD, {other_et})->size(), 0); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::NEW, {other_et})->size(), 0); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::OLD, {et, other_et})->size(), 1); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::NEW, {et, other_et})->size(), 1); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::OLD, {}, &*vertex_from)->size(), 1); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::NEW, {}, &*vertex_from)->size(), 1); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::OLD, {}, &*vertex_to)->size(), 0); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::NEW, {}, &*vertex_to)->size(), 0); - - ASSERT_FALSE(acc.Commit().HasError()); - } - - // Delete edge - { - auto acc = store.Access(); - auto vertex_from = acc.FindVertex(gid_from, memgraph::storage::View::NEW); - auto vertex_to = acc.FindVertex(gid_to, memgraph::storage::View::NEW); - ASSERT_TRUE(vertex_from); - ASSERT_TRUE(vertex_to); - - auto et = acc.NameToEdgeType("et5"); - - auto edge = vertex_from->OutEdges(memgraph::storage::View::NEW).GetValue()[0]; - - auto res = acc.DeleteEdge(&edge); - ASSERT_TRUE(res.HasValue()); - ASSERT_TRUE(res.GetValue()); - - // Check edges without filters - ASSERT_EQ(vertex_from->InEdges(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(*vertex_from->InDegree(memgraph::storage::View::OLD), 0); - ASSERT_EQ(vertex_from->InEdges(memgraph::storage::View::NEW)->size(), 0); - ASSERT_EQ(*vertex_from->InDegree(memgraph::storage::View::NEW), 0); - { - auto ret = vertex_from->OutEdges(memgraph::storage::View::OLD); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex_from->OutDegree(memgraph::storage::View::OLD), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et); - ASSERT_EQ(e.FromVertex(), *vertex_from); - ASSERT_EQ(e.ToVertex(), *vertex_to); - } - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::NEW)->size(), 0); - ASSERT_EQ(*vertex_from->OutDegree(memgraph::storage::View::NEW), 0); - { - auto ret = vertex_to->InEdges(memgraph::storage::View::OLD); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex_to->InDegree(memgraph::storage::View::OLD), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et); - ASSERT_EQ(e.FromVertex(), *vertex_from); - ASSERT_EQ(e.ToVertex(), *vertex_to); - } - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::NEW)->size(), 0); - ASSERT_EQ(*vertex_to->InDegree(memgraph::storage::View::NEW), 0); - ASSERT_EQ(vertex_to->OutEdges(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(*vertex_to->OutDegree(memgraph::storage::View::OLD), 0); - ASSERT_EQ(vertex_to->OutEdges(memgraph::storage::View::NEW)->size(), 0); - ASSERT_EQ(*vertex_to->OutDegree(memgraph::storage::View::NEW), 0); - - auto other_et = acc.NameToEdgeType("other"); - - // Check edges with filters - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::OLD, {other_et})->size(), 0); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::OLD, {et, other_et})->size(), 1); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::OLD, {}, &*vertex_to)->size(), 1); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::OLD, {}, &*vertex_from)->size(), 0); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::OLD, {other_et})->size(), 0); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::OLD, {et, other_et})->size(), 1); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::OLD, {}, &*vertex_from)->size(), 1); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::OLD, {}, &*vertex_to)->size(), 0); - - ASSERT_FALSE(acc.Commit().HasError()); - } - - // Check whether the edge exists - { - auto acc = store.Access(); - auto vertex_from = acc.FindVertex(gid_from, memgraph::storage::View::NEW); - auto vertex_to = acc.FindVertex(gid_to, memgraph::storage::View::NEW); - ASSERT_TRUE(vertex_from); - ASSERT_TRUE(vertex_to); - - // Check edges without filters - ASSERT_EQ(vertex_from->InEdges(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(*vertex_from->InDegree(memgraph::storage::View::OLD), 0); - ASSERT_EQ(vertex_from->InEdges(memgraph::storage::View::NEW)->size(), 0); - ASSERT_EQ(*vertex_from->InDegree(memgraph::storage::View::NEW), 0); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(*vertex_from->OutDegree(memgraph::storage::View::OLD), 0); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::NEW)->size(), 0); - ASSERT_EQ(*vertex_from->OutDegree(memgraph::storage::View::NEW), 0); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(*vertex_to->InDegree(memgraph::storage::View::OLD), 0); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::NEW)->size(), 0); - ASSERT_EQ(*vertex_to->InDegree(memgraph::storage::View::NEW), 0); - ASSERT_EQ(vertex_to->OutEdges(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(*vertex_to->OutDegree(memgraph::storage::View::OLD), 0); - ASSERT_EQ(vertex_to->OutEdges(memgraph::storage::View::NEW)->size(), 0); - ASSERT_EQ(*vertex_to->OutDegree(memgraph::storage::View::NEW), 0); - - ASSERT_FALSE(acc.Commit().HasError()); - } -} - -// NOLINTNEXTLINE(hicpp-special-member-functions) -TEST_P(StorageEdgeTest, EdgeDeleteFromSameCommit) { - memgraph::storage::Storage store({.items = {.properties_on_edges = GetParam()}}); - memgraph::storage::Gid gid_vertex = memgraph::storage::Gid::FromUint(std::numeric_limits::max()); - - // Create vertex - { - auto acc = store.Access(); - auto vertex = acc.CreateVertex(); - gid_vertex = vertex.Gid(); - ASSERT_FALSE(acc.Commit().HasError()); - } - - // Create edge - { - auto acc = store.Access(); - auto vertex = acc.FindVertex(gid_vertex, memgraph::storage::View::NEW); - ASSERT_TRUE(vertex); - - auto et = acc.NameToEdgeType("et5"); - - auto res = acc.CreateEdge(&*vertex, &*vertex, et); - ASSERT_TRUE(res.HasValue()); - auto edge = res.GetValue(); - ASSERT_EQ(edge.EdgeType(), et); - ASSERT_EQ(edge.FromVertex(), *vertex); - ASSERT_EQ(edge.ToVertex(), *vertex); - - // Check edges without filters - ASSERT_EQ(vertex->InEdges(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(*vertex->InDegree(memgraph::storage::View::OLD), 0); - { - auto ret = vertex->InEdges(memgraph::storage::View::NEW); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex->InDegree(memgraph::storage::View::NEW), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et); - ASSERT_EQ(e.FromVertex(), *vertex); - ASSERT_EQ(e.ToVertex(), *vertex); - } - ASSERT_EQ(vertex->OutEdges(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(*vertex->OutDegree(memgraph::storage::View::OLD), 0); - { - auto ret = vertex->OutEdges(memgraph::storage::View::NEW); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex->OutDegree(memgraph::storage::View::NEW), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et); - ASSERT_EQ(e.FromVertex(), *vertex); - ASSERT_EQ(e.ToVertex(), *vertex); - } - - auto other_et = acc.NameToEdgeType("other"); - - // Check edges with filters - ASSERT_EQ(vertex->OutEdges(memgraph::storage::View::NEW, {other_et})->size(), 0); - ASSERT_EQ(vertex->OutEdges(memgraph::storage::View::NEW, {et, other_et})->size(), 1); - ASSERT_EQ(vertex->OutEdges(memgraph::storage::View::NEW, {}, &*vertex)->size(), 1); - ASSERT_EQ(vertex->OutEdges(memgraph::storage::View::NEW, {other_et}, &*vertex)->size(), 0); - ASSERT_EQ(vertex->InEdges(memgraph::storage::View::NEW, {other_et})->size(), 0); - ASSERT_EQ(vertex->InEdges(memgraph::storage::View::NEW, {et, other_et})->size(), 1); - ASSERT_EQ(vertex->InEdges(memgraph::storage::View::NEW, {}, &*vertex)->size(), 1); - ASSERT_EQ(vertex->InEdges(memgraph::storage::View::NEW, {other_et}, &*vertex)->size(), 0); - - ASSERT_FALSE(acc.Commit().HasError()); - } - - // Check whether the edge exists - { - auto acc = store.Access(); - auto vertex = acc.FindVertex(gid_vertex, memgraph::storage::View::NEW); - ASSERT_TRUE(vertex); - - auto et = acc.NameToEdgeType("et5"); - - // Check edges without filters - { - auto ret = vertex->InEdges(memgraph::storage::View::OLD); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex->InDegree(memgraph::storage::View::OLD), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et); - ASSERT_EQ(e.FromVertex(), *vertex); - ASSERT_EQ(e.ToVertex(), *vertex); - } - { - auto ret = vertex->InEdges(memgraph::storage::View::NEW); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex->InDegree(memgraph::storage::View::NEW), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et); - ASSERT_EQ(e.FromVertex(), *vertex); - ASSERT_EQ(e.ToVertex(), *vertex); - } - { - auto ret = vertex->OutEdges(memgraph::storage::View::OLD); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex->OutDegree(memgraph::storage::View::OLD), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et); - ASSERT_EQ(e.FromVertex(), *vertex); - ASSERT_EQ(e.ToVertex(), *vertex); - } - { - auto ret = vertex->OutEdges(memgraph::storage::View::NEW); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex->OutDegree(memgraph::storage::View::NEW), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et); - ASSERT_EQ(e.FromVertex(), *vertex); - ASSERT_EQ(e.ToVertex(), *vertex); - } - - auto other_et = acc.NameToEdgeType("other"); - - // Check edges with filters - ASSERT_EQ(vertex->InEdges(memgraph::storage::View::OLD, {other_et})->size(), 0); - ASSERT_EQ(vertex->InEdges(memgraph::storage::View::NEW, {other_et})->size(), 0); - ASSERT_EQ(vertex->InEdges(memgraph::storage::View::OLD, {et, other_et})->size(), 1); - ASSERT_EQ(vertex->InEdges(memgraph::storage::View::NEW, {et, other_et})->size(), 1); - ASSERT_EQ(vertex->InEdges(memgraph::storage::View::OLD, {}, &*vertex)->size(), 1); - ASSERT_EQ(vertex->InEdges(memgraph::storage::View::NEW, {}, &*vertex)->size(), 1); - ASSERT_EQ(vertex->InEdges(memgraph::storage::View::OLD, {other_et}, &*vertex)->size(), 0); - ASSERT_EQ(vertex->InEdges(memgraph::storage::View::NEW, {other_et}, &*vertex)->size(), 0); - ASSERT_EQ(vertex->OutEdges(memgraph::storage::View::OLD, {other_et})->size(), 0); - ASSERT_EQ(vertex->OutEdges(memgraph::storage::View::NEW, {other_et})->size(), 0); - ASSERT_EQ(vertex->OutEdges(memgraph::storage::View::OLD, {et, other_et})->size(), 1); - ASSERT_EQ(vertex->OutEdges(memgraph::storage::View::NEW, {et, other_et})->size(), 1); - ASSERT_EQ(vertex->OutEdges(memgraph::storage::View::OLD, {}, &*vertex)->size(), 1); - ASSERT_EQ(vertex->OutEdges(memgraph::storage::View::NEW, {}, &*vertex)->size(), 1); - ASSERT_EQ(vertex->OutEdges(memgraph::storage::View::OLD, {other_et}, &*vertex)->size(), 0); - ASSERT_EQ(vertex->OutEdges(memgraph::storage::View::NEW, {other_et}, &*vertex)->size(), 0); - - ASSERT_FALSE(acc.Commit().HasError()); - } - - // Delete edge - { - auto acc = store.Access(); - auto vertex = acc.FindVertex(gid_vertex, memgraph::storage::View::NEW); - ASSERT_TRUE(vertex); - - auto et = acc.NameToEdgeType("et5"); - - auto edge = vertex->OutEdges(memgraph::storage::View::NEW).GetValue()[0]; - - auto res = acc.DeleteEdge(&edge); - ASSERT_TRUE(res.HasValue()); - ASSERT_TRUE(res.GetValue()); - - // Check edges without filters - { - auto ret = vertex->InEdges(memgraph::storage::View::OLD); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex->InDegree(memgraph::storage::View::OLD), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et); - ASSERT_EQ(e.FromVertex(), *vertex); - ASSERT_EQ(e.ToVertex(), *vertex); - } - ASSERT_EQ(vertex->InEdges(memgraph::storage::View::NEW)->size(), 0); - ASSERT_EQ(*vertex->InDegree(memgraph::storage::View::NEW), 0); - { - auto ret = vertex->OutEdges(memgraph::storage::View::OLD); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex->OutDegree(memgraph::storage::View::OLD), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et); - ASSERT_EQ(e.FromVertex(), *vertex); - ASSERT_EQ(e.ToVertex(), *vertex); - } - ASSERT_EQ(vertex->OutEdges(memgraph::storage::View::NEW)->size(), 0); - ASSERT_EQ(*vertex->OutDegree(memgraph::storage::View::NEW), 0); - - auto other_et = acc.NameToEdgeType("other"); - - // Check edges with filters - ASSERT_EQ(vertex->InEdges(memgraph::storage::View::OLD, {other_et})->size(), 0); - ASSERT_EQ(vertex->InEdges(memgraph::storage::View::OLD, {et, other_et})->size(), 1); - ASSERT_EQ(vertex->InEdges(memgraph::storage::View::OLD, {}, &*vertex)->size(), 1); - ASSERT_EQ(vertex->InEdges(memgraph::storage::View::OLD, {other_et}, &*vertex)->size(), 0); - ASSERT_EQ(vertex->OutEdges(memgraph::storage::View::OLD, {other_et})->size(), 0); - ASSERT_EQ(vertex->OutEdges(memgraph::storage::View::OLD, {et, other_et})->size(), 1); - ASSERT_EQ(vertex->OutEdges(memgraph::storage::View::OLD, {}, &*vertex)->size(), 1); - ASSERT_EQ(vertex->OutEdges(memgraph::storage::View::OLD, {other_et}, &*vertex)->size(), 0); - - ASSERT_FALSE(acc.Commit().HasError()); - } - - // Check whether the edge exists - { - auto acc = store.Access(); - auto vertex = acc.FindVertex(gid_vertex, memgraph::storage::View::NEW); - ASSERT_TRUE(vertex); - - // Check edges without filters - ASSERT_EQ(vertex->InEdges(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(*vertex->InDegree(memgraph::storage::View::OLD), 0); - ASSERT_EQ(vertex->InEdges(memgraph::storage::View::NEW)->size(), 0); - ASSERT_EQ(*vertex->InDegree(memgraph::storage::View::NEW), 0); - ASSERT_EQ(vertex->OutEdges(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(*vertex->OutDegree(memgraph::storage::View::OLD), 0); - ASSERT_EQ(vertex->OutEdges(memgraph::storage::View::NEW)->size(), 0); - ASSERT_EQ(*vertex->OutDegree(memgraph::storage::View::NEW), 0); - - ASSERT_FALSE(acc.Commit().HasError()); - } -} - -// NOLINTNEXTLINE(hicpp-special-member-functions) -TEST_P(StorageEdgeTest, EdgeDeleteFromSmallerAbort) { - memgraph::storage::Storage store({.items = {.properties_on_edges = GetParam()}}); - memgraph::storage::Gid gid_from = memgraph::storage::Gid::FromUint(std::numeric_limits::max()); - memgraph::storage::Gid gid_to = memgraph::storage::Gid::FromUint(std::numeric_limits::max()); - - // Create vertices - { - auto acc = store.Access(); - auto vertex_from = acc.CreateVertex(); - auto vertex_to = acc.CreateVertex(); - gid_from = vertex_from.Gid(); - gid_to = vertex_to.Gid(); - ASSERT_FALSE(acc.Commit().HasError()); - } - - // Create edge - { - auto acc = store.Access(); - auto vertex_from = acc.FindVertex(gid_from, memgraph::storage::View::NEW); - auto vertex_to = acc.FindVertex(gid_to, memgraph::storage::View::NEW); - ASSERT_TRUE(vertex_from); - ASSERT_TRUE(vertex_to); - - auto et = acc.NameToEdgeType("et5"); - - auto res = acc.CreateEdge(&*vertex_from, &*vertex_to, et); - ASSERT_TRUE(res.HasValue()); - auto edge = res.GetValue(); - ASSERT_EQ(edge.EdgeType(), et); - ASSERT_EQ(edge.FromVertex(), *vertex_from); - ASSERT_EQ(edge.ToVertex(), *vertex_to); - - // Check edges without filters - ASSERT_EQ(vertex_from->InEdges(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(*vertex_from->InDegree(memgraph::storage::View::OLD), 0); - ASSERT_EQ(vertex_from->InEdges(memgraph::storage::View::NEW)->size(), 0); - ASSERT_EQ(*vertex_from->InDegree(memgraph::storage::View::NEW), 0); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(*vertex_from->OutDegree(memgraph::storage::View::OLD), 0); - { - auto ret = vertex_from->OutEdges(memgraph::storage::View::NEW); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex_from->OutDegree(memgraph::storage::View::NEW), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et); - ASSERT_EQ(e.FromVertex(), *vertex_from); - ASSERT_EQ(e.ToVertex(), *vertex_to); - } - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(*vertex_to->InDegree(memgraph::storage::View::OLD), 0); - { - auto ret = vertex_to->InEdges(memgraph::storage::View::NEW); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex_to->InDegree(memgraph::storage::View::NEW), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et); - ASSERT_EQ(e.FromVertex(), *vertex_from); - ASSERT_EQ(e.ToVertex(), *vertex_to); - } - ASSERT_EQ(vertex_to->OutEdges(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(*vertex_to->OutDegree(memgraph::storage::View::OLD), 0); - ASSERT_EQ(vertex_to->OutEdges(memgraph::storage::View::NEW)->size(), 0); - ASSERT_EQ(*vertex_to->OutDegree(memgraph::storage::View::NEW), 0); - - auto other_et = acc.NameToEdgeType("other"); - - // Check edges with filters - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::NEW, {other_et})->size(), 0); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::NEW, {et, other_et})->size(), 1); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::NEW, {}, &*vertex_to)->size(), 1); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::NEW, {}, &*vertex_from)->size(), 0); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::NEW, {other_et})->size(), 0); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::NEW, {et, other_et})->size(), 1); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::NEW, {}, &*vertex_from)->size(), 1); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::NEW, {}, &*vertex_to)->size(), 0); - - ASSERT_FALSE(acc.Commit().HasError()); - } - - // Check whether the edge exists - { - auto acc = store.Access(); - auto vertex_from = acc.FindVertex(gid_from, memgraph::storage::View::NEW); - auto vertex_to = acc.FindVertex(gid_to, memgraph::storage::View::NEW); - ASSERT_TRUE(vertex_from); - ASSERT_TRUE(vertex_to); - - auto et = acc.NameToEdgeType("et5"); - - // Check edges without filters - ASSERT_EQ(vertex_from->InEdges(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(*vertex_from->InDegree(memgraph::storage::View::OLD), 0); - ASSERT_EQ(vertex_from->InEdges(memgraph::storage::View::NEW)->size(), 0); - ASSERT_EQ(*vertex_from->InDegree(memgraph::storage::View::NEW), 0); - { - auto ret = vertex_from->OutEdges(memgraph::storage::View::OLD); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex_from->OutDegree(memgraph::storage::View::OLD), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et); - ASSERT_EQ(e.FromVertex(), *vertex_from); - ASSERT_EQ(e.ToVertex(), *vertex_to); - } - { - auto ret = vertex_from->OutEdges(memgraph::storage::View::NEW); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex_from->OutDegree(memgraph::storage::View::NEW), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et); - ASSERT_EQ(e.FromVertex(), *vertex_from); - ASSERT_EQ(e.ToVertex(), *vertex_to); - } - { - auto ret = vertex_to->InEdges(memgraph::storage::View::OLD); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex_to->InDegree(memgraph::storage::View::OLD), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et); - ASSERT_EQ(e.FromVertex(), *vertex_from); - ASSERT_EQ(e.ToVertex(), *vertex_to); - } - { - auto ret = vertex_to->InEdges(memgraph::storage::View::NEW); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex_to->InDegree(memgraph::storage::View::NEW), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et); - ASSERT_EQ(e.FromVertex(), *vertex_from); - ASSERT_EQ(e.ToVertex(), *vertex_to); - } - ASSERT_EQ(vertex_to->OutEdges(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(*vertex_to->OutDegree(memgraph::storage::View::OLD), 0); - ASSERT_EQ(vertex_to->OutEdges(memgraph::storage::View::NEW)->size(), 0); - ASSERT_EQ(*vertex_to->OutDegree(memgraph::storage::View::NEW), 0); - - auto other_et = acc.NameToEdgeType("other"); - - // Check edges with filters - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::OLD, {other_et})->size(), 0); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::NEW, {other_et})->size(), 0); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::OLD, {et, other_et})->size(), 1); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::NEW, {et, other_et})->size(), 1); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::OLD, {}, &*vertex_to)->size(), 1); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::NEW, {}, &*vertex_to)->size(), 1); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::OLD, {}, &*vertex_from)->size(), 0); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::NEW, {}, &*vertex_from)->size(), 0); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::OLD, {other_et})->size(), 0); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::NEW, {other_et})->size(), 0); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::OLD, {et, other_et})->size(), 1); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::NEW, {et, other_et})->size(), 1); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::OLD, {}, &*vertex_from)->size(), 1); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::NEW, {}, &*vertex_from)->size(), 1); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::OLD, {}, &*vertex_to)->size(), 0); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::NEW, {}, &*vertex_to)->size(), 0); - - ASSERT_FALSE(acc.Commit().HasError()); - } - - // Delete the edge, but abort the transaction - { - auto acc = store.Access(); - auto vertex_from = acc.FindVertex(gid_from, memgraph::storage::View::NEW); - auto vertex_to = acc.FindVertex(gid_to, memgraph::storage::View::NEW); - ASSERT_TRUE(vertex_from); - ASSERT_TRUE(vertex_to); - - auto et = acc.NameToEdgeType("et5"); - - auto edge = vertex_from->OutEdges(memgraph::storage::View::NEW).GetValue()[0]; - - auto res = acc.DeleteEdge(&edge); - ASSERT_TRUE(res.HasValue()); - ASSERT_TRUE(res.GetValue()); - - // Check edges without filters - ASSERT_EQ(vertex_from->InEdges(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(*vertex_from->InDegree(memgraph::storage::View::OLD), 0); - ASSERT_EQ(vertex_from->InEdges(memgraph::storage::View::NEW)->size(), 0); - ASSERT_EQ(*vertex_from->InDegree(memgraph::storage::View::NEW), 0); - { - auto ret = vertex_from->OutEdges(memgraph::storage::View::OLD); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex_from->OutDegree(memgraph::storage::View::OLD), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et); - ASSERT_EQ(e.FromVertex(), *vertex_from); - ASSERT_EQ(e.ToVertex(), *vertex_to); - } - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::NEW)->size(), 0); - ASSERT_EQ(*vertex_from->OutDegree(memgraph::storage::View::NEW), 0); - { - auto ret = vertex_to->InEdges(memgraph::storage::View::OLD); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex_to->InDegree(memgraph::storage::View::OLD), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et); - ASSERT_EQ(e.FromVertex(), *vertex_from); - ASSERT_EQ(e.ToVertex(), *vertex_to); - } - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::NEW)->size(), 0); - ASSERT_EQ(*vertex_to->InDegree(memgraph::storage::View::NEW), 0); - ASSERT_EQ(vertex_to->OutEdges(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(*vertex_to->OutDegree(memgraph::storage::View::OLD), 0); - ASSERT_EQ(vertex_to->OutEdges(memgraph::storage::View::NEW)->size(), 0); - ASSERT_EQ(*vertex_to->OutDegree(memgraph::storage::View::NEW), 0); - - auto other_et = acc.NameToEdgeType("other"); - - // Check edges with filters - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::OLD, {other_et})->size(), 0); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::OLD, {et, other_et})->size(), 1); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::OLD, {}, &*vertex_to)->size(), 1); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::OLD, {}, &*vertex_from)->size(), 0); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::OLD, {other_et})->size(), 0); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::OLD, {et, other_et})->size(), 1); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::OLD, {}, &*vertex_from)->size(), 1); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::OLD, {}, &*vertex_to)->size(), 0); - - acc.Abort(); - } - - // Check whether the edge exists - { - auto acc = store.Access(); - auto vertex_from = acc.FindVertex(gid_from, memgraph::storage::View::NEW); - auto vertex_to = acc.FindVertex(gid_to, memgraph::storage::View::NEW); - ASSERT_TRUE(vertex_from); - ASSERT_TRUE(vertex_to); - - auto et = acc.NameToEdgeType("et5"); - - // Check edges without filters - ASSERT_EQ(vertex_from->InEdges(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(*vertex_from->InDegree(memgraph::storage::View::OLD), 0); - ASSERT_EQ(vertex_from->InEdges(memgraph::storage::View::NEW)->size(), 0); - ASSERT_EQ(*vertex_from->InDegree(memgraph::storage::View::NEW), 0); - { - auto ret = vertex_from->OutEdges(memgraph::storage::View::OLD); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex_from->OutDegree(memgraph::storage::View::OLD), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et); - ASSERT_EQ(e.FromVertex(), *vertex_from); - ASSERT_EQ(e.ToVertex(), *vertex_to); - } - { - auto ret = vertex_from->OutEdges(memgraph::storage::View::NEW); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex_from->OutDegree(memgraph::storage::View::NEW), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et); - ASSERT_EQ(e.FromVertex(), *vertex_from); - ASSERT_EQ(e.ToVertex(), *vertex_to); - } - { - auto ret = vertex_to->InEdges(memgraph::storage::View::OLD); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex_to->InDegree(memgraph::storage::View::OLD), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et); - ASSERT_EQ(e.FromVertex(), *vertex_from); - ASSERT_EQ(e.ToVertex(), *vertex_to); - } - { - auto ret = vertex_to->InEdges(memgraph::storage::View::NEW); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex_to->InDegree(memgraph::storage::View::NEW), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et); - ASSERT_EQ(e.FromVertex(), *vertex_from); - ASSERT_EQ(e.ToVertex(), *vertex_to); - } - ASSERT_EQ(vertex_to->OutEdges(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(*vertex_to->OutDegree(memgraph::storage::View::OLD), 0); - ASSERT_EQ(vertex_to->OutEdges(memgraph::storage::View::NEW)->size(), 0); - ASSERT_EQ(*vertex_to->OutDegree(memgraph::storage::View::NEW), 0); - - auto other_et = acc.NameToEdgeType("other"); - - // Check edges with filters - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::OLD, {other_et})->size(), 0); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::NEW, {other_et})->size(), 0); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::OLD, {et, other_et})->size(), 1); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::NEW, {et, other_et})->size(), 1); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::OLD, {}, &*vertex_to)->size(), 1); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::NEW, {}, &*vertex_to)->size(), 1); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::OLD, {}, &*vertex_from)->size(), 0); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::NEW, {}, &*vertex_from)->size(), 0); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::OLD, {other_et})->size(), 0); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::NEW, {other_et})->size(), 0); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::OLD, {et, other_et})->size(), 1); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::NEW, {et, other_et})->size(), 1); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::OLD, {}, &*vertex_from)->size(), 1); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::NEW, {}, &*vertex_from)->size(), 1); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::OLD, {}, &*vertex_to)->size(), 0); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::NEW, {}, &*vertex_to)->size(), 0); - - ASSERT_FALSE(acc.Commit().HasError()); - } - - // Delete the edge - { - auto acc = store.Access(); - auto vertex_from = acc.FindVertex(gid_from, memgraph::storage::View::NEW); - auto vertex_to = acc.FindVertex(gid_to, memgraph::storage::View::NEW); - ASSERT_TRUE(vertex_from); - ASSERT_TRUE(vertex_to); - - auto et = acc.NameToEdgeType("et5"); - - auto edge = vertex_from->OutEdges(memgraph::storage::View::NEW).GetValue()[0]; - - auto res = acc.DeleteEdge(&edge); - ASSERT_TRUE(res.HasValue()); - ASSERT_TRUE(res.GetValue()); - - // Check edges without filters - ASSERT_EQ(vertex_from->InEdges(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(*vertex_from->InDegree(memgraph::storage::View::OLD), 0); - ASSERT_EQ(vertex_from->InEdges(memgraph::storage::View::NEW)->size(), 0); - ASSERT_EQ(*vertex_from->InDegree(memgraph::storage::View::NEW), 0); - { - auto ret = vertex_from->OutEdges(memgraph::storage::View::OLD); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex_from->OutDegree(memgraph::storage::View::OLD), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et); - ASSERT_EQ(e.FromVertex(), *vertex_from); - ASSERT_EQ(e.ToVertex(), *vertex_to); - } - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::NEW)->size(), 0); - ASSERT_EQ(*vertex_from->OutDegree(memgraph::storage::View::NEW), 0); - { - auto ret = vertex_to->InEdges(memgraph::storage::View::OLD); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex_to->InDegree(memgraph::storage::View::OLD), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et); - ASSERT_EQ(e.FromVertex(), *vertex_from); - ASSERT_EQ(e.ToVertex(), *vertex_to); - } - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::NEW)->size(), 0); - ASSERT_EQ(*vertex_to->InDegree(memgraph::storage::View::NEW), 0); - ASSERT_EQ(vertex_to->OutEdges(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(*vertex_to->OutDegree(memgraph::storage::View::OLD), 0); - ASSERT_EQ(vertex_to->OutEdges(memgraph::storage::View::NEW)->size(), 0); - ASSERT_EQ(*vertex_to->OutDegree(memgraph::storage::View::NEW), 0); - - auto other_et = acc.NameToEdgeType("other"); - - // Check edges with filters - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::OLD, {other_et})->size(), 0); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::OLD, {et, other_et})->size(), 1); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::OLD, {}, &*vertex_to)->size(), 1); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::OLD, {}, &*vertex_from)->size(), 0); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::OLD, {other_et})->size(), 0); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::OLD, {et, other_et})->size(), 1); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::OLD, {}, &*vertex_from)->size(), 1); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::OLD, {}, &*vertex_to)->size(), 0); - - ASSERT_FALSE(acc.Commit().HasError()); - } - - // Check whether the edge exists - { - auto acc = store.Access(); - auto vertex_from = acc.FindVertex(gid_from, memgraph::storage::View::NEW); - auto vertex_to = acc.FindVertex(gid_to, memgraph::storage::View::NEW); - ASSERT_TRUE(vertex_from); - ASSERT_TRUE(vertex_to); - - // Check edges without filters - ASSERT_EQ(vertex_from->InEdges(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(*vertex_from->InDegree(memgraph::storage::View::OLD), 0); - ASSERT_EQ(vertex_from->InEdges(memgraph::storage::View::NEW)->size(), 0); - ASSERT_EQ(*vertex_from->InDegree(memgraph::storage::View::NEW), 0); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(*vertex_from->OutDegree(memgraph::storage::View::OLD), 0); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::NEW)->size(), 0); - ASSERT_EQ(*vertex_from->OutDegree(memgraph::storage::View::NEW), 0); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(*vertex_to->InDegree(memgraph::storage::View::OLD), 0); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::NEW)->size(), 0); - ASSERT_EQ(*vertex_to->InDegree(memgraph::storage::View::NEW), 0); - ASSERT_EQ(vertex_to->OutEdges(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(*vertex_to->OutDegree(memgraph::storage::View::OLD), 0); - ASSERT_EQ(vertex_to->OutEdges(memgraph::storage::View::NEW)->size(), 0); - ASSERT_EQ(*vertex_to->OutDegree(memgraph::storage::View::NEW), 0); - - ASSERT_FALSE(acc.Commit().HasError()); - } -} - -// NOLINTNEXTLINE(hicpp-special-member-functions) -TEST_P(StorageEdgeTest, EdgeDeleteFromLargerAbort) { - memgraph::storage::Storage store({.items = {.properties_on_edges = GetParam()}}); - memgraph::storage::Gid gid_from = memgraph::storage::Gid::FromUint(std::numeric_limits::max()); - memgraph::storage::Gid gid_to = memgraph::storage::Gid::FromUint(std::numeric_limits::max()); - - // Create vertices - { - auto acc = store.Access(); - auto vertex_from = acc.CreateVertex(); - auto vertex_to = acc.CreateVertex(); - gid_from = vertex_from.Gid(); - gid_to = vertex_to.Gid(); - ASSERT_FALSE(acc.Commit().HasError()); - } - - // Create edge - { - auto acc = store.Access(); - auto vertex_to = acc.FindVertex(gid_to, memgraph::storage::View::NEW); - auto vertex_from = acc.FindVertex(gid_from, memgraph::storage::View::NEW); - ASSERT_TRUE(vertex_from); - ASSERT_TRUE(vertex_to); - - auto et = acc.NameToEdgeType("et5"); - - auto res = acc.CreateEdge(&*vertex_from, &*vertex_to, et); - ASSERT_TRUE(res.HasValue()); - auto edge = res.GetValue(); - ASSERT_EQ(edge.EdgeType(), et); - ASSERT_EQ(edge.FromVertex(), *vertex_from); - ASSERT_EQ(edge.ToVertex(), *vertex_to); - - // Check edges without filters - ASSERT_EQ(vertex_from->InEdges(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(*vertex_from->InDegree(memgraph::storage::View::OLD), 0); - ASSERT_EQ(vertex_from->InEdges(memgraph::storage::View::NEW)->size(), 0); - ASSERT_EQ(*vertex_from->InDegree(memgraph::storage::View::NEW), 0); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(*vertex_from->OutDegree(memgraph::storage::View::OLD), 0); - { - auto ret = vertex_from->OutEdges(memgraph::storage::View::NEW); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex_from->OutDegree(memgraph::storage::View::NEW), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et); - ASSERT_EQ(e.FromVertex(), *vertex_from); - ASSERT_EQ(e.ToVertex(), *vertex_to); - } - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(*vertex_to->InDegree(memgraph::storage::View::OLD), 0); - { - auto ret = vertex_to->InEdges(memgraph::storage::View::NEW); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex_to->InDegree(memgraph::storage::View::NEW), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et); - ASSERT_EQ(e.FromVertex(), *vertex_from); - ASSERT_EQ(e.ToVertex(), *vertex_to); - } - ASSERT_EQ(vertex_to->OutEdges(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(*vertex_to->OutDegree(memgraph::storage::View::OLD), 0); - ASSERT_EQ(vertex_to->OutEdges(memgraph::storage::View::NEW)->size(), 0); - ASSERT_EQ(*vertex_to->OutDegree(memgraph::storage::View::NEW), 0); - - auto other_et = acc.NameToEdgeType("other"); - - // Check edges with filters - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::NEW, {other_et})->size(), 0); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::NEW, {et, other_et})->size(), 1); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::NEW, {}, &*vertex_to)->size(), 1); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::NEW, {}, &*vertex_from)->size(), 0); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::NEW, {other_et})->size(), 0); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::NEW, {et, other_et})->size(), 1); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::NEW, {}, &*vertex_from)->size(), 1); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::NEW, {}, &*vertex_to)->size(), 0); - - ASSERT_FALSE(acc.Commit().HasError()); - } - - // Check whether the edge exists - { - auto acc = store.Access(); - auto vertex_from = acc.FindVertex(gid_from, memgraph::storage::View::NEW); - auto vertex_to = acc.FindVertex(gid_to, memgraph::storage::View::NEW); - ASSERT_TRUE(vertex_from); - ASSERT_TRUE(vertex_to); - - auto et = acc.NameToEdgeType("et5"); - - // Check edges without filters - ASSERT_EQ(vertex_from->InEdges(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(*vertex_from->InDegree(memgraph::storage::View::OLD), 0); - ASSERT_EQ(vertex_from->InEdges(memgraph::storage::View::NEW)->size(), 0); - ASSERT_EQ(*vertex_from->InDegree(memgraph::storage::View::NEW), 0); - { - auto ret = vertex_from->OutEdges(memgraph::storage::View::OLD); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex_from->OutDegree(memgraph::storage::View::OLD), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et); - ASSERT_EQ(e.FromVertex(), *vertex_from); - ASSERT_EQ(e.ToVertex(), *vertex_to); - } - { - auto ret = vertex_from->OutEdges(memgraph::storage::View::NEW); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex_from->OutDegree(memgraph::storage::View::NEW), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et); - ASSERT_EQ(e.FromVertex(), *vertex_from); - ASSERT_EQ(e.ToVertex(), *vertex_to); - } - { - auto ret = vertex_to->InEdges(memgraph::storage::View::OLD); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex_to->InDegree(memgraph::storage::View::OLD), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et); - ASSERT_EQ(e.FromVertex(), *vertex_from); - ASSERT_EQ(e.ToVertex(), *vertex_to); - } - { - auto ret = vertex_to->InEdges(memgraph::storage::View::NEW); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex_to->InDegree(memgraph::storage::View::NEW), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et); - ASSERT_EQ(e.FromVertex(), *vertex_from); - ASSERT_EQ(e.ToVertex(), *vertex_to); - } - ASSERT_EQ(vertex_to->OutEdges(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(*vertex_to->OutDegree(memgraph::storage::View::OLD), 0); - ASSERT_EQ(vertex_to->OutEdges(memgraph::storage::View::NEW)->size(), 0); - ASSERT_EQ(*vertex_to->OutDegree(memgraph::storage::View::NEW), 0); - - auto other_et = acc.NameToEdgeType("other"); - - // Check edges with filters - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::OLD, {other_et})->size(), 0); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::NEW, {other_et})->size(), 0); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::OLD, {et, other_et})->size(), 1); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::NEW, {et, other_et})->size(), 1); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::OLD, {}, &*vertex_to)->size(), 1); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::NEW, {}, &*vertex_to)->size(), 1); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::OLD, {}, &*vertex_from)->size(), 0); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::NEW, {}, &*vertex_from)->size(), 0); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::OLD, {other_et})->size(), 0); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::NEW, {other_et})->size(), 0); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::OLD, {et, other_et})->size(), 1); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::NEW, {et, other_et})->size(), 1); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::OLD, {}, &*vertex_from)->size(), 1); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::NEW, {}, &*vertex_from)->size(), 1); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::OLD, {}, &*vertex_to)->size(), 0); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::NEW, {}, &*vertex_to)->size(), 0); - - ASSERT_FALSE(acc.Commit().HasError()); - } - - // Delete the edge, but abort the transaction - { - auto acc = store.Access(); - auto vertex_from = acc.FindVertex(gid_from, memgraph::storage::View::NEW); - auto vertex_to = acc.FindVertex(gid_to, memgraph::storage::View::NEW); - ASSERT_TRUE(vertex_from); - ASSERT_TRUE(vertex_to); - - auto et = acc.NameToEdgeType("et5"); - - auto edge = vertex_from->OutEdges(memgraph::storage::View::NEW).GetValue()[0]; - - auto res = acc.DeleteEdge(&edge); - ASSERT_TRUE(res.HasValue()); - ASSERT_TRUE(res.GetValue()); - - // Check edges without filters - ASSERT_EQ(vertex_from->InEdges(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(*vertex_from->InDegree(memgraph::storage::View::OLD), 0); - ASSERT_EQ(vertex_from->InEdges(memgraph::storage::View::NEW)->size(), 0); - ASSERT_EQ(*vertex_from->InDegree(memgraph::storage::View::NEW), 0); - { - auto ret = vertex_from->OutEdges(memgraph::storage::View::OLD); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex_from->OutDegree(memgraph::storage::View::OLD), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et); - ASSERT_EQ(e.FromVertex(), *vertex_from); - ASSERT_EQ(e.ToVertex(), *vertex_to); - } - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::NEW)->size(), 0); - ASSERT_EQ(*vertex_from->OutDegree(memgraph::storage::View::NEW), 0); - { - auto ret = vertex_to->InEdges(memgraph::storage::View::OLD); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex_to->InDegree(memgraph::storage::View::OLD), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et); - ASSERT_EQ(e.FromVertex(), *vertex_from); - ASSERT_EQ(e.ToVertex(), *vertex_to); - } - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::NEW)->size(), 0); - ASSERT_EQ(*vertex_to->InDegree(memgraph::storage::View::NEW), 0); - ASSERT_EQ(vertex_to->OutEdges(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(*vertex_to->OutDegree(memgraph::storage::View::OLD), 0); - ASSERT_EQ(vertex_to->OutEdges(memgraph::storage::View::NEW)->size(), 0); - ASSERT_EQ(*vertex_to->OutDegree(memgraph::storage::View::NEW), 0); - - auto other_et = acc.NameToEdgeType("other"); - - // Check edges with filters - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::OLD, {other_et})->size(), 0); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::OLD, {et, other_et})->size(), 1); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::OLD, {}, &*vertex_to)->size(), 1); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::OLD, {}, &*vertex_from)->size(), 0); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::OLD, {other_et})->size(), 0); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::OLD, {et, other_et})->size(), 1); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::OLD, {}, &*vertex_from)->size(), 1); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::OLD, {}, &*vertex_to)->size(), 0); - - acc.Abort(); - } - - // Check whether the edge exists - { - auto acc = store.Access(); - auto vertex_from = acc.FindVertex(gid_from, memgraph::storage::View::NEW); - auto vertex_to = acc.FindVertex(gid_to, memgraph::storage::View::NEW); - ASSERT_TRUE(vertex_from); - ASSERT_TRUE(vertex_to); - - auto et = acc.NameToEdgeType("et5"); - - // Check edges without filters - ASSERT_EQ(vertex_from->InEdges(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(*vertex_from->InDegree(memgraph::storage::View::OLD), 0); - ASSERT_EQ(vertex_from->InEdges(memgraph::storage::View::NEW)->size(), 0); - ASSERT_EQ(*vertex_from->InDegree(memgraph::storage::View::NEW), 0); - { - auto ret = vertex_from->OutEdges(memgraph::storage::View::OLD); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex_from->OutDegree(memgraph::storage::View::OLD), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et); - ASSERT_EQ(e.FromVertex(), *vertex_from); - ASSERT_EQ(e.ToVertex(), *vertex_to); - } - { - auto ret = vertex_from->OutEdges(memgraph::storage::View::NEW); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex_from->OutDegree(memgraph::storage::View::NEW), 1); - ASSERT_EQ(*vertex_from->OutDegree(memgraph::storage::View::NEW), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et); - ASSERT_EQ(e.FromVertex(), *vertex_from); - ASSERT_EQ(e.ToVertex(), *vertex_to); - } - { - auto ret = vertex_to->InEdges(memgraph::storage::View::OLD); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex_to->InDegree(memgraph::storage::View::OLD), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et); - ASSERT_EQ(e.FromVertex(), *vertex_from); - ASSERT_EQ(e.ToVertex(), *vertex_to); - } - { - auto ret = vertex_to->InEdges(memgraph::storage::View::NEW); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex_to->InDegree(memgraph::storage::View::NEW), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et); - ASSERT_EQ(e.FromVertex(), *vertex_from); - ASSERT_EQ(e.ToVertex(), *vertex_to); - } - ASSERT_EQ(vertex_to->OutEdges(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(*vertex_to->OutDegree(memgraph::storage::View::OLD), 0); - ASSERT_EQ(vertex_to->OutEdges(memgraph::storage::View::NEW)->size(), 0); - ASSERT_EQ(*vertex_to->OutDegree(memgraph::storage::View::NEW), 0); - - auto other_et = acc.NameToEdgeType("other"); - - // Check edges with filters - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::OLD, {other_et})->size(), 0); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::NEW, {other_et})->size(), 0); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::OLD, {et, other_et})->size(), 1); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::NEW, {et, other_et})->size(), 1); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::OLD, {}, &*vertex_to)->size(), 1); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::NEW, {}, &*vertex_to)->size(), 1); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::OLD, {}, &*vertex_from)->size(), 0); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::NEW, {}, &*vertex_from)->size(), 0); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::OLD, {other_et})->size(), 0); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::NEW, {other_et})->size(), 0); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::OLD, {et, other_et})->size(), 1); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::NEW, {et, other_et})->size(), 1); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::OLD, {}, &*vertex_from)->size(), 1); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::NEW, {}, &*vertex_from)->size(), 1); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::OLD, {}, &*vertex_to)->size(), 0); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::NEW, {}, &*vertex_to)->size(), 0); - - ASSERT_FALSE(acc.Commit().HasError()); - } - - // Delete the edge - { - auto acc = store.Access(); - auto vertex_from = acc.FindVertex(gid_from, memgraph::storage::View::NEW); - auto vertex_to = acc.FindVertex(gid_to, memgraph::storage::View::NEW); - ASSERT_TRUE(vertex_from); - ASSERT_TRUE(vertex_to); - - auto et = acc.NameToEdgeType("et5"); - - auto edge = vertex_from->OutEdges(memgraph::storage::View::NEW).GetValue()[0]; - - auto res = acc.DeleteEdge(&edge); - ASSERT_TRUE(res.HasValue()); - ASSERT_TRUE(res.GetValue()); - - // Check edges without filters - ASSERT_EQ(vertex_from->InEdges(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(*vertex_from->InDegree(memgraph::storage::View::OLD), 0); - ASSERT_EQ(vertex_from->InEdges(memgraph::storage::View::NEW)->size(), 0); - ASSERT_EQ(*vertex_from->InDegree(memgraph::storage::View::NEW), 0); - { - auto ret = vertex_from->OutEdges(memgraph::storage::View::OLD); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex_from->OutDegree(memgraph::storage::View::OLD), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et); - ASSERT_EQ(e.FromVertex(), *vertex_from); - ASSERT_EQ(e.ToVertex(), *vertex_to); - } - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::NEW)->size(), 0); - ASSERT_EQ(*vertex_from->OutDegree(memgraph::storage::View::NEW), 0); - { - auto ret = vertex_to->InEdges(memgraph::storage::View::OLD); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex_to->InDegree(memgraph::storage::View::OLD), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et); - ASSERT_EQ(e.FromVertex(), *vertex_from); - ASSERT_EQ(e.ToVertex(), *vertex_to); - } - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::NEW)->size(), 0); - ASSERT_EQ(*vertex_to->InDegree(memgraph::storage::View::NEW), 0); - ASSERT_EQ(vertex_to->OutEdges(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(*vertex_to->OutDegree(memgraph::storage::View::OLD), 0); - ASSERT_EQ(vertex_to->OutEdges(memgraph::storage::View::NEW)->size(), 0); - ASSERT_EQ(*vertex_to->OutDegree(memgraph::storage::View::NEW), 0); - - auto other_et = acc.NameToEdgeType("other"); - - // Check edges with filters - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::OLD, {other_et})->size(), 0); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::OLD, {et, other_et})->size(), 1); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::OLD, {}, &*vertex_to)->size(), 1); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::OLD, {}, &*vertex_from)->size(), 0); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::OLD, {other_et})->size(), 0); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::OLD, {et, other_et})->size(), 1); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::OLD, {}, &*vertex_from)->size(), 1); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::OLD, {}, &*vertex_to)->size(), 0); - - ASSERT_FALSE(acc.Commit().HasError()); - } - - // Check whether the edge exists - { - auto acc = store.Access(); - auto vertex_from = acc.FindVertex(gid_from, memgraph::storage::View::NEW); - auto vertex_to = acc.FindVertex(gid_to, memgraph::storage::View::NEW); - ASSERT_TRUE(vertex_from); - ASSERT_TRUE(vertex_to); - - // Check edges without filters - ASSERT_EQ(vertex_from->InEdges(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(*vertex_from->InDegree(memgraph::storage::View::OLD), 0); - ASSERT_EQ(vertex_from->InEdges(memgraph::storage::View::NEW)->size(), 0); - ASSERT_EQ(*vertex_from->InDegree(memgraph::storage::View::NEW), 0); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(*vertex_from->OutDegree(memgraph::storage::View::OLD), 0); - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::NEW)->size(), 0); - ASSERT_EQ(*vertex_from->OutDegree(memgraph::storage::View::NEW), 0); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(*vertex_to->InDegree(memgraph::storage::View::OLD), 0); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::NEW)->size(), 0); - ASSERT_EQ(*vertex_to->InDegree(memgraph::storage::View::NEW), 0); - ASSERT_EQ(vertex_to->OutEdges(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(*vertex_to->OutDegree(memgraph::storage::View::OLD), 0); - ASSERT_EQ(vertex_to->OutEdges(memgraph::storage::View::NEW)->size(), 0); - ASSERT_EQ(*vertex_to->OutDegree(memgraph::storage::View::NEW), 0); - - ASSERT_FALSE(acc.Commit().HasError()); - } -} - -// NOLINTNEXTLINE(hicpp-special-member-functions) -TEST_P(StorageEdgeTest, EdgeDeleteFromSameAbort) { - memgraph::storage::Storage store({.items = {.properties_on_edges = GetParam()}}); - memgraph::storage::Gid gid_vertex = memgraph::storage::Gid::FromUint(std::numeric_limits::max()); - - // Create vertex - { - auto acc = store.Access(); - auto vertex = acc.CreateVertex(); - gid_vertex = vertex.Gid(); - ASSERT_FALSE(acc.Commit().HasError()); - } - - // Create edge - { - auto acc = store.Access(); - auto vertex = acc.FindVertex(gid_vertex, memgraph::storage::View::NEW); - ASSERT_TRUE(vertex); - - auto et = acc.NameToEdgeType("et5"); - - auto res = acc.CreateEdge(&*vertex, &*vertex, et); - ASSERT_TRUE(res.HasValue()); - auto edge = res.GetValue(); - ASSERT_EQ(edge.EdgeType(), et); - ASSERT_EQ(edge.FromVertex(), *vertex); - ASSERT_EQ(edge.ToVertex(), *vertex); - - // Check edges without filters - ASSERT_EQ(vertex->InEdges(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(*vertex->InDegree(memgraph::storage::View::OLD), 0); - { - auto ret = vertex->InEdges(memgraph::storage::View::NEW); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex->InDegree(memgraph::storage::View::NEW), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et); - ASSERT_EQ(e.FromVertex(), *vertex); - ASSERT_EQ(e.ToVertex(), *vertex); - } - ASSERT_EQ(vertex->OutEdges(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(*vertex->OutDegree(memgraph::storage::View::OLD), 0); - { - auto ret = vertex->OutEdges(memgraph::storage::View::NEW); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex->OutDegree(memgraph::storage::View::NEW), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et); - ASSERT_EQ(e.FromVertex(), *vertex); - ASSERT_EQ(e.ToVertex(), *vertex); - } - - auto other_et = acc.NameToEdgeType("other"); - - // Check edges with filters - ASSERT_EQ(vertex->OutEdges(memgraph::storage::View::NEW, {other_et})->size(), 0); - ASSERT_EQ(vertex->OutEdges(memgraph::storage::View::NEW, {et, other_et})->size(), 1); - ASSERT_EQ(vertex->OutEdges(memgraph::storage::View::NEW, {}, &*vertex)->size(), 1); - ASSERT_EQ(vertex->OutEdges(memgraph::storage::View::NEW, {other_et}, &*vertex)->size(), 0); - ASSERT_EQ(vertex->InEdges(memgraph::storage::View::NEW, {other_et})->size(), 0); - ASSERT_EQ(vertex->InEdges(memgraph::storage::View::NEW, {et, other_et})->size(), 1); - ASSERT_EQ(vertex->InEdges(memgraph::storage::View::NEW, {}, &*vertex)->size(), 1); - ASSERT_EQ(vertex->InEdges(memgraph::storage::View::NEW, {other_et}, &*vertex)->size(), 0); - - ASSERT_FALSE(acc.Commit().HasError()); - } - - // Check whether the edge exists - { - auto acc = store.Access(); - auto vertex = acc.FindVertex(gid_vertex, memgraph::storage::View::NEW); - ASSERT_TRUE(vertex); - - auto et = acc.NameToEdgeType("et5"); - - // Check edges without filters - { - auto ret = vertex->InEdges(memgraph::storage::View::OLD); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex->InDegree(memgraph::storage::View::OLD), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et); - ASSERT_EQ(e.FromVertex(), *vertex); - ASSERT_EQ(e.ToVertex(), *vertex); - } - { - auto ret = vertex->InEdges(memgraph::storage::View::NEW); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex->InDegree(memgraph::storage::View::NEW), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et); - ASSERT_EQ(e.FromVertex(), *vertex); - ASSERT_EQ(e.ToVertex(), *vertex); - } - { - auto ret = vertex->OutEdges(memgraph::storage::View::OLD); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex->OutDegree(memgraph::storage::View::OLD), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et); - ASSERT_EQ(e.FromVertex(), *vertex); - ASSERT_EQ(e.ToVertex(), *vertex); - } - { - auto ret = vertex->OutEdges(memgraph::storage::View::NEW); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex->OutDegree(memgraph::storage::View::NEW), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et); - ASSERT_EQ(e.FromVertex(), *vertex); - ASSERT_EQ(e.ToVertex(), *vertex); - } - - auto other_et = acc.NameToEdgeType("other"); - - // Check edges with filters - ASSERT_EQ(vertex->InEdges(memgraph::storage::View::OLD, {other_et})->size(), 0); - ASSERT_EQ(vertex->InEdges(memgraph::storage::View::NEW, {other_et})->size(), 0); - ASSERT_EQ(vertex->InEdges(memgraph::storage::View::OLD, {et, other_et})->size(), 1); - ASSERT_EQ(vertex->InEdges(memgraph::storage::View::NEW, {et, other_et})->size(), 1); - ASSERT_EQ(vertex->InEdges(memgraph::storage::View::OLD, {}, &*vertex)->size(), 1); - ASSERT_EQ(vertex->InEdges(memgraph::storage::View::NEW, {}, &*vertex)->size(), 1); - ASSERT_EQ(vertex->InEdges(memgraph::storage::View::OLD, {other_et}, &*vertex)->size(), 0); - ASSERT_EQ(vertex->InEdges(memgraph::storage::View::NEW, {other_et}, &*vertex)->size(), 0); - ASSERT_EQ(vertex->OutEdges(memgraph::storage::View::OLD, {other_et})->size(), 0); - ASSERT_EQ(vertex->OutEdges(memgraph::storage::View::NEW, {other_et})->size(), 0); - ASSERT_EQ(vertex->OutEdges(memgraph::storage::View::OLD, {et, other_et})->size(), 1); - ASSERT_EQ(vertex->OutEdges(memgraph::storage::View::NEW, {et, other_et})->size(), 1); - ASSERT_EQ(vertex->OutEdges(memgraph::storage::View::OLD, {}, &*vertex)->size(), 1); - ASSERT_EQ(vertex->OutEdges(memgraph::storage::View::NEW, {}, &*vertex)->size(), 1); - ASSERT_EQ(vertex->OutEdges(memgraph::storage::View::OLD, {other_et}, &*vertex)->size(), 0); - ASSERT_EQ(vertex->OutEdges(memgraph::storage::View::NEW, {other_et}, &*vertex)->size(), 0); - - ASSERT_FALSE(acc.Commit().HasError()); - } - - // Delete the edge, but abort the transaction - { - auto acc = store.Access(); - auto vertex = acc.FindVertex(gid_vertex, memgraph::storage::View::NEW); - ASSERT_TRUE(vertex); - - auto et = acc.NameToEdgeType("et5"); - - auto edge = vertex->OutEdges(memgraph::storage::View::NEW).GetValue()[0]; - - auto res = acc.DeleteEdge(&edge); - ASSERT_TRUE(res.HasValue()); - ASSERT_TRUE(res.GetValue()); - - // Check edges without filters - { - auto ret = vertex->InEdges(memgraph::storage::View::OLD); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex->InDegree(memgraph::storage::View::OLD), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et); - ASSERT_EQ(e.FromVertex(), *vertex); - ASSERT_EQ(e.ToVertex(), *vertex); - } - ASSERT_EQ(vertex->InEdges(memgraph::storage::View::NEW)->size(), 0); - ASSERT_EQ(*vertex->InDegree(memgraph::storage::View::NEW), 0); - { - auto ret = vertex->OutEdges(memgraph::storage::View::OLD); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex->OutDegree(memgraph::storage::View::OLD), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et); - ASSERT_EQ(e.FromVertex(), *vertex); - ASSERT_EQ(e.ToVertex(), *vertex); - } - ASSERT_EQ(vertex->OutEdges(memgraph::storage::View::NEW)->size(), 0); - ASSERT_EQ(*vertex->OutDegree(memgraph::storage::View::NEW), 0); - - auto other_et = acc.NameToEdgeType("other"); - - // Check edges with filters - ASSERT_EQ(vertex->InEdges(memgraph::storage::View::OLD, {other_et})->size(), 0); - ASSERT_EQ(vertex->InEdges(memgraph::storage::View::OLD, {et, other_et})->size(), 1); - ASSERT_EQ(vertex->InEdges(memgraph::storage::View::OLD, {}, &*vertex)->size(), 1); - ASSERT_EQ(vertex->InEdges(memgraph::storage::View::OLD, {other_et}, &*vertex)->size(), 0); - ASSERT_EQ(vertex->OutEdges(memgraph::storage::View::OLD, {other_et})->size(), 0); - ASSERT_EQ(vertex->OutEdges(memgraph::storage::View::OLD, {et, other_et})->size(), 1); - ASSERT_EQ(vertex->OutEdges(memgraph::storage::View::OLD, {}, &*vertex)->size(), 1); - ASSERT_EQ(vertex->OutEdges(memgraph::storage::View::OLD, {other_et}, &*vertex)->size(), 0); - - acc.Abort(); - } - - // Check whether the edge exists - { - auto acc = store.Access(); - auto vertex = acc.FindVertex(gid_vertex, memgraph::storage::View::NEW); - ASSERT_TRUE(vertex); - - auto et = acc.NameToEdgeType("et5"); - - // Check edges without filters - { - auto ret = vertex->InEdges(memgraph::storage::View::OLD); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex->InDegree(memgraph::storage::View::OLD), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et); - ASSERT_EQ(e.FromVertex(), *vertex); - ASSERT_EQ(e.ToVertex(), *vertex); - } - { - auto ret = vertex->InEdges(memgraph::storage::View::NEW); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex->InDegree(memgraph::storage::View::NEW), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et); - ASSERT_EQ(e.FromVertex(), *vertex); - ASSERT_EQ(e.ToVertex(), *vertex); - } - { - auto ret = vertex->OutEdges(memgraph::storage::View::OLD); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex->OutDegree(memgraph::storage::View::OLD), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et); - ASSERT_EQ(e.FromVertex(), *vertex); - ASSERT_EQ(e.ToVertex(), *vertex); - } - { - auto ret = vertex->OutEdges(memgraph::storage::View::NEW); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex->OutDegree(memgraph::storage::View::NEW), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et); - ASSERT_EQ(e.FromVertex(), *vertex); - ASSERT_EQ(e.ToVertex(), *vertex); - } - - auto other_et = acc.NameToEdgeType("other"); - - // Check edges with filters - ASSERT_EQ(vertex->InEdges(memgraph::storage::View::OLD, {other_et})->size(), 0); - ASSERT_EQ(vertex->InEdges(memgraph::storage::View::NEW, {other_et})->size(), 0); - ASSERT_EQ(vertex->InEdges(memgraph::storage::View::OLD, {et, other_et})->size(), 1); - ASSERT_EQ(vertex->InEdges(memgraph::storage::View::NEW, {et, other_et})->size(), 1); - ASSERT_EQ(vertex->InEdges(memgraph::storage::View::OLD, {}, &*vertex)->size(), 1); - ASSERT_EQ(vertex->InEdges(memgraph::storage::View::NEW, {}, &*vertex)->size(), 1); - ASSERT_EQ(vertex->InEdges(memgraph::storage::View::OLD, {other_et}, &*vertex)->size(), 0); - ASSERT_EQ(vertex->InEdges(memgraph::storage::View::NEW, {other_et}, &*vertex)->size(), 0); - ASSERT_EQ(vertex->OutEdges(memgraph::storage::View::OLD, {other_et})->size(), 0); - ASSERT_EQ(vertex->OutEdges(memgraph::storage::View::NEW, {other_et})->size(), 0); - ASSERT_EQ(vertex->OutEdges(memgraph::storage::View::OLD, {et, other_et})->size(), 1); - ASSERT_EQ(vertex->OutEdges(memgraph::storage::View::NEW, {et, other_et})->size(), 1); - ASSERT_EQ(vertex->OutEdges(memgraph::storage::View::OLD, {}, &*vertex)->size(), 1); - ASSERT_EQ(vertex->OutEdges(memgraph::storage::View::NEW, {}, &*vertex)->size(), 1); - ASSERT_EQ(vertex->OutEdges(memgraph::storage::View::OLD, {other_et}, &*vertex)->size(), 0); - ASSERT_EQ(vertex->OutEdges(memgraph::storage::View::NEW, {other_et}, &*vertex)->size(), 0); - - ASSERT_FALSE(acc.Commit().HasError()); - } - - // Delete the edge - { - auto acc = store.Access(); - auto vertex = acc.FindVertex(gid_vertex, memgraph::storage::View::NEW); - ASSERT_TRUE(vertex); - - auto et = acc.NameToEdgeType("et5"); - - auto edge = vertex->OutEdges(memgraph::storage::View::NEW).GetValue()[0]; - - auto res = acc.DeleteEdge(&edge); - ASSERT_TRUE(res.HasValue()); - ASSERT_TRUE(res.GetValue()); - - // Check edges without filters - { - auto ret = vertex->InEdges(memgraph::storage::View::OLD); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex->InDegree(memgraph::storage::View::OLD), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et); - ASSERT_EQ(e.FromVertex(), *vertex); - ASSERT_EQ(e.ToVertex(), *vertex); - } - ASSERT_EQ(vertex->InEdges(memgraph::storage::View::NEW)->size(), 0); - ASSERT_EQ(*vertex->InDegree(memgraph::storage::View::NEW), 0); - { - auto ret = vertex->OutEdges(memgraph::storage::View::OLD); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex->OutDegree(memgraph::storage::View::OLD), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et); - ASSERT_EQ(e.FromVertex(), *vertex); - ASSERT_EQ(e.ToVertex(), *vertex); - } - ASSERT_EQ(vertex->OutEdges(memgraph::storage::View::NEW)->size(), 0); - ASSERT_EQ(*vertex->OutDegree(memgraph::storage::View::NEW), 0); - - auto other_et = acc.NameToEdgeType("other"); - - // Check edges with filters - ASSERT_EQ(vertex->InEdges(memgraph::storage::View::OLD, {other_et})->size(), 0); - ASSERT_EQ(vertex->InEdges(memgraph::storage::View::OLD, {et, other_et})->size(), 1); - ASSERT_EQ(vertex->InEdges(memgraph::storage::View::OLD, {}, &*vertex)->size(), 1); - ASSERT_EQ(vertex->InEdges(memgraph::storage::View::OLD, {other_et}, &*vertex)->size(), 0); - ASSERT_EQ(vertex->OutEdges(memgraph::storage::View::OLD, {other_et})->size(), 0); - ASSERT_EQ(vertex->OutEdges(memgraph::storage::View::OLD, {et, other_et})->size(), 1); - ASSERT_EQ(vertex->OutEdges(memgraph::storage::View::OLD, {}, &*vertex)->size(), 1); - ASSERT_EQ(vertex->OutEdges(memgraph::storage::View::OLD, {other_et}, &*vertex)->size(), 0); - - ASSERT_FALSE(acc.Commit().HasError()); - } - - // Check whether the edge exists - { - auto acc = store.Access(); - auto vertex = acc.FindVertex(gid_vertex, memgraph::storage::View::NEW); - ASSERT_TRUE(vertex); - - // Check edges without filters - ASSERT_EQ(vertex->InEdges(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(*vertex->InDegree(memgraph::storage::View::OLD), 0); - ASSERT_EQ(vertex->InEdges(memgraph::storage::View::NEW)->size(), 0); - ASSERT_EQ(*vertex->InDegree(memgraph::storage::View::NEW), 0); - ASSERT_EQ(vertex->OutEdges(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(*vertex->OutDegree(memgraph::storage::View::OLD), 0); - ASSERT_EQ(vertex->OutEdges(memgraph::storage::View::NEW)->size(), 0); - ASSERT_EQ(*vertex->OutDegree(memgraph::storage::View::NEW), 0); - - ASSERT_FALSE(acc.Commit().HasError()); - } -} - -// NOLINTNEXTLINE(hicpp-special-member-functions) -TEST_P(StorageEdgeTest, VertexDetachDeleteSingleCommit) { - memgraph::storage::Storage store({.items = {.properties_on_edges = GetParam()}}); - memgraph::storage::Gid gid_from = memgraph::storage::Gid::FromUint(std::numeric_limits::max()); - memgraph::storage::Gid gid_to = memgraph::storage::Gid::FromUint(std::numeric_limits::max()); - - // Create dataset - { - auto acc = store.Access(); - auto vertex_from = acc.CreateVertex(); - auto vertex_to = acc.CreateVertex(); - - auto et = acc.NameToEdgeType("et5"); - - auto res = acc.CreateEdge(&vertex_from, &vertex_to, et); - ASSERT_TRUE(res.HasValue()); - auto edge = res.GetValue(); - ASSERT_EQ(edge.EdgeType(), et); - ASSERT_EQ(edge.FromVertex(), vertex_from); - ASSERT_EQ(edge.ToVertex(), vertex_to); - - gid_from = vertex_from.Gid(); - gid_to = vertex_to.Gid(); - - // Check edges - ASSERT_EQ(vertex_from.InEdges(memgraph::storage::View::NEW)->size(), 0); - ASSERT_EQ(*vertex_from.InDegree(memgraph::storage::View::NEW), 0); - { - auto ret = vertex_from.OutEdges(memgraph::storage::View::NEW); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex_from.OutDegree(memgraph::storage::View::NEW), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et); - ASSERT_EQ(e.FromVertex(), vertex_from); - ASSERT_EQ(e.ToVertex(), vertex_to); - } - { - auto ret = vertex_to.InEdges(memgraph::storage::View::NEW); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex_to.InDegree(memgraph::storage::View::NEW), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et); - ASSERT_EQ(e.FromVertex(), vertex_from); - ASSERT_EQ(e.ToVertex(), vertex_to); - } - ASSERT_EQ(vertex_to.OutEdges(memgraph::storage::View::NEW)->size(), 0); - ASSERT_EQ(*vertex_to.OutDegree(memgraph::storage::View::NEW), 0); - - ASSERT_FALSE(acc.Commit().HasError()); - } - - // Detach delete vertex - { - auto acc = store.Access(); - auto vertex_from = acc.FindVertex(gid_from, memgraph::storage::View::NEW); - auto vertex_to = acc.FindVertex(gid_to, memgraph::storage::View::NEW); - ASSERT_TRUE(vertex_from); - ASSERT_TRUE(vertex_to); - - auto et = acc.NameToEdgeType("et5"); - - // Delete must fail - { - auto ret = acc.DeleteVertex(&*vertex_from); - ASSERT_TRUE(ret.HasError()); - ASSERT_EQ(ret.GetError(), memgraph::storage::Error::VERTEX_HAS_EDGES); - } - - // Detach delete vertex - { - auto ret = acc.DetachDeleteVertex(&*vertex_from); - ASSERT_TRUE(ret.HasValue()); - ASSERT_TRUE(*ret); - } - - // Check edges - ASSERT_EQ(vertex_from->InEdges(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(*vertex_from->InDegree(memgraph::storage::View::OLD), 0); - ASSERT_EQ(vertex_from->InEdges(memgraph::storage::View::NEW).GetError(), memgraph::storage::Error::DELETED_OBJECT); - ASSERT_EQ(vertex_from->InDegree(memgraph::storage::View::NEW).GetError(), memgraph::storage::Error::DELETED_OBJECT); - { - auto ret = vertex_from->OutEdges(memgraph::storage::View::OLD); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex_from->OutDegree(memgraph::storage::View::OLD), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et); - ASSERT_EQ(e.FromVertex(), *vertex_from); - ASSERT_EQ(e.ToVertex(), *vertex_to); - } - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::NEW).GetError(), memgraph::storage::Error::DELETED_OBJECT); - ASSERT_EQ(vertex_from->OutDegree(memgraph::storage::View::NEW).GetError(), - memgraph::storage::Error::DELETED_OBJECT); - { - auto ret = vertex_to->InEdges(memgraph::storage::View::OLD); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex_to->InDegree(memgraph::storage::View::OLD), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et); - ASSERT_EQ(e.FromVertex(), *vertex_from); - ASSERT_EQ(e.ToVertex(), *vertex_to); - } - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::NEW)->size(), 0); - ASSERT_EQ(*vertex_to->InDegree(memgraph::storage::View::NEW), 0); - ASSERT_EQ(vertex_to->OutEdges(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(*vertex_to->OutDegree(memgraph::storage::View::OLD), 0); - ASSERT_EQ(vertex_to->OutEdges(memgraph::storage::View::NEW)->size(), 0); - ASSERT_EQ(*vertex_to->OutDegree(memgraph::storage::View::NEW), 0); - - ASSERT_FALSE(acc.Commit().HasError()); - } - - // Check dataset - { - auto acc = store.Access(); - auto vertex_from = acc.FindVertex(gid_from, memgraph::storage::View::NEW); - auto vertex_to = acc.FindVertex(gid_to, memgraph::storage::View::NEW); - ASSERT_FALSE(vertex_from); - ASSERT_TRUE(vertex_to); - - // Check edges - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(*vertex_to->InDegree(memgraph::storage::View::OLD), 0); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::NEW)->size(), 0); - ASSERT_EQ(*vertex_to->InDegree(memgraph::storage::View::NEW), 0); - ASSERT_EQ(vertex_to->OutEdges(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(*vertex_to->OutDegree(memgraph::storage::View::OLD), 0); - ASSERT_EQ(vertex_to->OutEdges(memgraph::storage::View::NEW)->size(), 0); - ASSERT_EQ(*vertex_to->OutDegree(memgraph::storage::View::NEW), 0); - } -} - -// NOLINTNEXTLINE(hicpp-special-member-functions) -TEST_P(StorageEdgeTest, VertexDetachDeleteMultipleCommit) { - memgraph::storage::Storage store({.items = {.properties_on_edges = GetParam()}}); - memgraph::storage::Gid gid_vertex1 = memgraph::storage::Gid::FromUint(std::numeric_limits::max()); - memgraph::storage::Gid gid_vertex2 = memgraph::storage::Gid::FromUint(std::numeric_limits::max()); - - // Create dataset - { - auto acc = store.Access(); - auto vertex1 = acc.CreateVertex(); - auto vertex2 = acc.CreateVertex(); - - gid_vertex1 = vertex1.Gid(); - gid_vertex2 = vertex2.Gid(); - - auto et1 = acc.NameToEdgeType("et1"); - auto et2 = acc.NameToEdgeType("et2"); - auto et3 = acc.NameToEdgeType("et3"); - auto et4 = acc.NameToEdgeType("et4"); - - auto res1 = acc.CreateEdge(&vertex1, &vertex2, et1); - ASSERT_TRUE(res1.HasValue()); - auto edge1 = res1.GetValue(); - ASSERT_EQ(edge1.EdgeType(), et1); - ASSERT_EQ(edge1.FromVertex(), vertex1); - ASSERT_EQ(edge1.ToVertex(), vertex2); - - auto res2 = acc.CreateEdge(&vertex2, &vertex1, et2); - ASSERT_TRUE(res2.HasValue()); - auto edge2 = res2.GetValue(); - ASSERT_EQ(edge2.EdgeType(), et2); - ASSERT_EQ(edge2.FromVertex(), vertex2); - ASSERT_EQ(edge2.ToVertex(), vertex1); - - auto res3 = acc.CreateEdge(&vertex1, &vertex1, et3); - ASSERT_TRUE(res3.HasValue()); - auto edge3 = res3.GetValue(); - ASSERT_EQ(edge3.EdgeType(), et3); - ASSERT_EQ(edge3.FromVertex(), vertex1); - ASSERT_EQ(edge3.ToVertex(), vertex1); - - auto res4 = acc.CreateEdge(&vertex2, &vertex2, et4); - ASSERT_TRUE(res4.HasValue()); - auto edge4 = res4.GetValue(); - ASSERT_EQ(edge4.EdgeType(), et4); - ASSERT_EQ(edge4.FromVertex(), vertex2); - ASSERT_EQ(edge4.ToVertex(), vertex2); - - // Check edges - { - auto ret = vertex1.InEdges(memgraph::storage::View::NEW); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - std::sort(edges.begin(), edges.end(), [](const auto &a, const auto &b) { return a.EdgeType() < b.EdgeType(); }); - ASSERT_EQ(edges.size(), 2); - ASSERT_EQ(*vertex1.InDegree(memgraph::storage::View::NEW), 2); - { - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et2); - ASSERT_EQ(e.FromVertex(), vertex2); - ASSERT_EQ(e.ToVertex(), vertex1); - } - { - auto e = edges[1]; - ASSERT_EQ(e.EdgeType(), et3); - ASSERT_EQ(e.FromVertex(), vertex1); - ASSERT_EQ(e.ToVertex(), vertex1); - } - } - { - auto ret = vertex1.OutEdges(memgraph::storage::View::NEW); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - std::sort(edges.begin(), edges.end(), [](const auto &a, const auto &b) { return a.EdgeType() < b.EdgeType(); }); - ASSERT_EQ(edges.size(), 2); - ASSERT_EQ(*vertex1.OutDegree(memgraph::storage::View::NEW), 2); - { - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et1); - ASSERT_EQ(e.FromVertex(), vertex1); - ASSERT_EQ(e.ToVertex(), vertex2); - } - { - auto e = edges[1]; - ASSERT_EQ(e.EdgeType(), et3); - ASSERT_EQ(e.FromVertex(), vertex1); - ASSERT_EQ(e.ToVertex(), vertex1); - } - } - { - auto ret = vertex2.InEdges(memgraph::storage::View::NEW); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - std::sort(edges.begin(), edges.end(), [](const auto &a, const auto &b) { return a.EdgeType() < b.EdgeType(); }); - ASSERT_EQ(edges.size(), 2); - ASSERT_EQ(*vertex2.InDegree(memgraph::storage::View::NEW), 2); - { - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et1); - ASSERT_EQ(e.FromVertex(), vertex1); - ASSERT_EQ(e.ToVertex(), vertex2); - } - { - auto e = edges[1]; - ASSERT_EQ(e.EdgeType(), et4); - ASSERT_EQ(e.FromVertex(), vertex2); - ASSERT_EQ(e.ToVertex(), vertex2); - } - } - { - auto ret = vertex2.OutEdges(memgraph::storage::View::NEW); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - std::sort(edges.begin(), edges.end(), [](const auto &a, const auto &b) { return a.EdgeType() < b.EdgeType(); }); - ASSERT_EQ(edges.size(), 2); - ASSERT_EQ(*vertex2.OutDegree(memgraph::storage::View::NEW), 2); - { - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et2); - ASSERT_EQ(e.FromVertex(), vertex2); - ASSERT_EQ(e.ToVertex(), vertex1); - } - { - auto e = edges[1]; - ASSERT_EQ(e.EdgeType(), et4); - ASSERT_EQ(e.FromVertex(), vertex2); - ASSERT_EQ(e.ToVertex(), vertex2); - } - } - - ASSERT_FALSE(acc.Commit().HasError()); - } - - // Detach delete vertex - { - auto acc = store.Access(); - auto vertex1 = acc.FindVertex(gid_vertex1, memgraph::storage::View::NEW); - auto vertex2 = acc.FindVertex(gid_vertex2, memgraph::storage::View::NEW); - ASSERT_TRUE(vertex1); - ASSERT_TRUE(vertex2); - - auto et1 = acc.NameToEdgeType("et1"); - auto et2 = acc.NameToEdgeType("et2"); - auto et3 = acc.NameToEdgeType("et3"); - auto et4 = acc.NameToEdgeType("et4"); - - // Delete must fail - { - auto ret = acc.DeleteVertex(&*vertex1); - ASSERT_TRUE(ret.HasError()); - ASSERT_EQ(ret.GetError(), memgraph::storage::Error::VERTEX_HAS_EDGES); - } - - // Detach delete vertex - { - auto ret = acc.DetachDeleteVertex(&*vertex1); - ASSERT_TRUE(ret.HasValue()); - ASSERT_TRUE(*ret); - } - - // Check edges - { - auto ret = vertex1->InEdges(memgraph::storage::View::OLD); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - std::sort(edges.begin(), edges.end(), [](const auto &a, const auto &b) { return a.EdgeType() < b.EdgeType(); }); - ASSERT_EQ(edges.size(), 2); - ASSERT_EQ(*vertex1->InDegree(memgraph::storage::View::OLD), 2); - { - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et2); - ASSERT_EQ(e.FromVertex(), *vertex2); - ASSERT_EQ(e.ToVertex(), *vertex1); - } - { - auto e = edges[1]; - ASSERT_EQ(e.EdgeType(), et3); - ASSERT_EQ(e.FromVertex(), *vertex1); - ASSERT_EQ(e.ToVertex(), *vertex1); - } - } - ASSERT_EQ(vertex1->InEdges(memgraph::storage::View::NEW).GetError(), memgraph::storage::Error::DELETED_OBJECT); - ASSERT_EQ(vertex1->InDegree(memgraph::storage::View::NEW).GetError(), memgraph::storage::Error::DELETED_OBJECT); - { - auto ret = vertex1->OutEdges(memgraph::storage::View::OLD); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - std::sort(edges.begin(), edges.end(), [](const auto &a, const auto &b) { return a.EdgeType() < b.EdgeType(); }); - ASSERT_EQ(edges.size(), 2); - ASSERT_EQ(*vertex1->OutDegree(memgraph::storage::View::OLD), 2); - { - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et1); - ASSERT_EQ(e.FromVertex(), *vertex1); - ASSERT_EQ(e.ToVertex(), *vertex2); - } - { - auto e = edges[1]; - ASSERT_EQ(e.EdgeType(), et3); - ASSERT_EQ(e.FromVertex(), *vertex1); - ASSERT_EQ(e.ToVertex(), *vertex1); - } - } - ASSERT_EQ(vertex1->OutEdges(memgraph::storage::View::NEW).GetError(), memgraph::storage::Error::DELETED_OBJECT); - ASSERT_EQ(vertex1->OutDegree(memgraph::storage::View::NEW).GetError(), memgraph::storage::Error::DELETED_OBJECT); - { - auto ret = vertex2->InEdges(memgraph::storage::View::OLD); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - std::sort(edges.begin(), edges.end(), [](const auto &a, const auto &b) { return a.EdgeType() < b.EdgeType(); }); - ASSERT_EQ(edges.size(), 2); - ASSERT_EQ(*vertex2->InDegree(memgraph::storage::View::OLD), 2); - { - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et1); - ASSERT_EQ(e.FromVertex(), *vertex1); - ASSERT_EQ(e.ToVertex(), *vertex2); - } - { - auto e = edges[1]; - ASSERT_EQ(e.EdgeType(), et4); - ASSERT_EQ(e.FromVertex(), *vertex2); - ASSERT_EQ(e.ToVertex(), *vertex2); - } - } - { - auto ret = vertex2->InEdges(memgraph::storage::View::NEW); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex2->InDegree(memgraph::storage::View::NEW), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et4); - ASSERT_EQ(e.FromVertex(), *vertex2); - ASSERT_EQ(e.ToVertex(), *vertex2); - } - { - auto ret = vertex2->OutEdges(memgraph::storage::View::OLD); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - std::sort(edges.begin(), edges.end(), [](const auto &a, const auto &b) { return a.EdgeType() < b.EdgeType(); }); - ASSERT_EQ(edges.size(), 2); - ASSERT_EQ(*vertex2->OutDegree(memgraph::storage::View::OLD), 2); - { - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et2); - ASSERT_EQ(e.FromVertex(), *vertex2); - ASSERT_EQ(e.ToVertex(), *vertex1); - } - { - auto e = edges[1]; - ASSERT_EQ(e.EdgeType(), et4); - ASSERT_EQ(e.FromVertex(), *vertex2); - ASSERT_EQ(e.ToVertex(), *vertex2); - } - } - { - auto ret = vertex2->OutEdges(memgraph::storage::View::NEW); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex2->OutDegree(memgraph::storage::View::NEW), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et4); - ASSERT_EQ(e.FromVertex(), *vertex2); - ASSERT_EQ(e.ToVertex(), *vertex2); - } - - ASSERT_FALSE(acc.Commit().HasError()); - } - - // Check dataset - { - auto acc = store.Access(); - auto vertex1 = acc.FindVertex(gid_vertex1, memgraph::storage::View::NEW); - auto vertex2 = acc.FindVertex(gid_vertex2, memgraph::storage::View::NEW); - ASSERT_FALSE(vertex1); - ASSERT_TRUE(vertex2); - - auto et4 = acc.NameToEdgeType("et4"); - - // Check edges - { - auto ret = vertex2->InEdges(memgraph::storage::View::OLD); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex2->InDegree(memgraph::storage::View::OLD), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et4); - ASSERT_EQ(e.FromVertex(), *vertex2); - ASSERT_EQ(e.ToVertex(), *vertex2); - } - { - auto ret = vertex2->InEdges(memgraph::storage::View::NEW); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex2->InDegree(memgraph::storage::View::NEW), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et4); - ASSERT_EQ(e.FromVertex(), *vertex2); - ASSERT_EQ(e.ToVertex(), *vertex2); - } - { - auto ret = vertex2->OutEdges(memgraph::storage::View::OLD); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex2->OutDegree(memgraph::storage::View::OLD), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et4); - ASSERT_EQ(e.FromVertex(), *vertex2); - ASSERT_EQ(e.ToVertex(), *vertex2); - } - { - auto ret = vertex2->OutEdges(memgraph::storage::View::NEW); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex2->OutDegree(memgraph::storage::View::NEW), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et4); - ASSERT_EQ(e.FromVertex(), *vertex2); - ASSERT_EQ(e.ToVertex(), *vertex2); - } - } -} - -// NOLINTNEXTLINE(hicpp-special-member-functions) -TEST_P(StorageEdgeTest, VertexDetachDeleteSingleAbort) { - memgraph::storage::Storage store({.items = {.properties_on_edges = GetParam()}}); - memgraph::storage::Gid gid_from = memgraph::storage::Gid::FromUint(std::numeric_limits::max()); - memgraph::storage::Gid gid_to = memgraph::storage::Gid::FromUint(std::numeric_limits::max()); - - // Create dataset - { - auto acc = store.Access(); - auto vertex_from = acc.CreateVertex(); - auto vertex_to = acc.CreateVertex(); - - auto et = acc.NameToEdgeType("et5"); - - auto res = acc.CreateEdge(&vertex_from, &vertex_to, et); - ASSERT_TRUE(res.HasValue()); - auto edge = res.GetValue(); - ASSERT_EQ(edge.EdgeType(), et); - ASSERT_EQ(edge.FromVertex(), vertex_from); - ASSERT_EQ(edge.ToVertex(), vertex_to); - - gid_from = vertex_from.Gid(); - gid_to = vertex_to.Gid(); - - // Check edges - ASSERT_EQ(vertex_from.InEdges(memgraph::storage::View::NEW)->size(), 0); - ASSERT_EQ(*vertex_from.InDegree(memgraph::storage::View::NEW), 0); - { - auto ret = vertex_from.OutEdges(memgraph::storage::View::NEW); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex_from.OutDegree(memgraph::storage::View::NEW), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et); - ASSERT_EQ(e.FromVertex(), vertex_from); - ASSERT_EQ(e.ToVertex(), vertex_to); - } - { - auto ret = vertex_to.InEdges(memgraph::storage::View::NEW); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex_to.InDegree(memgraph::storage::View::NEW), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et); - ASSERT_EQ(e.FromVertex(), vertex_from); - ASSERT_EQ(e.ToVertex(), vertex_to); - } - ASSERT_EQ(vertex_to.OutEdges(memgraph::storage::View::NEW)->size(), 0); - ASSERT_EQ(*vertex_to.OutDegree(memgraph::storage::View::NEW), 0); - - ASSERT_FALSE(acc.Commit().HasError()); - } - - // Detach delete vertex, but abort the transaction - { - auto acc = store.Access(); - auto vertex_from = acc.FindVertex(gid_from, memgraph::storage::View::NEW); - auto vertex_to = acc.FindVertex(gid_to, memgraph::storage::View::NEW); - ASSERT_TRUE(vertex_from); - ASSERT_TRUE(vertex_to); - - auto et = acc.NameToEdgeType("et5"); - - // Delete must fail - { - auto ret = acc.DeleteVertex(&*vertex_from); - ASSERT_TRUE(ret.HasError()); - ASSERT_EQ(ret.GetError(), memgraph::storage::Error::VERTEX_HAS_EDGES); - } - - // Detach delete vertex - { - auto ret = acc.DetachDeleteVertex(&*vertex_from); - ASSERT_TRUE(ret.HasValue()); - ASSERT_TRUE(*ret); - } - - // Check edges - ASSERT_EQ(vertex_from->InEdges(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(*vertex_from->InDegree(memgraph::storage::View::OLD), 0); - ASSERT_EQ(vertex_from->InEdges(memgraph::storage::View::NEW).GetError(), memgraph::storage::Error::DELETED_OBJECT); - ASSERT_EQ(vertex_from->InDegree(memgraph::storage::View::NEW).GetError(), memgraph::storage::Error::DELETED_OBJECT); - { - auto ret = vertex_from->OutEdges(memgraph::storage::View::OLD); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex_from->OutDegree(memgraph::storage::View::OLD), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et); - ASSERT_EQ(e.FromVertex(), *vertex_from); - ASSERT_EQ(e.ToVertex(), *vertex_to); - } - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::NEW).GetError(), memgraph::storage::Error::DELETED_OBJECT); - ASSERT_EQ(vertex_from->OutDegree(memgraph::storage::View::NEW).GetError(), - memgraph::storage::Error::DELETED_OBJECT); - { - auto ret = vertex_to->InEdges(memgraph::storage::View::OLD); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex_to->InDegree(memgraph::storage::View::OLD), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et); - ASSERT_EQ(e.FromVertex(), *vertex_from); - ASSERT_EQ(e.ToVertex(), *vertex_to); - } - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::NEW)->size(), 0); - ASSERT_EQ(*vertex_to->InDegree(memgraph::storage::View::NEW), 0); - ASSERT_EQ(vertex_to->OutEdges(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(*vertex_to->OutDegree(memgraph::storage::View::OLD), 0); - ASSERT_EQ(vertex_to->OutEdges(memgraph::storage::View::NEW)->size(), 0); - ASSERT_EQ(*vertex_to->OutDegree(memgraph::storage::View::NEW), 0); - - acc.Abort(); - } - - // Check dataset - { - auto acc = store.Access(); - auto vertex_from = acc.FindVertex(gid_from, memgraph::storage::View::NEW); - auto vertex_to = acc.FindVertex(gid_to, memgraph::storage::View::NEW); - ASSERT_TRUE(vertex_from); - ASSERT_TRUE(vertex_to); - - auto et = acc.NameToEdgeType("et5"); - - // Check edges - ASSERT_EQ(vertex_from->InEdges(memgraph::storage::View::NEW)->size(), 0); - ASSERT_EQ(*vertex_from->InDegree(memgraph::storage::View::NEW), 0); - { - auto ret = vertex_from->OutEdges(memgraph::storage::View::NEW); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex_from->OutDegree(memgraph::storage::View::NEW), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et); - ASSERT_EQ(e.FromVertex(), *vertex_from); - ASSERT_EQ(e.ToVertex(), *vertex_to); - } - { - auto ret = vertex_to->InEdges(memgraph::storage::View::NEW); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex_to->InDegree(memgraph::storage::View::NEW), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et); - ASSERT_EQ(e.FromVertex(), *vertex_from); - ASSERT_EQ(e.ToVertex(), *vertex_to); - } - ASSERT_EQ(vertex_to->OutEdges(memgraph::storage::View::NEW)->size(), 0); - ASSERT_EQ(*vertex_to->OutDegree(memgraph::storage::View::NEW), 0); - - ASSERT_FALSE(acc.Commit().HasError()); - } - - // Detach delete vertex - { - auto acc = store.Access(); - auto vertex_from = acc.FindVertex(gid_from, memgraph::storage::View::NEW); - auto vertex_to = acc.FindVertex(gid_to, memgraph::storage::View::NEW); - ASSERT_TRUE(vertex_from); - ASSERT_TRUE(vertex_to); - - auto et = acc.NameToEdgeType("et5"); - - // Delete must fail - { - auto ret = acc.DeleteVertex(&*vertex_from); - ASSERT_TRUE(ret.HasError()); - ASSERT_EQ(ret.GetError(), memgraph::storage::Error::VERTEX_HAS_EDGES); - } - - // Detach delete vertex - { - auto ret = acc.DetachDeleteVertex(&*vertex_from); - ASSERT_TRUE(ret.HasValue()); - ASSERT_TRUE(*ret); - } - - // Check edges - ASSERT_EQ(vertex_from->InEdges(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(*vertex_from->InDegree(memgraph::storage::View::OLD), 0); - ASSERT_EQ(vertex_from->InEdges(memgraph::storage::View::NEW).GetError(), memgraph::storage::Error::DELETED_OBJECT); - ASSERT_EQ(vertex_from->InDegree(memgraph::storage::View::NEW).GetError(), memgraph::storage::Error::DELETED_OBJECT); - { - auto ret = vertex_from->OutEdges(memgraph::storage::View::OLD); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex_from->OutDegree(memgraph::storage::View::OLD), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et); - ASSERT_EQ(e.FromVertex(), *vertex_from); - ASSERT_EQ(e.ToVertex(), *vertex_to); - } - ASSERT_EQ(vertex_from->OutEdges(memgraph::storage::View::NEW).GetError(), memgraph::storage::Error::DELETED_OBJECT); - ASSERT_EQ(vertex_from->OutDegree(memgraph::storage::View::NEW).GetError(), - memgraph::storage::Error::DELETED_OBJECT); - { - auto ret = vertex_to->InEdges(memgraph::storage::View::OLD); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex_to->InDegree(memgraph::storage::View::OLD), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et); - ASSERT_EQ(e.FromVertex(), *vertex_from); - ASSERT_EQ(e.ToVertex(), *vertex_to); - } - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::NEW)->size(), 0); - ASSERT_EQ(*vertex_to->InDegree(memgraph::storage::View::NEW), 0); - ASSERT_EQ(vertex_to->OutEdges(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(*vertex_to->OutDegree(memgraph::storage::View::OLD), 0); - ASSERT_EQ(vertex_to->OutEdges(memgraph::storage::View::NEW)->size(), 0); - ASSERT_EQ(*vertex_to->OutDegree(memgraph::storage::View::NEW), 0); - - ASSERT_FALSE(acc.Commit().HasError()); - } - - // Check dataset - { - auto acc = store.Access(); - auto vertex_from = acc.FindVertex(gid_from, memgraph::storage::View::NEW); - auto vertex_to = acc.FindVertex(gid_to, memgraph::storage::View::NEW); - ASSERT_FALSE(vertex_from); - ASSERT_TRUE(vertex_to); - - // Check edges - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(*vertex_to->InDegree(memgraph::storage::View::OLD), 0); - ASSERT_EQ(vertex_to->InEdges(memgraph::storage::View::NEW)->size(), 0); - ASSERT_EQ(*vertex_to->InDegree(memgraph::storage::View::NEW), 0); - ASSERT_EQ(vertex_to->OutEdges(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(*vertex_to->OutDegree(memgraph::storage::View::OLD), 0); - ASSERT_EQ(vertex_to->OutEdges(memgraph::storage::View::NEW)->size(), 0); - ASSERT_EQ(*vertex_to->OutDegree(memgraph::storage::View::NEW), 0); - } -} - -// NOLINTNEXTLINE(hicpp-special-member-functions) -TEST_P(StorageEdgeTest, VertexDetachDeleteMultipleAbort) { - memgraph::storage::Storage store({.items = {.properties_on_edges = GetParam()}}); - memgraph::storage::Gid gid_vertex1 = memgraph::storage::Gid::FromUint(std::numeric_limits::max()); - memgraph::storage::Gid gid_vertex2 = memgraph::storage::Gid::FromUint(std::numeric_limits::max()); - - // Create dataset - { - auto acc = store.Access(); - auto vertex1 = acc.CreateVertex(); - auto vertex2 = acc.CreateVertex(); - - gid_vertex1 = vertex1.Gid(); - gid_vertex2 = vertex2.Gid(); - - auto et1 = acc.NameToEdgeType("et1"); - auto et2 = acc.NameToEdgeType("et2"); - auto et3 = acc.NameToEdgeType("et3"); - auto et4 = acc.NameToEdgeType("et4"); - - auto res1 = acc.CreateEdge(&vertex1, &vertex2, et1); - ASSERT_TRUE(res1.HasValue()); - auto edge1 = res1.GetValue(); - ASSERT_EQ(edge1.EdgeType(), et1); - ASSERT_EQ(edge1.FromVertex(), vertex1); - ASSERT_EQ(edge1.ToVertex(), vertex2); - - auto res2 = acc.CreateEdge(&vertex2, &vertex1, et2); - ASSERT_TRUE(res2.HasValue()); - auto edge2 = res2.GetValue(); - ASSERT_EQ(edge2.EdgeType(), et2); - ASSERT_EQ(edge2.FromVertex(), vertex2); - ASSERT_EQ(edge2.ToVertex(), vertex1); - - auto res3 = acc.CreateEdge(&vertex1, &vertex1, et3); - ASSERT_TRUE(res3.HasValue()); - auto edge3 = res3.GetValue(); - ASSERT_EQ(edge3.EdgeType(), et3); - ASSERT_EQ(edge3.FromVertex(), vertex1); - ASSERT_EQ(edge3.ToVertex(), vertex1); - - auto res4 = acc.CreateEdge(&vertex2, &vertex2, et4); - ASSERT_TRUE(res4.HasValue()); - auto edge4 = res4.GetValue(); - ASSERT_EQ(edge4.EdgeType(), et4); - ASSERT_EQ(edge4.FromVertex(), vertex2); - ASSERT_EQ(edge4.ToVertex(), vertex2); - - // Check edges - { - auto ret = vertex1.InEdges(memgraph::storage::View::NEW); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - std::sort(edges.begin(), edges.end(), [](const auto &a, const auto &b) { return a.EdgeType() < b.EdgeType(); }); - ASSERT_EQ(edges.size(), 2); - ASSERT_EQ(*vertex1.InDegree(memgraph::storage::View::NEW), 2); - { - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et2); - ASSERT_EQ(e.FromVertex(), vertex2); - ASSERT_EQ(e.ToVertex(), vertex1); - } - { - auto e = edges[1]; - ASSERT_EQ(e.EdgeType(), et3); - ASSERT_EQ(e.FromVertex(), vertex1); - ASSERT_EQ(e.ToVertex(), vertex1); - } - } - { - auto ret = vertex1.OutEdges(memgraph::storage::View::NEW); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - std::sort(edges.begin(), edges.end(), [](const auto &a, const auto &b) { return a.EdgeType() < b.EdgeType(); }); - ASSERT_EQ(edges.size(), 2); - ASSERT_EQ(*vertex1.OutDegree(memgraph::storage::View::NEW), 2); - { - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et1); - ASSERT_EQ(e.FromVertex(), vertex1); - ASSERT_EQ(e.ToVertex(), vertex2); - } - { - auto e = edges[1]; - ASSERT_EQ(e.EdgeType(), et3); - ASSERT_EQ(e.FromVertex(), vertex1); - ASSERT_EQ(e.ToVertex(), vertex1); - } - } - { - auto ret = vertex2.InEdges(memgraph::storage::View::NEW); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - std::sort(edges.begin(), edges.end(), [](const auto &a, const auto &b) { return a.EdgeType() < b.EdgeType(); }); - ASSERT_EQ(edges.size(), 2); - ASSERT_EQ(*vertex2.InDegree(memgraph::storage::View::NEW), 2); - { - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et1); - ASSERT_EQ(e.FromVertex(), vertex1); - ASSERT_EQ(e.ToVertex(), vertex2); - } - { - auto e = edges[1]; - ASSERT_EQ(e.EdgeType(), et4); - ASSERT_EQ(e.FromVertex(), vertex2); - ASSERT_EQ(e.ToVertex(), vertex2); - } - } - { - auto ret = vertex2.OutEdges(memgraph::storage::View::NEW); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - std::sort(edges.begin(), edges.end(), [](const auto &a, const auto &b) { return a.EdgeType() < b.EdgeType(); }); - ASSERT_EQ(edges.size(), 2); - ASSERT_EQ(*vertex2.OutDegree(memgraph::storage::View::NEW), 2); - { - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et2); - ASSERT_EQ(e.FromVertex(), vertex2); - ASSERT_EQ(e.ToVertex(), vertex1); - } - { - auto e = edges[1]; - ASSERT_EQ(e.EdgeType(), et4); - ASSERT_EQ(e.FromVertex(), vertex2); - ASSERT_EQ(e.ToVertex(), vertex2); - } - } - - ASSERT_FALSE(acc.Commit().HasError()); - } - - // Detach delete vertex, but abort the transaction - { - auto acc = store.Access(); - auto vertex1 = acc.FindVertex(gid_vertex1, memgraph::storage::View::NEW); - auto vertex2 = acc.FindVertex(gid_vertex2, memgraph::storage::View::NEW); - ASSERT_TRUE(vertex1); - ASSERT_TRUE(vertex2); - - auto et1 = acc.NameToEdgeType("et1"); - auto et2 = acc.NameToEdgeType("et2"); - auto et3 = acc.NameToEdgeType("et3"); - auto et4 = acc.NameToEdgeType("et4"); - - // Delete must fail - { - auto ret = acc.DeleteVertex(&*vertex1); - ASSERT_TRUE(ret.HasError()); - ASSERT_EQ(ret.GetError(), memgraph::storage::Error::VERTEX_HAS_EDGES); - } - - // Detach delete vertex - { - auto ret = acc.DetachDeleteVertex(&*vertex1); - ASSERT_TRUE(ret.HasValue()); - ASSERT_TRUE(*ret); - } - - // Check edges - { - auto ret = vertex1->InEdges(memgraph::storage::View::OLD); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - std::sort(edges.begin(), edges.end(), [](const auto &a, const auto &b) { return a.EdgeType() < b.EdgeType(); }); - ASSERT_EQ(edges.size(), 2); - ASSERT_EQ(*vertex1->InDegree(memgraph::storage::View::OLD), 2); - { - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et2); - ASSERT_EQ(e.FromVertex(), *vertex2); - ASSERT_EQ(e.ToVertex(), *vertex1); - } - { - auto e = edges[1]; - ASSERT_EQ(e.EdgeType(), et3); - ASSERT_EQ(e.FromVertex(), *vertex1); - ASSERT_EQ(e.ToVertex(), *vertex1); - } - } - ASSERT_EQ(vertex1->InEdges(memgraph::storage::View::NEW).GetError(), memgraph::storage::Error::DELETED_OBJECT); - ASSERT_EQ(vertex1->InDegree(memgraph::storage::View::NEW).GetError(), memgraph::storage::Error::DELETED_OBJECT); - { - auto ret = vertex1->OutEdges(memgraph::storage::View::OLD); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - std::sort(edges.begin(), edges.end(), [](const auto &a, const auto &b) { return a.EdgeType() < b.EdgeType(); }); - ASSERT_EQ(edges.size(), 2); - ASSERT_EQ(*vertex1->OutDegree(memgraph::storage::View::OLD), 2); - { - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et1); - ASSERT_EQ(e.FromVertex(), *vertex1); - ASSERT_EQ(e.ToVertex(), *vertex2); - } - { - auto e = edges[1]; - ASSERT_EQ(e.EdgeType(), et3); - ASSERT_EQ(e.FromVertex(), *vertex1); - ASSERT_EQ(e.ToVertex(), *vertex1); - } - } - ASSERT_EQ(vertex1->OutEdges(memgraph::storage::View::NEW).GetError(), memgraph::storage::Error::DELETED_OBJECT); - ASSERT_EQ(vertex1->OutDegree(memgraph::storage::View::NEW).GetError(), memgraph::storage::Error::DELETED_OBJECT); - { - auto ret = vertex2->InEdges(memgraph::storage::View::OLD); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - std::sort(edges.begin(), edges.end(), [](const auto &a, const auto &b) { return a.EdgeType() < b.EdgeType(); }); - ASSERT_EQ(edges.size(), 2); - ASSERT_EQ(*vertex2->InDegree(memgraph::storage::View::OLD), 2); - { - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et1); - ASSERT_EQ(e.FromVertex(), *vertex1); - ASSERT_EQ(e.ToVertex(), *vertex2); - } - { - auto e = edges[1]; - ASSERT_EQ(e.EdgeType(), et4); - ASSERT_EQ(e.FromVertex(), *vertex2); - ASSERT_EQ(e.ToVertex(), *vertex2); - } - } - { - auto ret = vertex2->InEdges(memgraph::storage::View::NEW); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex2->InDegree(memgraph::storage::View::NEW), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et4); - ASSERT_EQ(e.FromVertex(), *vertex2); - ASSERT_EQ(e.ToVertex(), *vertex2); - } - { - auto ret = vertex2->OutEdges(memgraph::storage::View::OLD); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - std::sort(edges.begin(), edges.end(), [](const auto &a, const auto &b) { return a.EdgeType() < b.EdgeType(); }); - ASSERT_EQ(edges.size(), 2); - ASSERT_EQ(*vertex2->OutDegree(memgraph::storage::View::OLD), 2); - { - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et2); - ASSERT_EQ(e.FromVertex(), *vertex2); - ASSERT_EQ(e.ToVertex(), *vertex1); - } - { - auto e = edges[1]; - ASSERT_EQ(e.EdgeType(), et4); - ASSERT_EQ(e.FromVertex(), *vertex2); - ASSERT_EQ(e.ToVertex(), *vertex2); - } - } - { - auto ret = vertex2->OutEdges(memgraph::storage::View::NEW); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex2->OutDegree(memgraph::storage::View::NEW), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et4); - ASSERT_EQ(e.FromVertex(), *vertex2); - ASSERT_EQ(e.ToVertex(), *vertex2); - } - - acc.Abort(); - } - - // Check dataset - { - auto acc = store.Access(); - auto vertex1 = acc.FindVertex(gid_vertex1, memgraph::storage::View::NEW); - auto vertex2 = acc.FindVertex(gid_vertex2, memgraph::storage::View::NEW); - ASSERT_TRUE(vertex1); - ASSERT_TRUE(vertex2); - - auto et1 = acc.NameToEdgeType("et1"); - auto et2 = acc.NameToEdgeType("et2"); - auto et3 = acc.NameToEdgeType("et3"); - auto et4 = acc.NameToEdgeType("et4"); - - // Check edges - { - auto ret = vertex1->InEdges(memgraph::storage::View::OLD); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - std::sort(edges.begin(), edges.end(), [](const auto &a, const auto &b) { return a.EdgeType() < b.EdgeType(); }); - ASSERT_EQ(edges.size(), 2); - ASSERT_EQ(*vertex1->InDegree(memgraph::storage::View::OLD), 2); - { - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et2); - ASSERT_EQ(e.FromVertex(), *vertex2); - ASSERT_EQ(e.ToVertex(), *vertex1); - } - { - auto e = edges[1]; - ASSERT_EQ(e.EdgeType(), et3); - ASSERT_EQ(e.FromVertex(), *vertex1); - ASSERT_EQ(e.ToVertex(), *vertex1); - } - } - { - auto ret = vertex1->InEdges(memgraph::storage::View::NEW); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - std::sort(edges.begin(), edges.end(), [](const auto &a, const auto &b) { return a.EdgeType() < b.EdgeType(); }); - ASSERT_EQ(edges.size(), 2); - ASSERT_EQ(*vertex1->InDegree(memgraph::storage::View::NEW), 2); - { - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et2); - ASSERT_EQ(e.FromVertex(), *vertex2); - ASSERT_EQ(e.ToVertex(), *vertex1); - } - { - auto e = edges[1]; - ASSERT_EQ(e.EdgeType(), et3); - ASSERT_EQ(e.FromVertex(), *vertex1); - ASSERT_EQ(e.ToVertex(), *vertex1); - } - } - { - auto ret = vertex1->OutEdges(memgraph::storage::View::OLD); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - std::sort(edges.begin(), edges.end(), [](const auto &a, const auto &b) { return a.EdgeType() < b.EdgeType(); }); - ASSERT_EQ(edges.size(), 2); - ASSERT_EQ(*vertex1->OutDegree(memgraph::storage::View::OLD), 2); - { - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et1); - ASSERT_EQ(e.FromVertex(), *vertex1); - ASSERT_EQ(e.ToVertex(), *vertex2); - } - { - auto e = edges[1]; - ASSERT_EQ(e.EdgeType(), et3); - ASSERT_EQ(e.FromVertex(), *vertex1); - ASSERT_EQ(e.ToVertex(), *vertex1); - } - } - { - auto ret = vertex1->OutEdges(memgraph::storage::View::NEW); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - std::sort(edges.begin(), edges.end(), [](const auto &a, const auto &b) { return a.EdgeType() < b.EdgeType(); }); - ASSERT_EQ(edges.size(), 2); - ASSERT_EQ(*vertex1->OutDegree(memgraph::storage::View::NEW), 2); - { - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et1); - ASSERT_EQ(e.FromVertex(), *vertex1); - ASSERT_EQ(e.ToVertex(), *vertex2); - } - { - auto e = edges[1]; - ASSERT_EQ(e.EdgeType(), et3); - ASSERT_EQ(e.FromVertex(), *vertex1); - ASSERT_EQ(e.ToVertex(), *vertex1); - } - } - { - auto ret = vertex2->InEdges(memgraph::storage::View::OLD); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - std::sort(edges.begin(), edges.end(), [](const auto &a, const auto &b) { return a.EdgeType() < b.EdgeType(); }); - ASSERT_EQ(edges.size(), 2); - ASSERT_EQ(*vertex2->InDegree(memgraph::storage::View::OLD), 2); - { - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et1); - ASSERT_EQ(e.FromVertex(), *vertex1); - ASSERT_EQ(e.ToVertex(), *vertex2); - } - { - auto e = edges[1]; - ASSERT_EQ(e.EdgeType(), et4); - ASSERT_EQ(e.FromVertex(), *vertex2); - ASSERT_EQ(e.ToVertex(), *vertex2); - } - } - { - auto ret = vertex2->InEdges(memgraph::storage::View::NEW); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - std::sort(edges.begin(), edges.end(), [](const auto &a, const auto &b) { return a.EdgeType() < b.EdgeType(); }); - ASSERT_EQ(edges.size(), 2); - ASSERT_EQ(*vertex2->InDegree(memgraph::storage::View::NEW), 2); - { - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et1); - ASSERT_EQ(e.FromVertex(), *vertex1); - ASSERT_EQ(e.ToVertex(), *vertex2); - } - { - auto e = edges[1]; - ASSERT_EQ(e.EdgeType(), et4); - ASSERT_EQ(e.FromVertex(), *vertex2); - ASSERT_EQ(e.ToVertex(), *vertex2); - } - } - { - auto ret = vertex2->OutEdges(memgraph::storage::View::OLD); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - std::sort(edges.begin(), edges.end(), [](const auto &a, const auto &b) { return a.EdgeType() < b.EdgeType(); }); - ASSERT_EQ(edges.size(), 2); - ASSERT_EQ(*vertex2->OutDegree(memgraph::storage::View::OLD), 2); - { - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et2); - ASSERT_EQ(e.FromVertex(), *vertex2); - ASSERT_EQ(e.ToVertex(), *vertex1); - } - { - auto e = edges[1]; - ASSERT_EQ(e.EdgeType(), et4); - ASSERT_EQ(e.FromVertex(), *vertex2); - ASSERT_EQ(e.ToVertex(), *vertex2); - } - } - { - auto ret = vertex2->OutEdges(memgraph::storage::View::NEW); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - std::sort(edges.begin(), edges.end(), [](const auto &a, const auto &b) { return a.EdgeType() < b.EdgeType(); }); - ASSERT_EQ(edges.size(), 2); - ASSERT_EQ(*vertex2->OutDegree(memgraph::storage::View::NEW), 2); - { - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et2); - ASSERT_EQ(e.FromVertex(), *vertex2); - ASSERT_EQ(e.ToVertex(), *vertex1); - } - { - auto e = edges[1]; - ASSERT_EQ(e.EdgeType(), et4); - ASSERT_EQ(e.FromVertex(), *vertex2); - ASSERT_EQ(e.ToVertex(), *vertex2); - } - } - - ASSERT_FALSE(acc.Commit().HasError()); - } - - // Detach delete vertex - { - auto acc = store.Access(); - auto vertex1 = acc.FindVertex(gid_vertex1, memgraph::storage::View::NEW); - auto vertex2 = acc.FindVertex(gid_vertex2, memgraph::storage::View::NEW); - ASSERT_TRUE(vertex1); - ASSERT_TRUE(vertex2); - - auto et1 = acc.NameToEdgeType("et1"); - auto et2 = acc.NameToEdgeType("et2"); - auto et3 = acc.NameToEdgeType("et3"); - auto et4 = acc.NameToEdgeType("et4"); - - // Delete must fail - { - auto ret = acc.DeleteVertex(&*vertex1); - ASSERT_TRUE(ret.HasError()); - ASSERT_EQ(ret.GetError(), memgraph::storage::Error::VERTEX_HAS_EDGES); - } - - // Detach delete vertex - { - auto ret = acc.DetachDeleteVertex(&*vertex1); - ASSERT_TRUE(ret.HasValue()); - ASSERT_TRUE(*ret); - } - - // Check edges - { - auto ret = vertex1->InEdges(memgraph::storage::View::OLD); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - std::sort(edges.begin(), edges.end(), [](const auto &a, const auto &b) { return a.EdgeType() < b.EdgeType(); }); - ASSERT_EQ(edges.size(), 2); - ASSERT_EQ(*vertex1->InDegree(memgraph::storage::View::OLD), 2); - { - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et2); - ASSERT_EQ(e.FromVertex(), *vertex2); - ASSERT_EQ(e.ToVertex(), *vertex1); - } - { - auto e = edges[1]; - ASSERT_EQ(e.EdgeType(), et3); - ASSERT_EQ(e.FromVertex(), *vertex1); - ASSERT_EQ(e.ToVertex(), *vertex1); - } - } - ASSERT_EQ(vertex1->InEdges(memgraph::storage::View::NEW).GetError(), memgraph::storage::Error::DELETED_OBJECT); - ASSERT_EQ(vertex1->InDegree(memgraph::storage::View::NEW).GetError(), memgraph::storage::Error::DELETED_OBJECT); - { - auto ret = vertex1->OutEdges(memgraph::storage::View::OLD); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - std::sort(edges.begin(), edges.end(), [](const auto &a, const auto &b) { return a.EdgeType() < b.EdgeType(); }); - ASSERT_EQ(edges.size(), 2); - ASSERT_EQ(*vertex1->OutDegree(memgraph::storage::View::OLD), 2); - { - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et1); - ASSERT_EQ(e.FromVertex(), *vertex1); - ASSERT_EQ(e.ToVertex(), *vertex2); - } - { - auto e = edges[1]; - ASSERT_EQ(e.EdgeType(), et3); - ASSERT_EQ(e.FromVertex(), *vertex1); - ASSERT_EQ(e.ToVertex(), *vertex1); - } - } - ASSERT_EQ(vertex1->OutEdges(memgraph::storage::View::NEW).GetError(), memgraph::storage::Error::DELETED_OBJECT); - ASSERT_EQ(vertex1->OutDegree(memgraph::storage::View::NEW).GetError(), memgraph::storage::Error::DELETED_OBJECT); - { - auto ret = vertex2->InEdges(memgraph::storage::View::OLD); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - std::sort(edges.begin(), edges.end(), [](const auto &a, const auto &b) { return a.EdgeType() < b.EdgeType(); }); - ASSERT_EQ(edges.size(), 2); - ASSERT_EQ(*vertex2->InDegree(memgraph::storage::View::OLD), 2); - { - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et1); - ASSERT_EQ(e.FromVertex(), *vertex1); - ASSERT_EQ(e.ToVertex(), *vertex2); - } - { - auto e = edges[1]; - ASSERT_EQ(e.EdgeType(), et4); - ASSERT_EQ(e.FromVertex(), *vertex2); - ASSERT_EQ(e.ToVertex(), *vertex2); - } - } - { - auto ret = vertex2->InEdges(memgraph::storage::View::NEW); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex2->InDegree(memgraph::storage::View::NEW), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et4); - ASSERT_EQ(e.FromVertex(), *vertex2); - ASSERT_EQ(e.ToVertex(), *vertex2); - } - { - auto ret = vertex2->OutEdges(memgraph::storage::View::OLD); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - std::sort(edges.begin(), edges.end(), [](const auto &a, const auto &b) { return a.EdgeType() < b.EdgeType(); }); - ASSERT_EQ(edges.size(), 2); - ASSERT_EQ(*vertex2->OutDegree(memgraph::storage::View::OLD), 2); - { - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et2); - ASSERT_EQ(e.FromVertex(), *vertex2); - ASSERT_EQ(e.ToVertex(), *vertex1); - } - { - auto e = edges[1]; - ASSERT_EQ(e.EdgeType(), et4); - ASSERT_EQ(e.FromVertex(), *vertex2); - ASSERT_EQ(e.ToVertex(), *vertex2); - } - } - { - auto ret = vertex2->OutEdges(memgraph::storage::View::NEW); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex2->OutDegree(memgraph::storage::View::NEW), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et4); - ASSERT_EQ(e.FromVertex(), *vertex2); - ASSERT_EQ(e.ToVertex(), *vertex2); - } - - ASSERT_FALSE(acc.Commit().HasError()); - } - - // Check dataset - { - auto acc = store.Access(); - auto vertex1 = acc.FindVertex(gid_vertex1, memgraph::storage::View::NEW); - auto vertex2 = acc.FindVertex(gid_vertex2, memgraph::storage::View::NEW); - ASSERT_FALSE(vertex1); - ASSERT_TRUE(vertex2); - - auto et4 = acc.NameToEdgeType("et4"); - - // Check edges - { - auto ret = vertex2->InEdges(memgraph::storage::View::OLD); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex2->InDegree(memgraph::storage::View::OLD), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et4); - ASSERT_EQ(e.FromVertex(), *vertex2); - ASSERT_EQ(e.ToVertex(), *vertex2); - } - { - auto ret = vertex2->InEdges(memgraph::storage::View::NEW); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex2->InDegree(memgraph::storage::View::NEW), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et4); - ASSERT_EQ(e.FromVertex(), *vertex2); - ASSERT_EQ(e.ToVertex(), *vertex2); - } - { - auto ret = vertex2->OutEdges(memgraph::storage::View::OLD); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex2->OutDegree(memgraph::storage::View::OLD), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et4); - ASSERT_EQ(e.FromVertex(), *vertex2); - ASSERT_EQ(e.ToVertex(), *vertex2); - } - { - auto ret = vertex2->OutEdges(memgraph::storage::View::NEW); - ASSERT_TRUE(ret.HasValue()); - auto edges = ret.GetValue(); - ASSERT_EQ(edges.size(), 1); - ASSERT_EQ(*vertex2->OutDegree(memgraph::storage::View::NEW), 1); - auto e = edges[0]; - ASSERT_EQ(e.EdgeType(), et4); - ASSERT_EQ(e.FromVertex(), *vertex2); - ASSERT_EQ(e.ToVertex(), *vertex2); - } - } -} - -// NOLINTNEXTLINE(hicpp-special-member-functions) -TEST(StorageWithProperties, EdgePropertyCommit) { - memgraph::storage::Storage store({.items = {.properties_on_edges = true}}); - memgraph::storage::Gid gid = memgraph::storage::Gid::FromUint(std::numeric_limits::max()); - { - auto acc = store.Access(); - auto vertex = acc.CreateVertex(); - gid = vertex.Gid(); - auto et = acc.NameToEdgeType("et5"); - auto edge = acc.CreateEdge(&vertex, &vertex, et).GetValue(); - ASSERT_EQ(edge.EdgeType(), et); - ASSERT_EQ(edge.FromVertex(), vertex); - ASSERT_EQ(edge.ToVertex(), vertex); - - auto property = acc.NameToProperty("property5"); - - ASSERT_TRUE(edge.GetProperty(property, memgraph::storage::View::NEW)->IsNull()); - ASSERT_EQ(edge.Properties(memgraph::storage::View::NEW)->size(), 0); - - { - auto old_value = edge.SetProperty(property, memgraph::storage::PropertyValue("temporary")); - ASSERT_TRUE(old_value.HasValue()); - ASSERT_TRUE(old_value->IsNull()); - } - - ASSERT_EQ(edge.GetProperty(property, memgraph::storage::View::NEW)->ValueString(), "temporary"); - { - auto properties = edge.Properties(memgraph::storage::View::NEW).GetValue(); - ASSERT_EQ(properties.size(), 1); - ASSERT_EQ(properties[property].ValueString(), "temporary"); - } - - { - auto old_value = edge.SetProperty(property, memgraph::storage::PropertyValue("nandare")); - ASSERT_TRUE(old_value.HasValue()); - ASSERT_FALSE(old_value->IsNull()); - } - - ASSERT_EQ(edge.GetProperty(property, memgraph::storage::View::NEW)->ValueString(), "nandare"); - { - auto properties = edge.Properties(memgraph::storage::View::NEW).GetValue(); - ASSERT_EQ(properties.size(), 1); - ASSERT_EQ(properties[property].ValueString(), "nandare"); - } - - ASSERT_FALSE(acc.Commit().HasError()); - } - { - auto acc = store.Access(); - auto vertex = acc.FindVertex(gid, memgraph::storage::View::OLD); - ASSERT_TRUE(vertex); - auto edge = vertex->OutEdges(memgraph::storage::View::NEW).GetValue()[0]; - - auto property = acc.NameToProperty("property5"); - - ASSERT_EQ(edge.GetProperty(property, memgraph::storage::View::OLD)->ValueString(), "nandare"); - { - auto properties = edge.Properties(memgraph::storage::View::OLD).GetValue(); - ASSERT_EQ(properties.size(), 1); - ASSERT_EQ(properties[property].ValueString(), "nandare"); - } - - ASSERT_EQ(edge.GetProperty(property, memgraph::storage::View::NEW)->ValueString(), "nandare"); - { - auto properties = edge.Properties(memgraph::storage::View::NEW).GetValue(); - ASSERT_EQ(properties.size(), 1); - ASSERT_EQ(properties[property].ValueString(), "nandare"); - } - - auto other_property = acc.NameToProperty("other"); - - ASSERT_TRUE(edge.GetProperty(other_property, memgraph::storage::View::OLD)->IsNull()); - ASSERT_TRUE(edge.GetProperty(other_property, memgraph::storage::View::NEW)->IsNull()); - - acc.Abort(); - } - { - auto acc = store.Access(); - auto vertex = acc.FindVertex(gid, memgraph::storage::View::OLD); - ASSERT_TRUE(vertex); - auto edge = vertex->OutEdges(memgraph::storage::View::NEW).GetValue()[0]; - - auto property = acc.NameToProperty("property5"); - - { - auto old_value = edge.SetProperty(property, memgraph::storage::PropertyValue()); - ASSERT_TRUE(old_value.HasValue()); - ASSERT_FALSE(old_value->IsNull()); - } - - ASSERT_EQ(edge.GetProperty(property, memgraph::storage::View::OLD)->ValueString(), "nandare"); - { - auto properties = edge.Properties(memgraph::storage::View::OLD).GetValue(); - ASSERT_EQ(properties.size(), 1); - ASSERT_EQ(properties[property].ValueString(), "nandare"); - } - - ASSERT_TRUE(edge.GetProperty(property, memgraph::storage::View::NEW)->IsNull()); - ASSERT_EQ(edge.Properties(memgraph::storage::View::NEW)->size(), 0); - - { - auto old_value = edge.SetProperty(property, memgraph::storage::PropertyValue()); - ASSERT_TRUE(old_value.HasValue()); - ASSERT_TRUE(old_value->IsNull()); - } - - ASSERT_FALSE(acc.Commit().HasError()); - } - { - auto acc = store.Access(); - auto vertex = acc.FindVertex(gid, memgraph::storage::View::OLD); - ASSERT_TRUE(vertex); - auto edge = vertex->OutEdges(memgraph::storage::View::NEW).GetValue()[0]; - - auto property = acc.NameToProperty("property5"); - - ASSERT_TRUE(edge.GetProperty(property, memgraph::storage::View::OLD)->IsNull()); - ASSERT_TRUE(edge.GetProperty(property, memgraph::storage::View::NEW)->IsNull()); - ASSERT_EQ(edge.Properties(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(edge.Properties(memgraph::storage::View::NEW)->size(), 0); - - auto other_property = acc.NameToProperty("other"); - - ASSERT_TRUE(edge.GetProperty(other_property, memgraph::storage::View::OLD)->IsNull()); - ASSERT_TRUE(edge.GetProperty(other_property, memgraph::storage::View::NEW)->IsNull()); - - acc.Abort(); - } -} - -// NOLINTNEXTLINE(hicpp-special-member-functions) -TEST(StorageWithProperties, EdgePropertyAbort) { - memgraph::storage::Storage store({.items = {.properties_on_edges = true}}); - memgraph::storage::Gid gid = memgraph::storage::Gid::FromUint(std::numeric_limits::max()); - - // Create the vertex. - { - auto acc = store.Access(); - auto vertex = acc.CreateVertex(); - gid = vertex.Gid(); - auto et = acc.NameToEdgeType("et5"); - auto edge = acc.CreateEdge(&vertex, &vertex, et).GetValue(); - ASSERT_EQ(edge.EdgeType(), et); - ASSERT_EQ(edge.FromVertex(), vertex); - ASSERT_EQ(edge.ToVertex(), vertex); - ASSERT_FALSE(acc.Commit().HasError()); - } - - // Set property 5 to "nandare", but abort the transaction. - { - auto acc = store.Access(); - auto vertex = acc.FindVertex(gid, memgraph::storage::View::OLD); - ASSERT_TRUE(vertex); - auto edge = vertex->OutEdges(memgraph::storage::View::NEW).GetValue()[0]; - - auto property = acc.NameToProperty("property5"); - - ASSERT_TRUE(edge.GetProperty(property, memgraph::storage::View::NEW)->IsNull()); - ASSERT_EQ(edge.Properties(memgraph::storage::View::NEW)->size(), 0); - - { - auto old_value = edge.SetProperty(property, memgraph::storage::PropertyValue("temporary")); - ASSERT_TRUE(old_value.HasValue()); - ASSERT_TRUE(old_value->IsNull()); - } - - ASSERT_EQ(edge.GetProperty(property, memgraph::storage::View::NEW)->ValueString(), "temporary"); - { - auto properties = edge.Properties(memgraph::storage::View::NEW).GetValue(); - ASSERT_EQ(properties.size(), 1); - ASSERT_EQ(properties[property].ValueString(), "temporary"); - } - - { - auto old_value = edge.SetProperty(property, memgraph::storage::PropertyValue("nandare")); - ASSERT_TRUE(old_value.HasValue()); - ASSERT_FALSE(old_value->IsNull()); - } - - ASSERT_EQ(edge.GetProperty(property, memgraph::storage::View::NEW)->ValueString(), "nandare"); - { - auto properties = edge.Properties(memgraph::storage::View::NEW).GetValue(); - ASSERT_EQ(properties.size(), 1); - ASSERT_EQ(properties[property].ValueString(), "nandare"); - } - - acc.Abort(); - } - - // Check that property 5 is null. - { - auto acc = store.Access(); - auto vertex = acc.FindVertex(gid, memgraph::storage::View::OLD); - ASSERT_TRUE(vertex); - auto edge = vertex->OutEdges(memgraph::storage::View::NEW).GetValue()[0]; - - auto property = acc.NameToProperty("property5"); - - ASSERT_TRUE(edge.GetProperty(property, memgraph::storage::View::OLD)->IsNull()); - ASSERT_TRUE(edge.GetProperty(property, memgraph::storage::View::NEW)->IsNull()); - ASSERT_EQ(edge.Properties(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(edge.Properties(memgraph::storage::View::NEW)->size(), 0); - - auto other_property = acc.NameToProperty("other"); - - ASSERT_TRUE(edge.GetProperty(other_property, memgraph::storage::View::OLD)->IsNull()); - ASSERT_TRUE(edge.GetProperty(other_property, memgraph::storage::View::NEW)->IsNull()); - - acc.Abort(); - } - - // Set property 5 to "nandare". - { - auto acc = store.Access(); - auto vertex = acc.FindVertex(gid, memgraph::storage::View::OLD); - ASSERT_TRUE(vertex); - auto edge = vertex->OutEdges(memgraph::storage::View::NEW).GetValue()[0]; - - auto property = acc.NameToProperty("property5"); - - ASSERT_TRUE(edge.GetProperty(property, memgraph::storage::View::NEW)->IsNull()); - ASSERT_EQ(edge.Properties(memgraph::storage::View::NEW)->size(), 0); - - { - auto old_value = edge.SetProperty(property, memgraph::storage::PropertyValue("temporary")); - ASSERT_TRUE(old_value.HasValue()); - ASSERT_TRUE(old_value->IsNull()); - } - - ASSERT_EQ(edge.GetProperty(property, memgraph::storage::View::NEW)->ValueString(), "temporary"); - { - auto properties = edge.Properties(memgraph::storage::View::NEW).GetValue(); - ASSERT_EQ(properties.size(), 1); - ASSERT_EQ(properties[property].ValueString(), "temporary"); - } - - { - auto old_value = edge.SetProperty(property, memgraph::storage::PropertyValue("nandare")); - ASSERT_TRUE(old_value.HasValue()); - ASSERT_FALSE(old_value->IsNull()); - } - - ASSERT_EQ(edge.GetProperty(property, memgraph::storage::View::NEW)->ValueString(), "nandare"); - { - auto properties = edge.Properties(memgraph::storage::View::NEW).GetValue(); - ASSERT_EQ(properties.size(), 1); - ASSERT_EQ(properties[property].ValueString(), "nandare"); - } - - ASSERT_FALSE(acc.Commit().HasError()); - } - - // Check that property 5 is "nandare". - { - auto acc = store.Access(); - auto vertex = acc.FindVertex(gid, memgraph::storage::View::OLD); - ASSERT_TRUE(vertex); - auto edge = vertex->OutEdges(memgraph::storage::View::NEW).GetValue()[0]; - - auto property = acc.NameToProperty("property5"); - - ASSERT_EQ(edge.GetProperty(property, memgraph::storage::View::OLD)->ValueString(), "nandare"); - { - auto properties = edge.Properties(memgraph::storage::View::OLD).GetValue(); - ASSERT_EQ(properties.size(), 1); - ASSERT_EQ(properties[property].ValueString(), "nandare"); - } - - ASSERT_EQ(edge.GetProperty(property, memgraph::storage::View::NEW)->ValueString(), "nandare"); - { - auto properties = edge.Properties(memgraph::storage::View::NEW).GetValue(); - ASSERT_EQ(properties.size(), 1); - ASSERT_EQ(properties[property].ValueString(), "nandare"); - } - - auto other_property = acc.NameToProperty("other"); - - ASSERT_TRUE(edge.GetProperty(other_property, memgraph::storage::View::OLD)->IsNull()); - ASSERT_TRUE(edge.GetProperty(other_property, memgraph::storage::View::NEW)->IsNull()); - - acc.Abort(); - } - - // Set property 5 to null, but abort the transaction. - { - auto acc = store.Access(); - auto vertex = acc.FindVertex(gid, memgraph::storage::View::OLD); - ASSERT_TRUE(vertex); - auto edge = vertex->OutEdges(memgraph::storage::View::NEW).GetValue()[0]; - - auto property = acc.NameToProperty("property5"); - - ASSERT_EQ(edge.GetProperty(property, memgraph::storage::View::OLD)->ValueString(), "nandare"); - { - auto properties = edge.Properties(memgraph::storage::View::OLD).GetValue(); - ASSERT_EQ(properties.size(), 1); - ASSERT_EQ(properties[property].ValueString(), "nandare"); - } - - ASSERT_EQ(edge.GetProperty(property, memgraph::storage::View::NEW)->ValueString(), "nandare"); - { - auto properties = edge.Properties(memgraph::storage::View::NEW).GetValue(); - ASSERT_EQ(properties.size(), 1); - ASSERT_EQ(properties[property].ValueString(), "nandare"); - } - - { - auto old_value = edge.SetProperty(property, memgraph::storage::PropertyValue()); - ASSERT_TRUE(old_value.HasValue()); - ASSERT_FALSE(old_value->IsNull()); - } - - ASSERT_EQ(edge.GetProperty(property, memgraph::storage::View::OLD)->ValueString(), "nandare"); - { - auto properties = edge.Properties(memgraph::storage::View::OLD).GetValue(); - ASSERT_EQ(properties.size(), 1); - ASSERT_EQ(properties[property].ValueString(), "nandare"); - } - - ASSERT_TRUE(edge.GetProperty(property, memgraph::storage::View::NEW)->IsNull()); - ASSERT_EQ(edge.Properties(memgraph::storage::View::NEW)->size(), 0); - - acc.Abort(); - } - - // Check that property 5 is "nandare". - { - auto acc = store.Access(); - auto vertex = acc.FindVertex(gid, memgraph::storage::View::OLD); - ASSERT_TRUE(vertex); - auto edge = vertex->OutEdges(memgraph::storage::View::NEW).GetValue()[0]; - - auto property = acc.NameToProperty("property5"); - - ASSERT_EQ(edge.GetProperty(property, memgraph::storage::View::OLD)->ValueString(), "nandare"); - { - auto properties = edge.Properties(memgraph::storage::View::OLD).GetValue(); - ASSERT_EQ(properties.size(), 1); - ASSERT_EQ(properties[property].ValueString(), "nandare"); - } - - ASSERT_EQ(edge.GetProperty(property, memgraph::storage::View::NEW)->ValueString(), "nandare"); - { - auto properties = edge.Properties(memgraph::storage::View::NEW).GetValue(); - ASSERT_EQ(properties.size(), 1); - ASSERT_EQ(properties[property].ValueString(), "nandare"); - } - - auto other_property = acc.NameToProperty("other"); - - ASSERT_TRUE(edge.GetProperty(other_property, memgraph::storage::View::OLD)->IsNull()); - ASSERT_TRUE(edge.GetProperty(other_property, memgraph::storage::View::NEW)->IsNull()); - - acc.Abort(); - } - - // Set property 5 to null. - { - auto acc = store.Access(); - auto vertex = acc.FindVertex(gid, memgraph::storage::View::OLD); - ASSERT_TRUE(vertex); - auto edge = vertex->OutEdges(memgraph::storage::View::NEW).GetValue()[0]; - - auto property = acc.NameToProperty("property5"); - - ASSERT_EQ(edge.GetProperty(property, memgraph::storage::View::OLD)->ValueString(), "nandare"); - { - auto properties = edge.Properties(memgraph::storage::View::OLD).GetValue(); - ASSERT_EQ(properties.size(), 1); - ASSERT_EQ(properties[property].ValueString(), "nandare"); - } - - ASSERT_EQ(edge.GetProperty(property, memgraph::storage::View::NEW)->ValueString(), "nandare"); - { - auto properties = edge.Properties(memgraph::storage::View::NEW).GetValue(); - ASSERT_EQ(properties.size(), 1); - ASSERT_EQ(properties[property].ValueString(), "nandare"); - } - - { - auto old_value = edge.SetProperty(property, memgraph::storage::PropertyValue()); - ASSERT_TRUE(old_value.HasValue()); - ASSERT_FALSE(old_value->IsNull()); - } - - ASSERT_EQ(edge.GetProperty(property, memgraph::storage::View::OLD)->ValueString(), "nandare"); - { - auto properties = edge.Properties(memgraph::storage::View::OLD).GetValue(); - ASSERT_EQ(properties.size(), 1); - ASSERT_EQ(properties[property].ValueString(), "nandare"); - } - - ASSERT_TRUE(edge.GetProperty(property, memgraph::storage::View::NEW)->IsNull()); - ASSERT_EQ(edge.Properties(memgraph::storage::View::NEW)->size(), 0); - - ASSERT_FALSE(acc.Commit().HasError()); - } - - // Check that property 5 is null. - { - auto acc = store.Access(); - auto vertex = acc.FindVertex(gid, memgraph::storage::View::OLD); - ASSERT_TRUE(vertex); - auto edge = vertex->OutEdges(memgraph::storage::View::NEW).GetValue()[0]; - - auto property = acc.NameToProperty("property5"); - - ASSERT_TRUE(edge.GetProperty(property, memgraph::storage::View::OLD)->IsNull()); - ASSERT_TRUE(edge.GetProperty(property, memgraph::storage::View::NEW)->IsNull()); - ASSERT_EQ(edge.Properties(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(edge.Properties(memgraph::storage::View::NEW)->size(), 0); - - auto other_property = acc.NameToProperty("other"); - - ASSERT_TRUE(edge.GetProperty(other_property, memgraph::storage::View::OLD)->IsNull()); - ASSERT_TRUE(edge.GetProperty(other_property, memgraph::storage::View::NEW)->IsNull()); - - acc.Abort(); - } -} - -// NOLINTNEXTLINE(hicpp-special-member-functions) -TEST(StorageWithProperties, EdgePropertySerializationError) { - memgraph::storage::Storage store({.items = {.properties_on_edges = true}}); - memgraph::storage::Gid gid = memgraph::storage::Gid::FromUint(std::numeric_limits::max()); - { - auto acc = store.Access(); - auto vertex = acc.CreateVertex(); - gid = vertex.Gid(); - auto et = acc.NameToEdgeType("et5"); - auto edge = acc.CreateEdge(&vertex, &vertex, et).GetValue(); - ASSERT_EQ(edge.EdgeType(), et); - ASSERT_EQ(edge.FromVertex(), vertex); - ASSERT_EQ(edge.ToVertex(), vertex); - ASSERT_FALSE(acc.Commit().HasError()); - } - - auto acc1 = store.Access(); - auto acc2 = store.Access(); - - // Set property 1 to 123 in accessor 1. - { - auto vertex = acc1.FindVertex(gid, memgraph::storage::View::OLD); - ASSERT_TRUE(vertex); - auto edge = vertex->OutEdges(memgraph::storage::View::NEW).GetValue()[0]; - - auto property1 = acc1.NameToProperty("property1"); - auto property2 = acc1.NameToProperty("property2"); - - ASSERT_TRUE(edge.GetProperty(property1, memgraph::storage::View::OLD)->IsNull()); - ASSERT_TRUE(edge.GetProperty(property1, memgraph::storage::View::NEW)->IsNull()); - ASSERT_TRUE(edge.GetProperty(property2, memgraph::storage::View::OLD)->IsNull()); - ASSERT_TRUE(edge.GetProperty(property2, memgraph::storage::View::NEW)->IsNull()); - ASSERT_EQ(edge.Properties(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(edge.Properties(memgraph::storage::View::NEW)->size(), 0); - - { - auto old_value = edge.SetProperty(property1, memgraph::storage::PropertyValue(123)); - ASSERT_TRUE(old_value.HasValue()); - ASSERT_TRUE(old_value->IsNull()); - } - - ASSERT_TRUE(edge.GetProperty(property1, memgraph::storage::View::OLD)->IsNull()); - ASSERT_EQ(edge.GetProperty(property1, memgraph::storage::View::NEW)->ValueInt(), 123); - ASSERT_TRUE(edge.GetProperty(property2, memgraph::storage::View::OLD)->IsNull()); - ASSERT_TRUE(edge.GetProperty(property2, memgraph::storage::View::NEW)->IsNull()); - ASSERT_EQ(edge.Properties(memgraph::storage::View::OLD)->size(), 0); - { - auto properties = edge.Properties(memgraph::storage::View::NEW).GetValue(); - ASSERT_EQ(properties.size(), 1); - ASSERT_EQ(properties[property1].ValueInt(), 123); - } - } - - // Set property 2 to "nandare" in accessor 2. - { - auto vertex = acc2.FindVertex(gid, memgraph::storage::View::OLD); - ASSERT_TRUE(vertex); - auto edge = vertex->OutEdges(memgraph::storage::View::NEW).GetValue()[0]; - - auto property1 = acc2.NameToProperty("property1"); - auto property2 = acc2.NameToProperty("property2"); - - ASSERT_TRUE(edge.GetProperty(property1, memgraph::storage::View::OLD)->IsNull()); - ASSERT_TRUE(edge.GetProperty(property1, memgraph::storage::View::NEW)->IsNull()); - ASSERT_TRUE(edge.GetProperty(property2, memgraph::storage::View::OLD)->IsNull()); - ASSERT_TRUE(edge.GetProperty(property2, memgraph::storage::View::NEW)->IsNull()); - ASSERT_EQ(edge.Properties(memgraph::storage::View::OLD)->size(), 0); - ASSERT_EQ(edge.Properties(memgraph::storage::View::NEW)->size(), 0); - - { - auto res = edge.SetProperty(property2, memgraph::storage::PropertyValue("nandare")); - ASSERT_TRUE(res.HasError()); - ASSERT_EQ(res.GetError(), memgraph::storage::Error::SERIALIZATION_ERROR); - } - } - - // Finalize both accessors. - ASSERT_FALSE(acc1.Commit().HasError()); - acc2.Abort(); - - // Check which properties exist. - { - auto acc = store.Access(); - auto vertex = acc.FindVertex(gid, memgraph::storage::View::OLD); - ASSERT_TRUE(vertex); - auto edge = vertex->OutEdges(memgraph::storage::View::NEW).GetValue()[0]; - - auto property1 = acc.NameToProperty("property1"); - auto property2 = acc.NameToProperty("property2"); - - ASSERT_EQ(edge.GetProperty(property1, memgraph::storage::View::OLD)->ValueInt(), 123); - ASSERT_TRUE(edge.GetProperty(property2, memgraph::storage::View::OLD)->IsNull()); - { - auto properties = edge.Properties(memgraph::storage::View::OLD).GetValue(); - ASSERT_EQ(properties.size(), 1); - ASSERT_EQ(properties[property1].ValueInt(), 123); - } - - ASSERT_EQ(edge.GetProperty(property1, memgraph::storage::View::NEW)->ValueInt(), 123); - ASSERT_TRUE(edge.GetProperty(property2, memgraph::storage::View::NEW)->IsNull()); - { - auto properties = edge.Properties(memgraph::storage::View::NEW).GetValue(); - ASSERT_EQ(properties.size(), 1); - ASSERT_EQ(properties[property1].ValueInt(), 123); - } - - acc.Abort(); - } -} - -TEST(StorageWithProperties, EdgePropertyClear) { - memgraph::storage::Storage store({.items = {.properties_on_edges = true}}); - memgraph::storage::Gid gid; - auto property1 = store.NameToProperty("property1"); - auto property2 = store.NameToProperty("property2"); - { - auto acc = store.Access(); - auto vertex = acc.CreateVertex(); - gid = vertex.Gid(); - auto et = acc.NameToEdgeType("et5"); - auto edge = acc.CreateEdge(&vertex, &vertex, et).GetValue(); - ASSERT_EQ(edge.EdgeType(), et); - ASSERT_EQ(edge.FromVertex(), vertex); - ASSERT_EQ(edge.ToVertex(), vertex); - - auto old_value = edge.SetProperty(property1, memgraph::storage::PropertyValue("value")); - ASSERT_TRUE(old_value.HasValue()); - ASSERT_TRUE(old_value->IsNull()); - - ASSERT_FALSE(acc.Commit().HasError()); - } - { - auto acc = store.Access(); - auto vertex = acc.FindVertex(gid, memgraph::storage::View::OLD); - ASSERT_TRUE(vertex); - auto edge = vertex->OutEdges(memgraph::storage::View::NEW).GetValue()[0]; - - ASSERT_EQ(edge.GetProperty(property1, memgraph::storage::View::OLD)->ValueString(), "value"); - ASSERT_TRUE(edge.GetProperty(property2, memgraph::storage::View::OLD)->IsNull()); - ASSERT_THAT(edge.Properties(memgraph::storage::View::OLD).GetValue(), - UnorderedElementsAre(std::pair(property1, memgraph::storage::PropertyValue("value")))); - - { - auto old_values = edge.ClearProperties(); - ASSERT_TRUE(old_values.HasValue()); - ASSERT_FALSE(old_values->empty()); - } - - ASSERT_TRUE(edge.GetProperty(property1, memgraph::storage::View::NEW)->IsNull()); - ASSERT_TRUE(edge.GetProperty(property2, memgraph::storage::View::NEW)->IsNull()); - ASSERT_EQ(edge.Properties(memgraph::storage::View::NEW).GetValue().size(), 0); - - { - auto old_values = edge.ClearProperties(); - ASSERT_TRUE(old_values.HasValue()); - ASSERT_TRUE(old_values->empty()); - } - - ASSERT_TRUE(edge.GetProperty(property1, memgraph::storage::View::NEW)->IsNull()); - ASSERT_TRUE(edge.GetProperty(property2, memgraph::storage::View::NEW)->IsNull()); - ASSERT_EQ(edge.Properties(memgraph::storage::View::NEW).GetValue().size(), 0); - - acc.Abort(); - } - { - auto acc = store.Access(); - auto vertex = acc.FindVertex(gid, memgraph::storage::View::OLD); - ASSERT_TRUE(vertex); - auto edge = vertex->OutEdges(memgraph::storage::View::NEW).GetValue()[0]; - - auto old_value = edge.SetProperty(property2, memgraph::storage::PropertyValue(42)); - ASSERT_TRUE(old_value.HasValue()); - ASSERT_TRUE(old_value->IsNull()); - - ASSERT_FALSE(acc.Commit().HasError()); - } - { - auto acc = store.Access(); - auto vertex = acc.FindVertex(gid, memgraph::storage::View::OLD); - ASSERT_TRUE(vertex); - auto edge = vertex->OutEdges(memgraph::storage::View::NEW).GetValue()[0]; - - ASSERT_EQ(edge.GetProperty(property1, memgraph::storage::View::OLD)->ValueString(), "value"); - ASSERT_EQ(edge.GetProperty(property2, memgraph::storage::View::OLD)->ValueInt(), 42); - ASSERT_THAT(edge.Properties(memgraph::storage::View::OLD).GetValue(), - UnorderedElementsAre(std::pair(property1, memgraph::storage::PropertyValue("value")), - std::pair(property2, memgraph::storage::PropertyValue(42)))); - - { - auto old_values = edge.ClearProperties(); - ASSERT_TRUE(old_values.HasValue()); - ASSERT_FALSE(old_values->empty()); - } - - ASSERT_TRUE(edge.GetProperty(property1, memgraph::storage::View::NEW)->IsNull()); - ASSERT_TRUE(edge.GetProperty(property2, memgraph::storage::View::NEW)->IsNull()); - ASSERT_EQ(edge.Properties(memgraph::storage::View::NEW).GetValue().size(), 0); - - { - auto old_values = edge.ClearProperties(); - ASSERT_TRUE(old_values.HasValue()); - ASSERT_TRUE(old_values->empty()); - } - - ASSERT_TRUE(edge.GetProperty(property1, memgraph::storage::View::NEW)->IsNull()); - ASSERT_TRUE(edge.GetProperty(property2, memgraph::storage::View::NEW)->IsNull()); - ASSERT_EQ(edge.Properties(memgraph::storage::View::NEW).GetValue().size(), 0); - - ASSERT_FALSE(acc.Commit().HasError()); - } - { - auto acc = store.Access(); - auto vertex = acc.FindVertex(gid, memgraph::storage::View::OLD); - ASSERT_TRUE(vertex); - auto edge = vertex->OutEdges(memgraph::storage::View::NEW).GetValue()[0]; - - ASSERT_TRUE(edge.GetProperty(property1, memgraph::storage::View::NEW)->IsNull()); - ASSERT_TRUE(edge.GetProperty(property2, memgraph::storage::View::NEW)->IsNull()); - ASSERT_EQ(edge.Properties(memgraph::storage::View::NEW).GetValue().size(), 0); - - acc.Abort(); - } -} - -// NOLINTNEXTLINE(hicpp-special-member-functions) -TEST(StorageWithoutProperties, EdgePropertyAbort) { - memgraph::storage::Storage store({.items = {.properties_on_edges = false}}); - memgraph::storage::Gid gid = memgraph::storage::Gid::FromUint(std::numeric_limits::max()); - { - auto acc = store.Access(); - auto vertex = acc.CreateVertex(); - gid = vertex.Gid(); - auto et = acc.NameToEdgeType("et5"); - auto edge = acc.CreateEdge(&vertex, &vertex, et).GetValue(); - ASSERT_EQ(edge.EdgeType(), et); - ASSERT_EQ(edge.FromVertex(), vertex); - ASSERT_EQ(edge.ToVertex(), vertex); - ASSERT_FALSE(acc.Commit().HasError()); - } - { - auto acc = store.Access(); - auto vertex = acc.FindVertex(gid, memgraph::storage::View::OLD); - ASSERT_TRUE(vertex); - auto edge = vertex->OutEdges(memgraph::storage::View::NEW).GetValue()[0]; - - auto property = acc.NameToProperty("property5"); - - ASSERT_TRUE(edge.GetProperty(property, memgraph::storage::View::NEW)->IsNull()); - ASSERT_EQ(edge.Properties(memgraph::storage::View::NEW)->size(), 0); - - { - auto res = edge.SetProperty(property, memgraph::storage::PropertyValue("temporary")); - ASSERT_TRUE(res.HasError()); - ASSERT_EQ(res.GetError(), memgraph::storage::Error::PROPERTIES_DISABLED); - } - - ASSERT_TRUE(edge.GetProperty(property, memgraph::storage::View::NEW)->IsNull()); - ASSERT_EQ(edge.Properties(memgraph::storage::View::NEW)->size(), 0); - - { - auto res = edge.SetProperty(property, memgraph::storage::PropertyValue("nandare")); - ASSERT_TRUE(res.HasError()); - ASSERT_EQ(res.GetError(), memgraph::storage::Error::PROPERTIES_DISABLED); - } - - ASSERT_TRUE(edge.GetProperty(property, memgraph::storage::View::NEW)->IsNull()); - ASSERT_EQ(edge.Properties(memgraph::storage::View::NEW)->size(), 0); - - acc.Abort(); - } - { - auto acc = store.Access(); - auto vertex = acc.FindVertex(gid, memgraph::storage::View::OLD); - ASSERT_TRUE(vertex); - auto edge = vertex->OutEdges(memgraph::storage::View::NEW).GetValue()[0]; - - auto property = acc.NameToProperty("property5"); - - ASSERT_TRUE(edge.GetProperty(property, memgraph::storage::View::OLD)->IsNull()); - ASSERT_EQ(edge.Properties(memgraph::storage::View::OLD)->size(), 0); - - ASSERT_TRUE(edge.GetProperty(property, memgraph::storage::View::NEW)->IsNull()); - ASSERT_EQ(edge.Properties(memgraph::storage::View::NEW)->size(), 0); - - auto other_property = acc.NameToProperty("other"); - - ASSERT_TRUE(edge.GetProperty(other_property, memgraph::storage::View::OLD)->IsNull()); - ASSERT_TRUE(edge.GetProperty(other_property, memgraph::storage::View::NEW)->IsNull()); - - acc.Abort(); - } -} - -TEST(StorageWithoutProperties, EdgePropertyClear) { - memgraph::storage::Storage store({.items = {.properties_on_edges = false}}); - memgraph::storage::Gid gid; - { - auto acc = store.Access(); - auto vertex = acc.CreateVertex(); - gid = vertex.Gid(); - auto et = acc.NameToEdgeType("et5"); - auto edge = acc.CreateEdge(&vertex, &vertex, et).GetValue(); - ASSERT_EQ(edge.EdgeType(), et); - ASSERT_EQ(edge.FromVertex(), vertex); - ASSERT_EQ(edge.ToVertex(), vertex); - ASSERT_FALSE(acc.Commit().HasError()); - } - { - auto acc = store.Access(); - auto vertex = acc.FindVertex(gid, memgraph::storage::View::OLD); - ASSERT_TRUE(vertex); - auto edge = vertex->OutEdges(memgraph::storage::View::NEW).GetValue()[0]; - - ASSERT_EQ(edge.ClearProperties().GetError(), memgraph::storage::Error::PROPERTIES_DISABLED); - - acc.Abort(); - } -} - -TEST(StorageWithProperties, EdgeNonexistentPropertyAPI) { - memgraph::storage::Storage store({.items = {.properties_on_edges = true}}); - - auto property = store.NameToProperty("property"); - - auto acc = store.Access(); - auto vertex = acc.CreateVertex(); - auto edge = acc.CreateEdge(&vertex, &vertex, acc.NameToEdgeType("edge")); - ASSERT_TRUE(edge.HasValue()); - - // Check state before (OLD view). - ASSERT_EQ(edge->Properties(memgraph::storage::View::OLD).GetError(), memgraph::storage::Error::NONEXISTENT_OBJECT); - ASSERT_EQ(edge->GetProperty(property, memgraph::storage::View::OLD).GetError(), - memgraph::storage::Error::NONEXISTENT_OBJECT); - - // Check state before (NEW view). - ASSERT_EQ(edge->Properties(memgraph::storage::View::NEW)->size(), 0); - ASSERT_EQ(*edge->GetProperty(property, memgraph::storage::View::NEW), memgraph::storage::PropertyValue()); - - // Modify edge. - ASSERT_TRUE(edge->SetProperty(property, memgraph::storage::PropertyValue("value"))->IsNull()); - - // Check state after (OLD view). - ASSERT_EQ(edge->Properties(memgraph::storage::View::OLD).GetError(), memgraph::storage::Error::NONEXISTENT_OBJECT); - ASSERT_EQ(edge->GetProperty(property, memgraph::storage::View::OLD).GetError(), - memgraph::storage::Error::NONEXISTENT_OBJECT); - - // Check state after (NEW view). - ASSERT_EQ(edge->Properties(memgraph::storage::View::NEW)->size(), 1); - ASSERT_EQ(*edge->GetProperty(property, memgraph::storage::View::NEW), memgraph::storage::PropertyValue("value")); - - ASSERT_FALSE(acc.Commit().HasError()); -} diff --git a/tests/unit/storage_v2_gc.cpp b/tests/unit/storage_v2_gc.cpp deleted file mode 100644 index 34b7b74aa..000000000 --- a/tests/unit/storage_v2_gc.cpp +++ /dev/null @@ -1,200 +0,0 @@ -// Copyright 2022 Memgraph Ltd. -// -// Use of this software is governed by the Business Source License -// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source -// License, and you may not use this file except in compliance with the Business Source License. -// -// As of the Change Date specified in that file, in accordance with -// the Business Source License, use of this software will be governed -// by the Apache License, Version 2.0, included in the file -// licenses/APL.txt. - -#include -#include - -#include "storage/v2/storage.hpp" - -using testing::UnorderedElementsAre; - -// TODO: The point of these is not to test GC fully, these are just simple -// sanity checks. These will be superseded by a more sophisticated stress test -// which will verify that GC is working properly in a multithreaded environment. - -// A simple test trying to get GC to run while a transaction is still alive and -// then verify that GC didn't delete anything it shouldn't have. -// NOLINTNEXTLINE(hicpp-special-member-functions) -TEST(StorageV2Gc, Sanity) { - memgraph::storage::Storage storage(memgraph::storage::Config{ - .gc = {.type = memgraph::storage::Config::Gc::Type::PERIODIC, .interval = std::chrono::milliseconds(100)}}); - - std::vector vertices; - - { - auto acc = storage.Access(); - // Create some vertices, but delete some of them immediately. - for (uint64_t i = 0; i < 1000; ++i) { - auto vertex = acc.CreateVertex(); - vertices.push_back(vertex.Gid()); - } - - acc.AdvanceCommand(); - - for (uint64_t i = 0; i < 1000; ++i) { - auto vertex = acc.FindVertex(vertices[i], memgraph::storage::View::OLD); - ASSERT_TRUE(vertex.has_value()); - if (i % 5 == 0) { - EXPECT_FALSE(acc.DeleteVertex(&vertex.value()).HasError()); - } - } - - // Wait for GC. - std::this_thread::sleep_for(std::chrono::milliseconds(300)); - - for (uint64_t i = 0; i < 1000; ++i) { - auto vertex_old = acc.FindVertex(vertices[i], memgraph::storage::View::OLD); - auto vertex_new = acc.FindVertex(vertices[i], memgraph::storage::View::NEW); - EXPECT_TRUE(vertex_old.has_value()); - EXPECT_EQ(vertex_new.has_value(), i % 5 != 0); - } - - ASSERT_FALSE(acc.Commit().HasError()); - } - - // Verify existing vertices and add labels to some of them. - { - auto acc = storage.Access(); - for (uint64_t i = 0; i < 1000; ++i) { - auto vertex = acc.FindVertex(vertices[i], memgraph::storage::View::OLD); - EXPECT_EQ(vertex.has_value(), i % 5 != 0); - - if (vertex.has_value()) { - EXPECT_FALSE(vertex->AddLabel(memgraph::storage::LabelId::FromUint(3 * i)).HasError()); - EXPECT_FALSE(vertex->AddLabel(memgraph::storage::LabelId::FromUint(3 * i + 1)).HasError()); - EXPECT_FALSE(vertex->AddLabel(memgraph::storage::LabelId::FromUint(3 * i + 2)).HasError()); - } - } - - // Wait for GC. - std::this_thread::sleep_for(std::chrono::milliseconds(300)); - - // Verify labels. - for (uint64_t i = 0; i < 1000; ++i) { - auto vertex = acc.FindVertex(vertices[i], memgraph::storage::View::NEW); - EXPECT_EQ(vertex.has_value(), i % 5 != 0); - - if (vertex.has_value()) { - auto labels_old = vertex->Labels(memgraph::storage::View::OLD); - EXPECT_TRUE(labels_old.HasValue()); - EXPECT_TRUE(labels_old->empty()); - - auto labels_new = vertex->Labels(memgraph::storage::View::NEW); - EXPECT_TRUE(labels_new.HasValue()); - EXPECT_THAT(labels_new.GetValue(), UnorderedElementsAre(memgraph::storage::LabelId::FromUint(3 * i), - memgraph::storage::LabelId::FromUint(3 * i + 1), - memgraph::storage::LabelId::FromUint(3 * i + 2))); - } - } - - ASSERT_FALSE(acc.Commit().HasError()); - } - - // Add and remove some edges. - { - auto acc = storage.Access(); - for (uint64_t i = 0; i < 1000; ++i) { - auto from_vertex = acc.FindVertex(vertices[i], memgraph::storage::View::OLD); - auto to_vertex = acc.FindVertex(vertices[(i + 1) % 1000], memgraph::storage::View::OLD); - EXPECT_EQ(from_vertex.has_value(), i % 5 != 0); - EXPECT_EQ(to_vertex.has_value(), (i + 1) % 5 != 0); - - if (from_vertex.has_value() && to_vertex.has_value()) { - EXPECT_FALSE( - acc.CreateEdge(&from_vertex.value(), &to_vertex.value(), memgraph::storage::EdgeTypeId::FromUint(i)) - .HasError()); - } - } - - // Detach delete some vertices. - for (uint64_t i = 0; i < 1000; ++i) { - auto vertex = acc.FindVertex(vertices[i], memgraph::storage::View::NEW); - EXPECT_EQ(vertex.has_value(), i % 5 != 0); - if (vertex.has_value()) { - if (i % 3 == 0) { - EXPECT_FALSE(acc.DetachDeleteVertex(&vertex.value()).HasError()); - } - } - } - - // Wait for GC. - std::this_thread::sleep_for(std::chrono::milliseconds(300)); - - // Vertify edges. - for (uint64_t i = 0; i < 1000; ++i) { - auto vertex = acc.FindVertex(vertices[i], memgraph::storage::View::NEW); - EXPECT_EQ(vertex.has_value(), i % 5 != 0 && i % 3 != 0); - if (vertex.has_value()) { - auto out_edges = vertex->OutEdges(memgraph::storage::View::NEW); - if (i % 5 != 4 && i % 3 != 2) { - EXPECT_EQ(out_edges.GetValue().size(), 1); - EXPECT_EQ(*vertex->OutDegree(memgraph::storage::View::NEW), 1); - EXPECT_EQ(out_edges.GetValue().at(0).EdgeType().AsUint(), i); - } else { - EXPECT_TRUE(out_edges->empty()); - } - - auto in_edges = vertex->InEdges(memgraph::storage::View::NEW); - if (i % 5 != 1 && i % 3 != 1) { - EXPECT_EQ(in_edges.GetValue().size(), 1); - EXPECT_EQ(*vertex->InDegree(memgraph::storage::View::NEW), 1); - EXPECT_EQ(in_edges.GetValue().at(0).EdgeType().AsUint(), (i + 999) % 1000); - } else { - EXPECT_TRUE(in_edges->empty()); - } - } - } - - ASSERT_FALSE(acc.Commit().HasError()); - } -} - -// A simple sanity check for index GC: -// 1. Start transaction 0, create some vertices, add a label to them and -// commit. -// 2. Start transaction 1. -// 3. Start transaction 2, remove the labels and commit; -// 4. Wait for GC. GC shouldn't remove the vertices from index because -// transaction 1 can still see them with that label. -// NOLINTNEXTLINE(hicpp-special-member-functions) -TEST(StorageV2Gc, Indices) { - memgraph::storage::Storage storage(memgraph::storage::Config{ - .gc = {.type = memgraph::storage::Config::Gc::Type::PERIODIC, .interval = std::chrono::milliseconds(100)}}); - - ASSERT_TRUE(storage.CreateIndex(storage.NameToLabel("label"))); - - { - auto acc0 = storage.Access(); - for (uint64_t i = 0; i < 1000; ++i) { - auto vertex = acc0.CreateVertex(); - ASSERT_TRUE(*vertex.AddLabel(acc0.NameToLabel("label"))); - } - ASSERT_FALSE(acc0.Commit().HasError()); - } - { - auto acc1 = storage.Access(); - - auto acc2 = storage.Access(); - for (auto vertex : acc2.Vertices(memgraph::storage::View::OLD)) { - ASSERT_TRUE(*vertex.RemoveLabel(acc2.NameToLabel("label"))); - } - ASSERT_FALSE(acc2.Commit().HasError()); - - // Wait for GC. - std::this_thread::sleep_for(std::chrono::milliseconds(300)); - - std::set gids; - for (auto vertex : acc1.Vertices(acc1.NameToLabel("label"), memgraph::storage::View::OLD)) { - gids.insert(vertex.Gid()); - } - EXPECT_EQ(gids.size(), 1000); - } -} diff --git a/tests/unit/storage_v2_indices.cpp b/tests/unit/storage_v2_indices.cpp deleted file mode 100644 index 894752bf7..000000000 --- a/tests/unit/storage_v2_indices.cpp +++ /dev/null @@ -1,832 +0,0 @@ -// Copyright 2022 Memgraph Ltd. -// -// Use of this software is governed by the Business Source License -// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source -// License, and you may not use this file except in compliance with the Business Source License. -// -// As of the Change Date specified in that file, in accordance with -// the Business Source License, use of this software will be governed -// by the Apache License, Version 2.0, included in the file -// licenses/APL.txt. - -#include -#include - -#include "storage/v2/property_value.hpp" -#include "storage/v2/storage.hpp" -#include "storage/v2/temporal.hpp" - -// NOLINTNEXTLINE(google-build-using-namespace) -using namespace memgraph::storage; - -using testing::IsEmpty; -using testing::UnorderedElementsAre; - -// NOLINTNEXTLINE(cppcoreguidelines-macro-usage) -#define ASSERT_NO_ERROR(result) ASSERT_FALSE((result).HasError()) - -class IndexTest : public testing::Test { - protected: - void SetUp() override { - auto acc = storage.Access(); - prop_id = acc.NameToProperty("id"); - prop_val = acc.NameToProperty("val"); - label1 = acc.NameToLabel("label1"); - label2 = acc.NameToLabel("label2"); - vertex_id = 0; - } - - Storage storage; - PropertyId prop_id; - PropertyId prop_val; - LabelId label1; - LabelId label2; - - VertexAccessor CreateVertex(Storage::Accessor *accessor) { - VertexAccessor vertex = accessor->CreateVertex(); - MG_ASSERT(!vertex.SetProperty(prop_id, PropertyValue(vertex_id++)).HasError()); - return vertex; - } - - template - std::vector GetIds(TIterable iterable, View view = View::OLD) { - std::vector ret; - for (auto vertex : iterable) { - ret.push_back(vertex.GetProperty(prop_id, view)->ValueInt()); - } - return ret; - } - - private: - int vertex_id; -}; - -// NOLINTNEXTLINE(hicpp-special-member-functions) -TEST_F(IndexTest, LabelIndexCreate) { - { - auto acc = storage.Access(); - EXPECT_FALSE(acc.LabelIndexExists(label1)); - } - EXPECT_EQ(storage.ListAllIndices().label.size(), 0); - - { - auto acc = storage.Access(); - for (int i = 0; i < 10; ++i) { - auto vertex = CreateVertex(&acc); - ASSERT_NO_ERROR(vertex.AddLabel(i % 2 ? label1 : label2)); - } - ASSERT_NO_ERROR(acc.Commit()); - } - - EXPECT_TRUE(storage.CreateIndex(label1)); - - { - auto acc = storage.Access(); - EXPECT_THAT(GetIds(acc.Vertices(label1, View::OLD), View::OLD), UnorderedElementsAre(1, 3, 5, 7, 9)); - EXPECT_THAT(GetIds(acc.Vertices(label1, View::NEW), View::NEW), UnorderedElementsAre(1, 3, 5, 7, 9)); - } - - { - auto acc = storage.Access(); - for (int i = 10; i < 20; ++i) { - auto vertex = CreateVertex(&acc); - ASSERT_NO_ERROR(vertex.AddLabel(i % 2 ? label1 : label2)); - } - - EXPECT_THAT(GetIds(acc.Vertices(label1, View::OLD), View::OLD), UnorderedElementsAre(1, 3, 5, 7, 9)); - EXPECT_THAT(GetIds(acc.Vertices(label1, View::NEW), View::NEW), - UnorderedElementsAre(1, 3, 5, 7, 9, 11, 13, 15, 17, 19)); - - acc.AdvanceCommand(); - - EXPECT_THAT(GetIds(acc.Vertices(label1, View::OLD), View::NEW), - UnorderedElementsAre(1, 3, 5, 7, 9, 11, 13, 15, 17, 19)); - EXPECT_THAT(GetIds(acc.Vertices(label1, View::NEW), View::NEW), - UnorderedElementsAre(1, 3, 5, 7, 9, 11, 13, 15, 17, 19)); - - acc.Abort(); - } - - { - auto acc = storage.Access(); - for (int i = 10; i < 20; ++i) { - auto vertex = CreateVertex(&acc); - ASSERT_NO_ERROR(vertex.AddLabel(i % 2 ? label1 : label2)); - } - - EXPECT_THAT(GetIds(acc.Vertices(label1, View::OLD), View::OLD), UnorderedElementsAre(1, 3, 5, 7, 9)); - EXPECT_THAT(GetIds(acc.Vertices(label1, View::NEW), View::NEW), - UnorderedElementsAre(1, 3, 5, 7, 9, 21, 23, 25, 27, 29)); - - acc.AdvanceCommand(); - - EXPECT_THAT(GetIds(acc.Vertices(label1, View::OLD), View::NEW), - UnorderedElementsAre(1, 3, 5, 7, 9, 21, 23, 25, 27, 29)); - EXPECT_THAT(GetIds(acc.Vertices(label1, View::NEW), View::NEW), - UnorderedElementsAre(1, 3, 5, 7, 9, 21, 23, 25, 27, 29)); - - ASSERT_NO_ERROR(acc.Commit()); - } - - { - auto acc = storage.Access(); - EXPECT_THAT(GetIds(acc.Vertices(label1, View::OLD), View::OLD), - UnorderedElementsAre(1, 3, 5, 7, 9, 21, 23, 25, 27, 29)); - EXPECT_THAT(GetIds(acc.Vertices(label1, View::NEW), View::NEW), - UnorderedElementsAre(1, 3, 5, 7, 9, 21, 23, 25, 27, 29)); - - acc.AdvanceCommand(); - - EXPECT_THAT(GetIds(acc.Vertices(label1, View::OLD), View::NEW), - UnorderedElementsAre(1, 3, 5, 7, 9, 21, 23, 25, 27, 29)); - EXPECT_THAT(GetIds(acc.Vertices(label1, View::NEW), View::NEW), - UnorderedElementsAre(1, 3, 5, 7, 9, 21, 23, 25, 27, 29)); - - ASSERT_NO_ERROR(acc.Commit()); - } -} - -// NOLINTNEXTLINE(hicpp-special-member-functions) -TEST_F(IndexTest, LabelIndexDrop) { - { - auto acc = storage.Access(); - EXPECT_FALSE(acc.LabelIndexExists(label1)); - } - EXPECT_EQ(storage.ListAllIndices().label.size(), 0); - - { - auto acc = storage.Access(); - for (int i = 0; i < 10; ++i) { - auto vertex = CreateVertex(&acc); - ASSERT_NO_ERROR(vertex.AddLabel(i % 2 ? label1 : label2)); - } - ASSERT_NO_ERROR(acc.Commit()); - } - - EXPECT_TRUE(storage.CreateIndex(label1)); - - { - auto acc = storage.Access(); - EXPECT_THAT(GetIds(acc.Vertices(label1, View::OLD), View::OLD), UnorderedElementsAre(1, 3, 5, 7, 9)); - EXPECT_THAT(GetIds(acc.Vertices(label1, View::NEW), View::NEW), UnorderedElementsAre(1, 3, 5, 7, 9)); - } - - EXPECT_TRUE(storage.DropIndex(label1)); - { - auto acc = storage.Access(); - EXPECT_FALSE(acc.LabelIndexExists(label1)); - } - EXPECT_EQ(storage.ListAllIndices().label.size(), 0); - - EXPECT_FALSE(storage.DropIndex(label1)); - { - auto acc = storage.Access(); - EXPECT_FALSE(acc.LabelIndexExists(label1)); - } - EXPECT_EQ(storage.ListAllIndices().label.size(), 0); - - { - auto acc = storage.Access(); - for (int i = 10; i < 20; ++i) { - auto vertex = CreateVertex(&acc); - ASSERT_NO_ERROR(vertex.AddLabel(i % 2 ? label1 : label2)); - } - ASSERT_NO_ERROR(acc.Commit()); - } - - EXPECT_TRUE(storage.CreateIndex(label1)); - { - auto acc = storage.Access(); - EXPECT_TRUE(acc.LabelIndexExists(label1)); - } - EXPECT_THAT(storage.ListAllIndices().label, UnorderedElementsAre(label1)); - - { - auto acc = storage.Access(); - - EXPECT_THAT(GetIds(acc.Vertices(label1, View::OLD), View::OLD), - UnorderedElementsAre(1, 3, 5, 7, 9, 11, 13, 15, 17, 19)); - EXPECT_THAT(GetIds(acc.Vertices(label1, View::NEW), View::NEW), - UnorderedElementsAre(1, 3, 5, 7, 9, 11, 13, 15, 17, 19)); - - acc.AdvanceCommand(); - - EXPECT_THAT(GetIds(acc.Vertices(label1, View::OLD), View::NEW), - UnorderedElementsAre(1, 3, 5, 7, 9, 11, 13, 15, 17, 19)); - EXPECT_THAT(GetIds(acc.Vertices(label1, View::NEW), View::NEW), - UnorderedElementsAre(1, 3, 5, 7, 9, 11, 13, 15, 17, 19)); - } -} - -// NOLINTNEXTLINE(hicpp-special-member-functions) -TEST_F(IndexTest, LabelIndexBasic) { - // The following steps are performed and index correctness is validated after - // each step: - // 1. Create 10 vertices numbered from 0 to 9. - // 2. Add Label1 to odd numbered, and Label2 to even numbered vertices. - // 3. Remove Label1 from odd numbered vertices, and add it to even numbered - // vertices. - // 4. Delete even numbered vertices. - EXPECT_TRUE(storage.CreateIndex(label1)); - EXPECT_TRUE(storage.CreateIndex(label2)); - - auto acc = storage.Access(); - EXPECT_THAT(storage.ListAllIndices().label, UnorderedElementsAre(label1, label2)); - EXPECT_THAT(GetIds(acc.Vertices(label1, View::OLD), View::OLD), IsEmpty()); - EXPECT_THAT(GetIds(acc.Vertices(label2, View::OLD), View::OLD), IsEmpty()); - EXPECT_THAT(GetIds(acc.Vertices(label1, View::NEW), View::NEW), IsEmpty()); - EXPECT_THAT(GetIds(acc.Vertices(label2, View::NEW), View::NEW), IsEmpty()); - - for (int i = 0; i < 10; ++i) { - auto vertex = CreateVertex(&acc); - ASSERT_NO_ERROR(vertex.AddLabel(i % 2 ? label1 : label2)); - } - - EXPECT_THAT(GetIds(acc.Vertices(label1, View::OLD), View::OLD), IsEmpty()); - EXPECT_THAT(GetIds(acc.Vertices(label2, View::OLD), View::OLD), IsEmpty()); - EXPECT_THAT(GetIds(acc.Vertices(label1, View::NEW), View::NEW), UnorderedElementsAre(1, 3, 5, 7, 9)); - EXPECT_THAT(GetIds(acc.Vertices(label2, View::NEW), View::NEW), UnorderedElementsAre(0, 2, 4, 6, 8)); - - acc.AdvanceCommand(); - EXPECT_THAT(GetIds(acc.Vertices(label1, View::OLD), View::OLD), UnorderedElementsAre(1, 3, 5, 7, 9)); - EXPECT_THAT(GetIds(acc.Vertices(label2, View::OLD), View::OLD), UnorderedElementsAre(0, 2, 4, 6, 8)); - EXPECT_THAT(GetIds(acc.Vertices(label1, View::NEW), View::NEW), UnorderedElementsAre(1, 3, 5, 7, 9)); - EXPECT_THAT(GetIds(acc.Vertices(label2, View::NEW), View::NEW), UnorderedElementsAre(0, 2, 4, 6, 8)); - - for (auto vertex : acc.Vertices(View::OLD)) { - int64_t id = vertex.GetProperty(prop_id, View::OLD)->ValueInt(); - if (id % 2) { - ASSERT_NO_ERROR(vertex.RemoveLabel(label1)); - } else { - ASSERT_NO_ERROR(vertex.AddLabel(label1)); - } - } - - EXPECT_THAT(GetIds(acc.Vertices(label1, View::OLD), View::OLD), UnorderedElementsAre(1, 3, 5, 7, 9)); - EXPECT_THAT(GetIds(acc.Vertices(label2, View::OLD), View::OLD), UnorderedElementsAre(0, 2, 4, 6, 8)); - EXPECT_THAT(GetIds(acc.Vertices(label1, View::NEW), View::NEW), UnorderedElementsAre(0, 2, 4, 6, 8)); - EXPECT_THAT(GetIds(acc.Vertices(label2, View::NEW), View::NEW), UnorderedElementsAre(0, 2, 4, 6, 8)); - - for (auto vertex : acc.Vertices(View::OLD)) { - int64_t id = vertex.GetProperty(prop_id, View::OLD)->ValueInt(); - if (id % 2 == 0) { - ASSERT_NO_ERROR(acc.DeleteVertex(&vertex)); - } - } - - EXPECT_THAT(GetIds(acc.Vertices(label1, View::OLD), View::OLD), UnorderedElementsAre(1, 3, 5, 7, 9)); - EXPECT_THAT(GetIds(acc.Vertices(label2, View::OLD), View::OLD), UnorderedElementsAre(0, 2, 4, 6, 8)); - EXPECT_THAT(GetIds(acc.Vertices(label1, View::NEW), View::NEW), IsEmpty()); - EXPECT_THAT(GetIds(acc.Vertices(label2, View::NEW), View::NEW), IsEmpty()); - - acc.AdvanceCommand(); - - EXPECT_THAT(GetIds(acc.Vertices(label1, View::OLD), View::OLD), IsEmpty()); - EXPECT_THAT(GetIds(acc.Vertices(label2, View::OLD), View::OLD), IsEmpty()); - EXPECT_THAT(GetIds(acc.Vertices(label1, View::NEW), View::NEW), IsEmpty()); - EXPECT_THAT(GetIds(acc.Vertices(label2, View::NEW), View::NEW), IsEmpty()); -} - -// NOLINTNEXTLINE(hicpp-special-member-functions) -TEST_F(IndexTest, LabelIndexDuplicateVersions) { - // By removing labels and adding them again we create duplicate entries for - // the same vertex in the index (they only differ by the timestamp). This test - // checks that duplicates are properly filtered out. - EXPECT_TRUE(storage.CreateIndex(label1)); - EXPECT_TRUE(storage.CreateIndex(label2)); - - { - auto acc = storage.Access(); - for (int i = 0; i < 5; ++i) { - auto vertex = CreateVertex(&acc); - ASSERT_NO_ERROR(vertex.AddLabel(label1)); - } - - EXPECT_THAT(GetIds(acc.Vertices(label1, View::NEW), View::NEW), UnorderedElementsAre(0, 1, 2, 3, 4)); - - ASSERT_NO_ERROR(acc.Commit()); - } - - { - auto acc = storage.Access(); - EXPECT_THAT(GetIds(acc.Vertices(label1, View::OLD), View::OLD), UnorderedElementsAre(0, 1, 2, 3, 4)); - - for (auto vertex : acc.Vertices(View::OLD)) { - ASSERT_NO_ERROR(vertex.RemoveLabel(label1)); - } - - EXPECT_THAT(GetIds(acc.Vertices(label1, View::OLD), View::OLD), UnorderedElementsAre(0, 1, 2, 3, 4)); - EXPECT_THAT(GetIds(acc.Vertices(label1, View::NEW), View::NEW), IsEmpty()); - - for (auto vertex : acc.Vertices(View::OLD)) { - ASSERT_NO_ERROR(vertex.AddLabel(label1)); - } - EXPECT_THAT(GetIds(acc.Vertices(label1, View::OLD), View::OLD), UnorderedElementsAre(0, 1, 2, 3, 4)); - EXPECT_THAT(GetIds(acc.Vertices(label1, View::NEW), View::NEW), UnorderedElementsAre(0, 1, 2, 3, 4)); - } -} - -// NOLINTNEXTLINE(hicpp-special-member-functions) -TEST_F(IndexTest, LabelIndexTransactionalIsolation) { - // Check that transactions only see entries they are supposed to see. - EXPECT_TRUE(storage.CreateIndex(label1)); - EXPECT_TRUE(storage.CreateIndex(label2)); - - auto acc_before = storage.Access(); - auto acc = storage.Access(); - auto acc_after = storage.Access(); - - for (int i = 0; i < 5; ++i) { - auto vertex = CreateVertex(&acc); - ASSERT_NO_ERROR(vertex.AddLabel(label1)); - } - - EXPECT_THAT(GetIds(acc.Vertices(label1, View::NEW), View::NEW), UnorderedElementsAre(0, 1, 2, 3, 4)); - EXPECT_THAT(GetIds(acc_before.Vertices(label1, View::NEW), View::NEW), IsEmpty()); - EXPECT_THAT(GetIds(acc_after.Vertices(label1, View::NEW), View::NEW), IsEmpty()); - - ASSERT_NO_ERROR(acc.Commit()); - - auto acc_after_commit = storage.Access(); - - EXPECT_THAT(GetIds(acc_before.Vertices(label1, View::NEW), View::NEW), IsEmpty()); - EXPECT_THAT(GetIds(acc_after.Vertices(label1, View::NEW), View::NEW), IsEmpty()); - EXPECT_THAT(GetIds(acc_after_commit.Vertices(label1, View::NEW), View::NEW), UnorderedElementsAre(0, 1, 2, 3, 4)); -} - -// NOLINTNEXTLINE(hicpp-special-member-functions) -TEST_F(IndexTest, LabelIndexCountEstimate) { - EXPECT_TRUE(storage.CreateIndex(label1)); - EXPECT_TRUE(storage.CreateIndex(label2)); - - auto acc = storage.Access(); - for (int i = 0; i < 20; ++i) { - auto vertex = CreateVertex(&acc); - ASSERT_NO_ERROR(vertex.AddLabel(i % 3 ? label1 : label2)); - } - - EXPECT_EQ(acc.ApproximateVertexCount(label1), 13); - EXPECT_EQ(acc.ApproximateVertexCount(label2), 7); -} - -// NOLINTNEXTLINE(hicpp-special-member-functions) -TEST_F(IndexTest, LabelPropertyIndexCreateAndDrop) { - EXPECT_EQ(storage.ListAllIndices().label_property.size(), 0); - EXPECT_TRUE(storage.CreateIndex(label1, prop_id)); - { - auto acc = storage.Access(); - EXPECT_TRUE(acc.LabelPropertyIndexExists(label1, prop_id)); - } - EXPECT_THAT(storage.ListAllIndices().label_property, UnorderedElementsAre(std::make_pair(label1, prop_id))); - { - auto acc = storage.Access(); - EXPECT_FALSE(acc.LabelPropertyIndexExists(label2, prop_id)); - } - EXPECT_FALSE(storage.CreateIndex(label1, prop_id)); - EXPECT_THAT(storage.ListAllIndices().label_property, UnorderedElementsAre(std::make_pair(label1, prop_id))); - - EXPECT_TRUE(storage.CreateIndex(label2, prop_id)); - { - auto acc = storage.Access(); - EXPECT_TRUE(acc.LabelPropertyIndexExists(label2, prop_id)); - } - EXPECT_THAT(storage.ListAllIndices().label_property, - UnorderedElementsAre(std::make_pair(label1, prop_id), std::make_pair(label2, prop_id))); - - EXPECT_TRUE(storage.DropIndex(label1, prop_id)); - { - auto acc = storage.Access(); - EXPECT_FALSE(acc.LabelPropertyIndexExists(label1, prop_id)); - } - EXPECT_THAT(storage.ListAllIndices().label_property, UnorderedElementsAre(std::make_pair(label2, prop_id))); - EXPECT_FALSE(storage.DropIndex(label1, prop_id)); - - EXPECT_TRUE(storage.DropIndex(label2, prop_id)); - { - auto acc = storage.Access(); - EXPECT_FALSE(acc.LabelPropertyIndexExists(label2, prop_id)); - } - EXPECT_EQ(storage.ListAllIndices().label_property.size(), 0); -} - -// The following three tests are almost an exact copy-paste of the corresponding -// label index tests. We request all vertices with given label and property from -// the index, without range filtering. Range filtering is tested in a separate -// test. - -// NOLINTNEXTLINE(hicpp-special-member-functions) -TEST_F(IndexTest, LabelPropertyIndexBasic) { - storage.CreateIndex(label1, prop_val); - storage.CreateIndex(label2, prop_val); - - auto acc = storage.Access(); - EXPECT_THAT(GetIds(acc.Vertices(label1, prop_val, View::OLD), View::OLD), IsEmpty()); - - for (int i = 0; i < 10; ++i) { - auto vertex = CreateVertex(&acc); - ASSERT_NO_ERROR(vertex.AddLabel(i % 2 ? label1 : label2)); - ASSERT_NO_ERROR(vertex.SetProperty(prop_val, PropertyValue(i))); - } - - EXPECT_THAT(GetIds(acc.Vertices(label1, prop_val, View::OLD), View::OLD), IsEmpty()); - EXPECT_THAT(GetIds(acc.Vertices(label2, prop_val, View::OLD), View::OLD), IsEmpty()); - EXPECT_THAT(GetIds(acc.Vertices(label1, prop_val, View::NEW), View::NEW), UnorderedElementsAre(1, 3, 5, 7, 9)); - EXPECT_THAT(GetIds(acc.Vertices(label2, prop_val, View::NEW), View::NEW), UnorderedElementsAre(0, 2, 4, 6, 8)); - - acc.AdvanceCommand(); - - EXPECT_THAT(GetIds(acc.Vertices(label1, prop_val, View::OLD), View::OLD), UnorderedElementsAre(1, 3, 5, 7, 9)); - EXPECT_THAT(GetIds(acc.Vertices(label2, prop_val, View::OLD), View::OLD), UnorderedElementsAre(0, 2, 4, 6, 8)); - EXPECT_THAT(GetIds(acc.Vertices(label1, prop_val, View::NEW), View::NEW), UnorderedElementsAre(1, 3, 5, 7, 9)); - EXPECT_THAT(GetIds(acc.Vertices(label2, prop_val, View::NEW), View::NEW), UnorderedElementsAre(0, 2, 4, 6, 8)); - - for (auto vertex : acc.Vertices(View::OLD)) { - int64_t id = vertex.GetProperty(prop_id, View::OLD)->ValueInt(); - if (id % 2) { - ASSERT_NO_ERROR(vertex.SetProperty(prop_val, PropertyValue())); - } else { - ASSERT_NO_ERROR(vertex.AddLabel(label1)); - } - } - - EXPECT_THAT(GetIds(acc.Vertices(label1, prop_val, View::OLD), View::OLD), UnorderedElementsAre(1, 3, 5, 7, 9)); - EXPECT_THAT(GetIds(acc.Vertices(label2, prop_val, View::OLD), View::OLD), UnorderedElementsAre(0, 2, 4, 6, 8)); - EXPECT_THAT(GetIds(acc.Vertices(label1, prop_val, View::NEW), View::NEW), UnorderedElementsAre(0, 2, 4, 6, 8)); - EXPECT_THAT(GetIds(acc.Vertices(label2, prop_val, View::NEW), View::NEW), UnorderedElementsAre(0, 2, 4, 6, 8)); - - for (auto vertex : acc.Vertices(View::OLD)) { - int64_t id = vertex.GetProperty(prop_id, View::OLD)->ValueInt(); - if (id % 2 == 0) { - ASSERT_NO_ERROR(acc.DeleteVertex(&vertex)); - } - } - - EXPECT_THAT(GetIds(acc.Vertices(label1, prop_val, View::OLD), View::OLD), UnorderedElementsAre(1, 3, 5, 7, 9)); - EXPECT_THAT(GetIds(acc.Vertices(label2, prop_val, View::OLD), View::OLD), UnorderedElementsAre(0, 2, 4, 6, 8)); - EXPECT_THAT(GetIds(acc.Vertices(label1, prop_val, View::NEW), View::NEW), IsEmpty()); - EXPECT_THAT(GetIds(acc.Vertices(label2, prop_val, View::NEW), View::NEW), IsEmpty()); - - acc.AdvanceCommand(); - - EXPECT_THAT(GetIds(acc.Vertices(label1, prop_val, View::OLD), View::OLD), IsEmpty()); - EXPECT_THAT(GetIds(acc.Vertices(label2, prop_val, View::OLD), View::OLD), IsEmpty()); - EXPECT_THAT(GetIds(acc.Vertices(label1, prop_val, View::NEW), View::NEW), IsEmpty()); - EXPECT_THAT(GetIds(acc.Vertices(label2, prop_val, View::NEW), View::NEW), IsEmpty()); -} - -// NOLINTNEXTLINE(hicpp-special-member-functions) -TEST_F(IndexTest, LabelPropertyIndexDuplicateVersions) { - storage.CreateIndex(label1, prop_val); - { - auto acc = storage.Access(); - for (int i = 0; i < 5; ++i) { - auto vertex = CreateVertex(&acc); - ASSERT_NO_ERROR(vertex.AddLabel(label1)); - ASSERT_NO_ERROR(vertex.SetProperty(prop_val, PropertyValue(i))); - } - - EXPECT_THAT(GetIds(acc.Vertices(label1, prop_val, View::NEW), View::NEW), UnorderedElementsAre(0, 1, 2, 3, 4)); - - ASSERT_NO_ERROR(acc.Commit()); - } - - { - auto acc = storage.Access(); - EXPECT_THAT(GetIds(acc.Vertices(label1, prop_val, View::OLD), View::OLD), UnorderedElementsAre(0, 1, 2, 3, 4)); - - for (auto vertex : acc.Vertices(View::OLD)) { - ASSERT_NO_ERROR(vertex.SetProperty(prop_val, PropertyValue())); - } - - EXPECT_THAT(GetIds(acc.Vertices(label1, prop_val, View::OLD), View::OLD), UnorderedElementsAre(0, 1, 2, 3, 4)); - EXPECT_THAT(GetIds(acc.Vertices(label1, prop_val, View::NEW), View::NEW), IsEmpty()); - - for (auto vertex : acc.Vertices(View::OLD)) { - ASSERT_NO_ERROR(vertex.SetProperty(prop_val, PropertyValue(42))); - } - EXPECT_THAT(GetIds(acc.Vertices(label1, prop_val, View::OLD), View::OLD), UnorderedElementsAre(0, 1, 2, 3, 4)); - EXPECT_THAT(GetIds(acc.Vertices(label1, prop_val, View::NEW), View::NEW), UnorderedElementsAre(0, 1, 2, 3, 4)); - } -} - -// NOLINTNEXTLINE(hicpp-special-member-functions) -TEST_F(IndexTest, LabelPropertyIndexTransactionalIsolation) { - storage.CreateIndex(label1, prop_val); - - auto acc_before = storage.Access(); - auto acc = storage.Access(); - auto acc_after = storage.Access(); - - for (int i = 0; i < 5; ++i) { - auto vertex = CreateVertex(&acc); - ASSERT_NO_ERROR(vertex.AddLabel(label1)); - ASSERT_NO_ERROR(vertex.SetProperty(prop_val, PropertyValue(i))); - } - - EXPECT_THAT(GetIds(acc.Vertices(label1, prop_val, View::NEW), View::NEW), UnorderedElementsAre(0, 1, 2, 3, 4)); - EXPECT_THAT(GetIds(acc_before.Vertices(label1, prop_val, View::NEW), View::NEW), IsEmpty()); - EXPECT_THAT(GetIds(acc_after.Vertices(label1, prop_val, View::NEW), View::NEW), IsEmpty()); - - ASSERT_NO_ERROR(acc.Commit()); - - auto acc_after_commit = storage.Access(); - - EXPECT_THAT(GetIds(acc_before.Vertices(label1, prop_val, View::NEW), View::NEW), IsEmpty()); - EXPECT_THAT(GetIds(acc_after.Vertices(label1, prop_val, View::NEW), View::NEW), IsEmpty()); - EXPECT_THAT(GetIds(acc_after_commit.Vertices(label1, prop_val, View::NEW), View::NEW), - UnorderedElementsAre(0, 1, 2, 3, 4)); -} - -// NOLINTNEXTLINE(hicpp-special-member-functions) -TEST_F(IndexTest, LabelPropertyIndexFiltering) { - // We insert vertices with values: - // 0 0.0 1 1.0 2 2.0 3 3.0 4 4.0 - // Then we check all combinations of inclusive and exclusive bounds. - // We also have a mix of doubles and integers to verify that they are sorted - // properly. - - storage.CreateIndex(label1, prop_val); - - { - auto acc = storage.Access(); - - for (int i = 0; i < 10; ++i) { - auto vertex = CreateVertex(&acc); - ASSERT_NO_ERROR(vertex.AddLabel(label1)); - ASSERT_NO_ERROR(vertex.SetProperty(prop_val, i % 2 ? PropertyValue(i / 2) : PropertyValue(i / 2.0))); - } - ASSERT_NO_ERROR(acc.Commit()); - } - { - auto acc = storage.Access(); - for (int i = 0; i < 5; ++i) { - EXPECT_THAT(GetIds(acc.Vertices(label1, prop_val, PropertyValue(i), View::OLD)), - UnorderedElementsAre(2 * i, 2 * i + 1)); - } - - // [1, +inf> - EXPECT_THAT(GetIds(acc.Vertices(label1, prop_val, memgraph::utils::MakeBoundInclusive(PropertyValue(1)), - std::nullopt, View::OLD)), - UnorderedElementsAre(2, 3, 4, 5, 6, 7, 8, 9)); - // <1, +inf> - EXPECT_THAT(GetIds(acc.Vertices(label1, prop_val, memgraph::utils::MakeBoundExclusive(PropertyValue(1)), - std::nullopt, View::OLD)), - UnorderedElementsAre(4, 5, 6, 7, 8, 9)); - - // <-inf, 3] - EXPECT_THAT(GetIds(acc.Vertices(label1, prop_val, std::nullopt, - memgraph::utils::MakeBoundInclusive(PropertyValue(3)), View::OLD)), - UnorderedElementsAre(0, 1, 2, 3, 4, 5, 6, 7)); - // <-inf, 3> - EXPECT_THAT(GetIds(acc.Vertices(label1, prop_val, std::nullopt, - memgraph::utils::MakeBoundExclusive(PropertyValue(3)), View::OLD)), - UnorderedElementsAre(0, 1, 2, 3, 4, 5)); - - // [1, 3] - EXPECT_THAT(GetIds(acc.Vertices(label1, prop_val, memgraph::utils::MakeBoundInclusive(PropertyValue(1)), - memgraph::utils::MakeBoundInclusive(PropertyValue(3)), View::OLD)), - UnorderedElementsAre(2, 3, 4, 5, 6, 7)); - // <1, 3] - EXPECT_THAT(GetIds(acc.Vertices(label1, prop_val, memgraph::utils::MakeBoundExclusive(PropertyValue(1)), - memgraph::utils::MakeBoundInclusive(PropertyValue(3)), View::OLD)), - UnorderedElementsAre(4, 5, 6, 7)); - // [1, 3> - EXPECT_THAT(GetIds(acc.Vertices(label1, prop_val, memgraph::utils::MakeBoundInclusive(PropertyValue(1)), - memgraph::utils::MakeBoundExclusive(PropertyValue(3)), View::OLD)), - UnorderedElementsAre(2, 3, 4, 5)); - // <1, 3> - EXPECT_THAT(GetIds(acc.Vertices(label1, prop_val, memgraph::utils::MakeBoundExclusive(PropertyValue(1)), - memgraph::utils::MakeBoundExclusive(PropertyValue(3)), View::OLD)), - UnorderedElementsAre(4, 5)); - } -} - -// NOLINTNEXTLINE(hicpp-special-member-functions) -TEST_F(IndexTest, LabelPropertyIndexCountEstimate) { - storage.CreateIndex(label1, prop_val); - - auto acc = storage.Access(); - for (int i = 1; i <= 10; ++i) { - for (int j = 0; j < i; ++j) { - auto vertex = CreateVertex(&acc); - ASSERT_NO_ERROR(vertex.AddLabel(label1)); - ASSERT_NO_ERROR(vertex.SetProperty(prop_val, PropertyValue(i))); - } - } - - EXPECT_EQ(acc.ApproximateVertexCount(label1, prop_val), 55); - for (int i = 1; i <= 10; ++i) { - EXPECT_EQ(acc.ApproximateVertexCount(label1, prop_val, PropertyValue(i)), i); - } - - EXPECT_EQ(acc.ApproximateVertexCount(label1, prop_val, memgraph::utils::MakeBoundInclusive(PropertyValue(2)), - memgraph::utils::MakeBoundInclusive(PropertyValue(6))), - 2 + 3 + 4 + 5 + 6); -} - -TEST_F(IndexTest, LabelPropertyIndexMixedIteration) { - storage.CreateIndex(label1, prop_val); - - const std::array temporals{TemporalData{TemporalType::Date, 23}, TemporalData{TemporalType::Date, 28}, - TemporalData{TemporalType::LocalDateTime, 20}}; - - std::vector values = { - PropertyValue(false), - PropertyValue(true), - PropertyValue(-std::numeric_limits::infinity()), - PropertyValue(std::numeric_limits::min()), - PropertyValue(-1), - PropertyValue(-0.5), - PropertyValue(0), - PropertyValue(0.5), - PropertyValue(1), - PropertyValue(1.5), - PropertyValue(2), - PropertyValue(std::numeric_limits::max()), - PropertyValue(std::numeric_limits::infinity()), - PropertyValue(""), - PropertyValue("a"), - PropertyValue("b"), - PropertyValue("c"), - PropertyValue(std::vector()), - PropertyValue(std::vector{PropertyValue(0.8)}), - PropertyValue(std::vector{PropertyValue(2)}), - PropertyValue(std::map()), - PropertyValue(std::map{{"id", PropertyValue(5)}}), - PropertyValue(std::map{{"id", PropertyValue(10)}}), - PropertyValue(temporals[0]), - PropertyValue(temporals[1]), - PropertyValue(temporals[2]), - }; - - // Create vertices, each with one of the values above. - { - auto acc = storage.Access(); - for (const auto &value : values) { - auto v = acc.CreateVertex(); - ASSERT_TRUE(v.AddLabel(label1).HasValue()); - ASSERT_TRUE(v.SetProperty(prop_val, value).HasValue()); - } - ASSERT_FALSE(acc.Commit().HasError()); - } - - // Verify that all nodes are in the index. - { - auto acc = storage.Access(); - auto iterable = acc.Vertices(label1, prop_val, View::OLD); - auto it = iterable.begin(); - for (const auto &value : values) { - ASSERT_NE(it, iterable.end()); - auto vertex = *it; - auto maybe_value = vertex.GetProperty(prop_val, View::OLD); - ASSERT_TRUE(maybe_value.HasValue()); - ASSERT_EQ(value, *maybe_value); - ++it; - } - ASSERT_EQ(it, iterable.end()); - } - - auto verify = [&](const std::optional> &from, - const std::optional> &to, - const std::vector &expected) { - auto acc = storage.Access(); - auto iterable = acc.Vertices(label1, prop_val, from, to, View::OLD); - size_t i = 0; - for (auto it = iterable.begin(); it != iterable.end(); ++it, ++i) { - auto vertex = *it; - auto maybe_value = vertex.GetProperty(prop_val, View::OLD); - ASSERT_TRUE(maybe_value.HasValue()); - ASSERT_EQ(*maybe_value, expected[i]); - } - ASSERT_EQ(i, expected.size()); - }; - - // Range iteration with two specified bounds that have the same type should - // yield the naturally expected items. - verify(memgraph::utils::MakeBoundExclusive(PropertyValue(false)), - memgraph::utils::MakeBoundExclusive(PropertyValue(true)), {}); - verify(memgraph::utils::MakeBoundExclusive(PropertyValue(false)), - memgraph::utils::MakeBoundInclusive(PropertyValue(true)), {PropertyValue(true)}); - verify(memgraph::utils::MakeBoundInclusive(PropertyValue(false)), - memgraph::utils::MakeBoundExclusive(PropertyValue(true)), {PropertyValue(false)}); - verify(memgraph::utils::MakeBoundInclusive(PropertyValue(false)), - memgraph::utils::MakeBoundInclusive(PropertyValue(true)), {PropertyValue(false), PropertyValue(true)}); - verify(memgraph::utils::MakeBoundExclusive(PropertyValue(0)), memgraph::utils::MakeBoundExclusive(PropertyValue(1.8)), - {PropertyValue(0.5), PropertyValue(1), PropertyValue(1.5)}); - verify(memgraph::utils::MakeBoundExclusive(PropertyValue(0)), memgraph::utils::MakeBoundInclusive(PropertyValue(1.8)), - {PropertyValue(0.5), PropertyValue(1), PropertyValue(1.5)}); - verify(memgraph::utils::MakeBoundInclusive(PropertyValue(0)), memgraph::utils::MakeBoundExclusive(PropertyValue(1.8)), - {PropertyValue(0), PropertyValue(0.5), PropertyValue(1), PropertyValue(1.5)}); - verify(memgraph::utils::MakeBoundInclusive(PropertyValue(0)), memgraph::utils::MakeBoundInclusive(PropertyValue(1.8)), - {PropertyValue(0), PropertyValue(0.5), PropertyValue(1), PropertyValue(1.5)}); - verify(memgraph::utils::MakeBoundExclusive(PropertyValue("b")), - memgraph::utils::MakeBoundExclusive(PropertyValue("memgraph")), {PropertyValue("c")}); - verify(memgraph::utils::MakeBoundExclusive(PropertyValue("b")), - memgraph::utils::MakeBoundInclusive(PropertyValue("memgraph")), {PropertyValue("c")}); - verify(memgraph::utils::MakeBoundInclusive(PropertyValue("b")), - memgraph::utils::MakeBoundExclusive(PropertyValue("memgraph")), {PropertyValue("b"), PropertyValue("c")}); - verify(memgraph::utils::MakeBoundInclusive(PropertyValue("b")), - memgraph::utils::MakeBoundInclusive(PropertyValue("memgraph")), {PropertyValue("b"), PropertyValue("c")}); - verify(memgraph::utils::MakeBoundExclusive(PropertyValue(std::vector{PropertyValue(0.8)})), - memgraph::utils::MakeBoundExclusive(PropertyValue(std::vector{PropertyValue("b")})), - {PropertyValue(std::vector{PropertyValue(2)})}); - verify(memgraph::utils::MakeBoundExclusive(PropertyValue(std::vector{PropertyValue(0.8)})), - memgraph::utils::MakeBoundInclusive(PropertyValue(std::vector{PropertyValue("b")})), - {PropertyValue(std::vector{PropertyValue(2)})}); - verify(memgraph::utils::MakeBoundInclusive(PropertyValue(std::vector{PropertyValue(0.8)})), - memgraph::utils::MakeBoundExclusive(PropertyValue(std::vector{PropertyValue("b")})), - {PropertyValue(std::vector{PropertyValue(0.8)}), - PropertyValue(std::vector{PropertyValue(2)})}); - verify(memgraph::utils::MakeBoundInclusive(PropertyValue(std::vector{PropertyValue(0.8)})), - memgraph::utils::MakeBoundInclusive(PropertyValue(std::vector{PropertyValue("b")})), - {PropertyValue(std::vector{PropertyValue(0.8)}), - PropertyValue(std::vector{PropertyValue(2)})}); - verify(memgraph::utils::MakeBoundExclusive( - PropertyValue(std::map{{"id", PropertyValue(5.0)}})), - memgraph::utils::MakeBoundExclusive( - PropertyValue(std::map{{"id", PropertyValue("b")}})), - {PropertyValue(std::map{{"id", PropertyValue(10)}})}); - verify(memgraph::utils::MakeBoundExclusive( - PropertyValue(std::map{{"id", PropertyValue(5.0)}})), - memgraph::utils::MakeBoundInclusive( - PropertyValue(std::map{{"id", PropertyValue("b")}})), - {PropertyValue(std::map{{"id", PropertyValue(10)}})}); - verify(memgraph::utils::MakeBoundInclusive( - PropertyValue(std::map{{"id", PropertyValue(5.0)}})), - memgraph::utils::MakeBoundExclusive( - PropertyValue(std::map{{"id", PropertyValue("b")}})), - {PropertyValue(std::map{{"id", PropertyValue(5)}}), - PropertyValue(std::map{{"id", PropertyValue(10)}})}); - verify(memgraph::utils::MakeBoundInclusive( - PropertyValue(std::map{{"id", PropertyValue(5.0)}})), - memgraph::utils::MakeBoundInclusive( - PropertyValue(std::map{{"id", PropertyValue("b")}})), - {PropertyValue(std::map{{"id", PropertyValue(5)}}), - PropertyValue(std::map{{"id", PropertyValue(10)}})}); - - verify(memgraph::utils::MakeBoundExclusive(PropertyValue(temporals[0])), - memgraph::utils::MakeBoundInclusive(PropertyValue(TemporalData{TemporalType::Date, 200})), - // LocalDateTime has a "higher" type number so it is not part of the range - {PropertyValue(temporals[1])}); - verify(memgraph::utils::MakeBoundExclusive(PropertyValue(temporals[0])), - memgraph::utils::MakeBoundInclusive(PropertyValue(temporals[2])), - {PropertyValue(temporals[1]), PropertyValue(temporals[2])}); - verify(memgraph::utils::MakeBoundInclusive(PropertyValue(temporals[0])), - memgraph::utils::MakeBoundExclusive(PropertyValue(temporals[2])), - {PropertyValue(temporals[0]), PropertyValue(temporals[1])}); - verify(memgraph::utils::MakeBoundInclusive(PropertyValue(temporals[0])), - memgraph::utils::MakeBoundInclusive(PropertyValue(temporals[2])), - {PropertyValue(temporals[0]), PropertyValue(temporals[1]), PropertyValue(temporals[2])}); - - // Range iteration with one unspecified bound should only yield items that - // have the same type as the specified bound. - verify(memgraph::utils::MakeBoundInclusive(PropertyValue(false)), std::nullopt, - {PropertyValue(false), PropertyValue(true)}); - verify(std::nullopt, memgraph::utils::MakeBoundExclusive(PropertyValue(true)), {PropertyValue(false)}); - verify(memgraph::utils::MakeBoundInclusive(PropertyValue(1)), std::nullopt, - {PropertyValue(1), PropertyValue(1.5), PropertyValue(2), PropertyValue(std::numeric_limits::max()), - PropertyValue(std::numeric_limits::infinity())}); - verify(std::nullopt, memgraph::utils::MakeBoundExclusive(PropertyValue(0)), - {PropertyValue(-std::numeric_limits::infinity()), PropertyValue(std::numeric_limits::min()), - PropertyValue(-1), PropertyValue(-0.5)}); - verify(memgraph::utils::MakeBoundInclusive(PropertyValue("b")), std::nullopt, - {PropertyValue("b"), PropertyValue("c")}); - verify(std::nullopt, memgraph::utils::MakeBoundExclusive(PropertyValue("b")), - {PropertyValue(""), PropertyValue("a")}); - verify(memgraph::utils::MakeBoundInclusive(PropertyValue(std::vector{PropertyValue(false)})), - std::nullopt, - {PropertyValue(std::vector{PropertyValue(0.8)}), - PropertyValue(std::vector{PropertyValue(2)})}); - verify(std::nullopt, memgraph::utils::MakeBoundExclusive(PropertyValue(std::vector{PropertyValue(1)})), - {PropertyValue(std::vector()), PropertyValue(std::vector{PropertyValue(0.8)})}); - verify(memgraph::utils::MakeBoundInclusive( - PropertyValue(std::map{{"id", PropertyValue(false)}})), - std::nullopt, - {PropertyValue(std::map{{"id", PropertyValue(5)}}), - PropertyValue(std::map{{"id", PropertyValue(10)}})}); - verify(std::nullopt, - memgraph::utils::MakeBoundExclusive( - PropertyValue(std::map{{"id", PropertyValue(7.5)}})), - {PropertyValue(std::map()), - PropertyValue(std::map{{"id", PropertyValue(5)}})}); - verify(memgraph::utils::MakeBoundInclusive(PropertyValue(TemporalData(TemporalType::Date, 10))), std::nullopt, - {PropertyValue(temporals[0]), PropertyValue(temporals[1]), PropertyValue(temporals[2])}); - verify(std::nullopt, memgraph::utils::MakeBoundExclusive(PropertyValue(TemporalData(TemporalType::Duration, 0))), - {PropertyValue(temporals[0]), PropertyValue(temporals[1]), PropertyValue(temporals[2])}); - - // Range iteration with two specified bounds that don't have the same type - // should yield no items. - for (size_t i = 0; i < values.size(); ++i) { - for (size_t j = i; j < values.size(); ++j) { - if (PropertyValue::AreComparableTypes(values[i].type(), values[j].type())) { - verify(memgraph::utils::MakeBoundInclusive(values[i]), memgraph::utils::MakeBoundInclusive(values[j]), - {values.begin() + i, values.begin() + j + 1}); - } else { - verify(memgraph::utils::MakeBoundInclusive(values[i]), memgraph::utils::MakeBoundInclusive(values[j]), {}); - } - } - } - - // Iteration without any bounds should return all items of the index. - verify(std::nullopt, std::nullopt, values); -} diff --git a/tests/unit/storage_v2_isolation_level.cpp b/tests/unit/storage_v2_isolation_level.cpp deleted file mode 100644 index c626d5952..000000000 --- a/tests/unit/storage_v2_isolation_level.cpp +++ /dev/null @@ -1,110 +0,0 @@ -// Copyright 2022 Memgraph Ltd. -// -// Use of this software is governed by the Business Source License -// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source -// License, and you may not use this file except in compliance with the Business Source License. -// -// As of the Change Date specified in that file, in accordance with -// the Business Source License, use of this software will be governed -// by the Apache License, Version 2.0, included in the file -// licenses/APL.txt. - -#include - -#include "storage/v2/isolation_level.hpp" -#include "storage/v2/storage.hpp" - -namespace { -int64_t VerticesCount(memgraph::storage::Storage::Accessor &accessor) { - int64_t count{0}; - for ([[maybe_unused]] const auto &vertex : accessor.Vertices(memgraph::storage::View::NEW)) { - ++count; - } - - return count; -} - -inline constexpr std::array isolation_levels{memgraph::storage::IsolationLevel::SNAPSHOT_ISOLATION, - memgraph::storage::IsolationLevel::READ_COMMITTED, - memgraph::storage::IsolationLevel::READ_UNCOMMITTED}; - -std::string_view IsolationLevelToString(const memgraph::storage::IsolationLevel isolation_level) { - switch (isolation_level) { - case memgraph::storage::IsolationLevel::SNAPSHOT_ISOLATION: - return "SNAPSHOT_ISOLATION"; - case memgraph::storage::IsolationLevel::READ_COMMITTED: - return "READ_COMMITTED"; - case memgraph::storage::IsolationLevel::READ_UNCOMMITTED: - return "READ_UNCOMMITTED"; - } -} -} // namespace - -class StorageIsolationLevelTest : public ::testing::TestWithParam { - public: - struct PrintToStringParamName { - std::string operator()(const testing::TestParamInfo &info) { - return std::string(IsolationLevelToString(static_cast(info.param))); - } - }; -}; - -TEST_P(StorageIsolationLevelTest, Visibility) { - const auto default_isolation_level = GetParam(); - - for (const auto override_isolation_level : isolation_levels) { - memgraph::storage::Storage storage{ - memgraph::storage::Config{.transaction = {.isolation_level = default_isolation_level}}}; - auto creator = storage.Access(); - auto default_isolation_level_reader = storage.Access(); - auto override_isolation_level_reader = storage.Access(override_isolation_level); - - ASSERT_EQ(VerticesCount(default_isolation_level_reader), 0); - ASSERT_EQ(VerticesCount(override_isolation_level_reader), 0); - - static constexpr auto iteration_count = 10; - { - SCOPED_TRACE(fmt::format( - "Visibility while the creator transaction is active " - "(default isolation level = {}, override isolation level = {})", - IsolationLevelToString(default_isolation_level), IsolationLevelToString(override_isolation_level))); - for (size_t i = 1; i <= iteration_count; ++i) { - creator.CreateVertex(); - - const auto check_vertices_count = [i](auto &accessor, const auto isolation_level) { - const auto expected_count = isolation_level == memgraph::storage::IsolationLevel::READ_UNCOMMITTED ? i : 0; - EXPECT_EQ(VerticesCount(accessor), expected_count); - }; - check_vertices_count(default_isolation_level_reader, default_isolation_level); - check_vertices_count(override_isolation_level_reader, override_isolation_level); - } - } - - ASSERT_FALSE(creator.Commit().HasError()); - { - SCOPED_TRACE(fmt::format( - "Visibility after the creator transaction is committed " - "(default isolation level = {}, override isolation level = {})", - IsolationLevelToString(default_isolation_level), IsolationLevelToString(override_isolation_level))); - const auto check_vertices_count = [](auto &accessor, const auto isolation_level) { - const auto expected_count = - isolation_level == memgraph::storage::IsolationLevel::SNAPSHOT_ISOLATION ? 0 : iteration_count; - ASSERT_EQ(VerticesCount(accessor), expected_count); - }; - - check_vertices_count(default_isolation_level_reader, default_isolation_level); - check_vertices_count(override_isolation_level_reader, override_isolation_level); - } - - ASSERT_FALSE(default_isolation_level_reader.Commit().HasError()); - ASSERT_FALSE(override_isolation_level_reader.Commit().HasError()); - - SCOPED_TRACE("Visibility after a new transaction is started"); - auto verifier = storage.Access(); - ASSERT_EQ(VerticesCount(verifier), iteration_count); - ASSERT_FALSE(verifier.Commit().HasError()); - } -} - -INSTANTIATE_TEST_CASE_P(ParameterizedStorageIsolationLevelTests, StorageIsolationLevelTest, - ::testing::ValuesIn(isolation_levels), StorageIsolationLevelTest::PrintToStringParamName()); diff --git a/tests/unit/storage_v2_name_id_mapper.cpp b/tests/unit/storage_v2_name_id_mapper.cpp deleted file mode 100644 index b7865d775..000000000 --- a/tests/unit/storage_v2_name_id_mapper.cpp +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright 2022 Memgraph Ltd. -// -// Use of this software is governed by the Business Source License -// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source -// License, and you may not use this file except in compliance with the Business Source License. -// -// As of the Change Date specified in that file, in accordance with -// the Business Source License, use of this software will be governed -// by the Apache License, Version 2.0, included in the file -// licenses/APL.txt. - -#include - -#include "storage/v2/name_id_mapper.hpp" - -// NOLINTNEXTLINE(hicpp-special-member-functions) -TEST(NameIdMapper, Basic) { - memgraph::storage::NameIdMapper mapper; - - ASSERT_EQ(mapper.NameToId("n1"), 0); - ASSERT_EQ(mapper.NameToId("n2"), 1); - ASSERT_EQ(mapper.NameToId("n1"), 0); - ASSERT_EQ(mapper.NameToId("n2"), 1); - ASSERT_EQ(mapper.NameToId("n3"), 2); - - ASSERT_EQ(mapper.IdToName(0), "n1"); - ASSERT_EQ(mapper.IdToName(1), "n2"); -} - -// NOLINTNEXTLINE(hicpp-special-member-functions) -TEST(NameIdMapper, Correctness) { - memgraph::storage::NameIdMapper mapper; - - ASSERT_DEATH(mapper.IdToName(0), ""); - ASSERT_EQ(mapper.NameToId("n1"), 0); - ASSERT_EQ(mapper.IdToName(0), "n1"); - - ASSERT_DEATH(mapper.IdToName(1), ""); - ASSERT_EQ(mapper.NameToId("n2"), 1); - ASSERT_EQ(mapper.IdToName(1), "n2"); - - ASSERT_EQ(mapper.NameToId("n1"), 0); - ASSERT_EQ(mapper.NameToId("n2"), 1); - - ASSERT_EQ(mapper.IdToName(1), "n2"); - ASSERT_EQ(mapper.IdToName(0), "n1"); -} diff --git a/tests/unit/storage_v2_property_store.cpp b/tests/unit/storage_v2_property_store.cpp deleted file mode 100644 index e247806d8..000000000 --- a/tests/unit/storage_v2_property_store.cpp +++ /dev/null @@ -1,651 +0,0 @@ -// Copyright 2022 Memgraph Ltd. -// -// Use of this software is governed by the Business Source License -// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source -// License, and you may not use this file except in compliance with the Business Source License. -// -// As of the Change Date specified in that file, in accordance with -// the Business Source License, use of this software will be governed -// by the Apache License, Version 2.0, included in the file -// licenses/APL.txt. - -#include -#include - -#include - -#include "storage/v2/property_store.hpp" -#include "storage/v2/property_value.hpp" -#include "storage/v2/temporal.hpp" - -using testing::UnorderedElementsAre; - -const memgraph::storage::PropertyValue kSampleValues[] = { - memgraph::storage::PropertyValue(), - memgraph::storage::PropertyValue(false), - memgraph::storage::PropertyValue(true), - memgraph::storage::PropertyValue(0), - memgraph::storage::PropertyValue(33), - memgraph::storage::PropertyValue(-33), - memgraph::storage::PropertyValue(-3137), - memgraph::storage::PropertyValue(3137), - memgraph::storage::PropertyValue(310000007), - memgraph::storage::PropertyValue(-310000007), - memgraph::storage::PropertyValue(3100000000007L), - memgraph::storage::PropertyValue(-3100000000007L), - memgraph::storage::PropertyValue(0.0), - memgraph::storage::PropertyValue(33.33), - memgraph::storage::PropertyValue(-33.33), - memgraph::storage::PropertyValue(3137.3137), - memgraph::storage::PropertyValue(-3137.3137), - memgraph::storage::PropertyValue("sample"), - memgraph::storage::PropertyValue(std::string(404, 'n')), - memgraph::storage::PropertyValue(std::vector{ - memgraph::storage::PropertyValue(33), memgraph::storage::PropertyValue(std::string("sample")), - memgraph::storage::PropertyValue(-33.33)}), - memgraph::storage::PropertyValue(std::vector{ - memgraph::storage::PropertyValue(), memgraph::storage::PropertyValue(false)}), - memgraph::storage::PropertyValue(std::map{ - {"sample", memgraph::storage::PropertyValue()}, {"key", memgraph::storage::PropertyValue(false)}}), - memgraph::storage::PropertyValue(std::map{ - {"test", memgraph::storage::PropertyValue(33)}, - {"map", memgraph::storage::PropertyValue(std::string("sample"))}, - {"item", memgraph::storage::PropertyValue(-33.33)}}), - memgraph::storage::PropertyValue(memgraph::storage::TemporalData(memgraph::storage::TemporalType::Date, 23)), -}; - -void TestIsPropertyEqual(const memgraph::storage::PropertyStore &store, memgraph::storage::PropertyId property, - const memgraph::storage::PropertyValue &value) { - ASSERT_TRUE(store.IsPropertyEqual(property, value)); - for (const auto &sample : kSampleValues) { - if (sample == value) { - ASSERT_TRUE(store.IsPropertyEqual(property, sample)); - } else { - ASSERT_FALSE(store.IsPropertyEqual(property, sample)); - } - } -} - -TEST(PropertyStore, Simple) { - memgraph::storage::PropertyStore props; - auto prop = memgraph::storage::PropertyId::FromInt(42); - auto value = memgraph::storage::PropertyValue(42); - ASSERT_TRUE(props.SetProperty(prop, value)); - ASSERT_EQ(props.GetProperty(prop), value); - ASSERT_TRUE(props.HasProperty(prop)); - TestIsPropertyEqual(props, prop, value); - ASSERT_THAT(props.Properties(), UnorderedElementsAre(std::pair(prop, value))); - - ASSERT_FALSE(props.SetProperty(prop, memgraph::storage::PropertyValue())); - ASSERT_TRUE(props.GetProperty(prop).IsNull()); - ASSERT_FALSE(props.HasProperty(prop)); - TestIsPropertyEqual(props, prop, memgraph::storage::PropertyValue()); - ASSERT_EQ(props.Properties().size(), 0); -} - -TEST(PropertyStore, SimpleLarge) { - memgraph::storage::PropertyStore props; - auto prop = memgraph::storage::PropertyId::FromInt(42); - { - auto value = memgraph::storage::PropertyValue(std::string(10000, 'a')); - ASSERT_TRUE(props.SetProperty(prop, value)); - ASSERT_EQ(props.GetProperty(prop), value); - ASSERT_TRUE(props.HasProperty(prop)); - TestIsPropertyEqual(props, prop, value); - ASSERT_THAT(props.Properties(), UnorderedElementsAre(std::pair(prop, value))); - } - { - auto value = - memgraph::storage::PropertyValue(memgraph::storage::TemporalData(memgraph::storage::TemporalType::Date, 23)); - ASSERT_FALSE(props.SetProperty(prop, value)); - ASSERT_EQ(props.GetProperty(prop), value); - ASSERT_TRUE(props.HasProperty(prop)); - TestIsPropertyEqual(props, prop, value); - ASSERT_THAT(props.Properties(), UnorderedElementsAre(std::pair(prop, value))); - } - - ASSERT_FALSE(props.SetProperty(prop, memgraph::storage::PropertyValue())); - ASSERT_TRUE(props.GetProperty(prop).IsNull()); - ASSERT_FALSE(props.HasProperty(prop)); - TestIsPropertyEqual(props, prop, memgraph::storage::PropertyValue()); - ASSERT_EQ(props.Properties().size(), 0); -} - -TEST(PropertyStore, EmptySetToNull) { - memgraph::storage::PropertyStore props; - auto prop = memgraph::storage::PropertyId::FromInt(42); - ASSERT_TRUE(props.SetProperty(prop, memgraph::storage::PropertyValue())); - ASSERT_TRUE(props.GetProperty(prop).IsNull()); - ASSERT_FALSE(props.HasProperty(prop)); - TestIsPropertyEqual(props, prop, memgraph::storage::PropertyValue()); - ASSERT_EQ(props.Properties().size(), 0); -} - -TEST(PropertyStore, Clear) { - memgraph::storage::PropertyStore props; - auto prop = memgraph::storage::PropertyId::FromInt(42); - auto value = memgraph::storage::PropertyValue(42); - ASSERT_TRUE(props.SetProperty(prop, value)); - ASSERT_EQ(props.GetProperty(prop), value); - ASSERT_TRUE(props.HasProperty(prop)); - TestIsPropertyEqual(props, prop, value); - ASSERT_THAT(props.Properties(), UnorderedElementsAre(std::pair(prop, value))); - ASSERT_TRUE(props.ClearProperties()); - ASSERT_TRUE(props.GetProperty(prop).IsNull()); - ASSERT_FALSE(props.HasProperty(prop)); - TestIsPropertyEqual(props, prop, memgraph::storage::PropertyValue()); - ASSERT_EQ(props.Properties().size(), 0); -} - -TEST(PropertyStore, EmptyClear) { - memgraph::storage::PropertyStore props; - ASSERT_FALSE(props.ClearProperties()); - ASSERT_EQ(props.Properties().size(), 0); -} - -TEST(PropertyStore, MoveConstruct) { - memgraph::storage::PropertyStore props1; - auto prop = memgraph::storage::PropertyId::FromInt(42); - auto value = memgraph::storage::PropertyValue(42); - ASSERT_TRUE(props1.SetProperty(prop, value)); - ASSERT_EQ(props1.GetProperty(prop), value); - ASSERT_TRUE(props1.HasProperty(prop)); - TestIsPropertyEqual(props1, prop, value); - ASSERT_THAT(props1.Properties(), UnorderedElementsAre(std::pair(prop, value))); - { - memgraph::storage::PropertyStore props2(std::move(props1)); - ASSERT_EQ(props2.GetProperty(prop), value); - ASSERT_TRUE(props2.HasProperty(prop)); - TestIsPropertyEqual(props2, prop, value); - ASSERT_THAT(props2.Properties(), UnorderedElementsAre(std::pair(prop, value))); - } - // NOLINTNEXTLINE(bugprone-use-after-move,clang-analyzer-cplusplus.Move,hicpp-invalid-access-moved) - ASSERT_TRUE(props1.GetProperty(prop).IsNull()); - ASSERT_FALSE(props1.HasProperty(prop)); - TestIsPropertyEqual(props1, prop, memgraph::storage::PropertyValue()); - ASSERT_EQ(props1.Properties().size(), 0); -} - -TEST(PropertyStore, MoveConstructLarge) { - memgraph::storage::PropertyStore props1; - auto prop = memgraph::storage::PropertyId::FromInt(42); - auto value = memgraph::storage::PropertyValue(std::string(10000, 'a')); - ASSERT_TRUE(props1.SetProperty(prop, value)); - ASSERT_EQ(props1.GetProperty(prop), value); - ASSERT_TRUE(props1.HasProperty(prop)); - TestIsPropertyEqual(props1, prop, value); - ASSERT_THAT(props1.Properties(), UnorderedElementsAre(std::pair(prop, value))); - { - memgraph::storage::PropertyStore props2(std::move(props1)); - ASSERT_EQ(props2.GetProperty(prop), value); - ASSERT_TRUE(props2.HasProperty(prop)); - TestIsPropertyEqual(props2, prop, value); - ASSERT_THAT(props2.Properties(), UnorderedElementsAre(std::pair(prop, value))); - } - // NOLINTNEXTLINE(bugprone-use-after-move,clang-analyzer-cplusplus.Move,hicpp-invalid-access-moved) - ASSERT_TRUE(props1.GetProperty(prop).IsNull()); - ASSERT_FALSE(props1.HasProperty(prop)); - TestIsPropertyEqual(props1, prop, memgraph::storage::PropertyValue()); - ASSERT_EQ(props1.Properties().size(), 0); -} - -TEST(PropertyStore, MoveAssign) { - memgraph::storage::PropertyStore props1; - auto prop = memgraph::storage::PropertyId::FromInt(42); - auto value = memgraph::storage::PropertyValue(42); - ASSERT_TRUE(props1.SetProperty(prop, value)); - ASSERT_EQ(props1.GetProperty(prop), value); - ASSERT_TRUE(props1.HasProperty(prop)); - TestIsPropertyEqual(props1, prop, value); - ASSERT_THAT(props1.Properties(), UnorderedElementsAre(std::pair(prop, value))); - { - auto value2 = memgraph::storage::PropertyValue(68); - memgraph::storage::PropertyStore props2; - ASSERT_TRUE(props2.SetProperty(prop, value2)); - ASSERT_EQ(props2.GetProperty(prop), value2); - ASSERT_TRUE(props2.HasProperty(prop)); - TestIsPropertyEqual(props2, prop, value2); - ASSERT_THAT(props2.Properties(), UnorderedElementsAre(std::pair(prop, value2))); - props2 = std::move(props1); - ASSERT_EQ(props2.GetProperty(prop), value); - ASSERT_TRUE(props2.HasProperty(prop)); - TestIsPropertyEqual(props2, prop, value); - ASSERT_THAT(props2.Properties(), UnorderedElementsAre(std::pair(prop, value))); - } - // NOLINTNEXTLINE(bugprone-use-after-move,clang-analyzer-cplusplus.Move,hicpp-invalid-access-moved) - ASSERT_TRUE(props1.GetProperty(prop).IsNull()); - ASSERT_FALSE(props1.HasProperty(prop)); - TestIsPropertyEqual(props1, prop, memgraph::storage::PropertyValue()); - ASSERT_EQ(props1.Properties().size(), 0); -} - -TEST(PropertyStore, MoveAssignLarge) { - memgraph::storage::PropertyStore props1; - auto prop = memgraph::storage::PropertyId::FromInt(42); - auto value = memgraph::storage::PropertyValue(std::string(10000, 'a')); - ASSERT_TRUE(props1.SetProperty(prop, value)); - ASSERT_EQ(props1.GetProperty(prop), value); - ASSERT_TRUE(props1.HasProperty(prop)); - TestIsPropertyEqual(props1, prop, value); - ASSERT_THAT(props1.Properties(), UnorderedElementsAre(std::pair(prop, value))); - { - auto value2 = memgraph::storage::PropertyValue(std::string(10000, 'b')); - memgraph::storage::PropertyStore props2; - ASSERT_TRUE(props2.SetProperty(prop, value2)); - ASSERT_EQ(props2.GetProperty(prop), value2); - ASSERT_TRUE(props2.HasProperty(prop)); - TestIsPropertyEqual(props2, prop, value2); - ASSERT_THAT(props2.Properties(), UnorderedElementsAre(std::pair(prop, value2))); - props2 = std::move(props1); - ASSERT_EQ(props2.GetProperty(prop), value); - ASSERT_TRUE(props2.HasProperty(prop)); - TestIsPropertyEqual(props2, prop, value); - ASSERT_THAT(props2.Properties(), UnorderedElementsAre(std::pair(prop, value))); - } - // NOLINTNEXTLINE(bugprone-use-after-move,clang-analyzer-cplusplus.Move,hicpp-invalid-access-moved) - ASSERT_TRUE(props1.GetProperty(prop).IsNull()); - ASSERT_FALSE(props1.HasProperty(prop)); - TestIsPropertyEqual(props1, prop, memgraph::storage::PropertyValue()); - ASSERT_EQ(props1.Properties().size(), 0); -} - -TEST(PropertyStore, EmptySet) { - std::vector vec{memgraph::storage::PropertyValue(true), - memgraph::storage::PropertyValue(123), - memgraph::storage::PropertyValue()}; - std::map map{{"nandare", memgraph::storage::PropertyValue(false)}}; - const memgraph::storage::TemporalData temporal{memgraph::storage::TemporalType::LocalDateTime, 23}; - std::vector data{ - memgraph::storage::PropertyValue(true), memgraph::storage::PropertyValue(123), - memgraph::storage::PropertyValue(123.5), memgraph::storage::PropertyValue("nandare"), - memgraph::storage::PropertyValue(vec), memgraph::storage::PropertyValue(map), - memgraph::storage::PropertyValue(temporal)}; - - auto prop = memgraph::storage::PropertyId::FromInt(42); - for (const auto &value : data) { - memgraph::storage::PropertyStore props; - - ASSERT_TRUE(props.SetProperty(prop, value)); - ASSERT_EQ(props.GetProperty(prop), value); - ASSERT_TRUE(props.HasProperty(prop)); - TestIsPropertyEqual(props, prop, value); - ASSERT_THAT(props.Properties(), UnorderedElementsAre(std::pair(prop, value))); - ASSERT_FALSE(props.SetProperty(prop, value)); - ASSERT_EQ(props.GetProperty(prop), value); - ASSERT_TRUE(props.HasProperty(prop)); - TestIsPropertyEqual(props, prop, value); - ASSERT_THAT(props.Properties(), UnorderedElementsAre(std::pair(prop, value))); - ASSERT_FALSE(props.SetProperty(prop, memgraph::storage::PropertyValue())); - ASSERT_TRUE(props.GetProperty(prop).IsNull()); - ASSERT_FALSE(props.HasProperty(prop)); - TestIsPropertyEqual(props, prop, memgraph::storage::PropertyValue()); - ASSERT_EQ(props.Properties().size(), 0); - ASSERT_TRUE(props.SetProperty(prop, memgraph::storage::PropertyValue())); - ASSERT_TRUE(props.GetProperty(prop).IsNull()); - ASSERT_FALSE(props.HasProperty(prop)); - TestIsPropertyEqual(props, prop, memgraph::storage::PropertyValue()); - ASSERT_EQ(props.Properties().size(), 0); - } -} - -TEST(PropertyStore, FullSet) { - std::vector vec{memgraph::storage::PropertyValue(true), - memgraph::storage::PropertyValue(123), - memgraph::storage::PropertyValue()}; - std::map map{{"nandare", memgraph::storage::PropertyValue(false)}}; - const memgraph::storage::TemporalData temporal{memgraph::storage::TemporalType::LocalDateTime, 23}; - std::map data{ - {memgraph::storage::PropertyId::FromInt(1), memgraph::storage::PropertyValue(true)}, - {memgraph::storage::PropertyId::FromInt(2), memgraph::storage::PropertyValue(123)}, - {memgraph::storage::PropertyId::FromInt(3), memgraph::storage::PropertyValue(123.5)}, - {memgraph::storage::PropertyId::FromInt(4), memgraph::storage::PropertyValue("nandare")}, - {memgraph::storage::PropertyId::FromInt(5), memgraph::storage::PropertyValue(vec)}, - {memgraph::storage::PropertyId::FromInt(6), memgraph::storage::PropertyValue(map)}, - {memgraph::storage::PropertyId::FromInt(7), memgraph::storage::PropertyValue(temporal)}}; - - std::vector alt{memgraph::storage::PropertyValue(), - memgraph::storage::PropertyValue(std::string()), - memgraph::storage::PropertyValue(std::string(10, 'a')), - memgraph::storage::PropertyValue(std::string(100, 'a')), - memgraph::storage::PropertyValue(std::string(1000, 'a')), - memgraph::storage::PropertyValue(std::string(10000, 'a')), - memgraph::storage::PropertyValue(std::string(100000, 'a'))}; - - memgraph::storage::PropertyStore props; - for (const auto &target : data) { - for (const auto &item : data) { - ASSERT_TRUE(props.SetProperty(item.first, item.second)); - } - - for (size_t i = 0; i < alt.size(); ++i) { - if (i == 1) { - ASSERT_TRUE(props.SetProperty(target.first, alt[i])); - } else { - ASSERT_FALSE(props.SetProperty(target.first, alt[i])); - } - for (const auto &item : data) { - if (item.first == target.first) { - ASSERT_EQ(props.GetProperty(item.first), alt[i]); - if (alt[i].IsNull()) { - ASSERT_FALSE(props.HasProperty(item.first)); - } else { - ASSERT_TRUE(props.HasProperty(item.first)); - } - TestIsPropertyEqual(props, item.first, alt[i]); - } else { - ASSERT_EQ(props.GetProperty(item.first), item.second); - ASSERT_TRUE(props.HasProperty(item.first)); - TestIsPropertyEqual(props, item.first, item.second); - } - } - auto current = data; - if (alt[i].IsNull()) { - current.erase(target.first); - } else { - current[target.first] = alt[i]; - } - ASSERT_EQ(props.Properties(), current); - } - - for (ssize_t i = alt.size() - 1; i >= 0; --i) { - ASSERT_FALSE(props.SetProperty(target.first, alt[i])); - for (const auto &item : data) { - if (item.first == target.first) { - ASSERT_EQ(props.GetProperty(item.first), alt[i]); - if (alt[i].IsNull()) { - ASSERT_FALSE(props.HasProperty(item.first)); - } else { - ASSERT_TRUE(props.HasProperty(item.first)); - } - TestIsPropertyEqual(props, item.first, alt[i]); - } else { - ASSERT_EQ(props.GetProperty(item.first), item.second); - ASSERT_TRUE(props.HasProperty(item.first)); - TestIsPropertyEqual(props, item.first, item.second); - } - } - auto current = data; - if (alt[i].IsNull()) { - current.erase(target.first); - } else { - current[target.first] = alt[i]; - } - ASSERT_EQ(props.Properties(), current); - } - - ASSERT_TRUE(props.SetProperty(target.first, target.second)); - ASSERT_EQ(props.GetProperty(target.first), target.second); - ASSERT_TRUE(props.HasProperty(target.first)); - TestIsPropertyEqual(props, target.first, target.second); - - props.ClearProperties(); - ASSERT_EQ(props.Properties().size(), 0); - for (const auto &item : data) { - ASSERT_TRUE(props.GetProperty(item.first).IsNull()); - ASSERT_FALSE(props.HasProperty(item.first)); - TestIsPropertyEqual(props, item.first, memgraph::storage::PropertyValue()); - } - } -} - -TEST(PropertyStore, IntEncoding) { - std::map data{ - {memgraph::storage::PropertyId::FromUint(0UL), - memgraph::storage::PropertyValue(std::numeric_limits::min())}, - {memgraph::storage::PropertyId::FromUint(10UL), memgraph::storage::PropertyValue(-137438953472L)}, - {memgraph::storage::PropertyId::FromUint(std::numeric_limits::max()), - memgraph::storage::PropertyValue(-4294967297L)}, - {memgraph::storage::PropertyId::FromUint(256UL), - memgraph::storage::PropertyValue(std::numeric_limits::min())}, - {memgraph::storage::PropertyId::FromUint(1024UL), memgraph::storage::PropertyValue(-1048576L)}, - {memgraph::storage::PropertyId::FromUint(1025UL), memgraph::storage::PropertyValue(-65537L)}, - {memgraph::storage::PropertyId::FromUint(1026UL), - memgraph::storage::PropertyValue(std::numeric_limits::min())}, - {memgraph::storage::PropertyId::FromUint(1027UL), memgraph::storage::PropertyValue(-1024L)}, - {memgraph::storage::PropertyId::FromUint(2000UL), memgraph::storage::PropertyValue(-257L)}, - {memgraph::storage::PropertyId::FromUint(3000UL), - memgraph::storage::PropertyValue(std::numeric_limits::min())}, - {memgraph::storage::PropertyId::FromUint(4000UL), memgraph::storage::PropertyValue(-1L)}, - {memgraph::storage::PropertyId::FromUint(10000UL), memgraph::storage::PropertyValue(0L)}, - {memgraph::storage::PropertyId::FromUint(20000UL), memgraph::storage::PropertyValue(1L)}, - {memgraph::storage::PropertyId::FromUint(30000UL), - memgraph::storage::PropertyValue(std::numeric_limits::max())}, - {memgraph::storage::PropertyId::FromUint(40000UL), memgraph::storage::PropertyValue(256L)}, - {memgraph::storage::PropertyId::FromUint(50000UL), memgraph::storage::PropertyValue(1024L)}, - {memgraph::storage::PropertyId::FromUint(std::numeric_limits::max()), - memgraph::storage::PropertyValue(std::numeric_limits::max())}, - {memgraph::storage::PropertyId::FromUint(65536UL), memgraph::storage::PropertyValue(65536L)}, - {memgraph::storage::PropertyId::FromUint(1048576UL), memgraph::storage::PropertyValue(1048576L)}, - {memgraph::storage::PropertyId::FromUint(std::numeric_limits::max()), - memgraph::storage::PropertyValue(std::numeric_limits::max())}, - {memgraph::storage::PropertyId::FromUint(4294967296UL), memgraph::storage::PropertyValue(4294967296L)}, - {memgraph::storage::PropertyId::FromUint(137438953472UL), memgraph::storage::PropertyValue(137438953472L)}, - {memgraph::storage::PropertyId::FromUint(std::numeric_limits::max()), - memgraph::storage::PropertyValue(std::numeric_limits::max())}}; - - memgraph::storage::PropertyStore props; - for (const auto &item : data) { - ASSERT_TRUE(props.SetProperty(item.first, item.second)); - ASSERT_EQ(props.GetProperty(item.first), item.second); - ASSERT_TRUE(props.HasProperty(item.first)); - TestIsPropertyEqual(props, item.first, item.second); - } - for (auto it = data.rbegin(); it != data.rend(); ++it) { - const auto &item = *it; - ASSERT_FALSE(props.SetProperty(item.first, item.second)); - ASSERT_EQ(props.GetProperty(item.first), item.second); - ASSERT_TRUE(props.HasProperty(item.first)); - TestIsPropertyEqual(props, item.first, item.second); - } - - ASSERT_EQ(props.Properties(), data); - - props.ClearProperties(); - ASSERT_EQ(props.Properties().size(), 0); - for (const auto &item : data) { - ASSERT_TRUE(props.GetProperty(item.first).IsNull()); - ASSERT_FALSE(props.HasProperty(item.first)); - TestIsPropertyEqual(props, item.first, memgraph::storage::PropertyValue()); - } -} - -TEST(PropertyStore, IsPropertyEqualIntAndDouble) { - memgraph::storage::PropertyStore props; - auto prop = memgraph::storage::PropertyId::FromInt(42); - - ASSERT_TRUE(props.SetProperty(prop, memgraph::storage::PropertyValue(42))); - - std::vector> tests{ - {memgraph::storage::PropertyValue(0), memgraph::storage::PropertyValue(0.0)}, - {memgraph::storage::PropertyValue(123), memgraph::storage::PropertyValue(123.0)}, - {memgraph::storage::PropertyValue(12345), memgraph::storage::PropertyValue(12345.0)}, - {memgraph::storage::PropertyValue(12345678), memgraph::storage::PropertyValue(12345678.0)}, - {memgraph::storage::PropertyValue(1234567890123L), memgraph::storage::PropertyValue(1234567890123.0)}, - }; - - // Test equality with raw values. - for (auto test : tests) { - ASSERT_EQ(test.first, test.second); - - // Test first, second - ASSERT_FALSE(props.SetProperty(prop, test.first)); - ASSERT_EQ(props.GetProperty(prop), test.first); - ASSERT_TRUE(props.HasProperty(prop)); - ASSERT_TRUE(props.IsPropertyEqual(prop, test.first)); - ASSERT_TRUE(props.IsPropertyEqual(prop, test.second)); - - // Test second, first - ASSERT_FALSE(props.SetProperty(prop, test.second)); - ASSERT_EQ(props.GetProperty(prop), test.second); - ASSERT_TRUE(props.HasProperty(prop)); - ASSERT_TRUE(props.IsPropertyEqual(prop, test.second)); - ASSERT_TRUE(props.IsPropertyEqual(prop, test.first)); - - // Make both negative - test.first = memgraph::storage::PropertyValue(test.first.ValueInt() * -1); - test.second = memgraph::storage::PropertyValue(test.second.ValueDouble() * -1.0); - ASSERT_EQ(test.first, test.second); - - // Test -first, -second - ASSERT_FALSE(props.SetProperty(prop, test.first)); - ASSERT_EQ(props.GetProperty(prop), test.first); - ASSERT_TRUE(props.HasProperty(prop)); - ASSERT_TRUE(props.IsPropertyEqual(prop, test.first)); - ASSERT_TRUE(props.IsPropertyEqual(prop, test.second)); - - // Test -second, -first - ASSERT_FALSE(props.SetProperty(prop, test.second)); - ASSERT_EQ(props.GetProperty(prop), test.second); - ASSERT_TRUE(props.HasProperty(prop)); - ASSERT_TRUE(props.IsPropertyEqual(prop, test.second)); - ASSERT_TRUE(props.IsPropertyEqual(prop, test.first)); - } - - // Test equality with values wrapped in lists. - for (auto test : tests) { - test.first = memgraph::storage::PropertyValue( - std::vector{memgraph::storage::PropertyValue(test.first.ValueInt())}); - test.second = memgraph::storage::PropertyValue( - std::vector{memgraph::storage::PropertyValue(test.second.ValueDouble())}); - ASSERT_EQ(test.first, test.second); - - // Test first, second - ASSERT_FALSE(props.SetProperty(prop, test.first)); - ASSERT_EQ(props.GetProperty(prop), test.first); - ASSERT_TRUE(props.HasProperty(prop)); - ASSERT_TRUE(props.IsPropertyEqual(prop, test.first)); - ASSERT_TRUE(props.IsPropertyEqual(prop, test.second)); - - // Test second, first - ASSERT_FALSE(props.SetProperty(prop, test.second)); - ASSERT_EQ(props.GetProperty(prop), test.second); - ASSERT_TRUE(props.HasProperty(prop)); - ASSERT_TRUE(props.IsPropertyEqual(prop, test.second)); - ASSERT_TRUE(props.IsPropertyEqual(prop, test.first)); - - // Make both negative - test.first = memgraph::storage::PropertyValue(std::vector{ - memgraph::storage::PropertyValue(test.first.ValueList()[0].ValueInt() * -1)}); - test.second = memgraph::storage::PropertyValue(std::vector{ - memgraph::storage::PropertyValue(test.second.ValueList()[0].ValueDouble() * -1.0)}); - ASSERT_EQ(test.first, test.second); - - // Test -first, -second - ASSERT_FALSE(props.SetProperty(prop, test.first)); - ASSERT_EQ(props.GetProperty(prop), test.first); - ASSERT_TRUE(props.HasProperty(prop)); - ASSERT_TRUE(props.IsPropertyEqual(prop, test.first)); - ASSERT_TRUE(props.IsPropertyEqual(prop, test.second)); - - // Test -second, -first - ASSERT_FALSE(props.SetProperty(prop, test.second)); - ASSERT_EQ(props.GetProperty(prop), test.second); - ASSERT_TRUE(props.HasProperty(prop)); - ASSERT_TRUE(props.IsPropertyEqual(prop, test.second)); - ASSERT_TRUE(props.IsPropertyEqual(prop, test.first)); - } -} - -TEST(PropertyStore, IsPropertyEqualString) { - memgraph::storage::PropertyStore props; - auto prop = memgraph::storage::PropertyId::FromInt(42); - ASSERT_TRUE(props.SetProperty(prop, memgraph::storage::PropertyValue("test"))); - ASSERT_TRUE(props.IsPropertyEqual(prop, memgraph::storage::PropertyValue("test"))); - - // Different length. - ASSERT_FALSE(props.IsPropertyEqual(prop, memgraph::storage::PropertyValue("helloworld"))); - - // Same length, different value. - ASSERT_FALSE(props.IsPropertyEqual(prop, memgraph::storage::PropertyValue("asdf"))); - - // Shortened and extended. - ASSERT_FALSE(props.IsPropertyEqual(prop, memgraph::storage::PropertyValue("tes"))); - ASSERT_FALSE(props.IsPropertyEqual(prop, memgraph::storage::PropertyValue("testt"))); -} - -TEST(PropertyStore, IsPropertyEqualList) { - memgraph::storage::PropertyStore props; - auto prop = memgraph::storage::PropertyId::FromInt(42); - ASSERT_TRUE( - props.SetProperty(prop, memgraph::storage::PropertyValue(std::vector{ - memgraph::storage::PropertyValue(42), memgraph::storage::PropertyValue("test")}))); - ASSERT_TRUE(props.IsPropertyEqual( - prop, memgraph::storage::PropertyValue(std::vector{ - memgraph::storage::PropertyValue(42), memgraph::storage::PropertyValue("test")}))); - - // Different length. - ASSERT_FALSE(props.IsPropertyEqual( - prop, memgraph::storage::PropertyValue( - std::vector{memgraph::storage::PropertyValue(24)}))); - - // Same length, different value. - ASSERT_FALSE(props.IsPropertyEqual( - prop, memgraph::storage::PropertyValue(std::vector{ - memgraph::storage::PropertyValue(42), memgraph::storage::PropertyValue("asdf")}))); - - // Shortened and extended. - ASSERT_FALSE(props.IsPropertyEqual( - prop, memgraph::storage::PropertyValue( - std::vector{memgraph::storage::PropertyValue(42)}))); - ASSERT_FALSE( - props.IsPropertyEqual(prop, memgraph::storage::PropertyValue(std::vector{ - memgraph::storage::PropertyValue(42), memgraph::storage::PropertyValue("test"), - memgraph::storage::PropertyValue(true)}))); -} - -TEST(PropertyStore, IsPropertyEqualMap) { - memgraph::storage::PropertyStore props; - auto prop = memgraph::storage::PropertyId::FromInt(42); - ASSERT_TRUE(props.SetProperty( - prop, memgraph::storage::PropertyValue(std::map{ - {"abc", memgraph::storage::PropertyValue(42)}, {"zyx", memgraph::storage::PropertyValue("test")}}))); - ASSERT_TRUE(props.IsPropertyEqual( - prop, memgraph::storage::PropertyValue(std::map{ - {"abc", memgraph::storage::PropertyValue(42)}, {"zyx", memgraph::storage::PropertyValue("test")}}))); - - // Different length. - ASSERT_FALSE(props.IsPropertyEqual( - prop, memgraph::storage::PropertyValue(std::map{ - {"fgh", memgraph::storage::PropertyValue(24)}}))); - - // Same length, different value. - ASSERT_FALSE(props.IsPropertyEqual( - prop, memgraph::storage::PropertyValue(std::map{ - {"abc", memgraph::storage::PropertyValue(42)}, {"zyx", memgraph::storage::PropertyValue("testt")}}))); - - // Same length, different key (different length). - ASSERT_FALSE(props.IsPropertyEqual( - prop, memgraph::storage::PropertyValue(std::map{ - {"abc", memgraph::storage::PropertyValue(42)}, {"zyxw", memgraph::storage::PropertyValue("test")}}))); - - // Same length, different key (same length). - ASSERT_FALSE(props.IsPropertyEqual( - prop, memgraph::storage::PropertyValue(std::map{ - {"abc", memgraph::storage::PropertyValue(42)}, {"zyw", memgraph::storage::PropertyValue("test")}}))); - - // Shortened and extended. - ASSERT_FALSE(props.IsPropertyEqual( - prop, memgraph::storage::PropertyValue(std::map{ - {"abc", memgraph::storage::PropertyValue(42)}}))); - ASSERT_FALSE(props.IsPropertyEqual( - prop, memgraph::storage::PropertyValue(std::map{ - {"abc", memgraph::storage::PropertyValue(42)}, - {"sdf", memgraph::storage::PropertyValue(true)}, - {"zyx", memgraph::storage::PropertyValue("test")}}))); -} - -TEST(PropertyStore, IsPropertyEqualTemporalData) { - memgraph::storage::PropertyStore props; - auto prop = memgraph::storage::PropertyId::FromInt(42); - const memgraph::storage::TemporalData temporal{memgraph::storage::TemporalType::Date, 23}; - ASSERT_TRUE(props.SetProperty(prop, memgraph::storage::PropertyValue(temporal))); - ASSERT_TRUE(props.IsPropertyEqual(prop, memgraph::storage::PropertyValue(temporal))); - - // Different type. - ASSERT_FALSE(props.IsPropertyEqual(prop, memgraph::storage::PropertyValue(memgraph::storage::TemporalData{ - memgraph::storage::TemporalType::Duration, 23}))); - - // Same type, different value. - ASSERT_FALSE(props.IsPropertyEqual(prop, memgraph::storage::PropertyValue(memgraph::storage::TemporalData{ - memgraph::storage::TemporalType::Date, 30}))); -} diff --git a/tests/unit/storage_v2_replication.cpp b/tests/unit/storage_v2_replication.cpp deleted file mode 100644 index e453ae17e..000000000 --- a/tests/unit/storage_v2_replication.cpp +++ /dev/null @@ -1,828 +0,0 @@ -// Copyright 2022 Memgraph Ltd. -// -// Use of this software is governed by the Business Source License -// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source -// License, and you may not use this file except in compliance with the Business Source License. -// -// As of the Change Date specified in that file, in accordance with -// the Business Source License, use of this software will be governed -// by the Apache License, Version 2.0, included in the file -// licenses/APL.txt. - -#include -#include - -#include -#include -#include -#include - -#include -#include -#include -#include "storage/v2/view.hpp" - -using testing::UnorderedElementsAre; - -class ReplicationTest : public ::testing::Test { - protected: - std::filesystem::path storage_directory{std::filesystem::temp_directory_path() / - "MG_test_unit_storage_v2_replication"}; - void SetUp() override { Clear(); } - - void TearDown() override { Clear(); } - - memgraph::storage::Config configuration{ - .items = {.properties_on_edges = true}, - .durability = { - .storage_directory = storage_directory, - .snapshot_wal_mode = memgraph::storage::Config::Durability::SnapshotWalMode::PERIODIC_SNAPSHOT_WITH_WAL, - }}; - - const std::string local_host = ("127.0.0.1"); - const std::array ports{10000, 20000}; - const std::array replicas = {"REPLICA1", "REPLICA2"}; - - private: - void Clear() { - if (!std::filesystem::exists(storage_directory)) return; - std::filesystem::remove_all(storage_directory); - } -}; - -TEST_F(ReplicationTest, BasicSynchronousReplicationTest) { - memgraph::storage::Storage main_store(configuration); - - memgraph::storage::Storage replica_store(configuration); - replica_store.SetReplicaRole(memgraph::io::network::Endpoint{local_host, ports[0]}); - - ASSERT_FALSE(main_store - .RegisterReplica("REPLICA", memgraph::io::network::Endpoint{local_host, ports[0]}, - memgraph::storage::replication::ReplicationMode::SYNC, - memgraph::storage::replication::RegistrationMode::MUST_BE_INSTANTLY_VALID) - .HasError()); - - // vertex create - // vertex add label - // vertex set property - const auto *vertex_label = "vertex_label"; - const auto *vertex_property = "vertex_property"; - const auto *vertex_property_value = "vertex_property_value"; - std::optional vertex_gid; - { - auto acc = main_store.Access(); - auto v = acc.CreateVertex(); - vertex_gid.emplace(v.Gid()); - ASSERT_TRUE(v.AddLabel(main_store.NameToLabel(vertex_label)).HasValue()); - ASSERT_TRUE(v.SetProperty(main_store.NameToProperty(vertex_property), - memgraph::storage::PropertyValue(vertex_property_value)) - .HasValue()); - ASSERT_FALSE(acc.Commit().HasError()); - } - - { - auto acc = replica_store.Access(); - const auto v = acc.FindVertex(*vertex_gid, memgraph::storage::View::OLD); - ASSERT_TRUE(v); - const auto labels = v->Labels(memgraph::storage::View::OLD); - ASSERT_TRUE(labels.HasValue()); - ASSERT_EQ(labels->size(), 1); - ASSERT_THAT(*labels, UnorderedElementsAre(replica_store.NameToLabel(vertex_label))); - const auto properties = v->Properties(memgraph::storage::View::OLD); - ASSERT_TRUE(properties.HasValue()); - ASSERT_EQ(properties->size(), 1); - ASSERT_THAT(*properties, - UnorderedElementsAre(std::make_pair(replica_store.NameToProperty(vertex_property), - memgraph::storage::PropertyValue(vertex_property_value)))); - - ASSERT_FALSE(acc.Commit().HasError()); - } - - // vertex remove label - { - auto acc = main_store.Access(); - auto v = acc.FindVertex(*vertex_gid, memgraph::storage::View::OLD); - ASSERT_TRUE(v); - ASSERT_TRUE(v->RemoveLabel(main_store.NameToLabel(vertex_label)).HasValue()); - ASSERT_FALSE(acc.Commit().HasError()); - } - - { - auto acc = replica_store.Access(); - const auto v = acc.FindVertex(*vertex_gid, memgraph::storage::View::OLD); - ASSERT_TRUE(v); - const auto labels = v->Labels(memgraph::storage::View::OLD); - ASSERT_TRUE(labels.HasValue()); - ASSERT_EQ(labels->size(), 0); - ASSERT_FALSE(acc.Commit().HasError()); - } - - // vertex delete - { - auto acc = main_store.Access(); - auto v = acc.FindVertex(*vertex_gid, memgraph::storage::View::OLD); - ASSERT_TRUE(v); - ASSERT_TRUE(acc.DeleteVertex(&*v).HasValue()); - ASSERT_FALSE(acc.Commit().HasError()); - } - - { - auto acc = replica_store.Access(); - const auto v = acc.FindVertex(*vertex_gid, memgraph::storage::View::OLD); - ASSERT_FALSE(v); - vertex_gid.reset(); - ASSERT_FALSE(acc.Commit().HasError()); - } - - // edge create - // edge set property - const auto *edge_type = "edge_type"; - const auto *edge_property = "edge_property"; - const auto *edge_property_value = "edge_property_value"; - std::optional edge_gid; - { - auto acc = main_store.Access(); - auto v = acc.CreateVertex(); - vertex_gid.emplace(v.Gid()); - auto edge = acc.CreateEdge(&v, &v, main_store.NameToEdgeType(edge_type)); - ASSERT_TRUE(edge.HasValue()); - ASSERT_TRUE(edge->SetProperty(main_store.NameToProperty(edge_property), - memgraph::storage::PropertyValue(edge_property_value)) - .HasValue()); - edge_gid.emplace(edge->Gid()); - ASSERT_FALSE(acc.Commit().HasError()); - } - - const auto find_edge = [&](const auto &edges, - const memgraph::storage::Gid edge_gid) -> std::optional { - for (const auto &edge : edges) { - if (edge.Gid() == edge_gid) { - return edge; - } - } - return std::nullopt; - }; - - { - auto acc = replica_store.Access(); - const auto v = acc.FindVertex(*vertex_gid, memgraph::storage::View::OLD); - ASSERT_TRUE(v); - const auto out_edges = v->OutEdges(memgraph::storage::View::OLD); - ASSERT_TRUE(out_edges.HasValue()); - const auto edge = find_edge(*out_edges, *edge_gid); - ASSERT_EQ(edge->EdgeType(), replica_store.NameToEdgeType(edge_type)); - const auto properties = edge->Properties(memgraph::storage::View::OLD); - ASSERT_TRUE(properties.HasValue()); - ASSERT_EQ(properties->size(), 1); - ASSERT_THAT(*properties, - UnorderedElementsAre(std::make_pair(replica_store.NameToProperty(edge_property), - memgraph::storage::PropertyValue(edge_property_value)))); - ASSERT_FALSE(acc.Commit().HasError()); - } - - // delete edge - { - auto acc = main_store.Access(); - auto v = acc.FindVertex(*vertex_gid, memgraph::storage::View::OLD); - ASSERT_TRUE(v); - auto out_edges = v->OutEdges(memgraph::storage::View::OLD); - auto edge = find_edge(*out_edges, *edge_gid); - ASSERT_TRUE(edge); - ASSERT_TRUE(acc.DeleteEdge(&*edge).HasValue()); - ASSERT_FALSE(acc.Commit().HasError()); - } - - { - auto acc = replica_store.Access(); - const auto v = acc.FindVertex(*vertex_gid, memgraph::storage::View::OLD); - ASSERT_TRUE(v); - const auto out_edges = v->OutEdges(memgraph::storage::View::OLD); - ASSERT_TRUE(out_edges.HasValue()); - ASSERT_FALSE(find_edge(*out_edges, *edge_gid)); - ASSERT_FALSE(acc.Commit().HasError()); - } - - // label index create - // label property index create - // existence constraint create - // unique constriant create - const auto *label = "label"; - const auto *property = "property"; - const auto *property_extra = "property_extra"; - { - ASSERT_TRUE(main_store.CreateIndex(main_store.NameToLabel(label))); - ASSERT_TRUE(main_store.CreateIndex(main_store.NameToLabel(label), main_store.NameToProperty(property))); - ASSERT_FALSE( - main_store.CreateExistenceConstraint(main_store.NameToLabel(label), main_store.NameToProperty(property)) - .HasError()); - ASSERT_FALSE(main_store - .CreateUniqueConstraint(main_store.NameToLabel(label), {main_store.NameToProperty(property), - main_store.NameToProperty(property_extra)}) - .HasError()); - } - - { - const auto indices = replica_store.ListAllIndices(); - ASSERT_THAT(indices.label, UnorderedElementsAre(replica_store.NameToLabel(label))); - ASSERT_THAT(indices.label_property, UnorderedElementsAre(std::make_pair(replica_store.NameToLabel(label), - replica_store.NameToProperty(property)))); - - const auto constraints = replica_store.ListAllConstraints(); - ASSERT_THAT(constraints.existence, UnorderedElementsAre(std::make_pair(replica_store.NameToLabel(label), - replica_store.NameToProperty(property)))); - ASSERT_THAT(constraints.unique, - UnorderedElementsAre(std::make_pair( - replica_store.NameToLabel(label), - std::set{replica_store.NameToProperty(property), replica_store.NameToProperty(property_extra)}))); - } - - // label index drop - // label property index drop - // existence constraint drop - // unique constriant drop - { - ASSERT_TRUE(main_store.DropIndex(main_store.NameToLabel(label))); - ASSERT_TRUE(main_store.DropIndex(main_store.NameToLabel(label), main_store.NameToProperty(property))); - ASSERT_TRUE(main_store.DropExistenceConstraint(main_store.NameToLabel(label), main_store.NameToProperty(property))); - ASSERT_EQ( - main_store.DropUniqueConstraint(main_store.NameToLabel(label), {main_store.NameToProperty(property), - main_store.NameToProperty(property_extra)}), - memgraph::storage::UniqueConstraints::DeletionStatus::SUCCESS); - } - - { - const auto indices = replica_store.ListAllIndices(); - ASSERT_EQ(indices.label.size(), 0); - ASSERT_EQ(indices.label_property.size(), 0); - - const auto constraints = replica_store.ListAllConstraints(); - ASSERT_EQ(constraints.existence.size(), 0); - ASSERT_EQ(constraints.unique.size(), 0); - } -} - -TEST_F(ReplicationTest, MultipleSynchronousReplicationTest) { - memgraph::storage::Storage main_store( - {.durability = { - .storage_directory = storage_directory, - .snapshot_wal_mode = memgraph::storage::Config::Durability::SnapshotWalMode::PERIODIC_SNAPSHOT_WITH_WAL, - }}); - - memgraph::storage::Storage replica_store1( - {.durability = { - .storage_directory = storage_directory, - .snapshot_wal_mode = memgraph::storage::Config::Durability::SnapshotWalMode::PERIODIC_SNAPSHOT_WITH_WAL, - }}); - replica_store1.SetReplicaRole(memgraph::io::network::Endpoint{local_host, ports[0]}); - - memgraph::storage::Storage replica_store2( - {.durability = { - .storage_directory = storage_directory, - .snapshot_wal_mode = memgraph::storage::Config::Durability::SnapshotWalMode::PERIODIC_SNAPSHOT_WITH_WAL, - }}); - replica_store2.SetReplicaRole(memgraph::io::network::Endpoint{local_host, ports[1]}); - - ASSERT_FALSE(main_store - .RegisterReplica(replicas[0], memgraph::io::network::Endpoint{local_host, ports[0]}, - memgraph::storage::replication::ReplicationMode::SYNC, - memgraph::storage::replication::RegistrationMode::MUST_BE_INSTANTLY_VALID) - .HasError()); - ASSERT_FALSE(main_store - .RegisterReplica(replicas[1], memgraph::io::network::Endpoint{local_host, ports[1]}, - memgraph::storage::replication::ReplicationMode::SYNC, - memgraph::storage::replication::RegistrationMode::MUST_BE_INSTANTLY_VALID) - .HasError()); - - const auto *vertex_label = "label"; - const auto *vertex_property = "property"; - const auto *vertex_property_value = "property_value"; - std::optional vertex_gid; - { - auto acc = main_store.Access(); - auto v = acc.CreateVertex(); - ASSERT_TRUE(v.AddLabel(main_store.NameToLabel(vertex_label)).HasValue()); - ASSERT_TRUE(v.SetProperty(main_store.NameToProperty(vertex_property), - memgraph::storage::PropertyValue(vertex_property_value)) - .HasValue()); - vertex_gid.emplace(v.Gid()); - ASSERT_FALSE(acc.Commit().HasError()); - } - - const auto check_replica = [&](memgraph::storage::Storage *replica_store) { - auto acc = replica_store->Access(); - const auto v = acc.FindVertex(*vertex_gid, memgraph::storage::View::OLD); - ASSERT_TRUE(v); - const auto labels = v->Labels(memgraph::storage::View::OLD); - ASSERT_TRUE(labels.HasValue()); - ASSERT_THAT(*labels, UnorderedElementsAre(replica_store->NameToLabel(vertex_label))); - ASSERT_FALSE(acc.Commit().HasError()); - }; - - check_replica(&replica_store1); - check_replica(&replica_store2); - - main_store.UnregisterReplica(replicas[1]); - { - auto acc = main_store.Access(); - auto v = acc.CreateVertex(); - vertex_gid.emplace(v.Gid()); - ASSERT_FALSE(acc.Commit().HasError()); - } - - // REPLICA1 should contain the new vertex - { - auto acc = replica_store1.Access(); - const auto v = acc.FindVertex(*vertex_gid, memgraph::storage::View::OLD); - ASSERT_TRUE(v); - ASSERT_FALSE(acc.Commit().HasError()); - } - - // REPLICA2 should not contain the new vertex - { - auto acc = replica_store2.Access(); - const auto v = acc.FindVertex(*vertex_gid, memgraph::storage::View::OLD); - ASSERT_FALSE(v); - ASSERT_FALSE(acc.Commit().HasError()); - } -} - -TEST_F(ReplicationTest, RecoveryProcess) { - std::vector vertex_gids; - // Force the creation of snapshot - { - memgraph::storage::Storage main_store( - {.durability = { - .storage_directory = storage_directory, - .recover_on_startup = true, - .snapshot_wal_mode = memgraph::storage::Config::Durability::SnapshotWalMode::PERIODIC_SNAPSHOT_WITH_WAL, - .snapshot_on_exit = true, - }}); - { - auto acc = main_store.Access(); - // Create the vertex before registering a replica - auto v = acc.CreateVertex(); - vertex_gids.emplace_back(v.Gid()); - ASSERT_FALSE(acc.Commit().HasError()); - } - } - - { - // Create second WAL - memgraph::storage::Storage main_store( - {.durability = { - .storage_directory = storage_directory, - .recover_on_startup = true, - .snapshot_wal_mode = memgraph::storage::Config::Durability::SnapshotWalMode::PERIODIC_SNAPSHOT_WITH_WAL}}); - // Create vertices in 2 different transactions - { - auto acc = main_store.Access(); - auto v = acc.CreateVertex(); - vertex_gids.emplace_back(v.Gid()); - ASSERT_FALSE(acc.Commit().HasError()); - } - { - auto acc = main_store.Access(); - auto v = acc.CreateVertex(); - vertex_gids.emplace_back(v.Gid()); - ASSERT_FALSE(acc.Commit().HasError()); - } - } - - memgraph::storage::Storage main_store( - {.durability = { - .storage_directory = storage_directory, - .recover_on_startup = true, - .snapshot_wal_mode = memgraph::storage::Config::Durability::SnapshotWalMode::PERIODIC_SNAPSHOT_WITH_WAL, - }}); - - static constexpr const auto *property_name = "property_name"; - static constexpr const auto property_value = 1; - { - // Force the creation of current WAL file - auto acc = main_store.Access(); - for (const auto &vertex_gid : vertex_gids) { - auto v = acc.FindVertex(vertex_gid, memgraph::storage::View::OLD); - ASSERT_TRUE(v); - ASSERT_TRUE( - v->SetProperty(main_store.NameToProperty(property_name), memgraph::storage::PropertyValue(property_value)) - .HasValue()); - } - ASSERT_FALSE(acc.Commit().HasError()); - } - - std::filesystem::path replica_storage_directory{std::filesystem::temp_directory_path() / - "MG_test_unit_storage_v2_replication_replica"}; - memgraph::utils::OnScopeExit replica_directory_cleaner( - [&]() { std::filesystem::remove_all(replica_storage_directory); }); - - static constexpr const auto *vertex_label = "vertex_label"; - { - memgraph::storage::Storage replica_store( - {.durability = { - .storage_directory = replica_storage_directory, - .snapshot_wal_mode = memgraph::storage::Config::Durability::SnapshotWalMode::PERIODIC_SNAPSHOT_WITH_WAL}}); - - replica_store.SetReplicaRole(memgraph::io::network::Endpoint{local_host, ports[0]}); - - ASSERT_FALSE(main_store - .RegisterReplica(replicas[0], memgraph::io::network::Endpoint{local_host, ports[0]}, - memgraph::storage::replication::ReplicationMode::SYNC, - memgraph::storage::replication::RegistrationMode::MUST_BE_INSTANTLY_VALID) - .HasError()); - - ASSERT_EQ(main_store.GetReplicaState(replicas[0]), memgraph::storage::replication::ReplicaState::RECOVERY); - - while (main_store.GetReplicaState(replicas[0]) != memgraph::storage::replication::ReplicaState::READY) { - std::this_thread::sleep_for(std::chrono::milliseconds(10)); - } - - { - auto acc = main_store.Access(); - for (const auto &vertex_gid : vertex_gids) { - auto v = acc.FindVertex(vertex_gid, memgraph::storage::View::OLD); - ASSERT_TRUE(v); - ASSERT_TRUE(v->AddLabel(main_store.NameToLabel(vertex_label)).HasValue()); - } - ASSERT_FALSE(acc.Commit().HasError()); - } - { - auto acc = replica_store.Access(); - for (const auto &vertex_gid : vertex_gids) { - auto v = acc.FindVertex(vertex_gid, memgraph::storage::View::OLD); - ASSERT_TRUE(v); - const auto labels = v->Labels(memgraph::storage::View::OLD); - ASSERT_TRUE(labels.HasValue()); - ASSERT_THAT(*labels, UnorderedElementsAre(replica_store.NameToLabel(vertex_label))); - const auto properties = v->Properties(memgraph::storage::View::OLD); - ASSERT_TRUE(properties.HasValue()); - ASSERT_THAT(*properties, - UnorderedElementsAre(std::make_pair(replica_store.NameToProperty(property_name), - memgraph::storage::PropertyValue(property_value)))); - } - ASSERT_FALSE(acc.Commit().HasError()); - } - } - { - memgraph::storage::Storage replica_store( - {.durability = { - .storage_directory = replica_storage_directory, - .recover_on_startup = true, - .snapshot_wal_mode = memgraph::storage::Config::Durability::SnapshotWalMode::PERIODIC_SNAPSHOT_WITH_WAL}}); - { - auto acc = replica_store.Access(); - for (const auto &vertex_gid : vertex_gids) { - auto v = acc.FindVertex(vertex_gid, memgraph::storage::View::OLD); - ASSERT_TRUE(v); - const auto labels = v->Labels(memgraph::storage::View::OLD); - ASSERT_TRUE(labels.HasValue()); - ASSERT_THAT(*labels, UnorderedElementsAre(replica_store.NameToLabel(vertex_label))); - const auto properties = v->Properties(memgraph::storage::View::OLD); - ASSERT_TRUE(properties.HasValue()); - ASSERT_THAT(*properties, - UnorderedElementsAre(std::make_pair(replica_store.NameToProperty(property_name), - memgraph::storage::PropertyValue(property_value)))); - } - ASSERT_FALSE(acc.Commit().HasError()); - } - } -} - -TEST_F(ReplicationTest, BasicAsynchronousReplicationTest) { - memgraph::storage::Storage main_store(configuration); - - memgraph::storage::Storage replica_store_async(configuration); - - replica_store_async.SetReplicaRole(memgraph::io::network::Endpoint{local_host, ports[1]}); - - ASSERT_FALSE(main_store - .RegisterReplica("REPLICA_ASYNC", memgraph::io::network::Endpoint{local_host, ports[1]}, - memgraph::storage::replication::ReplicationMode::ASYNC, - memgraph::storage::replication::RegistrationMode::MUST_BE_INSTANTLY_VALID) - .HasError()); - - static constexpr size_t vertices_create_num = 10; - std::vector created_vertices; - for (size_t i = 0; i < vertices_create_num; ++i) { - auto acc = main_store.Access(); - auto v = acc.CreateVertex(); - created_vertices.push_back(v.Gid()); - ASSERT_FALSE(acc.Commit().HasError()); - - if (i == 0) { - ASSERT_EQ(main_store.GetReplicaState("REPLICA_ASYNC"), memgraph::storage::replication::ReplicaState::REPLICATING); - } else { - ASSERT_EQ(main_store.GetReplicaState("REPLICA_ASYNC"), memgraph::storage::replication::ReplicaState::RECOVERY); - } - } - - while (main_store.GetReplicaState("REPLICA_ASYNC") != memgraph::storage::replication::ReplicaState::READY) { - std::this_thread::sleep_for(std::chrono::milliseconds(10)); - } - - ASSERT_TRUE(std::all_of(created_vertices.begin(), created_vertices.end(), [&](const auto vertex_gid) { - auto acc = replica_store_async.Access(); - auto v = acc.FindVertex(vertex_gid, memgraph::storage::View::OLD); - const bool exists = v.has_value(); - EXPECT_FALSE(acc.Commit().HasError()); - return exists; - })); -} - -TEST_F(ReplicationTest, EpochTest) { - memgraph::storage::Storage main_store(configuration); - - memgraph::storage::Storage replica_store1(configuration); - - replica_store1.SetReplicaRole(memgraph::io::network::Endpoint{local_host, ports[0]}); - - memgraph::storage::Storage replica_store2(configuration); - - replica_store2.SetReplicaRole(memgraph::io::network::Endpoint{local_host, 10001}); - - ASSERT_FALSE(main_store - .RegisterReplica(replicas[0], memgraph::io::network::Endpoint{local_host, ports[0]}, - memgraph::storage::replication::ReplicationMode::SYNC, - memgraph::storage::replication::RegistrationMode::MUST_BE_INSTANTLY_VALID) - .HasError()); - - ASSERT_FALSE(main_store - .RegisterReplica(replicas[1], memgraph::io::network::Endpoint{local_host, 10001}, - memgraph::storage::replication::ReplicationMode::SYNC, - memgraph::storage::replication::RegistrationMode::MUST_BE_INSTANTLY_VALID) - .HasError()); - - std::optional vertex_gid; - { - auto acc = main_store.Access(); - const auto v = acc.CreateVertex(); - vertex_gid.emplace(v.Gid()); - ASSERT_FALSE(acc.Commit().HasError()); - } - { - auto acc = replica_store1.Access(); - const auto v = acc.FindVertex(*vertex_gid, memgraph::storage::View::OLD); - ASSERT_TRUE(v); - ASSERT_FALSE(acc.Commit().HasError()); - } - { - auto acc = replica_store2.Access(); - const auto v = acc.FindVertex(*vertex_gid, memgraph::storage::View::OLD); - ASSERT_TRUE(v); - ASSERT_FALSE(acc.Commit().HasError()); - } - - main_store.UnregisterReplica(replicas[0]); - main_store.UnregisterReplica(replicas[1]); - - replica_store1.SetMainReplicationRole(); - ASSERT_FALSE(replica_store1 - .RegisterReplica(replicas[1], memgraph::io::network::Endpoint{local_host, 10001}, - memgraph::storage::replication::ReplicationMode::SYNC, - memgraph::storage::replication::RegistrationMode::MUST_BE_INSTANTLY_VALID) - .HasError()); - - { - auto acc = main_store.Access(); - acc.CreateVertex(); - ASSERT_FALSE(acc.Commit().HasError()); - } - { - auto acc = replica_store1.Access(); - auto v = acc.CreateVertex(); - vertex_gid.emplace(v.Gid()); - ASSERT_FALSE(acc.Commit().HasError()); - } - // Replica1 should forward it's vertex to Replica2 - { - auto acc = replica_store2.Access(); - const auto v = acc.FindVertex(*vertex_gid, memgraph::storage::View::OLD); - ASSERT_TRUE(v); - ASSERT_FALSE(acc.Commit().HasError()); - } - - replica_store1.SetReplicaRole(memgraph::io::network::Endpoint{local_host, ports[0]}); - ASSERT_TRUE(main_store - .RegisterReplica(replicas[0], memgraph::io::network::Endpoint{local_host, ports[0]}, - memgraph::storage::replication::ReplicationMode::SYNC, - memgraph::storage::replication::RegistrationMode::MUST_BE_INSTANTLY_VALID) - .HasError()); - - { - auto acc = main_store.Access(); - const auto v = acc.CreateVertex(); - vertex_gid.emplace(v.Gid()); - ASSERT_FALSE(acc.Commit().HasError()); - } - // Replica1 is not compatible with the main so it shouldn't contain - // it's newest vertex - { - auto acc = replica_store1.Access(); - const auto v = acc.FindVertex(*vertex_gid, memgraph::storage::View::OLD); - ASSERT_FALSE(v); - ASSERT_FALSE(acc.Commit().HasError()); - } -} - -TEST_F(ReplicationTest, ReplicationInformation) { - memgraph::storage::Storage main_store(configuration); - - memgraph::storage::Storage replica_store1(configuration); - - const memgraph::io::network::Endpoint replica1_endpoint{local_host, 10001}; - replica_store1.SetReplicaRole(replica1_endpoint); - - const memgraph::io::network::Endpoint replica2_endpoint{local_host, 10002}; - memgraph::storage::Storage replica_store2(configuration); - - replica_store2.SetReplicaRole(replica2_endpoint); - - const std::string replica1_name{replicas[0]}; - ASSERT_FALSE(main_store - .RegisterReplica(replica1_name, replica1_endpoint, - memgraph::storage::replication::ReplicationMode::SYNC, - memgraph::storage::replication::RegistrationMode::MUST_BE_INSTANTLY_VALID) - .HasError()); - - const std::string replica2_name{replicas[1]}; - ASSERT_FALSE(main_store - .RegisterReplica(replica2_name, replica2_endpoint, - memgraph::storage::replication::ReplicationMode::ASYNC, - memgraph::storage::replication::RegistrationMode::MUST_BE_INSTANTLY_VALID) - .HasError()); - - ASSERT_EQ(main_store.GetReplicationRole(), memgraph::storage::ReplicationRole::MAIN); - ASSERT_EQ(replica_store1.GetReplicationRole(), memgraph::storage::ReplicationRole::REPLICA); - ASSERT_EQ(replica_store2.GetReplicationRole(), memgraph::storage::ReplicationRole::REPLICA); - - const auto replicas_info = main_store.ReplicasInfo(); - ASSERT_EQ(replicas_info.size(), 2); - - const auto &first_info = replicas_info[0]; - ASSERT_EQ(first_info.name, replica1_name); - ASSERT_EQ(first_info.mode, memgraph::storage::replication::ReplicationMode::SYNC); - ASSERT_EQ(first_info.endpoint, replica1_endpoint); - ASSERT_EQ(first_info.state, memgraph::storage::replication::ReplicaState::READY); - - const auto &second_info = replicas_info[1]; - ASSERT_EQ(second_info.name, replica2_name); - ASSERT_EQ(second_info.mode, memgraph::storage::replication::ReplicationMode::ASYNC); - ASSERT_EQ(second_info.endpoint, replica2_endpoint); - ASSERT_EQ(second_info.state, memgraph::storage::replication::ReplicaState::READY); -} - -TEST_F(ReplicationTest, ReplicationReplicaWithExistingName) { - memgraph::storage::Storage main_store(configuration); - - memgraph::storage::Storage replica_store1(configuration); - - const memgraph::io::network::Endpoint replica1_endpoint{local_host, 10001}; - replica_store1.SetReplicaRole(replica1_endpoint); - - const memgraph::io::network::Endpoint replica2_endpoint{local_host, 10002}; - memgraph::storage::Storage replica_store2(configuration); - - replica_store2.SetReplicaRole(replica2_endpoint); - - const std::string replica1_name{replicas[0]}; - ASSERT_FALSE(main_store - .RegisterReplica(replica1_name, replica1_endpoint, - memgraph::storage::replication::ReplicationMode::SYNC, - memgraph::storage::replication::RegistrationMode::MUST_BE_INSTANTLY_VALID) - .HasError()); - - const std::string replica2_name{replicas[0]}; - ASSERT_TRUE(main_store - .RegisterReplica(replica2_name, replica2_endpoint, - memgraph::storage::replication::ReplicationMode::ASYNC, - memgraph::storage::replication::RegistrationMode::MUST_BE_INSTANTLY_VALID) - .GetError() == memgraph::storage::Storage::RegisterReplicaError::NAME_EXISTS); -} - -TEST_F(ReplicationTest, ReplicationReplicaWithExistingEndPoint) { - memgraph::storage::Storage main_store(configuration); - - memgraph::storage::Storage replica_store1(configuration); - - const memgraph::io::network::Endpoint replica1_endpoint{local_host, 10001}; - replica_store1.SetReplicaRole(replica1_endpoint); - - const memgraph::io::network::Endpoint replica2_endpoint{local_host, 10001}; - memgraph::storage::Storage replica_store2(configuration); - - replica_store2.SetReplicaRole(replica2_endpoint); - - const std::string replica1_name{replicas[0]}; - ASSERT_FALSE(main_store - .RegisterReplica(replica1_name, replica1_endpoint, - memgraph::storage::replication::ReplicationMode::SYNC, - memgraph::storage::replication::RegistrationMode::MUST_BE_INSTANTLY_VALID) - .HasError()); - - const std::string replica2_name{replicas[1]}; - ASSERT_TRUE(main_store - .RegisterReplica(replica2_name, replica2_endpoint, - memgraph::storage::replication::ReplicationMode::ASYNC, - memgraph::storage::replication::RegistrationMode::MUST_BE_INSTANTLY_VALID) - .GetError() == memgraph::storage::Storage::RegisterReplicaError::END_POINT_EXISTS); -} - -TEST_F(ReplicationTest, RestoringReplicationAtStartupAftgerDroppingReplica) { - auto main_config = configuration; - main_config.durability.restore_replicas_on_startup = true; - auto main_store = std::make_unique(main_config); - - memgraph::storage::Storage replica_store1(configuration); - replica_store1.SetReplicaRole(memgraph::io::network::Endpoint{local_host, ports[0]}); - - memgraph::storage::Storage replica_store2(configuration); - replica_store2.SetReplicaRole(memgraph::io::network::Endpoint{local_host, ports[1]}); - - auto res = main_store->RegisterReplica(replicas[0], memgraph::io::network::Endpoint{local_host, ports[0]}, - memgraph::storage::replication::ReplicationMode::SYNC, - memgraph::storage::replication::RegistrationMode::MUST_BE_INSTANTLY_VALID); - ASSERT_FALSE(res.HasError()); - res = main_store->RegisterReplica(replicas[1], memgraph::io::network::Endpoint{local_host, ports[1]}, - memgraph::storage::replication::ReplicationMode::SYNC, - memgraph::storage::replication::RegistrationMode::MUST_BE_INSTANTLY_VALID); - ASSERT_FALSE(res.HasError()); - - auto replica_infos = main_store->ReplicasInfo(); - - ASSERT_EQ(replica_infos.size(), 2); - ASSERT_EQ(replica_infos[0].name, replicas[0]); - ASSERT_EQ(replica_infos[0].endpoint.address, local_host); - ASSERT_EQ(replica_infos[0].endpoint.port, ports[0]); - ASSERT_EQ(replica_infos[1].name, replicas[1]); - ASSERT_EQ(replica_infos[1].endpoint.address, local_host); - ASSERT_EQ(replica_infos[1].endpoint.port, ports[1]); - - main_store.reset(); - - auto other_main_store = std::make_unique(main_config); - replica_infos = other_main_store->ReplicasInfo(); - ASSERT_EQ(replica_infos.size(), 2); - ASSERT_EQ(replica_infos[0].name, replicas[0]); - ASSERT_EQ(replica_infos[0].endpoint.address, local_host); - ASSERT_EQ(replica_infos[0].endpoint.port, ports[0]); - ASSERT_EQ(replica_infos[1].name, replicas[1]); - ASSERT_EQ(replica_infos[1].endpoint.address, local_host); - ASSERT_EQ(replica_infos[1].endpoint.port, ports[1]); -} - -TEST_F(ReplicationTest, RestoringReplicationAtStartup) { - auto main_config = configuration; - main_config.durability.restore_replicas_on_startup = true; - auto main_store = std::make_unique(main_config); - memgraph::storage::Storage replica_store1(configuration); - replica_store1.SetReplicaRole(memgraph::io::network::Endpoint{local_host, ports[0]}); - - memgraph::storage::Storage replica_store2(configuration); - replica_store2.SetReplicaRole(memgraph::io::network::Endpoint{local_host, ports[1]}); - - auto res = main_store->RegisterReplica(replicas[0], memgraph::io::network::Endpoint{local_host, ports[0]}, - memgraph::storage::replication::ReplicationMode::SYNC, - memgraph::storage::replication::RegistrationMode::MUST_BE_INSTANTLY_VALID); - ASSERT_FALSE(res.HasError()); - res = main_store->RegisterReplica(replicas[1], memgraph::io::network::Endpoint{local_host, ports[1]}, - memgraph::storage::replication::ReplicationMode::SYNC, - memgraph::storage::replication::RegistrationMode::MUST_BE_INSTANTLY_VALID); - ASSERT_FALSE(res.HasError()); - - auto replica_infos = main_store->ReplicasInfo(); - - ASSERT_EQ(replica_infos.size(), 2); - ASSERT_EQ(replica_infos[0].name, replicas[0]); - ASSERT_EQ(replica_infos[0].endpoint.address, local_host); - ASSERT_EQ(replica_infos[0].endpoint.port, ports[0]); - ASSERT_EQ(replica_infos[1].name, replicas[1]); - ASSERT_EQ(replica_infos[1].endpoint.address, local_host); - ASSERT_EQ(replica_infos[1].endpoint.port, ports[1]); - - const auto unregister_res = main_store->UnregisterReplica(replicas[0]); - ASSERT_TRUE(unregister_res); - - replica_infos = main_store->ReplicasInfo(); - ASSERT_EQ(replica_infos.size(), 1); - ASSERT_EQ(replica_infos[0].name, replicas[1]); - ASSERT_EQ(replica_infos[0].endpoint.address, local_host); - ASSERT_EQ(replica_infos[0].endpoint.port, ports[1]); - - main_store.reset(); - - auto other_main_store = std::make_unique(main_config); - replica_infos = other_main_store->ReplicasInfo(); - ASSERT_EQ(replica_infos.size(), 1); - ASSERT_EQ(replica_infos[0].name, replicas[1]); - ASSERT_EQ(replica_infos[0].endpoint.address, local_host); - ASSERT_EQ(replica_infos[0].endpoint.port, ports[1]); -} - -TEST_F(ReplicationTest, AddingInvalidReplica) { - memgraph::storage::Storage main_store(configuration); - - ASSERT_TRUE(main_store - .RegisterReplica("REPLICA", memgraph::io::network::Endpoint{local_host, ports[0]}, - memgraph::storage::replication::ReplicationMode::SYNC, - memgraph::storage::replication::RegistrationMode::MUST_BE_INSTANTLY_VALID) - .GetError() == memgraph::storage::Storage::RegisterReplicaError::CONNECTION_FAILED); -} diff --git a/tests/unit/storage_v2_wal_file.cpp b/tests/unit/storage_v2_wal_file.cpp deleted file mode 100644 index 5eb554aab..000000000 --- a/tests/unit/storage_v2_wal_file.cpp +++ /dev/null @@ -1,623 +0,0 @@ -// Copyright 2022 Memgraph Ltd. -// -// Use of this software is governed by the Business Source License -// included in the file licenses/BSL.txt; by using this file, you agree to be bound by the terms of the Business Source -// License, and you may not use this file except in compliance with the Business Source License. -// -// As of the Change Date specified in that file, in accordance with -// the Business Source License, use of this software will be governed -// by the Apache License, Version 2.0, included in the file -// licenses/APL.txt. - -#include - -#include - -#include -#include -#include - -#include "storage/v2/durability/exceptions.hpp" -#include "storage/v2/durability/version.hpp" -#include "storage/v2/durability/wal.hpp" -#include "storage/v2/mvcc.hpp" -#include "storage/v2/name_id_mapper.hpp" -#include "utils/file.hpp" -#include "utils/file_locker.hpp" -#include "utils/uuid.hpp" - -// Helper function used to convert between enum types. -memgraph::storage::durability::WalDeltaData::Type StorageGlobalOperationToWalDeltaDataType( - memgraph::storage::durability::StorageGlobalOperation operation) { - switch (operation) { - case memgraph::storage::durability::StorageGlobalOperation::LABEL_INDEX_CREATE: - return memgraph::storage::durability::WalDeltaData::Type::LABEL_INDEX_CREATE; - case memgraph::storage::durability::StorageGlobalOperation::LABEL_INDEX_DROP: - return memgraph::storage::durability::WalDeltaData::Type::LABEL_INDEX_DROP; - case memgraph::storage::durability::StorageGlobalOperation::LABEL_PROPERTY_INDEX_CREATE: - return memgraph::storage::durability::WalDeltaData::Type::LABEL_PROPERTY_INDEX_CREATE; - case memgraph::storage::durability::StorageGlobalOperation::LABEL_PROPERTY_INDEX_DROP: - return memgraph::storage::durability::WalDeltaData::Type::LABEL_PROPERTY_INDEX_DROP; - case memgraph::storage::durability::StorageGlobalOperation::EXISTENCE_CONSTRAINT_CREATE: - return memgraph::storage::durability::WalDeltaData::Type::EXISTENCE_CONSTRAINT_CREATE; - case memgraph::storage::durability::StorageGlobalOperation::EXISTENCE_CONSTRAINT_DROP: - return memgraph::storage::durability::WalDeltaData::Type::EXISTENCE_CONSTRAINT_DROP; - case memgraph::storage::durability::StorageGlobalOperation::UNIQUE_CONSTRAINT_CREATE: - return memgraph::storage::durability::WalDeltaData::Type::UNIQUE_CONSTRAINT_CREATE; - case memgraph::storage::durability::StorageGlobalOperation::UNIQUE_CONSTRAINT_DROP: - return memgraph::storage::durability::WalDeltaData::Type::UNIQUE_CONSTRAINT_DROP; - } -} - -// This class mimics the internals of the storage to generate the deltas. -class DeltaGenerator final { - public: - class Transaction final { - private: - friend class DeltaGenerator; - - explicit Transaction(DeltaGenerator *gen) - : gen_(gen), - transaction_(gen->transaction_id_++, gen->timestamp_++, - memgraph::storage::IsolationLevel::SNAPSHOT_ISOLATION) {} - - public: - memgraph::storage::Vertex *CreateVertex() { - auto gid = memgraph::storage::Gid::FromUint(gen_->vertices_count_++); - auto delta = memgraph::storage::CreateDeleteObjectDelta(&transaction_); - auto &it = gen_->vertices_.emplace_back(gid, delta); - delta->prev.Set(&it); - { - memgraph::storage::durability::WalDeltaData data; - data.type = memgraph::storage::durability::WalDeltaData::Type::VERTEX_CREATE; - data.vertex_create_delete.gid = gid; - data_.push_back(data); - } - return ⁢ - } - - void DeleteVertex(memgraph::storage::Vertex *vertex) { - memgraph::storage::CreateAndLinkDelta(&transaction_, &*vertex, memgraph::storage::Delta::RecreateObjectTag()); - { - memgraph::storage::durability::WalDeltaData data; - data.type = memgraph::storage::durability::WalDeltaData::Type::VERTEX_DELETE; - data.vertex_create_delete.gid = vertex->gid; - data_.push_back(data); - } - } - - void AddLabel(memgraph::storage::Vertex *vertex, const std::string &label) { - auto label_id = memgraph::storage::LabelId::FromUint(gen_->mapper_.NameToId(label)); - vertex->labels.push_back(label_id); - memgraph::storage::CreateAndLinkDelta(&transaction_, &*vertex, memgraph::storage::Delta::RemoveLabelTag(), - label_id); - { - memgraph::storage::durability::WalDeltaData data; - data.type = memgraph::storage::durability::WalDeltaData::Type::VERTEX_ADD_LABEL; - data.vertex_add_remove_label.gid = vertex->gid; - data.vertex_add_remove_label.label = label; - data_.push_back(data); - } - } - - void RemoveLabel(memgraph::storage::Vertex *vertex, const std::string &label) { - auto label_id = memgraph::storage::LabelId::FromUint(gen_->mapper_.NameToId(label)); - vertex->labels.erase(std::find(vertex->labels.begin(), vertex->labels.end(), label_id)); - memgraph::storage::CreateAndLinkDelta(&transaction_, &*vertex, memgraph::storage::Delta::AddLabelTag(), label_id); - { - memgraph::storage::durability::WalDeltaData data; - data.type = memgraph::storage::durability::WalDeltaData::Type::VERTEX_REMOVE_LABEL; - data.vertex_add_remove_label.gid = vertex->gid; - data.vertex_add_remove_label.label = label; - data_.push_back(data); - } - } - - void SetProperty(memgraph::storage::Vertex *vertex, const std::string &property, - const memgraph::storage::PropertyValue &value) { - auto property_id = memgraph::storage::PropertyId::FromUint(gen_->mapper_.NameToId(property)); - auto &props = vertex->properties; - auto old_value = props.GetProperty(property_id); - memgraph::storage::CreateAndLinkDelta(&transaction_, &*vertex, memgraph::storage::Delta::SetPropertyTag(), - property_id, old_value); - props.SetProperty(property_id, value); - { - memgraph::storage::durability::WalDeltaData data; - data.type = memgraph::storage::durability::WalDeltaData::Type::VERTEX_SET_PROPERTY; - data.vertex_edge_set_property.gid = vertex->gid; - data.vertex_edge_set_property.property = property; - // We don't store the property value here. That is because the storage - // generates multiple `SetProperty` deltas using only the final values - // of the property. The intermediate values aren't encoded. The value is - // later determined in the `Finalize` function. - data_.push_back(data); - } - } - - void Finalize(bool append_transaction_end = true) { - auto commit_timestamp = gen_->timestamp_++; - for (const auto &delta : transaction_.deltas) { - auto owner = delta.prev.Get(); - while (owner.type == memgraph::storage::PreviousPtr::Type::DELTA) { - owner = owner.delta->prev.Get(); - } - if (owner.type == memgraph::storage::PreviousPtr::Type::VERTEX) { - gen_->wal_file_.AppendDelta(delta, *owner.vertex, commit_timestamp); - } else if (owner.type == memgraph::storage::PreviousPtr::Type::EDGE) { - gen_->wal_file_.AppendDelta(delta, *owner.edge, commit_timestamp); - } else { - LOG_FATAL("Invalid delta owner!"); - } - } - if (append_transaction_end) { - gen_->wal_file_.AppendTransactionEnd(commit_timestamp); - if (gen_->valid_) { - gen_->UpdateStats(commit_timestamp, transaction_.deltas.size() + 1); - for (auto &data : data_) { - if (data.type == memgraph::storage::durability::WalDeltaData::Type::VERTEX_SET_PROPERTY) { - // We need to put the final property value into the SET_PROPERTY - // delta. - auto vertex = - std::find(gen_->vertices_.begin(), gen_->vertices_.end(), data.vertex_edge_set_property.gid); - ASSERT_NE(vertex, gen_->vertices_.end()); - auto property_id = memgraph::storage::PropertyId::FromUint( - gen_->mapper_.NameToId(data.vertex_edge_set_property.property)); - data.vertex_edge_set_property.value = vertex->properties.GetProperty(property_id); - } - gen_->data_.emplace_back(commit_timestamp, data); - } - memgraph::storage::durability::WalDeltaData data{ - .type = memgraph::storage::durability::WalDeltaData::Type::TRANSACTION_END}; - gen_->data_.emplace_back(commit_timestamp, data); - } - } else { - gen_->valid_ = false; - } - } - - private: - DeltaGenerator *gen_; - memgraph::storage::Transaction transaction_; - std::vector data_; - }; - - using DataT = std::vector>; - - DeltaGenerator(const std::filesystem::path &data_directory, bool properties_on_edges, uint64_t seq_num) - : uuid_(memgraph::utils::GenerateUUID()), - epoch_id_(memgraph::utils::GenerateUUID()), - seq_num_(seq_num), - wal_file_(data_directory, uuid_, epoch_id_, {.properties_on_edges = properties_on_edges}, &mapper_, seq_num, - &file_retainer_) {} - - Transaction CreateTransaction() { return Transaction(this); } - - void ResetTransactionIds() { - transaction_id_ = memgraph::storage::kTransactionInitialId; - timestamp_ = memgraph::storage::kTimestampInitialId; - valid_ = false; - } - - void AppendOperation(memgraph::storage::durability::StorageGlobalOperation operation, const std::string &label, - const std::set properties = {}) { - auto label_id = memgraph::storage::LabelId::FromUint(mapper_.NameToId(label)); - std::set property_ids; - for (const auto &property : properties) { - property_ids.insert(memgraph::storage::PropertyId::FromUint(mapper_.NameToId(property))); - } - wal_file_.AppendOperation(operation, label_id, property_ids, timestamp_); - if (valid_) { - UpdateStats(timestamp_, 1); - memgraph::storage::durability::WalDeltaData data; - data.type = StorageGlobalOperationToWalDeltaDataType(operation); - switch (operation) { - case memgraph::storage::durability::StorageGlobalOperation::LABEL_INDEX_CREATE: - case memgraph::storage::durability::StorageGlobalOperation::LABEL_INDEX_DROP: - data.operation_label.label = label; - break; - case memgraph::storage::durability::StorageGlobalOperation::LABEL_PROPERTY_INDEX_CREATE: - case memgraph::storage::durability::StorageGlobalOperation::LABEL_PROPERTY_INDEX_DROP: - case memgraph::storage::durability::StorageGlobalOperation::EXISTENCE_CONSTRAINT_CREATE: - case memgraph::storage::durability::StorageGlobalOperation::EXISTENCE_CONSTRAINT_DROP: - data.operation_label_property.label = label; - data.operation_label_property.property = *properties.begin(); - case memgraph::storage::durability::StorageGlobalOperation::UNIQUE_CONSTRAINT_CREATE: - case memgraph::storage::durability::StorageGlobalOperation::UNIQUE_CONSTRAINT_DROP: - data.operation_label_properties.label = label; - data.operation_label_properties.properties = properties; - } - data_.emplace_back(timestamp_, data); - } - } - - uint64_t GetPosition() { return wal_file_.GetSize(); } - - memgraph::storage::durability::WalInfo GetInfo() { - return {.offset_metadata = 0, - .offset_deltas = 0, - .uuid = uuid_, - .epoch_id = epoch_id_, - .seq_num = seq_num_, - .from_timestamp = tx_from_, - .to_timestamp = tx_to_, - .num_deltas = deltas_count_}; - } - - DataT GetData() { return data_; } - - private: - void UpdateStats(uint64_t timestamp, uint64_t count) { - if (deltas_count_ == 0) { - tx_from_ = timestamp; - } - tx_to_ = timestamp; - deltas_count_ += count; - } - - std::string uuid_; - std::string epoch_id_; - uint64_t seq_num_; - - uint64_t transaction_id_{memgraph::storage::kTransactionInitialId}; - uint64_t timestamp_{memgraph::storage::kTimestampInitialId}; - uint64_t vertices_count_{0}; - std::list vertices_; - memgraph::storage::NameIdMapper mapper_; - - memgraph::storage::durability::WalFile wal_file_; - - DataT data_; - - uint64_t deltas_count_{0}; - uint64_t tx_from_{0}; - uint64_t tx_to_{0}; - uint64_t valid_{true}; - - memgraph::utils::FileRetainer file_retainer_; -}; - -// NOLINTNEXTLINE(cppcoreguidelines-macro-usage) -#define TRANSACTION(append_transaction_end, ops) \ - { \ - auto tx = gen.CreateTransaction(); \ - ops; \ - tx.Finalize(append_transaction_end); \ - } - -// NOLINTNEXTLINE(cppcoreguidelines-macro-usage) -#define OPERATION(op, ...) gen.AppendOperation(memgraph::storage::durability::StorageGlobalOperation::op, __VA_ARGS__) - -void AssertWalInfoEqual(const memgraph::storage::durability::WalInfo &a, - const memgraph::storage::durability::WalInfo &b) { - ASSERT_EQ(a.uuid, b.uuid); - ASSERT_EQ(a.epoch_id, b.epoch_id); - ASSERT_EQ(a.seq_num, b.seq_num); - ASSERT_EQ(a.from_timestamp, b.from_timestamp); - ASSERT_EQ(a.to_timestamp, b.to_timestamp); - ASSERT_EQ(a.num_deltas, b.num_deltas); -} - -void AssertWalDataEqual(const DeltaGenerator::DataT &data, const std::filesystem::path &path) { - auto info = memgraph::storage::durability::ReadWalInfo(path); - memgraph::storage::durability::Decoder wal; - wal.Initialize(path, memgraph::storage::durability::kWalMagic); - wal.SetPosition(info.offset_deltas); - DeltaGenerator::DataT current; - for (uint64_t i = 0; i < info.num_deltas; ++i) { - auto timestamp = memgraph::storage::durability::ReadWalDeltaHeader(&wal); - current.emplace_back(timestamp, memgraph::storage::durability::ReadWalDeltaData(&wal)); - } - ASSERT_EQ(data.size(), current.size()); - ASSERT_EQ(data, current); -} - -class WalFileTest : public ::testing::TestWithParam { - public: - WalFileTest() {} - - void SetUp() override { Clear(); } - - void TearDown() override { Clear(); } - - std::vector GetFilesList() { - std::vector ret; - for (auto &item : std::filesystem::directory_iterator(storage_directory)) { - ret.push_back(item.path()); - } - std::sort(ret.begin(), ret.end()); - std::reverse(ret.begin(), ret.end()); - return ret; - } - - std::filesystem::path storage_directory{std::filesystem::temp_directory_path() / "MG_test_unit_storage_v2_wal_file"}; - - private: - void Clear() { - if (!std::filesystem::exists(storage_directory)) return; - std::filesystem::remove_all(storage_directory); - } -}; - -INSTANTIATE_TEST_CASE_P(EdgesWithProperties, WalFileTest, ::testing::Values(true)); -INSTANTIATE_TEST_CASE_P(EdgesWithoutProperties, WalFileTest, ::testing::Values(false)); - -// NOLINTNEXTLINE(hicpp-special-member-functions) -TEST_P(WalFileTest, EmptyFile) { - { DeltaGenerator gen(storage_directory, GetParam(), 5); } - auto wal_files = GetFilesList(); - ASSERT_EQ(wal_files.size(), 0); -} - -// NOLINTNEXTLINE(cppcoreguidelines-macro-usage) -#define GENERATE_SIMPLE_TEST(name, ops) \ - TEST_P(WalFileTest, name) { \ - memgraph::storage::durability::WalInfo info; \ - DeltaGenerator::DataT data; \ - \ - { \ - DeltaGenerator gen(storage_directory, GetParam(), 5); \ - ops; \ - info = gen.GetInfo(); \ - data = gen.GetData(); \ - } \ - \ - auto wal_files = GetFilesList(); \ - ASSERT_EQ(wal_files.size(), 1); \ - \ - if (info.num_deltas == 0) { \ - ASSERT_THROW(memgraph::storage::durability::ReadWalInfo(wal_files.front()), \ - memgraph::storage::durability::RecoveryFailure); \ - } else { \ - AssertWalInfoEqual(info, memgraph::storage::durability::ReadWalInfo(wal_files.front())); \ - AssertWalDataEqual(data, wal_files.front()); \ - } \ - } - -// NOLINTNEXTLINE(hicpp-special-member-functions) -GENERATE_SIMPLE_TEST(TransactionWithEnd, { TRANSACTION(true, { tx.CreateVertex(); }); }); -// NOLINTNEXTLINE(hicpp-special-member-functions) -GENERATE_SIMPLE_TEST(TransactionWithoutEnd, { TRANSACTION(false, { tx.CreateVertex(); }); }); -// NOLINTNEXTLINE(hicpp-special-member-functions) -GENERATE_SIMPLE_TEST(OperationSingle, { OPERATION(LABEL_INDEX_CREATE, "hello"); }); - -// NOLINTNEXTLINE(hicpp-special-member-functions) -GENERATE_SIMPLE_TEST(TransactionsEnd00, { - TRANSACTION(false, { tx.CreateVertex(); }); - TRANSACTION(false, { tx.CreateVertex(); }); -}); -// NOLINTNEXTLINE(hicpp-special-member-functions) -GENERATE_SIMPLE_TEST(TransactionsEnd01, { - TRANSACTION(false, { tx.CreateVertex(); }); - TRANSACTION(true, { tx.CreateVertex(); }); -}); -// NOLINTNEXTLINE(hicpp-special-member-functions) -GENERATE_SIMPLE_TEST(TransactionsEnd10, { - TRANSACTION(true, { tx.CreateVertex(); }); - TRANSACTION(false, { tx.CreateVertex(); }); -}); -// NOLINTNEXTLINE(hicpp-special-member-functions) -GENERATE_SIMPLE_TEST(TransactionsEnd11, { - TRANSACTION(true, { tx.CreateVertex(); }); - TRANSACTION(true, { tx.CreateVertex(); }); -}); - -// NOLINTNEXTLINE(hicpp-special-member-functions) -GENERATE_SIMPLE_TEST(TransactionsWithOperation_00, { - OPERATION(LABEL_INDEX_CREATE, "hello"); - TRANSACTION(false, { tx.CreateVertex(); }); - TRANSACTION(false, { tx.CreateVertex(); }); -}); -// NOLINTNEXTLINE(hicpp-special-member-functions) -GENERATE_SIMPLE_TEST(TransactionsWithOperation_01, { - OPERATION(LABEL_INDEX_CREATE, "hello"); - TRANSACTION(false, { tx.CreateVertex(); }); - TRANSACTION(true, { tx.CreateVertex(); }); -}); -// NOLINTNEXTLINE(hicpp-special-member-functions) -GENERATE_SIMPLE_TEST(TransactionsWithOperation_10, { - OPERATION(LABEL_INDEX_CREATE, "hello"); - TRANSACTION(true, { tx.CreateVertex(); }); - TRANSACTION(false, { tx.CreateVertex(); }); -}); -// NOLINTNEXTLINE(hicpp-special-member-functions) -GENERATE_SIMPLE_TEST(TransactionsWithOperation_11, { - OPERATION(LABEL_INDEX_CREATE, "hello"); - TRANSACTION(true, { tx.CreateVertex(); }); - TRANSACTION(true, { tx.CreateVertex(); }); -}); - -// NOLINTNEXTLINE(hicpp-special-member-functions) -GENERATE_SIMPLE_TEST(TransactionsWithOperation0_0, { - TRANSACTION(false, { tx.CreateVertex(); }); - OPERATION(LABEL_INDEX_CREATE, "hello"); - TRANSACTION(false, { tx.CreateVertex(); }); -}); -// NOLINTNEXTLINE(hicpp-special-member-functions) -GENERATE_SIMPLE_TEST(TransactionsWithOperation0_1, { - TRANSACTION(false, { tx.CreateVertex(); }); - OPERATION(LABEL_INDEX_CREATE, "hello"); - TRANSACTION(true, { tx.CreateVertex(); }); -}); -// NOLINTNEXTLINE(hicpp-special-member-functions) -GENERATE_SIMPLE_TEST(TransactionsWithOperation1_0, { - TRANSACTION(true, { tx.CreateVertex(); }); - OPERATION(LABEL_INDEX_CREATE, "hello"); - TRANSACTION(false, { tx.CreateVertex(); }); -}); -// NOLINTNEXTLINE(hicpp-special-member-functions) -GENERATE_SIMPLE_TEST(TransactionsWithOperation1_1, { - TRANSACTION(true, { tx.CreateVertex(); }); - OPERATION(LABEL_INDEX_CREATE, "hello"); - TRANSACTION(true, { tx.CreateVertex(); }); -}); - -// NOLINTNEXTLINE(hicpp-special-member-functions) -GENERATE_SIMPLE_TEST(TransactionsWithOperation00_, { - TRANSACTION(false, { tx.CreateVertex(); }); - TRANSACTION(false, { tx.CreateVertex(); }); - OPERATION(LABEL_INDEX_CREATE, "hello"); -}); -// NOLINTNEXTLINE(hicpp-special-member-functions) -GENERATE_SIMPLE_TEST(TransactionsWithOperation01_, { - TRANSACTION(false, { tx.CreateVertex(); }); - TRANSACTION(true, { tx.CreateVertex(); }); - OPERATION(LABEL_INDEX_CREATE, "hello"); -}); -// NOLINTNEXTLINE(hicpp-special-member-functions) -GENERATE_SIMPLE_TEST(TransactionsWithOperation10_, { - TRANSACTION(true, { tx.CreateVertex(); }); - TRANSACTION(false, { tx.CreateVertex(); }); - OPERATION(LABEL_INDEX_CREATE, "hello"); -}); -// NOLINTNEXTLINE(hicpp-special-member-functions) -GENERATE_SIMPLE_TEST(TransactionsWithOperation11_, { - TRANSACTION(true, { tx.CreateVertex(); }); - TRANSACTION(true, { tx.CreateVertex(); }); - OPERATION(LABEL_INDEX_CREATE, "hello"); -}); - -// NOLINTNEXTLINE(hicpp-special-member-functions) -GENERATE_SIMPLE_TEST(AllTransactionOperationsWithEnd, { - TRANSACTION(true, { - auto vertex1 = tx.CreateVertex(); - auto vertex2 = tx.CreateVertex(); - tx.AddLabel(vertex1, "test"); - tx.AddLabel(vertex2, "hello"); - tx.SetProperty(vertex2, "hello", memgraph::storage::PropertyValue("nandare")); - tx.RemoveLabel(vertex1, "test"); - tx.SetProperty(vertex2, "hello", memgraph::storage::PropertyValue(123)); - tx.SetProperty(vertex2, "hello", memgraph::storage::PropertyValue()); - tx.DeleteVertex(vertex1); - }); -}); -// NOLINTNEXTLINE(hicpp-special-member-functions) -GENERATE_SIMPLE_TEST(AllTransactionOperationsWithoutEnd, { - TRANSACTION(false, { - auto vertex1 = tx.CreateVertex(); - auto vertex2 = tx.CreateVertex(); - tx.AddLabel(vertex1, "test"); - tx.AddLabel(vertex2, "hello"); - tx.SetProperty(vertex2, "hello", memgraph::storage::PropertyValue("nandare")); - tx.RemoveLabel(vertex1, "test"); - tx.SetProperty(vertex2, "hello", memgraph::storage::PropertyValue(123)); - tx.SetProperty(vertex2, "hello", memgraph::storage::PropertyValue()); - tx.DeleteVertex(vertex1); - }); -}); -// NOLINTNEXTLINE(hicpp-special-member-functions) -GENERATE_SIMPLE_TEST(AllGlobalOperations, { - OPERATION(LABEL_INDEX_CREATE, "hello"); - OPERATION(LABEL_INDEX_DROP, "hello"); - OPERATION(LABEL_PROPERTY_INDEX_CREATE, "hello", {"world"}); - OPERATION(LABEL_PROPERTY_INDEX_DROP, "hello", {"world"}); - OPERATION(EXISTENCE_CONSTRAINT_CREATE, "hello", {"world"}); - OPERATION(EXISTENCE_CONSTRAINT_DROP, "hello", {"world"}); - OPERATION(UNIQUE_CONSTRAINT_CREATE, "hello", {"world", "and", "universe"}); - OPERATION(UNIQUE_CONSTRAINT_DROP, "hello", {"world", "and", "universe"}); -}); - -// NOLINTNEXTLINE(hicpp-special-member-functions) -GENERATE_SIMPLE_TEST(InvalidTransactionOrdering, { - TRANSACTION(true, { tx.CreateVertex(); }); - TRANSACTION(true, { tx.CreateVertex(); }); - TRANSACTION(true, { tx.CreateVertex(); }); - gen.ResetTransactionIds(); - TRANSACTION(true, { tx.CreateVertex(); }); -}); - -// NOLINTNEXTLINE(hicpp-special-member-functions) -TEST_P(WalFileTest, InvalidMarker) { - memgraph::storage::durability::WalInfo info; - - { - DeltaGenerator gen(storage_directory, GetParam(), 5); - TRANSACTION(true, { tx.CreateVertex(); }); - info = gen.GetInfo(); - } - - auto wal_files = GetFilesList(); - ASSERT_EQ(wal_files.size(), 1); - const auto &wal_file = wal_files.front(); - - auto final_info = memgraph::storage::durability::ReadWalInfo(wal_file); - AssertWalInfoEqual(info, final_info); - - size_t i = 0; - for (auto marker : memgraph::storage::durability::kMarkersAll) { - if (marker == memgraph::storage::durability::Marker::SECTION_DELTA) continue; - auto current_file = storage_directory / fmt::format("temporary_{}", i); - ASSERT_TRUE(std::filesystem::copy_file(wal_file, current_file)); - memgraph::utils::OutputFile file; - file.Open(current_file, memgraph::utils::OutputFile::Mode::OVERWRITE_EXISTING); - file.SetPosition(memgraph::utils::OutputFile::Position::SET, final_info.offset_deltas); - auto value = static_cast(marker); - file.Write(&value, sizeof(value)); - file.Sync(); - file.Close(); - ASSERT_THROW(memgraph::storage::durability::ReadWalInfo(current_file), - memgraph::storage::durability::RecoveryFailure); - ++i; - } -} - -// NOLINTNEXTLINE(hicpp-special-member-functions) -TEST_P(WalFileTest, PartialData) { - std::vector> infos; - - { - DeltaGenerator gen(storage_directory, GetParam(), 5); - TRANSACTION(true, { tx.CreateVertex(); }); - infos.emplace_back(gen.GetPosition(), gen.GetInfo()); - TRANSACTION(true, { - auto vertex = tx.CreateVertex(); - tx.AddLabel(vertex, "hello"); - }); - infos.emplace_back(gen.GetPosition(), gen.GetInfo()); - OPERATION(LABEL_PROPERTY_INDEX_CREATE, "hello", {"world"}); - infos.emplace_back(gen.GetPosition(), gen.GetInfo()); - TRANSACTION(true, { - auto vertex1 = tx.CreateVertex(); - auto vertex2 = tx.CreateVertex(); - tx.AddLabel(vertex1, "test"); - tx.AddLabel(vertex2, "hello"); - tx.SetProperty(vertex2, "hello", memgraph::storage::PropertyValue("nandare")); - tx.RemoveLabel(vertex1, "test"); - tx.SetProperty(vertex2, "hello", memgraph::storage::PropertyValue(123)); - tx.SetProperty(vertex2, "hello", memgraph::storage::PropertyValue()); - tx.DeleteVertex(vertex1); - }); - infos.emplace_back(gen.GetPosition(), gen.GetInfo()); - } - - auto wal_files = GetFilesList(); - ASSERT_EQ(wal_files.size(), 1); - const auto &wal_file = wal_files.front(); - - AssertWalInfoEqual(infos.back().second, memgraph::storage::durability::ReadWalInfo(wal_file)); - - auto current_file = storage_directory / "temporary"; - memgraph::utils::InputFile infile; - infile.Open(wal_file); - - uint64_t pos = 0; - for (size_t i = 0; i < infile.GetSize(); ++i) { - if (i < infos.front().first) { - ASSERT_THROW(memgraph::storage::durability::ReadWalInfo(current_file), - memgraph::storage::durability::RecoveryFailure); - } else { - if (i >= infos[pos + 1].first) ++pos; - AssertWalInfoEqual(infos[pos].second, memgraph::storage::durability::ReadWalInfo(current_file)); - } - { - memgraph::utils::OutputFile outfile; - outfile.Open(current_file, memgraph::utils::OutputFile::Mode::APPEND_TO_EXISTING); - uint8_t value; - ASSERT_TRUE(infile.Read(&value, sizeof(value))); - outfile.Write(&value, sizeof(value)); - outfile.Sync(); - outfile.Close(); - } - } - ASSERT_EQ(pos, infos.size() - 2); - AssertWalInfoEqual(infos[infos.size() - 1].second, memgraph::storage::durability::ReadWalInfo(current_file)); -}