Reliability fixes for PackageDeploymentManager test - #6693
Merged
Vineeth Thomas Alex (vineeththomasalex) merged 4 commits intoAug 18, 2026
Conversation
…n ERROR_PACKAGES_IN_USE retry Test::Packages::AddPackage() retries AddPackageAsync up to 5 times with exponential backoff (~15s total) when it hits ERROR_PACKAGES_IN_USE (0x80073D02), but always reissues with DeploymentOptions::None. When an earlier test's activated app (e.g. IsPackageRegistrationPending_Pending's Test.PackageManager.M.Black instance) hasn't fully released its package lock within that window -- or a deferred registration from a prior test hasn't completed settling -- every retry fails identically and the in-place upgrade to Test.PackageManager.M.Blacker never makes progress. RemovePackage_Blacker()/RemovePackage_Black() call into this same AddPackage() path whenever the target package is staged-but-not-registered (to register it before removal), and are invoked pervasively across PackageDeploymentManagerTests_Register, _IsPackageRegistrationPending, and _IsReadyOrNewerAvailable -- including from TEST_CLASS_SETUP/TEST_CLASS_CLEANUP. A single stuck AddPackage() there fails the fixture and TAEF cascades every test in the class to [Failed] with empty error text, then the leftover staged package repeats the same race in the next class that runs. Fix: once AddPackageAsync fails with ERROR_PACKAGES_IN_USE, escalate to DeploymentOptions::ForceTargetApplicationShutdown on the next retry so the deployment service force-closes the blocking process itself instead of us guessing how long to wait -- this is the option the platform documents for exactly this error. The first attempt is left as DeploymentOptions::None so a clean install is never destructive. This should eliminate the 0x80073D02 cascade behind ~221 failures in Test-Foundation (PackageDeploymentManagerTests_Register, _IsPackageRegistrationPending, _IsReadyOrNewerAvailable). It does not change the unrelated, already-known IsPackageRegistrationPending_Pending API-behavior assertion at IsPackageRegistrationPending.cpp:108. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 7a243429-2b18-4b9a-aea2-f207cc2ea908
|
Azure Pipelines: There may be pipelines that require an authorized user to comment /azp run to run. |
Add a short note to the AddPackage() comment clarifying that the escalation can only ever close a process left over from an earlier, already-finished test - no test installs the package it's actively exercising via this helper while that app is running (confirmed: the IsPackageRegistrationPending "_Pending" tests exercise the in-use/deferred scenario through AddPackageByUri's DeferRegistrationWhenPackagesAreInUse path, which this change doesn't touch) - and that unconditional use of ForceApplicationShutdown in Shared.cpp's and TestSetupAndTeardownHelper.h's InstallPackage() helpers is existing precedent for this exact mitigation in this test suite. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: 7a243429-2b18-4b9a-aea2-f207cc2ea908
Collaborator
Author
|
/azp run |
|
Azure Pipelines: Successfully started running 1 pipeline(s). 1 pipeline(s) were filtered out due to trigger conditions. |
…er/vithoma/fix-packagedeploymentmanager-test-isolation
Collaborator
Author
|
/azp run |
|
Azure Pipelines: Successfully started running 1 pipeline(s). 1 pipeline(s) were filtered out due to trigger conditions. |
Vineeth Thomas Alex (vineeththomasalex)
requested a review
from Kyaw Thant (kythant)
August 18, 2026 21:10
Vineeth Thomas Alex (vineeththomasalex)
marked this pull request as ready for review
August 18, 2026 21:10
|
Azure Pipelines: There may be pipelines that require an authorized user to comment /azp run to run. |
Vineeth Thomas Alex (vineeththomasalex)
enabled auto-merge (squash)
August 18, 2026 21:10
ssparach
approved these changes
Aug 18, 2026
Vineeth Thomas Alex (vineeththomasalex)
disabled auto-merge
August 18, 2026 23:16
Vineeth Thomas Alex (vineeththomasalex)
merged commit Aug 18, 2026
3b1f049
into
release/dev/monobuild
44 of 46 checks passed
Vineeth Thomas Alex (vineeththomasalex)
deleted the
user/vithoma/fix-packagedeploymentmanager-test-isolation
branch
August 18, 2026 23:17
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
221 of the ~228 transient failures on WinAppSDK-Test-Foundation (def 192441) stem from one test-isolation defect:
Reference runs:
Root cause (cascade)
Test::Packages::AddPackage()already retriesAddPackageAsyncup to 5 times with exponential backoff (~15s total) when it hitsERROR_PACKAGES_IN_USE(0x80073D02), but always reissues withDeploymentOptions::None.RemovePackage_Blacker()/RemovePackage_Black()call into this exactAddPackage()path whenever the target package is staged-but-not-registered (they register it first so it can be removed). These helpers are called pervasively acrossPackageDeploymentManagerTests_Register,_IsPackageRegistrationPending, and_IsReadyOrNewerAvailable— including fromTEST_CLASS_SETUP/TEST_CLASS_CLEANUP.PackageDeploymentManagerTests_IsPackageRegistrationPending's*_Pendingtests activateTest.PackageManager.M.Black(same package family as Blacker) and defer-register Blacker while it's running. A prior fix (#6678) added a wait for the activated process to exit, but the OS-side "in use" bookkeeping for the package family doesn't necessarily clear the instant the process handle signals — the deferred registration completing is a separate async step. When it hasn't settled by the time the nextRemovePackage_Blacker()call fires (in the same class's cleanup, or the next class's setup),AddPackageAsyncfails with0x80073D02again, and 5 retries at ~15s total isn't always enough. A single stuck call inside aTEST_CLASS_SETUP/TEST_CLASS_CLEANUPfixture fails the whole fixture, and TAEF cascades every test in the class to[Failed]with empty error text — and the leftover staged package repeats the same race in the next class that runs, which is why the cascade spans three classes.Confirmed directly from the ADO test results for build 154915868 (
IsPackageRegistrationPendingForUser_NotInstalled,_Registered,_Pending, and bothIsReadyOrNewerAvailablefailures all show the identicalAddPackageAsync('...Blacker...') = 0x80073D02...Test.PackageManager.M.Black_1.2.3.4...failure atWindowsAppRuntime.Test.Package.h:459; all 38Register::*tests fail with empty error text from the cascadedClassSetup).Fix 1: cascade fix (force-close on retry)
Once
AddPackageAsyncfails withERROR_PACKAGES_IN_USE, escalate toDeploymentOptions::ForceTargetApplicationShutdownon the next retry so the deployment service force-closes the blocking process itself instead of guessing how long to wait — this is the option the platform documents for exactly this error ("If this package is currently in use, the processes associated with the package are shut down forcibly so that registration can continue."). The first attempt is left asDeploymentOptions::Noneso a clean install is never destructive; only a confirmedERROR_PACKAGES_IN_USEfailure escalates subsequent retries.This is a single, universal choke point: every
RemovePackage_Blacker()/RemovePackage_Black()call across all three affected test classes funnels through this sameAddPackage()function, so the fix addresses the cascade regardless of which specific test left the package family "in use".Fix 2: defensive hardening (bounded
OpenEventWretry)While investigating the 2 residual
IsPackageRegistrationPending_Pending/IsPackageRegistrationPendingForUser_Pendingfailures (a separate, pre-existing, real product-behavior issue — see Scope below), an exhaustive local-VM investigation (raw FrameworkUdk export, compiled WinRT wrapper, native harness replicating the real test's exact call sequence, and finally the actual unmodified TAEF test binary end-to-end — all passed reliably) did not force-reproduce the CI-specific trigger. The most concrete candidate mechanism found was a fragile, non-retryingOpenEventW+RETURN_LAST_ERROR_IF_NULLpattern in the test apps'winmain.cpp(PackageManager.Test.M.Black.msix/PackageManager.Test.M.Blacker.msix) — a single missed/delayed event-open attempt fails the whole app launch with no retry.Added a bounded retry (5s budget, 50ms poll interval) before falling back to the original behavior. This is defensive hardening for a plausible CI-environment-specific timing issue, not a proven fix for the
_Pendingissue — that issue remains open and out of scope (see below), but this change is safe, tested, and closes off one class of test-app-side flakiness regardless.Scope
test/inc/WindowsAppRuntime.Test.Package.h,test/PackageManager/data/PackageManager.Test.M.{Black,Blacker}.msix/winmain.cpp). No product code changed.IsPackageRegistrationPending_Pending/IsPackageRegistrationPendingForUser_PendingAPI-behavior assertion atIsPackageRegistrationPending.cpp:108(API returnsfalsefor the pending state) — that's a real product-behavior issue investigated exhaustively (local VM: raw export, compiled wrapper, native harness, and the actual unmodified TAEF binary all pass reliably) but not root-caused; it's a separate, real, CI-environment-specific issue tracked for future work, out of scope per the original task.ABForward::FunctionalTests::ClassInit(2 failures) is a separate fixture, not addressed here.Verification — real CI, real source-built IXP, twice
Validated via the monobuild's targeted rebuild-stage mechanism (
useBuildOutput_RebuildStage=Foundation), which rebuilds Foundation from this branch against a prior monobuild run's already-source-builtInteractiveExperiences(LiftedIXP/FrameworkUdk) artifacts, then auto-triggers a realWinAppSDK-Test-Foundation(def 192441) run — without triggering a full monobuild.Cascade fix alone: producer build 155077760 → test build 155084977.
Combined (cascade fix + hardening, this branch's current state): producer build 155179455 → test build 155187907.
Result (both runs, identical): 228 → 14 total individual test failures across all 12 configs, queried directly via the Test Results API:
IsPackageRegistrationPending_Pending/...ForUser_Pending(pre-existing, known, out-of-scope — see above)Zero
0x80073D02and zeroRegister::ClassSetupfailures anywhere across all 12 configs — confirmed by scanning every failed-test's title and error message.Also independently validated via
WinAppSDK-Foundation-PR(def 189940, builds from PR merge ref against a pinned/NuGet IXP dependency — proves no regression, though it doesn't exercise the source-built-IXP condition): 0/12 configs failed for both the cascade fix alone and the combined branch. And via local VM: the actual unmodified TAEFPackageManagerTests.dll, real MSIX packages, real Framework/DataStore/LifetimeManager packages, and real bootstrap infrastructure — all built from source and run end-to-end, 8/8 tests passing in the affected class.