GeezerVison is showing github.com — Make xUnit test run sequentially to rule out race conditions around 'powershell.config.json' by daxian-dbw · Pull Request #8945 · PowerShell/PowerShell
Conversation
PR Summary
Make xUnit test truly run sequentially to rule out race conditions around powershell.config.json.
Fix #8784 #8715
PR Context
We keep getting xUnit test failures due to the race condition around manipulating powershell.config.json file, even though we have been trying to run xUnit tests sequentially by having dotnet test -p:ParallelizeTestCollections=false. It turns out -p:ParallelizeTestCollections=false doesn't work, and we have to use xunit.runner.json to disable parallel running.
Failure example: https://powershell.visualstudio.com/PowerShell/_build/results?buildId=13830
From the exception below, we can see the all-user scope config file was there when we check for file existence in ReadValueFromFile, but was deleted when we came to creating a FileStream out of it.
This is because the all-user scope config file as created and deleted as part of the PSConfiguration tests. This is an evidence that tests are still running in parallel with dotnet test -p:ParallelizeTestCollections=false.
[xUnit.net 00:00:03.20] PSTests.Sequential.RunspaceTests.TestRunspaceWithPowerShellAndInitialSessionState [FAIL]
Failed PSTests.Sequential.RunspaceTests.TestRunspaceWithPowerShellAndInitialSessionState
Error Message:
System.IO.FileNotFoundException : Could not find file 'C:\Users\VssAdministrator\Documents\PowerShell\powershell.config.json'.
Stack Trace:
at System.IO.FileStream.ValidateFileHandle(SafeFileHandle fileHandle)
at System.IO.FileStream.CreateFileOpenHandle(FileMode mode, FileShare share, FileOptions options)
at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share, Int32 bufferSize, FileOptions options)
at System.Management.Automation.Configuration.PowerShellConfig.WaitForFile(String fullPath, FileMode mode, FileAccess access, FileShare share) in D:\a\1\s\src\System.Management.Automation\engine\PSConfiguration.cs:line 426
at System.Management.Automation.Configuration.PowerShellConfig.ReadValueFromFile[T](ConfigScope scope, String key, T defaultValue, Func`4 readImpl) in D:\a\1\s\src\System.Management.Automation\engine\PSConfiguration.cs:line 397
at System.Management.Automation.Utils.GetPolicySettingFromConfigFile[T](ConfigScope[] preferenceOrder) in D:\a\1\s\src\System.Management.Automation\engine\Utils.cs:line 523
at System.Management.Automation.Utils.GetPolicySetting[T](ConfigScope[] preferenceOrder) in D:\a\1\s\src\System.Management.Automation\engine\Utils.cs:line 509
at Microsoft.PowerShell.Commands.ModuleCmdletBase.GetModuleLoggingInformation(IEnumerable`1& moduleNames) in D:\a\1\s\src\System.Management.Automation\engine\Modules\ModuleCmdletBase.cs:line 4507
at System.Management.Automation.PSSnapInReader.ReadEnginePSSnapIns() in D:\a\1\s\src\System.Management.Automation\singleshell\config\MshSnapinInfo.cs:line 1068
at System.Management.Automation.Runspaces.InitialSessionState.CreateDefault() in D:\a\1\s\src\System.Management.Automation\engine\InitialSessionState.cs:line 1526
at PSTests.Sequential.RunspaceTests.TestRunspaceWithPowerShellAndInitialSessionState() in D:\a\1\s\test\xUnit\csharp\test_Runspace.cs:line 72
Results File: D:\a\1\s\ParallelXUnitTestResults.xml
PR Checklist
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
|
|
- powershell: |
|
|
|
Import-Module .\tools\ci.psm1
|
|
|
$ParallelXUnitTestResultsFile = "$(System.ArtifactsDirectory)\xunit\ParallelXUnitTestResults.xml"
|
|
|
$xUnitTestResultsFile = "$(System.ArtifactsDirectory)\xunit\xUnitTestResults.xml"
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could do something smarter here. Like:
- Get all items in the
xunit folder
- run
Test-XUnitTestResults on each item found
- or throw an exception if no items were found
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Although, this is not changed frequently. So, this is not blocking this PR.
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
|
I very wonder why we mask BUGs which are revealed by the tests?
Are we going to release 6.2 version that is subject to DoS attack by unprivileged user?
Are we going to release 6.2 version in which hosting applications will fall unpredictably in 9% of cases?
I expect that we fast fix the bugs:
|
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
I very wonder why we mask BUGs which are revealed by the tests?
This is not hiding bugs, but to fix our test script. Blindly running all xUnit tests in parallel is just wrong. Please take a look at the original script in Start-PSxUnit before your changes in #8356, the tests are categorized into PSTests.Sequential and PSTests.Parallel namespaces and the original script ran the PSTests.Sequential tests sequentially, and run PSTests.Parallel tests in parallel.
The categorization was for a reason -- config files get created and deleted in test_PSConfiguration.cs, and that will definitely cause unusually frequent race conditions with tests in test_Runspace.cs. That's why they are categorized into PSTests.Sequential namespace. Using default values when failed to access the file as you suggested won't help here, because that will still make the setting values unpredictable and cause the tests to fail randomly -- a test might expect a specific value of a setting but it gets a default value because of the race condition.
I could make the test script behave like before -- running PSTests.Sequential namespace tests in sequence and PSTests.Parallel namespace tests in parallel, but I chose to not do that because:
- we have to use the xunit config file to disable parallel, which make it cumbersome to run part of the tests sequentially and other part in parallel.
- it makes writing xunit test harder by requiring the author to know which namespace to use for his/her tests.
Be noted that, fixing the test script doesn't mean we don't want to fix the race condition issue regard to processing the config file.
Are we going to release 6.2 version that is subject to DoS attack by unprivileged user?
Travis Plunk (@TravisEz13) and I chatted about this offline and we believe this is not a release blocker because it's already an existing issue.
Are we going to release 6.2 version in which hosting applications will fall unpredictably in 9% of cases?
The 9% failure was because of the frequent creation/deletion of the config files within test_PSConfiguration.cs, which would be really really rare to happen in real scenarios.
|
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
Be noted that, fixing the test script doesn't mean we don't want to fix the race condition issue regard to processing the config file.
I am 😄 that the team will keep it under control. Thanks!
One extra note that if I hadn’t made these tests parallel, we wouldn’t start fixing these race conditions. I do not know how now we can identify such problems (?)
|
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
One extra note that if I hadn’t made these tests parallel, we wouldn’t start fixing these race conditions. I do not know how now we can identify such problems (?)
The flag -p:ParallelizeTestCollections=false stopped working starting from some point, so luckily we will run into the same failures even without your changes.
Besides, the intra-process synchronization problem was a known issue. Please see the PR description in #5809 (I just updated it to add a bullet point about the case that config file is not accessible).
|
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
the intra-process synchronization problem was a known issue.
We have so many open issues that it is easy to lost/forget important ones. It is difficult to prioritize work. And it seems GiHub doesn't help well. :-(
|
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
The flag -p:ParallelizeTestCollections=false stopped working starting from some point, so luckily we will run into the same failures even without your changes.
This problem is too rarely raised and running the tests in parallel is useless locally. Can we do it on CI (maybe optional) to track the race conditions?
|
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
Can we do it on CI (maybe optional) to track the race conditions?
Like I said previously, fixing the race condition won't help to make our test reliable if they are running in parallel, because the setting values returned are not predictable. A test may expect a specific value for a setting but instead get back the default value due to race condition and thus would fail. It should be tracked by an issue.
This problem is too rarely raised and running the tests in parallel is useless locally.
It's rarely raised because it rarely happens in real scenarios, and that's likely why the this issue has not been treated with high priority.
|
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
It should be tracked by an issue.
In long term yes. For now my suggestion was to create optional CI job (like CodeFactor or Codacy) so that we can track the state of affairs until we find better solution.
|
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
It's rarely raised because it rarely happens in real scenarios, and that's likely why the this issue has not been treated with high priority.
Rather, because PowerShell is rarely used. If we imagine that it would be used in high-load application such as Microsoft SCOR we would catch a bunch of unpredictable crashes. Or in multi-user system like Misrosoft Remote Desktop any regular user would block all system scripts by locking the config file!
|
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
any regular user would block all system scripts by locking the config file!
You could do the same to any applications.
For example, hold the pwsh.exe by opening the file with [System.IO.FileShare]::None, and you won't be able to start the pwsh.exe anymore:

So, yes, it's technically a DoS attack, but if a user is able to do it (has the permission), then there's always a way for him/her to do it, no matter we fix the race condition regarding config.json or not.
|
iSazonov reacted with thumbs up emoji
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
Reviewers
+1 more reviewer
Reviewers whose approvals may not affect merge requirements
Uh oh!
There was an error while loading. Please reload this page.
Labels
CL-Test
Indicates that a PR should be marked as a test change in the Change Log
Milestone
No milestone
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.
|