Remove DCOM support from *-Computer cmdlets (#5277)

Since DCOM is not supported in corefx there was a great deal of dead code in the computer cmdlets.
This PR removes all vestiges of DCOM support from:

- Rename-Computer
- Restart-Computer
- Stop-Computer

removing about 4500 lines of dead code. Also, tests are updated to provide more complete coverage.
I also removed test-connection completely to make way for @iSazonov upcoming PR to improve coverage in tests, I created some test hook code which will test the cmdlet code without actually calling the WMI method to restart/rename/stop the system
This commit is contained in:
James Truher [MSFT]
2017-11-01 10:59:41 -07:00
committed by Aditya Patwardhan
parent 6cbcf5dd3e
commit d43b2cf958
12 changed files with 357 additions and 4843 deletions
File diff suppressed because it is too large Load Diff
@@ -357,18 +357,6 @@
<data name="RestartComputerSkipped" xml:space="preserve">
<value>The computer {0} is skipped. Fail to retrieve its LastBootUpTime via the WMI service with the following error message: {1}.</value>
</data>
<data name="InvalidParameterForDCOM" xml:space="preserve">
<value>Parameter WsmanAuthentication should not be specified when the DCOM protocol is in use. {0}</value>
</data>
<data name="InvalidParameterForWSMan" xml:space="preserve">
<value>Parameters DcomAuthentication and Impersonation should not be specified when the WSMan protocol is in use. {0}</value>
</data>
<data name="ParameterConfliction" xml:space="preserve">
<value>Parameter WsmanAuthentication should not be specified with DcomAuthentication and Impersonation at the same time. {0}</value>
</data>
<data name="ParameterUsage" xml:space="preserve">
<value>Parameter WsmanAuthentication is valid only if the WSMan protocol is used. Parameters DcomAuthentication (Authentication) and Impersonation are valid only if the DCOM protocol is used.</value>
</data>
<data name="FailToTestSecureChannel" xml:space="preserve">
<value>Cannot verify the secure channel for the local computer. Operation failed with the following exception: {0}.</value>
</data>
@@ -396,24 +384,6 @@
<data name="FailToRetrieveLastRestorePoint" xml:space="preserve">
<value>Cannot validate the time interval for restore point creation. It failed to retrieve the last restore point with the following error message: {0}.</value>
</data>
<data name="RenameCommandWsmanAuthParamConflict" xml:space="preserve">
<value>Parameter WsmanAuthentication cannot be specified with the DCOM protocol. Parameter WSManAuthentication is valid only when the WSMan protocol is used.</value>
</data>
<data name="StopCommandAuthProtocolConflict" xml:space="preserve">
<value>Parameters DcomAuthentication and Impersonation cannot be specified with the WSMan protocol. {0}</value>
</data>
<data name="StopCommandParamMessage" xml:space="preserve">
<value>Parameter WsmanAuthentication is valid only when the WSMan protocol is used. Parameters DcomAuthentication and Impersonation are valid only when the DCOM protocol is used.</value>
</data>
<data name="StopCommandParamWSManAuthConflict" xml:space="preserve">
<value>Parameter WsmanAuthentication cannot be specified with DcomAuthentication or Impersonation parameters. {0}</value>
</data>
<data name="StopCommandWSManAuthProtocolConflict" xml:space="preserve">
<value>Parameter WsmanAuthentication cannot be specified with the DCOM protocol. {0}</value>
</data>
<data name="InvalidParameterDCOMNotSupported" xml:space="preserve">
<value>DcomAuthentication is not supported. Please use WsmanAuthentication instead.</value>
</data>
<data name="InvalidParameterSetAsJob" xml:space="preserve">
<value>The AsJob Parameter Set is not supported.</value>
</data>
@@ -59,7 +59,6 @@ CmdletsToExport=@("Add-Content",
"Remove-Service",
"Set-Content",
"Set-ItemProperty",
"Test-Connection",
"Restart-Computer",
"Stop-Computer",
"Rename-Computer",
@@ -1416,6 +1416,14 @@ namespace System.Management.Automation.Internal
internal static bool UseDebugAmsiImplementation;
internal static bool BypassAppLockerPolicyCaching;
internal static bool BypassOnlineHelpRetrieval;
// Stop/Restart/Rename Computer tests
internal static bool TestStopComputer;
internal static bool TestWaitStopComputer;
internal static bool TestRenameComputer;
internal static int TestStopComputerResults;
internal static int TestRenameComputerResults;
// It's useful to test that we don't depend on the ScriptBlock and AST objects and can use a re-parsed version.
internal static bool IgnoreScriptBlockCache;
// Simulate 'System.Diagnostics.Stopwatch.IsHighResolution is false' to test Get-Uptime throw
@@ -1423,7 +1431,7 @@ namespace System.Management.Automation.Internal
internal static bool DisableGACLoading;
/// <summary>This member is used for internal test purposes.</summary>
public static void SetTestHook(string property, bool value)
public static void SetTestHook(string property, object value)
{
var fieldInfo = typeof(InternalTestHooks).GetField(property, BindingFlags.Static | BindingFlags.NonPublic);
if (fieldInfo != null)
@@ -0,0 +1,79 @@
$RenameTesthook = "TestRenameComputer"
$RenameResultName = "TestRenameComputerResults"
$DefaultResultValue = 0
try
{
# set up for testing
$PSDefaultParameterValues["it:skip"] = ! $IsWindows
Enable-Testhook -testhookName $RenameTesthook
# we also set TestStopComputer
Enable-Testhook -testhookName TestStopComputer
# TEST START HERE
Describe "Rename-Computer" -Tag Feature {
# if we throw in BeforeEach, the test will fail and the stop will not be called
BeforeEach {
if ( ! (Test-TesthookIsSet -testhookName $RenameTesthook) ) {
throw "Testhook '${TesthookName}' is not set"
}
}
AfterEach {
Set-TesthookResult -testhookName $RenameResultName -value $defaultResultValue
}
It "Should rename the local computer" {
Set-TesthookResult -testhookName $RenameResultName -value $defaultResultValue
$newname = "mynewname"
$result = Rename-Computer -ErrorAction Stop -ComputerName . -NewName "$newname" -Pass -WarningAction SilentlyContinue
$result.HasSucceeded | should be $true
$result.NewComputerName | should be $newname
}
# we can't really look for the string "reboot" as it will change
# when translated. We are guaranteed that the old computer name will
# be present, so we'll look for that
It "Should produce a reboot warning when renaming computer" {
Set-TesthookResult -testhookName $RenameResultName -value $defaultResultValue
$newname = "mynewname"
$result = Rename-Computer -ErrorAction Stop -ComputerName . -NewName "$newname" -Pass -WarningAction SilentlyContinue -WarningVariable WarnVar
$WarnVar.Message | should match $result.OldComputerName
}
It "Should not produce a reboot warning when renaming a computer with the reboot flag" {
Set-TesthookResult -testhookName $RenameResultName -value $defaultResultValue
$newname = "mynewname"
$result = Rename-Computer -ErrorAction Stop -ComputerName . -NewName "$newname" -Pass -WarningAction SilentlyContinue -WarningVariable WarnVar -Restart
$result.HasSucceeded | should be $true
$result.NewComputerName | should be $newname
$WarnVar | should BeNullOrEmpty
}
Context "Rename-Computer Error Conditions" {
$testcases =
@{ OldName = "." ; NewName = "localhost" ; ExpectedError = "FailToRenameComputer,Microsoft.PowerShell.Commands.RenameComputerCommand" },
@{ OldName = "." ; NewName = "." ; ExpectedError = "InvalidNewName,Microsoft.PowerShell.Commands.RenameComputerCommand" },
@{ OldName = "." ; NewName = "::1" ; ExpectedError = "InvalidNewName,Microsoft.PowerShell.Commands.RenameComputerCommand" },
@{ OldName = "." ; NewName = "127.0.0.1" ; ExpectedError = "InvalidNewName,Microsoft.PowerShell.Commands.RenameComputerCommand" },
@{ OldName = "." ; NewName = ${env:ComputerName} ; ExpectedError = "NewNameIsOldName,Microsoft.PowerShell.Commands.RenameComputerCommand" },
@{ OldName = "." ; NewName = ${env:ComputerName} + "." + ${env:USERDNSDOMAIN} ; ExpectedError = "InvalidNewName,Microsoft.PowerShell.Commands.RenameComputerCommand" },
@{ OldName = ".\$#" ; NewName = "NewName"; ExpectedError = "AddressResolutionException,Microsoft.PowerShell.Commands.RenameComputerCommand" }
It "Renaming '<OldName>' to '<NewName>' creates the right error" -testcase $testcases {
param ( $OldName, $NewName, $ExpectedError )
Set-TesthookResult -testhookName $RenameResultName -value 0x1
{ Rename-Computer -ComputerName $OldName -NewName $NewName -ErrorAction Stop } | ShouldBeErrorId $ExpectedError
}
}
}
}
finally
{
$PSDefaultParameterValues.Remove("it:skip")
Disable-Testhook -testhookName $RenameTestHook
Disable-Testhook -testhookName TestStopComputer
Set-TesthookResult -testhookName $RenameResultName -value 0
}
@@ -0,0 +1,99 @@
# the testhook for restart-computer is the same as for stop-computer
$restartTesthookName = "TestStopComputer"
$restartTesthookResultName = "TestStopComputerResults"
$DefaultResultValue = 0
try
{
# set up for testing
$PSDefaultParameterValues["it:skip"] = ! $IsWindows
Enable-Testhook -testhookName $restartTesthookName
Describe "Restart-Computer" -Tag Feature {
# if we throw in BeforeEach, the test will fail and the restart will not be called
BeforeEach {
if ( ! (Test-TesthookIsSet -testhookName $restartTesthookName) ) {
throw "Testhook '${restartTesthookName}' is not set"
}
}
AfterEach {
Set-TesthookResult -testhookName $restartTesthookResultName -value $defaultResultValue
}
It "Should restart the local computer" {
Set-TesthookResult -testhookName $restartTesthookResultName -value $defaultResultValue
Restart-Computer -ErrorAction Stop| Should BeNullOrEmpty
}
It "Should support -computer parameter" {
Set-TesthookResult -testhookName $restartTesthookResultName -value $defaultResultValue
$computerNames = "localhost","${env:COMPUTERNAME}"
Restart-Computer -Computer $computerNames -ErrorAction Stop| Should BeNullOrEmpty
}
It "Should support WsmanAuthentication types" {
$authChoices = "Default","Basic","Negotiate","CredSSP","Digest","Kerberos"
foreach ( $auth in $authChoices ) {
Restart-Computer -WsmanAuthentication $auth | Should BeNullOrEmpty
}
}
# this requires setting a test hook, so we wrap the execution with try/finally of the
# set operation. Internally, we want to suppress the progress, so
# that is also wrapped in try/finally
It "Should wait for a remote system" {
try
{
Enable-Testhook -testhookname TestWaitStopComputer
$timeout = 3
try
{
$pPref = $ProgressPreference
$ProgressPreference="SilentlyContinue"
$duration = Measure-Command {
Restart-Computer -computer localhost -Wait -Timeout $timeout -ErrorAction stop | Should BeNullOrEmpty
}
}
finally
{
$ProgressPreference=$pPref
}
$duration.TotalSeconds | Should BeGreaterThan $timeout
}
finally
{
Disable-Testhook -testhookname TestWaitStopComputer
}
}
Context "Restart-Computer Error Conditions" {
It "Should return the proper error when it occurs" {
Set-TesthookResult -testhookName $restartTesthookResultName -value 0x300000
Restart-Computer -ErrorVariable RestartError 2>$null
$RestartError.Exception.Message | Should match 0x300000
}
It "Should produce an error when 'Delay' is specified" {
{ Restart-Computer -Delay 30 } | ShouldBeErrorId "RestartComputerInvalidParameter,Microsoft.PowerShell.Commands.RestartComputerCommand"
}
It "Should not support timeout on localhost" {
Set-TesthookResult -testhookName $restartTesthookResultName -value $defaultResultValue
{ Restart-Computer -timeout 3 -ErrorAction Stop } | ShouldBeErrorId "RestartComputerInvalidParameter,Microsoft.PowerShell.Commands.RestartComputerCommand"
}
It "Should not support timeout on localhost" {
Set-TesthookResult -testhookName $restartTesthookResultName -value $defaultResultValue
{ Restart-Computer -timeout 3 -ErrorAction Stop } | ShouldBeErrorId "RestartComputerInvalidParameter,Microsoft.PowerShell.Commands.RestartComputerCommand"
}
}
}
}
finally
{
$PSDefaultParameterValues.Remove("it:skip")
Disable-Testhook -testhookName $restartTesthookName
Set-TesthookResult -testhookName $restartTesthookResultName -value 0
}
@@ -0,0 +1,58 @@
# note these will manipulate private data in the PowerShell engine which will
# enable us to not actually stop the system, but return right before we do
$stopTesthook = "TestStopComputer"
$stopTesthookResultName = "TestStopComputerResults"
$DefaultResultValue = 0
try
{
# set up for testing
$PSDefaultParameterValues["it:skip"] = ! $IsWindows
Enable-Testhook -testhookName $stopTesthook
Describe "Stop-Computer" -Tag Feature {
# if we throw in BeforeEach, the test will fail and the stop will not be called
BeforeEach {
if ( ! (Test-TesthookIsSet -testhookName $stopTesthook) ) {
throw "Testhook '${stopTesthook}' is not set"
}
}
AfterEach {
Set-TesthookResult -testhookName $stopTesthookResultName -Value $defaultResultValue
}
It "Should stop the local computer" {
Set-TesthookResult -testhookName $stopTesthookResultName -Value $defaultResultValue
Stop-Computer -ErrorAction Stop| Should BeNullOrEmpty
}
It "Should support -Computer parameter" {
Set-TesthookResult -testhookName $stopTesthookResultName -Value $defaultResultValue
$computerNames = "localhost","${env:COMPUTERNAME}"
Stop-Computer -Computer $computerNames -ErrorAction Stop| Should BeNullOrEmpty
}
It "Should support WsmanAuthentication types" {
$authChoices = "Default","Basic","Negotiate","CredSSP","Digest","Kerberos"
foreach ( $auth in $authChoices ) {
Stop-Computer -WsmanAuthentication $auth | Should BeNullOrEmpty
}
}
Context "Stop-Computer Error Conditions" {
It "Should return the proper error when it occurs" {
Set-TesthookResult -testhookName $stopTesthookResultName -Value 0x300000
Stop-Computer -ErrorVariable StopError 2>$null
$StopError.Exception.Message | Should match 0x300000
}
}
}
}
finally
{
$PSDefaultParameterValues.Remove("it:skip")
Disable-Testhook -testhookName $stopTesthook
Set-TesthookResult -testhookName $stopTesthookResultName -Value $DefaultResultValue
}
@@ -1,39 +0,0 @@
Describe "Test-Connection" -Tags "CI" {
BeforeAll {
$originalDefaultParameterValues = $PSDefaultParameterValues.Clone()
if ( ! $IsWindows )
{
$PSDefaultParameterValues["it:skip"] = $true
}
else
{
$countCases = @(
@{count = 2}
@{count = 3}
)
$quietTests = @(
@{computerName = 'localhost'; message = 'online' ; result = $true}
@{computerName = '_fake_computer_namex'; message = 'offline' ; result = $false}
)
}
}
AfterAll {
$global:PSDefaultParameterValues = $originalDefaultParameterValues
}
It "Gets the right IP Address" {
$localHost = Test-Connection -ComputerName localhost -Count 1
$localHost.IPV4Address | Should Be '127.0.0.1'
$localhost.IPV6Address | Should Be '::1'
}
It "The count parameter counting to <count>" -TestCases $countCases {
param($count)
(Test-Connection -ComputerName localhost -Count $count).Count | Should Be $count
}
It "The quiet parameter on a <message> computer" -TestCases $quietTests {
param($computername, $result)
Test-Connection -ComputerName $computername -Count 1 -Quiet | Should Be $result
}
}
@@ -16,8 +16,6 @@ Describe "Unimplemented Management Cmdlet Tests" -Tags "CI" {
"Get-ComputerInfo",
"Test-Connection",
"Set-TimeZone"
)
@@ -435,7 +435,6 @@ Describe "Verify approved aliases list" -Tags "CI" {
"Cmdlet", "Suspend-Service", , $($FullCLR -or $CoreWindows )
"Cmdlet", "Tee-Object", , $($FullCLR -or $CoreWindows -or $CoreUnix)
"Cmdlet", "Test-ComputerSecureChannel", , $($FullCLR )
"Cmdlet", "Test-Connection", , $($FullCLR -or $CoreWindows )
"Cmdlet", "Test-FileCatalog", , $($FullCLR -or $CoreWindows )
"Cmdlet", "Test-ModuleManifest", , $($FullCLR -or $CoreWindows -or $CoreUnix)
"Cmdlet", "Test-Path", , $($FullCLR -or $CoreWindows -or $CoreUnix)
@@ -16,5 +16,5 @@ Copyright = 'Copyright (c) Microsoft Corporation. All rights reserved.'
Description = 'Temporary module contains functions for using in tests'
FunctionsToExport = 'Wait-UntilTrue', 'Test-IsElevated', 'ShouldBeErrorId', 'Wait-FileToBePresent', 'Get-RandomFileName'
FunctionsToExport = 'Wait-UntilTrue', 'Test-IsElevated', 'ShouldBeErrorId', 'Wait-FileToBePresent', 'Get-RandomFileName', 'Enable-Testhook', 'Disable-Testhook', 'Set-TesthookResult', 'Test-TesthookIsSet'
}
@@ -82,3 +82,58 @@ function Get-RandomFileName
{
[System.IO.Path]::GetFileNameWithoutExtension([IO.Path]::GetRandomFileName())
}
#
# Testhook setting functions
# note these manipulate private data in the PowerShell engine which will
# enable us to not actually alter the system or mock returned data
#
$SCRIPT:TesthookType = [system.management.automation.internal.internaltesthooks]
function Test-TesthookIsSet
{
param (
[ValidateNotNullOrEmpty()]
[Parameter(Mandatory=$true)]
$testhookName
)
try {
return ${Script:TesthookType}.GetField($testhookName, "NonPublic,Static").GetValue($null)
}
catch {
# fall through
}
return $false
}
function Enable-Testhook
{
param (
[ValidateNotNullOrEmpty()]
[Parameter(Mandatory=$true)]
$testhookName
)
${Script:TesthookType}::SetTestHook($testhookName, $true)
}
function Disable-Testhook
{
param (
[ValidateNotNullOrEmpty()]
[Parameter(Mandatory=$true)]
$testhookName
)
${Script:TesthookType}::SetTestHook($testhookName, $false)
}
function Set-TesthookResult
{
param (
[ValidateNotNullOrEmpty()]
[Parameter(Mandatory=$true)]
$testhookName,
[ValidateNotNullOrEmpty()]
[Parameter(Mandatory=$true)]
$value
)
${Script:TesthookType}::SetTestHook($testhookName, $value)
}