Skip to content

Commit eda425b

Browse files
ajtmccartyfatih-acar
authored andcommitted
unit test for duplicate attribute edges in database
1 parent cf07cf4 commit eda425b

File tree

1 file changed

+73
-0
lines changed

1 file changed

+73
-0
lines changed
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
import asyncio
2+
3+
import pytest
4+
5+
from infrahub.core.node import Node
6+
from infrahub.core.schema.schema_branch import SchemaBranch
7+
from infrahub.database import InfrahubDatabase, get_db
8+
9+
10+
class TestNodeConcurrentSave:
11+
the_value = 122
12+
13+
@pytest.fixture
14+
async def node_with_duplicate_edges(self, db: InfrahubDatabase, car_person_schema: SchemaBranch) -> Node:
15+
# create a node
16+
node = await Node.init(db=db, schema="TestPerson")
17+
await node.new(db=db, name="Concurrynthia")
18+
await node.save(db=db)
19+
20+
# make an update
21+
node.height.value = self.the_value
22+
23+
# save the update simulataneously on two different db connections
24+
# creating multiple AttributeValue nodes with the same value
25+
db_drivers: list[InfrahubDatabase] = []
26+
try:
27+
for _ in range(2):
28+
driver = InfrahubDatabase(driver=await get_db(retry=5))
29+
db_drivers.append(driver)
30+
31+
await asyncio.gather(*[node.save(db=db_drivers[i]) for i in range(2)])
32+
finally:
33+
for driver in db_drivers:
34+
await driver.close()
35+
return node
36+
37+
async def _validate_no_duplicate_edges(self, db: InfrahubDatabase, node: Node, attribute_name: str) -> None:
38+
# validate that this node
39+
# - does not have duplicate HAS_VALUE, IS_VISIBLE, or IS_PROTECTED edges
40+
# - only connects to one AttributeValue node even though multiple exist
41+
params = {"node_id": node.get_id(), "attribute_name": attribute_name}
42+
query = """
43+
MATCH (:Node {uuid: $node_id})-[:HAS_ATTRIBUTE]->(a:Attribute {name: $attribute_name})
44+
MATCH (a)-[e]-(p)
45+
RETURN a, type(e) AS edge_type, p.value AS value, COUNT(*) AS num_edges
46+
"""
47+
results = await db.execute_query(query=query, params=params)
48+
for result in results:
49+
edge_type = result.get("edge_type")
50+
value = result.get("value")
51+
num_edges = result.get("num_edges")
52+
assert num_edges == 1, f"{num_edges} duplicate {edge_type} edges with {value=}"
53+
54+
async def test_new_node_avoids_duplicate_edges(
55+
self, db: InfrahubDatabase, car_person_schema: SchemaBranch, node_with_duplicate_edges: Node
56+
) -> None:
57+
another_node = await Node.init(db=db, schema="TestPerson")
58+
await another_node.new(db=db, name="Tango", height=self.the_value)
59+
await another_node.save(db=db)
60+
61+
await self._validate_no_duplicate_edges(db=db, node=another_node, attribute_name="height")
62+
63+
async def test_updated_node_avoids_duplicate_edges(
64+
self, db: InfrahubDatabase, car_person_schema: SchemaBranch, node_with_duplicate_edges: Node
65+
) -> None:
66+
another_node = await Node.init(db=db, schema="TestPerson")
67+
await another_node.new(db=db, name="Cash", height=self.the_value - 1)
68+
await another_node.save(db=db)
69+
70+
another_node.height.value = self.the_value
71+
await another_node.save(db=db)
72+
73+
await self._validate_no_duplicate_edges(db=db, node=another_node, attribute_name="height")

0 commit comments

Comments
 (0)