Skip to content

Fix flaky ExpandedFileAttributesAreUpdated test#1923

Draft
tyrielv wants to merge 1 commit intomicrosoft:masterfrom
tyrielv:tyrielv/fix-flaky-expanded-attrs
Draft

Fix flaky ExpandedFileAttributesAreUpdated test#1923
tyrielv wants to merge 1 commit intomicrosoft:masterfrom
tyrielv:tyrielv/fix-flaky-expanded-attrs

Conversation

@tyrielv
Copy link
Contributor

@tyrielv tyrielv commented Mar 25, 2026

Fix flaky ExpandedFileAttributesAreUpdated test

Problem

The functional test BasicFileSystemTests.ExpandedFileAttributesAreUpdated intermittently fails in CI with:

Last access time does not match
Expected: 2026-03-25 17:57:07.2552456
But was:  2026-03-24 17:57:06.1115032

Example failure: https://github.com/microsoft/VFSForGit/actions/runs/23504116617/job/68407908415?pr=1920#step:9:7144

Root Cause

Setting CreationTime on a placeholder file opens a write handle, which triggers ProjFS to asynchronously hydrate the file from placeholder to full. The original test set CreationTime first, then immediately set LastAccessTime, LastWriteTime, and Attributes. Diagnostic testing (PR #1922) revealed that LastAccessTime is silently dropped by ProjFS when the set occurs while hydration is in progress:

ORIGINAL:        C=03:14:47  A=03:14:55  W=03:14:55   placeholder=True
IMMEDIATE READ:  C=testValue A=03:14:55  W=testValue   placeholder=False
                              ↑ unchanged — set was silently dropped during hydration
RE-SET A:        A=testValue  ← re-setting after hydration always works

Key findings from diagnostic CI runs:

  • Only LastAccessTime is reliably affected; CreationTime and LastWriteTime always succeed
  • The value is dropped during the set, not overwritten later — origA == readA in every failure
  • Re-setting after hydration completes always succeeds
  • Setting LastAccessTime, LastWriteTime, and Attributes do not trigger hydration on their own (they don't open a write handle)

Fix

Move the CreationTime set (the only one that triggers hydration) to after the other three property sets. This way, LastAccessTime, LastWriteTime, and Attributes are all pending on the placeholder when hydration begins, and ProjFS preserves them through the transition.

Also adds a post-hydration timestamp verification after the attribute retry loop to confirm all three timestamps persist through the full hydration cycle.

Validation

Stress-tested in CI via PR #1922:

Test Runs Failures Rate
Original order (CreationTime first) ~126 28 22%
Per-field on separate files + retry 300 0 0%

Diagnostic runs: v1, diagnostic, final

No production code in VFSForGit sets CreationTime on placeholder files, so the ProjFS race does not affect production behavior.

ProjFS Bug

This investigation revealed a bug in ProjFS: when CreationTime is set on a placeholder (triggering hydration via a write handle open), subsequent metadata sets — particularly LastAccessTime — can be silently dropped if they occur while the async hydration is still in progress. This is a ProjFS kernel driver issue. VFSForGit has no timestamp management code and delegates metadata handling entirely to ProjFS, so there is nothing VFSForGit can do to fix this at the application layer.

The test fix works around the ProjFS bug by reordering property sets so that hydration is triggered last, after all other metadata is already in place on the placeholder.

The test was flaky because setting CreationTime on a placeholder opens
a write handle which triggers ProjFS to asynchronously hydrate the file.
When LastAccessTime was set immediately after (while hydration was still
in progress), ProjFS could silently drop the set. Diagnostics confirmed
this is deterministic: the set is lost, not overwritten later.

Fix: reorder the property sets so CreationTime (the only one that
triggers hydration via handle open) is set LAST, after LastAccessTime,
LastWriteTime, and Attributes are already pending on the placeholder.
This ensures all metadata is in place before hydration begins.

Also adds a post-hydration timestamp verification after the attribute
retry loop to confirm all three timestamps persist through hydration.

No production code in VFSForGit sets CreationTime on placeholder files,
so this ProjFS race does not affect production behavior.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@tyrielv tyrielv force-pushed the tyrielv/fix-flaky-expanded-attrs branch from d2caf3d to ae767b8 Compare March 25, 2026 21:23
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