Skip to content

Commit

Permalink
Fix tests
Browse files Browse the repository at this point in the history
# Conflicts:
#	backend/tests/query_benchmark/test_node_get_list.py
  • Loading branch information
LucasG0 committed Jan 3, 2025
1 parent b3716b1 commit d9dbb1b
Show file tree
Hide file tree
Showing 9 changed files with 83 additions and 35 deletions.
8 changes: 7 additions & 1 deletion backend/infrahub/core/node/constraints/grouped_uniqueness.py
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,11 @@ async def _check_one_schema(
at: Optional[Timestamp] = None,
filters: Optional[list[str]] = None,
) -> None:
"""
Raises a `ValidationError` if database contains at least one node having same `uniqueness_constraint` attributes
than input `node` ones.
"""

schema_branch = self.db.schema.get_schema_branch(name=self.branch.name)
path_groups = node_schema.get_unique_constraint_schema_attribute_paths(schema_branch=schema_branch)

Expand All @@ -158,7 +163,7 @@ async def _check_one_schema(
updated_node=node, node_schema=node_schema, path_groups=[path_group], filters=filters
)

if not query_request:
if query_request.is_empty():
continue

if query_request.has_attributes_only:
Expand All @@ -179,6 +184,7 @@ async def _check_one_schema(
await get_node_query.execute(db=self.db)
node_ids = get_node_query.get_node_ids()

# Node may or may not already exist in the database.
if (node.id in node_ids and len(node_ids) > 1) or (node.id not in node_ids and len(node_ids) > 0):
raise ValidationError(query_request.get_error_message())

Expand Down
2 changes: 1 addition & 1 deletion backend/infrahub/core/validators/uniqueness/checker.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ async def check_one_schema(
) -> list[NonUniqueNode]:
query_request = await self.build_query_request(schema)

if not query_request:
if query_request.is_empty():
return []

query = await NodeUniqueAttributeConstraintQuery.init(
Expand Down
10 changes: 5 additions & 5 deletions backend/infrahub/core/validators/uniqueness/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,8 @@ class NodeUniquenessQueryRequest(BaseModel):
unique_attribute_paths: set[QueryAttributePath] = Field(default_factory=set)
relationship_attribute_paths: set[QueryRelationshipAttributePath] = Field(default_factory=set)

def __bool__(self) -> bool:
if self.unique_attribute_paths or self.relationship_attribute_paths:
return True
return False
def is_empty(self) -> bool:
return not self.unique_attribute_paths and not self.relationship_attribute_paths

def __str__(self) -> str:
return (
Expand All @@ -65,7 +63,9 @@ def has_attributes_only(self) -> bool:
return True

def get_error_message(self) -> str:
uniqueness_constaints = [f"{attr.attribute_name}__{attr.property_name}" for attr in self.unique_attribute_paths]
uniqueness_constaints = sorted(
[f"{attr.attribute_name}__{attr.property_name}" for attr in self.unique_attribute_paths]
)
return f"Violates uniqueness constraint '{uniqueness_constaints}'"


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
from infrahub.dependencies.interface import DependencyBuilder, DependencyBuilderContext

from ..node.grouped_uniqueness import NodeGroupedUniquenessConstraintDependency
from ..node.uniqueness import NodeAttributeUniquenessConstraintDependency
from ..relationship_manager.count import RelationshipCountConstraintDependency
from ..relationship_manager.peer_kind import RelationshipPeerKindConstraintDependency
from ..relationship_manager.profiles_kind import RelationshipProfilesKindConstraintDependency
Expand All @@ -15,7 +14,6 @@ def build(cls, context: DependencyBuilderContext) -> NodeConstraintRunner:
db=context.db,
branch=context.branch,
node_constraints=[
NodeAttributeUniquenessConstraintDependency.build(context=context), # NOTE we probably don't need this Checker, it's redundant with NodeGroupedUniquenessConstraintDependency
NodeGroupedUniquenessConstraintDependency.build(context=context),
],
relationship_manager_constraints=[
Expand Down
52 changes: 37 additions & 15 deletions backend/tests/query_benchmark/test_node_get_list.py
Original file line number Diff line number Diff line change
@@ -1,21 +1,18 @@
import inspect
from pathlib import Path
from pickle import FALSE

import pytest

from infrahub.core import registry
from infrahub.core.initialization import create_branch
from infrahub.core.manager import NodeManager
from infrahub.core.query.diff import DiffAllPathsQuery
from infrahub.core.query.node import NodeGetListQuery
from infrahub.core.timestamp import Timestamp
from infrahub.core.validators.uniqueness.model import NodeUniquenessQueryRequest, QueryAttributePath
from infrahub.core.validators.uniqueness.query import NodeUniqueAttributeConstraintQuery
from infrahub.database.constants import Neo4jRuntime
from infrahub.log import get_logger
from tests.helpers.constants import NEO4J_COMMUNITY_IMAGE, NEO4J_ENTERPRISE_IMAGE
from tests.helpers.constants import NEO4J_ENTERPRISE_IMAGE
from tests.helpers.query_benchmark.benchmark_config import BenchmarkConfig
from tests.helpers.query_benchmark.car_person_generators import (
CarWithDiffInSecondBranchGenerator, CarGenerator,
CarGenerator,
)
from tests.helpers.query_benchmark.data_generator import load_data_and_profile
from tests.query_benchmark.conftest import RESULTS_FOLDER
Expand All @@ -30,18 +27,36 @@
@pytest.mark.parametrize(
"benchmark_config, ordering",
[
(BenchmarkConfig(neo4j_runtime=Neo4jRuntime.PARALLEL, neo4j_image=NEO4J_ENTERPRISE_IMAGE, load_db_indexes=False), False),
(BenchmarkConfig(neo4j_runtime=Neo4jRuntime.PARALLEL, neo4j_image=NEO4J_ENTERPRISE_IMAGE, load_db_indexes=False), True),
# (BenchmarkConfig(neo4j_runtime=Neo4jRuntime.PARALLEL, neo4j_image=NEO4J_ENTERPRISE_IMAGE, load_db_indexes=False), False),
(
BenchmarkConfig(
neo4j_runtime=Neo4jRuntime.PARALLEL, neo4j_image=NEO4J_ENTERPRISE_IMAGE, load_db_indexes=False
),
True,
),
],
)
async def test_node_get_list_ordering(benchmark_config, car_person_schema_root, graph_generator, increase_query_size_limit, ordering):
async def test_node_get_list_ordering_vs_uniqueness(
benchmark_config, car_person_schema_root, graph_generator, increase_query_size_limit, ordering
):
# Initialization
db_profiling_queries, default_branch = await start_db_and_create_default_branch(
neo4j_image=benchmark_config.neo4j_image,
load_indexes=benchmark_config.load_db_indexes,
)
registry.schema.register_schema(schema=car_person_schema_root, branch=default_branch.name)

query_request = NodeUniquenessQueryRequest(
kind="TestCar",
unique_attribute_paths={
QueryAttributePath(attribute_name="name", property_name="value"),
# QueryAttributePath(attribute_name="nbr_seats", property_name="value"),
},
# relationship_attribute_paths={
# QueryRelationshipAttributePath(identifier="testcar__testperson", attribute_name="name")
# },
)

# Build function to profile
async def init_and_execute():
car_node_schema = registry.get_node_schema(name="TestCar", branch=default_branch.name)
Expand All @@ -50,13 +65,20 @@ async def init_and_execute():
schema=car_node_schema,
branch=default_branch,
ordering=ordering,
filters={"name": "aaaa"},
)
res = await query.execute(db=db_profiling_queries)
print(f"{len(res.get_node_ids())=}")
return res
res_node_get_list = await query.execute(db=db_profiling_queries)
print(f"{len(res_node_get_list.get_node_ids())=}")

query_uniqueness = await NodeUniqueAttributeConstraintQuery.init(
db=db_profiling_queries,
branch=default_branch,
query_request=query_request,
)
await query_uniqueness.execute(db=db_profiling_queries)
print(f"{query_uniqueness.results=}")

nb_cars = 10_000
nb_cars = 5_000
cars_generator = CarGenerator(db=db_profiling_queries)
test_name = inspect.currentframe().f_code.co_name
module_name = Path(__file__).stem
Expand All @@ -67,7 +89,7 @@ async def init_and_execute():
await load_data_and_profile(
data_generator=cars_generator,
func_call=init_and_execute,
profile_frequency=1_000,
profile_frequency=500,
nb_elements=nb_cars,
graphs_output_location=graph_output_location,
test_label=test_label,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import re

import pytest

from infrahub.core import registry
Expand Down Expand Up @@ -31,7 +33,7 @@ async def test_uniqueness_constraint_conflict_attribute(
car_accord_main.name.value = "camry"
car_accord_main.get_schema().uniqueness_constraints = [["name__value"]]

with pytest.raises(ValidationError, match="Violates uniqueness constraint 'name'"):
with pytest.raises(ValidationError, match=re.escape("Violates uniqueness constraint '['name__value']'")):
await self.__call_system_under_test(db=db, branch=default_branch, node=car_accord_main)

async def test_uniqueness_constraint_filters(
Expand Down Expand Up @@ -66,14 +68,34 @@ async def test_uniqueness_constraint_conflict_two_attribute(
car_camry_main: Node,
car_volt_main: Node,
):
car_accord_main.name.value = "camry"
car_accord_main.color.value = "#123456"
car_accord_main.name.value = car_camry_main.name.value
car_accord_main.get_schema().uniqueness_constraints = [
["name__value", "color__value"],
["nbr_seats__value", "name__value"],
]

with pytest.raises(ValidationError, match="Violates uniqueness constraint 'name-color'"):
with pytest.raises(
ValidationError, match=re.escape("Violates uniqueness constraint '['color__value', 'name__value']'")
):
await self.__call_system_under_test(db=db, branch=default_branch, node=car_accord_main)

async def test_uniqueness_constraint_conflict_multiple_constraints(
self,
db: InfrahubDatabase,
default_branch: Branch,
car_accord_main: Node,
car_camry_main: Node,
car_volt_main: Node,
):
car_accord_main.nbr_seats.value = car_camry_main.nbr_seats.value
car_accord_main.color.value = car_camry_main.color.value
car_accord_main.get_schema().uniqueness_constraints = [
["name__value", "color__value"],
["nbr_seats__value", "color__value"],
]

with pytest.raises(
ValidationError, match=re.escape("Violates uniqueness constraint '['color__value', 'nbr_seats__value']'")
):
await self.__call_system_under_test(db=db, branch=default_branch, node=car_accord_main)

async def test_uniqueness_constraint_no_conflict_attribute_enum(
Expand Down Expand Up @@ -108,7 +130,7 @@ async def test_uniqueness_constraint_conflict_attribute_enum(
car_accord_main.name.value = "camry"
car_accord_main.get_schema().uniqueness_constraints = [["nbr_seats__value", "name__value"]]

with pytest.raises(ValidationError, match="Violates uniqueness constraint 'nbr_seats-name'"):
with pytest.raises(ValidationError, match="Violates uniqueness constraint ['name__value', 'nbr_seats__value']"):
await self.__call_system_under_test(db=db, branch=default_branch, node=car_accord_main)

async def test_uniqueness_constraint_no_conflict_one_relationship(
Expand Down
6 changes: 3 additions & 3 deletions backend/tests/unit/graphql/test_mutation_create.py
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ async def test_create_check_unique(db: InfrahubDatabase, default_branch, car_per

assert result.errors
assert len(result.errors) == 1
assert "An object already exist" in result.errors[0].message
assert "Violates uniqueness constraint '['name__value']'" in result.errors[0].message


async def test_create_check_unique_across_branch(db: InfrahubDatabase, default_branch, car_person_schema):
Expand Down Expand Up @@ -172,7 +172,7 @@ async def test_create_check_unique_across_branch(db: InfrahubDatabase, default_b

assert result.errors
assert len(result.errors) == 1
assert "An object already exist" in result.errors[0].message
assert "Violates uniqueness constraint '['name__value']'" in result.errors[0].message


async def test_create_check_unique_in_branch(db: InfrahubDatabase, default_branch, car_person_schema):
Expand Down Expand Up @@ -203,7 +203,7 @@ async def test_create_check_unique_in_branch(db: InfrahubDatabase, default_branc

assert result.errors
assert len(result.errors) == 1
assert "An object already exist" in result.errors[0].message
assert "Violates uniqueness constraint '['name__value']'" in result.errors[0].message


async def test_all_attributes(db: InfrahubDatabase, default_branch, all_attribute_types_schema):
Expand Down
2 changes: 1 addition & 1 deletion backend/tests/unit/graphql/test_mutation_update.py
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ async def test_update_check_unique(db: InfrahubDatabase, person_john_main: Node,

assert result.errors
assert len(result.errors) == 1
assert "An object already exist" in result.errors[0].message
assert "Violates uniqueness constraint '['name__value']'" in result.errors[0].message


async def test_update_object_with_flag_property(db: InfrahubDatabase, person_john_main: Node, branch: Branch):
Expand Down
2 changes: 1 addition & 1 deletion backend/tests/unit/graphql/test_mutation_upsert.py
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ async def test_update_by_id_to_nonunique_value_raises_error(
variable_values={},
)

expected_error = "An object already exist with this value: name: Jim at name"
expected_error = "Violates uniqueness constraint '['name__value']'"
assert any(expected_error in error.message for error in result.errors)


Expand Down

0 comments on commit d9dbb1b

Please sign in to comment.