4e37da2471
Merge the two separate database transactions in ensure_default_mock_actor() into a single atomic transaction to prevent Time-of-Check-Time-of-Use (TOCTOU) race conditions in concurrent environments (e.g., parallel test workers). The original implementation had a gap between checking for an existing default actor and creating a new mock actor. In concurrent scenarios, multiple threads could both observe no default and attempt to create one, leading to potential constraint violations or inconsistent state. The fix consolidates both operations into a single transaction, ensuring that the check and creation are atomic and safe for concurrent callers. Added BDD test scenarios to verify idempotency and concurrent safety: - Idempotency: calling ensure_default_mock_actor multiple times produces same result - Existing default safety: respects existing default actors - Single actor creation: ensures only one mock actor is created Closes #8448
116 lines
5.4 KiB
Gherkin
116 lines
5.4 KiB
Gherkin
Feature: Actor service coverage
|
|
As a developer
|
|
I want actor service behaviors covered
|
|
So that custom and built-in actors are validated
|
|
|
|
Scenario: Normalizes missing prefix to local
|
|
Given an actor service with stubbed dependencies
|
|
When I normalize actor name "custom"
|
|
Then the normalized actor name should be "local/custom"
|
|
|
|
Scenario Outline: Invalid actor names are rejected
|
|
Given an actor service with stubbed dependencies
|
|
When I try to normalize actor name "<name>" without allowing built-ins
|
|
Then a ValidationError should be raised containing "<message>"
|
|
|
|
Examples:
|
|
| name | message |
|
|
| | cannot be empty |
|
|
| local/extra/slash/name | exactly one '/' separator |
|
|
| /missing-id | include both prefix and identifier |
|
|
| remote/model | 'local/<id>' naming pattern |
|
|
|
|
Scenario: Listing actors returns stored entries
|
|
Given an actor service with stubbed dependencies
|
|
And existing actors named "local/first" and "local/second"
|
|
When I list all actors
|
|
Then I should receive actors ["local/first", "local/second"]
|
|
|
|
Scenario: Getting an unknown actor raises not found
|
|
Given an actor service with stubbed dependencies
|
|
When I attempt to fetch actor "vendor/model"
|
|
Then a NotFoundError should be raised for the actor
|
|
|
|
Scenario: Upserting cannot overwrite built-in actors
|
|
Given an actor service with stubbed dependencies
|
|
And a built-in actor named "vendor/model" already exists
|
|
When I attempt to upsert "vendor/model" as custom
|
|
Then a BusinessRuleViolation should be raised
|
|
|
|
Scenario: Upserting with set_default marks actor as default
|
|
Given an actor service with stubbed dependencies
|
|
And an actor named "local/defaultable" exists
|
|
When I upsert "local/defaultable" with set_default
|
|
Then the stored actor "local/defaultable" should be default
|
|
|
|
Scenario: Removing missing actors raises not found
|
|
Given an actor service with stubbed dependencies
|
|
When I try to remove actor "local/missing"
|
|
Then a NotFoundError should be raised for the actor
|
|
|
|
Scenario: Removing protected actors surfaces business rule violation
|
|
Given an actor service with stubbed dependencies
|
|
And a built-in actor named "local/protected" already exists
|
|
When I try to remove actor "local/protected"
|
|
Then a BusinessRuleViolation should be raised
|
|
|
|
Scenario: Setting default actor requires existing entry
|
|
Given an actor service with stubbed dependencies
|
|
When I set default actor "local/absent"
|
|
Then a NotFoundError should be raised for the actor
|
|
|
|
Scenario: Setting default actor updates repository default
|
|
Given an actor service with stubbed dependencies
|
|
And an actor named "local/current" exists
|
|
When I set default actor "local/current"
|
|
Then the stored actor "local/current" should be default
|
|
|
|
Scenario: Ensuring default mock actor returns existing default
|
|
Given an actor service with stubbed dependencies
|
|
And an actor named "local/existing-default" exists as default
|
|
When I ensure the default mock actor with env value "true"
|
|
Then the returned actor name should be "local/existing-default"
|
|
And no additional actors should be created
|
|
|
|
Scenario: Ensuring default mock actor promotes existing mock
|
|
Given an actor service with stubbed dependencies
|
|
And a mock actor named "local/mock-default" exists without default flag
|
|
When I ensure the default mock actor with env value "1"
|
|
Then the returned actor name should be "local/mock-default"
|
|
And the stored actor "local/mock-default" should be default
|
|
|
|
Scenario: Ensuring default mock actor creates a new default when missing
|
|
Given an actor service with stubbed dependencies
|
|
When I ensure the default mock actor with env value "yes"
|
|
Then the returned actor name should be "local/mock-default"
|
|
And the stored actor "local/mock-default" should be default
|
|
|
|
Scenario: Ensuring default mock actor is a no-op when env disabled
|
|
Given an actor service with stubbed dependencies
|
|
And any existing actors are cleared
|
|
When I ensure the default mock actor with env value "0"
|
|
Then the result should be None
|
|
|
|
Scenario: Ensuring default mock actor is idempotent
|
|
Given an actor service with stubbed dependencies
|
|
When I ensure the default mock actor with env value "true"
|
|
Then the returned actor name should be "local/mock-default"
|
|
And the stored actor "local/mock-default" should be default
|
|
When I ensure the default mock actor with env value "true" again
|
|
Then the returned actor name should be "local/mock-default"
|
|
And only one "local/mock-default" actor should exist
|
|
|
|
Scenario: Ensuring default mock actor with existing default is safe
|
|
Given an actor service with stubbed dependencies
|
|
And an actor named "local/existing-default" exists as default
|
|
When I ensure the default mock actor with env value "true"
|
|
Then the returned actor name should be "local/existing-default"
|
|
And the stored actor "local/existing-default" should be default
|
|
And only one default actor should exist
|
|
|
|
Scenario: Ensuring default mock actor creates exactly one actor
|
|
Given an actor service with stubbed dependencies
|
|
When I ensure the default mock actor with env value "true"
|
|
Then exactly one actor should exist
|
|
And the stored actor "local/mock-default" should be default
|