Skip to content

Commit

Permalink
(MODULES-7661) Add tests for PowerShell task
Browse files Browse the repository at this point in the history
This commit adds tests for the Invoke-ExecuteTask function.  This also includes
mocking functions to create objects similar to that returned from the Windows
Update Agent API.
  • Loading branch information
glennsarti committed Sep 10, 2018
1 parent bd92f86 commit 354c34e
Show file tree
Hide file tree
Showing 3 changed files with 155 additions and 3 deletions.
46 changes: 46 additions & 0 deletions spec/spec_helper.ps1
Expand Up @@ -2,3 +2,49 @@ $DebugPreference = "SilentlyContinue"

$here = Split-Path -Parent $MyInvocation.MyCommand.Definition
$src = Resolve-Path -Path "$($here)\.."
Function New-MockUpdate($UpdateID, $Title) {
$properties = @{
Operation = Get-Random -Minimum 1 -Maximum 3
ResultCode = Get-Random -Minimum 0 -Maximum 6
Date = [DateTime]::Now
UpdateIdentity = @{
RevisionNumber = Get-Random -Minimum 1 -Maximum 11
UpdateID = [GUID]::NewGuid().ToString()
}
Title = "Mock Update Title $(Get-Random)"
ServiceID = [GUID]::NewGuid().ToString()
Categories = @() # TODO
HResult = Get-Random -Minimum 0 -Maximum 32768
Description = "Mock Description $(Get-Random)"
UnmappedResultCode = Get-Random -Minimum 0 -Maximum 32768

ClientApplicationID = "Mock ClientApplicationID $(Get-Random)"
ServerSelection = Get-Random -Minimum 0 -Maximum 4
UninstallationSteps = @("Mock UninstallationStep $(Get-Random)")
UninstallationNotes = "Mock UninstallationNotes $(Get-Random)"
SupportUrl = "Mock SupportUrl $(Get-Random)"
}

if (-Not [String]::IsNullOrEmpty($UpdateID)) { $properties.UpdateIdentity.UpdateID = $UpdateID}
if (-Not [String]::IsNullOrEmpty($Title)) { $properties.Title = $Title}

New-Object -TypeName PSObject -Property $properties
}
Function New-MockUpdateSession($UpdateCount = 0, $UpdateObjects = @()) {
$mock = New-Object -TypeName PSObject

$mock | Add-Member -MemberType NoteProperty -Name MockGetTotalHistoryCount -Value $UpdateCount | Out-Null

# Create a random update list
$Updates = $UpdateObjects
While ($Updates.Count -lt $UpdateCount) {
$Updates += New-MockUpdate
}
$mock | Add-Member -MemberType NoteProperty -Name MockQueryHistory -Value $Updates | Out-Null

# The following are methods not a properties and we can't do closures so just mirror the mock properties
$mock | Add-Member -MemberType ScriptMethod -Name GetTotalHistoryCount -Value { $this.MockGetTotalHistoryCount } | Out-Null
$mock | Add-Member -MemberType ScriptMethod -Name QueryHistory -Value { param($start, $count) $this.MockQueryHistory[$start..($start + $count - 1)] } | Out-Null

Write-Output $mock
}
102 changes: 102 additions & 0 deletions spec/tasks/update_history.Tests.ps1
Expand Up @@ -59,3 +59,105 @@ Describe 'Convert-ToUpdateOperationString' {
Convert-ToUpdateOperationString 2 | Should Be 'Uninstallation'
}
}

