Feature: CheckpointManager full coverage As a developer I want thorough tests for every method, branch, and edge case in checkpoint.py So that line-rate and branch-rate reach 1.0 # --------------------------------------------------------------------------- # SandboxCheckpoint Pydantic model # --------------------------------------------------------------------------- Scenario: SandboxCheckpoint model can be constructed with all fields Given I build a SandboxCheckpoint with valid fields Then the constructed checkpoint model should expose all field values And the constructed checkpoint model should be frozen Scenario: SandboxCheckpoint model uses empty dict as default metadata Given I build a SandboxCheckpoint without explicit metadata Then the constructed checkpoint metadata should be an empty dict # --------------------------------------------------------------------------- # Checkpointable protocol # --------------------------------------------------------------------------- Scenario: An object satisfying Checkpointable passes isinstance check Given a mock object with sandbox_id and context properties Then the mock object should satisfy the Checkpointable protocol Scenario: An object missing sandbox_id fails Checkpointable isinstance check Given a mock object without a sandbox_id property Then the mock object should not satisfy the Checkpointable protocol # --------------------------------------------------------------------------- # CheckpointManager.__init__ # --------------------------------------------------------------------------- Scenario: CheckpointManager initialises with empty state Given a freshly created CheckpointManager Then the manager internal checkpoints dict should be empty And the manager should have a threading lock # --------------------------------------------------------------------------- # create_checkpoint – context is None (metadata-only) # --------------------------------------------------------------------------- Scenario: Creating a checkpoint when sandbox context is None produces a metadata-only snapshot Given a freshly created CheckpointManager And a mock sandbox whose context is None When I invoke create_checkpoint with plan "plan-m1" phase "pre_execute" and no metadata Then the returned checkpoint should have a non-empty snapshot_path directory And the returned checkpoint sandbox_id should equal the mock sandbox id Scenario: Creating a checkpoint with explicit metadata converts values to strings Given a freshly created CheckpointManager And a mock sandbox whose context is None When I invoke create_checkpoint with plan "plan-m2" phase "post_execute" and numeric metadata Then the returned checkpoint metadata values should all be strings Scenario: Creating a checkpoint with None metadata defaults to empty dict Given a freshly created CheckpointManager And a mock sandbox whose context is None When I invoke create_checkpoint with plan "plan-m3" phase "pre_apply" and None metadata Then the returned checkpoint metadata should be an empty dict # --------------------------------------------------------------------------- # create_checkpoint – context with sandbox_path # --------------------------------------------------------------------------- Scenario: Creating a checkpoint with a real sandbox path snapshots the directory Given a freshly created CheckpointManager And a temporary sandbox directory with sample files And a mock sandbox whose context points to the temporary directory When I invoke create_checkpoint with plan "plan-s1" phase "pre_execute" and no metadata Then the snapshot directory should contain copies of the sample files Scenario: Creating a checkpoint with a real sandbox path stores sandbox_path in metadata Given a freshly created CheckpointManager And a temporary sandbox directory with sample files And a mock sandbox whose context points to the temporary directory When I invoke create_checkpoint with plan "plan-s2" phase "pre_execute" and no metadata Then the returned checkpoint metadata should contain the sandbox path Scenario: Rollback succeeds without manually supplying sandbox_path in metadata Given a freshly created CheckpointManager And a temporary sandbox directory with sample files And a mock sandbox whose context points to the temporary directory And a checkpoint was created for the temporary sandbox without explicit sandbox_path metadata And the temporary sandbox files are then modified When I invoke rollback_to on the created checkpoint Then the rollback result should be true And the temporary sandbox should contain the original files # --------------------------------------------------------------------------- # _snapshot_directory – branches # --------------------------------------------------------------------------- Scenario: _snapshot_directory with None path creates an empty snapshot dir Given a freshly created CheckpointManager When I call _snapshot_directory with a None sandbox_path Then the returned snapshot should be an existing empty directory Scenario: _snapshot_directory with non-existent path creates an empty snapshot dir Given a freshly created CheckpointManager When I call _snapshot_directory with a non-existent sandbox_path Then the returned snapshot should be an existing empty directory Scenario: _snapshot_directory with a valid path copies the tree Given a freshly created CheckpointManager And a temporary sandbox directory with sample files When I call _snapshot_directory with the temporary sandbox_path Then the returned snapshot should contain the sample files Scenario: _snapshot_directory raises SandboxError when copytree fails Given a freshly created CheckpointManager And a temporary sandbox directory with sample files When I call _snapshot_directory with a path that triggers OSError Then a SandboxError should have been raised # --------------------------------------------------------------------------- # _cleanup_snapshot – branches # --------------------------------------------------------------------------- Scenario: _cleanup_snapshot with empty string is a no-op Given a freshly created CheckpointManager When I call _cleanup_snapshot with an empty string Then no error should occur from cleanup_snapshot Scenario: _cleanup_snapshot removes parent directory when it exists Given a freshly created CheckpointManager And a temporary snapshot directory tree for cleanup When I call _cleanup_snapshot with the temporary snapshot path Then the temporary snapshot parent should no longer exist Scenario: _cleanup_snapshot with non-existent parent is a no-op Given a freshly created CheckpointManager When I call _cleanup_snapshot with a non-existent path Then no error should occur from cleanup_snapshot # --------------------------------------------------------------------------- # rollback_to – all branches # --------------------------------------------------------------------------- Scenario: Rollback returns false when snapshot_path is empty string Given a freshly created CheckpointManager And a SandboxCheckpoint with empty snapshot_path When I invoke rollback_to on the crafted checkpoint Then the rollback result should be false Scenario: Rollback returns false when snapshot_path does not exist on disk Given a freshly created CheckpointManager And a SandboxCheckpoint with a non-existent snapshot_path When I invoke rollback_to on the crafted checkpoint Then the rollback result should be false Scenario: Rollback returns false when sandbox_path is missing from metadata Given a freshly created CheckpointManager And a SandboxCheckpoint whose snapshot exists but metadata has no sandbox_path When I invoke rollback_to on the crafted checkpoint Then the rollback result should be false Scenario: Rollback returns false when sandbox_path directory does not exist Given a freshly created CheckpointManager And a SandboxCheckpoint whose snapshot exists but sandbox_path points nowhere When I invoke rollback_to on the crafted checkpoint Then the rollback result should be false Scenario: Rollback succeeds and restores files and subdirectories Given a freshly created CheckpointManager And a temporary sandbox directory with sample files And a mock sandbox whose context points to the temporary directory And a checkpoint was created for the temporary sandbox And the temporary sandbox files are then modified When I invoke rollback_to on the created checkpoint Then the rollback result should be true And the temporary sandbox should contain the original files Scenario: Rollback handles OSError during restore gracefully Given a freshly created CheckpointManager And a SandboxCheckpoint whose snapshot and sandbox exist but restore will fail When I invoke rollback_to on the crafted checkpoint Then the rollback result should be false # --------------------------------------------------------------------------- # list_checkpoints – branches # --------------------------------------------------------------------------- Scenario: Listing checkpoints for unknown sandbox returns empty list Given a freshly created CheckpointManager When I invoke list_checkpoints for sandbox "unknown-sb-99" Then the checkpoint list should be empty Scenario: Listing checkpoints returns all created checkpoints in order Given a freshly created CheckpointManager And a mock sandbox whose context is None And I create two checkpoints for the mock sandbox When I invoke list_checkpoints for the mock sandbox Then the checkpoint list should have 2 entries in creation order # --------------------------------------------------------------------------- # delete_checkpoint – branches # --------------------------------------------------------------------------- Scenario: Deleting a known checkpoint returns true and removes it Given a freshly created CheckpointManager And a mock sandbox whose context is None And a single checkpoint is created for the mock sandbox When I invoke delete_checkpoint with the created checkpoint id Then the checkpoint delete result should be true And listing checkpoints for the mock sandbox should return 0 entries Scenario: Deleting an unknown checkpoint id returns false Given a freshly created CheckpointManager When I invoke delete_checkpoint with id "no-such-cp-id" Then the checkpoint delete result should be false