Merge branch 'project-pineapples' into T1159-MG-Add-memgraph-functions
This commit is contained in:
@@ -137,7 +137,7 @@ void Commit(ShardClient &client, const coordinator::Hlc &transaction_timestamp)
|
||||
|
||||
auto write_response_result = write_res.GetValue();
|
||||
auto write_response = std::get<msgs::CommitResponse>(write_response_result);
|
||||
MG_ASSERT(write_response.success, "Commit expected to be successful, but it is failed");
|
||||
MG_ASSERT(!write_response.error.has_value(), "Commit expected to be successful, but it is failed");
|
||||
|
||||
break;
|
||||
}
|
||||
@@ -156,7 +156,7 @@ bool AttemptToCreateVertex(ShardClient &client, int64_t value) {
|
||||
create_req.transaction_id.logical_id = GetTransactionId();
|
||||
|
||||
auto write_res = client.SendWriteRequest(create_req);
|
||||
MG_ASSERT(write_res.HasValue() && std::get<msgs::CreateVerticesResponse>(write_res.GetValue()).success,
|
||||
MG_ASSERT(write_res.HasValue() && !std::get<msgs::CreateVerticesResponse>(write_res.GetValue()).error.has_value(),
|
||||
"Unexpected failure");
|
||||
|
||||
Commit(client, create_req.transaction_id);
|
||||
@@ -179,23 +179,26 @@ bool AttemptToDeleteVertex(ShardClient &client, int64_t value) {
|
||||
auto write_response = std::get<msgs::DeleteVerticesResponse>(write_response_result);
|
||||
|
||||
Commit(client, delete_req.transaction_id);
|
||||
return write_response.success;
|
||||
return !write_response.error.has_value();
|
||||
}
|
||||
}
|
||||
|
||||
bool AttemptToUpdateVertex(ShardClient &client, int64_t value) {
|
||||
auto vertex_id = GetValuePrimaryKeysWithValue(value)[0];
|
||||
bool AttemptToUpdateVertex(ShardClient &client, int64_t vertex_primary_key, std::vector<LabelId> add_labels = {},
|
||||
std::vector<LabelId> remove_labels = {}) {
|
||||
auto vertex_id = GetValuePrimaryKeysWithValue(vertex_primary_key)[0];
|
||||
|
||||
std::vector<std::pair<PropertyId, msgs::Value>> property_updates;
|
||||
auto property_update = std::make_pair(PropertyId::FromUint(5), msgs::Value(static_cast<int64_t>(10000)));
|
||||
|
||||
auto vertex_prop = msgs::UpdateVertexProp{};
|
||||
vertex_prop.primary_key = vertex_id;
|
||||
vertex_prop.property_updates = {property_update};
|
||||
msgs::UpdateVertex update_vertex;
|
||||
update_vertex.primary_key = vertex_id;
|
||||
update_vertex.property_updates = {property_update};
|
||||
update_vertex.add_labels = add_labels;
|
||||
update_vertex.remove_labels = remove_labels;
|
||||
|
||||
auto update_req = msgs::UpdateVerticesRequest{};
|
||||
msgs::UpdateVerticesRequest update_req;
|
||||
update_req.transaction_id.logical_id = GetTransactionId();
|
||||
update_req.new_properties = {vertex_prop};
|
||||
update_req.update_vertices = {update_vertex};
|
||||
|
||||
while (true) {
|
||||
auto write_res = client.SendWriteRequest(update_req);
|
||||
@@ -207,7 +210,38 @@ bool AttemptToUpdateVertex(ShardClient &client, int64_t value) {
|
||||
auto write_response = std::get<msgs::UpdateVerticesResponse>(write_response_result);
|
||||
|
||||
Commit(client, update_req.transaction_id);
|
||||
return write_response.success;
|
||||
return !write_response.error.has_value();
|
||||
}
|
||||
}
|
||||
|
||||
bool AttemptToRemoveVertexProperty(ShardClient &client, int64_t primary_key, std::vector<LabelId> add_labels = {},
|
||||
std::vector<LabelId> remove_labels = {}) {
|
||||
auto vertex_id = GetValuePrimaryKeysWithValue(primary_key)[0];
|
||||
|
||||
std::vector<std::pair<PropertyId, msgs::Value>> property_updates;
|
||||
auto property_update = std::make_pair(PropertyId::FromUint(5), msgs::Value());
|
||||
|
||||
msgs::UpdateVertex update_vertex;
|
||||
update_vertex.primary_key = vertex_id;
|
||||
update_vertex.property_updates = {property_update};
|
||||
update_vertex.add_labels = add_labels;
|
||||
update_vertex.remove_labels = remove_labels;
|
||||
|
||||
msgs::UpdateVerticesRequest update_req;
|
||||
update_req.transaction_id.logical_id = GetTransactionId();
|
||||
update_req.update_vertices = {update_vertex};
|
||||
|
||||
while (true) {
|
||||
auto write_res = client.SendWriteRequest(update_req);
|
||||
if (write_res.HasError()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
auto write_response_result = write_res.GetValue();
|
||||
auto write_response = std::get<msgs::UpdateVerticesResponse>(write_response_result);
|
||||
|
||||
Commit(client, update_req.transaction_id);
|
||||
return !write_response.error.has_value();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -244,7 +278,7 @@ bool AttemptToAddEdge(ShardClient &client, int64_t value_of_vertex_1, int64_t va
|
||||
|
||||
Commit(client, create_req.transaction_id);
|
||||
|
||||
return write_response.success;
|
||||
return !write_response.error.has_value();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -276,7 +310,7 @@ bool AttemptToAddEdgeWithProperties(ShardClient &client, int64_t value_of_vertex
|
||||
create_req.transaction_id.logical_id = GetTransactionId();
|
||||
|
||||
auto write_res = client.SendWriteRequest(create_req);
|
||||
MG_ASSERT(write_res.HasValue() && std::get<msgs::CreateExpandResponse>(write_res.GetValue()).success,
|
||||
MG_ASSERT(write_res.HasValue() && !std::get<msgs::CreateExpandResponse>(write_res.GetValue()).error.has_value(),
|
||||
"Unexpected failure");
|
||||
|
||||
Commit(client, create_req.transaction_id);
|
||||
@@ -316,7 +350,7 @@ bool AttemptToDeleteEdge(ShardClient &client, int64_t value_of_vertex_1, int64_t
|
||||
auto write_response = std::get<msgs::DeleteEdgesResponse>(write_response_result);
|
||||
|
||||
Commit(client, delete_req.transaction_id);
|
||||
return write_response.success;
|
||||
return !write_response.error.has_value();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -356,7 +390,7 @@ bool AttemptToUpdateEdge(ShardClient &client, int64_t value_of_vertex_1, int64_t
|
||||
auto write_response = std::get<msgs::UpdateEdgesResponse>(write_response_result);
|
||||
|
||||
Commit(client, update_req.transaction_id);
|
||||
return write_response.success;
|
||||
return !write_response.error.has_value();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -379,7 +413,7 @@ std::tuple<size_t, std::optional<msgs::VertexId>> AttemptToScanAllWithoutBatchLi
|
||||
auto write_response_result = read_res.GetValue();
|
||||
auto write_response = std::get<msgs::ScanVerticesResponse>(write_response_result);
|
||||
|
||||
MG_ASSERT(write_response.success);
|
||||
MG_ASSERT(write_response.error == std::nullopt);
|
||||
|
||||
return {write_response.results.size(), write_response.next_start_id};
|
||||
}
|
||||
@@ -405,7 +439,7 @@ std::tuple<size_t, std::optional<msgs::VertexId>> AttemptToScanAllWithBatchLimit
|
||||
auto write_response_result = read_res.GetValue();
|
||||
auto write_response = std::get<msgs::ScanVerticesResponse>(write_response_result);
|
||||
|
||||
MG_ASSERT(write_response.success);
|
||||
MG_ASSERT(!write_response.error.has_value());
|
||||
|
||||
return {write_response.results.size(), write_response.next_start_id};
|
||||
}
|
||||
@@ -439,7 +473,7 @@ std::tuple<size_t, std::optional<msgs::VertexId>> AttemptToScanAllWithExpression
|
||||
auto write_response_result = read_res.GetValue();
|
||||
auto write_response = std::get<msgs::ScanVerticesResponse>(write_response_result);
|
||||
|
||||
MG_ASSERT(write_response.success);
|
||||
MG_ASSERT(!write_response.error.has_value());
|
||||
MG_ASSERT(!write_response.results.empty(), "There are no results!");
|
||||
MG_ASSERT(write_response.results[0].evaluated_vertex_expressions[0].int_v == 4);
|
||||
return {write_response.results.size(), write_response.next_start_id};
|
||||
@@ -464,7 +498,7 @@ void AttemptToScanAllWithOrderByOnPrimaryProperty(ShardClient &client, msgs::Ver
|
||||
auto write_response_result = read_res.GetValue();
|
||||
auto write_response = std::get<msgs::ScanVerticesResponse>(write_response_result);
|
||||
|
||||
MG_ASSERT(write_response.success);
|
||||
MG_ASSERT(!write_response.error.has_value());
|
||||
MG_ASSERT(write_response.results.size() == 5, "Expecting 5 results!");
|
||||
for (int64_t i{0}; i < 5; ++i) {
|
||||
const auto expected_primary_key = std::vector{msgs::Value(1023 - i)};
|
||||
@@ -494,7 +528,7 @@ void AttemptToScanAllWithOrderByOnSecondaryProperty(ShardClient &client, msgs::V
|
||||
auto write_response_result = read_res.GetValue();
|
||||
auto write_response = std::get<msgs::ScanVerticesResponse>(write_response_result);
|
||||
|
||||
MG_ASSERT(write_response.success);
|
||||
MG_ASSERT(!write_response.error.has_value());
|
||||
MG_ASSERT(write_response.results.size() == 5, "Expecting 5 results!");
|
||||
for (int64_t i{0}; i < 5; ++i) {
|
||||
const auto expected_prop4 = std::vector{msgs::Value(1023 - i)};
|
||||
@@ -531,7 +565,8 @@ void AttemptToExpandOneWithWrongEdgeType(ShardClient &client, uint64_t src_verte
|
||||
std::optional<std::vector<PropertyId>> edge_properties = {};
|
||||
|
||||
std::vector<std::string> expressions;
|
||||
std::optional<std::vector<msgs::OrderBy>> order_by = {};
|
||||
std::vector<msgs::OrderBy> order_by_vertices = {};
|
||||
std::vector<msgs::OrderBy> order_by_edges = {};
|
||||
std::optional<size_t> limit = {};
|
||||
std::vector<std::string> filter = {};
|
||||
|
||||
@@ -543,7 +578,8 @@ void AttemptToExpandOneWithWrongEdgeType(ShardClient &client, uint64_t src_verte
|
||||
expand_one_req.vertex_expressions = expressions;
|
||||
expand_one_req.filters = filter;
|
||||
expand_one_req.limit = limit;
|
||||
expand_one_req.order_by = order_by;
|
||||
expand_one_req.order_by_vertices = order_by_vertices;
|
||||
expand_one_req.order_by_edges = order_by_edges;
|
||||
expand_one_req.src_vertex_properties = src_vertex_properties;
|
||||
expand_one_req.src_vertices = {src_vertex};
|
||||
expand_one_req.transaction_id.logical_id = GetTransactionId();
|
||||
@@ -586,7 +622,8 @@ void AttemptToExpandOneSimple(ShardClient &client, uint64_t src_vertex_val, Edge
|
||||
std::optional<std::vector<PropertyId>> edge_properties = {};
|
||||
|
||||
std::vector<std::string> expressions;
|
||||
std::optional<std::vector<msgs::OrderBy>> order_by = {};
|
||||
std::vector<msgs::OrderBy> order_by_vertices = {};
|
||||
std::vector<msgs::OrderBy> order_by_edges = {};
|
||||
std::optional<size_t> limit = {};
|
||||
std::vector<std::string> filter = {};
|
||||
|
||||
@@ -598,7 +635,8 @@ void AttemptToExpandOneSimple(ShardClient &client, uint64_t src_vertex_val, Edge
|
||||
expand_one_req.vertex_expressions = expressions;
|
||||
expand_one_req.filters = filter;
|
||||
expand_one_req.limit = limit;
|
||||
expand_one_req.order_by = order_by;
|
||||
expand_one_req.order_by_vertices = order_by_vertices;
|
||||
expand_one_req.order_by_edges = order_by_edges;
|
||||
expand_one_req.src_vertex_properties = src_vertex_properties;
|
||||
expand_one_req.src_vertices = {src_vertex};
|
||||
expand_one_req.transaction_id.logical_id = GetTransactionId();
|
||||
@@ -642,7 +680,8 @@ void AttemptToExpandOneWithUniqueEdges(ShardClient &client, uint64_t src_vertex_
|
||||
std::optional<std::vector<PropertyId>> edge_properties = {};
|
||||
|
||||
std::vector<std::string> expressions;
|
||||
std::optional<std::vector<msgs::OrderBy>> order_by = {};
|
||||
std::vector<msgs::OrderBy> order_by_vertices = {};
|
||||
std::vector<msgs::OrderBy> order_by_edges = {};
|
||||
std::optional<size_t> limit = {};
|
||||
std::vector<std::string> filter = {};
|
||||
|
||||
@@ -654,7 +693,8 @@ void AttemptToExpandOneWithUniqueEdges(ShardClient &client, uint64_t src_vertex_
|
||||
expand_one_req.vertex_expressions = expressions;
|
||||
expand_one_req.filters = filter;
|
||||
expand_one_req.limit = limit;
|
||||
expand_one_req.order_by = order_by;
|
||||
expand_one_req.order_by_vertices = order_by_vertices;
|
||||
expand_one_req.order_by_edges = order_by_edges;
|
||||
expand_one_req.src_vertex_properties = src_vertex_properties;
|
||||
expand_one_req.src_vertices = {src_vertex};
|
||||
expand_one_req.only_unique_neighbor_rows = true;
|
||||
@@ -680,6 +720,88 @@ void AttemptToExpandOneWithUniqueEdges(ShardClient &client, uint64_t src_vertex_
|
||||
}
|
||||
}
|
||||
|
||||
void AttemptToExpandOneLimitAndOrderBy(ShardClient &client, uint64_t src_vertex_val, uint64_t other_src_vertex_val,
|
||||
EdgeTypeId edge_type_id) {
|
||||
// Source vertex
|
||||
msgs::Label label = {.id = get_primary_label()};
|
||||
auto src_vertex = std::make_pair(label, GetPrimaryKey(src_vertex_val));
|
||||
auto other_src_vertex = std::make_pair(label, GetPrimaryKey(other_src_vertex_val));
|
||||
|
||||
// Edge type
|
||||
auto edge_type = msgs::EdgeType{};
|
||||
edge_type.id = edge_type_id;
|
||||
|
||||
// Edge direction
|
||||
auto edge_direction = msgs::EdgeDirection::OUT;
|
||||
|
||||
// Source Vertex properties to look for
|
||||
std::optional<std::vector<PropertyId>> src_vertex_properties = {};
|
||||
|
||||
// Edge properties to look for
|
||||
std::optional<std::vector<PropertyId>> edge_properties = {};
|
||||
|
||||
std::vector<msgs::OrderBy> order_by_vertices = {
|
||||
{msgs::Expression{"MG_SYMBOL_NODE.prop1"}, msgs::OrderingDirection::ASCENDING}};
|
||||
std::vector<msgs::OrderBy> order_by_edges = {
|
||||
{msgs::Expression{"MG_SYMBOL_EDGE.prop4"}, msgs::OrderingDirection::DESCENDING}};
|
||||
|
||||
size_t limit = 1;
|
||||
std::vector<std::string> filters = {"MG_SYMBOL_NODE.prop1 != -1"};
|
||||
|
||||
msgs::ExpandOneRequest expand_one_req{};
|
||||
|
||||
expand_one_req.direction = edge_direction;
|
||||
expand_one_req.edge_properties = edge_properties;
|
||||
expand_one_req.edge_types = {edge_type};
|
||||
expand_one_req.filters = filters;
|
||||
expand_one_req.limit = limit;
|
||||
expand_one_req.order_by_vertices = order_by_vertices;
|
||||
expand_one_req.order_by_edges = order_by_edges;
|
||||
expand_one_req.src_vertex_properties = src_vertex_properties;
|
||||
expand_one_req.src_vertices = {src_vertex, other_src_vertex};
|
||||
expand_one_req.transaction_id.logical_id = GetTransactionId();
|
||||
|
||||
while (true) {
|
||||
auto read_res = client.SendReadRequest(expand_one_req);
|
||||
if (read_res.HasError()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
auto write_response_result = read_res.GetValue();
|
||||
auto write_response = std::get<msgs::ExpandOneResponse>(write_response_result);
|
||||
|
||||
// We check that we do not have more results than the limit. Based on the data in the graph, we know that we should
|
||||
// receive exactly limit responses.
|
||||
auto expected_number_of_rows = std::min(expand_one_req.src_vertices.size(), limit);
|
||||
MG_ASSERT(expected_number_of_rows == 1);
|
||||
MG_ASSERT(write_response.result.size() == expected_number_of_rows);
|
||||
|
||||
// We know there are 1 out-going edges from V1->V2
|
||||
// We know there are 10 out-going edges from V2->V3
|
||||
// Since we sort on prop1 and limit 1, we will have a single response
|
||||
// with two edges corresponding to V1->V2 and V1->V3
|
||||
const auto expected_number_of_edges = 2;
|
||||
MG_ASSERT(write_response.result[0].out_edges_with_all_properties.size() == expected_number_of_edges);
|
||||
MG_ASSERT(write_response.result[0]
|
||||
.out_edges_with_specific_properties.empty()); // We are not asking for specific properties
|
||||
|
||||
// We also check that the vertices are ordered by prop1 DESC
|
||||
|
||||
auto is_sorted = std::is_sorted(write_response.result.cbegin(), write_response.result.cend(),
|
||||
[](const auto &vertex, const auto &other_vertex) {
|
||||
const auto primary_key = vertex.src_vertex.id.second;
|
||||
const auto other_primary_key = other_vertex.src_vertex.id.second;
|
||||
|
||||
MG_ASSERT(primary_key.size() == 1);
|
||||
MG_ASSERT(other_primary_key.size() == 1);
|
||||
return primary_key[0].int_v > other_primary_key[0].int_v;
|
||||
});
|
||||
|
||||
MG_ASSERT(is_sorted);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void AttemptToExpandOneWithSpecifiedSrcVertexProperties(ShardClient &client, uint64_t src_vertex_val,
|
||||
EdgeTypeId edge_type_id) {
|
||||
// Source vertex
|
||||
@@ -701,7 +823,8 @@ void AttemptToExpandOneWithSpecifiedSrcVertexProperties(ShardClient &client, uin
|
||||
std::optional<std::vector<PropertyId>> edge_properties = {};
|
||||
|
||||
std::vector<std::string> expressions;
|
||||
std::optional<std::vector<msgs::OrderBy>> order_by = {};
|
||||
std::vector<msgs::OrderBy> order_by_vertices = {};
|
||||
std::vector<msgs::OrderBy> order_by_edges = {};
|
||||
std::optional<size_t> limit = {};
|
||||
std::vector<std::string> filter = {};
|
||||
|
||||
@@ -713,7 +836,8 @@ void AttemptToExpandOneWithSpecifiedSrcVertexProperties(ShardClient &client, uin
|
||||
expand_one_req.vertex_expressions = expressions;
|
||||
expand_one_req.filters = filter;
|
||||
expand_one_req.limit = limit;
|
||||
expand_one_req.order_by = order_by;
|
||||
expand_one_req.order_by_vertices = order_by_vertices;
|
||||
expand_one_req.order_by_edges = order_by_edges;
|
||||
expand_one_req.src_vertex_properties = src_vertex_properties;
|
||||
expand_one_req.src_vertices = {src_vertex};
|
||||
expand_one_req.transaction_id.logical_id = GetTransactionId();
|
||||
@@ -761,7 +885,8 @@ void AttemptToExpandOneWithSpecifiedEdgeProperties(ShardClient &client, uint64_t
|
||||
std::optional<std::vector<PropertyId>> edge_properties = {specified_edge_prop};
|
||||
|
||||
std::vector<std::string> expressions;
|
||||
std::optional<std::vector<msgs::OrderBy>> order_by = {};
|
||||
std::vector<msgs::OrderBy> order_by_vertices = {};
|
||||
std::vector<msgs::OrderBy> order_by_edges = {};
|
||||
std::optional<size_t> limit = {};
|
||||
std::vector<std::string> filter = {};
|
||||
|
||||
@@ -773,7 +898,8 @@ void AttemptToExpandOneWithSpecifiedEdgeProperties(ShardClient &client, uint64_t
|
||||
expand_one_req.vertex_expressions = expressions;
|
||||
expand_one_req.filters = filter;
|
||||
expand_one_req.limit = limit;
|
||||
expand_one_req.order_by = order_by;
|
||||
expand_one_req.order_by_vertices = order_by_vertices;
|
||||
expand_one_req.order_by_edges = order_by_edges;
|
||||
expand_one_req.src_vertex_properties = src_vertex_properties;
|
||||
expand_one_req.src_vertices = {src_vertex};
|
||||
expand_one_req.transaction_id.logical_id = GetTransactionId();
|
||||
@@ -820,7 +946,8 @@ void AttemptToExpandOneWithFilters(ShardClient &client, uint64_t src_vertex_val,
|
||||
std::optional<std::vector<PropertyId>> edge_properties = {};
|
||||
|
||||
std::vector<std::string> expressions;
|
||||
std::optional<std::vector<msgs::OrderBy>> order_by = {};
|
||||
std::vector<msgs::OrderBy> order_by_vertices = {};
|
||||
std::vector<msgs::OrderBy> order_by_edges = {};
|
||||
std::optional<size_t> limit = {};
|
||||
std::vector<std::string> filter = {};
|
||||
|
||||
@@ -832,7 +959,8 @@ void AttemptToExpandOneWithFilters(ShardClient &client, uint64_t src_vertex_val,
|
||||
expand_one_req.vertex_expressions = expressions;
|
||||
expand_one_req.filters = {filter_expr1};
|
||||
expand_one_req.limit = limit;
|
||||
expand_one_req.order_by = order_by;
|
||||
expand_one_req.order_by_vertices = order_by_vertices;
|
||||
expand_one_req.order_by_edges = order_by_edges;
|
||||
expand_one_req.src_vertex_properties = src_vertex_properties;
|
||||
expand_one_req.src_vertices = {src_vertex};
|
||||
expand_one_req.transaction_id.logical_id = GetTransactionId();
|
||||
@@ -872,7 +1000,9 @@ void TestCreateAndUpdateVertices(ShardClient &client) {
|
||||
auto unique_prop_val = GetUniqueInteger();
|
||||
|
||||
MG_ASSERT(AttemptToCreateVertex(client, unique_prop_val));
|
||||
MG_ASSERT(AttemptToUpdateVertex(client, unique_prop_val));
|
||||
MG_ASSERT(AttemptToUpdateVertex(client, unique_prop_val, {LabelId::FromInt(3)}, {}));
|
||||
MG_ASSERT(AttemptToUpdateVertex(client, unique_prop_val, {}, {LabelId::FromInt(3)}));
|
||||
MG_ASSERT(AttemptToRemoveVertexProperty(client, unique_prop_val));
|
||||
}
|
||||
|
||||
void TestCreateEdge(ShardClient &client) {
|
||||
@@ -1021,6 +1151,9 @@ void TestExpandOneGraphOne(ShardClient &client) {
|
||||
auto edge_prop_id = GetUniqueInteger();
|
||||
auto edge_prop_val = GetUniqueInteger();
|
||||
|
||||
std::vector<uint64_t> edges_ids(10);
|
||||
std::generate(edges_ids.begin(), edges_ids.end(), GetUniqueInteger);
|
||||
|
||||
// (V1)-[edge_type_id]->(V2)
|
||||
MG_ASSERT(AttemptToAddEdgeWithProperties(client, unique_prop_val_1, unique_prop_val_2, edge_gid_1, edge_prop_id,
|
||||
edge_prop_val, {edge_type_id}));
|
||||
@@ -1028,7 +1161,14 @@ void TestExpandOneGraphOne(ShardClient &client) {
|
||||
MG_ASSERT(AttemptToAddEdgeWithProperties(client, unique_prop_val_1, unique_prop_val_3, edge_gid_2, edge_prop_id,
|
||||
edge_prop_val, {edge_type_id}));
|
||||
|
||||
// (V2)-[edge_type_id]->(V3) x 10
|
||||
std::for_each(edges_ids.begin(), edges_ids.end(), [&](const auto &edge_id) {
|
||||
MG_ASSERT(AttemptToAddEdgeWithProperties(client, unique_prop_val_2, unique_prop_val_3, edge_id, edge_prop_id,
|
||||
edge_prop_val, {edge_type_id}));
|
||||
});
|
||||
|
||||
AttemptToExpandOneSimple(client, unique_prop_val_1, edge_type_id);
|
||||
AttemptToExpandOneLimitAndOrderBy(client, unique_prop_val_1, unique_prop_val_2, edge_type_id);
|
||||
AttemptToExpandOneWithWrongEdgeType(client, unique_prop_val_1, wrong_edge_type_id);
|
||||
AttemptToExpandOneWithSpecifiedSrcVertexProperties(client, unique_prop_val_1, edge_type_id);
|
||||
AttemptToExpandOneWithSpecifiedEdgeProperties(client, unique_prop_val_1, edge_type_id, edge_prop_id);
|
||||
|
||||
@@ -177,7 +177,7 @@ void ExecuteOp(msgs::ShardRequestManager<SimulatorTransport> &shard_request_mana
|
||||
auto result = shard_request_manager.Request(state, std::move(new_vertices));
|
||||
|
||||
RC_ASSERT(result.size() == 1);
|
||||
RC_ASSERT(result[0].success);
|
||||
RC_ASSERT(!result[0].error.has_value());
|
||||
|
||||
correctness_model.emplace(std::make_pair(create_vertex.first, create_vertex.second));
|
||||
}
|
||||
|
||||
@@ -343,6 +343,9 @@ target_link_libraries(${test_prefix}storage_v3_edge mg-storage-v3)
|
||||
add_unit_test(storage_v3_isolation_level.cpp)
|
||||
target_link_libraries(${test_prefix}storage_v3_isolation_level mg-storage-v3)
|
||||
|
||||
add_unit_test(storage_v3_shard_rsm.cpp)
|
||||
target_link_libraries(${test_prefix}storage_v3_shard_rsm mg-storage-v3)
|
||||
|
||||
add_unit_test(replication_persistence_helper.cpp)
|
||||
target_link_libraries(${test_prefix}replication_persistence_helper mg-storage-v2)
|
||||
|
||||
|
||||
@@ -187,7 +187,7 @@ void ExecuteOp(msgs::ShardRequestManager<LocalTransport> &shard_request_manager,
|
||||
auto result = shard_request_manager.Request(state, std::move(new_vertices));
|
||||
|
||||
MG_ASSERT(result.size() == 1);
|
||||
MG_ASSERT(result[0].success);
|
||||
MG_ASSERT(!result[0].error.has_value());
|
||||
|
||||
correctness_model.emplace(std::make_pair(create_vertex.first, create_vertex.second));
|
||||
}
|
||||
|
||||
@@ -131,6 +131,7 @@ void TestCreateVertices(msgs::ShardRequestManagerInterface &shard_request_manage
|
||||
|
||||
auto result = shard_request_manager.Request(state, std::move(new_vertices));
|
||||
EXPECT_EQ(result.size(), 1);
|
||||
EXPECT_FALSE(result[0].error.has_value()) << result[0].error->message;
|
||||
}
|
||||
|
||||
void TestCreateExpand(msgs::ShardRequestManagerInterface &shard_request_manager) {
|
||||
@@ -151,7 +152,7 @@ void TestCreateExpand(msgs::ShardRequestManagerInterface &shard_request_manager)
|
||||
|
||||
auto responses = shard_request_manager.Request(state, std::move(new_expands));
|
||||
MG_ASSERT(responses.size() == 1);
|
||||
MG_ASSERT(responses[0].success);
|
||||
MG_ASSERT(!responses[0].error.has_value());
|
||||
}
|
||||
|
||||
void TestExpandOne(msgs::ShardRequestManagerInterface &shard_request_manager) {
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include <gtest/gtest-death-test.h>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "common/errors.hpp"
|
||||
#include "coordinator/hybrid_logical_clock.hpp"
|
||||
#include "io/time.hpp"
|
||||
#include "storage/v3/delta.hpp"
|
||||
@@ -579,7 +580,7 @@ TEST_P(StorageV3, VertexDeleteSerializationError) {
|
||||
EXPECT_EQ(CountVertices(acc2, View::NEW), 1U);
|
||||
auto res = acc2.DeleteVertex(&*vertex);
|
||||
ASSERT_TRUE(res.HasError());
|
||||
ASSERT_EQ(res.GetError(), Error::SERIALIZATION_ERROR);
|
||||
ASSERT_EQ(res.GetError(), SHARD_ERROR(ErrorCode::SERIALIZATION_ERROR));
|
||||
EXPECT_EQ(CountVertices(acc2, View::OLD), 1U);
|
||||
EXPECT_EQ(CountVertices(acc2, View::NEW), 1U);
|
||||
acc2.AdvanceCommand();
|
||||
@@ -660,12 +661,11 @@ TEST_P(StorageV3, VertexDeleteSpecialCases) {
|
||||
}
|
||||
}
|
||||
|
||||
template <typename TError, typename TResultHolder>
|
||||
void AssertErrorInVariant(TResultHolder &holder, TError error_type) {
|
||||
ASSERT_TRUE(holder.HasError());
|
||||
const auto error = holder.GetError();
|
||||
ASSERT_TRUE(std::holds_alternative<TError>(error));
|
||||
ASSERT_EQ(std::get<TError>(error), error_type);
|
||||
template <typename T>
|
||||
void AssertShardErrorEqual(const ShardResult<T> &lhs, const ShardError &rhs) {
|
||||
ASSERT_TRUE(lhs.HasError());
|
||||
const auto error = lhs.GetError();
|
||||
ASSERT_EQ(error, rhs);
|
||||
}
|
||||
|
||||
// NOLINTNEXTLINE(hicpp-special-member-functions)
|
||||
@@ -711,20 +711,20 @@ TEST_P(StorageV3, VertexDeleteLabel) {
|
||||
|
||||
// Check whether label 5 exists
|
||||
ASSERT_FALSE(vertex->HasLabel(label5, View::OLD).GetValue());
|
||||
ASSERT_EQ(vertex->HasLabel(label5, View::NEW).GetError(), Error::DELETED_OBJECT);
|
||||
ASSERT_EQ(vertex->HasLabel(label5, View::NEW).GetError(), SHARD_ERROR(ErrorCode::DELETED_OBJECT));
|
||||
ASSERT_EQ(vertex->Labels(View::OLD)->size(), 0);
|
||||
ASSERT_EQ(vertex->Labels(View::NEW).GetError(), Error::DELETED_OBJECT);
|
||||
ASSERT_EQ(vertex->Labels(View::NEW).GetError(), SHARD_ERROR(ErrorCode::DELETED_OBJECT));
|
||||
|
||||
// Try to add the label
|
||||
{
|
||||
auto ret = vertex->AddLabelAndValidate(label5);
|
||||
AssertErrorInVariant(ret, Error::DELETED_OBJECT);
|
||||
AssertShardErrorEqual(ret, SHARD_ERROR(ErrorCode::DELETED_OBJECT));
|
||||
}
|
||||
|
||||
// Try to remove the label
|
||||
{
|
||||
auto ret = vertex->RemoveLabelAndValidate(label5);
|
||||
AssertErrorInVariant(ret, Error::DELETED_OBJECT);
|
||||
AssertShardErrorEqual(ret, SHARD_ERROR(ErrorCode::DELETED_OBJECT));
|
||||
}
|
||||
|
||||
acc.Abort();
|
||||
@@ -779,33 +779,33 @@ TEST_P(StorageV3, VertexDeleteLabel) {
|
||||
|
||||
// Check whether label 5 exists
|
||||
ASSERT_TRUE(vertex->HasLabel(label5, View::OLD).GetValue());
|
||||
ASSERT_EQ(vertex->HasLabel(label5, View::NEW).GetError(), Error::DELETED_OBJECT);
|
||||
ASSERT_EQ(vertex->HasLabel(label5, View::NEW).GetError(), SHARD_ERROR(ErrorCode::DELETED_OBJECT));
|
||||
{
|
||||
auto labels = vertex->Labels(View::OLD).GetValue();
|
||||
ASSERT_EQ(labels.size(), 1);
|
||||
ASSERT_EQ(labels[0], label5);
|
||||
}
|
||||
ASSERT_EQ(vertex->Labels(View::NEW).GetError(), Error::DELETED_OBJECT);
|
||||
ASSERT_EQ(vertex->Labels(View::NEW).GetError(), SHARD_ERROR(ErrorCode::DELETED_OBJECT));
|
||||
|
||||
// Advance command
|
||||
acc.AdvanceCommand();
|
||||
|
||||
// Check whether label 5 exists
|
||||
ASSERT_EQ(vertex->HasLabel(label5, View::OLD).GetError(), Error::DELETED_OBJECT);
|
||||
ASSERT_EQ(vertex->HasLabel(label5, View::NEW).GetError(), Error::DELETED_OBJECT);
|
||||
ASSERT_EQ(vertex->Labels(View::OLD).GetError(), Error::DELETED_OBJECT);
|
||||
ASSERT_EQ(vertex->Labels(View::NEW).GetError(), Error::DELETED_OBJECT);
|
||||
ASSERT_EQ(vertex->HasLabel(label5, View::OLD).GetError(), SHARD_ERROR(ErrorCode::DELETED_OBJECT));
|
||||
ASSERT_EQ(vertex->HasLabel(label5, View::NEW).GetError(), SHARD_ERROR(ErrorCode::DELETED_OBJECT));
|
||||
ASSERT_EQ(vertex->Labels(View::OLD).GetError(), SHARD_ERROR(ErrorCode::DELETED_OBJECT));
|
||||
ASSERT_EQ(vertex->Labels(View::NEW).GetError(), SHARD_ERROR(ErrorCode::DELETED_OBJECT));
|
||||
|
||||
// Try to add the label
|
||||
{
|
||||
auto ret = vertex->AddLabelAndValidate(label5);
|
||||
AssertErrorInVariant(ret, Error::DELETED_OBJECT);
|
||||
AssertShardErrorEqual(ret, SHARD_ERROR(ErrorCode::DELETED_OBJECT));
|
||||
}
|
||||
|
||||
// Try to remove the label
|
||||
{
|
||||
auto ret = vertex->RemoveLabelAndValidate(label5);
|
||||
AssertErrorInVariant(ret, Error::DELETED_OBJECT);
|
||||
AssertShardErrorEqual(ret, SHARD_ERROR(ErrorCode::DELETED_OBJECT));
|
||||
}
|
||||
|
||||
acc.Abort();
|
||||
@@ -855,14 +855,14 @@ TEST_P(StorageV3, VertexDeleteProperty) {
|
||||
|
||||
// Check whether label 5 exists
|
||||
ASSERT_TRUE(vertex->GetProperty(property5, View::OLD)->IsNull());
|
||||
ASSERT_EQ(vertex->GetProperty(property5, View::NEW).GetError(), Error::DELETED_OBJECT);
|
||||
ASSERT_EQ(vertex->GetProperty(property5, View::NEW).GetError(), SHARD_ERROR(ErrorCode::DELETED_OBJECT));
|
||||
ASSERT_EQ(vertex->Properties(View::OLD)->size(), 0);
|
||||
ASSERT_EQ(vertex->Properties(View::NEW).GetError(), Error::DELETED_OBJECT);
|
||||
ASSERT_EQ(vertex->Properties(View::NEW).GetError(), SHARD_ERROR(ErrorCode::DELETED_OBJECT));
|
||||
|
||||
// Try to set the property5
|
||||
{
|
||||
auto ret = vertex->SetPropertyAndValidate(property5, PropertyValue("haihai"));
|
||||
AssertErrorInVariant(ret, Error::DELETED_OBJECT);
|
||||
AssertShardErrorEqual(ret, SHARD_ERROR(ErrorCode::DELETED_OBJECT));
|
||||
}
|
||||
|
||||
acc.Abort();
|
||||
@@ -918,27 +918,27 @@ TEST_P(StorageV3, VertexDeleteProperty) {
|
||||
|
||||
// Check whether property 5 exists
|
||||
ASSERT_EQ(vertex->GetProperty(property5, View::OLD)->ValueString(), "nandare");
|
||||
ASSERT_EQ(vertex->GetProperty(property5, View::NEW).GetError(), Error::DELETED_OBJECT);
|
||||
ASSERT_EQ(vertex->GetProperty(property5, View::NEW).GetError(), SHARD_ERROR(ErrorCode::DELETED_OBJECT));
|
||||
{
|
||||
auto properties = vertex->Properties(View::OLD).GetValue();
|
||||
ASSERT_EQ(properties.size(), 1);
|
||||
ASSERT_EQ(properties[property5].ValueString(), "nandare");
|
||||
}
|
||||
ASSERT_EQ(vertex->Properties(View::NEW).GetError(), Error::DELETED_OBJECT);
|
||||
ASSERT_EQ(vertex->Properties(View::NEW).GetError(), SHARD_ERROR(ErrorCode::DELETED_OBJECT));
|
||||
|
||||
// Advance command
|
||||
acc.AdvanceCommand();
|
||||
|
||||
// Check whether property 5 exists
|
||||
ASSERT_EQ(vertex->GetProperty(property5, View::OLD).GetError(), Error::DELETED_OBJECT);
|
||||
ASSERT_EQ(vertex->GetProperty(property5, View::NEW).GetError(), Error::DELETED_OBJECT);
|
||||
ASSERT_EQ(vertex->Properties(View::OLD).GetError(), Error::DELETED_OBJECT);
|
||||
ASSERT_EQ(vertex->Properties(View::NEW).GetError(), Error::DELETED_OBJECT);
|
||||
ASSERT_EQ(vertex->GetProperty(property5, View::OLD).GetError(), SHARD_ERROR(ErrorCode::DELETED_OBJECT));
|
||||
ASSERT_EQ(vertex->GetProperty(property5, View::NEW).GetError(), SHARD_ERROR(ErrorCode::DELETED_OBJECT));
|
||||
ASSERT_EQ(vertex->Properties(View::OLD).GetError(), SHARD_ERROR(ErrorCode::DELETED_OBJECT));
|
||||
ASSERT_EQ(vertex->Properties(View::NEW).GetError(), SHARD_ERROR(ErrorCode::DELETED_OBJECT));
|
||||
|
||||
// Try to set the property
|
||||
{
|
||||
auto ret = vertex->SetPropertyAndValidate(property5, PropertyValue("haihai"));
|
||||
AssertErrorInVariant(ret, Error::DELETED_OBJECT);
|
||||
AssertShardErrorEqual(ret, SHARD_ERROR(ErrorCode::DELETED_OBJECT));
|
||||
}
|
||||
|
||||
acc.Abort();
|
||||
@@ -1371,7 +1371,7 @@ TEST_P(StorageV3, VertexLabelSerializationError) {
|
||||
|
||||
{
|
||||
auto res = vertex->AddLabelAndValidate(label1);
|
||||
AssertErrorInVariant(res, Error::SERIALIZATION_ERROR);
|
||||
AssertShardErrorEqual(res, SHARD_ERROR(ErrorCode::SERIALIZATION_ERROR));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1865,7 +1865,7 @@ TEST_P(StorageV3, VertexPropertySerializationError) {
|
||||
|
||||
{
|
||||
auto res = vertex->SetPropertyAndValidate(property2, PropertyValue("nandare"));
|
||||
AssertErrorInVariant(res, Error::SERIALIZATION_ERROR);
|
||||
AssertShardErrorEqual(res, SHARD_ERROR(ErrorCode::SERIALIZATION_ERROR));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2255,14 +2255,14 @@ TEST_P(StorageV3, VertexNonexistentLabelPropertyEdgeAPI) {
|
||||
auto vertex = CreateVertexAndValidate(acc, {}, PropertyValue{0}, {});
|
||||
|
||||
// Check state before (OLD view).
|
||||
ASSERT_EQ(vertex.Labels(View::OLD).GetError(), Error::NONEXISTENT_OBJECT);
|
||||
ASSERT_EQ(vertex.HasLabel(label1, View::OLD).GetError(), Error::NONEXISTENT_OBJECT);
|
||||
ASSERT_EQ(vertex.Properties(View::OLD).GetError(), Error::NONEXISTENT_OBJECT);
|
||||
ASSERT_EQ(vertex.GetProperty(property1, View::OLD).GetError(), Error::NONEXISTENT_OBJECT);
|
||||
ASSERT_EQ(vertex.InEdges(View::OLD).GetError(), Error::NONEXISTENT_OBJECT);
|
||||
ASSERT_EQ(vertex.OutEdges(View::OLD).GetError(), Error::NONEXISTENT_OBJECT);
|
||||
ASSERT_EQ(vertex.InDegree(View::OLD).GetError(), Error::NONEXISTENT_OBJECT);
|
||||
ASSERT_EQ(vertex.OutDegree(View::OLD).GetError(), Error::NONEXISTENT_OBJECT);
|
||||
ASSERT_EQ(vertex.Labels(View::OLD).GetError(), SHARD_ERROR(ErrorCode::NONEXISTENT_OBJECT));
|
||||
ASSERT_EQ(vertex.HasLabel(label1, View::OLD).GetError(), SHARD_ERROR(ErrorCode::NONEXISTENT_OBJECT));
|
||||
ASSERT_EQ(vertex.Properties(View::OLD).GetError(), SHARD_ERROR(ErrorCode::NONEXISTENT_OBJECT));
|
||||
ASSERT_EQ(vertex.GetProperty(property1, View::OLD).GetError(), SHARD_ERROR(ErrorCode::NONEXISTENT_OBJECT));
|
||||
ASSERT_EQ(vertex.InEdges(View::OLD).GetError(), SHARD_ERROR(ErrorCode::NONEXISTENT_OBJECT));
|
||||
ASSERT_EQ(vertex.OutEdges(View::OLD).GetError(), SHARD_ERROR(ErrorCode::NONEXISTENT_OBJECT));
|
||||
ASSERT_EQ(vertex.InDegree(View::OLD).GetError(), SHARD_ERROR(ErrorCode::NONEXISTENT_OBJECT));
|
||||
ASSERT_EQ(vertex.OutDegree(View::OLD).GetError(), SHARD_ERROR(ErrorCode::NONEXISTENT_OBJECT));
|
||||
|
||||
// Check state before (NEW view).
|
||||
ASSERT_EQ(vertex.Labels(View::NEW)->size(), 0);
|
||||
@@ -2282,14 +2282,14 @@ TEST_P(StorageV3, VertexNonexistentLabelPropertyEdgeAPI) {
|
||||
.HasValue());
|
||||
|
||||
// Check state after (OLD view).
|
||||
ASSERT_EQ(vertex.Labels(View::OLD).GetError(), Error::NONEXISTENT_OBJECT);
|
||||
ASSERT_EQ(vertex.HasLabel(label1, View::OLD).GetError(), Error::NONEXISTENT_OBJECT);
|
||||
ASSERT_EQ(vertex.Properties(View::OLD).GetError(), Error::NONEXISTENT_OBJECT);
|
||||
ASSERT_EQ(vertex.GetProperty(property1, View::OLD).GetError(), Error::NONEXISTENT_OBJECT);
|
||||
ASSERT_EQ(vertex.InEdges(View::OLD).GetError(), Error::NONEXISTENT_OBJECT);
|
||||
ASSERT_EQ(vertex.OutEdges(View::OLD).GetError(), Error::NONEXISTENT_OBJECT);
|
||||
ASSERT_EQ(vertex.InDegree(View::OLD).GetError(), Error::NONEXISTENT_OBJECT);
|
||||
ASSERT_EQ(vertex.OutDegree(View::OLD).GetError(), Error::NONEXISTENT_OBJECT);
|
||||
ASSERT_EQ(vertex.Labels(View::OLD).GetError(), SHARD_ERROR(ErrorCode::NONEXISTENT_OBJECT));
|
||||
ASSERT_EQ(vertex.HasLabel(label1, View::OLD).GetError(), SHARD_ERROR(ErrorCode::NONEXISTENT_OBJECT));
|
||||
ASSERT_EQ(vertex.Properties(View::OLD).GetError(), SHARD_ERROR(ErrorCode::NONEXISTENT_OBJECT));
|
||||
ASSERT_EQ(vertex.GetProperty(property1, View::OLD).GetError(), SHARD_ERROR(ErrorCode::NONEXISTENT_OBJECT));
|
||||
ASSERT_EQ(vertex.InEdges(View::OLD).GetError(), SHARD_ERROR(ErrorCode::NONEXISTENT_OBJECT));
|
||||
ASSERT_EQ(vertex.OutEdges(View::OLD).GetError(), SHARD_ERROR(ErrorCode::NONEXISTENT_OBJECT));
|
||||
ASSERT_EQ(vertex.InDegree(View::OLD).GetError(), SHARD_ERROR(ErrorCode::NONEXISTENT_OBJECT));
|
||||
ASSERT_EQ(vertex.OutDegree(View::OLD).GetError(), SHARD_ERROR(ErrorCode::NONEXISTENT_OBJECT));
|
||||
|
||||
// Check state after (NEW view).
|
||||
ASSERT_EQ(vertex.Labels(View::NEW)->size(), 1);
|
||||
@@ -2657,42 +2657,31 @@ TEST_P(StorageV3, TestCreateVertexAndValidate) {
|
||||
|
||||
ASSERT_TRUE(vertex2.HasError());
|
||||
auto error = vertex2.GetError();
|
||||
auto error_ptr = std::get_if<memgraph::storage::v3::Error>(&error);
|
||||
ASSERT_TRUE(error_ptr);
|
||||
ASSERT_TRUE(*error_ptr == storage::v3::Error::VERTEX_ALREADY_INSERTED);
|
||||
ASSERT_TRUE(error == common::ErrorCode::VERTEX_ALREADY_INSERTED);
|
||||
}
|
||||
{
|
||||
auto acc = store.Access(GetNextHlc());
|
||||
auto vertex = acc.CreateVertexAndValidate({primary_label}, {PropertyValue{0}}, {});
|
||||
ASSERT_TRUE(vertex.HasError());
|
||||
ASSERT_TRUE(std::holds_alternative<SchemaViolation>(vertex.GetError()));
|
||||
EXPECT_EQ(std::get<SchemaViolation>(vertex.GetError()),
|
||||
SchemaViolation(SchemaViolation::ValidationStatus::VERTEX_SECONDARY_LABEL_IS_PRIMARY, primary_label));
|
||||
EXPECT_EQ(vertex.GetError(), SHARD_ERROR(ErrorCode::SCHEMA_VERTEX_SECONDARY_LABEL_IS_PRIMARY));
|
||||
}
|
||||
{
|
||||
auto acc = store.Access(GetNextHlc());
|
||||
auto vertex = acc.CreateVertexAndValidate({primary_label}, {PropertyValue{0}}, {});
|
||||
ASSERT_TRUE(vertex.HasError());
|
||||
ASSERT_TRUE(std::holds_alternative<SchemaViolation>(vertex.GetError()));
|
||||
EXPECT_EQ(std::get<SchemaViolation>(vertex.GetError()),
|
||||
SchemaViolation(SchemaViolation::ValidationStatus::VERTEX_SECONDARY_LABEL_IS_PRIMARY, primary_label));
|
||||
EXPECT_EQ(vertex.GetError(), SHARD_ERROR(ErrorCode::SCHEMA_VERTEX_SECONDARY_LABEL_IS_PRIMARY));
|
||||
}
|
||||
{
|
||||
auto acc = store.Access(GetNextHlc());
|
||||
auto vertex = acc.CreateVertexAndValidate({}, {}, {});
|
||||
ASSERT_TRUE(vertex.HasError());
|
||||
ASSERT_TRUE(std::holds_alternative<SchemaViolation>(vertex.GetError()));
|
||||
EXPECT_EQ(std::get<SchemaViolation>(vertex.GetError()),
|
||||
SchemaViolation(SchemaViolation::ValidationStatus::VERTEX_PRIMARY_PROPERTIES_UNDEFINED, primary_label));
|
||||
EXPECT_EQ(vertex.GetError(), SHARD_ERROR(ErrorCode::SCHEMA_VERTEX_PRIMARY_PROPERTIES_UNDEFINED));
|
||||
}
|
||||
{
|
||||
auto acc = store.Access(GetNextHlc());
|
||||
auto vertex = acc.CreateVertexAndValidate({}, {PropertyValue{"test"}}, {});
|
||||
ASSERT_TRUE(vertex.HasError());
|
||||
ASSERT_TRUE(std::holds_alternative<SchemaViolation>(vertex.GetError()));
|
||||
EXPECT_EQ(std::get<SchemaViolation>(vertex.GetError()),
|
||||
SchemaViolation(SchemaViolation::ValidationStatus::VERTEX_PROPERTY_WRONG_TYPE, primary_label,
|
||||
{primary_property, common::SchemaType::INT}, PropertyValue("test")));
|
||||
EXPECT_EQ(vertex.GetError(), SHARD_ERROR(ErrorCode::SCHEMA_VERTEX_PROPERTY_WRONG_TYPE));
|
||||
}
|
||||
}
|
||||
} // namespace memgraph::storage::v3::tests
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
#include "storage/v3/name_id_mapper.hpp"
|
||||
#include "storage/v3/property_value.hpp"
|
||||
#include "storage/v3/shard.hpp"
|
||||
#include "storage/v3/shard_operation_result.hpp"
|
||||
|
||||
namespace memgraph::storage::v3::tests {
|
||||
using testing::UnorderedElementsAre;
|
||||
@@ -39,7 +38,7 @@ class StorageEdgeTest : public ::testing::TestWithParam<bool> {
|
||||
return store.NameToEdgeType(edge_type_name);
|
||||
}
|
||||
|
||||
static ShardOperationResult<VertexAccessor> CreateVertex(Shard::Accessor &acc, const PropertyValue &key) {
|
||||
static ShardResult<VertexAccessor> CreateVertex(Shard::Accessor &acc, const PropertyValue &key) {
|
||||
return acc.CreateVertexAndValidate({}, {key}, {});
|
||||
}
|
||||
|
||||
@@ -1157,7 +1156,7 @@ TEST_P(StorageEdgeTest, VertexDetachDeleteSingleCommit) {
|
||||
{
|
||||
auto ret = acc.DeleteVertex(&vertex_from.value());
|
||||
ASSERT_TRUE(ret.HasError());
|
||||
ASSERT_EQ(ret.GetError(), Error::VERTEX_HAS_EDGES);
|
||||
ASSERT_EQ(ret.GetError(), SHARD_ERROR(ErrorCode::VERTEX_HAS_EDGES));
|
||||
}
|
||||
|
||||
// Detach delete vertex
|
||||
@@ -1170,8 +1169,8 @@ TEST_P(StorageEdgeTest, VertexDetachDeleteSingleCommit) {
|
||||
// Check edges
|
||||
ASSERT_EQ(vertex_from->InEdges(View::OLD)->size(), 0);
|
||||
ASSERT_EQ(*vertex_from->InDegree(View::OLD), 0);
|
||||
ASSERT_EQ(vertex_from->InEdges(View::NEW).GetError(), Error::DELETED_OBJECT);
|
||||
ASSERT_EQ(vertex_from->InDegree(View::NEW).GetError(), Error::DELETED_OBJECT);
|
||||
ASSERT_EQ(vertex_from->InEdges(View::NEW).GetError(), SHARD_ERROR(ErrorCode::DELETED_OBJECT));
|
||||
ASSERT_EQ(vertex_from->InDegree(View::NEW).GetError(), SHARD_ERROR(ErrorCode::DELETED_OBJECT));
|
||||
{
|
||||
auto ret = vertex_from->OutEdges(View::OLD);
|
||||
ASSERT_TRUE(ret.HasValue());
|
||||
@@ -1184,8 +1183,8 @@ TEST_P(StorageEdgeTest, VertexDetachDeleteSingleCommit) {
|
||||
ASSERT_EQ(e.From(), from_id);
|
||||
ASSERT_EQ(e.To(), to_id);
|
||||
}
|
||||
ASSERT_EQ(vertex_from->OutEdges(View::NEW).GetError(), Error::DELETED_OBJECT);
|
||||
ASSERT_EQ(vertex_from->OutDegree(View::NEW).GetError(), Error::DELETED_OBJECT);
|
||||
ASSERT_EQ(vertex_from->OutEdges(View::NEW).GetError(), SHARD_ERROR(ErrorCode::DELETED_OBJECT));
|
||||
ASSERT_EQ(vertex_from->OutDegree(View::NEW).GetError(), SHARD_ERROR(ErrorCode::DELETED_OBJECT));
|
||||
{
|
||||
auto ret = vertex_to->InEdges(View::OLD);
|
||||
ASSERT_TRUE(ret.HasValue());
|
||||
|
||||
@@ -14,10 +14,10 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <fmt/format.h>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "common/errors.hpp"
|
||||
#include "common/types.hpp"
|
||||
#include "storage/v3/id_types.hpp"
|
||||
#include "storage/v3/property_value.hpp"
|
||||
@@ -150,7 +150,15 @@ TEST_F(SchemaTest, TestSchemaDrop) {
|
||||
|
||||
class SchemaValidatorTest : public testing::Test {
|
||||
private:
|
||||
NameIdMapper id_mapper_{{{1, "label1"}, {2, "label2"}, {3, "prop1"}, {4, "prop2"}, {5, "prop3"}}};
|
||||
NameIdMapper id_mapper_{{{1, "label1"},
|
||||
{2, "label2"},
|
||||
{3, "prop1"},
|
||||
{4, "prop2"},
|
||||
{5, "prop3"},
|
||||
{6, "label4"},
|
||||
{7, "label5"},
|
||||
{8, "label6"},
|
||||
{9, "test"}}};
|
||||
|
||||
protected:
|
||||
void SetUp() override {
|
||||
@@ -162,9 +170,8 @@ class SchemaValidatorTest : public testing::Test {
|
||||
|
||||
PropertyId NameToProperty(const std::string &name) { return PropertyId::FromUint(id_mapper_.NameToId(name)); }
|
||||
|
||||
protected:
|
||||
Schemas schemas;
|
||||
SchemaValidator schema_validator{schemas};
|
||||
SchemaValidator schema_validator{schemas, id_mapper_};
|
||||
PropertyId prop_string{NameToProperty("prop1")};
|
||||
PropertyId prop_int{NameToProperty("prop2")};
|
||||
PropertyId prop_duration{NameToProperty("prop3")};
|
||||
@@ -179,100 +186,92 @@ TEST_F(SchemaValidatorTest, TestSchemaValidateVertexCreate) {
|
||||
// Validate against secondary label
|
||||
{
|
||||
const auto schema_violation = schema_validator.ValidateVertexCreate(NameToLabel("test"), {}, {PropertyValue(1)});
|
||||
ASSERT_NE(schema_violation, std::nullopt);
|
||||
EXPECT_EQ(*schema_violation,
|
||||
SchemaViolation(SchemaViolation::ValidationStatus::NO_SCHEMA_DEFINED_FOR_LABEL, NameToLabel("test")));
|
||||
ASSERT_TRUE(schema_violation.HasError());
|
||||
EXPECT_EQ(schema_violation.GetError(), SHARD_ERROR(ErrorCode::SCHEMA_NO_SCHEMA_DEFINED_FOR_LABEL));
|
||||
}
|
||||
|
||||
{
|
||||
const auto schema_violation = schema_validator.ValidateVertexCreate(label2, {}, {});
|
||||
ASSERT_NE(schema_violation, std::nullopt);
|
||||
EXPECT_EQ(*schema_violation,
|
||||
SchemaViolation(SchemaViolation::ValidationStatus::VERTEX_PRIMARY_PROPERTIES_UNDEFINED, label2));
|
||||
ASSERT_TRUE(schema_violation.HasError());
|
||||
EXPECT_EQ(schema_violation.GetError(), SHARD_ERROR(ErrorCode::SCHEMA_VERTEX_PRIMARY_PROPERTIES_UNDEFINED));
|
||||
}
|
||||
// Validate wrong secondary label
|
||||
{
|
||||
const auto schema_violation = schema_validator.ValidateVertexCreate(label1, {label1}, {PropertyValue("test")});
|
||||
ASSERT_NE(schema_violation, std::nullopt);
|
||||
EXPECT_EQ(*schema_violation,
|
||||
SchemaViolation(SchemaViolation::ValidationStatus::VERTEX_SECONDARY_LABEL_IS_PRIMARY, label1));
|
||||
ASSERT_TRUE(schema_violation.HasError());
|
||||
EXPECT_EQ(schema_violation.GetError(), SHARD_ERROR(ErrorCode::SCHEMA_VERTEX_SECONDARY_LABEL_IS_PRIMARY));
|
||||
}
|
||||
{
|
||||
const auto schema_violation = schema_validator.ValidateVertexCreate(label1, {label2}, {PropertyValue("test")});
|
||||
ASSERT_NE(schema_violation, std::nullopt);
|
||||
EXPECT_EQ(*schema_violation,
|
||||
SchemaViolation(SchemaViolation::ValidationStatus::VERTEX_SECONDARY_LABEL_IS_PRIMARY, label2));
|
||||
ASSERT_TRUE(schema_violation.HasError());
|
||||
EXPECT_EQ(schema_violation.GetError(), SHARD_ERROR(ErrorCode::SCHEMA_VERTEX_SECONDARY_LABEL_IS_PRIMARY));
|
||||
}
|
||||
// Validate wrong property type
|
||||
{
|
||||
const auto schema_violation = schema_validator.ValidateVertexCreate(label1, {}, {PropertyValue(1)});
|
||||
ASSERT_NE(schema_violation, std::nullopt);
|
||||
EXPECT_EQ(*schema_violation, SchemaViolation(SchemaViolation::ValidationStatus::VERTEX_PROPERTY_WRONG_TYPE, label1,
|
||||
schema_prop_string, PropertyValue(1)));
|
||||
ASSERT_TRUE(schema_violation.HasError());
|
||||
EXPECT_EQ(schema_violation.GetError(), SHARD_ERROR(ErrorCode::SCHEMA_VERTEX_PROPERTY_WRONG_TYPE));
|
||||
}
|
||||
{
|
||||
const auto schema_violation =
|
||||
schema_validator.ValidateVertexCreate(label2, {}, {PropertyValue("test"), PropertyValue(12), PropertyValue(1)});
|
||||
ASSERT_NE(schema_violation, std::nullopt);
|
||||
EXPECT_EQ(*schema_violation, SchemaViolation(SchemaViolation::ValidationStatus::VERTEX_PROPERTY_WRONG_TYPE, label2,
|
||||
schema_prop_duration, PropertyValue(1)));
|
||||
ASSERT_TRUE(schema_violation.HasError());
|
||||
EXPECT_EQ(schema_violation.GetError(), SHARD_ERROR(ErrorCode::SCHEMA_VERTEX_PROPERTY_WRONG_TYPE));
|
||||
}
|
||||
{
|
||||
const auto wrong_prop = PropertyValue(TemporalData(TemporalType::Date, 1234));
|
||||
const auto schema_violation =
|
||||
schema_validator.ValidateVertexCreate(label2, {}, {PropertyValue("test"), PropertyValue(12), wrong_prop});
|
||||
ASSERT_NE(schema_violation, std::nullopt);
|
||||
EXPECT_EQ(*schema_violation, SchemaViolation(SchemaViolation::ValidationStatus::VERTEX_PROPERTY_WRONG_TYPE, label2,
|
||||
schema_prop_duration, wrong_prop));
|
||||
ASSERT_TRUE(schema_violation.HasError());
|
||||
EXPECT_EQ(schema_violation.GetError(), SHARD_ERROR(ErrorCode::SCHEMA_VERTEX_PROPERTY_WRONG_TYPE));
|
||||
}
|
||||
// Passing validations
|
||||
EXPECT_EQ(schema_validator.ValidateVertexCreate(label1, {}, {PropertyValue("test")}), std::nullopt);
|
||||
EXPECT_EQ(schema_validator.ValidateVertexCreate(label1, {NameToLabel("label3"), NameToLabel("label4")},
|
||||
{PropertyValue("test")}),
|
||||
std::nullopt);
|
||||
EXPECT_EQ(schema_validator.ValidateVertexCreate(
|
||||
label2, {},
|
||||
{PropertyValue("test"), PropertyValue(122), PropertyValue(TemporalData(TemporalType::Duration, 1234))}),
|
||||
std::nullopt);
|
||||
EXPECT_EQ(schema_validator.ValidateVertexCreate(label2, {NameToLabel("label5"), NameToLabel("label6")},
|
||||
{PropertyValue("test123"), PropertyValue(122221),
|
||||
PropertyValue(TemporalData(TemporalType::Duration, 12344321))}),
|
||||
std::nullopt);
|
||||
EXPECT_FALSE(schema_validator.ValidateVertexCreate(label1, {}, {PropertyValue("test")}).HasError());
|
||||
EXPECT_FALSE(
|
||||
schema_validator
|
||||
.ValidateVertexCreate(label1, {NameToLabel("label3"), NameToLabel("label4")}, {PropertyValue("test")})
|
||||
.HasError());
|
||||
EXPECT_FALSE(schema_validator
|
||||
.ValidateVertexCreate(label2, {},
|
||||
{PropertyValue("test"), PropertyValue(122),
|
||||
PropertyValue(TemporalData(TemporalType::Duration, 1234))})
|
||||
.HasError());
|
||||
EXPECT_FALSE(schema_validator
|
||||
.ValidateVertexCreate(label2, {NameToLabel("label5"), NameToLabel("label6")},
|
||||
{PropertyValue("test123"), PropertyValue(122221),
|
||||
PropertyValue(TemporalData(TemporalType::Duration, 12344321))})
|
||||
.HasError());
|
||||
}
|
||||
|
||||
TEST_F(SchemaValidatorTest, TestSchemaValidatePropertyUpdate) {
|
||||
// Validate updating of primary key
|
||||
{
|
||||
const auto schema_violation = schema_validator.ValidatePropertyUpdate(label1, prop_string);
|
||||
ASSERT_NE(schema_violation, std::nullopt);
|
||||
EXPECT_EQ(*schema_violation, SchemaViolation(SchemaViolation::ValidationStatus::VERTEX_UPDATE_PRIMARY_KEY, label1,
|
||||
schema_prop_string));
|
||||
ASSERT_TRUE(schema_violation.HasError());
|
||||
EXPECT_EQ(schema_violation.GetError(), SHARD_ERROR(ErrorCode::SCHEMA_VERTEX_UPDATE_PRIMARY_KEY));
|
||||
}
|
||||
{
|
||||
const auto schema_violation = schema_validator.ValidatePropertyUpdate(label2, prop_duration);
|
||||
ASSERT_NE(schema_violation, std::nullopt);
|
||||
EXPECT_EQ(*schema_violation, SchemaViolation(SchemaViolation::ValidationStatus::VERTEX_UPDATE_PRIMARY_KEY, label2,
|
||||
schema_prop_duration));
|
||||
ASSERT_TRUE(schema_violation.HasError());
|
||||
EXPECT_EQ(schema_violation.GetError(), SHARD_ERROR(ErrorCode::SCHEMA_VERTEX_UPDATE_PRIMARY_KEY));
|
||||
}
|
||||
EXPECT_EQ(schema_validator.ValidatePropertyUpdate(label1, prop_int), std::nullopt);
|
||||
EXPECT_EQ(schema_validator.ValidatePropertyUpdate(label1, prop_duration), std::nullopt);
|
||||
EXPECT_EQ(schema_validator.ValidatePropertyUpdate(label2, NameToProperty("test")), std::nullopt);
|
||||
EXPECT_FALSE(schema_validator.ValidatePropertyUpdate(label1, prop_int).HasError());
|
||||
EXPECT_FALSE(schema_validator.ValidatePropertyUpdate(label1, prop_duration).HasError());
|
||||
EXPECT_FALSE(schema_validator.ValidatePropertyUpdate(label2, NameToProperty("test")).HasError());
|
||||
}
|
||||
|
||||
TEST_F(SchemaValidatorTest, TestSchemaValidatePropertyUpdateLabel) {
|
||||
// Validate adding primary label
|
||||
{
|
||||
const auto schema_violation = schema_validator.ValidateLabelUpdate(label1);
|
||||
ASSERT_NE(schema_violation, std::nullopt);
|
||||
EXPECT_EQ(*schema_violation,
|
||||
SchemaViolation(SchemaViolation::ValidationStatus::VERTEX_UPDATE_PRIMARY_LABEL, label1));
|
||||
ASSERT_TRUE(schema_violation.HasError());
|
||||
EXPECT_EQ(schema_violation.GetError(), SHARD_ERROR(ErrorCode::SCHEMA_VERTEX_UPDATE_PRIMARY_LABEL));
|
||||
}
|
||||
{
|
||||
const auto schema_violation = schema_validator.ValidateLabelUpdate(label2);
|
||||
ASSERT_NE(schema_violation, std::nullopt);
|
||||
EXPECT_EQ(*schema_violation,
|
||||
SchemaViolation(SchemaViolation::ValidationStatus::VERTEX_UPDATE_PRIMARY_LABEL, label2));
|
||||
ASSERT_TRUE(schema_violation.HasError());
|
||||
EXPECT_EQ(schema_violation.GetError(), SHARD_ERROR(ErrorCode::SCHEMA_VERTEX_UPDATE_PRIMARY_LABEL));
|
||||
}
|
||||
EXPECT_EQ(schema_validator.ValidateLabelUpdate(NameToLabel("test")), std::nullopt);
|
||||
EXPECT_FALSE(schema_validator.ValidateLabelUpdate(NameToLabel("test")).HasError());
|
||||
}
|
||||
} // namespace memgraph::storage::v3::tests
|
||||
|
||||
316
tests/unit/storage_v3_shard_rsm.cpp
Normal file
316
tests/unit/storage_v3_shard_rsm.cpp
Normal file
@@ -0,0 +1,316 @@
|
||||
// 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 <gmock/gmock-matchers.h>
|
||||
#include <gmock/gmock.h>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <fmt/format.h>
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <variant>
|
||||
#include <vector>
|
||||
|
||||
#include "common/types.hpp"
|
||||
#include "query/v2/requests.hpp"
|
||||
#include "storage/v3/id_types.hpp"
|
||||
#include "storage/v3/property_value.hpp"
|
||||
#include "storage/v3/schema_validator.hpp"
|
||||
#include "storage/v3/schemas.hpp"
|
||||
#include "storage/v3/shard_rsm.hpp"
|
||||
#include "storage/v3/temporal.hpp"
|
||||
#include "storage/v3/vertex_id.hpp"
|
||||
|
||||
using testing::Pair;
|
||||
using testing::UnorderedElementsAre;
|
||||
using SchemaType = memgraph::common::SchemaType;
|
||||
|
||||
namespace memgraph::storage::v3::tests {
|
||||
|
||||
uint64_t GetTransactionId() {
|
||||
static uint64_t transaction_id = 0;
|
||||
return transaction_id++;
|
||||
}
|
||||
|
||||
class ShardRSMTest : public testing::Test {
|
||||
private:
|
||||
NameIdMapper id_mapper_{{{1, "primary_label"},
|
||||
{2, "primary_label2"},
|
||||
{3, "label"},
|
||||
{4, "primary_prop1"},
|
||||
{5, "primary_prop2"},
|
||||
{6, "prop"}}};
|
||||
|
||||
protected:
|
||||
ShardRSMTest() {
|
||||
PropertyValue min_pk(static_cast<int64_t>(0));
|
||||
std::vector<PropertyValue> min_prim_key = {min_pk};
|
||||
PropertyValue max_pk(static_cast<int64_t>(10000000));
|
||||
std::vector<PropertyValue> max_prim_key = {max_pk};
|
||||
|
||||
auto shard_ptr1 = std::make_unique<Shard>(primary_label, min_prim_key, max_prim_key, std::vector{schema_prop});
|
||||
shard_ptr1->StoreMapping({{1, "primary_label"},
|
||||
{2, "primary_label2"},
|
||||
{3, "label"},
|
||||
{4, "primary_prop1"},
|
||||
{5, "primary_prop2"},
|
||||
{6, "prop"}});
|
||||
shard_ptr1->CreateSchema(primary_label2, {{primary_property2, SchemaType::INT}});
|
||||
shard_rsm = std::make_unique<ShardRsm>(std::move(shard_ptr1));
|
||||
}
|
||||
|
||||
LabelId NameToLabel(const std::string &name) { return LabelId::FromUint(id_mapper_.NameToId(name)); }
|
||||
|
||||
PropertyId NameToProperty(const std::string &name) { return PropertyId::FromUint(id_mapper_.NameToId(name)); }
|
||||
|
||||
auto Commit(const auto &req) {
|
||||
const coordinator::Hlc commit_timestamp{GetTransactionId()};
|
||||
msgs::CommitRequest commit_req;
|
||||
commit_req.transaction_id = req.transaction_id;
|
||||
commit_req.commit_timestamp = commit_timestamp;
|
||||
return shard_rsm->Apply(commit_req);
|
||||
}
|
||||
|
||||
void CreateVertex(const msgs::PrimaryKey &primary_key, const std::vector<msgs::Label> labels,
|
||||
const std::vector<std::pair<msgs::PropertyId, msgs::Value>> &properties) {
|
||||
msgs::NewVertex vertex = {labels, primary_key, properties};
|
||||
msgs::CreateVerticesRequest create_req;
|
||||
create_req.new_vertices = {vertex};
|
||||
create_req.new_vertices = {vertex};
|
||||
create_req.transaction_id.logical_id = GetTransactionId();
|
||||
|
||||
auto write_res = shard_rsm->Apply(create_req);
|
||||
ASSERT_TRUE(std::holds_alternative<msgs::CreateVerticesResponse>(write_res));
|
||||
|
||||
auto commit_res = Commit(create_req);
|
||||
ASSERT_TRUE(std::holds_alternative<msgs::CommitResponse>(commit_res));
|
||||
ASSERT_FALSE(std::get<msgs::CommitResponse>(commit_res).error.has_value());
|
||||
}
|
||||
|
||||
void AssertVertexExists(const msgs::PrimaryKey &primary_key, const std::vector<msgs::Label> &labels,
|
||||
const std::vector<std::pair<msgs::PropertyId, msgs::Value>> &properties) {
|
||||
msgs::ScanVerticesRequest scan_req;
|
||||
scan_req.props_to_return = std::nullopt;
|
||||
scan_req.start_id = msgs::VertexId{msgs::Label{.id = primary_label}, primary_key};
|
||||
scan_req.storage_view = msgs::StorageView::OLD;
|
||||
scan_req.transaction_id.logical_id = GetTransactionId();
|
||||
|
||||
// Make request
|
||||
auto maybe_read_res = shard_rsm->Read(scan_req);
|
||||
ASSERT_TRUE(std::holds_alternative<msgs::ScanVerticesResponse>(maybe_read_res));
|
||||
const auto read_res = std::get<msgs::ScanVerticesResponse>(maybe_read_res);
|
||||
EXPECT_FALSE(read_res.error.has_value());
|
||||
EXPECT_EQ(read_res.results.size(), 1);
|
||||
|
||||
// Read results
|
||||
const auto res = read_res.results[0];
|
||||
const auto vtx_id = msgs::VertexId{msgs::Label{.id = primary_label}, primary_key};
|
||||
EXPECT_EQ(res.vertex.id, vtx_id);
|
||||
EXPECT_EQ(res.vertex.labels, labels);
|
||||
EXPECT_EQ(res.props, properties);
|
||||
}
|
||||
|
||||
LabelId primary_label{NameToLabel("primary_label")};
|
||||
LabelId primary_label2{NameToLabel("primary_label2")};
|
||||
LabelId label{NameToLabel("label")};
|
||||
PropertyId primary_property1{NameToProperty("primary_prop1")};
|
||||
PropertyId primary_property2{NameToProperty("primary_prop2")};
|
||||
PropertyId prop{NameToProperty("prop")};
|
||||
SchemaProperty schema_prop{primary_property1, SchemaType::INT};
|
||||
std::unique_ptr<ShardRsm> shard_rsm;
|
||||
};
|
||||
|
||||
TEST_F(ShardRSMTest, TestUpdateVertexSecondaryProperty) {
|
||||
const msgs::Value primary_key_val{static_cast<int64_t>(1)};
|
||||
const msgs::PrimaryKey pk{primary_key_val};
|
||||
|
||||
// Create Vertex
|
||||
CreateVertex(pk, {}, {});
|
||||
|
||||
// Add property prop
|
||||
static constexpr int64_t updated_vertex_id{10};
|
||||
{
|
||||
msgs::UpdateVerticesRequest update_req;
|
||||
update_req.transaction_id.logical_id = GetTransactionId();
|
||||
|
||||
update_req.update_vertices =
|
||||
std::vector<msgs::UpdateVertex>{{pk, {}, {}, {{msgs::PropertyId(prop), msgs::Value(updated_vertex_id)}}}};
|
||||
|
||||
const auto write_res = shard_rsm->Apply(update_req);
|
||||
ASSERT_TRUE(std::holds_alternative<msgs::UpdateVerticesResponse>(write_res));
|
||||
EXPECT_FALSE(std::get<msgs::UpdateVerticesResponse>(write_res).error.has_value());
|
||||
|
||||
const auto commit_res = Commit(update_req);
|
||||
ASSERT_TRUE(std::holds_alternative<msgs::CommitResponse>(commit_res));
|
||||
EXPECT_FALSE(std::get<msgs::CommitResponse>(commit_res).error.has_value());
|
||||
}
|
||||
AssertVertexExists(pk, {}, {{primary_property1, primary_key_val}, {prop, msgs::Value(updated_vertex_id)}});
|
||||
|
||||
// Update property prop
|
||||
static constexpr int64_t updated_vertex_id_2{101};
|
||||
{
|
||||
msgs::UpdateVerticesRequest update_req;
|
||||
update_req.transaction_id.logical_id = GetTransactionId();
|
||||
|
||||
update_req.update_vertices =
|
||||
std::vector<msgs::UpdateVertex>{{pk, {}, {}, {{msgs::PropertyId(prop), msgs::Value(updated_vertex_id_2)}}}};
|
||||
|
||||
const auto write_res = shard_rsm->Apply(update_req);
|
||||
ASSERT_TRUE(std::holds_alternative<msgs::UpdateVerticesResponse>(write_res));
|
||||
EXPECT_FALSE(std::get<msgs::UpdateVerticesResponse>(write_res).error.has_value());
|
||||
|
||||
const auto commit_res = Commit(update_req);
|
||||
ASSERT_TRUE(std::holds_alternative<msgs::CommitResponse>(commit_res));
|
||||
EXPECT_FALSE(std::get<msgs::CommitResponse>(commit_res).error.has_value());
|
||||
AssertVertexExists(pk, {}, {{primary_property1, primary_key_val}, {prop, msgs::Value(updated_vertex_id_2)}});
|
||||
}
|
||||
AssertVertexExists(pk, {}, {{primary_property1, primary_key_val}, {prop, msgs::Value(updated_vertex_id_2)}});
|
||||
|
||||
// Remove property prop
|
||||
{
|
||||
msgs::UpdateVerticesRequest update_req;
|
||||
update_req.transaction_id.logical_id = GetTransactionId();
|
||||
|
||||
update_req.update_vertices =
|
||||
std::vector<msgs::UpdateVertex>{{pk, {}, {}, {{msgs::PropertyId(prop), msgs::Value()}}}};
|
||||
|
||||
const auto write_res = shard_rsm->Apply(update_req);
|
||||
ASSERT_TRUE(std::holds_alternative<msgs::UpdateVerticesResponse>(write_res));
|
||||
EXPECT_FALSE(std::get<msgs::UpdateVerticesResponse>(write_res).error.has_value());
|
||||
|
||||
const auto commit_res = Commit(update_req);
|
||||
ASSERT_TRUE(std::holds_alternative<msgs::CommitResponse>(commit_res));
|
||||
EXPECT_FALSE(std::get<msgs::CommitResponse>(commit_res).error.has_value());
|
||||
}
|
||||
AssertVertexExists(pk, {}, {{primary_property1, primary_key_val}});
|
||||
}
|
||||
|
||||
TEST_F(ShardRSMTest, TestUpdateVertexPrimaryProperty) {
|
||||
const msgs::Value primary_key_val{static_cast<int64_t>(1)};
|
||||
const msgs::PrimaryKey pk{primary_key_val};
|
||||
|
||||
// Create Vertex
|
||||
CreateVertex(pk, {}, {});
|
||||
|
||||
// Try to update primary property
|
||||
static constexpr int64_t updated_vertex_id{10};
|
||||
{
|
||||
msgs::UpdateVerticesRequest update_req;
|
||||
update_req.transaction_id.logical_id = GetTransactionId();
|
||||
|
||||
update_req.update_vertices = std::vector<msgs::UpdateVertex>{
|
||||
{pk, {}, {}, {{msgs::PropertyId(primary_property1), msgs::Value(updated_vertex_id)}}}};
|
||||
|
||||
const auto write_res = shard_rsm->Apply(update_req);
|
||||
ASSERT_TRUE(std::holds_alternative<msgs::UpdateVerticesResponse>(write_res));
|
||||
EXPECT_TRUE(std::get<msgs::UpdateVerticesResponse>(write_res).error.has_value());
|
||||
}
|
||||
AssertVertexExists(pk, {}, {{primary_property1, primary_key_val}});
|
||||
// Try to update primary property of another schema
|
||||
{
|
||||
msgs::UpdateVerticesRequest update_req;
|
||||
update_req.transaction_id.logical_id = GetTransactionId();
|
||||
|
||||
update_req.update_vertices = std::vector<msgs::UpdateVertex>{
|
||||
{pk, {}, {}, {{msgs::PropertyId(primary_property2), msgs::Value(updated_vertex_id)}}}};
|
||||
|
||||
const auto write_res = shard_rsm->Apply(update_req);
|
||||
ASSERT_TRUE(std::holds_alternative<msgs::UpdateVerticesResponse>(write_res));
|
||||
EXPECT_FALSE(std::get<msgs::UpdateVerticesResponse>(write_res).error.has_value());
|
||||
|
||||
const auto commit_res = Commit(update_req);
|
||||
ASSERT_TRUE(std::holds_alternative<msgs::CommitResponse>(commit_res));
|
||||
EXPECT_FALSE(std::get<msgs::CommitResponse>(commit_res).error.has_value());
|
||||
}
|
||||
AssertVertexExists(pk, {},
|
||||
{{primary_property1, primary_key_val}, {primary_property2, msgs::Value(updated_vertex_id)}});
|
||||
}
|
||||
|
||||
TEST_F(ShardRSMTest, TestUpdateSecondaryLabel) {
|
||||
const msgs::Value primary_key_val{static_cast<int64_t>(1)};
|
||||
const msgs::PrimaryKey pk{primary_key_val};
|
||||
|
||||
// Create Vertex
|
||||
CreateVertex(pk, {}, {});
|
||||
|
||||
// Add label label
|
||||
const msgs::Label secondary_label{label};
|
||||
{
|
||||
msgs::UpdateVerticesRequest update_req;
|
||||
update_req.transaction_id.logical_id = GetTransactionId();
|
||||
|
||||
update_req.update_vertices = std::vector<msgs::UpdateVertex>{{pk, {label}, {}, {}}};
|
||||
|
||||
const auto write_res = shard_rsm->Apply(update_req);
|
||||
ASSERT_TRUE(std::holds_alternative<msgs::UpdateVerticesResponse>(write_res));
|
||||
EXPECT_FALSE(std::get<msgs::UpdateVerticesResponse>(write_res).error.has_value());
|
||||
|
||||
const auto commit_res = Commit(update_req);
|
||||
ASSERT_TRUE(std::holds_alternative<msgs::CommitResponse>(commit_res));
|
||||
EXPECT_FALSE(std::get<msgs::CommitResponse>(commit_res).error.has_value());
|
||||
}
|
||||
AssertVertexExists(pk, {secondary_label}, {{primary_property1, primary_key_val}});
|
||||
|
||||
// Remove primary label
|
||||
{
|
||||
msgs::UpdateVerticesRequest update_req;
|
||||
update_req.transaction_id.logical_id = GetTransactionId();
|
||||
|
||||
update_req.update_vertices = std::vector<msgs::UpdateVertex>{{pk, {}, {label}, {}}};
|
||||
|
||||
const auto write_res = shard_rsm->Apply(update_req);
|
||||
ASSERT_TRUE(std::holds_alternative<msgs::UpdateVerticesResponse>(write_res));
|
||||
EXPECT_FALSE(std::get<msgs::UpdateVerticesResponse>(write_res).error.has_value());
|
||||
|
||||
const auto commit_res = Commit(update_req);
|
||||
ASSERT_TRUE(std::holds_alternative<msgs::CommitResponse>(commit_res));
|
||||
EXPECT_FALSE(std::get<msgs::CommitResponse>(commit_res).error.has_value());
|
||||
}
|
||||
AssertVertexExists(pk, {}, {{primary_property1, primary_key_val}});
|
||||
}
|
||||
|
||||
TEST_F(ShardRSMTest, TestUpdatePrimaryLabel) {
|
||||
const msgs::Value primary_key_val{static_cast<int64_t>(1)};
|
||||
const msgs::PrimaryKey pk{primary_key_val};
|
||||
|
||||
// Create Vertex
|
||||
CreateVertex(pk, {}, {});
|
||||
|
||||
// Remove primary label
|
||||
{
|
||||
msgs::UpdateVerticesRequest update_req;
|
||||
update_req.transaction_id.logical_id = GetTransactionId();
|
||||
|
||||
update_req.update_vertices = std::vector<msgs::UpdateVertex>{{pk, {}, {primary_label}, {}}};
|
||||
|
||||
const auto write_res = shard_rsm->Apply(update_req);
|
||||
ASSERT_TRUE(std::holds_alternative<msgs::UpdateVerticesResponse>(write_res));
|
||||
EXPECT_TRUE(std::get<msgs::UpdateVerticesResponse>(write_res).error.has_value());
|
||||
}
|
||||
AssertVertexExists(pk, {}, {{primary_property1, primary_key_val}});
|
||||
|
||||
// Add different primary label
|
||||
{
|
||||
msgs::UpdateVerticesRequest update_req;
|
||||
update_req.transaction_id.logical_id = GetTransactionId();
|
||||
|
||||
update_req.update_vertices = std::vector<msgs::UpdateVertex>{{pk, {primary_label2}, {}, {}}};
|
||||
|
||||
const auto write_res = shard_rsm->Apply(update_req);
|
||||
ASSERT_TRUE(std::holds_alternative<msgs::UpdateVerticesResponse>(write_res));
|
||||
EXPECT_TRUE(std::get<msgs::UpdateVerticesResponse>(write_res).error.has_value());
|
||||
}
|
||||
AssertVertexExists(pk, {}, {{primary_property1, primary_key_val}});
|
||||
}
|
||||
|
||||
} // namespace memgraph::storage::v3::tests
|
||||
@@ -16,6 +16,7 @@
|
||||
#include <gmock/gmock.h>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "common/errors.hpp"
|
||||
#include "common/types.hpp"
|
||||
#include "storage/v3/delta.hpp"
|
||||
#include "storage/v3/id_types.hpp"
|
||||
@@ -76,7 +77,7 @@ TEST_F(StorageV3Accessor, TestPrimaryLabel) {
|
||||
ASSERT_TRUE(vertex.PrimaryLabel(View::OLD).HasError());
|
||||
const auto error_primary_label = vertex.PrimaryLabel(View::OLD).GetError();
|
||||
ASSERT_FALSE(vertex.PrimaryLabel(View::NEW).HasError());
|
||||
EXPECT_EQ(error_primary_label, Error::NONEXISTENT_OBJECT);
|
||||
EXPECT_EQ(error_primary_label, SHARD_ERROR(ErrorCode::NONEXISTENT_OBJECT));
|
||||
}
|
||||
{
|
||||
auto acc = storage.Access(GetNextHlc());
|
||||
@@ -127,9 +128,7 @@ TEST_F(StorageV3Accessor, TestAddLabels) {
|
||||
const auto label1 = NameToLabelId("label");
|
||||
auto vertex = acc.CreateVertexAndValidate({label1}, {PropertyValue{2}}, {});
|
||||
ASSERT_TRUE(vertex.HasError());
|
||||
ASSERT_TRUE(std::holds_alternative<SchemaViolation>(vertex.GetError()));
|
||||
EXPECT_EQ(std::get<SchemaViolation>(vertex.GetError()),
|
||||
SchemaViolation(SchemaViolation::ValidationStatus::VERTEX_SECONDARY_LABEL_IS_PRIMARY, label1));
|
||||
EXPECT_EQ(vertex.GetError(), SHARD_ERROR(ErrorCode::SCHEMA_VERTEX_SECONDARY_LABEL_IS_PRIMARY));
|
||||
}
|
||||
{
|
||||
auto acc = storage.Access(GetNextHlc());
|
||||
@@ -138,9 +137,7 @@ TEST_F(StorageV3Accessor, TestAddLabels) {
|
||||
ASSERT_TRUE(vertex.HasValue());
|
||||
const auto schema_violation = vertex->AddLabelAndValidate(label1);
|
||||
ASSERT_TRUE(schema_violation.HasError());
|
||||
ASSERT_TRUE(std::holds_alternative<SchemaViolation>(schema_violation.GetError()));
|
||||
EXPECT_EQ(std::get<SchemaViolation>(schema_violation.GetError()),
|
||||
SchemaViolation(SchemaViolation::ValidationStatus::VERTEX_UPDATE_PRIMARY_LABEL, label1));
|
||||
EXPECT_EQ(schema_violation.GetError(), SHARD_ERROR(ErrorCode::SCHEMA_VERTEX_UPDATE_PRIMARY_LABEL));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -184,9 +181,7 @@ TEST_F(StorageV3Accessor, TestRemoveLabels) {
|
||||
auto vertex = CreateVertexAndValidate(acc, {}, PropertyValue{2});
|
||||
const auto res1 = vertex.RemoveLabelAndValidate(primary_label);
|
||||
ASSERT_TRUE(res1.HasError());
|
||||
ASSERT_TRUE(std::holds_alternative<SchemaViolation>(res1.GetError()));
|
||||
EXPECT_EQ(std::get<SchemaViolation>(res1.GetError()),
|
||||
SchemaViolation(SchemaViolation::ValidationStatus::VERTEX_UPDATE_PRIMARY_LABEL, primary_label));
|
||||
EXPECT_EQ(res1.GetError(), SHARD_ERROR(ErrorCode::SCHEMA_VERTEX_UPDATE_PRIMARY_LABEL));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -205,20 +200,14 @@ TEST_F(StorageV3Accessor, TestSetKeysAndProperties) {
|
||||
auto vertex = CreateVertexAndValidate(acc, {}, PropertyValue{1});
|
||||
const auto res = vertex.SetPropertyAndValidate(primary_property, PropertyValue(1));
|
||||
ASSERT_TRUE(res.HasError());
|
||||
ASSERT_TRUE(std::holds_alternative<SchemaViolation>(res.GetError()));
|
||||
EXPECT_EQ(std::get<SchemaViolation>(res.GetError()),
|
||||
SchemaViolation(SchemaViolation::ValidationStatus::VERTEX_UPDATE_PRIMARY_KEY, primary_label,
|
||||
SchemaProperty{primary_property, common::SchemaType::INT}));
|
||||
EXPECT_EQ(res.GetError(), SHARD_ERROR(ErrorCode::SCHEMA_VERTEX_UPDATE_PRIMARY_KEY));
|
||||
}
|
||||
{
|
||||
auto acc = storage.Access(GetNextHlc());
|
||||
auto vertex = CreateVertexAndValidate(acc, {}, PropertyValue{2});
|
||||
const auto res = vertex.SetPropertyAndValidate(primary_property, PropertyValue());
|
||||
ASSERT_TRUE(res.HasError());
|
||||
ASSERT_TRUE(std::holds_alternative<SchemaViolation>(res.GetError()));
|
||||
EXPECT_EQ(std::get<SchemaViolation>(res.GetError()),
|
||||
SchemaViolation(SchemaViolation::ValidationStatus::VERTEX_UPDATE_PRIMARY_KEY, primary_label,
|
||||
SchemaProperty{primary_property, common::SchemaType::INT}));
|
||||
EXPECT_EQ(res.GetError(), SHARD_ERROR(ErrorCode::SCHEMA_VERTEX_UPDATE_PRIMARY_KEY));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user