Skip to content

refactor: adopt typed filesystem paths across tests#91

Merged
woutervanranst merged 99 commits into
masterfrom
remove-blobpathstrings
May 27, 2026
Merged

refactor: adopt typed filesystem paths across tests#91
woutervanranst merged 99 commits into
masterfrom
remove-blobpathstrings

Conversation

@woutervanranst

@woutervanranst woutervanranst commented May 12, 2026

Copy link
Copy Markdown
Owner

Summary

  • replace repo-relative string helpers with typed filesystem and local-state path APIs across Core, integration, and E2E test code
  • simplify shared test fixture setup and temp-root/cache cleanup, including reusable rooted filesystems and stronger fake storage path typing
  • add focused coverage and documentation for filetree path validation, staging/session behavior, and test fixture boundaries

Testing

  • not run (PR metadata update only)

@coderabbitai

coderabbitai Bot commented May 12, 2026

Copy link
Copy Markdown
Contributor

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

This PR migrates tests, fixtures, fakes and helpers from string/path APIs to typed LocalDirectory/RelativePath/RelativeFileSystem; rekeys in-memory blob fakes to RelativePath, adds TestTempRoots and BlobPathsExtensions, and updates related Snapshot/Repository APIs and many tests.

Changes

Typed filesystem & test infra migration

