Skip to content

[TST-E4] test: the workspace live tests assert the files' actual contents, read through the containment check - #458

Merged
Blind-Striker merged 1 commit into
masterfrom
test/tst-e4a-workspace-reads
Oct 17, 2026
Merged

Blind-Striker merged 1 commit into
masterfrom
test/tst-e4a-workspace-reads

Conversation

@Blind-Striker

@Blind-Striker Blind-Striker commented Oct 17, 2026 •

Copy link
Copy Markdown
Collaborator

📝 Description

What does this PR do?
It is TST-E4a's U8-17 PR. Four live tests asserted a workspace file's content through a true/false ownership predicate, workspace.HasTextFile(...).IsTrue() or HasBytes(...).IsTrue(). A failure said only "expected true". They now read the file and assert its exact content, with the path in the expression.

  • TestWorkspace.ReadBytes(relativePath) and ReadTextFile(directory, relativePath) resolve through the existing, unchanged ResolvePathBelow. A rooted path, a ../ traversal and a sibling directory that shares the workspace's name prefix are refused before anything is read.

  • The four live sites:

    • FileSystemClientLiveTests.FindEntriesAsync_And_ListEntriesAsync_Should_Report_The_Workspace_Entries;
    • FileSystemClientLiveTests.WriteFileAsync_Should_Write_Bytes_That_ReadFileAsync_Reads_Back, where the bytes on disk are compared in order;
    • ProjectsClientLiveTests.GetLocationAsync_And_ListProjectsAsync_Should_Report_The_Workspace_Project, with both of its sites.

    Each keeps the same file and the same expected content.

  • HasBytes, HasTextFile, their other ownership uses and their contract test are unchanged.

  • New TestWorkspaceTests: valid nested reads; a read returns the actual (wrong) content rather than a verdict; a missing file propagates; blank inputs refuse with the exact parameter name; and the three escapes refuse on both read APIs. The escapes are seeded with real files outside the workspace, so a read that skipped the containment check would succeed with their content and fail the test.

  • The missing-file test asserts the exact exception type only. Testably's MockFileSystem leaves FileNotFoundException.FileName empty, so a path assertion there would be testing the mock, not the workspace.

No test method is removed. PipelineScenario, the other half of this package, follows separately (#448 explains why three of its disposal tests wait).

🔄 Type of Change

  • 🧪 Test improvements

🎯 Protocol & API Surface

  • No change to the public API surface
  • Nothing under external/, spec/ or src/ was touched

🧪 Testing

Test mapping (mechanical: e4_test_map.py over git diff 282a4c1e ac39cfd4)

File Base test method At head Target
tests/OpenCode.Sdk.Tests/FileSystem/FileSystemClientLiveTests.cs FindEntriesAsync_And_ListEntriesAsync_Should_Report_The_Workspace_Entries converted in place
tests/OpenCode.Sdk.Tests/FileSystem/FileSystemClientLiveTests.cs WriteFileAsync_Should_Write_Bytes_That_ReadFileAsync_Reads_Back converted in place
tests/OpenCode.Sdk.Tests/Projects/ProjectsClientLiveTests.cs GetLocationAsync_And_ListProjectsAsync_Should_Report_The_Workspace_Project converted in place

Unmapped: 0

File Assert.That at base at head delta
tests/OpenCode.Sdk.Tests/FileSystem/FileSystemClientLiveTests.cs 24 24 +0
tests/OpenCode.Sdk.Tests/Harness/TestWorkspace.cs 0 0 +0
tests/OpenCode.Sdk.Tests/Harness/TestWorkspaceTests.cs 11 23 +12
tests/OpenCode.Sdk.Tests/Projects/ProjectsClientLiveTests.cs 11 11 +0

The TestWorkspaceTests delta (+12) is the six new read-contract tests. The three converted live methods keep every assertion they had, and each converted site now asserts exact content.

Mutants (each restored byte-identically)

Mutant Result
Before: HasBytes/HasTextFile return true without reading (base) Rejected by analyzer S2325, which counts as a second guard. With analyzers off (a demo), the three live methods survive on net10.0 and net472.
After: ReadBytes/ReadTextFile return empty content without reading The same three live methods are red on net10.0 and net472.
A read that skips ResolvePathBelow and returns the outside file's real content The rooted, traversal and sibling-prefix cases are red on both read APIs (failure: no exception thrown).
ReadBytes returns the bytes reversed WriteFileAsync_Should_Write_Bytes_That_ReadFileAsync_Reads_Back is red (index 0: expected 115, got 254).

One limit: the Projects test fails at its first converted site, so the "after" mutant does not reach its second site on its own.

Review

  • The coordinator read the diff and fixed one doc-comment wording.
  • A fresh Sol reviewer, given only the requirements and the diff, found no defects, no out-of-scope changes and no notes. It confirmed that seeded escapes cannot pass through a missing-file exception, and that the polyfill covers ThrowIfNullOrWhiteSpace on net472.

✅ Completion Gate

Local check (quality-gates.md) on head ac39cfd4, base 282a4c1e. Every step's own exit code was read:

  • slopwatch: zero findings
  • dotnet build --configuration Release: 0 warnings, 0 errors
  • dotnet format whitespace / dotnet format style --severity warn: no changes
  • verify-clones: passed, 0 new (tests 5.35%); baseline unchanged
  • OpenCode.Sdk.Tools.Tests (all but NativeAot): 2081, 0 failed
  • OpenCode.Sdk.Tests (all but ServiceElection/NativeAot): 8441, 0 failed

The host runs Bun 1.4.3, a maintainer-named off-pin host (OPENCODE_SDK_TESTS_BUN_MISMATCH=allow); the pin is 1.4.2.

✅ Code Quality Checklist

  • No new suppression
  • No tests skipped, weakened, or deleted to make the suite pass

View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need.

…d through the containment check

TST-E4a P01b-1 (U8-17). TestWorkspace gains ReadBytes and ReadTextFile, which resolve through the unchanged ResolvePathBelow, so a rooted, traversal or sibling-prefix path is refused before anything is read. The four live sites in FileSystemClientLiveTests and ProjectsClientLiveTests now assert the exact contents with the path in the expression, where they asserted a true/false ownership predicate. HasBytes, HasTextFile and their contract test stay.
@Blind-Striker
Blind-Striker added this pull request to the merge queue Oct 17, 2026
Merged via the queue into master with commit 7738dc3 Oct 17, 2026
12 checks passed
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