Add Python query module API mock (#757)
This commit is contained in:
parent
6abd356d01
commit
97d45ab1d8
343
include/_mgp_mock.py
Normal file
343
include/_mgp_mock.py
Normal file
@ -0,0 +1,343 @@
|
||||
import typing
|
||||
from enum import Enum
|
||||
|
||||
import networkx as nx
|
||||
|
||||
NX_LABEL_ATTR = "labels"
|
||||
NX_TYPE_ATTR = "type"
|
||||
|
||||
SOURCE_TYPE_KAFKA = "SOURCE_TYPE_KAFKA"
|
||||
SOURCE_TYPE_PULSAR = "SOURCE_TYPE_PULSAR"
|
||||
|
||||
"""
|
||||
This module provides helpers for the mock Python API, much like _mgp.py does for mgp.py.
|
||||
"""
|
||||
|
||||
|
||||
class InvalidArgumentError(Exception):
|
||||
"""
|
||||
Signals that some of the arguments have invalid values.
|
||||
"""
|
||||
|
||||
pass
|
||||
|
||||
|
||||
class ImmutableObjectError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class LogicErrorError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class DeletedObjectError(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class EdgeConstants(Enum):
|
||||
I_START = 0
|
||||
I_END = 1
|
||||
I_KEY = 2
|
||||
|
||||
|
||||
class Graph:
|
||||
"""Wrapper around a NetworkX MultiDiGraph instance."""
|
||||
|
||||
__slots__ = ("nx", "_highest_vertex_id", "_highest_edge_id", "_valid")
|
||||
|
||||
def __init__(self, graph: nx.MultiDiGraph) -> None:
|
||||
if not isinstance(graph, nx.MultiDiGraph):
|
||||
raise TypeError(f"Expected 'networkx.classes.multidigraph.MultiDiGraph', got '{type(graph)}'")
|
||||
|
||||
self.nx = graph
|
||||
self._highest_vertex_id = None
|
||||
self._highest_edge_id = None
|
||||
self._valid = True
|
||||
|
||||
@property
|
||||
def vertex_ids(self):
|
||||
return self.nx.nodes
|
||||
|
||||
def vertex_is_isolate(self, vertex_id: int) -> bool:
|
||||
return nx.is_isolate(self.nx, vertex_id)
|
||||
|
||||
@property
|
||||
def vertices(self):
|
||||
return (Vertex(node_id, self) for node_id in self.nx.nodes)
|
||||
|
||||
def has_node(self, node_id):
|
||||
return self.nx.has_node(node_id)
|
||||
|
||||
@property
|
||||
def edges(self):
|
||||
return self.nx.edges
|
||||
|
||||
def is_valid(self) -> bool:
|
||||
return self._valid
|
||||
|
||||
def get_vertex_by_id(self, vertex_id: int) -> "Vertex":
|
||||
return Vertex(vertex_id, self)
|
||||
|
||||
def invalidate(self):
|
||||
self._valid = False
|
||||
|
||||
def is_immutable(self) -> bool:
|
||||
return nx.is_frozen(self.nx)
|
||||
|
||||
def make_immutable(self):
|
||||
self.nx = nx.freeze(self.nx)
|
||||
|
||||
def _new_vertex_id(self):
|
||||
if self._highest_vertex_id is None:
|
||||
self._highest_vertex_id = max(vertex_id for vertex_id in self.nx.nodes)
|
||||
|
||||
return self._highest_vertex_id + 1
|
||||
|
||||
def _new_edge_id(self):
|
||||
if self._highest_edge_id is None:
|
||||
self._highest_edge_id = max(edge[EdgeConstants.I_KEY.value] for edge in self.nx.edges(keys=True))
|
||||
|
||||
return self._highest_edge_id + 1
|
||||
|
||||
def create_vertex(self) -> "Vertex":
|
||||
vertex_id = self._new_vertex_id()
|
||||
|
||||
self.nx.add_node(vertex_id)
|
||||
self._highest_vertex_id = vertex_id
|
||||
|
||||
return Vertex(vertex_id, self)
|
||||
|
||||
def create_edge(self, from_vertex: "Vertex", to_vertex: "Vertex", edge_type: str) -> "Edge":
|
||||
if from_vertex.is_deleted() or to_vertex.is_deleted():
|
||||
raise DeletedObjectError("Accessing deleted object.")
|
||||
|
||||
edge_id = self._new_edge_id()
|
||||
|
||||
from_id = from_vertex.id
|
||||
to_id = to_vertex.id
|
||||
|
||||
self.nx.add_edge(from_id, to_id, key=edge_id, type=edge_type)
|
||||
self._highest_edge_id = edge_id
|
||||
|
||||
return Edge((from_id, to_id, edge_id), self)
|
||||
|
||||
def delete_vertex(self, vertex_id: int):
|
||||
self.nx.remove_node(vertex_id)
|
||||
|
||||
def delete_edge(self, from_vertex_id: int, to_vertex_id: int, edge_id: int):
|
||||
self.nx.remove_edge(from_vertex_id, to_vertex_id, edge_id)
|
||||
|
||||
@property
|
||||
def highest_vertex_id(self) -> int:
|
||||
if self._highest_vertex_id is None:
|
||||
self._highest_vertex_id = max(vertex_id for vertex_id in self.nx.nodes) + 1
|
||||
|
||||
return self._highest_vertex_id
|
||||
|
||||
@property
|
||||
def highest_edge_id(self) -> int:
|
||||
if self._highest_edge_id is None:
|
||||
self._highest_edge_id = max(edge[EdgeConstants.I_KEY.value] for edge in self.nx.edges(keys=True))
|
||||
|
||||
return self._highest_edge_id + 1
|
||||
|
||||
|
||||
class Vertex:
|
||||
"""Represents a graph vertex."""
|
||||
|
||||
__slots__ = ("_id", "_graph")
|
||||
|
||||
def __init__(self, id: int, graph: Graph) -> None:
|
||||
if not isinstance(id, int):
|
||||
raise TypeError(f"Expected 'int', got '{type(id)}'")
|
||||
|
||||
if not isinstance(graph, Graph):
|
||||
raise TypeError(f"Expected '_mgp_mock.Graph', got '{type(graph)}'")
|
||||
|
||||
if not graph.nx.has_node(id):
|
||||
raise IndexError(f"Unable to find vertex with ID {id}.")
|
||||
|
||||
self._id = id
|
||||
self._graph = graph
|
||||
|
||||
def is_valid(self) -> bool:
|
||||
return self._graph.is_valid()
|
||||
|
||||
def is_deleted(self) -> bool:
|
||||
return not self._graph.nx.has_node(self._id) and self._id <= self._graph.highest_vertex_id
|
||||
|
||||
@property
|
||||
def underlying_graph(self) -> Graph:
|
||||
return self._graph
|
||||
|
||||
def underlying_graph_is_mutable(self) -> bool:
|
||||
return not nx.is_frozen(self._graph.nx)
|
||||
|
||||
@property
|
||||
def labels(self) -> typing.List[int]:
|
||||
return self._graph.nx.nodes[self._id][NX_LABEL_ATTR].split(":")
|
||||
|
||||
def add_label(self, label: str) -> None:
|
||||
if nx.is_frozen(self._graph.nx):
|
||||
raise ImmutableObjectError("Cannot modify immutable object.")
|
||||
|
||||
self._graph.nx.nodes[self._id][NX_LABEL_ATTR] += f":{label}"
|
||||
|
||||
def remove_label(self, label: str) -> None:
|
||||
if nx.is_frozen(self._graph.nx):
|
||||
raise ImmutableObjectError("Cannot modify immutable object.")
|
||||
|
||||
labels = self._graph.nx.nodes[self._id][NX_LABEL_ATTR]
|
||||
if labels.startswith(f"{label}:"):
|
||||
labels = "\n" + labels # pseudo-string starter
|
||||
self._graph.nx.nodes[self._id][NX_LABEL_ATTR] = labels.replace(f"\n{label}:", "")
|
||||
elif labels.endswith(f":{label}"):
|
||||
labels += "\n" # pseudo-string terminator
|
||||
self._graph.nx.nodes[self._id][NX_LABEL_ATTR] = labels.replace(f":{label}\n", "")
|
||||
else:
|
||||
self._graph.nx.nodes[self._id][NX_LABEL_ATTR] = labels.replace(f":{label}:", ":")
|
||||
|
||||
@property
|
||||
def id(self) -> int:
|
||||
return self._id
|
||||
|
||||
@property
|
||||
def properties(self):
|
||||
return (
|
||||
(key, value)
|
||||
for key, value in self._graph.nx.nodes[self._id].items()
|
||||
if key not in (NX_LABEL_ATTR, NX_TYPE_ATTR)
|
||||
)
|
||||
|
||||
def get_property(self, property_name: str):
|
||||
return self._graph.nx.nodes[self._id][property_name]
|
||||
|
||||
def set_property(self, property_name: str, value: object):
|
||||
self._graph.nx.nodes[self._id][property_name] = value
|
||||
|
||||
@property
|
||||
def in_edges(self) -> typing.Iterable["Edge"]:
|
||||
return [Edge(edge, self._graph) for edge in self._graph.nx.in_edges(self._id, keys=True)]
|
||||
|
||||
@property
|
||||
def out_edges(self) -> typing.Iterable["Edge"]:
|
||||
return [Edge(edge, self._graph) for edge in self._graph.nx.out_edges(self._id, keys=True)]
|
||||
|
||||
|
||||
class Edge:
|
||||
"""Represents a graph edge."""
|
||||
|
||||
__slots__ = ("_edge", "_graph")
|
||||
|
||||
def __init__(self, edge: typing.Tuple[int, int, int], graph: Graph) -> None:
|
||||
if not isinstance(edge, typing.Tuple):
|
||||
raise TypeError(f"Expected 'Tuple', got '{type(edge)}'")
|
||||
|
||||
if not isinstance(graph, Graph):
|
||||
raise TypeError(f"Expected '_mgp_mock.Graph', got '{type(graph)}'")
|
||||
|
||||
if not graph.nx.has_edge(*edge):
|
||||
raise IndexError(f"Unable to find edge with ID {edge[EdgeConstants.I_KEY.value]}.")
|
||||
|
||||
self._edge = edge
|
||||
self._graph = graph
|
||||
|
||||
def is_valid(self) -> bool:
|
||||
return self._graph.is_valid()
|
||||
|
||||
def is_deleted(self) -> bool:
|
||||
return (
|
||||
not self._graph.nx.has_edge(*self._edge)
|
||||
and self._edge[EdgeConstants.I_KEY.value] <= self._graph.highest_edge_id
|
||||
)
|
||||
|
||||
def underlying_graph_is_mutable(self) -> bool:
|
||||
return not nx.is_frozen(self._graph.nx)
|
||||
|
||||
@property
|
||||
def id(self) -> int:
|
||||
return self._edge[EdgeConstants.I_KEY.value]
|
||||
|
||||
@property
|
||||
def edge(self) -> typing.Tuple[int, int, int]:
|
||||
return self._edge
|
||||
|
||||
@property
|
||||
def start_id(self) -> int:
|
||||
return self._edge[EdgeConstants.I_START.value]
|
||||
|
||||
@property
|
||||
def end_id(self) -> int:
|
||||
return self._edge[EdgeConstants.I_END.value]
|
||||
|
||||
def get_type_name(self):
|
||||
return self._graph.nx.get_edge_data(*self._edge)[NX_TYPE_ATTR]
|
||||
|
||||
def from_vertex(self) -> Vertex:
|
||||
return Vertex(self.start_id, self._graph)
|
||||
|
||||
def to_vertex(self) -> Vertex:
|
||||
return Vertex(self.end_id, self._graph)
|
||||
|
||||
@property
|
||||
def properties(self):
|
||||
return (
|
||||
(key, value)
|
||||
for key, value in self._graph.nx.edges[self._edge].items()
|
||||
if key not in (NX_LABEL_ATTR, NX_TYPE_ATTR)
|
||||
)
|
||||
|
||||
def get_property(self, property_name: str):
|
||||
return self._graph.nx.edges[self._edge][property_name]
|
||||
|
||||
def set_property(self, property_name: str, value: object):
|
||||
self._graph.nx.edges[self._edge][property_name] = value
|
||||
|
||||
|
||||
class Path:
|
||||
"""Represents a path comprised of `Vertex` and `Edge` instances."""
|
||||
|
||||
__slots__ = ("_vertices", "_edges", "_graph")
|
||||
__create_key = object()
|
||||
|
||||
def __init__(self, create_key, vertex_id: int, graph: Graph) -> None:
|
||||
assert create_key == Path.__create_key, "Path objects must be created using Path.make_with_start"
|
||||
|
||||
self._vertices = [vertex_id]
|
||||
self._edges = []
|
||||
self._graph = graph
|
||||
|
||||
@classmethod
|
||||
def make_with_start(cls, vertex: Vertex) -> "Path":
|
||||
if not isinstance(vertex, Vertex):
|
||||
raise TypeError(f"Expected 'Vertex', got '{type(vertex)}'")
|
||||
|
||||
if not isinstance(vertex.underlying_graph, Graph):
|
||||
raise TypeError(f"Expected '_mgp_mock.Graph', got '{type(vertex.underlying_graph)}'")
|
||||
|
||||
if not vertex.underlying_graph.nx.has_node(vertex._id):
|
||||
raise IndexError(f"Unable to find vertex with ID {vertex._id}.")
|
||||
|
||||
return Path(cls.__create_key, vertex._id, vertex.underlying_graph)
|
||||
|
||||
def is_valid(self) -> bool:
|
||||
return self._graph.is_valid()
|
||||
|
||||
def underlying_graph_is_mutable(self) -> bool:
|
||||
return not nx.is_frozen(self._graph.nx)
|
||||
|
||||
def expand(self, edge: Edge):
|
||||
if edge.start_id != self._vertices[-1]:
|
||||
raise LogicErrorError("Logic error.")
|
||||
|
||||
self._vertices.append(edge.end_id)
|
||||
self._edges.append((edge.start_id, edge.end_id, edge.id))
|
||||
|
||||
def vertex_at(self, index: int) -> Vertex:
|
||||
return Vertex(self._vertices[index], self._graph)
|
||||
|
||||
def edge_at(self, index: int) -> Edge:
|
||||
return Edge(self._edges[index], self._graph)
|
||||
|
||||
def size(self) -> int:
|
||||
return len(self._edges)
|
1655
include/mgp_mock.py
Normal file
1655
include/mgp_mock.py
Normal file
File diff suppressed because it is too large
Load Diff
@ -106,6 +106,10 @@ install(PROGRAMS $<TARGET_FILE:memgraph>
|
||||
# Install Python source for supporting our embedded Python.
|
||||
install(FILES ${CMAKE_SOURCE_DIR}/include/mgp.py
|
||||
DESTINATION lib/memgraph/python_support)
|
||||
install(FILES ${CMAKE_SOURCE_DIR}/include/mgp_mock.py
|
||||
DESTINATION lib/memgraph/python_support)
|
||||
install(FILES ${CMAKE_SOURCE_DIR}/include/_mgp_mock.py
|
||||
DESTINATION lib/memgraph/python_support)
|
||||
|
||||
# Install the includes file for writing custom procedures in C and C++>
|
||||
install(FILES ${CMAKE_SOURCE_DIR}/include/mg_procedure.h
|
||||
|
@ -44,6 +44,7 @@ add_subdirectory(module_file_manager)
|
||||
add_subdirectory(monitoring_server)
|
||||
add_subdirectory(lba_procedures)
|
||||
add_subdirectory(python_query_modules_reloading)
|
||||
add_subdirectory(mock_api)
|
||||
|
||||
copy_e2e_python_files(pytest_runner pytest_runner.sh "")
|
||||
file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/memgraph-selfsigned.crt DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
8
tests/e2e/mock_api/CMakeLists.txt
Normal file
8
tests/e2e/mock_api/CMakeLists.txt
Normal file
@ -0,0 +1,8 @@
|
||||
function(copy_mock_python_api_e2e_files FILE_NAME)
|
||||
copy_e2e_python_files(mock_python_api ${FILE_NAME})
|
||||
endfunction()
|
||||
|
||||
add_subdirectory(procedures)
|
||||
|
||||
copy_mock_python_api_e2e_files(common.py)
|
||||
copy_mock_python_api_e2e_files(test_compare_mock.py)
|
14
tests/e2e/mock_api/common.py
Normal file
14
tests/e2e/mock_api/common.py
Normal file
@ -0,0 +1,14 @@
|
||||
import typing
|
||||
|
||||
import mgclient
|
||||
|
||||
|
||||
def connect(**kwargs) -> mgclient.Connection:
|
||||
connection = mgclient.connect(host="localhost", port=7687, **kwargs)
|
||||
connection.autocommit = True
|
||||
return connection
|
||||
|
||||
|
||||
def execute_and_fetch_results_dict(cursor, query) -> typing.Dict:
|
||||
cursor.execute(query)
|
||||
return cursor.fetchall()[0][0]
|
10
tests/e2e/mock_api/procedures/CMakeLists.txt
Normal file
10
tests/e2e/mock_api/procedures/CMakeLists.txt
Normal file
@ -0,0 +1,10 @@
|
||||
copy_mock_python_api_e2e_files(test_utils.py)
|
||||
copy_mock_python_api_e2e_files(edge_type.py)
|
||||
copy_mock_python_api_e2e_files(edge.py)
|
||||
copy_mock_python_api_e2e_files(graph.py)
|
||||
copy_mock_python_api_e2e_files(label.py)
|
||||
copy_mock_python_api_e2e_files(path.py)
|
||||
copy_mock_python_api_e2e_files(properties.py)
|
||||
copy_mock_python_api_e2e_files(record.py)
|
||||
copy_mock_python_api_e2e_files(vertex.py)
|
||||
copy_mock_python_api_e2e_files(vertices.py)
|
85
tests/e2e/mock_api/procedures/edge.py
Normal file
85
tests/e2e/mock_api/procedures/edge.py
Normal file
@ -0,0 +1,85 @@
|
||||
import mgp
|
||||
import mgp_mock
|
||||
import test_utils
|
||||
|
||||
|
||||
@mgp.read_proc
|
||||
def compare_apis(ctx: mgp.ProcCtx) -> mgp.Record(results_dict=mgp.Map):
|
||||
mock_ctx = test_utils.get_mock_proc_ctx(is_write=False)
|
||||
results = dict()
|
||||
|
||||
TARGET_EDGE_1_ID = 9
|
||||
TARGET_EDGE_2_ID = 37
|
||||
|
||||
target_edge_1 = test_utils.get_edge(ctx, permanent_id=TARGET_EDGE_1_ID)
|
||||
target_edge_2 = test_utils.get_edge(ctx, permanent_id=TARGET_EDGE_2_ID)
|
||||
target_mock_edge_1 = test_utils.get_mock_edge(mock_ctx, id=TARGET_EDGE_1_ID)
|
||||
target_mock_edge_2 = test_utils.get_mock_edge(mock_ctx, id=TARGET_EDGE_2_ID)
|
||||
|
||||
results["is_valid"] = test_utils.all_equal(
|
||||
target_edge_1.is_valid(),
|
||||
target_mock_edge_1.is_valid(),
|
||||
True,
|
||||
)
|
||||
|
||||
results["underlying_graph_is_mutable"] = test_utils.all_equal(
|
||||
target_edge_1.underlying_graph_is_mutable(),
|
||||
target_mock_edge_1.underlying_graph_is_mutable(),
|
||||
False,
|
||||
)
|
||||
|
||||
results["id"] = test_utils.all_equal(
|
||||
isinstance(target_edge_1.id, int),
|
||||
isinstance(target_mock_edge_1.id, int),
|
||||
True,
|
||||
)
|
||||
|
||||
results["type"] = test_utils.all_equal(
|
||||
target_edge_1.type.name,
|
||||
target_mock_edge_1.type.name,
|
||||
"HAS_TEAM",
|
||||
)
|
||||
|
||||
results["from_vertex"] = test_utils.all_equal(
|
||||
isinstance(target_edge_1.from_vertex, mgp.Vertex),
|
||||
isinstance(target_mock_edge_1.from_vertex, mgp_mock.Vertex),
|
||||
True,
|
||||
)
|
||||
|
||||
results["to_vertex"] = test_utils.all_equal(
|
||||
isinstance(target_edge_1.to_vertex, mgp.Vertex),
|
||||
isinstance(target_mock_edge_1.to_vertex, mgp_mock.Vertex),
|
||||
True,
|
||||
)
|
||||
|
||||
results["properties"] = test_utils.all_equal(
|
||||
isinstance(target_edge_1.properties, mgp.Properties),
|
||||
isinstance(target_mock_edge_1.properties, mgp_mock.Properties),
|
||||
True,
|
||||
) and test_utils.all_equal(
|
||||
{prop.name: prop.value for prop in target_edge_1.properties.items()},
|
||||
{prop.name: prop.value for prop in target_mock_edge_1.properties.items()},
|
||||
{"permanent_id": 9},
|
||||
)
|
||||
|
||||
results["__eq__"] = test_utils.all_equal(
|
||||
target_edge_1 == target_edge_1,
|
||||
target_mock_edge_1 == target_mock_edge_1,
|
||||
True,
|
||||
) and test_utils.all_equal(
|
||||
target_edge_1 != target_edge_1,
|
||||
target_mock_edge_1 != target_mock_edge_1,
|
||||
False,
|
||||
)
|
||||
|
||||
results["__ne__"] = test_utils.all_equal(
|
||||
target_edge_1 != target_edge_2,
|
||||
target_mock_edge_1 != target_mock_edge_2,
|
||||
True,
|
||||
) and test_utils.all_equal(
|
||||
target_edge_1 == target_edge_2,
|
||||
target_mock_edge_1 == target_mock_edge_2,
|
||||
False,
|
||||
)
|
||||
|
||||
return mgp.Record(results_dict=results)
|
33
tests/e2e/mock_api/procedures/edge_type.py
Normal file
33
tests/e2e/mock_api/procedures/edge_type.py
Normal file
@ -0,0 +1,33 @@
|
||||
import mgp
|
||||
import test_utils
|
||||
|
||||
|
||||
@mgp.read_proc
|
||||
def compare_apis(ctx: mgp.ProcCtx) -> mgp.Record(results_dict=mgp.Map):
|
||||
mock_ctx = test_utils.get_mock_proc_ctx(is_write=False)
|
||||
results = dict()
|
||||
|
||||
TARGET_EDGE_ID = 0
|
||||
|
||||
target_edge_type = test_utils.get_edge(ctx, permanent_id=TARGET_EDGE_ID).type
|
||||
target_mock_edge_type = test_utils.get_mock_edge(mock_ctx, id=TARGET_EDGE_ID).type
|
||||
|
||||
results["name"] = test_utils.all_equal(
|
||||
target_edge_type.name,
|
||||
target_mock_edge_type.name,
|
||||
"IS_PART_OF",
|
||||
)
|
||||
|
||||
results["__eq__"] = test_utils.all_equal(
|
||||
target_edge_type == target_edge_type,
|
||||
target_edge_type == "IS_PART_OF",
|
||||
target_mock_edge_type == target_mock_edge_type,
|
||||
target_mock_edge_type == "IS_PART_OF",
|
||||
)
|
||||
|
||||
results["__ne__"] = test_utils.all_equal(
|
||||
target_edge_type != "HAS_TEAM",
|
||||
target_mock_edge_type != "HAS_TEAM",
|
||||
)
|
||||
|
||||
return mgp.Record(results_dict=results)
|
102
tests/e2e/mock_api/procedures/graph.py
Normal file
102
tests/e2e/mock_api/procedures/graph.py
Normal file
@ -0,0 +1,102 @@
|
||||
import mgp
|
||||
import mgp_mock
|
||||
import test_utils
|
||||
|
||||
|
||||
@mgp.write_proc
|
||||
def compare_apis(ctx: mgp.ProcCtx) -> mgp.Record(results_dict=mgp.Map):
|
||||
VERTEX_ID = 6
|
||||
|
||||
mock_ctx = test_utils.get_mock_proc_ctx(is_write=True)
|
||||
results = dict()
|
||||
|
||||
results["is_valid"] = test_utils.all_equal(
|
||||
ctx.graph.is_valid(),
|
||||
mock_ctx.graph.is_valid(),
|
||||
True,
|
||||
)
|
||||
|
||||
results["get_vertex_by_id"] = test_utils.all_equal(
|
||||
test_utils.get_vertex(ctx, permanent_id=VERTEX_ID).properties["permanent_id"],
|
||||
mock_ctx.graph.get_vertex_by_id(VERTEX_ID).properties["permanent_id"],
|
||||
VERTEX_ID,
|
||||
)
|
||||
|
||||
results["vertices"] = test_utils.all_equal(
|
||||
len(ctx.graph.vertices),
|
||||
len(mock_ctx.graph.vertices),
|
||||
27,
|
||||
)
|
||||
|
||||
results["is_mutable"] = test_utils.all_equal(
|
||||
ctx.graph.is_mutable(),
|
||||
mock_ctx.graph.is_mutable(),
|
||||
True,
|
||||
)
|
||||
|
||||
new_mock_vertex = mock_ctx.graph.create_vertex()
|
||||
new_mock_vertex_id = new_mock_vertex.id
|
||||
results["create_vertex"] = test_utils.all_equal(
|
||||
new_mock_vertex_id in [v.id for v in mock_ctx.graph.vertices],
|
||||
True,
|
||||
)
|
||||
|
||||
mock_ctx.graph.delete_vertex(new_mock_vertex)
|
||||
results["delete_vertex"] = test_utils.all_equal(
|
||||
new_mock_vertex_id not in [v.id for v in mock_ctx.graph.vertices],
|
||||
True,
|
||||
)
|
||||
|
||||
mock_vertex_to_delete = mock_ctx.graph.get_vertex_by_id(VERTEX_ID)
|
||||
mock_ctx.graph.detach_delete_vertex(mock_vertex_to_delete)
|
||||
results["detach_delete_vertex"] = test_utils.all_equal(
|
||||
VERTEX_ID not in [v.properties["permanent_id"] for v in mock_ctx.graph.vertices],
|
||||
True,
|
||||
)
|
||||
|
||||
MAX_EDGE_ID = 37
|
||||
|
||||
START_ID = 10
|
||||
END1_ID = 13
|
||||
END2_ID = 14
|
||||
start_mock_vertex, end1_mock_vertex, end2_mock_vertex = (
|
||||
mock_ctx.graph.get_vertex_by_id(START_ID),
|
||||
mock_ctx.graph.get_vertex_by_id(END1_ID),
|
||||
mock_ctx.graph.get_vertex_by_id(END2_ID),
|
||||
)
|
||||
EDGE_TYPE = "CONNECTED_TO"
|
||||
mock_edge_type = mgp_mock.EdgeType(EDGE_TYPE)
|
||||
new_mock_edge = mock_ctx.graph.create_edge(start_mock_vertex, end1_mock_vertex, mock_edge_type)
|
||||
new_mock_edge_id = new_mock_edge.id
|
||||
results["create_edge"] = test_utils.all_equal(
|
||||
new_mock_edge_id,
|
||||
MAX_EDGE_ID + 1,
|
||||
)
|
||||
|
||||
mock_ctx.graph.delete_edge(new_mock_edge)
|
||||
results["delete_edge"] = test_utils.all_equal(
|
||||
new_mock_edge_id not in [e.id for e in start_mock_vertex.out_edges],
|
||||
True,
|
||||
)
|
||||
|
||||
another_mock_edge = mock_ctx.graph.create_edge(start_mock_vertex, end2_mock_vertex, mock_edge_type)
|
||||
results["edge_id_assignment"] = test_utils.all_equal(
|
||||
another_mock_edge.id,
|
||||
MAX_EDGE_ID + 2,
|
||||
)
|
||||
|
||||
return mgp.Record(results_dict=results)
|
||||
|
||||
|
||||
@mgp.read_proc
|
||||
def test_read_proc_mutability(ctx: mgp.ProcCtx) -> mgp.Record(results_dict=mgp.Map):
|
||||
mock_ctx = test_utils.get_mock_proc_ctx(is_write=False)
|
||||
results = dict()
|
||||
|
||||
results["is_not_mutable"] = test_utils.all_equal(
|
||||
ctx.graph.is_mutable(),
|
||||
mock_ctx.graph.is_mutable(),
|
||||
False,
|
||||
)
|
||||
|
||||
return mgp.Record(results_dict=results)
|
52
tests/e2e/mock_api/procedures/label.py
Normal file
52
tests/e2e/mock_api/procedures/label.py
Normal file
@ -0,0 +1,52 @@
|
||||
import mgp
|
||||
import test_utils
|
||||
|
||||
|
||||
@mgp.read_proc
|
||||
def compare_apis(ctx: mgp.ProcCtx) -> mgp.Record(results_dict=mgp.Map):
|
||||
mock_ctx = test_utils.get_mock_proc_ctx(is_write=False)
|
||||
results = dict()
|
||||
|
||||
TARGET_LABELLED_NODE_ID = 5
|
||||
|
||||
target_vertex = test_utils.get_vertex(ctx, permanent_id=TARGET_LABELLED_NODE_ID)
|
||||
target_mock_vertex = mock_ctx.graph.get_vertex_by_id(TARGET_LABELLED_NODE_ID)
|
||||
|
||||
label_1, label_2 = sorted(target_vertex.labels, key=lambda l: l.name) # ("Company", "Startup")
|
||||
mock_label_1, mock_label_2 = sorted(target_mock_vertex.labels, key=lambda l: l.name) # ditto
|
||||
|
||||
results["name"] = test_utils.all_equal(
|
||||
(label_1.name, label_2.name),
|
||||
(mock_label_1.name, mock_label_2.name),
|
||||
("Company", "Startup"),
|
||||
)
|
||||
|
||||
results["__eq__"] = test_utils.all_equal(
|
||||
label_1 == label_1,
|
||||
label_1 == "Company",
|
||||
mock_label_1 == mock_label_1,
|
||||
mock_label_1 == "Company",
|
||||
True,
|
||||
) and test_utils.all_equal(
|
||||
label_1 == label_2,
|
||||
label_1 == "Startup",
|
||||
mock_label_1 == mock_label_2,
|
||||
mock_label_1 == "Startup",
|
||||
False,
|
||||
)
|
||||
|
||||
results["__ne__"] = test_utils.all_equal(
|
||||
label_1 != label_2,
|
||||
label_1 != "Startup",
|
||||
mock_label_1 != mock_label_2,
|
||||
mock_label_1 != "Startup",
|
||||
True,
|
||||
) and test_utils.all_equal(
|
||||
label_1 != label_1,
|
||||
label_1 != "Company",
|
||||
mock_label_1 != mock_label_1,
|
||||
mock_label_1 != "Company",
|
||||
False,
|
||||
)
|
||||
|
||||
return mgp.Record(results_dict=results)
|
65
tests/e2e/mock_api/procedures/path.py
Normal file
65
tests/e2e/mock_api/procedures/path.py
Normal file
@ -0,0 +1,65 @@
|
||||
import copy
|
||||
|
||||
import mgp
|
||||
import mgp_mock
|
||||
import test_utils
|
||||
|
||||
|
||||
@mgp.read_proc
|
||||
def compare_apis(ctx: mgp.ProcCtx) -> mgp.Record(results_dict=mgp.Map):
|
||||
mock_ctx = test_utils.get_mock_proc_ctx(is_write=False)
|
||||
results = dict()
|
||||
|
||||
START_ID = 0
|
||||
start_vertex = test_utils.get_vertex(ctx, permanent_id=START_ID)
|
||||
mock_start_vertex = mock_ctx.graph.get_vertex_by_id(START_ID)
|
||||
path = mgp.Path(start_vertex)
|
||||
mock_path = mgp_mock.Path(mock_start_vertex)
|
||||
|
||||
results["is_valid"] = test_utils.all_equal(
|
||||
path.is_valid(),
|
||||
mock_path.is_valid(),
|
||||
True,
|
||||
)
|
||||
|
||||
EDGE_ID = 0
|
||||
edge_to_add = test_utils.get_edge(ctx, permanent_id=EDGE_ID)
|
||||
mock_edge_to_add = test_utils.get_mock_edge(mock_ctx, id=EDGE_ID)
|
||||
path.expand(edge_to_add)
|
||||
mock_path.expand(mock_edge_to_add)
|
||||
results["expand"] = test_utils.all_equal(
|
||||
(len(path.vertices), len(path.edges)),
|
||||
(len(mock_path.vertices), len(mock_path.edges)),
|
||||
(2, 1),
|
||||
)
|
||||
|
||||
NEXT_ID = 1
|
||||
results["vertices"] = test_utils.all_equal(
|
||||
all(isinstance(vertex, mgp.Vertex) for vertex in path.vertices),
|
||||
all(isinstance(vertex, mgp_mock.Vertex) for vertex in mock_path.vertices),
|
||||
True,
|
||||
) and test_utils.all_equal(
|
||||
[vertex.properties["permanent_id"] for vertex in path.vertices],
|
||||
[vertex.properties["permanent_id"] for vertex in mock_path.vertices],
|
||||
[START_ID, NEXT_ID],
|
||||
)
|
||||
|
||||
results["edges"] = test_utils.all_equal(
|
||||
all(isinstance(edge, mgp.Edge) for edge in path.edges),
|
||||
all(isinstance(edge, mgp_mock.Edge) for edge in mock_path.edges),
|
||||
True,
|
||||
) and test_utils.all_equal(
|
||||
[edge.properties["permanent_id"] for edge in path.edges],
|
||||
[edge.properties["permanent_id"] for edge in mock_path.edges],
|
||||
[0],
|
||||
)
|
||||
|
||||
path_copy = copy.copy(path)
|
||||
mock_path_copy = copy.copy(mock_path)
|
||||
results["__copy__"] = test_utils.all_equal(
|
||||
path_copy.is_valid(),
|
||||
mock_path_copy.is_valid(),
|
||||
True,
|
||||
)
|
||||
|
||||
return mgp.Record(results_dict=results)
|
184
tests/e2e/mock_api/procedures/properties.py
Normal file
184
tests/e2e/mock_api/procedures/properties.py
Normal file
@ -0,0 +1,184 @@
|
||||
import mgp
|
||||
import test_utils
|
||||
|
||||
|
||||
@mgp.write_proc
|
||||
def compare_apis_on_vertex(ctx: mgp.ProcCtx) -> mgp.Record(results_dict=mgp.Map):
|
||||
mock_ctx = test_utils.get_mock_proc_ctx(is_write=True)
|
||||
results = dict()
|
||||
|
||||
TARGET_ID = 0
|
||||
target_vertex = test_utils.get_vertex(ctx, permanent_id=TARGET_ID)
|
||||
target_mock_vertex = mock_ctx.graph.get_vertex_by_id(TARGET_ID)
|
||||
|
||||
properties = target_vertex.properties
|
||||
mock_properties = target_mock_vertex.properties
|
||||
|
||||
results["get"] = test_utils.all_equal(
|
||||
properties.get("name"),
|
||||
mock_properties.get("name"),
|
||||
"Peter",
|
||||
)
|
||||
results["get[default]"] = test_utils.all_equal(
|
||||
properties.get("YoE", default="N/A"),
|
||||
mock_properties.get("YoE", default="N/A"),
|
||||
"N/A",
|
||||
)
|
||||
|
||||
properties.set("education", "PhD")
|
||||
mock_properties.set("education", "PhD")
|
||||
results["set"] = test_utils.all_equal(
|
||||
properties.get("education"),
|
||||
mock_properties.get("education"),
|
||||
"PhD",
|
||||
)
|
||||
|
||||
results["items"] = test_utils.all_equal(
|
||||
{prop.name: prop.value for prop in properties.items()},
|
||||
{prop.name: prop.value for prop in mock_properties.items()},
|
||||
{"name": "Peter", "surname": "Yang", "education": "PhD", "permanent_id": 0},
|
||||
)
|
||||
|
||||
results["keys"] = test_utils.all_equal(
|
||||
{key for key in properties.keys()},
|
||||
{key for key in mock_properties.keys()},
|
||||
{"name", "surname", "education", "permanent_id"},
|
||||
)
|
||||
|
||||
results["values"] = test_utils.all_equal(
|
||||
{val for val in properties.values()},
|
||||
{val for val in mock_properties.values()},
|
||||
{"Peter", "Yang", "PhD", 0},
|
||||
)
|
||||
|
||||
results["__len__"] = test_utils.all_equal(
|
||||
len(properties),
|
||||
len(mock_properties),
|
||||
4,
|
||||
)
|
||||
|
||||
results["__iter__"] = test_utils.all_equal(
|
||||
{name for name in properties},
|
||||
{name for name in mock_properties},
|
||||
{"name", "surname", "education", "permanent_id"},
|
||||
)
|
||||
|
||||
results["__getitem__"] = test_utils.all_equal(
|
||||
{properties[name] for name in properties},
|
||||
{mock_properties[name] for name in mock_properties},
|
||||
{"Peter", "Yang", "PhD", 0},
|
||||
)
|
||||
|
||||
properties["YoE"] = 6
|
||||
mock_properties["YoE"] = 6
|
||||
results["__setitem__"] = test_utils.all_equal(
|
||||
properties["YoE"],
|
||||
mock_properties["YoE"],
|
||||
6,
|
||||
)
|
||||
|
||||
results["__contains__"] = test_utils.all_equal(
|
||||
"YoE" in properties,
|
||||
"age" not in properties,
|
||||
"YoE" in mock_properties,
|
||||
"age" not in mock_properties,
|
||||
True,
|
||||
) and test_utils.all_equal(
|
||||
"YoE" not in properties,
|
||||
"age" in properties,
|
||||
"YoE" not in mock_properties,
|
||||
"age" in mock_properties,
|
||||
False,
|
||||
)
|
||||
|
||||
return mgp.Record(results_dict=results)
|
||||
|
||||
|
||||
@mgp.write_proc
|
||||
def compare_apis_on_edge(ctx: mgp.ProcCtx) -> mgp.Record(results_dict=mgp.Map):
|
||||
mock_ctx = test_utils.get_mock_proc_ctx(is_write=True)
|
||||
results = dict()
|
||||
|
||||
TARGET_EDGE_ID = 37
|
||||
|
||||
target_edge_properties = test_utils.get_edge(ctx, permanent_id=TARGET_EDGE_ID).properties
|
||||
target_mock_edge_properties = test_utils.get_mock_edge(mock_ctx, id=TARGET_EDGE_ID).properties
|
||||
|
||||
results["get"] = test_utils.all_equal(
|
||||
target_edge_properties.get("importance"),
|
||||
target_mock_edge_properties.get("importance"),
|
||||
"HIGH",
|
||||
)
|
||||
results["get[default]"] = test_utils.all_equal(
|
||||
target_edge_properties.get("priority", default="N/A"),
|
||||
target_mock_edge_properties.get("priority", default="N/A"),
|
||||
"N/A",
|
||||
)
|
||||
|
||||
target_edge_properties.set("priority", "MEDIUM")
|
||||
target_mock_edge_properties.set("priority", "MEDIUM")
|
||||
results["set"] = test_utils.all_equal(
|
||||
target_edge_properties.get("priority"),
|
||||
target_mock_edge_properties.get("priority"),
|
||||
"MEDIUM",
|
||||
)
|
||||
|
||||
results["items"] = test_utils.all_equal(
|
||||
{prop.name: prop.value for prop in target_edge_properties.items()},
|
||||
{prop.name: prop.value for prop in target_mock_edge_properties.items()},
|
||||
{"importance": "HIGH", "priority": "MEDIUM", "permanent_id": 37},
|
||||
)
|
||||
|
||||
results["keys"] = test_utils.all_equal(
|
||||
{key for key in target_edge_properties.keys()},
|
||||
{key for key in target_mock_edge_properties.keys()},
|
||||
{"importance", "priority", "permanent_id"},
|
||||
)
|
||||
|
||||
results["values"] = test_utils.all_equal(
|
||||
{val for val in target_edge_properties.values()},
|
||||
{val for val in target_mock_edge_properties.values()},
|
||||
{"HIGH", "MEDIUM", 37},
|
||||
)
|
||||
|
||||
results["__len__"] = test_utils.all_equal(
|
||||
len(target_edge_properties),
|
||||
len(target_mock_edge_properties),
|
||||
3,
|
||||
)
|
||||
|
||||
results["__iter__"] = test_utils.all_equal(
|
||||
{name for name in target_edge_properties},
|
||||
{name for name in target_mock_edge_properties},
|
||||
{"importance", "priority", "permanent_id"},
|
||||
)
|
||||
|
||||
results["__getitem__"] = test_utils.all_equal(
|
||||
{target_edge_properties[name] for name in target_edge_properties},
|
||||
{target_mock_edge_properties[name] for name in target_mock_edge_properties},
|
||||
{"HIGH", "MEDIUM", 37},
|
||||
)
|
||||
|
||||
target_edge_properties["priority"] = "LOW"
|
||||
target_mock_edge_properties["priority"] = "LOW"
|
||||
results["__setitem__"] = test_utils.all_equal(
|
||||
target_edge_properties["priority"],
|
||||
target_mock_edge_properties["priority"],
|
||||
"LOW",
|
||||
)
|
||||
|
||||
results["__contains__"] = test_utils.all_equal(
|
||||
"priority" in target_edge_properties,
|
||||
"status" not in target_edge_properties,
|
||||
"priority" in target_mock_edge_properties,
|
||||
"status" not in target_mock_edge_properties,
|
||||
True,
|
||||
) and test_utils.all_equal(
|
||||
"priority" not in target_edge_properties,
|
||||
"status" in target_edge_properties,
|
||||
"priority" not in target_mock_edge_properties,
|
||||
"status" in target_mock_edge_properties,
|
||||
False,
|
||||
)
|
||||
|
||||
return mgp.Record(results_dict=results)
|
18
tests/e2e/mock_api/procedures/record.py
Normal file
18
tests/e2e/mock_api/procedures/record.py
Normal file
@ -0,0 +1,18 @@
|
||||
import mgp
|
||||
import mgp_mock
|
||||
import test_utils
|
||||
|
||||
|
||||
@mgp.read_proc
|
||||
def compare_apis(ctx: mgp.ProcCtx) -> mgp.Record(results_dict=mgp.Map):
|
||||
results = dict()
|
||||
|
||||
record = mgp.Record(a=1, b=2.0, c="3")
|
||||
mock_record = mgp_mock.Record(a=1, b=2.0, c="3")
|
||||
|
||||
results["fields"] = test_utils.all_equal(
|
||||
record.fields,
|
||||
mock_record.fields,
|
||||
)
|
||||
|
||||
return mgp.Record(results_dict=results)
|
160
tests/e2e/mock_api/procedures/test_utils.py
Normal file
160
tests/e2e/mock_api/procedures/test_utils.py
Normal file
@ -0,0 +1,160 @@
|
||||
from itertools import groupby
|
||||
|
||||
import _mgp_mock
|
||||
import mgp
|
||||
import mgp_mock
|
||||
import networkx as nx
|
||||
|
||||
|
||||
def all_equal(*args):
|
||||
"""Returns True if all the elements are equal to each other
|
||||
(source: https://docs.python.org/3/library/itertools.html#itertools-recipes)"""
|
||||
g = groupby(args)
|
||||
return next(g, True) and not next(g, False)
|
||||
|
||||
|
||||
def get_mock_proc_ctx(is_write: bool) -> mgp_mock.ProcCtx:
|
||||
GRAPH_DATA = [
|
||||
(0, 1, 0),
|
||||
(5, 1, 9),
|
||||
(5, 1, 37),
|
||||
(10, 1, 15),
|
||||
(1, 2, 4),
|
||||
(1, 3, 5),
|
||||
(1, 4, 6),
|
||||
(0, 5, 1),
|
||||
(10, 5, 16),
|
||||
(22, 5, 33),
|
||||
(1, 6, 7),
|
||||
(6, 7, 12),
|
||||
(11, 7, 18),
|
||||
(13, 7, 26),
|
||||
(26, 7, 35),
|
||||
(6, 8, 13),
|
||||
(26, 8, 36),
|
||||
(0, 9, 2),
|
||||
(10, 9, 17),
|
||||
(22, 9, 34),
|
||||
(1, 11, 8),
|
||||
(9, 12, 14),
|
||||
(14, 13, 27),
|
||||
(0, 14, 3),
|
||||
(5, 14, 11),
|
||||
(12, 14, 22),
|
||||
(13, 15, 23),
|
||||
(13, 16, 24),
|
||||
(13, 17, 25),
|
||||
(11, 18, 19),
|
||||
(11, 19, 20),
|
||||
(11, 20, 21),
|
||||
(5, 21, 10),
|
||||
(22, 21, 32),
|
||||
(21, 23, 28),
|
||||
(21, 24, 29),
|
||||
(21, 25, 30),
|
||||
(21, 26, 31),
|
||||
]
|
||||
NODE_INFO = {
|
||||
0: {"labels": "Person", "name": "Peter", "surname": "Yang", "permanent_id": 0},
|
||||
1: {"labels": "Team", "name": "Engineering", "permanent_id": 1},
|
||||
2: {"labels": "Repository", "name": "Memgraph", "permanent_id": 2},
|
||||
3: {"labels": "Repository", "name": "MAGE", "permanent_id": 3},
|
||||
4: {"labels": "Repository", "name": "GQLAlchemy", "permanent_id": 4},
|
||||
5: {"labels": "Company:Startup", "name": "Memgraph", "permanent_id": 5},
|
||||
6: {"labels": "File", "name": "welcome_to_engineering.txt", "permanent_id": 6},
|
||||
7: {"labels": "Storage", "name": "Google Drive", "permanent_id": 7},
|
||||
8: {"labels": "Storage", "name": "Notion", "permanent_id": 8},
|
||||
9: {"labels": "File", "name": "welcome_to_memgraph.txt", "permanent_id": 9},
|
||||
10: {"labels": "Person", "name": "Carl", "permanent_id": 10},
|
||||
11: {"labels": "Folder", "name": "engineering_folder", "permanent_id": 11},
|
||||
12: {"labels": "Person", "name": "Anna", "permanent_id": 12},
|
||||
13: {"labels": "Folder", "name": "operations_folder", "permanent_id": 13},
|
||||
14: {"labels": "Team", "name": "Operations", "permanent_id": 14},
|
||||
15: {"labels": "File", "name": "operations101.txt", "permanent_id": 15},
|
||||
16: {"labels": "File", "name": "expenses2022.csv", "permanent_id": 16},
|
||||
17: {"labels": "File", "name": "salaries2022.csv", "permanent_id": 17},
|
||||
18: {"labels": "File", "name": "engineering101.txt", "permanent_id": 18},
|
||||
19: {"labels": "File", "name": "working_with_github.txt", "permanent_id": 19},
|
||||
20: {"labels": "File", "name": "working_with_notion.txt", "permanent_id": 20},
|
||||
21: {"labels": "Team", "name": "Marketing", "permanent_id": 21},
|
||||
22: {"labels": "Person", "name": "Julie", "permanent_id": 22},
|
||||
23: {"labels": "Account", "name": "Facebook", "permanent_id": 23},
|
||||
24: {"labels": "Account", "name": "LinkedIn", "permanent_id": 24},
|
||||
25: {"labels": "Account", "name": "HackerNews", "permanent_id": 25},
|
||||
26: {"labels": "File", "name": "welcome_to_marketing.txt", "permanent_id": 26},
|
||||
}
|
||||
EDGE_INFO = {
|
||||
(0, 1, 0): {"type": "IS_PART_OF", "permanent_id": 0},
|
||||
(0, 5, 1): {"type": "IS_PART_OF", "permanent_id": 1},
|
||||
(0, 9, 2): {"type": "HAS_ACCESS_TO", "permanent_id": 2},
|
||||
(0, 14, 3): {"type": "IS_PART_OF", "permanent_id": 3},
|
||||
(1, 2, 4): {"type": "HAS_ACCESS_TO", "permanent_id": 4},
|
||||
(1, 3, 5): {"type": "HAS_ACCESS_TO", "permanent_id": 5},
|
||||
(1, 4, 6): {"type": "HAS_ACCESS_TO", "permanent_id": 6},
|
||||
(1, 6, 7): {"type": "HAS_ACCESS_TO", "permanent_id": 7},
|
||||
(1, 11, 8): {"type": "HAS_ACCESS_TO", "permanent_id": 8},
|
||||
(5, 1, 9): {"type": "HAS_TEAM", "permanent_id": 9},
|
||||
(5, 1, 37): {"type": "HAS_TEAM_2", "importance": "HIGH", "permanent_id": 37},
|
||||
(5, 14, 11): {"type": "HAS_TEAM", "permanent_id": 11},
|
||||
(5, 21, 10): {"type": "HAS_TEAM", "permanent_id": 10},
|
||||
(6, 7, 12): {"type": "IS_STORED_IN", "permanent_id": 12},
|
||||
(6, 8, 13): {"type": "IS_STORED_IN", "permanent_id": 13},
|
||||
(9, 12, 14): {"type": "CREATED_BY", "permanent_id": 14},
|
||||
(10, 1, 15): {"type": "IS_PART_OF", "permanent_id": 15},
|
||||
(10, 5, 16): {"type": "IS_PART_OF", "permanent_id": 16},
|
||||
(10, 9, 17): {"type": "HAS_ACCESS_TO", "permanent_id": 17},
|
||||
(11, 7, 18): {"type": "IS_STORED_IN", "permanent_id": 18},
|
||||
(11, 18, 19): {"type": "HAS_ACCESS_TO", "permanent_id": 19},
|
||||
(11, 19, 20): {"type": "HAS_ACCESS_TO", "permanent_id": 20},
|
||||
(11, 20, 21): {"type": "HAS_ACCESS_TO", "permanent_id": 21},
|
||||
(12, 14, 22): {"type": "IS_PART_OF", "permanent_id": 22},
|
||||
(13, 7, 26): {"type": "IS_STORED_IN", "permanent_id": 26},
|
||||
(13, 15, 23): {"type": "HAS_ACCESS_TO", "permanent_id": 23},
|
||||
(13, 16, 24): {"type": "HAS_ACCESS_TO", "permanent_id": 24},
|
||||
(13, 17, 25): {"type": "HAS_ACCESS_TO", "permanent_id": 25},
|
||||
(14, 13, 27): {"type": "HAS_ACCESS_TO", "permanent_id": 27},
|
||||
(21, 23, 28): {"type": "HAS_ACCESS_TO", "permanent_id": 28},
|
||||
(21, 24, 29): {"type": "HAS_ACCESS_TO", "permanent_id": 29},
|
||||
(21, 25, 30): {"type": "HAS_ACCESS_TO", "permanent_id": 30},
|
||||
(21, 26, 31): {"type": "HAS_ACCESS_TO", "permanent_id": 31},
|
||||
(22, 5, 33): {"type": "IS_PART_OF", "permanent_id": 33},
|
||||
(22, 9, 34): {"type": "HAS_ACCESS_TO", "permanent_id": 34},
|
||||
(22, 21, 32): {"type": "IS_PART_OF", "permanent_id": 32},
|
||||
(26, 7, 35): {"type": "IS_STORED_IN", "permanent_id": 35},
|
||||
(26, 8, 36): {"type": "IS_STORED_IN", "permanent_id": 36},
|
||||
}
|
||||
|
||||
example_graph = nx.MultiDiGraph(GRAPH_DATA)
|
||||
nx.set_node_attributes(example_graph, NODE_INFO)
|
||||
nx.set_edge_attributes(example_graph, EDGE_INFO)
|
||||
|
||||
if not is_write:
|
||||
example_graph = nx.freeze(example_graph)
|
||||
|
||||
return mgp_mock.ProcCtx(_mgp_mock.Graph(example_graph))
|
||||
|
||||
|
||||
def get_vertex(ctx, permanent_id: int) -> mgp.Vertex:
|
||||
for vertex in ctx.graph.vertices:
|
||||
if vertex.properties["permanent_id"] == permanent_id:
|
||||
return vertex
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def get_edge(ctx: mgp.ProcCtx, permanent_id: int) -> mgp.Edge:
|
||||
for vertex in ctx.graph.vertices:
|
||||
for edge in vertex.out_edges:
|
||||
if edge.properties["permanent_id"] == permanent_id:
|
||||
return edge
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def get_mock_edge(ctx: mgp_mock.ProcCtx, id: int) -> mgp_mock.Edge:
|
||||
for vertex in ctx.graph.vertices:
|
||||
for edge in vertex.out_edges:
|
||||
if edge.id == id:
|
||||
return edge
|
||||
|
||||
return None
|
101
tests/e2e/mock_api/procedures/vertex.py
Normal file
101
tests/e2e/mock_api/procedures/vertex.py
Normal file
@ -0,0 +1,101 @@
|
||||
import typing
|
||||
|
||||
import mgp
|
||||
import mgp_mock
|
||||
import test_utils
|
||||
|
||||
|
||||
@mgp.read_proc
|
||||
def compare_apis(ctx: mgp.ProcCtx) -> mgp.Record(results_dict=mgp.Map):
|
||||
mock_ctx = test_utils.get_mock_proc_ctx(is_write=False)
|
||||
results = dict()
|
||||
|
||||
ID = 1
|
||||
|
||||
target_vertex = test_utils.get_vertex(ctx, permanent_id=ID)
|
||||
target_mock_vertex = mock_ctx.graph.get_vertex_by_id(ID)
|
||||
|
||||
results["is_valid"] = test_utils.all_equal(
|
||||
target_vertex.is_valid(),
|
||||
target_mock_vertex.is_valid(),
|
||||
True,
|
||||
)
|
||||
|
||||
results["underlying_graph_is_mutable"] = test_utils.all_equal(
|
||||
target_vertex.underlying_graph_is_mutable(),
|
||||
target_mock_vertex.underlying_graph_is_mutable(),
|
||||
False,
|
||||
)
|
||||
|
||||
results["id"] = test_utils.all_equal(
|
||||
isinstance(target_vertex.id, int),
|
||||
isinstance(target_mock_vertex.id, int),
|
||||
True,
|
||||
)
|
||||
|
||||
results["labels"] = test_utils.all_equal(
|
||||
isinstance(target_vertex.labels, typing.Tuple),
|
||||
isinstance(target_mock_vertex.labels, typing.Tuple),
|
||||
True,
|
||||
) and test_utils.all_equal(
|
||||
{label.name for label in target_vertex.labels},
|
||||
{mock_label.name for mock_label in target_mock_vertex.labels},
|
||||
{"Team"},
|
||||
)
|
||||
|
||||
results["properties"] = test_utils.all_equal(
|
||||
isinstance(target_vertex.properties, mgp.Properties),
|
||||
isinstance(target_mock_vertex.properties, mgp_mock.Properties),
|
||||
True,
|
||||
) and test_utils.all_equal(
|
||||
{prop for prop in target_vertex.properties},
|
||||
{mock_prop for mock_prop in target_mock_vertex.properties},
|
||||
{"name", "permanent_id"},
|
||||
)
|
||||
|
||||
results["in_edges"] = test_utils.all_equal(
|
||||
all(isinstance(edge, mgp.Edge) for edge in target_vertex.in_edges),
|
||||
all(isinstance(edge, mgp_mock.Edge) for edge in target_mock_vertex.in_edges),
|
||||
True,
|
||||
) and test_utils.all_equal(
|
||||
{edge.properties["permanent_id"] for edge in target_vertex.in_edges},
|
||||
{edge.properties["permanent_id"] for edge in target_mock_vertex.in_edges},
|
||||
{0, 9, 15, 37},
|
||||
)
|
||||
|
||||
results["out_edges"] = test_utils.all_equal(
|
||||
all(isinstance(edge, mgp.Edge) for edge in target_vertex.out_edges),
|
||||
all(isinstance(edge, mgp_mock.Edge) for edge in target_mock_vertex.out_edges),
|
||||
True,
|
||||
) and test_utils.all_equal(
|
||||
{edge.properties["permanent_id"] for edge in target_vertex.out_edges},
|
||||
{edge.properties["permanent_id"] for edge in target_mock_vertex.out_edges},
|
||||
{4, 5, 6, 7, 8},
|
||||
)
|
||||
|
||||
ID_2 = 2
|
||||
|
||||
target_vertex_2 = test_utils.get_vertex(ctx, permanent_id=ID_2)
|
||||
target_mock_vertex_2 = mock_ctx.graph.get_vertex_by_id(ID_2)
|
||||
|
||||
results["__eq__"] = test_utils.all_equal(
|
||||
target_vertex == target_vertex,
|
||||
target_mock_vertex == target_mock_vertex,
|
||||
True,
|
||||
) and test_utils.all_equal(
|
||||
target_vertex == target_vertex_2,
|
||||
target_mock_vertex == target_mock_vertex_2,
|
||||
False,
|
||||
)
|
||||
|
||||
results["__ne__"] = test_utils.all_equal(
|
||||
target_vertex != target_vertex_2,
|
||||
target_mock_vertex != target_mock_vertex_2,
|
||||
True,
|
||||
) and test_utils.all_equal(
|
||||
target_vertex != target_vertex,
|
||||
target_mock_vertex != target_mock_vertex,
|
||||
False,
|
||||
)
|
||||
|
||||
return mgp.Record(results_dict=results)
|
32
tests/e2e/mock_api/procedures/vertices.py
Normal file
32
tests/e2e/mock_api/procedures/vertices.py
Normal file
@ -0,0 +1,32 @@
|
||||
import mgp
|
||||
import mgp_mock
|
||||
import test_utils
|
||||
|
||||
|
||||
@mgp.read_proc
|
||||
def compare_apis(ctx: mgp.ProcCtx) -> mgp.Record(results_dict=mgp.Map):
|
||||
mock_ctx = test_utils.get_mock_proc_ctx(is_write=False)
|
||||
results = dict()
|
||||
|
||||
vertices = ctx.graph.vertices
|
||||
mock_vertices = mock_ctx.graph.vertices
|
||||
|
||||
results["is_valid"] = test_utils.all_equal(
|
||||
vertices.is_valid(),
|
||||
mock_vertices.is_valid(),
|
||||
True,
|
||||
)
|
||||
|
||||
results["__iter__"] = test_utils.all_equal(
|
||||
all(isinstance(vertex, mgp.Vertex) for vertex in vertices),
|
||||
all(isinstance(vertex, mgp_mock.Vertex) for vertex in mock_vertices),
|
||||
True,
|
||||
)
|
||||
|
||||
results["__len__"] = test_utils.all_equal(
|
||||
len(vertices),
|
||||
len(mock_vertices),
|
||||
27,
|
||||
)
|
||||
|
||||
return mgp.Record(results_dict=results)
|
195
tests/e2e/mock_api/test_compare_mock.py
Normal file
195
tests/e2e/mock_api/test_compare_mock.py
Normal file
@ -0,0 +1,195 @@
|
||||
import sys
|
||||
|
||||
import pytest
|
||||
from common import connect, execute_and_fetch_results_dict
|
||||
|
||||
|
||||
def test_label():
|
||||
expected_results = {
|
||||
"name": True,
|
||||
"__eq__": True,
|
||||
"__ne__": True,
|
||||
}
|
||||
|
||||
cursor = connect().cursor()
|
||||
results = execute_and_fetch_results_dict(
|
||||
cursor, "CALL label.compare_apis() YIELD results_dict RETURN results_dict;"
|
||||
)
|
||||
|
||||
assert results == expected_results
|
||||
|
||||
|
||||
def test_properties_on_vertex():
|
||||
expected_results = {
|
||||
"get": True,
|
||||
"get[default]": True,
|
||||
"set": True,
|
||||
"items": True,
|
||||
"keys": True,
|
||||
"values": True,
|
||||
"__len__": True,
|
||||
"__iter__": True,
|
||||
"__getitem__": True,
|
||||
"__setitem__": True,
|
||||
"__contains__": True,
|
||||
}
|
||||
|
||||
cursor = connect().cursor()
|
||||
results = execute_and_fetch_results_dict(
|
||||
cursor, "CALL properties.compare_apis_on_vertex() YIELD results_dict RETURN results_dict;"
|
||||
)
|
||||
|
||||
assert results == expected_results
|
||||
|
||||
|
||||
def test_properties_on_edge():
|
||||
expected_results = {
|
||||
"get": True,
|
||||
"get[default]": True,
|
||||
"set": True,
|
||||
"items": True,
|
||||
"keys": True,
|
||||
"values": True,
|
||||
"__len__": True,
|
||||
"__iter__": True,
|
||||
"__getitem__": True,
|
||||
"__setitem__": True,
|
||||
"__contains__": True,
|
||||
}
|
||||
|
||||
cursor = connect().cursor()
|
||||
results = execute_and_fetch_results_dict(
|
||||
cursor, "CALL properties.compare_apis_on_edge() YIELD results_dict RETURN results_dict;"
|
||||
)
|
||||
|
||||
assert results == expected_results
|
||||
|
||||
|
||||
def test_edge_type():
|
||||
expected_results = {
|
||||
"name": True,
|
||||
"__eq__": True,
|
||||
"__ne__": True,
|
||||
}
|
||||
|
||||
cursor = connect().cursor()
|
||||
results = execute_and_fetch_results_dict(
|
||||
cursor, "CALL edge_type.compare_apis() YIELD results_dict RETURN results_dict;"
|
||||
)
|
||||
|
||||
assert results == expected_results
|
||||
|
||||
|
||||
def test_edge():
|
||||
expected_results = {
|
||||
"is_valid": True,
|
||||
"underlying_graph_is_mutable": True,
|
||||
"id": True,
|
||||
"type": True,
|
||||
"from_vertex": True,
|
||||
"to_vertex": True,
|
||||
"properties": True,
|
||||
"__eq__": True,
|
||||
"__ne__": True,
|
||||
}
|
||||
|
||||
cursor = connect().cursor()
|
||||
results = execute_and_fetch_results_dict(cursor, "CALL edge.compare_apis() YIELD results_dict RETURN results_dict;")
|
||||
|
||||
assert results == expected_results
|
||||
|
||||
|
||||
def test_vertex():
|
||||
expected_results = {
|
||||
"is_valid": True,
|
||||
"underlying_graph_is_mutable": True,
|
||||
"id": True,
|
||||
"labels": True,
|
||||
"properties": True,
|
||||
"in_edges": True,
|
||||
"out_edges": True,
|
||||
"__eq__": True,
|
||||
"__ne__": True,
|
||||
}
|
||||
|
||||
cursor = connect().cursor()
|
||||
results = execute_and_fetch_results_dict(
|
||||
cursor, "CALL vertex.compare_apis() YIELD results_dict RETURN results_dict;"
|
||||
)
|
||||
|
||||
assert results == expected_results
|
||||
|
||||
|
||||
def test_path():
|
||||
expected_results = {
|
||||
"__copy__": True,
|
||||
"is_valid": True,
|
||||
"expand": True,
|
||||
"vertices": True,
|
||||
"edges": True,
|
||||
}
|
||||
|
||||
cursor = connect().cursor()
|
||||
results = execute_and_fetch_results_dict(cursor, "CALL path.compare_apis() YIELD results_dict RETURN results_dict;")
|
||||
|
||||
assert results == expected_results
|
||||
|
||||
|
||||
def test_record():
|
||||
expected_results = {
|
||||
"fields": True,
|
||||
}
|
||||
|
||||
cursor = connect().cursor()
|
||||
results = execute_and_fetch_results_dict(
|
||||
cursor, "CALL record.compare_apis() YIELD results_dict RETURN results_dict;"
|
||||
)
|
||||
|
||||
assert results == expected_results
|
||||
|
||||
|
||||
def test_vertices():
|
||||
expected_results = {
|
||||
"is_valid": True,
|
||||
"__iter__": True,
|
||||
"__len__": True,
|
||||
}
|
||||
|
||||
cursor = connect().cursor()
|
||||
results = execute_and_fetch_results_dict(
|
||||
cursor, "CALL vertices.compare_apis() YIELD results_dict RETURN results_dict;"
|
||||
)
|
||||
|
||||
assert results == expected_results
|
||||
|
||||
|
||||
def test_graph():
|
||||
expected_results = {
|
||||
"create_edge": True,
|
||||
"create_vertex": True,
|
||||
"delete_edge": True,
|
||||
"delete_vertex": True,
|
||||
"detach_delete_vertex": True,
|
||||
"edge_id_assignment": True,
|
||||
"get_vertex_by_id": True,
|
||||
"is_mutable": True,
|
||||
"is_not_mutable": True,
|
||||
"is_valid": True,
|
||||
"vertices": True,
|
||||
}
|
||||
|
||||
cursor = connect().cursor()
|
||||
results = execute_and_fetch_results_dict(
|
||||
cursor, "CALL graph.compare_apis() YIELD results_dict RETURN results_dict;"
|
||||
)
|
||||
results.update(
|
||||
execute_and_fetch_results_dict(
|
||||
cursor, "CALL graph.test_read_proc_mutability() YIELD results_dict RETURN results_dict;"
|
||||
)
|
||||
)
|
||||
|
||||
assert results == expected_results
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(pytest.main([__file__, "-rA"]))
|
83
tests/e2e/mock_api/workloads.yaml
Normal file
83
tests/e2e/mock_api/workloads.yaml
Normal file
@ -0,0 +1,83 @@
|
||||
compare_mock: &compare_mock
|
||||
cluster:
|
||||
main:
|
||||
args: ["--bolt-port", "7687", "--log-level=TRACE", "--also-log-to-stderr"]
|
||||
log_file: "test-compare-mock-e2e.log"
|
||||
setup_queries:
|
||||
- "CREATE INDEX ON :__mg_vertex__(__mg_id__);"
|
||||
- "CREATE (:__mg_vertex__:`Person` {__mg_id__: 0, `name`: 'Peter', `surname`: 'Yang'});"
|
||||
- "CREATE (:__mg_vertex__:`Team` {__mg_id__: 1, `name`: 'Engineering'});"
|
||||
- "CREATE (:__mg_vertex__:`Repository` {__mg_id__: 2, `name`: 'Memgraph'});"
|
||||
- "CREATE (:__mg_vertex__:`Repository` {__mg_id__: 3, `name`: 'MAGE'});"
|
||||
- "CREATE (:__mg_vertex__:`Repository` {__mg_id__: 4, `name`: 'GQLAlchemy'});"
|
||||
- "CREATE (:__mg_vertex__:`Company`:`Startup` {__mg_id__: 5, `name`: 'Memgraph'});"
|
||||
- "CREATE (:__mg_vertex__:`File` {__mg_id__: 6, `name`: 'welcome_to_engineering.txt'});"
|
||||
- "CREATE (:__mg_vertex__:`Storage` {__mg_id__: 7, `name`: 'Google Drive'});"
|
||||
- "CREATE (:__mg_vertex__:`Storage` {__mg_id__: 8, `name`: 'Notion'});"
|
||||
- "CREATE (:__mg_vertex__:`File` {__mg_id__: 9, `name`: 'welcome_to_memgraph.txt'});"
|
||||
- "CREATE (:__mg_vertex__:`Person` {__mg_id__: 10, `name`: 'Carl'});"
|
||||
- "CREATE (:__mg_vertex__:`Folder` {__mg_id__: 11, `name`: 'engineering_folder'});"
|
||||
- "CREATE (:__mg_vertex__:`Person` {__mg_id__: 12, `name`: 'Anna'});"
|
||||
- "CREATE (:__mg_vertex__:`Folder` {__mg_id__: 13, `name`: 'operations_folder'});"
|
||||
- "CREATE (:__mg_vertex__:`Team` {__mg_id__: 14, `name`: 'Operations'});"
|
||||
- "CREATE (:__mg_vertex__:`File` {__mg_id__: 15, `name`: 'operations101.txt'});"
|
||||
- "CREATE (:__mg_vertex__:`File` {__mg_id__: 16, `name`: 'expenses2022.csv'});"
|
||||
- "CREATE (:__mg_vertex__:`File` {__mg_id__: 17, `name`: 'salaries2022.csv'});"
|
||||
- "CREATE (:__mg_vertex__:`File` {__mg_id__: 18, `name`: 'engineering101.txt'});"
|
||||
- "CREATE (:__mg_vertex__:`File` {__mg_id__: 19, `name`: 'working_with_github.txt'});"
|
||||
- "CREATE (:__mg_vertex__:`File` {__mg_id__: 20, `name`: 'working_with_notion.txt'});"
|
||||
- "CREATE (:__mg_vertex__:`Team` {__mg_id__: 21, `name`: 'Marketing'});"
|
||||
- "CREATE (:__mg_vertex__:`Person` {__mg_id__: 22, `name`: 'Julie'});"
|
||||
- "CREATE (:__mg_vertex__:`Account` {__mg_id__: 23, `name`: 'Facebook'});"
|
||||
- "CREATE (:__mg_vertex__:`Account` {__mg_id__: 24, `name`: 'LinkedIn'});"
|
||||
- "CREATE (:__mg_vertex__:`Account` {__mg_id__: 25, `name`: 'HackerNews'});"
|
||||
- "CREATE (:__mg_vertex__:`File` {__mg_id__: 26, `name`: 'welcome_to_marketing.txt'});"
|
||||
- "MATCH (u:__mg_vertex__), (v:__mg_vertex__) WHERE u.__mg_id__ = 0 AND v.__mg_id__ = 1 CREATE (u)-[:`IS_PART_OF` {`permanent_id`: 0}]->(v);"
|
||||
- "MATCH (u:__mg_vertex__), (v:__mg_vertex__) WHERE u.__mg_id__ = 0 AND v.__mg_id__ = 5 CREATE (u)-[:`IS_PART_OF` {`permanent_id`: 1}]->(v);"
|
||||
- "MATCH (u:__mg_vertex__), (v:__mg_vertex__) WHERE u.__mg_id__ = 0 AND v.__mg_id__ = 9 CREATE (u)-[:`HAS_ACCESS_TO` {`permanent_id`: 2}]->(v);"
|
||||
- "MATCH (u:__mg_vertex__), (v:__mg_vertex__) WHERE u.__mg_id__ = 0 AND v.__mg_id__ = 14 CREATE (u)-[:`IS_PART_OF` {`permanent_id`: 3}]->(v);"
|
||||
- "MATCH (u:__mg_vertex__), (v:__mg_vertex__) WHERE u.__mg_id__ = 1 AND v.__mg_id__ = 2 CREATE (u)-[:`HAS_ACCESS_TO` {`permanent_id`: 4}]->(v);"
|
||||
- "MATCH (u:__mg_vertex__), (v:__mg_vertex__) WHERE u.__mg_id__ = 1 AND v.__mg_id__ = 3 CREATE (u)-[:`HAS_ACCESS_TO` {`permanent_id`: 5}]->(v);"
|
||||
- "MATCH (u:__mg_vertex__), (v:__mg_vertex__) WHERE u.__mg_id__ = 1 AND v.__mg_id__ = 4 CREATE (u)-[:`HAS_ACCESS_TO` {`permanent_id`: 6}]->(v);"
|
||||
- "MATCH (u:__mg_vertex__), (v:__mg_vertex__) WHERE u.__mg_id__ = 1 AND v.__mg_id__ = 6 CREATE (u)-[:`HAS_ACCESS_TO` {`permanent_id`: 7}]->(v);"
|
||||
- "MATCH (u:__mg_vertex__), (v:__mg_vertex__) WHERE u.__mg_id__ = 1 AND v.__mg_id__ = 11 CREATE (u)-[:`HAS_ACCESS_TO` {`permanent_id`: 8}]->(v);"
|
||||
- "MATCH (u:__mg_vertex__), (v:__mg_vertex__) WHERE u.__mg_id__ = 5 AND v.__mg_id__ = 1 CREATE (u)-[:`HAS_TEAM` {`permanent_id`: 9}]->(v);"
|
||||
- "MATCH (u:__mg_vertex__), (v:__mg_vertex__) WHERE u.__mg_id__ = 5 AND v.__mg_id__ = 21 CREATE (u)-[:`HAS_TEAM` {`permanent_id`: 10}]->(v);"
|
||||
- "MATCH (u:__mg_vertex__), (v:__mg_vertex__) WHERE u.__mg_id__ = 5 AND v.__mg_id__ = 14 CREATE (u)-[:`HAS_TEAM` {`permanent_id`: 11}]->(v);"
|
||||
- "MATCH (u:__mg_vertex__), (v:__mg_vertex__) WHERE u.__mg_id__ = 6 AND v.__mg_id__ = 7 CREATE (u)-[:`IS_STORED_IN` {`permanent_id`: 12}]->(v);"
|
||||
- "MATCH (u:__mg_vertex__), (v:__mg_vertex__) WHERE u.__mg_id__ = 6 AND v.__mg_id__ = 8 CREATE (u)-[:`IS_STORED_IN` {`permanent_id`: 13}]->(v);"
|
||||
- "MATCH (u:__mg_vertex__), (v:__mg_vertex__) WHERE u.__mg_id__ = 9 AND v.__mg_id__ = 12 CREATE (u)-[:`CREATED_BY` {`permanent_id`: 14}]->(v);"
|
||||
- "MATCH (u:__mg_vertex__), (v:__mg_vertex__) WHERE u.__mg_id__ = 10 AND v.__mg_id__ = 1 CREATE (u)-[:`IS_PART_OF` {`permanent_id`: 15}]->(v);"
|
||||
- "MATCH (u:__mg_vertex__), (v:__mg_vertex__) WHERE u.__mg_id__ = 10 AND v.__mg_id__ = 5 CREATE (u)-[:`IS_PART_OF` {`permanent_id`: 16}]->(v);"
|
||||
- "MATCH (u:__mg_vertex__), (v:__mg_vertex__) WHERE u.__mg_id__ = 10 AND v.__mg_id__ = 9 CREATE (u)-[:`HAS_ACCESS_TO` {`permanent_id`: 17}]->(v);"
|
||||
- "MATCH (u:__mg_vertex__), (v:__mg_vertex__) WHERE u.__mg_id__ = 11 AND v.__mg_id__ = 7 CREATE(u)-[:`IS_STORED_IN` {`permanent_id`: 18}]->(v);"
|
||||
- "MATCH (u:__mg_vertex__), (v:__mg_vertex__) WHERE u.__mg_id__ = 11 AND v.__mg_id__ = 18 CREATE (u)-[:`HAS_ACCESS_TO` {`permanent_id`: 19}]->(v);"
|
||||
- "MATCH (u:__mg_vertex__), (v:__mg_vertex__) WHERE u.__mg_id__ = 11 AND v.__mg_id__ = 19 CREATE (u)-[:`HAS_ACCESS_TO` {`permanent_id`: 20}]->(v);"
|
||||
- "MATCH (u:__mg_vertex__), (v:__mg_vertex__) WHERE u.__mg_id__ = 11 AND v.__mg_id__ = 20 CREATE (u)-[:`HAS_ACCESS_TO` {`permanent_id`: 21}]->(v);"
|
||||
- "MATCH (u:__mg_vertex__), (v:__mg_vertex__) WHERE u.__mg_id__ = 12 AND v.__mg_id__ = 14 CREATE (u)-[:`IS_PART_OF` {`permanent_id`: 22}]->(v);"
|
||||
- "MATCH (u:__mg_vertex__), (v:__mg_vertex__) WHERE u.__mg_id__ = 13 AND v.__mg_id__ = 15 CREATE (u)-[:`HAS_ACCESS_TO` {`permanent_id`: 23}]->(v);"
|
||||
- "MATCH (u:__mg_vertex__), (v:__mg_vertex__) WHERE u.__mg_id__ = 13 AND v.__mg_id__ = 16 CREATE (u)-[:`HAS_ACCESS_TO` {`permanent_id`: 24}]->(v);"
|
||||
- "MATCH (u:__mg_vertex__), (v:__mg_vertex__) WHERE u.__mg_id__ = 13 AND v.__mg_id__ = 17 CREATE (u)-[:`HAS_ACCESS_TO` {`permanent_id`: 25}]->(v);"
|
||||
- "MATCH (u:__mg_vertex__), (v:__mg_vertex__) WHERE u.__mg_id__ = 13 AND v.__mg_id__ = 7 CREATE (u)-[:`IS_STORED_IN` {`permanent_id`: 26}]->(v);"
|
||||
- "MATCH (u:__mg_vertex__), (v:__mg_vertex__) WHERE u.__mg_id__ = 14 AND v.__mg_id__ = 13 CREATE (u)-[:`HAS_ACCESS_TO` {`permanent_id`: 27}]->(v);"
|
||||
- "MATCH (u:__mg_vertex__), (v:__mg_vertex__) WHERE u.__mg_id__ = 21 AND v.__mg_id__ = 23 CREATE (u)-[:`HAS_ACCESS_TO` {`permanent_id`: 28}]->(v);"
|
||||
- "MATCH (u:__mg_vertex__), (v:__mg_vertex__) WHERE u.__mg_id__ = 21 AND v.__mg_id__ = 24 CREATE (u)-[:`HAS_ACCESS_TO` {`permanent_id`: 29}]->(v);"
|
||||
- "MATCH (u:__mg_vertex__), (v:__mg_vertex__) WHERE u.__mg_id__ = 21 AND v.__mg_id__ = 25 CREATE (u)-[:`HAS_ACCESS_TO` {`permanent_id`: 30}]->(v);"
|
||||
- "MATCH (u:__mg_vertex__), (v:__mg_vertex__) WHERE u.__mg_id__ = 21 AND v.__mg_id__ = 26 CREATE (u)-[:`HAS_ACCESS_TO` {`permanent_id`: 31}]->(v);"
|
||||
- "MATCH (u:__mg_vertex__), (v:__mg_vertex__) WHERE u.__mg_id__ = 22 AND v.__mg_id__ = 21 CREATE (u)-[:`IS_PART_OF` {`permanent_id`: 32}]->(v);"
|
||||
- "MATCH (u:__mg_vertex__), (v:__mg_vertex__) WHERE u.__mg_id__ = 22 AND v.__mg_id__ = 5 CREATE (u)-[:`IS_PART_OF` {`permanent_id`: 33}]->(v);"
|
||||
- "MATCH (u:__mg_vertex__), (v:__mg_vertex__) WHERE u.__mg_id__ = 22 AND v.__mg_id__ = 9 CREATE (u)-[:`HAS_ACCESS_TO` {`permanent_id`: 34}]->(v);"
|
||||
- "MATCH (u:__mg_vertex__), (v:__mg_vertex__) WHERE u.__mg_id__ = 26 AND v.__mg_id__ = 7 CREATE (u)-[:`IS_STORED_IN` {`permanent_id`: 35}]->(v);"
|
||||
- "MATCH (u:__mg_vertex__), (v:__mg_vertex__) WHERE u.__mg_id__ = 26 AND v.__mg_id__ = 8 CREATE (u)-[:`IS_STORED_IN` {`permanent_id`: 36}]->(v);"
|
||||
- "MATCH (u:__mg_vertex__), (v:__mg_vertex__) WHERE u.__mg_id__ = 5 AND v.__mg_id__ = 1 CREATE (u)-[:`HAS_TEAM_2` {`importance`: 'HIGH', `permanent_id`: 37}]->(v);"
|
||||
- "DROP INDEX ON :__mg_vertex__(__mg_id__);"
|
||||
- "MATCH (u) SET u.permanent_id = u.__mg_id__;"
|
||||
- "MATCH (u) REMOVE u:__mg_vertex__, u.__mg_id__;"
|
||||
validation_queries: []
|
||||
|
||||
workloads:
|
||||
- name: "test-compare-mock" # should be the same as the python file
|
||||
binary: "tests/e2e/pytest_runner.sh"
|
||||
proc: "tests/e2e/mock_api/procedures/"
|
||||
args: ["mock_api/test_compare_mock.py"]
|
||||
<<: *compare_mock
|
@ -15,6 +15,7 @@ PIP_DEPS=(
|
||||
"pytest==6.2.3"
|
||||
"pyyaml==5.4.1"
|
||||
"six==1.15.0"
|
||||
"networkx==2.4"
|
||||
)
|
||||
cd "$DIR"
|
||||
|
||||
|
@ -6,3 +6,4 @@ python-dateutil==2.6.1
|
||||
pytz==2017.2
|
||||
six==1.11.0
|
||||
tabulate==0.8.1
|
||||
networkx==2.4
|
||||
|
Loading…
Reference in New Issue
Block a user