Title: Test failures from module-path refactor PR #26565: tests 103778 / 103842 / 108309 fail on ZIP/TAR/portable distribution lanes · Issue #27346 · PowerShell/PowerShell · GitHub
Open Graph Title: Test failures from module-path refactor PR #26565: tests 103778 / 103842 / 108309 fail on ZIP/TAR/portable distribution lanes · Issue #27346 · PowerShell/PowerShell
X Title: Test failures from module-path refactor PR #26565: tests 103778 / 103842 / 108309 fail on ZIP/TAR/portable distribution lanes · Issue #27346 · PowerShell/PowerShell
Description: Summary Three Pester tests fail in the ReleaseAutomationTest comparison of 7.7.0-preview.1 against the 7.6.0-rc.1 baseline on portable (ZIP/TAR) and several non-portable distribution lanes. All three are downstream of PR #26565 ("Refacto...
Open Graph Description: Summary Three Pester tests fail in the ReleaseAutomationTest comparison of 7.7.0-preview.1 against the 7.6.0-rc.1 baseline on portable (ZIP/TAR) and several non-portable distribution lanes. All thr...
X Description: Summary Three Pester tests fail in the ReleaseAutomationTest comparison of 7.7.0-preview.1 against the 7.6.0-rc.1 baseline on portable (ZIP/TAR) and several non-portable distribution lanes. All thr...
Opengraph URL: https://github.com/PowerShell/PowerShell/issues/27346
X: @github
Domain: github.com
{"@context":"https://schema.org","@type":"DiscussionForumPosting","headline":"Test failures from module-path refactor PR #26565: tests 103778 / 103842 / 108309 fail on ZIP/TAR/portable distribution lanes","articleBody":"## Summary\n\nThree Pester tests fail in the `ReleaseAutomationTest` comparison of 7.7.0-preview.1 against the 7.6.0-rc.1 baseline on portable (ZIP/TAR) and several non-portable distribution lanes. All three are downstream of PR #26565 (\"Refactor the module path construction code\", commit `592668bd0`), which is in `release/v7.7.0-preview.1` but is **not** in `v7.6.0-rc.1` (verified: `git merge-base --is-ancestor 592668bd0 v7.6.0-rc.1` returns 1).\n\n| Test ID | Test | File | Origin |\n|---|---|---|---|\n| 103778 | `ConsoleHost - SettingsFile - PSModulePath - Verify PowerShell PSModulePath should contain paths from config file` (Windows) | `test/powershell/Host/ConsoleHost.Tests.ps1#L402` | New test added by PR #26565 |\n| 103842 | Non-Windows equivalent of 103778 (same `It` block, run on Linux/macOS lanes) | `test/powershell/Host/ConsoleHost.Tests.ps1#L402` | New test added by PR #26565 |\n| 108309 | `Import-Module with WinCompat - WinCompat process does not inherit PowerShell-Core-specific paths` | `test/powershell/Modules/Microsoft.PowerShell.Core/CompatiblePSEditions.Module.Tests.ps1#L727` | Pre-existing since PR #7183 (2018); newly fails in preview.1 |\n\nLanes affected (one or more of these tests fail per lane):\n\n- `WindowsServer2016ZIP - Unelevated`\n- `ubuntu22 TAR`\n- `mariner ARM64`\n- `macOS TAR`, `macOS`\n- `linux ARM32`\n- `debian12`\n- `azurelinux30`\n\nFirst failing build: `ReleaseAutomationTest-27557-ps-671171`.\n\nThese tests were previously tracked as **Case 2 of issue #27343** and are split out here because the root cause is unrelated to PR #27305 (the original framing of #27343).\n\n## Background: what PR #26565 changed\n\nCommit `592668bd0` rewrote `ModuleIntrinsics.GetModulePath` and replaced the helper `AddToPath` (with `PathContainsSubstring`) with `UpdatePath`, which uses `HashSet\u003cstring\u003e` plus `Path.TrimEndingDirectorySeparator` for dedup and advances `insertPosition` after each insert. It also added a static `static ModuleIntrinsics() { SetModulePath(); }` initializer.\n\nThe \"EVT.Process exists\" branch in preview.1's `GetModulePath` is:\n\n```csharp\nstring systemModulePathToUse = string.IsNullOrEmpty(hklmMachineModulePath)\n ? psHomeModulePath\n : hklmMachineModulePath;\n\nint insertIndex = 0;\ncurrentProcessModulePath = UpdatePath(currentProcessModulePath, personalModulePathToUse, ref insertIndex);\ncurrentProcessModulePath = UpdatePath(currentProcessModulePath, sharedModulePath, ref insertIndex);\ncurrentProcessModulePath = UpdatePath(currentProcessModulePath, systemModulePathToUse, ref insertIndex);\n```\n\nWhen `hklmMachineModulePath` is non-empty, `systemModulePathToUse = hklmMachineModulePath` and `psHomeModulePath` (i.e., `$PSHOME/Modules`) is never added to the process `PSModulePath`. The same logical branch exists on Linux/macOS via the equivalent OS-level system module path.\n\nPR #26565 also added the **new** test `Verify PowerShell PSModulePath should contain paths from config file` (test 103778 / 103842) that asserts `$PSHOME/Modules` is already present at `IndexOf \u003e 0` in `$env:PSModulePath`. That assertion is incompatible with portable distributions where `$PSHOME` is a user-local path not registered in the OS-level `PSModulePath`.\n\n## Why each test fails\n\n### Tests 103778 (Windows) and 103842 (non-Windows)\n\n```powershell\n# BeforeAll: write settings file with PSModulePath = \"$PSHOME/Modules\u003csep\u003e$TestDrive/NonExist\"\n$psModulePath = \u0026 $powershell -NoProfile -SettingsFile $CustomSettingsFile -Command '$env:PSModulePath'\n# Assertion:\n$index = $psModulePath.IndexOf(\"$mPath1$pathSep\", [StringComparison]::OrdinalIgnoreCase)\n$index | Should -BeGreaterThan 0 # FAILS - $PSHOME/Modules ends up at position 0\n```\n\nFailure mechanics on a portable distribution:\n\n1. Child pwsh inherits parent `$env:PSModulePath` = `\u003cpersonal\u003e\u003csep\u003e\u003cshared\u003e\u003csep\u003e\u003cOS-defaults\u003e` and does **not** contain the ZIP/TAR-extracted `$PSHOME/Modules`.\n2. Settings-file `PSModulePath` is read as `hkcuUserModulePath = \"$PSHOME/Modules\u003csep\u003e$TestDrive/NonExist\"`.\n3. `GetModulePath` \"Process exists\" branch sets `personalModulePathToUse = hkcuUserModulePath`.\n4. `UpdatePath(current, \"$PSHOME/Modules\u003csep\u003e$TestDrive/NonExist\", ref insertIndex=0)`:\n - `$PSHOME/Modules` is NOT in `initialPaths` -\u003e inserted at position 0.\n - `$TestDrive/NonExist` is NOT in `initialPaths` -\u003e inserted at position 1.\n5. Final `PSModulePath` starts with `$PSHOME/Modules\u003csep\u003e$TestDrive/NonExist\u003csep\u003e...`.\n6. `IndexOf(\"$PSHOME/Modules\u003csep\u003e\")` = `0` -\u003e `Should -BeGreaterThan 0` fails.\n7. `StartsWith(\"$TestDrive/NonExist\u003csep\u003e\")` = `false` -\u003e later assertion also fails.\n\nThe `BeforeAll` comment in the test literally states: *\"$mPath1 already exists in the value of env PSModulePath, so it won''t be added again.\"* That precondition does not hold on portable distributions. Since the `It` block is shared across platforms, it manifests as test 103778 on Windows lanes and 103842 on non-Windows lanes.\n\n### Test 108309\n\n```powershell\n$pscoreSystemPath = Join-Path -Path $PSHOME -ChildPath 'Modules'\n$pscorePaths = $env:psmodulepath\n$pscorePaths | Should -BeLike \"*$pscoreSystemPath*\" # FAILS\n```\n\nSame root assumption - the test requires `$PSHOME/Modules` to be in `$env:PSModulePath`. On portable distributions this is not guaranteed.\n\nThis test is 7+ years old and **passed on the v7.6.0-rc.1 baseline** (confirmed via the rc.1 `ReleaseAutomationTest` xUnit output: `\u003ctest-case description=\"WinCompat process does not inherit PowerShell-Core-specific paths\" ... result=\"Success\" success=\"True\" executed=\"True\"/\u003e`). It now fails on preview.1, so this is a **real product-side regression** introduced by PR #26565 - not just a comparator artifact. The rc.1 code (`AddToPath` + `PathContainsSubstring`) produced an effective `PSModulePath` that contained `$PSHOME/Modules` on the affected lanes; preview.1's `UpdatePath` rewrite no longer does. A product-side fix is required in addition to the test fix below.\n\n## Suggested resolution\n\n**Test side (required regardless):** make the assertions portable-distribution-aware.\n\nFor tests 103778 / 103842 (`test/powershell/Host/ConsoleHost.Tests.ps1`):\n\nOption A - have `BeforeAll` ensure the precondition the test was written against:\n\n```powershell\nBeforeAll {\n $CustomSettingsFile = Join-Path -Path $TestDrive -ChildPath 'powershell.test.json'\n $mPath1 = Join-Path $PSHOME 'Modules'\n $mPath2 = Join-Path $TestDrive 'NonExist'\n $pathSep = [System.IO.Path]::PathSeparator\n\n # Test assumes $PSHOME/Modules is already in $env:PSModulePath.\n # On ZIP/TAR/portable distributions this may not hold; ensure it.\n $contains = $env:PSModulePath -split [regex]::Escape($pathSep) |\n Where-Object { [string]::Equals($_, $mPath1, 'OrdinalIgnoreCase') }\n if (-not $contains) {\n $script:savedPSModulePath = $env:PSModulePath\n $env:PSModulePath = \"$mPath1$pathSep$env:PSModulePath\"\n }\n\n $ModulePath = \"${mPath1}${pathSep}${mPath2}\".Replace(''\\'', \"\\\\\")\n Set-Content -Path $CustomSettingsfile -Value \"{`\"Microsoft.PowerShell:ExecutionPolicy`\":`\"Unrestricted`\", `\"PSModulePath`\": `\"$ModulePath`\" }\" -ErrorAction Stop\n}\n\nAfterAll {\n if ($script:savedPSModulePath) {\n $env:PSModulePath = $script:savedPSModulePath\n }\n}\n```\n\nOption B - skip when the precondition does not hold:\n\n```powershell\nIt \"Verify PowerShell PSModulePath should contain paths from config file\" {\n if (($env:PSModulePath -split [regex]::Escape([IO.Path]::PathSeparator)) -notcontains $mPath1) {\n Set-ItResult -Skipped -Because ''$PSHOME/Modules is not in $env:PSModulePath (portable distribution); test precondition does not hold.''\n return\n }\n # ... existing assertions ...\n}\n```\n\nFor test 108309 (`test/powershell/Modules/Microsoft.PowerShell.Core/CompatiblePSEditions.Module.Tests.ps1`):\n\n```powershell\nIt ''WinCompat process does not inherit PowerShell-Core-specific paths'' {\n $pscoreUserPath = Join-Path -Path $HOME -ChildPath \"Documents/PowerShell/Modules\"\n $pscoreSharedPath = Join-Path -Path $env:ProgramFiles -ChildPath \"PowerShell/Modules\"\n $pscoreSystemPath = Join-Path -Path $PSHOME -ChildPath ''Modules''\n $pscorePaths = $env:psmodulepath\n $pscorePaths | Should -BeLike \"*$pscoreUserPath*\"\n $pscorePaths | Should -BeLike \"*$pscoreSharedPath*\"\n if ($pscorePaths -like \"*$pscoreSystemPath*\") {\n $pscorePaths | Should -BeLike \"*$pscoreSystemPath*\"\n }\n # else: tolerated - portable/ZIP/TAR distributions do not put $PSHOME/Modules in $env:PSModulePath.\n # Remaining WinCompat exclusion assertions still run unchanged.\n # ...\n}\n```\n\n**Product side (required - confirmed regression):** PR #26565's `AddToPath` -\u003e `UpdatePath` rewrite changed the effective `PSModulePath` shape on the affected lanes; rc.1 included `$PSHOME/Modules`, preview.1 does not. Two viable options:\n\n1. **Always include `psHomeModulePath` in the system path.** In the \"EVT.Process exists\" branch of `ModuleIntrinsics.GetModulePath`, instead of:\n\n ```csharp\n string systemModulePathToUse = string.IsNullOrEmpty(hklmMachineModulePath)\n ? psHomeModulePath\n : hklmMachineModulePath;\n ...\n currentProcessModulePath = UpdatePath(currentProcessModulePath, systemModulePathToUse, ref insertIndex);\n ```\n\n add both, so `$PSHOME/Modules` is always present regardless of HKLM state:\n\n ```csharp\n if (!string.IsNullOrEmpty(hklmMachineModulePath))\n {\n currentProcessModulePath = UpdatePath(currentProcessModulePath, hklmMachineModulePath, ref insertIndex);\n }\n currentProcessModulePath = UpdatePath(currentProcessModulePath, psHomeModulePath, ref insertIndex);\n ```\n\n `UpdatePath` already dedups via `HashSet\u003cstring\u003e`, so no double-insertion when HKLM also contains `$PSHOME/Modules` (e.g. MSI install).\n\n2. **Restore the rc.1 path-construction shape directly** by reverting the relevant portion of `GetModulePath` to the pre-#26565 behavior (compose via `AddToPath` semantics) for the affected branch. Lower-risk for backport but loses the dedup/ordering improvements of #26565.\n\nOption 1 is preferred. After the fix, re-run the `ReleaseAutomationTest` lanes that originally failed (especially `WindowsServer2016ZIP - Unelevated`) and confirm `$PSHOME/Modules` is in `$env:PSModulePath`.\n\n## Branch strategy\n\nPer `.github/instructions/code-review-branch-strategy.instructions.md`: PR #26565 is on `master` and on `release/v7.7.0-preview.1`. Fix the test files on `master` first; backport to release branches as needed. Do not add ZIP/TAR-specific workarounds only on the release branch.\n\n## Files affected\n\n- `test/powershell/Host/ConsoleHost.Tests.ps1` (lines 391-413) - tests 103778 / 103842\n- `test/powershell/Modules/Microsoft.PowerShell.Core/CompatiblePSEditions.Module.Tests.ps1` (line 727) - test 108309\n- `src/System.Management.Automation/engine/Modules/ModuleIntrinsics.cs` - product-side fix for confirmed 108309 regression (rc.1 result: `Success`)\n\n## Related\n\n- PR #26565 - \"Refactor the module path construction code\" (commit `592668bd0`); not in `v7.6.0-rc.1`\n- Issue #27343 - parent triage issue (Cases 1 and 3); Case 2 was extracted into this issue\n- First failing build: `ReleaseAutomationTest-27557-ps-671171`","author":{"url":"https://github.com/jshigetomi","@type":"Person","name":"jshigetomi"},"datePublished":"2026-04-23T18:40:43.000Z","interactionStatistic":{"@type":"InteractionCounter","interactionType":"https://schema.org/CommentAction","userInteractionCount":0},"url":"https://github.com/27346/PowerShell/issues/27346"}
| route-pattern | /_view_fragments/issues/show/:user_id/:repository/:id/issue_layout(.:format) |
| route-controller | voltron_issues_fragments |
| route-action | issue_layout |
| fetch-nonce | v2:d49df407-243c-04a5-7a71-ddced86153dc |
| current-catalog-service-hash | 81bb79d38c15960b92d99bca9288a9108c7a47b18f2423d0f6438c5b7bcd2114 |
| request-id | 9564:1255E3:2BC2CD4:3E9F8E8:6A590661 |
| html-safe-nonce | ae0b8ec6bac4f2b468adb3de63b07283591408c75a42cf0796de5f30cfde65c6 |
| visitor-payload | eyJyZWZlcnJlciI6IiIsInJlcXVlc3RfaWQiOiI5NTY0OjEyNTVFMzoyQkMyQ0Q0OjNFOUY4RTg6NkE1OTA2NjEiLCJ2aXNpdG9yX2lkIjoiMTI1NDg5ODUxMjYyNzgyODMyMSIsInJlZ2lvbl9lZGdlIjoiaWFkIiwicmVnaW9uX3JlbmRlciI6ImlhZCJ9 |
| visitor-hmac | 1fa80868cacc021b40f104c1a7c5009e9222409f7d315c2d2a714d7cd9a6a573 |
| hovercard-subject-tag | issue:4318076327 |
| github-keyboard-shortcuts | repository,issues,copilot |
| google-site-verification | Apib7-x98H0j5cPqHWwSMm6dNU4GmODRoqxLiDzdx9I |
| octolytics-url | https://collector.github.com/github/collect |
| analytics-location | / |
| fb:app_id | 1401488693436528 |
| apple-itunes-app | app-id=1477376905, app-argument=https://github.com/_view_fragments/issues/show/PowerShell/PowerShell/27346/issue_layout |
| twitter:image | https://opengraph.githubassets.com/af01600c4f0edf625ab02d1d29aee4794126e3e3643a92852c47fa50a8a6421d/PowerShell/PowerShell/issues/27346 |
| twitter:card | summary_large_image |
| og:image | https://opengraph.githubassets.com/af01600c4f0edf625ab02d1d29aee4794126e3e3643a92852c47fa50a8a6421d/PowerShell/PowerShell/issues/27346 |
| og:image:alt | Summary Three Pester tests fail in the ReleaseAutomationTest comparison of 7.7.0-preview.1 against the 7.6.0-rc.1 baseline on portable (ZIP/TAR) and several non-portable distribution lanes. All thr... |
| og:image:width | 1200 |
| og:image:height | 600 |
| og:site_name | GitHub |
| og:type | object |
| og:author:username | jshigetomi |
| hostname | github.com |
| expected-hostname | github.com |
| None | 5f2a0c7865178af3d91dd9f13b0cdfc3c73a2529c873d2780bb4c01271a57ec6 |
| turbo-cache-control | no-preview |
| go-import | github.com/PowerShell/PowerShell git https://github.com/PowerShell/PowerShell.git |
| octolytics-dimension-user_id | 11524380 |
| octolytics-dimension-user_login | PowerShell |
| octolytics-dimension-repository_id | 49609581 |
| octolytics-dimension-repository_nwo | PowerShell/PowerShell |
| octolytics-dimension-repository_public | true |
| octolytics-dimension-repository_is_fork | false |
| octolytics-dimension-repository_network_root_id | 49609581 |
| octolytics-dimension-repository_network_root_nwo | PowerShell/PowerShell |
| turbo-body-classes | logged-out env-production page-responsive |
| disable-turbo | false |
| browser-stats-url | https://api.github.com/_private/browser/stats |
| browser-errors-url | https://api.github.com/_private/browser/errors |
| release | 9842457e8d7e3b2e1635a63af28da35614845510 |
| ui-target | full |
| theme-color | #1e2327 |
| color-scheme | light dark |
Links:
Viewport: width=device-width