test: add TDD bug-capture test for #992 — DI container audit cache failure
CI / lint (pull_request) Failing after 5s
CI / typecheck (pull_request) Failing after 5s
CI / coverage (pull_request) Has been skipped
CI / security (pull_request) Failing after 5s
CI / quality (pull_request) Failing after 2s
CI / unit_tests (pull_request) Failing after 2s
CI / docker (pull_request) Has been skipped
CI / integration_tests (pull_request) Failing after 2s
CI / e2e_tests (pull_request) Failing after 2s
CI / build (pull_request) Failing after 4s
CI / helm (pull_request) Failing after 4s
CI / status-check (pull_request) Failing after 1s
CI / benchmark-publish (pull_request) Has been skipped
CI / benchmark-regression (pull_request) Has been skipped
CI / lint (pull_request) Failing after 5s
CI / typecheck (pull_request) Failing after 5s
CI / coverage (pull_request) Has been skipped
CI / security (pull_request) Failing after 5s
CI / quality (pull_request) Failing after 2s
CI / unit_tests (pull_request) Failing after 2s
CI / docker (pull_request) Has been skipped
CI / integration_tests (pull_request) Failing after 2s
CI / e2e_tests (pull_request) Failing after 2s
CI / build (pull_request) Failing after 4s
CI / helm (pull_request) Failing after 4s
CI / status-check (pull_request) Failing after 1s
CI / benchmark-publish (pull_request) Has been skipped
CI / benchmark-regression (pull_request) Has been skipped
Add a dedicated Behave bug-capture scenario that reproduces the get_container() audit subscriber initialization caching defect from #992. The steps patch container construction so audit subscriber initialization fails once then succeeds, call get_container() twice, and assert a retry should occur on the second access. The assertion intentionally fails against current behavior (only one initialization attempt), and the @tdd_expected_fail + @tdd_bug + @tdd_bug_992 tags invert that failure to a CI pass until the production fix lands. This creates a precise regression guard that will only pass without inversion when retry semantics are implemented. ISSUES CLOSED: #1096
This commit is contained in:
@@ -0,0 +1,70 @@
|
||||
"""Step definitions for tdd_di_audit_cache_failure.feature.
|
||||
|
||||
This test captures bug #992: ``get_container()`` caches a container even when
|
||||
eager audit subscriber initialization fails once during startup, and it does
|
||||
not retry on subsequent ``get_container()`` calls.
|
||||
|
||||
The scenario is tagged ``@tdd_expected_fail`` so the expected assertion failure
|
||||
(which proves the bug still exists) is inverted to a CI pass until the fix for
|
||||
#992 lands. After the fix, remove ``@tdd_expected_fail``.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
|
||||
from behave import given, then, when
|
||||
from behave.runner import Context
|
||||
|
||||
|
||||
@given("g992- a container whose audit subscriber init fails once then succeeds")
|
||||
def step_given_container_with_transient_audit_init_failure(context: Context) -> None:
|
||||
"""Patch container factory so audit subscriber fails once, then succeeds."""
|
||||
from cleveragents.application import container as container_module
|
||||
|
||||
class FakeContainer:
|
||||
"""Minimal fake container to track audit subscriber initialization calls."""
|
||||
|
||||
def __init__(self) -> None:
|
||||
self.audit_init_attempts = 0
|
||||
|
||||
def audit_event_subscriber(self) -> object:
|
||||
"""Fail first call (simulating DB not ready), then succeed."""
|
||||
self.audit_init_attempts += 1
|
||||
if self.audit_init_attempts == 1:
|
||||
raise RuntimeError("database not ready yet")
|
||||
return object()
|
||||
|
||||
context.g992_original_container_class = container_module.Container
|
||||
container_module.Container = FakeContainer
|
||||
|
||||
def _cleanup() -> None:
|
||||
container_module.Container = context.g992_original_container_class
|
||||
container_module.reset_container()
|
||||
|
||||
context.add_cleanup(_cleanup)
|
||||
container_module.reset_container()
|
||||
|
||||
|
||||
@when("g992- I call get_container twice")
|
||||
def step_when_call_get_container_twice(context: Context) -> None:
|
||||
"""Call get_container twice and keep references for assertions."""
|
||||
from cleveragents.application.container import get_container
|
||||
|
||||
context.g992_first_container = get_container()
|
||||
context.g992_second_container = get_container()
|
||||
|
||||
|
||||
@then("g992- audit subscriber init should have been attempted twice")
|
||||
def step_then_audit_subscriber_should_be_retried(context: Context) -> None:
|
||||
"""Expect retry on second access after first initialization failure."""
|
||||
first = context.g992_first_container
|
||||
second = context.g992_second_container
|
||||
assert first is second, "Expected get_container() to return a singleton instance"
|
||||
|
||||
attempts: Any = getattr(first, "audit_init_attempts", None)
|
||||
assert attempts == 2, (
|
||||
"Bug #992: get_container() did not retry audit subscriber initialization "
|
||||
"after the first failure. Expected 2 attempts after two get_container() "
|
||||
f"calls, but observed {attempts}."
|
||||
)
|
||||
@@ -0,0 +1,21 @@
|
||||
@tdd_expected_fail @tdd_issue @tdd_issue_992
|
||||
Feature: TDD Bug #992 — get_container() caches failed audit subscriber initialization
|
||||
As a long-lived process using the shared DI container
|
||||
I want get_container() to retry audit subscriber initialization after an initial failure
|
||||
So that audit subscriptions are eventually registered once prerequisites become available
|
||||
|
||||
This feature captures bug #992. Today, get_container() eagerly calls
|
||||
audit_event_subscriber() only during first container creation. If that first call
|
||||
fails, the exception is logged and swallowed, but the global _container remains set.
|
||||
Subsequent get_container() calls return the cached container without retrying the
|
||||
subscriber initialization.
|
||||
|
||||
This scenario is intentionally tagged with @tdd_expected_fail until bug #992 is
|
||||
fixed. The underlying assertion fails (proving the bug exists) and the tag inversion
|
||||
mechanism converts that failure to a CI pass. Remove @tdd_expected_fail when #992 is
|
||||
fixed so this runs as a normal regression test.
|
||||
|
||||
Scenario: Bug #992 — get_container retries audit subscriber initialization after first failure
|
||||
Given g992- a container whose audit subscriber init fails once then succeeds
|
||||
When g992- I call get_container twice
|
||||
Then g992- audit subscriber init should have been attempted twice
|
||||
Reference in New Issue
Block a user