f2f7aa5dc9
Implement multiple Stage A/B/E/SEC milestones for the v3 lifecycle system: - Stage A5.3+A5.4: Add LifecycleActionModel and LifecyclePlanModel SQLAlchemy models with to_domain()/from_domain() conversion methods - Stage A5.6: Implement ActionRepository with full CRUD, namespace/state queries, referential integrity checks, and retry decorator - Stage E1: Add subplan domain models (ExecutionMode, SubplanMergeStrategy, SubplanConfig, SubplanStatus, SubplanAttempt, SubplanFailureHandler) with computed properties on Plan (is_subplan, is_root_plan, depth, has_subplans) - Stage A6: Add AutomationLevel enum (MANUAL, REVIEW_BEFORE_APPLY, FULL_AUTOMATION), settings integration, PlanLifecycleService auto-progression, pause/resume, and CLI commands (--automation-level, set-automation-level) - Stage SEC1: Remove eval()/exec() from stream_router.py, replace with named operation and transform registries; code blocks and unregistered transforms now raise StreamRoutingError - Add langchain-anthropic dependency - Update BDD tests for security changes and relax ADR directory requirement
112 lines
5.8 KiB
Gherkin
112 lines
5.8 KiB
Gherkin
Feature: Validation test fixtures
|
|
As a QA engineer
|
|
I want to validate that code sanitization, model validation, and input coercion handle edge cases
|
|
So that edge case project structures and malformed input data are properly rejected
|
|
|
|
# NOTE: Sections 1, 1b, 2, and 2b (AST security validation, RestrictedPython,
|
|
# Lambda AST validation) were removed as part of SEC1. eval()/exec() are no
|
|
# longer used in stream_router.py; the SEC1 approach uses named operation and
|
|
# transform registries instead. See features/security_eval.feature for the
|
|
# replacement tests.
|
|
|
|
# ──────────────────────────────────────────────────
|
|
# Section 3: Invalid code samples - Python content sanitization
|
|
# ──────────────────────────────────────────────────
|
|
|
|
Scenario: Sanitize valid Python passes through unchanged
|
|
Given I have a plan service for sanitization tests
|
|
When I sanitize the python content "x = 1 + 2"
|
|
Then the sanitized content should be "x = 1 + 2"
|
|
And the sanitization error should be None
|
|
And the sanitization reason should be None
|
|
|
|
Scenario: Sanitize Python with markdown code fences
|
|
Given I have a plan service for sanitization tests
|
|
When I sanitize the python content with code fences wrapping "x = 42"
|
|
Then the sanitized content should be "x = 42"
|
|
And the sanitization error should be None
|
|
And the sanitization reason should be "code_fence_removed"
|
|
|
|
Scenario: Sanitize non-Python prose falls back to docstring wrapping
|
|
Given I have a plan service for sanitization tests
|
|
When I sanitize the python content "This is just plain English text, not code."
|
|
Then the sanitization error should be None
|
|
And the sanitization reason should be "docstring_wrapped"
|
|
|
|
Scenario: Sanitize irrecoverable syntax returns error
|
|
Given I have a plan service for sanitization tests
|
|
When I sanitize python content containing a null byte
|
|
Then the sanitization error should not be None
|
|
|
|
# ──────────────────────────────────────────────────
|
|
# Section 4: Edge case project structures - Project model validation
|
|
# ──────────────────────────────────────────────────
|
|
|
|
Scenario: Project rejects name with special characters
|
|
When I try to create a project with name "my@project"
|
|
Then a project validation error should be raised mentioning "alphanumeric"
|
|
|
|
Scenario: Project rejects name with slashes
|
|
When I try to create a project with name "my/project"
|
|
Then a project validation error should be raised mentioning "alphanumeric"
|
|
|
|
Scenario: Project rejects name with exclamation
|
|
When I try to create a project with name "project!"
|
|
Then a project validation error should be raised mentioning "alphanumeric"
|
|
|
|
Scenario: Project accepts name with hyphens underscores and spaces
|
|
When I create a project fixture with name "my-project_v2 final"
|
|
Then the project should be created with that name
|
|
|
|
Scenario: Project resolves relative path to absolute
|
|
When I create a project with relative path "relative/path"
|
|
Then the project fixture path should be absolute
|
|
|
|
Scenario: Project rejects empty name
|
|
When I try to create a project with empty name
|
|
Then a project validation error should be raised
|
|
|
|
# ──────────────────────────────────────────────────
|
|
# Section 5: Malformed input data - Change list coercion
|
|
# ──────────────────────────────────────────────────
|
|
|
|
Scenario: Coerce empty change list returns empty list
|
|
Given I have a plan service for coercion tests
|
|
When I coerce an empty change list
|
|
Then the coerced result should be an empty list
|
|
|
|
Scenario: Coerce mixed dict and Change entries
|
|
Given I have a plan service for coercion tests
|
|
When I coerce a list with one dict entry and one Change entry
|
|
Then the coerced result should have 2 changes
|
|
|
|
Scenario: Coerce non-list input raises PlanError
|
|
Given I have a plan service for coercion tests
|
|
When I try to coerce a non-list input
|
|
Then a PlanError should be raised mentioning "invalid change payload"
|
|
|
|
Scenario: Coerce list with non-change non-dict entry raises PlanError
|
|
Given I have a plan service for coercion tests
|
|
When I try to coerce a list containing an integer
|
|
Then a PlanError should be raised mentioning "non-change entry"
|
|
|
|
# ──────────────────────────────────────────────────
|
|
# Section 6: Malformed input data - ActionArgument parsing
|
|
# ──────────────────────────────────────────────────
|
|
|
|
Scenario: Parse argument with too few parts
|
|
When I try to parse action argument fixture "onlyname"
|
|
Then an argument fixture parse error should be raised
|
|
|
|
Scenario: Parse argument with invalid type
|
|
When I try to parse action argument fixture "name:badtype:required:desc"
|
|
Then an argument fixture parse error should be raised
|
|
|
|
Scenario: Parse argument with invalid requirement
|
|
When I try to parse action argument fixture "name:str:sometimes:desc"
|
|
Then an argument fixture parse error should be raised
|
|
|
|
Scenario: Parse argument with reserved keyword name
|
|
When I try to create argument with name "class"
|
|
Then the argument name should be accepted as valid identifier
|