*** Settings *** Documentation Resource DAG Linking and Discovery Tests Library Process Library OperatingSystem *** Variables *** ${PYTHON} python *** Test Cases *** Link Child And Verify Tree [Documentation] Link a child resource and verify it appears in children list ${script}= Catenate SEPARATOR=\n ... import json ... from datetime import datetime, UTC ... from sqlalchemy import create_engine, event ... from sqlalchemy.orm import sessionmaker ... from cleveragents.infrastructure.database.models import Base ... from cleveragents.infrastructure.database.repositories import ResourceTypeRepository, ResourceRepository ... from cleveragents.domain.models.core.resource_type import ResourceTypeSpec, ResourceKind, SandboxStrategy ... from cleveragents.domain.models.core.resource import Resource, PhysVirt, ResourceCapabilities ... engine = create_engine("sqlite:///:memory:") ... @event.listens_for(engine, "connect") ... def _fk(conn, _): conn.cursor().execute("PRAGMA foreign_keys=ON") ... Base.metadata.create_all(engine) ... factory = sessionmaker(bind=engine) ... shared_session = factory() ... rt_repo = ResourceTypeRepository(lambda: shared_session) ... res_repo = ResourceRepository(lambda: shared_session) ... parent_spec = ResourceTypeSpec(name="robot/dag-parent", description="Parent", resource_kind=ResourceKind.PHYSICAL, sandbox_strategy=SandboxStrategy.NONE, user_addable=True, cli_args=[], parent_types=[], child_types=["robot/dag-child"], auto_discovery=None, equivalence=None, handler=None, capabilities={"read": True, "write": True, "sandbox": True, "checkpoint": False}, built_in=False) ... child_spec = ResourceTypeSpec(name="robot/dag-child", description="Child", resource_kind=ResourceKind.PHYSICAL, sandbox_strategy=SandboxStrategy.NONE, user_addable=True, cli_args=[], parent_types=[], child_types=[], auto_discovery=None, equivalence=None, handler=None, capabilities={"read": True, "write": True, "sandbox": True, "checkpoint": False}, built_in=False) ... rt_repo.create(parent_spec) ... rt_repo.create(child_spec) ... p = Resource(resource_id="01HDAGR0B0T0000000PARENT01", name=None, resource_type_name="robot/dag-parent", classification=PhysVirt.PHYSICAL, properties={}, location=None, capabilities=ResourceCapabilities(), created_at=datetime.now(tz=UTC), updated_at=datetime.now(tz=UTC)) ... c = Resource(resource_id="01HDAGR0B0T00000CHXND00001", name=None, resource_type_name="robot/dag-child", classification=PhysVirt.PHYSICAL, properties={}, location=None, capabilities=ResourceCapabilities(), created_at=datetime.now(tz=UTC), updated_at=datetime.now(tz=UTC)) ... res_repo.create(p) ... res_repo.create(c) ... res_repo.link_child("01HDAGR0B0T0000000PARENT01", "01HDAGR0B0T00000CHXND00001") ... children = res_repo.get_children("01HDAGR0B0T0000000PARENT01") ... assert len(children) == 1, f"Expected 1 child, got {len(children)}" ... assert children[0].resource_id == "01HDAGR0B0T00000CHXND00001" ... shared_session.close() ... print("Link child and verify tree passed") ${result}= Run Process ${PYTHON} -c ${script} timeout=60s on_timeout=kill Should Be Equal As Integers ${result.rc} 0 Link test failed: ${result.stderr} Should Contain ${result.stdout} Link child and verify tree passed Cycle Detection Rejects A To B To A [Documentation] Linking A->B then B->A should raise CycleDetectedError ${script}= Catenate SEPARATOR=\n ... from datetime import datetime, UTC ... from sqlalchemy import create_engine, event ... from sqlalchemy.orm import sessionmaker ... from cleveragents.infrastructure.database.models import Base ... from cleveragents.infrastructure.database.repositories import ResourceTypeRepository, ResourceRepository, CycleDetectedError ... from cleveragents.domain.models.core.resource_type import ResourceTypeSpec, ResourceKind, SandboxStrategy ... from cleveragents.domain.models.core.resource import Resource, PhysVirt, ResourceCapabilities ... engine = create_engine("sqlite:///:memory:") ... @event.listens_for(engine, "connect") ... def _fk(conn, _): conn.cursor().execute("PRAGMA foreign_keys=ON") ... Base.metadata.create_all(engine) ... factory = sessionmaker(bind=engine) ... shared_session = factory() ... rt_repo = ResourceTypeRepository(lambda: shared_session) ... res_repo = ResourceRepository(lambda: shared_session) ... spec = ResourceTypeSpec(name="robot/cycle-type", description="Cycle", resource_kind=ResourceKind.PHYSICAL, sandbox_strategy=SandboxStrategy.NONE, user_addable=True, cli_args=[], parent_types=[], child_types=["robot/cycle-type"], auto_discovery=None, equivalence=None, handler=None, capabilities={"read": True, "write": True, "sandbox": True, "checkpoint": False}, built_in=False) ... rt_repo.create(spec) ... a = Resource(resource_id="01HDAGCYC000000000000000A1", name=None, resource_type_name="robot/cycle-type", classification=PhysVirt.PHYSICAL, properties={}, location=None, capabilities=ResourceCapabilities(), created_at=datetime.now(tz=UTC), updated_at=datetime.now(tz=UTC)) ... b = Resource(resource_id="01HDAGCYC000000000000000B1", name=None, resource_type_name="robot/cycle-type", classification=PhysVirt.PHYSICAL, properties={}, location=None, capabilities=ResourceCapabilities(), created_at=datetime.now(tz=UTC), updated_at=datetime.now(tz=UTC)) ... res_repo.create(a) ... res_repo.create(b) ... res_repo.link_child("01HDAGCYC000000000000000A1", "01HDAGCYC000000000000000B1") ... try: ... ${SPACE * 4}res_repo.link_child("01HDAGCYC000000000000000B1", "01HDAGCYC000000000000000A1") ... ${SPACE * 4}assert False, "Should have raised CycleDetectedError" ... except CycleDetectedError: ... ${SPACE * 4}print("Cycle detection passed") ... finally: ... ${SPACE * 4}shared_session.close() ${result}= Run Process ${PYTHON} -c ${script} timeout=60s on_timeout=kill Should Be Equal As Integers ${result.rc} 0 Cycle test failed: ${result.stderr} Should Contain ${result.stdout} Cycle detection passed Auto Discover Children [Documentation] Auto-discover creates child resources per type rules ${script}= Catenate SEPARATOR=\n ... import json ... from datetime import datetime, UTC ... from sqlalchemy import create_engine, event ... from sqlalchemy.orm import sessionmaker ... from cleveragents.infrastructure.database.models import Base ... from cleveragents.infrastructure.database.repositories import ResourceTypeRepository, ResourceRepository ... from cleveragents.domain.models.core.resource_type import ResourceTypeSpec, ResourceKind, SandboxStrategy ... from cleveragents.domain.models.core.resource import Resource, PhysVirt, ResourceCapabilities ... engine = create_engine("sqlite:///:memory:") ... @event.listens_for(engine, "connect") ... def _fk(conn, _): conn.cursor().execute("PRAGMA foreign_keys=ON") ... Base.metadata.create_all(engine) ... factory = sessionmaker(bind=engine) ... shared_session = factory() ... rt_repo = ResourceTypeRepository(lambda: shared_session) ... res_repo = ResourceRepository(lambda: shared_session) ... parent_spec = ResourceTypeSpec(name="robot/disc-parent", description="Discoverer", resource_kind=ResourceKind.PHYSICAL, sandbox_strategy=SandboxStrategy.NONE, user_addable=True, cli_args=[], parent_types=[], child_types=["robot/disc-child"], auto_discovery={"enabled": True, "rules": [{"type": "robot/disc-child", "pattern": "*"}]}, equivalence=None, handler=None, capabilities={"read": True, "write": True, "sandbox": True, "checkpoint": False}, built_in=False) ... child_spec = ResourceTypeSpec(name="robot/disc-child", description="Discovered", resource_kind=ResourceKind.PHYSICAL, sandbox_strategy=SandboxStrategy.NONE, user_addable=True, cli_args=[], parent_types=[], child_types=[], auto_discovery=None, equivalence=None, handler=None, capabilities={"read": True, "write": True, "sandbox": True, "checkpoint": False}, built_in=False) ... rt_repo.create(parent_spec) ... rt_repo.create(child_spec) ... p = Resource(resource_id="01HDAGR0B0TDSC00PARENT0001", name=None, resource_type_name="robot/disc-parent", classification=PhysVirt.PHYSICAL, properties={}, location=None, capabilities=ResourceCapabilities(), created_at=datetime.now(tz=UTC), updated_at=datetime.now(tz=UTC)) ... res_repo.create(p) ... created = res_repo.auto_discover_children("01HDAGR0B0TDSC00PARENT0001") ... assert len(created) >= 1, f"Expected >=1 children, got {len(created)}" ... assert created[0].resource_type_name == "robot/disc-child" ... children = res_repo.get_children("01HDAGR0B0TDSC00PARENT0001") ... assert len(children) >= 1, f"Expected >=1 linked children, got {len(children)}" ... shared_session.close() ... print("Auto discover children passed") ${result}= Run Process ${PYTHON} -c ${script} timeout=60s on_timeout=kill Should Be Equal As Integers ${result.rc} 0 Auto discover test failed: ${result.stderr} Should Contain ${result.stdout} Auto discover children passed *** Keywords ***