Add Python query module API mock (#757)

This commit is contained in:
Ante Pušić 2023-03-07 15:41:19 +01:00 committed by GitHub
parent 6abd356d01
commit 97d45ab1d8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 3147 additions and 0 deletions

343
include/_mgp_mock.py Normal file
View 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

File diff suppressed because it is too large Load Diff

View File

@ -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

View File

@ -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})

View 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)

View 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]

View 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)

View 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)

View 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)

View 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)

View 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)

View 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)

View 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)

View 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)

View 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

View 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)

View 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)

View 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"]))

View 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

View File

@ -15,6 +15,7 @@ PIP_DEPS=(
"pytest==6.2.3"
"pyyaml==5.4.1"
"six==1.15.0"
"networkx==2.4"
)
cd "$DIR"

View File

@ -6,3 +6,4 @@ python-dateutil==2.6.1
pytz==2017.2
six==1.11.0
tabulate==0.8.1
networkx==2.4