diff --git a/test/powershell/Modules/Microsoft.PowerShell.LocalAccounts/Pester.Command.Cmdlets.LocalAccounts.LocalGroup.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.LocalAccounts/Pester.Command.Cmdlets.LocalAccounts.LocalGroup.Tests.ps1 new file mode 100644 index 0000000000..d94de782e1 --- /dev/null +++ b/test/powershell/Modules/Microsoft.PowerShell.LocalAccounts/Pester.Command.Cmdlets.LocalAccounts.LocalGroup.Tests.ps1 @@ -0,0 +1,855 @@ +# This is a Pester test suite to validate the cmdlets in LocalAccounts module +# +# Copyright (c) Microsoft Corporation, 2015 + +# LocalAccounts does not work outside of windows +if(-not $IsWindows) +{ + return +} + +function RemoveTestGroups +{ + param([string] $basename) + + $results = Get-LocalGroup $basename* + foreach ($element in $results) { + Remove-LocalGroup -SID $element.SID + } +} + +function VerifyFailingTest +{ + param( + [scriptblock] $sb, + [string] $expectedFqeid + ) + + $backupEAP = $script:ErrorActionPreference + $script:ErrorActionPreference = "Stop" + + try { + & $sb + throw "Expected FullyQualifiedErrorId: $expectedFqeid" + } + catch { + $_.FullyQualifiedErrorId | Should Be $expectedFqeid + } + finally { + $script:ErrorActionPreference = $backupEAP + } +} + +Describe "Verify Expected LocalGroup Cmdlets are present" -Tags "CI" { + + It "Test command presence" { + $result = Get-Command -Module Microsoft.PowerShell.LocalAccounts | % Name + + $result -contains "New-LocalGroup" | Should Be $true + $result -contains "Set-LocalGroup" | Should Be $true + $result -contains "Get-LocalGroup" | Should Be $true + $result -contains "Rename-LocalGroup" | Should Be $true + $result -contains "Remove-LocalGroup" | Should Be $true + } +} + +Describe "Validate simple New-LocalGroup" -Tags "CI", "Feature" { + AfterEach { + RemoveTestGroups -basename TestGroupAddRemove + } + + It "Creates New-LocalGroup using only name" { + $result = New-LocalGroup -Name TestGroupAddRemove + + $result.Name | Should BeExactly TestGroupAddRemove + $result.ObjectClass | Should Be Group + } +} + +Describe "Validate New-LocalGroup cmdlet" -Tags "Feature" { + AfterEach { + RemoveTestGroups -basename TestGroupAddRemove + } + + It "Creates New-LocalGroup with name and description" { + $result = New-LocalGroup -Name TestGroupAddRemove -Description "Test Group New 1 Description" + + $result.Name | Should BeExactly TestGroupAddRemove + $result.Description | Should BeExactly "Test Group New 1 Description" + $result.SID | Should Not BeNullOrEmpty + $result.ObjectClass | Should Be Group + } + + It "Errors on New-LocalGroup with name collision" { + $sb = { + New-LocalGroup TestGroupAddRemove + return New-LocalGroup TestGroupAddRemove + } + VerifyFailingTest $sb "GroupExists,Microsoft.PowerShell.Commands.NewLocalGroupCommand" + } + + It "Can use SID for group name" { + $sidName = "S-1-5-21-3949576937-491355012-4054854628-1053" + try { + $result = New-LocalGroup -Name $sidName + + $result | Should Not BeNullOrEmpty + $result.Name | Should BeExactly $sidName + $result.SID | Should Not BeExactly $sidName + $result.ObjectClass | Should Be Group + } + finally { + RemoveTestGroups -basename $sidName + } + } + + It "Errors on empty group name" { + $sb = { New-LocalGroup -Name "" } + VerifyFailingTest $sb "ParameterArgumentValidationError,Microsoft.PowerShell.Commands.NewLocalGroupCommand" + } + + It "Creates New-LocalGroup with name(256) at max" { + $nameMax = "A"*256 + $desc = "D"*48 + + try { + $result = New-LocalGroup -Name $nameMax -Description $desc + + $result.Name | Should BeExactly $nameMax + $result.Description | Should BeExactly $desc + $result.SID | Should Not BeNullOrEmpty + $result.ObjectClass | Should Be Group + } + finally { + RemoveTestGroups -basename $nameMax + } + } + + It "Errors on New-LocalGroup with name(256) over max" { + $name = "A"*257 + $desc = "D"*129 + + try { + $shouldBeNull = New-LocalGroup -Name $name -Description $desc + throw "An error was expected" + } + catch { + $_.FullyQualifiedErrorId | Should Be "ParameterArgumentValidationError,Microsoft.PowerShell.Commands.NewLocalGroupCommand" + } + finally { + #clean up erroneous creation + if ($shouldBeNull) { Remove-LocalGroup -Name $name } + } + } + + It "Creates New-LocalGroup with Description > 48 characters" { + $descMax = "Test Group Add Description that is longer than 48 characters" + $result = New-LocalGroup -Name TestGroupAddRemove -Description $descMax + + $result.Description | Should BeExactly $descMax + } + + It "Errors on Invalid characters" { + #Arrange + #list of characters that should be invalid + $InvalidCharacters = @" +\/"[]:|<>+=;,?* +"@ + $failedCharacters = @() + + $InvalidCharacters = $InvalidCharacters[0..($InvalidCharacters.Length - 1)] + + #Act + foreach ($character in $InvalidCharacters) { + try { + $invalidGroup = New-LocalGroup -Name ("InvalidBecauseOf" + $character) -ErrorAction Stop + } + catch { + } + finally { + if ($invalidGroup) { + Remove-LocalGroup -Name $invalidGroup + $failedCharacters += $character + } + } + } + + if ($failedCharacters.Count -gt 0) { Write-Host "characters causing test fail: $failedCharacters" } + $failedCharacters.Count -eq 0 | Should Be true + } + + It "Error on names containing only spaces" { + $sb = { New-LocalGroup -Name " " } + + VerifyFailingTest $sb "InvalidName,Microsoft.PowerShell.Commands.NewLocalGroupCommand" + } + + It "Error on names containing only periods" { + $sb = { + New-LocalGroup -Name "..." + } + + VerifyFailingTest $sb "InvalidName,Microsoft.PowerShell.Commands.NewLocalGroupCommand" + } + + It "Errors on names ending in a period" { + $sb = { + New-LocalGroup -Name "TestEndInPeriod." + } + + VerifyFailingTest $sb "InvalidName,Microsoft.PowerShell.Commands.NewLocalGroupCommand" + + $sb = { + New-LocalGroup -Name ".TestEndIn.Period.." + } + + VerifyFailingTest $sb "InvalidName,Microsoft.PowerShell.Commands.NewLocalGroupCommand" + } + + It "Errors on Name over 256 characters" { + $sb = { New-LocalGroup -Name ("A"*257) } + + try { + VerifyFailingTest $sb "ParameterArgumentValidationError,Microsoft.PowerShell.Commands.NewLocalGroupCommand" + } + finally { + RemoveTestGroups -basename ("A"*257) + } + } +} + +Describe "Validate simple Get-LocalGroup" -Tags "CI", "Feature" { + BeforeAll { + New-LocalGroup -Name TestGroupGet1 -Description "Test Group Get 1 Description" | Out-Null + } + + AfterAll { + RemoveTestGroups -basename TestGroupGet + } + + It "Can Get-LocalGroup by specific group name" { + $result = Get-LocalGroup TestGroupGet1 + + $result.Name | Should Be "TestGroupGet1" + $result.Description | Should Be "Test Group Get 1 Description" + $result.ObjectClass | Should Be "Group" + } +} + +Describe "Validate Get-LocalGroup cmdlet" -Tags "Feature" { + + BeforeAll { + New-LocalGroup -Name TestGroupGet1 -Description "Test Group Get 1 Description" | Out-Null + New-LocalGroup -Name TestGroupGet2 -Description "Test Group Get 2 Description" | Out-Null + } + + AfterAll { + RemoveTestGroups -basename TestGroupGet + } + + #Note: this test is no longer in the test plan + It "Can Get-LocalGroup of all groups" { + $result = Get-LocalGroup + + $result.Count -gt 2 | Should Be true + } + + It "Can Get-LocalGroup of a specific group by SID" { + $result = Get-LocalGroup TestGroupGet1 + $resultBySID = Get-LocalGroup -SID $result.SID + + $resultBySID.SID | Should Not BeNullOrEmpty + $resultBySID.Name | Should Be TestGroupGet1 + } + + It "Can Get-LocalGroup of a well-known group by SID string" { + $sid = New-Object System.Security.Principal.SecurityIdentifier -ArgumentList BG + $guestGroup = Get-LocalGroup -SID BG + + $guestGroup.SID | Should Be $sid.Value + } + + It "Can Get-LocalGroup by wildcard" { + $result = Get-LocalGroup TestGroupGet* + + $result.Count -eq 2 | Should Be true + $result.Name -contains "TestGroupGet1" | Should Be true + $result.Name -contains "TestGroupGet2" | Should Be true + } + + It "Can Get-LocalGroup gets by array of names" { + $result = Get-LocalGroup @("TestGroupGet1", "TestGroupGet2") + + $result.Count -eq 2 | Should Be true + $result.Name -contains "TestGroupGet1" | Should Be true + $result.Name -contains "TestGroupGet2" | Should Be true + } + + It "Can Get-LocalGroups by array of SIDs" { + $sid1 = (Get-LocalGroup TestGroupGet1).SID + $sid2 = (Get-LocalGroup TestGroupGet2).SID + $result = Get-LocalGroup -SID @($sid1, $sid2) + + $result.Count -eq 2 | Should Be true + $result.Name -contains "TestGroupGet1" | Should Be true + $result.Name -contains "TestGroupGet2" | Should Be true + } + + It "Can Get-LocalGroups by pipe of an array of Group objects" { + $testGroups = Get-LocalGroup TestGroupGet* + $result = @($testGroups, $testGroups) | Get-LocalGroup + + $result.Count -eq 4 | Should Be true + $result.Name -contains "TestGroupGet1" | Should Be true + $result.Name -contains "TestGroupGet2" | Should Be true + } + + It "Can respond to -ErrorAction Stop" { + $result = $null + try { + Get-LocalGroup @("TestGroupGet1", "TestGroupGetNameThatDoesntExist1", "TestGroupGetNameThatDoesntExist2") -ErrorAction Stop -ErrorVariable outErr -OutVariable outOut | Out-Null + } + catch { + $result = @($outErr.Count, $outErr[0].ErrorRecord.CategoryInfo.Reason, $outOut.Name) + } + + if ($result -eq $null) + { + # Force failing the test because an unexpected outcome occurred + $false | Should Be $true + } + else + { + $result[0] -eq 1 | Should Be true + $result[1] -match "GroupNotFound" | Should Be true + $result[2] -match "TestGroupGet1" | Should Be true + } + } + + It "Errors on Get-LocalGroup by an invalid group name" { + $sb = { + Get-LocalGroup 'TestGroupGetNameThatDoesntExist' + } + VerifyFailingTest $sb "GroupNotFound,Microsoft.PowerShell.Commands.GetLocalGroupCommand" + } + + It "Errors on Get-LocalGroup by an invalid group SID" { + $sb = { + $result = New-LocalGroup -Name TestGroupGet3 -Description "Test Group Get 3 Description" + Remove-LocalGroup TestGroupGet3 + Get-LocalGroup -SID $result.SID + } + VerifyFailingTest $sb "GroupNotFound,Microsoft.PowerShell.Commands.GetLocalGroupCommand" + } + + It "Can get no local groups if none match wildcard" { + $localGroupName = 'TestGroupGetNameThatDoesntExist' + $result = (Get-LocalGroup $localGroupName*).Count + + $result -eq 0 | Should Be true + } +} + +Describe "Validate simple Set-LocalGroup" -Tags "CI", "Feature" { + BeforeAll { + $group1SID = "" + } + + BeforeEach { + $group1SID = (New-LocalGroup -Name TestGroupSet1).SID + } + + AfterEach { + RemoveTestGroups -basename TestGroupSet + $group1SID = "" + } + + It "Can Set-LocalGroup by name" { + Set-LocalGroup -Name TestGroupSet1 -Description "Test Group Set 1 new description" + $result = Get-LocalGroup -Name TestGroupSet1 + + $result.Description | Should BeExactly "Test Group Set 1 new description" + } +} + +Describe "Validate Set-LocalGroup cmdlet" -Tags "Feature" { + BeforeAll { + $group1SID = "" + } + + BeforeEach { + $group1SID = (New-LocalGroup -Name TestGroupSet1).SID + } + + AfterEach { + RemoveTestGroups -basename TestGroupSet + $group1SID = "" + } + + It "Can Set-LocalGroup by SID" { + Set-LocalGroup -SID $group1SID -Description "Test Group Set 1 newer description" + $result = Get-LocalGroup -Name TestGroupSet1 + + $result.Description | Should BeExactly "Test Group Set 1 newer description" + } + + It "Can Set-LocalGroup using -InputObject" { + $group = Get-LocalGroup TestGroupSet1 + Set-LocalGroup -InputObject $group -Description "Test Group Set 1 newer still description" + $result = Get-LocalGroup TestGroupSet1 + + $result.Description | Should BeExactly "Test Group Set 1 newer still description" + } + + It "Can Set-LocalGroup using pipeline" { + Get-LocalGroup TestGroupSet1 | Set-LocalGroup -Description "Test Group Set 1 newer still description" + $result = Get-LocalGroup TestGroupSet1 + + $result.Description | Should BeExactly "Test Group Set 1 newer still description" + } + + It "Errors on Set-LocalGroup without specifying a Group" { + $sb = { + Set-LocalGroup -Description "Test Group Set 1 newer still description" + } + VerifyFailingTest $sb "AmbiguousParameterSet,Microsoft.PowerShell.Commands.SetLocalGroupCommand" + } + + It "Errors on Set-LocalGroup with an invalid Group name" { + $sb = { + Set-LocalGroup -Name "NonexistantGroupName" -Description "Test Group Set 1 newer still description" + } + VerifyFailingTest $sb "GroupNotFound,Microsoft.PowerShell.Commands.SetLocalGroupCommand" + } + + It "Errors on Set-LocalGroup with an invalid Group SID" { + $sb = { + Set-LocalGroup -SID "S-1-5-21-1220945662-555555555-555555555-5555" -Description "Test Group Set 1 newer still description" + } + + VerifyFailingTest $sb "GroupNotFound,Microsoft.PowerShell.Commands.SetLocalGroupCommand" + } + + It "Can Set-LocalGroup with description over 48 characters" { + $desc = "A"*129 + Set-LocalGroup -Name TestGroupSet1 -Description $desc + $result = Get-LocalGroup -Name TestGroupSet1 + + $result.Description | Should BeExactly $desc + } +} + +Describe "Validate simple Rename-LocalGroup" -Tags "CI", "Feature" { + BeforeAll { + $group1SID = "" + $group2SID = (New-LocalGroup -Name TestGroupRename2 -Description "Test Group Rename 2 Description" ).SID + } + + AfterAll { + RemoveTestGroups -basename TestGroupRename + } + + BeforeEach { + $group1SID = ( New-LocalGroup -Name TestGroupRename1 -Description "Test Group Rename 1 Description" ).SID + } + + AfterEach { + Remove-LocalGroup -SID $group1SID + $group1SID = "" + } + + It "Can Rename-LocalGroup using a valid group name" { + $group1SID | Should Not BeNullOrEmpty + Rename-LocalGroup TestGroupRename1 TestGroupRename1x + $result = Get-LocalGroup -SID $group1SID + + $result.Name | Should BeExactly TestGroupRename1x + } +} + +Describe "Validate Rename-LocalGroup cmdlet" -Tags "Feature" { + BeforeAll { + $group1SID = "" + $group2SID = (New-LocalGroup -Name TestGroupRename2 -Description "Test Group Rename 2 Description" ).SID + } + + AfterAll { + RemoveTestGroups -basename TestGroupRename + } + + BeforeEach { + $group1SID = (New-LocalGroup -Name TestGroupRename1 -Description "Test Group Rename 1 Description" ).SID + } + + AfterEach { + Remove-LocalGroup -SID $group1SID + $group1SID = "" + } + + It "Can Rename-LocalGroup using a valid group SID" { + $group1SID | Should Not BeNullOrEmpty + Rename-LocalGroup -SID $group1SID TestGroupRename1x + $result = Get-LocalGroup -SID $group1SID + + $result.Name | Should BeExactly TestGroupRename1x + } + + It "Can Rename-LocalGroup using a valid group -InputObject" { + $group1SID | Should Not BeNullOrEmpty + $group = Get-LocalGroup TestGroupRename1 + Rename-LocalGroup -InputObject $group -NewName TestGroupRename1x + $result = Get-LocalGroup -SID $group1SID + + $result.Name | Should BeExactly TestGroupRename1x + } + + It "Can Rename-LocalGroup using a valid group sent using pipeline" { + $group1SID | Should Not BeNullOrEmpty + Get-LocalGroup TestGroupRename1 | Rename-LocalGroup -NewName TestGroupRename1x + $result = Get-LocalGroup -SID $group1SID + + $result.Name | Should BeExactly TestGroupRename1x + } + + It "Errors on Rename-LocalGroup without specifying a Group" { + $sb = { + Rename-LocalGroup + } + VerifyFailingTest $sb "AmbiguousParameterSet,Microsoft.PowerShell.Commands.RenameLocalGroupCommand" + } + + It "Errors onRename-LocalGroup nonexistant group name" { + $sb = { + Rename-LocalGroup nonexistantGroupName -NewName DummyNewName + } + VerifyFailingTest $sb "GroupNotFound,Microsoft.PowerShell.Commands.RenameLocalGroupCommand" + } + + It "Errors onRename-LocalGroup nonexistant group SID" { + $nonexistantSid = + $sb = { + Rename-LocalGroup -SID "S-1-5-21-1220945662-555555555-555555555-5555" -NewName DummyNewName + } + VerifyFailingTest $sb "GroupNotFound,Microsoft.PowerShell.Commands.RenameLocalGroupCommand" + } + + It "Errors on Rename-LocalGroup Renames a valid group to already existing name" { + $newName = "TestGroupRename2" + + $sb = { + Rename-LocalGroup TestGroupRename1 $newName + } + VerifyFailingTest $sb "NameInUse,Microsoft.PowerShell.Commands.RenameLocalGroupCommand" + + $group1Name = (Get-LocalGroup -SID $group1SID).Name + $group2Name = (Get-LocalGroup -SID $group2SID).Name + + $group1Name | Should BeExactly TestGroupRename1 + $group2Name | Should BeExactly $newName + } + + It "Errors on Invalid characters" { + #Arrange + #list of characters that should be invalid + $InvalidCharacters = @" +\/"[]:|<>+=;,?* +"@ + $InvalidCharacters = $InvalidCharacters[0..($InvalidCharacters.Length - 1)] + $failedCharacters = @() + + #Act + foreach ($character in $InvalidCharacters) { + try { + Rename-LocalGroup -Name TestGroupRename1 -NewName ("InvalidBecauseOf" + $character) -ErrorAction Stop + $invalidGroup = (Get-LocalGroup ("InvalidBecauseOf" + $character)) + } + catch { + } + finally { + #handle groups being erroneously renamed + if ($invalidGroup) { + Rename-LocalGroup -Name ("InvalidBecauseOf" + $character) -NewName TestGroupRename1 + $failedCharacters += $character + } + } + } + + #Assert + if ($failedCharacters.Count -gt 0) { Write-Host "characters causing test fail: $failedCharacters" } + $failedCharacters.Count -eq 0 | Should Be true + } + + It "Error on names containing only spaces" { + $sb = { + Rename-LocalGroup -Name TestGroupRename1 -NewName " " + } + VerifyFailingTest $sb "InvalidName,Microsoft.PowerShell.Commands.RenameLocalGroupCommand" + } + + It "Error on names containing only periods" { + $sb = { + Rename-LocalGroup -Name TestGroupRename1 -NewName "..." + } + VerifyFailingTest $sb "InvalidName,Microsoft.PowerShell.Commands.RenameLocalGroupCommand" + } + + It "Errors on names ending in a period" { + $sb = { + Rename-LocalGroup -Name TestGroupRename1 -NewName "TestEndInPeriod." + } + VerifyFailingTest $sb "InvalidName,Microsoft.PowerShell.Commands.RenameLocalGroupCommand" + + $sb = { + Rename-LocalGroup -Name TestGroupRename1 -NewName ".TestEndIn.Period.." + } + VerifyFailingTest $sb "InvalidName,Microsoft.PowerShell.Commands.RenameLocalGroupCommand" + } + + It "Errors on Rename-LocalGroup using a valid group but invalid -NewName" { + $sb = { + Rename-LocalGroup -Name TestGroupRename1 -NewName "TestGroupRename<>1x" + } + VerifyFailingTest $sb "InvalidName,Microsoft.PowerShell.Commands.RenameLocalGroupCommand" + } + + It "Can Rename-LocalGroup using a valid group name at max length 256" { + $newName = "A"*256 + Rename-LocalGroup TestGroupRename1 $newName + $result = Get-LocalGroup -SID $group1SID + + $result.Name | Should BeExactly $newName + } + + It "Errors on Rename-LocalGroup using a valid group name over max length 256" { + $newName = "A"*257 + $sb = { + Rename-LocalGroup TestGroupRename1 $newName + } + VerifyFailingTest $sb "InvalidName,Microsoft.PowerShell.Commands.RenameLocalGroupCommand" + + (Get-LocalGroup -SID $group1SID).Name | Should BeExactly TestGroupRename1 + } +} + +Describe "Validate simple Remove-LocalGroup" -Tags "CI", "Feature" { + BeforeAll { + $group1SID = "" + } + + BeforeEach { + $group1SID = (New-LocalGroup -Name TestGroupRemove1 -Description "Test Group Remove 1 Description" ).SID + } + + AfterEach { + RemoveTestGroups -basename TestGroupRemove + $group1SID = "" + } + + It "Can Remove-LocalGroup by name" { + $initialCount = (Get-LocalGroup).Count + $initialCount -gt 1 | Should Be true + + $removeResult = Remove-LocalGroup TestGroupRemove1 2>&1 + $removeResult | Should BeNullOrEmpty + + $sb = { + Get-LocalGroup -SID $group1SID + } + VerifyFailingTest $sb "GroupNotFound,Microsoft.PowerShell.Commands.GetLocalGroupCommand" + + $finalCount = (Get-LocalGroup).Count + $initialCount -eq $finalCount + 1 | Should Be true + } +} + +Describe "Validate Remove-LocalGroup cmdlet" -Tags "Feature" { + BeforeAll { + $group1SID = "" + $group2SID = "" + + function VerifyBasicRemoval { + param ( + [scriptblock]$removalAction + ) + $initialCount = (Get-LocalGroup).Count + $initialCount -gt 1 | Should Be true + + & $removalAction + + $sb = { + Get-LocalGroup -SID $group1SID + } + VerifyFailingTest $sb "GroupNotFound,Microsoft.PowerShell.Commands.GetLocalGroupCommand" + + $finalCount = (Get-LocalGroup).Count + $initialCount -eq $finalCount + 1 | Should Be true + } + + function VerifyArrayRemoval { + param ( + [scriptblock]$removalAction + ) + $initialCount = (Get-LocalGroup).Count + $initialCount -gt 1 | Should Be $true + + & $removalAction + + $sb = { + Get-LocalGroup -SID $group1SID + } + VerifyFailingTest $sb "GroupNotFound,Microsoft.PowerShell.Commands.GetLocalGroupCommand" + + $sb = { + Get-LocalGroup -SID $group2SID + } + VerifyFailingTest $sb "GroupNotFound,Microsoft.PowerShell.Commands.GetLocalGroupCommand" + + $finalCount = (Get-LocalGroup).Count + $initialCount -eq $finalCount + 2 | Should Be $true + } + } + + BeforeEach { + $group1SID = [String](New-LocalGroup -Name TestGroupRemove1 -Description "Test Group Remove 1 Description" 2>&1).SID + $group2SID = [String](New-LocalGroup -Name TestGroupRemove2 -Description "Test Group Remove 2 Description" 2>&1).SID + } + + AfterEach { + RemoveTestGroups -basename TestGroupRemove + $group1SID = "" + $group2SID = "" + } + + It "Can Remove-LocalGroup by SID" { + $sb = { + $removeResult = Remove-LocalGroup -SID $group1SID 2>&1 + $removeResult | Should BeNullOrEmpty + } + VerifyBasicRemoval $sb + } + + It "Can Remove-LocalGroup using -InputObject" { + $sb = { + $group = Get-LocalGroup TestGroupRemove1 + $removeResult = Remove-LocalGroup -InputObject $group 2>&1 + $removeResult | Should BeNullOrEmpty + } + VerifyBasicRemoval $sb + } + + It "Can Remove-LocalGroup using pipeline" { + $sb = { + $removeResult = Get-LocalGroup TestGroupRemove1 | Remove-LocalGroup 2>&1 + $removeResult | Should BeNullOrEmpty + } + VerifyBasicRemoval $sb + } + + It "Can Remove-LocalGroup by array of names" { + $sb = { + $removeResult = Remove-LocalGroup @("TestGroupRemove1","TestGroupRemove2") 2>&1 + $removeResult | Should BeNullOrEmpty + } + VerifyArrayRemoval $sb + } + + It "Can Remove-LocalGroup by array of SIDs" { + $sb = { + $removeResult = Remove-LocalGroup -SID @($group1SID, $group2SID) 2>&1 + $removeResult | Should BeNullOrEmpty + } + VerifyArrayRemoval $sb + } + + It "Can Remove-LocalGroup by array using -InputObject" { + $sb = { + $groups = Get-LocalGroup -Name @("TestGroupRemove1","TestGroupRemove2") + $removeResult = Remove-LocalGroup -InputObject $groups 2>&1 + $removeResult | Should BeNullOrEmpty + } + VerifyArrayRemoval $sb + } + + It "Can Remove-LocalGroup by array using pipeline" { + $sb = { + $removeResult = Get-LocalGroup -Name @("TestGroupRemove1","TestGroupRemove2") | Remove-LocalGroup 2>&1 + $removeResult | Should BeNullOrEmpty + } + VerifyArrayRemoval $sb + } + + It "Errors on Remove-LocalGroup without specifying a Name or SID" { + $sb = { Remove-LocalGroup } + VerifyFailingTest $sb "AmbiguousParameterSet,Microsoft.PowerShell.Commands.RemoveLocalGroupCommand" + } + + It "Can Remove-LocalGroup with members" { + New-LocalUser TestUserRemove1 -NoPassword | Out-Null + Add-LocalGroupMember TestGroupRemove1 -Member TestUserRemove1 | Out-Null + $initialCount = (Get-LocalGroup).Count + $initialCount -gt 1 | Should Be true + + $removeResult = Remove-LocalGroup TestGroupRemove1 2>&1 + $removeResult | Should BeNullOrEmpty + + #clean-up + Remove-LocalUser TestUserRemove1 | Out-Null + + $sb = { + Get-LocalGroup TestGroupRemove1 + } + VerifyFailingTest $sb "GroupNotFound,Microsoft.PowerShell.Commands.GetLocalGroupCommand" + + $finalCount = (Get-LocalGroup).Count + $initialCount -eq $finalCount + 1 | Should Be true + } + + It "Errors on Remove-LocalGroup by invalid name" { + $initialCount = (Get-LocalGroup).Count + $initialCount -gt 1 | Should Be true + + $sb = { + Remove-LocalGroup TestGroupRemove1NameThatDoesntExist + } + VerifyFailingTest $sb "GroupNotFound,Microsoft.PowerShell.Commands.RemoveLocalGroupCommand" + + $finalCount = (Get-LocalGroup).Count + $initialCount -eq $finalCount | Should Be true + } + + It "Errors on Remove-LocalGroup by invalid SID" { + $initialCount = (Get-LocalGroup).Count + $initialCount -gt 1 | Should Be true + + $sb = { + Remove-LocalGroup -SID $group1SID + Remove-LocalGroup -SID $group1SID + } + VerifyFailingTest $sb "GroupNotFound,Microsoft.PowerShell.Commands.RemoveLocalGroupCommand" + + $finalCount = (Get-LocalGroup).Count + $initialCount -eq $finalCount + 1 | Should Be $true + } + + It "Can respond to -ErrorAction Stop" { + $errCount = 0 + $fqeid = "" + try { + Remove-LocalGroup @("TestGroupRemove1", "TestGroupRemoveNameThatDoesntExist1", "TestGroupRemoveNameThatDoesntExist2") -ErrorAction Stop -ErrorVariable outError + } + catch { + $errCount = $outError.Count + $fqeid = $_.FullyQualifiedErrorId + } + + # Confirm that the expected errors were caught + $errCount | Should Be 2 + $fqeid | Should Be "GroupNotFound,Microsoft.PowerShell.Commands.RemoveLocalGroupCommand" + + # confirm that the first group was removed + $sb = { + Get-LocalGroup "TestGroupRemove1" + } + VerifyFailingTest $sb "GroupNotFound,Microsoft.PowerShell.Commands.GetLocalGroupCommand" + } +} diff --git a/test/powershell/Modules/Microsoft.PowerShell.LocalAccounts/Pester.Command.Cmdlets.LocalAccounts.LocalGroupMember.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.LocalAccounts/Pester.Command.Cmdlets.LocalAccounts.LocalGroupMember.Tests.ps1 new file mode 100644 index 0000000000..fcd2497f78 --- /dev/null +++ b/test/powershell/Modules/Microsoft.PowerShell.LocalAccounts/Pester.Command.Cmdlets.LocalAccounts.LocalGroupMember.Tests.ps1 @@ -0,0 +1,561 @@ +# This is a Pester test suite to validate the cmdlets in LocalAccounts module +# +# Copyright (c) Microsoft Corporation, 2015 +# LocalAccounts does not work outside of windows + +if(-not $IsWindows) +{ + return +} + +function IsWin10OrHigher +{ + $version = [system.environment]::osversion.version + + return ($version.Major -ge 10) +} + +function RemoveTestUsers +{ + param([string] $basename) + + $results = Get-LocalUser $basename* + foreach ($element in $results) { + Remove-LocalUser -SID $element.SID + } +} + +function RemoveTestGroups +{ + param([string] $basename) + + $results = Get-LocalGroup $basename* + foreach ($element in $results) { + Remove-LocalGroup -SID $element.SID + } +} + +function VerifyFailingTest +{ + param( + [scriptblock] $sb, + [string] $expectedFqeid + ) + + $backupEAP = $script:ErrorActionPreference + $script:ErrorActionPreference = "Stop" + + try { + & $sb + throw "Expected error: $expectedFqeid" + } + catch { + $_.FullyQualifiedErrorId | Should Be $expectedFqeid + } + finally { + $script:ErrorActionPreference = $backupEAP + } +} + +Describe "Verify Expected LocalGroupMember Cmdlets are present" -Tags "CI" { + + It "Test command presence" { + $result = Get-Command -Module Microsoft.PowerShell.LocalAccounts | % Name + + $result -contains "Add-LocalGroupMember" | Should Be $true + $result -contains "Get-LocalGroupMember" | Should Be $true + $result -contains "Remove-LocalGroupMember" | Should Be $true + } +} + +Describe "Validate simple Add-LocalGroupMember" -Tags "CI", "Feature" { + BeforeEach { + $user1sid = [String](New-LocalUser TestUser1 -NoPassword).SID + $group1sid = [String](New-LocalGroup TestGroup1).SID + } + + AfterEach { + RemoveTestGroups -basename TestGroup + RemoveTestUsers -basename TestUser + } + + It "Can add local user to group by name" { + Add-LocalGroupMember TestGroup1 -Member TestUser1 + $result = Get-LocalGroupMember TestGroup1 + + $result.Name.EndsWith("TestUser1") | Should Be $true + $result.SID | Should Be $user1sid + } +} + +Describe "Validate Add-LocalGroupMember cmdlet" -Tags "Feature" { + BeforeAll { + $OptDomainPrefix="(.+\\)?" + } + + BeforeEach { + $user1sid = [String](New-LocalUser TestUser1 -NoPassword).SID + $user2sid = [String](New-LocalUser TestUser2 -NoPassword).SID + $group1sid = [String](New-LocalGroup TestGroup1).SID + $group2sid = [String](New-LocalGroup TestGroup2).SID + } + + AfterEach { + RemoveTestGroups -basename TestGroup + RemoveTestUsers -basename TestUser + } + + It "Can add user to group using SID" { + Add-LocalGroupMember -SID $group1sid -Member TestUser1 + $result = Get-LocalGroupMember TestGroup1 + + $result.Name.EndsWith("TestUser1") | Should Be $true + $result.SID | Should Be $user1sid + } + + It "Can add user to group using group object" { + $groupObject = Get-LocalGroup TestGroup1 + Add-LocalGroupMember -Group $groupObject -Member TestUser1 + $result = Get-LocalGroupMember TestGroup1 + + $result.Name.EndsWith("TestUser1") | Should Be $true + $result.SID | Should Be $user1sid + } + + It "Can add user to group using pipeline" { + Get-LocalUser TestUser1 | Add-LocalGroupMember -Name TestGroup1 + $result = Get-LocalGroupMember TestGroup1 + + $result.Name.EndsWith("TestUser1") | Should Be $true + $result.SID | Should Be $user1sid + } + + It "Errors on missing group parameter value missing" { + $sb = { + Add-LocalGroupMember -Member TestUser1 + } + VerifyFailingTest $sb "AmbiguousParameterSet,Microsoft.PowerShell.Commands.AddLocalGroupMemberCommand" + } + + It "Errors on missing user parameter value missing" { + $sb = { + Add-LocalGroupMember TestGroup1 -Member + } + VerifyFailingTest $sb "MissingArgument,Microsoft.PowerShell.Commands.AddLocalGroupMemberCommand" + } + + It "Errors on adding group to group" { + $sb = { + Add-LocalGroupMember TestGroup1 TestGroup2 + } + VerifyFailingTest $sb "Internal,Microsoft.PowerShell.Commands.AddLocalGroupMemberCommand" + } + + It "Can add array of members to group" { + Add-LocalGroupMember TestGroup1 -Member @("TestUser1", "TestUser2") + $result = Get-LocalGroupMember TestGroup1 + + $result[0].Name -match ($OptDomainPrefix + "TestUser1") | Should Be $true + $result[1].Name -match ($OptDomainPrefix + "TestUser2") | Should Be $true + } + + It "Can add array of user SIDs to group" { + Add-LocalGroupMember TestGroup1 -Member @($user1sid, $user2sid) + $result = Get-LocalGroupMember TestGroup1 + + $result[0].Name -match ($OptDomainPrefix + "TestUser1") | Should Be $true + $result[1].Name -match ($OptDomainPrefix + "TestUser2") | Should Be $true + } + + It "Can add array of users names or SIDs to group" { + Add-LocalGroupMember TestGroup1 -Member @($user1sid, "TestUser2") + $result = Get-LocalGroupMember TestGroup1 + + $result[0].Name -match ($OptDomainPrefix + "TestUser1") | Should Be $true + $result[1].Name -match ($OptDomainPrefix + "TestUser2") | Should Be $true + } + + It "Can add array of user names using pipeline" { + @("TestUser1", "TestUser2") | Add-LocalGroupMember TestGroup1 + $result = Get-LocalGroupMember TestGroup1 + + $result[0].Name -match ($OptDomainPrefix + "TestUser1") | Should Be $true + $result[1].Name -match ($OptDomainPrefix + "TestUser2") | Should Be $true + } + + It "Can add array of existent and nonexistent users names to group" { + $sb = { + Add-LocalGroupMember TestGroup1 -Member @("TestUser1", "TestNonexistentUser", "TestUser2") + } + VerifyFailingTest $sb "PrincipalNotFound,Microsoft.PowerShell.Commands.AddLocalGroupMemberCommand" + + $result = Get-LocalGroupMember TestGroup1 + $result.Name -match ($OptDomainPrefix + "TestUser1") | Should Be $true + $result.Name -match ($OptDomainPrefix + "TestUser2") | Should Be $false + } + + It "Errors on adding user to group by name twice" { + $sb = { + Add-LocalGroupMember TestGroup1 -Member TestUser1 + Add-LocalGroupMember TestGroup1 -Member TestUser1 + } + VerifyFailingTest $sb "MemberExists,Microsoft.PowerShell.Commands.AddLocalGroupMemberCommand" + + $result = Get-LocalGroupMember TestGroup1 + $result.Name.EndsWith("TestUser1") | Should Be $true + $result.SID | Should Be $user1sid + } + + It "Errors on adding nonexistent user to group" { + $sb = { + Add-LocalGroupMember -name TestGroup1 -Member TestNonexistentUser1 + } + VerifyFailingTest $sb "PrincipalNotFound,Microsoft.PowerShell.Commands.AddLocalGroupMemberCommand" + } + + It "Errors on adding user to nonexistent group" { + $sb = { + Add-LocalGroupMember TestNonexistentGroup1 -Member TestUser1 -ErrorAction Stop + } + VerifyFailingTest $sb "GroupNotFound,Microsoft.PowerShell.Commands.AddLocalGroupMemberCommand" + } + + It "Can respond to -ErrorAction Stop" { + $sb = { + Add-LocalGroupMember TestGroup1 -Member @("TestUser1", "TestNonexistentUser1", "TestNonexistentUser2") -ErrorAction Stop -ErrorVariable OutputError | Out-Null + } + VerifyFailingTest $sb "PrincipalNotFound,Microsoft.PowerShell.Commands.AddLocalGroupMemberCommand" + + $result = Get-LocalGroupMember TestGroup1 + $result.Name -match ($OptDomainPrefix + "TestUser1") | Should Be $true + } +} + +Describe "Validate simple Get-LocalGroupMember" -Tags "CI", "Feature" { + BeforeEach { + $user1 = New-LocalUser TestUserGet1 -NoPassword + $group1 = New-LocalGroup TestGroupGet1 + Add-LocalGroupMember TestGroupGet1 -Member TestUserGet1 + $user1sid = [String]($user1.SID) + $group1sid = [String]($group1.SID) + } + + AfterEach { + RemoveTestGroups -basename TestGroupGet + RemoveTestUsers -basename TestUserGet + } + + It "Can get a local group member by name" { + $result = Get-LocalGroupMember TestGroupGet1 + + $result.Name.EndsWith("TestUserGet1") | Should Be $true + $result.SID | Should Be $user1sid + if (IsWin10OrHigher) + { + $result.PrincipalSource | Should Be Local + } + $result.ObjectClass | Should Be User + } +} + +Describe "Validate Get-LocalGroupMember cmdlet" -Tags "Feature" { + BeforeAll { + $OptDomainPrefix="(.+\\)?" + } + + BeforeEach { + $user1 = New-LocalUser TestUserGet1 -NoPassword + $user2 = New-LocalUser TestUserGet2 -NoPassword + $group1 = New-LocalGroup TestGroupGet1 + $group2 = New-LocalGroup TestGroupGet2 + Add-LocalGroupMember TestGroupGet1 -Member TestUserGet1 + Add-LocalGroupMember TestGroupGet1 -Member TestUserGet2 + $user1sid = [String]($user1.SID) + $user2sid = [String]($user2.SID) + $group1sid = [String]($group1.SID) + $group2sid = [String]($group2.SID) + } + + AfterEach { + RemoveTestGroups -basename TestGroupGet + RemoveTestUsers -basename TestUserGet + } + + It "Can get all group members by name" { + $result = Get-LocalGroupMember TestGroupGet1 + + $result[0].Name.EndsWith("TestUserGet1") | Should Be $true + $result[0].SID | Should Be $user1sid + if (IsWin10OrHigher) + { + $result[0].PrincipalSource | Should Be Local + } + $result[0].ObjectClass | Should Be User + $result[1].Name.EndsWith("TestUserGet2") | Should Be $true + $result[1].SID | Should Be $user2sid + if (IsWin10OrHigher) + { + $result[1].PrincipalSource | Should Be Local + } + $result[1].ObjectClass | Should Be User + } + + It "Can get all group members by SID" { + $result = Get-LocalGroupMember -SID $group1sid + + $result[0].Name.EndsWith("TestUserGet1") | Should Be $true + $result[0].SID | Should Be $user1sid + if (IsWin10OrHigher) + { + $result[0].PrincipalSource | Should Be Local + } + $result[0].ObjectClass | Should Be User + $result[1].Name.EndsWith("TestUserGet2") | Should Be $true + $result[1].SID | Should Be $user2sid + if (IsWin10OrHigher) + { + $result[1].PrincipalSource | Should Be Local + } + $result[1].ObjectClass | Should Be User + } + + It "Can get all group members by Group object" { + $group = Get-LocalGroup TestGroupGet1 + $result = Get-LocalGroupMember -Group $group + + $result[0].Name.EndsWith("TestUserGet1") | Should Be $true + $result[0].SID | Should Be $user1sid + if (IsWin10OrHigher) + { + $result[0].PrincipalSource | Should Be Local + } + $result[0].ObjectClass | Should Be User + $result[1].Name.EndsWith("TestUserGet2") | Should Be $true + $result[1].SID | Should Be $user2sid + if (IsWin10OrHigher) + { + $result[1].PrincipalSource | Should Be Local + } + $result[1].ObjectClass | Should Be User + } + + It "Can get all group members by pipeline" { + $result = Get-LocalGroup TestGroupGet1 | Get-LocalGroupMember + + $result[0].Name.EndsWith("TestUserGet1") | Should Be $true + $result[0].SID | Should Be $user1sid + if (IsWin10OrHigher) + { + $result[0].PrincipalSource | Should Be Local + } + $result[0].ObjectClass | Should Be User + $result[1].Name.EndsWith("TestUserGet2") | Should Be $true + $result[1].SID | Should Be $user2sid + if (IsWin10OrHigher) + { + $result[1].PrincipalSource | Should Be Local + } + $result[1].ObjectClass | Should Be User + } + + It "Can get group members by wildcard" { + $result = Get-LocalGroupMember TestGroupGet1 -Member TestUserGet* + $result.Count -eq 2 | Should Be $true + $result[0].Name -match ($OptDomainPrefix+"TestUserGet1") | Should Be $true + $result[1].Name -match ($OptDomainPrefix + "TestUserGet2") | Should Be $true + } + + It "Errors on group name being nonexistent" { + $sb = { + Get-LocalGroupMember NonexistentGroup + } + VerifyFailingTest $sb "GroupNotFound,Microsoft.PowerShell.Commands.GetLocalGroupMemberCommand" + } + + It "Can get specific group member by name" { + $result = Get-LocalGroupMember TestGroupGet1 -Member TestUserGet1 + + $result.Name.EndsWith("TestUserGet1") | Should Be $true + $result.SID | Should Be $user1sid + if (IsWin10OrHigher) + { + $result.PrincipalSource | Should Be Local + } + $result.ObjectClass | Should Be User + } + + #TODO: 10.A valid user attempts to get membership from a group to which they don’t have access +} + +Describe "Validate simple Remove-LocalGroupMember" -Tags "CI", "Feature" { + BeforeEach { + $user1 = New-LocalUser TestUserRemove1 -NoPassword + $group1 = New-LocalGroup TestGroupRemove1 + Add-LocalGroupMember TestGroupRemove1 -Member TestUserRemove1 + $user1sid = [String]($user1.SID) + $group1sid = [String]($group1.SID) + } + + AfterEach { + RemoveTestGroups -basename TestGroupRemove + RemoveTestUsers -basename TestUserRemove + } + + It "Can remove a local group member by name" { + Remove-LocalGroupMember TestGroupRemove1 -Member TestUserRemove1 + $result = Get-LocalGroupMember TestGroupRemove1 + + $result -eq $null | Should Be $true + } +} + +Describe "Validate Remove-LocalGroupMember cmdlet" -Tags "Feature" { + BeforeEach { + $user1 = New-LocalUser TestUserRemove1 -NoPassword + $user2 = New-LocalUser TestUserRemove2 -NoPassword + $group1 = New-LocalGroup TestGroupRemove1 + $group2 = New-LocalGroup TestGroupRemove2 + Add-LocalGroupMember TestGroupRemove1 -Member TestUserRemove1 + Add-LocalGroupMember TestGroupRemove1 -Member TestUserRemove2 + $user1sid = [String]($user1.SID) + $user2sid = [String]($user2.SID) + $group1sid = [String]($group1.SID) + $group2sid = [String]($group2.SID) + } + + AfterEach { + RemoveTestGroups -basename TestGroupRemove + RemoveTestUsers -basename TestUserRemove + } + + It "Can remove a group member by name" { + Remove-LocalGroupMember TestGroupRemove1 -Member TestUserRemove2 + $result = Get-LocalGroupMember TestGroupRemove1 + + $result.Name.EndsWith("TestUserRemove1") | Should Be $true + } + + It "Can remove a group member by SID" { + Remove-LocalGroupMember -SID $group1sid -Member TestUserRemove2 + $result = Get-LocalGroupMember TestGroupRemove1 + + $result.Name.EndsWith("TestUserRemove1") | Should Be $true + } + + It "Can remove a group member by Group object" { + $group = Get-LocalGroup TestGroupRemove1 + Remove-LocalGroupMember -Group $group -Member TestUserRemove2 + $result = Get-LocalGroupMember TestGroupRemove1 + + $result.Name.EndsWith("TestUserRemove1") | Should Be $true + } + + It "Can remove a group member by pipeline" { + Get-LocalUser TestUserRemove2 | Remove-LocalGroupMember -Name TestGroupRemove1 + $result = Get-LocalGroupMember TestGroupRemove1 + + $result.Name.EndsWith("TestUserRemove1") | Should Be $true + } + + It "Errors on group argument missing" { + $sb = { + Remove-LocalGroupMember -Member TestUserRemove2 + } + VerifyFailingTest $sb "AmbiguousParameterSet,Microsoft.PowerShell.Commands.RemoveLocalGroupMemberCommand" + } + + It "Errors on member argument missing" { + $sb = { + Remove-LocalGroupMember TestGroupRemove1 -Member + } + VerifyFailingTest $sb "MissingArgument,Microsoft.PowerShell.Commands.RemoveLocalGroupMemberCommand" + } + + It "Errors on remove a group member not in the group" { + $sb = { + Remove-LocalGroupMember TestGroupRemove2 -Member TestUserRemove2 + } + VerifyFailingTest $sb "MemberNotFound,Microsoft.PowerShell.Commands.RemoveLocalGroupMemberCommand" + } + + It "Errors on remove group members by array of name" { + $sb = { + Remove-LocalGroupMember TestGroupRemove2 -Member TestUserRemove2 + Get-LocalGroupMember TestGroupRemove1 + } + VerifyFailingTest $sb "MemberNotFound,Microsoft.PowerShell.Commands.RemoveLocalGroupMemberCommand" + } + + It "Can remove array of user names from group" { + Remove-LocalGroupMember TestGroupRemove1 -Member @("TestUserRemove1", "TestUserRemove2") + $result = Get-LocalGroupMember TestGroupRemove1 + + $result -eq $null | Should Be $true + } + + It "Can remove array of user SIDs from group" { + Remove-LocalGroupMember TestGroupRemove1 -Member @($user1sid, $user2sid) + $result = Get-LocalGroupMember TestGroupRemove1 + + $result -eq $null | Should Be $true + } + + It "Can remove array of users names or SIDs from group" { + Remove-LocalGroupMember TestGroupRemove1 -Member @($user1sid, "TestUserRemove2") + $result = Get-LocalGroupMember TestGroupRemove1 + + $result -eq $null | Should Be $true + } + + It "Can remove array of user names using pipeline" { + $name1 = (Get-LocalUser "TestUserRemove1").Name + $name2 = (Get-LocalUser "TestUserRemove2").Name + @($name1, $name2) | Remove-LocalGroupMember TestGroupRemove1 + $result = Get-LocalGroupMember TestGroupRemove1 + + $result -eq $null | Should Be $true + } + + It "Errors on remove nonexistent user from group" { + $sb = { + Remove-LocalGroupMember TestGroupRemove1 -Member TestNonexistentUser1 + } + VerifyFailingTest $sb "PrincipalNotFound,Microsoft.PowerShell.Commands.RemoveLocalGroupMemberCommand" + } + + It "Errors on remove user from nonexistent group" { + $sb = { + Remove-LocalGroupMember TestNonexistentGroup1 -Member TestUserRemove1 -ErrorAction Stop + } + VerifyFailingTest $sb "GroupNotFound,Microsoft.PowerShell.Commands.RemoveLocalGroupMemberCommand" + } + + #TODO: 16.A valid user attempts to remove a user/group from a group to which they don’t have access + + It "Can remove array of existent and nonexistent users names from group" { + $sb = { + Remove-LocalGroupMember TestGroupRemove1 -Member @("TestUserRemove1", "TestNonexistentUser", "TestUserRemove2") + } + VerifyFailingTest $sb "PrincipalNotFound,Microsoft.PowerShell.Commands.RemoveLocalGroupMemberCommand" + + $result = Get-LocalGroupMember TestGroupRemove2 + $result -eq $null | Should Be $true + } + + It "Errors on remove user from nonexistent group" { + $sb = { + Remove-LocalGroupMember TestGroupRemove1 -Member TestGroupRemove2 -ErrorAction Stop + } + VerifyFailingTest $sb "MemberNotFound,Microsoft.PowerShell.Commands.RemoveLocalGroupMemberCommand" + } + + It "Can respond to -ErrorAction Stop" { + $sb = { + Remove-LocalGroupMember TestGroupRemove1 -Member @("TestUserRemove1", "TestNonexistentUser1", "TestUserRemove2") -ErrorAction Stop -ErrorVariable outError | Out-Null + } + VerifyFailingTest $sb "PrincipalNotFound,Microsoft.PowerShell.Commands.RemoveLocalGroupMemberCommand" + + $result = Get-LocalGroupMember TestGroupRemove1 2>&1 + $result.Name -match ($OptDomainPrefix + "TestUserRemove2") | Should Be $true + } +} diff --git a/test/powershell/Modules/Microsoft.PowerShell.LocalAccounts/Pester.Command.Cmdlets.LocalAccounts.LocalUser.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.LocalAccounts/Pester.Command.Cmdlets.LocalAccounts.LocalUser.Tests.ps1 new file mode 100644 index 0000000000..5769686826 --- /dev/null +++ b/test/powershell/Modules/Microsoft.PowerShell.LocalAccounts/Pester.Command.Cmdlets.LocalAccounts.LocalUser.Tests.ps1 @@ -0,0 +1,1451 @@ +# This is a Pester test suite to validate the cmdlets in LocalAccounts module +# +# Copyright (c) Microsoft Corporation, 2015 + +# LocalAccounts does not work outside of windows +if(-not $IsWindows) +{ + return +} + +Set-Variable dateInFuture -option Constant -value "12/12/2036 09:00" +Set-Variable dateInPast -option Constant -value "12/12/2010 09:00" +Set-Variable dateInvalid -option Constant -value "12/12/2016 25:00" + +function RemoveTestUsers +{ + param([string] $basename) + + $results = Get-LocalUser $basename* + foreach ($element in $results) { + Remove-LocalUser -SID $element.SID + } +} + +function VerifyFailingTest +{ + param( + [scriptblock] $sb, + [string] $expectedFqeid + ) + + $backupEAP = $script:ErrorActionPreference + $script:ErrorActionPreference = "Stop" + + try { + & $sb + throw "Expected error: $expectedFqeid" + } + catch { + $_.FullyQualifiedErrorId | Should Be $expectedFqeid + } + finally { + $script:ErrorActionPreference = $backupEAP + } +} + +Describe "Verify Expected LocalUser Cmdlets are present" -Tags "CI" { + + It "Test command presence" { + $result = Get-Command -Module Microsoft.PowerShell.LocalAccounts | % Name + + $result -contains "New-LocalUser" | Should Be $true + $result -contains "Set-LocalUser" | Should Be $true + $result -contains "Get-LocalUser" | Should Be $true + $result -contains "Rename-LocalUser" | Should Be $true + $result -contains "Remove-LocalUser" | Should Be $true + $result -contains "Enable-LocalUser" | Should Be $true + $result -contains "Disable-LocalUser" | Should Be $true + } +} + +Describe "Verify Expected LocalUser Aliases are present" -Tags "CI" { + + It "Test command presence" { + $result = get-alias | % { if ($_.Source -eq "Microsoft.PowerShell.LocalAccounts") {$_}} + + $result.Name -contains "algm" | Should Be $true + $result.Name -contains "dlu" | Should Be $true + $result.Name -contains "elu" | Should Be $true + $result.Name -contains "glg" | Should Be $true + $result.Name -contains "glgm" | Should Be $true + $result.Name -contains "glu" | Should Be $true + $result.Name -contains "nlg" | Should Be $true + $result.Name -contains "nlu" | Should Be $true + $result.Name -contains "rlg" | Should Be $true + $result.Name -contains "rlgm" | Should Be $true + $result.Name -contains "rlu" | Should Be $true + $result.Name -contains "rnlg" | Should Be $true + $result.Name -contains "rnlu" | Should Be $true + $result.Name -contains "slg" | Should Be $true + $result.Name -contains "slu" | Should Be $true + } +} + +Describe "Validate simple New-LocalUser" -Tags "CI", "Feature" { + AfterEach { + RemoveTestUsers -basename TestUserNew + } + + It "Can create New-LocalUser with only name" { + $result = New-LocalUser TestUserNew1 -NoPassword + + $result.Name | Should BeExactly TestUserNew1 + $result.Description | Should BeNullOrEmpty + $result.Enabled | Should Be $true + $result.SID | Should Not BeNullOrEmpty + $result.ObjectClass | Should Be User + } +} + +Describe "Validate New-LocalUser cmdlet" -Tags "Feature" { + AfterEach { + RemoveTestUsers -basename TestUserNew + RemoveTestUsers -basename "S-1-5-32-545" + } + + It "Can set a SID like name" { + $userName = "S-1-5-32-545" + $result = New-LocalUser $userName -NoPassword + + $result.Name | Should BeExactly $userName + $result.Description | Should BeNullOrEmpty + $result.Enabled | Should Be $true + $result.SID | Should Not BeNullOrEmpty + $result.ObjectClass | Should Be User + } + + It "Errors on Name argument of empty string or null" { + $sb = { + New-LocalUser -Name "" -NoPassword + } + VerifyFailingTest $sb "ParameterArgumentValidationError,Microsoft.PowerShell.Commands.NewLocalUserCommand" + + $sb = { + New-LocalUser -Name $null -NoPassword + } + VerifyFailingTest $sb "ParameterArgumentValidationError,Microsoft.PowerShell.Commands.NewLocalUserCommand" + } + + It "Errors on Invalid characters" { + #Arrange + #list of characters that should be invalid + $InvalidCharacters = @" +\/"[]:|<>+=;,?* +"@ + $InvalidCharacters = $InvalidCharacters[0..($InvalidCharacters.Length - 1)] + #Act + foreach ($character in $InvalidCharacters) { + try { + $invalidUser = New-LocalUser -Name ("InvalidBecauseOf" + $character) -NoPassword -ErrorAction Stop + } + catch { + } + finally { + if ($invalidUser) { + Remove-LocalUser -Name $invalidUser + $failedCharacters += $character + } + } + } + + #Assert + if ($failedCharacters.Count -gt 0) { Write-Host "characters causing test fail: $failedCharacters" } + $failedCharacters.Count -eq 0 | Should Be $true + } + + It "Errors on names containing only spaces or periods" { + $sb = { + New-LocalUser -Name " " -NoPassword + } + VerifyFailingTest $sb "InvalidName,Microsoft.PowerShell.Commands.NewLocalUserCommand" + + $sb = { + New-LocalUser -Name "..." -NoPassword + } + VerifyFailingTest $sb "InvalidName,Microsoft.PowerShell.Commands.NewLocalUserCommand" + } + + It "Errors on names ending in a period" { + $sb = { + New-LocalUser -Name "TestEndInPeriod." -NoPassword + } + VerifyFailingTest $sb "InvalidName,Microsoft.PowerShell.Commands.NewLocalUserCommand" + + $sb = { + New-LocalUser -Name ".TestEndIn.Period.." -NoPassword + } + VerifyFailingTest $sb "InvalidName,Microsoft.PowerShell.Commands.NewLocalUserCommand" + } + + It "Errors on name collison" { + $sb = { + New-LocalUser TestUserNew1 -NoPassword + New-LocalUser TestUserNew1 -NoPassword + } + VerifyFailingTest $sb "UserExists,Microsoft.PowerShell.Commands.NewLocalUserCommand" + } + + It "Errors on Name over 20 characters" { + $sb = { + New-LocalUser -Name ("A"*21) -NoPassword + } + try { + VerifyFailingTest $sb "ParameterArgumentValidationError,Microsoft.PowerShell.Commands.NewLocalUserCommand" + } + finally { + RemoveTestUsers -basename ("A"*21) + } + } + + It "Can set AccountExpires to the future" { + $expiration = $dateInFuture + $result = New-LocalUser TestUserNew1 -NoPassword -AccountExpires $expiration + + $result.Name | Should BeExactly TestUserNew1 + $result.Description | Should BeNullOrEmpty + $result.Enabled | Should Be $true + $result.SID | Should Not BeNullOrEmpty + $result.ObjectClass | Should Be User + $result.AccountExpires | Should Be ([DateTime]$expiration) + } + + It "Can set AccountExpires to the past" { + $expiration = $dateInPast + $result = New-LocalUser TestUserNew1 -NoPassword -AccountExpires $expiration + + $result.Name | Should BeExactly TestUserNew1 + $result.Description | Should BeNullOrEmpty + $result.Enabled | Should Be $true + $result.SID | Should Not BeNullOrEmpty + $result.ObjectClass | Should Be User + $result.AccountExpires | Should Be ([DateTime]$expiration) + } + + It "Errors on AccountExpires being set to invalid date" { + $expiration = $dateInvalid + $sb = { + New-LocalUser TestUserNew1 -NoPassword -AccountExpires $expiration + } + VerifyFailingTest $sb "CannotConvertArgumentNoMessage,Microsoft.PowerShell.Commands.NewLocalUserCommand" + } + + It "Can set AccountNeverExpires to create a user with null for AccountExpires date" { + $result = New-LocalUser TestUserNew1 -NoPassword -AccountNeverExpires + + $result.Name | Should BeExactly TestUserNew1 + $result.Description | Should BeNullOrEmpty + $result.Enabled | Should Be $true + $result.SID | Should Not BeNullOrEmpty + $result.ObjectClass | Should Be User + $result.AccountExpires | Should BeNullOrEmpty + } + + + It "Errors on both AccountExpires and AccountNeverExpires being set" { + $sb = { + New-LocalUser TestUserNew1 -NoPassword -AccountExpires $dateInFuture -AccountNeverExpires + } + VerifyFailingTest $sb "InvalidParameters,Microsoft.PowerShell.Commands.NewLocalUserCommand" + } + + + It "Can set empty string for Description" { + $result = New-LocalUser TestUserNew1 -NoPassword -Description "" + + $result.Name | Should BeExactly TestUserNew1 + $result.Description | Should BeExactly "" + $result.Enabled | Should Be $true + $result.SID | Should Not BeNullOrEmpty + $result.ObjectClass | Should Be User + } + + It "Can set with description at max 48" { + $result = New-LocalUser TestUserNew1 -NoPassword -Description ("A"*48) + + $result.Name | Should BeExactly TestUserNew1 + $result.Description | Should BeExactly ("A"*48) + $result.Enabled | Should Be $true + $result.SID | Should Not BeNullOrEmpty + $result.ObjectClass | Should Be User + } + + It "Can set with description over max 48" { + $result = New-LocalUser TestUserNew1 -NoPassword -Description ("A"*257) + + $result.Name | Should BeExactly TestUserNew1 + } + + It "Enabled is true by default" { + $result = New-LocalUser TestUserNew1 -NoPassword + + $result.Name | Should BeExactly TestUserNew1 + $result.Description | Should BeNullOrEmpty + $result.Enabled | Should Be $true + $result.SID | Should Not BeNullOrEmpty + $result.ObjectClass | Should Be User + } + + It "Can set enabled to false" { + $result = New-LocalUser TestUserNew1 -NoPassword -Disabled + + $result.Name | Should BeExactly TestUserNew1 + $result.Description | Should BeNullOrEmpty + $result.Enabled | Should Be $false + $result.SID | Should Not BeNullOrEmpty + $result.ObjectClass | Should Be User + } + + It "Can set empty string for FullName" { + $result = New-LocalUser TestUserNew1 -NoPassword -FullName "" + + $result.Name | Should BeExactly TestUserNew1 + $result.Description | Should BeNullOrEmpty + $result.Enabled | Should Be $true + $result.SID | Should Not BeNullOrEmpty + $result.ObjectClass | Should Be User + $result.FullName | Should BeNullOrEmpty + } + + It "Can set string for FullName at 256 characters" { + $result = New-LocalUser TestUserNew1 -NoPassword -FullName ("A"*256) + + $result.Name | Should BeExactly TestUserNew1 + $result.Description | Should BeNullOrEmpty + $result.Enabled | Should Be $true + $result.SID | Should Not BeNullOrEmpty + $result.ObjectClass | Should Be User + $result.FullName | Should BeExactly ("A"*256) + } + + It "Errors when Password is an empty string" { + $sb = { + New-LocalUser TestUserNew1 -Password (ConvertTo-SecureString "" -Asplaintext -Force) + } + VerifyFailingTest $sb "ParameterArgumentValidationErrorEmptyStringNotAllowed,Microsoft.PowerShell.Commands.ConvertToSecureStringCommand" + } + + It "Can set Password value at max 256" { + $result = New-LocalUser TestUserNew1 -Password (ConvertTo-SecureString ("135@"+"A"*252) -AsPlainText -Force) + + $result.Name | Should BeExactly TestUserNew1 + $result.Description | Should BeNullOrEmpty + $result.Enabled | Should Be $true + $result.SID | Should Not BeNullOrEmpty + $result.ObjectClass | Should Be User + } + + It "Errors when Password over max 257" { + $sb = { + New-LocalUser TestUserNew1 -Password (ConvertTo-SecureString ("A"*257) -AsPlainText -Force) + } + VerifyFailingTest $sb "InvalidPassword,Microsoft.PowerShell.Commands.NewLocalUserCommand" + } + + It "Can set UserMayNotChangePassword" { + $result = New-LocalUser TestUserNew1 -NoPassword -UserMayNotChangePassword + + $result.Name | Should BeExactly TestUserNew1 + $result.Description | Should BeNullOrEmpty + $result.Enabled | Should Be $true + $result.SID | Should Not BeNullOrEmpty + $result.ObjectClass | Should Be User + $result.UserMayChangePassword | Should Be $false + } + + It "Can set PasswordNeverExpires to create a user with null for PasswordExpires date" { + $result = New-LocalUser TestUserNew1 -Password (ConvertTo-SecureString "p@ssw0rd" -Asplaintext -Force) -PasswordNeverExpires + + $result.Name | Should BeExactly TestUserNew1 + $result.PasswordExpires | Should BeNullOrEmpty + } + + It "Errors on both NoPassword and PasswordNeverExpires being set" { + $sb = { + New-LocalUser TestUserNew1 -NoPassword -PasswordNeverExpires + } + VerifyFailingTest $sb "AmbiguousParameterSet,Microsoft.PowerShell.Commands.NewLocalUserCommand" + } + + It "UserMayChangePassword is true by default" { + $result = New-LocalUser TestUserNew1 -NoPassword + + $result.Name | Should BeExactly TestUserNew1 + $result.Description | Should BeNullOrEmpty + $result.Enabled | Should Be $true + $result.SID | Should Not BeNullOrEmpty + $result.ObjectClass | Should Be User + $result.UserMayChangePassword | Should Be $true + } +} + +Describe "Validate simple Get-LocalUser" -Tags "CI", "Feature" { + BeforeAll { + New-LocalUser -Name TestUserGet1 -NoPassword -Description "Test User Get 1 Description" | Out-Null + New-LocalUser -Name TestUserGet2 -NoPassword -Description "Test User Get 2 Description" | Out-Null + } + + AfterAll { + RemoveTestUsers -basename TestUserGet + } + + It "Can Get-LocalUser by only name" { + $result = Get-LocalUser TestUserGet1 + + $result.Name | Should Be "TestUserGet1" + $result.Description | Should Be "Test User Get 1 Description" + $result.ObjectClass | Should Be "User" + } +} + +Describe "Validate Get-LocalUser cmdlet" -Tags "Feature" { + BeforeAll { + New-LocalUser -Name TestUserGet1 -NoPassword -Description "Test User Get 1 Description" | Out-Null + New-LocalUser -Name TestUserGet2 -NoPassword -Description "Test User Get 2 Description" | Out-Null + } + + AfterAll { + RemoveTestUsers -basename TestUserGet + } + + It "Get-LocalUser gets all users" { + $result = Get-LocalUser + + $result.Count -gt 2 | Should Be $true + } + + It "Can get a specific user by SID" { + $result = Get-LocalUser TestUserGet1 + $resultBySID = Get-LocalUser -SID $result.SID + + $resultBySID.SID | Should Not BeNullOrEmpty + $resultBySID.Name | Should Be TestUserGet1 + } + + It "Can get a well-known user by SID string" { + $sid = New-Object System.Security.Principal.SecurityIdentifier -ArgumentList LG + $guestUser = Get-LocalUser -SID LG + + $guestUser.SID | Should Be $sid.Value + } + + It "Can get users by wildcard" { + $result = Get-LocalUser TestUserGet* + + $result.Count -eq 2 | Should Be $true + $result.Name -contains "TestUserGet1" | Should Be $true + $result.Name -contains "TestUserGet2" | Should Be $true + } + + It "Can get a user by array of names" { + $result = Get-LocalUser @("TestUserGet1", "TestUserGet2") + + $result.Count -eq 2 | Should Be $true + $result.Name -contains "TestUserGet1" | Should Be $true + $result.Name -contains "TestUserGet2" | Should Be $true + } + + It "Can get a user by array of SIDs" { + $sid1 = (Get-LocalUser TestUserGet1).SID + $sid2 = (Get-LocalUser TestUserGet2).SID + $result = Get-LocalUser -SID @($sid1, $sid2) + + $result.Count -eq 2 | Should Be $true + $result.Name -contains "TestUserGet1" | Should Be $true + $result.Name -contains "TestUserGet2" | Should Be $true + } + + It "Can respond to -ErrorAction Stop" { + Try { + Get-LocalUser @("TestUserGet1", "TestUserGetNameThatDoesntExist1", "TestUserGetNameThatDoesntExist2") -ErrorAction Stop -ErrorVariable outErr -OutVariable outOut | Out-Null + } + Catch { + # Ignore the execption + } + $outErr.Count -eq 1 | Should Be $true + $outErr[0].ErrorRecord.CategoryInfo.Reason -match "UserNotFound" | Should Be $true + $outOut.Name -match "TestUserGet1" | Should Be $true + } + + It "Error on Name not being supplied an argument" { + $sb = { + Get-LocalUser -Name + } + VerifyFailingTest $sb "MissingArgument,Microsoft.PowerShell.Commands.GetLocalUserCommand" + } + + It "Error on SID not being supplied an argument" { + $sb = { + Get-LocalUser -SID + } + VerifyFailingTest $sb "MissingArgument,Microsoft.PowerShell.Commands.GetLocalUserCommand" + } + + It "Error on both -Name and -SID being supplied at the same time" { + $sb = { + Get-LocalUser -Name TestUserGet1 -SID (Get-LocalUser TestUserGet1).SID + } + VerifyFailingTest $sb "AmbiguousParameterSet,Microsoft.PowerShell.Commands.GetLocalUserCommand" + } + + It "Errors on a non-existant user by name" { + $sb = { + Get-LocalUser 'TestUserGetNameThatDoesntExist' + } + VerifyFailingTest $sb "UserNotFound,Microsoft.PowerShell.Commands.GetLocalUserCommand" + } + + It "Errors on a non-existant user by SID" { + $sb = { + New-LocalUser -Name TestUserGet3 -NoPassword -Description "Test User Get 3 Description" + $sid = (Get-LocalUser -Name TestUserGet3).SID + Remove-LocalUser TestUserGet3 + Get-LocalUser -SID $sid + } + VerifyFailingTest $sb "UserNotFound,Microsoft.PowerShell.Commands.GetLocalUserCommand" + } + + It "Gets no results using a wildcard" { + $localUserName = 'TestUserGetNameThatDoesntExist' + $result = Get-LocalGroup $localUserName* + + $result -eq $null | Should Be $true + } + + It "Returns the correct property values of a user" { + $Name = "TestUserGet3" + $AccountExpires = $dateInFuture + $Description = "Describe" + $FullName = $Name + $ObjectClass = "User" + # TODO $LastLogon + # TODO $PasswordExpires + # TODO $PasswordLastSet + # TODO $PasswordRequired + # TODO $PrincipalSource + + $result = New-LocalUser TestUserGet3 -NoPassword -AccountExpires $AccountExpires -Description $Description -Disabled -FullName $FullName -UserMayNotChangePassword + + $result.Name | Should BeExactly $Name + $result.AccountExpires | Should Be ([DateTime]$AccountExpires) + $result.Description | Should BeExactly $Description + $result.Enabled | Should Be $false + $result.FullName | Should BeExactly $FullName + $result.ObjectClass -eq "User" | Should be true + $result.UserMayChangePassword | Should Be $false + $result.SID | Should Not BeNullOrEmpty + $result.ObjectClass | Should Be User + } +} + +Describe "Validate simple Set-LocalUser" -Tags "CI", "Feature" { + BeforeAll { + $user1SID = "" + } + + BeforeEach { + New-LocalUser -Name TestUserSet1 -NoPassword -Description "Test User Set 1 Description" | Out-Null + $user1SID = [String](Get-LocalUser -Name TestUserSet1).SID + } + + AfterEach { + RemoveTestUsers -basename TestUserSet + $user1SID = "" + } + + It "Can Set-LocalUser description by only name" { + Set-LocalUser -Name TestUserSet1 -Description "Test User Set 1 new description" + $result = Get-LocalUser -Name TestUserSet1 + + $result.Description | Should BeExactly "Test User Set 1 new description" + } +} + +Describe "Validate Set-LocalUser cmdlet" -Tags "Feature" { + BeforeAll { + $user1SID = "" + } + + BeforeEach { + New-LocalUser -Name TestUserSet1 -NoPassword -Description "Test User Set 1 Description" | Out-Null + $user1SID = [String](Get-LocalUser -Name TestUserSet1).SID + } + + AfterEach { + RemoveTestUsers -basename TestUserSet + $user1SID = "" + } + + It "Can set user description by SID" { + Set-LocalUser -SID $user1SID -Description "Test User Set 1 new description" + $result = Get-LocalUser -Name TestUserSet1 + + $result.Description | Should BeExactly "Test User Set 1 new description" + } + + It "Can set user description by -InputObject" { + $user = Get-LocalUser -Name TestUserSet1 + Set-LocalUser -InputObject $user -Description "Test User Set 1 new description" + $result = Get-LocalUser -Name TestUserSet1 + + $result.Description | Should BeExactly "Test User Set 1 new description" + } + + It "Can set user description by pipeline" { + Get-LocalUser -Name TestUserSet1 | Set-LocalUser -Description "Test User Set 1 new description" + $result = Get-LocalUser -Name TestUserSet1 + + $result.Description | Should BeExactly "Test User Set 1 new description" + } + + It "Errors on nonexistent user name" { + $sb = { + Set-LocalUser -Name TestUserSetNonexistent1 -Description "Test User Set 1 new description" -ErrorAction Stop + } + VerifyFailingTest $sb "UserNotFound,Microsoft.PowerShell.Commands.SetLocalUserCommand" + } + + It "Errors on nonexistent SID" { + $sb = { + Set-LocalUser -SID "S-1-5-32-545" -Description "Test User Set 1 new description" -ErrorAction Stop + } + VerifyFailingTest $sb "UserNotFound,Microsoft.PowerShell.Commands.SetLocalUserCommand" + } + + It "Can set AccountExpires to the future" { + $expiration = $dateInFuture + Set-LocalUser -Name TestUserSet1 -AccountExpires $expiration + $result = Get-LocalUser -Name TestUserSet1 + + $result.Name | Should BeExactly TestUserSet1 + $result.Description | Should BeExactly "Test User Set 1 Description" + $result.Enabled | Should Be $true + $result.SID | Should Not BeNullOrEmpty + $result.ObjectClass | Should Be User + $result.AccountExpires | Should Be ([DateTime]$expiration) + } + + It "Can set AccountExpires to the past" { + $expiration = $dateInPast + Set-LocalUser -Name TestUserSet1 -AccountExpires $expiration + $result = Get-LocalUser -Name TestUserSet1 + + $result.Name | Should BeExactly TestUserSet1 + $result.Description | Should BeExactly "Test User Set 1 Description" + $result.Enabled | Should Be $true + $result.SID | Should Not BeNullOrEmpty + $result.ObjectClass | Should Be User + $result.AccountExpires | Should Be ([DateTime]$expiration) + } + + It "Errors on AccountExpires being set to invalid date" { + $expiration = $dateInvalid + $sb = { + Set-LocalUser TestUserSet1 -AccountExpires $expiration + } + VerifyFailingTest $sb "CannotConvertArgumentNoMessage,Microsoft.PowerShell.Commands.SetLocalUserCommand" + } + + It "Can set AccountNeverExpires to create a user with null for AccountExpires date" { + Set-LocalUser -Name TestUserSet1 -AccountExpires $dateInFuture + Set-LocalUser -Name TestUserSet1 -AccountNeverExpires + $result = Get-LocalUser -Name TestUserSet1 + + $result.Name | Should BeExactly TestUserSet1 + $result.AccountExpires | Should BeNullOrEmpty + } + + It "Errors on both AccountExpires and AccountNeverExpires being set" { + $sb = { + Set-LocalUser TestUserSet1 -AccountExpires $dateInFuture -AccountNeverExpires + } + VerifyFailingTest $sb "InvalidParameters,Microsoft.PowerShell.Commands.SetLocalUserCommand" + } + + It "Can set user description to empty string" { + Set-LocalUser -Name TestUserSet1 -Description "" + $result = Get-LocalUser -Name TestUserSet1 + + $result.Description | Should BeExactly "" + } + + It "Can set empty string for Description" { + Set-LocalUser -Name TestUserSet1 -Description "" + $result = Get-LocalUser -Name TestUserSet1 + + $result.Description | Should BeExactly "" + } + + It "Can set string for Description at max 48" { + Set-LocalUser TestUserSet1 -Description ("A"*48) + $result = Get-LocalUser TestUserSet1 + + $result.Name | Should BeExactly TestUserSet1 + $result.Description | Should BeExactly ("A"*48) + $result.SID | Should Not BeNullOrEmpty + $result.ObjectClass | Should Be User + } + + It "Can set empty string for FullName" { + Set-LocalUser -Name TestUserSet1 -FullName "" + $result = Get-LocalUser -Name TestUserSet1 + + $result.FullName | Should BeExactly "" + } + + It "Can set string for FullName at 256" { + Set-LocalUser TestUserSet1 -FullName ("A"*256) + $result = Get-LocalUser TestUserSet1 + + $result.Name | Should BeExactly TestUserSet1 + $result.FullName | Should BeExactly ("A"*256) + $result.SID | Should Not BeNullOrEmpty + $result.ObjectClass | Should Be User + } + + It "Errors when Password is an empty string" { + $sb = { + Set-LocalUser -Name TestUserSet1 -Password (ConvertTo-SecureString "" -Asplaintext -Force) + } + VerifyFailingTest $sb "ParameterArgumentValidationErrorEmptyStringNotAllowed,Microsoft.PowerShell.Commands.ConvertToSecureStringCommand" + } + + It "Errors when Password is null" { + $sb = { + Set-LocalUser -Name TestUserSet1 -Password (ConvertTo-SecureString $null -Asplaintext -Force) + } + VerifyFailingTest $sb "ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.ConvertToSecureStringCommand" + } + + It "Can set Password value at max 256" { + Set-LocalUser -Name TestUserSet1 -Password (ConvertTo-SecureString ("123@"+"A"*252) -asplaintext -Force) + $result = Get-LocalUser -Name TestUserSet1 + + $result.Name | Should BeExactly TestUserSet1 + $result.Enabled | Should Be $true + $result.SID | Should Not BeNullOrEmpty + $result.ObjectClass | Should Be User + } + + It "Errors when Password over max 257" { + $sb = { + Set-LocalUser -Name TestUserSet1 -Password (ConvertTo-SecureString ("A"*257) -asplaintext -Force) -ErrorAction Stop + } + VerifyFailingTest $sb "InvalidPassword,Microsoft.PowerShell.Commands.SetLocalUserCommand" + } + + It 'Can use PasswordNeverExpires:$true to null a PasswordExpires date' { + $user = New-LocalUser TestUserSet2 -Password (ConvertTo-SecureString "p@ssw0rd" -Asplaintext -Force) + $user | Set-LocalUser -PasswordNeverExpires:$true + $result = Get-LocalUser TestUserSet2 + + $result.Name | Should BeExactly TestUserSet2 + $result.PasswordExpires | Should BeNullOrEmpty + } + + It 'Can use PasswordNeverExpires:$false to activate a PasswordExpires date' { + $user = New-LocalUser TestUserSet2 -Password (ConvertTo-SecureString "p@ssw0rd" -Asplaintext -Force) -PasswordNeverExpires + $user | Set-LocalUser -PasswordNeverExpires:$false + $result = Get-LocalUser TestUserSet2 + + $result.Name | Should BeExactly TestUserSet2 + $result.PasswordExpires | Should Not BeNullOrEmpty + } + + It "Can set UserMayChangePassword to true" { + Set-LocalUser TestUserSet1 -UserMayChangePassword $true + $result = Get-LocalUser -Name TestUserSet1 + + $result.Name | Should BeExactly TestUserSet1 + $result.SID | Should Not BeNullOrEmpty + $result.ObjectClass | Should Be User + $result.UserMayChangePassword | Should Be $true + } + + It "Can set UserMayChangePassword to false" { + Set-LocalUser TestUserSet1 -UserMayChangePassword $false + $result = Get-LocalUser -Name TestUserSet1 + + $result.Name | Should BeExactly TestUserSet1 + $result.SID | Should Not BeNullOrEmpty + $result.ObjectClass | Should Be User + $result.UserMayChangePassword | Should Be $false + } +} + +Describe "Validate simple Rename-LocalUser" -Tags "CI", "Feature" { + BeforeAll { + $user1SID = "" + } + + BeforeEach { + New-LocalUser -Name TestUserRename1 -NoPassword -Description "Test User Rename 1 Description" | Out-Null + $user1SID = [String](Get-LocalUser -Name TestUserRename1).SID + } + + AfterEach { + RemoveTestUsers -basename TestUserRename + $user1SID = "" + } + + It "Can Rename-LocalUser by only name" { + Rename-LocalUser -Name TestUserRename1 -NewName TestUserRename2 + $result = Get-LocalUser -SID $user1SID + + $result.Name | Should BeExactly TestUserRename2 + } +} + +Describe "Validate Rename-LocalUser cmdlet" -Tags "Feature" { + BeforeAll { + $user1SID = "" + } + + BeforeEach { + New-LocalUser -Name TestUserRename1 -NoPassword -Description "Test User Rename 1 Description" | Out-Null + $user1SID = [String](Get-LocalUser -Name TestUserRename1).SID + } + + AfterEach { + RemoveTestUsers -basename TestUserRename + $user1SID = "" + } + + It "Can rename by SID" { + Rename-LocalUser -SID $user1SID -NewName TestUserRename2 + $result = Get-LocalUser -SID $user1SID + + $result.Name | Should BeExactly TestUserRename2 + } + + It "Can rename using -InputObject" { + $user = Get-LocalUser -SID $user1SID + Rename-LocalUser -InputObject $user -NewName TestUserRename2 + $result = Get-LocalUser -SID $user1SID + + $result.Name | Should BeExactly TestUserRename2 + $result.SID | Should BeExactly $user1SID + } + + It "Can rename using pipeline" { + Get-LocalUser -SID $user1SID | Rename-LocalUser -NewName TestUserRename2 + $result = Get-LocalUser -SID $user1SID + + $result.Name | Should BeExactly TestUserRename2 + $result.SID | Should BeExactly $user1SID + } + + It "Errors on no name or SID specified" { + $sb = { + Rename-LocalUser + } + VerifyFailingTest $sb "AmbiguousParameterSet,Microsoft.PowerShell.Commands.RenameLocalUserCommand" + } + + It "Errors on nonexistant user name" { + $sb = { + Rename-LocalUser -Name TestUserRenameThatDoesntExist -NewName TestUserRenameThatDoesntExist2 + } + VerifyFailingTest $sb "UserNotFound,Microsoft.PowerShell.Commands.RenameLocalUserCommand" + } + + It "Errors on nonexistant user SID" { + $sb = { + Remove-LocalUser -SID $user1SID + Rename-LocalUser -SID $user1SID -NewName TestUserRename2 + } + VerifyFailingTest $sb "UserNotFound,Microsoft.PowerShell.Commands.RenameLocalUserCommand" + } + + It "Errors on rename of user to existing user, name collison" { + $sb = { + New-LocalUser TestUserRename4 -NoPassword + Rename-LocalUser -Name TestUserRename1 -NewName TestUserRename4 + } + try { + VerifyFailingTest $sb "NameInUse,Microsoft.PowerShell.Commands.RenameLocalUserCommand" + } + finally { + RemoveTestUsers -basename TestUserRename4 + } + } + + It "Errors on Invalid characters" { + #Arrange + #list of characters that should be invalid + $InvalidCharacters = @" +\/"[]:|<>+=;,?* +"@ + $failedCharacters = @() + $InvalidCharacters = $InvalidCharacters[0..($InvalidCharacters.Length - 1)] + + #Act + foreach ($character in $InvalidCharacters) { + try { + Rename-LocalUser -Name TestUserRename1 -NewName ("InvalidBecauseOf" + $character) -ErrorAction Stop + $invalidUser = (Get-LocalUser ("InvalidBecauseOf" + $character)) + } + catch { + } + finally { + #handle users being erroneously renamed + if ($invalidUser) { + Rename-LocalUser -Name ("InvalidBecauseOf" + $character) -NewName TestUserRename1 + $failedCharacters += $character + } + } + } + + #Assert + if ($failedCharacters.Count -gt 0) { Write-Host "characters causing test fail: $failedCharacters" } + $failedCharacters.Count -eq 0 | Should Be $true + } + + It "Errors on names containing only spaces or periods" { + $sb = { + Rename-LocalUser -Name TestUserRename1 -NewName "..." + } + VerifyFailingTest $sb "InvalidName,Microsoft.PowerShell.Commands.RenameLocalUserCommand" + + $sb = { + Rename-LocalUser -Name TestUserRename1 -NewName " " + } + VerifyFailingTest $sb "InvalidName,Microsoft.PowerShell.Commands.RenameLocalUserCommand" + } + + It "Errors on names ending in a period" { + $sb = { + Rename-LocalUser -Name TestUserRename1 -NewName "TestEndInPeriod." + } + VerifyFailingTest $sb "InvalidName,Microsoft.PowerShell.Commands.RenameLocalUserCommand" + + $sb = { + Rename-LocalUser -Name TestUserRename1 -NewName ".TestEndIn.Period.." + } + VerifyFailingTest $sb "InvalidName,Microsoft.PowerShell.Commands.RenameLocalUserCommand" + } + + It "Can rename by only name" { + Rename-LocalUser -Name TestUserRename1 -NewName TestUserRename2 + $result = Get-LocalUser -SID $user1SID + + $result.Name | Should BeExactly TestUserRename2 + } + + It "Errors when NewName over max 20" { + $sb = { + Rename-LocalUser -Name TestUserRename1 -NewName ("A"*21) + } + VerifyFailingTest $sb "InvalidName,Microsoft.PowerShell.Commands.RenameLocalUserCommand" + } +} + +Describe "Validate simple Remove-LocalUser" -Tags "CI", "Feature" { + BeforeAll { + $user1SID = "" + } + + BeforeEach { + New-LocalUser -Name TestUserRemove1 -NoPassword -Description "Test User Remove 1 Description" | Out-Null + $user1SID = [String](Get-LocalUser -Name TestUserRemove1).SID + } + + AfterEach { + RemoveTestUsers -basename TestUserRemove + $user1SID = "" + } + + It "Can Remove-LocalUser with only name" { + $initialCount = (Get-LocalUser).Count + $initialCount -gt 1 | Should Be $true + + $removeResult = Remove-LocalUser TestUserRemove1 2>&1 + $removeResult | Should BeNullOrEmpty + + $sb = { + Get-LocalUser -SID $user1SID + } + VerifyFailingTest $sb "UserNotFound,Microsoft.PowerShell.Commands.GetLocalUserCommand" + + $finalCount = (Get-LocalUser).Count + $initialCount -eq $finalCount + 1 | Should Be $true + } +} + +Describe "Validate Remove-LocalUser cmdlet" -Tags "Feature" { + BeforeAll { + $user1SID = "" + $user2SID = "" + + function VerifyBasicRemoval { + param ( + [scriptblock]$removalAction + ) + $initialCount = (Get-LocalUser).Count + $initialCount -gt 1 | Should Be true + + & $removalAction + + $sb = { + Get-LocalUser -SID $user1SID + } + VerifyFailingTest $sb "UserNotFound,Microsoft.PowerShell.Commands.GetLocalUserCommand" + + $finalCount = (Get-LocalUser).Count + $initialCount -eq $finalCount + 1 | Should Be true + } + + function VerifyArrayRemoval { + param ( + [scriptblock]$removalAction + ) + $initialCount = (Get-LocalUser).Count + $initialCount -gt 1 | Should Be true + + & $removalAction + + $sb = { + Get-LocalUser -SID $user1SID + } + VerifyFailingTest $sb "UserNotFound,Microsoft.PowerShell.Commands.GetLocalUserCommand" + + $sb = { + Get-LocalUser -SID $user2SID + } + VerifyFailingTest $sb "UserNotFound,Microsoft.PowerShell.Commands.GetLocalUserCommand" + + $finalCount = (Get-LocalUser).Count + $initialCount -eq $finalCount + 2 | Should Be $true + } + } + + BeforeEach { + $user1SID = [String](New-LocalUser -Name TestUserRemove1 -NoPassword -Description "Test User Remove 1 Description").SID + $user2SID = [String](New-LocalUser -Name TestUserRemove2 -NoPassword -Description "Test User Remove 2 Description").SID + } + + AfterEach { + RemoveTestUsers -basename TestUserRemove + $user1SID = "" + $user2SID = "" + } + + It "Can remove by SID" { + $user1SID | Should Not BeNullOrEmpty + $sb = { + $result = Remove-LocalUser -SID $user1SID 2>&1 + $result | Should BeNullOrEmpty + } + VerifyBasicRemoval $sb + } + + It "Can remove using -InputObject" { + $sb = { + $user = Get-LocalUser -SID $user1SID + $result = Remove-LocalUser -InputObject $user 2>&1 + $result | Should BeNullOrEmpty + } + VerifyBasicRemoval $sb + } + + It "Can remove using pipeline" { + $sb = { + $result = Get-LocalUser -SID $user1SID | Remove-LocalUser 2>&1 + $result | Should BeNullOrEmpty + } + VerifyBasicRemoval $sb + } + + It "Errors on no name or SID specified" { + $sb = { + Remove-LocalUser + } + VerifyFailingTest $sb "AmbiguousParameterSet,Microsoft.PowerShell.Commands.RemoveLocalUserCommand" + } + + It "Can remove by array of names" { + $sb = { + $result = Remove-LocalUser @("TestUserRemove1", "TestUserRemove2") 2>&1 + $result | Should BeNullOrEmpty + } + VerifyArrayRemoval $sb + } + + It "Can remove by array of SIDs" { + $sb = { + $result = Remove-LocalUser -SID @($user1SID, $user2SID) 2>&1 + $result | Should BeNullOrEmpty + } + VerifyArrayRemoval $sb + } + + It "Can remove by array using -InputObject" { + $sb = { + $users = Get-LocalUser @("TestUserRemove1", "TestUserRemove2") + $results = Remove-LocalUser -InputObject $users 2>&1 + $result | Should BeNullOrEmpty + } + VerifyArrayRemoval $sb + } + + It "Can remove by array using pipeline" { + $sb = { + $result = Get-LocalUser @("TestUserRemove1", "TestUserRemove2") | Remove-LocalUser 2>&1 + $result | Should BeNullOrEmpty + } + VerifyArrayRemoval $sb + } + + It "Errors on remove by invalid name" { + $initialCount = (Get-LocalUser).Count + $initialCount -gt 1 | Should Be $true + + $sb = { + Remove-LocalUser TestUserRemove1NameThatDoesntExist + } + VerifyFailingTest $sb "UserNotFound,Microsoft.PowerShell.Commands.RemoveLocalUserCommand" + + $finalCount = (Get-LocalUser).Count + $initialCount -eq $finalCount | Should Be $true + } + + It "Errors on remove by invalid SID" { + Remove-LocalUser -SID $user1SID + # This test verifies that it cannot be removed a second time + $initialCount = (Get-LocalUser).Count + $initialCount -gt 1 | Should Be $true + + $sb = { + Remove-LocalUser -SID $user1SID + } + VerifyFailingTest $sb "UserNotFound,Microsoft.PowerShell.Commands.RemoveLocalUserCommand" + + $finalCount = (Get-LocalUser).Count + $initialCount -eq $finalCount | Should Be $true + } + + It "Can respond to -ErrorAction Stop" { + try { + Remove-LocalUser @("TestUserGet1", "TestUserGetNameThatDoesntExist1", "TestUserGetNameThatDoesntExist2") -ErrorAction Stop -ErrorVariable outError | Out-Null + } + catch { + # Nothing to do here + } + $outError.Count | Should Be 2 + $outError[0].ErrorRecord.FullyQualifiedErrorId | Should Be "UserNotFound,Microsoft.PowerShell.Commands.RemoveLocalUserCommand" + + $getResult = Get-LocalUser TestUserGet1 2>&1 + $getResult.FullyQualifiedErrorId -match "UserNotFound" | Should Be $true + } +} + +Describe "Validate simple Enable-LocalUser" -Tags "CI", "Feature" { + BeforeAll { + $disabledUser1SID = "" + } + + BeforeEach { + New-LocalUser -Name TestUserDisabled1 -NoPassword -Disabled -Description "Test User Disabled 1 Description" | Out-Null + $disabledUser1SID = [String](Get-LocalUser -Name TestUserDisabled1).SID + } + + AfterEach { + Remove-LocalUser -SID $disabledUser1SID + $disabledUser1SID = "" + } + + It "Can Enable-LocalUser that is disabled by name" { + Enable-LocalUser TestUserDisabled1 + $result = Get-LocalUser TestUserDisabled1 + + $result.Enabled | Should Be $true + } +} + +Describe "Validate Enable-LocalUser cmdlet" -Tags "Feature" { + BeforeAll { + $enabledUser1SID = "" + $enabledUser2SID = "" + $disabledUser1SID = "" + $disabledUser2SID = "" + } + + BeforeEach { + $enabledUser1SID = [String](New-LocalUser -Name TestUserEnabled1 -NoPassword -Description "Test User Enabled 1 Description").SID + $enabledUser2SID = [String](New-LocalUser -Name TestUserEnabled2 -NoPassword -Description "Test User Enabled 2 Description").SID + $disabledUser1SID = [String](New-LocalUser -Name TestUserDisabled1 -NoPassword -Description "Test User Disabled 1 Description" -Disabled).SID + $disabledUser2SID = [String](New-LocalUser -Name TestUserDisabled2 -NoPassword -Description "Test User Disabled 2 Description" -Disabled).SID + } + + AfterEach { + RemoveTestUsers -basename TestUserEnabled + RemoveTestUsers -basename TestUserDisabled + + $enabledUser1SID = "" + $enabledUser2SID = "" + $disabledUser1SID = "" + $disabledUser2SID = "" + } + + It "Can enable a disabled user by SID" { + Enable-LocalUser -SID $disabledUser1SID + $result = Get-LocalUser -SID $disabledUser1SID + + $result.Enabled | Should Be $true + } + + It "Can enable a disabled user using -InputObject" { + $user = Get-LocalUser TestUserDisabled1 + Enable-LocalUser -InputObject $user + $result = Get-LocalUser TestUserDisabled1 + + $result.Enabled | Should Be $true + } + + It "Can enable a disabled user using pipeline" { + Get-LocalUser TestUserDisabled1 | Enable-LocalUser + $result = Get-LocalUser TestUserDisabled1 + + $result.Enabled | Should Be $true + } + + It "Can enable a disabled user by array of names" { + Enable-LocalUser @("TestUserDisabled1", "TestUserDisabled2") + + (Get-LocalUser "TestUserDisabled1").Enabled | Should Be $true + (Get-LocalUser "TestUserDisabled2").Enabled | Should Be $true + } + + It "Can enable a disabled user by array of SIDs" { + Enable-LocalUser -SID @($disabledUser1SID, $disabledUser2SID) + + (Get-LocalUser -SID $disabledUser1SID).Enabled | Should Be $true + (Get-LocalUser -SID $disabledUser2SID).Enabled | Should Be $true + } + + It "Can enable a disabled user by array sent using -InputObject" { + $users = @((Get-LocalUser "TestUserDisabled1"), (Get-LocalUser "TestUserDisabled2")) + Enable-LocalUser -InputObject $users + + (Get-LocalUser "TestUserDisabled1").Enabled | Should Be $true + (Get-LocalUser "TestUserDisabled2").Enabled | Should Be $true + } + + It "Can enable a disabled user by array sent using pipeline" { + @((Get-LocalUser "TestUserDisabled1"), (Get-LocalUser "TestUserDisabled2")) | Enable-LocalUser + + (Get-LocalUser "TestUserDisabled1").Enabled | Should Be $true + (Get-LocalUser "TestUserDisabled2").Enabled | Should Be $true + } + + It "Errors on no name or SID specified" { + $sb = { + Enable-LocalUser + } + VerifyFailingTest $sb "AmbiguousParameterSet,Microsoft.PowerShell.Commands.EnableLocalUserCommand" + } + + It "Can enable an already enabled user by name" { + Enable-LocalUser TestUserEnabled1 + $result = Get-LocalUser TestUserEnabled1 + + $result.Enabled | Should Be $true + } + + It "Can enable an already enabled user by SID" { + Enable-LocalUser -SID $enabledUser1SID + $result = Get-LocalUser -SID $enabledUser1SID + + $result.Enabled | Should Be $true + } + + It "Can enable an already enabled user using the pipeline" { + Get-LocalUser TestUserEnabled1 | Enable-LocalUser + $result = Get-LocalUser TestUserEnabled1 + + $result.Enabled | Should Be $true + } + + It "Errors on enabling an invalid user by name" { + $sb = { + Enable-LocalUser -Name TestUserEnableNameThatDoesntExist + } + VerifyFailingTest $sb "UserNotFound,Microsoft.PowerShell.Commands.EnableLocalUserCommand" + } + + It "Errors on enabling an invalid user by SID" { + $sb = { + Remove-LocalUser -SID $enabledUser1SID + Enable-LocalUser -SID $enabledUser1SID + } + VerifyFailingTest $sb "UserNotFound,Microsoft.PowerShell.Commands.EnableLocalUserCommand" + } + + It "Can respond to -ErrorAction Stop" { + Try { + Enable-LocalUser @("TestUserDisabled1", "TestUserNameThatDoesntExist1", "TestUserNameThatDoesntExist2") -ErrorAction Stop -ErrorVariable outError | Out-Null + } + Catch { + # do nothing + } + $outError.Count | Should Be 2 + $outError[0].ErrorRecord.FullyQualifiedErrorId | Should Be "UserNotFound,Microsoft.PowerShell.Commands.EnableLocalUserCommand" + + $getResult = Get-LocalUser TestUserDisabled1 2>&1 + $getResult.Enabled | Should Be $true + } +} + +Describe "Validate simple Disable-LocalUser" -Tags "CI", "Feature" { + BeforeAll { + $enabledUser1SID = "" + } + + BeforeEach { + New-LocalUser -Name TestUserEnabled1 -NoPassword -Disabled -Description "Test User Enabled 1 Description" | Out-Null + $enabledUser1SID = [String](Get-LocalUser -Name TestUserEnabled1).SID + } + + AfterEach { + Remove-LocalUser -SID $enabledUser1SID + $enabledUser1SID = "" + } + + It "Can Disable-LocalUser that is enabled by name" { + Disable-LocalUser TestUserEnabled1 + $result = Get-LocalUser TestUserEnabled1 + + $result.Enabled | Should Be $false + } +} + +Describe "Validate Disable-LocalUser cmdlet" -Tags "Feature" { + BeforeAll { + $enabledUser1SID = "" + $enabledUser2SID = "" + $disabledUser1SID = "" + $disabledUser2SID = "" + } + + BeforeEach { + $enabledUser1SID = [String](New-LocalUser -Name TestUserEnabled1 -NoPassword -Description "Test User Enabled 1 Description").SID + $enabledUser2SID = [String](New-LocalUser -Name TestUserEnabled2 -NoPassword -Description "Test User Enabled 2 Description").SID + $disabledUser1SID = [String](New-LocalUser -Name TestUserDisabled1 -NoPassword -Description "Test User Disabled 1 Description" -Disabled).SID + $disabledUser2SID = [String](New-LocalUser -Name TestUserDisabled2 -NoPassword -Description "Test User Disabled 2 Description" -Disabled).SID + } + + AfterEach { + RemoveTestUsers -basename TestUserEnabled + RemoveTestUsers -basename TestUserDisabled + + $enabledUser1SID = "" + $enabledUser2SID = "" + $disabledUser1SID = "" + $disabledUser2SID = "" + } + + It "Can disable an enabled user by SID" { + Disable-LocalUser -SID $enabledUser1SID + $result = Get-LocalUser -SID $enabledUser1SID + + $result.Enabled | Should Be $false + } + + It "Can disable an enabled user using -InputObject" { + $user = Get-LocalUser TestUserEnabled1 + Disable-LocalUser -InputObject $user + $result = Get-LocalUser TestUserEnabled1 + + $result.Enabled | Should Be $false + } + + It "Can disable an enabled user using pipeline" { + Get-LocalUser TestUserEnabled1 | Disable-LocalUser + $result = Get-LocalUser TestUserEnabled1 + + $result.Enabled | Should Be $false + } + + It "Can disable an enabled user by array of names" { + Disable-LocalUser @("TestUserEnabled1", "TestUserEnabled2") + + (Get-LocalUser "TestUserEnabled1").Enabled | Should Be $false + (Get-LocalUser "TestUserEnabled2").Enabled | Should Be $false + } + + It "Can disable an enabled user by array of SIDs" { + Disable-LocalUser -SID @($enabledUser1SID, $enabledUser2SID) + + (Get-LocalUser -SID $enabledUser1SID).Enabled | Should Be $false + (Get-LocalUser -SID $enabledUser2SID).Enabled | Should Be $false + } + + It "Can disable an enabled user by array sent using pipeline" { + $users = @((Get-LocalUser "TestUserEnabled1"), (Get-LocalUser "TestUserEnabled2")) + Disable-LocalUser -InputObject $users + + (Get-LocalUser "TestUserEnabled1").Enabled | Should Be $false + (Get-LocalUser "TestUserEnabled2").Enabled | Should Be $false + } + + It "Can disable an enabled user by array sent using pipeline" { + @((Get-LocalUser "TestUserEnabled1"), (Get-LocalUser "TestUserEnabled2")) | Disable-LocalUser + + (Get-LocalUser "TestUserEnabled1").Enabled | Should Be $false + (Get-LocalUser "TestUserEnabled2").Enabled | Should Be $false + } + + It "Errors on no name or SID specified" { + $sb = { + Disable-LocalUser + } + VerifyFailingTest $sb "AmbiguousParameterSet,Microsoft.PowerShell.Commands.DisableLocalUserCommand" + } + + It "Can disable an already disabled user by name" { + Disable-LocalUser TestUserDisabled1 + + (Get-LocalUser TestUserDisabled1).Enabled | Should Be $false + } + + It "Can disable an already disabled user by SID" { + Disable-LocalUser -SID $disabledUser1SID + + (Get-LocalUser -SID $disabledUser1SID).Enabled | Should Be $false + } + + It "Can disable an already disabled user using the pipeline" { + Get-LocalUser TestUserDisabled1 | Disable-LocalUser + + (Get-LocalUser TestUserDisabled1).Enabled | Should Be $false + } + + It "Errors on disabling an invalid user by name" { + $sb = { + Disable-LocalUser -Name TestUserNameThatDoesntExist + } + VerifyFailingTest $sb "UserNotFound,Microsoft.PowerShell.Commands.DisableLocalUserCommand" + } + + It "Errors on disabling an invalid user by SID" { + $sb = { + Remove-LocalUser -SID $enabledUser1SID + return Disable-LocalUser -SID $enabledUser1SID + } + VerifyFailingTest $sb "UserNotFound,Microsoft.PowerShell.Commands.DisableLocalUserCommand" + } + + It "Can respond to -ErrorAction Stop" { + Try { + Disable-LocalUser @("TestUserEnabled1", "TestUserNameThatDoesntExist1", "TestUserNameThatDoesntExist2") -ErrorAction Stop -ErrorVariable outError | Out-Null + } + Catch { + # Do nothing here + } + $outError.Count | Should Be 2 + $outError[0].ErrorRecord.FullyQualifiedErrorId | Should Be "UserNotFound,Microsoft.PowerShell.Commands.DisableLocalUserCommand" + + $getResult = Get-LocalUser TestUserEnabled1 2>&1 + $getResult.Enabled | Should Be $false + } +} diff --git a/test/powershell/Modules/Microsoft.PowerShell.Utility/Get-Alias.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Utility/Get-Alias.Tests.ps1 index 1a102d1f1b..84198e1297 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Utility/Get-Alias.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Utility/Get-Alias.Tests.ps1 @@ -1,166 +1,166 @@ Describe "Get-Alias DRT Unit Tests" -Tags "CI" { - It "Get-Alias Bogus Scope Name should throw PSArgumentException"{ - try { - Get-Alias -Name "ABCD" -Scope "bogus" - Throw "Execution OK" - } - catch { - $_.FullyQualifiedErrorId | Should be "Argument,Microsoft.PowerShell.Commands.GetAliasCommand" - } - } - It "Get-Alias OutOfRange Scope"{ - try { - Get-Alias -Name "ABCD" -Scope "99999" - Throw "Execution OK" - } - catch { - $_.FullyQualifiedErrorId | Should be "ArgumentOutOfRange,Microsoft.PowerShell.Commands.GetAliasCommand" - } - } - It "Get-Alias Named Single Valid"{ - Set-Alias -Name ABCD -Value "foo" - $result=Get-Alias -Name ABCD - $result.Name| Should Be "ABCD" - $result.Definition| Should Be "foo" - $result.Description| Should Be "" - $result.Options| Should Be "None" - } - It "Get-Alias Positional Single Valid"{ - Set-Alias -Name ABCD -Value "foo" - $result=Get-Alias ABCD - $result.Name| Should Be "ABCD" - $result.Definition| Should Be "foo" - $result.Description| Should Be "" - $result.Options| Should Be "None" - } - It "Get-Alias Named Multiple Valid"{ - Set-Alias -Name ABCD -Value "foo" - Set-Alias -Name AEFG -Value "bar" - $result=Get-Alias -Name ABCD,AEFG - $result[0].Name| Should Be "ABCD" - $result[0].Definition| Should Be "foo" - $result[0].Description| Should Be "" - $result[0].Options| Should Be "None" - $result[1].Name| Should Be "AEFG" - $result[1].Definition| Should Be "bar" - $result[1].Description| Should Be "" - $result[1].Options| Should Be "None" - } - It "Get-Alias Named Wildcard Valid"{ - Set-Alias -Name ABCD -Value "foo" - Set-Alias -Name ABCG -Value "bar" - $result=Get-Alias -Name ABC* - $result[0].Name| Should Be "ABCD" - $result[0].Definition| Should Be "foo" - $result[0].Description| Should Be "" - $result[0].Options| Should Be "None" - $result[1].Name| Should Be "ABCG" - $result[1].Definition| Should Be "bar" - $result[1].Description| Should Be "" - $result[1].Options| Should Be "None" - } - It "Get-Alias Positional Wildcard Valid"{ - Set-Alias -Name ABCD -Value "foo" - Set-Alias -Name ABCG -Value "bar" - $result=Get-Alias ABC* - $result[0].Name| Should Be "ABCD" - $result[0].Definition| Should Be "foo" - $result[0].Description| Should Be "" - $result[0].Options| Should Be "None" - $result[1].Name| Should Be "ABCG" - $result[1].Definition| Should Be "bar" - $result[1].Description| Should Be "" - $result[1].Options| Should Be "None" - } - It "Get-Alias Named Wildcard And Exclude Valid"{ - Set-Alias -Name ABCD -Value "foo" - Set-Alias -Name ABCG -Value "bar" - $result=Get-Alias -Name ABC* -Exclude "*BCG" - $result[0].Name| Should Be "ABCD" - $result[0].Definition| Should Be "foo" - $result[0].Description| Should Be "" - $result[0].Options| Should Be "None" - } - It "Get-Alias Scope Valid"{ - Set-Alias -Name ABCD -Value "foo" - $result=Get-Alias -Name ABCD - $result.Name| Should Be "ABCD" - $result.Definition| Should Be "foo" - $result.Description| Should Be "" - $result.Options| Should Be "None" - - Set-Alias -Name ABCD -Value "localfoo" -scope local - $result=Get-Alias -Name ABCD -scope local - $result.Name| Should Be "ABCD" - $result.Definition| Should Be "localfoo" - $result.Description| Should Be "" - $result.Options| Should Be "None" - - Set-Alias -Name ABCD -Value "globalfoo" -scope global - Set-Alias -Name ABCD -Value "scriptfoo" -scope "script" - Set-Alias -Name ABCD -Value "foo0" -scope "0" - Set-Alias -Name ABCD -Value "foo1" -scope "1" - - $result=Get-Alias -Name ABCD - $result.Name| Should Be "ABCD" - $result.Definition| Should Be "foo0" - $result.Description| Should Be "" - $result.Options| Should Be "None" - - $result=Get-Alias -Name ABCD -scope local - $result.Name| Should Be "ABCD" - $result.Definition| Should Be "foo0" - $result.Description| Should Be "" - $result.Options| Should Be "None" - - $result=Get-Alias -Name ABCD -scope global - $result.Name| Should Be "ABCD" - $result.Definition| Should Be "globalfoo" - $result.Description| Should Be "" - $result.Options| Should Be "None" - - $result=Get-Alias -Name ABCD -scope "script" - $result.Name| Should Be "ABCD" - $result.Definition| Should Be "scriptfoo" - $result.Description| Should Be "" - $result.Options| Should Be "None" - - $result=Get-Alias -Name ABCD -scope "0" - $result.Name| Should Be "ABCD" - $result.Definition| Should Be "foo0" - $result.Description| Should Be "" - $result.Options| Should Be "None" - - $result=Get-Alias -Name ABCD -scope "1" - $result.Name| Should Be "ABCD" - $result.Definition| Should Be "foo1" - $result.Description| Should Be "" - $result.Options| Should Be "None" - } - It "Get-Alias Expose Bug 1065828, BugId:905235"{ - try { - Get-Alias -Name "ABCD" -Scope "100" - Throw "Execution OK" - } - catch { - $_.FullyQualifiedErrorId | Should be "ArgumentOutOfRange,Microsoft.PowerShell.Commands.GetAliasCommand" - } - } - It "Get-Alias Zero Scope Valid"{ - Set-Alias -Name ABCD -Value "foo" - $result=Get-Alias -Name ABCD - $result.Name| Should Be "ABCD" - $result.Definition| Should Be "foo" - $result.Description| Should Be "" - $result.Options| Should Be "None" - - $result=Get-Alias -Name ABCD -scope "0" - $result.Name| Should Be "ABCD" - $result.Definition| Should Be "foo" - $result.Description| Should Be "" - $result.Options| Should Be "None" - } + It "Get-Alias Bogus Scope Name should throw PSArgumentException"{ + try { + Get-Alias -Name "ABCD" -Scope "bogus" + Throw "Execution OK" + } + catch { + $_.FullyQualifiedErrorId | Should be "Argument,Microsoft.PowerShell.Commands.GetAliasCommand" + } + } + It "Get-Alias OutOfRange Scope"{ + try { + Get-Alias -Name "ABCD" -Scope "99999" + Throw "Execution OK" + } + catch { + $_.FullyQualifiedErrorId | Should be "ArgumentOutOfRange,Microsoft.PowerShell.Commands.GetAliasCommand" + } + } + It "Get-Alias Named Single Valid"{ + Set-Alias -Name ABCD -Value "foo" + $result=Get-Alias -Name ABCD + $result.Name| Should Be "ABCD" + $result.Definition| Should Be "foo" + $result.Description| Should Be "" + $result.Options| Should Be "None" + } + It "Get-Alias Positional Single Valid"{ + Set-Alias -Name ABCD -Value "foo" + $result=Get-Alias ABCD + $result.Name| Should Be "ABCD" + $result.Definition| Should Be "foo" + $result.Description| Should Be "" + $result.Options| Should Be "None" + } + It "Get-Alias Named Multiple Valid"{ + Set-Alias -Name ABCD -Value "foo" + Set-Alias -Name AEFG -Value "bar" + $result=Get-Alias -Name ABCD,AEFG + $result[0].Name| Should Be "ABCD" + $result[0].Definition| Should Be "foo" + $result[0].Description| Should Be "" + $result[0].Options| Should Be "None" + $result[1].Name| Should Be "AEFG" + $result[1].Definition| Should Be "bar" + $result[1].Description| Should Be "" + $result[1].Options| Should Be "None" + } + It "Get-Alias Named Wildcard Valid"{ + Set-Alias -Name ABCD -Value "foo" + Set-Alias -Name ABCG -Value "bar" + $result=Get-Alias -Name ABC* + $result[0].Name| Should Be "ABCD" + $result[0].Definition| Should Be "foo" + $result[0].Description| Should Be "" + $result[0].Options| Should Be "None" + $result[1].Name| Should Be "ABCG" + $result[1].Definition| Should Be "bar" + $result[1].Description| Should Be "" + $result[1].Options| Should Be "None" + } + It "Get-Alias Positional Wildcard Valid"{ + Set-Alias -Name ABCD -Value "foo" + Set-Alias -Name ABCG -Value "bar" + $result=Get-Alias ABC* + $result[0].Name| Should Be "ABCD" + $result[0].Definition| Should Be "foo" + $result[0].Description| Should Be "" + $result[0].Options| Should Be "None" + $result[1].Name| Should Be "ABCG" + $result[1].Definition| Should Be "bar" + $result[1].Description| Should Be "" + $result[1].Options| Should Be "None" + } + It "Get-Alias Named Wildcard And Exclude Valid"{ + Set-Alias -Name ABCD -Value "foo" + Set-Alias -Name ABCG -Value "bar" + $result=Get-Alias -Name ABC* -Exclude "*BCG" + $result[0].Name| Should Be "ABCD" + $result[0].Definition| Should Be "foo" + $result[0].Description| Should Be "" + $result[0].Options| Should Be "None" + } + It "Get-Alias Scope Valid"{ + Set-Alias -Name ABCD -Value "foo" + $result=Get-Alias -Name ABCD + $result.Name| Should Be "ABCD" + $result.Definition| Should Be "foo" + $result.Description| Should Be "" + $result.Options| Should Be "None" + + Set-Alias -Name ABCD -Value "localfoo" -scope local + $result=Get-Alias -Name ABCD -scope local + $result.Name| Should Be "ABCD" + $result.Definition| Should Be "localfoo" + $result.Description| Should Be "" + $result.Options| Should Be "None" + + Set-Alias -Name ABCD -Value "globalfoo" -scope global + Set-Alias -Name ABCD -Value "scriptfoo" -scope "script" + Set-Alias -Name ABCD -Value "foo0" -scope "0" + Set-Alias -Name ABCD -Value "foo1" -scope "1" + + $result=Get-Alias -Name ABCD + $result.Name| Should Be "ABCD" + $result.Definition| Should Be "foo0" + $result.Description| Should Be "" + $result.Options| Should Be "None" + + $result=Get-Alias -Name ABCD -scope local + $result.Name| Should Be "ABCD" + $result.Definition| Should Be "foo0" + $result.Description| Should Be "" + $result.Options| Should Be "None" + + $result=Get-Alias -Name ABCD -scope global + $result.Name| Should Be "ABCD" + $result.Definition| Should Be "globalfoo" + $result.Description| Should Be "" + $result.Options| Should Be "None" + + $result=Get-Alias -Name ABCD -scope "script" + $result.Name| Should Be "ABCD" + $result.Definition| Should Be "scriptfoo" + $result.Description| Should Be "" + $result.Options| Should Be "None" + + $result=Get-Alias -Name ABCD -scope "0" + $result.Name| Should Be "ABCD" + $result.Definition| Should Be "foo0" + $result.Description| Should Be "" + $result.Options| Should Be "None" + + $result=Get-Alias -Name ABCD -scope "1" + $result.Name| Should Be "ABCD" + $result.Definition| Should Be "foo1" + $result.Description| Should Be "" + $result.Options| Should Be "None" + } + It "Get-Alias Expose Bug 1065828, BugId:905235"{ + try { + Get-Alias -Name "ABCD" -Scope "100" + Throw "Execution OK" + } + catch { + $_.FullyQualifiedErrorId | Should be "ArgumentOutOfRange,Microsoft.PowerShell.Commands.GetAliasCommand" + } + } + It "Get-Alias Zero Scope Valid"{ + Set-Alias -Name ABCD -Value "foo" + $result=Get-Alias -Name ABCD + $result.Name| Should Be "ABCD" + $result.Definition| Should Be "foo" + $result.Description| Should Be "" + $result.Options| Should Be "None" + + $result=Get-Alias -Name ABCD -scope "0" + $result.Name| Should Be "ABCD" + $result.Definition| Should Be "foo" + $result.Description| Should Be "" + $result.Options| Should Be "None" + } It "Test get-alias with Definition parameter" { $returnObject = Get-Alias -Definition Get-Command @@ -175,40 +175,39 @@ Describe "Get-Alias DRT Unit Tests" -Tags "CI" { Describe "Get-Alias" -Tags "CI" { It "Should have a return type of System.Array when gal returns more than one object" { - $val1=(Get-Alias a*) - $val2=(Get-Alias c*) - $i=0 + $val1=(Get-Alias a*) + $val2=(Get-Alias c*) + $i=0 - $val1 | ForEach-Object{ $i++}; - if($i -lt 2) { - $val1.GetType().BaseType.FullName | Should Be "System.Management.Automation.CommandInfo" - } - else - { - $val1.GetType().BaseType.FullName | Should Be "System.Array" - } - - $val2 | ForEach-Object{ $i++}; - if($i -lt 2) { - $val2.GetType().BaseType.FullName | Should Be "System.Management.Automation.CommandInfo" - } - else - { - $val2.GetType().BaseType.FullName | Should Be "System.Array" - } + $val1 | ForEach-Object{ $i++}; + if($i -lt 2) { + $val1.GetType().BaseType.FullName | Should Be "System.Management.Automation.CommandInfo" + } + else + { + $val1.GetType().BaseType.FullName | Should Be "System.Array" + } + $val2 | ForEach-Object{ $i++}; + if($i -lt 2) { + $val2.GetType().BaseType.FullName | Should Be "System.Management.Automation.CommandInfo" + } + else + { + $val2.GetType().BaseType.FullName | Should Be "System.Array" + } } - It "should return an array of 3 objects" { - $val = Get-Alias a* - $alias = gal a* + It "should return an array of objects" { + $val = Get-Alias a* + $alias = gal a* - $val.CommandType | Should Not BeNullOrEmpty - $val.Name | Should Not BeNullOrEmpty - $val.ModuleName | Should BeNullOrEmpty - - $alias.CommandType | Should Not BeNullOrEmpty - $alias.Name | Should Not BeNullOrEmpty - $alias.ModuleName | Should BeNullOrEmpty + $val.Count | Should Be $alias.Count + for ($i=0; $i -lt $val.Count;$i++) + { + $val[$i].CommandType | Should Be $alias[$i].CommandType + $val[$i].Name | Should Be $alias[$i].Name + $val[$i].ModuleName | Should Be $alias[$i].ModuleName + } } }