diff options
| author | DanConwayDev <DanConwayDev@protonmail.com> | 2025-12-02 21:20:17 +0000 |
|---|---|---|
| committer | DanConwayDev <DanConwayDev@protonmail.com> | 2025-12-02 21:20:17 +0000 |
| commit | 72683beea066d066637e747c40dc859fb709babf (patch) | |
| tree | 2db3462ebbcb7501e56491148cc3ffa7aa294071 /grasp-audit/src/fixtures.rs | |
| parent | 5c10ca008413744b09136618eaa85275c997704c (diff) | |
refactor: rename AuditMode variants and change CLI default to shared
Breaking change: Renamed AuditMode enum variants for clarity:
- AuditMode::CI -> AuditMode::Isolated (fresh fixtures per test)
- AuditMode::Production -> AuditMode::Shared (reuse fixtures across tests)
Config constructors renamed (with deprecated aliases):
- AuditConfig::ci() -> AuditConfig::isolated()
- AuditConfig::production() -> AuditConfig::shared()
CLI default changed from 'ci' to 'shared' mode, which enables
fixture caching across tests. This fixes the issue where fixtures
were being re-created for every test in CLI mode.
Fixture caching behavior:
- Shared mode (CLI default): Uses client's cache, fixtures reused
- Isolated mode (for cargo test): Local cache per TestContext
Diffstat (limited to 'grasp-audit/src/fixtures.rs')
| -rw-r--r-- | grasp-audit/src/fixtures.rs | 63 |
1 files changed, 38 insertions, 25 deletions
diff --git a/grasp-audit/src/fixtures.rs b/grasp-audit/src/fixtures.rs index e5a80d7..cc2d2f6 100644 --- a/grasp-audit/src/fixtures.rs +++ b/grasp-audit/src/fixtures.rs | |||
| @@ -3,19 +3,25 @@ | |||
| 3 | //! This module provides a TestContext abstraction that manages prerequisite events | 3 | //! This module provides a TestContext abstraction that manages prerequisite events |
| 4 | //! differently based on the audit mode: | 4 | //! differently based on the audit mode: |
| 5 | //! | 5 | //! |
| 6 | //! - **CI Mode (Isolated)**: Creates fresh events for each test, ensuring complete isolation | 6 | //! - **Isolated Mode**: Creates fresh events for each test, ensuring complete isolation. |
| 7 | //! - **Production Mode (Shared)**: Reuses shared fixtures to minimize event publication | 7 | //! Use this for `cargo test` where tests run in parallel and need isolation. |
| 8 | //! - **Shared Mode**: Reuses shared fixtures across tests to minimize event publication. | ||
| 9 | //! Use this for CLI audit where tests run sequentially and build on each other. | ||
| 8 | //! | 10 | //! |
| 9 | //! # Cache Sharing Strategy | 11 | //! # Cache Sharing Strategy |
| 10 | //! | 12 | //! |
| 11 | //! The fixture cache lives on the `AuditClient`, not on `TestContext`. This provides | 13 | //! The caching behavior depends on the mode: |
| 12 | //! natural cache sharing semantics: | ||
| 13 | //! | 14 | //! |
| 14 | //! - **CLI mode**: Creates one `AuditClient` → fixtures shared across all tests | 15 | //! - **Shared mode** (default for CLI): Uses the client's fixture cache, shared across |
| 15 | //! - **cargo test**: Creates one `AuditClient` per test → fixtures isolated per test | 16 | //! all TestContext instances. Fixtures are created once and reused. |
| 17 | //! - **Isolated mode**: Each TestContext has its own local cache. Fixtures are created | ||
| 18 | //! fresh for each TestContext, providing complete test isolation. | ||
| 16 | //! | 19 | //! |
| 17 | //! This eliminates the need for global state while still enabling fixture reuse | 20 | //! # When to Use Each Mode |
| 18 | //! when appropriate. | 21 | //! |
| 22 | //! - **CLI audit tool**: Use Shared mode (default). Tests run sequentially and fixtures | ||
| 23 | //! build on each other efficiently. | ||
| 24 | //! - **cargo test**: Use Isolated mode. Tests run in parallel and need complete isolation. | ||
| 19 | //! | 25 | //! |
| 20 | //! # What is a Fixture? | 26 | //! # What is a Fixture? |
| 21 | //! A fixture represents the state of a repository on a grasp server (events and git refs) | 27 | //! A fixture represents the state of a repository on a grasp server (events and git refs) |
| @@ -36,7 +42,7 @@ | |||
| 36 | //! use grasp_audit::*; | 42 | //! use grasp_audit::*; |
| 37 | //! | 43 | //! |
| 38 | //! # async fn example() -> anyhow::Result<()> { | 44 | //! # async fn example() -> anyhow::Result<()> { |
| 39 | //! let config = AuditConfig::ci(); | 45 | //! let config = AuditConfig::shared(); // Use shared() for CLI, isolated() for cargo test |
| 40 | //! let client = AuditClient::new("ws://localhost:7000", config).await?; | 46 | //! let client = AuditClient::new("ws://localhost:7000", config).await?; |
| 41 | //! let ctx = TestContext::new(&client); | 47 | //! let ctx = TestContext::new(&client); |
| 42 | //! | 48 | //! |
| @@ -341,8 +347,8 @@ pub enum ContextMode { | |||
| 341 | impl From<AuditMode> for ContextMode { | 347 | impl From<AuditMode> for ContextMode { |
| 342 | fn from(mode: AuditMode) -> Self { | 348 | fn from(mode: AuditMode) -> Self { |
| 343 | match mode { | 349 | match mode { |
| 344 | AuditMode::CI => ContextMode::Isolated, | 350 | AuditMode::Isolated => ContextMode::Isolated, |
| 345 | AuditMode::Production => ContextMode::Shared, | 351 | AuditMode::Shared => ContextMode::Shared, |
| 346 | } | 352 | } |
| 347 | } | 353 | } |
| 348 | } | 354 | } |
| @@ -350,30 +356,37 @@ impl From<AuditMode> for ContextMode { | |||
| 350 | /// Test context for managing prerequisite events | 356 | /// Test context for managing prerequisite events |
| 351 | /// | 357 | /// |
| 352 | /// The TestContext provides mode-aware fixture management: | 358 | /// The TestContext provides mode-aware fixture management: |
| 353 | /// - In Isolated mode: Creates fresh events for each test | 359 | /// - In **Isolated mode**: Each TestContext has its own local cache, creating fresh |
| 354 | /// - In Shared mode: Caches and reuses events across tests | 360 | /// fixtures for each test. Use this for `cargo test` where tests run in parallel. |
| 361 | /// - In **Shared mode**: Uses the client's fixture cache, shared across all TestContexts. | ||
| 362 | /// Use this for CLI audit where tests run sequentially and build on each other. | ||
| 355 | /// | 363 | /// |
| 356 | /// # Cache Location | 364 | /// # Mode Selection |
| 357 | /// | 365 | /// |
| 358 | /// The fixture cache lives on `AuditClient`, not on `TestContext`. This means: | 366 | /// The mode is determined by `AuditConfig::mode`: |
| 359 | /// - Multiple `TestContext` instances from the same client share the cache | 367 | /// - `AuditConfig::isolated()` → Creates fresh fixtures per TestContext |
| 360 | /// - CLI mode (one client) naturally shares fixtures across all tests | 368 | /// - `AuditConfig::shared()` → Reuses fixtures across all TestContexts (default for CLI) |
| 361 | /// - Test mode (one client per test) naturally isolates fixtures | ||
| 362 | /// | 369 | /// |
| 363 | /// # Example | 370 | /// # Example |
| 364 | /// | 371 | /// |
| 365 | /// ```no_run | 372 | /// ```no_run |
| 366 | /// # use grasp_audit::*; | 373 | /// # use grasp_audit::*; |
| 367 | /// # async fn example() -> anyhow::Result<()> { | 374 | /// # async fn example() -> anyhow::Result<()> { |
| 368 | /// let config = AuditConfig::ci(); | 375 | /// // For CLI audit (shared fixtures - default) |
| 376 | /// let config = AuditConfig::shared(); | ||
| 369 | /// let client = AuditClient::new("ws://localhost:7000", config).await?; | 377 | /// let client = AuditClient::new("ws://localhost:7000", config).await?; |
| 370 | /// let ctx = TestContext::new(&client); | 378 | /// let ctx = TestContext::new(&client); |
| 371 | /// | 379 | /// |
| 372 | /// // Get a repository fixture | 380 | /// // Get a repository fixture - will be reused by subsequent TestContexts |
| 373 | /// let repo = ctx.get_fixture(FixtureKind::ValidRepo).await?; | 381 | /// let repo = ctx.get_fixture(FixtureKind::ValidRepo).await?; |
| 374 | /// | 382 | /// |
| 375 | /// // In CI mode: Creates new repo | 383 | /// // For cargo test (isolated fixtures) |
| 376 | /// // In Production mode: Returns cached repo | 384 | /// let config = AuditConfig::isolated(); |
| 385 | /// let client = AuditClient::new("ws://localhost:7000", config).await?; | ||
| 386 | /// let ctx = TestContext::new(&client); | ||
| 387 | /// | ||
| 388 | /// // Get a repository fixture - fresh for this TestContext only | ||
| 389 | /// let repo = ctx.get_fixture(FixtureKind::ValidRepo).await?; | ||
| 377 | /// # Ok(()) | 390 | /// # Ok(()) |
| 378 | /// # } | 391 | /// # } |
| 379 | /// ``` | 392 | /// ``` |
| @@ -1960,9 +1973,9 @@ mod tests { | |||
| 1960 | 1973 | ||
| 1961 | #[test] | 1974 | #[test] |
| 1962 | fn test_context_mode_from_audit_mode() { | 1975 | fn test_context_mode_from_audit_mode() { |
| 1963 | assert_eq!(ContextMode::from(AuditMode::CI), ContextMode::Isolated); | 1976 | assert_eq!(ContextMode::from(AuditMode::Isolated), ContextMode::Isolated); |
| 1964 | assert_eq!( | 1977 | assert_eq!( |
| 1965 | ContextMode::from(AuditMode::Production), | 1978 | ContextMode::from(AuditMode::Shared), |
| 1966 | ContextMode::Shared | 1979 | ContextMode::Shared |
| 1967 | ); | 1980 | ); |
| 1968 | } | 1981 | } |
| @@ -1981,7 +1994,7 @@ mod tests { | |||
| 1981 | 1994 | ||
| 1982 | #[tokio::test] | 1995 | #[tokio::test] |
| 1983 | async fn test_context_creation() { | 1996 | async fn test_context_creation() { |
| 1984 | let config = AuditConfig::ci(); | 1997 | let config = AuditConfig::isolated(); |
| 1985 | let client = crate::AuditClient::new_test(config); | 1998 | let client = crate::AuditClient::new_test(config); |
| 1986 | 1999 | ||
| 1987 | let ctx = TestContext::new(&client); | 2000 | let ctx = TestContext::new(&client); |