Files

167 lines
7.4 KiB
Gherkin

@phase1 @domain @repository @resource_dag
Feature: Resource DAG Linking and Discovery
As a system operator managing resource hierarchies
I want to link resources in a directed acyclic graph
So that parent-child relationships are enforced with type safety
Background:
Given a clean resource DAG database
And a resource type repository for DAG tests
And a resource repository for DAG tests
# ---------------------------------------------------------------------------
# link_child / unlink_child basic operations
# ---------------------------------------------------------------------------
@dag_link
Scenario: Link a child resource to a parent
Given a DAG parent type "dag/parent-type" allowing children '["dag/child-type"]'
And a DAG child type "dag/child-type"
And a DAG resource "P1" typed "dag/parent-type"
And a DAG resource "C1" typed "dag/child-type"
When DAG child "C1" is linked to parent "P1"
Then the DAG link should succeed without error
And DAG children of "P1" should include "C1"
@dag_unlink
Scenario: Unlink a child resource from a parent
Given a DAG parent type "dag/parent-type" allowing children '["dag/child-type"]'
And a DAG child type "dag/child-type"
And a DAG resource "P1" typed "dag/parent-type"
And a DAG resource "C1" typed "dag/child-type"
And DAG child "C1" is already linked to parent "P1"
When DAG child "C1" is unlinked from parent "P1"
Then the DAG unlink should succeed without error
And DAG children of "P1" should be empty
@dag_link @error_handling
Scenario: Linking a non-existent parent raises an error
Given a DAG child type "dag/child-type"
And a DAG resource "C1" typed "dag/child-type"
When DAG linking child "C1" to missing parent "MISSING_ID_00000000000000"
Then a DAG ResourceNotFoundRepoError should be raised
@dag_link @error_handling
Scenario: Linking a non-existent child raises an error
Given a DAG parent type "dag/parent-type" allowing children '["dag/child-type"]'
And a DAG resource "P1" typed "dag/parent-type"
When DAG linking missing child "MISSING_ID_00000000000000" to parent "P1"
Then a DAG ResourceNotFoundRepoError should be raised
@dag_link @error_handling
Scenario: Duplicate link raises an error
Given a DAG parent type "dag/parent-type" allowing children '["dag/child-type"]'
And a DAG child type "dag/child-type"
And a DAG resource "P1" typed "dag/parent-type"
And a DAG resource "C1" typed "dag/child-type"
And DAG child "C1" is already linked to parent "P1"
When DAG child "C1" is linked to parent "P1" again
Then a DAG DuplicateResourceLinkError should be raised
# ---------------------------------------------------------------------------
# Cycle detection
# ---------------------------------------------------------------------------
@dag_cycle
Scenario: Self-link is rejected
Given a DAG parent type "dag/parent-type" allowing children '["dag/parent-type"]'
And a DAG resource "P1" typed "dag/parent-type"
When DAG resource "P1" is linked to itself
Then a DAG CycleDetectedError should be raised
@dag_cycle
Scenario: Direct cycle A->B->A is rejected
Given a DAG parent type "dag/parent-type" allowing children '["dag/parent-type"]'
And a DAG resource "A" typed "dag/parent-type"
And a DAG resource "B" typed "dag/parent-type"
And DAG child "B" is already linked to parent "A"
When DAG child "A" is linked to parent "B"
Then a DAG CycleDetectedError should be raised
@dag_cycle
Scenario: Transitive cycle A->B->C->A is rejected
Given a DAG parent type "dag/parent-type" allowing children '["dag/parent-type"]'
And a DAG resource "A" typed "dag/parent-type"
And a DAG resource "B" typed "dag/parent-type"
And a DAG resource "C" typed "dag/parent-type"
And DAG child "B" is already linked to parent "A"
And DAG child "C" is already linked to parent "B"
When DAG child "A" is linked to parent "C"
Then a DAG CycleDetectedError should be raised
# ---------------------------------------------------------------------------
# Type compatibility enforcement
# ---------------------------------------------------------------------------
@dag_type_compat
Scenario: Linking incompatible types is rejected
Given a DAG parent type "dag/parent-type" allowing children '["dag/child-type"]'
And a DAG child type "dag/other-type"
And a DAG resource "P1" typed "dag/parent-type"
And a DAG resource "C1" typed "dag/other-type"
When DAG child "C1" is linked to parent "P1"
Then a DAG TypeIncompatibleError should be raised
@dag_type_compat
Scenario: Linking compatible types succeeds
Given a DAG parent type "dag/parent-type" allowing children '["dag/child-type"]'
And a DAG child type "dag/child-type"
And a DAG resource "P1" typed "dag/parent-type"
And a DAG resource "C1" typed "dag/child-type"
When DAG child "C1" is linked to parent "P1"
Then the DAG link should succeed without error
# ---------------------------------------------------------------------------
# auto_discover_children
# ---------------------------------------------------------------------------
@dag_auto_discover
Scenario: Auto-discover creates child resources per type rules
Given a DAG parent type "dag/discover-parent" with auto-discovery for "dag/discover-child"
And a DAG child type "dag/discover-child"
And a DAG resource "P1" typed "dag/discover-parent"
When DAG auto_discover_children is called for "P1"
Then at least 1 DAG child should be created
And DAG created children should be typed "dag/discover-child"
And DAG created children should be linked to "P1"
@dag_auto_discover
Scenario: Auto-discover with no rules creates nothing
Given a DAG parent type "dag/no-disc-parent" without auto-discovery
And a DAG resource "P1" typed "dag/no-disc-parent"
When DAG auto_discover_children is called for "P1"
Then 0 DAG children should be created
@dag_auto_discover @error_handling
Scenario: Auto-discover for non-existent resource raises error
When DAG auto_discover_children is called for missing "MISSING_ID_00000000000000"
Then a DAG ResourceNotFoundRepoError should be raised
# ---------------------------------------------------------------------------
# Tree traversal
# ---------------------------------------------------------------------------
@dag_traversal
Scenario: Get children returns all direct children
Given a DAG parent type "dag/parent-type" allowing children '["dag/child-type"]'
And a DAG child type "dag/child-type"
And a DAG resource "P1" typed "dag/parent-type"
And a DAG resource "C1" typed "dag/child-type"
And a DAG resource "C2" typed "dag/child-type"
And DAG child "C1" is already linked to parent "P1"
And DAG child "C2" is already linked to parent "P1"
When DAG children of "P1" are retrieved
Then 2 DAG children should be returned
@dag_traversal
Scenario: Get parents returns all direct parents
Given a DAG parent type "dag/parent-type" allowing children '["dag/child-type"]'
And a DAG child type "dag/child-type"
And a DAG resource "P1" typed "dag/parent-type"
And a DAG resource "P2" typed "dag/parent-type"
And a DAG resource "C1" typed "dag/child-type"
And DAG child "C1" is already linked to parent "P1"
And DAG child "C1" is already linked to parent "P2"
When DAG parents of "C1" are retrieved
Then 2 DAG parents should be returned