135481f9a6
CI / benchmark-publish (pull_request) Has been skipped
CI / lint (pull_request) Successful in 14s
CI / quality (pull_request) Successful in 18s
CI / build (pull_request) Successful in 16s
CI / unit_tests (pull_request) Failing after 25s
CI / security (pull_request) Successful in 34s
CI / typecheck (pull_request) Successful in 36s
CI / docker (pull_request) Has been skipped
CI / coverage (pull_request) Failing after 25s
CI / integration_tests (pull_request) Failing after 2m19s
CI / benchmark-regression (pull_request) Has been cancelled
- P2-1: Add field_validator('inherits') on ResourceTypeSpec
- P2-2: Remove 'properties' from _COLLECTION_FIELDS (scalar override)
- P2-3: Add behave scenarios for exception rollback paths
- P2-4: Add ordering comment to BUILTIN_TYPES
- P2-5: Define RegistryHost Protocol, remove type:ignore on mixins
- P2-6: Add if_not_exists=True on migration index creation
- P3-1: Use deque.popleft() in get_ancestors for O(1) BFS
- P3-2: Filter private attrs in _to_dict vars() fallback
- P3-3: Replace _handler_cache import with clear_handler_cache()
- P3-4: Add migration downgrade test for m6_004
- P3-5: Extract ResourceDagMixin to _resource_registry_dag.py
All files remain under 500-line CONTRIBUTING limit.
Lint, typecheck, and 85 behave scenarios pass.
160 lines
8.6 KiB
Gherkin
160 lines
8.6 KiB
Gherkin
Feature: Coverage boost for resource type inheritance service and resolver
|
|
As a developer
|
|
I want full coverage of inheritance-related service and resolver code paths
|
|
So that diff coverage meets the 97% threshold
|
|
|
|
# ── resource_registry_service.py: register_type with inherits ───────────
|
|
|
|
Scenario: register_type rejects type when parent is not registered
|
|
Given a fresh in-memory registry service for cov
|
|
And a YAML config for "acme/child" that inherits "nonexistent-parent" for cov
|
|
When I call register_type with that config for cov
|
|
Then a ValidationError should be raised mentioning "not registered" for cov
|
|
|
|
Scenario: register_type rejects type when chain validation fails
|
|
Given a fresh in-memory registry service for cov
|
|
And a YAML config for "acme/child" that inherits a type causing chain error for cov
|
|
When I call register_type with that config for cov
|
|
Then a ValidationError should be raised mentioning chain error for cov
|
|
|
|
Scenario: register_type rejects duplicate type name
|
|
Given a fresh in-memory registry service for cov
|
|
And a YAML config for a built-in type name "git-checkout" for cov
|
|
When I call register_type with that config for cov
|
|
Then a ValidationError should be raised mentioning "already exists" for cov
|
|
|
|
# ── resource_registry_service.py: remove_type guards ────────────────────
|
|
|
|
Scenario: remove_type rejects removal of built-in type
|
|
Given a fresh in-memory registry service for cov
|
|
When I call remove_type for "git-checkout" for cov
|
|
Then a ValidationError should be raised mentioning "built-in" for cov
|
|
|
|
Scenario: remove_type rejects removal when resources reference the type
|
|
Given a fresh in-memory registry service for cov
|
|
And a custom type "test/removable" is registered for cov
|
|
And a resource of type "test/removable" exists for cov
|
|
When I call remove_type for "test/removable" for cov
|
|
Then a ValidationError should be raised mentioning "resource(s) still reference" for cov
|
|
|
|
Scenario: remove_type rejects removal when subtypes exist
|
|
Given a fresh in-memory registry service for cov
|
|
And a custom type "test/parent" is registered for cov
|
|
And a child type "test/child" inheriting "test/parent" is registered for cov
|
|
When I call remove_type for "test/parent" for cov
|
|
Then a ResourceTypeParentRemovalError should be raised for cov
|
|
|
|
Scenario: remove_type succeeds for custom type with no dependents
|
|
Given a fresh in-memory registry service for cov
|
|
And a custom type "test/removable" is registered for cov
|
|
When I call remove_type for "test/removable" for cov
|
|
Then no error should be raised for cov
|
|
|
|
# ── resource_registry_service.py: resolve_type_inheritance_chain ────────
|
|
|
|
Scenario: resolve_type_inheritance_chain returns chain for inherited type
|
|
Given a fresh in-memory registry service for cov
|
|
When I call resolve_type_inheritance_chain for "devcontainer-instance" for cov
|
|
Then the chain should contain "devcontainer-instance" and "container-instance"
|
|
|
|
Scenario: resolve_type_inheritance_chain raises NotFoundError for unknown type
|
|
Given a fresh in-memory registry service for cov
|
|
When I call resolve_type_inheritance_chain for "nonexistent" for cov
|
|
Then a NotFoundError should be raised for cov
|
|
|
|
# ── resource_registry_service.py: is_subtype_of ────────────────────────
|
|
|
|
Scenario: is_subtype_of returns True for subtype relationship
|
|
Given a fresh in-memory registry service for cov
|
|
When I check is_subtype_of "devcontainer-instance" of "container-instance" for cov
|
|
Then the is_subtype_of result should be True for cov
|
|
|
|
Scenario: is_subtype_of returns False for unrelated types
|
|
Given a fresh in-memory registry service for cov
|
|
When I check is_subtype_of "git-checkout" of "fs-directory" for cov
|
|
Then the is_subtype_of result should be False for cov
|
|
|
|
# ── _resource_registry_ops.py: list_resources exact filter ─────────────
|
|
|
|
Scenario: list_resources with exact=True filters only the exact type
|
|
Given a fresh in-memory registry service for cov
|
|
And a resource of type "container-instance" exists for cov ops
|
|
When I call list_resources with type_name "container-instance" and exact=True for cov
|
|
Then the result list should contain only "container-instance" typed resources for cov
|
|
|
|
# ── _resource_registry_ops.py: link_child type mismatch ────────────────
|
|
|
|
Scenario: link_child rejects child whose type is not in allowed_child_types
|
|
Given a fresh in-memory registry service for cov
|
|
And two resources of incompatible types for cov ops
|
|
When I call link_child with incompatible types for cov ops
|
|
Then a ValidationError should be raised mentioning "not allowed" for cov
|
|
|
|
# ── _resource_registry_ops.py: get_resource_tree with type_filter ──────
|
|
|
|
Scenario: get_resource_tree with type_filter excludes non-matching children
|
|
Given a fresh in-memory registry service for cov
|
|
And a parent resource with children of mixed types for cov ops
|
|
When I call get_resource_tree with type_filter for cov ops
|
|
Then the tree should only contain children matching the filter for cov
|
|
|
|
# ── resolver.py: resolve_handler error paths ───────────────────────────
|
|
|
|
Scenario: resolve_handler raises on generic import error
|
|
When I call resolve_handler with a module that has an import error for cov
|
|
Then a HandlerResolutionError should be raised mentioning "Error importing" for cov
|
|
|
|
Scenario: resolve_handler raises on instantiation error
|
|
When I call resolve_handler with a class that fails to instantiate for cov
|
|
Then a HandlerResolutionError should be raised mentioning "Cannot instantiate" for cov
|
|
|
|
Scenario: resolve_handler raises on protocol non-conformance
|
|
When I call resolve_handler with a class that does not satisfy ResourceHandler for cov
|
|
Then a HandlerResolutionError should be raised mentioning "does not satisfy" for cov
|
|
|
|
Scenario: resolve_handler_polymorphic wraps chain errors
|
|
When I call resolve_handler_polymorphic with a broken chain for cov
|
|
Then a HandlerResolutionError should be raised mentioning "Cannot resolve handler" for cov
|
|
|
|
Scenario: resolve_handler_polymorphic walks chain to find ancestor handler
|
|
Given a type registry with child having no handler but ancestor has one for cov
|
|
When I call resolve_handler_polymorphic for the child type for cov
|
|
Then a valid handler should be returned for cov
|
|
|
|
# ── inheritance.py: _merge_dict and _to_dict fallback ──────────────────
|
|
|
|
Scenario: resolve_fields treats properties as scalar override (not merged)
|
|
Given a registry where parent has properties and child overrides one for cov
|
|
When I call resolve_fields for the child for cov
|
|
Then the child properties should replace parent properties for cov
|
|
|
|
Scenario: resolve_fields skips missing registry entries gracefully
|
|
Given a registry with a gap in the chain for cov
|
|
When I call resolve_fields for the type with a gap for cov
|
|
Then the result should still contain the available fields for cov
|
|
|
|
# ── Exception rollback paths (P2-3) ────────────────────────────────────
|
|
|
|
Scenario: remove_type rolls back on unexpected database error
|
|
Given a fresh in-memory registry service for cov
|
|
And a custom type "test/removable" is registered for cov
|
|
When I call remove_type for "test/removable" with a simulated commit error for cov
|
|
Then a RuntimeError should be raised for cov
|
|
|
|
Scenario: resolve_type_inheritance_chain converts ValueError to ValidationError
|
|
Given a fresh in-memory registry service for cov
|
|
When I call resolve_type_inheritance_chain with a cycle-induced ValueError for cov
|
|
Then a ValidationError should be raised mentioning "cycle" for cov
|
|
|
|
Scenario: register_resource rolls back on unexpected database error
|
|
Given a fresh in-memory registry service for cov
|
|
When I call register_resource with a simulated commit error for cov
|
|
Then a RuntimeError should be raised for cov
|
|
|
|
# ── Migration m6_004 downgrade (P3-4) ──────────────────────────────────
|
|
|
|
Scenario: m6_004 migration downgrade removes inherits column
|
|
Given an in-memory database with the inherits column applied
|
|
When I run the m6_004 downgrade
|
|
Then the resource_types table should not have an inherits column
|