Tests/Unit/MSFT_xVMSwitch_BandwidthReservationMode.Tests.ps1
[CmdletBinding()] Param ( ) if (!$PSScriptRoot) # $PSScriptRoot is not defined in 2.0 { $PSScriptRoot = [System.IO.Path]::GetDirectoryName($MyInvocation.MyCommand.Path) } $ErrorActionPreference = 'Stop' Set-StrictMode -Version latest $RepoRoot = (Resolve-Path $PSScriptRoot\..\..).Path $ModuleName = 'MSFT_xVMSwitch' Import-Module (Join-Path $RepoRoot "DSCResources\$ModuleName\$ModuleName.psm1") -Force; Describe 'xVMSwitch' { InModuleScope $ModuleName { # Defines a variable that contains all the possible Bandwidth Reservation Modes which will be used # for foreach loops later on New-Variable -Name 'BANDWIDTH_RESERVATION_MODES' -Option 'Constant' -Value @('Default','Weight','Absolute','None') # A helper function to mock a VMSwitch function New-MockedVMSwitch { Param ( [Parameter(Mandatory=$true)] [string]$Name, [Parameter(Mandatory=$true)] [ValidateSet('Default','Weight','Absolute','None','NA')] [string]$BandwidthReservationMode, [bool]$AllowManagementOS = $false ) $mockedVMSwitch = @{ Name = $Name SwitchType = 'External' AllowManagementOS = $AllowManagementOS NetAdapterInterfaceDescription = 'Microsoft Network Adapter Multiplexor Driver' } if ($BandwidthReservationMode -ne 'NA') { $mockedVMSwitch['BandwidthReservationMode'] = $BandwidthReservationMode } return [PsObject]$mockedVMSwitch } # Create an empty function to be able to mock the missing Hyper-V cmdlet function Get-VMSwitch { [CmdletBinding()] Param( [string]$Name, [string]$SwitchType ) } # Create an empty function to be able to mock the missing Hyper-V cmdlet function New-VMSwitch { [CmdletBinding()] Param( [string]$Name, [string]$MinimumBandwidthMode, [string]$NetAdapterName, [bool]$AllowManagementOS = $false ) } # Create an empty function to be able to mock the missing Hyper-V cmdlet function Remove-VMSwitch { } # Create an empty function to be able to mock the missing Hyper-V cmdlet function Set-VMSwitch { [CmdletBinding()] Param ( [bool]$AllowManagementOS ) } # Mocks Get-VMSwitch and will return $global:mockedVMSwitch which is # a variable that is created during most It statements to mock a VMSwitch Mock -CommandName Get-VMSwitch -MockWith { Param ( [string]$ErrorAction ) if ($ErrorAction -eq 'Stop' -and $global:mockedVMSwitch -eq $null) { throw [System.Management.Automation.ActionPreferenceStopException]'No switch can be found by given criteria.' } return $global:mockedVMSwitch } # Mocks New-VMSwitch and will assign a mocked switch to $global:mockedVMSwitch. This returns $global:mockedVMSwitch # which is a variable that is created during most It statements to mock a VMSwitch Mock -CommandName New-VMSwitch -MockWith { Param ( [string]$Name, [string]$NetAdapterName, [string]$MinimumBandwidthMode, [bool]$AllowManagementOS ) $global:mockedVMSwitch = New-MockedVMSwitch -Name $Name -BandwidthReservationMode $MinimumBandwidthMode -AllowManagementOS $AllowManagementOS return $global:mockedVMSwitch } # Mocks Set-VMSwitch and will modify $global:mockedVMSwitch which is # a variable that is created during most It statements to mock a VMSwitch Mock -CommandName Set-VMSwitch -MockWith { Param ( [bool]$AllowManagementOS ) if ($AllowManagementOS) { $global:mockedVMSwitch['AllowManagementOS'] = $AllowManagementOS } } # Mocks Remove-VMSwitch and will remove the variable $global:mockedVMSwitch which is # a variable that is created during most It statements to mock a VMSwitch Mock -CommandName Remove-VMSwitch -MockWith { $global:mockedVMSwitch = $null } # Mocks Get-NetAdapter which returns a simplified network adapter Mock -CommandName Get-NetAdapter -MockWith { return [PSCustomObject]@{ Name = 'SomeNIC' InterfaceDescription = 'Microsoft Network Adapter Multiplexor Driver' } } # Mocks "Get-Module -Name Hyper-V" so that the DSC resource thinks the Hyper-V module is on the test system Mock -CommandName Get-Module -ParameterFilter { ($Name -eq 'Hyper-V') -and ($ListAvailable -eq $true) } -MockWith { return $true } # Mock "Get-WmiObject -Class -eq 'Win32_OperatingSystem'" to output a valid Windows version that supports BandwidthReservationMode Mock -CommandName Get-WmiObject -ParameterFilter { $Class -eq 'Win32_OperatingSystem' } -MockWith { return [PSCustomObject]@{ Version = '6.3.9600' } } # Create all the test cases for Get-TargetResource $getTestCases = @() foreach ($brmMode in $BANDWIDTH_RESERVATION_MODES) { $getTestCases += @{ CurrentName = $brmMode + 'BRM' CurrentBandwidthReservationMode = $brmMode } } Context 'Validates Get-TargetResource Function' { # Test Get-TargetResource with the test cases created above It 'Current switch''s BandwidthReservationMode is set to <CurrentBandwidthReservationMode>' -TestCases $getTestCases { Param ( [string]$CurrentName, [string]$CurrentBandwidthReservationMode ) # Set the mocked VMSwitch to be returned from Get-VMSwitch based on the input from $getTestCases $global:mockedVMSwitch = New-MockedVMSwitch -Name $CurrentName -BandwidthReservationMode $CurrentBandwidthReservationMode $targetResource = Get-TargetResource -Name $CurrentName -Type 'External' $targetResource -is [System.Collections.Hashtable] | Should Be $true $targetResource['BandwidthReservationMode'] | Should Be $CurrentBandwidthReservationMode Remove-Variable -Scope 'Global' -Name 'mockedVMSwitch' -ErrorAction 'SilentlyContinue' } # Test Get-TargetResource when the VMSwitch's BandwidthReservationMode member variable is not # set which simulates older versions of Windows that don't support it It 'BandwidthReservationMode is set to null' { # Set the mocked VMSwitch to be returned from Get-VMSwitch $global:mockedVMSwitch = New-MockedVMSwitch -Name 'NaBRM' -BandwidthReservationMode 'NA' $targetResource = Get-TargetResource -Name 'NaBRM' -Type 'External' $targetResource -is [System.Collections.Hashtable] | Should Be $true $targetResource['BandwidthReservationMode'] | Should Be $null Remove-Variable -Scope 'Global' -Name 'mockedVMSwitch' -ErrorAction 'SilentlyContinue' } } # Create all the test cases for Test-TargetResource and Set-TargetResource when the switch already exists $testSetTestCases = @() foreach ($currentBrmMode in $BANDWIDTH_RESERVATION_MODES) { foreach ($desiredBrmMode in $BANDWIDTH_RESERVATION_MODES) { foreach ($ensureOption in @('Present', 'Absent')) { $case = @{ CurrentName = $currentBrmMode + 'BRM' CurrentBandwidthReservationMode = $currentBrmMode DesiredName = $desiredBrmMode + 'BRM' DesiredBandwidthReservationMode = $desiredBrmMode Ensure = $ensureOption ExpectedResult = $ensureOption -eq 'Present' -and $currentBrmMode -eq $desiredBrmMode } $testSetTestCases += $case } } } # Create all the test cases for Test-TargetResource and Set-TargetResource when the switch does not exists foreach ($desiredBrmMode in $BANDWIDTH_RESERVATION_MODES) { foreach ($ensureOption in @('Present', 'Absent')) { $case = @{ CurrentName = $null CurrentBandwidthReservationMode = $null DesiredName = $desiredBrmMode + 'BRM' DesiredBandwidthReservationMode = $desiredBrmMode Ensure = $ensureOption ExpectedResult = $ensureOption -eq 'Absent' } $testSetTestCases += $case } } Context 'Validates Test-TargetResource Function' { # Test Test-TargetResource with the test cases created above It 'Current Name "<CurrentName>" | Current BandwidthReservationMode set to "<CurrentBandwidthReservationMode>" | Desired BandwidthReservationMode set to "<DesiredBandwidthReservationMode>" | Ensure "<Ensure>"' -TestCases $testSetTestCases { Param ( [string]$CurrentName, [string]$CurrentBandwidthReservationMode, [string]$DesiredName, [string]$DesiredBandwidthReservationMode, [string]$Ensure, [bool]$ExpectedResult ) # Set the mocked VMSwitch to be returned from Get-VMSwitch if the switch exists if ($CurrentName) { $global:mockedVMSwitch = New-MockedVMSwitch -Name $CurrentName -BandwidthReservationMode $CurrentBandwidthReservationMode -AllowManagementOS $true } $targetResource = Test-TargetResource -Name $DesiredName -BandwidthReservationMode $DesiredBandwidthReservationMode -Type 'External' -NetAdapterName 'SomeNIC' -Ensure $Ensure -AllowManagementOS $true $targetResource | Should Be $ExpectedResult Remove-Variable -Scope 'Global' -Name 'mockedVMSwitch' -ErrorAction 'SilentlyContinue' } # Mock "Get-WmiObject -Class -eq 'Win32_OperatingSystem'" to output an Windows version that does not support BandwidthReservationMode Mock -CommandName Get-WmiObject -ParameterFilter { $Class -eq 'Win32_OperatingSystem' } -MockWith { return [PSCustomObject]@{ Version = '6.1.7601' } } # Test Test-TargetResource when the version of Windows doesn't support BandwidthReservationMode It 'Invalid Operating System Exception' { {Test-TargetResource -Name 'WeightBRM' -Type 'External' -NetAdapterName 'SomeNIC' -AllowManagementOS $true -BandwidthReservationMode 'Weight' -Ensure 'Present'} | Should Throw 'The BandwidthReservationMode cannot be set on a Hyper-V version lower than 2012' } # Test Test-TargetResource when the version of Windows doesn't support BandwidthReservationMode and specifies NA for BandwidthReservationMode It 'Simulates Windows Server 2008 R2 | Desired BandwidthReservationMode set to "NA" | Ensure Present | Expected Result is True' { $global:mockedVMSwitch = New-MockedVMSwitch -Name 'SomeSwitch' -BandwidthReservationMode 'NA' -AllowManagementOS $true $targetResource = Test-TargetResource -Name 'SomeSwitch' -BandwidthReservationMode 'NA' -Type 'External' -NetAdapterName 'SomeNIC' -Ensure 'Present' -AllowManagementOS $true $targetResource | Should Be $true } It 'Passes when "BandwidthReservationMode" does not match but is not specified (#48)' { $global:mockedVMSwitch = New-MockedVMSwitch -Name 'SomeSwitch' -BandwidthReservationMode 'Absolute' $targetResource = Test-TargetResource -Name 'SomeSwitch' -Type 'Internal' -Ensure 'Present' $targetResource | Should Be $true } } Context 'Validates Set-TargetResource Function' { It 'Current Name "<CurrentName>" | Current BandwidthReservationMode set to "<CurrentBandwidthReservationMode>" | Desired BandwidthReservationMode set to "<DesiredBandwidthReservationMode>" | Ensure "<Ensure>"' -TestCases $testSetTestCases { Param ( [string]$CurrentName, [string]$CurrentBandwidthReservationMode, [string]$DesiredName, [string]$DesiredBandwidthReservationMode, [string]$Ensure, [bool]$ExpectedResult ) # Set the mocked VMSwitch to be returned from Get-VMSwitch if the switch exists if ($CurrentName) { $global:mockedVMSwitch = New-MockedVMSwitch -Name $CurrentName -BandwidthReservationMode $CurrentBandwidthReservationMode -AllowManagementOS $true } $targetResource = Set-TargetResource -Name $DesiredName -BandwidthReservationMode $DesiredBandwidthReservationMode -Type 'External' -NetAdapterName 'SomeNIC' -Ensure $Ensure -AllowManagementOS $true $targetResource | Should Be $null if ($CurrentName -and $Ensure -eq 'Present') { if ($DesiredBandwidthReservationMode -ne $CurrentBandwidthReservationMode) { Assert-MockCalled -CommandName Get-VMSwitch -Times 2 -Scope 'It' Assert-MockCalled -CommandName Remove-VMSwitch -Times 1 -Scope 'It' Assert-MockCalled -CommandName New-VMSwitch -Times 1 -Scope 'It' Assert-MockCalled -CommandName Set-VMSwitch -Times 0 -Scope 'It' } else { Assert-MockCalled -CommandName Get-VMSwitch -Times 1 -Scope 'It' } } elseif ($Ensure -eq 'Present') { Assert-MockCalled -CommandName Get-VMSwitch -Times 1 -Scope 'It' Assert-MockCalled -CommandName New-VMSwitch -Times 1 -Scope 'It' } else { Assert-MockCalled -CommandName Get-VMSwitch -Times 1 -Scope 'It' Assert-MockCalled -CommandName Remove-VMSwitch -Times 1 -Scope 'It' } Remove-Variable -Scope 'Global' -Name 'mockedVMSwitch' -ErrorAction 'SilentlyContinue' } # Test Set-TargetResource when the version of Windows doesn't support BandwidthReservationMode It 'Invalid Operating System Exception' { Mock -CommandName Get-WmiObject -ParameterFilter { $Class -eq 'Win32_OperatingSystem' } -MockWith { return [PSCustomObject]@{ Version = '6.1.7601' } } {Set-TargetResource -Name 'WeightBRM' -Type 'External' -NetAdapterName 'SomeNIC' -AllowManagementOS $true -BandwidthReservationMode 'Weight' -Ensure 'Present'} | Should Throw 'The BandwidthReservationMode cannot be set on a Hyper-V version lower than 2012' } } } } |