# Stand-ins for the WindowsServerBackup cmdlets. Object shapes follow Get-WsbCollectorDiagnostics.ps1 # output from a real Hyper-V host (Server 2019): job times are culture-formatted local-time strings # to the minute ("10/6/2026 9:00 PM" on en-US), HRESULTs are strings, and a Hyper-V backup has one # VirtualMachineList item whose SubItemList holds the VMs. When nothing is running, Get-WBJob # returns an empty job (JobType None). # # . ./tests/MockWsb.ps1 # nothing running # . ./tests/MockWsb.ps1 -WithRunningJob # a backup in progress # ./Send-WsbBackupStatus.ps1 -ConfigPath ./my-test-config.json -DryRun param([switch]$WithRunningJob) # Fixed to the top of the hour so repeated runs see the same jobs $now = Get-Date -Minute 0 -Second 0 -Millisecond 0 # Same format as the real cmdlet: short date + short time in the current culture function Format-WbTime($Value) { if ($null -eq $Value) { return '' } return ([datetime]$Value).ToString('g', [Globalization.CultureInfo]::CurrentCulture) } function New-MockItem($Name, $Type = 'Volume', [long]$Bytes = 0, [string]$HResult = '0', $ErrorDescription = '', $SubItems = $null) { $failedSubs = @($SubItems | Where-Object { $_ -and $_.HResult -ne '0' }).Count [pscustomobject]@{ Name = $Name Type = $Type State = $(if ($HResult -ne '0') { 'Failed' } else { 'Completed' }) HResult = $HResult DetailedHResult = '0' ErrorDescription = $ErrorDescription BytesProcessed = $Bytes TotalBytes = $Bytes CurrentItem = $null SubItemProcessed = [long]@($SubItems | Where-Object { $_ }).Count SubItemFailed = [long]$failedSubs TotalSubItem = [long]@($SubItems | Where-Object { $_ }).Count SubItemList = $SubItems } } function New-VmList([long]$VmBytes, [string]$VmHResult = '0', $VmError = '') { $vms = @( (New-MockItem 'AAOG-EDM-AD1' 'Component' $VmBytes $VmHResult $VmError), (New-MockItem 'Host Component' 'Component' 447729) ) New-MockItem 'VirtualMachineList' 'VirtualmachineList' ($VmBytes + 447729) -SubItems $vms } function New-MockJob($Type, $Start, $End, $State, [string]$HResult = '0', [string]$DetailedHResult = '0', $ErrorDescription = '', $Items = $null) { [pscustomobject]@{ JobType = $Type StartTime = Format-WbTime $Start EndTime = Format-WbTime $End JobState = $State CurrentOperation = '' HResult = $HResult DetailedHResult = $DetailedHResult ErrorDescription = $ErrorDescription JobItems = $Items VersionId = $(if ($End) { $Start.ToUniversalTime().ToString('MM/dd/yyyy-HH:mm', [Globalization.CultureInfo]::InvariantCulture) } else { '' }) SuccessLogPath = 'C:\Windows\Logs\WindowsServerBackup\Backup.log' # Populated even for successful backups, as on the real server FailureLogPath = 'C:\Windows\Logs\WindowsServerBackup\Backup_Error.log' } } $global:MockWsbRunning = if ($WithRunningJob) { @(New-MockJob 'Backup' $now.AddMinutes(-10) $null 'Running' -Items @(New-VmList 10GB)) } else { @(New-MockJob 'None' $null $null 'Unknown') } $global:MockWsbPrevious = @( (New-MockJob 'Backup' $now.AddHours(-12) $now.AddHours(-11.6) 'Completed' -Items @(New-VmList 124756706036)), # Completed overall, but one VM failed (New-MockJob 'Backup' $now.AddHours(-36) $now.AddHours(-35.6) 'Completed' '0' '0' '' @( New-VmList 0 '-2147024891' 'Access is denied.')), # Failed outright: backup target not found (0x80042302) (New-MockJob 'Backup' $now.AddHours(-30) $now.AddHours(-29.9) 'Completed' '-2147212542' '0' ` 'The backup storage location could not be found.'), # A volume-based backup, for servers that aren't Hyper-V hosts (New-MockJob 'Backup' $now.AddHours(-20) $now.AddHours(-19.5) 'Completed' -Items @( (New-MockItem 'C:' 'Volume' 40GB), (New-MockItem 'D:' 'Volume' 200GB))), (New-MockJob 'Recovery' $now.AddHours(-5) $now.AddHours(-4) 'Completed'), # a restore: must be ignored (New-MockJob 'Backup' $now.AddDays(-5) $now.AddDays(-5).AddHours(1) 'Completed') # outside 48h lookback ) $global:MockWsbSummary = [pscustomobject]@{ NextBackupTime = $now.Date.AddHours(21).AddDays($(if ($now.Hour -ge 21) { 1 } else { 0 })) NumberOfVersions = 1 LastSuccessfulBackupTime = $now.AddHours(-12) LastBackupResultHR = [uint32]0 CurrentOperationStatus = $(if ($WithRunningJob) { 'BackupInProgress' } else { 'NoOperationInProgress' }) } # Same limit as the real cmdlet function Get-WBJob { param([ValidateRange(1, 100)][int]$Previous) if ($PSBoundParameters.ContainsKey('Previous')) { $global:MockWsbPrevious } else { $global:MockWsbRunning } } function Get-WBSummary { $global:MockWsbSummary } function Get-WBPolicy { [pscustomobject]@{ PolicyName = 'Scheduled' } } function Get-WBSchedule { param($Policy) @($global:MockWsbSummary.NextBackupTime) }