Skip to content

Commit

Permalink
Fix tests
Browse files Browse the repository at this point in the history
  • Loading branch information
LucasG0 committed Jan 3, 2025
1 parent 80e9275 commit 9e285dc
Show file tree
Hide file tree
Showing 9 changed files with 127 additions and 20 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
81 changes: 81 additions & 0 deletions backend/tests/query_benchmark/test_node_get_list.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import inspect
from pathlib import Path

import pytest

from infrahub.core import registry
from infrahub.core.query.node import NodeGetListQuery
from infrahub.database.constants import Neo4jRuntime
from infrahub.log import get_logger
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 (
CarGenerator,
)
from tests.helpers.query_benchmark.data_generator import load_data_and_profile
from tests.query_benchmark.conftest import RESULTS_FOLDER
from tests.query_benchmark.utils import start_db_and_create_default_branch

log = get_logger()

# pytestmark = pytest.mark.skip("Not relevant to test this currently.")


@pytest.mark.timeout(36000) # 10 hours
@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,
),
],
)
async def test_node_get_list_ordering(
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)

# Build function to profile
async def init_and_execute():
car_node_schema = registry.get_node_schema(name="TestCar", branch=default_branch.name)
query = await NodeGetListQuery.init(
db=db_profiling_queries,
schema=car_node_schema,
branch=default_branch,
ordering=ordering,
)
res = await query.execute(db=db_profiling_queries)
print(f"{len(res.get_node_ids())=}")
return res

nb_cars = 50_000
cars_generator = CarGenerator(db=db_profiling_queries)
test_name = inspect.currentframe().f_code.co_name
module_name = Path(__file__).stem
graph_output_location = RESULTS_FOLDER / module_name / test_name

test_label = str(benchmark_config) + "_ordering_" + str(ordering)

await load_data_and_profile(
data_generator=cars_generator,
func_call=init_and_execute,
profile_frequency=10_000,
nb_elements=nb_cars,
graphs_output_location=graph_output_location,
test_label=test_label,
graph_generator=graph_generator,
)
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 9e285dc

Please sign in to comment.