Layer / File(s) Summary
Core filesystem primitives & APIs
src/Arius.Core.Shared.FileSystem/*, src/Arius.Core.Shared/Snapshot/SnapshotService.cs, src/Arius.Core/Shared/RepositoryPaths.cs, src/Arius.Core/Shared/Storage/BlobConstants.cs
Adds LocalDirectory/RelativeFileSystem APIs, changes SnapshotService.ParseTimestamp to accept RelativePath, and updates repository/blob path helpers to use PathSegment/RelativePath types.
RepositoryTestFixture & test helpers
src/Arius.Tests.Shared/Fixtures/RepositoryTestFixture.cs, src/Arius.Tests.Shared/TestTempRoots.cs, src/Arius.Tests.Shared/IO/FileSystemHelper.cs
Rewrites RepositoryTestFixture to typed LocalDirectory/RelativeFileSystem, adds TestTempRoots, converts FileSystemHelper to LocalDirectory-based copy helper and syncs cache-reset APIs.
Fake blob containers & BlobPaths extensions
src/Arius.Tests.Shared/Storage/FakeInMemoryBlobContainerService.cs, src/Arius.Core.Tests/Fakes/FakeSeededBlobContainerService.cs, src/Arius.Tests.Shared/BlobPathsExtensions.cs
Rekeys in-memory blob dictionaries to RelativePath, updates seed/list/download APIs to use RelativePath, and adds BlobPathsExtensions convenience overloads returning RelativePath.
E2E / Integration fixtures and workflows
src/Arius.E2E.Tests/Fixtures/E2EFixture.cs, src/Arius.Integration.Tests/Pipeline/PipelineFixture.cs, src/Arius.E2E.Tests/Workflows/*
Converts E2E and Pipeline fixtures to use RepositoryTestFixture and LocalDirectory/RelativeFileSystem; updates workflow steps and representative runner to typed LocalDirectory usage.
Mass test updates
many src/Arius.*.Tests/* files (ArchiveRecoveryTests, RestoreCommandHandlerTests, RoundtripTests, FileTree tests, etc.)
Updates hundreds of test cases and helpers to write/read via LocalFileSystem/RestoreFileSystem, use RelativePath.Parse(...) for paths, and to assert pointer/timestamps via typed APIs.
Misc: benchmarks, docs, skills
src/Arius.Benchmarks/*, .agents/skills/*
Benchmarks and documentation adjusted to the typed paths and minor documentation relocations/expansions. All changed ranges are listed in the hidden review stack.

Sequence Diagram(s)

(omitted — migration is broad and not a single sequential control-flow change)

Estimated code review effort

🎯 5 (Critical) | ⏱️ ~120 minutes

Possibly related PRs

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch remove-blobpathstrings

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (2)
src/Arius.Integration.Tests/ChunkIndex/ChunkIndexServiceIntegrationTests.cs (1)

108-109: ⚡ Quick win

Use RelativePath.Root / prefix instead of RelativePath.Parse(prefix.ToString()).

prefix is already a typed PathSegment from Shard.PrefixOf(). Composing it directly via the / operator avoids the stringify/parse round-trip:

Suggested fix
-var l2Path = RepositoryPaths.GetChunkIndexCacheRoot(Account, containerName).Resolve(RelativePath.Parse(prefix.ToString()));
+var l2Path = RepositoryPaths.GetChunkIndexCacheRoot(Account, containerName).Resolve(RelativePath.Root / prefix);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/Arius.Integration.Tests/ChunkIndex/ChunkIndexServiceIntegrationTests.cs`
around lines 108 - 109, The code builds l2Path by composing
RepositoryPaths.GetChunkIndexCacheRoot(Account, containerName) with
RelativePath.Parse(prefix.ToString()), but prefix is already a PathSegment from
Shard.PrefixOf(contentHash); replace the parse round-trip with direct
composition using RelativePath.Root / prefix so that l2Path is created by
resolving RelativePath.Root / prefix instead of parsing prefix.ToString().
src/Arius.Core.Tests/Features/ArchiveCommand/ArchiveTestEnvironment.cs (1)

49-49: ⚡ Quick win

Expose FileTreeCacheDirectory as LocalDirectory instead of string.

This currently forces a LocalDirectory -> string -> LocalDirectory round-trip (see downstream LocalDirectory.Parse(env.FileTreeCacheDirectory)), which weakens the type-safety this PR is introducing.

Suggested diff
diff --git a/src/Arius.Core.Tests/Features/ArchiveCommand/ArchiveTestEnvironment.cs b/src/Arius.Core.Tests/Features/ArchiveCommand/ArchiveTestEnvironment.cs
@@
-    public string FileTreeCacheDirectory => _fileTreeCacheDirectory.ToString();
+    public LocalDirectory FileTreeCacheDirectory => _fileTreeCacheDirectory;
diff --git a/src/Arius.Core.Tests/Features/ArchiveCommand/ArchiveRecoveryTests.cs b/src/Arius.Core.Tests/Features/ArchiveCommand/ArchiveRecoveryTests.cs
@@
-        await using var stagingSession = await FileTreeStagingSession.OpenAsync(LocalDirectory.Parse(env.FileTreeCacheDirectory));
+        await using var stagingSession = await FileTreeStagingSession.OpenAsync(env.FileTreeCacheDirectory);

As per coding guidelines, "Avoid stringify/parse round-trips. Preserve strong types until a real foreign boundary such as console output, configuration, serialization, or external SDK calls."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/Arius.Core.Tests/Features/ArchiveCommand/ArchiveTestEnvironment.cs` at
line 49, Change the FileTreeCacheDirectory property to return a LocalDirectory
instead of string to avoid stringify/parse round-trips: replace the getter
signature for FileTreeCacheDirectory to return the existing
_fileTreeCacheDirectory (as a LocalDirectory) and update callers that currently
do LocalDirectory.Parse(env.FileTreeCacheDirectory) to use the property
directly; ensure any tests or consumers expecting a string are adjusted to call
.ToString() only when crossing a foreign boundary.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/Arius.Core.Tests/Shared/FileTree/FileTreeBuilderTests.cs`:
- Line 350: The test currently calls Directory.Delete(cacheDir.ToString(),
recursive: true) which can throw if the directory is already removed; replace
that raw delete with the existing helper DeleteDirectoryIfExists(cacheDir) to
safely guard against missing directories and match the file's cleanup
pattern—locate the call in FileTreeBuilderTests (the line invoking
Directory.Delete) and swap it for the DeleteDirectoryIfExists(cacheDir) helper
method.

---

Nitpick comments:
In `@src/Arius.Core.Tests/Features/ArchiveCommand/ArchiveTestEnvironment.cs`:
- Line 49: Change the FileTreeCacheDirectory property to return a LocalDirectory
instead of string to avoid stringify/parse round-trips: replace the getter
signature for FileTreeCacheDirectory to return the existing
_fileTreeCacheDirectory (as a LocalDirectory) and update callers that currently
do LocalDirectory.Parse(env.FileTreeCacheDirectory) to use the property
directly; ensure any tests or consumers expecting a string are adjusted to call
.ToString() only when crossing a foreign boundary.

In `@src/Arius.Integration.Tests/ChunkIndex/ChunkIndexServiceIntegrationTests.cs`:
- Around line 108-109: The code builds l2Path by composing
RepositoryPaths.GetChunkIndexCacheRoot(Account, containerName) with
RelativePath.Parse(prefix.ToString()), but prefix is already a PathSegment from
Shard.PrefixOf(contentHash); replace the parse round-trip with direct
composition using RelativePath.Root / prefix so that l2Path is created by
resolving RelativePath.Root / prefix instead of parsing prefix.ToString().
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 88ef845a-f3bc-4729-95fa-12b7b54234ab

📥 Commits

Reviewing files that changed from the base of the PR and between 0447b29 and 79e8bc5.

📒 Files selected for processing (32)
  • src/Arius.Core.Tests/Fakes/FakeSeededBlobContainerService.cs
  • src/Arius.Core.Tests/Features/ArchiveCommand/ArchiveRecoveryTests.cs
  • src/Arius.Core.Tests/Features/ArchiveCommand/ArchiveTestEnvironment.cs
  • src/Arius.Core.Tests/Features/RestoreCommand/RestoreCommandHandlerTests.cs
  • src/Arius.Core.Tests/Shared/FileTree/Fakes/UnsortedSnapshotBlobContainerService.cs
  • src/Arius.Core.Tests/Shared/FileTree/FileTreeBuilderTests.cs
  • src/Arius.Core.Tests/Shared/FileTree/FileTreeServiceTests.cs
  • src/Arius.Core.Tests/Shared/RepositoryPathsTests.cs
  • src/Arius.Core.Tests/Shared/Snapshot/SnapshotSerializerTests.cs
  • src/Arius.Core/Shared/Snapshot/SnapshotService.cs
  • src/Arius.E2E.Tests/Datasets/SyntheticRepositoryMaterializer.cs
  • src/Arius.E2E.Tests/E2ETests.cs
  • src/Arius.E2E.Tests/Fixtures/E2EFixture.cs
  • src/Arius.E2E.Tests/Workflows/Steps/ArchiveTierLifecycleStep.cs
  • src/Arius.E2E.Tests/Workflows/Steps/Helpers.cs
  • src/Arius.Integration.Tests/ChunkIndex/ChunkIndexServiceIntegrationTests.cs
  • src/Arius.Integration.Tests/Pipeline/ContainerCreationTests.cs
  • src/Arius.Integration.Tests/Pipeline/CrashRecoveryTests.cs
  • src/Arius.Integration.Tests/Pipeline/GcmIntegrationTests.cs
  • src/Arius.Integration.Tests/Pipeline/ListQueryIntegrationTests.cs
  • src/Arius.Integration.Tests/Pipeline/PipelineFixture.cs
  • src/Arius.Integration.Tests/Pipeline/RecoveryScriptTests.cs
  • src/Arius.Integration.Tests/Pipeline/RehydrationStateTests.cs
  • src/Arius.Integration.Tests/Pipeline/RestoreCostModelTests.cs
  • src/Arius.Integration.Tests/Pipeline/RestoreDispositionTests.cs
  • src/Arius.Integration.Tests/Pipeline/RestorePointerTimestampTests.cs
  • src/Arius.Integration.Tests/Pipeline/RoundtripTests.cs
  • src/Arius.Integration.Tests/Shared/FileTree/FileTreeBuilderIntegrationTests.cs
  • src/Arius.Tests.Shared/AssemblyMarker.cs
  • src/Arius.Tests.Shared/Fixtures/RepositoryTestFixture.cs
  • src/Arius.Tests.Shared/RepositoryPathStrings.cs
  • src/Arius.Tests.Shared/Storage/FakeInMemoryBlobContainerService.cs
💤 Files with no reviewable changes (3)
  • src/Arius.Core/Shared/Snapshot/SnapshotService.cs
  • src/Arius.Tests.Shared/RepositoryPathStrings.cs
  • src/Arius.Core.Tests/Fakes/FakeSeededBlobContainerService.cs

Comment thread src/Arius.Core.Tests/Shared/FileTree/FileTreeBuilderTests.cs Outdated
@codecov

codecov Bot commented May 12, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 74.74747% with 25 lines in your changes missing coverage. Please review.
✅ Project coverage is 78.52%. Comparing base (7206122) to head (3b88160).
⚠️ Report is 107 commits behind head on master.

Files with missing lines Patch % Lines
...Arius.Core/Shared/FileSystem/RelativeFileSystem.cs 64.70% 11 Missing and 7 partials ⚠️
src/Arius.Core/Shared/Extensions.cs 16.66% 4 Missing and 1 partial ⚠️
src/Arius.Core/Shared/FileSystem/LocalDirectory.cs 71.42% 1 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master      #91      +/-   ##
==========================================
- Coverage   78.77%   78.52%   -0.25%     
==========================================
  Files          78       78              
  Lines        5277     5300      +23     
  Branches      722      731       +9     
==========================================
+ Hits         4157     4162       +5     
- Misses        928      939      +11     
- Partials      192      199       +7     
Flag Coverage Δ
linux 81.63% <74.74%> (-0.30%) ⬇️
windows 76.98% <74.74%> (-0.15%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/Arius.Core.Tests/Shared/RepositoryTestFixtureTests.cs`:
- Around line 21-37: The test double-disposes the fixture:
RepositoryTestFixture.CreateWithEncryptionAsync is awaited into "fixture" with
"await using", so remove the explicit await fixture.DisposeAsync() call (the
DisposeAsync invocation on the fixture) to avoid running cleanup twice; rely on
the language-scoped disposal provided by "await using" and keep the remaining
assertions after the scope as-is.

In `@src/Arius.E2E.Tests/Fixtures/E2EFixtureTests.cs`:
- Around line 9-41: The test class E2EFixtureTests and its test method
DisposeAsync_PreservesLocalCache_WhenRequested (which uses
E2EFixture.ResetLocalCacheAsync, E2EFixture.CreateAsync,
PreserveLocalCacheAsync, DisposeAsync) should be moved out of
src/Arius.E2E.Tests into an appropriate unit-test project (e.g.,
Arius.Tests.Shared.Tests or a dedicated fixtures test project); create a new
test file in that project, update the namespace and test project references to
include any required test helpers or FakeInMemoryBlobContainerService, and
ensure the target test project's csproj references the production assembly
containing E2EFixture and RepositoryPaths so the test compiles and runs.

In `@src/Arius.Tests.Shared/AssemblyMarker.cs`:
- Line 9: Change the visibility of the marker type AssemblyMarker from public to
internal: locate the declaration "AssemblyMarker" (the sealed marker class) and
replace its public modifier with internal so tests access it via
InternalsVisibleTo; ensure no external non-test consumers require it before
changing.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: cff7dc05-374e-455b-b4f8-085af535675a

📥 Commits

Reviewing files that changed from the base of the PR and between 79e8bc5 and eab5716.

📒 Files selected for processing (26)
  • src/Arius.Core.Tests/Features/ArchiveCommand/ArchiveRecoveryTests.cs
  • src/Arius.Core.Tests/Features/ArchiveCommand/ArchiveTestEnvironment.cs
  • src/Arius.Core.Tests/Features/RestoreCommand/RestoreCommandHandlerTests.cs
  • src/Arius.Core.Tests/Shared/RepositoryTestFixtureTests.cs
  • src/Arius.Core/AssemblyMarker.cs
  • src/Arius.E2E.Tests/E2ETests.cs
  • src/Arius.E2E.Tests/Fixtures/E2EFixture.cs
  • src/Arius.E2E.Tests/Fixtures/E2EFixtureTests.cs
  • src/Arius.E2E.Tests/Workflows/RepresentativeWorkflowRunner.cs
  • src/Arius.E2E.Tests/Workflows/RepresentativeWorkflowState.cs
  • src/Arius.E2E.Tests/Workflows/Steps/ArchiveTierLifecycleStep.cs
  • src/Arius.E2E.Tests/Workflows/Steps/Helpers.cs
  • src/Arius.E2E.Tests/Workflows/Steps/MaterializeVersionStep.cs
  • src/Arius.Integration.Tests/Pipeline/ContainerCreationTests.cs
  • src/Arius.Integration.Tests/Pipeline/CrashRecoveryTests.cs
  • src/Arius.Integration.Tests/Pipeline/GcmIntegrationTests.cs
  • src/Arius.Integration.Tests/Pipeline/ListQueryIntegrationTests.cs
  • src/Arius.Integration.Tests/Pipeline/PipelineFixture.cs
  • src/Arius.Integration.Tests/Pipeline/RecoveryScriptTests.cs
  • src/Arius.Integration.Tests/Pipeline/RehydrationStateTests.cs
  • src/Arius.Integration.Tests/Pipeline/RestoreCostModelTests.cs
  • src/Arius.Integration.Tests/Pipeline/RestoreDispositionTests.cs
  • src/Arius.Integration.Tests/Pipeline/RestorePointerTimestampTests.cs
  • src/Arius.Integration.Tests/Pipeline/RoundtripTests.cs
  • src/Arius.Tests.Shared/AssemblyMarker.cs
  • src/Arius.Tests.Shared/Fixtures/RepositoryTestFixture.cs
✅ Files skipped from review due to trivial changes (1)
  • src/Arius.Core/AssemblyMarker.cs
🚧 Files skipped from review as they are similar to previous changes (11)
  • src/Arius.Integration.Tests/Pipeline/RestoreCostModelTests.cs
  • src/Arius.Integration.Tests/Pipeline/RehydrationStateTests.cs
  • src/Arius.Integration.Tests/Pipeline/RestorePointerTimestampTests.cs
  • src/Arius.Integration.Tests/Pipeline/RecoveryScriptTests.cs
  • src/Arius.E2E.Tests/E2ETests.cs
  • src/Arius.Integration.Tests/Pipeline/RestoreDispositionTests.cs
  • src/Arius.Integration.Tests/Pipeline/CrashRecoveryTests.cs
  • src/Arius.Core.Tests/Features/ArchiveCommand/ArchiveTestEnvironment.cs
  • src/Arius.Integration.Tests/Pipeline/GcmIntegrationTests.cs
  • src/Arius.Integration.Tests/Pipeline/ListQueryIntegrationTests.cs
  • src/Arius.Core.Tests/Features/ArchiveCommand/ArchiveRecoveryTests.cs

Comment thread src/Arius.Core.Tests/Shared/RepositoryTestFixtureTests.cs Outdated
Comment thread src/Arius.E2E.Tests/Fixtures/E2EFixtureTests.cs Outdated
Comment thread src/Arius.Tests.Shared/AssemblyMarker.cs
Keep repository-relative existence checks on RelativeFileSystem so test code follows the same typed path boundaries as the rest of the codebase. Preserve LocalDirectory.Resolve for true host-path boundaries such as File.OpenRead and directory lifecycle work.
Keep in-memory blob test doubles on typed blob paths instead of string keys so blob lookups, listings, and collision state stay inside the existing RelativePath boundary.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/Arius.Tests.Shared/Storage/FakeInMemoryBlobContainerService.cs`:
- Around line 34-37: The current check-then-write on the ConcurrentDictionary
_blobs in UploadAsync and the OpenWriteAsync callback is non-atomic and can
cause TOCTOU races; change the logic so that when overwrite == false you use
_blobs.TryAdd(blobName, new StoredBlob(...)) and throw
BlobAlreadyExistsException if TryAdd returns false, while preserving direct
assignment (_blobs[blobName] = ...) when overwrite == true; apply the same
TryAdd+throw pattern inside the OpenWriteAsync callback where a new StoredBlob
is added so the add is atomic.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: dfc51704-bbe0-4ef7-8d0f-76829fce4848

📥 Commits

Reviewing files that changed from the base of the PR and between 16396ed and d0ce214.

📒 Files selected for processing (2)
  • src/Arius.Core.Tests/Fakes/FakeSeededBlobContainerService.cs
  • src/Arius.Tests.Shared/Storage/FakeInMemoryBlobContainerService.cs

Comment thread src/Arius.Tests.Shared/Storage/FakeInMemoryBlobContainerService.cs
Keep synthetic dataset state keyed by RelativePath so workflow helpers and disk assertions can compare repository-relative files without stringify/parse round trips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
src/Arius.E2E.Tests/Datasets/SyntheticRepositoryStateAssertions.cs (1)

17-17: ⚡ Quick win

Avoid string-based path logic in typed-path assertions.

The pointer-file filter and ordering currently depend on RelativePath.ToString(), which reintroduces string-path semantics in core test logic. Prefer a RelativePath-aware helper/comparer for suffix checks and ordering so the assertion path stays strongly typed end-to-end.

As per coding guidelines, "Avoid stringify/parse round-trips. Preserve strong types until a real foreign boundary such as console output, configuration, serialization, or external SDK calls." and "Prefer RelativePath for repository-relative paths, subtree roots, and prefixes that may contain multiple segments."

Also applies to: 24-25

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/Arius.E2E.Tests/Datasets/SyntheticRepositoryStateAssertions.cs` at line
17, The code is using relativePath.ToString().EndsWith(".pointer.arius", ...)
which reintroduces string-path logic; replace this with a RelativePath-aware
check and ordering using the RelativePath value itself. Create/inline a helper
such as HasPointerFileSuffix(RelativePath relativePath) (or a small
RelativePathSuffixComparer) and use that in the if condition instead of
ToString().EndsWith, and update any sorting logic at the other occurrences
(lines 24–25) to use the same RelativePath-aware comparator so suffix checks and
ordering remain strongly typed and avoid string round-trips; reference the local
variable relativePath and the includePointerFiles flag when applying the new
helper.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@src/Arius.E2E.Tests/Datasets/SyntheticRepositoryStateAssertions.cs`:
- Line 17: The code is using relativePath.ToString().EndsWith(".pointer.arius",
...) which reintroduces string-path logic; replace this with a
RelativePath-aware check and ordering using the RelativePath value itself.
Create/inline a helper such as HasPointerFileSuffix(RelativePath relativePath)
(or a small RelativePathSuffixComparer) and use that in the if condition instead
of ToString().EndsWith, and update any sorting logic at the other occurrences
(lines 24–25) to use the same RelativePath-aware comparator so suffix checks and
ordering remain strongly typed and avoid string round-trips; reference the local
variable relativePath and the includePointerFiles flag when applying the new
helper.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 6d87fe3b-93b9-4796-80e3-1c93119ce064

📥 Commits

Reviewing files that changed from the base of the PR and between d0ce214 and 20263ae.

📒 Files selected for processing (4)
  • src/Arius.E2E.Tests/Datasets/SyntheticRepositoryMaterializer.cs
  • src/Arius.E2E.Tests/Datasets/SyntheticRepositoryState.cs
  • src/Arius.E2E.Tests/Datasets/SyntheticRepositoryStateAssertions.cs
  • src/Arius.E2E.Tests/Workflows/Steps/Helpers.cs
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/Arius.E2E.Tests/Workflows/Steps/Helpers.cs
  • src/Arius.E2E.Tests/Datasets/SyntheticRepositoryMaterializer.cs

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/Arius.Integration.Tests/Pipeline/PipelineFixture.cs (1)

143-144: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Update stale DisposeAsync XML summary.

Line 143-144 still states chunk-index cache deletion, but DisposeAsync now only delegates to Repository.DisposeAsync(). Please align the summary with actual behavior to avoid misleading maintenance/debugging.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/Arius.Integration.Tests/Pipeline/PipelineFixture.cs` around lines 143 -
144, Update the XML summary for the PipelineFixture.DisposeAsync method to
reflect its current behavior: remove the mention of deleting the fixture's
temporary directory and repository-specific chunk-index cache and state that
DisposeAsync simply delegates to Repository.DisposeAsync(); reference the
DisposeAsync method and the Repository.DisposeAsync() call in the summary so the
comment matches the implementation.
🧹 Nitpick comments (1)
src/Arius.E2E.Tests/Fixtures/E2EFixture.cs (1)

71-85: 💤 Low value

PreserveRequested flag is set but never consumed.

PreserveLocalCacheAsync sets PreserveRequested = true in the lease struct, but this flag is never read. The cache-reset-on-dispose logic that previously consumed this flag was removed from DisposeAsync.

Either remove this dead code or restore the logic that consumes the flag during disposal.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/Arius.E2E.Tests/Fixtures/E2EFixture.cs` around lines 71 - 85,
PreserveLocalCacheAsync currently sets the PreserveRequested flag on the lease
(via GetRepositoryCacheKey and RepositoryCacheLeases under
RepositoryCacheLeaseLock) but nothing reads it; update the disposal path in
DisposeAsync to check the lease for PreserveRequested and skip
resetting/clearing the cache when true (or alternatively remove the
PreserveRequested write in PreserveLocalCacheAsync if you prefer to drop the
feature). Specifically, either remove the unused assignment to
RepositoryCacheLeases[cacheKey].PreserveRequested in PreserveLocalCacheAsync, or
restore logic in DisposeAsync to look up RepositoryCacheLeases[cacheKey],
respect lease.PreserveRequested, and avoid cache reset when set.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/Arius.Core.Tests/Shared/FileTree/FileTreeBuilderTests.cs`:
- Line 258: The test double-disposes the staging session: remove the explicit
await stagingSession1.DisposeAsync() call since stagingSession1 is already
scoped by the await using at its creation; locate the await using declaration
for stagingSession1 and delete the redundant DisposeAsync invocation so disposal
is handled only by the using scope (do not change the await using itself or
other cleanup logic).

In `@src/Arius.Core/Shared/FileSystem/RelativeFileSystem.cs`:
- Around line 207-211: DeleteDirectory(RelativePath, bool) in RelativeFileSystem
now calls Directory.Delete(_root.Resolve(path), recursive) directly which will
throw DirectoryNotFoundException for missing paths; to restore previous no-op
behavior, check existence first and only call Directory.Delete if
Directory.Exists(fullPath) (use _root.Resolve(path) to get fullPath) or
document/propagate the new behavior if intentional. Ensure you update the
DeleteDirectory method in class RelativeFileSystem and keep the recursive
semantics when performing the deletion.

In `@src/Arius.E2E.Tests/Fixtures/E2EFixture.cs`:
- Around line 111-115: DisposeAsync currently only calls Repository.DisposeAsync
and awaits Task.CompletedTask, but never decrements the static lease counter
LiveFixtureCount so HasActiveLease stays true; update DisposeAsync to decrement
LiveFixtureCount (preferably with thread-safe Interlocked.Decrement(ref
LiveFixtureCount)) after disposing the repository and remove the redundant await
Task.CompletedTask so the method simply awaits Repository.DisposeAsync() then
decrements the counter to restore correct lease behavior for ResetLocalCache.

In `@src/Arius.Tests.Shared/Fixtures/RepositoryTestFixture.cs`:
- Line 204: The property ResetLocalCacheOnDispose is unused; update DisposeAsync
to respect it by invoking the index cache reset before disposal when the flag is
true: inside DisposeAsync, add "if (ResetLocalCacheOnDispose) await
Index.ResetLocalCacheAsync()" (or call the appropriate
Index.ClearLocalCache/ResetLocalCache synchronous API if async variant doesn't
exist), then proceed to dispose Index; alternatively, if there is no index
cache-reset API or you prefer explicit cleanup, remove the
ResetLocalCacheOnDispose property and its assignments in the factory methods to
avoid misleading callers.

In `@src/Arius.Tests.Shared/TestTempRoots.cs`:
- Around line 19-21: The current cleanup in TestTempRoots.cs builds tempRoot
from FolderName and deletes the entire shared Path.GetTempPath()/FolderName,
which can collide across parallel test runs; change the logic so that
Setup/constructor for the TestSession (or wherever FolderName is used) creates a
per-session subfolder (e.g., combine FolderName with a unique session id or
GUID) and use that as tempRoot, track created session roots (e.g., a list in the
TestSession or TestTempRoots class), and update the teardown/After(TestSession)
logic to only delete the tracked per-session folder(s) (referencing FolderName,
tempRoot and the After(TestSession) teardown hook) rather than deleting the
whole shared folder tree.

---

Outside diff comments:
In `@src/Arius.Integration.Tests/Pipeline/PipelineFixture.cs`:
- Around line 143-144: Update the XML summary for the
PipelineFixture.DisposeAsync method to reflect its current behavior: remove the
mention of deleting the fixture's temporary directory and repository-specific
chunk-index cache and state that DisposeAsync simply delegates to
Repository.DisposeAsync(); reference the DisposeAsync method and the
Repository.DisposeAsync() call in the summary so the comment matches the
implementation.

---

Nitpick comments:
In `@src/Arius.E2E.Tests/Fixtures/E2EFixture.cs`:
- Around line 71-85: PreserveLocalCacheAsync currently sets the
PreserveRequested flag on the lease (via GetRepositoryCacheKey and
RepositoryCacheLeases under RepositoryCacheLeaseLock) but nothing reads it;
update the disposal path in DisposeAsync to check the lease for
PreserveRequested and skip resetting/clearing the cache when true (or
alternatively remove the PreserveRequested write in PreserveLocalCacheAsync if
you prefer to drop the feature). Specifically, either remove the unused
assignment to RepositoryCacheLeases[cacheKey].PreserveRequested in
PreserveLocalCacheAsync, or restore logic in DisposeAsync to look up
RepositoryCacheLeases[cacheKey], respect lease.PreserveRequested, and avoid
cache reset when set.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 09be2f59-1d5d-415d-9c1c-cd59667481db

📥 Commits

Reviewing files that changed from the base of the PR and between adc436a and 70ab58d.

📒 Files selected for processing (19)
  • .agents/skills/csharp-coding-standards/SKILL.md
  • .agents/skills/csharp-tunit/SKILL.md
  • src/Arius.Benchmarks/ArchiveStepBenchmarks.cs
  • src/Arius.Core.Tests/Features/ArchiveCommand/ArchiveTestEnvironment.cs
  • src/Arius.Core.Tests/Features/RestoreCommand/RestoreCommandHandlerTests.cs
  • src/Arius.Core.Tests/Shared/FileSystem/RelativeFileSystemTests.cs
  • src/Arius.Core.Tests/Shared/FileTree/FileTreeBuilderTests.cs
  • src/Arius.Core.Tests/Shared/FileTree/FileTreeServiceTests.cs
  • src/Arius.Core.Tests/Shared/RepositoryPathsTests.cs
  • src/Arius.Core.Tests/Shared/Storage/BlobPathsTests.cs
  • src/Arius.Core/Shared/FileSystem/LocalDirectory.cs
  • src/Arius.Core/Shared/FileSystem/RelativeFileSystem.cs
  • src/Arius.Core/Shared/RepositoryPaths.cs
  • src/Arius.E2E.Tests/Fixtures/E2EFixture.cs
  • src/Arius.E2E.Tests/Workflows/Steps/ResetCacheStep.cs
  • src/Arius.Integration.Tests/Pipeline/PipelineFixture.cs
  • src/Arius.Tests.Shared/BlobPathsExtensions.cs
  • src/Arius.Tests.Shared/Fixtures/RepositoryTestFixture.cs
  • src/Arius.Tests.Shared/TestTempRoots.cs
✅ Files skipped from review due to trivial changes (1)
  • .agents/skills/csharp-coding-standards/SKILL.md
🚧 Files skipped from review as they are similar to previous changes (5)
  • src/Arius.Core/Shared/RepositoryPaths.cs
  • src/Arius.Core/Shared/FileSystem/LocalDirectory.cs
  • src/Arius.Benchmarks/ArchiveStepBenchmarks.cs
  • src/Arius.Core.Tests/Shared/RepositoryPathsTests.cs
  • src/Arius.Core.Tests/Features/ArchiveCommand/ArchiveTestEnvironment.cs

Comment thread src/Arius.Core.Tests/Shared/FileTree/FileTreeBuilderTests.cs
Comment thread src/Arius.Core/Shared/FileSystem/RelativeFileSystem.cs Outdated
Comment thread src/Arius.E2E.Tests/Fixtures/E2EFixture.cs
Comment thread src/Arius.Tests.Shared/Fixtures/RepositoryTestFixture.cs Outdated
Comment thread src/Arius.Tests.Shared/TestTempRoots.cs Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (1)
src/Arius.Tests.Shared/Fixtures/RepositoryTestFixture.cs (1)

204-204: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Honor ResetLocalCacheOnDispose in DisposeAsync or remove it.

ResetLocalCacheOnDispose is required but not consumed, so callers can’t rely on the behavior implied by the API contract.

Proposed fix
 public ValueTask DisposeAsync()
 {
+    if (ResetLocalCacheOnDispose)
+        DeleteLocalCacheDirectory(AccountName, ContainerName);
+
     Index.Dispose();

     return ValueTask.CompletedTask;
 }

Also applies to: 250-255

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/Arius.Tests.Shared/Fixtures/RepositoryTestFixture.cs` at line 204,
RepositoryTestFixture declares the required property ResetLocalCacheOnDispose
but DisposeAsync does not use it; update the RepositoryTestFixture.DisposeAsync
method to check the ResetLocalCacheOnDispose flag and perform the local-cache
reset/cleanup when true (call the existing reset/clear method or code path that
clears the fixture's cache), or if you intended not to support this behavior
remove the required modifier from ResetLocalCacheOnDispose (and any similar
required bool properties) so the API surface matches implementation; reference
ResetLocalCacheOnDispose and the DisposeAsync method in RepositoryTestFixture
when making the change.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/Arius.Core.Tests/Features/ArchiveCommand/ArchiveRecoveryTests.cs`:
- Line 35: The test incorrectly calls ShouldNotBeNull() on the Task instead of
the awaited lookup result in ArchiveRecoveryTests; change both occurrences (the
LookupAsync(contentHash) assertions) to await the task first and assert on the
returned value (e.g., either var result = await
fixture.Index.LookupAsync(contentHash); result.ShouldNotBeNull(); or (await
fixture.Index.LookupAsync(contentHash)).ShouldNotBeNull()), updating the
assertions at the two locations that reference LookupAsync in
ArchiveRecoveryTests.

---

Duplicate comments:
In `@src/Arius.Tests.Shared/Fixtures/RepositoryTestFixture.cs`:
- Line 204: RepositoryTestFixture declares the required property
ResetLocalCacheOnDispose but DisposeAsync does not use it; update the
RepositoryTestFixture.DisposeAsync method to check the ResetLocalCacheOnDispose
flag and perform the local-cache reset/cleanup when true (call the existing
reset/clear method or code path that clears the fixture's cache), or if you
intended not to support this behavior remove the required modifier from
ResetLocalCacheOnDispose (and any similar required bool properties) so the API
surface matches implementation; reference ResetLocalCacheOnDispose and the
DisposeAsync method in RepositoryTestFixture when making the change.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 2b1357f2-8305-415c-b42c-6820c9e100f8

📥 Commits

Reviewing files that changed from the base of the PR and between 76cf176 and ac74db2.

📒 Files selected for processing (5)
  • src/Arius.Core.Tests/Features/ArchiveCommand/ArchiveRecoveryTests.cs
  • src/Arius.Core.Tests/Features/ArchiveCommand/ArchiveTestEnvironment.cs
  • src/Arius.Core.Tests/Shared/FileSystem/RelativeFileSystemTests.cs
  • src/Arius.Core.Tests/Shared/FileTree/FileTreeServiceTests.cs
  • src/Arius.Tests.Shared/Fixtures/RepositoryTestFixture.cs
💤 Files with no reviewable changes (1)
  • src/Arius.Core.Tests/Features/ArchiveCommand/ArchiveTestEnvironment.cs
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/Arius.Core.Tests/Shared/FileTree/FileTreeServiceTests.cs

Comment thread src/Arius.Core.Tests/Features/ArchiveCommand/ArchiveRecoveryTests.cs Outdated
@woutervanranst woutervanranst changed the title refactor: replace repo-relative string helpers with RelativePath refactor: adopt typed filesystem paths across tests and local state May 27, 2026
@woutervanranst woutervanranst changed the title refactor: adopt typed filesystem paths across tests and local state refactor: adopt typed filesystem paths across tests May 27, 2026
@woutervanranst woutervanranst merged commit a49d494 into master May 27, 2026
10 checks passed
@woutervanranst woutervanranst deleted the remove-blobpathstrings branch May 27, 2026 22:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant