Skip to content

Fix Directory_Delete_MountVolume test: guard Unmount calls with Directory.Exists check#125348

Draft
Copilot wants to merge 2 commits intomainfrom
copilot/fix-guard-unmount-calls
Draft

Fix Directory_Delete_MountVolume test: guard Unmount calls with Directory.Exists check#125348
Copilot wants to merge 2 commits intomainfrom
copilot/fix-guard-unmount-calls

Conversation

Copy link
Contributor

Copilot AI commented Mar 9, 2026

finally blocks in Scenarios 1, 2, 3.1, and 3.2 unconditionally called MountHelper.Unmount(mountedDirName). When Directory.Delete removes the mount point directory as part of the delete operation, the subsequent Unmount call throws (Win32 error 4390/3), gets caught by the scenario's catch, and sets s_pass = false.

Changes

  • Delete_MountVolume.cs — Scenarios 1, 2, 3.1, 3.2 finally blocks: Wrap Unmount/DeleteDir calls with Directory.Exists(mountedDirName), matching the pattern already used in Scenarios 3.3–3.5.
// Before
finally
{
    MountHelper.Unmount(mountedDirName);
    DeleteDir(mountedDirName, true);
}

// After
finally
{
    if (Directory.Exists(mountedDirName))
    {
        MountHelper.Unmount(mountedDirName);
        DeleteDir(mountedDirName, true);
    }
}
Original prompt

Problem

The Directory_Delete_MountVolume.RunTest() test in src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/Directory/Delete_MountVolume.cs fails because the finally blocks in Scenarios 1, 2, 3.1, and 3.2 unconditionally call MountHelper.Unmount(mountedDirName), but Directory.Delete may have already removed the mount point directory. When Unmount tries to call DeleteVolumeMountPoint on a path that no longer exists, it throws (Win32 error 4390 or 3), which gets caught by the scenario's catch block and sets s_pass = false, failing the test.

Scenarios 3.3, 3.4, and 3.5 already correctly guard their cleanup with if (Directory.Exists(mountedDirName)) before attempting to unmount. The fix is to apply the same pattern to the 4 finally blocks that are missing it.

Fix

Change the finally blocks in Scenarios 1, 2, 3.1, and 3.2 to guard the Unmount and DeleteDir calls with Directory.Exists(mountedDirName), matching the existing pattern used in Scenarios 3.3–3.5.

There are exactly 4 finally blocks to change. Each one currently looks like:

finally
{
    MountHelper.Unmount(mountedDirName);
    DeleteDir(mountedDirName, true);
}

Each should be changed to:

finally
{
    if (Directory.Exists(mountedDirName))
    {
        MountHelper.Unmount(mountedDirName);
        DeleteDir(mountedDirName, true);
    }
}

The 4 locations in the file src/libraries/System.Runtime/tests/System.IO.FileSystem.Tests/Directory/Delete_MountVolume.cs are:

  1. Scenario 1 finally (around lines 80–84)
  2. Scenario 2 finally (around lines 125–129)
  3. Scenario 3.1 finally (around lines 167–171)
  4. Scenario 3.2 finally (around lines 209–213)

Do not change anything else. No changes to s_pass, Eval, method signatures, test structure, or any other lines. Only add the Directory.Exists guard to these 4 finally blocks.

The following is the prior conversation context from the user's chat exploration (may be truncated):

User: explain this test to me and what s_pass asserts

Assistant: ## Explanation of Delete_MountVolume.RunTest()

This is a Windows-specific test that verifies Directory.Delete works correctly when NTFS volume mount points are involved. A volume mount point is a directory that acts as an entry point to another volume (similar to a drive letter, but mapped to a folder).

What It Tests

The test runs 7 scenarios, all variations of the same theme — deleting directories that are accessed through or contain mounted volumes:

Scenario Description
1 A different drive is mounted onto the current drive. Delete a directory on the other drive via the mount point.
2 The current drive is mounted onto a different drive. Delete a directory on the current drive via the mount point on the other drive.
3.1 The current drive is mounted onto itself (at the root). Delete a directory via that self-referencing mount.
3.2 The current drive is mounted onto the current working directory. Delete via that mount.
3.3 ⚠️ Delete the mounted directory itself (the mount point). Verifies the mount point is removed without nuking the underlying volume.
3.4 ⚠️ Delete the parent directory of a mount point (parent also has other files/dirs). Verifies recursive delete handles mount points inside the tree.
3.5 Same as 3.4 but targets a different subdirectory as the mount point within the tree.

The Pattern in Each Scenario

  1. Create a directory to serve as a mount point.
  2. Mount a volume onto that directory using MountHelper.Mount.
  3. Create a directory tree (files and subdirectories) on the source volume.
  4. Delete the tree — either via the mount path or by deleting a parent that contains the mount.
  5. Verify the directory no longer exists.
  6. Clean up — unmount and delete the mount directory in a finally block.

What s_pass Asserts

s_pass is a boolean accumulator for the overall test result. It starts as true and is set to false in two situations:

  1. Any Eval(...) call returns falseEval checks a condition (e.g., "directory was deleted") and sets s_pass = false if the condition fails, logging the error.
  2. Any scenario throws an unhandled exception — each catch block sets s_pass = false and logs the error.

At the very end, in the outermost finally:

Assert.True(s_pass);

This is a single assertion that summarizes all scenarios. If any scenario failed a condition or threw an exception, s_pass will be false and the test fails. This pattern was common in older test code — it lets the test run all scenarios even if one fails (rather than stopping at the first Assert failure), collecting all errors before reporting.

Why It's Disabled

The [ActiveIssue("https://github.com/dotnet/runtime/issues/14378")] attribute means this...

This pull request was created from Copilot chat.


💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.

…tory.Exists check

Co-authored-by: jozkee <16040868+jozkee@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix unmount calls in Directory_Delete_MountVolume tests Fix Directory_Delete_MountVolume test: guard Unmount calls with Directory.Exists check Mar 9, 2026
@dotnet-policy-service
Copy link
Contributor

Tagging subscribers to this area: @agocke
See info in area-owners.md if you want to be subscribed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

System.IO.Tests.Directory_Delete_MountVolume.RunTest failure

2 participants