Team Ai
Datasetpublic

MegaBites-AI/Windows-powershell

sourceHugging Facemitupdated 6mo agoView on Hugging Face
0likes372downloads
ConfigProvider.Tests.ps1471 linesDownload Raw Back to Microsoft.WSMan.Management
1# Copyright (c) Microsoft Corporation.2# Licensed under the MIT License.3 4[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingConvertToSecureStringWithPlainText', '')]5param()6 7Describe "WSMan Config Provider" -Tag Feature,RequireAdminOnWindows {8    BeforeAll {9        #skip all tests on non-windows platform10        $originalDefaultParameterValues = $PSDefaultParameterValues.Clone()11        $PSDefaultParameterValues["it:skip"] = !$IsWindows12 13        if ($IsWindows) {14            $badCredentialError = 132615            $pluginXml = [xml](winrm g winrm/config/plugin?name=microsoft.powershell -format:xml)16            $pluginPath = "WSMan:\localhost\Plugin\microsoft.powershell"17            $testPluginXml = [xml]($pluginXml.OuterXml)18            $testPluginXml.PlugInConfiguration.Name = "TestPlugin"19            $testPluginXml.PlugInConfiguration.RemoveAttribute("xml:lang")20            $testPluginXml.PlugInConfiguration.Resources.Resource.ResourceUri = "http://schemas.microsoft.com/powershell/TestPlugin"21            $testPluginXml.PlugInConfiguration.Resources.Resource.Security.Uri = "http://schemas.microsoft.com/powershell/TestPlugin"22            Set-Content $TestDrive\plugin.xml -Value $testPluginXml.OuterXml23            $null = winrm c winrm/config/plugin?Name=TestPlugin -file:$TestDrive\plugin.xml24            $testPluginPath = "WSMan:\localhost\Plugin\TestPlugin"25            $testUser = (Get-Random)26            $testPass = "Secret123!"27            $null = net user $testUser $testPass /add28        }29    }30 31    AfterAll {32        $Global:PSDefaultParameterValues = $originalDefaultParameterValues33        if ($IsWindows) {34            $null = winrm d winrm/config/plugin?Name=TestPlugin35            $null = net user $testUser /DELETE36        }37    }38 39    Function Test-Plugin($plugin, $expectedMissingProperties, $expectedMissingAttributes) {40        $plugin.PSPath | Should -Exist41        $testPluginXml = [xml](winrm g winrm/config/plugin?name=$($plugin.Name) -format:xml)42        $pluginProperties = Get-ChildItem $plugin.PSPath43        $xmlElementCount = ($testPluginXml.PluginConfiguration | Get-Member -Type Properties).Count + $expectedMissingProperties.Count - $expectedMissingAttributes.Count44        $pluginProperties.Count | Should -BeExactly $xmlElementCount45        foreach ($pluginProperty in $pluginProperties) {46            if ($pluginProperty.Type -eq "System.String") {47                $pluginProperty.Value | Should -Be $testPluginXml.PluginConfiguration.$($pluginProperty.Name)48                (Get-Item "$($plugin.PSPath)\$($pluginProperty.Name)").Value | Should -Be $testPluginXml.PluginConfiguration.$($pluginProperty.Name)49            }50        }51    }52 53    AfterEach {54        if (-not (Test-Path wsman:))55        {56            $null = New-PSDrive -Name WSMan -PSProvider WSMan -Root "" -Scope Global57        }58    }59 60    Context "Misc tests" {61        It "Can remove and add wsman drive" {62            $wsmanDrive = Get-PSDrive -Name WSMan63            Remove-PSDrive -Name wsman64            { Get-PSDrive -Name wsman -ErrorAction Stop } | Should -Throw -ErrorId "GetLocationNoMatchingDrive,Microsoft.PowerShell.Commands.GetPSDriveCommand"65            $wsmanDrive2 = $wsmanDrive | New-PSDrive -PSProvider WSMan66            $wsmanDrive2 | Should -BeOfType System.Management.Automation.PSDriveInfo67            $wsmanDrive2.Name | Should -BeExactly "WSMan"68            $wsmanDrive2.Provider.Name | Should -BeExactly "WSMan"69        }70 71        It "WSMan Config Provider starts WinRM if it is stopped" {72            try {73                Stop-Service WinRM74                Get-ChildItem wsman:\localhost -Force | Should -Not -BeNullOrEmpty75                (Get-Service WinRM).Status | Should -Be 'Running'76            }77            finally {78                if ((Get-Service WinRM).Status -eq 'stopped') {79                    Start-Service WinRM80                }81            }82        }83 84        It "Container check works" {85            Test-Path wsman:\foo -PathType container | Should -BeFalse86        }87    }88 89    Context "Get-Item tests" {90 91        It "Plugin has correct properties" {92            $plugin = Get-Item $pluginPath93            Test-Plugin -Plugin $plugin94        }95 96        It "Plugin InitializationParameters are correct" {97            $initializationParameters = Get-ChildItem $pluginPath\InitializationParameters98            $initializationParameters.Count | Should -Be (,$pluginXml.PluginConfiguration.InitializationParameters.Param).Count99            foreach ($initializationParameter in $initializationParameters) {100                $initializationParameter.Value | Should -Be ($pluginXml.PluginConfiguration.InitializationParameters | Where-Object { $_.Param.Name -eq $initializationParameter.Name }).Param.Value101                (Get-Item $pluginPath\InitializationParameters\$($initializationParameter.Name)).Value | Should -Be ($pluginXml.PluginConfiguration.InitializationParameters | Where-Object { $_.Param.Name -eq $initializationParameter.Name }).Param.Value102            }103        }104 105        It "Plugin Quotas are correct" {106            $quotas = Get-ChildItem $pluginPath\Quotas107            $quotas.Count | Should -Be ($pluginXml.PluginConfiguration.Quotas | Get-Member -Type Properties).Count108            foreach ($quota in $quotas) {109                $quota.Value | Should -Be $pluginXml.PluginConfiguration.Quotas.$($quota.Name)110            }111        }112 113        It "Plugin Resources are correct" {114            $resources = Get-ChildItem $pluginPath\Resources115            $resources.Count | Should -Be (,$pluginXml.PluginConfiguration.Resources.Resource).Count116        }117 118        It "Plugin Security Resource is correct" {119            (,$pluginXml.PluginConfiguration.Resources.Resource).Count | Should -Be 1 # by default only Security resource should be there120            $resource = Get-ChildItem "$pluginPath\Resources" | Select-Object -First 1121            $resourceUri = Get-Item "$($resource.PSPath)\ResourceUri"122            $resourceUri.Value | Should -Be "http://schemas.microsoft.com/powershell/microsoft.powershell"123            $securityContainer = Get-ChildItem "$pluginPath\Resources\$($resource.Name)\Security" | Select-Object -First 1124            $securityProperties = Get-ChildItem $securityContainer.PSPath125            $skippedAttributes = @("ParentResourceUri","xmlns") # these are added by the WSMan Config Provider but not in the original xml126 127            # ParentResourceUri is added by the Config Provider, xmlns existing seems to be dependent on WinRM which is inconsistent128            $securityProperties.Count | Should -BeGreaterThan (($pluginXml.PluginConfiguration.Resources.Resource.Security | Get-Member -Type Properties).Count)129            foreach ($securityProperty in $securityProperties) {130                if ($skippedAttributes -notcontains $securityProperty.Name) {131                    $securityProperty.Value | Should -Be ($pluginXml.PluginConfiguration.Resources.Resource.Security.$($securityProperty.Name))132                    (Get-Item "$($securityContainer.PSPath)\$($securityProperty.Name)").Value | Should -Be ($pluginXml.PluginConfiguration.Resources.Resource.Security.$($securityProperty.Name))133                }134            }135        }136    }137 138    Context "Set-Item tests" {139        It "Set-Item should fail for `$null value" {140            { Set-Item WSMan:\localhost\Client\TrustedHosts $null } | Should -Throw -ErrorId "System.ArgumentException,Microsoft.PowerShell.Commands.SetItemCommand"141        }142 143        It "Set-Item should fail for <path>" -TestCases @(144            @{path="WSMan:\"},145            @{path="WSMan:\localhost"}146        ) {147            param ($path)148            { Set-Item $path "foo" } | Should -Throw -ErrorId "System.InvalidOperationException,Microsoft.PowerShell.Commands.SetItemCommand"149        }150 151        It "Set-Item -WhatIf should work" {152            $trustedHostsPath = "WSMan:\localhost\Client\TrustedHosts"153            $trustedHosts = Get-Item $trustedHostsPath154            Set-Item $trustedHostsPath "hello" -WhatIf155            (Get-Item $trustedHostsPath).Value | Should -Be $trustedHosts.Value156        }157 158        It "Set-Item on TrustedHosts should succeed" {159            try {160                $trustedHostsPath = "WSMan:\localhost\Client\TrustedHosts\"161                $trustedHosts = Get-Item $trustedHostsPath162                Set-Item -Path $trustedHostsPath -Value "hello" -Force163                (Get-Item $trustedHostsPath).Value | Should -Be "hello"164            }165            finally {166                Set-Item $trustedHostsPath $trustedHosts.Value -Force167            }168        }169 170        It "Set-Item on plugin RunAsUser should fail for invalid creds" {171            #[SuppressMessage("Microsoft.Security", "CS002:SecretInNextLine", Justification="Demo/doc/test secret.")]172            $password = ConvertTo-SecureString "My voice is my passport, verify me" -AsPlainText -Force173            $creds = [pscredential]::new((Get-Random),$password)174            $exception = { Set-Item $testPluginPath\RunAsUser $creds } | Should -Throw -ErrorId "System.InvalidOperationException,Microsoft.PowerShell.Commands.SetItemCommand" -PassThru175            $exception.Exception.Message | Should -Match ".*$badCredentialError.*"176        }177 178        It "Set-Item and Clear-Item on plugin RunAsUser should succeed for valid creds" {179            $password = ConvertTo-SecureString $testPass -AsPlainText -Force180            $creds = [pscredential]::new($testUser,$password)181            Set-Item $testPluginPath\RunAsUser $creds -WarningAction SilentlyContinue182            (Get-Item $testPluginPath\RunAsUser).Value | Should -Be $testUser183            (Get-Item $testPluginPath\RunAsPassword).Value | Should -Be "System.Security.SecureString"184            Clear-Item $testPluginPath\RunAsUser -WarningAction SilentlyContinue185            (Get-Item $testPluginPath\RunAsUser).Value | Should -BeNullOrEmpty186            (Get-Item $testPluginPath\RunAsPassword).Value | Should -BeNullOrEmpty187        }188 189        It "Set-Item on plugin RunAsUser should fail for invalid password" {190            #[SuppressMessage("Microsoft.Security", "CS002:SecretInNextLine", Justification="Demo/doc/test secret.")]191            $password = ConvertTo-SecureString "My voice is my passport, verify me" -AsPlainText -Force192            $creds = [pscredential]::new($testUser,$password)193            $exception = { Set-Item $testPluginPath\RunAsUser $creds } | Should -Throw -ErrorId "System.InvalidOperationException,Microsoft.PowerShell.Commands.SetItemCommand" -PassThru194            $exception.Exception.Message | Should -Match ".*$badCredentialError.*"195        }196 197        It "Set-Item on password without user on plugin should fail for <password>" -TestCases @(198            #[SuppressMessage("Microsoft.Security", "CS002:SecretInNextLine", Justification="Demo/doc/test secret.")]199            @{password=(ConvertTo-SecureString "My voice is my passport, verify me" -AsPlainText -Force)},200            #[SuppressMessage("Microsoft.Security", "CS002:SecretInNextLine", Justification="Demo/doc/test secret.")]201            @{password="hello"}202        ) {203            param($password)204            Clear-Item $testPluginPath\RunAsUser -WarningAction SilentlyContinue205            { Set-Item $testPluginPath\RunAsPassword $password } | Should -Throw -ErrorId "System.InvalidOperationException,Microsoft.PowerShell.Commands.SetItemCommand"206        }207 208        It "Set-Item on plugin XmlRenderingType property should succeed for '<type>'" -TestCases @(209            @{type="XmlReader"},210            @{type="text"},211            @{type="xMLrEADER"},212            @{type="TEXT"}213        ) {214            param ($type)215            Set-Item $testPluginPath\XmlRenderingType $type -WarningAction SilentlyContinue216            (Get-Item $testPluginPath\XmlRenderingType).Value | Should -Be $type217        }218 219        It "Set-Item on non-existent property should fail" {220            { Set-Item $testPluginPath\foo "bar" } | Should -Throw -ErrorId "System.InvalidOperationException,Microsoft.PowerShell.Commands.SetItemCommand"221        }222 223        It "Set-Item on plugin Resource '<property>' property with '<value>' should succeed" -TestCases @(224            @{property="SupportsOptions"; value=$false; expected="False"},225            @{property="sUPPORTSoPTIONS"; value=$true; expected="True"}226        ) {227            param($property, $value, $expected)228            $resource = Get-ChildItem "$testPluginPath\Resources" | Select-Object -First 1229            Set-Item "$($resource.PSPath)\$property" $value -WarningAction SilentlyContinue230            (Get-Item "$($resource.PSPath)\$property").Value | Should -BeExactly $expected231        }232 233        It "Set-Item on plugin Security Resource '<property>' property with '<value>' should succeed" -TestCases @(234            # truncated version of the default SDDL235            @{property="Sddl"; value="O:NSG:BAD:P(A;;GA;;;BA)"},236            # default SDDL set by WinRM237            @{property="SDDL"; value="O:NSG:BAD:P(A;;GA;;;BA)(A;;GA;;;IU)(A;;GA;;;RM)S:P(AU;FA;GA;;;WD)(AU;SA;GXGW;;;WD)"}238        ) {239            param($property, $value, $expected)240            $resource = Get-ChildItem "$testPluginPath\Resources" | Select-Object -First 1241            $security = Get-ChildItem "$($resource.PSPath)\Security" | Select-Object -First 1242            Set-Item "$($security.PSPath)\$property" $value -WarningAction SilentlyContinue -Force243            (Get-Item "$($security.PSPath)\$property").Value | Should -Be $value244        }245 246        It "Set-Item on plugin Security Resource '<property>' property with invalid '<value>' should fail" -TestCases @(247            @{property="Sddl"; value="foo"},248            @{property="sDDL"; value="D:P(A;;GA;;;BA)"} # truncated version of default SDDL with owner removed249        ) {250            param($property, $value, $expected)251            $resource = Get-ChildItem "$testPluginPath\Resources" | Select-Object -First 1252            $security = Get-ChildItem "$($resource.PSPath)\Security" | Select-Object -First 1253            { Set-Item "$($security.PSPath)\$property" $value -Force } | Should -Throw -ErrorId "System.InvalidOperationException,Microsoft.PowerShell.Commands.SetItemCommand"254        }255 256        It "Set-Item on plugin InitializationParameters '<property>' property with '<value>' should succeed" -TestCases @(257            @{property="PSVersion"; value="6.0.0"},258            @{property="psvERSION"; value="5.1"}259        ) {260            param($property, $value)261            Set-Item "$testPluginPath\InitializationParameters\$property" $value -WarningAction SilentlyContinue262            (Get-Item "$testPluginPath\InitializationParameters\$property").Value | Should -Be $value263        }264 265        It "Set-Item on plugin Quotas '<property>' property with '<value>' should succeed" -TestCases @(266            @{property="IdleTimeoutms"; value=61000},267            @{property="iDLEtIMEOUTMS"; value=7200000},268            @{property="MaxShells"; value=1},269            @{property="mAXsHELLS"; value=2147483647}270            ) {271            param($property, $value)272            Set-Item "$testPluginPath\Quotas\$property" $value -WarningAction SilentlyContinue273            (Get-Item "$testPluginPath\Quotas\$property").Value | Should -Be $value274        }275 276        It "Set-Item on plugin Quotas out of range on '<property>' property with '<value>' should fail" -TestCases @(277            @{property="IdleTimeoutms"; value=59999},278            @{property="MaxShells"; value=0}279        ) {280            param($property, $value)281            { Set-Item "$testPluginPath\Quotas\$property" $value -WarningAction SilentlyContinue } | Should -Throw -ErrorId "System.InvalidOperationException,Microsoft.PowerShell.Commands.SetItemCommand"282        }283    }284 285    Context "Clear-Item tests" {286        It "Clear-Item on <property> should fail" -TestCases @(287            @{property="Filename"},288            @{property="Quotas\IdleTimeoutms"},289            @{property="InitializationParameters\PSVersion"}290        ) {291            { Clear-Item "$testPluginPath\$property" -WarningAction SilentlyContinue } | Should -Throw -ErrorId "System.InvalidOperationException,Microsoft.PowerShell.Commands.ClearItemCommand"292        }293    }294 295    Context "New-Item and Remove-Item tests" {296        It "New-Item and Remove-Item at root should succeed" -TestCases @(297            @{name=$env:computername;expected=$env:computername},298            @{name="${env:computername}\";expected=$env:computername}299        ) {300            param($name, $expected)301            try {302                $connections = Get-ChildItem wsman:\303                $newItem = New-Item WSMan:\$name304                "WSMan:\$name" | Should -Exist305                (Get-ChildItem wsman:\).Count | Should -Be ($connections.Count + 1)306                # not a .Net type so can't use BeOfType307                $newItem.PSObject.TypeNames[0] | Should -Be "Microsoft.WSMan.Management.WSManConfigContainerElement#ComputerLevel"308                $newItem.Name | Should -Be $expected309                Remove-Item WSMan:\$name -Recurse -Force310                "WSMan:\$name" | Should -Not -Exist311            }312            finally {313                Remove-Item WSMan:\$name -Recurse -Force -ErrorAction SilentlyContinue314            }315        }316 317        It "New-Item and Remove-Item for a listener" {318            try {319                $newListener = New-Item -Path WSMan:\localhost\Listener\ -Address IP:127.0.0.1 -port 6666 -Transport HTTP -Enabled $false -HostName foo -URLPrefix bar -Force320                $listenerName = $newListener.Name321                $listenerName | Should -Not -BeNullOrEmpty322                $properties = Get-ChildItem "WSMan:\localhost\Listener\$listenerName"323                $listenerXml = [xml](winrm g winrm/config/listener?Address=IP:127.0.0.1+Transport=HTTP -format:xml)324                $expectedMissingAttributes = "cfg","xsi","lang"325                $properties.Count | Should -Be (($listenerXml.Listener | Get-Member -Type Properties).Count - $expectedMissingAttributes.Count)326                foreach ($property in $properties) {327                    if (-not $property.Name.StartsWith("ListeningOn")) { # this property is represented differently328                        $property.Value | Should -Be $listenerXml.Listener.$($property.Name)329                    }330                }331                Remove-Item -Path "WSMan:\localhost\Listener\$listenerName" -Recurse -Force332                $newListener.PSPath | Should -Not -Exist333            }334            finally {335                Remove-Item -Path "WSMan:\localhost\Listener\$listenerName" -Recurse -Force -ErrorAction SilentlyContinue336            }337        }338 339        It "New-Item and Remove-Item for a plugin using parameters" {340            try {341                $password = ConvertTo-SecureString $testPass -AsPlainText -Force342                $creds = [pscredential]::new($testUser, $password)343                $plugin = New-Item -Plugin TestPlugin2 -UseSharedProcess -AutoRestart `344                    -ProcessIdleTimeoutSec 120 -FileName "${env:windir}\system32\pwrshplugin.dll" `345                    -SDKVersion 2 -Resource foo -Capability shell -XMLRenderingType text -Path WSMan:\localhost\plugin `346                    -RunAsCredential $creds347                $expectedMissingProperties = @("InitializationParameters")348                Test-Plugin -Plugin $plugin -expectedMissingProperties $expectedMissingProperties349                Remove-Item WSMan:\localhost\Plugin\TestPlugin2\ -Recurse -Force350                "WSMan:\localhost\Plugin\TestPlugin2" | Should -Not -Exist351            }352            finally {353                Remove-Item WSMan:\localhost\Plugin\TestPlugin2\ -Recurse -Force -ErrorAction SilentlyContinue354            }355        }356 357        It "New-Item and Remove-Item for a plugin using a file" {358            $fileXml = @"359<PlugInConfiguration Name="TestPlugin2" Filename="${env:windir}\system32\pwrshplugin.dll" SDKVersion="2" XmlRenderingType="text" Enabled="false"360 Architecture="64" UseSharedProcess="true" ProcessIdleTimeoutSec="0" RunAsUser="" RunAsPassword="" AutoRestart="false" RunAsVirtualAccount="false"361 RunAsVirtualAccountGroups="" OutputBufferingMode="Block" xmlns="http://schemas.microsoft.com/wbem/wsman/1/config/PluginConfiguration">362    <InitializationParameters>363        <Param Name="PSVersion" Value="5.1"></Param>364    </InitializationParameters>365    <Resources>366        <Resource ResourceUri="http://schemas.microsoft.com/powershell/TestPlugin2" SupportsOptions="true" ExactMatch="true">367            <Security Uri="http://schemas.microsoft.com/powershell/TestPlugin2"368                Sddl="O:NSG:BAD:P(A;;GA;;;BA)(A;;GA;;;IU)(A;;GA;;;RM)S:P(AU;FA;GA;;;WD)(AU;SA;GXGW;;;WD)" ExactMatch="False"></Security>369            <Capability Type="Shell"></Capability>370        </Resource>371    </Resources>372    <Quotas MaxIdleTimeoutms="2147483646" MaxConcurrentUsers="{0}" IdleTimeoutms="6200000" MaxProcessesPerShell="2147483646"373        MaxMemoryPerShellMB="2147483646" MaxConcurrentCommandsPerShell="2147483646" MaxShells="2147483646" MaxShellsPerUser="2147483646"></Quotas>374</PlugInConfiguration>375"@376            $osInfo = [System.Environment]::OSVersion.Version377            $isSrv2k12R2 = $osInfo.Major -eq 6 -and $osInfo.Minor -eq 3378 379            # On Windows Server 2012R2 MaxConcurrentUsers is limited to 100.380            $maxConcurrentUsers = if ($isSrv2k12R2) { '50' } else { '2147483646' }381 382            $fileXml = $fileXml -f $maxConcurrentUsers383 384            Set-Content -Path $testdrive\plugin.xml -Value $fileXml385            try {386                $plugin = New-Item -Path WSMan:\localhost\Plugin -File $testdrive\plugin.xml -Name TestPlugin2387                Test-Plugin -Plugin $plugin388                Remove-Item WSMan:\localhost\Plugin\TestPlugin2\ -Recurse -Force389                "WSMan:\localhost\Plugin\TestPlugin2\" | Should -Not -Exist390            }391            finally {392                Remove-Item "WSMan:\localhost\Plugin\TestPlugin2\" -Recurse -Force -ErrorAction SilentlyContinue393            }394        }395 396        It "New-Item and Remove-Item for a plugin resource" {397            try {398                $resource = New-Item -Path WSMan:\localhost\Plugin\TestPlugin\Resources\ `399                    -ResourceUri http://foo -Capability shell400                $resource.PSPath | Should -Exist401                $properties = Get-ChildItem $resource.PSPath402                ($properties | Where-Object { $_.Name -eq "ResourceUri" }).Value | Should -Be "http://foo/"403                ($properties | Where-Object { $_.Name -eq "Capability" })[0].Value | Should -Be "shell"404                Remove-Item $resource.PSPath -Recurse -Force405                $resource.PSPath | Should -Not -Exist406            }407            finally {408                Remove-Item $resource.PSPath -Recurse -Force -ErrorAction SilentlyContinue409            }410        }411 412        It "New-Item and Remove-Item for an initialization parameter" {413            try {414                $parameter = New-Item -Path WSMan:\localhost\Plugin\TestPlugin\InitializationParameters `415                    -ParamName foo -ParamValue bar416                $parameterObj = Get-Item $parameter.PSPath417                $parameterObj.Name | Should -Be "foo"418                $parameterObj.Value | Should -Be "bar"419                Remove-Item $parameter.PSPath -Force420                $parameter.PSPath | Should -Not -Exist421            }422            finally {423                Remove-Item $parameter.PSPath -Force -ErrorAction SilentlyContinue424            }425        }426 427        It "New-Item and Remove-Item for a security resource" {428            try {429                $sddl = "O:NSG:BAD:P(A;;GA;;;BA)"430                $resource = Get-ChildItem -Path WSMan:\localhost\Plugin\TestPlugin\Resources\ | Select-Object -First 1431                # remove existing security resource since the folder name is just a hash of the resource uri432                Get-ChildItem "$($resource.PSPath)\Security" | Remove-Item -Recurse -Force433                $security = New-Item "$($resource.PSPath)\Security" -SDDL $sddl -Force434                $security.PSPath | Should -Exist435                $securityObj = Get-Item $security.PSPath436                (Get-ChildItem $securityObj.PSPath | Where-Object { $_.Name -eq 'sddl' }).Value | Should -Be $sddl437                Remove-Item $security.PSPath -Recurse -Force438                $security.PSPath | Should -Not -Exist439            }440            finally {441                Remove-Item $security.PSPath -Recurse -Force -ErrorAction SilentlyContinue442            }443        }444    }445 446    Context "Get-Help tests" {447        It "Get-Help while in WSMan: drive works" {448            try {449                Push-Location WSMan:\localhost450                Get-Help New-Item | Should -Not -BeNullOrEmpty451            }452            finally {453                Pop-Location454            }455        }456    }457 458    Context 'ItemSeparator properties' {459        It 'WSMan provider has ItemSeparator properties' {460 461            (Get-PSProvider WSMan).ItemSeparator | Should -Be '\'462            (Get-PSProvider WSMan).AltItemSeparator | Should -Be '/'463        }464 465        It 'ItemSeparator properties is read-only in WSMan provider' {466            { (Get-PSProvider WSMan).ItemSeparator = $null } | Should -Throw467            { (Get-PSProvider WSMan).AltItemSeparator = $null } | Should -Throw468        }469    }470}471