# This test captures bug #991 - AuditService._ensure_session() TOCTOU race.
#
# Originally tagged @tdd_expected_fail while the bug was unfixed (see TDD
# issue #1095).  The @tdd_expected_fail tag was removed when the fix for
# #991 was merged.
#
# See: https://git.cleverthis.com/cleveragents/cleveragents-core/issues/991

@tdd_issue @tdd_issue_991
Feature: TDD Bug #991 - AuditService._ensure_session() TOCTOU race
  AuditService._ensure_session() used to check if self._session is None,
  then create an engine, run create_all, build a sessionmaker, and assign
  self._session - all without a threading.Lock.  If two threads called
  _ensure_session() concurrently, both saw self._session as None, both
  created separate engines and sessions, and the second assignment won,
  leaking the first engine/session.

  The fix adds a threading.Lock with double-checked locking so that only
  the first thread to acquire the lock performs the initialisation.

  This test proves the fix works by launching multiple threads that call
  _ensure_session() simultaneously via a threading.Barrier and verifying
  that create_engine is called exactly once.

  Scenario: Concurrent _ensure_session() calls must create only one engine
    Given an AuditService with no pre-injected session and a temp database
    When 10 threads call _ensure_session concurrently through a barrier
    Then create_engine should have been called exactly once
    And all 10 threads should have received a valid session