Describe 'Invoke-ExecuteTask' {
$DefaultExecuteParams = @{
Detailed = $false;
Title = $null
UpdateID = $null
MaximumUpdates = 300
}

It 'should return empty JSON if no history' {
Mock Get-UpdateSessionObject { New-MockUpdateSession 0 }

$Result = Invoke-ExecuteTask @DefaultExecuteParams | ConvertFrom-JSON
$Result | Should -HaveCount 0
}

It 'should return a JSON array for a single element' {
Mock Get-UpdateSessionObject { New-MockUpdateSession 1 }

$ResultJSON = Invoke-ExecuteTask @DefaultExecuteParams
$ResultJSON | Should -Match "^\["
$ResultJSON | Should -Match "\]$"

$Result = $ResultJSON | ConvertFrom-JSON
$Result | Should -HaveCount 1
}

It 'should not return detailed information when Detailed specified as false' {
Mock Get-UpdateSessionObject { New-MockUpdateSession 1 }
$ExecuteParams = $DefaultExecuteParams.Clone()
$ExecuteParams.Detailed = $false

$Result = Invoke-ExecuteTask @ExecuteParams | ConvertFrom-JSON
$Result | Should -HaveCount 1
$Result[0].HResult | Should -BeNullOrEmpty
$Result[0].Description | Should -BeNullOrEmpty
$Result[0].UnmappedResultCode | Should -BeNullOrEmpty
$Result[0].ClientApplicationID | Should -BeNullOrEmpty
$Result[0].ServerSelection | Should -BeNullOrEmpty
$Result[0].UninstallationSteps | Should -BeNullOrEmpty
$Result[0].UninstallationNotes | Should -BeNullOrEmpty
$Result[0].SupportUrl | Should -BeNullOrEmpty
$Result[0].UnmappedResultCode | Should -BeNullOrEmpty
$Result[0].UnmappedResultCode | Should -BeNullOrEmpty
}

It 'should return detailed information when Detailed specified as true' {
Mock Get-UpdateSessionObject { New-MockUpdateSession 1 }
$ExecuteParams = $DefaultExecuteParams.Clone()
$ExecuteParams.Detailed = $true

$Result = Invoke-ExecuteTask @ExecuteParams | ConvertFrom-JSON
$Result | Should -HaveCount 1
$Result[0].HResult | Should -Not -BeNullOrEmpty
$Result[0].Description | Should -Not -BeNullOrEmpty
$Result[0].UnmappedResultCode | Should -Not -BeNullOrEmpty
$Result[0].ClientApplicationID | Should -Not -BeNullOrEmpty
$Result[0].ServerSelection | Should -Not -BeNullOrEmpty
$Result[0].UninstallationSteps | Should -Not -BeNullOrEmpty
$Result[0].UninstallationNotes | Should -Not -BeNullOrEmpty
$Result[0].SupportUrl | Should -Not -BeNullOrEmpty
$Result[0].UnmappedResultCode | Should -Not -BeNullOrEmpty
$Result[0].UnmappedResultCode | Should -Not -BeNullOrEmpty
}

It 'should return only the maximum number of updates when specified' {
Mock Get-UpdateSessionObject { New-MockUpdateSession 20 }
$ExecuteParams = $DefaultExecuteParams
$ExecuteParams.MaximumUpdates = 5

$Result = Invoke-ExecuteTask @ExecuteParams | ConvertFrom-JSON
$Result | Should -HaveCount 5
}

It 'should return a single update when UpdateID is specified' {
$UpdateGUID = [GUID]::NewGuid().ToString()
$UpdateObject = New-MockUpdate -UpdateID $UpdateGUID
Mock Get-UpdateSessionObject { New-MockUpdateSession 10 @($UpdateObject) }
$ExecuteParams = $DefaultExecuteParams.Clone()
$ExecuteParams.UpdateID = $UpdateGUID

$Result = Invoke-ExecuteTask @ExecuteParams | ConvertFrom-JSON
$Result | Should -HaveCount 1
}

It 'should return a matching updates when Title is specified' {
$UpdateObjects = @(
New-MockUpdate -Title 'asserttitle'
New-MockUpdate -Title 'zzAssertTitlezz'
)
Mock Get-UpdateSessionObject { New-MockUpdateSession 10 $UpdateObjects }
$ExecuteParams = $DefaultExecuteParams.Clone()
$ExecuteParams.Title = 'AssertTitle'

$Result = Invoke-ExecuteTask @ExecuteParams | ConvertFrom-JSON
$Result | Should -HaveCount 2

$UpdateTitles = $Result | ForEach-Object { Write-Output $_.Title }
$UpdateTitles | Should -Contain 'asserttitle'
$UpdateTitles | Should -Contain 'zzAssertTitlezz'
}
}
10 changes: 7 additions & 3 deletions tasks/update_history.ps1
Expand Up @@ -65,9 +65,13 @@ Function Convert-ToUpdateOperationString($value) {
}
}

Function Invoke-ExecuteTask() {
Function Get-UpdateSessionObject() {
$Session = New-Object -ComObject "Microsoft.Update.Session"
$Searcher = $Session.CreateUpdateSearcher()
Write-Output $Session.CreateUpdateSearcher()
}

Function Invoke-ExecuteTask($Detailed, $Title, $UpdateID, $MaximumUpdates) {
$Searcher = Get-UpdateSessionObject
# Returns IUpdateSearcher https://msdn.microsoft.com/en-us/library/windows/desktop/aa386515(v=vs.85).aspx

$historyCount = $Searcher.GetTotalHistoryCount()
Expand Down Expand Up @@ -109,4 +113,4 @@ Function Invoke-ExecuteTask() {
} | ConvertTo-JSON
}

if (-Not $NoOperation) { Invoke-ExecuteTask }
if (-Not $NoOperation) { Invoke-ExecuteTask -Detailed $Detailed -Title $Title -UpdateID $UpdateID -MaximumUpdates $MaximumUpdates }

0 comments on commit 354c34e

Please sign in to comment.